commit cf135322d872770712edcef9e76b65ed18e7d714 Author: BlubbFish Date: Sun Nov 15 23:51:29 2015 +0000 gspylogin hinzugefügt diff --git a/gspylogin.sln b/gspylogin.sln new file mode 100644 index 0000000..bebf9e3 --- /dev/null +++ b/gspylogin.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gspylogin", "gspylogin\gspylogin.csproj", "{ADFD42CE-4E2E-42F2-94BC-634AAE32A7BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ADFD42CE-4E2E-42F2-94BC-634AAE32A7BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADFD42CE-4E2E-42F2-94BC-634AAE32A7BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADFD42CE-4E2E-42F2-94BC-634AAE32A7BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADFD42CE-4E2E-42F2-94BC-634AAE32A7BD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/gspylogin/Database/DatabaseDriver.cs b/gspylogin/Database/DatabaseDriver.cs new file mode 100644 index 0000000..7da31e6 --- /dev/null +++ b/gspylogin/Database/DatabaseDriver.cs @@ -0,0 +1,527 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Data.SQLite; +using MySql; +using MySql.Data.Common; +using MySql.Data.MySqlClient; + +namespace BF2Statistics.Database +{ + public class DatabaseDriver : IDisposable + { + /// + /// Current DB Engine + /// + public DatabaseEngine DatabaseEngine { get; protected set; } + + /// + /// The database connection + /// + public DbConnection Connection { get; protected set; } + + /// + /// Returns whether the Database connection is open + /// + public bool IsConnected + { + get { return (Connection.State == ConnectionState.Open); } + } + + /// + /// Returns the current conenction state of the database + /// + public ConnectionState State + { + get { return Connection.State; } + } + + /// + /// Gets the number of queries ran by this instance + /// + public int NumQueries = 0; + + /// + /// Random, yes... But its used here when building queries dynamically + /// + protected static char Comma = ','; + + /// + /// Indicates whether the disposed method was called + /// + protected bool IsDisposed = false; + + /// + /// Constructor + /// + /// The string name, for the GetDatabaseEngine() method + /// The Database server IP Address + /// The Database server Port Number + /// The name of the database + /// A username, with database privliages + /// The password to the User + public DatabaseDriver(string Engine, string Host, int Port, string DatabaseName, string User, string Pass) + { + // Set class variables, and create a new connection builder + this.DatabaseEngine = GetDatabaseEngine(Engine); + DbConnectionStringBuilder Builder; + + // Establish the connection + if (this.DatabaseEngine == DatabaseEngine.Sqlite) + { + // Create the connection + Builder = new SQLiteConnectionStringBuilder(); + Builder.Add("Data Source", Path.Combine(Program.RootPath, DatabaseName + ".sqlite3")); + Connection = new SQLiteConnection(Builder.ConnectionString); + } + else if (this.DatabaseEngine == DatabaseEngine.Mysql) + { + // Create the connection + Builder = new MySqlConnectionStringBuilder(); + Builder.Add("Server", Host); + Builder.Add("Port", Port); + Builder.Add("User ID", User); + Builder.Add("Password", Pass); + Builder.Add("Database", DatabaseName); + Builder.Add("Convert Zero Datetime", "true"); + Connection = new MySqlConnection(Builder.ConnectionString); + } + else + { + throw new Exception("Invalid Database type."); + } + } + + /// + /// Destructor + /// + ~DatabaseDriver() + { + Dispose(); + } + + /// + /// Disposes the DB connection + /// + public void Dispose() + { + if(Connection != null && !IsDisposed) + { + try + { + Connection.Close(); + Connection.Dispose(); + } + catch (ObjectDisposedException) { } + + IsDisposed = true; + } + } + + /// + /// Opens the database connection + /// + public void Connect() + { + if (Connection.State != ConnectionState.Open) + { + try + { + Connection.Open(); + } + catch (Exception e) + { + throw new DbConnectException("Unable to etablish database connection", e); + } + } + } + + /// + /// Closes the connection to the database + /// + public void Close() + { + try { + if (Connection.State != ConnectionState.Closed) + Connection.Close(); + } + catch (ObjectDisposedException) { } + } + + /// + /// Creates a new command to be executed on the database + /// + /// + public DbCommand CreateCommand(string QueryString) + { + if (DatabaseEngine == Database.DatabaseEngine.Sqlite) + return new SQLiteCommand(QueryString, Connection as SQLiteConnection); + else + return new MySqlCommand(QueryString, Connection as MySqlConnection); + } + + /// + /// Creates a DbParameter using the current Database engine's Parameter object + /// + /// + public DbParameter CreateParam() + { + if (DatabaseEngine == Database.DatabaseEngine.Sqlite) + return (new SQLiteParameter() as DbParameter); + else + return (new MySqlParameter() as DbParameter); + } + + /// + /// Queries the database, and returns a result set + /// + /// The SQL Statement to run on the database + /// + public List> Query(string Sql) + { + return this.Query(Sql, new List()); + } + + /// + /// Queries the database, and returns a result set + /// + /// The SQL Statement to run on the database + /// Additional parameters are parameter values for the query. + /// The first parameter replaces @P0, second @P1 etc etc. + /// + /// + public List> Query(string Sql, params object[] Items) + { + List Params = new List(Items.Length); + for (int i = 0; i < Items.Length; i++) + { + DbParameter Param = this.CreateParam(); + Param.ParameterName = "@P" + i; + Param.Value = Items[i]; + Params.Add(Param); + } + + return this.Query(Sql, Params); + } + + /// + /// Queries the database, and returns a result set + /// + /// The SQL Statement to run on the database + /// A list of sql params to add to the command + /// + public List> Query(string Sql, List Params) + { + // Create our Rows result + List> Rows = new List>(); + + // Increase Query Count + NumQueries++; + + // Create the SQL Command + using (DbCommand Command = this.CreateCommand(Sql)) + { + // Add params + foreach (DbParameter Param in Params) + Command.Parameters.Add(Param); + + // Execute the query + using (DbDataReader Reader = Command.ExecuteReader()) + { + // If we have rows, add them to the list + if (Reader.HasRows) + { + // Add each row to the rows list + while (Reader.Read()) + { + Dictionary Row = new Dictionary(Reader.FieldCount); + for (int i = 0; i < Reader.FieldCount; ++i) + Row.Add(Reader.GetName(i), Reader.GetValue(i)); + + Rows.Add(Row); + } + } + + // Cleanup + Reader.Close(); + } + } + + // Return Rows + return Rows; + } + + /// + /// Queries the database, and returns 1 row at a time until all rows are returned + /// + /// The SQL Statement to run on the database + /// + public IEnumerable> QueryReader(string Sql) + { + // Increase Query Count + NumQueries++; + + // Create the SQL Command, and execute the reader + using (DbCommand Command = this.CreateCommand(Sql)) + using (DbDataReader Reader = Command.ExecuteReader()) + { + // If we have rows, add them to the list + if (Reader.HasRows) + { + // Add each row to the rows list + while (Reader.Read()) + { + Dictionary Row = new Dictionary(Reader.FieldCount); + for (int i = 0; i < Reader.FieldCount; ++i) + Row.Add(Reader.GetName(i), Reader.GetValue(i)); + + yield return Row; + } + } + + // Cleanup + Reader.Close(); + } + } + + /// + /// Executes a command, and returns 1 row at a time until all rows are returned + /// + /// The database command to execute the reader on + /// + public IEnumerable> QueryReader(DbCommand Command) + { + // Increase Query Count + NumQueries++; + + // Execute the query + using (Command) + using (DbDataReader Reader = Command.ExecuteReader()) + { + // If we have rows, add them to the list + if (Reader.HasRows) + { + // Add each row to the rows list + while (Reader.Read()) + { + Dictionary Row = new Dictionary(Reader.FieldCount); + for (int i = 0; i < Reader.FieldCount; ++i) + Row.Add(Reader.GetName(i), Reader.GetValue(i)); + + yield return Row; + } + } + + // Cleanup + Reader.Close(); + } + } + + + /// + /// Executes a command, and returns the resulting rows + /// + /// The database command to execute the reader on + /// + public List> ExecuteReader(DbCommand Command) + { + // Execute the query + List> Rows = new List>(); + + // Increase Query Count + NumQueries++; + + using (Command) + using (DbDataReader Reader = Command.ExecuteReader()) + { + // If we have rows, add them to the list + if (Reader.HasRows) + { + // Add each row to the rows list + while (Reader.Read()) + { + Dictionary Row = new Dictionary(Reader.FieldCount); + for (int i = 0; i < Reader.FieldCount; ++i) + Row.Add(Reader.GetName(i), Reader.GetValue(i)); + + Rows.Add(Row); + } + } + + // Cleanup + Reader.Close(); + } + + // Return Rows + return Rows; + } + + /// + /// Executes a statement on the database (Update, Delete, Insert) + /// + /// The SQL statement to be executes + /// Returns the number of rows affected by the statement + public int Execute(string Sql) + { + // Create the SQL Command + using (DbCommand Command = this.CreateCommand(Sql)) + return Command.ExecuteNonQuery(); + } + + /// + /// Executes a statement on the database (Update, Delete, Insert) + /// + /// The SQL statement to be executed + /// A list of Sqlparameters + /// Returns the number of rows affected by the statement + public int Execute(string Sql, List Params) + { + // Create the SQL Command + using (DbCommand Command = this.CreateCommand(Sql)) + { + // Increase Query Count + NumQueries++; + + // Add params + foreach (DbParameter Param in Params) + Command.Parameters.Add(Param); + + // Execute command, and dispose of the command + return Command.ExecuteNonQuery(); + } + } + + /// + /// Executes a statement on the database (Update, Delete, Insert) + /// + /// The SQL statement to be executed + /// Additional parameters are parameter values for the query. + /// The first parameter replaces @P0, second @P1 etc etc. + /// + /// Returns the number of rows affected by the statement + public int Execute(string Sql, params object[] Items) + { + // Create the SQL Command + using (DbCommand Command = this.CreateCommand(Sql)) + { + // Add params + for (int i = 0; i < Items.Length; i++) + { + DbParameter Param = this.CreateParam(); + Param.ParameterName = "@P" + i; + Param.Value = Items[i]; + Command.Parameters.Add(Param); + } + + // Increase Query Count + NumQueries++; + + // Execute command, and dispose of the command + return Command.ExecuteNonQuery(); + } + } + + /// + /// Executes the query, and returns the first column of the first row in the result + /// set returned by the query. Additional columns or rows are ignored. + /// + /// The SQL statement to be executed + /// + public object ExecuteScalar(string Sql) + { + // Increase Query Count + NumQueries++; + + // Create the SQL Command + using (DbCommand Command = this.CreateCommand(Sql)) + return Command.ExecuteScalar(); + } + + /// + /// Executes the query, and returns the first column of the first row in the result + /// set returned by the query. Additional columns or rows are ignored. + /// + /// The SQL statement to be executed + /// A list of Sqlparameters + /// + public object ExecuteScalar(string Sql, List Params) + { + // Create the SQL Command + using (DbCommand Command = this.CreateCommand(Sql)) + { + // Increase Query Count + NumQueries++; + + // Add params + foreach (DbParameter Param in Params) + Command.Parameters.Add(Param); + + // Execute command, and dispose of the command + return Command.ExecuteScalar(); + } + } + + /// + /// Executes the query, and returns the first column of the first row in the result + /// set returned by the query. Additional columns or rows are ignored. + /// + /// The SQL statement to be executed + /// + /// + public object ExecuteScalar(string Sql, params object[] Items) + { + // Create the SQL Command + using (DbCommand Command = this.CreateCommand(Sql)) + { + // Add params + for (int i = 0; i < Items.Length; i++) + { + DbParameter Param = this.CreateParam(); + Param.ParameterName = "@P" + i; + Param.Value = Items[i]; + Command.Parameters.Add(Param); + } + + // Increase Query Count + NumQueries++; + + // Execute command, and dispose of the command + return Command.ExecuteScalar(); + } + } + + /// + /// Begins a new database transaction + /// + /// + public DbTransaction BeginTransaction() + { + return Connection.BeginTransaction(); + } + + /// + /// Begins a new database transaction + /// + /// + /// + public DbTransaction BeginTransaction(IsolationLevel Level) + { + return Connection.BeginTransaction(Level); + } + + /// + /// Converts a database string name to a DatabaseEngine type. + /// + /// + /// + public static DatabaseEngine GetDatabaseEngine(string Name) + { + return ((DatabaseEngine)Enum.Parse(typeof(DatabaseEngine), Name, true)); + } + } +} diff --git a/gspylogin/Database/DatabaseEngine.cs b/gspylogin/Database/DatabaseEngine.cs new file mode 100644 index 0000000..f60591b --- /dev/null +++ b/gspylogin/Database/DatabaseEngine.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BF2Statistics.Database +{ + public enum DatabaseEngine + { + Sqlite, + Mysql, + } +} diff --git a/gspylogin/Database/GamespyDatabase.cs b/gspylogin/Database/GamespyDatabase.cs new file mode 100644 index 0000000..689c35a --- /dev/null +++ b/gspylogin/Database/GamespyDatabase.cs @@ -0,0 +1,298 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BF2Statistics.Database +{ + /// + /// A class to provide common tasks against the Gamespy Login Database + /// + public class GamespyDatabase : DatabaseDriver, IDisposable + { + /// + /// Constructor + /// + public GamespyDatabase() : + base( + MainForm.Config.GamespyDBEngine, + MainForm.Config.GamespyDBHost, + MainForm.Config.GamespyDBPort, + MainForm.Config.GamespyDBName, + MainForm.Config.GamespyDBUser, + MainForm.Config.GamespyDBPass + ) + { + // Try and Reconnect + try + { + Connect(); + + // Try to get the database version + try + { + if (base.Query("SELECT dbver FROM _version LIMIT 1").Count == 0) + throw new Exception(); + } + catch + { + // If an exception is thrown, table doesnt exist... fresh install + if (DatabaseEngine == DatabaseEngine.Sqlite) + base.Execute(Utils.GetResourceAsString("BF2Statistics.SQL.SQLite.Gamespy.sql")); + else + base.Execute(Utils.GetResourceAsString("BF2Statistics.SQL.MySQL.Gamespy.sql")); + } + } + catch (Exception) + { + if (Connection != null) + Connection.Dispose(); + + throw; + } + } + + /// + /// Destructor + /// + ~GamespyDatabase() + { + if (!IsDisposed) + base.Dispose(); + } + + /// + /// Fetches an account from the gamespy database + /// + /// The user's Nick + /// + public Dictionary GetUser(string Nick) + { + // Fetch the user + var Rows = base.Query("SELECT * FROM accounts WHERE name=@P0", Nick); + return (Rows.Count == 0) ? null : Rows[0]; + } + + /// + /// Fetches an account from the gamespy database + /// + /// The account player ID + /// + public Dictionary GetUser(int Pid) + { + // Fetch the user + var Rows = base.Query("SELECT * FROM accounts WHERE id=@P0", Pid); + return (Rows.Count == 0) ? null : Rows[0]; + } + + /// + /// Fetches an account from the gamespy database + /// + /// Account email + /// Account Password + /// + public Dictionary GetUser(string Email, string Password) + { + var Rows = base.Query("SELECT * FROM accounts WHERE email=@P0 AND password=@P1", Email, Password); + return (Rows.Count == 0) ? null : Rows[0]; + } + + /// + /// Returns a list of player names that are similar to the passed parameter + /// + /// + /// + public List GetUsersLike(string Nick) + { + // Generate our return list + List List = new List(); + var Rows = base.Query("SELECT name FROM accounts WHERE name LIKE @P0", "%" + Nick + "%"); + foreach (Dictionary Account in Rows) + List.Add(Account["name"].ToString()); + + return List; + } + + /// + /// Returns wether an account exists from the provided Nick + /// + /// + /// + public bool UserExists(string Nick) + { + // Fetch the user + return (base.Query("SELECT id FROM accounts WHERE name=@P0", Nick).Count != 0); + } + + /// + /// Returns wether an account exists from the provided Account Id + /// + /// + /// + public bool UserExists(int PID) + { + // Fetch the user + return (base.Query("SELECT name FROM accounts WHERE id=@P0", PID).Count != 0); + } + + /// + /// Creates a new Gamespy Account + /// + /// Used by the login server when a create account request is made + /// The Account Name + /// The Account Password + /// The Account Email Address + /// The Country Code for this Account + /// A bool indicating whether the account was created sucessfully + public bool CreateUser(string Nick, string Pass, string Email, string Country) + { + int Pid = 0; + + // Attempt to connect to stats database, and get a PID from there + /*try + { + // try see if the player ID exists in the stats database + using (StatsDatabase Db = new StatsDatabase()) + { + // NOTE: online account names in the stats DB start with a single space! + var Row = Db.Query("SELECT id FROM player WHERE upper(name) = upper(@P0)", " " + Nick); + Pid = (Row.Count == 0) ? GenerateAccountId() : Int32.Parse(Row[0]["id"].ToString()); + } + } + catch + {*/ + Pid = GenerateAccountId(); + //} + + // Create the user in the database + int Rows = base.Execute("INSERT INTO accounts(id, name, password, email, country) VALUES(@P0, @P1, @P2, @P3, @P4)", + Pid, Nick, Pass, Email, Country + ); + + return (Rows != 0); + } + + /// + /// Generates a new Account Id + /// + /// + private int GenerateAccountId() + { + var Row = base.Query("SELECT COALESCE(MAX(id), 500000000) AS max FROM accounts"); + int max = Int32.Parse(Row[0]["max"].ToString()) + 1; + return (max < 500000000) ? 500000000 : max; + } + + /// + /// Creates a new Gamespy Account + /// + /// Only used in the Gamespy Account Creation Form + /// The Profile Id to assign this account + /// The Account Name + /// The Account Password + /// The Account Email Address + /// The Country Code for this Account + /// A bool indicating whether the account was created sucessfully + public bool CreateUser(int Pid, string Nick, string Pass, string Email, string Country) + { + // Make sure the user doesnt exist! + if (UserExists(Pid)) + throw new Exception("Account ID is already taken!"); + else if(UserExists(Nick)) + throw new Exception("Account username is already taken!"); + + // Create the user in the database + int Rows = base.Execute("INSERT INTO accounts(id, name, password, email, country) VALUES(@P0, @P1, @P2, @P3, @P4)", + Pid, Nick, Pass, Email, Country + ); + + return (Rows != 0); + } + + /// + /// Updates an Accounts Country Code + /// + /// + /// + public void UpdateUser(string Nick, string Country) + { + base.Execute("UPDATE accounts SET country=@P0 WHERE name=@P1", Nick, Country); + } + + /// + /// Updates an Account's information by ID + /// + /// The Current Account ID + /// New Account ID + /// New Account Name + /// New Account Password + /// New Account Email Address + public void UpdateUser(int Id, int NewPid, string NewNick, string NewPassword, string NewEmail) + { + base.Execute("UPDATE accounts SET id=@P0, name=@P1, password=@P2, email=@P3 WHERE id=@P4", + NewPid, NewNick, NewPassword, NewEmail, Id); + } + + /// + /// Deletes a Gamespy Account + /// + /// + /// + public int DeleteUser(string Nick) + { + return base.Execute("DELETE FROM accounts WHERE name=@P0", Nick); + } + + /// + /// Deletes a Gamespy Account + /// + /// + /// + public int DeleteUser(int Pid) + { + return base.Execute("DELETE FROM accounts WHERE id=@P0", Pid); + } + + /// + /// Fetches a Gamespy Account id from an account name + /// + /// + /// + public int GetPID(string Nick) + { + var Rows = base.Query("SELECT id FROM accounts WHERE name=@P0", Nick); + return (Rows.Count == 0) ? 0 : Int32.Parse(Rows[0]["id"].ToString()); + } + + /// + /// Sets the Account (Player) Id for an account by Name + /// + /// The account Nick we are setting the new Pid for + /// The new Pid + /// + public int SetPID(string Nick, int Pid) + { + // If no user exists, return code -1 + if (!UserExists(Nick)) + return -1; + + // If the Pid already exists, return -2 + if (UserExists(Pid)) + return -2; + + // If PID is false, the PID is not taken + int Success = base.Execute("UPDATE accounts SET id=@P0 WHERE name=@P1", Pid, Nick); + return (Success > 0) ? 1 : 0; + } + + /// + /// Returns the number of accounts in the database + /// + /// + public int GetNumAccounts() + { + var Row = base.Query("SELECT COUNT(id) AS count FROM accounts"); + return Int32.Parse(Row[0]["count"].ToString()); + } + } +} diff --git a/gspylogin/Delegates.cs b/gspylogin/Delegates.cs new file mode 100644 index 0000000..6b7f4d5 --- /dev/null +++ b/gspylogin/Delegates.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using BF2Statistics.Gamespy; + +namespace BF2Statistics +{ + public delegate void ShutdownEventHandler(); + + public delegate void StartupEventHandler(); + + public delegate void ConnectionUpdate(object sender); + + public delegate void AspRequest(); + + public delegate void SnapshotProccessed(); + + public delegate void SnapshotRecieved(bool Proccessed); + + public delegate void DataRecivedEvent(string Message); + + public delegate void ConnectionClosed(); + + public delegate void GpspConnectionClosed(GpspClient client); + + public delegate void GpcmConnectionClosed(GpcmClient client); +} diff --git a/gspylogin/Extentions/DateExtensions.cs b/gspylogin/Extentions/DateExtensions.cs new file mode 100644 index 0000000..f1949f7 --- /dev/null +++ b/gspylogin/Extentions/DateExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BF2Statistics +{ + public static class DateExtensions + { + /// + /// Returns the current Unix Timestamp + /// + /// + /// + public static int ToUnixTimestamp(this DateTime target) + { + return (int)(target - new DateTime(1970, 1, 1, 0, 0, 0, target.Kind)).TotalSeconds; + } + + /// + /// Converts a timestamp to a DataTime + /// + /// + /// + /// + public static DateTime ToDateTime(this DateTime target, int timestamp) + { + DateTime Date = new DateTime(1970, 1, 1, 0, 0, 0, target.Kind); + return Date.AddSeconds(timestamp); + } + } +} diff --git a/gspylogin/Extentions/DbConnectException.cs b/gspylogin/Extentions/DbConnectException.cs new file mode 100644 index 0000000..f3deca4 --- /dev/null +++ b/gspylogin/Extentions/DbConnectException.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BF2Statistics +{ + public class DbConnectException : Exception + { + public DbConnectException(string Message, Exception Inner) : base(Message, Inner) { } + } +} diff --git a/gspylogin/Extentions/SocketExtensions.cs b/gspylogin/Extentions/SocketExtensions.cs new file mode 100644 index 0000000..972d359 --- /dev/null +++ b/gspylogin/Extentions/SocketExtensions.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace System.Net.Sockets +{ + public static class SocketExtensions + { + /// + /// Determines if the connection to the machine on the other side of the socket is still active. + /// Serves the same purpose as TcpClient.Connected and TcpListener.Connected. + /// + /// + /// A bool of whether the remote client is still connected. + public static bool IsConnected(this Socket iSocket) + { + try + { + return !(iSocket.Poll(1, SelectMode.SelectRead) && iSocket.Available == 0); + } + catch + { + return false; + } + } + } +} diff --git a/gspylogin/GamespyUtils.cs b/gspylogin/GamespyUtils.cs new file mode 100644 index 0000000..5a98f4e --- /dev/null +++ b/gspylogin/GamespyUtils.cs @@ -0,0 +1,96 @@ +using System; +using System.Text; + +namespace BF2Statistics.Gamespy +{ + public static class GamespyUtils + { + /// + /// Encodes a password to Gamespy format + /// + /// + /// + public static string EncodePassword(string Password) + { + // Get password string as UTF8 String, Convert to Base64 + byte[] PasswordBytes = Encoding.UTF8.GetBytes(Password); + string Pass = Convert.ToBase64String(GsPassEncode(PasswordBytes)); + + // Convert Standard Base64 to Gamespy Base 64 + StringBuilder builder = new StringBuilder(Pass); + builder.Replace('=', '_'); + builder.Replace('+', '['); + builder.Replace('/', ']'); + return builder.ToString(); + } + + /// + /// Decodes a Gamespy encoded password + /// + /// + /// + public static string DecodePassword(string Password) + { + // Convert Gamespy Base64 to Standard Base 64 + StringBuilder builder = new StringBuilder(Password); + builder.Replace('_', '='); + builder.Replace('[', '+'); + builder.Replace(']', '/'); + + // Decode passsword + byte[] PasswordBytes = Convert.FromBase64String(builder.ToString()); + return Encoding.UTF8.GetString(GsPassEncode(PasswordBytes)); + } + + /// + /// Gamespy's XOR method to encrypt and decrypt a password + /// + /// + /// + public static byte[] GsPassEncode(byte[] pass) + { + int a = 0; + int num = 0x79707367; // gspy + for (int i = 0; i < pass.Length; ++i) + { + num = Gslame(num); + a = num % 0xFF; + pass[i] ^= (byte)a; + } + + return pass; + } + + /// + /// Not exactly sure what this does, but i know its used to + /// reverse the encryption and decryption of a string + /// + /// + /// + private static int Gslame(int num) + { + int c = (num >> 16) & 0xffff; + int a = num & 0xffff; + + c *= 0x41a7; + a *= 0x41a7; + a += ((c & 0x7fff) << 16); + + if (a < 0) + { + a &= 0x7fffffff; + a++; + } + + a += (c >> 15); + + if (a < 0) + { + a &= 0x7fffffff; + a++; + } + + return a; + } + } +} diff --git a/gspylogin/Gpcm/ClientList.cs b/gspylogin/Gpcm/ClientList.cs new file mode 100644 index 0000000..ae56824 --- /dev/null +++ b/gspylogin/Gpcm/ClientList.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BF2Statistics.Gamespy +{ + class ClientList : EventArgs + { + public List Clients; + + public ClientList(List Clients) + { + this.Clients = Clients; + } + } +} diff --git a/gspylogin/Gpcm/GpcmClient.cs b/gspylogin/Gpcm/GpcmClient.cs new file mode 100644 index 0000000..2fdb6da --- /dev/null +++ b/gspylogin/Gpcm/GpcmClient.cs @@ -0,0 +1,541 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Security.Cryptography; +using BF2Statistics.Utilities; + +namespace BF2Statistics.Gamespy +{ + /// + /// Gamespy Client Manager + /// This class is used to proccess the client login process, + /// create new user accounts, and fetch profile information + /// gpcm.gamespy.com + /// + public class GpcmClient : IDisposable + { + #region Variables + + /// + /// The current step of the login proccess + /// + private int Step = 0; + + /// + /// The connected clients Nick + /// + public string ClientNick { get; protected set; } + + /// + /// The connected clients Player Id + /// + public int ClientPID { get; protected set; } + + /// + /// Clients table data from the gamespy database + /// + private Dictionary User; + + /// + /// The users session key + /// + private ushort SessionKey; + + /// + /// The Clients generated proof string, used for checking password validity. + /// This is used as part of the hash used to "prove" to the client + /// that the password in our database matches what the user enters + /// + private string ClientChallengeKey; + + /// + /// The Servers challange key, sent when the client first connects. + /// This is used as part of the hash used to "proove" to the client + /// that the password in our database matches what the user enters + /// + private string ServerChallengeKey; + + /// + /// The Clients response key. The is the expected Hash value for the server + /// when generating the client proof string + /// + private string ClientResponseKey; + + /// + /// Variable that determines if the client is disconnected, + /// and this object can be cleared from memory + /// + public bool Disposed { get; protected set; } + + /// + /// The clients socket network stream + /// + private TcpClientStream Stream; + + /// + /// The TcpClient for our connection + /// + private TcpClient Connection; + + /// + /// The TcpClient's Endpoint + /// + private EndPoint ClientEP; + + /// + /// The Connected Clients IpAddress + /// + public IPAddress IpAddress = null; + + /// + /// A random... random + /// + private Random RandInstance = new Random((int)DateTime.Now.Ticks); + + /// + /// Our CRC16 object for generating Checksums + /// + protected static Crc16 Crc; + + /// + /// Our MD5 Object + /// + protected static MD5 CreateMD5; + + /// + /// A literal backslash + /// + private const char Backslash = '\\'; + + /// + /// Array of characters used in generating a signiture + /// + private static char[] AlphaChars = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + + /// + /// An array of Alpha Numeric characters used in generating a random string + /// + private static char[] AlphaNumChars = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + + /// + /// Array of Hex cahracters, with no leading 0 + /// + private static char[] HexChars = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' + }; + + /// + /// Gamespy password hash table (Byte To Hex) + /// + private static string[] BtoH = { + "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", + "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", + "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", + "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" + }; + + /// + /// An Event that is fired when the client successfully logs in. + /// + public static event ConnectionUpdate OnSuccessfulLogin; + + /// + /// Event fired when that remote connection logs out, or + /// the socket gets disconnected. This event will not fire + /// unless OnSuccessfulLogin event was fired first. + /// + public static event GpcmConnectionClosed OnDisconnect; + + #endregion Variables + + /// + /// Static Construct. Builds the Crc table uesd in the login process + /// + static GpcmClient() + { + Crc = new Crc16(Crc16Mode.Standard); + CreateMD5 = MD5.Create(); + } + + /// + /// Constructor + /// + /// The Tcp Client connection + public GpcmClient(TcpClient Client) + { + // Set default variable values + ClientNick = "Connecting..."; + Connection = Client; + ClientEP = Connection.Client.RemoteEndPoint; + IpAddress = ((IPEndPoint)ClientEP).Address; + Disposed = false; + + // Create our Client Stream + Stream = new TcpClientStream(Client); + Stream.DataReceived += new DataRecivedEvent(Stream_DataReceived); + Stream.OnDisconnect += new ConnectionClosed(Stream_OnDisconnect); + + // Log Incoming Connections + LoginServer.Log("[GPCM] Client Connected: {0}", ClientEP); + + // Start by sending the server challenge + SendServerChallenge(); + } + + /// + /// Destructor + /// + ~GpcmClient() + { + if (!Disposed) + this.Dispose(); + } + + /// + /// Closes the connection, and disposes of the client object + /// + public void Dispose() + { + // If connection is still alive, disconnect user + if (Connection.Client.IsConnected()) + { + Stream.IsClosing = true; + Connection.Close(); + } + + // Call disconnect event + if(OnDisconnect != null) + OnDisconnect(this); + + // Preapare to be unloaded from memory + this.Disposed = true; + + // Log + LoginServer.Log("[GPCM] Client Disconnected: {0}", ClientEP); + } + + /// + /// Logs the client out of the game client, and closes the stream + /// + public void LogOut() + { + LoginServer.Database.Execute("UPDATE accounts SET session=0 WHERE id=" + ClientPID); + Dispose(); + } + + #region Stream Callbacks + + /// + /// Main listner loop. Keeps an open stream between the client and server while + /// the client is logged in / playing + /// + private void Stream_DataReceived(string message) + { + // Read client message, and parse it into key value pairs + string[] recieved = message.TrimStart(Backslash).Split(Backslash); + Dictionary Recv = ConvertToKeyValue(recieved); + + // Switch by task + switch (recieved[0]) + { + case "newuser": + HandleNewUser(Recv); + Step++; + break; + case "login": + ProcessLogin(Recv); + Step++; + break; + case "getprofile": + if (Step < 2) + { + SendProfile(false); + Step++; + } + else + SendProfile(true); + break; + case "updatepro": + UpdateUser(Recv); + Step++; + break; + case "logout": + LogOut(); + break; + default: + LoginServer.Log("Unkown Message Passed: {0}", message); + break; + } + } + + /// + /// Main loop for handling the client stream + /// + private void Stream_OnDisconnect() + { + LogOut(); + } + + #endregion Stream Callbacks + + #region Login Steps + + /// + /// This method starts off by sending a random string 10 characters + /// in length, known as the Server challenge key. This is used by + /// the client to return a client challenge key, which is used + /// to validate login information later. + /// + public void SendServerChallenge() + { + // First we need to create a random string the length of 10 characters + StringBuilder Temp = new StringBuilder(); + for (int i = 0; i < 10; i++) + Temp.Append(AlphaChars[RandInstance.Next(AlphaChars.Length)]); + + // Next we send the client the challenge key + ServerChallengeKey = Temp.ToString(); + Stream.Send("\\lc\\1\\challenge\\{0}\\id\\1\\final\\", ServerChallengeKey); + } + + /// + /// This method verifies the login information sent by + /// the client, and returns encrypted data for the client + /// to verify as well + /// + public void ProcessLogin(Dictionary Recv) + { + // Set instance variables now that we know who's connected + ClientNick = Recv["uniquenick"]; + ClientChallengeKey = Recv["challenge"]; + ClientResponseKey = Recv["response"]; + + // Get user data from database + try + { + User = LoginServer.Database.GetUser(ClientNick); + if (User == null) + { + Stream.Send("\\error\\\\err\\265\\fatal\\\\errmsg\\The uniquenick provided is incorrect!\\id\\1\\final\\"); + Dispose(); + return; + } + } + catch + { + Dispose(); + return; + } + + // Set client PID var + ClientPID = Int32.Parse(User["id"].ToString()); + + // Use the GenerateProof method to compare with the "response" value. This validates the given password + if (ClientResponseKey == GenerateProof(ClientChallengeKey, ServerChallengeKey)) + { + // Create session key + SessionKey = Crc.ComputeChecksum(ClientNick); + + // Password is correct + Stream.Send( + "\\lc\\2\\sesskey\\{0}\\proof\\{1}\\userid\\{2}\\profileid\\{2}\\uniquenick\\{3}\\lt\\{4}__\\id\\1\\final\\", + SessionKey, + GenerateProof(ServerChallengeKey, ClientChallengeKey), + ClientPID, + ClientNick, + GenerateRandomString(22) // Generate LT whatever that is (some sort of random string, 22 chars long) + ); + + // Call successful login event + OnSuccessfulLogin(this); + LoginServer.Database.Execute("UPDATE accounts SET session=@P0, lastip=@P1 WHERE id=@P2", SessionKey, IpAddress, ClientPID); + } + else + { + // Password is incorrect with database value + Stream.Send("\\error\\\\err\\260\\fatal\\\\errmsg\\The password provided is incorrect.\\id\\1\\final\\"); + Dispose(); + } + } + + /// + /// This method is called when the client requests for the Account profile + /// + /// Determines the return ID + private void SendProfile(bool retrieve) + { + Stream.Send( + "\\pi\\\\profileid\\{0}\\nick\\{1}\\userid\\{0}\\email\\{2}\\sig\\{3}\\uniquenick\\{1}\\pid\\0\\firstname\\\\lastname\\" + + "\\countrycode\\{4}\\birthday\\16844722\\lon\\0.000000\\lat\\0.000000\\loc\\\\id\\{5}\\final\\", + User["id"], ClientNick, User["email"], GenerateSig(), User["country"], (retrieve ? "5" : "2") + ); + } + + #endregion Steps + + #region User Methods + + /// + /// Whenever the "newuser" command is recieved, this method is called to + /// add the new users information into the database + /// + /// Array of parms sent by the server + private void HandleNewUser(Dictionary Recv) + { + string Nick = Recv["nick"]; + string Email = Recv["email"]; + + // Make sure the user doesnt exist already + try + { + if (LoginServer.Database.UserExists(Nick)) + { + Stream.Send("\\error\\\\err\\516\\fatal\\\\errmsg\\This account name is already in use!\\id\\1\\final\\"); + Dispose(); + return; + } + } + catch + { + Dispose(); + return; + } + + // We need to decode the Gamespy specific encoding for the password + string Password = GamespyUtils.DecodePassword(Recv["passwordenc"]); + bool result = LoginServer.Database.CreateUser(Nick, Password, Email, "US"); + User = LoginServer.Database.GetUser(Nick); + + // Fetch the user to make sure we are good + if (!result || User == null) + { + Stream.Send("\\error\\\\err\\516\\fatal\\\\errmsg\\Error creating account!\\id\\1\\final\\"); + Dispose(); + return; + } + + Stream.Send("\\nur\\\\userid\\{0}\\profileid\\{0}\\id\\1\\final\\", User["id"]); + } + + + /// + /// Updates the Users Country code when sent by the client + /// + /// Array of information sent by the server + private void UpdateUser(Dictionary Recv) + { + // Set clients country code + try { + LoginServer.Database.UpdateUser(ClientNick, Recv["countrycode"]); + } + catch { + Dispose(); + } + } + + #endregion + + #region Misc Methods + + /// + /// Converts a recived parameter array from the client string to a keyValue pair dictionary + /// + /// The array of data from the client + /// + private Dictionary ConvertToKeyValue(string[] parts) + { + Dictionary Dic = new Dictionary(); + for (int i = 2; i < parts.Length; i += 2) + Dic.Add(parts[i], parts[i + 1]); + + return Dic; + } + + /// + /// Generates an encrypted reponse to return to the client, which verifies + /// the clients account information, and login info + /// + /// First challenge key + /// Second challenge key + /// Encrypted account info / Login verification + private string GenerateProof(string challenge1, string challenge2) + { + // Prepare variables + StringBuilder Response = new StringBuilder(); + StringBuilder PassHash = new StringBuilder(); + byte[] Md5Hash; + + // Convert MD5 password bytes to hex characters + Md5Hash = CreateMD5.ComputeHash(Encoding.ASCII.GetBytes(User["password"].ToString())); + foreach (byte b in Md5Hash) + PassHash.Append(BtoH[b]); + + // Generate our string to be hashed + string pHash = PassHash.ToString(); + PassHash.Append(' ', 48); // 48 spaces + PassHash.Append(String.Concat(ClientNick, challenge1, challenge2, pHash)); + + // Create our final MD5 hash, and convert all the bytes to hex yet again + Md5Hash = CreateMD5.ComputeHash(Encoding.ASCII.GetBytes(PassHash.ToString())); + foreach (byte b in Md5Hash) + Response.Append(BtoH[b]); + + return Response.ToString(); + } + + /// + /// Generates a random alpha-numeric string + /// + /// The lenght of the string to be generated + /// + private string GenerateRandomString(int length) + { + StringBuilder Response = new StringBuilder(); + for(int i = 0; i < length; i++) + Response.Append(AlphaNumChars[RandInstance.Next(62)]); + + return Response.ToString(); + } + + /// + /// Generates a random signature + /// + /// + private string GenerateSig() + { + StringBuilder Response = new StringBuilder(); + for (int length = 0; length < 32; length++) + Response.Append(HexChars[RandInstance.Next(14)]); + + return Response.ToString(); + } + + #endregion + } +} diff --git a/gspylogin/Gpcm/GpcmServer.cs b/gspylogin/Gpcm/GpcmServer.cs new file mode 100644 index 0000000..7624b7c --- /dev/null +++ b/gspylogin/Gpcm/GpcmServer.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +namespace BF2Statistics.Gamespy +{ + class GpcmServer + { + /// + /// Our GPSP Server Listener Socket + /// + private static TcpListener Listener; + + /// + /// List of connected clients + /// + private static List Clients = new List(); + + /// + /// An event called everytime a client connects, or disconnects from the server + /// + public static event EventHandler OnClientsUpdate; + + public GpcmServer() + { + // Attempt to bind to port 29900 + Listener = new TcpListener(IPAddress.Any, 29900); + Listener.Start(); + + // Create a new thread to accept the connection + Listener.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), null); + + // Enlist for events + GpcmClient.OnSuccessfulLogin += new ConnectionUpdate(GpcmClient_OnSuccessfulLogin); + GpcmClient.OnDisconnect += new GpcmConnectionClosed(GpcmClient_OnDisconnect); + } + + /// + /// Shutsdown the GPSP server and socket + /// + public void Shutdown() + { + // Stop updating client checks + Listener.Stop(); + + // Unregister events so we dont get a shit ton of calls + GpcmClient.OnDisconnect -= new GpcmConnectionClosed(GpcmClient_OnDisconnect); + + // Disconnected all connected clients + foreach (GpcmClient C in Clients) + C.Dispose(); // Donot call logout here! + + // Update Connected Clients in the Database + LoginServer.Database.Execute("UPDATE accounts SET session=0"); + Clients.Clear(); + } + + /// + /// Returns the number of connected clients + /// + /// + public int NumClients() + { + return Clients.Count; + } + + /// + /// Forces the logout of a connected client + /// + /// The account ID + /// + public bool ForceLogout(int Pid) + { + foreach (GpcmClient C in Clients) + { + if (C.ClientPID == Pid) + { + C.LogOut(); + return true; + } + } + return false; + } + + /// + /// Accepts a TcpClient + /// + /// + private void AcceptClient(IAsyncResult ar) + { + // End the operation and display the received data on + // the console. + try + { + // Hurry up and get ready to accept another client + TcpClient Client = Listener.EndAcceptTcpClient(ar); + Listener.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), null); + + // Convert the TcpClient to a GpcmClient, which will handle the client login info + Clients.Add(new GpcmClient(Client)); + } + catch { } + } + + /// + /// Callback for a successful login + /// + /// + private void GpcmClient_OnSuccessfulLogin(object sender) + { + OnClientsUpdate(this, new ClientList(Clients)); + } + + /// + /// Callback for when a connection had disconnected + /// + /// The client object whom is disconnecting + private void GpcmClient_OnDisconnect(GpcmClient client) + { + // Remove client, and call OnUpdate Event + Clients.Remove(client); + OnClientsUpdate(this, new ClientList(Clients)); + } + } +} diff --git a/gspylogin/Gpsp/GpspClient.cs b/gspylogin/Gpsp/GpspClient.cs new file mode 100644 index 0000000..c913173 --- /dev/null +++ b/gspylogin/Gpsp/GpspClient.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +namespace BF2Statistics.Gamespy +{ + public class GpspClient : IDisposable + { + /// + /// Indicates whether this object is disposed + /// + public bool Disposed { get; protected set; } + + /// + /// Connection TcpClient Stream + /// + private TcpClientStream Stream; + + /// + /// The Tcp Client + /// + private TcpClient Client; + + /// + /// The TcpClient's Endpoint + /// + private EndPoint ClientEP; + + /// + /// Event fired when the connection is closed + /// + public static event GpspConnectionClosed OnDisconnect; + + /// + /// Constructor + /// + /// + public GpspClient(TcpClient client) + { + // Set disposed to false! + this.Disposed = false; + + // Set the client variable + this.Client = client; + this.ClientEP = client.Client.RemoteEndPoint; + LoginServer.Log("[GPSP] Client Connected: {0}", ClientEP); + + // Init a new client stream class + Stream = new TcpClientStream(client); + Stream.DataReceived += new DataRecivedEvent(Stream_DataReceived); + Stream.OnDisconnect += new ConnectionClosed(Stream_OnDisconnect); + } + + /// + /// Destructor + /// + ~GpspClient() + { + if(!Disposed) + this.Dispose(); + } + + /// + /// Dispose method to be called by the server + /// + public void Dispose() + { + // If connection is still alive, disconnect user + if (Client.Client.IsConnected()) + { + Stream.IsClosing = true; + Client.Close(); + } + + // Call disconnect event + if (OnDisconnect != null) + OnDisconnect(this); + + // Preapare to be unloaded from memory + this.Disposed = true; + + // Log + LoginServer.Log("[GPSP] Client Disconnected: {0}", ClientEP); + } + + /// + /// ECallback for when when the client stream is disconnected + /// + protected void Stream_OnDisconnect() + { + Dispose(); + } + + /// + /// Callback for when a message has been recieved by the connected client + /// + public void Stream_DataReceived(string message) + { + // Parse input message + string[] recv = message.Split('\\'); + if (recv.Length == 1) + return; + + switch (recv[1]) + { + case "nicks": + SendGPSP(recv); + break; + case "check": + SendCheck(recv); + break; + } + } + + /// + /// This method is requested by the client whenever an accounts existance needs validated + /// + /// + private void SendGPSP(string[] recv) + { + // Try to get user data from database + Dictionary ClientData; + try + { + ClientData = LoginServer.Database.GetUser(GetParameterValue(recv, "email"), GetParameterValue(recv, "pass")); + if (ClientData == null) + { + Stream.Send("\\nr\\0\\ndone\\\\final\\"); + return; + } + } + catch + { + Dispose(); + return; + } + + Stream.Send("\\nr\\1\\nick\\{0}\\uniquenick\\{0}\\ndone\\\\final\\", ClientData["name"]); + } + + /// + /// This is the primary method for fetching an accounts BF2 PID + /// + /// + private void SendCheck(string[] recv) + { + try { + Stream.Send("\\cur\\0\\pid\\{0}\\final\\", LoginServer.Database.GetPID(GetParameterValue(recv, "nick"))); + } + catch + { + Dispose(); + return; + } + } + + /// + /// A simple method of getting the value of the passed parameter key, + /// from the returned array of data from the client + /// + /// The array of data from the client + /// The parameter + /// The value of the paramenter key + private string GetParameterValue(string[] parts, string parameter) + { + bool next = false; + foreach (string part in parts) + { + if (next) + return part; + else if (part == parameter) + next = true; + } + return ""; + } + } +} diff --git a/gspylogin/Gpsp/GpspServer.cs b/gspylogin/Gpsp/GpspServer.cs new file mode 100644 index 0000000..30e79fe --- /dev/null +++ b/gspylogin/Gpsp/GpspServer.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net; +using System.Net.Sockets; +using System.Threading; + +namespace BF2Statistics.Gamespy +{ + class GpspServer + { + /// + /// Our GPSP Server Listener Socket + /// + private TcpListener Listener; + + /// + /// List of connected clients + /// + public List Clients = new List(); + + public GpspServer() + { + // Attempt to bind to port 29901 + Listener = new TcpListener(IPAddress.Any, 29901); + Listener.Start(); + + // Register for disconnect + GpspClient.OnDisconnect += new GpspConnectionClosed(GpspClient_OnDisconnect); + + // Create a new thread to accept the connection + Listener.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), null); + } + + /// + /// Shutsdown the GPSP server and socket + /// + public void Shutdown() + { + // Stop updating client checks + Listener.Stop(); + + // Unregister events so we dont get a shit ton of calls + GpspClient.OnDisconnect -= new GpspConnectionClosed(GpspClient_OnDisconnect); + + // Disconnected all connected clients + foreach (GpspClient C in Clients) + C.Dispose(); + + // clear clients + Clients.Clear(); + } + + /// + /// Accepts a TcpClient + /// + /// + private void AcceptClient(IAsyncResult ar) + { + // End the operation and display the received data on + // the console. + try + { + TcpClient Client = Listener.EndAcceptTcpClient(ar); + Listener.BeginAcceptTcpClient(new AsyncCallback(AcceptClient), null); + Clients.Add(new GpspClient(Client)); + } + catch { } + } + + /// + /// Callback for when a connection had disconnected + /// + /// The client object whom is disconnecting + private void GpspClient_OnDisconnect(GpspClient client) + { + Clients.Remove(client); + } + } +} diff --git a/gspylogin/Logging/LogMessage.cs b/gspylogin/Logging/LogMessage.cs new file mode 100644 index 0000000..3966aff --- /dev/null +++ b/gspylogin/Logging/LogMessage.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; + +namespace BF2Statistics.Logging +{ + class LogMessage + { + public string Message; + public int LogTimestamp { get; protected set; } + public DateTime LogTime { get; protected set; } + + public LogMessage(string Message) + { + this.Message = Message; + this.LogTimestamp = DateTime.UtcNow.ToUnixTimestamp(); + this.LogTime = DateTime.Now; + } + + public LogMessage(string Message, params object[] Items) + { + this.Message = String.Format(Message, Items); + this.LogTimestamp = DateTime.UtcNow.ToUnixTimestamp(); + this.LogTime = DateTime.Now; + } + } +} diff --git a/gspylogin/Logging/LogWritter.cs b/gspylogin/Logging/LogWritter.cs new file mode 100644 index 0000000..eb47c24 --- /dev/null +++ b/gspylogin/Logging/LogWritter.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Timers; + +namespace BF2Statistics.Logging +{ + public class LogWritter + { + /// + /// Our Queue of log messages to be written + /// + private Queue LogQueue; + + /// + /// Full path to the log file + /// + private FileInfo LogFile; + + /// + /// Our Timer object for writing to the log file + /// + private Timer LogTimer; + + /// + /// Creates a new Log Writter, Appending all messages to a logfile + /// + /// The location of the logfile. If the file doesnt exist, + /// It will be created. + public LogWritter(string FileLocation) : this(FileLocation, false) { } + + /// + /// Creates a new Log Writter instance + /// + /// The location of the logfile. If the file doesnt exist, + /// It will be created. + /// If set to true and the logfile is over 1MB, it will be truncated to 0 length + public LogWritter(string FileLocation, bool Truncate) + { + this.createFolder(FileLocation); + LogFile = new FileInfo(FileLocation); + LogQueue = new Queue(); + + // Test that we are able to open and write to the file + using (FileStream stream = LogFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { + // If the file is over 1MB, and we want to truncate big files + if (Truncate && LogFile.Length > 1048576) + { + stream.SetLength(0); + stream.Flush(); + } + } + + // Start a log timer, and auto write new logs every 3 seconds + LogTimer = new Timer(3000); + LogTimer.Elapsed += new ElapsedEventHandler(LogTimer_Elapsed); + LogTimer.Start(); + } + + private void createFolder(string FileLocation) + { + if (!File.Exists(FileLocation)) + { + string folder = Path.GetDirectoryName(Path.GetFullPath(FileLocation)); + if (!Directory.Exists(folder)) + { + Directory.CreateDirectory(folder); + } + } + } + + /// + /// Event Fired every itnerval, which flushes the log + /// + /// + /// + private void LogTimer_Elapsed(object sender, ElapsedEventArgs e) + { + FlushLog(); + } + + /// + /// Adds a message to the queue, to be written to the log file + /// + /// The message to write to the log + public void Write(string message) + { + // Lock the queue while writing to prevent contention for the log file + LogMessage logEntry = new LogMessage(message); + lock (LogQueue) + { + // Push to the Queue + LogQueue.Enqueue(logEntry); + } + } + + /// + /// Adds a message to the queue, to be written to the log file + /// + /// The message to write to the log + public void Write(string message, params object[] items) + { + Write(String.Format(message, items)); + } + + /// + /// Flushes the Queue to the physical log file + /// + private void FlushLog() + { + // Only log if we have a queue + if (LogQueue.Count > 0) + { + using (FileStream fs = LogFile.Open(FileMode.Append, FileAccess.Write, FileShare.Read)) + using (StreamWriter log = new StreamWriter(fs)) + { + while (LogQueue.Count > 0) + { + LogMessage entry = LogQueue.Dequeue(); + String message = String.Format("[{0}]\t{1}", entry.LogTime, entry.Message); + Console.WriteLine(message); + log.WriteLine(message); + } + } + } + } + + /// + /// Destructor. Make sure we flush! + /// + ~LogWritter() + { + LogTimer.Stop(); + LogTimer.Dispose(); + FlushLog(); + } + } +} diff --git a/gspylogin/LoginServer.cs b/gspylogin/LoginServer.cs new file mode 100644 index 0000000..c57fdb1 --- /dev/null +++ b/gspylogin/LoginServer.cs @@ -0,0 +1,164 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Threading; +//using System.Windows.Forms; +using BF2Statistics.Database; +using BF2Statistics.Logging; + +namespace BF2Statistics.Gamespy +{ + /// + /// The Login Server is used to emulate the Official Gamespy Login servers, + /// and provide players the ability to create fake "Online" accounts. + /// + public class LoginServer + { + /// + /// Returns whether the login server is running or not + /// + protected static bool isRunning = false; + + /// + /// Returns whether the login server is running or not + /// + public static bool IsRunning + { + get { return isRunning; } + } + + /// + /// Gamespy GpCm Server Object + /// + private static GpcmServer CmServer; + + /// + /// The Gamespy GpSp Server Object + /// + private static GpspServer SpServer; + + /// + /// The Gamespy Database Object + /// + public static GamespyDatabase Database; + + /// + /// The Login Server Log Writter + /// + private static LogWritter Logger; + + /// + /// Event that is fired when the login server is started + /// + public static event StartupEventHandler OnStart; + + /// + /// Event that is fired when the login server is shutdown + /// + public static event ShutdownEventHandler OnShutdown; + + /// + /// Event fires to update the client list + /// + public static event EventHandler OnUpdate; + + static LoginServer() + { + // Create our log file, and register for events + Logger = new LogWritter(Path.Combine(Program.RootPath, "Logs", "LoginServer.log"), true); + GpcmServer.OnClientsUpdate += new EventHandler(CmServer_OnUpdate); + } + + /// + /// Starts the Login Server listeners, and begins accepting new connections + /// + public static void Start() + { + // Make sure we arent already running! + if (isRunning) return; + + // Start the DB Connection + Database = new GamespyDatabase(); + + // Bind gpcm server on port 29900 + int port = 29900; + try + { + CmServer = new GpcmServer(); + port++; + SpServer = new GpspServer(); + } + catch (Exception E) + { + Notify.Show( + "Failed to Start Login Server!", + "Error binding to port " + port + ": " + Environment.NewLine + E.Message, + AlertType.Warning + ); + Database.Dispose(); + throw; + } + + // Let the client know we are ready for connections + isRunning = true; + OnStart(); + } + + /// + /// Event fired when an account logs in or out + /// + /// + /// + private static void CmServer_OnUpdate(object sender, EventArgs e) + { + OnUpdate(sender, e); + } + + /// + /// Shutsdown the Login Server listeners and stops accepting new connections + /// + public static void Shutdown() + { + // Shutdown Login Servers + CmServer.Shutdown(); + SpServer.Shutdown(); + + // Close the database connection + Database.Dispose(); + + // Trigger the OnShutdown Event + OnShutdown(); + + // Update status + isRunning = false; + } + + /// + /// Forces the logout of a connected client + /// + /// + /// + public static bool ForceLogout(int Pid) + { + return (IsRunning) ? CmServer.ForceLogout(Pid) : false; + } + + /// + /// This method is used to store a message in the console.log file + /// + /// The message to be written to the log file + public static void Log(string message) + { + Logger.Write(message); + } + + /// + /// This method is used to store a message in the console.log file + /// + /// The message to be written to the log file + public static void Log(string message, params object[] items) + { + Logger.Write(String.Format(message, items)); + } + } +} diff --git a/gspylogin/MainForm.cs b/gspylogin/MainForm.cs new file mode 100644 index 0000000..45e605f --- /dev/null +++ b/gspylogin/MainForm.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BF2Statistics +{ + class MainForm + { + //public static Settings Config = Settings.Default; + public static class SysIcon + { + public static void ShowBalloonTip(int time, string mess, string text, object icon) { + Console.WriteLine(time + " " + mess + " " + text); + } + } + public static class Config + { + private static BlubbFish.Utils.InIReader i = BlubbFish.Utils.InIReader.getInstance("settings.ini"); + public static string GamespyDBEngine + { + get { return i.getValue("general", "GamespyDBEngine"); } + } + public static string GamespyDBHost + { + get { return i.getValue("general", "GamespyDBHost"); } + } + public static int GamespyDBPort + { + get { return Int32.Parse(i.getValue("general", "GamespyDBPort")); } + } + public static string GamespyDBName + { + get { return i.getValue("general", "GamespyDBName"); } + } + public static string GamespyDBUser + { + get { return i.getValue("general", "GamespyDBUser"); } + } + public static string GamespyDBPass + { + get { return i.getValue("general", "GamespyDBPass"); } + } + public static bool DebugStream + { + get { return Boolean.Parse(i.getValue("general", "DebugStream")); } + } + } + } +} diff --git a/gspylogin/Program.cs b/gspylogin/Program.cs new file mode 100644 index 0000000..80abe88 --- /dev/null +++ b/gspylogin/Program.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BF2Statistics.Gamespy; + +namespace BF2Statistics +{ + static class Program + { + private static int PeakClients = 0; + public static readonly string RootPath = "";//Application.StartupPath; + static void Main(string[] args) + { + LoginServer.OnStart += new StartupEventHandler(LoginServer_OnStart); + LoginServer.OnShutdown += new ShutdownEventHandler(LoginServer_OnShutdown); + LoginServer.OnUpdate += new EventHandler(LoginServer_OnUpdate); + LoginServer.Start(); + System.Threading.Thread t = new System.Threading.Thread(Input); + while (LoginServer.IsRunning) + { + System.Threading.Thread.Sleep(100); + if ((t.ThreadState == System.Threading.ThreadState.Stopped || + t.ThreadState == System.Threading.ThreadState.Unstarted) && LoginServer.IsRunning) + { + t = new System.Threading.Thread(Input); + t.Start(); + } + } + } + + private static void Input() + { + string inp = Console.ReadLine().Replace("\r","").Replace("\n","").Trim(); + if (inp.ToLower() == "exit") + { + LoginServer.Shutdown(); + } + } + + static void LoginServer_OnShutdown() + { + Console.WriteLine("Server Stopped!"); + } + + static void LoginServer_OnUpdate(object sender, EventArgs e) + { + // DO processing in this thread + StringBuilder SB = new StringBuilder(); + List Clients = ((ClientList)e).Clients; + if (PeakClients < Clients.Count) + PeakClients = Clients.Count; + + foreach (GpcmClient C in Clients) + SB.AppendFormat(" {0} ({1}) - {2}{3}", C.ClientNick, C.ClientPID, C.IpAddress, Environment.NewLine); + + Console.WriteLine("Clients: " + Clients.Count + " Peak: " + PeakClients); + Console.WriteLine(SB.ToString()); + } + + static void LoginServer_OnStart() + { + Console.WriteLine("Server Started!"); + } + } +} diff --git a/gspylogin/Properties/AssemblyInfo.cs b/gspylogin/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3469991 --- /dev/null +++ b/gspylogin/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die mit einer Assembly verknüpft sind. +[assembly: AssemblyTitle("gspylogin")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("gspylogin")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar +// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von +// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("8afa9350-e7b2-42c2-95e8-b382004a746c")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/gspylogin/TcpClientStream.cs b/gspylogin/TcpClientStream.cs new file mode 100644 index 0000000..cc98487 --- /dev/null +++ b/gspylogin/TcpClientStream.cs @@ -0,0 +1,170 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net; +using System.Net.Sockets; +using BF2Statistics.Logging; + +namespace BF2Statistics.Gamespy +{ + class TcpClientStream + { + /// + /// The current clients stream + /// + private TcpClient Client; + + /// + /// Clients NetworkStream + /// + private NetworkStream Stream; + + /// + /// Write all data sent/recieved to the stream log? + /// + private bool Debugging; + + /// + /// If set to true, we will not contiue listening anymore + /// + public bool IsClosing = false; + + /// + /// StreamLog Object + /// + private static LogWritter StreamLog = new LogWritter(Path.Combine(Program.RootPath, "Logs", "Stream.log")); + + /// + /// Our message buffer + /// + private byte[] buffer = new byte[2048]; + + /// + /// Our remote message from the buffer, converted to a string + /// + private StringBuilder Message = new StringBuilder(); + + /// + /// Event fired when a completed message has been recieved + /// + public event DataRecivedEvent DataReceived; + + /// + /// Event fire when the remote connection is closed + /// + public event ConnectionClosed OnDisconnect; + + /// + /// Constructor + /// + /// + public TcpClientStream(TcpClient client) + { + this.Client = client; + this.Stream = client.GetStream(); + this.Debugging = MainForm.Config.DebugStream; + Stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), Stream); + } + + /// + /// Callback for BeginRead. This method handles the message parsing + /// + /// + private void ReadCallback(IAsyncResult ar) + { + // End the Async Read + int bytesRead = 0; + try + { + bytesRead = Stream.EndRead(ar); + } + catch (IOException e) + { + // If we got an IOException, client connection is lost + if (Client.Client.IsConnected()) + Log("ERROR: IOException Thrown during read: " + e.Message); + } + catch (ObjectDisposedException) { } // Fired when a the login server is shutown + + // Force disconnect (Specifically for Gpsp, whom will spam null bytes) + if (bytesRead == 0) + { + OnDisconnect(); // Parent is responsible for closing the connection + return; + } + + // Add message to buffer + Message.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead)); + + // If we have no more data, then the message is complete + if (!Stream.DataAvailable) + { + // Debugging + if (Debugging) + Log("Port {0} Recieves: {1}", ((IPEndPoint)Client.Client.LocalEndPoint).Port, Message.ToString()); + + // tell our parent that we recieved a message + DataReceived(Message.ToString()); + Message = new StringBuilder(); + } + + // Begin a new Read + if (!IsClosing) + Stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), Stream); + } + + /// + /// Writes a message to the client stream + /// + /// The complete message to be sent to the client + public void Send(string message) + { + if (Debugging) + Log("Port {0} Sends: {1}", ((IPEndPoint)Client.Client.LocalEndPoint).Port, message); + + this.Send(Encoding.ASCII.GetBytes(message)); + } + + /// + /// Writes a message to the client stream + /// + /// The complete message to be sent to the client + public void Send(string message, params object[] items) + { + message = String.Format(message, items); + if (Debugging) + Log("Port {0} Sends: {1}", ((IPEndPoint)Client.Client.LocalEndPoint).Port, message); + + this.Send(Encoding.ASCII.GetBytes(message)); + } + + /// + /// Writes a message to the client stream + /// + /// An array of bytes to send to the stream + public void Send(byte[] bytes) + { + Stream.Write(bytes, 0, bytes.Length); + } + + /// + /// Writes a message to the stream log + /// + /// + private static void Log(string message) + { + StreamLog.Write(message); + } + + /// + /// Writes a message to the stream log + /// + /// + private static void Log(string message, params object[] items) + { + StreamLog.Write(String.Format(message, items)); + } + } +} diff --git a/gspylogin/Utilities/Crc16.cs b/gspylogin/Utilities/Crc16.cs new file mode 100644 index 0000000..71fe72a --- /dev/null +++ b/gspylogin/Utilities/Crc16.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BF2Statistics.Utilities +{ + public enum Crc16Mode : ushort + { + Standard = 0xA001, + CCITT = 4129, + CCITTKermit = 0x8408 + } + + /// + /// Credits go to http://www.sanity-free.com/134/standard_crc_16_in_csharp.html + /// + public class Crc16 + { + /// + /// The Crc16 Table + /// + public ushort[] CrcTable + { + get; + protected set; + } + + public Crc16() + { + // Build Standard Crc16 Table + BuildCrcTable(0xA001); + } + + public Crc16(ushort polynomial) + { + BuildCrcTable(polynomial); + } + + public Crc16(Crc16Mode Mode) + { + BuildCrcTable((ushort)Mode); + } + + /// + /// Calculates the Checksum for the input string + /// + /// + /// + public ushort ComputeChecksum(string Input) + { + return ComputeChecksum(Encoding.ASCII.GetBytes(Input)); + } + + /// + /// Calculates the Checksum for the given bytes + /// + /// + /// + public ushort ComputeChecksum(byte[] bytes) + { + ushort crc = 0; + for (int i = 0; i < bytes.Length; ++i) + { + //byte index = (byte)(crc ^ bytes[i]); + //crc = (ushort)((crc >> 8) ^ CrcTable[index]); + crc = (ushort)(CrcTable[(bytes[i] ^ crc) & 0xFF] ^ (crc >> 8)); + // crc = (ushort)((crc << 8) ^ CrcTable[((crc >> 8) ^ (0xff & bytes[i]))]); + } + return crc; + } + + /// + /// Builds the Crc table programatically with the given polynomial + /// + /// + private void BuildCrcTable(ushort polynomial) + { + ushort value; + ushort temp; + + // Build standard Crc16 Table + CrcTable = new ushort[256]; + for (ushort i = 0; i < 256; ++i) + { + value = 0; + temp = i; + for (byte j = 0; j < 8; ++j) + { + if (((value ^ temp) & 0x0001) != 0) + value = (ushort)((value >> 1) ^ polynomial); + else + value >>= 1; + + temp >>= 1; + } + + CrcTable[i] = value; + } + } + } +} diff --git a/gspylogin/Utilities/Notify.cs b/gspylogin/Utilities/Notify.cs new file mode 100644 index 0000000..19eab8f --- /dev/null +++ b/gspylogin/Utilities/Notify.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +//using System.Windows.Forms; +using System.Threading; + +namespace BF2Statistics +{ + + public enum AlertType + { + Info, Success, Warning + } + /// + /// Notify is a class that queues and shows Alert "toast" messages + /// to the user, which spawn just above the task bar, in the lower + /// right hand side of the screen + /// + class Notify + { + /// + /// A queue of alerts to display. Alerts are added here to prevent + /// too many alerts from showing at once + /// + protected static Queue Alerts = new Queue(); + + /// + /// Returns the number of open / active alerts + /// + public static bool AlertsShowing { get; protected set; } + + /// + /// Gets or Sets the default dock time of an alert, if one is not specified in + /// the ShowAlert method + /// + public static int DefaultDockTime = 3000; + + /// + /// Static Constructor + /// + static Notify() + { + AlertsShowing = false; + //MainForm.SysIcon.BalloonTipClosed += new EventHandler(AlertClosed); + } + + /// + /// Displays a generic Toast message with the Info icon + /// + /// + /// + public static void Show(string Message, string SubText) + { + Alerts.Enqueue(new NotifyOptions(Message, SubText, AlertType.Info)); + CheckAlerts(); + } + + /// + /// Shows a custom Toast message with the specified icon + /// + /// + /// + /// + public static void Show(string Message, string SubText, AlertType Type) + { + Alerts.Enqueue(new NotifyOptions(Message, SubText, Type)); + CheckAlerts(); + } + + /// + /// This method is called internally to determine if a new alert + /// can be shown from the alert queue. + /// + protected static void CheckAlerts() + { + if (!AlertsShowing && Alerts.Count > 0) + { + AlertsShowing = true; + NotifyOptions Opt = Alerts.Dequeue(); + //MainForm.Instance.Invoke((Action)delegate + //{ + MainForm.SysIcon.ShowBalloonTip(DefaultDockTime, Opt.Message, Opt.SubText, null); + //}); + } + } + + /// + /// Event is fired whenever a Toast alert is closed. This method is responsible + /// for displaying the next queued alert message + /// + /// + /// + private static void AlertClosed(object sender, EventArgs e) + { + AlertsShowing = false; + CheckAlerts(); + } + + /// + /// An internal structure used to descibe the details on an Alert message + /// to be displayed in the future + /// + internal struct NotifyOptions + { + public string Message; + public string SubText; + //public ToolTipIcon Icon; + + public NotifyOptions(string Message, string SubText, AlertType Type) + { + this.Message = Message; + this.SubText = SubText; + + switch (Type) + { + default: + //Icon = ToolTipIcon.Info; + break; + case AlertType.Warning: + //Icon = ToolTipIcon.Warning; + break; + } + } + } + } +} diff --git a/gspylogin/Utilities/Utils.cs b/gspylogin/Utilities/Utils.cs new file mode 100644 index 0000000..d4dbff7 --- /dev/null +++ b/gspylogin/Utilities/Utils.cs @@ -0,0 +1,75 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using System.Diagnostics; +using System.Net; + +namespace BF2Statistics +{ + public static class Utils + { + /// + /// Gets the string contents of an embedded resource + /// + /// + /// + public static string GetResourceAsString(string ResourceName) + { + string Result = ""; + using (Stream ResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ResourceName)) + using (StreamReader Reader = new StreamReader(ResourceStream)) + Result = Reader.ReadToEnd(); + + return Result; + } + + /// + /// Gets the lines of a resource file + /// + /// + /// + public static string[] GetResourceFileLines(string ResourceName) + { + List Lines = new List(); + using (Stream ResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ResourceName)) + using (StreamReader Reader = new StreamReader(ResourceStream)) + while(!Reader.EndOfStream) + Lines.Add(Reader.ReadLine()); + + return Lines.ToArray(); + } + + /// + /// Converts a Timespan of seconds into Hours, Minutes, and Seconds + /// + /// Seconds to convert + /// + public static string Sec2hms(int seconds) + { + TimeSpan t = TimeSpan.FromSeconds(seconds); + StringBuilder SB = new StringBuilder(); + char[] trim = new char[] { ',', ' ' }; + int Hours = t.Hours; + + // If we have more then 24 hours, then we need to + // convert the days to hours + if (t.Days > 0) + Hours += t.Days * 24; + + // Format + if (Hours > 0) + SB.AppendFormat("{0} Hours, ", Hours); + + if (t.Minutes > 0) + SB.AppendFormat("{0} Minutes, ", t.Minutes); + + if (t.Seconds > 0) + SB.AppendFormat("{0} Seconds, ", t.Seconds); + + return SB.ToString().TrimEnd(trim); + } + } +} diff --git a/gspylogin/gspylogin.csproj b/gspylogin/gspylogin.csproj new file mode 100644 index 0000000..1fe1eab --- /dev/null +++ b/gspylogin/gspylogin.csproj @@ -0,0 +1,91 @@ + + + + + Debug + AnyCPU + {ADFD42CE-4E2E-42F2-94BC-634AAE32A7BD} + Exe + Properties + gspylogin + gspylogin + v4.5 + 512 + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\lib\MySql.Data.dll + + + + + ..\lib\System.Data.SQLite.dll + + + + + + + + ..\..\Utils\Utils\bin\Debug\Utils.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + \ No newline at end of file diff --git a/gspylogin/settings.ini b/gspylogin/settings.ini new file mode 100644 index 0000000..6be86d8 --- /dev/null +++ b/gspylogin/settings.ini @@ -0,0 +1,8 @@ +[general] +GamespyDBEngine=Mysql +GamespyDBHost=localhost +GamespyDBPort=3306 +GamespyDBName=gamespy +GamespyDBUser=root +GamespyDBPass=mafia +DebugStream=True \ No newline at end of file diff --git a/lib/MySql.Data.dll b/lib/MySql.Data.dll new file mode 100644 index 0000000..fd3c20a Binary files /dev/null and b/lib/MySql.Data.dll differ diff --git a/lib/System.Data.SQLite.dll b/lib/System.Data.SQLite.dll new file mode 100644 index 0000000..ddd5c8a Binary files /dev/null and b/lib/System.Data.SQLite.dll differ diff --git a/lib/System.Data.SQLite.xml b/lib/System.Data.SQLite.xml new file mode 100644 index 0000000..d2f5e65 --- /dev/null +++ b/lib/System.Data.SQLite.xml @@ -0,0 +1,5365 @@ + + + + System.Data.SQLite + + + + + This is the method signature for the SQLite core library logging callback + function for use with sqlite3_log() and the SQLITE_CONFIG_LOG. + + WARNING: This delegate is used more-or-less directly by native code, do + not modify its type signature. + + + The extra data associated with this message, if any. + + + The error code associated with this message. + + + The message string to be logged. + + + + + This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET + + + + + This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement + a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite. + + + + + This base class provides datatype conversion services for the SQLite provider. + + + + + The format string for DateTime values when using the InvariantCulture or CurrentCulture formats. + + + + + The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC). + + + + + The value of the OLE Automation epoch represented as a Julian day. + + + + + An array of ISO8601 datetime formats we support conversion from + + + + + The internal default format for UTC DateTime values when converting + to a string. + + + + + The internal default format for local DateTime values when converting + to a string. + + + + + An UTF-8 Encoding instance, so we can convert strings to and from UTF-8 + + + + + The default DateTime format for this instance + + + + + The default DateTimeKind for this instance. + + + + + Initializes the conversion class + + The default date/time format to use for this instance + The DateTimeKind to use. + + + + Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character. + + The string to convert to UTF-8 + A byte array containing the converted string plus an extra 0 terminating byte at the end of the array. + + + + Convert a DateTime to a UTF-8 encoded, zero-terminated byte array. + + + This function is a convenience function, which first calls ToString() on the DateTime, and then calls ToUTF8() with the + string result. + + The DateTime to convert. + The UTF-8 encoded string, including a 0 terminating byte at the end of the array. + + + + Converts a UTF-8 encoded IntPtr of the specified length into a .NET string + + The pointer to the memory where the UTF-8 string is encoded + The number of bytes to decode + A string containing the translated character(s) + + + + Converts a UTF-8 encoded IntPtr of the specified length into a .NET string + + The pointer to the memory where the UTF-8 string is encoded + The number of bytes to decode + A string containing the translated character(s) + + + + Converts a string into a DateTime, using the current DateTimeFormat specified for the connection when it was opened. + + + Acceptable ISO8601 DateTime formats are: + + THHmmssK + THHmmK + HH:mm:ss.FFFFFFFK + HH:mm:ssK + HH:mmK + yyyy-MM-dd HH:mm:ss.FFFFFFFK + yyyy-MM-dd HH:mm:ssK + yyyy-MM-dd HH:mmK + yyyy-MM-ddTHH:mm:ss.FFFFFFFK + yyyy-MM-ddTHH:mmK + yyyy-MM-ddTHH:mm:ssK + yyyyMMddHHmmssK + yyyyMMddHHmmK + yyyyMMddTHHmmssFFFFFFFK + THHmmss + THHmm + HH:mm:ss.FFFFFFF + HH:mm:ss + HH:mm + yyyy-MM-dd HH:mm:ss.FFFFFFF + yyyy-MM-dd HH:mm:ss + yyyy-MM-dd HH:mm + yyyy-MM-ddTHH:mm:ss.FFFFFFF + yyyy-MM-ddTHH:mm + yyyy-MM-ddTHH:mm:ss + yyyyMMddHHmmss + yyyyMMddHHmm + yyyyMMddTHHmmssFFFFFFF + yyyy-MM-dd + yyyyMMdd + yy-MM-dd + + If the string cannot be matched to one of the above formats, an exception will be thrown. + + The string containing either a long integer number of 100-nanosecond units since + System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a + culture-independent formatted date and time string, a formatted date and time string in the current + culture, or an ISO8601-format string. + A DateTime value + + + + Converts a string into a DateTime, using the specified DateTimeFormat and DateTimeKind. + + + Acceptable ISO8601 DateTime formats are: + + THHmmssK + THHmmK + HH:mm:ss.FFFFFFFK + HH:mm:ssK + HH:mmK + yyyy-MM-dd HH:mm:ss.FFFFFFFK + yyyy-MM-dd HH:mm:ssK + yyyy-MM-dd HH:mmK + yyyy-MM-ddTHH:mm:ss.FFFFFFFK + yyyy-MM-ddTHH:mmK + yyyy-MM-ddTHH:mm:ssK + yyyyMMddHHmmssK + yyyyMMddHHmmK + yyyyMMddTHHmmssFFFFFFFK + THHmmss + THHmm + HH:mm:ss.FFFFFFF + HH:mm:ss + HH:mm + yyyy-MM-dd HH:mm:ss.FFFFFFF + yyyy-MM-dd HH:mm:ss + yyyy-MM-dd HH:mm + yyyy-MM-ddTHH:mm:ss.FFFFFFF + yyyy-MM-ddTHH:mm + yyyy-MM-ddTHH:mm:ss + yyyyMMddHHmmss + yyyyMMddHHmm + yyyyMMddTHHmmssFFFFFFF + yyyy-MM-dd + yyyyMMdd + yy-MM-dd + + If the string cannot be matched to one of the above formats, an exception will be thrown. + + The string containing either a long integer number of 100-nanosecond units since + System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a + culture-independent formatted date and time string, a formatted date and time string in the current + culture, or an ISO8601-format string. + The SQLiteDateFormats to use. + The DateTimeKind to use. + A DateTime value + + + + Converts a julianday value into a DateTime + + The value to convert + A .NET DateTime + + + + Converts a julianday value into a DateTime + + The value to convert + The DateTimeKind to use. + A .NET DateTime + + + + Converts a DateTime struct to a JulianDay double + + The DateTime to convert + The JulianDay value the Datetime represents + + + + Converts a DateTime struct to the whole number of seconds since the + Unix epoch. + + The DateTime to convert + The whole number of seconds since the Unix epoch + + + + Returns the default DateTime format string to use for the specified + DateTimeKind. + + The DateTimeKind to use. + + The default DateTime format string to use for the specified DateTimeKind. + + + + + Converts a DateTime to a string value, using the current DateTimeFormat specified for the connection when it was opened. + + The DateTime value to convert + Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a + Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time + string, a formatted date and time string in the current culture, or an ISO8601-format date/time string. + + + + Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime. + + + This is a convenience function, which first calls ToString() on the IntPtr to convert it to a string, then calls + ToDateTime() on the string to return a DateTime. + + A pointer to the UTF-8 encoded string + The length in bytes of the string + The parsed DateTime value + + + + Smart method of splitting a string. Skips quoted elements, removes the quotes. + + + This split function works somewhat like the String.Split() function in that it breaks apart a string into + pieces and returns the pieces as an array. The primary differences are: + + Only one character can be provided as a separator character + Quoted text inside the string is skipped over when searching for the separator, and the quotes are removed. + + Thus, if splitting the following string looking for a comma:
+ One,Two, "Three, Four", Five
+
+ The resulting array would contain
+ [0] One
+ [1] Two
+ [2] Three, Four
+ [3] Five
+
+ Note that the leading and trailing spaces were removed from each item during the split. +
+ Source string to split apart + Separator character + A string array of the split up elements +
+ + + Convert a value to true or false. + + A string or number representing true or false + + + + + Convert a string to true or false. + + A string representing true or false + + + "yes", "no", "y", "n", "0", "1", "on", "off" as well as Boolean.FalseString and Boolean.TrueString will all be + converted to a proper boolean value. + + + + + Determines the data type of a column in a statement + + The statement to retrieve information for + The column to retrieve type information on + The SQLiteType to receive the affinity for the given column + + + + Converts a SQLiteType to a .NET Type object + + The SQLiteType to convert + Returns a .NET Type object + + + + For a given intrinsic type, return a DbType + + The native type to convert + The corresponding (closest match) DbType + + + + Returns the ColumnSize for the given DbType + + The DbType to get the size of + + + + + Convert a DbType to a Type + + The DbType to convert from + The closest-match .NET type + + + + For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types. + + The type to evaluate + The SQLite type affinity for that type. + + + + For a given type name, return a closest-match .NET type + + The name of the type to match + The .NET DBType the text evaluates to. + + + + Sets the status of the memory usage tracking subsystem in the SQLite core library. By default, this is enabled. + If this is disabled, memory usage tracking will not be performed. This is not really a per-connection value, it is + global to the process. + + Non-zero to enable memory usage tracking, zero otherwise. + A standard SQLite return code (i.e. zero for success and non-zero for failure). + + + + Shutdown the SQLite engine so that it can be restarted with different config options. + We depend on auto initialization to recover. + + + + + Returns non-zero if a database connection is open. + + + + + + Opens a database. + + + Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection + to bind all attributed user-defined functions and collating sequences to the new connection. + + The filename of the database to open. SQLite automatically creates it if it doesn't exist. + The flags associated with the parent connection object + The open flags to use when creating the connection + The maximum size of the pool for the given filename + If true, the connection can be pulled from the connection pool + + + + Closes the currently-open database. + + + After the database has been closed implemeters should call SQLiteFunction.UnbindFunctions() to deallocate all interop allocated + memory associated with the user-defined functions and collating sequences tied to the closed connection. + + Non-zero if the operation is allowed to throw exceptions, zero otherwise. + + + + Sets the busy timeout on the connection. SQLiteCommand will call this before executing any command. + + The number of milliseconds to wait before returning SQLITE_BUSY + + + + Returns the text of the last error issued by SQLite + + + + + + When pooling is enabled, force this connection to be disposed rather than returned to the pool + + + + + When pooling is enabled, returns the number of pool entries matching the current file name. + + The number of pool entries matching the current file name. + + + + Prepares a SQL statement for execution. + + The source connection preparing the command. Can be null for any caller except LINQ + The SQL command text to prepare + The previous statement in a multi-statement command, or null if no previous statement exists + The timeout to wait before aborting the prepare + The remainder of the statement that was not processed. Each call to prepare parses the + SQL up to to either the end of the text or to the first semi-colon delimiter. The remaining text is returned + here for a subsequent call to Prepare() until all the text has been processed. + Returns an initialized SQLiteStatement. + + + + Steps through a prepared statement. + + The SQLiteStatement to step through + True if a row was returned, False if not. + + + + Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA, + transparently attempt to rebuild the SQL statement and throw an error if that was not possible. + + The statement to reset + Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock + + + + Enables or disabled extension loading by SQLite. + + + True to enable loading of extensions, false to disable. + + + + + Loads a SQLite extension library from the named file. + + + The name of the dynamic link library file containing the extension. + + + The name of the exported function used to initialize the extension. + If null, the default "sqlite3_extension_init" will be used. + + + + + Enables or disabled extened result codes returned by SQLite + + true to enable extended result codes, false to disable. + + + + + Returns the numeric result code for the most recent failed SQLite API call + associated with the database connection. + + Result code + + + + Returns the extended numeric result code for the most recent failed SQLite API call + associated with the database connection. + + Extended result code + + + + Add a log message via the SQLite sqlite3_log interface. + + Error code to be logged with the message. + String to be logged. Unlike the SQLite sqlite3_log() + interface, this should be pre-formatted. Consider using the + String.Format() function. + + + + + Checks if the SQLite core library has been initialized in the current process. + + + Non-zero if the SQLite core library has been initialized in the current process, + zero otherwise. + + + + + Creates a new SQLite backup object based on the provided destination + database connection. The source database connection is the one + associated with this object. The source and destination database + connections cannot be the same. + + The destination database connection. + The destination database name. + The source database name. + The newly created backup object. + + + + Copies up to N pages from the source database to the destination + database associated with the specified backup object. + + The backup object to use. + + The number of pages to copy or negative to copy all remaining pages. + + + Set to true if the operation needs to be retried due to database + locking issues. + + + True if there are more pages to be copied, false otherwise. + + + + + Returns the number of pages remaining to be copied from the source + database to the destination database associated with the specified + backup object. + + The backup object to check. + The number of pages remaining to be copied. + + + + Returns the total number of pages in the source database associated + with the specified backup object. + + The backup object to check. + The total number of pages in the source database. + + + + Destroys the backup object, rolling back any backup that may be in + progess. + + The backup object to destroy. + + + + Returns the error message for the specified SQLite return code using + the internal static lookup table. + + The SQLite return code. + The error message or null if it cannot be found. + + + + Returns the error message for the specified SQLite return code using + the sqlite3_errstr() function, falling back to the internal lookup + table if necessary. + + The SQLite return code. + The error message or null if it cannot be found. + + + + Returns a string representing the active version of SQLite + + + + + Returns an integer representing the active version of SQLite + + + + + Returns the rowid of the most recent successful INSERT into the database from this connection. + + + + + Returns the number of changes the last executing insert/update caused. + + + + + Returns the amount of memory (in bytes) currently in use by the SQLite core library. This is not really a per-connection + value, it is global to the process. + + + + + Returns the maximum amount of memory (in bytes) used by the SQLite core library since the high-water mark was last reset. + This is not really a per-connection value, it is global to the process. + + + + + The opaque pointer returned to us by the sqlite provider + + + + + The user-defined functions registered on this connection + + + + + Shutdown the SQLite engine so that it can be restarted with different config options. + We depend on auto initialization to recover. + + Returns a result code + + + + Enables or disabled extension loading by SQLite. + + + True to enable loading of extensions, false to disable. + + + + + Loads a SQLite extension library from the named file. + + + The name of the dynamic link library file containing the extension. + + + The name of the exported function used to initialize the extension. + If null, the default "sqlite3_extension_init" will be used. + + + + Enables or disabled extended result codes returned by SQLite + + + Gets the last SQLite error code + + + Gets the last SQLite extended error code + + + Add a log message via the SQLite sqlite3_log interface. + + + + Allows the setting of a logging callback invoked by SQLite when a + log event occurs. Only one callback may be set. If NULL is passed, + the logging callback is unregistered. + + The callback function to invoke. + Returns a result code + + + + Creates a new SQLite backup object based on the provided destination + database connection. The source database connection is the one + associated with this object. The source and destination database + connections cannot be the same. + + The destination database connection. + The destination database name. + The source database name. + The newly created backup object. + + + + Copies up to N pages from the source database to the destination + database associated with the specified backup object. + + The backup object to use. + + The number of pages to copy, negative to copy all remaining pages. + + + Set to true if the operation needs to be retried due to database + locking issues; otherwise, set to false. + + + True if there are more pages to be copied, false otherwise. + + + + + Returns the number of pages remaining to be copied from the source + database to the destination database associated with the specified + backup object. + + The backup object to check. + The number of pages remaining to be copied. + + + + Returns the total number of pages in the source database associated + with the specified backup object. + + The backup object to check. + The total number of pages in the source database. + + + + Destroys the backup object, rolling back any backup that may be in + progess. + + The backup object to destroy. + + + + Determines if the SQLite core library has been initialized for the + current process. + + + A boolean indicating whether or not the SQLite core library has been + initialized for the current process. + + + + + Determines if the SQLite core library has been initialized for the + current process. + + + A boolean indicating whether or not the SQLite core library has been + initialized for the current process. + + + + + Helper function to retrieve a column of data from an active statement. + + The statement being step()'d through + The column index to retrieve + The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information. + Returns the data in the column + + + + Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) + + + + + Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8 + + A pointer to a UTF-16 string + The length (IN BYTES) of the string + A .NET string + + + + Represents a single SQL backup in SQLite. + + + + + The underlying SQLite object this backup is bound to. + + + + + The actual backup handle. + + + + + The destination database for the backup. + + + + + The destination database name for the backup. + + + + + The source database for the backup. + + + + + The source database name for the backup. + + + + + The last result from the StepBackup method of the SQLite3 class. + This is used to determine if the call to the FinishBackup method of + the SQLite3 class should throw an exception when it receives a non-Ok + return code from the core SQLite library. + + + + + Initializes the backup. + + The base SQLite object. + The backup handle. + The destination database for the backup. + The destination database name for the backup. + The source database for the backup. + The source database name for the backup. + + + + Disposes and finalizes the backup. + + + + + The extra behavioral flags that can be applied to a connection. + + + + + No extra flags. + + + + + Enable logging of all SQL statements to be prepared. + + + + + Enable logging of all bound parameter types and raw values. + + + + + Enable logging of all bound parameter strongly typed values. + + + + + Enable logging of all exceptions caught from user-provided + managed code called from native code via delegates. + + + + + Enable logging of backup API errors. + + + + + Skip adding the extension functions provided by the native + interop assembly. + + + + + Enable all logging. + + + + + The default extra flags for new connections. + + + + + SQLite implementation of DbCommand. + + + + + The command text this command is based on + + + + + The connection the command is associated with + + + + + The version of the connection the command is associated with + + + + + Indicates whether or not a DataReader is active on the command. + + + + + The timeout for the command, kludged because SQLite doesn't support per-command timeout values + + + + + Designer support + + + + + Used by DbDataAdapter to determine updating behavior + + + + + The collection of parameters for the command + + + + + The SQL command text, broken into individual SQL statements as they are executed + + + + + Unprocessed SQL text that has not been executed + + + + + Transaction associated with this command + + + + + Constructs a new SQLiteCommand + + + Default constructor + + + + + Initializes the command with the given command text + + The SQL command text + + + + Initializes the command with the given SQL command text and attach the command to the specified + connection. + + The SQL command text + The connection to associate with the command + + + + Initializes the command and associates it with the specified connection. + + The connection to associate with the command + + + + Initializes a command with the given SQL, connection and transaction + + The SQL command text + The connection to associate with the command + The transaction the command should be associated with + + + + Disposes of the command and clears all member variables + + Whether or not the class is being explicitly or implicitly disposed + + + + Clears and destroys all statements currently prepared + + + + + Builds an array of prepared statements for each complete SQL statement in the command text + + + + + Not implemented + + + + + Forwards to the local CreateParameter() function + + + + + + Create a new parameter + + + + + + This function ensures there are no active readers, that we have a valid connection, + that the connection is open, that all statements are prepared and all parameters are assigned + in preparation for allocating a data reader. + + + + + Creates a new SQLiteDataReader to execute/iterate the array of SQLite prepared statements + + The behavior the data reader should adopt + Returns a SQLiteDataReader object + + + + Overrides the default behavior to return a SQLiteDataReader specialization class + + The flags to be associated with the reader + A SQLiteDataReader + + + + Overrides the default behavior of DbDataReader to return a specialized SQLiteDataReader class + + A SQLiteDataReader + + + + Called by the SQLiteDataReader when the data reader is closed. + + + + + Execute the command and return the number of rows inserted/updated affected by it. + + + + + + Execute the command and return the first column of the first row of the resultset + (if present), or null if no resultset was returned. + + The first column of the first row of the first resultset from the query + + + + Does nothing. Commands are prepared as they are executed the first time, and kept in prepared state afterwards. + + + + + Clones a command, including all its parameters + + A new SQLiteCommand with the same commandtext, connection and parameters + + + + The SQL command text associated with the command + + + + + The amount of time to wait for the connection to become available before erroring out + + + + + The type of the command. SQLite only supports CommandType.Text + + + + + The connection associated with this command + + + + + Forwards to the local Connection property + + + + + Returns the SQLiteParameterCollection for the given command + + + + + Forwards to the local Parameters property + + + + + The transaction associated with this command. SQLite only supports one transaction per connection, so this property forwards to the + command's underlying connection. + + + + + Forwards to the local Transaction property + + + + + Sets the method the SQLiteCommandBuilder uses to determine how to update inserted or updated rows in a DataTable. + + + + + Determines if the command is visible at design time. Defaults to True. + + + + + SQLite implementation of DbCommandBuilder. + + + + + Default constructor + + + + + Initializes the command builder and associates it with the specified data adapter. + + + + + + Minimal amount of parameter processing. Primarily sets the DbType for the parameter equal to the provider type in the schema + + The parameter to use in applying custom behaviors to a row + The row to apply the parameter to + The type of statement + Whether the application of the parameter is part of a WHERE clause + + + + Returns a valid named parameter + + The name of the parameter + Error + + + + Returns a named parameter for the given ordinal + + The i of the parameter + Error + + + + Returns a placeholder character for the specified parameter i. + + The index of the parameter to provide a placeholder for + Returns a named parameter + + + + Sets the handler for receiving row updating events. Used by the DbCommandBuilder to autogenerate SQL + statements that may not have previously been generated. + + A data adapter to receive events on. + + + + Returns the automatically-generated SQLite command to delete rows from the database + + + + + + Returns the automatically-generated SQLite command to delete rows from the database + + + + + + + Returns the automatically-generated SQLite command to update rows in the database + + + + + + Returns the automatically-generated SQLite command to update rows in the database + + + + + + + Returns the automatically-generated SQLite command to insert rows into the database + + + + + + Returns the automatically-generated SQLite command to insert rows into the database + + + + + + + Places brackets around an identifier + + The identifier to quote + The bracketed identifier + + + + Removes brackets around an identifier + + The quoted (bracketed) identifier + The undecorated identifier + + + + Override helper, which can help the base command builder choose the right keys for the given query + + + + + + + Gets/sets the DataAdapter for this CommandBuilder + + + + + Overridden to hide its property from the designer + + + + + Overridden to hide its property from the designer + + + + + Overridden to hide its property from the designer + + + + + Overridden to hide its property from the designer + + + + + Overridden to hide its property from the designer + + + + + Event data for connection event handlers. + + + + + The type of event being raised. + + + + + The associated with this event, if any. + + + + + The transaction associated with this event, if any. + + + + + The command associated with this event, if any. + + + + + Command or message text associated with this event, if any. + + + + + Extra data associated with this event, if any. + + + + + Constructs the object. + + The type of event being raised. + The base associated + with this event, if any. + The transaction associated with this event, if any. + The command associated with this event, if any. + The command or message text, if any. + The extra data, if any. + + + + Raised when an event pertaining to a connection occurs. + + The connection involved. + Extra information about the event. + + + + SQLite implentation of DbConnection. + + + The property can contain the following parameter(s), delimited with a semi-colon: + + + Parameter + Values + Required + Default + + + Data Source + This may be a file name, the string ":memory:", or any supported URI (starting with SQLite 3.7.7). + Y + + + + Version + 3 + N + 3 + + + UseUTF16Encoding + True
False
+ N + False +
+ + DateTimeFormat + + Ticks - Use the value of DateTime.Ticks.
+ ISO8601 - Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC + DateTime values and "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values).
+ JulianDay - The interval of time in days and fractions of a day since January 1, 4713 BC.
+ UnixEpoch - The whole number of seconds since the Unix epoch (January 1, 1970).
+ InvariantCulture - Any culture-independent string value that the .NET Framework can interpret as a valid DateTime.
+ CurrentCulture - Any string value that the .NET Framework can interpret as a valid DateTime using the current culture.
+ N + ISO8601 +
+ + DateTimeKind + Unspecified - Not specified as either UTC or local time.
Utc - The time represented is UTC.
Local - The time represented is local time.
+ N + Unspecified +
+ + BaseSchemaName + Some base data classes in the framework (e.g. those that build SQL queries dynamically) + assume that an ADO.NET provider cannot support an alternate catalog (i.e. database) without supporting + alternate schemas as well; however, SQLite does not fit into this model. Therefore, this value is used + as a placeholder and removed prior to preparing any SQL statements that may contain it. + N + sqlite_default_schema + + + BinaryGUID + True - Store GUID columns in binary form
False - Store GUID columns as text
+ N + True +
+ + Cache Size + {size in bytes} + N + 2000 + + + Synchronous + Normal - Normal file flushing behavior
Full - Full flushing after all writes
Off - Underlying OS flushes I/O's
+ N + Full +
+ + Page Size + {size in bytes} + N + 1024 + + + Password + {password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection. + N + + + + Enlist + Y - Automatically enlist in distributed transactions
N - No automatic enlistment
+ N + Y +
+ + Pooling + True - Use connection pooling
False - Do not use connection pooling
+ N + False +
+ + FailIfMissing + True - Don't create the database if it does not exist, throw an error instead
False - Automatically create the database if it does not exist
+ N + False +
+ + Max Page Count + {size in pages} - Limits the maximum number of pages (limits the size) of the database + N + 0 + + + Legacy Format + True - Use the more compatible legacy 3.x database format
False - Use the newer 3.3x database format which compresses numbers more effectively
+ N + False +
+ + Default Timeout + {time in seconds}
The default command timeout
+ N + 30 +
+ + Journal Mode + Delete - Delete the journal file after a commit
Persist - Zero out and leave the journal file on disk after a commit
Off - Disable the rollback journal entirely
+ N + Delete +
+ + Read Only + True - Open the database for read only access
False - Open the database for normal read/write access
+ N + False +
+ + Max Pool Size + The maximum number of connections for the given connection string that can be in the connection pool + N + 100 + + + Default IsolationLevel + The default transaciton isolation level + N + Serializable + + + Foreign Keys + Enable foreign key constraints + N + False + + + Flags + Extra behavioral flags for the connection. See the enumeration for possible values. + N + Default + + + SetDefaults + + True - Apply the default connection settings to the opened database.
+ False - Skip applying the default connection settings to the opened database. +
+ N + True +
+ + ToFullPath + + True - Attempt to expand the data source file name to a fully qualified path before opening.
+ False - Skip attempting to expand the data source file name to a fully qualified path before opening. +
+ N + True +
+
+
+
+ + + The default "stub" (i.e. placeholder) base schema name to use when + returning column schema information. Used as the initial value of + the BaseSchemaName property. This should start with "sqlite_*" + because those names are reserved for use by SQLite (i.e. they cannot + be confused with the names of user objects). + + + + + Object used to synchronize access to the static instance data + for this class. + + + + + State of the current connection + + + + + The connection string + + + + + Nesting level of the transactions open on the connection + + + + + If set, then the connection is currently being disposed. + + + + + The default isolation level for new transactions + + + + + Whether or not the connection is enlisted in a distrubuted transaction + + + + + The base SQLite object to interop with + + + + + The database filename minus path and extension + + + + + Temporary password storage, emptied after the database has been opened + + + + + The "stub" (i.e. placeholder) base schema name to use when returning + column schema information. + + + + + The extra behavioral flags for this connection, if any. See the + enumeration for a list of + possible values. + + + + + Default command timeout + + + + + Non-zero if the built-in (i.e. framework provided) connection string + parser should be used when opening the connection. + + + + + Constructs a new SQLiteConnection object + + + Default constructor + + + + + Initializes the connection with the specified connection string. + + The connection string to use. + + + + Initializes the connection with the specified connection string. + + + The connection string to use on. + + + Non-zero to parse the connection string using the built-in (i.e. + framework provided) parser when opening the connection. + + + + + Clones the settings and connection string from an existing connection. If the existing connection is already open, this + function will open its own connection, enumerate any attached databases of the original connection, and automatically + attach to them. + + The connection to copy the settings from. + + + + Raises the event. + + + The connection associated with this event. + + + A that contains the event data. + + + + + Backs up the database, using the specified database connection as the + destination. + + The destination database connection. + The destination database name. + The source database name. + + The number of pages to copy or negative to copy all remaining pages. + + + The method to invoke between each step of the backup process. This + parameter may be null (i.e. no callbacks will be performed). + + + The number of milliseconds to sleep after encountering a locking error + during the backup process. A value less than zero means that no sleep + should be performed. + + + + + Creates a clone of the connection. All attached databases and user-defined functions are cloned. If the existing connection is open, the cloned connection + will also be opened. + + + + + + Creates a database file. This just creates a zero-byte file which SQLite + will turn into a database when the file is opened properly. + + The file to create + + + + Raises the state change event when the state of the connection changes + + The new connection state. If this is different + from the previous state, the event is + raised. + The event data created for the raised event, if + it was actually raised. + + + + OBSOLETE. Creates a new SQLiteTransaction if one isn't already active on the connection. + + This parameter is ignored. + When TRUE, SQLite defers obtaining a write lock until a write operation is requested. + When FALSE, a writelock is obtained immediately. The default is TRUE, but in a multi-threaded multi-writer + environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock. + Returns a SQLiteTransaction object. + + + + OBSOLETE. Creates a new SQLiteTransaction if one isn't already active on the connection. + + When TRUE, SQLite defers obtaining a write lock until a write operation is requested. + When FALSE, a writelock is obtained immediately. The default is false, but in a multi-threaded multi-writer + environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock. + Returns a SQLiteTransaction object. + + + + Creates a new if one isn't already active on the connection. + + Supported isolation levels are Serializable, ReadCommitted and Unspecified. + + Unspecified will use the default isolation level specified in the connection string. If no isolation level is specified in the + connection string, Serializable is used. + Serializable transactions are the default. In this mode, the engine gets an immediate lock on the database, and no other threads + may begin a transaction. Other threads may read from the database, but not write. + With a ReadCommitted isolation level, locks are deferred and elevated as needed. It is possible for multiple threads to start + a transaction in ReadCommitted mode, but if a thread attempts to commit a transaction while another thread + has a ReadCommitted lock, it may timeout or cause a deadlock on both threads until both threads' CommandTimeout's are reached. + + Returns a SQLiteTransaction object. + + + + Creates a new if one isn't already + active on the connection. + + Returns the new transaction object. + + + + Forwards to the local function + + Supported isolation levels are Unspecified, Serializable, and ReadCommitted + + + + + This method is not implemented; however, the + event will still be raised. + + + + + + When the database connection is closed, all commands linked to this connection are automatically reset. + + + + + Clears the connection pool associated with the connection. Any other active connections using the same database file + will be discarded instead of returned to the pool when they are closed. + + + + + + Clears all connection pools. Any active connections will be discarded instead of sent to the pool when they are closed. + + + + + Create a new and associate it with this connection. + + Returns a new command object already assigned to this connection. + + + + Forwards to the local function. + + + + + + Parses the connection string into component parts using the custom + connection string parser. + + The connection string to parse + An array of key-value pairs representing each parameter of the connection string + + + + Parses a connection string using the built-in (i.e. framework provided) + connection string parser class and returns the key/value pairs. An + exception may be thrown if the connection string is invalid or cannot be + parsed. When compiled for the .NET Compact Framework, the custom + connection string parser is always used instead because the framework + provided one is unavailable there. + + + The connection string to parse. + + + Non-zero to throw an exception if any connection string values are not of + the type. + + The list of key/value pairs. + + + + Manual distributed transaction enlistment support + + The distributed transaction to enlist in + + + + Looks for a key in the array of key/values of the parameter string. If not found, return the specified default value + + The list to look in + The key to find + The default value to return if the key is not found + The value corresponding to the specified key, or the default value if not found. + + + + Attempts to convert the string value to an enumerated value of the specified type. + + The enumerated type to convert the string value to. + The string value to be converted. + Non-zero to make the conversion case-insensitive. + The enumerated value upon success or null upon error. + + + + Enables or disabled extension loading. + + + True to enable loading of extensions, false to disable. + + + + + Loads a SQLite extension library from the named dynamic link library file. + + + The name of the dynamic link library file containing the extension. + + + + + Loads a SQLite extension library from the named dynamic link library file. + + + The name of the dynamic link library file containing the extension. + + + The name of the exported function used to initialize the extension. + If null, the default "sqlite3_extension_init" will be used. + + + + + Opens the connection using the parameters found in the . + + + + + Opens the connection using the parameters found in the and then returns it. + + The current connection object. + + + + This method causes any pending database operation to abort and return at + its earliest opportunity. This routine is typically called in response + to a user action such as pressing "Cancel" or Ctrl-C where the user wants + a long query operation to halt immediately. It is safe to call this + routine from any thread. However, it is not safe to call this routine + with a database connection that is closed or might close before this method + returns. + + + + + Sets the status of the memory usage tracking subsystem in the SQLite core library. By default, this is enabled. + If this is disabled, memory usage tracking will not be performed. This is not really a per-connection value, it is + global to the process. + + Non-zero to enable memory usage tracking, zero otherwise. + A standard SQLite return code (i.e. zero for success and non-zero for failure). + + + Passes a shutdown request off to SQLite. + + + Enables or disabled extended result codes returned by SQLite + + + Enables or disabled extended result codes returned by SQLite + + + Enables or disabled extended result codes returned by SQLite + + + Add a log message via the SQLite sqlite3_log interface. + + + Add a log message via the SQLite sqlite3_log interface. + + + + Change the password (or assign a password) to an open database. + + + No readers or writers may be active for this process. The database must already be open + and if it already was password protected, the existing password must already have been supplied. + + The new password to assign to the database + + + + Change the password (or assign a password) to an open database. + + + No readers or writers may be active for this process. The database must already be open + and if it already was password protected, the existing password must already have been supplied. + + The new password to assign to the database + + + + Sets the password for a password-protected database. A password-protected database is + unusable for any operation until the password has been set. + + The password for the database + + + + Sets the password for a password-protected database. A password-protected database is + unusable for any operation until the password has been set. + + The password for the database + + + + Queries or modifies the number of retries or the retry interval (in milliseconds) for + certain I/O operations that may fail due to anti-virus software. + + The number of times to retry the I/O operation. A negative value + will cause the current count to be queried and replace that negative value. + The number of milliseconds to wait before retrying the I/O + operation. This number is multiplied by the number of retry attempts so far to come + up with the final number of milliseconds to wait. A negative value will cause the + current interval to be queried and replace that negative value. + Zero for success, non-zero for error. + + + + Removes one set of surrounding single -OR- double quotes from the string + value and returns the resulting string value. If the string is null, empty, + or contains quotes that are not balanced, nothing is done and the original + string value will be returned. + + The string value to process. + + The string value, modified to remove one set of surrounding single -OR- + double quotes, if applicable. + + + + + Expand the filename of the data source, resolving the |DataDirectory| + macro as appropriate. + + The database filename to expand + + Non-zero if the returned file name should be converted to a full path + (except when using the .NET Compact Framework). + + The expanded path and filename of the filename + + + + The following commands are used to extract schema information out of the database. Valid schema types are: + + + MetaDataCollections + + + DataSourceInformation + + + Catalogs + + + Columns + + + ForeignKeys + + + Indexes + + + IndexColumns + + + Tables + + + Views + + + ViewColumns + + + + + Returns the MetaDataCollections schema + + A DataTable of the MetaDataCollections schema + + + + Returns schema information of the specified collection + + The schema collection to retrieve + A DataTable of the specified collection + + + + Retrieves schema information using the specified constraint(s) for the specified collection + + The collection to retrieve + The restrictions to impose + A DataTable of the specified collection + + + + Builds a MetaDataCollections schema datatable + + DataTable + + + + Builds a DataSourceInformation datatable + + DataTable + + + + Build a Columns schema + + The catalog (attached database) to query, can be null + The table to retrieve schema information for, must not be null + The column to retrieve schema information for, can be null + DataTable + + + + Returns index information for the given database and catalog + + The catalog (attached database) to query, can be null + The name of the index to retrieve information for, can be null + The table to retrieve index information for, can be null + DataTable + + + + Retrieves table schema information for the database and catalog + + The catalog (attached database) to retrieve tables on + The table to retrieve, can be null + The table type, can be null + DataTable + + + + Retrieves view schema information for the database + + The catalog (attached database) to retrieve views on + The view name, can be null + DataTable + + + + Retrieves catalog (attached databases) schema information for the database + + The catalog to retrieve, can be null + DataTable + + + + Returns the base column information for indexes in a database + + The catalog to retrieve indexes for (can be null) + The table to restrict index information by (can be null) + The index to restrict index information by (can be null) + The source column to restrict index information by (can be null) + A DataTable containing the results + + + + Returns detailed column information for a specified view + + The catalog to retrieve columns for (can be null) + The view to restrict column information by (can be null) + The source column to restrict column information by (can be null) + A DataTable containing the results + + + + Retrieves foreign key information from the specified set of filters + + An optional catalog to restrict results on + An optional table to restrict results on + An optional foreign key name to restrict results on + A DataTable with the results of the query + + + + Static variable to store the connection event handlers to call. + + + + + This event is raised whenever the database is opened or closed. + + + + + This event is raised when events related to the lifecycle of a + SQLiteConnection object occur. + + + + + Returns the number of pool entries for the file name associated with this connection. + + + + + The connection string containing the parameters for the connection + + + + + Parameter + Values + Required + Default + + + Data Source + This may be a file name, the string ":memory:", or any supported URI (starting with SQLite 3.7.7). + Y + + + + Version + 3 + N + 3 + + + UseUTF16Encoding + True
False
+ N + False +
+ + DateTimeFormat + + Ticks - Use the value of DateTime.Ticks.
+ ISO8601 - Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC + DateTime values and "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values).
+ JulianDay - The interval of time in days and fractions of a day since January 1, 4713 BC.
+ UnixEpoch - The whole number of seconds since the Unix epoch (January 1, 1970).
+ InvariantCulture - Any culture-independent string value that the .NET Framework can interpret as a valid DateTime.
+ CurrentCulture - Any string value that the .NET Framework can interpret as a valid DateTime using the current culture.
+ N + ISO8601 +
+ + DateTimeKind + Unspecified - Not specified as either UTC or local time.
Utc - The time represented is UTC.
Local - The time represented is local time.
+ N + Unspecified +
+ + BaseSchemaName + Some base data classes in the framework (e.g. those that build SQL queries dynamically) + assume that an ADO.NET provider cannot support an alternate catalog (i.e. database) without supporting + alternate schemas as well; however, SQLite does not fit into this model. Therefore, this value is used + as a placeholder and removed prior to preparing any SQL statements that may contain it. + N + sqlite_default_schema + + + BinaryGUID + True - Store GUID columns in binary form
False - Store GUID columns as text
+ N + True +
+ + Cache Size + {size in bytes} + N + 2000 + + + Synchronous + Normal - Normal file flushing behavior
Full - Full flushing after all writes
Off - Underlying OS flushes I/O's
+ N + Full +
+ + Page Size + {size in bytes} + N + 1024 + + + Password + {password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection. + N + + + + Enlist + Y - Automatically enlist in distributed transactions
N - No automatic enlistment
+ N + Y +
+ + Pooling + True - Use connection pooling
False - Do not use connection pooling
+ N + False +
+ + FailIfMissing + True - Don't create the database if it does not exist, throw an error instead
False - Automatically create the database if it does not exist
+ N + False +
+ + Max Page Count + {size in pages} - Limits the maximum number of pages (limits the size) of the database + N + 0 + + + Legacy Format + True - Use the more compatible legacy 3.x database format
False - Use the newer 3.3x database format which compresses numbers more effectively
+ N + False +
+ + Default Timeout + {time in seconds}
The default command timeout
+ N + 30 +
+ + Journal Mode + Delete - Delete the journal file after a commit
Persist - Zero out and leave the journal file on disk after a commit
Off - Disable the rollback journal entirely
+ N + Delete +
+ + Read Only + True - Open the database for read only access
False - Open the database for normal read/write access
+ N + False +
+ + Max Pool Size + The maximum number of connections for the given connection string that can be in the connection pool + N + 100 + + + Default IsolationLevel + The default transaciton isolation level + N + Serializable + + + Foreign Keys + Enable foreign key constraints + N + False + + + Flags + Extra behavioral flags for the connection. See the enumeration for possible values. + N + Default + + + SetDefaults + + True - Apply the default connection settings to the opened database.
+ False - Skip applying the default connection settings to the opened database. +
+ N + True +
+ + ToFullPath + + True - Attempt to expand the data source file name to a fully qualified path before opening.
+ False - Skip attempting to expand the data source file name to a fully qualified path before opening. +
+ N + True +
+
+
+
+ + + Returns the data source file name without extension or path. + + + + + Returns the string "main". + + + + + Gets/sets the default command timeout for newly-created commands. This is especially useful for + commands used internally such as inside a SQLiteTransaction, where setting the timeout is not possible. + This can also be set in the ConnectionString with "Default Timeout" + + + + + Non-zero if the built-in (i.e. framework provided) connection string + parser should be used when opening the connection. + + + + + Gets/sets the extra behavioral flags for this connection. See the + enumeration for a list of + possible values. + + + + + Returns the version of the underlying SQLite database engine + + + + + Returns the rowid of the most recent successful INSERT into the database from this connection. + + + + + Returns the number of rows changed by the last INSERT, UPDATE, or DELETE statement executed on + this connection. + + + + + Returns the amount of memory (in bytes) currently in use by the SQLite core library. + + + + + Returns the maximum amount of memory (in bytes) used by the SQLite core library since the high-water mark was last reset. + + + + + Returns a string containing the define constants (i.e. compile-time + options) used to compile the core managed assembly, delimited with + spaces. + + + + + Returns the version of the underlying SQLite database engine + + + + + This method returns the string whose value is the same as the + SQLITE_SOURCE_ID C preprocessor macro used when compiling the + SQLite core library. + + + + + Returns the state of the connection. + + + + + This event is raised whenever SQLite makes an update/delete/insert into the database on + this connection. It only applies to the given connection. + + + + + This event is raised whenever SQLite is committing a transaction. + Return non-zero to trigger a rollback. + + + + + This event is raised whenever SQLite statement first begins executing on + this connection. It only applies to the given connection. + + + + + This event is raised whenever SQLite is rolling back a transaction. + + + + + Returns the instance. + + + + + The I/O file cache flushing behavior for the connection + + + + + Normal file flushing at critical sections of the code + + + + + Full file flushing after every write operation + + + + + Use the default operating system's file flushing, SQLite does not explicitly flush the file buffers after writing + + + + + Raised when a transaction is about to be committed. To roll back a transaction, set the + rollbackTrans boolean value to true. + + The connection committing the transaction + Event arguments on the transaction + + + + Raised when data is inserted, updated and deleted on a given connection + + The connection committing the transaction + The event parameters which triggered the event + + + + Raised when a statement first begins executing on a given connection + + The connection executing the statement + Event arguments of the trace + + + + Raised between each backup step. + + + The source database connection. + + + The source database name. + + + The destination database connection. + + + The destination database name. + + + The number of pages copied with each step. + + + The number of pages remaining to be copied. + + + The total number of pages in the source database. + + + Set to true if the operation needs to be retried due to database + locking issues; otherwise, set to false. + + + True to continue with the backup process or false to halt the backup + process, rolling back any changes that have been made so far. + + + + + Whenever an update event is triggered on a connection, this enum will indicate + exactly what type of operation is being performed. + + + + + A row is being deleted from the given database and table + + + + + A row is being inserted into the table. + + + + + A row is being updated in the table. + + + + + Passed during an Update callback, these event arguments detail the type of update operation being performed + on the given connection. + + + + + The name of the database being updated (usually "main" but can be any attached or temporary database) + + + + + The name of the table being updated + + + + + The type of update being performed (insert/update/delete) + + + + + The RowId affected by this update. + + + + + Event arguments raised when a transaction is being committed + + + + + Set to true to abort the transaction and trigger a rollback + + + + + Passed during an Trace callback, these event arguments contain the UTF-8 rendering of the SQL statement text + + + + + SQL statement text as the statement first begins executing + + + + + The connection pool object + + + + + The default version number new pools will get + + + + + The number of connections successfully opened from any pool. + This value is incremented by the Remove method. + + + + + The number of connections successfully closed from any pool. + This value is incremented by the Add method. + + + + + Counts the number of pool entries matching the specified file name. + + The file name to match or null to match all files. + The pool entry counts for each matching file. + The total number of connections successfully opened from any pool. + The total number of connections successfully closed from any pool. + The total number of pool entries for all matching files. + + + + Attempt to pull a pooled connection out of the queue for active duty + + The filename for a desired connection + The maximum size the connection pool for the filename can be + The pool version the returned connection will belong to + Returns NULL if no connections were available. Even if none are, the poolversion will still be a valid pool version + + + + Clears out all pooled connections and rev's up the default pool version to force all old active objects + not in the pool to get discarded rather than returned to their pools. + + + + + Clear a given pool for a given filename. Discards anything in the pool for the given file, and revs the pool + version so current active objects on the old version of the pool will get discarded rather than be returned to the pool. + + The filename of the pool to clear + + + + Return a connection to the pool for someone else to use. + + The filename of the pool to use + The connection handle to pool + The pool version the handle was created under + + If the version numbers don't match between the connection and the pool, then the handle is discarded. + + + + + We don't have to thread-lock anything in this function, because it's only called by other functions above + which already have a thread-safe lock. + + The queue to resize + If a function intends to add to the pool, this is true, which forces the resize + to take one more than it needs from the pool + + + + Keeps track of connections made on a specified file. The PoolVersion dictates whether old objects get + returned to the pool or discarded when no longer in use. + + + + + SQLite implementation of DbConnectionStringBuilder. + + + + + Properties of this class + + + + + Constructs a new instance of the class + + + Default constructor + + + + + Constructs a new instance of the class using the specified connection string. + + The connection string to parse + + + + Private initializer, which assigns the connection string and resets the builder + + The connection string to assign + + + + Helper function for retrieving values from the connectionstring + + The keyword to retrieve settings for + The resulting parameter value + Returns true if the value was found and returned + + + + Fallback method for MONO, which doesn't implement DbConnectionStringBuilder.GetProperties() + + The hashtable to fill with property descriptors + + + + Gets/Sets the default version of the SQLite engine to instantiate. Currently the only valid value is 3, indicating version 3 of the sqlite library. + + + + + Gets/Sets the synchronization mode (file flushing) of the connection string. Default is "Normal". + + + + + Gets/Sets the encoding for the connection string. The default is "False" which indicates UTF-8 encoding. + + + + + Gets/Sets whether or not to use connection pooling. The default is "False" + + + + + Gets/Sets whethor not to store GUID's in binary format. The default is True + which saves space in the database. + + + + + Gets/Sets the filename to open on the connection string. + + + + + An alternate to the data source property + + + + + An alternate to the data source property that uses the SQLite URI syntax. + + + + + Gets/sets the default command timeout for newly-created commands. This is especially useful for + commands used internally such as inside a SQLiteTransaction, where setting the timeout is not possible. + + + + + Determines whether or not the connection will automatically participate + in the current distributed transaction (if one exists) + + + + + If set to true, will throw an exception if the database specified in the connection + string does not exist. If false, the database will be created automatically. + + + + + If enabled, uses the legacy 3.xx format for maximum compatibility, but results in larger + database sizes. + + + + + When enabled, the database will be opened for read-only access and writing will be disabled. + + + + + Gets/sets the database encryption password + + + + + Gets/Sets the page size for the connection. + + + + + Gets/Sets the maximum number of pages the database may hold + + + + + Gets/Sets the cache size for the connection. + + + + + Gets/Sets the DateTime format for the connection. + + + + + Gets/Sets the DateTime kind for the connection. + + + + + Gets/Sets the placeholder base schema name used for + .NET Framework compatibility purposes. + + + + + Determines how SQLite handles the transaction journal file. + + + + + Sets the default isolation level for transactions on the connection. + + + + + If enabled, use foreign key constraints + + + + + Gets/Sets the extra behavioral flags. + + + + + If enabled, apply the default connection settings to opened databases. + + + + + If enabled, attempt to resolve the provided data source file name to a + full path before opening. + + + + + SQLite has very limited types, and is inherently text-based. The first 5 types below represent the sum of all types SQLite + understands. The DateTime extension to the spec is for internal use only. + + + + + Not used + + + + + All integers in SQLite default to Int64 + + + + + All floating point numbers in SQLite default to double + + + + + The default data type of SQLite is text + + + + + Typically blob types are only seen when returned from a function + + + + + Null types can be returned from functions + + + + + Used internally by this provider + + + + + Used internally + + + + + These are the event types associated with the + + delegate (and its corresponding event) and the + class. + + + + + Not used. + + + + + Not used. + + + + + The connection is being opened. + + + + + The connection string has been parsed. + + + + + The connection was opened. + + + + + The method was called on the + connection. + + + + + A transaction was created using the connection. + + + + + The connection was enlisted into a transaction. + + + + + A command was created using the connection. + + + + + The connection is being closed. + + + + + The connection was closed. + + + + + This implementation of SQLite for ADO.NET can process date/time fields in databases in only one of three formats. Ticks, ISO8601 + and JulianDay. + + + ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second. + JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools. It is + not readable as text without post-processing. + Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing. + + The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks. Ticks is mainly present for legacy + code support. + + + + + Use the value of DateTime.Ticks. This value is not recommended and is not well supported with LINQ. + + + + + Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC DateTime values and + "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values). + + + + + The interval of time in days and fractions of a day since January 1, 4713 BC. + + + + + The whole number of seconds since the Unix epoch (January 1, 1970). + + + + + Any culture-independent string value that the .NET Framework can interpret as a valid DateTime. + + + + + Any string value that the .NET Framework can interpret as a valid DateTime using the current culture. + + + + + The default format for this provider. + + + + + This enum determines how SQLite treats its journal file. + + + By default SQLite will create and delete the journal file when needed during a transaction. + However, for some computers running certain filesystem monitoring tools, the rapid + creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite. + + If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file" + when starting a transaction. If this is happening, you may want to change the default journal mode to Persist. + + + + + The default mode, this causes SQLite to use the existing journaling mode for the database. + + + + + SQLite will create and destroy the journal file as-needed. + + + + + When this is set, SQLite will keep the journal file even after a transaction has completed. It's contents will be erased, + and the journal re-used as often as needed. If it is deleted, it will be recreated the next time it is needed. + + + + + This option disables the rollback journal entirely. Interrupted transactions or a program crash can cause database + corruption in this mode! + + + + + SQLite will truncate the journal file to zero-length instead of deleting it. + + + + + SQLite will store the journal in volatile RAM. This saves disk I/O but at the expense of database safety and integrity. + If the application using SQLite crashes in the middle of a transaction when the MEMORY journaling mode is set, then the + database file will very likely go corrupt. + + + + + SQLite uses a write-ahead log instead of a rollback journal to implement transactions. The WAL journaling mode is persistent; + after being set it stays in effect across multiple database connections and after closing and reopening the database. A database + in WAL journaling mode can only be accessed by SQLite version 3.7.0 or later. + + + + + Possible values for the "synchronous" database setting. This setting determines + how often the database engine calls the xSync method of the VFS. + + + + + Use the default "synchronous" database setting. Currently, this should be + the same as using the FULL mode. + + + + + The database engine continues without syncing as soon as it has handed + data off to the operating system. If the application running SQLite + crashes, the data will be safe, but the database might become corrupted + if the operating system crashes or the computer loses power before that + data has been written to the disk surface. + + + + + The database engine will still sync at the most critical moments, but + less often than in FULL mode. There is a very small (though non-zero) + chance that a power failure at just the wrong time could corrupt the + database in NORMAL mode. + + + + + The database engine will use the xSync method of the VFS to ensure that + all content is safely written to the disk surface prior to continuing. + This ensures that an operating system crash or power failure will not + corrupt the database. FULL synchronous is very safe, but it is also + slower. + + + + + Struct used internally to determine the datatype of a column in a resultset + + + + + The DbType of the column, or DbType.Object if it cannot be determined + + + + + The affinity of a column, used for expressions or when Type is DbType.Object + + + + + SQLite implementation of DbDataAdapter. + + + + + This class is just a shell around the DbDataAdapter. Nothing from DbDataAdapter is overridden here, just a few constructors are defined. + + + Default constructor. + + + + + Constructs a data adapter using the specified select command. + + The select command to associate with the adapter. + + + + Constructs a data adapter with the supplied select command text and associated with the specified connection. + + The select command text to associate with the data adapter. + The connection to associate with the select command. + + + + Constructs a data adapter with the specified select command text, and using the specified database connection string. + + The select command text to use to construct a select command. + A connection string suitable for passing to a new SQLiteConnection, which is associated with the select command. + + + + Raised by the underlying DbDataAdapter when a row is being updated + + The event's specifics + + + + Raised by DbDataAdapter after a row is updated + + The event's specifics + + + + Row updating event handler + + + + + Row updated event handler + + + + + Gets/sets the select command for this DataAdapter + + + + + Gets/sets the insert command for this DataAdapter + + + + + Gets/sets the update command for this DataAdapter + + + + + Gets/sets the delete command for this DataAdapter + + + + + SQLite implementation of DbDataReader. + + + + + Underlying command this reader is attached to + + + + + Index of the current statement in the command being processed + + + + + Current statement being Read() + + + + + State of the current statement being processed. + -1 = First Step() executed, so the first Read() will be ignored + 0 = Actively reading + 1 = Finished reading + 2 = Non-row-returning statement, no records + + + + + Number of records affected by the insert/update statements executed on the command + + + + + Count of fields (columns) in the row-returning statement currently being processed + + + + + Maps the field (column) names to their corresponding indexes within the results. + + + + + Datatypes of active fields (columns) in the current statement, used for type-restricting data + + + + + The behavior of the datareader + + + + + If set, then dispose of the command object when the reader is finished + + + + + If set, then raise an exception when the object is accessed after being disposed. + + + + + An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified + + + + + Matches the version of the connection. + + + + + The "stub" (i.e. placeholder) base schema name to use when returning + column schema information. Matches the base schema name used by the + associated connection. + + + + + Internal constructor, initializes the datareader and sets up to begin executing statements + + The SQLiteCommand this data reader is for + The expected behavior of the data reader + + + + Dispose of all resources used by this datareader. + + + + + + Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified. + + + + + Throw an error if the datareader is closed + + + + + Throw an error if a row is not loaded + + + + + Enumerator support + + Returns a DbEnumerator object. + + + + SQLite is inherently un-typed. All datatypes in SQLite are natively strings. The definition of the columns of a table + and the affinity of returned types are all we have to go on to type-restrict data in the reader. + + This function attempts to verify that the type of data being requested of a column matches the datatype of the column. In + the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob) + to a set of known types that closely match that affinity. It's not an exact science, but its the best we can do. + + + This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity. + + The index of the column to type-check + The type we want to get out of the column + + + + Retrieves the column as a boolean value + + The index of the column to retrieve + bool + + + + Retrieves the column as a single byte value + + The index of the column to retrieve + byte + + + + Retrieves a column as an array of bytes (blob) + + The index of the column to retrieve + The zero-based index of where to begin reading the data + The buffer to write the bytes into + The zero-based index of where to begin writing into the array + The number of bytes to retrieve + The actual number of bytes written into the array + + To determine the number of bytes in the column, pass a null value for the buffer. The total length will be returned. + + + + + Returns the column as a single character + + The index of the column to retrieve + char + + + + Retrieves a column as an array of chars (blob) + + The index of the column to retrieve + The zero-based index of where to begin reading the data + The buffer to write the characters into + The zero-based index of where to begin writing into the array + The number of bytes to retrieve + The actual number of characters written into the array + + To determine the number of characters in the column, pass a null value for the buffer. The total length will be returned. + + + + + Retrieves the name of the back-end datatype of the column + + The index of the column to retrieve + string + + + + Retrieve the column as a date/time value + + The index of the column to retrieve + DateTime + + + + Retrieve the column as a decimal value + + The index of the column to retrieve + decimal + + + + Returns the column as a double + + The index of the column to retrieve + double + + + + Returns the .NET type of a given column + + The index of the column to retrieve + Type + + + + Returns a column as a float value + + The index of the column to retrieve + float + + + + Returns the column as a Guid + + The index of the column to retrieve + Guid + + + + Returns the column as a short + + The index of the column to retrieve + Int16 + + + + Retrieves the column as an int + + The index of the column to retrieve + Int32 + + + + Retrieves the column as a long + + The index of the column to retrieve + Int64 + + + + Retrieves the name of the column + + The index of the column to retrieve + string + + + + Retrieves the i of a column, given its name + + The name of the column to retrieve + The int i of the column + + + + Schema information in SQLite is difficult to map into .NET conventions, so a lot of work must be done + to gather the necessary information so it can be represented in an ADO.NET manner. + + Returns a DataTable containing the schema information for the active SELECT statement being processed. + + + + Retrieves the column as a string + + The index of the column to retrieve + string + + + + Retrieves the column as an object corresponding to the underlying datatype of the column + + The index of the column to retrieve + object + + + + Retreives the values of multiple columns, up to the size of the supplied array + + The array to fill with values from the columns in the current resultset + The number of columns retrieved + + + + Returns a collection containing all the column names and values for the + current row of data in the current resultset, if any. If there is no + current row or no current resultset, an exception may be thrown. + + + The collection containing the column name and value information for the + current row of data in the current resultset or null if this information + cannot be obtained. + + + + + Returns True if the specified column is null + + The index of the column to retrieve + True or False + + + + Moves to the next resultset in multiple row-returning SQL command. + + True if the command was successful and a new resultset is available, False otherwise. + + + + Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls. + + The index of the column to retrieve + A SQLiteType structure + + + + Reads the next row from the resultset + + True if a new row was successfully loaded and is ready for processing + + + + Not implemented. Returns 0 + + + + + Returns the number of columns in the current resultset + + + + + Returns the number of visible fields in the current resultset + + + + + Returns True if the resultset has rows that can be fetched + + + + + Returns True if the data reader is closed + + + + + Retrieve the count of records affected by an update/insert command. Only valid once the data reader is closed! + + + + + Indexer to retrieve data from a column given its name + + The name of the column to retrieve data for + The value contained in the column + + + + Indexer to retrieve data from a column given its i + + The index of the column to retrieve + The value contained in the column + + + + SQLite exception class. + + + + + Private constructor for use with serialization. + + + Holds the serialized object data about the exception being thrown. + + + Contains contextual information about the source or destination. + + + + + Public constructor for generating a SQLite exception given the error + code and message. + + + The SQLite return code to report. + + + Message text to go along with the return code message text. + + + + + Public constructor that uses the base class constructor for the error + message. + + Error message text. + + + + Public constructor that uses the default base class constructor. + + + + + Public constructor that uses the base class constructor for the error + message and inner exception. + + Error message text. + The original (inner) exception. + + + + Adds extra information to the serialized object data specific to this + class type. This is only used for serialization. + + + Holds the serialized object data about the exception being thrown. + + + Contains contextual information about the source or destination. + + + + + Returns the error message for the specified SQLite return code. + + The SQLite return code. + The error message or null if it cannot be found. + + + + Returns the composite error message based on the SQLite return code + and the optional detailed error message. + + The SQLite return code. + Optional detailed error message. + Error message text for the return code. + + + + Gets the associated SQLite return code for this exception as a + . This property returns the same + underlying value as the property. + + + + + Gets the associated SQLite return code for this exception as an + . For desktop versions of the .NET Framework, + this property overrides the property of the same name within the + + class. This property returns the same underlying value as the + property. + + + + + SQLite error codes. Actually, this enumeration represents a return code, + which may also indicate success in one of several ways (e.g. SQLITE_OK, + SQLITE_ROW, and SQLITE_DONE). Therefore, the name of this enumeration is + something of a misnomer. + + + + + Successful result + + + + + SQL error or missing database + + + + + Internal logic error in SQLite + + + + + Access permission denied + + + + + Callback routine requested an abort + + + + + The database file is locked + + + + + A table in the database is locked + + + + + A malloc() failed + + + + + Attempt to write a readonly database + + + + + Operation terminated by sqlite3_interrupt() + + + + + Some kind of disk I/O error occurred + + + + + The database disk image is malformed + + + + + Unknown opcode in sqlite3_file_control() + + + + + Insertion failed because database is full + + + + + Unable to open the database file + + + + + Database lock protocol error + + + + + Database is empty + + + + + The database schema changed + + + + + String or BLOB exceeds size limit + + + + + Abort due to constraint violation + + + + + Data type mismatch + + + + + Library used incorrectly + + + + + Uses OS features not supported on host + + + + + Authorization denied + + + + + Auxiliary database format error + + + + + 2nd parameter to sqlite3_bind out of range + + + + + File opened that is not a database file + + + + + sqlite3_step() has another row ready + + + + + sqlite3_step() has finished executing + + + + + SQLite implementation of . + + + SQLite implementation of . + + + + + Constructs a new instance. + + + + + Static instance member which returns an instanced class. + + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Will provide a object in .NET 3.5. + + The class or interface type to query for. + + + + + This event is raised whenever SQLite raises a logging event. + Note that this should be set as one of the first things in the + application. This event is provided for backward compatibility only. + New code should use the class instead. + + + + + This abstract class is designed to handle user-defined functions easily. An instance of the derived class is made for each + connection to the database. + + + Although there is one instance of a class derived from SQLiteFunction per database connection, the derived class has no access + to the underlying connection. This is necessary to deter implementers from thinking it would be a good idea to make database + calls during processing. + + It is important to distinguish between a per-connection instance, and a per-SQL statement context. One instance of this class + services all SQL statements being stepped through on that connection, and there can be many. One should never store per-statement + information in member variables of user-defined function classes. + + For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step. This data will + be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes. + + + + + The error code used for logging exceptions caught in user-provided + code. + + + + + The base connection this function is attached to + + + + + Internal array used to keep track of aggregate function context data + + + + + The connection flags associated with this object (this should be the + same value as the flags associated with the parent connection object). + + + + + Holds a reference to the callback function for user functions + + + + + Holds a reference to the callbakc function for stepping in an aggregate function + + + + + Holds a reference to the callback function for finalizing an aggregate function + + + + + Holds a reference to the callback function for collation sequences + + + + + Current context of the current callback. Only valid during a callback + + + + + This static list contains all the user-defined functions declared using the proper attributes. + + + + + Internal constructor, initializes the function's internal variables. + + + + + Disposes of any active contextData variables that were not automatically cleaned up. Sometimes this can happen if + someone closes the connection while a DataReader is open. + + + + + Placeholder for a user-defined disposal routine + + True if the object is being disposed explicitly + + + + Scalar functions override this method to do their magic. + + + Parameters passed to functions have only an affinity for a certain data type, there is no underlying schema available + to force them into a certain type. Therefore the only types you will ever see as parameters are + DBNull.Value, Int64, Double, String or byte[] array. + + The arguments for the command to process + You may return most simple types as a return value, null or DBNull.Value to return null, DateTime, or + you may return an Exception-derived class if you wish to return an error to SQLite. Do not actually throw the error, + just return it! + + + + Aggregate functions override this method to do their magic. + + + Typically you'll be updating whatever you've placed in the contextData field and returning as quickly as possible. + + The arguments for the command to process + The 1-based step number. This is incrememted each time the step method is called. + A placeholder for implementers to store contextual data pertaining to the current context. + + + + Aggregate functions override this method to finish their aggregate processing. + + + If you implemented your aggregate function properly, + you've been recording and keeping track of your data in the contextData object provided, and now at this stage you should have + all the information you need in there to figure out what to return. + NOTE: It is possible to arrive here without receiving a previous call to Step(), in which case the contextData will + be null. This can happen when no rows were returned. You can either return null, or 0 or some other custom return value + if that is the case. + + Your own assigned contextData, provided for you so you can return your final results. + You may return most simple types as a return value, null or DBNull.Value to return null, DateTime, or + you may return an Exception-derived class if you wish to return an error to SQLite. Do not actually throw the error, + just return it! + + + + + User-defined collation sequences override this method to provide a custom string sorting algorithm. + + The first string to compare + The second strnig to compare + 1 if param1 is greater than param2, 0 if they are equal, or -1 if param1 is less than param2 + + + + Converts an IntPtr array of context arguments to an object array containing the resolved parameters the pointers point to. + + + Parameters passed to functions have only an affinity for a certain data type, there is no underlying schema available + to force them into a certain type. Therefore the only types you will ever see as parameters are + DBNull.Value, Int64, Double, String or byte[] array. + + The number of arguments + A pointer to the array of arguments + An object array of the arguments once they've been converted to .NET values + + + + Takes the return value from Invoke() and Final() and figures out how to return it to SQLite's context. + + The context the return value applies to + The parameter to return to SQLite + + + + Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method. + WARNING: Must not throw exceptions. + + A raw context pointer + Number of arguments passed in + A pointer to the array of arguments + + + + Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. + WARNING: Must not throw exceptions. + + Not used + Length of the string pv1 + Pointer to the first string to compare + Length of the string pv2 + Pointer to the second string to compare + Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater + than the second. Returns 0 if an exception is caught. + + + + Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. + WARNING: Must not throw exceptions. + + Not used + Length of the string pv1 + Pointer to the first string to compare + Length of the string pv2 + Pointer to the second string to compare + Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater + than the second. Returns 0 if an exception is caught. + + + + The internal aggregate Step function callback, which wraps the raw context pointer and calls the virtual Step() method. + WARNING: Must not throw exceptions. + + + This function takes care of doing the lookups and getting the important information put together to call the Step() function. + That includes pulling out the user's contextData and updating it after the call is made. We use a sorted list for this so + binary searches can be done to find the data. + + A raw context pointer + Number of arguments passed in + A pointer to the array of arguments + + + + An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method. + WARNING: Must not throw exceptions. + + A raw context pointer + + + + Using reflection, enumerate all assemblies in the current appdomain looking for classes that + have a SQLiteFunctionAttribute attribute, and registering them accordingly. + + + + + Manual method of registering a function. The type must still have the SQLiteFunctionAttributes in order to work + properly, but this is a workaround for the Compact Framework where enumerating assemblies is not currently supported. + + The type of the function to register + + + + Called by SQLiteBase derived classes, this function binds all user-defined functions to a connection. + It is done this way so that all user-defined functions will access the database using the same encoding scheme + as the connection (UTF-8 or UTF-16). + + + The wrapper functions that interop with SQLite will create a unique cookie value, which internally is a pointer to + all the wrapped callback functions. The interop function uses it to map CDecl callbacks to StdCall callbacks. + + The base object on which the functions are to bind + The flags associated with the parent connection object + Returns an array of functions which the connection object should retain until the connection is closed. + + + + Returns a reference to the underlying connection's SQLiteConvert class, which can be used to convert + strings and DateTime's into the current connection's encoding schema. + + + + + Extends SQLiteFunction and allows an inherited class to obtain the collating sequence associated with a function call. + + + User-defined functions can call the GetCollationSequence() method in this class and use it to compare strings and char arrays. + + + + + Obtains the collating sequence in effect for the given function. + + + + + + The type of user-defined function to declare + + + + + Scalar functions are designed to be called and return a result immediately. Examples include ABS(), Upper(), Lower(), etc. + + + + + Aggregate functions are designed to accumulate data until the end of a call and then return a result gleaned from the accumulated data. + Examples include SUM(), COUNT(), AVG(), etc. + + + + + Collation sequences are used to sort textual data in a custom manner, and appear in an ORDER BY clause. Typically text in an ORDER BY is + sorted using a straight case-insensitive comparison function. Custom collating sequences can be used to alter the behavior of text sorting + in a user-defined manner. + + + + + An internal callback delegate declaration. + + Raw context pointer for the user function + Count of arguments to the function + A pointer to the array of argument pointers + + + + An internal final callback delegate declaration. + + Raw context pointer for the user function + + + + Internal callback delegate for implementing collation sequences + + Not used + Length of the string pv1 + Pointer to the first string to compare + Length of the string pv2 + Pointer to the second string to compare + Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater + than the second. + + + + The type of collating sequence + + + + + The built-in BINARY collating sequence + + + + + The built-in NOCASE collating sequence + + + + + The built-in REVERSE collating sequence + + + + + A custom user-defined collating sequence + + + + + The encoding type the collation sequence uses + + + + + The collation sequence is UTF8 + + + + + The collation sequence is UTF16 little-endian + + + + + The collation sequence is UTF16 big-endian + + + + + A struct describing the collating sequence a function is executing in + + + + + The name of the collating sequence + + + + + The type of collating sequence + + + + + The text encoding of the collation sequence + + + + + Context of the function that requested the collating sequence + + + + + Calls the base collating sequence to compare two strings + + The first string to compare + The second string to compare + -1 if s1 is less than s2, 0 if s1 is equal to s2, and 1 if s1 is greater than s2 + + + + Calls the base collating sequence to compare two character arrays + + The first array to compare + The second array to compare + -1 if c1 is less than c2, 0 if c1 is equal to c2, and 1 if c1 is greater than c2 + + + + A simple custom attribute to enable us to easily find user-defined functions in + the loaded assemblies and initialize them in SQLite as connections are made. + + + + + Default constructor, initializes the internal variables for the function. + + + + + The function's name as it will be used in SQLite command text. + + + + + The number of arguments this function expects. -1 if the number of arguments is variable. + + + + + The type of function this implementation will be. + + + + + This class provides key info for a given SQLite statement. + + Providing key information for a given statement is non-trivial :( + + + + + + This function does all the nasty work at determining what keys need to be returned for + a given statement. + + + + + + + + Make sure all the subqueries are open and ready and sync'd with the current rowid + of the table they're supporting + + + + + Release any readers on any subqueries + + + + + Append all the columns we've added to the original query to the schema + + + + + + How many additional columns of keyinfo we're holding + + + + + Used to support CommandBehavior.KeyInfo + + + + + A single sub-query for a given table/database. + + + + + Event data for logging event handlers. + + + + + The error code. The type of this object value should be + or . + + + + + SQL statement text as the statement first begins executing + + + + + Extra data associated with this event, if any. + + + + + Constructs the object. + + Should be null. + + The error code. The type of this object value should be + or . + + The error message, if any. + The extra data, if any. + + + + Raised when a log event occurs. + + The current connection + Event arguments of the trace + + + + Manages the SQLite custom logging functionality and the associated + callback for the whole process. + + + + + Object used to synchronize access to the static instance data + for this class. + + + + + Member variable to store the AppDomain.DomainUnload event handler. + + + + + The default log event handler. + + + + + The log callback passed to native SQLite engine. This must live + as long as the SQLite library has a pointer to it. + + + + + The base SQLite object to interop with. + + + + + This will be non-zero if logging is currently enabled. + + + + + Initializes the SQLite logging facilities. + + + + + Handles the AppDomain being unloaded. + + Should be null. + The data associated with this event. + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + The message to be logged. + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + The SQLite error code. + The message to be logged. + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + The integer error code. + The message to be logged. + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + + The error code. The type of this object value should be + System.Int32 or SQLiteErrorCode. + + The message to be logged. + + + + Creates and initializes the default log event handler. + + + + + Adds the default log event handler to the list of handlers. + + + + + Removes the default log event handler from the list of handlers. + + + + + Internal proxy function that calls any registered application log + event handlers. + + WARNING: This method is used more-or-less directly by native code, + do not modify its type signature. + + + The extra data associated with this message, if any. + + + The error code associated with this message. + + + The message string to be logged. + + + + + Default logger. Currently, uses the Trace class (i.e. sends events + to the current trace listeners, if any). + + Should be null. + The data associated with this event. + + + + Member variable to store the application log handler to call. + + + + + This event is raised whenever SQLite raises a logging event. + Note that this should be set as one of the first things in the + application. + + + + + If this property is true, logging is enabled; otherwise, logging is + disabled. When logging is disabled, no logging events will fire. + + + + + MetaDataCollections specific to SQLite + + + + + Returns a list of databases attached to the connection + + + + + Returns column information for the specified table + + + + + Returns index information for the optionally-specified table + + + + + Returns base columns for the given index + + + + + Returns the tables in the given catalog + + + + + Returns user-defined views in the given catalog + + + + + Returns underlying column information on the given view + + + + + Returns foreign key information for the given catalog + + + + + Returns the triggers on the database + + + + + SQLite implementation of DbParameter. + + + + + The data type of the parameter + + + + + The version information for mapping the parameter + + + + + The value of the data in the parameter + + + + + The source column for the parameter + + + + + The column name + + + + + The data size, unused by SQLite + + + + + Default constructor + + + + + Constructs a named parameter given the specified parameter name + + The parameter name + + + + Constructs a named parameter given the specified parameter name and initial value + + The parameter name + The initial value of the parameter + + + + Constructs a named parameter of the specified type + + The parameter name + The datatype of the parameter + + + + Constructs a named parameter of the specified type and source column reference + + The parameter name + The data type + The source column + + + + Constructs a named parameter of the specified type, source column and row version + + The parameter name + The data type + The source column + The row version information + + + + Constructs an unnamed parameter of the specified data type + + The datatype of the parameter + + + + Constructs an unnamed parameter of the specified data type and sets the initial value + + The datatype of the parameter + The initial value of the parameter + + + + Constructs an unnamed parameter of the specified data type and source column + + The datatype of the parameter + The source column + + + + Constructs an unnamed parameter of the specified data type, source column and row version + + The data type + The source column + The row version information + + + + Constructs a named parameter of the specified type and size + + The parameter name + The data type + The size of the parameter + + + + Constructs a named parameter of the specified type, size and source column + + The name of the parameter + The data type + The size of the parameter + The source column + + + + Constructs a named parameter of the specified type, size, source column and row version + + The name of the parameter + The data type + The size of the parameter + The source column + The row version information + + + + Constructs a named parameter of the specified type, size, source column and row version + + The name of the parameter + The data type + The size of the parameter + Only input parameters are supported in SQLite + Ignored + Ignored + Ignored + The source column + The row version information + The initial value to assign the parameter + + + + Constructs a named parameter, yet another flavor + + The name of the parameter + The data type + The size of the parameter + Only input parameters are supported in SQLite + Ignored + Ignored + The source column + The row version information + Whether or not this parameter is for comparing NULL's + The intial value to assign the parameter + + + + Constructs an unnamed parameter of the specified type and size + + The data type + The size of the parameter + + + + Constructs an unnamed parameter of the specified type, size, and source column + + The data type + The size of the parameter + The source column + + + + Constructs an unnamed parameter of the specified type, size, source column and row version + + The data type + The size of the parameter + The source column + The row version information + + + + Resets the DbType of the parameter so it can be inferred from the value + + + + + Clones a parameter + + A new, unassociated SQLiteParameter + + + + Whether or not the parameter can contain a null value + + + + + Returns the datatype of the parameter + + + + + Supports only input parameters + + + + + Returns the parameter name + + + + + Returns the size of the parameter + + + + + Gets/sets the source column + + + + + Used by DbCommandBuilder to determine the mapping for nullable fields + + + + + Gets and sets the row version + + + + + Gets and sets the parameter value. If no datatype was specified, the datatype will assume the type from the value given. + + + + + SQLite implementation of DbParameterCollection. + + + + + The underlying command to which this collection belongs + + + + + The internal array of parameters in this collection + + + + + Determines whether or not all parameters have been bound to their statement(s) + + + + + Initializes the collection + + The command to which the collection belongs + + + + Retrieves an enumerator for the collection + + An enumerator for the underlying array + + + + Adds a parameter to the collection + + The parameter name + The data type + The size of the value + The source column + A SQLiteParameter object + + + + Adds a parameter to the collection + + The parameter name + The data type + The size of the value + A SQLiteParameter object + + + + Adds a parameter to the collection + + The parameter name + The data type + A SQLiteParameter object + + + + Adds a parameter to the collection + + The parameter to add + A zero-based index of where the parameter is located in the array + + + + Adds a parameter to the collection + + The parameter to add + A zero-based index of where the parameter is located in the array + + + + Adds a named/unnamed parameter and its value to the parameter collection. + + Name of the parameter, or null to indicate an unnamed parameter + The initial value of the parameter + Returns the SQLiteParameter object created during the call. + + + + Adds an array of parameters to the collection + + The array of parameters to add + + + + Adds an array of parameters to the collection + + The array of parameters to add + + + + Clears the array and resets the collection + + + + + Determines if the named parameter exists in the collection + + The name of the parameter to check + True if the parameter is in the collection + + + + Determines if the parameter exists in the collection + + The SQLiteParameter to check + True if the parameter is in the collection + + + + Not implemented + + + + + + + Retrieve a parameter by name from the collection + + The name of the parameter to fetch + A DbParameter object + + + + Retrieves a parameter by its index in the collection + + The index of the parameter to retrieve + A DbParameter object + + + + Returns the index of a parameter given its name + + The name of the parameter to find + -1 if not found, otherwise a zero-based index of the parameter + + + + Returns the index of a parameter + + The parameter to find + -1 if not found, otherwise a zero-based index of the parameter + + + + Inserts a parameter into the array at the specified location + + The zero-based index to insert the parameter at + The parameter to insert + + + + Removes a parameter from the collection + + The parameter to remove + + + + Removes a parameter from the collection given its name + + The name of the parameter to remove + + + + Removes a parameter from the collection given its index + + The zero-based parameter index to remove + + + + Re-assign the named parameter to a new parameter object + + The name of the parameter to replace + The new parameter + + + + Re-assign a parameter at the specified index + + The zero-based index of the parameter to replace + The new parameter + + + + Un-binds all parameters from their statements + + + + + This function attempts to map all parameters in the collection to all statements in a Command. + Since named parameters may span multiple statements, this function makes sure all statements are bound + to the same named parameter. Unnamed parameters are bound in sequence. + + + + + Returns true + + + + + Returns false + + + + + Returns false + + + + + Returns null + + + + + Returns a count of parameters in the collection + + + + + Overloaded to specialize the return value of the default indexer + + Name of the parameter to get/set + The specified named SQLite parameter + + + + Overloaded to specialize the return value of the default indexer + + The index of the parameter to get/set + The specified SQLite parameter + + + + Represents a single SQL statement in SQLite. + + + + + The underlying SQLite object this statement is bound to + + + + + The command text of this SQL statement + + + + + The actual statement pointer + + + + + An index from which unnamed parameters begin + + + + + Names of the parameters as SQLite understands them to be + + + + + Parameters for this statement + + + + + Command this statement belongs to (if any) + + + + + The flags associated with the parent connection object. + + + + + Initializes the statement and attempts to get all information about parameters in the statement + + The base SQLite object + The flags associated with the parent connection object + The statement + The command text for this statement + The previous command in a multi-statement command + + + + Disposes and finalizes the statement + + + + + If the underlying database connection is open, fetches the number of changed rows + resulting from the most recent query; otherwise, does nothing. + + + The number of changes when true is returned. + Undefined if false is returned. + + Non-zero if the number of changed rows was fetched. + + + + Called by SQLiteParameterCollection, this function determines if the specified parameter name belongs to + this statement, and if so, keeps a reference to the parameter so it can be bound later. + + The parameter name to map + The parameter to assign it + + + + Bind all parameters, making sure the caller didn't miss any + + + + + Attempts to convert an arbitrary object to the Boolean data type. + Null object values are converted to false. Throws a SQLiteException + upon failure. + + The object value to convert. + The format provider to use. + The converted boolean value. + + + + Perform the bind operation for an individual parameter + + The index of the parameter to bind + The parameter we're binding + + + + SQLite implementation of DbTransaction. + + + + + The connection to which this transaction is bound + + + + + Constructs the transaction object, binding it to the supplied connection + + The connection to open a transaction on + TRUE to defer the writelock, or FALSE to lock immediately + + + + Disposes the transaction. If it is currently active, any changes are rolled back. + + + + + Commits the current transaction. + + + + + Rolls back the active transaction. + + + + + Returns the underlying connection to which this transaction applies. + + + + + Forwards to the local Connection property + + + + + Gets the isolation level of the transaction. SQLite only supports Serializable transactions. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to <?xml version="1.0" standalone="yes"?> + <DocumentElement> + <DataTypes> + <TypeName>smallint</TypeName> + <ProviderDbType>10</ProviderDbType> + <ColumnSize>5</ColumnSize> + <DataType>System.Int16</DataType> + <CreateFormat>smallint</CreateFormat> + <IsAutoIncrementable>false</IsAutoIncrementable> + <IsCaseSensitive>false</IsCaseSensitive> + <IsFixedLength>true</IsFixedLength> + <IsFixedPrecisionScale>true</IsFixedPrecisionScale> + <IsLong>false</IsLong> + <IsNullable>true</ [rest of string was truncated]";. + + + + + Looks up a localized string similar to ALL,ALTER,AND,AS,AUTOINCREMENT,BETWEEN,BY,CASE,CHECK,COLLATE,COMMIT,CONSTRAINT,CREATE,CROSS,DEFAULT,DEFERRABLE,DELETE,DISTINCT,DROP,ELSE,ESCAPE,EXCEPT,FOREIGN,FROM,FULL,GROUP,HAVING,IN,INDEX,INNER,INSERT,INTERSECT,INTO,IS,ISNULL,JOIN,LEFT,LIMIT,NATURAL,NOT,NOTNULL,NULL,ON,OR,ORDER,OUTER,PRIMARY,REFERENCES,RIGHT,ROLLBACK,SELECT,SET,TABLE,THEN,TO,TRANSACTION,UNION,UNIQUE,UPDATE,USING,VALUES,WHEN,WHERE. + + + + + Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> + <DocumentElement> + <MetaDataCollections> + <CollectionName>MetaDataCollections</CollectionName> + <NumberOfRestrictions>0</NumberOfRestrictions> + <NumberOfIdentifierParts>0</NumberOfIdentifierParts> + </MetaDataCollections> + <MetaDataCollections> + <CollectionName>DataSourceInformation</CollectionName> + <NumberOfRestrictions>0</NumberOfRestrictions> + <NumberOfIdentifierParts>0</NumberOfIdentifierParts> + </MetaDataCollections> + <MetaDataC [rest of string was truncated]";. + + + + + The name of the environment variable containing the processor + architecture of the current process. + + + + + This is the P/Invoke method that wraps the native Win32 LoadLibrary + function. See the MSDN documentation for full details on what it + does. + + + The name of the executable library. + + + The native module handle upon success -OR- IntPtr.Zero on failure. + + + + + This lock is used to protect the static _SQLiteModule and + processorArchitecturePlatforms fields, below. + + + + + Stores the mappings between processor architecture names and platform + names. + + + + + The native module handle for the native SQLite library or the value + IntPtr.Zero. + + + + + For now, this method simply calls the Initialize method. + + + + + Attempts to initialize this class by pre-loading the native SQLite + library for the processor architecture of the current process. + + + + + Queries and returns the base directory of the current application + domain. + + + The base directory for the current application domain -OR- null if it + cannot be determined. + + + + + Determines if the dynamic link library file name requires a suffix + and adds it if necessary. + + + The original dynamic link library file name to inspect. + + + The dynamic link library file name, possibly modified to include an + extension. + + + + + Queries and returns the processor architecture of the current + process. + + + The processor architecture of the current process -OR- null if it + cannot be determined. Always returns an empty string when running on + the .NET Compact Framework. + + + + + Given the processor architecture, returns the name of the platform. + + + The processor architecture to be translated to a platform name. + + + The platform name for the specified processor architecture -OR- null + if it cannot be determined. + + + + + Attempts to load the native SQLite library based on the specified + directory and processor architecture. + + + The base directory to use, null for default (the base directory of + the current application domain). This directory should contain the + processor architecture specific sub-directories. + + + The requested processor architecture, null for default (the + processor architecture of the current process). This caller should + almost always specify null for this parameter. + + + The native module handle as returned by LoadLibrary -OR- IntPtr.Zero + if the loading fails for any reason. + + +
+