root/dev/common/includes/class.parser.php @ 328

Revision 328, 22.1 KB (checked in by exi, 14 years ago)

Parser fix for german killmails from Haka

Line 
1<?php
2require_once("class.alliance.php");
3require_once("class.corp.php");
4require_once("class.pilot.php");
5require_once("class.kill.php");
6require_once("class.item.php");
7
8class Parser
9{
10    function Parser($killmail)
11    {
12        $this->error_ = array();
13        $this->killmail_ = trim(str_replace("\r", '', $killmail));
14        $this->returnmail = false;
15
16        if (strpos($this->killmail_, 'Beteiligte Parteien:'))
17        {
18            $this->preparse('german');
19        }
20        elseif (strpos($this->killmail_, 'System Security Level:'))
21        {
22            // this converts the killmail internally from pre-rmr to kali format
23            $this->preparse('prermr');
24        }
25
26        if (strpos($this->killmail_, '**** Truncated - mail is too large ****') > 0)
27        {
28            $this->killmail_ = str_replace('**** Truncated - mail is too large ****', '', $this->killmail_);
29        }
30
31        // Parser fix, since some killmails don't have a final blow, they would break the KB
32        if (strpos($this->killmail_, 'laid the final blow') < 1)
33        {
34            $this->needs_final_blow_ = 1;
35        }
36    }
37
38    function parse($checkauth = true)
39    {
40        // header
41        $involvedpos = strpos($this->killmail_, "Involved parties:");
42
43        $header = substr($this->killmail_, 0, $involvedpos);
44        $timestamp = substr($header, 0, 16);
45
46        if (preg_match("/Victim: (.*?)Alliance: (.*)/", $header))
47        {
48            $this->error('Found no linefeeds.');
49            return 0;
50        }
51
52        if (preg_match("/Victim: (.*)/", $header, $matches))
53        {
54            $victimname = trim($matches[1]);
55        }
56        else
57        {
58            $this->error('No victim found.');
59        }
60        if (preg_match("/Alliance: (.*)/", $header, $matches))
61        {
62            $alliancename = trim($matches[1]);
63        }
64        else
65        {
66            $this->error('No alliance found.');
67        }
68        if (preg_match("/Corp: (.*)/", $header, $matches))
69        {
70            $corpname = trim($matches[1]);
71        }
72        else
73        {
74            $this->error('No corp found.');
75        }
76        if (preg_match("/Destroyed: (.*)/", $header, $matches))
77        {
78            $shipname = trim($matches[1]);
79        }
80        else
81        {
82            $this->error('No destroyed ship found.');
83        }
84        if (preg_match("/System: (.*)/", $header, $matches))
85        {
86            $systemname = trim($matches[1]);
87        }
88        else
89        {
90            $this->error('No system found.');
91        }
92        if (preg_match("/Security: (.*)/", $header, $matches))
93        {
94            $systemsec = trim($matches[1]);
95        }
96        else
97        {
98            $this->error('No security found.');
99        }
100        $dmgtaken = false;
101        if (preg_match("/Damage Taken: (.*)/", $header, $matches))
102        {
103            $dmgtaken = trim($matches[1]);
104            $this->dmgtaken = $dmgtaken;
105        }
106        $empyrean = false;
107        if (preg_match("/Faction: (.*)/", $header, $matches))
108        {
109            $empyrean = true;
110        }
111
112        if (!isset($timestamp) ||
113                !isset($alliancename) ||
114                !isset($corpname) ||
115                !isset($victimname) ||
116                !isset($shipname) ||
117                !isset($systemname) ||
118                !isset($systemsec))
119            return 0;
120
121        if ($checkauth)
122        {
123            $authorized = false;
124        }
125        else
126        {
127            $authorized = true;
128        }
129
130        // populate/update database
131        $alliance = new Alliance();
132        $alliance->add($alliancename);
133        $corp = new Corporation();
134        $corp->add($corpname, $alliance, $timestamp);
135        $victim = new Pilot();
136        $victim->add($victimname, $corp, $timestamp);
137        $system = new SolarSystem();
138        $system->lookup($systemname);
139        if (!$system->getID())
140        {
141            $this->error('System not found.', $systemname);
142        }
143        $ship = new Ship();
144        $ship->lookup($shipname);
145        if (!$ship->getID())
146        {
147            $this->error('Ship not found.', $shipname);
148        }
149        $kill = new Kill();
150        $kill->setTimeStamp($timestamp);
151        $kill->setVictimID($victim->getID());
152        $kill->setVictimCorpID($corp->getID());
153        $kill->setVictimAllianceID($alliance->getID());
154        $kill->setVictimShip($ship);
155        $kill->setSolarSystem($system);
156        if ($dmgtaken)
157        {
158            $kill->set('dmgtaken', $dmgtaken);
159        }
160
161        if (ALLIANCE_ID != 0 && $alliance->getID() == ALLIANCE_ID)
162            $authorized = true;
163        elseif (CORP_ID != 0)
164        {
165            $corps = explode(",", CORP_ID);
166            foreach($corps as $checkcorp)
167            {
168                if ($corp->getID() == $checkcorp)
169                    $authorized = true;
170            }
171        }
172
173        // involved
174        $end = strpos($this->killmail_, "Destroyed items:");
175        if ($end == 0)
176        {
177            $end = strlen($this->killmail_);
178        }
179        $involved = explode("\n", trim(substr($this->killmail_, strpos($this->killmail_, "Involved parties:") + 17, $end - (strpos($this->killmail_, "Involved parties:") + 17))));
180
181        $i = 0;
182
183        $order = 0;
184        while ($i < count($involved))
185        {
186            if ($involved[$i] == "")
187            {
188                $i++;
189                continue;
190            }
191
192            preg_match("/Name: (.*)/", $involved[$i], $matches);
193            $ipname = $matches[1];
194
195            preg_match("/(.*) \\(laid the final blow\\)/", $ipname, $matches);
196            if ($matches[1])
197            {
198                $ipname = $matches[1];
199                $finalblow = 1;
200            }
201            else
202            {
203                $finalblow = 0;
204            }
205
206            /* This is part of the final blow fix, mentioned above */
207            if ($this->needs_final_blow_)
208            {
209                $finalblow = 1;
210                $this->needs_final_blow_ = 0;
211            }
212            /* END FIX */
213
214            preg_match("/Security: (.*)/", $involved[$i + 1], $matches);
215            $secstatus = $matches[1];
216
217            if ($secstatus == "") // NPC or POS
218            {
219                $secstatus = "0.0";
220                preg_match("/(.*) \/ (.*)/", $ipname, $pmatches);
221                $icname = $pmatches[2];
222                $isname = "Unknown";
223                $iwname = $pmatches[1];
224                if ($dmgtaken)
225                {
226                    preg_match("/Damage Done: (.*)/", $involved[++$i], $matches);
227                    $idmgdone = $matches[1];
228                }
229
230                if (!strlen($icname) && !strlen($iwname))
231                {
232                    // fucked up bclinic killmail, no person here, continue
233                    $i++;
234                    continue;
235                }
236
237                $tmpcorp = new Corporation();
238                $tmpcorp->lookup($icname);
239
240                if (!$tmpcorp->getID())
241                {
242                    // not a known corp, add it
243                    $ialliance = new Alliance();
244                    $ialliance->add('None');
245                    $icorp = new Corporation();
246                    $icorp->add($icname, $ialliance, $kill->getTimeStamp());
247                    $tmpcorp = $icorp;
248                }
249                                $iweapon = new Item();
250                                $iweapon->lookup($pmatches[1]);
251                                $ipname = '#'.$tmpcorp->getID().'#'.$iweapon->getID().'#'.$iwname;
252                $tmpall = $tmpcorp->getAlliance();
253                // name will be None if no alliance is set
254                $ianame = $tmpall->getName();
255
256                $ialliance = &$tmpall;
257                $icorp = &$tmpcorp;
258
259                $i++;
260            }
261            else
262            {
263                if ($empyrean)
264                {
265                    preg_match("/Corp: (.*)/", $involved[$i + 2], $matches);
266                    $icname = $matches[1];
267
268                    preg_match("/Alliance: (.*)/", $involved[$i + 3], $matches);
269                    $ianame = $matches[1];
270
271                    preg_match("/Ship: (.*)/", $involved[$i + 5], $matches);
272                    $isname = $matches[1];
273
274                    preg_match("/Weapon: (.*)/", $involved[$i + 6], $matches);
275                    $iwname = $matches[1];
276                    $i += 7;
277                }
278                else
279                {
280                    preg_match("/Alliance: (.*)/", $involved[$i + 2], $matches);
281                    $ianame = $matches[1];
282
283                    preg_match("/Corp: (.*)/", $involved[$i + 3], $matches);
284                    $icname = $matches[1];
285
286                    preg_match("/Ship: (.*)/", $involved[$i + 4], $matches);
287                    $isname = $matches[1];
288
289                    preg_match("/Weapon: (.*)/", $involved[$i + 5], $matches);
290                    $iwname = $matches[1];
291                    $i += 6;
292                }
293
294                if ($dmgtaken)
295                {
296                    preg_match("/Damage Done: (.*)/", $involved[$i++], $matches);
297                    $idmgdone = $matches[1];
298                }
299
300                $ialliance = new Alliance();
301                $ialliance->add($ianame);
302                $icorp = new Corporation();
303                $icorp->add($icname, $ialliance, $kill->getTimeStamp());
304            }
305
306            $ipilot = new Pilot();
307            $ipilot->add($ipname, $icorp, $timestamp);
308
309            $iship = new Ship();
310            $iship->lookup($isname);
311            if (!$iship->getID())
312            {
313                $this->error('Ship not found.', $isname);
314            }
315
316            if (!trim($iwname))
317            {
318                // set weapon to unknown in case we didn't found one
319                $iwname = 'Unknown';
320            }
321            $iweapon = new Item();
322            $iweapon->lookup($iwname);
323            if (!$iweapon->getID())
324            {
325                $this->error('Weapon not found.', $iwname);
326            }
327
328            if (ALLIANCE_ID != 0 && $ialliance->getID() == ALLIANCE_ID)
329            {
330                $authorized = true;
331            }
332            elseif (CORP_ID != 0)
333            {
334                $corps = explode(",", CORP_ID);
335                foreach($corps as $corp)
336                {
337                    if ($icorp->getID() == $corp)
338                        $authorized = true;
339                }
340            }
341            if (!$authorized)
342            {
343                if ($string = config::get('post_permission'))
344                {
345                    if ($string == 'all')
346                    {
347                        $authorized = true;
348                    }
349                    else
350                    {
351                        $tmp = explode(',', $string);
352                        foreach ($tmp as $item)
353                        {
354                            if (!$item)
355                            {
356                                continue;
357                            }
358                            $typ = substr($item, 0, 1);
359                            $id = substr($item, 1);
360                            if ($typ == 'a')
361                            {
362                                if ($ialliance->getID() == $id || $kill->getVictimAllianceID() == $id)
363                                {
364                                    $authorized = true;
365                                    break;
366                                }
367                            }
368                            elseif ($typ == 'c')
369                            {
370                                if ($icorp->getID() == $id || $kill->getVictimCorpID() == $id)
371                                {
372                                    $authorized = true;
373                                    break;
374                                }
375                            }
376                            elseif ($typ == 'p')
377                            {
378                                if ($ipilot->getID() == $id || $kill->getVictimID() == $id)
379                                {
380                                    $authorized = true;
381                                    break;
382                                }
383                            }
384                        }
385                    }
386                }
387            }
388
389            $iparty = new InvolvedParty($ipilot->getID(), $icorp->getID(),
390                $ialliance->getID(), $secstatus, $iship, $iweapon);
391            if ($dmgtaken)
392            {
393                $iparty->dmgdone_ = $idmgdone;
394            }
395            $kill->addInvolvedParty($iparty);
396
397            if ($finalblow == 1)
398            {
399                $kill->setFBPilotID($ipilot->getID());
400                $kill->setFBCorpID($icorp->getID());
401                $kill->setFBAllianceID($ialliance->getID());
402            }
403        }
404
405        // destroyed items
406        $destroyedpos = strpos($this->killmail_, "Destroyed items:");
407
408        if ($destroyedpos)
409        {
410            $endpos = strlen($this->killmail_) - $destroyedpos + 16;
411            if ($dmgtaken)
412            {
413                $pos = strpos($this->killmail_, "Dropped items:");
414                if ($pos === false)
415                {
416                    $pos = strlen($this->killmail_);
417                }
418                $endpos = $pos - $destroyedpos - 16;
419            }
420
421            $destroyed = explode("\n", trim(substr($this->killmail_, $destroyedpos + 16, $endpos)));
422            #var_dump($destroyed); exit;
423            $destroyed_items = $this->scanForItems($destroyed);
424            foreach ($destroyed_items as $item)
425            {
426                $ditem = new DestroyedItem($item['item'], $item['quantity'], $item['location']);
427                $kill->addDestroyedItem($ditem);
428            }
429        }
430        if ($dmgtaken)
431        {
432            $startpos = strpos($this->killmail_, "Dropped items:");
433            if ($startpos)
434            {
435                $endpos = strlen($this->killmail_) - $startpos + 14;
436
437                $dropped = explode("\n", trim(substr($this->killmail_, $startpos + 14, $endpos)));
438                #var_dump($dropped); exit;
439
440                $dropped_items = $this->scanForItems($dropped);
441                foreach ($dropped_items as $item)
442                {
443                    $ditem = new DroppedItem($item['item'], $item['quantity'], $item['location']);
444                    $kill->addDroppedItem($ditem);
445                }
446            }
447        }
448
449        if (!$authorized)
450        {
451            return -2;
452        }
453        if ($this->getError())
454        {
455            return 0;
456        }
457
458        if ($this->returnmail)
459        {
460            return $kill;
461        }
462        $id = $kill->add();
463        if ($id == -1)
464        {
465            $this->dupeid_ = $kill->dupeid_;
466        }
467
468        return $id;
469    }
470
471    function scanForItems($destroyed)
472    {
473        $i = 0;
474        $num = count($destroyed);
475        while ($i < $num)
476        {
477            $destroyed[$i] = trim($destroyed[$i]);
478            if ($destroyed[$i] == "")
479            {
480                $i++;
481                continue;
482            }
483
484            if ($destroyed[$i] == "Empty.")
485            {
486                $container = false;
487                $i++;
488                continue;
489            }
490
491            $qtypos = 0;
492            $locpos = 0;
493            $itemname = "";
494            $quantity = "";
495            $location = "";
496
497            $qtypos = strpos($destroyed[$i], ", Qty: ");
498            $locpos = strrpos($destroyed[$i], "(");
499
500            if ($container && $locpos != false)
501            {
502                $container = false;
503            }
504            if (strpos($destroyed[$i], "Container"))
505            {
506                $container = true;
507            }
508            if ($qtypos <= 0 && !$locpos)
509            {
510                $itemlen = strlen($destroyed[$i]);
511                if ($container) $location = "Cargo";
512            }
513            if ($qtypos > 0 && !$locpos)
514            {
515                $itemlen = $qtypos;
516                $qtylen = strlen($destroyed[$i]) - $qtypos;
517                if ($container) $location = "Cargo";
518            }
519            if ($locpos > 0 && $qtypos <= 0)
520            {
521                $itemlen = $locpos - 1;
522                $qtylen = 0;
523                $loclen = strlen($destroyed[$i]) - $locpos - 2;
524                if (!$locpos) $container = false;
525            }
526            if ($locpos > 0 && $qtypos > 0)
527            {
528                $itemlen = $qtypos;
529                $qtylen = $locpos - $qtypos - 7;
530                $loclen = strlen($destroyed[$i]) - $locpos - 2;
531                if (!$locpos) $container = false;
532            }
533
534            $itemname = substr($destroyed[$i], 0, $itemlen);
535            if ($qtypos) $quantity = substr($destroyed[$i], $qtypos + 6, $qtylen);
536            if ($locpos) $location = substr($destroyed[$i], $locpos + 1, $loclen);
537
538            if ($quantity == "")
539            {
540                $quantity = 1;
541            }
542
543            $item = new Item();
544            $item->lookup(trim($itemname));
545            if (!$item->getID())
546            {
547                $this->error('Item not found.', trim($itemname));
548            }
549            if ($location == 'In Container')
550            {
551                $location = 'Cargo';
552            }
553
554            $items[] = array('item' => $item, 'quantity' => $quantity, 'location' => $location);
555            $i++;
556        }
557
558        return $items;
559    }
560
561    function error($message, $debugtext = null)
562    {
563        $this->error_[] = array($message, $debugtext);
564    }
565
566    function getError()
567    {
568        if (count($this->error_))
569        {
570            return $this->error_;
571        }
572        return false;
573    }
574
575    function preparse($set)
576    {
577        if ($set == 'german')
578        {
579            $this->killmail_ = str_replace(array(chr(195).chr(182), chr(195).chr(164)), array(chr(246), chr(228)), $this->killmail_);
580
581            $search = array('Ziel:', 'Allianz: KEINE', 'Allianz: keine', 'Allianz: Keine', 'Allianz:',
582                            'Allianz: NICHTS', 'Allianz: nichts', 'Allianz: Nichts',
583                            'Fraktion: KEINE','Fraktion: keine','Fraktion: Keine',
584                            'Zerst'.chr(246).'rte Gegenst'.chr(228).'nde', 'Zerst'.chr(246).'rt:', 'Sicherheit:',
585                            'Beteiligte Parteien:','Anz:','Corporation:','(Fracht)', 'Schiff:','Waffe:','(Im Container)',
586                            'Verursachter Schaden:','Erlittener Schaden:', '(gab den letzten Schuss ab)',
587                            'Hinterlassene Gegenst'.chr(228).'nde:', 'Anz.:', 'Unbekannt', 'Dronenhangar', 'Drohnenhangar');
588           
589            $replace = array('Victim:','Alliance: None','Alliance: None','Alliance: None','Alliance:',
590                             'Alliance: None','Alliance: None','Alliance: None',
591                             'Faction: NONE','Faction: NONE','Faction: NONE',
592                             'Destroyed items','Destroyed:', 'Security:',
593                             'Involved parties:', 'Qty:', 'Corp:', '(Cargo)', 'Ship:', 'Weapon:','(In Container)',
594                             'Damage Done:', 'Damage Taken:', '(laid the final blow)',
595                             'Dropped items:', 'Qty:', 'Unknown', 'Drone Bay', 'Drone Bay');
596
597            //if (strpos($this->killmail, chr(246)) === false)
598            //{
599            //    $this->killmail_ = utf8_decode($this->killmail_);
600            //}
601            $this->killmail_ = str_replace($search, $replace, $this->killmail_);
602            return;
603        }
604        if ($set == 'prermr')
605        {
606            $search = array('Corporation:','Destroyed Type:','Solar System:', 'System Security Level:', 'Security Status:', 'Ship Type:', 'Weapon Type:', '(Fitted - Medium slot)', '(Fitted - Low slot)', '(Fitted - High slot)');
607            $replace = array('Corp:','Destroyed:', 'System:', 'Security:', 'Security:', 'Ship:', 'Weapon:', '', '', '');
608            $this->killmail_ = str_replace($search, $replace, $this->killmail_);
609            $position = strpos($this->killmail_, 'Destroyed items:');
610            if ($position !== false)
611            {
612                $destroyed = explode("\n", strstr($this->killmail_, 'Destroyed items:'));
613                $i = 0;
614                $num = count($destroyed);
615                while ($i < $num)
616                {
617                    $destroyed[$i] = trim($destroyed[$i]);
618
619                    $itempos = strpos($destroyed[$i], 'Type: ');
620                    if ($itempos !== false)
621                    {
622                        $destroyed[$i] = substr($destroyed[$i], $itempos+6);
623                        if (isset($destroyed[$i+1]))
624                        {
625                            $quantitypos = strstr($destroyed[$i+1], 'Quantity: ');
626                            if ($quantitypos !== false)
627                            {
628                                $qty = ', Qty: '.substr($destroyed[$i+1], $quantitypos+10);
629                                $pos = strpos($destroyed[$i], '(');
630                                if ($pos !== false)
631                                {
632                                    $destroyed[$i] = trim(substr($destroyed[$i], 0, $pos)).$qty.' '.substr($destroyed[$i], $pos);
633                                }
634                                else
635                                {
636                                    $destroyed[$i] .= $qty;
637                                }
638                                unset($destroyed[$i+1]);
639                                $i++;
640                            }
641                        }
642                    }
643                    else
644                    {
645                        unset($destroyed[$i]);
646                    }
647                    $i++;
648                }
649                $this->killmail_ = substr($this->killmail_, 0, $position).'Destroyed items: '."\n\n\n".join("\n", $destroyed)."\n";
650            }
651        }
652    }
653}
654?>
Note: See TracBrowser for help on using the browser.