Onlinebox und Serverzeit Problematik (Version A-O)

Eingetragen von Rock@wulf am Do, 18. Apr 2013 - 19:08


Wie man hier immer mehr zu lesen bekommt, gibt es viele Probleme mit einer nicht richtig funktionierenden Onlinebox aufgrund von falsch konfigurierten Serverzeiten.

Nun generell laufen alle Server wenn man sie installiert auf UTC/GMT/ZULU Zeit da diese Zeit weltweit immer gleich ist. Allerdings gibt es dann Zeitunterschiede zu den Anwendern die natürlich Ihre Zeit auf dem PC eingestellt haben. Bei uns in Deutschland ist das normalerweise MEZ/MET/ALFA Zeit (ZULU +1h) da wir noch die "unnützige" Sommerzeit haben ist das in Sommerzeitmonaten
MESZ/MEST/ALFA (ZULU +2h). Ich hoffe das ist nun jedem soweit klar.

Warum hat die Onlinebox damit ein Problem wieso tut sie nicht das was Sie soll?

Nun defakto macht die box haar genau das was sie soll. Sie ist nicht defekt kaputt und man muss auch nicht panisch nach Hilfe schreien.

Um das Problem zu erkennen, müssen wir ersteinmal verstehen, was die Online Box/ Funktion tut:

<?php
if (!defined('main')) {die("no direct access");}
$dif = date('Y-m-d H:i:s', time() - 60);
$abf = "SELECT uid FROM `prefix_online` WHERE uptime > '". $dif."'";
$resultID = db_query($abf);
$brk='';
$uid = array();
$guests = 0;
$guestn = $lang['guests'];
$content='';

while ($row = db_fetch_object($resultID)) {
	if ($row->uid != 0 AND $brk!=$row->uid) {
		$name=@db_result(db_query('SELECT name FROM prefix_user WHERE id='.$row->uid),0);
		$content.= '<tr><td><img src="include/images/icons/online.gif" border="0" alt="online"></td>';
		$content.='<td><a href="index.php?user-details-'.$row->uid.'">'.$name.'</a></td></tr>'."\n";
		$uid[] = $row->uid;
	}
	if ($row->uid == 0) { $guests++; }
	$brk=$row->uid;
}
if ($guests == 1) { $guestn = $lang['guest']; }
if (empty($content)) { $content.='<tr><td><img src="include/images/icons/offline.gif"  border="0" alt="offline"></td><td><font color="#003366">0 User </font></td></tr>'."\n"; }

$content.='<tr><td colspan="2"><hr style="height: 0px; border: dashed #9AB1C8 0px; border-top-width: 1px;"></td></tr>'."\n";
$where = (count($uid)>0) ? 'WHERE id NOT IN ('.implode(', ', $uid).')' : '';
$abf2 = 'SELECT * FROM prefix_user '.$where.' ORDER BY llogin DESC LIMIT 0,5';
$erg2 = db_query($abf2);

while ($row2 = db_fetch_object($erg2)) {
	$datum = date('H:i d.m.y',$row2->llogin);
	$user = $row2->name;
	$content.='<tr><td><img src="include/images/icons/offline.gif"  border="0" alt="offline"></td><td><a href="index.php?user-details-'.$row2->id.'" title="'.$lang['lasttimeonline'].$datum.'">'.$user.'</a></td></tr>'."\n";
}
if ($guests == 0) {
	$content.= '<tr><td colspan="2"><hr style="height: 0px; border: dashed #9AB1C8 0px; border-top-width: 1px";></td></tr>'."\n".'
		<tr><td><img src="include/images/icons/offline.gif"  border="0" alt="offline"></td><td><font size="-1" color="#003366">0 '.$lang['guests'].'</td></tr>'."\n";
} else {
	$content.= '<tr><td colspan="2"><hr style="height: 0px; border: dashed #9AB1C8 0px; border-top-width: 1px;"></td></tr>'."\n".'
		<tr><td><img src="include/images/icons/online.gif" border="0" alt="online"></td><td><font size=-1>'.$guests.' '.$guestn.'</font></td></tr>'."\n";
}
?>
<table align="center" border="0" cellpadding="0" cellspacing="0" >
 <?php echo $content; ?>
</table>


Hier werden alle Benutzer Identifikationsnummern aus der Tabelle Online ausgelesen deren Onlinezeit größer der Aktuellen Zeit abzüglich von 60 Sekunden ist.
Ok da klingt erstmal soweit logisch, aber woher weiß das Skript wer seit wann online ist und woher kommen die Einträge in der Online Tabelle… Die Antwort findet sich in der folgenden Datei:

function user_update_database () {
  $dif = date('Y-m-d H:i:s', time() - 7200);
  db_query("UPDATE prefix_online SET uptime = now() WHERE sid = '".session_id()."'");
  db_query("DELETE FROM prefix_online WHERE uptime < '". $dif."'");
  if ( loggedin() ) {
    db_query("UPDATE prefix_user SET llogin = '".time()."' WHERE id = '".$_SESSION['authid']."'");
  }
}


Hier wird die Online Tabelle mit den ersten Daten und auch den Zeitschlüsseln gefüttert. Wichtig hierbei ist das der eingetragene Zeitschlüssel (Zeile 51) der MYSQL Funktion now() entnommen wir, also die aktuelle Zeit des MYSQL Servers. Erstmal soweit kein Problem hier.
Die Zeilen 50 & 52 Sorgen dafür das die Online Tabelle bei jedem Aufrufen der Funktion aufgeräumt wird, das verhindert Datenmüll und Tausende Einträge in der Tabelle aber hier ist genau das Problem. Denn hier wird mit der Zeit des PHP-Servers abzüglich der Differenz von 7200 Sekunden (2h) der Zeitdifferenzwert berechnet, der zur Löschung der Einträge führt.
Mann kann jetzt diskutieren ob es sinnvoll ist einmal PHP Zeit und gleichzeitig MySQL Zeit zu nutzen.
Allerdings ist das nicht Sinn und Zweck des FAQ Eintrages ! Allerdings werde ich mich hier für eine Korrektur in folgenden Versionen Stark machen.
So wie beheben wir das ganze jetzt.
Ich gehe jetzt mal davon aus das wir einen Korrekt funktionierenden PHP-Server haben aber einen MySQL Server der eben „vergessen“ worden ist korrekt einzustellen.
Das sieht dann so aus:

PHP Zeit 2013-04-18 09:34:10
SQL Zeit 2013-04-18 07:34:10

Wenn ich jetzt nochmal über das eben erläuterte nachdenke, fällt mir auf PHP Zeit – 2h = Löschung aus der Datenbank. Wobei mit der SQL Zeit verglichen wird. Hoppala schon haben wir eine Bedingung die immer wahr ist doof.
Bevor wir jetzt wie wild im PHP-Code rumfingern prüfen wir ersteinmal zwei dinge:
In der index.php sollte sich die Zeile

date_default_timezone_set('Europe/Berlin')


befinden. Wenn nicht gibt es im Thema
Fehler und Lösungen für PHP 5.3
Eine Anleitung wie es behoben wird.Und ich empfehle auch dringend diese Anpassungen durchzuführen.
So damit haben wir sichergestellt, das wir unsere Aktuelle Zeitzone als PHP Zeit nutzen, moment aber da war schon so… Richtig nun sind wir aber sicher das es immer so ist zwinker
Jetzt kümmern wir uns um unsere MySql Zeit.
Dazu rufen wir die folgende php datei auf:

function db_connect () {
  if (defined('CONN')) {
    return;
  }
  define ( 'CONN', @mysql_pconnect(DBHOST, DBUSER, DBPASS));
  $db = @mysql_select_db(DBDATE, CONN);
  
  if (!CONN) {
    die('Verbindung nicht möglich, bitte prüfen Sie ihre mySQL Daten wie Passwort, Username und Host<br />');
  }
  if ( !$db ) {
    die ('Kann Datenbank "'.DBDATE.'" nicht benutzen : ' . mysql_error(CONN));
  }
}


Hier fügen wir das folgende ein:

mysql_query("SET `time_zone` = '".date('P')."'");


Nachdem wir die Datei gespeichert und wieder hochgeladen haben, sollten alle Zeitbasierten Funktionen egal ob PHP oder MySQL wieder die gleiche Zeit haben. Also sollte auch die OnlineBox wieder funktionieren.
Ich hoffe ich konnte weiterhelfen
Grüße
Rock@wulf