/// <summary>
        /// Calculates estimated update size in bytes based on local and remote build information.
        /// </summary>
        /// <returns>The estimated update size in bytes.</returns>
        private long GetUpdateSize()
        {
            // We don't take into account potential local modified or corrupted files,
            // instead we assume that all files listed in the local build info match
            // the actual files on the local file system.
            // This is because checking the actual hashes of the files would take too
            // long for a quick update check. Instead we'll check the actual file
            // hashes when actually downloading the update.
            // This is why the calculated update size could only be an estimate
            // (although it'll be correct for everyone who doesn't modify the product).

            long updateSize = 0;

            LocalBuildInfo  lbi = localBuildInfo;
            RemoteBuildInfo rbi = remoteBuildInfo;

            foreach (var fileInfo in rbi.FileInfos)
            {
                var localMatch = lbi.FileInfos.Find(localFileInfo => localFileInfo.FilePath == fileInfo.FilePath);

                if (localMatch == null || !HashHelper.ByteArraysMatch(localMatch.Hash, fileInfo.UncompressedHash))
                {
                    updateSize += fileInfo.GetDownloadSize();
                }
            }

            return(updateSize);
        }
예제 #2
0
        /// <summary>
        /// Cleans the build directory from files that don't exist in the list
        /// of files for the build.
        /// </summary>
        public void CleanBuildDirectory()
        {
            char   dsc            = Path.DirectorySeparatorChar;
            string buildDirectory = Environment.CurrentDirectory + dsc + BuildDirectory;

            string[] files = Directory.GetFiles(buildDirectory, "*", SearchOption.AllDirectories);

            RemoteBuildInfo remoteBuildInfo = new RemoteBuildInfo();

            if (File.Exists(buildDirectory + dsc + BuildHandler.REMOTE_BUILD_INFO_FILE))
            {
                remoteBuildInfo.Parse(buildDirectory + dsc + BuildHandler.REMOTE_BUILD_INFO_FILE);
            }

            foreach (string path in files)
            {
                string relativePath = path.Substring(buildDirectory.Length + 1);

                if (relativePath == BuildHandler.LOCAL_BUILD_INFO_FILE ||
                    relativePath == BuildHandler.REMOTE_BUILD_INFO_FILE)
                {
                    continue;
                }

                if (remoteBuildInfo.FileInfos.Find(f => f.GetFilePathWithCompression() ==
                                                   relativePath) == null)
                {
                    Console.WriteLine("Deleting " + relativePath);
                    File.Delete(path);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Writes new local and remote version files into the build directory.
        /// </summary>
        public void WriteVersionFiles()
        {
            var localBuildInfo = new LocalBuildInfo();

            localBuildInfo.ProductVersionInfo = new ProductVersionInfo(InternalVersion, DisplayedVersion);

            var remoteBuildInfo = new RemoteBuildInfo();

            remoteBuildInfo.ProductVersionInfo = new ProductVersionInfo(InternalVersion, DisplayedVersion);

            string buildPath = Environment.CurrentDirectory +
                               Path.DirectorySeparatorChar + BuildDirectory + Path.DirectorySeparatorChar;

            foreach (FileEntry file in FileEntries)
            {
                string originalFilePath = Environment.CurrentDirectory +
                                          Path.DirectorySeparatorChar + file.FilePath;

                byte[] hash = HashHelper.ComputeHashForFile(originalFilePath);
                long   size = new FileInfo(originalFilePath).Length;
                localBuildInfo.AddFileInfo(new LocalFileInfo(file.FilePath, hash, size));

                RemoteFileInfo remoteFileInfo;

                if (file.Compressed)
                {
                    string compressedFilePath = buildPath + file.FilePath + RemoteFileInfo.COMPRESSED_FILE_EXTENSION;
                    remoteFileInfo = new RemoteFileInfo(file.FilePath, hash, size, true,
                                                        HashHelper.ComputeHashForFile(compressedFilePath),
                                                        new FileInfo(compressedFilePath).Length);
                }
                else
                {
                    remoteFileInfo = new RemoteFileInfo(file.FilePath, hash, size, false);
                }

                remoteBuildInfo.AddFileInfo(remoteFileInfo);
            }

            localBuildInfo.Write(buildPath + BuildHandler.LOCAL_BUILD_INFO_FILE);
            remoteBuildInfo.Write(buildPath + BuildHandler.REMOTE_BUILD_INFO_FILE);
        }
        private void CheckForUpdatesInternal()
        {
            UpdaterLogger.Log("Checking for updates.");

            updateMirrors = updateMirrors.OrderBy(um => um.Rating).ToList();

            using (WebClient webClient = CreateWebClient())
            {
                webClient.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
                webClient.Encoding    = Encoding.GetEncoding(1252);

                CreateTemporaryDirectory();

                int i = 0;

                UpdateMirror updateMirror;

                string downloadDirectory = localBuildInfo.BuildPath + TEMPORARY_UPDATER_DIRECTORY + Path.DirectorySeparatorChar;

                while (i < updateMirrors.Count)
                {
                    updateMirror = updateMirrors[i];
                    UpdaterLogger.Log("Attempting to download version information from " +
                                      updateMirror.UIName + " (" + updateMirror.URL + ")");

                    try
                    {
                        webClient.DownloadFile(updateMirror.URL + REMOTE_BUILD_INFO_FILE, downloadDirectory + REMOTE_BUILD_INFO_FILE);

                        UpdaterLogger.Log("Version information downloaded, proceeding to parsing it.");

                        remoteBuildInfo = new RemoteBuildInfo();
                        remoteBuildInfo.Parse(downloadDirectory + REMOTE_BUILD_INFO_FILE);

                        lastUpdateMirrorId = i;

                        lock (locker)
                        {
                            updateCheckInProgress = false;
                        }

                        if (remoteBuildInfo.ProductVersionInfo.VersionNumber == localBuildInfo.ProductVersionInfo.VersionNumber)
                        {
                            BuildState = BuildState.UPTODATE;
                            BuildUpToDate?.Invoke(this, EventArgs.Empty);
                            return;
                        }
                        else
                        {
                            BuildState = BuildState.OUTDATED;
                            BuildOutdated?.Invoke(this, new BuildOutdatedEventArgs(
                                                      remoteBuildInfo.ProductVersionInfo.DisplayString, GetUpdateSize()));
                            return;
                        }
                    }
                    catch (WebException ex)
                    {
                        UpdaterLogger.Log("WebException when downloading version information: " + ex.Message);
                        i++;
                    }
                    catch (ParseException ex)
                    {
                        UpdaterLogger.Log("ParseException when parsing version information: " + ex.Message);
                        i++;
                    }
                    catch (FormatException ex)
                    {
                        UpdaterLogger.Log("FormatException when parsing version information: " + ex.Message);
                        i++;
                    }
                }
            }

            UpdaterLogger.Log("Failed to download version information from all update mirrors. Aborting.");

            lock (locker)
            {
                updateCheckInProgress = false;
            }

            UpdateCheckFailed?.Invoke(this, EventArgs.Empty);
        }
예제 #5
0
        /// <summary>
        /// Gathers a list of files that do not exist or are outdated in the
        /// build directory.
        /// </summary>
        public List <FileEntry> GetOutdatedFileList()
        {
            string targetDirectory = Environment.CurrentDirectory +
                                     Path.DirectorySeparatorChar + BuildDirectory;

            // If the build directory doesn't exist, we need to process all the files
            if (!Directory.Exists(targetDirectory))
            {
                return(new List <FileEntry>(FileEntries));
            }

            if (targetDirectory[targetDirectory.Length - 1] != Path.DirectorySeparatorChar)
            {
                targetDirectory = targetDirectory + Path.DirectorySeparatorChar;
            }

            RemoteBuildInfo remoteBuildInfo = new RemoteBuildInfo();

            if (File.Exists(targetDirectory + BuildHandler.REMOTE_BUILD_INFO_FILE))
            {
                remoteBuildInfo.Parse(targetDirectory + BuildHandler.REMOTE_BUILD_INFO_FILE);
            }

            List <FileEntry> outdatedList = new List <FileEntry>();

            foreach (FileEntry file in FileEntries)
            {
                string filePath         = targetDirectory + file.FilePath;
                string originalFilePath = Environment.CurrentDirectory + Path.DirectorySeparatorChar + file.FilePath;

                if (file.Compressed)
                {
                    // Compressed files have an additional file extension
                    filePath = filePath + RemoteFileInfo.COMPRESSED_FILE_EXTENSION;
                }

                if (!File.Exists(filePath))
                {
                    // If the file doesn't exist in the build, we obviously need
                    // to process it
                    outdatedList.Add(file);
                    continue;
                }

                if (file.Compressed)
                {
                    // If the file is compressed, check if the uncompressed hash
                    // in RemoteVersion matches the hash of the original (uncompressed) file
                    // If not (or there is no record of the file in RemoteVersion), we need
                    // to process the file

                    RemoteFileInfo existingFileInfo = remoteBuildInfo.FileInfos.Find(
                        f => f.FilePath == file.FilePath);

                    if (existingFileInfo == null ||
                        !HashHelper.ByteArraysMatch(existingFileInfo.UncompressedHash,
                                                    HashHelper.ComputeHashForFile(originalFilePath)))
                    {
                        outdatedList.Add(file);
                    }
                }
                else
                {
                    // For uncompressed files we can just compare its hash
                    // to the original file's hash directly

                    if (!HashHelper.ByteArraysMatch(HashHelper.ComputeHashForFile(filePath),
                                                    HashHelper.ComputeHashForFile(originalFilePath)))
                    {
                        outdatedList.Add(file);
                    }
                }
            }

            return(outdatedList);
        }