<?php
define('RANGE_PCRE', '/bytes=(\d*)-(\d*)/si');
class RecoverStream {
var $ErrNo = -1;
var $ErrStr = '';
var $BufferSize = -1;
function RecoverStream() {
$this->__constructor();
}
function __constructor() {
$_SERVER['HTTP_RANGE'] = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : '';
$this->BufferSize = 512 * 1024; // 512Kb
}
function Error(&$errno, &$errstr) {
$errno = $this->ErrNo;
$errstr = $this->ErrStr;
return ($this->ErrNo !== -1);
}
function HandleAndExit() {
if ($this->Handle()) {
exit();
}
return false;
}
function Handle() {
$this->ErrNo = -1;
$this->ErrStr = '';
$offset = 0;
$length = 0;
if (preg_match(RANGE_PCRE, $_SERVER['HTTP_RANGE'], $matches)) {
if (($matches[1] !== '') && ($matches[2] !== '')) {
$offset = $matches[1];
$length = $matches[2] + 1;
} elseif ($matches[1] !== '') {
$offset = $matches[1];
$length = $this->ContentLength() - $matches[1];
} else { // if ($matches[2] !== '') {
$offset = $this->ContentLength() - $matches[2];
$length = $matches[2];
}
} else {
$offset = 0;
$length = $this->ContentLength();
}
if ($this->Open()) {
if ($this->Seek($offset)) {
$headers = $this->AdditionalHeaders();
foreach ($headers as $header) {
if (is_array($header) && isset($header['header']) && isset($header['replace'])) {
header($header['header'], $header['replace']);
} else {
header($header);
}
}
header('Content-Type: ' . $this->ContentType());
header('Content-Length: ' . $length);
while ($length > $this->BufferSize) {
$content = $this->Read($this->BufferSize);
if ($content !== false) {
echo($content);
} else {
return false;
}
$length = $length - $this->BufferSize;
}
$content = $this->Read($length);
if ($content !== false) {
echo($content);
} else {
return false;
}
return $this->Close();
}
}
return false;
}
// abstract
function AdditionalHeaders() {
// RecoverStream::AdditionalHeaders() method COULD be overwritten!
return array();
}
// abstract
function Open() {
// RecoverStream::Open() method COULD be overwritten!
return true;
}
// abstract
function Close() {
// RecoverStream::Close() method COULD be overwritten!
return true;
}
// abstract
function Seek($offset) {
die('RecoverStream::Seek() method MUST be overwritten!');
}
// abstract
function Read($length) {
die('RecoverStream::Read() method MUST be overwritten!');
}
// abstract
function ContentType() {
die('RecoverStream::ContentType() method MUST be overwritten!');
}
// abstract
function ContentLength() {
die('RecoverStream::ContentLength() method MUST be overwritten!');
}
}
?>