Jörg Reinholz: Das Skript zum Montag - Blocklist.de befragen

Moin!

Blocklist.de bietet eine nette Möglichkeit, von anderen bereits erkannte Angreifer via DNS über deren IP zu identifizieren.

Diese Hosts sind oft geknackte Webserver oder mit Viren infiziert und dienen Angreifern für recht multible Zwecke. Man möchte diese deshalb vielleicht bei sicherheitskritischen Anwendungen (wie z.B. einem Login) draußen halten....

Hier eine API für die DNS-Abfrage, die das Ergebnis JSON-codiert zurückwirft:

<?php
ini_set('display_errors', 0);
define('nslookup_exe',  '/usr/bin/nslookup');
define('host_exe',      '/usr/bin/host');

//Test:
if ( empty($_REQUEST['ip'])) {
    header("Content-Type: text/plain; charset=UTF-8");
    $ips[]='82.48.1.197';
    $ips[]='1.2.3.4';
    #$method='PHP'; # use dns_get_record
    #$method='nslookup';
    $method='host';
    $line="\n=========================================\n";

    foreach ( $ips as $ip ) {
        echo $line, "Ergebnis für ", $ip, " mit ", $method, $line;
        echo json_encode(ask_blocklist_de($ip, $method), JSON_PRETTY_PRINT);
    }
    exit;
}
// Ende Test

if ( empty($_REQUEST['method'])) {
    $_REQUEST['method'] = 'HOST';
}

$_REQUEST['method']=strtoupper($_REQUEST['method']);
if (
    $_REQUEST['method'] != 'PHP'
    && $_REQUEST['method'] != 'NSLOOKUP'
    && $_REQUEST['method'] != 'HOST'
    ) {
    $_REQUEST['method'] = 'HOST';
}

$return=ask_blocklist_de(trim($_REQUEST['ip']), $method);
if ( $return['error_type'] == 'FATAL' ) {
    header('Status: 500 ');
    echo $return['error_string'];
    exit;
}
header("Content-Type: text/plain; charset=UTF-8");
if (! $return['found']) {
    header('Status: 404');
} else {
    header('Status: 200');
}
echo  json_encode($return, JSON_PRETTY_PRINT);
exit;


function ask_blocklist_de($ip, $method='HOST') {
    $return['Hint']             = 'Dies ist ein Test! Um eine stabile API zu erhalten fragen Sie beim Autor nach (www.fastix.org)';
    $return['error_type']       = FALSE;
    $return['error_number']     = 0;
    $return['error_string']     = FALSE;
    $return['found']            = FALSE;
    $return['services']         = FALSE;
    $return['timestamp']        = FALSE;
    $return['timestamp_human']  = FALSE;

    $patternIP4='/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/';

    if (! preg_match($patternIP4, $ip)) {
        $return['error_type'] = "FATAL";
        $return['error_number'] += 1;
        $return['error_string'] = "'$ip' ist keine IP-Adresse.";
        trigger_error($return['error_string'], E_USER_NOTICE);
        return $return;
    }

    if ( 'NSLOOKUP' == strtoupper($method) && ! is_file(nslookup_exe) ) {
        $method='HOST';
        $return['error_type'] = 'NOTICE';
        $return['error_number'] += 2;
        $return['error_string'] = "'nslookup' nicht verfügbar oder falsch konfiguriert. Es wird versucht 'host' zu benutzen";
        trigger_error($return['error_string'], E_USER_NOTICE);
    }

    if ( 'HOST' == strtoupper($method) && ! is_file(host_exe) ) {
        $method='PHP';
        $return['error_type'] = 'NOTICE';
        $return['error_number'] += 4;
        $return['error_string'] = "'host' nicht verfügbar oder falsch konfiguriert. Es wird versucht 'php' zu benutzen";
        trigger_error($return['error_string'], E_USER_NOTICE);
    }

    if ( 'PHP' == strtoupper($method) && ! function_exists('dns_get_record') ) {
        $method='PHP';
        $return['error_type'] = 'FATAL';
        $return['error_number'] += 8;
        $return['error_string'] = "Die Funktion 'dns_get_record()' soll benutzt werden, steht aber auf dem Server nicht zur Verfügung. Lösung: host, nslookup benutzen oder PHP upgraden.";
        trigger_error($return['error_string'], E_USER_NOTICE);
        return $return;
    }


    $PATTERN_SERVICE =              '/Service: (.*), Last-Attack/'  ;
    $PATTERN_LAST_ATTACK =          '/Last-Attack: ([\d]+)\)/'      ;
    $HUMAN_READABLE_DATE_FORMAT =   'Y-m-d H:i:s (O)'               ;

    $queryAdress=implode('.', array_reverse(explode('.', $ip))).'.bl.blocklist.de';

    if ('PHP' == strtoupper($method) ) {
        $arr = dns_get_record($queryAdress, DNS_ALL);
        $erg = array();
        $return['IP'] = $arr[0]['ip'];
        if ( $arr && ! empty($arr[1]['txt']) ) {
            $return['found'] = TRUE;
            $return['DNS_TXT']=$arr[1]['txt'];
            $dummy = preg_match($PATTERN_SERVICE, $arr[1]['txt'], $t);
            if (! empty($t[1]) ) {
                    $return['services'] = $t[1];
            }

            $dummy = preg_match($PATTERN_LAST_ATTACK, $arr[1]['txt'], $t);
            if (! empty($t[1]) ) {
                $return['timestamp'] = $t[1];
                $return['timestamp_human'] = date($HUMAN_READABLE_DATE_FORMAT, $t[1]);
            }

        }
    } else {
        if ('NSLOOKUP' == strtoupper($method)) {
            $sys=nslookup_exe . " -query=txt $queryAdress | grep -i 'Service'";
        } else {
            $sys=host_exe . " -t txt $queryAdress | grep -i 'Service'";
        }

        $return['DNS_TXT'] = trim(`$sys`);
        if (! empty($return['DNS_TXT'])) {
            $return['found'] = TRUE;
            $dummy = preg_match($PATTERN_SERVICE, $return['DNS_TXT'], $t);
            if (! empty($t[1]) ) {
                $return['services'] = $t[1];
            }

            $dummy=preg_match($PATTERN_LAST_ATTACK, $return['DNS_TXT'], $t);
            if (! empty($t) ) {
                $return['timestamp'] = $t[1];
                $return['timestamp_human'] = date($HUMAN_READABLE_DATE_FORMAT, $t[1]);
            }
            $return['ip'] = $ip;
        }
    }
    $return['DNS_TXT']=str_replace('"', "'", $return['DNS_TXT']);
    return $return;
}

Legt man sich auf eine Methode fest und entfernt den "Selbsttest", dann wird das Skript natürlich kürzer.

Jörg Reinholz

  1. Moin!

    Download (als txt-Datei) ...

    Hinweise:

    Die Möglichkeit, den DNS-Request mit host bzw. nslookup zu machen habe ich eingebaut, weil die PHP-Funktion dns_get_record() auf meinem Banana recht (unvertretbar) lange (2s) für eine Reaktion brauchte, mit host bzw. nslookup nicht. Auf dem Webserver geht das besser.

    Das muss wohl jeder mit seinem System selbst probieren.

    Jörg Reinholz

  2. Blocklist.de bietet eine nette Möglichkeit, von anderen bereits erkannte Angreifer via DNS über deren IP zu identifizieren.

    Ich kenne den Dienst nicht, aber es gibt scheinbar auch eine bereits eine HTTP-API dafür. Mir ist nicht so recht klar, welchen Vorteil dein Skript demgegenüber bietet.

    Ein paar stilistische Anmerkungen zu deinem Skript hätte ich auch noch:

    ini_set('display_errors', 0);
    

    Wieso überschreibst du diese Server-Einstellung? Auf Produktiv-Servern kann man damit rechnen, dass diese Eigenschaft bereits deaktivert ist. Auf Entwicklungs-Servern möchte man Fehler bewusst anzeigen lassen, da erschwert diese Überschreibung nur die Fehlersuche.

    if ( empty($_REQUEST['method'])) {
        $_REQUEST['method'] = 'HOST';
    }
    

    $_REQUEST ist nicht der Ort um benutzerdefinierte Werte darin zu speichern. Das Array hat eine fest definierte Semantik, die im PHP-Handbuch nachgelesen werden kann. Wenn du dort selber reinschreibst, missachtest du die Semantik und machst deinen Code unverhersehbar. Ich erinnere mich daran, dass diese Praxis auch in diesem Forum schon Nutzer verunsichert hat. Variablen sind keine Mangelware, das einzige Limit für Variablen ist deine Vorstellungskraft beim Ausdenken neuer Bezeichner.

    if (
        $_REQUEST['method'] != 'PHP'
        && $_REQUEST['method'] != 'NSLOOKUP'
        && $_REQUEST['method'] != 'HOST'
        ) {
        $_REQUEST['method'] = 'HOST';
    }
    

    Die Stelle musste ich 3 Mal lesen, um die Klammernpaare einander zuzuordnen. Dabei sind Codeblöcke bei konventioneller Einrückung etwas, das man schon beim Überfliegen erkennen kann und können sollte. Noch schwieriger wird es, weil du selbst innerhalb dieses Skriptes nicht konsistent vorgehst. Allgemein empfiehlt es sich einen Styleguide zu befolgen.

    if ( $return['error_type'] == 'FATAL' ) {
        header('Status: 500 ');
        echo $return['error_string'];
        exit;
    }
    

    exit; macht es ebenfalls schwer die Struktur von Quelltexten zu erfassen. Es ist verwirrend, dass der folgende Code abhängig davon ausgeführt wird, ob dieser if-Block betreten wird. Und das obwohl sich die Codeblöcke auf gleicher Höhe befinden. Ein else-Block signalisiert schon beim überfliegen, dass hier eine Abhängigkeit existiert.

        $return['Hint']             = 'Dies ist ein Test! Um eine stabile API zu erhalten fragen Sie beim Autor nach (www.fastix.org)';
    

    Diser Kommentar verunsichert nur. Entweder würde ich hier direkt dokumentieren, worauf du auch hinaus wolltest, oder ich würde den Kommentar gänzlich sparen. Anhand dieses Textes kann ich nicht Mal erkennen, ob es hier um eine kritische Sicherheitslücke geht oder ob die Kontaktaufnahme zu einer bezahlten Service-Leistung führen soll.

        if ( 'NSLOOKUP' == strtoupper($method) && ! is_file(nslookup_exe) ) {
            $method='HOST';
            $return['error_type'] = 'NOTICE';
            $return['error_number'] += 2;
            $return['error_string'] = "'nslookup' nicht verfügbar oder falsch konfiguriert. Es wird versucht 'host' zu benutzen";
            trigger_error($return['error_string'], E_USER_NOTICE);
        }
    

    Du hast vier Codeblöcke dieser Art. Nur der erste Codeblock behandelt dabei einen Fehler, der durch eine Fehlbedienung der Funktion ausgelöst wird. Die anderen Fehlermeldungen beziehen sich auf die Ausführungsumgebung: Existiert dieses Programm? Existiert diese Funktion? Diese Blöcke gehören nicht in diese Funktion, weil sie Fehler aufdecken, die u.U. schon viel früher entstanden sind und weil sie keine Sinneinheit mit der Funktion bilden. Darüberhinaus ist viel Code-Duplikation ein sicheres Zeichen dafür, dass man gemeinsame Code-Fragmente in eine wiederverwendbare eigene Einheit ausgliedern sollte.

        $PATTERN_SERVICE =              '/Service: (.*), Last-Attack/'  ;
    

    Du hast dir sicher etwas dabei gedacht, diese und andere Variablen groß zu schreiben. Für mich als unbeteiligten Leser erschließt sich mir aber nicht, was dahinter stecken könnte. Dies ist ebenfalls ein Thema, das von Styleguides abgedeckt wird und damit zum Konsens beiträgt.

    1. Moin!

      Ich kenne den Dienst nicht, aber es gibt scheinbar auch eine bereits eine HTTP-API dafür. Mir ist nicht so recht klar, welchen Vorteil dein Skript demgegenüber bietet.

      Dafür wollen die einen Key (Dann kann man aber auch Angreifer dort einwerfen). Für die DNS-Abfrage nicht ...

      Ein paar stilistische Anmerkungen zu deinem Skript hätte ich auch noch:

      ini_set('display_errors', 0);
      

      Wieso überschreibst du diese Server-Einstellung? Auf Produktiv-Servern kann man damit rechnen, dass diese Eigenschaft bereits deaktivert ist. Auf Entwicklungs-Servern möchte man Fehler bewusst anzeigen lassen, da erschwert diese Überschreibung nur die Fehlersuche.

      Volle Absicht. Macht man das nicht werden die Notizen in der Ausgabe ausgeworfen und der HTTP-Status auf 200 gesetzt. Das genau will ich hier nicht.

      Ich will (wenn man es denn als Web-Api nutzt:

      • außer bei einem Konfiguarationsfehler JSON also Ausgabe
      • Fehlercodes (404) im HTTP-Header
      • und die Fehler also nur im Error-Log
      if ( empty($_REQUEST['method'])) {
          $_REQUEST['method'] = 'HOST';
      }
      

      $_REQUEST ist nicht der Ort um benutzerdefinierte Werte darin zu speichern.

      Du hast nicht erkannt, dass das eigentlich zum Test gehört. Wer das produktiv nutzt sollte natürlich den Testbereich rauswerfen und wird sich wohl je nach Nutzung auf eine andere Methode der Übergabe bzw. Fixierung festlegen.

      if (
          $_REQUEST['method'] != 'PHP'
          && $_REQUEST['method'] != 'NSLOOKUP'
          && $_REQUEST['method'] != 'HOST'
          ) {
          $_REQUEST['method'] = 'HOST';
      }
      

      Die Stelle musste ich 3 Mal lesen, um die Klammernpaare einander zuzuordnen.

      Hätte nicht gedacht, dass das schwer zu lesen ist. Ich habe die 3 Bedingungen auf 3 Zeilen verteilt, damit der Umbruch nicht durch die Darstellung hier im Forum an willkürlicher Stelle erfolgt - was den Code noch viel schlechter lesbar macht.

      In meinem Styleguide steht: "Brich die Bedingungen um und rücke diese bei Klammerung genau sei ein wie Du es bei Codeblöcken tun würdest." Ist prima lesbar!

      Ohnehin gilt: wenn jemand das produktiv nutzen will, dann sollte er sich auf eine Abfragemethode festlegen, den Test rauswerfen und kann sich so mehr als die Hälfte der Codezeilen sparen.

      Deshalb steht da auch "Legt man sich auf eine Methode fest und entfernt den "Selbsttest", dann wird das Skript natürlich kürzer."

      Ohne deklaratorische Zeilen wie das letzte exit vor der Funktion kommt das Skript nach dem Rauswerfen nicht benötigter Funktionen auf 60 Zeilen, ohne Leerzeilen sind es 51...

      if ( $return['error_type'] == 'FATAL' ) {
          header('Status: 500 ');
          echo $return['error_string'];
          exit;
      }
      

      exit; macht es ebenfalls schwer die Struktur von Quelltexten zu erfassen.

      Ich komme damit gut klar. trigger_error ("Foo, blah, blubb", USER_ERROR) bricht auch ab und ich muss es bis nach ganz rechts lesen um das zu wissen. Mir signalisiert das exit deutlich genug, was da los ist und ich empfinde es eher als Zumutung, wenn ich womöglich erst 3000 Zeilen und 24 Dutzend elseif weiter unten erst sehe: da kommt nichts mehr. Abbruchbedingung erfüllt? Exit! ist für mich eine klare und lesbare Ansage. Ich schätze, der Interpreter sieht das auch so...

          $return['Hint']             = 'Dies ist ein Test! Um eine stabile API zu erhalten fragen Sie beim Autor nach (www.fastix.org)';
      

      Diser Kommentar verunsichert nur. Entweder würde ich hier direkt dokumentieren ...

      Was bedeutet wohl, dass das Skript im Ordner /test/ ist? Könnte beides zusammen die sehr deutliche Nachricht beinhalten, dass ich so klar wie möglich machen will, dass niemand darauf vertrauen soll, dass das Skript auch übermorgen noch dort ist und so wie bisher funktioniert? Dieser Kommentar soll also gerade klar machen, dass es nicht sicher ist, das Skript zu benutzen. Zur Datensicherheit gehört die Verfügbarkeit. Hinsichtlich einer API-Sicherheit gilt das auch.

      if ( 'NSLOOKUP' == strtoupper($method) && ! is_file(nslookup_exe) ) {

      Du hast vier Codeblöcke dieser Art. Nur der erste Codeblock behandelt dabei einen Fehler, der durch eine Fehlbedienung der Funktion ausgelöst wird.

      Fehlbedienung? Eigentlich Fehlkonfiguration. Fehlbedienung war weiter oben (falsche Methode im Request). Im übrigen unterscheiden sich diese Codeblöcke doch etwas zu sehr als dass ich hier von einer "wiederverwendbaren eigenen Einheit" ausgehen würde.

      Die anderen Fehlermeldungen beziehen sich auf die Ausführungsumgebung: Existiert dieses Programm?

      Ist hier auch drin.

      Du hast dir sicher etwas dabei gedacht, diese und andere Variablen groß zu schreiben.

      Der ursprüngliche Plan sah Konstanten vor. Davon bin ich abgerückt, weil PATTEN_SONSTWAS irgendwie zu allgemein ist. Wem das nicht passt, der kann mit "Suchen und Ersetzen" daraus machen was in seinem Styleguide steht.

      Jörg Reinholz

      1. Ich kenne den Dienst nicht, aber es gibt scheinbar auch eine bereits eine HTTP-API dafür. Mir ist nicht so recht klar, welchen Vorteil dein Skript demgegenüber bietet.

        Dafür wollen die einen Key (Dann kann man aber auch Angreifer dort einwerfen). Für die DNS-Abfrage nicht ...

        Für das Abfragen von IP-Adressen braucht man keinen API-Key. Steht dort direkt unter der ersten Tabelle.

        Ein paar stilistische Anmerkungen zu deinem Skript hätte ich auch noch:

        ini_set('display_errors', 0);
        

        Wieso überschreibst du diese Server-Einstellung? Auf Produktiv-Servern kann man damit rechnen, dass diese Eigenschaft bereits deaktivert ist. Auf Entwicklungs-Servern möchte man Fehler bewusst anzeigen lassen, da erschwert diese Überschreibung nur die Fehlersuche.

        Volle Absicht. Macht man das nicht werden die Notizen in der Ausgabe ausgeworfen und der HTTP-Status auf 200 gesetzt. Das genau will ich hier nicht.

        Die Frage war, wieso du das in PHP machst und nicht in der PHP-Konfiguration? Das würde dir erlauben, das Skript mit und ohne display_errors auszuführen ohne das Skript selber berühren zu müssen. Auf Entwicklungsservern will man ja gerade Fehler sehen, da bildet dein Skrtip auch keine Ausnahme.

        if ( empty($_REQUEST['method'])) {
            $_REQUEST['method'] = 'HOST';
        }
        

        $_REQUEST ist nicht der Ort um benutzerdefinierte Werte darin zu speichern.

        Du hast nicht erkannt, dass das eigentlich zum Test gehört.

        Zum einen würde ich hier keine Ausnahme für Tests machen, zum anderen gehört der Code bereits nicht mehr zum Test, wie der Kommentar "Ende Test" der Zeile unmittelbar davor es belegt.

        Wer das produktiv nutzt sollte natürlich den Testbereich rauswerfen und wird sich wohl je nach Nutzung auf eine andere Methode der Übergabe bzw. Fixierung festlegen.

        Das ist Benutzerunfreundlich und wird so nur selten geschehen. Dafür müsste ein Anwender ja erst das ganze Skript lesen und verstehen und darüber hinaus bereit sein es zu manipulieren, wohlwissend, dass eventuelle Updates des Original-Autors danach nicht mehr einfach eingespielt werden können. Da lehnen erfahrene Entwickler schos aus Scheu vor dem Wartungsaufwand ab.

        if (
            $_REQUEST['method'] != 'PHP'
            && $_REQUEST['method'] != 'NSLOOKUP'
            && $_REQUEST['method'] != 'HOST'
            ) {
            $_REQUEST['method'] = 'HOST';
        }
        

        Die Stelle musste ich 3 Mal lesen, um die Klammernpaare einander zuzuordnen.

        Hätte nicht gedacht, dass das schwer zu lesen ist. Ich habe die 3 Bedingungen auf 3 Zeilen verteilt, damit der Umbruch nicht durch die Darstellung hier im Forum an willkürlicher Stelle erfolgt - was den Code noch viel schlechter lesbar macht.

        Der Umbruch innerhalb der Bedingung trägt weniger zur Verwirrung bei als die Positionierung der Klammern. Alternativ hättest du die Bedinung aber auch so kürzen können, dass ein Umbruch gänzlich überflüssig wird.

        if (!in_array($_REQUEST['method'],['PHP','NSLOOKUP','HOST']))
        

        In meinem Styleguide steht: "Brich die Bedingungen um und rücke diese bei Klammerung genau sei ein wie Du es bei Codeblöcken tun würdest." Ist prima lesbar!

        Das tust du aber nicht, wieso ist die schließende Klammer der if-Bedingung eingerückt? Bei Code-Blöcken ist die schließende Klammer auf selber Höhe wie der Beginn der öffnenden Zeile. Als ich von Styleguides sprach, dachte ich übrigens an einen etablierten Stylguide. Die haben zum Vorteil, dass man den eigenen PHP-Code automatisiert dagegen validieren kann.

        exit; macht es ebenfalls schwer die Struktur von Quelltexten zu erfassen.

        Ich komme damit gut klar. trigger_error ("Foo, blah, blubb", USER_ERROR) bricht auch ab und ich muss es bis nach ganz rechts lesen um das zu wissen. Mir signalisiert das exit deutlich genug, was da los ist und ich empfinde es eher als Zumutung, wenn ich womöglich erst 3000 Zeilen und 24 Dutzend elseif weiter unten erst sehe: da kommt nichts mehr.

        Bei gut strukturietem Quelltext musst du gar nicht danach fragen, ob noch etwas kommt. Das Programm sollte so strukturiert sein, dass es dir völlig egal sein kann, ob nach einer geschlossenen Sinneinheit noch eine weitere geschlossene Einheit ausgeführt wird. Das ist das Lokalitätsprinzip. exit; ist das Gegenteil davon, nachfolgender Code wird einfach radikal abgeschnitten, "nach mir die Sintflut". Implikationen davon sind, dass Unit-Testing und Post-Processing nicht mehr möglich sind.

        Ich schätze, der Interpreter sieht das auch so...

        Der Interpreter muss dein Programm nicht sinnerfassend lesen und verstehen. Er muss es nur stumpf ausführen, das ermächtigt ihn dazu selbst Programmiersprachen mit Leichtigkeit auszuführen, die für den Menschen völlig unverständlich sind, z.B. Brainfuck. Als Maßstab für deinen Programm-Entwurf sollten kognitive Fähigkeiten des Menschen dienen.

            $return['Hint']             = 'Dies ist ein Test! Um eine stabile API zu erhalten fragen Sie beim Autor nach (www.fastix.org)';
        

        Diser Kommentar verunsichert nur. Entweder würde ich hier direkt dokumentieren ...

        Was bedeutet wohl, dass das Skript im Ordner /test/ ist? Könnte beides zusammen die sehr deutliche Nachricht beinhalten, dass ich so klar wie möglich machen will, dass niemand darauf vertrauen soll, dass das Skript auch übermorgen noch dort ist und so wie bisher funktioniert?

        Ah, dies ist also ein Hinweis an die Nutzer deiner Demo. Ich hatte ihn erst als einen Hinweis an den Anwendungsentwickler wahrgenommen.

        Im übrigen unterscheiden sich diese Codeblöcke doch etwas zu sehr als dass ich hier von einer "wiederverwendbaren eigenen Einheit" ausgehen würde.

        Kennst du das DRY-Prinzip? Defakto kannst du jedes Programm so refaktorisieren, dass sich keine zwei Zeilen mehr gleichen müssen. Das führt zu erstaunlich eleganten Programmentwürfen. Voraussetzung ist natürlich, dass man die richtigen Abstraktionen wählt. Du musst das Prinzip ja nicht gleich bis ins Extrem betreiben, aber eine Annäherung daran würde deinen Programmen sicher gut tun. Aktuell machst du von Abstraktion und Wiederverwendung überhaupt keinen Gebrauch und stehst somit beim gegenüberliegendem Extrem.

        Die anderen Fehlermeldungen beziehen sich auf die Ausführungsumgebung: Existiert dieses Programm?

        Ist hier auch drin.

        Das war die Kritik. Denn "hier" gehören sie nicht hin.

        Du hast dir sicher etwas dabei gedacht, diese und andere Variablen groß zu schreiben.

        Der ursprüngliche Plan sah Konstanten vor. Davon bin ich abgerückt, weil PATTEN_SONSTWAS irgendwie zu allgemein ist. Wem das nicht passt, der kann mit "Suchen und Ersetzen" daraus machen was in seinem Styleguide steht.

        Wem das nicht passt, der wird nicht in die Pflege deines Skriptes einsteigen, der wird einfach davon Abstand nehmen. Das kann ja auch nicht in deinem Sinn sein.

        1. Moin!

          Für das Abfragen von IP-Adressen braucht man keinen API-Key. Steht dort direkt unter der ersten Tabelle.

          Allerdings habe ich die Erfahrung gemacht, dass das nicht unbegrenzt oft klappt. Habe ich vergessen zu erwähnen.

          Die Frage war, wieso du das in PHP machst und nicht in der PHP-Konfiguration?

          Weil das benutzte Verzeichnis so konfiguriert ist, dass PHP die Fehler eben anzeigt.

          Du hast nicht erkannt, dass das eigentlich zum Test gehört. Zum einen würde ich hier keine Ausnahme für Tests machen, zum anderen gehört der Code bereits nicht mehr zum Test, wie der Kommentar "Ende Test" der Zeile unmittelbar davor es belegt.

          Offenbar hast Du eine Leseproblem. Du stößt auf etwas, was Du als Aussage deuten kannst und schaltest das Gehirn ab. Wenn Du den Code ansiehst, dann wird Dir klar, dass ich das komplette $_REQUEST['method'] nur "mit mir rumschleppe" um die 3 Methoden (PHP-nativ, hosts und nslookup) testen zu können, was einem im produktiven Einsatz ja wohl kaum einfallen wird. Will ich nicht testen, dann brauche ich $_REQUEST['method'] nicht.

          Spätestens ab diesem Posting sollte auch klar sein, warum ich überhaupt getestet habe.

          Als Maßstab für deinen Programm-Entwurf sollten kognitive Fähigkeiten des Menschen dienen.

          Na wunderbar! Ich bin ein Mensch und komme mit Abbruchbedingung erfüllt? Exit! sehr gut klar.

          Implikationen davon sind, dass Unit-Testing und Post-Processing nicht mehr möglich sind.

          Die Version ohne die Tests hat 60 Zeilen ... die kann man aber mit try { ... } catch { ... }, set_exception_handler () und throw new [custom]Exception () so lange aufblasen bis keiner mehr Fehler findet.

          Aktuell machst du von Abstraktion und Wiederverwendung überhaupt keinen Gebrauch und stehst somit beim gegenüberliegendem Extrem.

          Ja, nee, ist klar. Für einen Test martere ich mir das Hirn um aus 3 Blöcken mit 4 Zeilen, von denen 4 zwar ähnlich aussehen aber unterschiedlich sind durch einen Affenaufwand mit der Parametrisierung und einen Haufen "wenn und aber-Konstrukten" irgendwas mit 80 Zeilen zu bauen, was dann "wiederverwendbar" ist...

          Das führt zu erstaunlich eleganten Programmentwürfen.

          Mag sein. Eleganz als Selbstzweck?

          if (!in_array($_REQUEST['method'],['PHP','NSLOOKUP','HOST']))

          Das scheint Dir besser lesbar, mir indes nicht. Und ich kann das durchaus auch begründen: ein not(!) davor, eine Funktion mehr (in_array) und ein Syntaxkonstrukt ([,,,]) mehr - also für mich schwieriger zu lesen als das simple, wenn a != 1 und b != 2 und c != 3, dann leck mich doch am ...

          Ich hatte ihn erst als einen Hinweis an den Anwendungsentwickler wahrgenommen.

          Hups. Ein "Anwendungsentwickler" der sich aus dem Skript nicht mehr zieht als die Idee, dass und wie das DNS zu befragen ist, wie man mit simplen regulären Ausdrücken die Informationen extrahiert und sich dann den von ihm benötigten 60-Zeiler nicht selbst zusammenzuschießen kann … naja, der sollte sich nicht so nennen.

          Wem das nicht passt, der wird nicht in die Pflege deines Skriptes einsteigen, der wird einfach davon Abstand nehmen.

          Dann nimm doch, bitte, Abstand!

          Jörg Reinholz

          1. Tach,

            Wem das nicht passt, der wird nicht in die Pflege deines Skriptes einsteigen, der wird einfach davon Abstand nehmen. Dann nimm doch, bitte, Abstand!

            du postest dein Script hier in diesen Raum und willst dann keine Kritik daran hören? Das verstehe ich nicht, denn das hier ist weder ein Scriptdump noch eine Werbeveranstaltung.

            mfg
            Woodfighter

          2. Als Maßstab für deinen Programm-Entwurf sollten kognitive Fähigkeiten des Menschen dienen.

            Na wunderbar! Ich bin ein Mensch und komme mit Abbruchbedingung erfüllt? Exit! sehr gut klar.

            Nadann bist du wohl safe.

            Bildbeschreibung

            Oder du hast noch nicht genug Zeit mit Software-Testing verbracht.

            1. Moin!

              Mir gefällt zwar schon der Umstand nicht, dass Du hier (um es äußerst zurückhaltend zu formulieren) unsachlich wirst, aber der Umstand, dass das offenbar auch noch jemand unwidersprochen gut findet, lässt mich im Zusammenhang mit den sehr konkreten Entäußerungen des Woodfighter zu dem Schluss kommen, dass meine Beiträge aus den selben konkreten Gründen nicht erwünscht sind und deshalb nicht etwa wohlwollend sondern mit dem Vorsatz, etwas Negatives zu finden, untersucht werden.

              Ich muss mich weder aufdrängen noch sehe ich einen überzeugenden Grund mich dem auszusetzen.

              Also erfülle ich den aus den Äußerungen von "1unitedpower" und "woodfighter" offenbar gewordenen Herzenswunsch und füge meinen Name der Trauerliste hinzu.

              (Auch) Ich bin also "mal weg". @1unitedpower und @woodfighter haben also einen schönen Erfolg zu feiern.

              Jörg Reinholz

              1. Tach,

                Mir gefällt zwar schon der Umstand nicht, dass Du hier (um es äußerst zurückhaltend zu formulieren) unsachlich wirst, aber der Umstand, dass das offenbar auch noch jemand unwidersprochen gut findet, lässt mich im Zusammenhang mit den sehr konkreten Entäußerungen des Woodfighter zu dem Schluss kommen, dass meine Beiträge aus den selben konkreten Gründen nicht erwünscht sind

                wenn ich schreibe, dass ich etwas nicht verstehe, meine ich genau das. Ich war davon ausgegeangen, dass du deine Scripte postest, in der Hoffnung anderen zu helfen und gleichzeitig etwas dabei zu lernen; deswegen kann ich tatsächlich deine Reaktion auf die Kritik nicht nachvollziehen, selbst wenn du vielleicht den genannten Punkten nicht übereinstimmst.

                Also erfülle ich den aus den Äußerungen von "1unitedpower" und "woodfighter" offenbar gewordenen Herzenswunsch und füge meinen Name der Trauerliste hinzu.

                Da interpretierst du mich und vermutlich auch @1unitedpower falsch.

                mfg
                Woodfighter

                1. Hallo,

                  Also erfülle ich den aus den Äußerungen von "1unitedpower" und "woodfighter" offenbar gewordenen Herzenswunsch und füge meinen Name der Trauerliste hinzu.

                  Da interpretierst du mich und vermutlich auch @1unitedpower falsch.

                  ja, ich bedaure auch, dass Jörg hier ungewohnt empfindlich reagiert, und kann das nicht ganz nachvollziehen. Aber ebensowenig kann ich nachvollziehen, wieso er im Kontext des oben zitierten Satzes auf die Forenstatistik bzw. die Liste der "Jährling"-Medailleninhaber verlinkt. Da kann ich keinerlei Zusammenhang erkennen.

                  So long,
                   Martin

                  1. Tach,

                    Aber ebensowenig kann ich nachvollziehen, wieso er im Kontext des oben zitierten Satzes auf die Forenstatistik bzw. die Liste der "Jährling"-Medailleninhaber verlinkt. Da kann ich keinerlei Zusammenhang erkennen.

                    er meint damit, dass er sich in die Liste der vor langer Zeit schon hiergewesenen Ehemaliger einordnet.

                    mfg
                    Woodfighter

  3. vielen Dank, dieser Quellcode bringt mich in vielerlei Hinsicht ein Stück weiter... bows