wolfuli

Auslieferung von Gravatar-Icons aus einem lokalen Cache – Download per curl

Vor einigen Tagen bin ich über Crazytoast auf einem Blog auf die Idee der Auslieferung der Gravatar-Bilder aus einem lokalen Cache gestoßen. Prinzipiell fand ich das keine schlechte Idee, da auch bei mir einige Ladezeit von Gravatar verursacht wird. Auch der regelmäßige Refresh erschien mir als durchaus sinnvoll. Lediglich die Art der Einbindung wollte mir noch nicht so recht gefallen. Auch programmiertechnisch fehlten mir einige Dinge.

Werbung


So wurde beispielsweise als einzige Möglichkeit des Herunterladen der Bilder die Funktion fopen() angeboten, welche jedoch bei den meisten Hostern deaktiviert (allow_url_fopen=0) wird, da es durchaus genügend Beispiele für Sicherheitslücken welche durch die unkluge Nutzung dieser Funktion gibt. Aus meinem Patch für Piwik habe ich daher einen Teil des Codes extrahiert, welcher es mir erlaubt, curl zu benutzen.

Wie bei Plerzelwupp beschrieben muss man zunächst die comments.php öffnen und die folgende Zeile suchen:

<?php echo get_avatar( $comment, 60); ?>

Das zweite Argument der Größe könnte bei euch auch durchaus anders aussehen!

Wie auch immer, man löscht jedenfalls diese Zeile und setzt dafür den folgenden Code ein:

<?php
// Script originally from:
// http://www.plerzelwupp.de/wordpress-gravatare-cachen/
//
// Modified by Uli from https://wolf-u.li:
// - Translation
// - Cleanup
// - Added curl
 
// Modify the settings below according to your needs:
 
// Path to the cache-directory of the gravatar images:
$gimagecachedir 		= "upload/g/";
 
// Path of the directory of the gravatar-images:
$gimageurldomain = "https://wolf-u.li/upload/g/";
 
// Size of the gravatar-images:
$gimagesize = 64;
 
// If the mailadress was not found, you can get various images:
// - identicon
// - monsterid
// - wavatar
$mailnotfound = "identicon";
 
// Do not modify the code below:
$gravatar_hash = md5(strtolower(get_comment_author_email()));
$gcachetime = 40320 * 60; // 40320 = 4 Weeks
$gimage = $gimagecachedir . "/" . $gravatar_hash . ".png";
if (!file_exists($gimage) || (time() - $gcachetime > filemtime($gimage))) {
    ob_start();
    $grav_img = "http://www.gravatar.com/avatar/" . $gravatar_hash . "?s=" . $gimagesize . "&d=" . $mailnotfound . "&r=G";
 
    if(extension_loaded('curl')) {
        $gch = @curl_init();
        $gcurl_options = array(
            CURLOPT_URL => $grav_img,
            CURLOPT_HEADER => false,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 20,
            CURLOPT_BINARYTRANSFER => is_resource($file),
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 2
        );
        @curl_setopt_array($gch, $gcurl_options);
 
        $gdata = @curl_exec($gch);    
        @curl_close ($gch);
        unset($gch);
    } else {
        ob_start();
        $gfilehandle_url = fopen($grav_img, "rb");
        fpassthru($gfilehandle_url);
        fclose($gfilehandle_url);
        $gdata = ob_get_contents();
        ob_end_clean();
        unset($gfilehandle_url);
    }
    $gfilehandle_img = fopen($gimage, "wb+");
    fwrite($gfilehandle_img, $gdata);
    fclose($gfilehandle_img);
    unset($gfilehandle_img);
    unset($gdata);
}
echo "<img src='" . $gimageurldomain . $gravatar_hash . ".png' height='" . $gimagesize . "' width='" . $gimagesize . "'>";
?>

Über die Einstellungen im Kopf des Codes kann man nun das Cacheverzeichnis festlegen. Die darauffolgende URL ist die URL, so wie sie zum Bild zeigen würde. Darunter befindet sich die Größe.

Die konkreten Änderungen gegenüber der Version des Blogs:

  • Übersetzung des Codes auf Englisch (sorry, ich steh da drauf)
  • Cleanup, Entfernung überflüssiger Codestücke
  • Einbau von Curl als präferierte Downloadoption
  • Entfernung der Erstellung von HTML-Dateien, da dies nicht benötigt wird

Soweit so gut. Nun habe ich noch das CronJob-Script von diesem Blogeintrag auf infoblog.li kurz aufgeräumt:

<?php 
// Script originally from:
// http://infoblog.li/wordpress-gravatar-cache-mit-automatischer-aktualisierung/
//
// Modified by Uli from https://wolf-u.li:
// - Translation
// - Cleanup
// - Added curl
 
// Modify the settings below according to your needs:
 
// Path to the cache-directory of the gravatar images:
$imagecachedir 		= "blog/cdn-g/";
 
// Size of the gravatar-images:
$imagesize = 64;
 
// Update files older than this time:
$maxcacheage = 604800; // 7 * 24 * 3600 = 7 Days
 
// If the mailadress was not found, you can get various images:
// - identicon
// - monsterid
// - wavatar
$mailnotfound = "identicon";
 
// Do not modify the code below:
$handle= opendir($imagecachedir);
while ($file = readdir ($handle))
{
	// Einzelne Pfade und Dateinamen auslesen
	$gravatar_hash              =   substr($file, 0, 32);
	$gravatarimg                = 	$imagecachedir . $file ;
 
	if ($gravatar_hash != ".." && $gravatar_hash != ".")
	{
		// Update only if timestamp of the file is older than $maxcacheage
		$cachedtime = filemtime($gravatarimg) - time();
 
		if ($cachedtime > $maxcacheage)
		{
			$grav_img = "http://www.gravatar.com/avatar/".$gravatar_hash."?s=" . $imagesize . "&d=" . $mailnotfound . "&r=G";
			if(extension_loaded('curl')) {
			    $ch = @curl_init();
    			$curl_options = array(
    				CURLOPT_URL => $grav_img,
    				CURLOPT_HEADER => false,
    				CURLOPT_RETURNTRANSFER => true,
    				CURLOPT_TIMEOUT => 20,
    				CURLOPT_BINARYTRANSFER => true,
    				CURLOPT_FOLLOWLOCATION => true,
    				CURLOPT_MAXREDIRS => 2
    			);
    			@curl_setopt_array($ch, $curl_options);
 
    			$data = @curl_exec($ch);    
    			@curl_close ($ch);
    			unset($ch);
			} else {
			    ob_start();
			    $filehandle_url = fopen($grav_img, "rb");
			    fpassthru($filehandle_url);
			    fclose($filehandle_url);
			    $data = ob_get_contents();
			    ob_end_clean();
			    unset($filehandle_url);
      }
      $filehandle_img = fopen($gravatarimg, "wb+");
			fwrite($filehandle_img, $data);
			fclose($filehandle_img);
			unset($filehandle_img);
			unset($data);
		}
	}
}
closedir($handle);

Was macht dieses Script? Es aktualisiert alle 7 Tage die Gravatars, die bereits im Cache liegen. Auch dieses Script wurde auf curl umgestellt und ein bisschen aufgeräumt. Ich rate dazu, das Script wenigstens alle Stunde einmal ausführen zu lassen, um die Anzahl der gleichzeitig zu aktualisierenden Gravatare so gering wie möglich zu halten. Dies kann entweder per lokalem CronJob, oder einem CronJob-Dienst aus dem Internet wie beispielsweise cronjob.de ausgeführt werden (HowTo für letzteren Fall).

Meine letzten Hinweise zur Performance: Man sollte sich im klaren sein, dass bei größeren Kommentaranzahlen (sagen wir mal 300) auch bei jedem Kommentar geprüft wird, ob die Datei vorhanden ist (d.h. 300 Dateisystemaufrufe). Das kann definitiv bremsen.

Daher habe ich mir eine andere Methode der Auslieferung überlegt, welche ich in einem weiteren Artikel beschreiben werde.

Veröffentlicht von

Uli

IT-Nerd und Admin

9 Gedanken zu „Auslieferung von Gravatar-Icons aus einem lokalen Cache – Download per curl“

  1. So …. jetzt will ich mich hier auch nochmlas zu Wort melden und mich recht herzlich für die Überarbeitung bedanken.

    Das hier vorliegende Script benutze ich in leicht abgewandelter Form, um die per tinthumb generierten Artikelbilder auf der Startseite zu cachen. Die tinthumb.php ist dazu da, um das statische Artikelbild jeweils für die verschiedenen Ansichten zurechtzuschneiden (Artikelansicht, STartseite, Suchseite, etc.) Das gab einen richtigen Schub von rund einer Sekunde und weitere Vorteile. Die tinthumb-Bilder haben keine Dateiendung; liegen in der Form tinthumb&source=xxx vor. nun sind es png-Dateien, die auch vom Browser gecached werden können.

    Ich bin begeistert. Lediglich für die Vorschaubildchen 45×45 im „Featured-Bereich“ ist es mir nicht gelungen, da diese in einer Schleife liegen. Da hört mein Verständnis auf.

    Herzlichen Dank nochmals und viele Grüße aus Käfertal.
    Oliver

  2. Pingback: WordPress GravatarCache | www.patrick-gotthard.de

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.