Archiv Dezember 2013

Donnerstag, 19. Dezember 2013

Hochzeit-Fotos von ichwuensche.ch automatisiert herunterladen

Heuer war es wieder mal soweit — Bekannte, welche im September 2013 geheiratet und an deren Hochzeit Stephanie und ich teilgenommen haben, haben die Fotos über ichwuensche.ch zugänglich gemacht. Da es mir zu blöd war, mich durch die 12 Web-Seiten voller Hochzeitsbilder zu klicken, habe ich mir ein kleines PHP-Script geschrieben, welches mir die URLs der Fotos generiert. Dafür benötige ich die fortlaufende Nummer des ersten sowie letzten Bildes der Serie; das Script generiert anschliessend automatisiert alle URLs.

<?php
    $base = 'http://www.ichwuensche.ch/images/gallery/';
    $start = 1269245;
    $end = 1269774;
    $suffix = '_l.jpg';
    
    $counter = 0;
    for($i = $start; $i <= $end; $i++) {
        $counter++;
        
        // $middle = 4/4/2/9/6/ if JPEG basename is 1269245
        $middle = strrev($i);
        $middle = substr($middle,0,5);
        $middle = implode('/',str_split($middle)) . '/';
        
        $url = $base . $middle. $i . $suffix;
        echo $url . "\n";
    }
    
    echo "\n" . $counter . "\n";
?>

Anschliessend führt man das Script aus, pipet die Ausgabe in eine Textdatei und lässt dann wget seine Arbeit verrichten:

$ php generate-urls.php > urls.txt
$ wget -i urls.txt
--2013-12-19 16:06:37--  http://www.ichwuensche.ch/images/gallery/4/7/7/9/6/1269774_l.jpg
Verbindungsaufbau zu www.ichwuensche.ch (www.ichwuensche.ch)|85.158.232.45|:80... verbunden.
HTTP-Anforderung gesendet, warte auf Antwort... 200 OK
Länge: 150027 (147K) [image/jpeg]
In »»1269774_l.jpg«« speichern.
...

ACHTUNG: Leider haben die Entwickler der Web-Site nicht viel überlegt: Unter den Total 530 Fotos findet sich auch die Hochzeit eines unbekannten Paares aus dem Thurgau, eine Amerika-Reise eines anderen, ebenfalls unbekannten Paares sowie die wohl fast schon obligatorischen Katzenfotos.

Umgekehrt bedeutet dies, dass ein Script-Kiddie in einer Nacht alle Fotos der Web-Site abräumen könnte. Na dann.

Tags: , , , , , ,
Labels: Web

7 Kommentare | neuen Kommentar verfassen

Mittwoch, 18. Dezember 2013

Schwer zu eruierende LaTeX-Kompilationsfehler debuggen

Kürzlich konnte ich ein Dokument eines aktuellen LaTeX-Projektes nicht mehr kompilieren. pdflatex brach immer mit der folgenden Fehlermeldung ab:

...
! Missing \endcsname inserted.
 
\protect 
l.75 \printbibliography[heading=none]
...

Welcher der über 300 Einträge in der Bibliographie verursachte das Problem? Erst das manuelle Eingrenzen durch radikales Löschen (natürlich mit Sicherheitskopie der .bib-Datei) von Bibliographie-Einträgen brachte schlussendlich den verantwortlichen Eintrag zu Tage: Auf Grund der Overfull \hbox-Meldungen in der Log-Datei wusste ich, zwischen welchen zwei Einträgen das Problem bestand, nicht aber, welcher der circa 30 Einträge effektiv das Problem war. Nach der Löschaktion war der Eintrag isoliert. Meine Analyse ergab, dass ich in JabRef in das Feld Language den Wert Französisch eingetragen hatte, welches beim Abspeichern der Bibliographie zu Franz{\“o}sisch wird. Offenbar mag das Paket biblatex solche Sonderzeichen in diesem Feld gar nicht und bricht stumm ab …

Tags: , , , , , , ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 18. Dezember 2013

MacPorts bricht die Installation von python27 ab

Das Problem stellte sich bei mir bereits auf mehreren Computern. Bei der Analyse der von MacPorts erstellten Log-Datei wird offensichtlich, wo das Problem liegt:

:info:destroot You have not agreed to the Xcode license agreements, please run 'xcodebuild -license' (for user-level acceptance) or 'sudo xcodebuild -license' (for system-wide acceptance) from within a Terminal window to review and agree to the Xcode license agreements.

Wer kürzlich Apple Xcode aktualisiert hat, muss wie von Apple angeraten folgenden Befehl ausführen:

# xcodebuild -license

Danach laufen die MacPorts-Installationen wieder sauber durch.

Tags: , , , , ,
Labels: IT

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 18. Dezember 2013

Google crawlt einmal entdeckte URLs auf immer und ewig

Seit Monaten plagten mich die Log-Dateien eines von mir betreuten Web-Projektes: Bestimmte URLs wurden von Googlebot periodisch wiederkehrend aufgerufen, obwohl die Informationen dieser Web-Seiten vor langer Zeit deaktiviert worden waren (kurz: Die Objekte wie Personen und Referate waren nicht mehr in der Datenbank vorhanden und generierten beim Aufruf eine PHP-Exception, welche zwar abgefangen wurde, aber meine Log-Dateien vollmüllte) und das Script seit einigen Wochen einen HTTP 404-Fehler zurückgab.

Wie zum Teufel kam der Googlebot immer wieder auf diese verflixten URLs zurück?

Ich hatte eine verdächtige Subdomain des Projektes im Visier, welche eine archivierte Version der Web-Site bereitstellte. Deshalb passte ich die URLs auf dieser Web-Seite dort an und fügte ihnen eine GET-Variable hinzu, welche unmissverständlich aufzeigen sollte, ob der Googlebot die URLs von dieser Web-Site bezog. Leider stellte sich heraus, dass die Ursache des Übels nicht von dieser Web-Site herrührte.

Daraufhin wählte ich URLs aus, welche eine ganz bestimmte, möglichst einmalige Zeichenkette enthielten und gab diese in der Google-Suche ein. Tatsächlich lieferte Google die Seite der Web-Site als Resultat aus — obwohl die Seite seit Wochen HTTP 404 retournierte. Ein Blick auf den Zeitpunkt des Caches bestätigte, dass Google eine mehrere Wochen alte Version aufbewahrte, welche kurz vor dem Einbau der 404-Routine gecrawlt wurde.

Nun gut, sagte ich mir: Irgendwann einmal muss ja der Googlebot akzeptieren, dass eine URL permanent einen 404er zurückliefert und diese URL dann nicht mehr regelmässig anpingen. Falsch gedacht:

Once Googlebot finds and crawls a URL, they will periodically come back and crawl it again forever. Even after you remove the page and have been returning 404 status for years, Googlebot will still crawl the URL from time to time.

Quelle: Google Crawls my disabled products on my Magento website [closed]

So ist das. Gibt es also wirklich nichts, was ein besorgter Webmaster tun kann? Doch, durchaus:

I followed up on the 404 vs 410 thing with the team here. As mentioned by some others here & elsewhere, we have generally been treating them the same in the past.

However, after looking at how webmasters use them in practice we are now treating the 410 HTTP result code as a bit „more permanent“ than a 404. So if you’re absolutely sure that a page no longer exists and will never exist again, using a 410 would likely be a good thing. I don’t think it’s worth rewriting a server to change from 404 to 410, but if you’re looking at that part of your code anyway, you might as well choose the „permanent“ result code if you can be absolutely sure that the URL will not be used again. If you can’t be sure of that (for whatever reason), then I would recommend sticking to the 404 HTTP result code.

In the worst case, the 410 will be treated the same as a 404; in the best case it’ll be a bit quicker & stickier :-).

Quelle: Does it make sense to return a 410 instead of 404 when some page has been permanently removed?, Via: Does it make sense to return a 410 instead of 404 when some page has been permanently removed?

Ich passte also meinen try-catch-Block im Script an, welcher neu heisst:

...
header("HTTP/1.0 410 Gone");
...

Tags: , , , , ,
Labels: Programmierung

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 18. Dezember 2013

Mit cURL unter Windows das Verhalten eines Tomcat-Servers debuggen

Obwohl ich primär als IT-Auditor unterwegs bin, haben wir uns vor einigen Tagen mit einer Tomcat-basierenden Audit-Applikation herumgeschlagen. Kurz ging es darum, die Kommunikation im Intranet zwingend mit HTTPS zu verschlüsseln. Da der Server mit verschiedenen Domainnamen (teilweise nicht FQDNs) angesprochen werden kann, mussten wir Tomcat zuerst einmal so konfigurieren, dass er alle HTTP-Anfragen auf eine bestimmte Domain umleitete, falls die Anfrage nicht bereits an den korrekten Host gerichtet war (wir haben uns den UrlRewriteFilter) zu Nutze gemacht — und trauerte dabei leise dem (noch) eleganteren mod_rewrite in .htaccess Dateien unter Apache nach …

Item. Da unsere Web-Browser nicht wirklich hilfreich waren, um die Redirects zu analysieren und auch noch ein Enterprise Proxy-Server dazwischenstand, behalf ich mich mit der Win32-Version von cURL, curl.exe mit den Optionen --verbose, um den gesamten Ablauf der Verbindungsaufnahme auf der Kommandozeile auszugeben, sowie mit --noproxy *, um sicherzugehen, dass wir direkt mit dem Server sprachen und den Enterprise Proxy so umgingen. Das Resultat sah folgendermassen aus:

C:\Temp\cURL\> curl.exe --verbose --noproxy * http://software.domain.tld:8080/r2d2/asdf
* Adding handle: conn: 0x1c3def0
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x1c3def0) send_pipe: 1, recv_pipe: 0
* About to connect() to software.domain.tld port 8080 (#0)
* Trying 10.0.0.111...
* Connected to software.domain.tld (10.0.0.111) port 8080 (#0)
> GET /r2d2/asdf HTTP/1.1
> User-Agent: curl/7.32.0
> Host: software.domain.tld:8080
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Location: https://protected.domain.tld:8443/r2d2/asdf
< Content-Length: 0
< Date: Wed, 11 Dec 2013 10:35:41 GMT
<
* Connection #0 to host software.domain.tld left intact

Alles Bestens: Anfragen auf http://software.domain.tld:8080/r2d2/asdf werden auf https://protected.domain.tld:8443/r2d2/asdf umgeleitet. Und das Auditorenherz schlägt höher.

Tags: , , , , , , , ,
Labels: Web

Keine Kommentare | neuen Kommentar verfassen

Mittwoch, 18. Dezember 2013

Den Netatmo PHP API-Client mit weniger strikten SSL-Anforderungen patchen

Vor einigen Tagen hörte mein Raspberry Pi-Dashboard auf, die Werte meiner Netatmo NWS01 Wetterstation für Apple iPhone und Android anzuzeigen.

Auf meinem lokalen Mac funktionierte das Dashboard hingegen problemlos; d.h. ich konnte mittels dem Netatmo PHP API-Client die JSON-Datei mit den aktuellen Messwerten wie Temperatur, Luftdruck und -feuchtigkeit abrufen.

Die genaue Ursache hinter dem Problem kenne ich bis heute nicht, doch ich vermute mit dem jetzigen Wissensstand, dass die Cyon-Ingenieure an der Konfiguration ihrer Server herumgewerkelt haben und dabei unter anderem das Root-Zertifikat entfernt haben, welches der Netatmo API-Client zur HTTPS-verschlüsselten Kommunikation mit den Netatmo-Servern verwendet.

Nachdem ich nämlich die Exception mittels vardump() genauer betrachtete, welche NACurlErrorType zurücklieferte, war der Fall schnell sonnenklar:

...
[message:protected] => SSL peer certificate or SSH remote key was not OK
...

Nun … gut! Was macht man da? Ich habe die Datei NAApiClient.php gepatcht, indem ich cURL mit der auf false gesetzten Option CURLOPT_SSL_VERIFYHOST sage, unverifizierte SSL-Zertifikate kommentarlos zu akzeptieren:

...
        else 
        {
            $opts[CURLOPT_HTTPHEADER] = array('Expect:');
        }
        
        $opts[CURLOPT_SSL_VERIFYHOST] = false;
        
        curl_setopt_array($ch, $opts);
...

Bei einer API wie Netatmo ist diese manuell herbeigeführte Schwachstelle zu verantworten. Ginge es um Mailverkehr oder Online-Banking, würde ich eine solche Option definitiv nicht aktivieren.

Tags: , , , , , , , ,
Labels: Programmierung

Keine Kommentare | neuen Kommentar verfassen

Samstag, 14. Dezember 2013

syslog-ng motzt über nicht konforme Konfigurationssyntax

Bei den gelegentlichen apt-get dist-upgrades auf meinem Linux-Server motzt syslog-ng bei jedem Neustart des Services über eine inkompatible Syntax von /etc/syslog-ng.conf:

WARNING: Configuration file format is too old, syslog-ng is running in compatibility mode Please update it to use the syslog-ng 3.5 format at your time of convinience, compatibility mode can operate less efficiently in some cases. To upgrade the configuration, please review the warnings about incompatible changes printed by syslog-ng, and once completed change the @version header at the top of the configuration file.;

Wie löst man dieses Problem? Ich bin folgendermassen vorgegangen:

  1. Zuerst passe ich die Zeichenkette in /etc/syslog-ng.conf an. Anstelle der Version 3.3 trage ich dort frech wie ich bin einfach probehalber mal folgendes ein:

    @version: 3.5
    ...
  2. Als nächstes prüfe ich, dass syslog-ng mit den restlichen Angaben in der Konfigurationsdatei einverstanden ist — sprich in der Datei keine Syntax-Fehler vorhanden sind:

    # syslog-ng --syntax-only

    Wird hier keine Meldung gemacht, ist alles in bester Ordnung.

  3. Schlussendlich startet man syslog-ng neu:

    /etc/init.d/syslog-ng restart

Und gut is!

Tags: , , ,
Labels: Linux

Keine Kommentare | neuen Kommentar verfassen