/// <summary> /// Creates a new Gamespy Account /// </summary> /// <remarks>Used by the login server when a create account request is made</remarks> /// <param name="Nick">The Account Name</param> /// <param name="Pass">The Account Password</param> /// <param name="Email">The Account Email Address</param> /// <param name="Country">The Country Code for this Account</param> /// <returns>A bool indicating whether the account was created sucessfully</returns> 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); }
/// <summary> /// Returns a bool stating whether the criteria for this award is met for a givin player /// </summary> /// <param name="Pid">The player ID</param> /// <param name="Level">The award level if the criteria is met</param> /// <returns></returns> public bool CriteriaMet(int Pid, StatsDatabase Driver, ref int Level) { // Get the award count (or level for badges) for this award string Query = "SELECT COALESCE(max(level), 0) FROM awards WHERE id=@P0 AND awd=@P1"; int AwardCount = Convert.ToInt32(Driver.ExecuteScalar(Query, Pid, AwardId)); bool IsRibbon = (AwardId > 3000000); // Can only recieve ribbons once in a lifetime, so return false if we have it already if (IsRibbon && AwardCount > 0) return false; // Medals and Badges can receive multiple times (Badges are award level, not count) if (!IsRibbon) Level = AwardCount + 1; // Loop through each criteria and see if we have met the criteria foreach (AwardCriteria Criteria in Criterias) { // Build the query. We always use a count() or sum() to return a sortof bool. string Where = Criteria.Where.Replace("###", Level.ToString()); Query = String.Format("SELECT {0} FROM {1} WHERE id={2} AND {3}", Criteria.Field, Criteria.Table, Pid, Where); // If we dont meet the expected result, the criteria is unmet, no use continuing if (Convert.ToInt32(Driver.ExecuteScalar(Query)) < Criteria.ExpectedResult) return false; } return true; }
/// <summary> /// This request provides details on a particular players rank, and /// whether or not to show the user a promotion/demotion announcement /// </summary> /// <queryParam name="pid" type="int">The unique player ID</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public GetRankInfo(HttpClient Client, StatsDatabase Driver) { int Pid = 0; List<Dictionary<string, object>> Rows; // Setup Params if (Client.Request.QueryString.ContainsKey("pid")) Int32.TryParse(Client.Request.QueryString["pid"], out Pid); // Fetch Player Rows = Driver.Query("SELECT rank, chng, decr FROM player WHERE id=@P0", Pid); if (Rows.Count == 0) { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("asof", "err"); Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Player Doesnt Exist"); Client.Response.Send(); return; } // Output status... chng set to 1 shows the Promotion Announcement, whereas decr shows the Demotion Announcement Client.Response.WriteResponseStart(); Client.Response.WriteHeaderLine("rank", "chng", "decr"); Client.Response.WriteDataLine(Rows[0]["rank"], Rows[0]["chng"], Rows[0]["decr"]); Client.Response.Send(); // Reset Driver.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid); }
/// <summary> /// This request provides a list of awards for a particular player /// </summary> /// <queryParam name="pid" type="int">The unique player ID</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public GetAwardsInfo(HttpClient Client, StatsDatabase Driver) { int Pid; // make sure we have a valid player ID if (!Client.Request.QueryString.ContainsKey("pid") || !Int32.TryParse(Client.Request.QueryString["pid"], out Pid)) { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("asof", "err"); Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Client.Response.Send(); return; } // Output header data Client.Response.WriteResponseStart(); Client.Response.WriteHeaderLine("pid", "asof"); Client.Response.WriteDataLine(Pid, DateTime.UtcNow.ToUnixTimestamp()); Client.Response.WriteHeaderLine("award", "level", "when", "first"); try { // Fetch Player Awards List<Dictionary<string, object>> Awards = Driver.GetPlayerAwards(Pid); // Write each award as a new data line foreach (Dictionary<string, object> Award in Awards) Client.Response.WriteDataLine(Award["awd"], Award["level"], Award["earned"], Award["first"]); } catch { } // Send Response Client.Response.Send(); }
public override void HandleRequest() { // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { int Pid = 0; // Setup Params if (Client.Request.QueryString.ContainsKey("pid")) Int32.TryParse(Client.Request.QueryString["pid"], out Pid); // Fetch Player var Rows = Database.Query("SELECT rank, chng, decr FROM player WHERE id=@P0", Pid); if (Rows.Count == 0) { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Player Doesnt Exist"); Response.Send(); return; } // Output status... chng set to 1 shows the Promotion Announcement, whereas decr shows the Demotion Announcement Response.WriteResponseStart(); Response.WriteHeaderLine("rank", "chng", "decr"); Response.WriteDataLine(Rows[0]["rank"], Rows[0]["chng"], Rows[0]["decr"]); Response.Send(); // Reset Database.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid); } }
/// <summary> /// Creates a new Gamespy Account /// </summary> /// <remarks>Used by the login server when a create account request is made</remarks> /// <param name="Nick">The Account Name</param> /// <param name="Pass">The UN-HASHED Account Password</param> /// <param name="Email">The Account Email Address</param> /// <param name="Country">The Country Code for this Account</param> /// <returns>Returns the Player ID if sucessful, 0 otherwise</returns> public int 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) ? StatsManager.GenerateNewPlayerPid() : Int32.Parse(Row[0]["id"].ToString()); } } catch { Pid = StatsManager.GenerateNewPlayerPid(); } // 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.GetMD5Hash(false), Email.ToLowerInvariant(), Country ); return((Rows != 0) ? Pid : 0); }
public SearchForPlayers(HttpClient Client, StatsDatabase Driver) { string Nick; List<Dictionary<string, object>> Rows; // Setup Params if (!Client.Request.QueryString.ContainsKey("nick")) { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("asof", "err"); Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Client.Response.Send(); return; } else Nick = Client.Request.QueryString["nick"]; // Timestamp Header Client.Response.WriteResponseStart(); Client.Response.WriteHeaderLine("asof"); Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp()); // Output status int i = 0; Client.Response.WriteHeaderLine("n", "pid", "nick", "score"); Rows = Driver.Query("SELECT id, name, score FROM player WHERE name LIKE @P0 LIMIT 20", "%" + Nick + "%"); foreach (Dictionary<string, object> Player in Rows) { Client.Response.WriteDataLine(i + 1, Rows[i]["id"], Rows[i]["name"].ToString().Trim(), Rows[i]["score"]); i++; } // Send Response Client.Response.Send(); }
public override void HandleRequest() { // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { int Pid = 0; List<Dictionary<string, object>> Rows; // Setup Params if (Client.Request.QueryString.ContainsKey("pid")) Int32.TryParse(Client.Request.QueryString["pid"], out Pid); // Fetch Player Rows = Database.Query("SELECT rank FROM player WHERE id=@P0", Pid); if (Rows.Count == 0) { Response.WriteResponseStart(false); Response.WriteFreeformLine("Player Doesnt Exist!"); Client.Response.Send(); return; } // Reset Database.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid); Response.WriteResponseStart(); Response.WriteFreeformLine(String.Format("Cleared rank notification {0}", Pid)); Response.Send(); } }
public override void HandleRequest() { int Pid; // make sure we have a valid player ID if (!Request.QueryString.ContainsKey("pid") || !Int32.TryParse(Request.QueryString["pid"], out Pid)) { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Response.Send(); return; } // Output header data Response.WriteResponseStart(); Response.WriteHeaderLine("pid", "asof"); Response.WriteDataLine(Pid, DateTime.UtcNow.ToUnixTimestamp()); Response.WriteHeaderLine("award", "level", "when", "first"); // Fetch Player Awards // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { List<Dictionary<string, object>> Awards = Database.GetPlayerAwards(Pid); // Write each award as a new data line foreach (Dictionary<string, object> Award in Awards) Response.WriteDataLine(Award["awd"], Award["level"], Award["earned"], Award["first"]); // Send Response Response.Send(); } }
/// <summary> /// This request clears all rank announcements for a specific player /// </summary> /// <queryParam name="pid" type="int">The unique player ID</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public RankNotification(HttpClient Client, StatsDatabase Driver) { int Pid = 0; List<Dictionary<string, object>> Rows; // Setup Params if (Client.Request.QueryString.ContainsKey("pid")) Int32.TryParse(Client.Request.QueryString["pid"], out Pid); // Fetch Player Rows = Driver.Query("SELECT rank FROM player WHERE id=@P0", Pid); if (Rows.Count == 0) { Client.Response.WriteResponseStart(false); Client.Response.WriteFreeformLine("Player Doesnt Exist!"); Client.Response.Send(); return; } // Reset Driver.Execute("UPDATE player SET chng=0, decr=0 WHERE id=@P0", Pid); Client.Response.WriteResponseStart(); Client.Response.WriteFreeformLine(String.Format("Cleared rank notification {0}", Pid)); Client.Response.Send(); }
public override void HandleRequest(MvcRoute Route) { // Try and Fetch Player ID Int32.TryParse(Route.Action, out Pid); // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { // Fetch Player Rows = Database.Query("SELECT * FROM player WHERE id=@P0", Pid); if (Rows.Count == 0) { Client.Response.Redirect("/bf2stats/search"); return; } // Load our page based on the param passed if (Route.Params.Length > 0) { if (Route.Params[0] == "rankings") ShowRankings(); else if (Route.Params[0] == "history") ShowHistory(); else Client.Response.StatusCode = 404; } else { ShowStats(); } } }
/// <summary> /// Clears the stats database of all data /// </summary> private void ClearStatsBtn_Click(object sender, EventArgs e) { if (MessageBox.Show( "Are you sure you want to clear the stats database? This will ERASE ALL stats data, and cannot be recovered!", "Confirm", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) { try { using (StatsDatabase Database = new StatsDatabase()) { Database.Truncate(); } Notify.Show("Database Successfully Cleared!", "All stats have successfully been cleared.", AlertType.Success); } catch (Exception E) { MessageBox.Show( "An error occured while clearing the stats database!\r\n\r\nMessage: " + E.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } }
/// <summary> /// This request provides details on a particular players map info /// </summary> /// <queryParam name="pid" type="int">The unique player ID</queryParam> /// <queryParam name="mapid" type="int">The unique map ID</queryParam> /// <queryParam name="customonly" type="int">Defines whether to only display custom maps</queryParam> /// <queryParam name="mapname" type="string">The unique map's name</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public GetMapInfo(HttpClient Client, StatsDatabase Driver) { // Setup Variables int Pid = 0, MapId = 0, CustomOnly = 0; string MapName = ""; SelectQueryBuilder Query = new SelectQueryBuilder(Driver); // Setup QueryString Params if (Client.Request.QueryString.ContainsKey("pid")) Int32.TryParse(Client.Request.QueryString["pid"], out Pid); if (Client.Request.QueryString.ContainsKey("mapid")) Int32.TryParse(Client.Request.QueryString["mapid"], out MapId); if (Client.Request.QueryString.ContainsKey("customonly")) Int32.TryParse(Client.Request.QueryString["customonly"], out CustomOnly); if (Client.Request.QueryString.ContainsKey("mapname")) MapName = Client.Request.QueryString["mapname"].Trim(); // Prepare Response Client.Response.WriteResponseStart(); // Is this a Player Map Request? if (Pid != 0) { // Build our query statement Query.SelectFromTable("maps"); Query.SelectColumns("maps.*", "mapinfo.name AS mapname"); Query.AddJoin(JoinType.InnerJoin, "mapinfo", "id", Comparison.Equals, "maps", "mapid"); Query.AddWhere("maps.id", Comparison.Equals, Pid); Query.AddOrderBy("mapid", Sorting.Ascending); // Execute the reader, and add each map to the output Client.Response.WriteHeaderLine("mapid", "mapname", "time", "win", "loss", "best", "worst"); foreach (Dictionary<string, object> Map in Driver.QueryReader(Query.BuildCommand())) Client.Response.WriteDataLine(Map["mapid"], Map["mapname"], Map["time"], Map["win"], Map["loss"], Map["best"], Map["worst"]); } else { // Build our query statement Query.SelectFromTable("mapinfo"); Query.SelectColumns("id", "name", "score", "time", "times", "kills", "deaths"); Query.AddOrderBy("id", Sorting.Ascending); // Select our where statement if (MapId > 0) Query.AddWhere("id", Comparison.Equals, MapId); else if (!String.IsNullOrEmpty(MapName)) Query.AddWhere("name", Comparison.Equals, MapName); else if (CustomOnly == 1) Query.AddWhere("id", Comparison.GreaterOrEquals, 700); // Execute the reader, and add each map to the output Client.Response.WriteHeaderLine("mapid", "name", "score", "time", "times", "kills", "deaths"); foreach (Dictionary<string, object> Map in Driver.QueryReader(Query.BuildCommand())) Client.Response.WriteDataLine(Map["id"], Map["name"], Map["score"], Map["time"], Map["times"], Map["kills"], Map["deaths"]); } // Send Response Client.Response.Send(); }
/// <summary> /// This request provides details of the leaderboard /// </summary> /// <queryParam name="pid" type="int">The unique player ID</queryParam> /// <queryParam name ="nick" type="string">Unique player nickname</queryParam> /// <queryParam name="type" type="string">"score", "kit", "vehicle", "weapon"</queryParam> /// <queryParam name="id" type="int|string (score)">the various fetch variables (kit ids, vehicle id's etc etc)</queryParam> /// <queryParam name="before" type="int">The number of players before</queryParam> /// <queryParam name="after" type="int">The number of players after</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public GetLeaderBoard(HttpClient Client, StatsDatabase Database) { // Set internal variables this.Response = Client.Response; this.QueryString = Client.Request.QueryString; this.Driver = Database; // We need a type! if (!QueryString.ContainsKey("type")) { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Response.Send(); return; } // Setup Params if(QueryString.ContainsKey("pid")) Int32.TryParse(QueryString["pid"], out Pid); if (QueryString.ContainsKey("id")) Id = QueryString["id"]; if (QueryString.ContainsKey("before")) Int32.TryParse(QueryString["before"], out Before); if(QueryString.ContainsKey("after")) Int32.TryParse(QueryString["after"], out After); if (QueryString.ContainsKey("pos")) Int32.TryParse(QueryString["pos"], out Pos); Min = (Pos - 1) - Before; Max = After + 1; // Do our requested Task switch (QueryString["type"]) { case "score": DoScore(); break; case "risingstar": DoRisingStar(); break; case "kit": DoKit(); break; case "vehicle": DoVehicles(); break; case "weapon": DoWeapons(); break; default: //Response.HTTPStatusCode = ASPResponse.HTTPStatus.BadRequest; Response.Send(); break; } }
public override void HandleRequest() { // We need a type! if (!Request.QueryString.ContainsKey("type")) { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Response.Send(); return; } // Setup Params if (Request.QueryString.ContainsKey("pid")) Int32.TryParse(Request.QueryString["pid"], out Pid); if (Request.QueryString.ContainsKey("id")) Id = Request.QueryString["id"]; if (Request.QueryString.ContainsKey("before")) Int32.TryParse(Request.QueryString["before"], out Before); if (Request.QueryString.ContainsKey("after")) Int32.TryParse(Request.QueryString["after"], out After); if (Request.QueryString.ContainsKey("pos")) Int32.TryParse(Request.QueryString["pos"], out Pos); Min = (Pos - 1) - Before; Max = After + 1; // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { // Do our requested Task switch (Request.QueryString["type"]) { case "score": DoScore(); break; case "risingstar": DoRisingStar(); break; case "kit": DoKit(); break; case "vehicle": DoVehicles(); break; case "weapon": DoWeapons(); break; default: //Response.HTTPStatusCode = ASPResponse.HTTPStatus.BadRequest; Response.Send(); break; } } }
/// <summary> /// Grab lowest PID on startup /// </summary> static GetPlayerID() { // Get the lowest Offline PID from the database using (StatsDatabase Driver = new StatsDatabase()) { int DefaultPid = MainForm.Config.ASP_DefaultPID; var Rows = Driver.Query(String.Format("SELECT COALESCE(MIN(id), {0}) AS min FROM player", DefaultPid)); int Lowest = Int32.Parse(Rows[0]["min"].ToString()); LowestPid = (Lowest > DefaultPid) ? DefaultPid : Lowest -1; } }
public override void HandleRequest() { int Pid = 0; int Unlock = 0; List<Dictionary<string, object>> Rows; // Setup Params if (Request.QueryString.ContainsKey("pid")) Int32.TryParse(Request.QueryString["pid"], out Pid); if (Request.QueryString.ContainsKey("id")) Int32.TryParse(Request.QueryString["id"], out Unlock); // Make sure we have valid parameters if (Pid == 0 || Unlock == 0) { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Response.Send(); return; } // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { // Fetch Player Rows = Database.Query("SELECT availunlocks, usedunlocks FROM player WHERE id=@P0", Pid); if (Rows.Count == 0) { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Player Doesnt Exist"); Response.Send(); return; } // Update Unlock, setting its state to 's' (unlocked) Database.Execute("UPDATE unlocks SET state = 's' WHERE id = @P0 AND kit = @P1", Pid, Unlock); // Update players used and avail unlock counts Database.Execute("UPDATE player SET availunlocks = @P0, usedunlocks = @P1 WHERE id = @P2", int.Parse(Rows[0]["availunlocks"].ToString()) - 1, int.Parse(Rows[0]["usedunlocks"].ToString()) + 1, Pid ); // Send Response Response.WriteResponseStart(); Response.WriteHeaderLine("response"); Response.WriteDataLine("OK"); Response.Send(); } }
//&info=per*,cmb*,twsc,cpcp,cacp,dfcp,kila,heal,rviv,rsup,rpar,tgte,dkas,dsab,cdsc,rank,cmsc,kick,kill,deth,suic,ospm,klpm,klpr,dtpr,bksk,wdsk,bbrs,tcdr,ban,dtpm,lbtl,osaa,vrk,tsql,tsqm,tlwf,mvks,vmks,mvn*,vmr*,fkit,fmap,fveh,fwea,wtm-,wkl-,wdt-,wac-,wkd-,vtm-,vkl-,vdt-,vkd-,vkr-,atm-,awn-,alo-,abr-,ktm-,kkl-,kdt-,kkd- /// <summary> /// This request provides details on a particular player /// </summary> /// <queryParam name="pid" type="int">The unique player ID</queryParam> /// <queryParam name="info" type="string">The requested player data keys, seperated by a comma</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public GetPlayerInfo(HttpClient Client, StatsDatabase Database) { // Load class Variables this.Response = Client.Response; this.QueryString = Client.Request.QueryString; this.Driver = Database; // Setup Params if (QueryString.ContainsKey("pid")) Int32.TryParse(QueryString["pid"], out Pid); if (QueryString.ContainsKey("transpose")) Int32.TryParse(QueryString["transpose"], out Transpose); if (QueryString.ContainsKey("info")) Info = QueryString["info"].Split(',').ToList<string>(); // Make sure our required params are indeed passed if (Pid == 0 || Info.Count == 0) { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("asof", "err"); Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Client.Response.Send(); return; } // Get Missing keys for a standard request List<string> ReqKeys = RequiredKeys.Split(',').ToList<string>(); IEnumerable<string> Diff = from item in ReqKeys where !Info.Contains(item) select item; List<string> MissingKeys = new List<string>(Diff); // Standard BF2HQ Request if (MissingKeys.Count == 0) DoFullRequest(); // Time Info else if (QueryString["info"] == "ktm-,vtm-,wtm-,mtm-") DoTimeRequest(); // Map Info else if (QueryString["info"].StartsWith("mtm-,mwn-,mls-")) DoMapRequest(); else if (QueryString["info"].StartsWith("rank") && QueryString["info"].EndsWith("vac-")) DoServerRequest(); else Response.Send(); }
public override void HandleRequest() { int Pid; // make sure we have a valid player ID if (!Request.QueryString.ContainsKey("pid") || !Int32.TryParse(Request.QueryString["pid"], out Pid) || !Request.QueryString.ContainsKey("nick")) { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Response.Send(); return; } // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { // Fetch Player string PlayerNick = Request.QueryString["nick"].Replace("%20", " "); string CC = (Request.QueryString.ContainsKey("cid")) ? Client.Request.QueryString["cid"] : ""; if (Database.ExecuteScalar<int>("SELECT COUNT(*) FROM player WHERE id=@P0 OR name=@P1", Pid, PlayerNick) > 0) { Response.WriteResponseStart(false); Response.WriteFreeformLine("Player already Exists!"); Response.Send(); return; } // Create Player Database.Execute( "INSERT INTO player(id, name, country, joined, isbot) VALUES(@P0, @P1, @P2, @P3, 0)", Pid, PlayerNick, CC, DateTime.UtcNow.ToUnixTimestamp() ); // Confirm Response.WriteResponseStart(); Response.WriteFreeformLine("Player Created Successfully!"); Response.Send(); } }
/// <summary> /// This request creates a player with the specified Pid when called /// </summary> /// <queryParam name="pid" type="int">The unique player ID</queryParam> /// <queryParam name ="nick" type="string">Unique player nickname</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public CreatePlayer(HttpClient Client, StatsDatabase Driver) { int Pid; // make sure we have a valid player ID if (!Client.Request.QueryString.ContainsKey("pid") || !Int32.TryParse(Client.Request.QueryString["pid"], out Pid) || !Client.Request.QueryString.ContainsKey("nick")) { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("asof", "err"); Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Client.Response.Send(); return; } // Fetch Player string PlayerNick = Client.Request.QueryString["nick"].Replace("%20", " "); string CC = (Client.Request.QueryString.ContainsKey("cid")) ? Client.Request.QueryString["cid"] : ""; var Rows = Driver.Query("SELECT name FROM player WHERE id=@P0 OR name=@P1", Pid, PlayerNick); if (Rows.Count > 0) { Client.Response.WriteResponseStart(false); Client.Response.WriteFreeformLine("Player already Exists!"); Client.Response.Send(); return; } // Create Player Driver.Execute( "INSERT INTO player(id, name, country, joined, isbot) VALUES(@P0, @P1, @P2, @P3, 0)", Pid, PlayerNick, CC, DateTime.UtcNow.ToUnixTimestamp() ); // Confirm Client.Response.WriteResponseStart(); Client.Response.WriteFreeformLine("Player Created Successfully!"); Client.Response.Send(); }
/// <summary> /// Constructor /// </summary> public PlayerSearchForm() { InitializeComponent(); // Establish DB connection try { Driver = new StatsDatabase(); } catch (DbConnectException Ex) { HttpServer.Stop(); ExceptionForm.ShowDbConnectError(Ex); Load += (s, e) => Close(); // Close form return; } // Initialize sorting SortedCol = DataTable.Columns[1]; SortedCol.HeaderCell.SortGlyphDirection = SortOrder.Ascending; LimitSelect.SelectedIndex = 2; }
/// <summary> /// This request provides claninfo to the bf2server, to set the filter rules /// for players joining the server. /// </summary> /// <queryParam name="type" type="int">The Listype (whitelist, blacklist)</queryParam> /// <queryParam name ="clantag" type="string">Specified the required clantag</queryParam> /// <queryParam name="score" type="int">The minimum required score</queryParam> /// <queryParam name="rank" type="int">The minimum required ranked</queryParam> /// <queryParam name="time" type="int">The minimum required global time</queryParam> /// <queryParam name="kdratio" type="float">The minimum required kill/death ratio</queryParam> /// <queryParam name="country" type="string">The country code (Ex: us, br, no) required, seperated by comma, that is required</queryParam> /// <queryParam name="banned" type="int">Specified the maximum ban count to be accepted into the list</queryParam> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public GetClanInfo(HttpClient Client, StatsDatabase Database) { int Type = 0; Dictionary<string, string> QueryString = Client.Request.QueryString; Driver = Database; // make sure we have a valid player ID if (!QueryString.ContainsKey("type") || !Int32.TryParse(QueryString["type"], out Type)) { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("asof", "err"); Client.Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); Client.Response.Send(); return; } // Filler Variables int I = 0; float F; string S; List<DbParameter> Params = new List<DbParameter>(); // Prepare Query SelectQueryBuilder Query = new SelectQueryBuilder(Driver); Query.SelectColumns("id", "name"); Query.SelectFromTable("player"); Query.SetWhereOperator(LogicOperator.And); Query.AddWhere("ip", Comparison.NotEqualTo, "0.0.0.0"); Query.AddOrderBy("id", Sorting.Ascending); WhereClause Where = null; switch (Type) { // Blacklist case 0: int BanLimit = (QueryString.ContainsKey("banned") && Int32.TryParse(QueryString["banned"], out I)) ? I : 100; Where = new WhereClause("banned", Comparison.GreaterOrEquals, BanLimit); Where.AddClause(LogicOperator.Or, "permban", Comparison.Equals, 1); break; // Whitelist case 1: if (QueryString.ContainsKey("clantag")) { Where = new WhereClause("clantag", Comparison.Equals, QueryString["clantag"]); Where.AddClause(LogicOperator.And, "permban", Comparison.Equals, 0); } break; // Greylist case 2: // List of possible query's string[] Queries = new string[] { "score", "rank", "time", "kdratio", "country", "banned" }; foreach (string Param in Queries) { if (QueryString.ContainsKey(Param)) { switch (Param) { case "score": case "time": case "rank": if (Int32.TryParse(QueryString[Param], out I)) { if (Where == null) Where = new WhereClause(Param, Comparison.GreaterOrEquals, I); else Where.AddClause(LogicOperator.And, Param, Comparison.GreaterOrEquals, I); } break; case "kdratio": if (float.TryParse(QueryString["kdratio"], out F)) { if (Where == null) Where = new WhereClause("(kills / deaths)", Comparison.GreaterOrEquals, F); else Where.AddClause(LogicOperator.And, "(kills / deaths)", Comparison.GreaterOrEquals, F); } break; case "country": S = QueryString["country"].Replace(",", "','"); if (Where == null) Where = new WhereClause(Param, Comparison.In, S.Split(',')); else Where.AddClause(LogicOperator.And, Param, Comparison.In, S.Split(',')); break; case "banned": if (Int32.TryParse(QueryString["banned"], out I)) { if(Where == null) Where = new WhereClause("banned", Comparison.LessThan, I); else Where.AddClause(LogicOperator.And,"banned", Comparison.LessThan, I); Where.AddClause(LogicOperator.And, "permban", Comparison.Equals, 0); } break; } } } break; } // Pepare 2 output headers int size = 0; FormattedOutput Output1 = new FormattedOutput("size", "asof"); FormattedOutput Output2 = new FormattedOutput("pid", "nick"); // Query the database, add each player to Output 2 if(Where != null) Query.AddWhere(Where); List<Dictionary<string, object>> Players = Driver.ExecuteReader(Query.BuildCommand()); foreach (Dictionary<string, object> P in Players) { size++; Output2.AddRow(P["id"].ToString(), P["name"].ToString()); } // Send Response Output1.AddRow(size, DateTime.UtcNow.ToUnixTimestamp()); Client.Response.AddData(Output1); Client.Response.AddData(Output2); Client.Response.Send(); }
/// <summary> /// This request takes snapshot data, and processes it into the stats database /// </summary> /// <param name="Client">The HttpClient who made the request</param> /// <param name="Driver">The Stats Database Driver. Connection errors are handled in the calling object</param> public SnapshotPost(HttpClient Client, StatsDatabase Driver) { // First and foremost. Make sure that we are authorized to be here! IPEndPoint RemoteIP = Client.RemoteEndPoint; if (!Client.Request.IsLocal) { // Setup local vars bool IsValid = false; IPAddress Ip; // Loop through all Config allowed game hosts, and determine if the remote host is allowed // to post snapshots here if (!String.IsNullOrWhiteSpace(MainForm.Config.ASP_GameHosts)) { string[] Hosts = MainForm.Config.ASP_GameHosts.Split(','); foreach (string Host in Hosts) { if (IPAddress.TryParse(Host, out Ip) && Ip.Equals(RemoteIP.Address)) { IsValid = true; break; } } } // If we are not on the GameHost list, too bad sucka! if (!IsValid) { // Notify User Notify.Show("Snapshot Denied!", "Invalid Server IP: " + RemoteIP.Address.ToString(), AlertType.Warning); if (Client.Request.UserAgent == "GameSpyHTTP/1.0") { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("response"); Client.Response.WriteDataLine("Unauthorised Gameserver"); } else Client.Response.StatusCode = (int)HttpStatusCode.Forbidden; Client.Response.Send(); return; } } // Make sure we have post data if (!Client.Request.HasEntityBody) { // No Post Data if (Client.Request.UserAgent == "GameSpyHTTP/1.0") { Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("response"); Client.Response.WriteDataLine("SNAPSHOT Data NOT found!"); } else Client.Response.StatusCode = (int)HttpStatusCode.BadRequest; Client.Response.Send(); return; } // Create our snapshot object and filename string SnapshotData; Snapshot Snapshot; string FileName = String.Empty; bool BackupCreated = false; // Create snapshot backup file if the snapshot is valid try { // Read Snapshot using (StreamReader Reader = new StreamReader(Client.Request.InputStream)) SnapshotData = Reader.ReadToEnd(); // Create the Snapshot Object Snapshot = new Snapshot(SnapshotData, DateTime.UtcNow, Driver); // Make sure data is valid! if (!Snapshot.IsValid) { Notify.Show("Error Processing Snapshot!", "Snapshot Data NOT Complete or Invalid!", AlertType.Warning); Client.Response.WriteResponseStart(false); Client.Response.WriteHeaderLine("response"); Client.Response.WriteDataLine("SNAPSHOT Data NOT complete or invalid!"); Client.Response.Send(); return; } } catch (Exception E) { ASPServer.Log("ERROR: [SnapshotPreProcess] " + E.Message + " @ " + E.TargetSite); Client.Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable; Client.Response.Send(); return; } // Create backup of snapshot try { // Backup the snapshot FileName = Snapshot.ServerPrefix + "-" + Snapshot.MapName + "_" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".txt"; File.AppendAllText(Path.Combine(Paths.SnapshotTempPath, FileName), SnapshotData); BackupCreated = true; } catch (Exception E) { ASPServer.Log("WARNING: Unable to create Snapshot Backup File: " + E.Message); } // Tell the server we are good to go Client.Response.WriteResponseStart(); Client.Response.WriteHeaderLine("response"); Client.Response.WriteDataLine("OK"); Client.Response.Send(); // Have the snapshot class handle the rest :) try { // Do the snapshot Snapshot.Process(); // Move the Temp snapshot to the Processed folder if (BackupCreated) { try { File.Move(Path.Combine(Paths.SnapshotTempPath, FileName), Path.Combine(Paths.SnapshotProcPath, FileName)); } catch (Exception e) { ASPServer.Log("WARNING: [SnapshotFileOperations] " + e.Message); File.Delete(Path.Combine(Paths.SnapshotTempPath, FileName)); } } // Notify User Notify.Show("Snapshot Processed Successfully!", "From Server IP: " + RemoteIP.Address.ToString(), AlertType.Success); // Fire Event SnapshotReceived(true); } catch (Exception E) { // Notify user Notify.Show("Error Processing Snapshot!", E.Message, AlertType.Warning); ASPServer.Log("ERROR: [SnapshotProcessing] " + E.Message); // Fire event SnapshotReceived(false); } }
/// <summary> /// Backs up the asp database /// </summary> private void ExportAsASPBtn_Click(object sender, EventArgs e) { // Define backup folder for this backup, and create it if it doesnt exist string Folder = Path.Combine(Paths.DocumentsFolder, "Backups", "bak_" + DateTime.Now.ToString("yyyyMMdd_HHmm")); if (!Directory.Exists(Folder)) Directory.CreateDirectory(Folder); // Abortion indicator bool Aborted = false; // Open the database connection StatsDatabase Database; try { Database = new StatsDatabase(); } catch (Exception Ex) { MessageBox.Show( "Unable to connect to database\r\n\r\nMessage: " + Ex.Message, "Database Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); // Stop the ASP server, and close this form ASP.ASPServer.Stop(); this.Close(); return; } // Show loading screen LoadingForm.ShowScreen(this); // Backup each table into its own bak file foreach (string Table in StatsDatabase.StatsTables) { // Create file path string BakFile = Path.Combine(Folder, Table + ".bak"); // Backup tables try { using (Stream Str = File.Open(BakFile, FileMode.Create)) using (StreamWriter Wtr = new StreamWriter(Str)) { // Use a memory efficient way to export this stuff foreach (Dictionary<string, object> Row in Database.QueryReader("SELECT * FROM " + Table)) Wtr.WriteLine(String.Join("\t", Row.Values)); Wtr.Flush(); } } catch (Exception Ex) { // Close loading form LoadingForm.CloseForm(); // Display the Exception Form ExceptionForm Form = new ExceptionForm(Ex, false); Form.Message = "An error occured while trying to backup the \"" + Table + "\" table. " + "The backup operation will now be cancelled."; DialogResult Result = Form.ShowDialog(); Aborted = true; // Try and remove backup folder try { DirectoryInfo Dir = new DirectoryInfo(Folder); Dir.Delete(true); } catch { } } if (Aborted) break; } // Only display success message if we didnt abort if (!Aborted) { // Close loading form LoadingForm.CloseForm(); string NL = Environment.NewLine; MessageBox.Show( String.Concat("Backup has been completed successfully!", NL, NL, "Backup files have been saved to:", NL, Folder), "Backup Success", MessageBoxButtons.OK, MessageBoxIcon.Information ); } // Close the connection Database.Dispose(); }
public override void HandleRequest() { // Setup Variables List<Dictionary<string, object>> Rows; Dictionary<string, string> QueryString = Request.QueryString; // Querystring vars int IsAI = 0; int ListPlayers = 0; string PlayerNick = ""; // Setup Params if (QueryString.ContainsKey("nick")) PlayerNick = Uri.UnescapeDataString(QueryString["nick"].Replace("%20", " ")); if (QueryString.ContainsKey("ai")) Int32.TryParse(QueryString["ai"], out IsAI); if (QueryString.ContainsKey("playerlist")) Int32.TryParse(QueryString["playerlist"], out ListPlayers); // NOTE: The HttpServer will handle the DbConnectException using (Database = new StatsDatabase()) { // Handle Request if (!String.IsNullOrWhiteSpace(PlayerNick)) { int Pid; // Create player if they donot exist Rows = Database.Query("SELECT id FROM player WHERE name = @P0 LIMIT 1", PlayerNick); if (Rows.Count == 0) { // Grab new Player ID using thread safe methods Pid = (IsAI > 0) ? StatsManager.GenerateNewAIPid() : StatsManager.GenerateNewPlayerPid(); // Create Player Database.Execute( "INSERT INTO player(id, name, joined, isbot) VALUES(@P0, @P1, @P2, @P3)", Pid, PlayerNick, DateTime.UtcNow.ToUnixTimestamp(), IsAI ); } else Pid = Int32.Parse(Rows[0]["id"].ToString()); // Send Response Response.WriteResponseStart(); Response.WriteHeaderLine("pid"); Response.WriteDataLine(Pid); } else if (ListPlayers != 0) { // Prepare Response Response.WriteResponseStart(); Response.WriteHeaderLine("pid"); // Fetch Players Rows = Database.Query("SELECT id FROM player WHERE isbot=0 LIMIT 1000"); foreach (Dictionary<string, object> Player in Rows) Response.WriteDataLine(Player["id"]); } else { Response.WriteResponseStart(false); Response.WriteHeaderLine("asof", "err"); Response.WriteDataLine(DateTime.UtcNow.ToUnixTimestamp(), "Invalid Syntax!"); } // Send Response Response.Send(); } }
/// <summary> /// Imports ASP created BAK files (Mysql Out FILE) /// </summary> private void ImportASPBtn_Click(object sender, EventArgs e) { // Open File Select Dialog FolderSelectDialog Dialog = new FolderSelectDialog(); Dialog.Title = "Select ASP Database Backup Folder"; Dialog.InitialDirectory = Path.Combine(Paths.DocumentsFolder, "Backups"); if (Dialog.ShowDialog()) { // Get files list from path string path = Dialog.SelectedPath; string[] BakFiles = Directory.GetFiles(path, "*.bak"); if (BakFiles.Length > 0) { // Open the database connection StatsDatabase Database; try { Database = new StatsDatabase(); } catch (Exception Ex) { MessageBox.Show( "Unable to connect to database\r\n\r\nMessage: " + Ex.Message, "Database Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); // Stop the ASP server, and close this form ASP.ASPServer.Stop(); this.Close(); return; } // Show task dialog TaskForm.Show(this, "Importing Stats", "Importing ASP Stats Bak Files...", false); TaskForm.UpdateStatus("Removing old stats data"); // Clear old database records Database.Truncate(); Thread.Sleep(500); // Begin transaction DbTransaction Transaction = Database.BeginTransaction(); // import each table foreach (string file in BakFiles) { // Get table name string table = Path.GetFileNameWithoutExtension(file); // Update progress TaskForm.UpdateStatus("Processing stats table: " + table); // Import table data try { // Sqlite kinda sucks... no import methods if (Database.DatabaseEngine == DatabaseEngine.Sqlite) { string[] Lines = File.ReadAllLines(file); foreach (string line in Lines) { string[] Values = line.Split('\t'); Database.Execute( String.Format("INSERT INTO {0} VALUES({1})", table, "\"" + String.Join("\", \"", Values) + "\"") ); } } else Database.Execute(String.Format("LOAD DATA LOCAL INFILE '{0}' INTO TABLE {1};", file.Replace('\\', '/'), table)); } catch (Exception Ex) { // Show exception error ExceptionForm Form = new ExceptionForm(Ex, false); Form.Message = String.Format("Failed to import data into table {0}!{2}{2}Error: {1}", table, Ex.Message, Environment.NewLine); DialogResult Result = Form.ShowDialog(); // Rollback! TaskForm.UpdateStatus("Rolling back stats data"); Transaction.Rollback(); // Update message TaskForm.CloseForm(); return; } } // Commit the transaction, and alert the user Transaction.Commit(); TaskForm.CloseForm(); Notify.Show("Stats imported successfully!", "Operation Successful", AlertType.Success); // Displose Connection Database.Dispose(); } else { // Alert the user and tell them they failed MessageBox.Show( "Unable to locate any .bak files in this folder. Please select an ASP created database backup folder that contains backup files.", "Backup Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } }
/// <summary> /// Adds a server's posted snapshot into the Snapshot Processing Queue, which /// will process the snapshot as soon as possible. This method is Non-Blocking. /// </summary> /// <remarks> /// Any errors that occur during the actual import of the data will be /// logged inside the StatsDebug log /// </remarks> /// <param name="Data">The snapshot data provided by the server.</param> /// <param name="ServerAddress">The IP address of the server.</param> /// <exception cref="UnauthorizedAccessException"> /// Thrown if the Server IP is not authorized to post game data to this server /// </exception> /// <exception cref="InvalidDataException"> /// Thrown if the provided Snapshot data is not valid, and cannot be processed /// </exception> public static void QueueServerSnapshot(string Data, IPAddress ServerAddress) { // Make sure the server is authorized if (!IsAuthorizedGameServer(ServerAddress)) throw new UnauthorizedAccessException("Un-Authorised Gameserver (Ip: " + ServerAddress + ")"); // Create the Snapshot Object Snapshot Snap = new Snapshot(Data, ServerAddress); // Update this server in the Database using (StatsDatabase Database = new StatsDatabase()) { // Try and grab the ID of this server int id = Database.ExecuteScalar<int>( "SELECT COALESCE(id, -1), COUNT(id) FROM servers WHERE ip=@P0 AND port=@P1", ServerAddress, Snap.ServerPort ); // New server? if (id < 0) { InsertQueryBuilder builder = new InsertQueryBuilder(Database); builder.SetTable("servers"); builder.SetField("ip", ServerAddress); builder.SetField("port", Snap.ServerPort); builder.SetField("prefix", Snap.ServerPrefix); builder.SetField("name", Snap.ServerName); builder.SetField("queryport", Snap.QueryPort); builder.SetField("lastupdate", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")); builder.Execute(); } else // existing { UpdateQueryBuilder builder = new UpdateQueryBuilder(Database); builder.SetTable("servers"); builder.SetField("prefix", Snap.ServerPrefix); builder.SetField("name", Snap.ServerName); builder.SetField("queryport", Snap.QueryPort); builder.SetField("lastupdate", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")); builder.AddWhere("id", Comparison.Equals, id); builder.Execute(); } } // Add snapshot to Queue SnapshotQueue.Enqueue(Snap); }
/// <summary> /// Method to be called everytime the HttpStatsServer is started /// </summary> public static void Load(StatsDatabase Driver) { // Get the lowest Offline PID from the database var Rows = Driver.Query( String.Format( "SELECT COALESCE(MIN(id), {0}) AS min, COALESCE(MAX(id), {0}) AS max FROM player WHERE id < {1}", DEFAULT_PID, MAX_PID ) ); int Lowest = Int32.Parse(Rows[0]["min"].ToString()); int Highest = Int32.Parse(Rows[0]["max"].ToString()); AiPid = (Lowest > DEFAULT_PID) ? DEFAULT_PID : Lowest; PlayerPid = (Highest < DEFAULT_PID) ? DEFAULT_PID : Highest; }
/// <summary> /// Imports a Player XML Sheet from the specified path /// </summary> /// <param name="XmlPath">The full path to the XML file</param> public static void ImportPlayerXml(string XmlPath) { // Connect to database first! using (StatsDatabase Driver = new StatsDatabase()) { // Load elements XDocument Doc = XDocument.Load(new FileStream(XmlPath, FileMode.Open, FileAccess.Read)); XElement Info = Doc.Root.Element("Info"); XElement TableData = Doc.Root.Element("TableData"); // Make sure player doesnt already exist int Pid = Int32.Parse(Info.Element("Pid").Value); if (Driver.PlayerExists(Pid)) throw new Exception(String.Format("Player with PID {0} already exists!", Pid)); // Begin Transaction using (DbTransaction Transaction = Driver.BeginTransaction()) { try { // Loop through tables foreach (XElement Table in TableData.Elements()) { // Loop through Rows foreach (XElement Row in Table.Elements()) { InsertQueryBuilder QueryBuilder = new InsertQueryBuilder(Table.Name.LocalName, Driver); foreach (XElement Col in Row.Elements()) { if (Col.Name.LocalName == "name") QueryBuilder.SetField(Col.Name.LocalName, Col.Value.UnescapeXML()); else QueryBuilder.SetField(Col.Name.LocalName, Col.Value); } QueryBuilder.Execute(); } } // Commit Transaction Transaction.Commit(); } catch { Transaction.Rollback(); throw; } } } }
/// <summary> /// Exports a players stats and history into an Xml file /// </summary> /// <param name="XmlPath">The folder path to where the XML will be saved</param> /// <param name="Pid">Player ID</param> /// <param name="Name">Player Name</param> public static void ExportPlayerXml(string XmlPath, int Pid, string Name) { // Create full path string sPath = Path.Combine( XmlPath, String.Format("{0}_{1}_{2}.xml", Name.Trim().MakeFileNameSafe(), Pid, DateTime.Now.ToString("yyyyMMdd_HHmm")) ); // Delete file if it exists already if (File.Exists(sPath)) File.Delete(sPath); // Create XML Settings XmlWriterSettings Settings = new XmlWriterSettings(); Settings.Indent = true; Settings.IndentChars = "\t"; Settings.NewLineChars = Environment.NewLine; Settings.NewLineHandling = NewLineHandling.Replace; // Write XML data using (StatsDatabase Driver = new StatsDatabase()) using (XmlWriter Writer = XmlWriter.Create(sPath, Settings)) { // Player Element Writer.WriteStartDocument(); Writer.WriteStartElement("Player"); // Manifest Writer.WriteStartElement("Info"); Writer.WriteElementString("Pid", Pid.ToString()); Writer.WriteElementString("Name", Name.EscapeXML()); Writer.WriteElementString("BackupDate", DateTime.Now.ToString()); Writer.WriteEndElement(); // Start Tables Element Writer.WriteStartElement("TableData"); // Add each tables data foreach (string Table in StatsDatabase.PlayerTables) { // Open table tag Writer.WriteStartElement(Table); // Fetch row List<Dictionary<string, object>> Rows; if (Table == "kills") Rows = Driver.Query(String.Format("SELECT * FROM {0} WHERE attacker={1} OR victim={1}", Table, Pid)); else Rows = Driver.Query(String.Format("SELECT * FROM {0} WHERE id={1}", Table, Pid)); // Write each row's columns with its value to the xml file foreach (Dictionary<string, object> Row in Rows) { // Open Row tag Writer.WriteStartElement("Row"); foreach (KeyValuePair<string, object> Column in Row) { if (Column.Key == "name") Writer.WriteElementString(Column.Key, Column.Value.ToString().EscapeXML()); else Writer.WriteElementString(Column.Key, Column.Value.ToString()); } // Close Row tag Writer.WriteEndElement(); } // Close table tag Writer.WriteEndElement(); } // Close Tags and File Writer.WriteEndElement(); // Close Tables Element Writer.WriteEndElement(); // Close Player Element Writer.WriteEndDocument(); // End and Save file } }
public override void HandleRequest(MvcRoute Route) { // Get our POST variables HttpRequest Request = Client.Request; Dictionary<string, string> postParams = Request.GetFormUrlEncodedPostVars(); int[] pids = new int[0]; // Fetch our cookie, which contains our PiD's Cookie C = Request.Request.Cookies["leaderboard"] ?? new Cookie("leaderboard", ""); // Convert cookie format into a readable one, and make sure we end with a comma! Model.CookieValue = C.Value.Trim().Replace('|', ','); if (!Model.CookieValue.EndsWith(",")) Model.CookieValue += ","; // Save Leaderboard if (postParams.ContainsKey("set") && postParams.ContainsKey("leaderboard")) // Save cookie { Model.CookieValue = postParams["leaderboard"]; } else if (Route.Action != "index" && Route.Params.Length != 0) { switch (Route.Action) { case "add": if (Validator.IsValidPID(Route.Params[0])) Model.CookieValue += $"{Route.Params[0]},"; break; case "remove": if (Validator.IsValidPID(Route.Params[0])) Model.CookieValue = Model.CookieValue.Replace($"{Route.Params[0]},", ""); break; case "list": Model.CookieValue = Route.Params[0]; break; } } // Read pids from the cookie try { // Pids are stored as xxxx,yyyyy,zzzz in the cookie if (Model.CookieValue.Length > 0) { string[] players = Model.CookieValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (players.Length > 0) { pids = Array.ConvertAll(players, Int32.Parse).Distinct().ToArray(); } } } catch { // Bad Cookie value, so flush it! Model.CookieValue = ""; C.Value = String.Empty; Client.Response.SetCookie(C); } // if "get" is POSTED, that means we are generated a URL instead of a cookie if (postParams.ContainsKey("get")) { Client.Response.Redirect(Model.Root + "/myleaderboard/list/" + String.Join(",", pids)); return; } // If we have some player ID's, then the leaderboard is not empty if (pids.Length > 0) { // NOTE: The HttpServer will handle the DbConnectException using (StatsDatabase Database = new StatsDatabase()) { var Rows = Database.Query( String.Format("SELECT id, name, score, time, country, rank, lastonline, kills, deaths FROM player WHERE id IN ({0})", String.Join(",", pids) )); // Loop through each result, and process foreach (Dictionary<string, object> Row in Rows) { // DO Kill Death Ratio double Kills = Int32.Parse(Row["kills"].ToString()); double Deaths = Int32.Parse(Row["deaths"].ToString()); double Kdr = (Deaths > 0) ? Math.Round(Kills / Deaths, 3) : Kills; // Get Score Per Min double Score = Int32.Parse(Row["score"].ToString()); double Mins = Int32.Parse(Row["time"].ToString()) / 60; double SPM = (Mins > 0) ? Math.Round(Score / Mins, 4) : Score; int Pid = Int32.Parse(Row["id"].ToString()); // Add Result Model.Players.Add(new PlayerResult { Pid = Pid, Name = Row["name"].ToString(), Score = (int)Score, Rank = Int32.Parse(Row["rank"].ToString()), TimePlayed = FormatTime(Int32.Parse(Row["time"].ToString())), LastOnline = FormatDate(Int32.Parse(Row["lastonline"].ToString())), Country = Row["country"].ToString().ToUpperInvariant(), Kdr = Kdr, Spm = SPM, Status = GetOnlineStatus(Pid) }); } } } // Finally, set the cookie if we arent viewing from a List if (Route.Action != "list") { Model.CookieValue = String.Join(",", pids); C.Value = String.Join("|", pids); C.Expires = DateTime.Now.AddYears(1); C.Path = "/"; Client.Response.SetCookie(C); } // TO prevent null expception in the template if (Model.CookieValue == null) Model.CookieValue = String.Empty; // Set content type base.SendTemplateResponse("myleaderboard", typeof(LeaderboardModel), Model); }