diff --git a/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs b/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs index efe60a5..58c8325 100644 --- a/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs +++ b/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs @@ -6,7 +6,8 @@ using System; using Newtonsoft.Json; using RothenburgAR.Common; using System.IO; -using TMPro; +using System.IO.Compression; +using System.Security.Cryptography; namespace RothenburgAR.Updater { @@ -24,6 +25,8 @@ namespace RothenburgAR.Updater private List httpHandlers = new List(); private LogFileHandler logFileHandler; + private readonly List downloadingMedia = new List(); + void Start() { #if !UNITY_EDITOR @@ -74,7 +77,7 @@ namespace RothenburgAR.Updater var answer = VersionAnswer; - if (answer.Data.TrueForAll(d => d.Meta.Status == VersionStatus.ok && d.Tracker.Status == VersionStatus.ok)) + if (VersionAnswer.Data.TrueForAll(d => d.Meta.Status == VersionStatus.ok && d.Tracker.Status == VersionStatus.ok)) { // no updates required, continue to app LoadMainScene(); @@ -116,7 +119,6 @@ namespace RothenburgAR.Updater }; result = result.Substring(0, result.Length - 1) + "}"; - return "{}"; return result; } @@ -141,6 +143,7 @@ namespace RothenburgAR.Updater UpdateConfirmationDialog.SetActive(false); UpdateFailedDialog.SetActive(false); + this.downloadingMedia.Clear(); if (VersionAnswer == null) { @@ -233,19 +236,22 @@ namespace RothenburgAR.Updater foreach (var mediaId in mediaIDs) { - //System.Security.Cryptography.MD5CryptoServiceProvider - //System.Security.Cryptography.SHA1CryptoServiceProvider - //System.Security.Cryptography.SHA256 + if (downloadingMedia.Contains(mediaId)) continue; + downloadingMedia.Add(mediaId); var path = PathHelper.CombinePaths(PathHelper.MediaPath, mediaId); - var filepath = Path.Combine(path, "media.zip"); + var filepath = Path.Combine(path, mediaId + ".med"); // create dir if nonexistent if (!Directory.Exists(path)) Directory.CreateDirectory(path); + //System.Security.Cryptography.SHA1CryptoServiceProvider + //System.Security.Cryptography.SHA256 + var eTag = GenerateETag(filepath); + var url = ApiInfo.FileEndpoint.Replace("{id}", mediaId); var http = new HttpRequest(url, HttpVerb.GET) - .WithHeader("ETag", "") + .WithHeader("If-None-Match", eTag) .Send(); httpHandlers.Add(http); @@ -257,16 +263,74 @@ namespace RothenburgAR.Updater return; } - var x = http; + // do nothing if unchanged + if (http.Request.responseCode == 304) return; - //TODO unzip - var type = http.Request.GetResponseHeader("Content-Type"); + // gzipped files are un-gzipped automagically File.WriteAllBytes(filepath, http.Download.data); + + var subfilesHeader = http.Request.GetResponseHeader("subfiles"); + if (subfilesHeader != null) + { + string[] separator = new string[1] { ";;" }; + var subfiles = subfilesHeader.Split(separator, StringSplitOptions.RemoveEmptyEntries); + foreach (var subfile in subfiles) + { + UpdateSubfile(path, mediaId, subfile); + } + } + Debug.Log(string.Format("{1}-DONE with {0}", url, Time.realtimeSinceStartup)); }; } } + private string GenerateETag(string filepath) + { + string eTag = ""; + if (File.Exists(filepath)) + { + var bytes = File.ReadAllBytes(filepath); + SHA256Managed hasher = new SHA256Managed(); + byte[] hash = hasher.ComputeHash(bytes); + eTag = "sha256-"; + foreach (byte x in hash) + { + eTag += String.Format("{0:x2}", x); + } + } + return eTag; + } + + private void UpdateSubfile(string path, string mediaId, string subfile) + { + var filepath = Path.Combine(path, subfile); + var eTag = GenerateETag(filepath); + + var url = ApiInfo.FileEndpoint.Replace("{id}", mediaId) + "/" + subfile; + var http = new HttpRequest(url, HttpVerb.GET) + .WithHeader("If-None-Match", eTag) + .Send(); + + httpHandlers.Add(http); + + http.Operation.completed += ar => + { + if (CheckNetworkErrors(http)) + { + return; + } + + // do nothing if unchanged + if (http.Request.responseCode == 304) return; + + // gzipped files are un-gzipped automagically + File.WriteAllBytes(filepath, http.Download.data); + + Debug.Log(string.Format("{1}-DONE with {0}", url, Time.realtimeSinceStartup)); + }; + } + private bool CheckNetworkErrors(HttpHandler http) { if (http.Request.isNetworkError || http.Request.isHttpError)