diff options
Diffstat (limited to 'inc/3rdparty/libraries/mpdf/mpdfi/pdf_parser.php')
-rw-r--r-- | inc/3rdparty/libraries/mpdf/mpdfi/pdf_parser.php | 690 |
1 files changed, 0 insertions, 690 deletions
diff --git a/inc/3rdparty/libraries/mpdf/mpdfi/pdf_parser.php b/inc/3rdparty/libraries/mpdf/mpdfi/pdf_parser.php deleted file mode 100644 index c7d69e2c..00000000 --- a/inc/3rdparty/libraries/mpdf/mpdfi/pdf_parser.php +++ /dev/null | |||
@@ -1,690 +0,0 @@ | |||
1 | <?php | ||
2 | // | ||
3 | // FPDI - Version 1.2 | ||
4 | // | ||
5 | // Copyright 2004-2007 Setasign - Jan Slabon | ||
6 | // | ||
7 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
8 | // you may not use this file except in compliance with the License. | ||
9 | // You may obtain a copy of the License at | ||
10 | // | ||
11 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
12 | // | ||
13 | // Unless required by applicable law or agreed to in writing, software | ||
14 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
16 | // See the License for the specific language governing permissions and | ||
17 | // limitations under the License. | ||
18 | // | ||
19 | |||
20 | if (!defined ('PDF_TYPE_NULL')) | ||
21 | define ('PDF_TYPE_NULL', 0); | ||
22 | if (!defined ('PDF_TYPE_NUMERIC')) | ||
23 | define ('PDF_TYPE_NUMERIC', 1); | ||
24 | if (!defined ('PDF_TYPE_TOKEN')) | ||
25 | define ('PDF_TYPE_TOKEN', 2); | ||
26 | if (!defined ('PDF_TYPE_HEX')) | ||
27 | define ('PDF_TYPE_HEX', 3); | ||
28 | if (!defined ('PDF_TYPE_STRING')) | ||
29 | define ('PDF_TYPE_STRING', 4); | ||
30 | if (!defined ('PDF_TYPE_DICTIONARY')) | ||
31 | define ('PDF_TYPE_DICTIONARY', 5); | ||
32 | if (!defined ('PDF_TYPE_ARRAY')) | ||
33 | define ('PDF_TYPE_ARRAY', 6); | ||
34 | if (!defined ('PDF_TYPE_OBJDEC')) | ||
35 | define ('PDF_TYPE_OBJDEC', 7); | ||
36 | if (!defined ('PDF_TYPE_OBJREF')) | ||
37 | define ('PDF_TYPE_OBJREF', 8); | ||
38 | if (!defined ('PDF_TYPE_OBJECT')) | ||
39 | define ('PDF_TYPE_OBJECT', 9); | ||
40 | if (!defined ('PDF_TYPE_STREAM')) | ||
41 | define ('PDF_TYPE_STREAM', 10); | ||
42 | |||
43 | |||
44 | class pdf_parser { | ||
45 | |||
46 | /** | ||
47 | * Filename | ||
48 | * @var string | ||
49 | */ | ||
50 | var $filename; | ||
51 | |||
52 | /** | ||
53 | * File resource | ||
54 | * @var resource | ||
55 | */ | ||
56 | var $f; | ||
57 | |||
58 | /** | ||
59 | * PDF Context | ||
60 | * @var object pdf_context-Instance | ||
61 | */ | ||
62 | var $c; | ||
63 | |||
64 | /** | ||
65 | * xref-Data | ||
66 | * @var array | ||
67 | */ | ||
68 | var $xref; | ||
69 | |||
70 | /** | ||
71 | * root-Object | ||
72 | * @var array | ||
73 | */ | ||
74 | var $root; | ||
75 | |||
76 | // mPDF 4.0 Added flag to show success on loading file | ||
77 | var $success; | ||
78 | var $errormsg; | ||
79 | |||
80 | /** | ||
81 | * Constructor | ||
82 | * | ||
83 | * @param string $filename Source-Filename | ||
84 | */ | ||
85 | function pdf_parser($filename) { | ||
86 | $this->filename = $filename; | ||
87 | // mPDF 4.0 | ||
88 | $this->success = true; | ||
89 | |||
90 | $this->f = @fopen($this->filename, "rb"); | ||
91 | |||
92 | if (!$this->f) { | ||
93 | $this->success = false; | ||
94 | $this->errormsg = sprintf("Cannot open %s !", $filename); | ||
95 | return false; | ||
96 | } | ||
97 | // mPDF 5.0 Removed pass by reference =& | ||
98 | $this->c = new pdf_context($this->f); | ||
99 | // Read xref-Data | ||
100 | $offset = $this->pdf_find_xref(); | ||
101 | if ($offset===false) { | ||
102 | $this->success = false; | ||
103 | $this->errormsg = sprintf("Cannot open %s !", $filename); | ||
104 | return false; | ||
105 | } | ||
106 | $this->pdf_read_xref($this->xref, $offset); | ||
107 | if ($this->success == false) { return false; } | ||
108 | |||
109 | // Check for Encryption | ||
110 | $this->getEncryption(); | ||
111 | if ($this->success == false) { return false; } | ||
112 | |||
113 | // Read root | ||
114 | $this->pdf_read_root(); | ||
115 | if ($this->success == false) { return false; } | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * Close the opened file | ||
120 | */ | ||
121 | function closeFile() { | ||
122 | if (isset($this->f)) { | ||
123 | fclose($this->f); | ||
124 | unset($this->f); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * Print Error and die | ||
130 | * | ||
131 | * @param string $msg Error-Message | ||
132 | */ | ||
133 | function error($msg) { | ||
134 | die("<b>PDF-Parser Error:</b> ".$msg); | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * Check Trailer for Encryption | ||
139 | */ | ||
140 | function getEncryption() { | ||
141 | if (isset($this->xref['trailer'][1]['/Encrypt'])) { | ||
142 | // mPDF 4.0 | ||
143 | $this->success = false; | ||
144 | $this->errormsg = sprintf("File is encrypted!"); | ||
145 | return false; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * Find/Return /Root | ||
151 | * | ||
152 | * @return array | ||
153 | */ | ||
154 | function pdf_find_root() { | ||
155 | if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { | ||
156 | // mPDF 4.0 | ||
157 | $this->success = false; | ||
158 | $this->errormsg = sprintf("Wrong Type of Root-Element! Must be an indirect reference"); | ||
159 | return false; | ||
160 | } | ||
161 | return $this->xref['trailer'][1]['/Root']; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * Read the /Root | ||
166 | */ | ||
167 | function pdf_read_root() { | ||
168 | // read root | ||
169 | $root = $this->pdf_find_root(); | ||
170 | if ($root ===false) { | ||
171 | $this->success = false; | ||
172 | return false; | ||
173 | } | ||
174 | $this->root = $this->pdf_resolve_object($this->c, $root); | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * Find the xref-Table | ||
179 | */ | ||
180 | function pdf_find_xref() { | ||
181 | fseek ($this->f, -min(filesize($this->filename),1500), SEEK_END); | ||
182 | $data = fread($this->f, 1500); | ||
183 | |||
184 | $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); | ||
185 | $data = substr($data, $pos); | ||
186 | |||
187 | if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { | ||
188 | // mPDF 4.0 | ||
189 | $this->success = false; | ||
190 | $this->errormsg = sprintf("Unable to find pointer to xref table"); | ||
191 | return false; | ||
192 | } | ||
193 | |||
194 | return (int) $matches[1]; | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * Read xref-table | ||
199 | * | ||
200 | * @param array $result Array of xref-table | ||
201 | * @param integer $offset of xref-table | ||
202 | * @param integer $start start-position in xref-table | ||
203 | * @param integer $end end-position in xref-table | ||
204 | */ | ||
205 | function pdf_read_xref(&$result, $offset, $start = null, $end = null) { | ||
206 | if (is_null ($start) || is_null ($end)) { | ||
207 | fseek($this->f, $o_pos = $offset); | ||
208 | $data = trim(fgets($this->f,1024)); | ||
209 | |||
210 | if (strlen($data) == 0) | ||
211 | $data = trim(fgets($this->f,1024)); | ||
212 | |||
213 | if ($data !== 'xref') { | ||
214 | fseek($this->f, $o_pos); | ||
215 | $data = trim(_fgets($this->f, true)); | ||
216 | if ($data !== 'xref') { | ||
217 | if (preg_match('/(.*xref)(.*)/m', $data, $m)) { // xref 0 128 - in one line | ||
218 | fseek($this->f, $o_pos+strlen($m[1])); | ||
219 | } elseif (preg_match('/(x|r|e|f)+/', $data, $m)) { // correct invalid xref-pointer | ||
220 | $tmpOffset = $offset-4+strlen($m[0]); | ||
221 | $this->pdf_read_xref($result, $tmpOffset, $start, $end); | ||
222 | return; | ||
223 | } else { | ||
224 | // mPDF 4.0 | ||
225 | $this->success = false; | ||
226 | $this->errormsg = sprintf("Unable to find xref table - Maybe a Problem with 'auto_detect_line_endings'"); | ||
227 | return; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | $o_pos = ftell($this->f); | ||
233 | $data = explode(' ', trim(fgets($this->f,1024))); | ||
234 | if (count($data) != 2) { | ||
235 | fseek($this->f, $o_pos); | ||
236 | $data = explode(' ', trim(_fgets($this->f, true))); | ||
237 | |||
238 | if (count($data) != 2) { | ||
239 | if (count($data) > 2) { // no lineending | ||
240 | $n_pos = $o_pos+strlen($data[0])+strlen($data[1])+2; | ||
241 | fseek($this->f, $n_pos); | ||
242 | } else { | ||
243 | // mPDF 4.0 | ||
244 | $this->success = false; | ||
245 | $this->errormsg = sprintf("Unexpected header in xref table"); | ||
246 | return; | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | $start = $data[0]; | ||
251 | $end = $start + $data[1]; | ||
252 | } | ||
253 | |||
254 | if (!isset($result['xref_location'])) { | ||
255 | $result['xref_location'] = $offset; | ||
256 | } | ||
257 | |||
258 | if (!isset($result['max_object']) || $end > $result['max_object']) { | ||
259 | $result['max_object'] = $end; | ||
260 | } | ||
261 | |||
262 | for (; $start < $end; $start++) { | ||
263 | $data = ltrim(fread($this->f, 20)); // Spezifications says: 20 bytes including newlines | ||
264 | $offset = substr($data, 0, 10); | ||
265 | $generation = substr($data, 11, 5); | ||
266 | |||
267 | if (!isset ($result['xref'][$start][(int) $generation])) { | ||
268 | $result['xref'][$start][(int) $generation] = (int) $offset; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | $o_pos = ftell($this->f); | ||
273 | $data = fgets($this->f,1024); | ||
274 | if (strlen(trim($data)) == 0) | ||
275 | $data = fgets($this->f, 1024); | ||
276 | |||
277 | if (preg_match("/trailer/",$data)) { | ||
278 | if (preg_match("/(.*trailer[ \n\r]*)/",$data,$m)) { | ||
279 | fseek($this->f, $o_pos+strlen($m[1])); | ||
280 | } | ||
281 | |||
282 | // mPDF 5.0 Removed pass by reference =& | ||
283 | $c = new pdf_context($this->f); | ||
284 | $trailer = $this->pdf_read_value($c); | ||
285 | |||
286 | if (isset($trailer[1]['/Prev'])) { | ||
287 | $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); | ||
288 | $result['trailer'][1] = array_merge($result['trailer'][1], $trailer[1]); | ||
289 | } else { | ||
290 | $result['trailer'] = $trailer; | ||
291 | } | ||
292 | } else { | ||
293 | $data = explode(' ', trim($data)); | ||
294 | |||
295 | if (count($data) != 2) { | ||
296 | fseek($this->f, $o_pos); | ||
297 | $data = explode(' ', trim (_fgets ($this->f, true))); | ||
298 | |||
299 | if (count($data) != 2) { | ||
300 | // mPDF 4.0 | ||
301 | $this->success = false; | ||
302 | $this->errormsg = sprintf("Unexpected data in xref table"); | ||
303 | return; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | $this->pdf_read_xref($result, null, (int) $data[0], (int) $data[0] + (int) $data[1]); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | |||
312 | /** | ||
313 | * Reads an Value | ||
314 | * | ||
315 | * @param object $c pdf_context | ||
316 | * @param string $token a Token | ||
317 | * @return mixed | ||
318 | */ | ||
319 | function pdf_read_value(&$c, $token = null) { | ||
320 | if (is_null($token)) { | ||
321 | $token = $this->pdf_read_token($c); | ||
322 | } | ||
323 | |||
324 | if ($token === false) { | ||
325 | return false; | ||
326 | } | ||
327 | |||
328 | switch ($token) { | ||
329 | case '<': | ||
330 | // This is a hex string. | ||
331 | // Read the value, then the terminator | ||
332 | |||
333 | $pos = $c->offset; | ||
334 | |||
335 | while(1) { | ||
336 | |||
337 | $match = strpos ($c->buffer, '>', $pos); | ||
338 | |||
339 | // If you can't find it, try | ||
340 | // reading more data from the stream | ||
341 | |||
342 | if ($match === false) { | ||
343 | if (!$c->increase_length()) { | ||
344 | return false; | ||
345 | } else { | ||
346 | continue; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | $result = substr ($c->buffer, $c->offset, $match - $c->offset); | ||
351 | $c->offset = $match+1; | ||
352 | |||
353 | return array (PDF_TYPE_HEX, $result); | ||
354 | } | ||
355 | |||
356 | break; | ||
357 | case '<<': | ||
358 | // This is a dictionary. | ||
359 | |||
360 | $result = array(); | ||
361 | |||
362 | // Recurse into this function until we reach | ||
363 | // the end of the dictionary. | ||
364 | while (($key = $this->pdf_read_token($c)) !== '>>') { | ||
365 | if ($key === false) { | ||
366 | return false; | ||
367 | } | ||
368 | |||
369 | if (($value = $this->pdf_read_value($c)) === false) { | ||
370 | return false; | ||
371 | } | ||
372 | $result[$key] = $value; | ||
373 | } | ||
374 | |||
375 | return array (PDF_TYPE_DICTIONARY, $result); | ||
376 | |||
377 | case '[': | ||
378 | // This is an array. | ||
379 | |||
380 | $result = array(); | ||
381 | |||
382 | // Recurse into this function until we reach | ||
383 | // the end of the array. | ||
384 | while (($token = $this->pdf_read_token($c)) !== ']') { | ||
385 | if ($token === false) { | ||
386 | return false; | ||
387 | } | ||
388 | |||
389 | if (($value = $this->pdf_read_value($c, $token)) === false) { | ||
390 | return false; | ||
391 | } | ||
392 | |||
393 | $result[] = $value; | ||
394 | } | ||
395 | |||
396 | return array (PDF_TYPE_ARRAY, $result); | ||
397 | |||
398 | case '(' : | ||
399 | // This is a string | ||
400 | |||
401 | $pos = $c->offset; | ||
402 | |||
403 | while(1) { | ||
404 | |||
405 | // Start by finding the next closed | ||
406 | // parenthesis | ||
407 | |||
408 | $match = strpos ($c->buffer, ')', $pos); | ||
409 | |||
410 | // If you can't find it, try | ||
411 | // reading more data from the stream | ||
412 | |||
413 | if ($match === false) { | ||
414 | if (!$c->increase_length()) { | ||
415 | return false; | ||
416 | } else { | ||
417 | continue; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | // Make sure that there is no backslash | ||
422 | // before the parenthesis. If there is, | ||
423 | // move on. Otherwise, return the string. | ||
424 | $esc = preg_match('/([\\\\]+)$/', $tmpresult = substr($c->buffer, $c->offset, $match - $c->offset), $m); | ||
425 | |||
426 | if ($esc === 0 || strlen($m[1]) % 2 == 0) { | ||
427 | $result = $tmpresult; | ||
428 | $c->offset = $match + 1; | ||
429 | return array (PDF_TYPE_STRING, $result); | ||
430 | } else { | ||
431 | $pos = $match + 1; | ||
432 | |||
433 | if ($pos > $c->offset + $c->length) { | ||
434 | $c->increase_length(); | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | |||
439 | case "stream": | ||
440 | $o_pos = ftell($c->file)-strlen($c->buffer); | ||
441 | $o_offset = $c->offset; | ||
442 | |||
443 | $c->reset($startpos = $o_pos + $o_offset); | ||
444 | |||
445 | $e = 0; // ensure line breaks in front of the stream | ||
446 | if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13)) | ||
447 | $e++; | ||
448 | if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10)) | ||
449 | $e++; | ||
450 | |||
451 | if ($this->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) { | ||
452 | // mPDF 5.0 Removed pass by reference =& | ||
453 | $tmp_c = new pdf_context($this->f); | ||
454 | $tmp_length = $this->pdf_resolve_object($tmp_c,$this->actual_obj[1][1]['/Length']); | ||
455 | $length = $tmp_length[1][1]; | ||
456 | } else { | ||
457 | $length = $this->actual_obj[1][1]['/Length'][1]; | ||
458 | } | ||
459 | |||
460 | if ($length > 0) { | ||
461 | $c->reset($startpos+$e,$length); | ||
462 | $v = $c->buffer; | ||
463 | } else { | ||
464 | $v = ''; | ||
465 | } | ||
466 | $c->reset($startpos+$e+$length+9); // 9 = strlen("endstream") | ||
467 | |||
468 | return array(PDF_TYPE_STREAM, $v); | ||
469 | |||
470 | default : | ||
471 | if (is_numeric ($token)) { | ||
472 | // A numeric token. Make sure that | ||
473 | // it is not part of something else. | ||
474 | if (($tok2 = $this->pdf_read_token ($c)) !== false) { | ||
475 | if (is_numeric ($tok2)) { | ||
476 | |||
477 | // Two numeric tokens in a row. | ||
478 | // In this case, we're probably in | ||
479 | // front of either an object reference | ||
480 | // or an object specification. | ||
481 | // Determine the case and return the data | ||
482 | if (($tok3 = $this->pdf_read_token ($c)) !== false) { | ||
483 | switch ($tok3) { | ||
484 | case 'obj' : | ||
485 | return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2); | ||
486 | case 'R' : | ||
487 | return array (PDF_TYPE_OBJREF, (int) $token, (int) $tok2); | ||
488 | } | ||
489 | // If we get to this point, that numeric value up | ||
490 | // there was just a numeric value. Push the extra | ||
491 | // tokens back into the stack and return the value. | ||
492 | array_push ($c->stack, $tok3); | ||
493 | } | ||
494 | } | ||
495 | |||
496 | array_push ($c->stack, $tok2); | ||
497 | } | ||
498 | |||
499 | return array (PDF_TYPE_NUMERIC, $token); | ||
500 | } else { | ||
501 | |||
502 | // Just a token. Return it. | ||
503 | return array (PDF_TYPE_TOKEN, $token); | ||
504 | } | ||
505 | |||
506 | } | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * Resolve an object | ||
511 | * | ||
512 | * @param object $c pdf_context | ||
513 | * @param array $obj_spec The object-data | ||
514 | * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para | ||
515 | */ | ||
516 | function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) { | ||
517 | // Exit if we get invalid data | ||
518 | if (!is_array($obj_spec)) { | ||
519 | return false; | ||
520 | } | ||
521 | |||
522 | if ($obj_spec[0] == PDF_TYPE_OBJREF) { | ||
523 | |||
524 | // This is a reference, resolve it | ||
525 | if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]])) { | ||
526 | |||
527 | // Save current file position | ||
528 | // This is needed if you want to resolve | ||
529 | // references while you're reading another object | ||
530 | // (e.g.: if you need to determine the length | ||
531 | // of a stream) | ||
532 | |||
533 | $old_pos = ftell($c->file); | ||
534 | |||
535 | // Reposition the file pointer and | ||
536 | // load the object header. | ||
537 | |||
538 | $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]); | ||
539 | |||
540 | $header = $this->pdf_read_value($c,null,true); | ||
541 | |||
542 | if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) { | ||
543 | // mPDF 4.0 | ||
544 | $this->success = false; | ||
545 | $this->errormsg = sprintf("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location"); | ||
546 | return false; | ||
547 | } | ||
548 | |||
549 | // If we're being asked to store all the information | ||
550 | // about the object, we add the object ID and generation | ||
551 | // number for later use | ||
552 | $this->actual_obj =& $result; | ||
553 | if ($encapsulate) { | ||
554 | $result = array ( | ||
555 | PDF_TYPE_OBJECT, | ||
556 | 'obj' => $obj_spec[1], | ||
557 | 'gen' => $obj_spec[2] | ||
558 | ); | ||
559 | } else { | ||
560 | $result = array(); | ||
561 | } | ||
562 | |||
563 | // Now simply read the object data until | ||
564 | // we encounter an end-of-object marker | ||
565 | while(1) { | ||
566 | $value = $this->pdf_read_value($c); | ||
567 | if ($value === false || count($result) > 4) { | ||
568 | // in this case the parser coudn't find an endobj so we break here | ||
569 | break; | ||
570 | } | ||
571 | |||
572 | if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') { | ||
573 | break; | ||
574 | } | ||
575 | |||
576 | $result[] = $value; | ||
577 | } | ||
578 | |||
579 | $c->reset($old_pos); | ||
580 | |||
581 | if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) { | ||
582 | $result[0] = PDF_TYPE_STREAM; | ||
583 | } | ||
584 | |||
585 | return $result; | ||
586 | } | ||
587 | } else { | ||
588 | return $obj_spec; | ||
589 | } | ||
590 | } | ||
591 | |||
592 | |||
593 | |||
594 | /** | ||
595 | * Reads a token from the file | ||
596 | * | ||
597 | * @param object $c pdf_context | ||
598 | * @return mixed | ||
599 | */ | ||
600 | function pdf_read_token(&$c) | ||
601 | { | ||
602 | // If there is a token available | ||
603 | // on the stack, pop it out and | ||
604 | // return it. | ||
605 | |||
606 | if (count($c->stack)) { | ||
607 | return array_pop($c->stack); | ||
608 | } | ||
609 | |||
610 | // Strip away any whitespace | ||
611 | |||
612 | do { | ||
613 | if (!$c->ensure_content()) { | ||
614 | return false; | ||
615 | } | ||
616 | $c->offset += _strspn($c->buffer, " \n\r\t", $c->offset); | ||
617 | } while ($c->offset >= $c->length - 1); | ||
618 | |||
619 | // Get the first character in the stream | ||
620 | |||
621 | $char = $c->buffer[$c->offset++]; | ||
622 | |||
623 | switch ($char) { | ||
624 | |||
625 | case '[' : | ||
626 | case ']' : | ||
627 | case '(' : | ||
628 | case ')' : | ||
629 | |||
630 | // This is either an array or literal string | ||
631 | // delimiter, Return it | ||
632 | |||
633 | return $char; | ||
634 | |||
635 | case '<' : | ||
636 | case '>' : | ||
637 | |||
638 | // This could either be a hex string or | ||
639 | // dictionary delimiter. Determine the | ||
640 | // appropriate case and return the token | ||
641 | |||
642 | if ($c->buffer[$c->offset] == $char) { | ||
643 | if (!$c->ensure_content()) { | ||
644 | return false; | ||
645 | } | ||
646 | $c->offset++; | ||
647 | return $char . $char; | ||
648 | } else { | ||
649 | return $char; | ||
650 | } | ||
651 | |||
652 | default : | ||
653 | |||
654 | // This is "another" type of token (probably | ||
655 | // a dictionary entry or a numeric value) | ||
656 | // Find the end and return it. | ||
657 | |||
658 | if (!$c->ensure_content()) { | ||
659 | return false; | ||
660 | } | ||
661 | |||
662 | while(1) { | ||
663 | |||
664 | // Determine the length of the token | ||
665 | |||
666 | $pos = _strcspn($c->buffer, " []<>()\r\n\t/", $c->offset); | ||
667 | if ($c->offset + $pos <= $c->length - 1) { | ||
668 | break; | ||
669 | } else { | ||
670 | // If the script reaches this point, | ||
671 | // the token may span beyond the end | ||
672 | // of the current buffer. Therefore, | ||
673 | // we increase the size of the buffer | ||
674 | // and try again--just to be safe. | ||
675 | |||
676 | $c->increase_length(); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | $result = substr($c->buffer, $c->offset - 1, $pos + 1); | ||
681 | |||
682 | $c->offset += $pos; | ||
683 | return $result; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | |||
688 | } | ||
689 | |||
690 | ?> \ No newline at end of file | ||