// -------------------------------------------------------------------------------------------------------------------- // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // // // The Update Service // // -------------------------------------------------------------------------------------------------------------------- namespace HandBrakeWPF.Services { using System; using System.IO; using System.Net; using System.Threading; using HandBrake.ApplicationServices.Utilities; using HandBrake.ApplicationServices.Interop; using HandBrakeWPF.Model; using HandBrakeWPF.Services.Interfaces; using AppcastReader = HandBrakeWPF.Utilities.AppcastReader; /// /// The Update Service /// public class UpdateService : IUpdateService { #region Constants and Fields /// /// Backing field for the update service /// private readonly IUserSettingService userSettingService; #endregion #region Constructors and Destructors /// /// Initializes a new instance of the class. /// /// /// The user setting service. /// public UpdateService(IUserSettingService userSettingService) { this.userSettingService = userSettingService; } #endregion #region Public Methods /// /// Perform an update check at application start, but only daily, weekly or monthly depending on the users settings. /// /// /// The callback. /// public void PerformStartupUpdateCheck(Action callback) { // Make sure it's running on the calling thread if (this.userSettingService.GetUserSetting(UserSettingConstants.UpdateStatus)) { DateTime lastUpdateCheck = this.userSettingService.GetUserSetting(UserSettingConstants.LastUpdateCheckDate); int checkFrequency = this.userSettingService.GetUserSetting(UserSettingConstants.DaysBetweenUpdateCheck) == 0 ? 7 : 30; if (DateTime.Now.Subtract(lastUpdateCheck).TotalDays > checkFrequency) { this.userSettingService.SetUserSetting(UserSettingConstants.LastUpdateCheckDate, DateTime.Now); this.CheckForUpdates(callback); } } } /// /// Check for Updates /// /// /// The callback. /// public void CheckForUpdates(Action callback) { ThreadPool.QueueUserWorkItem( delegate { try { string url = VersionHelper.Is64Bit() || Environment.Is64BitOperatingSystem ? Constants.Appcast64 : Constants.Appcast32; if (VersionHelper.IsNightly()) { url = VersionHelper.Is64Bit() || Environment.Is64BitOperatingSystem ? Constants.AppcastUnstable64 : Constants.AppcastUnstable32; } var currentBuild = HandBrakeUtils.Build; var skipBuild = this.userSettingService.GetUserSetting(UserSettingConstants.Skipversion); // Initialize variables WebRequest request = WebRequest.Create(url); WebResponse response = request.GetResponse(); var reader = new AppcastReader(); // Get the data, convert it to a string, and parse it into the AppcastReader reader.GetUpdateInfo(new StreamReader(response.GetResponseStream()).ReadToEnd()); // Further parse the information string build = reader.Build; int latest = int.Parse(build); int current = currentBuild; int skip = skipBuild; // If the user wanted to skip this version, don't report the update if (latest == skip) { var info = new UpdateCheckInformation { NewVersionAvailable = false }; callback(info); return; } var info2 = new UpdateCheckInformation { NewVersionAvailable = latest > current, DescriptionUrl = reader.DescriptionUrl, DownloadFile = reader.DownloadFile, Build = reader.Build, Version = reader.Version, }; callback(info2); } catch (Exception exc) { callback(new UpdateCheckInformation { NewVersionAvailable = false, Error = exc }); } }); } /// /// Download the update file. /// /// /// The url. /// /// /// The complete. /// /// /// The progress. /// public void DownloadFile(string url, Action completed, Action 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; HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse(); long fileSize = webResponse.ContentLength; Stream responceStream = wcDownload.OpenRead(url); Stream localStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.None); int bytesSize; byte[] downBuffer = new byte[2048]; long flength = 0; while ((bytesSize = responceStream.Read(downBuffer, 0, downBuffer.Length)) > 0) { localStream.Write(downBuffer, 0, bytesSize); flength = localStream.Length; progress(new DownloadStatus { BytesRead = localStream.Length, TotalBytes = fileSize}); } responceStream.Close(); localStream.Close(); completed( flength != fileSize ? new DownloadStatus { WasSuccessful = false, Message = "Partial Download. File is Incomplete. Please Retry the download." } : new DownloadStatus { WasSuccessful = true, Message = "Download Complete." }); } catch (Exception exc) { progress(new DownloadStatus { WasSuccessful = false, Exception = exc, Message = "Download Failed." }); } }); } #endregion } }