Mailinhalte fischen mit PHP und Javascript

tempa wrote this 20:55:

Ich programmiere noch für den kleinen Hausgebrauch und was da so zusammenkommt, das kann man teilweise hier zum gefälligen Gebrauch oder Nichtbeachtung wiederfinden. ES dient auch mir als Erinnerungstütze.

z.B. sollte ich nicht vergessen die Methode <form action="?" method="post"> anzugeben. Wenn ich auf $_SERVER[php_self] von wegen dem XSS-Exploit das heutzutage nicht mehr bei allen Servern geht und damit ist $_SERVER[php_self] nicht mehr generell böse … wie auch immer geht eben auch ohne.

  1. <?php $m = isset($_POST[m]) ? intval($_POST[m]) : 1 ; ?>
  2. <form action="?" method="post">
  3. <input type="text"
  4. value="<?php echo $m; ?>" name="m" id="m"
  5. style="width: 4em;"
  6. onfocus="this.value=''"
  7. onChange="this.value= isNaN(this.value)? 1 : parseInt(parseFloat(this.value))"
  8. onBlur="this.value= isNaN(this.value)? 1 : parseInt(parseFloat(this.value))"/>
  9. <input type="submit" value="go" class="button" />
  10. </form>

Es wird per Javascript schon dafür gesorgt, dass in das Formularfeld nur Ganzzahlen dürfen, nur Javascript kann leicht abgeschaltet werden oder im Browser überabeitet werden, ergo wird die Eingabe selbstredend auch in PHP noch einmal überprüft und überarbeitet bzw mit dem Defaultwert ersetzt. OK im PHP war ich noch etwas Faul. Schließlich müsste ich auch dort prüfen mit PHP is_float() prüfen statt mit PHP isset() seltsamer Weise aber scheint hier das Ergebnis immer false zu sein und der Default wird gewählt.

Dass die Werte in Javascript neben parseInt (= runde auf Ganzzahl ab) zunächst noch mit parseFloat (= behandle Wert als Zahl) bearbeitet wird liegt daran, dass bei der Suche nach der Javascript-Syntax für PHP intval() und Co mir die folgenden beiden Links begegneten:

  1. javascript parseInt is broken
  2. JavaScript parseInt() bug

A propos XSS. Da ist mir auch das Mantra „Never trust User-Input“ begegnet das ausfürlich ungefähr so lautet:

Most developers worth their paycheque, I’m sure, know the common rules of „never trust the user“, such as „escape all user-supplied data on output,“ „always validate user input,“ and „don’t rely on something not in your control to do so (ie. Javascript cannot be trusted).“ „Don’t output unescaped input“ goes without saying, in most cases. Only a fool would „echo $_GET[‚param‘];“ (and we’re all foolish sometimes, aren’t we?).

Copy&paste für diesen Beitrag von XSS-Woes

Das Snippet wird bei mir dafür genutzt eine Mail aus einem Ordner meines Mailprogramms zu fischen und auszuwerten. Ich verate nun nicht welches Programm ich verwende, nur soviel es geht problemlos mit Sypheed und Thunderbird. Wer Outlook im Einsatz hat, findet hier Hilfe zu den Pfaden: Speicherorte von Outlook-Dateien

.

  1. $dir = "[Laufwerk]:Dokumente und Einstellungen[Benutzer]Lokale EinstellungenAnwendungsdaten[Hersteller Mailprogramm][Mailordner]";
    // Pfad zum Speicherort der Mails
  2. $files = glob(utf8_decode($dir).'*');
    // Datei in UTF-8 gespeichert
  3. //$files = glob($dir.'*');
    // Wenn datei in Ansi gespeichert ist
  4. usort($files, create_function('$a,$b', 'return filemtime($a) - filemtime($b);'));
    // Mails nach Datum sortiert
  5. $MailsCount = count($files);
    // Alle Mails im Ordner zählen
  6. $c = $MailsCount-$m;
    \ Mail $m von hinten
  7. $string = file_get_contents($files[$c]);
    // Inhalt der Mail mit der Index-Nummer xy fischen gehen

Zur Auswertung der Mail sind die folgenden Code-Schnipsel sehr hilfreich:

  1. //Singleline – Zeichenfolge bis Zeilenende

    preg_match_all('/(?<=Zeichenfolge)(.){0,}/',$string,$out[$k], PREG_OFFSET_CAPTURE);
  2. //Multiline - Zeichenfolge 1 bis Zeichenfolge 2

    preg_match('/Zeichenfolge1(.*)Zeichenfolge2/msU',$string,$out);
  3. //Leere Zeilen löschen:

    $string = preg_replace("/(^[rn]*|[rn]+)[st]*[rn]+/", "n", $string);

Meine preg_match-Meriten holte ich mir von hier: PHP-Regex Blogspot

So das war es auch schon ... das heißt, weiß jemand wie man bei einer Serie von preg_match_all über die String-Position die Arrays so zusammen mischt, dass die Werte korrekt zugeordnet werden können?

  1. //FILTER WERTE AUS MAIL UND SCHREIBE IN ARRAY
    for($k=0;$k<=6;$k++){
  2. $werte[$k] = preg_match_all('/(?<='.$trenner[$k].')(.){0,}/',$string,$out[$k], PREG_OFFSET_CAPTURE);
  3. array_pop($out[$k]);
    /*AUSGABE IN ARRAY:
    [0] Bestellung [0]=> [0] wert [1] strpos
    [1] Anzahl [0]=> [0] wert [1] strpos
    [2] Preis [0]=> [0] wert [1] strpos
    [3] Produkt-Bezeichnung-Typ1 [0]=> [0] wert [1] strpos
    [4] Produkt-ID-Typ1 [0]=> [0] wert [1] strpos
    [5] Produkt-Bezeichnung-Typ2 [0]=> [0] wert [1] strpos
    [6] Produkt-ID-Typ2 [0]=> [0] wert [1] strpos
    [7] ...-Typ3 ...etc.
    */
  4. }

Das coole daran ist, dass die mit einer Zeile Zappzerapp die Mail ausgewertet ist. Das Dumme ist, nur über den nummerischen Wert der String-Position sind die Bestellungen den Produkttypen zuzuordnen und da hatte ich bislang einen Knoten im Hirn. Zur Klarstellung alle Bestellungen die zwischen dem strpos-Wert von Produkt Index1 und Produkt Index2 (sprich: Prod1-strpos < Bestell-strpos > Prod2-strpos) ... sieht einfach genug aus, aber in der Umsetzung ist das mir aktuell noch zu hoch. Für alle die das interessiert, hier das Ganze noch einmal mit ein paar Beispieldaten.

  1. <?php
  2. 
    $date = "Date: Fri, 25 Mar 2010 04:42:52 +0000 (UTC)";
    
    $string = <<<STRING
    Du hast heute auf dem Marktplatz Folgendes verkauft:
    
    Frischwarename: Äpfel (Kg)
    Frischware-ID: 7246899
    
    Bestellnummer: 2437838-2525661
    Anzahl: 1
    Einzelprovision: 2.45 €
    
    Bestellnummer: 2437838-2525661
    Anzahl: 1
    Einzelprovision: 2,45 €Bestellnummer: 2437838-2525661
    
    Anzahl: 3
    Einzelprovision: 2,45 €
    
    Frischware: Orangen (Kg)
    Frischware-ID: 5930826
    
    Bestellnummer: 2446464-2534439
    Anzahl: 1
    Einzelprovision: 2,45 €
    
    Frischwarename: Birnen (Kg)
    Frischware-ID: 10115488
    
    Bestellnummer: 2441306-2529176
    Anzahl: 1
    Einzelprovision: 2,45 EUR
    
    Kühlware: Frischkäse (Kg)
    Kühlware-ID: 16739414-11401126
    
    Bestellnummer: 2445140-2533086
    Anzahl: 1
    Einzelprovision: 2,45 €
    
    Kühlware: Schimmelkäse (Kg)
    Kühlware-ID: 15054156-10369264
    
    Bestellnummer: 2446425-2534400
    Anzahl: 1
    Einzelprovision: 2,45 €
    
    Kühlware: Butter (Kg)
    Kühlware-ID: 16739414-11401126
    
    Bestellnummer: 2445140-2533086
    Anzahl: 1
    Einzelprovision: 2,45 €
    
    Kühlware: Streichwurst (Kg)
    Kühlware-ID: 15054156-10369264
    
    Bestellnummer: 2446425-2534400
    Anzahl: 1
    Einzelprovision: 2,45 €
    STRING;
    
    $trenner = array(
    "0" => "Bestellnummer: ",
    "1" => "Anzahl: ",
    "2" => "Einzelprovision: ",
    "3" => "Frischwarename: ",
    "4" => "Frischware-ID: ",
    "5" => "Kühlware: ",
    "6" => "Kühlware-ID: ");
     
  3. //FILTER WERTE AUS MAIL UND SCHREIBE IN ARRAY
    for($k=0;$k<=6;$k++){
  4. $werte[$k] = preg_match_all('/(?<='.$trenner[$k].')(.){0,}/',$string,$out[$k], PREG_OFFSET_CAPTURE);
  5. array_pop($out[$k]);
    /*AUSGABE IN ARRAY:
    [0] Bestellung [0]=> [0] wert [1] strpos
    [1] Anzahl [0]=> [0] wert [1] strpos
    [2] Preis [0]=> [0] wert [1] strpos
    [3] Produkt-Bezeichnung-Typ1 [0]=> [0] wert [1] strpos
    [4] Produkt-ID-Typ1 [0]=> [0] wert [1] strpos
    [5] Produkt-Bezeichnung-Typ2 [0]=> [0] wert [1] strpos
    [6] Produkt-ID-Typ2 [0]=> [0] wert [1] strpos
    [7] ...-Typ3 ...etc.
    */
  6. }
  7. echo "<pre>n";
  8. var_dump($out);
  9. echo "n</pre>"; ?>

So ich hoffe, ich konnte dem einen oder anderen nun helfen seine Mail auszuwerten und wer weiß, vieleicht kommt ja auch noch zur kleinen Kniffelaufgabe mit dem Umsortieren des Arrays bzw. einem hilfreichen Index zur Zuordnung der Bestellungen zu den Waren. BTW. Ich habe eine Lösung die mit preg_match(), strpos() und substr() den String unterteilt und den Array Abschnittsweise schreibt schon entsprechend zugeordnet.

Gesucht ist wirklich die Weiterverarbeitung des Arrays, der sich ergibt durch die For-Schleife mit preg_match_all(). Natürlich sind auch Weise Worte zur Performance willkommen, sollte hier preg_match_all() eine echte Performance-Wutz sein. Ich finde an der Lösung vor allem die Kürze und Einfachheit im Code cool.

Leave a Reply