public function Set_Player_Progress($db_id, $input) { if (Cache::has($this->class_name . "_" . $db_id . "_Progress_MD5")) { //check the input MD5 against this if (md5($input) == Cache::get($this->class_name . "_" . $db_id . "_Progress_MD5")) { return true; } } else { //Check the last send for progress, see if we need to update, or make a new row $last_progress_update = Progress::where(function ($query) use($db_id) { $query->where('db_id', '=', $db_id); $query->where(DB::raw('DATE(updated_at)'), '=', $this->date_only); })->order_by('id', 'desc')->first('id'); try { if ($last_progress_update) { $query_update_prog = "UPDATE `progresses` SET `entry` = ?, updated_at = ? WHERE `id` = ?"; $bindings_update_progress = array(gzcompress(json_encode($input), 5), $this->date, $last_progress_update->id); if (DB::query($query_update_prog, $bindings_update_progress) === false) { throw new Exception('Error updating progress.'); } } else { $progress = new Progress(); $progress->db_id = $db_id; $progress->entry = gzcompress(json_encode($input), 5); if (!$progress->save()) { throw new Exception('Add progress query failed:'); } } } catch (Exception $e) { Log::info($log_header . $e->getMessage()); file_put_contents($this->logpath . $this->logdate . '_bad_player.json', json_encode($input)); return false; } } //set cache file and cache MD5 file Cache::forever($this->class_name . "_" . $db_id . "_Progress", json_encode($input)); Cache::forever($this->class_name . "_" . $db_id . "_Progress_MD5", md5($input)); return true; }
protected function afterSave() { parent::afterSave(); $users = DisciplineToUser::model()->findAllByAttributes(array('id_discipline' => $this->id_discipline)); if ($this->isNewRecord) { foreach ($users as $user) { $model = new Progress(); $model->id_user = $user->id_user; $model->id_lesson = $this->id_lesson; $model->save(); } } }
public function post_player() { $log_header = "addon_v2.php@player [" . $this->user_ip . "] - ({$this->logdate}): "; $line = Input::json(); if ($this->savedata) { file_put_contents($this->logpath . $this->logdate . '_player.json', serialize($line)); } $datlog = new DatLog(); $datlog->ip = ip2long($this->user_ip); $datlog->db_id = isset($line->Player_ID) ? $line->Player_ID : NULL; $datlog->name = isset($line->Player_Name) ? $line->Player_Name : NULL; $datlog->category = 'player'; $datlog->save(); try { /* ******************************** ** Validate Minimum Keys Exist** ******************************** * # Fail if invalid */ //Minimum keys if (!isset($line->Inventory) || !isset($line->Progress) || !isset($line->Website_Prefs) || !isset($line->Player_ID) || !isset($line->Player_Name) || !isset($line->Player_Instance) || !isset($line->Loadouts) || !isset($line->Player_EID) || !isset($line->Player_Coords) || !isset($line->ArmyID) || !isset($line->Battle_Frame)) { throw new Exception('Player did not send all keys.'); } /* ******************************** ** Validate Player ID (db_id) ** ******************************** * # Fail if invalid * @ sets $player_db_id * * -check digits only * -19 characters long * -Begins with a 9 */ //Digits only? if (preg_match('/[^0-9]/', $line->Player_ID)) { throw new Exception("Player ID was more than just numbers: " . $line->Player_ID); } //19 Characters long? if (strlen($line->Player_ID) !== 19) { throw new Exception("Player ID was not 19 characters: " . $line->Player_ID); } //Starts with a 9? if (substr($line->Player_ID, 0, 1) !== '9') { throw new Exception("Player ID did not start with a 9: " . $line->Player_ID); } $player_db_id = $line->Player_ID; /* ********************************** ** Validate Player Name/Army Tag** ********************************** * # Warn if invalid * @ sets $player_name * @ sets $player_army_tag * * -15 + 6 characters or less ~23 to be safe * -We don't care about character content as much as FF does */ //Check if name is way too long, or too short if (strlen($line->Player_Name) > 30 || trim(strlen($line->Player_Name)) < 3) { throw new Exception("Player ({$player_db_id}) name was longer than 30 characters, should be <= 23: " . $line->Player_Name); } //Warn if longer than expected (that's what she said) //But allow for armytag length too if (strlen($line->Player_Name) > 27) { Log::warn("Player ({$player_db_id}) sent a character name longer than max expected length of 27: " . $line->Player_Name); } //Name is ok, but does it have an army tag? Does it blend? if (strpos($line->Player_Name, ']')) { $last = strripos($line->Player_Name, ']') + 1; $player_army_tag = substr($line->Player_Name, 0, $last); $player_name = trim(substr($line->Player_Name, $last)); } else { $player_army_tag = NULL; $player_name = $line->Player_Name; } /* *********************************** ** Check existing name/db_id ** *********************************** * Does the db_id exist? * Does the submitted name match existing? */ $check_existing_sql = Player::where('db_id', '=', $player_db_id)->order_by('created_at', 'DESC')->first(); if ($check_existing_sql) { if ($check_existing_sql->name != $player_name) { throw new Exception("Existing db_id does not match existing name: (player sent:{$player_db_id}|{$player_name};existing:{$check_existing_sql->db_id}|{$check_existing_sql->name};)"); Log::warn("Existing db_id does not match existing name({$player_db_id}|in:{$player_name}|existing:{$check_existing_sql->name})"); } } /* ******************************** ** Validate Website Prefs ** ******************************** * # Allow, but only if valid * @ (self contained) * * -Contain all keys * -Only 0 or 1 values */ //Minimum keys if (isset($line->Website_Prefs) && isset($line->Website_Prefs->show_loadout) && isset($line->Website_Prefs->show_inventory) && isset($line->Website_Prefs->show_progress) && isset($line->Website_Prefs->show_unlocks) && isset($line->Website_Prefs->show_pve_kills) && isset($line->Website_Prefs->show_pve_stats) && isset($line->Website_Prefs->show_pve_events) && isset($line->Website_Prefs->show_location)) { //Get ready to save, check for boolean digit values only $save_prefs = true; foreach ($line->Website_Prefs as $pref) { //allowed values 1|0 if ($pref !== 0 && $pref !== 1) { $save_prefs = false; } } //because not everyone uses the latest version $show_workbench = isset($line->Website_Prefs->show_workbench) ? $line->Website_Prefs->show_workbench : 0; $show_craftables = isset($line->Website_Prefs->show_craftables) ? $line->Website_Prefs->show_craftables : 0; $show_market_listings = isset($line->Website_Prefs->show_market_listings) ? $line->Website_Prefs->show_market_listings : 0; //IF Website Prefs are appropriate, right click, save as if ($save_prefs) { $prefs = $line->Website_Prefs; $query_webpref = 'INSERT INTO `websiteprefs` (db_id, '; $query_webpref .= 'show_loadout, show_progress, show_inventory, show_unlocks, '; $query_webpref .= 'show_pve_kills, show_pve_stats, show_pve_events, show_location, '; $query_webpref .= 'show_workbench, show_craftables, show_market_listings, '; $query_webpref .= 'created_at, updated_at) VALUES '; $query_webpref .= '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE '; $query_webpref .= '`show_loadout` = ?, `show_progress` = ?, `show_inventory` = ?, show_unlocks = ?, '; $query_webpref .= '`show_pve_kills` = ?, `show_pve_stats` = ?, `show_pve_events` = ?, `show_location` = ?, '; $query_webpref .= '`show_workbench` = ?, `show_craftables` = ?, `show_market_listings` = ?, '; $query_webpref .= '`updated_at` = ?'; $bindings_webpref = array($player_db_id, $prefs->show_loadout, $prefs->show_progress, $prefs->show_inventory, $prefs->show_unlocks, $prefs->show_pve_kills, $prefs->show_pve_stats, $prefs->show_pve_events, $prefs->show_location, $show_workbench, $show_craftables, $show_market_listings, $this->date, $this->date, $prefs->show_loadout, $prefs->show_progress, $prefs->show_inventory, $prefs->show_unlocks, $prefs->show_pve_kills, $prefs->show_pve_stats, $prefs->show_pve_events, $prefs->show_location, $show_workbench, $show_craftables, $show_market_listings, $this->date); DB::query($query_webpref, $bindings_webpref); } else { Log::warn("Player ({$player_db_id}) sent invalid Website Prefs values: " . implode(',', (array) $line->Website_Prefs)); } } else { Log::warn($log_header . "Player ({$player_db_id}) did not send all website prefs or correct keys: "); } /* ********************************** ** Validate Instance ID ** ********************************** * # Fail if not numeric, or 9|10 long * @ sets $player_instance_id * * -Greater than 0 * -Expected length 9 or 10, but others possible */ //Not negative 1 for some reason if ($line->Player_Instance === -1) { throw new Exception("Player ({$player_db_id}) Instance ID was -1: " . $line->Player_Instance); } //Sending only digits if (preg_match('/[^0-9]/', $line->Player_Instance)) { throw new Exception("Player ({$player_db_id}) Instance ID contained something other than a number: " . $line->Player_Instance); } //Log if non regular instanceid (can be legit) if (strlen($line->Player_Instance) < 5) { Log::warn("Player ({$player_db_id}) Instance ID was less than 5 digits long: " . $line->Player_Instance); } $player_instance_id = $line->Player_Instance; /* ********************************** ** Validate Player EID ** ********************************** * # Fail is non numeric, NULL otherwise * @ sets $player_eid * * -Greater than 0 * -Expected length 9 or 10, but others possible */ //Sent only numbers if (preg_match('/[^0-9]/', $line->Player_EID)) { throw new Exception("Player ({$player_db_id}) EID contained something other than a number: " . $line->Player_EID); } //EID should be as long as a db_id if (strlen($line->Player_EID) !== 19) { Log::warn("Player ({$player_db_id}) EID was not the expected 19 digits long: " . $line->Player_EID); $line->Player_EID = NULL; } $player_eid = $line->Player_EID; /* ********************************** ** Validate Army ID ** ********************************** * # Fail if set and not nil or numeric * @ sets $player_army_id * * -Greater than 0 * -Expected length 9 or 10, but others possible */ //ArmyID nil -> null if (isset($line->ArmyID)) { if ($line->ArmyID == 'nil' || $line->ArmyID == false) { $player_army_id = NULL; } else { //Numbers only plx if (preg_match('/[^0-9]/', $line->ArmyID)) { throw new Exception("Player ({$player_db_id}) ArmyID was not numeric and not nil: " . $line->ArmyID); } else { $player_army_id = $line->ArmyID; } } } else { $player_army_id = NULL; } /* ********************************** ** Validate Current Archetype ** ********************************** * # Fail to null * @ sets $player_current_archetype * * -in array expected * -guardian,recon,medic,bunker,berzerker,unknown,NULL */ $expected_archetypes = array('guardian', 'recon', 'medic', 'bunker', 'berzerker', 'unknown'); //Valid archetype? I don't know what I expected if (!in_array($line->Battle_Frame, $expected_archetypes)) { $player_current_archetype = NULL; Log::warn("Player ({$player_db_id}) sent unexpected battleframe: " . $line->Battle_Frame); } else { $player_current_archetype = $line->Battle_Frame; } /* ********************************** ** Validate Player Region ** ********************************** * # Fail to null * @ sets $player_region * * Is alpha/-/num.. */ //Valid region; but not the nether region if (isset($line->Player_Region)) { $player_region = preg_replace('/[^A-Z0-9\\-]/i', '', $line->Player_Region); } else { $player_region = ""; } /* ********************************** ** Validate Player Coords ** ********************************** * # Fail if out of bounds * @ sets $player_coord_x * @ sets $player_coord_y * @ sets $player_coord_z * @ sets $spotter_db_id * * -check keys (x,y,z) * -coords within 0->3328 +/- * -spotter_db_id is db_id */ /* $spotter_db_id = $player_db_id; //Minimum keys if( !isset($line->Player_Coords->x) || !isset($line->Player_Coords->y) || !isset($line->Player_Coords->z) || !isset($line->Player_Coords->chunkX) || !isset($line->Player_Coords->chunkY) ) { throw new Exception("Player ($player_db_id) didn't send all location keys"); }else{ $save_loc = true; $log_loc = false; foreach ($line->Player_Coords as $k => $v) { //float values for locations if( $k == 'x' || $k == 'y' || $k == 'z' ) { if( !is_float($v) && $v !== 0 ) { $log_loc = true; } }else{ //integers for chunks if( !is_numeric($v) ) { $log_loc = true; } } } //We're going to allow all locations, but log unexpected ones if( $save_loc ) { $loc = new Location; $loc->db_id = $player_db_id; $loc->spotter_db_id = $spotter_db_id; $loc->name = $player_name; $loc->instanceId = $player_instance_id; $loc->current_archetype = $player_current_archetype; $loc->coord_x = $line->Player_Coords->x; $loc->coord_y = $line->Player_Coords->y; $loc->coord_z = $line->Player_Coords->z; $loc->chunkX = $line->Player_Coords->chunkX; $loc->chunkY = $line->Player_Coords->chunkY; $loc->save(); if($log_loc) { Log::warn("Player ($player_db_id) sent unexpected coordinates: (locid: {$loc->id}) " . implode(',', (array) $line->Player_Coords) ); } }else{ Log::warn("Player ($player_db_id) sent out of bounds coordinates: " . implode(',', (array) $line->Player_Coords) ); } } */ //------------------------------------------------------------------------------------------------------------- // UPDATE/INSERT PLAYER, FOLLOW WITH INVENTORY/PROGRESS/LOADOUTS ON SUCCESS ---------------------------------- //------------------------------------------------------------------------------------------------------------- $is_addon_user = 1; $query_add_player = "INSERT INTO `players` "; $query_add_player .= "(name, armyTag, instanceId, db_id, e_id,"; $query_add_player .= "armyId, current_archetype, region, "; $query_add_player .= "created_at, updated_at) "; $query_add_player .= "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "; $query_add_player .= "ON DUPLICATE KEY UPDATE "; $query_add_player .= "name = ?, armyTag = ?, instanceId = ?, armyId = ?, "; $query_add_player .= "e_id = ?, current_archetype = ?, addon_user = ?, region = ?, "; $query_add_player .= "updated_at = ?"; $bindings = array($player_name, $player_army_tag, $player_instance_id, $player_db_id, $player_eid, $player_army_id, $player_current_archetype, $player_region, $this->date, $this->date, $player_name, $player_army_tag, $player_instance_id, $player_army_id, $player_eid, $player_current_archetype, $is_addon_user, $player_region, $this->date); try { if (!DB::query($query_add_player, $bindings)) { throw new Exception('Add/Update player query failed'); } /* ********************************** ** Set Inventory If Not Empty ** ********************************** */ if (!empty($line->Inventory)) { //Check the last send for inventory, see if we need to update, or make a new row $last_inventory_update = Inventory::where(function ($query) use($player_db_id) { $query->where('db_id', '=', $player_db_id); $query->where(DB::raw('DATE(updated_at)'), '=', $this->date_only); })->order_by('id', 'desc')->first('id'); if ($last_inventory_update) { $query_update_inv = "UPDATE `inventories` SET `inventory` = ?, updated_at = ? WHERE `id` = ?"; $bindings_update_inventory = array(serialize($line->Inventory), $this->date, $last_inventory_update->id); if (DB::query($query_update_inv, $bindings_update_inventory) === false) { throw new Exception('Error updating inventory.'); } } else { $inv = new Inventory(); $inv->db_id = $player_db_id; $inv->inventory = serialize($line->Inventory); if (!$inv->save()) { throw new Exception('Add inventory query failed:'); } } } //not empty inventory /* ********************************** ** Set Progress If Not Empty ** ********************************** */ if (!empty($line->Progress)) { //Check the last send for progress, see if we need to update, or make a new row $last_progress_update = Progress::where(function ($query) use($player_db_id) { $query->where('db_id', '=', $player_db_id); $query->where(DB::raw('DATE(updated_at)'), '=', $this->date_only); })->order_by('id', 'desc')->first('id'); if ($last_progress_update) { $query_update_prog = "UPDATE `progresses` SET `entry` = ?, updated_at = ? WHERE `id` = ?"; $bindings_update_progress = array(serialize($line->Progress), $this->date, $last_progress_update->id); if (DB::query($query_update_prog, $bindings_update_progress) === false) { throw new Exception('Error updating progress.'); } } else { $progress = new Progress(); $progress->db_id = $player_db_id; $progress->entry = serialize($line->Progress); if (!$progress->save()) { throw new Exception('Add progress query failed:'); } } } //not empty progress /* ********************************** ** Set Loadouts If Not Empty ** ********************************** */ if (!empty($line->Loadouts)) { $query_add_loadout = "INSERT INTO `loadouts` "; $query_add_loadout .= "(db_id, entry, created_at, updated_at) "; $query_add_loadout .= "VALUES (?, ?, ?, ?) "; $query_add_loadout .= "ON DUPLICATE KEY UPDATE "; $query_add_loadout .= "entry = ?, updated_at = ?"; $loadout_entry = serialize($line->Loadouts); $bindings = array($player_db_id, $loadout_entry, $this->date, $this->date, $loadout_entry, $this->date); if (!DB::query($query_add_loadout, $bindings)) { throw new Exception('Add loadout query failed:'); } } } catch (Exception $e) { Log::info($log_header . $e->getMessage()); file_put_contents($this->logpath . $this->logdate . '_bad_player.json', serialize($line)); } } catch (Exception $e) { Log::info($log_header . $e->getMessage()); file_put_contents($this->logpath . $this->logdate . '_bad_player.json', serialize($line)); } return Response::json(array('ThumpDumpDB', '(Player) Thanks')); }