ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Escher.php
Go to the documentation of this file.
1 <?php
2 
4 
13 
14 class Escher
15 {
19  private $object;
20 
24  private $data;
25 
31  private $spOffsets;
32 
38  private $spTypes;
39 
45  public function __construct($object)
46  {
47  $this->object = $object;
48  }
49 
55  public function close()
56  {
57  // initialize
58  $this->data = '';
59 
60  switch (get_class($this->object)) {
61  case \PhpOffice\PhpSpreadsheet\Shared\Escher::class:
62  if ($dggContainer = $this->object->getDggContainer()) {
63  $writer = new self($dggContainer);
64  $this->data = $writer->close();
65  } elseif ($dgContainer = $this->object->getDgContainer()) {
66  $writer = new self($dgContainer);
67  $this->data = $writer->close();
68  $this->spOffsets = $writer->getSpOffsets();
69  $this->spTypes = $writer->getSpTypes();
70  }
71 
72  break;
73  case DggContainer::class:
74  // this is a container record
75 
76  // initialize
77  $innerData = '';
78 
79  // write the dgg
80  $recVer = 0x0;
81  $recInstance = 0x0000;
82  $recType = 0xF006;
83 
84  $recVerInstance = $recVer;
85  $recVerInstance |= $recInstance << 4;
86 
87  // dgg data
88  $dggData =
89  pack(
90  'VVVV',
91  $this->object->getSpIdMax(), // maximum shape identifier increased by one
92  $this->object->getCDgSaved() + 1, // number of file identifier clusters increased by one
93  $this->object->getCSpSaved(),
94  $this->object->getCDgSaved() // count total number of drawings saved
95  );
96 
97  // add file identifier clusters (one per drawing)
98  $IDCLs = $this->object->getIDCLs();
99 
100  foreach ($IDCLs as $dgId => $maxReducedSpId) {
101  $dggData .= pack('VV', $dgId, $maxReducedSpId + 1);
102  }
103 
104  $header = pack('vvV', $recVerInstance, $recType, strlen($dggData));
105  $innerData .= $header . $dggData;
106 
107  // write the bstoreContainer
108  if ($bstoreContainer = $this->object->getBstoreContainer()) {
109  $writer = new self($bstoreContainer);
110  $innerData .= $writer->close();
111  }
112 
113  // write the record
114  $recVer = 0xF;
115  $recInstance = 0x0000;
116  $recType = 0xF000;
117  $length = strlen($innerData);
118 
119  $recVerInstance = $recVer;
120  $recVerInstance |= $recInstance << 4;
121 
122  $header = pack('vvV', $recVerInstance, $recType, $length);
123 
124  $this->data = $header . $innerData;
125 
126  break;
127  case BstoreContainer::class:
128  // this is a container record
129 
130  // initialize
131  $innerData = '';
132 
133  // treat the inner data
134  if ($BSECollection = $this->object->getBSECollection()) {
135  foreach ($BSECollection as $BSE) {
136  $writer = new self($BSE);
137  $innerData .= $writer->close();
138  }
139  }
140 
141  // write the record
142  $recVer = 0xF;
143  $recInstance = count($this->object->getBSECollection());
144  $recType = 0xF001;
145  $length = strlen($innerData);
146 
147  $recVerInstance = $recVer;
148  $recVerInstance |= $recInstance << 4;
149 
150  $header = pack('vvV', $recVerInstance, $recType, $length);
151 
152  $this->data = $header . $innerData;
153 
154  break;
155  case BSE::class:
156  // this is a semi-container record
157 
158  // initialize
159  $innerData = '';
160 
161  // here we treat the inner data
162  if ($blip = $this->object->getBlip()) {
163  $writer = new self($blip);
164  $innerData .= $writer->close();
165  }
166 
167  // initialize
168  $data = '';
169 
170  $btWin32 = $this->object->getBlipType();
171  $btMacOS = $this->object->getBlipType();
172  $data .= pack('CC', $btWin32, $btMacOS);
173 
174  $rgbUid = pack('VVVV', 0, 0, 0, 0); // todo
175  $data .= $rgbUid;
176 
177  $tag = 0;
178  $size = strlen($innerData);
179  $cRef = 1;
180  $foDelay = 0; //todo
181  $unused1 = 0x0;
182  $cbName = 0x0;
183  $unused2 = 0x0;
184  $unused3 = 0x0;
185  $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3);
186 
187  $data .= $innerData;
188 
189  // write the record
190  $recVer = 0x2;
191  $recInstance = $this->object->getBlipType();
192  $recType = 0xF007;
193  $length = strlen($data);
194 
195  $recVerInstance = $recVer;
196  $recVerInstance |= $recInstance << 4;
197 
198  $header = pack('vvV', $recVerInstance, $recType, $length);
199 
200  $this->data = $header;
201 
202  $this->data .= $data;
203 
204  break;
205  case Blip::class:
206  // this is an atom record
207 
208  // write the record
209  switch ($this->object->getParent()->getBlipType()) {
210  case BSE::BLIPTYPE_JPEG:
211  // initialize
212  $innerData = '';
213 
214  $rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
215  $innerData .= $rgbUid1;
216 
217  $tag = 0xFF; // todo
218  $innerData .= pack('C', $tag);
219 
220  $innerData .= $this->object->getData();
221 
222  $recVer = 0x0;
223  $recInstance = 0x46A;
224  $recType = 0xF01D;
225  $length = strlen($innerData);
226 
227  $recVerInstance = $recVer;
228  $recVerInstance |= $recInstance << 4;
229 
230  $header = pack('vvV', $recVerInstance, $recType, $length);
231 
232  $this->data = $header;
233 
234  $this->data .= $innerData;
235 
236  break;
237  case BSE::BLIPTYPE_PNG:
238  // initialize
239  $innerData = '';
240 
241  $rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
242  $innerData .= $rgbUid1;
243 
244  $tag = 0xFF; // todo
245  $innerData .= pack('C', $tag);
246 
247  $innerData .= $this->object->getData();
248 
249  $recVer = 0x0;
250  $recInstance = 0x6E0;
251  $recType = 0xF01E;
252  $length = strlen($innerData);
253 
254  $recVerInstance = $recVer;
255  $recVerInstance |= $recInstance << 4;
256 
257  $header = pack('vvV', $recVerInstance, $recType, $length);
258 
259  $this->data = $header;
260 
261  $this->data .= $innerData;
262 
263  break;
264  }
265 
266  break;
267  case DgContainer::class:
268  // this is a container record
269 
270  // initialize
271  $innerData = '';
272 
273  // write the dg
274  $recVer = 0x0;
275  $recInstance = $this->object->getDgId();
276  $recType = 0xF008;
277  $length = 8;
278 
279  $recVerInstance = $recVer;
280  $recVerInstance |= $recInstance << 4;
281 
282  $header = pack('vvV', $recVerInstance, $recType, $length);
283 
284  // number of shapes in this drawing (including group shape)
285  $countShapes = count($this->object->getSpgrContainer()->getChildren());
286  $innerData .= $header . pack('VV', $countShapes, $this->object->getLastSpId());
287 
288  // write the spgrContainer
289  if ($spgrContainer = $this->object->getSpgrContainer()) {
290  $writer = new self($spgrContainer);
291  $innerData .= $writer->close();
292 
293  // get the shape offsets relative to the spgrContainer record
294  $spOffsets = $writer->getSpOffsets();
295  $spTypes = $writer->getSpTypes();
296 
297  // save the shape offsets relative to dgContainer
298  foreach ($spOffsets as &$spOffset) {
299  $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes)
300  }
301 
302  $this->spOffsets = $spOffsets;
303  $this->spTypes = $spTypes;
304  }
305 
306  // write the record
307  $recVer = 0xF;
308  $recInstance = 0x0000;
309  $recType = 0xF002;
310  $length = strlen($innerData);
311 
312  $recVerInstance = $recVer;
313  $recVerInstance |= $recInstance << 4;
314 
315  $header = pack('vvV', $recVerInstance, $recType, $length);
316 
317  $this->data = $header . $innerData;
318 
319  break;
320  case SpgrContainer::class:
321  // this is a container record
322 
323  // initialize
324  $innerData = '';
325 
326  // initialize spape offsets
327  $totalSize = 8;
328  $spOffsets = [];
329  $spTypes = [];
330 
331  // treat the inner data
332  foreach ($this->object->getChildren() as $spContainer) {
333  $writer = new self($spContainer);
334  $spData = $writer->close();
335  $innerData .= $spData;
336 
337  // save the shape offsets (where new shape records begin)
338  $totalSize += strlen($spData);
339  $spOffsets[] = $totalSize;
340 
341  $spTypes = array_merge($spTypes, $writer->getSpTypes());
342  }
343 
344  // write the record
345  $recVer = 0xF;
346  $recInstance = 0x0000;
347  $recType = 0xF003;
348  $length = strlen($innerData);
349 
350  $recVerInstance = $recVer;
351  $recVerInstance |= $recInstance << 4;
352 
353  $header = pack('vvV', $recVerInstance, $recType, $length);
354 
355  $this->data = $header . $innerData;
356  $this->spOffsets = $spOffsets;
357  $this->spTypes = $spTypes;
358 
359  break;
360  case SpContainer::class:
361  // initialize
362  $data = '';
363 
364  // build the data
365 
366  // write group shape record, if necessary?
367  if ($this->object->getSpgr()) {
368  $recVer = 0x1;
369  $recInstance = 0x0000;
370  $recType = 0xF009;
371  $length = 0x00000010;
372 
373  $recVerInstance = $recVer;
374  $recVerInstance |= $recInstance << 4;
375 
376  $header = pack('vvV', $recVerInstance, $recType, $length);
377 
378  $data .= $header . pack('VVVV', 0, 0, 0, 0);
379  }
380  $this->spTypes[] = ($this->object->getSpType());
381 
382  // write the shape record
383  $recVer = 0x2;
384  $recInstance = $this->object->getSpType(); // shape type
385  $recType = 0xF00A;
386  $length = 0x00000008;
387 
388  $recVerInstance = $recVer;
389  $recVerInstance |= $recInstance << 4;
390 
391  $header = pack('vvV', $recVerInstance, $recType, $length);
392 
393  $data .= $header . pack('VV', $this->object->getSpId(), $this->object->getSpgr() ? 0x0005 : 0x0A00);
394 
395  // the options
396  if ($this->object->getOPTCollection()) {
397  $optData = '';
398 
399  $recVer = 0x3;
400  $recInstance = count($this->object->getOPTCollection());
401  $recType = 0xF00B;
402  foreach ($this->object->getOPTCollection() as $property => $value) {
403  $optData .= pack('vV', $property, $value);
404  }
405  $length = strlen($optData);
406 
407  $recVerInstance = $recVer;
408  $recVerInstance |= $recInstance << 4;
409 
410  $header = pack('vvV', $recVerInstance, $recType, $length);
411  $data .= $header . $optData;
412  }
413 
414  // the client anchor
415  if ($this->object->getStartCoordinates()) {
416  $clientAnchorData = '';
417 
418  $recVer = 0x0;
419  $recInstance = 0x0;
420  $recType = 0xF010;
421 
422  // start coordinates
423  [$column, $row] = Coordinate::indexesFromString($this->object->getStartCoordinates());
424  $c1 = $column - 1;
425  $r1 = $row - 1;
426 
427  // start offsetX
428  $startOffsetX = $this->object->getStartOffsetX();
429 
430  // start offsetY
431  $startOffsetY = $this->object->getStartOffsetY();
432 
433  // end coordinates
434  [$column, $row] = Coordinate::indexesFromString($this->object->getEndCoordinates());
435  $c2 = $column - 1;
436  $r2 = $row - 1;
437 
438  // end offsetX
439  $endOffsetX = $this->object->getEndOffsetX();
440 
441  // end offsetY
442  $endOffsetY = $this->object->getEndOffsetY();
443 
444  $clientAnchorData = pack('vvvvvvvvv', $this->object->getSpFlag(), $c1, $startOffsetX, $r1, $startOffsetY, $c2, $endOffsetX, $r2, $endOffsetY);
445 
446  $length = strlen($clientAnchorData);
447 
448  $recVerInstance = $recVer;
449  $recVerInstance |= $recInstance << 4;
450 
451  $header = pack('vvV', $recVerInstance, $recType, $length);
452  $data .= $header . $clientAnchorData;
453  }
454 
455  // the client data, just empty for now
456  if (!$this->object->getSpgr()) {
457  $clientDataData = '';
458 
459  $recVer = 0x0;
460  $recInstance = 0x0;
461  $recType = 0xF011;
462 
463  $length = strlen($clientDataData);
464 
465  $recVerInstance = $recVer;
466  $recVerInstance |= $recInstance << 4;
467 
468  $header = pack('vvV', $recVerInstance, $recType, $length);
469  $data .= $header . $clientDataData;
470  }
471 
472  // write the record
473  $recVer = 0xF;
474  $recInstance = 0x0000;
475  $recType = 0xF004;
476  $length = strlen($data);
477 
478  $recVerInstance = $recVer;
479  $recVerInstance |= $recInstance << 4;
480 
481  $header = pack('vvV', $recVerInstance, $recType, $length);
482 
483  $this->data = $header . $data;
484 
485  break;
486  }
487 
488  return $this->data;
489  }
490 
496  public function getSpOffsets()
497  {
498  return $this->spOffsets;
499  }
500 
506  public function getSpTypes()
507  {
508  return $this->spTypes;
509  }
510 }
$object
The object we are writing.
Definition: Escher.php:19
$size
Definition: RandomTest.php:84
getSpOffsets()
Gets the shape offsets.
Definition: Escher.php:496
getSpTypes()
Gets the shape types.
Definition: Escher.php:506
close()
Process the object to be written.
Definition: Escher.php:55
static indexesFromString(string $coordinates)
Get indexes from a string coordinates.
Definition: Coordinate.php:52
$row
$this data['403_header']
__construct($object)
Constructor.
Definition: Escher.php:45
$data
The written binary data.
Definition: Escher.php:24
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35