docker-tmserver/xaseco/includes/ogg_comments.inc.php

155 lines
4.7 KiB
PHP
Raw Normal View History

2022-06-26 17:43:44 +02:00
<?php
/* vim: set noexpandtab tabstop=2 softtabstop=2 shiftwidth=2: */
/**
* Ogg_Comments - Extract comments (ID3 tags) from .ogg files
* Created by Xymph <tm@gamers.org>
* Derived from Ogg.class.php v1.3e by Nicolas Ricquemaque <f1iqf@hotmail.com>
* For more info see: http://opensource.grisambre.net/ogg/
* Ogg format: http://en.wikipedia.org/wiki/Ogg
* Comments : http://www.xiph.org/vorbis/doc/v-comment.html
*
* v1.1: Improved get_1block URL parsing; added User-Agent to the GET request
* v1.0: Initial release
*/
define('BLOCKSIZE', 512);
class Ogg_Comments {
public $comments = array();
/**
* Fetches all comments from a .ogg local file or URL
*
* @param String $path
* The .ogg file or URL
* @param Boolean $utf8
* If true, return fields in UTF-8, otherwise in ASCII/ISO-8859-1
* @return Ogg_Comments
* If $comments is empty, no .ogg file
*/
public function Ogg_Comments($path, $utf8 = false) {
// check for local file or URL
if (strpos($path, '://') === false) {
if (!$fp = @fopen($path, 'rb'))
return false;
$file = fread($fp, BLOCKSIZE);
fclose($fp);
if ($file === false)
return false;
} else {
$file = $this->get_1block($path);
if ($file === false || $file == -1)
return false;
}
// read OGG pages
for ($pos = 0; ($pos = strpos($file, 'OggS', $pos)) !== false; $pos++) {
// check stream version
if (ord($file[$pos+4]) != 0)
continue;
// compute offset of packet after header
$offset = $pos + 27 + ord($file[$pos+26]);
// check for second (== comments) packet
if ($this->read_intle($file, $pos+18) == 1) {
// check for vorbis comments
if (ord($file[$offset]) != 0x03 ||
substr($file, $offset+1, 6) != 'vorbis')
continue;
// read vendor string
$offset += 7;
$vndlen = $this->read_intle($file, $offset);
$this->comments['VENDOR'] = $this->decode_field(substr($file, $offset+4, $vndlen), $utf8);
// read comments count
$offset += 4 + $vndlen;
$cmtcnt = $this->read_intle($file, $offset);
// read/parse all comment fields
$offset += 4;
for ($i = 0; $i < $cmtcnt; $i++) {
$cmtlen = $this->read_intle($file, $offset);
$comment = substr($file, $offset+4, $cmtlen);
$offset += 4 + $cmtlen;
// store field name=value pair
$comment = explode('=', $comment, 2);
// check for repeated field & append
if (isset($this->comments[strtoupper($comment[0])]))
$this->comments[strtoupper($comment[0])] .= ', ' . $this->decode_field($comment[1], $utf8);
else
$this->comments[strtoupper($comment[0])] = $this->decode_field($comment[1], $utf8);
}
}
// check whether done
if (isset($this->comments['VENDOR']))
break;
}
} // Ogg_Comments
// Read 32-bits Little Endian integer
private function read_intle(&$buf, $pos) {
return (ord($buf[$pos+0]) + (ord($buf[$pos+1]) << 8) +
(ord($buf[$pos+2]) << 16) + (ord($buf[$pos+3]) << 24));
} // read_intle
// Decode comment field into specified charset
private function decode_field($str, $utf8) {
if ($utf8)
// return UTF8 or encode it in UTF8
return ((utf8_encode(utf8_decode($str)) == $str) ?
$str : utf8_encode($str));
else
// decode it to ASCII or return ASCII
return ((utf8_encode(utf8_decode($str)) == $str) ?
utf8_decode($str) : $str);
} // decode_field
// Simple HTTP Get 1 Block function with timeout
// ok: return string || error: return false || timeout: return -1
private function get_1block($url) {
$url = parse_url($url);
$port = isset($url['port']) ? $url['port'] : 80;
$query = isset($url['query']) ? '?' . $url['query'] : '';
$fp = @fsockopen($url['host'], $port, $errno, $errstr, 4);
if (!$fp)
return false;
$uri = '';
foreach (explode('/', $url['path']) as $subpath)
$uri .= rawurlencode($subpath) . '/';
$uri = substr($uri, 0, strlen($uri)-1); // strip trailing '/'
fwrite($fp, 'GET ' . $uri . $query . " HTTP/1.0\r\n" .
'Host: ' . $url['host'] . "\r\n" .
'User-Agent: Ogg_Comments (' . PHP_OS . ")\r\n\r\n");
stream_set_timeout($fp, 2);
$res = '';
$info['timed_out'] = false;
for ($i = 0; $i < 2; $i++)
if (feof($fp) || $info['timed_out']) {
break;
} else {
$res .= fread($fp, BLOCKSIZE);
$info = stream_get_meta_data($fp);
}
fclose($fp);
if ($info['timed_out']) {
return -1;
} else {
if (substr($res, 9, 3) != '200')
return false;
$page = explode("\r\n\r\n", $res, 2);
return trim($page[1]);
}
} // get_1block
} // class Ogg_Comments
?>