/// <summary> /// Returns a value indicating whether the signature of each package is valid, or not. If a package contains an invalid /// signature, it will be deleted directly. /// </summary> /// <returns>Returns <c>true</c> if the package is valid; otherwise <c>false</c>.</returns> /// <exception cref="FileNotFoundException">The update package to check could not be found.</exception> /// <exception cref="ArgumentException">The signature of the update package is null or empty.</exception> public bool ValidatePackages() { foreach (var filePathItem in _packageFilePaths) { if (!File.Exists(filePathItem.Value)) { throw new FileNotFoundException(string.Format(_lp.PackageFileNotFoundExceptionText, filePathItem.Key.FullText)); } var configuration = PackageConfigurations.First(config => config.LiteralVersion == filePathItem.Key.ToString()); if (configuration.Signature == null || configuration.Signature.Length <= 0) { throw new ArgumentException($"Signature of version \"{configuration}\" is null or empty."); } FileStream stream = File.Open(filePathItem.Value, FileMode.Open); try { RsaManager rsa; try { rsa = new RsaManager(PublicKey); } catch { try { DeletePackages(); Cleanup(); } catch (Exception ex) { throw new PackageDeleteException(ex.Message); } return(false); } if (rsa.VerifyData(stream, Convert.FromBase64String(configuration.Signature))) { continue; } try { DeletePackages(); } catch (Exception ex) { throw new PackageDeleteException(ex.Message); } Cleanup(); return(false); } finally { stream.Close(); } } return(true); }
/// <summary> /// Downloads the available update packages from the server. /// </summary> /// <seealso cref="DownloadPackagesAsync" /> public void DownloadPackages() { OnUpdateDownloadStarted(this, EventArgs.Empty); long received = 0; var total = PackageConfigurations.Select(config => GetUpdatePackageSize(config.UpdatePackageUri)) .Where(updatePackageSize => updatePackageSize != null) .Sum(updatePackageSize => updatePackageSize.Value); if (!Directory.Exists(_applicationUpdateDirectory)) { Directory.CreateDirectory(_applicationUpdateDirectory); } foreach (var updateConfiguration in PackageConfigurations) { WebResponse webResponse = null; try { var webRequest = WebRequestWrapper.Create(updateConfiguration.UpdatePackageUri); if (HttpAuthenticationCredentials != null) { webRequest.Credentials = HttpAuthenticationCredentials; } using (webResponse = webRequest.GetResponse()) { var buffer = new byte[1024]; _packageFilePaths.Add(new UpdateVersion(updateConfiguration.LiteralVersion), Path.Combine(_applicationUpdateDirectory, $"{updateConfiguration.LiteralVersion}.zip")); using (var fileStream = File.Create(Path.Combine(_applicationUpdateDirectory, $"{updateConfiguration.LiteralVersion}.zip"))) { using (var input = webResponse.GetResponseStream()) { if (input == null) { throw new Exception("The response stream couldn't be read."); } var size = input.Read(buffer, 0, buffer.Length); while (size > 0) { fileStream.Write(buffer, 0, size); received += size; OnUpdateDownloadProgressChanged(received, (long)total, (float)(received / total) * 100); size = input.Read(buffer, 0, buffer.Length); } if (_downloadCancellationTokenSource.IsCancellationRequested) { return; } if (!updateConfiguration.UseStatistics || !IncludeCurrentPcIntoStatistics) { continue; } var response = new WebClient { Credentials = HttpAuthenticationCredentials }.DownloadString( $"{updateConfiguration.UpdatePhpFileUri}?versionid={updateConfiguration.VersionId}&os={SystemInformation.OperatingSystemName}"); // Only for calling it if (string.IsNullOrEmpty(response)) { return; } OnStatisticsEntryFailed(new StatisticsException(string.Format( _lp.StatisticsScriptExceptionText, response))); } } } } finally { webResponse?.Close(); } } }
/// <summary> /// Downloads the available update packages from the server, asynchronously. /// </summary> /// <seealso cref="DownloadPackages" /> public async Task DownloadPackagesAsync(IProgress <UpdateDownloadProgressChangedEventArgs> progress) { if (_downloadCancellationTokenSource != null) { _downloadCancellationTokenSource.Dispose(); } _downloadCancellationTokenSource = new CancellationTokenSource(); long received = 0; double total = PackageConfigurations.Select(config => GetUpdatePackageSize(config.UpdatePackageUri)) .Where(updatePackageSize => updatePackageSize != null) .Sum(updatePackageSize => updatePackageSize.Value); if (!Directory.Exists(_applicationUpdateDirectory)) { Directory.CreateDirectory(_applicationUpdateDirectory); } foreach (var updateConfiguration in PackageConfigurations) { WebResponse webResponse = null; try { if (_downloadCancellationTokenSource.Token.IsCancellationRequested) { DeletePackages(); Cleanup(); throw new OperationCanceledException(); } var webRequest = WebRequest.Create(updateConfiguration.UpdatePackageUri); webResponse = await webRequest.GetResponseAsync(); var buffer = new byte[1024]; _packageFilePaths.Add(new UpdateVersion(updateConfiguration.LiteralVersion), Path.Combine(_applicationUpdateDirectory, String.Format("{0}.zip", updateConfiguration.LiteralVersion))); using (FileStream fileStream = File.Create(Path.Combine(_applicationUpdateDirectory, String.Format("{0}.zip", updateConfiguration.LiteralVersion)))) { using (Stream input = webResponse.GetResponseStream()) { if (input == null) { throw new Exception("The response stream couldn't be read."); } if (_downloadCancellationTokenSource.Token.IsCancellationRequested) { DeletePackages(); Cleanup(); throw new OperationCanceledException(); } int size = await input.ReadAsync(buffer, 0, buffer.Length); while (size > 0) { if (_downloadCancellationTokenSource.Token.IsCancellationRequested) { fileStream.Flush(); fileStream.Close(); DeletePackages(); Cleanup(); throw new OperationCanceledException(); } await fileStream.WriteAsync(buffer, 0, size); received += size; progress.Report(new UpdateDownloadProgressChangedEventArgs(received, (long)total, (float)(received / total) * 100)); size = await input.ReadAsync(buffer, 0, buffer.Length); } if (!updateConfiguration.UseStatistics || !IncludeCurrentPcIntoStatistics) { continue; } try { string response = new WebClient().DownloadString(String.Format("{0}?versionid={1}&os={2}", updateConfiguration.UpdatePhpFileUri, updateConfiguration.VersionId, SystemInformation.OperatingSystemName)); // Only for calling it if (!String.IsNullOrEmpty(response)) { throw new StatisticsException(String.Format( _lp.StatisticsScriptExceptionText, response)); } } catch (Exception ex) { throw new StatisticsException(ex.Message); } } } } finally { if (webResponse != null) { webResponse.Close(); } } } }
private void NewUpdateDialog_Load(object sender, EventArgs e) { if (!String.IsNullOrEmpty(LanguageFilePath)) { try { _lp = Serializer.Deserialize <LocalizationProperties>(File.ReadAllText(LanguageFilePath)); } catch (Exception) { _lp = new LocalizationProperties(); } } else if (String.IsNullOrEmpty(LanguageFilePath) && LanguageName != "en") { string resourceName = String.Format("nUpdate.Core.Localization.{0}.json", LanguageName); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) { _lp = Serializer.Deserialize <LocalizationProperties>(stream); } } else if (String.IsNullOrEmpty(LanguageFilePath) && LanguageName == "en") { _lp = new LocalizationProperties(); } headerLabel.Text = String.Format(PackageConfigurations.Count() > 1 ? _lp.NewUpdateDialogMultipleUpdatesHeader : _lp.NewUpdateDialogSingleUpdateHeader, PackageConfigurations.Count()); infoLabel.Text = String.Format(_lp.NewUpdateDialogInfoText, Application.ProductName); var availableVersions = PackageConfigurations.Select(item => new UpdateVersion(item.LiteralVersion)).ToArray(); newestVersionLabel.Text = String.Format(_lp.NewUpdateDialogAvailableVersionsText, PackageConfigurations.Count() <= 2 ? String.Join(", ", availableVersions.Select(item => item.FullText)) : String.Format("{0} - {1}", UpdateVersion.GetLowestUpdateVersion(availableVersions).FullText, UpdateVersion.GetHighestUpdateVersion(availableVersions).FullText)); currentVersionLabel.Text = String.Format(_lp.NewUpdateDialogCurrentVersionText, CurrentVersion.FullText); changelogLabel.Text = _lp.NewUpdateDialogChangelogText; cancelButton.Text = _lp.CancelButtonText; installButton.Text = _lp.InstallButtonText; var size = SizeHelper.ConvertSize(PackageSize); updateSizeLabel.Text = String.Format("{0} {1}", String.Format(_lp.NewUpdateDialogSizeText, size.Item1), size.Item2); Icon = _appIcon; Text = Application.ProductName; iconPictureBox.Image = _appIcon.ToBitmap(); iconPictureBox.BackgroundImageLayout = ImageLayout.Center; foreach (var updateConfiguration in PackageConfigurations) { var versionText = new UpdateVersion(updateConfiguration.LiteralVersion).FullText; var changelogText = updateConfiguration.Changelog.ContainsKey(new CultureInfo(LanguageName)) ? updateConfiguration.Changelog.First(item => item.Key.Name == LanguageName).Value : updateConfiguration.Changelog.First(item => item.Key.Name == "en").Value; if (PackageSize > GB) { changelogTextBox.Text += _lp.NewUpdateDialogBigPackageWarning; } changelogTextBox.Text += String.Format(String.IsNullOrEmpty(changelogTextBox.Text) ? "{0}:\n{1}" : "\n\n{0}:\n{1}", versionText, changelogText); } AddShieldToButton(installButton); if (OperationAreas == null || OperationAreas.Count == 0) { accessLabel.Text = String.Format("{0} -", _lp.NewUpdateDialogAccessText); _allowCancel = true; return; } accessLabel.Text = String.Format("{0} {1}", _lp.NewUpdateDialogAccessText, String.Join(", ", LocalizationHelper.GetLocalizedEnumerationValues(_lp, OperationAreas.Cast <object>().GroupBy(item => item).Select(item => item.First()).ToArray()))); _allowCancel = true; }