00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 if (!class_exists('File')) {
00026 uses('object', 'file');
00027 }
00028
00029
00030
00031
00032
00033
00034 class MagicDb extends Object {
00035
00036
00037
00038
00039
00040 var $db = array();
00041
00042
00043
00044
00045
00046
00047
00048
00049 function read($magicDb = null) {
00050 if (!is_string($magicDb) && !is_array($magicDb)) {
00051 return false;
00052 }
00053 if (is_array($magicDb) || strpos($magicDb, '# FILE_ID DB') === 0) {
00054 $data = $magicDb;
00055 } else {
00056 $File =& new File($magicDb);
00057 if (!$File->exists()) {
00058 return false;
00059 }
00060 if ($File->ext() == 'php') {
00061 include($File->pwd());
00062 $data = $magicDb;
00063 } else {
00064
00065 $data = $File->read();
00066 }
00067 }
00068
00069 $magicDb = $this->toArray($data);
00070 if (!$this->validates($magicDb)) {
00071 return false;
00072 }
00073 return !!($this->db = $magicDb);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083 function toArray($data = null) {
00084 if (is_array($data)) {
00085 return $data;
00086 }
00087 if ($data === null) {
00088 return $this->db;
00089 }
00090
00091 if (strpos($data, '# FILE_ID DB') !== 0) {
00092 return array();
00093 }
00094
00095 $lines = explode("\r\n", $data);
00096 $db = array();
00097
00098 $validHeader = count($lines > 3)
00099 && preg_match('/^# Date:([0-9]{4}-[0-9]{2}-[0-9]{2})$/', $lines[1], $date)
00100 && preg_match('/^# Source:(.+)$/', $lines[2], $source)
00101 && strlen($lines[3]) == 0;
00102 if (!$validHeader) {
00103 return $db;
00104 }
00105
00106 $db = array('header' => array('Date' => $date[1], 'Source' => $source[1]), 'database' => array());
00107 $lines = array_splice($lines, 3);
00108
00109 $format = array();
00110 while (!empty($lines)) {
00111 $line = array_shift($lines);
00112 if (isset($line[0]) && $line[0] == '#' || empty($line)) {
00113 continue;
00114 }
00115
00116 $columns = explode("\t", $line);
00117 if (in_array($columns[0]{0}, array('>', '&'))) {
00118 $format[] = $columns;
00119 } elseif (!empty($format)) {
00120 $db['database'][] = $format;
00121 $format = array($columns);
00122 } else {
00123 $format = array($columns);
00124 }
00125 }
00126
00127 return $db;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 function validates($magicDb = null) {
00138 if (is_null($magicDb)) {
00139 $magicDb = $this->db;
00140 } elseif (!is_array($magicDb)) {
00141 $magicDb = $this->toArray($magicDb);
00142 }
00143
00144 return isset($magicDb['header'], $magicDb['database']) && is_array($magicDb['header']) && is_array($magicDb['database']);
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 function analyze($file, $options = array()) {
00156 if (!is_string($file)) {
00157 return false;
00158 }
00159
00160 $matches = array();
00161 $MagicFileResource =& new MagicFileResource($file);
00162 foreach ($this->db['database'] as $format) {
00163 $magic = $format[0];
00164 $match = $MagicFileResource->test($magic);
00165 if ($match === false) {
00166 continue;
00167 }
00168 $matches[] = $magic;
00169 }
00170
00171 return $matches;
00172 }
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 class MagicFileResource extends Object{
00182
00183
00184
00185
00186
00187
00188 var $resource = null;
00189
00190
00191
00192
00193
00194
00195 var $offset = 0;
00196
00197
00198
00199
00200
00201
00202
00203 function __construct($file) {
00204 if (file_exists($file)) {
00205 $this->resource =& new File($file);
00206 } else {
00207 $this->resource = $file;
00208 }
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 function test($magic) {
00218 $offset = null;
00219 $type = null;
00220 $expected = null;
00221 $comment = null;
00222 if (isset($magic[0])) {
00223 $offset = $magic[0];
00224 }
00225 if (isset($magic[1])) {
00226 $type = $magic[1];
00227 }
00228 if (isset($magic[2])) {
00229 $expected = $magic[2];
00230 }
00231 if (isset($magic[3])) {
00232 $comment = $magic[3];
00233 }
00234 $val = $this->extract($offset, $type, $expected);
00235 return $val == $expected;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245 function read($length = null) {
00246 if (!is_object($this->resource)) {
00247 return substr($this->resource, $this->offset, $length);
00248 }
00249 return $this->resource->read($length);
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259 function extract($offset, $type, $expected) {
00260 switch ($type) {
00261 case 'string':
00262 $this->offset($offset);
00263 $val = $this->read(strlen($expected));
00264 if ($val === $expected) {
00265 return true;
00266 }
00267 break;
00268 }
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278 function offset($offset = null) {
00279 if (is_null($offset)) {
00280 if (!is_object($this->resource)) {
00281 return $this->offset;
00282 }
00283 return $this->offset;
00284 }
00285
00286 if (!ctype_digit($offset)) {
00287 return false;
00288 }
00289 if (is_object($this->resource)) {
00290 $this->resource->offset($offset);
00291 } else {
00292 $this->offset = $offset;
00293 }
00294 }
00295 }
00296
00297 ?>