magic_db.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: magic__db_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * MagicDb parser and file analyzer
00005  *
00006  * PHP versions 4 and 5
00007  *
00008  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00009  * Copyright 2005-2008, Cake Software Foundation, Inc.
00010  *                              1785 E. Sahara Avenue, Suite 490-204
00011  *                              Las Vegas, Nevada 89104
00012  *
00013  * Licensed under The MIT License
00014  * Redistributions of files must retain the above copyright notice.
00015  *
00016  * @filesource
00017  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00018  * @link            http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00019  * @package         cake
00020  * @subpackage      cake.cake.libs
00021  * @since           CakePHP(tm) v 1.2.0
00022  * @version         $Revision: 580 $
00023  * @modifiedby      $LastChangedBy: gwoo $
00024  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00025  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00026  */
00027 if (!class_exists('File')) {
00028     uses ('object', 'file');
00029 }
00030 /**
00031  * A class to parse and use the MagicDb for file type analysis
00032  *
00033  * @package     cake.tests
00034  * @subpackage  cake.tests.cases.libs
00035  */
00036 class MagicDb extends Object {
00037 /**
00038  * Holds the parsed MagicDb for this class instance
00039  *
00040  * @var array
00041  **/
00042     var $db = array();
00043 
00044 /**
00045  * Reads a MagicDb from various formats
00046  *
00047  * @var $magicDb mixed Can be an array containing the db, a magic db as a string, or a filename pointing to a magic db in .db or magic.db.php format
00048  * @return boolean Returns false if reading / validation failed or true on success.
00049  * @author Felix
00050  **/
00051     function read($magicDb = null) {
00052         if (!is_string($magicDb) && !is_array($magicDb)) {
00053             return false;
00054         }
00055         if (is_array($magicDb) || strpos($magicDb, '# FILE_ID DB') === 0) {
00056             $data = $magicDb;
00057         } else {
00058             $File =& new File($magicDb);
00059             if (!$File->exists()) {
00060                 return false;
00061             }
00062             if ($File->ext() == 'php') {
00063                 include($File->pwd());
00064                 $data = $magicDb;
00065             } else {
00066                 // @TODO: Needs test coverage
00067                 $data = $File->read();
00068             }
00069         }
00070 
00071         $magicDb = $this->toArray($data);
00072         if (!$this->validates($magicDb)) {
00073             return false;
00074         }
00075         return !!($this->db = $magicDb);
00076     }
00077 
00078 /**
00079  * Parses a MagicDb $data string into an array or returns the current MagicDb instance as an array
00080  *
00081  * @param string $data A MagicDb string to turn into an array
00082  * @return array A parsed MagicDb array or an empty array if the $data param was invalid. Returns the db property if $data is not set.
00083  * @access public
00084  */
00085     function toArray($data = null) {
00086         if (is_array($data)) {
00087             return $data;
00088         }
00089         if ($data === null) {
00090             return $this->db;
00091         }
00092 
00093         if (strpos($data, '# FILE_ID DB') !== 0) {
00094             return array();
00095         }
00096 
00097         $lines = explode("\r\n", $data);
00098         $db = array();
00099 
00100         $validHeader = count($lines > 3)
00101                     && preg_match('/^# Date:([0-9]{4}-[0-9]{2}-[0-9]{2})$/', $lines[1], $date)
00102                     && preg_match('/^# Source:(.+)$/', $lines[2], $source)
00103                     && strlen($lines[3]) == 0;
00104         if (!$validHeader) {
00105             return $db;
00106         }
00107 
00108         $db = array('header' => array('Date' => $date[1], 'Source' => $source[1]), 'database' => array());
00109         $lines = array_splice($lines, 3);
00110 
00111         $format = array();
00112         while (!empty($lines)) {
00113             $line = array_shift($lines);
00114             if (isset($line[0]) && $line[0] == '#' || empty($line)) {
00115                 continue;
00116             }
00117 
00118             $columns = explode("\t", $line);
00119             if (in_array($columns[0]{0}, array('>', '&'))) {
00120                 $format[] = $columns;
00121             } elseif (!empty($format)) {
00122                 $db['database'][] = $format;
00123                 $format = array($columns);
00124             } else {
00125                 $format = array($columns);
00126             }
00127         }
00128 
00129         return $db;
00130     }
00131 
00132 /**
00133  * Returns true if the MagicDb instance or the passed $magicDb is valid
00134  *
00135  * @param mixed $magicDb A $magicDb string / array to validate (optional)
00136  * @return boolean True if the $magicDb / instance db validates, false if not
00137  * @access public
00138  */
00139     function validates($magicDb = null) {
00140         if (is_null($magicDb)) {
00141             $magicDb = $this->db;
00142         } elseif (!is_array($magicDb)) {
00143             $magicDb = $this->toArray($magicDb);
00144         }
00145 
00146         return isset($magicDb['header'], $magicDb['database']) && is_array($magicDb['header']) && is_array($magicDb['database']);
00147     }
00148 
00149 /**
00150  * Analyzes a given $file using the currently loaded MagicDb information based on the desired $options
00151  *
00152  * @param string $file Absolute path to the file to analyze
00153  * @param array $options TBT
00154  * @return mixed
00155  * @access public
00156  */
00157     function analyze($file, $options = array()) {
00158         if (!is_string($file)) {
00159             return false;
00160         }
00161 
00162         $matches = array();
00163         $MagicFileResource =& new MagicFileResource($file);
00164         foreach ($this->db['database'] as $format) {
00165             $magic = $format[0];
00166             $match = $MagicFileResource->test($magic);
00167             if ($match === false) {
00168                 continue;
00169             }
00170             $matches[] = $magic;
00171         }
00172 
00173         return $matches;
00174     }
00175 }
00176 
00177 /**
00178  * undocumented class
00179  *
00180  * @package     cake.tests
00181  * @subpackage  cake.tests.cases.libs
00182  */
00183 class MagicFileResource extends Object{
00184 /**
00185  * undocumented variable
00186  *
00187  * @var unknown
00188  * @access public
00189  */
00190     var $resource = null;
00191 /**
00192  * undocumented variable
00193  *
00194  * @var unknown
00195  * @access public
00196  */
00197     var $offset = 0;
00198 /**
00199  * undocumented function
00200  *
00201  * @param unknown $file
00202  * @return void
00203  * @access public
00204  */
00205     function __construct($file) {
00206         if (file_exists($file)) {
00207             $this->resource =& new File($file);
00208         } else {
00209             $this->resource = $file;
00210         }
00211     }
00212 /**
00213  * undocumented function
00214  *
00215  * @param unknown $magic
00216  * @return void
00217  * @access public
00218  */
00219     function test($magic) {
00220         $offset = null;
00221         $type = null;
00222         $expected = null;
00223         $comment = null;
00224         if (isset($magic[0])) {
00225             $offset = $magic[0];
00226         }
00227         if (isset($magic[1])) {
00228             $type = $magic[1];
00229         }
00230         if (isset($magic[2])) {
00231             $expected = $magic[2];
00232         }
00233         if (isset($magic[3])) {
00234             $comment = $magic[3];
00235         }
00236         $val = $this->extract($offset, $type, $expected);
00237         return $val == $expected;
00238     }
00239 /**
00240  * undocumented function
00241  *
00242  * @param unknown $type
00243  * @param unknown $length
00244  * @return void
00245  * @access public
00246  */
00247     function read($length = null) {
00248         if (!is_object($this->resource)){
00249             return substr($this->resource, $this->offset, $length);
00250         } else {
00251             return $this->resource->read($length);
00252         }
00253     }
00254 /**
00255  * undocumented function
00256  *
00257  * @param unknown $type
00258  * @param unknown $expected
00259  * @return void
00260  * @access public
00261  */
00262     function extract($offset, $type, $expected) {
00263         switch ($type) {
00264             case 'string':
00265                 $this->offset($offset);
00266                 $val = $this->read(strlen($expected));
00267                 if ($val === $expected) {
00268                     return true;
00269                 }
00270                 break;
00271         }
00272     }
00273 /**
00274  * undocumented function
00275  *
00276  * @param unknown $offset
00277  * @param unknown $whence
00278  * @return void
00279  * @access public
00280  */
00281     function offset($offset = null) {
00282         if (is_null($offset)) {
00283             if (!is_object($this->resource)) {
00284                 return $this->offset;
00285             }
00286             return $this->offset;
00287         }
00288 
00289         if (!ctype_digit($offset)) {
00290             return false;
00291         }
00292         if (is_object($this->resource)) {
00293             $this->resource->offset($offset);
00294         } else {
00295             $this->offset = $offset;
00296         }
00297     }
00298 }
00299 
00300 ?>