Kategorie-Archiv: PHP

Piwik-Bug bei Output-Compression

Nach dem Update von Piwik (eine OpenSource Software zum Erstellen von Besucherstatistiken auf Websites) auf die aktuelle Version 1.1.1 stellte ich fest, dass das Design vollständig zerschossen war und auch die JS-Dateien nicht mehr geladen werden konnten. Genauer: es wurde noch alles geladen allerdings enthielten all diese Dateien nur noch seltsam anmutende Zeichen. Ein genauerer Blick verriet, dass es sich hier um doppelt gepackte Serverausgaben handelte.

Da mein Server von sich aus alles komprimiert (per gzip) was auszugeben ist – inkl. aller von PHP generierten Inhalte, lag es nahe zu vermuten, dass Piwik selbst ebenfalls noch einmal zur Tat schreitet. In der zentralen Klasse „Piwik“ (core/Piwik.php) Zeilen 664 und 665 findet sich der Auslöser:

$zlibOutputCompression = ini_get('zlib.output_compression');
$phpOutputCompressionEnabled = !empty($zlibOutputCompression);

Hier wird offensichtlich nur eine von mehreren Möglichkeiten der Ausgabe-Komprimierung geprüft. Ergebnis: für alle anderen möglichen Einstellungen wird die interne Kompression im nachfolgenden else-Zweig aktiv und somit doppelt komprimiert. Um das zu umgehen habe ich meine eigene config mit geprüft – heraus gekommen ist nun folgendes:

$zlibOutputCompression = ini_get('zlib.output_compression');
$outputHandler = ini_get('output_handler');
$phpOutputCompressionEnabled = (!empty($zlibOutputCompression) || $outputHandler == 'ob_gzhandler');

Mit diesem Fix läuft Piwik jetzt für mich wieder problemlos.

PHP-Bug im Vergleichsoperator == ?

Heute habe ich, zusammen mit einem Kollegen, feststellen müssen dass der Vergleichsoperator scheinbar ein Typecasting bei Vergleichen zwischen (etwaigen) Integerwerten und Strings vornimmt – und zwar immer zu Integer-Werten. Das hat zur Folge, dass Vergleiche mit „0“ mit einem String „abc“ zu einer wahren Aussage führen. Bei uns hat das eine „kleine“ Sicherheitslücke gerissen, die alles andere als schön war. Das ganze lässt sich unter Debian mit der PHP-Version 5.2.6-0.1~lenny1 und folgendem Code nachvollziehen:

$a = 0;
$b = "abdbbsb";
 
if($a == $b) echo 1;
else echo 0;
# Ausgabe 1

if((string)$a == $b) echo 1;
else echo 0;
# Ausgabe 0

if($a === $b) echo 1;
else echo 0;
# Ausgabe 0

Automatische Spracherkennung in PHP

Da ich es bisher schon ein paar Projekten benötigt habe, möchte ich hier ein kleines Script zur Ermittlung der vom Benutzer (bzw. Browser) gewünschten Sprache veröffentlichen. Es geht dabei nicht darum anhand der Benutzereingaben oder der geografischen Herkunft des Benutzers die Sprache zu ermitteln, sondern nur anhand der übermittelten Browserdaten. Natürlich hat dieses Verfahren den Nachteil, dass wenn keine vernünftige Anforderung durch den Browser erfolgt, eine Standardsprache verwendet werden muss. Andererseits wird dem Benutzer auch nicht auf Grund der Herkunft seiner IP-Adresse, die nicht mit seiner tatsächlichen Herkunft übereinstimmen muss, eine x-beliebige Sprachversion der Website vorgesetzt wird. Der Code bedarf denke ich über die schon vorhandenen Kommentare hinaus keiner weiteren Erläuterung.

// set $requested_language = "" for security reasons (activated register globals or what ever else)
$requested_language = "";
// first step: check if this is allready done
if (!isset($_SESSION["language"]))
{
	// second step - check if something usefull had been committed
	if(isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]) && $_SERVER["HTTP_ACCEPT_LANGUAGE"] != "")
	{
		// get the iso-code for the requested language - mostly these are the first alphabethical and decimal signs)
		$requested_language = preg_split("/[\W]+/",$_SERVER["HTTP_ACCEPT_LANGUAGE"], 2);
		$requested_language[0] = strtolower($requested_language[0]);
	}
	// set the language, if the first signs are alphabetical or decimal and if there is a language-file in the given folder
	if (preg_match('/^[\w]{2,3}$/', $requested_language[0]) && is_file(BACKEND_PATH."config/languages/".$requested_language[0].".php")) 
	{
		$_SESSION["language"] = $requested_language[0];
	}
	// otherwise set the DEFAULT_LANGUAGE - you will have to set this somewhere else (e.g.: define("DEFAULT_LANGUAGE", "de"))
	else 
	{
		$_SESSION["language"] = DEFAULT_LANGUAGE;
	}
}
// include the language-file - in this case the containing array $langVar have all the language-vars
require_once (CONFIG_PATH."languages/".$_SESSION["language"].".php");

Loadbalancing für MySQL (-Slaves)

Dieser Artikel im Blog eines Kollegen hat mich dazu veranlasst mir den verwendeten Algorithmus mal ein wenig näher anzusehen und zu überarbeiten – und ihn zumindest in Sachen Speicherbedarf zu verbessern. Heraus gekommen ist folgendes:

function getSlave($cluster)
{
        // gibt es nur einen Server im Array, wird dieser zurückgeliefert
        if(count($databaseClusters[$cluster]) == 1) {
                return "master";
        }
        else {
                $sum = 0;
                foreach($databaseClusters[$cluster] as $slave) {
                        $sum += $slave["prio"];
                }
                $randomVal = rand(0, $sum);
                if($randomVal < $sum / 2) {
                        $i = 0;
                        $tmpSum = 0;
                        while($tmpSum < $randomVal) {
                                  $tmpSum += $databaseClusters[$cluster]["slave$i"]["prio"];
                                  $i++;
                        }
                }
                else {
                        $i = count($databaseClusters[$cluster]);
                        $tmpSum = $sum;
                        while($tmpSum < $randomVal) {
                                $tmpSum -= $databaseClusters[$cluster]["slave$i"]["prio"];
                                $i--;
                        }
                }
 
                return "slave$i";
        }
}

Herausgekommen ist dadurch zwar eine längere aber im Allgemeinen speicherschonendere Methode um Datenbankqueries zu verteilen. Um weitere Informationen zu erhalten lest bitte bei meinem Kollegen weiter.

SVN mit JavaHL unter Windows

Im Rahmen einiger privater, als auch in Projekten für meinen Arbeitgeber setze ich in eclipse Subclipse für die Versionsverwaltung ein. Bisher war das an meinem Windows-PC nur in Verbindung mit dem (viel zu langsamen) SVNKIT möglich. Um das schnellere JavaHL einzusetzen muss man leider ein klein wenig „tricksen“. Hier nun eine kurze Anleitung wie es dennoch möglich ist:

1. Installation von subclipse wie auf subclipse.tigris.org beschrieben

2. Herunterladen und installieren von tortoisesvn (zu finden hier: tortoisesvn.net)

3. Nach dem Systemneustart (tortoisesvn erfordert diesen leider scheinbar) die Datei [Laufwerk]:\Dokumente und Einstellungen\[Aktueller Benutzername]\Anwendungsdaten\Subversion\config bearbeiten (Achtung: die doppelten Backslashes sind wichtig!):

3.1 nach „[tunnels]“ suchen
3.2 darunter einfügen (Mit public/private-key): ssh = [Laufwerk]:\\Programme\\TortoiseSVN\\bin\\TortoisePlink.exe -i "[Laufwerk]:\\[Pfad zum Keyfile]"
—-> sollte kein Key verfügbar sein, einfach den Parameter „-i“ mit allem was danach kommt weg lassen
3.3 speichern und schließen 😉

4. In eclipse in „Window“ -> „Preferences“ -> „Team“ -> „SVN“ unter „SVN Interface“ JavaHL auswählen und darunter („Configuration Location“) „Use Directory“ auswählen. Dort dann den Pfad zur Subversion-Config eintragen (s. Punkt 2), abschließend auf „Apply“ und/oder „Ok“ klicken und fertig. Ab jetzt könnt ihr JavaHL verwenden.

Hinweise zur Erstellung des Key-Files:
Hierfür bietet sich insbesondere das Tool „PUTTYgen“ das beim Putty dabei ist an – hat man bereits einen unter Linux erstellten Public/Private-Key kann man den hier in das unter Windows benötigte Format umwandeln. Putty gibt es unter anderem hier: PUTTY-Download

Diese Beschreibung sollte so auf allen eclipse-Plattformen (wie zum Beispiel auch Aptana Studio) ab eclipse-Version 3.2 funktionieren – wahrscheinlich auch schon früher.

PHP 5.2.5 veröffentlicht (Update)

Am 08.11. (also am Donnerstag) wurde eine neue Version von PHP veröffentlicht. Die aktuelle Version ist somit 5.2.5. Es wurden in diesem Release keine neuen Funktionen hinzugefügt sondern etwa 60 Bugs behoben, von denen ein paar SIcherheitsrelevant sind. Für die Behandlung von regulären Ausdrücken bringt PHP 5.2.5 PCRE 7.3 mit..

Hier eine Liste der sicherheitsrelevanten Änderungen (englisch – zitiert von PHP.net):

  • Fixed dl() to only accept filenames. Reported by Laurent Gaffie.
  • Fixed dl() to limit argument size to MAXPATHLEN (CVE-2007-4887). Reported by Laurent Gaffie.
  • Fixed htmlentities/htmlspecialchars not to accept partial multibyte sequences. Reported by Rasmus Lerdorf
  • Fixed possible triggering of buffer overflows inside glibc implementations of the fnmatch(), setlocale() and glob() functions. Reported by Laurent Gaffie.
  • Fixed „mail.force_extra_parameters“ php.ini directive not to be modifiable in .htaccess due to the security implications. Reported by SecurityReason.
  • Fixed bug #42869 (automatic session id insertion adds sessions id to non-local forms).
  • Fixed bug #41561 (Values set with php_admin_* in httpd.conf can be overwritten with ini_set()).

Eine vollständige Liste der Änderungen findet ihr hier: ChangeLog

12.11.07: Artikel bei golem.

PHP-Entwicklung – Neuerungen in PHP, Zend-Framework, PHP-Sicherheit

(Fortsetzung von: PHP-Entwicklung – Umstieg von 4 auf 5 sowie 5 auf 6)

Auf Golem wurde bereits am Freitag der zweite Teil des Interviews mit veröffentlicht, darin kamen unter anderem die Neuerungen in PHP6 noch einmal mehr zur Sprache.Ich werde daher heute eine „Liste“ der Neuerungen mit einer kurzen Erklärung dazu hier veröffentlichen (angelehnt an den genannten (und verlinkten) Artikel auf golem.de). Im Weiteren werde ich noch auf die Themen Sicherheit in PHP und das Zend-Framework eingehen. PHP-Entwicklung – Neuerungen in PHP, Zend-Framework, PHP-Sicherheit weiterlesen