/// <summary> /// Download the update file. /// </summary> /// <param name="url"> /// The url. /// </param> /// <param name="expectedSignature"> /// The expected DSA SHA265 Signature /// </param> /// <param name="completed"> /// The complete. /// </param> /// <param name="progress"> /// The progress. /// </param> public void DownloadFile(string url, string expectedSignature, Action <DownloadStatus> completed, Action <DownloadStatus> progress) { ThreadPool.QueueUserWorkItem( delegate { string tempPath = Path.Combine(Path.GetTempPath(), "handbrake-setup.exe"); WebClient wcDownload = new WebClient(); try { if (File.Exists(tempPath)) { File.Delete(tempPath); } HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Credentials = CredentialCache.DefaultCredentials; webRequest.UserAgent = string.Format("HandBrake Win Upd {0}", HandBrakeVersionHelper.GetVersionShort()); HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); long fileSize = webResponse.ContentLength; Stream responseStream = wcDownload.OpenRead(url); Stream localStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.None); int bytesSize; byte[] downBuffer = new byte[2048]; while ((bytesSize = responseStream.Read(downBuffer, 0, downBuffer.Length)) > 0) { localStream.Write(downBuffer, 0, bytesSize); progress(new DownloadStatus { BytesRead = localStream.Length, TotalBytes = fileSize }); } responseStream.Close(); localStream.Close(); completed( this.VerifyDownload(expectedSignature, tempPath) ? new DownloadStatus { WasSuccessful = true, Message = "Download Complete." } : new DownloadStatus { WasSuccessful = false, Message = "Download Failed. Checksum Failed. Please visit the website to download this update." }); } catch (Exception exc) { progress(new DownloadStatus { WasSuccessful = false, Exception = exc, Message = "Download Failed. Please visit the website to download this update." }); } }); }
/// <summary> /// Check for Updates /// </summary> /// <param name="callback"> /// The callback. /// </param> public void CheckForUpdates(Action <UpdateCheckInformation> callback) { ThreadPool.QueueUserWorkItem( delegate { try { // Figure out which appcast we want to read. string url = SystemInfo.IsArmDevice ? Constants.Appcast64Arm : Constants.Appcast64; if (HandBrakeVersionHelper.IsNightly()) { url = SystemInfo.IsArmDevice ? Constants.AppcastUnstable64Arm : Constants.AppcastUnstable64; } // Fetch the Appcast from our server. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.AllowAutoRedirect = false; // We will never do this. request.UserAgent = string.Format("HandBrake Win Upd {0}", HandBrakeVersionHelper.GetVersionShort()); WebResponse response = request.GetResponse(); // Parse the data with the AppcastReader var reader = new AppcastReader(); reader.GetUpdateInfo(new StreamReader(response.GetResponseStream()).ReadToEnd()); // Further parse the information string build = reader.Build; int latest = int.Parse(build); // Security Check // Verify the download URL is for handbrake.fr and served over https. // This prevents a compromised appcast download tricking the GUI into downloading a file, or accessing another website or local network resource. // The download itself will also be checked against a signature later. Uri uriResult; bool result = Uri.TryCreate(reader.DownloadFile, UriKind.Absolute, out uriResult) && uriResult.Scheme == Uri.UriSchemeHttps; if (!result || (uriResult.Host != "handbrake.fr" && uriResult.Host != "download.handbrake.fr" && uriResult.Host != "github.com")) { this.userSettingService.SetUserSetting(UserSettingConstants.IsUpdateAvailableBuild, 0); callback(new UpdateCheckInformation { NewVersionAvailable = false, Error = new Exception("The HandBrake update service is currently unavailable.") }); return; } // Validate the URL from the appcast is ours. var info2 = new UpdateCheckInformation { NewVersionAvailable = latest > HandBrakeVersionHelper.Build, DescriptionUrl = reader.DescriptionUrl, DownloadFile = reader.DownloadFile, Build = reader.Build, Version = reader.Version, Signature = reader.Hash }; this.userSettingService.SetUserSetting(UserSettingConstants.IsUpdateAvailableBuild, latest); callback(info2); } catch (Exception exc) { this.userSettingService.SetUserSetting(UserSettingConstants.IsUpdateAvailableBuild, 0); callback(new UpdateCheckInformation { NewVersionAvailable = false, Error = exc }); } }); }