diff --git a/gts/BoxUploadDecode.aspx b/gts/BoxUploadDecode.aspx
new file mode 100644
index 00000000..9f6eeb8c
--- /dev/null
+++ b/gts/BoxUploadDecode.aspx
@@ -0,0 +1,24 @@
+<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="BoxUploadDecode.aspx.cs" Inherits="PokeFoundations.GTS.BoxUploadDecode" %>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gts/BoxUploadDecode.aspx.cs b/gts/BoxUploadDecode.aspx.cs
new file mode 100644
index 00000000..eec29f87
--- /dev/null
+++ b/gts/BoxUploadDecode.aspx.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Text;
+
+namespace PokeFoundations.GTS
+{
+ public partial class BoxUploadDecode : System.Web.UI.Page
+ {
+ protected void Page_Load(object sender, EventArgs e)
+ {
+ byte data = 0x00;
+
+ StringBuilder builder = new StringBuilder();
+
+ for (int x = 0; x < 512; x++)
+ {
+ data = runRng(data);
+ builder.Append(data.ToString("x2"));
+ builder.Append(" ");
+ if (x % 16 == 15) builder.Append("
");
+ }
+
+ litDecrypted.Text = builder.ToString();
+ }
+
+ private byte runRng(byte data)
+ {
+ return (byte)((data + 0x4f) * 0x1c);
+ }
+ }
+}
\ No newline at end of file
diff --git a/gts/BoxUploadDecode.aspx.designer.cs b/gts/BoxUploadDecode.aspx.designer.cs
new file mode 100644
index 00000000..6618171f
--- /dev/null
+++ b/gts/BoxUploadDecode.aspx.designer.cs
@@ -0,0 +1,51 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace PokeFoundations.GTS {
+
+
+ public partial class BoxUploadDecode {
+
+ ///
+ /// form1 control.
+ ///
+ ///
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ ///
+ protected global::System.Web.UI.HtmlControls.HtmlForm form1;
+
+ ///
+ /// fuRequest control.
+ ///
+ ///
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ ///
+ protected global::System.Web.UI.WebControls.FileUpload fuRequest;
+
+ ///
+ /// btnUpload control.
+ ///
+ ///
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ ///
+ protected global::System.Web.UI.WebControls.Button btnUpload;
+
+ ///
+ /// litDecrypted control.
+ ///
+ ///
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ ///
+ protected global::System.Web.UI.WebControls.Literal litDecrypted;
+ }
+}
diff --git a/gts/Default.aspx b/gts/Default.aspx
index cf29973c..77cae1a8 100644
--- a/gts/Default.aspx
+++ b/gts/Default.aspx
@@ -4,6 +4,5 @@
-customGTS
diff --git a/gts/gts.csproj b/gts/gts.csproj
index 4ae7fc55..e0064db0 100644
--- a/gts/gts.csproj
+++ b/gts/gts.csproj
@@ -34,6 +34,9 @@
+
+ ..\library\lib\mysql.data.dll
+
@@ -51,6 +54,7 @@
+
@@ -62,6 +66,13 @@
+
+ BoxUploadDecode.aspx
+ ASPXCodeBehind
+
+
+ BoxUploadDecode.aspx
+
pokemondpds.ashx
@@ -100,6 +111,12 @@
+
+
+ {408EFC7E-C6B0-4160-8628-2679E34385CE}
+ Library
+
+
diff --git a/gts/pokemondpds.ashx.cs b/gts/pokemondpds.ashx.cs
index dcebc3de..09f14ae0 100644
--- a/gts/pokemondpds.ashx.cs
+++ b/gts/pokemondpds.ashx.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
+using PokeFoundations.Data;
namespace PokeFoundations.GTS
{
@@ -41,8 +42,9 @@ namespace PokeFoundations.GTS
context.Request.QueryString["data"].Length < 12)
{
// arguments missing, partial check for data length.
- // (require data to hold at least 7 bytes.
- // In reality, it must hold at least 8.)
+ // (Here, we require data to hold at least 7 bytes.
+ // In reality, it must hold at least 8, which is checked
+ // for below after decoding)
Error400(context);
return;
}
@@ -63,6 +65,8 @@ namespace PokeFoundations.GTS
if (data.Length < 4)
{
// data too short to contain a pid
+ // We check for 4 bytes, not 8, since the decrypt seed
+ // isn't included in DecryptData's result.
Error400(context);
return;
}
@@ -87,13 +91,34 @@ namespace PokeFoundations.GTS
{
default:
// unrecognized page url
+ // should be error 404 once we're done debugging
context.Response.Write("Almost there. Your path is:\n");
context.Response.Write(session.URL);
return;
+
+
case "/worldexchange/info.asp":
- context.Response.Write("It worked");
+ context.Response.OutputStream.Write(new byte[] { 0x01, 0x00 }, 0, 2);
break;
+
+ case "/common/setProfile.asp":
+ // todo: Figure out what fun stuff is contained in this blob!
+
+ context.Response.OutputStream.Write(new byte[]
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ 0, 8);
+ break;
+
+
+ case "/worldexchange/result.asp":
+ {
+
+
+ }
+ break;
+
+
}
}
else
diff --git a/gts/src/GtsContextExtender.cs b/gts/src/GtsContextExtender.cs
index c5a9fe72..eedcebaf 100644
--- a/gts/src/GtsContextExtender.cs
+++ b/gts/src/GtsContextExtender.cs
@@ -30,10 +30,19 @@ namespace PokeFoundations.GTS
Dictionary sessions = context.AllSessions4();
DateTime now = DateTime.UtcNow;
- foreach (KeyValuePair session in sessions)
+ lock (sessions)
{
- if (session.Value.ExpiryDate < now) sessions.Remove(session.Key);
+ Queue toRemove = new Queue();
+ foreach (KeyValuePair session in sessions)
+ {
+ if (session.Value.ExpiryDate < now) toRemove.Enqueue(session.Key);
+ }
+ while (toRemove.Count > 0)
+ {
+ sessions.Remove(toRemove.Dequeue());
+ }
}
}
+
}
}
\ No newline at end of file
diff --git a/gts/src/GtsSession4.cs b/gts/src/GtsSession4.cs
index 9ee22278..f00642ea 100644
--- a/gts/src/GtsSession4.cs
+++ b/gts/src/GtsSession4.cs
@@ -30,7 +30,7 @@ namespace PokeFoundations.GTS
byte[] data = new byte[longToken.Length];
MemoryStream stream = new MemoryStream(data);
StreamWriter writer = new StreamWriter(stream);
- writer.Write(longToken);
+ writer.Write(longToken); // fixme: this throws an OutOfBoundsException if the passed token contains non-ascii.
writer.Flush();
return m_sha1.ComputeHash(data).ToHexStringLower();
diff --git a/gts/src/GtsSessionBase.cs b/gts/src/GtsSessionBase.cs
index 87259eec..83d28f00 100644
--- a/gts/src/GtsSessionBase.cs
+++ b/gts/src/GtsSessionBase.cs
@@ -104,7 +104,7 @@ namespace PokeFoundations.GTS
for (int x = 0; x < token.Length; x++)
{
- // tokens have 62 chars: 0-9, A-Z, and a-z
+ // tokens have 62 possible chars: 0-9, A-Z, and a-z
m_rng.GetBytes(data);
uint rand = BitConverter.ToUInt32(data, 0) % 62u;
diff --git a/library/Data/DataAbstract.cs b/library/Data/DataAbstract.cs
index e6fb9066..a37e34a4 100644
--- a/library/Data/DataAbstract.cs
+++ b/library/Data/DataAbstract.cs
@@ -3,22 +3,40 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
+using PokeFoundations.Structures;
namespace PokeFoundations.Data
{
public abstract class DataAbstract
{
- public static String SqlSanitize(String s)
- {
- return SqlSanitize(s, "");
- }
+ #region Initialization
+ private static DataAbstract m_instance;
- public static String SqlSanitize(String s, String newChar)
+ public static DataAbstract Instance
{
- String result = s.Replace("\'", newChar).Replace("[", newChar).Replace("]", newChar).Replace("`", newChar);
- int x = result.IndexOf("--");
- if (x != -1) result = result.Substring(0, x);
- return result;
+ get
+ {
+ if (m_instance == null)
+ {
+ m_instance = new DataMysql();
+ }
+ return m_instance;
+ }
}
+ #endregion
+
+ #region Utility
+ #endregion
+
+ #region GTS
+ public abstract GtsDatagram4 GtsDataForUser4(int pid);
+
+ public abstract void GtsDepositPokemon4(GtsDatagram4 datagram);
+
+ public abstract void GtsDeletePokemon4(int pid);
+
+ public abstract void GtsTradePokemon4(int pidSrc, int pidDest);
+
+ #endregion
}
}
diff --git a/library/Data/DataMysql.cs b/library/Data/DataMysql.cs
index 80ac6638..45743813 100644
--- a/library/Data/DataMysql.cs
+++ b/library/Data/DataMysql.cs
@@ -4,14 +4,173 @@ using System.Linq;
using System.Text;
using System.Data;
using MySql.Data.MySqlClient;
+using PokeFoundations.Structures;
+using PokeFoundations.Support;
namespace PokeFoundations.Data
{
public class DataMysql : DataAbstract
{
+ #region Initialization
private MySqlConnection CreateConnection()
{
- return new MySqlConnection("Server=localhost;Database=pfound;User ID=pfound;Password=goldeen need log;Pooling=true;");
+ // hard-coded for now, will need to add configuration later
+ return new MySqlConnection("Server=10.211.55.2;Database=gts;User ID=gts;Password=gts;Pooling=true;");
}
+ #endregion
+
+ #region Utility
+ public static String SqlSanitize(String s)
+ {
+ return SqlSanitize(s, "");
+ }
+
+ public static String SqlSanitize(String s, String newChar)
+ {
+ String result = s.Replace("\'", newChar).Replace("[", newChar).Replace("]", newChar).Replace("`", newChar);
+ int x = result.IndexOf("--");
+ if (x != -1) result = result.Substring(0, x);
+ return result;
+ }
+ #endregion
+
+ #region GTS
+ public override GtsDatagram4 GtsDataForUser4(int pid)
+ {
+ using (MySqlConnection db = CreateConnection())
+ {
+ db.Open();
+ MySqlDataReader reader = (MySqlDataReader)db.ExecuteReader("SELECT Data, Species, Gender, Level, " +
+ "RequestedSpecies, RequestedGender, RequestedMinLevel, RequestedMaxLevel, " +
+ "Unknown1, TrainerGender, Unknown2, TimeDeposited, TimeWithdrawn, pid, " +
+ "TrainerName, TrainerOT, TrainerCountry, TrainerRegion, TrainerClass, " +
+ "IsExchanged, TrainerVersion, TrainerLanguage FROM GtsPokemon4 WHERE pid = @pid",
+ new MySqlParameter("@pid", pid));
+
+ if (!reader.Read()) return null;
+ GtsDatagram4 result = new GtsDatagram4();
+
+ byte[] data = new byte[236];
+ reader.GetBytes(0, 0, data, 0, 236);
+ result.Data = data;
+ data = null;
+
+ result.Species = reader.GetUInt16(1);
+ result.Gender = (Genders)reader.GetByte(2);
+ result.Level = reader.GetByte(3);
+ result.RequestedSpecies = reader.GetUInt16(4);
+ result.RequestedGender = (Genders)reader.GetByte(5);
+ result.RequestedMinLevel = reader.GetByte(6);
+ result.RequestedMaxLevel = reader.GetByte(7);
+ result.Unknown1 = reader.GetByte(8);
+ result.TrainerGender = (GtsTrainerGenders)reader.GetByte(9);
+ result.Unknown2 = reader.GetByte(10);
+ result.TimeDeposited = reader.GetDateTime(11);
+ result.TimeWithdrawn = reader.GetDateTime(12);
+ result.PID = reader.GetInt32(13);
+
+ data = new byte[16];
+ reader.GetBytes(14, 0, data, 0, 16);
+ result.TrainerName = data;
+ data = null;
+
+ result.TrainerOT = reader.GetUInt16(15);
+ result.TrainerCountry = reader.GetByte(16);
+ result.TrainerRegion = reader.GetByte(17);
+ result.TrainerClass = reader.GetByte(18);
+ result.IsExchanged = reader.GetByte(19);
+ result.TrainerVersion = reader.GetByte(20);
+ result.TrainerLanguage = reader.GetByte(21);
+#if DEBUG
+ AssertHelper.Equals(result.PID, pid);
+#endif
+ reader.Close();
+ return result;
+ }
+ }
+
+ public override bool GtsDepositPokemon4(GtsDatagram4 datagram)
+ {
+ if (datagram.Data.Length != 236) throw new FormatException("pkm data must be 236 bytes.");
+ if (datagram.TrainerName.Length != 16) throw new FormatException("Trainer name must be 16 bytes.");
+ // note that IsTraded being true in the datagram is not an error condition
+ // since it might have use later on. You should check for this in the upload handler.
+
+ using (MySqlConnection db = CreateConnection())
+ {
+ db.Open();
+
+ /*
+ MySqlDataReader reader = (MySqlDataReader)db.ExecuteReader("SELECT Data, Species, Gender, Level, " +
+ "RequestedSpecies, RequestedGender, RequestedMinLevel, RequestedMaxLevel, " +
+ "Unknown1, TrainerGender, Unknown2, TimeDeposited, TimeWithdrawn, pid, " +
+ "TrainerName, TrainerOT, TrainerCountry, TrainerRegion, TrainerClass, " +
+ "IsExchanged, TrainerVersion, TrainerLanguage FROM GtsPokemon4 WHERE pid = @pid",
+ new MySqlParameter("@pid", pid));
+ *
+ * */
+
+ MySqlTransaction tran = db.BeginTransaction();
+
+ int count = (int)tran.ExecuteScalar("SELECT Count(*) FROM GtsPokemon4 WHERE pid = @pid",
+ new MySqlParameter("@pid", datagram.PID));
+
+ if (count > 0)
+ {
+ // This player already has a pokemon in the system.
+ // we can possibly allow multiples under some future conditions
+ tran.Rollback();
+ return false;
+ }
+
+ tran.ExecuteNonQuery("INSERT INTO GtsPokemon4 " +
+ "(Data, Species, Gender, Level, RequestedSpecies, RequestedGender, " +
+ "RequestedMinLevel, RequestedMaxLevel, Unknown1, TrainerGender, " +
+ "Unknown2, TimeDeposited, TimeWithdrawn, pid, TrainerName, TrainerOT, " +
+ "TrainerCountry, TrainerRegion, TrainerClass, IsExchanged, TrainerVersion, " +
+ "TrainerLanguage) " +
+ "VALUES (@Data, @Species, @Gender, @Level, @RequestedSpecies, " +
+ "@RequestedGender, @RequestedMinLevel, @RequestedMaxLevel, @Unknown1, " +
+ "@TrainerGender, @Unknown2, @TimeDeposited, @TimeWithdrawn, @pid, " +
+ "@TrainerName, @TrainerOT, @TrainerCountry, @TrainerRegion, @TrainerClass, " +
+ "@IsExchanged, @TrainerVersion, @TrainerLanguage)",
+ new MySqlParameter("@Data", datagram.Data),
+ new MySqlParameter("@Species", datagram.Species),
+ new MySqlParameter("@Gender", (byte)datagram.Gender),
+ new MySqlParameter("@Level", datagram.Level),
+ new MySqlParameter("@RequestedSpecies", datagram.RequestedSpecies),
+ new MySqlParameter("@RequestedGender", (byte)datagram.RequestedGender),
+ new MySqlParameter("@RequestedMinLevel", datagram.RequestedMinLevel),
+ new MySqlParameter("@RequestedMaxLevel", datagram.RequestedMaxLevel),
+ new MySqlParameter("@Unknown1", datagram.Unknown1),
+ new MySqlParameter("@TrainerGender", (byte)datagram.TrainerGender),
+ new MySqlParameter("@Unknown2", datagram.Unknown2),
+ new MySqlParameter("@TimeDeposited", datagram.TimeDeposited),
+ new MySqlParameter("@TimeWithdrawn", datagram.TimeWithdrawn),
+ new MySqlParameter("@pid", datagram.PID),
+ new MySqlParameter("@TrainerName", datagram.TrainerName),
+ new MySqlParameter("@TrainerOT", datagram.TrainerOT),
+ new MySqlParameter("@TrainerCountry", datagram.TrainerCountry),
+ new MySqlParameter("@TrainerRegion", datagram.TrainerRegion),
+ new MySqlParameter("@TrainerClass", datagram.TrainerClass),
+ new MySqlParameter("@IsExchanged", datagram.IsExchanged),
+ new MySqlParameter("@TrainerVersion", datagram.TrainerVersion),
+ new MySqlParameter("@TrainerLanguage", datagram.TrainerLanguage));
+
+ tran.Commit();
+
+ return true;
+ }
+ }
+
+ public override void GtsDeletePokemon4(int pid)
+ {
+ }
+
+ public override void GtsTradePokemon4(int pidSrc, int pidDest)
+ {
+ }
+
+ #endregion
}
}
diff --git a/library/Library.csproj b/library/Library.csproj
index d7b7f1c1..43953da8 100644
--- a/library/Library.csproj
+++ b/library/Library.csproj
@@ -53,6 +53,10 @@
+
+
+
+