Rekording SoundMap DSS2016 v0.1
This commit is contained in:
commit
00817140dd
208
api/getID3/extension.cache.dbm.php
Executable file
208
api/getID3/extension.cache.dbm.php
Executable file
@ -0,0 +1,208 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// extension.cache.dbm.php - part of getID3() //
|
||||
// Please see readme.txt for more information //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This extension written by Allan Hansen <ahØartemis*dk> //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* This is a caching extension for getID3(). It works the exact same
|
||||
* way as the getID3 class, but return cached information very fast
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Normal getID3 usage (example):
|
||||
*
|
||||
* require_once 'getid3/getid3.php';
|
||||
* $getID3 = new getID3;
|
||||
* $getID3->encoding = 'UTF-8';
|
||||
* $info1 = $getID3->analyze('file1.flac');
|
||||
* $info2 = $getID3->analyze('file2.wv');
|
||||
*
|
||||
* getID3_cached usage:
|
||||
*
|
||||
* require_once 'getid3/getid3.php';
|
||||
* require_once 'getid3/getid3/extension.cache.dbm.php';
|
||||
* $getID3 = new getID3_cached('db3', '/tmp/getid3_cache.dbm',
|
||||
* '/tmp/getid3_cache.lock');
|
||||
* $getID3->encoding = 'UTF-8';
|
||||
* $info1 = $getID3->analyze('file1.flac');
|
||||
* $info2 = $getID3->analyze('file2.wv');
|
||||
*
|
||||
*
|
||||
* Supported Cache Types
|
||||
*
|
||||
* SQL Databases: (use extension.cache.mysql)
|
||||
*
|
||||
* cache_type cache_options
|
||||
* -------------------------------------------------------------------
|
||||
* mysql host, database, username, password
|
||||
*
|
||||
*
|
||||
* DBM-Style Databases: (this extension)
|
||||
*
|
||||
* cache_type cache_options
|
||||
* -------------------------------------------------------------------
|
||||
* gdbm dbm_filename, lock_filename
|
||||
* ndbm dbm_filename, lock_filename
|
||||
* db2 dbm_filename, lock_filename
|
||||
* db3 dbm_filename, lock_filename
|
||||
* db4 dbm_filename, lock_filename (PHP5 required)
|
||||
*
|
||||
* PHP must have write access to both dbm_filename and lock_filename.
|
||||
*
|
||||
*
|
||||
* Recommended Cache Types
|
||||
*
|
||||
* Infrequent updates, many reads any DBM
|
||||
* Frequent updates mysql
|
||||
*/
|
||||
|
||||
|
||||
class getID3_cached_dbm extends getID3
|
||||
{
|
||||
|
||||
// public: constructor - see top of this file for cache type and cache_options
|
||||
public function getID3_cached_dbm($cache_type, $dbm_filename, $lock_filename) {
|
||||
|
||||
// Check for dba extension
|
||||
if (!extension_loaded('dba')) {
|
||||
throw new Exception('PHP is not compiled with dba support, required to use DBM style cache.');
|
||||
}
|
||||
|
||||
// Check for specific dba driver
|
||||
if (!function_exists('dba_handlers') || !in_array($cache_type, dba_handlers())) {
|
||||
throw new Exception('PHP is not compiled --with '.$cache_type.' support, required to use DBM style cache.');
|
||||
}
|
||||
|
||||
// Create lock file if needed
|
||||
if (!file_exists($lock_filename)) {
|
||||
if (!touch($lock_filename)) {
|
||||
throw new Exception('failed to create lock file: '.$lock_filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Open lock file for writing
|
||||
if (!is_writeable($lock_filename)) {
|
||||
throw new Exception('lock file: '.$lock_filename.' is not writable');
|
||||
}
|
||||
$this->lock = fopen($lock_filename, 'w');
|
||||
|
||||
// Acquire exclusive write lock to lock file
|
||||
flock($this->lock, LOCK_EX);
|
||||
|
||||
// Create dbm-file if needed
|
||||
if (!file_exists($dbm_filename)) {
|
||||
if (!touch($dbm_filename)) {
|
||||
throw new Exception('failed to create dbm file: '.$dbm_filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to open dbm file for writing
|
||||
$this->dba = dba_open($dbm_filename, 'w', $cache_type);
|
||||
if (!$this->dba) {
|
||||
|
||||
// Failed - create new dbm file
|
||||
$this->dba = dba_open($dbm_filename, 'n', $cache_type);
|
||||
|
||||
if (!$this->dba) {
|
||||
throw new Exception('failed to create dbm file: '.$dbm_filename);
|
||||
}
|
||||
|
||||
// Insert getID3 version number
|
||||
dba_insert(getID3::VERSION, getID3::VERSION, $this->dba);
|
||||
}
|
||||
|
||||
// Init misc values
|
||||
$this->cache_type = $cache_type;
|
||||
$this->dbm_filename = $dbm_filename;
|
||||
|
||||
// Register destructor
|
||||
register_shutdown_function(array($this, '__destruct'));
|
||||
|
||||
// Check version number and clear cache if changed
|
||||
if (dba_fetch(getID3::VERSION, $this->dba) != getID3::VERSION) {
|
||||
$this->clear_cache();
|
||||
}
|
||||
|
||||
parent::getID3();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public: destructor
|
||||
public function __destruct() {
|
||||
|
||||
// Close dbm file
|
||||
dba_close($this->dba);
|
||||
|
||||
// Release exclusive lock
|
||||
flock($this->lock, LOCK_UN);
|
||||
|
||||
// Close lock file
|
||||
fclose($this->lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public: clear cache
|
||||
public function clear_cache() {
|
||||
|
||||
// Close dbm file
|
||||
dba_close($this->dba);
|
||||
|
||||
// Create new dbm file
|
||||
$this->dba = dba_open($this->dbm_filename, 'n', $this->cache_type);
|
||||
|
||||
if (!$this->dba) {
|
||||
throw new Exception('failed to clear cache/recreate dbm file: '.$this->dbm_filename);
|
||||
}
|
||||
|
||||
// Insert getID3 version number
|
||||
dba_insert(getID3::VERSION, getID3::VERSION, $this->dba);
|
||||
|
||||
// Re-register shutdown function
|
||||
register_shutdown_function(array($this, '__destruct'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public: analyze file
|
||||
public function analyze($filename) {
|
||||
|
||||
if (file_exists($filename)) {
|
||||
|
||||
// Calc key filename::mod_time::size - should be unique
|
||||
$key = $filename.'::'.filemtime($filename).'::'.filesize($filename);
|
||||
|
||||
// Loopup key
|
||||
$result = dba_fetch($key, $this->dba);
|
||||
|
||||
// Hit
|
||||
if ($result !== false) {
|
||||
return unserialize($result);
|
||||
}
|
||||
}
|
||||
|
||||
// Miss
|
||||
$result = parent::analyze($filename);
|
||||
|
||||
// Save result
|
||||
if (file_exists($filename)) {
|
||||
dba_insert($key, serialize($result), $this->dba);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
171
api/getID3/extension.cache.mysql.php
Executable file
171
api/getID3/extension.cache.mysql.php
Executable file
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// extension.cache.mysql.php - part of getID3() //
|
||||
// Please see readme.txt for more information //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This extension written by Allan Hansen <ahØartemis*dk> //
|
||||
// Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* This is a caching extension for getID3(). It works the exact same
|
||||
* way as the getID3 class, but return cached information very fast
|
||||
*
|
||||
* Example: (see also demo.cache.mysql.php in /demo/)
|
||||
*
|
||||
* Normal getID3 usage (example):
|
||||
*
|
||||
* require_once 'getid3/getid3.php';
|
||||
* $getID3 = new getID3;
|
||||
* $getID3->encoding = 'UTF-8';
|
||||
* $info1 = $getID3->analyze('file1.flac');
|
||||
* $info2 = $getID3->analyze('file2.wv');
|
||||
*
|
||||
* getID3_cached usage:
|
||||
*
|
||||
* require_once 'getid3/getid3.php';
|
||||
* require_once 'getid3/getid3/extension.cache.mysql.php';
|
||||
* // 5th parameter (tablename) is optional, default is 'getid3_cache'
|
||||
* $getID3 = new getID3_cached_mysql('localhost', 'database', 'username', 'password', 'tablename');
|
||||
* $getID3->encoding = 'UTF-8';
|
||||
* $info1 = $getID3->analyze('file1.flac');
|
||||
* $info2 = $getID3->analyze('file2.wv');
|
||||
*
|
||||
*
|
||||
* Supported Cache Types (this extension)
|
||||
*
|
||||
* SQL Databases:
|
||||
*
|
||||
* cache_type cache_options
|
||||
* -------------------------------------------------------------------
|
||||
* mysql host, database, username, password
|
||||
*
|
||||
*
|
||||
* DBM-Style Databases: (use extension.cache.dbm)
|
||||
*
|
||||
* cache_type cache_options
|
||||
* -------------------------------------------------------------------
|
||||
* gdbm dbm_filename, lock_filename
|
||||
* ndbm dbm_filename, lock_filename
|
||||
* db2 dbm_filename, lock_filename
|
||||
* db3 dbm_filename, lock_filename
|
||||
* db4 dbm_filename, lock_filename (PHP5 required)
|
||||
*
|
||||
* PHP must have write access to both dbm_filename and lock_filename.
|
||||
*
|
||||
*
|
||||
* Recommended Cache Types
|
||||
*
|
||||
* Infrequent updates, many reads any DBM
|
||||
* Frequent updates mysql
|
||||
*/
|
||||
|
||||
|
||||
class getID3_cached_mysql extends getID3
|
||||
{
|
||||
|
||||
// private vars
|
||||
private $cursor;
|
||||
private $connection;
|
||||
|
||||
|
||||
// public: constructor - see top of this file for cache type and cache_options
|
||||
public function getID3_cached_mysql($host, $database, $username, $password, $table='getid3_cache') {
|
||||
|
||||
// Check for mysql support
|
||||
if (!function_exists('mysql_pconnect')) {
|
||||
throw new Exception('PHP not compiled with mysql support.');
|
||||
}
|
||||
|
||||
// Connect to database
|
||||
$this->connection = mysql_pconnect($host, $username, $password);
|
||||
if (!$this->connection) {
|
||||
throw new Exception('mysql_pconnect() failed - check permissions and spelling.');
|
||||
}
|
||||
|
||||
// Select database
|
||||
if (!mysql_select_db($database, $this->connection)) {
|
||||
throw new Exception('Cannot use database '.$database);
|
||||
}
|
||||
|
||||
// Set table
|
||||
$this->table = $table;
|
||||
|
||||
// Create cache table if not exists
|
||||
$this->create_table();
|
||||
|
||||
// Check version number and clear cache if changed
|
||||
$version = '';
|
||||
if ($this->cursor = mysql_query("SELECT `value` FROM `".mysql_real_escape_string($this->table)."` WHERE (`filename` = '".mysql_real_escape_string(getID3::VERSION)."') AND (`filesize` = '-1') AND (`filetime` = '-1') AND (`analyzetime` = '-1')", $this->connection)) {
|
||||
list($version) = mysql_fetch_array($this->cursor);
|
||||
}
|
||||
if ($version != getID3::VERSION) {
|
||||
$this->clear_cache();
|
||||
}
|
||||
|
||||
parent::getID3();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public: clear cache
|
||||
public function clear_cache() {
|
||||
|
||||
$this->cursor = mysql_query("DELETE FROM `".mysql_real_escape_string($this->table)."`", $this->connection);
|
||||
$this->cursor = mysql_query("INSERT INTO `".mysql_real_escape_string($this->table)."` VALUES ('".getID3::VERSION."', -1, -1, -1, '".getID3::VERSION."')", $this->connection);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// public: analyze file
|
||||
public function analyze($filename) {
|
||||
|
||||
if (file_exists($filename)) {
|
||||
|
||||
// Short-hands
|
||||
$filetime = filemtime($filename);
|
||||
$filesize = filesize($filename);
|
||||
|
||||
// Lookup file
|
||||
$this->cursor = mysql_query("SELECT `value` FROM `".mysql_real_escape_string($this->table)."` WHERE (`filename` = '".mysql_real_escape_string($filename)."') AND (`filesize` = '".mysql_real_escape_string($filesize)."') AND (`filetime` = '".mysql_real_escape_string($filetime)."')", $this->connection);
|
||||
if (mysql_num_rows($this->cursor) > 0) {
|
||||
// Hit
|
||||
list($result) = mysql_fetch_array($this->cursor);
|
||||
return unserialize(base64_decode($result));
|
||||
}
|
||||
}
|
||||
|
||||
// Miss
|
||||
$analysis = parent::analyze($filename);
|
||||
|
||||
// Save result
|
||||
if (file_exists($filename)) {
|
||||
$this->cursor = mysql_query("INSERT INTO `".mysql_real_escape_string($this->table)."` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES ('".mysql_real_escape_string($filename)."', '".mysql_real_escape_string($filesize)."', '".mysql_real_escape_string($filetime)."', '".mysql_real_escape_string(time())."', '".mysql_real_escape_string(base64_encode(serialize($analysis)))."')", $this->connection);
|
||||
}
|
||||
return $analysis;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// private: (re)create sql table
|
||||
private function create_table($drop=false) {
|
||||
|
||||
$this->cursor = mysql_query("CREATE TABLE IF NOT EXISTS `".mysql_real_escape_string($this->table)."` (
|
||||
`filename` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`filesize` INT(11) NOT NULL DEFAULT '0',
|
||||
`filetime` INT(11) NOT NULL DEFAULT '0',
|
||||
`analyzetime` INT(11) NOT NULL DEFAULT '0',
|
||||
`value` TEXT NOT NULL,
|
||||
PRIMARY KEY (`filename`,`filesize`,`filetime`)) ENGINE=MyISAM", $this->connection);
|
||||
echo mysql_error($this->connection);
|
||||
}
|
||||
}
|
264
api/getID3/extension.cache.sqlite3.php
Executable file
264
api/getID3/extension.cache.sqlite3.php
Executable file
@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org ///
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// //
|
||||
// extension.cache.sqlite3.php - part of getID3() //
|
||||
// Please see readme.txt for more information //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// //
|
||||
// MySQL extension written by Allan Hansen <ahØartemis*dk> //
|
||||
// Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
|
||||
// MySQL extension was reworked for SQLite3 by Karl G. Holz <newaeonØmac*com> //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* This is a caching extension for getID3(). It works the exact same
|
||||
* way as the getID3 class, but return cached information much faster
|
||||
*
|
||||
* Normal getID3 usage (example):
|
||||
*
|
||||
* require_once 'getid3/getid3.php';
|
||||
* $getID3 = new getID3;
|
||||
* $getID3->encoding = 'UTF-8';
|
||||
* $info1 = $getID3->analyze('file1.flac');
|
||||
* $info2 = $getID3->analyze('file2.wv');
|
||||
*
|
||||
* getID3_cached usage:
|
||||
*
|
||||
* require_once 'getid3/getid3.php';
|
||||
* require_once 'getid3/extension.cache.sqlite3.php';
|
||||
* // all parameters are optional, defaults are:
|
||||
* $getID3 = new getID3_cached_sqlite3($table='getid3_cache', $hide=FALSE);
|
||||
* $getID3->encoding = 'UTF-8';
|
||||
* $info1 = $getID3->analyze('file1.flac');
|
||||
* $info2 = $getID3->analyze('file2.wv');
|
||||
*
|
||||
*
|
||||
* Supported Cache Types (this extension)
|
||||
*
|
||||
* SQL Databases:
|
||||
*
|
||||
* cache_type cache_options
|
||||
* -------------------------------------------------------------------
|
||||
* mysql host, database, username, password
|
||||
*
|
||||
* sqlite3 table='getid3_cache', hide=false (PHP5)
|
||||
*
|
||||
|
||||
*** database file will be stored in the same directory as this script,
|
||||
*** webserver must have write access to that directory!
|
||||
*** set $hide to TRUE to prefix db file with .ht to pervent access from web client
|
||||
*** this is a default setting in the Apache configuration:
|
||||
|
||||
# The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
|
||||
|
||||
<Files ~ "^\.ht">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy all
|
||||
</Files>
|
||||
|
||||
********************************************************************************
|
||||
*
|
||||
* -------------------------------------------------------------------
|
||||
* DBM-Style Databases: (use extension.cache.dbm)
|
||||
*
|
||||
* cache_type cache_options
|
||||
* -------------------------------------------------------------------
|
||||
* gdbm dbm_filename, lock_filename
|
||||
* ndbm dbm_filename, lock_filename
|
||||
* db2 dbm_filename, lock_filename
|
||||
* db3 dbm_filename, lock_filename
|
||||
* db4 dbm_filename, lock_filename (PHP5 required)
|
||||
*
|
||||
* PHP must have write access to both dbm_filename and lock_filename.
|
||||
*
|
||||
* Recommended Cache Types
|
||||
*
|
||||
* Infrequent updates, many reads any DBM
|
||||
* Frequent updates mysql
|
||||
********************************************************************************
|
||||
*
|
||||
* IMHO this is still a bit slow, I'm using this with MP4/MOV/ M4v files
|
||||
* there is a plan to add directory scanning and analyzing to make things work much faster
|
||||
*
|
||||
*
|
||||
*/
|
||||
class getID3_cached_sqlite3 extends getID3 {
|
||||
|
||||
/**
|
||||
* __construct()
|
||||
* @param string $table holds name of sqlite table
|
||||
* @return type
|
||||
*/
|
||||
public function __construct($table='getid3_cache', $hide=false) {
|
||||
$this->table = $table; // Set table
|
||||
$file = dirname(__FILE__).'/'.basename(__FILE__, 'php').'sqlite';
|
||||
if ($hide) {
|
||||
$file = dirname(__FILE__).'/.ht.'.basename(__FILE__, 'php').'sqlite';
|
||||
}
|
||||
$this->db = new SQLite3($file);
|
||||
$db = $this->db;
|
||||
$this->create_table(); // Create cache table if not exists
|
||||
$version = '';
|
||||
$sql = $this->version_check;
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
|
||||
$result = $stmt->execute();
|
||||
list($version) = $result->fetchArray();
|
||||
if ($version != getID3::VERSION) { // Check version number and clear cache if changed
|
||||
$this->clear_cache();
|
||||
}
|
||||
return parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* close the database connection
|
||||
*/
|
||||
public function __destruct() {
|
||||
$db=$this->db;
|
||||
$db->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* hold the sqlite db
|
||||
* @var SQLite Resource
|
||||
*/
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* table to use for caching
|
||||
* @var string $table
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* clear the cache
|
||||
* @access private
|
||||
* @return type
|
||||
*/
|
||||
private function clear_cache() {
|
||||
$db = $this->db;
|
||||
$sql = $this->delete_cache;
|
||||
$db->exec($sql);
|
||||
$sql = $this->set_version;
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':dirname', getID3::VERSION, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':val', getID3::VERSION, SQLITE3_TEXT);
|
||||
return $stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* analyze file and cache them, if cached pull from the db
|
||||
* @param type $filename
|
||||
* @return boolean
|
||||
*/
|
||||
public function analyze($filename) {
|
||||
if (!file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
// items to track for caching
|
||||
$filetime = filemtime($filename);
|
||||
$filesize = filesize($filename);
|
||||
// this will be saved for a quick directory lookup of analized files
|
||||
// ... why do 50 seperate sql quries when you can do 1 for the same result
|
||||
$dirname = dirname($filename);
|
||||
// Lookup file
|
||||
$db = $this->db;
|
||||
$sql = $this->get_id3_data;
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':filesize', $filesize, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
||||
$res = $stmt->execute();
|
||||
list($result) = $res->fetchArray();
|
||||
if (count($result) > 0 ) {
|
||||
return unserialize(base64_decode($result));
|
||||
}
|
||||
// if it hasn't been analyzed before, then do it now
|
||||
$analysis = parent::analyze($filename);
|
||||
// Save result
|
||||
$sql = $this->cache_file;
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':filesize', $filesize, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':atime', time(), SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT);
|
||||
$res = $stmt->execute();
|
||||
return $analysis;
|
||||
}
|
||||
|
||||
/**
|
||||
* create data base table
|
||||
* this is almost the same as MySQL, with the exception of the dirname being added
|
||||
* @return type
|
||||
*/
|
||||
private function create_table() {
|
||||
$db = $this->db;
|
||||
$sql = $this->make_table;
|
||||
return $db->exec($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* get cached directory
|
||||
*
|
||||
* This function is not in the MySQL extention, it's ment to speed up requesting multiple files
|
||||
* which is ideal for podcasting, playlists, etc.
|
||||
*
|
||||
* @access public
|
||||
* @param string $dir directory to search the cache database for
|
||||
* @return array return an array of matching id3 data
|
||||
*/
|
||||
public function get_cached_dir($dir) {
|
||||
$db = $this->db;
|
||||
$rows = array();
|
||||
$sql = $this->get_cached_dir;
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindValue(':dirname', $dir, SQLITE3_TEXT);
|
||||
$res = $stmt->execute();
|
||||
while ($row=$res->fetchArray()) {
|
||||
$rows[] = unserialize(base64_decode($row));
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* use the magical __get() for sql queries
|
||||
*
|
||||
* access as easy as $this->{case name}, returns NULL if query is not found
|
||||
*/
|
||||
public function __get($name) {
|
||||
switch($name) {
|
||||
case 'version_check':
|
||||
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
|
||||
break;
|
||||
case 'delete_cache':
|
||||
return "DELETE FROM $this->table";
|
||||
break;
|
||||
case 'set_version':
|
||||
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
|
||||
break;
|
||||
case 'get_id3_data':
|
||||
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
|
||||
break;
|
||||
case 'cache_file':
|
||||
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
|
||||
break;
|
||||
case 'make_table':
|
||||
return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
|
||||
break;
|
||||
case 'get_cached_dir':
|
||||
return "SELECT val FROM $this->table WHERE dirname = :dirname";
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
1320
api/getID3/getid3.lib.php
Executable file
1320
api/getID3/getid3.lib.php
Executable file
File diff suppressed because it is too large
Load Diff
1800
api/getID3/getid3.php
Executable file
1800
api/getID3/getid3.php
Executable file
File diff suppressed because it is too large
Load Diff
279
api/getID3/module.archive.gzip.php
Executable file
279
api/getID3/module.archive.gzip.php
Executable file
@ -0,0 +1,279 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// See readme.txt for more details //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// module.archive.gzip.php //
|
||||
// module for analyzing GZIP files //
|
||||
// dependencies: NONE //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Module originally written by //
|
||||
// Mike Mozolin <teddybearØmail*ru> //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class getid3_gzip extends getid3_handler {
|
||||
|
||||
// public: Optional file list - disable for speed.
|
||||
public $option_gzip_parse_contents = false; // decode gzipped files, if possible, and parse recursively (.tar.gz for example)
|
||||
|
||||
public function Analyze() {
|
||||
$info = &$this->getid3->info;
|
||||
|
||||
$info['fileformat'] = 'gzip';
|
||||
|
||||
$start_length = 10;
|
||||
$unpack_header = 'a1id1/a1id2/a1cmethod/a1flags/a4mtime/a1xflags/a1os';
|
||||
//+---+---+---+---+---+---+---+---+---+---+
|
||||
//|ID1|ID2|CM |FLG| MTIME |XFL|OS |
|
||||
//+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
if ($info['filesize'] > $info['php_memory_limit']) {
|
||||
$info['error'][] = 'File is too large ('.number_format($info['filesize']).' bytes) to read into memory (limit: '.number_format($info['php_memory_limit'] / 1048576).'MB)';
|
||||
return false;
|
||||
}
|
||||
fseek($this->getid3->fp, 0);
|
||||
$buffer = fread($this->getid3->fp, $info['filesize']);
|
||||
|
||||
$arr_members = explode("\x1F\x8B\x08", $buffer);
|
||||
while (true) {
|
||||
$is_wrong_members = false;
|
||||
$num_members = intval(count($arr_members));
|
||||
for ($i = 0; $i < $num_members; $i++) {
|
||||
if (strlen($arr_members[$i]) == 0) {
|
||||
continue;
|
||||
}
|
||||
$buf = "\x1F\x8B\x08".$arr_members[$i];
|
||||
|
||||
$attr = unpack($unpack_header, substr($buf, 0, $start_length));
|
||||
if (!$this->get_os_type(ord($attr['os']))) {
|
||||
// Merge member with previous if wrong OS type
|
||||
$arr_members[$i - 1] .= $buf;
|
||||
$arr_members[$i] = '';
|
||||
$is_wrong_members = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!$is_wrong_members) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$info['gzip']['files'] = array();
|
||||
|
||||
$fpointer = 0;
|
||||
$idx = 0;
|
||||
for ($i = 0; $i < $num_members; $i++) {
|
||||
if (strlen($arr_members[$i]) == 0) {
|
||||
continue;
|
||||
}
|
||||
$thisInfo = &$info['gzip']['member_header'][++$idx];
|
||||
|
||||
$buff = "\x1F\x8B\x08".$arr_members[$i];
|
||||
|
||||
$attr = unpack($unpack_header, substr($buff, 0, $start_length));
|
||||
$thisInfo['filemtime'] = getid3_lib::LittleEndian2Int($attr['mtime']);
|
||||
$thisInfo['raw']['id1'] = ord($attr['cmethod']);
|
||||
$thisInfo['raw']['id2'] = ord($attr['cmethod']);
|
||||
$thisInfo['raw']['cmethod'] = ord($attr['cmethod']);
|
||||
$thisInfo['raw']['os'] = ord($attr['os']);
|
||||
$thisInfo['raw']['xflags'] = ord($attr['xflags']);
|
||||
$thisInfo['raw']['flags'] = ord($attr['flags']);
|
||||
|
||||
$thisInfo['flags']['crc16'] = (bool) ($thisInfo['raw']['flags'] & 0x02);
|
||||
$thisInfo['flags']['extra'] = (bool) ($thisInfo['raw']['flags'] & 0x04);
|
||||
$thisInfo['flags']['filename'] = (bool) ($thisInfo['raw']['flags'] & 0x08);
|
||||
$thisInfo['flags']['comment'] = (bool) ($thisInfo['raw']['flags'] & 0x10);
|
||||
|
||||
$thisInfo['compression'] = $this->get_xflag_type($thisInfo['raw']['xflags']);
|
||||
|
||||
$thisInfo['os'] = $this->get_os_type($thisInfo['raw']['os']);
|
||||
if (!$thisInfo['os']) {
|
||||
$info['error'][] = 'Read error on gzip file';
|
||||
return false;
|
||||
}
|
||||
|
||||
$fpointer = 10;
|
||||
$arr_xsubfield = array();
|
||||
// bit 2 - FLG.FEXTRA
|
||||
//+---+---+=================================+
|
||||
//| XLEN |...XLEN bytes of "extra field"...|
|
||||
//+---+---+=================================+
|
||||
if ($thisInfo['flags']['extra']) {
|
||||
$w_xlen = substr($buff, $fpointer, 2);
|
||||
$xlen = getid3_lib::LittleEndian2Int($w_xlen);
|
||||
$fpointer += 2;
|
||||
|
||||
$thisInfo['raw']['xfield'] = substr($buff, $fpointer, $xlen);
|
||||
// Extra SubFields
|
||||
//+---+---+---+---+==================================+
|
||||
//|SI1|SI2| LEN |... LEN bytes of subfield data ...|
|
||||
//+---+---+---+---+==================================+
|
||||
$idx = 0;
|
||||
while (true) {
|
||||
if ($idx >= $xlen) {
|
||||
break;
|
||||
}
|
||||
$si1 = ord(substr($buff, $fpointer + $idx++, 1));
|
||||
$si2 = ord(substr($buff, $fpointer + $idx++, 1));
|
||||
if (($si1 == 0x41) && ($si2 == 0x70)) {
|
||||
$w_xsublen = substr($buff, $fpointer + $idx, 2);
|
||||
$xsublen = getid3_lib::LittleEndian2Int($w_xsublen);
|
||||
$idx += 2;
|
||||
$arr_xsubfield[] = substr($buff, $fpointer + $idx, $xsublen);
|
||||
$idx += $xsublen;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$fpointer += $xlen;
|
||||
}
|
||||
// bit 3 - FLG.FNAME
|
||||
//+=========================================+
|
||||
//|...original file name, zero-terminated...|
|
||||
//+=========================================+
|
||||
// GZIP files may have only one file, with no filename, so assume original filename is current filename without .gz
|
||||
$thisInfo['filename'] = preg_replace('#\.gz$#i', '', $info['filename']);
|
||||
if ($thisInfo['flags']['filename']) {
|
||||
while (true) {
|
||||
if (ord($buff[$fpointer]) == 0) {
|
||||
$fpointer++;
|
||||
break;
|
||||
}
|
||||
$thisInfo['filename'] .= $buff[$fpointer];
|
||||
$fpointer++;
|
||||
}
|
||||
}
|
||||
// bit 4 - FLG.FCOMMENT
|
||||
//+===================================+
|
||||
//|...file comment, zero-terminated...|
|
||||
//+===================================+
|
||||
if ($thisInfo['flags']['comment']) {
|
||||
while (true) {
|
||||
if (ord($buff[$fpointer]) == 0) {
|
||||
$fpointer++;
|
||||
break;
|
||||
}
|
||||
$thisInfo['comment'] .= $buff[$fpointer];
|
||||
$fpointer++;
|
||||
}
|
||||
}
|
||||
// bit 1 - FLG.FHCRC
|
||||
//+---+---+
|
||||
//| CRC16 |
|
||||
//+---+---+
|
||||
if ($thisInfo['flags']['crc16']) {
|
||||
$w_crc = substr($buff, $fpointer, 2);
|
||||
$thisInfo['crc16'] = getid3_lib::LittleEndian2Int($w_crc);
|
||||
$fpointer += 2;
|
||||
}
|
||||
// bit 0 - FLG.FTEXT
|
||||
//if ($thisInfo['raw']['flags'] & 0x01) {
|
||||
// Ignored...
|
||||
//}
|
||||
// bits 5, 6, 7 - reserved
|
||||
|
||||
$thisInfo['crc32'] = getid3_lib::LittleEndian2Int(substr($buff, strlen($buff) - 8, 4));
|
||||
$thisInfo['filesize'] = getid3_lib::LittleEndian2Int(substr($buff, strlen($buff) - 4));
|
||||
|
||||
$info['gzip']['files'] = getid3_lib::array_merge_clobber($info['gzip']['files'], getid3_lib::CreateDeepArray($thisInfo['filename'], '/', $thisInfo['filesize']));
|
||||
|
||||
if ($this->option_gzip_parse_contents) {
|
||||
// Try to inflate GZip
|
||||
$csize = 0;
|
||||
$inflated = '';
|
||||
$chkcrc32 = '';
|
||||
if (function_exists('gzinflate')) {
|
||||
$cdata = substr($buff, $fpointer);
|
||||
$cdata = substr($cdata, 0, strlen($cdata) - 8);
|
||||
$csize = strlen($cdata);
|
||||
$inflated = gzinflate($cdata);
|
||||
|
||||
// Calculate CRC32 for inflated content
|
||||
$thisInfo['crc32_valid'] = (bool) (sprintf('%u', crc32($inflated)) == $thisInfo['crc32']);
|
||||
|
||||
// determine format
|
||||
$formattest = substr($inflated, 0, 32774);
|
||||
$getid3_temp = new getID3();
|
||||
$determined_format = $getid3_temp->GetFileFormat($formattest);
|
||||
unset($getid3_temp);
|
||||
|
||||
// file format is determined
|
||||
$determined_format['module'] = (isset($determined_format['module']) ? $determined_format['module'] : '');
|
||||
switch ($determined_format['module']) {
|
||||
case 'tar':
|
||||
// view TAR-file info
|
||||
if (file_exists(GETID3_INCLUDEPATH.$determined_format['include']) && include_once(GETID3_INCLUDEPATH.$determined_format['include'])) {
|
||||
if (($temp_tar_filename = tempnam(GETID3_TEMP_DIR, 'getID3')) === false) {
|
||||
// can't find anywhere to create a temp file, abort
|
||||
$info['error'][] = 'Unable to create temp file to parse TAR inside GZIP file';
|
||||
break;
|
||||
}
|
||||
if ($fp_temp_tar = fopen($temp_tar_filename, 'w+b')) {
|
||||
fwrite($fp_temp_tar, $inflated);
|
||||
fclose($fp_temp_tar);
|
||||
$getid3_temp = new getID3();
|
||||
$getid3_temp->openfile($temp_tar_filename);
|
||||
$getid3_tar = new getid3_tar($getid3_temp);
|
||||
$getid3_tar->Analyze();
|
||||
$info['gzip']['member_header'][$idx]['tar'] = $getid3_temp->info['tar'];
|
||||
unset($getid3_temp, $getid3_tar);
|
||||
unlink($temp_tar_filename);
|
||||
} else {
|
||||
$info['error'][] = 'Unable to fopen() temp file to parse TAR inside GZIP file';
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '':
|
||||
default:
|
||||
// unknown or unhandled format
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Converts the OS type
|
||||
public function get_os_type($key) {
|
||||
static $os_type = array(
|
||||
'0' => 'FAT filesystem (MS-DOS, OS/2, NT/Win32)',
|
||||
'1' => 'Amiga',
|
||||
'2' => 'VMS (or OpenVMS)',
|
||||
'3' => 'Unix',
|
||||
'4' => 'VM/CMS',
|
||||
'5' => 'Atari TOS',
|
||||
'6' => 'HPFS filesystem (OS/2, NT)',
|
||||
'7' => 'Macintosh',
|
||||
'8' => 'Z-System',
|
||||
'9' => 'CP/M',
|
||||
'10' => 'TOPS-20',
|
||||
'11' => 'NTFS filesystem (NT)',
|
||||
'12' => 'QDOS',
|
||||
'13' => 'Acorn RISCOS',
|
||||
'255' => 'unknown'
|
||||
);
|
||||
return (isset($os_type[$key]) ? $os_type[$key] : '');
|
||||
}
|
||||
|
||||
// Converts the eXtra FLags
|
||||
public function get_xflag_type($key) {
|
||||
static $xflag_type = array(
|
||||
'0' => 'unknown',
|
||||
'2' => 'maximum compression',
|
||||
'4' => 'fastest algorithm'
|
||||
);
|
||||
return (isset($xflag_type[$key]) ? $xflag_type[$key] : '');
|
||||
}
|
||||
}
|
||||
|
50
api/getID3/module.archive.rar.php
Executable file
50
api/getID3/module.archive.rar.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// See readme.txt for more details //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// module.archive.rar.php //
|
||||
// module for analyzing RAR files //
|
||||
// dependencies: NONE //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class getid3_rar extends getid3_handler
|
||||
{
|
||||
|
||||
public $option_use_rar_extension = false;
|
||||
|
||||
public function Analyze() {
|
||||
$info = &$this->getid3->info;
|
||||
|
||||
$info['fileformat'] = 'rar';
|
||||
|
||||
if ($this->option_use_rar_extension === true) {
|
||||
if (function_exists('rar_open')) {
|
||||
if ($rp = rar_open($info['filenamepath'])) {
|
||||
$info['rar']['files'] = array();
|
||||
$entries = rar_list($rp);
|
||||
foreach ($entries as $entry) {
|
||||
$info['rar']['files'] = getid3_lib::array_merge_clobber($info['rar']['files'], getid3_lib::CreateDeepArray($entry->getName(), '/', $entry->getUnpackedSize()));
|
||||
}
|
||||
rar_close($rp);
|
||||
return true;
|
||||
} else {
|
||||
$info['error'][] = 'failed to rar_open('.$info['filename'].')';
|
||||
}
|
||||
} else {
|
||||
$info['error'][] = 'RAR support does not appear to be available in this PHP installation';
|
||||
}
|
||||
} else {
|
||||
$info['error'][] = 'PHP-RAR processing has been disabled (set $getid3_rar->option_use_rar_extension=true to enable)';
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
94
api/getID3/module.archive.szip.php
Executable file
94
api/getID3/module.archive.szip.php
Executable file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// See readme.txt for more details //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// module.archive.szip.php //
|
||||
// module for analyzing SZIP compressed files //
|
||||
// dependencies: NONE //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class getid3_szip extends getid3_handler
|
||||
{
|
||||
|
||||
public function Analyze() {
|
||||
$info = &$this->getid3->info;
|
||||
|
||||
fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
|
||||
$SZIPHeader = fread($this->getid3->fp, 6);
|
||||
if (substr($SZIPHeader, 0, 4) != "SZ\x0A\x04") {
|
||||
$info['error'][] = 'Expecting "53 5A 0A 04" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($SZIPHeader, 0, 4)).'"';
|
||||
return false;
|
||||
}
|
||||
$info['fileformat'] = 'szip';
|
||||
$info['szip']['major_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 4, 1));
|
||||
$info['szip']['minor_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 5, 1));
|
||||
|
||||
while (!feof($this->getid3->fp)) {
|
||||
$NextBlockID = fread($this->getid3->fp, 2);
|
||||
switch ($NextBlockID) {
|
||||
case 'SZ':
|
||||
// Note that szip files can be concatenated, this has the same effect as
|
||||
// concatenating the files. this also means that global header blocks
|
||||
// might be present between directory/data blocks.
|
||||
fseek($this->getid3->fp, 4, SEEK_CUR);
|
||||
break;
|
||||
|
||||
case 'BH':
|
||||
$BHheaderbytes = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 3));
|
||||
$BHheaderdata = fread($this->getid3->fp, $BHheaderbytes);
|
||||
$BHheaderoffset = 0;
|
||||
while (strpos($BHheaderdata, "\x00", $BHheaderoffset) > 0) {
|
||||
//filename as \0 terminated string (empty string indicates end)
|
||||
//owner as \0 terminated string (empty is same as last file)
|
||||
//group as \0 terminated string (empty is same as last file)
|
||||
//3 byte filelength in this block
|
||||
//2 byte access flags
|
||||
//4 byte creation time (like in unix)
|
||||
//4 byte modification time (like in unix)
|
||||
//4 byte access time (like in unix)
|
||||
|
||||
$BHdataArray['filename'] = substr($BHheaderdata, $BHheaderoffset, strcspn($BHheaderdata, "\x00"));
|
||||
$BHheaderoffset += (strlen($BHdataArray['filename']) + 1);
|
||||
|
||||
$BHdataArray['owner'] = substr($BHheaderdata, $BHheaderoffset, strcspn($BHheaderdata, "\x00"));
|
||||
$BHheaderoffset += (strlen($BHdataArray['owner']) + 1);
|
||||
|
||||
$BHdataArray['group'] = substr($BHheaderdata, $BHheaderoffset, strcspn($BHheaderdata, "\x00"));
|
||||
$BHheaderoffset += (strlen($BHdataArray['group']) + 1);
|
||||
|
||||
$BHdataArray['filelength'] = getid3_lib::BigEndian2Int(substr($BHheaderdata, $BHheaderoffset, 3));
|
||||
$BHheaderoffset += 3;
|
||||
|
||||
$BHdataArray['access_flags'] = getid3_lib::BigEndian2Int(substr($BHheaderdata, $BHheaderoffset, 2));
|
||||
$BHheaderoffset += 2;
|
||||
|
||||
$BHdataArray['creation_time'] = getid3_lib::BigEndian2Int(substr($BHheaderdata, $BHheaderoffset, 4));
|
||||
$BHheaderoffset += 4;
|
||||
|
||||
$BHdataArray['modification_time'] = getid3_lib::BigEndian2Int(substr($BHheaderdata, $BHheaderoffset, 4));
|
||||
$BHheaderoffset += 4;
|
||||
|
||||
$BHdataArray['access_time'] = getid3_lib::BigEndian2Int(substr($BHheaderdata, $BHheaderoffset, 4));
|
||||
$BHheaderoffset += 4;
|
||||
|
||||
$info['szip']['BH'][] = $BHdataArray;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
176
api/getID3/module.archive.tar.php
Executable file
176
api/getID3/module.archive.tar.php
Executable file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// See readme.txt for more details //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// module.archive.tar.php //
|
||||
// module for analyzing TAR files //
|
||||
// dependencies: NONE //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Module originally written by //
|
||||
// Mike Mozolin <teddybearØmail*ru> //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class getid3_tar extends getid3_handler
|
||||
{
|
||||
|
||||
public function Analyze() {
|
||||
$info = &$this->getid3->info;
|
||||
|
||||
$info['fileformat'] = 'tar';
|
||||
$info['tar']['files'] = array();
|
||||
|
||||
$unpack_header = 'a100fname/a8mode/a8uid/a8gid/a12size/a12mtime/a8chksum/a1typflag/a100lnkname/a6magic/a2ver/a32uname/a32gname/a8devmaj/a8devmin/a155prefix';
|
||||
$null_512k = str_repeat("\x00", 512); // end-of-file marker
|
||||
|
||||
fseek($this->getid3->fp, 0);
|
||||
while (!feof($this->getid3->fp)) {
|
||||
$buffer = fread($this->getid3->fp, 512);
|
||||
if (strlen($buffer) < 512) {
|
||||
break;
|
||||
}
|
||||
|
||||
// check the block
|
||||
$checksum = 0;
|
||||
for ($i = 0; $i < 148; $i++) {
|
||||
$checksum += ord($buffer{$i});
|
||||
}
|
||||
for ($i = 148; $i < 156; $i++) {
|
||||
$checksum += ord(' ');
|
||||
}
|
||||
for ($i = 156; $i < 512; $i++) {
|
||||
$checksum += ord($buffer{$i});
|
||||
}
|
||||
$attr = unpack($unpack_header, $buffer);
|
||||
$name = (isset($attr['fname'] ) ? trim($attr['fname'] ) : '');
|
||||
$mode = octdec(isset($attr['mode'] ) ? trim($attr['mode'] ) : '');
|
||||
$uid = octdec(isset($attr['uid'] ) ? trim($attr['uid'] ) : '');
|
||||
$gid = octdec(isset($attr['gid'] ) ? trim($attr['gid'] ) : '');
|
||||
$size = octdec(isset($attr['size'] ) ? trim($attr['size'] ) : '');
|
||||
$mtime = octdec(isset($attr['mtime'] ) ? trim($attr['mtime'] ) : '');
|
||||
$chksum = octdec(isset($attr['chksum'] ) ? trim($attr['chksum'] ) : '');
|
||||
$typflag = (isset($attr['typflag']) ? trim($attr['typflag']) : '');
|
||||
$lnkname = (isset($attr['lnkname']) ? trim($attr['lnkname']) : '');
|
||||
$magic = (isset($attr['magic'] ) ? trim($attr['magic'] ) : '');
|
||||
$ver = (isset($attr['ver'] ) ? trim($attr['ver'] ) : '');
|
||||
$uname = (isset($attr['uname'] ) ? trim($attr['uname'] ) : '');
|
||||
$gname = (isset($attr['gname'] ) ? trim($attr['gname'] ) : '');
|
||||
$devmaj = octdec(isset($attr['devmaj'] ) ? trim($attr['devmaj'] ) : '');
|
||||
$devmin = octdec(isset($attr['devmin'] ) ? trim($attr['devmin'] ) : '');
|
||||
$prefix = (isset($attr['prefix'] ) ? trim($attr['prefix'] ) : '');
|
||||
if (($checksum == 256) && ($chksum == 0)) {
|
||||
// EOF Found
|
||||
break;
|
||||
}
|
||||
if ($prefix) {
|
||||
$name = $prefix.'/'.$name;
|
||||
}
|
||||
if ((preg_match('#/$#', $name)) && !$name) {
|
||||
$typeflag = 5;
|
||||
}
|
||||
if ($buffer == $null_512k) {
|
||||
// it's the end of the tar-file...
|
||||
break;
|
||||
}
|
||||
|
||||
// Read to the next chunk
|
||||
fseek($this->getid3->fp, $size, SEEK_CUR);
|
||||
|
||||
$diff = $size % 512;
|
||||
if ($diff != 0) {
|
||||
// Padding, throw away
|
||||
fseek($this->getid3->fp, (512 - $diff), SEEK_CUR);
|
||||
}
|
||||
// Protect against tar-files with garbage at the end
|
||||
if ($name == '') {
|
||||
break;
|
||||
}
|
||||
$info['tar']['file_details'][$name] = array (
|
||||
'name' => $name,
|
||||
'mode_raw' => $mode,
|
||||
'mode' => self::display_perms($mode),
|
||||
'uid' => $uid,
|
||||
'gid' => $gid,
|
||||
'size' => $size,
|
||||
'mtime' => $mtime,
|
||||
'chksum' => $chksum,
|
||||
'typeflag' => self::get_flag_type($typflag),
|
||||
'linkname' => $lnkname,
|
||||
'magic' => $magic,
|
||||
'version' => $ver,
|
||||
'uname' => $uname,
|
||||
'gname' => $gname,
|
||||
'devmajor' => $devmaj,
|
||||
'devminor' => $devmin
|
||||
);
|
||||
$info['tar']['files'] = getid3_lib::array_merge_clobber($info['tar']['files'], getid3_lib::CreateDeepArray($info['tar']['file_details'][$name]['name'], '/', $size));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parses the file mode to file permissions
|
||||
public function display_perms($mode) {
|
||||
// Determine Type
|
||||
if ($mode & 0x1000) $type='p'; // FIFO pipe
|
||||
elseif ($mode & 0x2000) $type='c'; // Character special
|
||||
elseif ($mode & 0x4000) $type='d'; // Directory
|
||||
elseif ($mode & 0x6000) $type='b'; // Block special
|
||||
elseif ($mode & 0x8000) $type='-'; // Regular
|
||||
elseif ($mode & 0xA000) $type='l'; // Symbolic Link
|
||||
elseif ($mode & 0xC000) $type='s'; // Socket
|
||||
else $type='u'; // UNKNOWN
|
||||
|
||||
// Determine permissions
|
||||
$owner['read'] = (($mode & 00400) ? 'r' : '-');
|
||||
$owner['write'] = (($mode & 00200) ? 'w' : '-');
|
||||
$owner['execute'] = (($mode & 00100) ? 'x' : '-');
|
||||
$group['read'] = (($mode & 00040) ? 'r' : '-');
|
||||
$group['write'] = (($mode & 00020) ? 'w' : '-');
|
||||
$group['execute'] = (($mode & 00010) ? 'x' : '-');
|
||||
$world['read'] = (($mode & 00004) ? 'r' : '-');
|
||||
$world['write'] = (($mode & 00002) ? 'w' : '-');
|
||||
$world['execute'] = (($mode & 00001) ? 'x' : '-');
|
||||
|
||||
// Adjust for SUID, SGID and sticky bit
|
||||
if ($mode & 0x800) $owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S';
|
||||
if ($mode & 0x400) $group['execute'] = ($group['execute'] == 'x') ? 's' : 'S';
|
||||
if ($mode & 0x200) $world['execute'] = ($world['execute'] == 'x') ? 't' : 'T';
|
||||
|
||||
$s = sprintf('%1s', $type);
|
||||
$s .= sprintf('%1s%1s%1s', $owner['read'], $owner['write'], $owner['execute']);
|
||||
$s .= sprintf('%1s%1s%1s', $group['read'], $group['write'], $group['execute']);
|
||||
$s .= sprintf('%1s%1s%1s'."\n", $world['read'], $world['write'], $world['execute']);
|
||||
return $s;
|
||||
}
|
||||
|
||||
// Converts the file type
|
||||
public function get_flag_type($typflag) {
|
||||
static $flag_types = array(
|
||||
'0' => 'LF_NORMAL',
|
||||
'1' => 'LF_LINK',
|
||||
'2' => 'LF_SYNLINK',
|
||||
'3' => 'LF_CHR',
|
||||
'4' => 'LF_BLK',
|
||||
'5' => 'LF_DIR',
|
||||
'6' => 'LF_FIFO',
|
||||
'7' => 'LF_CONFIG',
|
||||
'D' => 'LF_DUMPDIR',
|
||||
'K' => 'LF_LONGLINK',
|
||||
'L' => 'LF_LONGNAME',
|
||||
'M' => 'LF_MULTIVOL',
|
||||
'N' => 'LF_NAMES',
|
||||
'S' => 'LF_SPARSE',
|
||||
'V' => 'LF_VOLHDR'
|
||||
);
|
||||
return (isset($flag_types[$typflag]) ? $flag_types[$typflag] : '');
|
||||
}
|
||||
|
||||
}
|
421
api/getID3/module.archive.zip.php
Executable file
421
api/getID3/module.archive.zip.php
Executable file
@ -0,0 +1,421 @@
|
||||
<?php
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// getID3() by James Heinrich <info@getid3.org> //
|
||||
// available at http://getid3.sourceforge.net //
|
||||
// or http://www.getid3.org //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// See readme.txt for more details //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// module.archive.zip.php //
|
||||
// module for analyzing pkZip files //
|
||||
// dependencies: NONE //
|
||||
// ///
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class getid3_zip extends getid3_handler
|
||||
{
|
||||
|
||||
public function Analyze() {
|
||||
$info = &$this->getid3->info;
|
||||
|
||||
$info['fileformat'] = 'zip';
|
||||
$info['zip']['encoding'] = 'ISO-8859-1';
|
||||
$info['zip']['files'] = array();
|
||||
|
||||
$info['zip']['compressed_size'] = 0;
|
||||
$info['zip']['uncompressed_size'] = 0;
|
||||
$info['zip']['entries_count'] = 0;
|
||||
|
||||
if (!getid3_lib::intValueSupported($info['filesize'])) {
|
||||
$info['error'][] = 'File is larger than '.round(PHP_INT_MAX / 1073741824).'GB, not supported by PHP';
|
||||
return false;
|
||||
} else {
|
||||
$EOCDsearchData = '';
|
||||
$EOCDsearchCounter = 0;
|
||||
while ($EOCDsearchCounter++ < 512) {
|
||||
|
||||
fseek($this->getid3->fp, -128 * $EOCDsearchCounter, SEEK_END);
|
||||
$EOCDsearchData = fread($this->getid3->fp, 128).$EOCDsearchData;
|
||||
|
||||
if (strstr($EOCDsearchData, 'PK'."\x05\x06")) {
|
||||
|
||||
$EOCDposition = strpos($EOCDsearchData, 'PK'."\x05\x06");
|
||||
fseek($this->getid3->fp, (-128 * $EOCDsearchCounter) + $EOCDposition, SEEK_END);
|
||||
$info['zip']['end_central_directory'] = $this->ZIPparseEndOfCentralDirectory();
|
||||
|
||||
fseek($this->getid3->fp, $info['zip']['end_central_directory']['directory_offset'], SEEK_SET);
|
||||
$info['zip']['entries_count'] = 0;
|
||||
while ($centraldirectoryentry = $this->ZIPparseCentralDirectory($this->getid3->fp)) {
|
||||
$info['zip']['central_directory'][] = $centraldirectoryentry;
|
||||
$info['zip']['entries_count']++;
|
||||
$info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
||||
$info['zip']['uncompressed_size'] += $centraldirectoryentry['uncompressed_size'];
|
||||
|
||||
if ($centraldirectoryentry['uncompressed_size'] > 0) {
|
||||
$info['zip']['files'] = getid3_lib::array_merge_clobber($info['zip']['files'], getid3_lib::CreateDeepArray($centraldirectoryentry['filename'], '/', $centraldirectoryentry['uncompressed_size']));
|
||||
}
|
||||
}
|
||||
|
||||
if ($info['zip']['entries_count'] == 0) {
|
||||
$info['error'][] = 'No Central Directory entries found (truncated file?)';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($info['zip']['end_central_directory']['comment'])) {
|
||||
$info['zip']['comments']['comment'][] = $info['zip']['end_central_directory']['comment'];
|
||||
}
|
||||
|
||||
if (isset($info['zip']['central_directory'][0]['compression_method'])) {
|
||||
$info['zip']['compression_method'] = $info['zip']['central_directory'][0]['compression_method'];
|
||||
}
|
||||
if (isset($info['zip']['central_directory'][0]['flags']['compression_speed'])) {
|
||||
$info['zip']['compression_speed'] = $info['zip']['central_directory'][0]['flags']['compression_speed'];
|
||||
}
|
||||
if (isset($info['zip']['compression_method']) && ($info['zip']['compression_method'] == 'store') && !isset($info['zip']['compression_speed'])) {
|
||||
$info['zip']['compression_speed'] = 'store';
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getZIPentriesFilepointer()) {
|
||||
|
||||
// central directory couldn't be found and/or parsed
|
||||
// scan through actual file data entries, recover as much as possible from probable trucated file
|
||||
if ($info['zip']['compressed_size'] > ($info['filesize'] - 46 - 22)) {
|
||||
$info['error'][] = 'Warning: Truncated file! - Total compressed file sizes ('.$info['zip']['compressed_size'].' bytes) is greater than filesize minus Central Directory and End Of Central Directory structures ('.($info['filesize'] - 46 - 22).' bytes)';
|
||||
}
|
||||
$info['error'][] = 'Cannot find End Of Central Directory - returned list of files in [zip][entries] array may not be complete';
|
||||
foreach ($info['zip']['entries'] as $key => $valuearray) {
|
||||
$info['zip']['files'][$valuearray['filename']] = $valuearray['uncompressed_size'];
|
||||
}
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
unset($info['zip']);
|
||||
$info['fileformat'] = '';
|
||||
$info['error'][] = 'Cannot find End Of Central Directory (truncated file?)';
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getZIPHeaderFilepointerTopDown() {
|
||||
$info = &$this->getid3->info;
|
||||
|
||||
$info['fileformat'] = 'zip';
|
||||
|
||||
$info['zip']['compressed_size'] = 0;
|
||||
$info['zip']['uncompressed_size'] = 0;
|
||||
$info['zip']['entries_count'] = 0;
|
||||
|
||||
rewind($this->getid3->fp);
|
||||
while ($fileentry = $this->ZIPparseLocalFileHeader()) {
|
||||
$info['zip']['entries'][] = $fileentry;
|
||||
$info['zip']['entries_count']++;
|
||||
}
|
||||
if ($info['zip']['entries_count'] == 0) {
|
||||
$info['error'][] = 'No Local File Header entries found';
|
||||
return false;
|
||||
}
|
||||
|
||||
$info['zip']['entries_count'] = 0;
|
||||
while ($centraldirectoryentry = $this->ZIPparseCentralDirectory($this->getid3->fp)) {
|
||||
$info['zip']['central_directory'][] = $centraldirectoryentry;
|
||||
$info['zip']['entries_count']++;
|
||||
$info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
||||
$info['zip']['uncompressed_size'] += $centraldirectoryentry['uncompressed_size'];
|
||||
}
|
||||
if ($info['zip']['entries_count'] == 0) {
|
||||
$info['error'][] = 'No Central Directory entries found (truncated file?)';
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($EOCD = $this->ZIPparseEndOfCentralDirectory()) {
|
||||
$info['zip']['end_central_directory'] = $EOCD;
|
||||
} else {
|
||||
$info['error'][] = 'No End Of Central Directory entry found (truncated file?)';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($info['zip']['end_central_directory']['comment'])) {
|
||||
$info['zip']['comments']['comment'][] = $info['zip']['end_central_directory']['comment'];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function getZIPentriesFilepointer() {
|
||||
$info = &$this->getid3->info;
|
||||
|
||||
$info['zip']['compressed_size'] = 0;
|
||||
$info['zip']['uncompressed_size'] = 0;
|
||||
$info['zip']['entries_count'] = 0;
|
||||
|
||||
rewind($this->getid3->fp);
|
||||
while ($fileentry = $this->ZIPparseLocalFileHeader()) {
|
||||
$info['zip']['entries'][] = $fileentry;
|
||||
$info['zip']['entries_count']++;
|
||||
$info['zip']['compressed_size'] += $fileentry['compressed_size'];
|
||||
$info['zip']['uncompressed_size'] += $fileentry['uncompressed_size'];
|
||||
}
|
||||
if ($info['zip']['entries_count'] == 0) {
|
||||
$info['error'][] = 'No Local File Header entries found';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function ZIPparseLocalFileHeader() {
|
||||
$LocalFileHeader['offset'] = ftell($this->getid3->fp);
|
||||
|
||||
$ZIPlocalFileHeader = fread($this->getid3->fp, 30);
|
||||
|
||||
$LocalFileHeader['raw']['signature'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 0, 4));
|
||||
if ($LocalFileHeader['raw']['signature'] != 0x04034B50) {
|
||||
// invalid Local File Header Signature
|
||||
fseek($this->getid3->fp, $LocalFileHeader['offset'], SEEK_SET); // seek back to where filepointer originally was so it can be handled properly
|
||||
return false;
|
||||
}
|
||||
$LocalFileHeader['raw']['extract_version'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 4, 2));
|
||||
$LocalFileHeader['raw']['general_flags'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 6, 2));
|
||||
$LocalFileHeader['raw']['compression_method'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 8, 2));
|
||||
$LocalFileHeader['raw']['last_mod_file_time'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 10, 2));
|
||||
$LocalFileHeader['raw']['last_mod_file_date'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 12, 2));
|
||||
$LocalFileHeader['raw']['crc_32'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 14, 4));
|
||||
$LocalFileHeader['raw']['compressed_size'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 18, 4));
|
||||
$LocalFileHeader['raw']['uncompressed_size'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 22, 4));
|
||||
$LocalFileHeader['raw']['filename_length'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 26, 2));
|
||||
$LocalFileHeader['raw']['extra_field_length'] = getid3_lib::LittleEndian2Int(substr($ZIPlocalFileHeader, 28, 2));
|
||||
|
||||
$LocalFileHeader['extract_version'] = sprintf('%1.1f', $LocalFileHeader['raw']['extract_version'] / 10);
|
||||
$LocalFileHeader['host_os'] = $this->ZIPversionOSLookup(($LocalFileHeader['raw']['extract_version'] & 0xFF00) >> 8);
|
||||
$LocalFileHeader['compression_method'] = $this->ZIPcompressionMethodLookup($LocalFileHeader['raw']['compression_method']);
|
||||
$LocalFileHeader['compressed_size'] = $LocalFileHeader['raw']['compressed_size'];
|
||||