예제 #1
0
        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;
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
 public string UpdateFilePath(UpdateFile uf)
 {
     return(_updateDir + Path.DirectorySeparatorChar + uf.SHA1 + ".gz");
 }
예제 #5
0
        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...");
                    }
                }
            }
        }