From 7356f4029c28a37397516475b2a5e33b9dbae423 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 24 Oct 2015 22:45:12 +0200 Subject: [PATCH] Created a Dialog for the injection save the folder strcuture: dumps: /saviine_root/dump/game_id/8000000x/ injections: /saviine_root/inject/game_id/8000000x/ didn't tested it. So probably this won't work. need to and the dialog option to overwrite the common folder on wiiU --- .gitignore | 6 + saviine/server/src/Program.cs | 144 +++++++++++++----- .../server/src/SaveSelectorDialog.Designer.cs | 86 +++++++++++ saviine/server/src/SaveSelectorDialog.cs | 67 ++++++++ saviine/server/src/SaveSelectorDialog.resx | 120 +++++++++++++++ saviine/server/src/bin/saviine_server.exe | Bin 30208 -> 34816 bytes ...saviine_server.csproj.FileListAbsolute.txt | 2 + ...erver.csprojResolveAssemblyReference.cache | Bin 4634 -> 7195 bytes saviine/server/src/saviine_server.csproj | 15 ++ saviine/server/src/saviine_server.v12.suo | Bin 32256 -> 41984 bytes 10 files changed, 398 insertions(+), 42 deletions(-) create mode 100644 saviine/server/src/SaveSelectorDialog.Designer.cs create mode 100644 saviine/server/src/SaveSelectorDialog.cs create mode 100644 saviine/server/src/SaveSelectorDialog.resx diff --git a/.gitignore b/.gitignore index 1a97e94..cf15d48 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,9 @@ saviine/server/src/obj/x86/Debug/saviine_server.pdb saviine/server/src/bin/saviine_server.vshost.exe saviine/server/src/bin/saviine_server.exe.config saviine/server/src/bin/saviine_server.vshost.exe.config +saviine/server/src/obj/x86/Debug/DesignTimeResolveAssemblyReferences.cache +saviine/server/src/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache +saviine/server/src/obj/x86/Debug/saviine_server.csprojResolveAssemblyReference.cache +saviine/server/src/obj/x86/Debug/saviine_server.csproj.FileListAbsolute.txt +saviine/server/src/obj/x86/Debug/saviine_server.csproj.GenerateResource.Cache +saviine/server/src/obj/x86/Debug/saviine_server.Form1.resources diff --git a/saviine/server/src/Program.cs b/saviine/server/src/Program.cs index cd09473..06fd765 100644 --- a/saviine/server/src/Program.cs +++ b/saviine/server/src/Program.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Net; +using System.Windows.Forms; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; @@ -83,6 +84,7 @@ namespace saviine_server const uint BUFFER_SIZE = 64 * 1024; static Boolean fastmode = false; static byte op_mode = BYTE_MODE_D; + [STAThread] static void Main(string[] args) { if (args.Length > 1) @@ -198,6 +200,30 @@ namespace saviine_server return x; } + + static string getRealPath(string path,string title_id){ + SaveSelectorDialog ofd = new SaveSelectorDialog(path, title_id); + try + { + DialogResult result = ofd.ShowDialog(); + if (result == System.Windows.Forms.DialogResult.OK) + { + Console.WriteLine("selected: " + ofd.NewPath); + return ofd.NewPath; + } + else + { + Console.WriteLine("nothing selected"); + } + } + catch(Exception e) + { + Console.WriteLine("No saves found to inject"); + } + return ""; + } + + static void Handle(object client_obj) { string name = Thread.CurrentThread.Name; @@ -217,10 +243,12 @@ namespace saviine_server uint[] ids = reader.ReadUInt32s(4); - - string LocalRoot = root + "\\" + ids[0].ToString("X8") + "-" + ids[1].ToString("X8") + "\\"; + + string LocalRootDump = root + "\\" + "dump" + "\\" + ids[0].ToString("X8") + "-" + ids[1].ToString("X8") + "\\"; + string LocalRootInject = root + "\\" + "inject" + "\\" + ids[0].ToString("X8") + "-" + ids[1].ToString("X8") + "\\"; + if (!ids[0].ToString("X8").Equals("00050000")) { writer.Write(BYTE_NORMAL); @@ -228,9 +256,13 @@ namespace saviine_server } else { - if (!Directory.Exists(LocalRoot)) + if (!Directory.Exists(LocalRootDump)) { - Directory.CreateDirectory(LocalRoot); + Directory.CreateDirectory(LocalRootDump); + } + if (!Directory.Exists(LocalRootInject)) + { + Directory.CreateDirectory(LocalRootInject); } } // Log connection @@ -240,7 +272,8 @@ namespace saviine_server // Create log file for current thread log = new StreamWriter(logs_root + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "-" + name + "-" + ids[0].ToString("X8") + "-" + ids[1].ToString("X8") + ".txt", true, Encoding.ASCII, 1024*64); log.WriteLine(name + " Accepted connection from client " + client.Client.RemoteEndPoint.ToString()); - log.WriteLine(name + " TitleID: " + ids[0].ToString("X8") + "-" + ids[1].ToString("X8")); + string title_id = ids[0].ToString("X8") + "-" + ids[1].ToString("X8"); + log.WriteLine(name + " TitleID: " + title_id); writer.Write(BYTE_SPECIAL); @@ -253,17 +286,19 @@ namespace saviine_server case BYTE_OPEN: { //Log(log, "BYTE_OPEN"); - bool request_slow = false; + Boolean failed = false; int len_path = reader.ReadInt32(); int len_mode = reader.ReadInt32(); string path = reader.ReadString(Encoding.ASCII, len_path - 1); if (reader.ReadByte() != 0) throw new InvalidDataException(); string mode = reader.ReadString(Encoding.ASCII, len_mode - 1); - if (reader.ReadByte() != 0) throw new InvalidDataException(); + if (reader.ReadByte() != 0) throw new InvalidDataException(); - - if (File.Exists(LocalRoot + path)) + path = getRealPathCurrent(path, title_id); + if (path.Length == 0) failed = true; + + if (File.Exists(path) && !failed) { int handle = -1; for (int i = 1; i < files.Length; i++) @@ -284,18 +319,16 @@ namespace saviine_server } //Log(log, name + " -> fopen(\"" + path + "\", \"" + mode + "\") = " + handle.ToString()); - files[handle] = new FileStream(LocalRoot + path, FileMode.Open, FileAccess.Read, FileShare.Read); + files[handle] = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); writer.Write(BYTE_SPECIAL); writer.Write(0); writer.Write(handle); - + break; } - else { writer.Write(BYTE_NORMAL); } - - // Log(log, "No request found: " + LocalRoot + path); - - + //else on error: + writer.Write(BYTE_NORMAL); + break; } case BYTE_SETPOS: @@ -326,21 +359,18 @@ namespace saviine_server } case BYTE_GET_FILES: { + Boolean failed = false; int len_path = reader.ReadInt32(); string path = reader.ReadString(Encoding.ASCII, len_path-1); if (reader.ReadByte() != 0) throw new InvalidDataException(); int x = 0; - if (path[0] == '/' && path[1] == '/') + + currentPersistentID = getPersistentIDFromPath(path); + path = getRealPath(path, title_id); + if(path.Length == 0)failed = true; + + if (Directory.Exists(path) && !failed) { - path = path.Substring(2); - } - else if (path[0] == '/') - { - path = path.Substring(1); - } - path = LocalRoot + path; - - if(Directory.Exists(path)) { x = countDirectory(path); if (x > 0) { @@ -391,26 +421,19 @@ namespace saviine_server } writer.Write(BYTE_SPECIAL); // //Console.Write("file sent, wrote special byte \n"); + break; } else { - writer.Write(BYTE_END); // - //Console.Write("list was empty return BYTE_END \n"); + dir_files.Remove(path); //Console.Write("removed \"" + path + "\" from dic \n"); } } - else - { - //Console.Write(path + "empty \n"); - writer.Write(BYTE_END); // - } - } - else - { - //Console.Write(path + " is not found\n"); - writer.Write(BYTE_END); // } + writer.Write(BYTE_END); // + //Console.Write("list was empty return BYTE_END \n"); + //Console.Write("in break \n"); break; } @@ -420,7 +443,6 @@ namespace saviine_server int size = reader.ReadInt32(); int fd = reader.ReadInt32(); - FileStream f = files[fd]; byte[] buffer = new byte[size]; @@ -464,13 +486,13 @@ namespace saviine_server int len_path = reader.ReadInt32(); string path = reader.ReadString(Encoding.ASCII, len_path - 1); if (reader.ReadByte() != 0) throw new InvalidDataException(); - if (!Directory.Exists(LocalRoot + "dump" + path)) + if (!Directory.Exists(LocalRootDump + path)) { - Directory.CreateDirectory(Path.GetDirectoryName(LocalRoot + "dump" + path)); + Directory.CreateDirectory(Path.GetDirectoryName(LocalRootDump + path)); } // Add new file for incoming data - files_request.Add(fd, new FileStream(LocalRoot + "dump" + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)); + files_request.Add(fd, new FileStream(LocalRootDump + path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)); // Send response if (fastmode) { writer.Write(BYTE_REQUEST); @@ -629,5 +651,43 @@ namespace saviine_server } Console.WriteLine(name + " Exit"); } + + private static string getPersistentIDFromPath(string path) + { + string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" }; + string[] result; + string resultstr = ""; + + result = path.Split(stringSeparators, StringSplitOptions.None); + if (result.Length < 2) return ""; + resultstr = result[result.Length-1]; + stringSeparators = new string[] { "/", "\\" }; + result = resultstr.Split(stringSeparators, StringSplitOptions.None); + if (result.Length < 1) return ""; + return result[0]; + } + private static string currentPersistentID = "80000009"; + private static string getRealPathCurrent(string path, string title_id) + { + if (currentPersistentID.Length == 0) return ""; + string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" }; + string[] result; + string resultstr = ""; + + result = path.Split(stringSeparators, StringSplitOptions.None); + if (result.Length < 2) return ""; + resultstr = result[result.Length-1]; + stringSeparators = new string[] { "/", "\\" }; + result = resultstr.Split(stringSeparators, StringSplitOptions.None); + if (result.Length < 2) return ""; + resultstr = ""; + for (int i = 1; i < result.Length; i++) + { + resultstr += "/" + result[i]; + } + string savePath = Program.root + "/" + "inject" + "/" + title_id + "/" + currentPersistentID + resultstr; + + return savePath; + } } } diff --git a/saviine/server/src/SaveSelectorDialog.Designer.cs b/saviine/server/src/SaveSelectorDialog.Designer.cs new file mode 100644 index 0000000..f69b463 --- /dev/null +++ b/saviine/server/src/SaveSelectorDialog.Designer.cs @@ -0,0 +1,86 @@ +namespace saviine_server +{ + partial class SaveSelectorDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btn_ok = new System.Windows.Forms.Button(); + this.btn_cancel = new System.Windows.Forms.Button(); + this.listBox_saves = new System.Windows.Forms.ListBox(); + this.SuspendLayout(); + // + // btn_ok + // + this.btn_ok.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btn_ok.Location = new System.Drawing.Point(167, 266); + this.btn_ok.Name = "btn_ok"; + this.btn_ok.Size = new System.Drawing.Size(105, 33); + this.btn_ok.TabIndex = 0; + this.btn_ok.Text = "OK"; + this.btn_ok.UseVisualStyleBackColor = true; + this.btn_ok.Click += new System.EventHandler(this.btn_ok_Click); + // + // btn_cancel + // + this.btn_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btn_cancel.Location = new System.Drawing.Point(332, 269); + this.btn_cancel.Name = "btn_cancel"; + this.btn_cancel.Size = new System.Drawing.Size(130, 29); + this.btn_cancel.TabIndex = 1; + this.btn_cancel.Text = "Cancel"; + this.btn_cancel.UseVisualStyleBackColor = true; + // + // listBox_saves + // + this.listBox_saves.FormattingEnabled = true; + this.listBox_saves.Location = new System.Drawing.Point(54, 48); + this.listBox_saves.Name = "listBox_saves"; + this.listBox_saves.Size = new System.Drawing.Size(408, 160); + this.listBox_saves.TabIndex = 2; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(499, 314); + this.Controls.Add(this.listBox_saves); + this.Controls.Add(this.btn_cancel); + this.Controls.Add(this.btn_ok); + this.Name = "Form1"; + this.Text = "Form1"; + this.Load += new System.EventHandler(this.Form1_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button btn_ok; + private System.Windows.Forms.Button btn_cancel; + private System.Windows.Forms.ListBox listBox_saves; + } +} \ No newline at end of file diff --git a/saviine/server/src/SaveSelectorDialog.cs b/saviine/server/src/SaveSelectorDialog.cs new file mode 100644 index 0000000..be599b5 --- /dev/null +++ b/saviine/server/src/SaveSelectorDialog.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace saviine_server +{ + public partial class SaveSelectorDialog : Form + { + private string newPath = ""; + + public string NewPath + { + get { return newPath; } + } + private static string savePath = Program.root + "/" + "inject"; + public SaveSelectorDialog(string path,string title_id) + { + InitializeComponent(); + string[] stringSeparators = new string[] { "vol/save/", "vol\\save\\" }; + string[] result; + + result = path.Split(stringSeparators, StringSplitOptions.None); + if (result.Length < 2) this.Close(); + string resultPath = result[result.Length-2]; + + Console.WriteLine(title_id); + savePath += "/" + title_id; + if (Directory.Exists(savePath)) + { + // Recurse into subdirectories of this directory. + string[] subdirectoryEntries = Directory.GetDirectories(savePath); + foreach (string subdirectory in subdirectoryEntries) + { + this.listBox_saves.Items.Add(Path.GetFileName(subdirectory)); + } + } + else + { + Console.WriteLine("dir not found! " + savePath); + this.Close(); + } + + } + + private void Form1_Load(object sender, EventArgs e) + { + + } + + private void btn_ok_Click(object sender, EventArgs e) + { + newPath = savePath + "/" + this.listBox_saves.SelectedItem.ToString(); + } + private void btn_cancel_Click(object sender, EventArgs e) + { + + } + + + } +} diff --git a/saviine/server/src/SaveSelectorDialog.resx b/saviine/server/src/SaveSelectorDialog.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/saviine/server/src/SaveSelectorDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/saviine/server/src/bin/saviine_server.exe b/saviine/server/src/bin/saviine_server.exe index ae95be6b99e9f5f4d776b40fa3527e3d6892ee5c..6ea09a5dee169b69620746de65c4042763ba939e 100644 GIT binary patch literal 34816 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 QM_2tBW&W?I|1lo;zf&t5)&Kwi literal 30208 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 z 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 ID%B#s|H>=`4*&oF diff --git a/saviine/server/src/saviine_server.csproj b/saviine/server/src/saviine_server.csproj index f5cb490..b8f286a 100644 --- a/saviine/server/src/saviine_server.csproj +++ b/saviine/server/src/saviine_server.csproj @@ -51,8 +51,18 @@ + + + + + + Form + + + SaveSelectorDialog.cs + @@ -83,6 +93,11 @@ true + + + SaveSelectorDialog.cs + +