<?php
/**
* Tail
*
* liesst eine Datei Zeilenweise aus
* und wartet auf aenderungen.
*
* @author Aron Schlesinger <as@paefchen.net>
* @version 1.0
* @license BSDL
* @php 5
* @cvs $paefchen$
*
* Example:
* $tail = new Tail('/var/log/access.log', 20);
* $tail->go();
* if ($tail->error())
* die($tail->getError());
**/
class Tail {
private $fh;
private $file;
private $linelength;
private $error = '';
/**
* __construct
*
* constructer, pruefft ob die Datei lesbar ist und setzt
* oefnet die Datei und setzt den Zeiger an die richtige stelle.
*
* @public
*
* @para file string Datei die gelesen werden soll
* @para lines int Zeilen die vom ende gelsen werden sollen.
* @para linelength int Max. laenge einer Zeile
**/
public function __construct($file, $lines = 5, $linelength = 1014) {
$this->open($file);
if (! $this->error())
$this->setLine($lines);
$this->linelength = (int)$linelength;
}
/**
* __destruct
*
* destructer, schliesst die Datei
*
* @public
**/
public function __destruct() {
@fclose($this->fh);
}
/**
* line
*
* liesst und wartet auf Zeilen
*
* @public
* @return string zeile
**/
public function line() {
if ($this->error())
return false;
$line = '';
while (true) {
clearstatcache();
if (ftell($this->fh) == filesize($this->file))
sleep(1);
else {
$c = fgetc($this->fh);
if (strlen($line) <= $this->linelength)
$line .= $c;
if ($c == "\n")
break;
}
}
return $line;
}
/**
* open
*
* oeffnet eine Datei
*
* @private
* @para file string Datei die geoeffnet werden soll.
* @return bool
**/
private function open($file) {
if (! is_readable($file)) {
$this->error = sprintf('File %s not readable', $file);
return false;
}
$this->fh = @fopen($file, 'r');
if (! $this->fh) {
$this->error = sprintf('fopen() make error on file %s', $file);
return false;
}
$this->file = $file;
}
/**
* setLine
*
* setzt den Zeiger vom ende aus gesehen
* auf dem anfang der gewuenschte Zeile
*
* @private
* @para line int Zeile von hinten aus
* @return bool
**/
private function setLine($line) {
fseek($this->fh, -1, SEEK_END);
$p = ftell($this->fh);
while ($line > 0) {
if ($p === 0)
break;
fseek($this->fh, --$p, SEEK_SET);
if (fgetc($this->fh) == "\n")
$line--;
}
}
/**
* go
*
* @public
**/
public function go() {
if ($this->error())
return false;
if (isset($_SERVER['REQUEST_METHOD'])) {
set_time_limit(0);
header('Content-type: text/plain');
header('Cache-Control: no-store, no-cache');
}
ob_implicit_flush(1);
while ($line = $this->line()) {
if (isset($_SERVER['REQUEST_METHOD'])
&& connection_status() > 0)
exit;
print $line;
}
}
/* Error Methods */
public function error() { return empty($this->error) ? false : true; }
public function getError() { return $this->error; }
}
?>