1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
20: if (!class_exists('Object')) {
21: require LIBS . 'object.php';
22: }
23: if (!class_exists('File')) {
24: require LIBS . 'file.php';
25: }
26:
27: 28: 29: 30: 31: 32:
33: class MagicDb extends Object {
34:
35: 36: 37: 38: 39:
40: var $db = array();
41:
42: 43: 44: 45: 46: 47: 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:
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: 78: 79: 80: 81: 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: 132: 133: 134: 135: 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: 149: 150: 151: 152: 153: 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: 177: 178: 179: 180:
181: class MagicFileResource extends Object{
182:
183: 184: 185: 186: 187: 188:
189: var $resource = null;
190:
191: 192: 193: 194: 195: 196:
197: var $offset = 0;
198:
199: 200: 201: 202: 203: 204: 205:
206: function __construct($file) {
207: if (file_exists($file)) {
208: $this->resource =& new File($file);
209: } else {
210: $this->resource = $file;
211: }
212: }
213:
214: 215: 216: 217: 218: 219: 220:
221: function test($magic) {
222: $offset = null;
223: $type = null;
224: $expected = null;
225: $comment = null;
226: if (isset($magic[0])) {
227: $offset = $magic[0];
228: }
229: if (isset($magic[1])) {
230: $type = $magic[1];
231: }
232: if (isset($magic[2])) {
233: $expected = $magic[2];
234: }
235: if (isset($magic[3])) {
236: $comment = $magic[3];
237: }
238: $val = $this->extract($offset, $type, $expected);
239: return $val == $expected;
240: }
241:
242: 243: 244: 245: 246: 247: 248: 249:
250: function read($length = null) {
251: if (!is_object($this->resource)) {
252: return substr($this->resource, $this->offset, $length);
253: }
254: return $this->resource->read($length);
255: }
256:
257: 258: 259: 260: 261: 262: 263: 264:
265: function extract($offset, $type, $expected) {
266: switch ($type) {
267: case 'string':
268: $this->offset($offset);
269: $val = $this->read(strlen($expected));
270: if ($val === $expected) {
271: return true;
272: }
273: break;
274: }
275: }
276:
277: 278: 279: 280: 281: 282: 283: 284:
285: function offset($offset = null) {
286: if (is_null($offset)) {
287: if (!is_object($this->resource)) {
288: return $this->offset;
289: }
290: return $this->offset;
291: }
292:
293: if (!ctype_digit($offset)) {
294: return false;
295: }
296: if (is_object($this->resource)) {
297: $this->resource->offset($offset);
298: } else {
299: $this->offset = $offset;
300: }
301: }
302: }
303: