ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
Escher.php
Go to the documentation of this file.
1<?php
36{
37 const DGGCONTAINER = 0xF000;
38 const BSTORECONTAINER = 0xF001;
39 const DGCONTAINER = 0xF002;
40 const SPGRCONTAINER = 0xF003;
41 const SPCONTAINER = 0xF004;
42 const DGG = 0xF006;
43 const BSE = 0xF007;
44 const DG = 0xF008;
45 const SPGR = 0xF009;
46 const SP = 0xF00A;
47 const OPT = 0xF00B;
48 const CLIENTTEXTBOX = 0xF00D;
49 const CLIENTANCHOR = 0xF010;
50 const CLIENTDATA = 0xF011;
51 const BLIPJPEG = 0xF01D;
52 const BLIPPNG = 0xF01E;
53 const SPLITMENUCOLORS = 0xF11E;
54 const TERTIARYOPT = 0xF122;
55
61 private $_data;
62
68 private $_dataSize;
69
75 private $_pos;
76
82 private $_object;
83
89 public function __construct($object)
90 {
91 $this->_object = $object;
92 }
93
99 public function load($data)
100 {
101 $this->_data = $data;
102
103 // total byte size of Excel data (workbook global substream + sheet substreams)
104 $this->_dataSize = strlen($this->_data);
105
106 $this->_pos = 0;
107
108 // Parse Escher stream
109 while ($this->_pos < $this->_dataSize) {
110
111 // offset: 2; size: 2: Record Type
112 $fbt = PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos + 2);
113
114 switch ($fbt) {
115 case self::DGGCONTAINER: $this->_readDggContainer(); break;
116 case self::DGG: $this->_readDgg(); break;
117 case self::BSTORECONTAINER: $this->_readBstoreContainer(); break;
118 case self::BSE: $this->_readBSE(); break;
119 case self::BLIPJPEG: $this->_readBlipJPEG(); break;
120 case self::BLIPPNG: $this->_readBlipPNG(); break;
121 case self::OPT: $this->_readOPT(); break;
122 case self::TERTIARYOPT: $this->_readTertiaryOPT(); break;
123 case self::SPLITMENUCOLORS: $this->_readSplitMenuColors(); break;
124 case self::DGCONTAINER: $this->_readDgContainer(); break;
125 case self::DG: $this->_readDg(); break;
126 case self::SPGRCONTAINER: $this->_readSpgrContainer(); break;
127 case self::SPCONTAINER: $this->_readSpContainer(); break;
128 case self::SPGR: $this->_readSpgr(); break;
129 case self::SP: $this->_readSp(); break;
130 case self::CLIENTTEXTBOX: $this->_readClientTextbox(); break;
131 case self::CLIENTANCHOR: $this->_readClientAnchor(); break;
132 case self::CLIENTDATA: $this->_readClientData(); break;
133 default: $this->_readDefault(); break;
134 }
135 }
136
137 return $this->_object;
138 }
139
143 private function _readDefault()
144 {
145 // offset 0; size: 2; recVer and recInstance
146 $verInstance = PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos);
147
148 // offset: 2; size: 2: Record Type
149 $fbt = PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos + 2);
150
151 // bit: 0-3; mask: 0x000F; recVer
152 $recVer = (0x000F & $verInstance) >> 0;
153
154 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
155 $recordData = substr($this->_data, $this->_pos + 8, $length);
156
157 // move stream pointer to next record
158 $this->_pos += 8 + $length;
159 }
160
164 private function _readDggContainer()
165 {
166 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
167 $recordData = substr($this->_data, $this->_pos + 8, $length);
168
169 // move stream pointer to next record
170 $this->_pos += 8 + $length;
171
172 // record is a container, read contents
173 $dggContainer = new PHPExcel_Shared_Escher_DggContainer();
174 $this->_object->setDggContainer($dggContainer);
175 $reader = new PHPExcel_Reader_Excel5_Escher($dggContainer);
176 $reader->load($recordData);
177 }
178
182 private function _readDgg()
183 {
184 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
185 $recordData = substr($this->_data, $this->_pos + 8, $length);
186
187 // move stream pointer to next record
188 $this->_pos += 8 + $length;
189 }
190
194 private function _readBstoreContainer()
195 {
196 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
197 $recordData = substr($this->_data, $this->_pos + 8, $length);
198
199 // move stream pointer to next record
200 $this->_pos += 8 + $length;
201
202 // record is a container, read contents
204 $this->_object->setBstoreContainer($bstoreContainer);
205 $reader = new PHPExcel_Reader_Excel5_Escher($bstoreContainer);
206 $reader->load($recordData);
207 }
208
212 private function _readBSE()
213 {
214 // offset: 0; size: 2; recVer and recInstance
215
216 // bit: 4-15; mask: 0xFFF0; recInstance
217 $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4;
218
219 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
220 $recordData = substr($this->_data, $this->_pos + 8, $length);
221
222 // move stream pointer to next record
223 $this->_pos += 8 + $length;
224
225 // add BSE to BstoreContainer
227 $this->_object->addBSE($BSE);
228
229 $BSE->setBLIPType($recInstance);
230
231 // offset: 0; size: 1; btWin32 (MSOBLIPTYPE)
232 $btWin32 = ord($recordData[0]);
233
234 // offset: 1; size: 1; btWin32 (MSOBLIPTYPE)
235 $btMacOS = ord($recordData[1]);
236
237 // offset: 2; size: 16; MD4 digest
238 $rgbUid = substr($recordData, 2, 16);
239
240 // offset: 18; size: 2; tag
241 $tag = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 18);
242
243 // offset: 20; size: 4; size of BLIP in bytes
244 $size = PHPExcel_Reader_Excel5::_GetInt4d($recordData, 20);
245
246 // offset: 24; size: 4; number of references to this BLIP
247 $cRef = PHPExcel_Reader_Excel5::_GetInt4d($recordData, 24);
248
249 // offset: 28; size: 4; MSOFO file offset
250 $foDelay = PHPExcel_Reader_Excel5::_GetInt4d($recordData, 28);
251
252 // offset: 32; size: 1; unused1
253 $unused1 = ord($recordData{32});
254
255 // offset: 33; size: 1; size of nameData in bytes (including null terminator)
256 $cbName = ord($recordData{33});
257
258 // offset: 34; size: 1; unused2
259 $unused2 = ord($recordData{34});
260
261 // offset: 35; size: 1; unused3
262 $unused3 = ord($recordData{35});
263
264 // offset: 36; size: $cbName; nameData
265 $nameData = substr($recordData, 36, $cbName);
266
267 // offset: 36 + $cbName, size: var; the BLIP data
268 $blipData = substr($recordData, 36 + $cbName);
269
270 // record is a container, read contents
272 $reader->load($blipData);
273 }
274
278 private function _readBlipJPEG()
279 {
280 // offset: 0; size: 2; recVer and recInstance
281
282 // bit: 4-15; mask: 0xFFF0; recInstance
283 $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4;
284
285 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
286 $recordData = substr($this->_data, $this->_pos + 8, $length);
287
288 // move stream pointer to next record
289 $this->_pos += 8 + $length;
290
291 $pos = 0;
292
293 // offset: 0; size: 16; rgbUid1 (MD4 digest of)
294 $rgbUid1 = substr($recordData, 0, 16);
295 $pos += 16;
296
297 // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3
298 if (in_array($recInstance, array(0x046B, 0x06E3))) {
299 $rgbUid2 = substr($recordData, 16, 16);
300 $pos += 16;
301 }
302
303 // offset: var; size: 1; tag
304 $tag = ord($recordData{$pos});
305 $pos += 1;
306
307 // offset: var; size: var; the raw image data
308 $data = substr($recordData, $pos);
309
311 $blip->setData($data);
312
313 $this->_object->setBlip($blip);
314 }
315
319 private function _readBlipPNG()
320 {
321 // offset: 0; size: 2; recVer and recInstance
322
323 // bit: 4-15; mask: 0xFFF0; recInstance
324 $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4;
325
326 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
327 $recordData = substr($this->_data, $this->_pos + 8, $length);
328
329 // move stream pointer to next record
330 $this->_pos += 8 + $length;
331
332 $pos = 0;
333
334 // offset: 0; size: 16; rgbUid1 (MD4 digest of)
335 $rgbUid1 = substr($recordData, 0, 16);
336 $pos += 16;
337
338 // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3
339 if ($recInstance == 0x06E1) {
340 $rgbUid2 = substr($recordData, 16, 16);
341 $pos += 16;
342 }
343
344 // offset: var; size: 1; tag
345 $tag = ord($recordData{$pos});
346 $pos += 1;
347
348 // offset: var; size: var; the raw image data
349 $data = substr($recordData, $pos);
350
352 $blip->setData($data);
353
354 $this->_object->setBlip($blip);
355 }
356
360 private function _readOPT()
361 {
362 // offset: 0; size: 2; recVer and recInstance
363
364 // bit: 4-15; mask: 0xFFF0; recInstance
365 $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4;
366
367 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
368 $recordData = substr($this->_data, $this->_pos + 8, $length);
369
370 // move stream pointer to next record
371 $this->_pos += 8 + $length;
372
373 $this->_readOfficeArtRGFOPTE($recordData, $recInstance);
374 }
375
379 private function _readTertiaryOPT()
380 {
381 // offset: 0; size: 2; recVer and recInstance
382
383 // bit: 4-15; mask: 0xFFF0; recInstance
384 $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4;
385
386 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
387 $recordData = substr($this->_data, $this->_pos + 8, $length);
388
389 // move stream pointer to next record
390 $this->_pos += 8 + $length;
391 }
392
396 private function _readSplitMenuColors()
397 {
398 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
399 $recordData = substr($this->_data, $this->_pos + 8, $length);
400
401 // move stream pointer to next record
402 $this->_pos += 8 + $length;
403 }
404
408 private function _readDgContainer()
409 {
410 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
411 $recordData = substr($this->_data, $this->_pos + 8, $length);
412
413 // move stream pointer to next record
414 $this->_pos += 8 + $length;
415
416 // record is a container, read contents
417 $dgContainer = new PHPExcel_Shared_Escher_DgContainer();
418 $this->_object->setDgContainer($dgContainer);
419 $reader = new PHPExcel_Reader_Excel5_Escher($dgContainer);
420 $escher = $reader->load($recordData);
421 }
422
426 private function _readDg()
427 {
428 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
429 $recordData = substr($this->_data, $this->_pos + 8, $length);
430
431 // move stream pointer to next record
432 $this->_pos += 8 + $length;
433 }
434
438 private function _readSpgrContainer()
439 {
440 // context is either context DgContainer or SpgrContainer
441
442 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
443 $recordData = substr($this->_data, $this->_pos + 8, $length);
444
445 // move stream pointer to next record
446 $this->_pos += 8 + $length;
447
448 // record is a container, read contents
450
451 if ($this->_object instanceof PHPExcel_Shared_Escher_DgContainer) {
452 // DgContainer
453 $this->_object->setSpgrContainer($spgrContainer);
454 } else {
455 // SpgrContainer
456 $this->_object->addChild($spgrContainer);
457 }
458
459 $reader = new PHPExcel_Reader_Excel5_Escher($spgrContainer);
460 $escher = $reader->load($recordData);
461 }
462
466 private function _readSpContainer()
467 {
468 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
469 $recordData = substr($this->_data, $this->_pos + 8, $length);
470
471 // add spContainer to spgrContainer
473 $this->_object->addChild($spContainer);
474
475 // move stream pointer to next record
476 $this->_pos += 8 + $length;
477
478 // record is a container, read contents
479 $reader = new PHPExcel_Reader_Excel5_Escher($spContainer);
480 $escher = $reader->load($recordData);
481 }
482
486 private function _readSpgr()
487 {
488 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
489 $recordData = substr($this->_data, $this->_pos + 8, $length);
490
491 // move stream pointer to next record
492 $this->_pos += 8 + $length;
493 }
494
498 private function _readSp()
499 {
500 // offset: 0; size: 2; recVer and recInstance
501
502 // bit: 4-15; mask: 0xFFF0; recInstance
503 $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4;
504
505 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
506 $recordData = substr($this->_data, $this->_pos + 8, $length);
507
508 // move stream pointer to next record
509 $this->_pos += 8 + $length;
510 }
511
515 private function _readClientTextbox()
516 {
517 // offset: 0; size: 2; recVer and recInstance
518
519 // bit: 4-15; mask: 0xFFF0; recInstance
520 $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4;
521
522 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
523 $recordData = substr($this->_data, $this->_pos + 8, $length);
524
525 // move stream pointer to next record
526 $this->_pos += 8 + $length;
527 }
528
532 private function _readClientAnchor()
533 {
534 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
535 $recordData = substr($this->_data, $this->_pos + 8, $length);
536
537 // move stream pointer to next record
538 $this->_pos += 8 + $length;
539
540 // offset: 2; size: 2; upper-left corner column index (0-based)
541 $c1 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 2);
542
543 // offset: 4; size: 2; upper-left corner horizontal offset in 1/1024 of column width
544 $startOffsetX = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 4);
545
546 // offset: 6; size: 2; upper-left corner row index (0-based)
547 $r1 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 6);
548
549 // offset: 8; size: 2; upper-left corner vertical offset in 1/256 of row height
550 $startOffsetY = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 8);
551
552 // offset: 10; size: 2; bottom-right corner column index (0-based)
553 $c2 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 10);
554
555 // offset: 12; size: 2; bottom-right corner horizontal offset in 1/1024 of column width
556 $endOffsetX = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 12);
557
558 // offset: 14; size: 2; bottom-right corner row index (0-based)
559 $r2 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 14);
560
561 // offset: 16; size: 2; bottom-right corner vertical offset in 1/256 of row height
562 $endOffsetY = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 16);
563
564 // set the start coordinates
565 $this->_object->setStartCoordinates(PHPExcel_Cell::stringFromColumnIndex($c1) . ($r1 + 1));
566
567 // set the start offsetX
568 $this->_object->setStartOffsetX($startOffsetX);
569
570 // set the start offsetY
571 $this->_object->setStartOffsetY($startOffsetY);
572
573 // set the end coordinates
574 $this->_object->setEndCoordinates(PHPExcel_Cell::stringFromColumnIndex($c2) . ($r2 + 1));
575
576 // set the end offsetX
577 $this->_object->setEndOffsetX($endOffsetX);
578
579 // set the end offsetY
580 $this->_object->setEndOffsetY($endOffsetY);
581 }
582
586 private function _readClientData()
587 {
588 $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4);
589 $recordData = substr($this->_data, $this->_pos + 8, $length);
590
591 // move stream pointer to next record
592 $this->_pos += 8 + $length;
593 }
594
601 private function _readOfficeArtRGFOPTE($data, $n) {
602
603 $splicedComplexData = substr($data, 6 * $n);
604
605 // loop through property-value pairs
606 for ($i = 0; $i < $n; ++$i) {
607 // read 6 bytes at a time
608 $fopte = substr($data, 6 * $i, 6);
609
610 // offset: 0; size: 2; opid
611 $opid = PHPExcel_Reader_Excel5::_GetInt2d($fopte, 0);
612
613 // bit: 0-13; mask: 0x3FFF; opid.opid
614 $opidOpid = (0x3FFF & $opid) >> 0;
615
616 // bit: 14; mask 0x4000; 1 = value in op field is BLIP identifier
617 $opidFBid = (0x4000 & $opid) >> 14;
618
619 // bit: 15; mask 0x8000; 1 = this is a complex property, op field specifies size of complex data
620 $opidFComplex = (0x8000 & $opid) >> 15;
621
622 // offset: 2; size: 4; the value for this property
623 $op = PHPExcel_Reader_Excel5::_GetInt4d($fopte, 2);
624
625 if ($opidFComplex) {
626 $complexData = substr($splicedComplexData, 0, $op);
627 $splicedComplexData = substr($splicedComplexData, $op);
628
629 // we store string value with complex data
630 $value = $complexData;
631 } else {
632 // we store integer value
633 $value = $op;
634 }
635
636 $this->_object->setOPT($opidOpid, $value);
637 }
638 }
639
640}
$n
Definition: RandomTest.php:80
$size
Definition: RandomTest.php:79
An exception for terminatinating execution or to throw for unit testing.
static stringFromColumnIndex($pColumnIndex=0)
String from columnindex.
Definition: Cell.php:825
_readSpContainer()
Read SpContainer record (Shape Container)
Definition: Escher.php:466
_readSpgrContainer()
Read SpgrContainer record (Shape Group Container)
Definition: Escher.php:438
_readTertiaryOPT()
Read TertiaryOPT record.
Definition: Escher.php:379
_readDgg()
Read Dgg record (Drawing Group)
Definition: Escher.php:182
_readBlipJPEG()
Read BlipJPEG record.
Definition: Escher.php:278
_readOfficeArtRGFOPTE($data, $n)
Read OfficeArtRGFOPTE table of property-value pairs.
Definition: Escher.php:601
_readBstoreContainer()
Read BstoreContainer record (Blip Store Container)
Definition: Escher.php:194
_readClientAnchor()
Read ClientAnchor record.
Definition: Escher.php:532
__construct($object)
Create a new PHPExcel_Reader_Excel5_Escher instance.
Definition: Escher.php:89
_readSpgr()
Read Spgr record (Shape Group)
Definition: Escher.php:486
_readDefault()
Read a generic record.
Definition: Escher.php:143
_readClientTextbox()
Read ClientTextbox record.
Definition: Escher.php:515
_readClientData()
Read ClientData record.
Definition: Escher.php:586
_readDggContainer()
Read DggContainer record (Drawing Group Container)
Definition: Escher.php:164
_readBlipPNG()
Read BlipPNG record.
Definition: Escher.php:319
_readDg()
Read Dg record (Drawing)
Definition: Escher.php:426
_readSp()
Read Sp record (Shape)
Definition: Escher.php:498
load($data)
Load Escher stream data.
Definition: Escher.php:99
_readSplitMenuColors()
Read SplitMenuColors record.
Definition: Escher.php:396
_readDgContainer()
Read DgContainer record (Drawing Container)
Definition: Escher.php:408
_readOPT()
Read OPT record.
Definition: Escher.php:360
_readBSE()
Read BSE record.
Definition: Escher.php:212
static _GetInt2d($data, $pos)
Read 16-bit unsigned integer.
Definition: Excel5.php:6774
static _GetInt4d($data, $pos)
Read 32-bit signed integer.
Definition: Excel5.php:6787