public static string GetStatusString(bool includeProgress = false) { switch (State) { case UpdateStates.Checking: return(LocalisationManager.GetString(OsuString.CommonUpdater_CheckingForUpdates)); case UpdateStates.Error: if (LastError is MissingFrameworkVersionException) { return(LocalisationManager.GetString(OsuString.GameBase_UpdateFailedFrameworkVersion)); } else { return(LocalisationManager.GetString(OsuString.CommonUpdater_ErrorOccurred)); } case UpdateStates.NeedsRestart: return(LocalisationManager.GetString(OsuString.CommonUpdater_RestartRequired)); case UpdateStates.Updating: lock (ActiveFiles) { totalUpdatableFiles = Math.Max(ActiveFiles.Count, totalUpdatableFiles); string progress = includeProgress && Percentage > 0 ? " (" + (int)Percentage + "%)" : string.Empty; if (ActiveFiles.Count == 0 || totalUpdatableFiles == 0) { return(LocalisationManager.GetString(OsuString.CommonUpdater_PerformingUpdates)); } int runningCount = ActiveFiles.FindAll(f => f.isRunning).Count; if (runningCount > 1) { if (totalUpdatableFiles == ActiveFiles.Count) { return(string.Format(LocalisationManager.GetString(OsuString.CommonUpdater_DownloadingRequiredFiles), totalUpdatableFiles) + progress); } else { //has at least one file finished. return(string.Format(LocalisationManager.GetString(OsuString.CommonUpdater_DownloadingRequiredFiles2), totalUpdatableFiles - ActiveFiles.Count, totalUpdatableFiles) + progress); } } DownloadableFileInfo lastRunning = ActiveFiles.FindLast(f => f.isRunning); if (lastRunning != null) { if (lastRunning.isPatching) { return(String.Format(LocalisationManager.GetString(OsuString.CommonUpdater_PatchingFilePercentage), lastRunning.filename) + progress); } else { return(String.Format(LocalisationManager.GetString(OsuString.CommonUpdater_DownloadingFile), lastRunning.filename + (lastRunning.url_patch != null ? @"_patch" : string.Empty)) + progress); } } return(LocalisationManager.GetString(OsuString.CommonUpdater_PerformingUpdates)); } default: return(LocalisationManager.GetString(OsuString.CommonUpdater_Updated)); } }
private static void smethod_11(DownloadableFileInfo downloadableFileInfo_0) { Class214.list_0.Remove(downloadableFileInfo_0); }
private static UpdateStates doUpdate() { //ensure we have the correct version of .net available. if (ReleaseStream.ToString().Contains(@"40") && !DotNetFramework.CheckInstalled(FrameworkVersion.dotnet4)) { Log(@"Not updating due to missing .NET 4 installation"); LastError = new MissingFrameworkVersionException(FrameworkVersion.dotnet4); return(UpdateStates.Error); } try { ConfigManagerCompact.LoadConfig(); //ensure we are starting clean. //note that we don't clear a pending update just yet because there are scenarios we can use this (see variable stagedAndWaitingToUpdate below). Cleanup(10000, false); List <DownloadableFileInfo> streamFiles = null; string rawString = string.Empty; try { Log(@"Requesting update information..."); var sn = new pWebRequest <List <DownloadableFileInfo> >(string.Format(CENTRAL_UPDATE_URL + @"?action=check&stream={0}&time={1}", ReleaseStream.ToString().ToLower(), DateTime.Now.Ticks)); sn.BlockingPerform(); rawString = sn.ResponseString; if (rawString == @"fallback") { Log(@"Server has requested an emergency fallback!"); return(UpdateStates.EmergencyFallback); } streamFiles = sn.ResponseObject; } catch (Exception e) { LastError = e; LastErrorExtraInformation = rawString; Log(LastError.ToString()); Log(rawString); return(UpdateStates.Error); } if (streamFiles == null || streamFiles.Count == 0) { LastError = new Exception($@"update file returned no results ({rawString})"); Log(LastError.ToString()); return(UpdateStates.Error); } tryAgain: bool stagedAndWaitingToUpdate = Directory.Exists(STAGING_COMPLETE_FOLDER); List <DownloadableFileInfo> updateFiles = new List <DownloadableFileInfo>(); foreach (DownloadableFileInfo file in streamFiles) { if (stagedAndWaitingToUpdate) { Log(@"A pending update is already waiting. Checking what we're working with..."); //special case where we already have a pending update. //if we find *any* file which doesn't match, we should remove the folder and restart the process. string pendingFilename = STAGING_COMPLETE_FOLDER + @"/" + file.filename; if (File.Exists(pendingFilename)) { Log(file.filename + @": PENDING"); //pending file exists and matches this update precisely. if (getMd5(pendingFilename) == file.file_hash) { continue; } } else if (File.Exists(file.filename) && getMd5(file.filename, true) == file.file_hash) { Log(file.filename + @": LATEST"); //current version is already newest. continue; } Log(file.filename + @": MISMATCH"); //something isn't up-to-date. let's run the update process again without our pending version. Reset(false); goto tryAgain; } if (!File.Exists(file.filename)) { updateFiles.Add(file); Log(file.filename + @": NEW"); } else if (getMd5(file.filename, true) != file.file_hash) { Log(file.filename + @": CHANGED (cached)"); updateFiles.Add(file); //cached md5 check failed. } else if (file.filename == @"osu!.exe" && getMd5(file.filename, true) != getMd5(file.filename)) //special intensive check for main osu!.exe { Log(file.filename + @": CHANGED"); ConfigManagerCompact.ResetHashes(); goto tryAgain; } } if (stagedAndWaitingToUpdate) { Log(@"Pending updating is waiting and requires no further changes."); //return early, as we've already done the rest of the process below in a previous run. return(MoveInPlace() ? UpdateStates.Completed : UpdateStates.NeedsRestart); } if (updateFiles.Count == 0) { Log(@"No changes to apply!"); if (!DotNetFramework.CheckInstalled(FrameworkVersion.dotnet4)) { Log(@"Becuase we had no changes, let's let the user know they need a newer framework in the future"); //if there are no pending updates but the user doesn't have dotnet4 available, we should tell them to get it. LastError = new MissingFrameworkVersionException(FrameworkVersion.dotnet4); return(UpdateStates.Error); } return(UpdateStates.NoUpdate); } totalUpdatableFiles = updateFiles.Count; if (!Directory.Exists(STAGING_FOLDER)) { Log(@"Creating staging folder"); DirectoryInfo di = Directory.CreateDirectory(STAGING_FOLDER); di.Attributes = FileAttributes.Directory | FileAttributes.Hidden; } setCallbackStatus(UpdateStates.Updating); lock (ActiveFiles) ActiveFiles.AddRange(updateFiles); foreach (DownloadableFileInfo f in updateFiles) { DownloadableFileInfo file = f; Log(@"Processing {0}...", file.ToString()); if (File.Exists(file.filename)) { Log(@"Exists locally; checking for patchability..."); string localHash = getMd5(file.filename); //check for patchability... try { var sn = new pWebRequest <List <DownloadableFileInfo> >(@"{0}?action=path&stream={1}&target={2}&existing={3}&time={4}", CENTRAL_UPDATE_URL, ReleaseStream.ToString().ToLower(), file.file_version, localHash, DateTime.Now.Ticks); sn.BlockingPerform(); List <DownloadableFileInfo> patchFiles = sn.ResponseObject; if (patchFiles.Count > 1) { Log(@"Server returned {0} patch files", patchFiles.Count.ToString()); //copy the local version to the staging path. File.Copy(file.filename, STAGING_FOLDER + @"/" + file.filename); bool success = false; lock (ActiveFiles) ActiveFiles.AddRange(patchFiles.GetRange(0, patchFiles.Count - 1)); totalUpdatableFiles += patchFiles.Count - 1; try { //we now know we have a patchable path, so let's try patching! foreach (DownloadableFileInfo patch in patchFiles) { try { if (patch.file_version == file.file_version) { Log(@"Reached end of patch chain ({0} / {1}), checking file checksum...", patch.file_version.ToString(), patch.file_hash); //reached the end of patching. if (getMd5(STAGING_FOLDER + @"/" + file.filename) != file.file_hash) { Log(@"Patching FAILED!"); throw new Exception(@"patching failed to end with correct checksum."); } Log(@"Patching success!"); success = true; break; //patching successful! } string localPatchFilename = STAGING_FOLDER + @"/" + patch.filename + @"_patch"; Log(@"Applying patch {0} (to {1})...", patch.file_version.ToString(), patch.file_hash); patch.Perform(true); } finally { lock (ActiveFiles) ActiveFiles.Remove(patch); } } if (success) { lock (ActiveFiles) ActiveFiles.Remove(file); continue; } } finally { lock (ActiveFiles) patchFiles.ForEach(pf => ActiveFiles.Remove(pf)); } } Log(@"No patches available; falling back to full download"); } catch (Exception e) { Log(@"Error occured during patching: " + e); //an error occurred when trying to patch; fallback to a full update. } } Log(@"Beginning download of {0} ({1})...", file.filename, file.url_full); file.PerformThreaded(delegate { lock (ActiveFiles) ActiveFiles.Remove(file); Log(@"Completed download of {0} ({1} files remain)!", file.filename, ActiveFiles.Count); }, delegate { Log(@"Failed download of {0}! Error: {1}", file.filename, file.Error); //error occurred }); } while (ActiveFiles.Count > 0) { foreach (DownloadableFileInfo dfi in ActiveFiles) { if (dfi.Error != null) { LastError = dfi.Error; return(UpdateStates.Error); } } Thread.Sleep(100); } if (State == UpdateStates.Updating) { if (Directory.Exists(STAGING_COMPLETE_FOLDER)) { Directory.Delete(STAGING_COMPLETE_FOLDER, true); } GeneralHelper.RecursiveMove(STAGING_FOLDER, STAGING_COMPLETE_FOLDER); ConfigManagerCompact.Configuration[@"_ReleaseStream"] = ReleaseStream.ToString(); return(MoveInPlace() ? UpdateStates.Completed : UpdateStates.NeedsRestart); } return(UpdateStates.NoUpdate); } catch (ThreadAbortException) { Log(@"Thread was aborted!"); foreach (DownloadableFileInfo dfi in ActiveFiles) { dfi.Abort(); } return(UpdateStates.NoUpdate); } catch (Exception e) { Log(@"Error: " + e.ToString()); LastError = e; return(UpdateStates.Error); } finally { Log(@"Saving out global config"); ConfigManagerCompact.SaveConfig(); updateThread = null; } }