private VersionIntegrity CheckIntegrity( PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken, int installedVersionId ) { ICheckVersionIntegrityCommand checkIntegrity = _commandFactory .CreateCheckVersionIntegrityCommand( versionId: installedVersionId, context: Context, isCheckingHash: CheckHashes, isCheckingSize: true, cancellationToken: cancellationToken); checkIntegrity.Prepare(_status, cancellationToken); checkIntegrity.Execute(cancellationToken); return(checkIntegrity.Results); }
private bool IsVersionIntegral(long contentSize, AppUpdaterContext context, CancellationToken cancellationToken) { var commandFactory = new AppUpdaterCommandFactory(); int installedVersionId = context.App.GetInstalledVersionId(); _logger.LogTrace("installedVersionId = " + installedVersionId); _logger.LogTrace("context.Configuration.HashSizeThreshold = " + context.Configuration.HashSizeThreshold); bool isCheckingHash = contentSize < context.Configuration.HashSizeThreshold; _logger.LogTrace("isCheckingHash = " + isCheckingHash); var checkVersionIntegrity = commandFactory.CreateCheckVersionIntegrityCommand( installedVersionId, context, isCheckingHash, true, cancellationToken); checkVersionIntegrity.Prepare(_status, cancellationToken); checkVersionIntegrity.Execute(CancellationToken.Empty); bool isValid = checkVersionIntegrity.Results.Files.All( fileIntegrity => fileIntegrity.Status == FileIntegrityStatus.Ok); if (!isValid) { foreach (var fileIntegrity in checkVersionIntegrity.Results.Files) { if (fileIntegrity.Status != FileIntegrityStatus.Ok) { string logMessage = string.Format("File {0} is not consistent - {1}", fileIntegrity.FileName, fileIntegrity.Status); if (!string.IsNullOrEmpty(fileIntegrity.Message)) { logMessage += " - " + fileIntegrity.Message; } _logger.LogDebug(logMessage); } } } return(isValid); }
private bool IsCheckIntegrityValid(AppUpdaterContext context) { var commandFactory = new AppUpdaterCommandFactory(); int installedVersionId = context.App.GetInstalledVersionId(); long contentCost = GetContentCost(context); // bytes long sizeThreshold = context.Configuration.HashSizeThreshold; bool isCheckingHash = contentCost < sizeThreshold; DebugLogger.LogFormat("IsCheckingHash: {0}, for content size: {1} and contentSizeThreshold: {2}", isCheckingHash, contentCost, sizeThreshold); var checkVersionIntegrity = commandFactory.CreateCheckVersionIntegrityCommand( installedVersionId, context, isCheckingHash); checkVersionIntegrity.Prepare(context.StatusMonitor); checkVersionIntegrity.Execute(CancellationToken.Empty); bool isValid = checkVersionIntegrity.Results.Files.All( fileIntegrity => fileIntegrity.Status == FileIntegrityStatus.Ok); if (isValid) { DebugLogger.Log("Version is consistent. Diff update is allowed."); } else { foreach (var fileIntegrity in checkVersionIntegrity.Results.Files) { if (fileIntegrity.Status != FileIntegrityStatus.Ok) { DebugLogger.Log(string.Format("File {0} is not consistent - {1}", fileIntegrity.FileName, fileIntegrity.Status)); } } DebugLogger.Log( "Version is not consistent. Diff update is forbidden - using content strategy."); } return(isValid); }
public void Update(CancellationToken cancellationToken) { _logger.LogDebug("Executing content repair strategy."); var installedVersionId = _context.App.GetInstalledVersionId(); string metaDestination = _context.App.DownloadDirectory.GetDiffPackageMetaPath(installedVersionId); var commandFactory = new AppUpdaterCommandFactory(); var validateLicense = commandFactory.CreateValidateLicenseCommand(_context); validateLicense.Prepare(_status, cancellationToken); validateLicense.Execute(cancellationToken); var geolocateCommand = commandFactory.CreateGeolocateCommand(); geolocateCommand.Prepare(_status, cancellationToken); geolocateCommand.Execute(cancellationToken); var resource = _context.App.RemoteData.GetContentPackageResource( installedVersionId, validateLicense.KeySecret, geolocateCommand.CountryCode, cancellationToken); if (!resource.HasMetaUrls()) { throw new ArgumentException("Cannot execute content repair strategy without meta files."); } _logger.LogDebug("Downloading the meta file."); var downloader = new HttpDownloader(metaDestination, resource.GetMetaUrls()); downloader.Download(cancellationToken); ICheckVersionIntegrityCommand checkVersionIntegrityCommand = commandFactory.CreateCheckVersionIntegrityCommand(installedVersionId, _context, true, true, cancellationToken); checkVersionIntegrityCommand.Prepare(_status, cancellationToken); checkVersionIntegrityCommand.Execute(cancellationToken); var meta = Pack1Meta.ParseFromFile(metaDestination); FileIntegrity[] filesIntegrity = checkVersionIntegrityCommand.Results.Files; var contentSummary = _context.App.RemoteMetaData.GetContentSummary(installedVersionId, cancellationToken); foreach (var invalidVersionIdFile in filesIntegrity.Where(x => x.Status == FileIntegrityStatus.InvalidVersion).ToArray()) { var fileName = invalidVersionIdFile.FileName; var file = contentSummary.Files.First(x => x.Path == fileName); var localPath = _context.App.LocalDirectory.Path.PathCombine(file.Path); string actualFileHash = HashCalculator.ComputeFileHash(localPath); if (actualFileHash != file.Hash) { FileOperations.Delete(localPath, cancellationToken); _context.App.LocalMetaData.RegisterEntry(fileName, installedVersionId); invalidVersionIdFile.Status = FileIntegrityStatus.MissingData; } else { _context.App.LocalMetaData.RegisterEntry(fileName, installedVersionId); invalidVersionIdFile.Status = FileIntegrityStatus.Ok; } } Pack1Meta.FileEntry[] brokenFiles = filesIntegrity // Filter only files with invalid size, hash or missing entirely .Where(f => f.Status == FileIntegrityStatus.InvalidHash || f.Status == FileIntegrityStatus.InvalidSize || f.Status == FileIntegrityStatus.MissingData) // Map to file entires from meta .Select(integrity => meta.Files.SingleOrDefault(file => file.Name == integrity.FileName)) // Filter only regular files .Where(file => file.Type == Pack1Meta.RegularFileType) .ToArray(); if (brokenFiles.Length == 0) { _logger.LogDebug("Nothing to repair."); return; } _logger.LogDebug(string.Format("Broken files count: {0}", brokenFiles.Length)); IRepairFilesCommand repairCommand = commandFactory.CreateRepairFilesCommand( installedVersionId, _context, resource, brokenFiles, meta); repairCommand.Prepare(_status, cancellationToken); repairCommand.Execute(cancellationToken); }
private void PreUpdate(PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken) { DebugLogger.Log("Pre update integrity check"); var commandFactory = new AppUpdaterCommandFactory(); int installedVersionId = Context.App.GetInstalledVersionId(); int latestVersionId = Context.App.GetLatestVersionId(); int lowestVersionWithContentId = Context.App.GetLowestVersionWithContentId(); if (lowestVersionWithContentId > installedVersionId) { DebugLogger.Log( "Repair is impossible because lowest version with content id is " + lowestVersionWithContentId + " and currently installed version id is " + installedVersionId + ". Uninstalling to prepare for content strategy."); IUninstallCommand uninstall = commandFactory.CreateUninstallCommand(Context); uninstall.Prepare(_status); uninstall.Execute(cancellationToken); return; } AppContentSummary installedVersionContentSummary = Context.App.RemoteMetaData.GetContentSummary(installedVersionId); AppContentSummary latestVersionContentSummary = Context.App.RemoteMetaData.GetContentSummary(latestVersionId); bool isNewVersionAvailable = installedVersionId < latestVersionId; long contentSize = isNewVersionAvailable ? latestVersionContentSummary.Size : installedVersionContentSummary.Size; ICheckVersionIntegrityCommand checkIntegrity = commandFactory .CreateCheckVersionIntegrityCommand( versionId: installedVersionId, context: Context, isCheckingHash: false, isCheckingSize: true); checkIntegrity.Prepare(_status); checkIntegrity.Execute(cancellationToken); var missingFiles = checkIntegrity.Results.Files .Where(f => f.Status == FileIntegrityStatus.MissingData); int missingFilesCount = missingFiles.Count(); var invalidSizeFiles = checkIntegrity.Results.Files .Where(f => f.Status == FileIntegrityStatus.InvalidSize); int invalidSizeFilesCount = invalidSizeFiles.Count(); if (missingFilesCount + invalidSizeFilesCount == 0) { DebugLogger.Log("No missing or invalid size files."); return; } double repairCost = CalculateRepairCost(installedVersionContentSummary, missingFiles.Concat(invalidSizeFiles)); if (repairCost < contentSize) { DebugLogger.Log(string.Format("Repair cost {0} is smaller than content cost {1}, repairing...", repairCost, contentSize)); IAppUpdaterStrategy repairStrategy = _strategyResolver.Create(StrategyType.Repair, Context); repairStrategy.Update(cancellationToken); } else { DebugLogger.Log("Content cost is smaller than repair. Uninstalling to prepare for content strategy."); IUninstallCommand uninstall = commandFactory.CreateUninstallCommand(Context); uninstall.Prepare(_status); uninstall.Execute(cancellationToken); } }
public IAppUpdaterStrategy Resolve(AppUpdaterContext context) { Checks.ArgumentNotNull(context, "context"); DebugLogger.Log("Resolving best strategy for updating..."); if (context.App.IsInstalled()) { int installedVersionId = context.App.GetInstalledVersionId(); int latestVersionId = context.App.GetLatestVersionId(); if (installedVersionId == latestVersionId) { DebugLogger.Log("Installed version is the same as the latest version. Using empty strategy."); return(new AppUpdaterEmptyStrategy()); } if (installedVersionId < latestVersionId) { DebugLogger.Log("Installed version is older than the latest version. Checking whether cost of updating with diff is lower than cost of updating with content..."); if (context.Configuration.CheckConsistencyBeforeDiffUpdate) { DebugLogger.Log("Checking consitency before allowing diff update..."); var commandFactory = new AppUpdaterCommandFactory(); var checkVersionIntegrity = commandFactory.CreateCheckVersionIntegrityCommand( installedVersionId, context); checkVersionIntegrity.Prepare(context.StatusMonitor); checkVersionIntegrity.Execute(CancellationToken.Empty); if (checkVersionIntegrity.Results.Files.All( fileIntegrity => fileIntegrity.Status == FileIntegrityStatus.Ok)) { DebugLogger.Log("Version is consistent. Diff update is allowed."); } else { foreach (var fileIntegrity in checkVersionIntegrity.Results.Files) { if (fileIntegrity.Status != FileIntegrityStatus.Ok) { DebugLogger.Log(string.Format("File {0} is not consistent - {1}", fileIntegrity.FileName, fileIntegrity.Status)); } } DebugLogger.Log( "Version is not consistent. Diff update is forbidden - using content strategy."); return(new AppUpdaterContentStrategy(context)); } } var diffCost = GetDiffCost(context); DebugLogger.LogVariable(diffCost, "diffCost"); DebugLogger.Log(string.Format("Cost of updating with diff equals {0}.", diffCost)); var contentCost = GetContentCost(context); DebugLogger.LogVariable(contentCost, "contentCost"); DebugLogger.Log(string.Format("Cost of updating with content equals {0}.", contentCost)); if (diffCost < contentCost) { DebugLogger.Log("Cost of updating with diff is lower than cost of updating with content. Using diff strategy."); return(new AppUpdaterDiffStrategy(context)); } DebugLogger.Log("Cost of updating with content is lower than cost of updating with diff. Using content strategy."); } else { DebugLogger.Log("Installed version is newer than the latest version. Using content strategy."); } } else { DebugLogger.Log("Application is not installed. Using content strategy."); } return(new AppUpdaterContentStrategy(context)); }