/// <summary> /// Downloads the provided manifest entry. /// This function resumes incomplete files, verifies downloaded files and /// downloads missing files. /// </summary> /// <param name="Entry">The entry to download.</param> /// <param name="Module">The module to download the file for. Determines download location.</param> private void DownloadEntry(ManifestEntry Entry, EModule Module) { ModuleDownloadProgressArgs.Module = Module; string baseRemotePath; string baseLocalPath; if (Module == EModule.Game) { baseRemotePath = Config.GetGameURL(); baseLocalPath = Config.GetGamePath(); } else { baseRemotePath = Config.GetLauncherBinariesURL(); baseLocalPath = ConfigHandler.GetTempLauncherDownloadPath(); } string RemotePath = String.Format("{0}{1}", baseRemotePath, Entry.RelativePath); string LocalPath = String.Format("{0}{1}{2}", baseLocalPath, Path.DirectorySeparatorChar, Entry.RelativePath); // Make sure we have a directory to put the file in Directory.CreateDirectory(Path.GetDirectoryName(LocalPath)); // Reset the cookie File.WriteAllText(ConfigHandler.GetInstallCookiePath(), String.Empty); // Write the current file progress to the install cookie using (TextWriter textWriterProgress = new StreamWriter(ConfigHandler.GetInstallCookiePath())) { textWriterProgress.WriteLine(Entry); textWriterProgress.Flush(); } if (File.Exists(LocalPath)) { FileInfo fileInfo = new FileInfo(LocalPath); if (fileInfo.Length != Entry.Size) { // If the file is partial, resume the download. if (fileInfo.Length < Entry.Size) { DownloadRemoteFile(RemotePath, LocalPath, fileInfo.Length); } else { // If it's larger than expected, toss it in the bin and try again. File.Delete(LocalPath); DownloadRemoteFile(RemotePath, LocalPath); } } else { string LocalHash; using (FileStream fs = File.OpenRead(LocalPath)) { LocalHash = MD5Handler.GetStreamHash(fs); } if (LocalHash != Entry.Hash) { File.Delete(LocalPath); DownloadRemoteFile(RemotePath, LocalPath); } } } else { //no file, download it DownloadRemoteFile(RemotePath, LocalPath); } if (ChecksHandler.IsRunningOnUnix()) { //if we're dealing with a file that should be executable, string gameName = Config.GetGameName(); bool bFileIsGameExecutable = (Path.GetFileName(LocalPath).EndsWith(".exe")) || (Path.GetFileName(LocalPath) == gameName); if (bFileIsGameExecutable) { //set the execute bits UnixHandler.MakeExecutable(LocalPath); } } // We've finished the download, so empty the cookie File.WriteAllText(ConfigHandler.GetInstallCookiePath(), String.Empty); }
protected virtual void DownloadManifestEntry(ManifestEntry Entry, EModule Module) { ModuleDownloadProgressArgs.Module = Module; string baseRemoteURL; string baseLocalPath; switch (Module) { case EModule.Launcher: { baseRemoteURL = Config.GetLauncherBinariesURL(); baseLocalPath = ConfigHandler.GetTempLauncherDownloadPath(); break; } case EModule.Game: { baseRemoteURL = Config.GetGameURL(); baseLocalPath = Config.GetGamePath(); break; } default: { throw new ArgumentOutOfRangeException(nameof(Module), Module, "The module passed to DownloadManifestEntry was invalid."); } } // Build the access strings string remoteURL = $"{baseRemoteURL}{Entry.RelativePath}"; string localPath = $"{baseLocalPath}{Path.DirectorySeparatorChar}{Entry.RelativePath}"; // Make sure we have a directory to put the file in if (Path.GetDirectoryName(localPath) != null) { Directory.CreateDirectory(Path.GetDirectoryName(localPath)); } else { throw new ArgumentNullException(nameof(localPath), "The local path was null."); } // Reset the cookie File.WriteAllText(ConfigHandler.GetInstallCookiePath(), string.Empty); // Write the current file progress to the install cookie using (TextWriter textWriterProgress = new StreamWriter(ConfigHandler.GetInstallCookiePath())) { textWriterProgress.WriteLine(Entry); textWriterProgress.Flush(); } if (File.Exists(localPath)) { FileInfo fileInfo = new FileInfo(localPath); if (fileInfo.Length != Entry.Size) { // If the file is partial, resume the download. if (fileInfo.Length < Entry.Size) { Log.Info($"Resuming interrupted file \"{Path.GetFileNameWithoutExtension(Entry.RelativePath)}\" at byte {fileInfo.Length}."); DownloadRemoteFile(remoteURL, localPath, Entry.Size, fileInfo.Length); } else { // If it's larger than expected, toss it in the bin and try again. Log.Info($"Restarting interrupted file \"{Path.GetFileNameWithoutExtension(Entry.RelativePath)}\": File bigger than expected."); File.Delete(localPath); DownloadRemoteFile(remoteURL, localPath, Entry.Size); } } else { string localHash; using (FileStream fs = File.OpenRead(localPath)) { localHash = MD5Handler.GetStreamHash(fs); } if (localHash != Entry.Hash) { // If the hash doesn't match, toss it in the bin and try again. Log.Info($"Redownloading file \"{Path.GetFileNameWithoutExtension(Entry.RelativePath)}\": " + $"Hash sum mismatch. Local: {localHash}, Expected: {Entry.Hash}"); File.Delete(localPath); DownloadRemoteFile(remoteURL, localPath, Entry.Size); } } } else { // No file, download it DownloadRemoteFile(remoteURL, localPath, Entry.Size); } if (ChecksHandler.IsRunningOnUnix()) { // If we're dealing with a file that should be executable, string gameName = Config.GetGameName(); bool bFileIsGameExecutable = (Path.GetFileName(localPath).EndsWith(".exe")) || (Path.GetFileName(localPath) == gameName); if (bFileIsGameExecutable) { // Set the execute bits UnixHandler.MakeExecutable(localPath); } } // We've finished the download, so empty the cookie File.WriteAllText(ConfigHandler.GetInstallCookiePath(), string.Empty); }