WBB 2.3.6 und PHP 5.6 *Updated 02.03.2016*

Hallo,

zur Abwechslung mal wieder ein ernster Beitrag.
Das Woltlab Burning Board 2 wird nicht jünger, hingegen wird PHP immer älter.
Kurzum: Diese alte Software funktioniert nicht mehr auf neuen PHP-Versionen und muss daher angepasst werden.

fire - kill0rz.com

Normalerweise bringt Michael Schüler von speedyservice.de immer gute Anleitungen heraus, doch leider ist seine Anleitung zu PHP 5.5 fehlerhaft.
Ich zeige euch heute wie ihr euer Forum so anpasst, dass es unter PHP 5.5 und 5.6 läuft. Dies ist nötig, weil heute Debian 8 aka Jessie stable wurde und dort PHP 5.6 vorinstalliert ist.

Zunächst noch der Hinweis, dass diese Anleitung im allgemeinen auch für alle möglichen anderen Scripte gilt, hier jedoch explizite Anweisungen für das WBB 2.3.6.
Auch noch mal der Hinweis, dass ich keine Garantie auf nichts gebe. Jeder ist für sein Handeln selbst verantwortlich, Backup machen, niemals in der Produktivumgebung die Änderungen ausführen, wenn diese noch nicht getestet sind. Ihr wisst bescheid!

Zunächst machen wir uns das Leben einfacher und laden alle .php-Dateien in der Struktur auf dem Server auf unsere lokale Festplatte. Das hat den signifikanten Vorteil, dass wir jede Änderung nur einmal (genau genommen zwei mal :P) machen müssen und schnell neue Änderungen prüfen können.
Als nächstes suchen wir uns einen geeigneten Texteditor, Notepad++ dürften wohl die meisten kennen, SublimeText ist aber besser, wenn man schon mal damit gearbeitet hat. Auf jeden Fall muss er Ersetzungen in Dateien durchführen können.

Nun lesen wir uns zunächst mal den Changelog zu PHP 5.5 durch und merken schnell, dass uns vor allem die mysql-Funktionen und der /e Identifier Probleme bereiten werden. Bei PHP 5.6 sollte es keine weiteren Probleme geben.
Wir ersetzen alle mysql-Funktionen durch ihren Nachfolger, die mysqli-Funktionen. Die bringen nicht nur wesentlich mehr Geschwindigkeit, sondern auch noch Sicherheit mit sich. Viele Davon erwarten einfach nur einen mysqli-Link als ersten Parameter, allerdings drehen sich bei anderen die Parameter rum. Knifflig.

Alles klar, ich zeige euch das am Beispiel Notepad++, weil das sicher die meisten verwenden werden.
Drücken wir zunächst Strg+H und wechseln in den Reiter „In Dateien suchen“.

notepad++_vorbereitung

In den Filter schreiben wir vorsichtshalber *.php rein, und im Verzeichnis geben wir das Verzeichnis an, in das wir unsere Dateien geladen haben.
In das Feld „Suchen nach“ können wir spaßeshalber mal den Suchbegriff mysql_ eingeben und sehen all das, was wir jetzt bearbeiten wollen.
Der signifikante Vorteil an dieser Methode ist, dass wir auch Hacks und Add-Ons mit anpassen.
Fangen wir also an:

Suche nach:

@mysql_list_fields($sqldb, $tabelle);

Ersetze durch:

fire - kill0rz.com
mysqli_query($db, "SHOW COLUMNS FROM {$tabelle}");

Suche nach:

mysql_list_tables($sqldb);

Ersetze durch:

$db->query("SHOW TABLES FROM ".$sqldb);

Suche nach:

$this->link_id = @mysql_connect($this->server, $this->user, $this->password);

Ersetze durch:

$this->link_id = mysqli_connect($this->server, $this->user, $this->password, $this->database);

Suche nach:

@mysql_select_db($this->database, $this->link_id)

Ersetze durch:

mysqli_select_db($this->link_id, $this->database)

Suche nach:

mysql_error(

Ersetze durch:

mysqli_error($db

Suche nach:

mysql_errno(

Ersetze durch:

mysqli_errno($db

Suche nach:

@mysql_field_name(

Ersetze durch:

mysqli_fetch_field_direct(

Suche nach:

mysql_num_rows(

Ersetze durch:

mysqli_num_rows(

Suche nach:

mysql_query(

Ersetze durch:

mysqli_query($db,

Sucht nun zunächst im Quelltext nach

mysql_unbuffered_query(

. Mit einem Doppelklick in Notepad++ gelangt ihr direkt zur Zeile in der jeweiligen Datei (alle Ergebnisse einzeln öffnen). Dort ersetzt ihr die schließende Klammer ( ) ) durch

, MYSQLI_USE_RESULT)

Jetzt könnt ihr folgende Ersetzung durchführen:
Suche nach:

mysql_unbuffered_query(

Ersetze durch:

mysqli_query($db,

Suche nach:

mysql_fetch_array(

Ersetze durch:

mysqli_fetch_array(

Suche nach:

mysql_fetch_row(

Ersetze durch:

mysqli_fetch_row(

Suche nach:

mysql_affected_rows(

Ersetze durch:

mysqli_affected_rows(

Suche nach:

mysql_insert_id(

Ersetze durch:

mysqli_insert_id(

Suche nach:

mysql_data_seek(

Ersetze durch:

mysqli_data_seek(

Suche nach:

mysql_fetch_array(

Ersetze durch:

mysqli_fetch_array(

Suche nach:

mysql_fetch_object(

Ersetze durch:

mysqli_fetch_object(

Suche nach:

mysql_real_escape_string(

Ersetze durch:

mysqli_real_escape_string($db,

Suche nach:

mysql_fetch_assoc(

Ersetze durch:

mysqli_fetch_assoc(

Suche nach:

MYSQL_ASSOC

Ersetze durch:

MYSQLI_ASSOC

Nachdem wir das erledigt haben, gehen wir nun in die Datei acp/lib/class_db.php und bearbeiten diese nach dem o.g. Muster (mit den Ersetzungen haben wir diese nämlich zerschossen und reparieren sie jetzt wieder):

Suche nach:

$this->query_id = mysqli_query($db,$query_string, $this->link_id);

Ersetze durch:

$this->query_id = mysqli_query($this->link_id, $query_string);

Suche nach:

if ($query_id != -1)

Ersetze durch:

if ($query_id <> false)

Suche nach:

mysqli_error($db);

Ersetze durch:

mysqli_error($this->link_id);

Suche nach:

mysqli_errno($db);

Ersetze durch:

mysqli_errno($this->link_id);

Abschließend sollten wir noch einmal eine Suche in allen Dateien durchführen nach dem String mysql_. Wir sollten nun nur noch ausgeklammerten Code als Treffer erhalten.
Sollte das nicht der Fall sein, müssen die anderen Funktionen per Hand geändert werden. Oftmals ist dies der Fall, wenn Entwickler zwischen Funktionsnamen und Klammer ein Leerzeichen setzen. So finden wir etwa im Pinwand-Hack die Zeile

mysql_data_seek ($result, $i);

, welche durch di o.g. Ersetzungen nicht angepasst wurde.

Außerdem ist per php.net der /e-Modifier veraltet; konkret geht es um folgende Zeile in der acp/lib/functions.php:

$post = preg_replace('/&#(3[2-9]|[4-9][0-9]|\d{3});/e', "chr(intval('\\1'))", $post);

Wir müssen diese Funktion also zu einem Aufruf der preg_replace_callback() umwandeln. In etwa so:

$post = preg_replace_callback('/&#(3[2-9]|[4-9][0-9]|\d{3});/', function($teetewazhere) { return chr(intval($teetewazhere[1])); }, $post);

Ihr erkennt, von wem die Funktion kommt? 😀

Außerdem ersetzen wir noch folgende Zeilen:

acp/users.php und acp/otherstuff.php

Suche: preg_replace("/(\d+)~/e", "getday('\\1')", $statdate);

Ersetze durch:

preg_replace_callback("/(\d+)~/", function($m) { return getday($m[1]); }, $statdate);
Suche: preg_replace("/(\d+)~/e", "getmonth('\\1')", $statdate);

Ersetze durch:

preg_replace_callback("/(\d+)~/", function($m) { return getmonth($m[1]); }, $statdate);

Danach die .php-Dateien wieder hochladen und testen. Es sollten keine Fehler auftreten. Inwieweit der /e-Modifier unter 5.6 Probleme macht kann ich nicht sagen, unter 5.5 verhindert er allerdings nicht die Ausführung.

Ich hoffe, ich konnte euch helfen. Für alle Hinweise bin ich dankbar.
kill0rz

//Update 26.04.2015

Vielen Dank an Schrimm für ungefragte Hinweise und Korrekturen.
Für diejenigen, die die Änderungen schon durchgeführt haben: Im Artikel Durchgestrichenes rückgängig machen und die weiteren Ersetzungen des /e-Modifier durchführen.

//Update 27.04.2015

Eine weitere Fehlerbehebung durch Schrimm betrifft die Funktion mysqli_fetch_field_direct():
Diese Funktion gibt uns ein Objekt zurück anstatt eines Strings, sodass unter jedem Vorkommen noch eine Zeile hinzufügen müssen. Beispiel: Wir haben folgende Zeile im Quelltext:

$feldname = mysqli_fetch_field_direct($res, $i);

Dann ergänzen wir darunter die Zeile:

$feldname = $feldname->name; 

Nach diesem Muster machen wir das bei jedem Vorkommen.

Außerdem habe ich einen Hinweis bei der Funktion mysql_unbuffered_query hinzugefügt.

//Update 03.05.2015

Der /e-Modifier kommt ja noch öfter vor, meine Fresse 😀

acp/lib/class_parsecode.php und acp/lib/class_parse.php:

Suche nach:

$post = preg_replace("/(\[(php|code)\])(.*)(\[\/\\2\])/seiU", "\$this->cachecode('\\3','\\2')", $post);

Ersetze durch:

$post = preg_replace_callback("/(\[(php|code)\])(.*)(\[\/\\2\])/siU", function($m) { return $this->cachecode($m[3], $m[2]); }, $post);

//Update 12.05.2015

Weiter geht’s; wieder zwei Verbesserungen von Schrimm:

acp/lib/class_templateparser.php

Suche nach:

$code = preg_replace('!<if\((.*)\)>!sieU', '"\".((".$this->stripSlashes(\'\\1\').") "', $code);</if>

Ersetze durch: $code = preg_replace_callback('!!siU', function($m) { return $this->stripSlashes($m[1]);}, $code); (s. Update vom 14.02.2016)

Suche nach:

$code = preg_replace('!<expression>(.*)</expression>!sieU', '"\".".$this->stripSlashes(\'\\1\').".\""', $code);

Ersetze durch: $code = preg_replace_callback('!(.*)!siU', function($m) { return $this->stripSlashes($m[1]);}, $code); (s. Update vom 14.02.2016)

// Update 14.02.2016

Nach einem dreiviertel Jahr mal ein Update 😉
Zunächst einmal ein Design-Update, sieht jetzt besser aus. 😉

Dann müssen noch die letzten beiden regulären Ausdrücke geändert werden. Ich habe es oben gekennzeichnet. Bitte so umbauen:

Suche nach:

$code = preg_replace('!<if\((.*)\)>!sieU', '"\".((".$this->stripSlashes(\'\\1\').") "', $code);</if>

Ersetze durch:

$code = preg_replace_callback('!<if\((.*)\)>!siU', function($matches) { return '".(('.$this->stripSlashes($matches[1]).') ';}, $code);

Suche nach:

$code = preg_replace('!<expression>(.*)</expression>!sieU', '"\".".$this->stripSlashes(\'\\1\').".\""', $code);

Ersetze durch:

$code = preg_replace_callback('!<expression>(.*)</expression>!siU', function($matches) { return '".'.$this->stripSlashes($matches[1]).'."';}, $code);

Außerdem habe wir hier noch folgendes zu machen (auch alles nochmal Inhalt meiner Anleitung zum WBB2 unter PHP 7):

/acp/lib/class_zip.php
Suche:

$date = ereg_replace($regexp, "\\1-\\2-\\3-\\4-\\5-\\6", $date);

Ersetze mit:

$date = preg_replace($regexp, "\\1-\\2-\\3-\\4-\\5-\\6", $date);

(siehe hierzu bitte das Update vom 02.03.2016!)

/acp/shoutbox.php (Offenbar ein Hack, also optional)
Suche:

$ereza = ereg_replace(",","", $groupwerte);

Ersetze mit:

$ereza = preg_replace("/,/","", $groupwerte);

Suche überall nach (insbesondere in /acp/group.php, /acp/lib/admin_functions.php, /acp/lib/functions.php und /acp/style.php):

MYSQL_BOTH

Ersetze mit:

MYSQLI_BOTH

/acp/lib/class_parse.php
Suche:

var $search = array();
var $replace = array();
var $replace2 = array();

Füge darunter ein:

var $search_replace = array();
var $search_replace2 = array();

Suche:

$this->search[] = "/\[list=(&quot;|['\"]?)([^\"']+)\\1](.+)\[\/list((=\\1[^\"']+\\1])|(\]))/esiU";
$this->replace[] = "\$this->formatlist('\\3', '\\2')";
$this->search[] = "/\[list](.+)\[\/list\]/esiU";
$this->replace[] = "\$this->formatlist('\\1')";
$this->search[] = "/\[url=("|['\"]?)([^\"']+)\\1](.+)\[\/url\]/esiU";
$this->replace[] = "\$this->formaturl('\\2','\\3')";
$this->search[] = "/\[url]([^\"\[]+)\[\/url\]/eiU";
$this->replace[] = "\$this->formaturl('\\1')";

Ersetze mit:

$this->search_replace['/\[list=("|[\'"]?)([^"\']+)\1](.+)\[\/list((=\1[^"\']+\1])|(\]))/siU'] = function($matches) { return $this->formatlist($matches[3],$matches[2]);};
$this->search_replace['/\[list](.+)\[\/list\]/siU'] = function($matches) { return $this->formatlist($matches[1]);};
$this->search_replace['/\[url=("|[\'"]?)([^"\']+)\1](.+)\[\/url\]/siU'] = function($matches) { return $this->formaturl($matches[2],$matches[3]);};
$this->search_replace['/\[url]([^"\[]+)\[\/url\]/iU'] = function($matches) { return $this->formaturl($matches[1]);};

Suche:

$this->replace2[] = "'$this->breakChar[list=\\1$this->breakChar\\2$this->breakChar\\1]$this->breakChar'.\$this->stripSlashes('\\3').'$this->breakChar[/list=\\1$this->breakChar\\2$this->breakChar\\1]$this->breakChar'"; 
$this->replace2[] = "'$this->breakChar[list]$this->breakChar'.\$this->stripSlashes('\\1').'$this->breakChar[/list]$this->breakChar'"; 
$this->replace2[] = "'$this->breakChar[url=\\1$this->breakChar'.\$this->insertBreakChar('\\2').'$this->breakChar\\1]$this->breakChar'.\$this->stripSlashes('\\3').'$this->breakChar[/url]$this->breakChar'";
$this->replace2[] = "'$this->breakChar[url]$this->breakChar' . \$this->insertBreakChar('\\1') . '$this->breakChar[/url]$this->breakChar'";

Ersetze mit:

$this->search_replace2['/\[list=(&quot;|[\'"]?)([^"\']+)\1](.+)\[\/list((=\1[^"\']+\1])|(\]))/siU'] = function($matches) { return $this->breakChar.'[list='.$matches[1].$this->breakChar.$matches[2].$this->breakChar.$matches[1].']'.$this->breakChar.$this->stripSlashes($matches[3]).$this->breakChar.'[/list='.$matches[1].$this->breakChar.$matches[2].$this->breakChar.$matches[1].']'.$this->breakChar;};
$this->search_replace2['/\[list](.+)\[\/list\]/siU'] = function($matches) { return $this->breakChar.'[list]'.$this->breakChar.$this->stripSlashes($matches[1]).$this->breakChar.'[/list]'.$this->breakChar;};
$this->search_replace2['/\[url=(&quot;|[\'"]?)([^"\']+)\1](.+)\[\/url\]/siU'] = function($matches) { return $this->breakChar.'[url='.$matches[1].$this->breakChar.$this->insertBreakChar($matches[2]).$this->breakChar.$matches[1].']'.$this->breakChar.$this->stripSlashes($matches[3]).$this->breakChar.'[/url]'.$this->breakChar;};
$this->search_replace2['/\[url]([^"\[]+)\[\/url\]/iU'] = function($matches) { return $this->breakChar.'[url]'.$this->breakChar.$this->insertBreakChar($matches[1]).$this->breakChar.'[/url]'.$this->breakChar;};

Suche:

if ($allowdynimg == 1) $this->imgsearch2 = "/\[img]([^\"]+)\[\/img\]/esiU";
else $this->imgsearch2 = "/\[img]([^\"\?\&]+\.(gif|jpg|jpeg|bmp|png))\[\/img\]/esiU";
$this->imgreplace2 = "'$this->breakChar[img]$this->breakChar' . \$this->insertBreakChar('\\1') . '$this->breakChar[/img]$this->breakChar'";

Ersetze mit:

if ($allowdynimg == 1) $this->imgsearch2 = "/\[img]([^\"]+)\[\/img\]/siU";
else $this->imgsearch2 = "/\[img]([^\"\?\&]+\.(gif|jpg|jpeg|bmp|png))\[\/img\]/siU";
$this->imgreplace2 = function($matches) { return $this->breakChar.'[img]'.$this->breakChar.$this->insertBreakChar($matches[1]).$this->breakChar.'[/img]'.$this->breakChar;};

/acp/lib/functions.php
Suche:

preg_replace("%\[url\]".$threadid_pattern."\[/url\]%ieU", "\$catched_threadids[]=\\3;", $message);
preg_replace("%\[url\]".$postid_pattern."\[/url\]%ieU", "\$catched_postids[]=\\3;", $message);

Ersetze mit:

preg_replace_callback("%\[url\]".$threadid_pattern."\[/url\]%iU", function($matches) use (&$catched_threadids) { $catched_threadids=$matches[3];}, $message);
preg_replace_callback("%\[url\]".$postid_pattern."\[/url\]%iU", function($matches) use (&$catched_postids) { $catched_postids=$matches[3];}, $message);

Suche:

if (count($threadcache)) {
	// insert topics
	$message = preg_replace("%\[url\]".$threadid_pattern."\[/url\]%ieU", "makeLocalLink('\\1',\\3)", $message);
	$message = preg_replace("%\[url\]".$postid_pattern."\[/url\]%ieU", "makeLocalLink('\\1',\\3,1)", $message);
}

Ersetze mit:

if (count($threadcache)) {
	// insert topics
	$message = preg_replace_callback("%\[url\]".$threadid_pattern."\[/url\]%iU", function($matches) { return makeLocalLink($matches[1],$matches[3]);},$message);
	$message = preg_replace_callback("%\[url\]".$postid_pattern."\[/url\]%iU", function($matches) { return makeLocalLink($matches[1],$matches[3],1);}, $message);
}

//Update 23.02.2016

Habe die Passage mit den

mysql_unbuffered_query(

verständlicher formuliert.

//Update 02.03.2016

Die Zeile

$this->search[] = "/\[list=(&quot;|['\"]?)([^\"']+)\\1](.+)\[\/list((=\\1[^\"']+\\1])|(\]))/esiU";

muss auch entfernt werden; oben korrigiert.

Weiterhin: Habe die Zeile

$date = preg_replace($regexp, "\\1-\\2-\\3 \\4:\\5:\\6", $date);

zu

$date = preg_replace($regexp, "\\1-\\2-\\3-\\4-\\5-\\6", $date);

korrigiert.
Schrimm hat dazu sogar noch eine Codeoptimierung rausgehauen:
Suche nach:

$date = date("Y-m-d H:i:s", $date);

$regexp = "([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})";
$date = ereg_replace($regexp, "\\1-\\2-\\3-\\4-\\5-\\6", $date);
$date_array = explode("-", $date);

(hier gff. preg_replace suchen)

Ersetze mit:

$date = date("Y-m-d-H-i-s", $date);
$date_array = explode("-", $date);

Außerdem habe ich noch zwei Ersetzungen von regulären Ausdrücken entfernt, da diese die Funktion preg_replace_callback nutzten. Die gibt es aber erst ab php 7. Wenn möglich gleich dahin durchmarschieren.

This entry was posted in Allgemein, Internet, kill0rz, self-coded, Tutorials, Updated, WBB. Bookmark the permalink.

Schreibe einen Kommentar

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

Bitte löse die Rechnung! * Time limit is exhausted. Please reload CAPTCHA.