function parse($checkauth = true) { $qry = DBFactory::getDBQuery(); $timestamp = substr($this->killmail_, 0, 16); $timestamp = str_replace('.', '-', $timestamp); //trim out any multiple spaces that may exist - //$this->killmail_ = preg_replace('/ +/', ' ', $this->killmail_); // header section $involvedpos = strpos($this->killmail_, "Involved parties:"); if ($involvedpos == 0) { $this->error("Mail lacks Involved parties header."); return 0; } $header = substr($this->killmail_, 0, $involvedpos); $timestamp = substr($header, 0, 16); $victim = explode("\n", trim(substr($this->killmail_, 0, $involvedpos))); $upper_limit = count($victim); $victimname = "Unknown"; //lovely default values $factionname = "None"; $alliancename = "None"; $corpname = "Unknown"; $shipname = "Unknown"; $systemname = "Unknown"; $systemsec = "0.0"; $dmgtaken = '0'; $this->dmgtaken = '0'; $pos = 0; $moon = ""; for ($counter = 0; $counter <= $upper_limit; $counter++) { if (preg_match("/Victim: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { $victimname = $matches[1]; } } elseif (preg_match("/Corp: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { $corpname = $matches[1]; } } elseif (preg_match("/Alliance: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { $alliancename = $matches[1]; } if ($alliancename == "Unknown") { $alliancename = "None"; } } elseif (preg_match("/Faction: (.*)/", $victim[$counter], $matches)) { if (strlen($matches[1]) > 5 && $matches[1] != "Unknown") { //catches faction mails from -A- $factionname = $matches[1]; } else { $factionname = "None"; } } elseif (preg_match("/Destroyed: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { $shipname = $matches[1]; } } elseif (preg_match("/System: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { //bad assumption here - moon has to come before security. $systemname = $matches[1]; if (strcmp($moon, 'Unknown') == 0 && $pos == 1) { $moon = $matches[1]; $victimname = $matches[1]; } } } elseif (preg_match("/Security: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { $systemsec = (double) $matches[1]; } } elseif (preg_match("/Damage Taken: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { $dmgtaken = (int) $matches[1]; $this->dmgtaken = $dmgtaken; } } elseif (preg_match("/Moon: (.*)/", $victim[$counter], $matches)) { if ($matches[1]) { $moon = $matches[1]; $victimname = $matches[1]; $pos = 1; } else { //if the system is valid, it will pick this up, provided it features after //the moon is listed - which is unlikely unless the mail format //drastically changes... again :) $moon = 'Unknown'; $victimname = 'Unknown'; $pos = 1; } } } //faction warfare stuff if (strcasecmp($alliancename, 'None') == 0) { $alliancename = $factionname; } //report the errors for the things that make sense. //we need pilot names, corp names, ship types, and the system to be sure //the rest aren't required but for completeness, you'd want them in :) // Customs Offices don't have names. Hack a fix in by accepting mails with // no victim name but that do have a system. if (strcmp($victimname, 'Unknown') == 0) { if (strcmp($systemname, 'Unknown') == 0) { $this->error('Victim has no name.'); unset($victimname); //we unset the variable so that it fails the next check $this->error('Killmail lacks solar system information.'); unset($systemname); } else { $victimname = $systemname; } } if (strcmp($corpname, 'Unknown') == 0) { $this->error('Victim has no corp.'); unset($corpname); } if (strcmp($shipname, 'Unknown') == 0) { $this->error('Victim has no ship type.'); unset($shipname); } if (strcmp($systemname, 'Unknown') == 0) { $this->error('Killmail lacks solar system information.'); unset($systemname); } if ($pos == 1) { $victimname = $moon; } if (!isset($timestamp) || !isset($factionname) || !isset($alliancename) || !isset($corpname) || !isset($victimname) || !isset($shipname) || !isset($systemname) || !isset($systemsec)) { return 0; } if ($checkauth) { $authorized = false; } else { $authorized = true; } // populate/update database $alliance = $this->fetchAlliance($alliancename); $corp = $this->fetchCorp($corpname, $alliance, $timestamp); $victim = $this->fetchPilot($victimname, $corp, $timestamp); $system = SolarSystem::lookup($systemname); if (!$system || !$system->getID()) { $this->error('System not found.', $systemname); $system = new SolarSystem(); } $ship = Ship::lookup($shipname); if (!$ship || !$ship->getID()) { $this->error('Ship not found.', $shipname); $ship = new Ship(); } $kill = new Kill(); if ($this->externalID) { $kill->setExternalID($this->externalID); } $kill->setTimeStamp($timestamp); $kill->setVictim($victim); $kill->setVictimID($victim->getID()); $kill->setVictimCorpID($corp->getID()); $kill->setVictimAllianceID($alliance->getID()); $kill->setVictimShip($ship); $kill->setSolarSystem($system); if ($dmgtaken) { $kill->set('dmgtaken', $dmgtaken); } if (config::get('cfg_allianceid') && in_array($alliance->getID(), config::get('cfg_allianceid'))) { $authorized = true; } elseif (config::get('cfg_corpid') && in_array($corp->getID(), config::get('cfg_corpid'))) { $authorized = true; } elseif (config::get('cfg_pilotid') && in_array($victim->getID(), config::get('cfg_pilotid'))) { $authorized = true; } // involved parties section $end = strpos($this->killmail_, "Destroyed items:"); if ($end == 0) { $end = strpos($this->killmail_, "Dropped items:"); if ($end == 0) { //try to parse to the end of the mail in the event sections are missing $end = strlen($this->killmail_); } } $involved = explode("\n", trim(substr($this->killmail_, strpos($this->killmail_, "Involved parties:") + 17, $end - (strpos($this->killmail_, "Involved parties:") + 17)))); $ipilot_count = 0; //allows us to be a bit more specific when errors strike $i = 0; $topdamage = 0; $order = 0; while ($i < count($involved)) { $iparts = count($involved); $finalblow = 0; while ($i < $iparts) { $ipilot_count++; $ipname = "Unknown"; $ianame = "None"; $ifname = "None"; $icname = "None"; $isname = "Unknown"; $iwname = "Unknown"; $idmgdone = '0'; $secstatus = "0.0"; while ($involved[$i] == '') { //compensates for multiple blank lines between involved parties $i++; if ($i > count($involved)) { $this->error("Involved parties section prematurely ends."); return 0; } } for ($counter = $i; $counter <= $iparts; $counter++) { if (preg_match("/Name: (.*)/", $involved[$counter], $matches)) { if ($matches[1]) { if (stristr($involved[$counter], '/')) { $slash = strpos($involved[$counter], '/'); $name = trim(substr($involved[$counter], 5, $slash - 5)); $corporation = trim(substr($involved[$counter], $slash + 1, strlen($involved[$counter]) - $slash + 1)); //now if the corp bit has final blow info, note it preg_match("/(.*) \\(laid the final blow\\)/", $corporation, $matched); if ($matched[1]) { $finalblow = 1; $iwname = $name; $end = strpos($corporation, '(') - 1; $corporation = substr($corporation, 0, $end); } else { $finalblow = 0; $iwname = $name; } //alliance lookup for warp disruptors - normal NPCs aren't to be bundled in $crp = $this->fetchCorp($corporation); if ($crp && $crp->getExternalID(true) > 0) { if ($crp->fetchCorp()) { $al = $crp->getAlliance(); $alName = $al->getName(); if (trim($alName) != "") { $ianame = $al->getName(); } } // else check db for kills with that corp at the same time? } $ipname = $name; $icname = $corporation; } else { $ipname = $matches[1]; preg_match("/(.*)\\s*\\(laid the final blow\\)/", $ipname, $matches); if (isset($matches[1])) { $ipname = trim($matches[1]); $finalblow = 1; } else { $finalblow = 0; } } } } else { if (preg_match("/Alliance: (.*)/", $involved[$counter], $matches)) { if ($matches[1]) { $ianame = $matches[1]; } if ($ianame == "Unknown") { $ianame = "None"; } } else { if (preg_match("/Faction: (.*)/", $involved[$counter], $matches)) { if (strlen($matches[1]) > 5 && $matches[1] != "Unknown") { //catches faction mails from -A- $ifname = $matches[1]; } else { $ifname = "NONE"; } } else { if (preg_match("/Corp: (.*)/", $involved[$counter], $matches)) { if ($matches[1]) { $icname = $matches[1]; } } else { if (preg_match("/Ship: (.*)/", $involved[$counter], $matches)) { if ($matches[1]) { $isname = $matches[1]; } } else { if (preg_match("/Weapon: (.*)/", $involved[$counter], $matches)) { if ($matches[1]) { $iwname = $matches[1]; } } else { if (preg_match("/Security: (.*)/", $involved[$counter], $matches)) { if ($matches[1]) { $secstatus = (double) $matches[1]; } } else { if (preg_match("/Damage Done: (.*)/", $involved[$counter], $matches)) { if ($matches[1]) { $idmgdone = (int) $matches[1]; } if ($idmgdone > $topdamage) { $topdamage = $idmgdone; } } else { if ($involved[$counter] == '') { //allows us to process the involved party. This is the empty line after the //involved party section $counter++; $i = $counter; break; } else { //skip over this entry, it could read anything, we don't care. Handy if/when //new mail fields get added and we aren't handling them yet. $counter++; $i = $counter; } } } } } } } } } if ($this->needs_final_blow_) { $finalblow = 1; $this->needs_final_blow_ = 0; } } // Faction Warfare stuff if (strcasecmp($ianame, "None") == 0) { $ianame = $ifname; } // end faction warfare stuff $ialliance = $this->fetchAlliance($ianame); if (strcmp($icname, 'None') == 0) { //don't add corp, because pilots have to be in corps. $this->error('Involved party has no corp. (Party No. ' . $ipilot_count . ')'); $icorp = new Corporation(); } else { $icorp = $this->fetchCorp($icname, $ialliance, $kill->getTimeStamp()); } if (preg_match("/^(Mobile \\w+ Warp|\\w+ Control Tower( \\w+)?)/", $iwname)) { //for involved parties parsed that lack a pilot, but are actually POS or mobile warp disruptors $ipname = $icname . ' - ' . $iwname; $ipilot = $this->fetchPilot($ipname, $icorp, $timestamp); } elseif (strcmp($ipname, 'Unknown') == 0 || empty($ipname)) { $ipilot = new Pilot(); $this->error('Involved party has no name. (Party No. ' . $ipilot_count . ')'); } else { //don't add pilot if the pilot's unknown or dud $ipilot = $this->fetchPilot($ipname, $icorp, $timestamp); } $iship = Ship::lookup($isname); if (!$iship || !$iship->getName()) { $this->error('Ship not found.', $isname); } if (strcmp($iwname, 'Unknown') == 0 && $iship && $iship->getID()) { $iwname = $iship->getName(); } $iweapon = Item::lookup($iwname); if (strcmp($iwname, 'Unknown') == 0) { $this->error('No weapon found for pilot "' . $ipname . '"'); $iweapon = new Item(); } else { if (!$iweapon || !$iweapon->getID()) { $this->error('Weapon not found.', $iwname); $iweapon = new Item(); } } if (config::get('cfg_allianceid') && in_array($ialliance->getID(), config::get('cfg_allianceid'))) { $authorized = true; } elseif (config::get('cfg_corpid') && in_array($icorp->getID(), config::get('cfg_corpid'))) { $authorized = true; } elseif (config::get('cfg_pilotid') && in_array($ipilot->getID(), config::get('cfg_pilotid'))) { $authorized = true; } if (!$authorized) { if ($string = config::get('post_permission')) { if ($string == 'all') { $authorized = true; } else { $tmp = explode(',', $string); foreach ($tmp as $item) { if (!$item) { continue; } $typ = substr($item, 0, 1); $id = substr($item, 1); if ($typ == 'a') { if ($ialliance->getID() == $id || $kill->getVictimAllianceID() == $id) { $authorized = true; break; } } elseif ($typ == 'c') { if ($icorp->getID() == $id || $kill->getVictimCorpID() == $id) { $authorized = true; break; } } elseif ($typ == 'p') { if ($ipilot->getID() == $id || $kill->getVictimID() == $id) { $authorized = true; break; } } } } } } $iparty = new InvolvedParty($ipilot->getID(), $icorp->getID(), $ialliance->getID(), $secstatus, $iship->getID(), $iweapon->getID(), $idmgdone); $kill->addInvolvedParty($iparty); if ($finalblow == 1) { $kill->setFBPilotID($ipilot->getID()); $kill->setFBCorpID($icorp->getID()); $kill->setFBAllianceID($ialliance->getID()); } if ($topdamage == $idmgdone) { $kill->setTDPilotID($ipilot->getID()); $kill->setFBCorpID($icorp->getID()); $kill->setFBAllianceID($ialliance->getID()); } } } // Duplicate check does not use items so it's safe to check now if ($id = $kill->getDupe()) { $this->dupeid_ = $id; if ($this->dupeid_ > 0 && $this->externalID) { //if this is a duplicate and we have an external id then update the existing kill $qry->execute("UPDATE kb3_kills SET kll_external_id = " . $this->externalID . " WHERE kll_id = " . $this->dupeid_); $qry->execute("UPDATE kb3_mails SET kll_external_id = " . $this->externalID . ", kll_modified_time = UTC_TIMESTAMP() " . "WHERE kll_id = " . $this->dupeid_ . " AND kll_external_id IS NULL"); } return -1; } // destroyed items section $destroyedpos = strpos($this->killmail_, "Destroyed items:"); if ($destroyedpos) { $endpos = strlen($this->killmail_) - $destroyedpos + 16; $pos = strpos($this->killmail_, "Dropped items:"); if ($pos === false) { $pos = strlen($this->killmail_); } $endpos = $pos - $destroyedpos - 16; $destroyed = explode("\n", trim(substr($this->killmail_, $destroyedpos + 16, $endpos))); $destroyed_items = $this->scanForItems($destroyed); foreach ($destroyed_items as $item) { $ditem = new DestroyedItem($item['item'], $item['quantity'], '', $item['location'], true); $kill->addDestroyedItem($ditem); } } $startpos = strpos($this->killmail_, "Dropped items:"); if ($startpos) { $endpos = strlen($this->killmail_) - $startpos + 14; $dropped = explode("\n", trim(substr($this->killmail_, $startpos + 14, $endpos))); $dropped_items = $this->scanForItems($dropped); foreach ($dropped_items as $item) { $ditem = new DestroyedItem($item['item'], $item['quantity'], '', $item['location'], true); $kill->addDroppedItem($ditem); } } if (!$authorized) { return -2; } if ($this->getError()) { return 0; } if ($this->returnmail) { return $kill; } $id = $kill->add(); if ($id == -2) { $this->error("An error has occurred. Please try again later."); $id = 0; } return $id; }