public long ToDownload(UpdateFile uf) { var ufp = UpdateFilePath(uf); if (!File.Exists(ufp)) { return(uf.Size); } return(uf.Size - new FileInfo(ufp).Length); }
public List <UpdateFile> Run() { List <UpdateFile> reinstall = new List <UpdateFile>(); string baseURL = new Regex("[^/]+$").Replace(manifest.ToString(), ""); OnStatusChanged(new UpdateCheckerEventArgs("Checking for updates...")); Log.Info("Downloading manifest from " + manifest); try { WebRequest req = WebRequest.Create(manifest); if (req == null) { throw new Exception("Invalid URL to manifest: " + manifest); } if (req.GetType() != typeof(HttpWebRequest)) { throw new Exception("WebRequest has invalid type: " + req.GetType()); } req.Timeout = ETag == null ? 30000 : 5000; if (ETag != null) { req.Headers["If-None-Match"] = ETag; } using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) using (MemoryStream ms = new MemoryStream()) using (Stream responseStream = resp.GetResponseStream()) { ETag = resp.Headers["ETag"]; responseStream.CopyTo(ms); responseStream.Close(); byte[] data = ms.ToArray(); string manifestData = System.Text.Encoding.UTF8.GetString(data); OnStatusChanged(new UpdateCheckerEventArgs("Calculating update size...")); foreach (string line in manifestData.Split(new char[] { '\r', '\n' })) { var m = System.Text.RegularExpressions.Regex.Match(line, "^([A-Za-z0-9]{40})\\s+(\\d+)\\s+([\\-\\?]?)(.+)$"); if (!m.Success) { continue; } var sha1 = m.Groups[1].ToString(); var size = Int32.Parse(m.Groups[2].ToString()); var path = m.Groups[4].ToString(); var deleted = m.Groups[3].ToString() == "-"; var anyVersion = m.Groups[3].ToString() == "?"; var uf = new UpdateFile(sha1, size, path, deleted, anyVersion, new Uri(baseURL + sha1 + ".gz")); if (!uf.Validate()) { Log.Info("File failed validation: " + uf.Path); reinstall.Add(uf); } } } return(reinstall); } catch (WebException e) { if (e.Status == WebExceptionStatus.ProtocolError) { HttpStatusCode status = ((HttpWebResponse)e.Response).StatusCode; if (status == HttpStatusCode.NotModified) { OnStatusChanged(new UpdateCheckerEventArgs("Up-to-date.")); return(reinstall); } } Log.Warning("WebException: {0}", e.Message); OnStatusChanged(new UpdateCheckerEventArgs(e.Message)); Thread.Sleep(3000); // allow launching if update check fails if we have an ETag if (ETag != null) { return(reinstall); } throw; } }
private void InstallFile(UpdateFile file) { var updateFilePath = UpdateFilePath(file); Log.Info("Installing {0} from {1}...", file.Path, file.SHA1 + ".gz"); UpdateInstallStatus(true, file.Path); if (file.SHA1 == null && File.Exists(file.Path)) { Log.Info("Skipping {0} because no hash and file exists...", file.Path); return; } string dir = Path.GetDirectoryName(file.Path); if (dir.Length > 0) { Directory.CreateDirectory(dir); } if (File.Exists(file.Path) && Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + file.Path == Application.ExecutablePath) { Log.Warning("Detected update to self, trying to cope with it."); if (File.Exists(Application.ExecutablePath + ".old")) { File.Delete(Application.ExecutablePath + ".old"); } File.Move(Application.ExecutablePath, Application.ExecutablePath + ".old"); } if (file.Size == 0) { using (FileStream ofs = new FileStream(file.Path, FileMode.Create)) { return; } } try { using (FileStream ifs = File.OpenRead(updateFilePath)) using (GZipStream gzs = new GZipStream(ifs, CompressionMode.Decompress)) using (FileStream ofs = new FileStream(file.Path, FileMode.Create)) { gzs.CopyTo(ofs); } } catch (InvalidDataException) { // corrupt downloads and dest files need to be removed File.Delete(updateFilePath); File.Delete(file.Path); throw; } _totalPosition += file.Size; UpdateInstallStatus(true); }
public string UpdateFilePath(UpdateFile uf) { return(_updateDir + Path.DirectorySeparatorChar + uf.SHA1 + ".gz"); }
private void DownloadFile(UpdateFile file) { long pos; int retry = 0; var updateFilePath = UpdateFilePath(file); if (ToDownload(file) == 0) { return; } while (retry < 3) { pos = 0; try { Log.Info("Downloading {0}...", file.URL); string dir = Path.GetDirectoryName(updateFilePath); if (dir.Length > 0) { Directory.CreateDirectory(dir); } if (file.SHA1 == null && File.Exists(file.Path)) { Log.Info("Skipping {0} because no hash and file exists...", file.Path); break; } HttpWebRequest req = (HttpWebRequest)WebRequest.Create(file.URL); req.Timeout = 30000; if (File.Exists(updateFilePath)) { req.AddRange(file.Size - ToDownload(file)); } using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) using (Stream responseStream = resp.GetResponseStream()) using (FileStream fs = new FileStream(updateFilePath, FileMode.Append)) { byte[] buf = new byte[16384]; int i; while ((i = responseStream.Read(buf, 0, buf.Length)) > 0) { fs.Write(buf, 0, i); _totalPosition += i; UpdateDownloadStatus(); } } break; } catch (Exception e) { _totalPosition -= pos; UpdateDownloadStatus(true); if (++retry == 3) { Log.Error(e.ToString(), e.Message); throw e; } else { Log.Warning(e.ToString(), e.Message); Log.Warning("File download failed, retrying..."); } } } }