internal static void Submit(OsuError err) { if (lastSubmission > 0 && GameBase.Time - lastSubmission < 10000) { return; } lastSubmission = GameBase.Time; try { Logger.Log($@"ERROR (hard crash): {err.Feedback}", LoggingTarget.Runtime, LogLevel.Error); Logger.Log($@"ERROR (hard crash): {err.Exception}", LoggingTarget.Runtime, LogLevel.Error); } catch { } try { pWebRequest r = new pWebRequest(General.WEB_ROOT + "/web/osu-error.php"); r.AddParameter("u", ConfigManager.sUsername); if (GameBase.User != null) { r.AddParameter("i", GameBase.User.Id.ToString()); } r.AddParameter("osumode", ((int)GameBase.Mode).ToString()); r.AddParameter("gamemode", ((int)Player.Mode).ToString()); r.AddParameter("gametime", GameBase.Time.ToString()); r.AddParameter("audiotime", AudioEngine.Time.ToString()); r.AddParameter("culture", Thread.CurrentThread.CurrentCulture.Name); r.AddParameter("b", BeatmapManager.Current != null ? BeatmapManager.Current.BeatmapId.ToString() : ""); r.AddParameter("bc", BeatmapManager.Current != null ? BeatmapManager.Current.BeatmapChecksum : ""); r.AddParameter("exception", err.Exception); r.AddParameter("feedback", err.Feedback); r.AddParameter("stacktrace", err.StackTrace); r.AddParameter("iltrace", err.ILTrace); r.AddParameter("version", General.BUILD_NAME); r.AddParameter("exehash", GameBase.ExeHash(Path.GetFileName(OsuMain.FullPath))); r.AddParameter("config", File.ReadAllText(Path.Combine(OsuMain.UserPath, ConfigManager.UserConfigFilename))); if (err.Screenshot != null) { r.AddFile(@"ss", err.Screenshot); } r.Timeout = 6000; r.BlockingPerform(); } catch { } }
private void submission_ForumSubmission(object sender, DoWorkEventArgs e) { string textSubject; if (beatmaps[0].Artist.Length == 0) { textSubject = beatmaps[0].Title; } else { textSubject = beatmaps[0].SortTitle; } List <PlayModes> modes = new List <PlayModes>(); foreach (Beatmap b in beatmaps) { if (!modes.Contains(b.PlayMode)) { modes.Add(b.PlayMode); } } if (modes.Count > 1 || modes[0] != PlayModes.Osu) { string modeString = string.Empty; foreach (PlayModes p in modes) { modeString = modeString + p + "|"; } modeString = modeString.TrimEnd('|'); textSubject += " [" + modeString + "]"; } UpdateStatus(LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_PostingToForums)); activeWebRequest = new pWebRequest(Urls.OSZ2_SUBMIT_FORUM); activeWebRequest.Timeout *= 2; activeWebRequest.AddParameter("u", ConfigManager.sUsername); activeWebRequest.AddParameter("p", ConfigManager.sPassword); activeWebRequest.AddParameter("b", newBeatmapSetID.ToString()); activeWebRequest.AddParameter("subject", textSubject); activeWebRequest.AddParameter("message", newMessage + textMessage.Text.Replace("\r", "")); activeWebRequest.AddParameter("complete", (radioButtonPending.Checked ? "1" : "0")); if (checkNotify.Checked) { activeWebRequest.AddParameter("notify", "1"); } activeWebRequest.BlockingPerform(); threadId = Int32.Parse(activeWebRequest.ResponseString); }
private static void UploadScreenshot(string filename, bool deleteAfterUpload) { if (filename == null) { return; } if (!GameBase.HasLogin) { NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Screenshot_LoginRequired)); return; } GameBase.RunBackgroundThread(delegate { try { if (lastUpload > 0 && GameBase.Time - lastUpload < 30000) { NotificationManager.ShowMessage("You are trying to upload screenshots too fast!"); return; } lastUpload = GameBase.Time; NotificationManager.ShowMessage("Uploading screenshot...", Color.Yellow, 3000); pWebRequest fileUpload = new pWebRequest(General.WEB_ROOT + "/web/osu-screenshot.php"); fileUpload.AddParameter("u", ConfigManager.sUsername); fileUpload.AddParameter("p", ConfigManager.sPassword); fileUpload.AddParameter("v", "1"); fileUpload.AddFile("ss", File.ReadAllBytes(filename)); fileUpload.BlockingPerform(); string returned = fileUpload.ResponseString; if (returned.Contains("http")) { GameBase.ProcessStart(returned); } else { GameBase.ProcessStart(General.WEB_ROOT + "/ss/" + returned); } NotificationManager.ShowMessage("Screenshot has been uploaded! Opening in browser window..." + filename, Color.YellowGreen, 6000); } catch { } finally { try { if (deleteAfterUpload) { File.Delete(filename); } } catch { } } }); }
//A temporary replacement for p2p updating private void updateOsz2Container() { Beatmap b = BeatmapManager.Current; if (b.Package == null) { throw new Exception("Can only update osz2 Packages."); } //todo: disable update button here AudioEngine.Stop(); AudioEngine.FreeMusic(); //ThreadPool.QueueUserWorkItem((o) => { List <osu_common.Libraries.Osz2.FileInfo> fileInfoCurrent = b.Package.GetFileInfo(); //b.Package.Close(); MapPackage currentPackage = b.Package; #if P2P if (!currentPackage.AcquireLock(20, true)) { String message = "Failed to update: Mappackage seems to be already in use."; GameBase.Scheduler.Add (() => NotificationManager.ShowMessage(message, Color.Cyan, 3000)); return; } #endif pWebRequest getFileInfo = new pWebRequest(String.Format(Urls.OSZ2_GET_FILE_INFO, ConfigManager.sUsername, ConfigManager.sPassword, b.BeatmapSetId)); status.SetStatus("Dowloading package version information"); string fileInfoEncoded = null; getFileInfo.Finished += (r, exc) => { if (exc == null) { fileInfoEncoded = r.ResponseString; } }; try { getFileInfo.BlockingPerform(); } catch { } if (fileInfoEncoded == null || fileInfoEncoded.Trim() == "" || fileInfoEncoded.StartsWith("5\n")) { #if P2P currentPackage.Unlock(); #endif String message = "Failed to update: Could not connect to the update service"; GameBase.Scheduler.AddDelayed (() => NotificationManager.ShowMessage(message, Color.Cyan, 3000), 100); return; } //decode string to FileInfo list string[] DatanList = fileInfoEncoded.Split('\n'); string[] fileInfoCollection = DatanList[0].Split('|'); List <osu_common.Libraries.Osz2.FileInfo> fileInfoNew = new List <osu_common.Libraries.Osz2.FileInfo>(fileInfoCollection.Length); status.SetStatus("Cross-referencing version information"); foreach (string fileInfoEnc in fileInfoCollection) { string[] fileInfoItems = fileInfoEnc.Split(':'); string filename = fileInfoItems[0]; int offset = Convert.ToInt32(fileInfoItems[1]); int length = Convert.ToInt32(fileInfoItems[2]); byte[] hash = GeneralHelper.StringToByteArray(fileInfoItems[3]); DateTime dateCreated = DateTime.FromBinary(Convert.ToInt64(fileInfoItems[4])); DateTime dateModified = DateTime.FromBinary(Convert.ToInt64(fileInfoItems[5])); osu_common.Libraries.Osz2.FileInfo infoDecoded; infoDecoded = new osu_common.Libraries.Osz2.FileInfo(filename, offset, length, hash, dateCreated, dateModified); fileInfoNew.Add(infoDecoded); } status.SetStatus("Downloading and updating files:"); //update all files that needs to be updated foreach (var fiNew in fileInfoNew) { //if already uptodate continue if (fileInfoCurrent.FindIndex((f) => f.Filename == fiNew.Filename) //&& MonoTorrent.Common.Toolbox.ByteMatch(f.Hash, fiNew.Hash)) != -1) { continue; } //if this file is a video and this package is a no-videoversion if (currentPackage.NoVideoVersion && MapPackage.IsVideoFile(fiNew.Filename)) { continue; } status.SetStatus("Updating " + fiNew.Filename + "..."); //download the file: string url = String.Format(Urls.OSZ2_GET_FILE_CONTENTS, ConfigManager.sUsername, ConfigManager.sPassword, b.BeatmapSetId, fiNew.Filename); byte[] fileContents = null; pWebRequest getFileContents = new pWebRequest(url); getFileContents.Finished += (r, exc) => { if (exc == null) { fileContents = r.ResponseData; } }; try { getFileContents.Perform(); } catch { } if (fileContents == null) { String message = String.Format("Failed to update: Dowloading {0} failed.", fiNew.Filename); GameBase.Scheduler.Add (() => NotificationManager.ShowMessage(message, Color.Cyan, 3300)); return; } currentPackage.AddFile(fiNew.Filename, fileContents, fiNew.CreationTime, fiNew.ModifiedTime, true); } status.SetStatus("Saving changes..."); currentPackage.Save(true); Osz2Factory.CloseMapPackage(currentPackage); status.SetStatus("Updating metadata..."); //get the new fileheader and replace the old string getHeaderUrl = String.Format(Urls.OSZ2_GET_RAW_HEADER, ConfigManager.sUsername, ConfigManager.sPassword, b.BeatmapSetId); byte[] rawHeader = null; pWebRequest getHeaderRaw = new pWebRequest(getHeaderUrl); getHeaderRaw.Finished += (r, exc) => { if (exc == null) { rawHeader = r.ResponseData; } }; getHeaderRaw.Perform(); if (rawHeader == null || rawHeader.Length < 60) { String message = "Failed to update: recieving header failed, please try to redownload."; GameBase.Scheduler.Add (() => NotificationManager.ShowMessage(message, Color.Cyan, 3300)); return; } int dataOffset = Convert.ToInt32(DatanList[1]); int dataSize = 0; //reorder all files to their new positions. fileInfoNew.ForEach((f) => { dataSize += f.Offset; }); MapPackage.Pad(b.ContainingFolderAbsolute, fileInfoNew, dataOffset, dataOffset + dataSize); //write received reader using (FileStream osz2Package = File.Open(b.ContainingFolderAbsolute, FileMode.Open, FileAccess.Write)) osz2Package.Write(rawHeader, 0, rawHeader.Length); GameBase.Scheduler.Add(() => { //open package again. //_package = Osz2Factory.TryOpen(ContainingFolder); BeatmapImport.SignalBeatmapCheck(true); BeatmapManager.ChangedPackages.Add(Path.GetFullPath(b.ContainingFolderAbsolute)); //BeatmapManager.CheckAndProcess(false); //GameBase.ChangeModeInstant(OsuModes.BeatmapImport, false); }); } //}); }
private void submission_PackageAndUpload(object sender, DoWorkEventArgs e) { bool workDone = false; UpdateStatus(LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_SynchronisingMaps)); //Run this on main thread to avoid threading issues (the editor is still being displayed in the background). GameBase.Scheduler.Add(delegate { using (HitObjectManager hitObjectManager = new HitObjectManagerEditor()) { Beatmap current = BeatmapManager.Current; bool requiresReload = false; try { //overwrite beatmap id's from the webservice and save them to disk. for (int i = 0; i < beatmaps.Count; i++) { Beatmap b = beatmaps[i]; if (b.BeatmapSetId != newBeatmapSetID || b.BeatmapId != newBeatmapIDs[i]) { AudioEngine.LoadedBeatmap = BeatmapManager.Current = b; hitObjectManager.SetBeatmap(b, Mods.None); hitObjectManager.LoadWithEvents(); b.BeatmapSetId = newBeatmapSetID; b.BeatmapId = newBeatmapIDs[i]; hitObjectManager.Save(false, false, false); requiresReload = true; } b.ComputeAndSetDifficultiesTomStars(b.PlayMode); } } catch { } if (requiresReload) { AudioEngine.LoadedBeatmap = BeatmapManager.Current = current; editor.LoadFile(current, false, false); } workDone = true; } }); if (checkCancel(e)) { return; } //get beatmap topic contents string url = String.Format(Urls.FORUM_GET_BEATMAP_TOPIC_INFO, ConfigManager.sUsername, ConfigManager.sPassword, newBeatmapSetID); activeWebRequest = new pWebRequest(url); string result = string.Empty; try { activeWebRequest.BlockingPerform(); result = activeWebRequest.ResponseString; if (!string.IsNullOrEmpty(result) && result[0] == '0') { string[] results = result.Split((char)3); threadId = int.Parse(results[1]); Invoke(() => oldMessage = results[3]); } } catch { } while (!workDone) { Thread.Sleep(100); } if (checkCancel(e)) { return; } UpdateStatus(LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_CreatingPackage)); //create a new Osz2 file string osz2Temp = GeneralHelper.GetTempPath(newBeatmapSetID + @".osz2"); //todo: add to progress bar packageCurrentUpload = BeatmapManager.Current.ConvertToOsz2(osz2Temp, false); if (packageCurrentUpload == null) { error = LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_CouldntCreatePackage) + LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_ExtraDiskSpace); submission_PackageAndUpload_Complete(null, null); return; } string osz2NewHash = (BitConverter.ToString(packageCurrentUpload.hash_body) + BitConverter.ToString(packageCurrentUpload.hash_meta)).Replace("-", ""); beatmapFilesize = new System.IO.FileInfo(packageCurrentUpload.Filename).Length; if (checkCancel(e)) { return; } Invoke(delegate { panelMain.Enabled = true; if (beatmaps.Count > 1) { radioButtonWorkInProgress.Checked = approved != 0; radioButtonPending.Checked = approved == 0; } else { radioButtonWorkInProgress.Checked = true; radioButtonPending.Checked = false; } newMessage = "[size=85]This beatmap was submitted using in-game submission on " + DateTime.Now.ToLongDateString() + " at " + DateTime.Now.ToLongTimeString() + "[/size]\n"; newMessage += "\n[b]Artist:[/b] " + beatmaps[0].Artist; newMessage += "\n[b]Title:[/b] " + beatmaps[0].Title; if (beatmaps[0].Source.Length > 0) { newMessage += "\n[b]Source:[/b] " + beatmaps[0].Source; } if (beatmaps[0].Tags.Length > 0) { newMessage += "\n[b]Tags:[/b] " + beatmaps[0].Tags; } newMessage += "\n[b]BPM:[/b] " + Math.Round(1000 / beatmaps[0].ControlPoints[0].BeatLength * 60, 2); newMessage += "\n[b]Filesize:[/b] " + (beatmapFilesize / 1024).ToString(GameBase.nfi) + "kb"; newMessage += String.Format("\n[b]Play Time:[/b] {0:00}:{1:00}", beatmaps[0].TotalLength / 60000, (beatmaps[0].TotalLength % 60000) / 1000); newMessage += "\n[b]Difficulties Available:[/b]\n[list]"; foreach (Beatmap b in beatmaps) { newMessage += string.Format("[*][url={0}]{1}{2}[/url] ({3} stars, {4} notes)\n", Urls.PATH_MAPS + GeneralHelper.UrlEncode(Path.GetFileName(b.Filename)), (b.Version.Length > 0 ? b.Version : "Normal"), (b.PlayMode == PlayModes.OsuMania ? " - " + (int)Math.Round(b.DifficultyCircleSize) + "Key" : ""), Math.Round(b.DifficultyTomStars(b.PlayMode), 2), b.ObjectCount); } newMessage += "[/list]\n"; newMessage += string.Format("\n[size=150][b]Download: [url={0}]{1}[/url][/b][/size]", string.Format(Urls.BEATMAP_SET_DOWNLOAD, newBeatmapSetID), beatmaps[0].SortTitle); if (hasVideo) { newMessage += string.Format("\n[size=120][b]Download: [url={0}]{1}[/url][/b][/size]", string.Format(Urls.BEATMAP_SET_DOWNLOAD_NO_VIDEO, newBeatmapSetID), beatmaps[0].SortTitle + " (no video)"); } newMessage += string.Format("\n[b]Information:[/b] [url={0}]Scores/Beatmap Listing[/url]", string.Format(Urls.BEATMAP_SET_LISTING, newBeatmapSetID)); newMessage += "\n---------------\n"; textMessage.Text = LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_CreatorsWords); if (!string.IsNullOrEmpty(oldMessage)) { if (oldMessage.IndexOf("---------------\n") > 0) { textMessage.Text = oldMessage.Remove(0, oldMessage.IndexOf("---------------") + 16).Trim('\n', '\r').Replace("\n", "\r\n"); } else { textMessage.Text = oldMessage.Replace("\n", "\r\n"); } } textMessage.Focus(); textMessage.SelectAll(); }); bool marathonException = beatmaps[0].Version.Contains("Marathon"); if (beatmapFilesize > 32 * 1024 * 1024 && !marathonException) //special marathon exception { error = LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_UploadFailed) + LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_BeatmapTooLarge); submission_PackageAndUpload_Complete(null, null); return; } if (beatmaps.Count < 2 && !marathonException) { Invoke(delegate { //don't allow submission to pending radioButtonPending.Enabled = false; radioButtonPending.Text = LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_PendingBeatmaps); }); } byte[] uploadBytes; if (!fullSubmit) { UpdateStatus(LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_PreparingChanges)); progressStartTime = DateTime.Now; BSDiffer patchCreator = new BSDiffer(); patchCreator.OnProgress += (object s, long current, long total) => { UpdateProgress(current, total); }; using (MemoryStream ms = new MemoryStream()) { patchCreator.Diff(packagePreviousUpload.Filename, osz2Temp, ms, Compression.GZip); uploadBytes = ms.ToArray(); } } else { uploadBytes = File.ReadAllBytes(osz2Temp); } if (checkCancel(e)) { return; } UpdateStatus(!isNewSubmission ? LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_SendingChanges) : LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_Uploading)); //Start the main upload process... activeWebRequest = new pWebRequest(Urls.OSZ2_SUBMIT_UPLOAD); activeWebRequest.Timeout = 3 * 60 * 1000; activeWebRequest.RetryCount = 0; activeWebRequest.AddParameter("u", ConfigManager.sUsername); activeWebRequest.AddParameter("h", ConfigManager.sPassword); activeWebRequest.AddParameter("t", fullSubmit ? "1" : "2"); activeWebRequest.AddParameter("z", string.Empty); activeWebRequest.AddParameter("s", newBeatmapSetID.ToString()); activeWebRequest.AddFile("osz2", uploadBytes); activeWebRequest.UploadProgress += delegate(pWebRequest r, long current, long total) { if (total == 0) { return; } if (current == total) { UpdateStatus(LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_Distributing)); } else { UpdateProgress(current, total); } }; activeWebRequest.Finished += submission_PackageAndUpload_Complete; activeWebRequest.Perform(); progressStartTime = DateTime.Now; }
/// <summary> /// Called when dialog window opens. Does preliminary checks in background. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void submission_InitialRequest(object sender, DoWorkEventArgs e) { string osz2Hash = string.Empty; string osz2FileHash = string.Empty; if (BeatmapManager.Current.Creator != GameBase.User.Name && (GameBase.User.Permission & Permissions.BAT) == 0) { error = LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_OwnershipError); return; } string lastUpload = lastUploadFilename; if (lastUpload != null && File.Exists(lastUpload)) { try { packagePreviousUpload = new MapPackage(lastUpload); osz2Hash = (BitConverter.ToString(packagePreviousUpload.hash_body) + BitConverter.ToString(packagePreviousUpload.hash_meta)).Replace("-", ""); } catch { } osz2FileHash = CryptoHelper.GetMd5(lastUpload); } int beatmapSetID = getBeatmapSetID(); string beatmapIDs = getBeatmapIdList(); string url = string.Format(Urls.OSZ2_SUBMIT_GET_ID, ConfigManager.sUsername, ConfigManager.sPassword, beatmapSetID, beatmapIDs, osz2FileHash); string result = String.Empty; try { activeWebRequest = new pWebRequest(url); activeWebRequest.BlockingPerform(); result = activeWebRequest.ResponseString; } catch (Exception ex) { Debug.Print(ex.ToString()); //something has gone wrong, but we handle this in the next few lines. } if (checkCancel(e)) { return; } if (string.IsNullOrEmpty(result)) { error = LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_BSSConnectFailed) + LocalisationManager.GetString(OsuString.BeatmapSubmissionSystem_CheckConnection); return; } string[] resultSplit = result.Split('\n'); if (handleErrorCode(resultSplit, 6)) { return; } newBeatmapSetID = System.Convert.ToInt32(resultSplit[1]); newBeatmapIDs = Array.ConvertAll <string, int>(resultSplit[2].Split(','), (s) => System.Convert.ToInt32(s)); fullSubmit = resultSplit[3] == "1" || packagePreviousUpload == null; Int32.TryParse(resultSplit[4], out submissionQuotaRemaining); bubblePop = resultSplit.Length > 5 && resultSplit[5] == "1"; approved = resultSplit.Length > 6 ? Int32.Parse(resultSplit[6]) : -1; }
private void submit(object sender, DoWorkEventArgs e) { #if ARCADE //Don't submit scores yet, no matter what. return; #endif #if NO_SCORE_SUBMIT NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_SubmissionDisabled)); return; #endif GameBase.User.spriteInfo.Text = LocalisationManager.GetString(OsuString.Score_SubmittingScore); try { byte[] zipped = new byte[0]; if (Pass) { if (BeatmapManager.Current.onlinePersonalScore != null && TotalScore > BeatmapManager.Current.onlinePersonalScore.TotalScore) { BeatmapManager.Current.Scores.Clear(); } //We should re-retrieve online scores no matter what, otherwise when clicking 'retry' the personal score won't be updated. ReplayCompressed = SevenZipHelper.Compress(new ASCIIEncoding().GetBytes(ReplayString)); #if DEBUG if (ReplayCompressed.Length < 100) { LoadLocalData(); } #endif zipped = ReplayCompressed; } pWebRequest req = new pWebRequest(General.WEB_ROOT + @"/web/osu-submit-modular.php"); req.AddFile(@"score", zipped); string iv = null; #if SUBMISSION_DEBUG File.AppendAllText(@"DEBUG.txt", @"Debug at " + DateTime.Now + @"\n"); #endif if (Pass) { Process[] procs = GameBase.Processes; GameBase.Processes = null; if (procs == null || procs.Length == 0) { procs = Process.GetProcesses(); } StringBuilder b = new StringBuilder(); foreach (Process p in procs) { string filename = string.Empty; try { filename = p.MainModule.FileName; FileInfo fi = new FileInfo(filename); if (fi != null) { filename = CryptoHelper.GetMd5String(fi.Length.ToString()) + @" " + filename; } } catch { } b.AppendLine(filename + @" | " + p.ProcessName + @" (" + p.MainWindowTitle + @")"); } #if SUBMISSION_DEBUG File.AppendAllText(@"DEBUG.txt", @"Running Processes:\n" + b + @"\n\n"); #endif req.AddParameter(@"pl", CryptoHelper.EncryptString(b.ToString(), Secrets.GetScoreSubmissionKey(), ref iv)); } else { req.AddParameter(@"x", Exit ? @"1" : @"0"); req.AddParameter(@"ft", FailTime.ToString()); } #if SUBMISSION_DEBUG File.AppendAllText(@"DEBUG.txt", @"\n1:" + onlineFormatted + @"\n"); File.AppendAllText(@"DEBUG.txt", @"\n2:" + GameBase.clientHash + @"\n"); File.AppendAllText(@"DEBUG.txt", @"\n3:" + iv + @"\n"); #endif req.AddParameter(@"score", CryptoHelper.EncryptString(onlineFormatted, Secrets.GetScoreSubmissionKey(), ref iv)); req.AddParameter(@"fs", CryptoHelper.EncryptString(visualSettingsString, Secrets.GetScoreSubmissionKey(), ref iv)); req.AddParameter(@"c1", GameBase.CreateUniqueId()); req.AddParameter(@"pass", ConfigManager.sPassword); req.AddParameter(@"osuver", General.VERSION.ToString()); req.AddParameter(@"s", CryptoHelper.EncryptString(GameBase.ClientHash, Secrets.GetScoreSubmissionKey(), ref iv)); try { if (Pass && ExtraData != null) { req.AddFile(@"i", ExtraData.ToArray()); } else { req.AddParameter(@"i", string.Empty); } } catch { } GameBase.ChangeAllowance++; ExtraData = null; req.AddParameter(@"iv", iv); int retryCount = Pass ? 10 : 2; int retryDelay = 7500; bool didError = false; while (retryCount-- > 0) { try { req.BlockingPerform(); SubmissionResponseString = req.ResponseString; #if SUBMISSION_DEBUG Debug.Print(SubmissionResponseString); File.AppendAllText(@"DEBUG.txt", @"\nres:" + SubmissionResponseString + @"\n\n\n\n\n-------------------\n\n\n\n"); #endif if (SubmissionResponseString.Contains(@"error:")) { switch (SubmissionResponseString.Replace(@"error: ", string.Empty)) { case @"reset": BanchoClient.HandlePasswordReset(); break; case @"verify": BanchoClient.RequireVerification(); break; case @"nouser": NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorNoUser)); break; case @"pass": NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorPassword)); break; case @"inactive": case @"ban": NotificationManager.ShowMessage("ERROR: Your account is no longer active. Please send an email to [email protected] if you think this is a mistake."); break; case @"beatmap": if (Beatmap != null && Beatmap.SubmissionStatus > osu_common.SubmissionStatus.Pending) { NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorBeatmap)); Beatmap.SubmissionStatus = osu_common.SubmissionStatus.Unknown; } break; case @"disabled": NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorDisabled)); break; case @"oldver": NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorVersion)); GameBase.CheckForUpdates(true); break; case @"no": break; } didError = true; } break; } catch { } if (retryDelay >= 60000) { NotificationManager.ShowMessage(string.Format(LocalisationManager.GetString(OsuString.Score_SubmissionFailed), (retryDelay / 60000))); } Thread.Sleep(retryDelay); retryDelay *= 2; } if (didError) { SubmissionStatus = ScoreSubmissionStatus.Complete; return; } } catch (Exception ex) { } if (SubmissionComplete != null) { SubmissionComplete(this); } SubmissionStatus = ScoreSubmissionStatus.Complete; if (!Pass) { GameBase.User.Refresh(); } }
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; } }