123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Compression;
- using System.Text;
- using System.Threading;
- using UnityEngine;
- namespace ZenFulcrum.EmbeddedBrowser {
- /**
- * Implements fetching BrowserAssets for standalone builds.
- *
- * During build, everything in BrowserAssets is packaged into a single file with the following format:
- * brString {FileHeader}
- * i32 numEntries
- * {numEntries} IndexEntry objects
- * data //The data section is a series of filedata chunks, as laid out in the index.
- */
- public class StandaloneWebResources : WebResources {
- public struct IndexEntry {
- public string name;
- public long offset;
- public int length;
- }
- private const string FileHeader = "zfbRes_v1";
- protected Dictionary<string, IndexEntry> toc = new Dictionary<string, IndexEntry>();
- protected string dataFile;
- public StandaloneWebResources(string dataFile) {
- this.dataFile = dataFile;
- }
- public const string DefaultPath = "Resources/browser_assets";
- public void LoadIndex() {
- using (var data = new BinaryReader(File.OpenRead(dataFile))) {
- var header = data.ReadString();
- if (header != FileHeader) throw new Exception("Invalid web resource file");
- var num = data.ReadInt32();
- for (int i = 0; i < num; ++i) {
- var entry = new IndexEntry() {
- name = data.ReadString(),
- offset = data.ReadInt64(),
- length = data.ReadInt32(),
- };
- toc[entry.name] = entry;
- }
- }
- }
-
- public override void HandleRequest(int id, string url) {
- var parsedURL = new Uri(url);
- var path = WWW.UnEscapeURL(parsedURL.AbsolutePath);
- IndexEntry entry;
- if (!toc.TryGetValue(path, out entry)) {
- SendError(id, "Not found", 404);
- return;
- }
- new Thread(() => {
- try {
- var ext = Path.GetExtension(entry.name);
- if (ext.Length > 0) ext = ext.Substring(1);
- string mimeType;
- if (!extensionMimeTypes.TryGetValue(ext, out mimeType)) {
- mimeType = extensionMimeTypes["*"];
- }
- using (var file = File.OpenRead(dataFile)) {
- var pre = new ResponsePreamble {
- headers = null,
- length = entry.length,
- mimeType = mimeType,
- statusCode = 200,
- };
- SendPreamble(id, pre);
- file.Seek(entry.offset, SeekOrigin.Begin);
- var data = new byte[entry.length];
- var readLen = file.Read(data, 0, entry.length);
- if (readLen != data.Length) throw new Exception("Insufficient data for file");
- SendData(id, data);
- }
- } catch (Exception ex) {
- Debug.LogException(ex);
- }
-
- }).Start();
- }
- public void WriteData(Dictionary<string, byte[]> files) {
- var entries = new Dictionary<string, IndexEntry>();
- using (var file = File.OpenWrite(dataFile)) {
- var writer = new BinaryWriter(file, Encoding.UTF8 /*, true (Mono too old)*/);
- writer.Write(FileHeader);
- writer.Write(files.Count);
- var tocStart = file.Position;
- foreach (var kvp in files) {
- writer.Write(kvp.Key);
- writer.Write(0L);
- writer.Write(0);
- }
- //we'll come back and fill it in right later
- foreach (var kvp in files) {
- var data = kvp.Value;
- var entry = new IndexEntry {
- name = kvp.Key,
- length = kvp.Value.Length,
- offset = file.Position,
- };
- writer.Write(data);
- entries[kvp.Key] = entry;
- }
- //now go back and write the correct data.
- writer.Seek((int)tocStart, SeekOrigin.Begin);
- foreach (var kvp in files) {
- var entry = entries[kvp.Key];
- writer.Write(kvp.Key);
- writer.Write(entry.offset);
- writer.Write(entry.length);
- }
- }
- }
- }
- }
|