root/trunk/server/www/cake/libs/magic_db.php @ 310

Revision 310, 6.8 KB (checked in by sander, 6 months ago)

Do not assign the return of 'new' by reference or PHP 5.3 will yell

Line 
1<?php
2/* SVN FILE: $Id: magic_db.php 7945 2008-12-19 02:16:01Z gwoo $ */
3/**
4 * MagicDb parser and file analyzer
5 *
6 * PHP versions 4 and 5
7 *
8 * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
9 * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
10 *
11 * Licensed under The MIT License
12 * Redistributions of files must retain the above copyright notice.
13 *
14 * @filesource
15 * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
16 * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
17 * @package       cake
18 * @subpackage    cake.cake.libs
19 * @since         CakePHP(tm) v 1.2.0
20 * @version       $Revision: 7945 $
21 * @modifiedby    $LastChangedBy: gwoo $
22 * @lastmodified  $Date: 2008-12-18 20:16:01 -0600 (Thu, 18 Dec 2008) $
23 * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
24 */
25if (!class_exists('File')) {
26        uses('object', 'file');
27}
28/**
29 * A class to parse and use the MagicDb for file type analysis
30 *
31 * @package       cake.tests
32 * @subpackage    cake.tests.cases.libs
33 */
34class MagicDb extends Object {
35/**
36 * Holds the parsed MagicDb for this class instance
37 *
38 * @var array
39 **/
40        var $db = array();
41
42/**
43 * Reads a MagicDb from various formats
44 *
45 * @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
46 * @return boolean Returns false if reading / validation failed or true on success.
47 * @author        Felix
48 **/
49        function read($magicDb = null) {
50                if (!is_string($magicDb) && !is_array($magicDb)) {
51                        return false;
52                }
53                if (is_array($magicDb) || strpos($magicDb, '# FILE_ID DB') === 0) {
54                        $data = $magicDb;
55                } else {
56                        $File = new File($magicDb);
57                        if (!$File->exists()) {
58                                return false;
59                        }
60                        if ($File->ext() == 'php') {
61                                include($File->pwd());
62                                $data = $magicDb;
63                        } else {
64                                // @TODO: Needs test coverage
65                                $data = $File->read();
66                        }
67                }
68
69                $magicDb = $this->toArray($data);
70                if (!$this->validates($magicDb)) {
71                        return false;
72                }
73                return !!($this->db = $magicDb);
74        }
75
76/**
77 * Parses a MagicDb $data string into an array or returns the current MagicDb instance as an array
78 *
79 * @param string $data A MagicDb string to turn into an array
80 * @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.
81 * @access public
82 */
83        function toArray($data = null) {
84                if (is_array($data)) {
85                        return $data;
86                }
87                if ($data === null) {
88                        return $this->db;
89                }
90
91                if (strpos($data, '# FILE_ID DB') !== 0) {
92                        return array();
93                }
94
95                $lines = explode("\r\n", $data);
96                $db = array();
97
98                $validHeader = count($lines > 3)
99                                        && preg_match('/^# Date:([0-9]{4}-[0-9]{2}-[0-9]{2})$/', $lines[1], $date)
100                                        && preg_match('/^# Source:(.+)$/', $lines[2], $source)
101                                        && strlen($lines[3]) == 0;
102                if (!$validHeader) {
103                        return $db;
104                }
105
106                $db = array('header' => array('Date' => $date[1], 'Source' => $source[1]), 'database' => array());
107                $lines = array_splice($lines, 3);
108
109                $format = array();
110                while (!empty($lines)) {
111                        $line = array_shift($lines);
112                        if (isset($line[0]) && $line[0] == '#' || empty($line)) {
113                                continue;
114                        }
115
116                        $columns = explode("\t", $line);
117                        if (in_array($columns[0]{0}, array('>', '&'))) {
118                                $format[] = $columns;
119                        } elseif (!empty($format)) {
120                                $db['database'][] = $format;
121                                $format = array($columns);
122                        } else {
123                                $format = array($columns);
124                        }
125                }
126
127                return $db;
128        }
129
130/**
131 * Returns true if the MagicDb instance or the passed $magicDb is valid
132 *
133 * @param mixed $magicDb A $magicDb string / array to validate (optional)
134 * @return boolean True if the $magicDb / instance db validates, false if not
135 * @access public
136 */
137        function validates($magicDb = null) {
138                if (is_null($magicDb)) {
139                        $magicDb = $this->db;
140                } elseif (!is_array($magicDb)) {
141                        $magicDb = $this->toArray($magicDb);
142                }
143
144                return isset($magicDb['header'], $magicDb['database']) && is_array($magicDb['header']) && is_array($magicDb['database']);
145        }
146
147/**
148 * Analyzes a given $file using the currently loaded MagicDb information based on the desired $options
149 *
150 * @param string $file Absolute path to the file to analyze
151 * @param array $options TBT
152 * @return mixed
153 * @access public
154 */
155        function analyze($file, $options = array()) {
156                if (!is_string($file)) {
157                        return false;
158                }
159
160                $matches = array();
161                $MagicFileResource = new MagicFileResource($file);
162                foreach ($this->db['database'] as $format) {
163                        $magic = $format[0];
164                        $match = $MagicFileResource->test($magic);
165                        if ($match === false) {
166                                continue;
167                        }
168                        $matches[] = $magic;
169                }
170
171                return $matches;
172        }
173}
174
175/**
176 * undocumented class
177 *
178 * @package       cake.tests
179 * @subpackage    cake.tests.cases.libs
180 */
181class MagicFileResource extends Object{
182/**
183 * undocumented variable
184 *
185 * @var unknown
186 * @access public
187 */
188        var $resource = null;
189/**
190 * undocumented variable
191 *
192 * @var unknown
193 * @access public
194 */
195        var $offset = 0;
196/**
197 * undocumented function
198 *
199 * @param unknown $file
200 * @return void
201 * @access public
202 */
203        function __construct($file) {
204                if (file_exists($file)) {
205                        $this->resource = new File($file);
206                } else {
207                        $this->resource = $file;
208                }
209        }
210/**
211 * undocumented function
212 *
213 * @param unknown $magic
214 * @return void
215 * @access public
216 */
217        function test($magic) {
218                $offset = null;
219                $type = null;
220                $expected = null;
221                $comment = null;
222                if (isset($magic[0])) {
223                        $offset = $magic[0];
224                }
225                if (isset($magic[1])) {
226                        $type = $magic[1];
227                }
228                if (isset($magic[2])) {
229                        $expected = $magic[2];
230                }
231                if (isset($magic[3])) {
232                        $comment = $magic[3];
233                }
234                $val = $this->extract($offset, $type, $expected);
235                return $val == $expected;
236        }
237/**
238 * undocumented function
239 *
240 * @param unknown $type
241 * @param unknown $length
242 * @return void
243 * @access public
244 */
245        function read($length = null) {
246                if (!is_object($this->resource)) {
247                        return substr($this->resource, $this->offset, $length);
248                }
249                return $this->resource->read($length);
250        }
251/**
252 * undocumented function
253 *
254 * @param unknown $type
255 * @param unknown $expected
256 * @return void
257 * @access public
258 */
259        function extract($offset, $type, $expected) {
260                switch ($type) {
261                        case 'string':
262                                $this->offset($offset);
263                                $val = $this->read(strlen($expected));
264                                if ($val === $expected) {
265                                        return true;
266                                }
267                                break;
268                }
269        }
270/**
271 * undocumented function
272 *
273 * @param unknown $offset
274 * @param unknown $whence
275 * @return void
276 * @access public
277 */
278        function offset($offset = null) {
279                if (is_null($offset)) {
280                        if (!is_object($this->resource)) {
281                                return $this->offset;
282                        }
283                        return $this->offset;
284                }
285
286                if (!ctype_digit($offset)) {
287                        return false;
288                }
289                if (is_object($this->resource)) {
290                        $this->resource->offset($offset);
291                } else {
292                        $this->offset = $offset;
293                }
294        }
295}
296
297?>
Note: See TracBrowser for help on using the browser.