Completed
Pull Request — develop (#208)
by Franck
07:39
created

ODPresentation::hash_pbkdf2()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 22
ccs 0
cts 9
cp 0
rs 8.9197
cc 4
eloc 9
nc 6
nop 6
crap 20
1
<?php
2
/**
3
 * This file is part of PHPPresentation - A pure PHP library for reading and writing
4
 * presentations documents.
5
 *
6
 * PHPPresentation is free software distributed under the terms of the GNU Lesser
7
 * General Public License version 3 as published by the Free Software Foundation.
8
 *
9
 * For the full copyright and license information, please read the LICENSE
10
 * file that was distributed with this source code. For the full list of
11
 * contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors.
12
 *
13
 * @link        https://github.com/PHPOffice/PHPPresentation
14
 * @copyright   2009-2015 PHPPresentation contributors
15
 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16
 */
17
18
namespace PhpOffice\PhpPresentation\Reader;
19
20
use ZipArchive;
21
use PhpOffice\Common\XMLReader;
22
use PhpOffice\Common\Drawing as CommonDrawing;
23
use PhpOffice\PhpPresentation\PhpPresentation;
24
use PhpOffice\PhpPresentation\Shape\Drawing\Gd;
25
use PhpOffice\PhpPresentation\Shape\RichText;
26
use PhpOffice\PhpPresentation\Shape\RichText\Paragraph;
27
use PhpOffice\PhpPresentation\Style\Bullet;
28
use PhpOffice\PhpPresentation\Style\Color;
29
use PhpOffice\PhpPresentation\Style\Font;
30
use PhpOffice\PhpPresentation\Style\Shadow;
31
use PhpOffice\PhpPresentation\Style\Alignment;
32
33
/**
34
 * Serialized format reader
35
 */
36
class ODPresentation extends AbstractReader implements ReaderInterface
37
{
38
    /**
39
     * Output Object
40
     * @var PhpPresentation
41
     */
42
    protected $oPhpPresentation;
43
44
    /**
45
     * Output Object
46
     * @var \ZipArchive
47
     */
48
    protected $oZip;
49
50
    /**
51
     * @var string
52
     */
53
    protected $filename;
54
55
    /**
56
     * @var array[]
57
     */
58
    protected $arrayStyles = array();
59
60
    /**
61
     * @var array[]
62
     */
63
    protected $arrayCommonStyles = array();
64
65
    /**
66
     * @var \PhpOffice\Common\XMLReader
67
     */
68
    protected $oXMLReader;
69
70
    /**
71
     * @var \PhpOffice\Common\XMLReader
72
     */
73
    protected $oXMLMetaInfManifest;
74
75
    /**
76
     * Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file?
77
     *
78
     * @param  string $pFilename
79
     * @throws \Exception
80
     * @return boolean
81
     */
82 2
    public function canRead($pFilename)
83
    {
84 2
        return $this->fileSupportsUnserializePhpPresentation($pFilename);
85
    }
86
87
    /**
88
     * Does a file support UnserializePhpPresentation ?
89
     *
90
     * @param  string    $pFilename
91
     * @throws \Exception
92
     * @return boolean
93
     */
94 8
    public function fileSupportsUnserializePhpPresentation($pFilename = '')
95
    {
96
        // Check if file exists
97 8
        if (!file_exists($pFilename)) {
98 2
            throw new \Exception("Could not open " . $pFilename . " for reading! File does not exist.");
99
        }
100
        
101 6
        $oZip = new ZipArchive();
102
        // Is it a zip ?
103 6
        if ($oZip->open($pFilename) === true) {
104
            // Is it an OpenXML Document ?
105
            // Is it a Presentation ?
106 4
            if (is_array($oZip->statName('META-INF/manifest.xml')) && is_array($oZip->statName('mimetype')) && $oZip->getFromName('mimetype') == 'application/vnd.oasis.opendocument.presentation') {
107 4
                return true;
108
            }
109
        }
110 3
        return false;
111
    }
112
113
    /**
114
     * Loads PhpPresentation Serialized file
115
     *
116
     * @param  string        $pFilename
117
     * @return \PhpOffice\PhpPresentation\PhpPresentation
118
     * @throws \Exception
119
     */
120 5
    public function load($pFilename)
121
    {
122
        // Unserialize... First make sure the file supports it!
123 5
        if (!$this->fileSupportsUnserializePhpPresentation($pFilename)) {
124 1
            throw new \Exception("Invalid file format for PhpOffice\PhpPresentation\Reader\ODPresentation: " . $pFilename . ".");
125
        }
126
127 3
        return $this->loadFile($pFilename);
128
    }
129
130
    /**
131
     * Load PhpPresentation Serialized file
132
     *
133
     * @param  string        $pFilename
134
     * @return \PhpOffice\PhpPresentation\PhpPresentation
135
     */
136 3
    protected function loadFile($pFilename)
137
    {
138 3
        $this->filename = $pFilename;
139
140 3
        $this->oPhpPresentation = new PhpPresentation();
141 3
        $this->oPhpPresentation->removeSlideByIndex();
142
        
143 3
        $this->oZip = new ZipArchive();
144 3
        $this->oZip->open($this->filename);
145
146 3
        if ($this->loadFileFromODP('meta.xml') !== false) {
147 3
            $this->loadDocumentProperties();
148
        }
149 3
        if ($this->loadFileFromODP('styles.xml') !== false) {
150 3
            $this->loadStylesFile();
151
        }
152 3
        if ($this->loadFileFromODP('content.xml') !== false) {
153 3
            $this->loadSlides();
154
        }
155
156 3
        return $this->oPhpPresentation;
157
    }
158
    
159
    /**
160
     * Read Document Properties
161
     */
162 3
    protected function loadDocumentProperties()
163
    {
164
        $arrayProperties = array(
165 3
            '/office:document-meta/office:meta/meta:initial-creator' => 'setCreator',
166
            '/office:document-meta/office:meta/dc:creator' => 'setLastModifiedBy',
167
            '/office:document-meta/office:meta/dc:title' => 'setTitle',
168
            '/office:document-meta/office:meta/dc:description' => 'setDescription',
169
            '/office:document-meta/office:meta/dc:subject' => 'setSubject',
170
            '/office:document-meta/office:meta/meta:keyword' => 'setKeywords',
171
            '/office:document-meta/office:meta/meta:creation-date' => 'setCreated',
172
            '/office:document-meta/office:meta/dc:date' => 'setModified',
173
        );
174 3
        $oProperties = $this->oPhpPresentation->getDocumentProperties();
175 3
        foreach ($arrayProperties as $path => $property) {
176 3
            if (is_object($oElement = $this->oXMLReader->getElement($path))) {
177 3
                if (in_array($property, array('setCreated', 'setModified'))) {
178 3
                    $oDateTime = new \DateTime();
179 3
                    $oDateTime->createFromFormat(\DateTime::W3C, $oElement->nodeValue);
180 3
                    $oProperties->{$property}($oDateTime->getTimestamp());
181
                } else {
182 3
                    $oProperties->{$property}($oElement->nodeValue);
183
                }
184
            }
185
        }
186 3
    }
187
    
188
    /**
189
     * Extract all slides
190
     */
191 3
    protected function loadSlides()
192
    {
193 3
        foreach ($this->oXMLReader->getElements('/office:document-content/office:automatic-styles/*') as $oElement) {
194 3
            if ($oElement->hasAttribute('style:name')) {
195 3
                $this->loadStyle($oElement);
196
            }
197
        }
198 3
        foreach ($this->oXMLReader->getElements('/office:document-content/office:body/office:presentation/draw:page') as $oElement) {
199 3
            if ($oElement->nodeName == 'draw:page') {
200 3
                $this->loadSlide($oElement);
201
            }
202
        }
203 3
    }
204
    
205
    /**
206
     * Extract style
207
     * @param \DOMElement $nodeStyle
208
     */
209 3
    protected function loadStyle(\DOMElement $nodeStyle)
210
    {
211 3
        $keyStyle = $nodeStyle->getAttribute('style:name');
212
213 3
        $nodeDrawingPageProps = $this->oXMLReader->getElement('style:drawing-page-properties', $nodeStyle);
214 3
        if ($nodeDrawingPageProps) {
215
            // Read Background Color
216 3
            if ($nodeDrawingPageProps->hasAttribute('draw:fill-color') && $nodeDrawingPageProps->getAttribute('draw:fill') == 'solid') {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
217
                $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Color();
218
                $oColor = new Color();
219
                $oColor->setRGB(substr($nodeDrawingPageProps->getAttribute('draw:fill-color'), -6));
220
                $oBackground->setColor($oColor);
221
            }
222
            // Read Background Image
223 3
            if ($nodeDrawingPageProps->getAttribute('draw:fill') == 'bitmap' && $nodeDrawingPageProps->hasAttribute('draw:fill-image-name')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
224
                $nameStyle = $nodeDrawingPageProps->getAttribute('draw:fill-image-name');
225
                if (!empty($this->arrayCommonStyles[$nameStyle]) && $this->arrayCommonStyles[$nameStyle]['type'] == 'image' && !empty($this->arrayCommonStyles[$nameStyle]['path'])) {
226
                    $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderODPBkg');
227
                    $contentImg = $this->oZip->getFromName($this->arrayCommonStyles[$nameStyle]['path']);
228
                    file_put_contents($tmpBkgImg, $contentImg);
229
230
                    $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Image();
231
                    $oBackground->setPath($tmpBkgImg);
232
                }
233
            }
234
        }
235
236 3
        $nodeGraphicProps = $this->oXMLReader->getElement('style:graphic-properties', $nodeStyle);
237 3
        if ($nodeGraphicProps) {
238
            // Read Shadow
239 3
            if ($nodeGraphicProps->hasAttribute('draw:shadow') && $nodeGraphicProps->getAttribute('draw:shadow') == 'visible') {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
240 1
                $oShadow = new Shadow();
241 1
                $oShadow->setVisible(true);
242 1
                if ($nodeGraphicProps->hasAttribute('draw:shadow-color')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
243 1
                    $oShadow->getColor()->setRGB(substr($nodeGraphicProps->getAttribute('draw:shadow-color'), -6));
244
                }
245 1
                if ($nodeGraphicProps->hasAttribute('draw:shadow-opacity')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
246 1
                    $oShadow->setAlpha(100 - (int)substr($nodeGraphicProps->getAttribute('draw:shadow-opacity'), 0, -1));
247
                }
248 1
                if ($nodeGraphicProps->hasAttribute('draw:shadow-offset-x') && $nodeGraphicProps->hasAttribute('draw:shadow-offset-y')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
249 1
                    $offsetX = substr($nodeGraphicProps->getAttribute('draw:shadow-offset-x'), 0, -2);
250 1
                    $offsetY = substr($nodeGraphicProps->getAttribute('draw:shadow-offset-y'), 0, -2);
251 1
                    $distance = 0;
252 1
                    if ($offsetX != 0) {
253 1
                        $distance = ($offsetX < 0 ? $offsetX * -1 : $offsetX);
254
                    } elseif ($offsetY != 0) {
255
                        $distance = ($offsetY < 0 ? $offsetY * -1 : $offsetY);
256
                    }
257 1
                    $oShadow->setDirection(rad2deg(atan2($offsetY, $offsetX)));
258 1
                    $oShadow->setDistance(CommonDrawing::centimetersToPixels($distance));
259
                }
260
            }
261
        }
262
        
263 3
        $nodeTextProperties = $this->oXMLReader->getElement('style:text-properties', $nodeStyle);
264 3
        if ($nodeTextProperties) {
265 1
            $oFont = new Font();
266 1
            if ($nodeTextProperties->hasAttribute('fo:color')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
267 1
                $oFont->getColor()->setRGB(substr($nodeTextProperties->getAttribute('fo:color'), -6));
268
            }
269 1
            if ($nodeTextProperties->hasAttribute('fo:font-family')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
270 1
                $oFont->setName($nodeTextProperties->getAttribute('fo:font-family'));
271
            }
272 1
            if ($nodeTextProperties->hasAttribute('fo:font-weight') && $nodeTextProperties->getAttribute('fo:font-weight') == 'bold') {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
273 1
                $oFont->setBold(true);
274
            }
275 1
            if ($nodeTextProperties->hasAttribute('fo:font-size')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
276 1
                $oFont->setSize(substr($nodeTextProperties->getAttribute('fo:font-size'), 0, -2));
277
            }
278
        }
279
280 3
        $nodeParagraphProps = $this->oXMLReader->getElement('style:paragraph-properties', $nodeStyle);
281 3
        if ($nodeParagraphProps) {
282 2
            $oAlignment = new Alignment();
283 2
            if ($nodeParagraphProps->hasAttribute('fo:text-align')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
284 2
                $oAlignment->setHorizontal($nodeParagraphProps->getAttribute('fo:text-align'));
285
            }
286
        }
287
        
288 3
        if ($nodeStyle->nodeName == 'text:list-style') {
289 2
            $arrayListStyle = array();
290 2
            foreach ($this->oXMLReader->getElements('text:list-level-style-bullet', $nodeStyle) as $oNodeListLevel) {
291 2
                $oAlignment = new Alignment();
292 2
                $oBullet = new Bullet();
293 2
                $oBullet->setBulletType(Bullet::TYPE_NONE);
294 2
                if ($oNodeListLevel->hasAttribute('text:level')) {
295 2
                    $oAlignment->setLevel((int) $oNodeListLevel->getAttribute('text:level') - 1);
296
                }
297 2
                if ($oNodeListLevel->hasAttribute('text:bullet-char')) {
298 2
                    $oBullet->setBulletChar($oNodeListLevel->getAttribute('text:bullet-char'));
299 2
                    $oBullet->setBulletType(Bullet::TYPE_BULLET);
300
                }
301
                
302 2
                $oNodeListProperties = $this->oXMLReader->getElement('style:list-level-properties', $oNodeListLevel);
303 2
                if ($oNodeListProperties) {
304 2
                    if ($oNodeListProperties->hasAttribute('text:min-label-width')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
305 2
                        $oAlignment->setIndent((int)round(CommonDrawing::centimetersToPixels(substr($oNodeListProperties->getAttribute('text:min-label-width'), 0, -2))));
306
                    }
307 2
                    if ($oNodeListProperties->hasAttribute('text:space-before')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
308 2
                        $iSpaceBefore = CommonDrawing::centimetersToPixels(substr($oNodeListProperties->getAttribute('text:space-before'), 0, -2));
309 2
                        $iMarginLeft = $iSpaceBefore + $oAlignment->getIndent();
310 2
                        $oAlignment->setMarginLeft($iMarginLeft);
311
                    }
312
                }
313 2
                $oNodeTextProperties = $this->oXMLReader->getElement('style:text-properties', $oNodeListLevel);
314 2
                if ($oNodeTextProperties) {
315 2
                    if ($oNodeTextProperties->hasAttribute('fo:font-family')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
316 2
                        $oBullet->setBulletFont($oNodeTextProperties->getAttribute('fo:font-family'));
317
                    }
318
                }
319
                
320 2
                $arrayListStyle[$oAlignment->getLevel()] = array(
321 2
                    'alignment' => $oAlignment,
322 2
                    'bullet' => $oBullet,
323
                );
324
            }
325
        }
326
        
327 3
        $this->arrayStyles[$keyStyle] = array(
328 3
            'alignment' => isset($oAlignment) ? $oAlignment : null,
329
            'background' => isset($oBackground) ? $oBackground : null,
330 1
            'font' => isset($oFont) ? $oFont : null,
331 1
            'shadow' => isset($oShadow) ? $oShadow : null,
332 2
            'listStyle' => isset($arrayListStyle) ? $arrayListStyle : null,
333
        );
334
        
335 3
        return true;
336
    }
337
338
    /**
339
     * Read Slide
340
     *
341
     * @param \DOMElement $nodeSlide
342
     */
343 3
    protected function loadSlide(\DOMElement $nodeSlide)
344
    {
345
        // Core
346 3
        $this->oPhpPresentation->createSlide();
347 3
        $this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1);
348 3
        if ($nodeSlide->hasAttribute('draw:name')) {
349 3
            $this->oPhpPresentation->getActiveSlide()->setName($nodeSlide->getAttribute('draw:name'));
350
        }
351 3
        if ($nodeSlide->hasAttribute('draw:style-name')) {
352 3
            $keyStyle = $nodeSlide->getAttribute('draw:style-name');
353 3
            if (isset($this->arrayStyles[$keyStyle])) {
354 3
                $this->oPhpPresentation->getActiveSlide()->setBackground($this->arrayStyles[$keyStyle]['background']);
355
            }
356
        }
357 3
        foreach ($this->oXMLReader->getElements('draw:frame', $nodeSlide) as $oNodeFrame) {
358 3
            if ($this->oXMLReader->getElement('draw:image', $oNodeFrame)) {
359 2
                $this->loadShapeDrawing($oNodeFrame);
360 2
                continue;
361
            }
362 3
            if ($this->oXMLReader->getElement('draw:text-box', $oNodeFrame)) {
363 3
                $this->loadShapeRichText($oNodeFrame);
364 3
                continue;
365
            }
366
        }
367 3
        return true;
368
    }
369
    
370
    /**
371
     * Read Shape Drawing
372
     *
373
     * @param \DOMElement $oNodeFrame
374
     */
375 2
    protected function loadShapeDrawing(\DOMElement $oNodeFrame)
376
    {
377
        // Core
378 2
        $oShape = new Gd();
379 2
        $oShape->getShadow()->setVisible(false);
380
381 2
        $oNodeImage = $this->oXMLReader->getElement('draw:image', $oNodeFrame);
382 2
        if ($oNodeImage) {
383 2
            if ($oNodeImage->hasAttribute('xlink:href')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
384 2
                $sFilename = $oNodeImage->getAttribute('xlink:href');
385
                // svm = StarView Metafile
386 2
                if (pathinfo($sFilename, PATHINFO_EXTENSION) == 'svm') {
387 1
                    return;
388
                }
389 2
                $imageFile = $this->oZip->getFromName($sFilename);
390 2
                if (!empty($imageFile)) {
391 2
                    $oShape->setImageResource(imagecreatefromstring($imageFile));
392
                }
393
            }
394
        }
395
        
396 2
        $oShape->setName($oNodeFrame->hasAttribute('draw:name') ? $oNodeFrame->getAttribute('draw:name') : '');
397 2
        $oShape->setDescription($oNodeFrame->hasAttribute('draw:name') ? $oNodeFrame->getAttribute('draw:name') : '');
398 2
        $oShape->setResizeProportional(false);
399 2
        $oShape->setWidth($oNodeFrame->hasAttribute('svg:width') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:width'), 0, -2))) : '');
400 2
        $oShape->setHeight($oNodeFrame->hasAttribute('svg:height') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:height'), 0, -2))) : '');
401 2
        $oShape->setResizeProportional(true);
402 2
        $oShape->setOffsetX($oNodeFrame->hasAttribute('svg:x') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:x'), 0, -2))) : '');
403 2
        $oShape->setOffsetY($oNodeFrame->hasAttribute('svg:y') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:y'), 0, -2))) : '');
404
        
405 2
        if ($oNodeFrame->hasAttribute('draw:style-name')) {
406 2
            $keyStyle = $oNodeFrame->getAttribute('draw:style-name');
407 2
            if (isset($this->arrayStyles[$keyStyle])) {
408 2
                $oShape->setShadow($this->arrayStyles[$keyStyle]['shadow']);
409
            }
410
        }
411
        
412 2
        $this->oPhpPresentation->getActiveSlide()->addShape($oShape);
413 2
    }
414
415
    /**
416
     * Read Shape RichText
417
     *
418
     * @param \DOMElement $oNodeFrame
419
     */
420 3
    protected function loadShapeRichText(\DOMElement $oNodeFrame)
421
    {
422
        // Core
423 3
        $oShape = $this->oPhpPresentation->getActiveSlide()->createRichTextShape();
424 3
        $oShape->setParagraphs(array());
425
        
426 3
        $oShape->setWidth($oNodeFrame->hasAttribute('svg:width') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:width'), 0, -2))) : '');
427 3
        $oShape->setHeight($oNodeFrame->hasAttribute('svg:height') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:height'), 0, -2))) : '');
428 3
        $oShape->setOffsetX($oNodeFrame->hasAttribute('svg:x') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:x'), 0, -2))) : '');
429 3
        $oShape->setOffsetY($oNodeFrame->hasAttribute('svg:y') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:y'), 0, -2))) : '');
430
        
431 3
        foreach ($this->oXMLReader->getElements('draw:text-box/*', $oNodeFrame) as $oNodeParagraph) {
432 2
            $this->levelParagraph = 0;
433 2
            if ($oNodeParagraph->nodeName == 'text:p') {
434 2
                $this->readParagraph($oShape, $oNodeParagraph);
435
            }
436 2
            if ($oNodeParagraph->nodeName == 'text:list') {
437 2
                $this->readList($oShape, $oNodeParagraph);
438
            }
439
        }
440
        
441 3
        if (count($oShape->getParagraphs()) > 0) {
442 2
            $oShape->setActiveParagraph(0);
443
        }
444 3
    }
445
    
446
    protected $levelParagraph = 0;
447
    
448
    /**
449
     * Read Paragraph
450
     * @param RichText $oShape
451
     * @param \DOMElement $oNodeParent
452
     */
453 2
    protected function readParagraph(RichText $oShape, \DOMElement $oNodeParent)
454
    {
455 2
        $oParagraph = $oShape->createParagraph();
456 2
        $oDomList = $this->oXMLReader->getElements('text:span', $oNodeParent);
457 2
        if ($oDomList->length == 0) {
458 1
            $this->readParagraphItem($oParagraph, $oNodeParent);
459
        } else {
460 1
            foreach ($oDomList as $oNodeRichTextElement) {
461 1
                $this->readParagraphItem($oParagraph, $oNodeRichTextElement);
462
            }
463
        }
464 2
    }
465
    
466
    /**
467
     * Read Paragraph Item
468
     * @param RichText $oShape
0 ignored issues
show
Bug introduced by
There is no parameter named $oShape. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
469
     * @param \DOMElement $oNodeParent
470
     */
471 2
    protected function readParagraphItem(Paragraph $oParagraph, \DOMElement $oNodeParent)
472
    {
473 2
        if ($this->oXMLReader->elementExists('text:line-break', $oNodeParent)) {
474 1
            $oParagraph->createBreak();
475
        } else {
476 2
            $oTextRun = $oParagraph->createTextRun();
477 2
            if ($oNodeParent->hasAttribute('text:style-name')) {
478 1
                $keyStyle = $oNodeParent->getAttribute('text:style-name');
479 1
                if (isset($this->arrayStyles[$keyStyle])) {
480 1
                    $oTextRun->setFont($this->arrayStyles[$keyStyle]['font']);
481
                }
482
            }
483 2
            if ($oTextRunLink = $this->oXMLReader->getElement('text:a', $oNodeParent)) {
484 1
                $oTextRun->setText($oTextRunLink->nodeValue);
485 1
                if ($oTextRunLink->hasAttribute('xlink:href')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
486 1
                    $oTextRun->getHyperlink()->setUrl($oTextRunLink->getAttribute('xlink:href'));
487
                }
488
            } else {
489 2
                $oTextRun->setText($oNodeParent->nodeValue);
490
            }
491
        }
492 2
    }
493
494
    /**
495
     * Read List
496
     *
497
     * @param RichText $oShape
498
     * @param \DOMElement $oNodeParent
499
     */
500 1
    protected function readList(RichText $oShape, \DOMElement $oNodeParent)
501
    {
502 1
        foreach ($this->oXMLReader->getElements('text:list-item/*', $oNodeParent) as $oNodeListItem) {
503 1
            if ($oNodeListItem->nodeName == 'text:p') {
504 1
                $this->readListItem($oShape, $oNodeListItem, $oNodeParent);
505
            }
506 1
            if ($oNodeListItem->nodeName == 'text:list') {
507 1
                $this->levelParagraph++;
508 1
                $this->readList($oShape, $oNodeListItem);
509 1
                $this->levelParagraph--;
510
            }
511
        }
512 1
    }
513
    
514
    /**
515
     * Read List Item
516
     * @param RichText $oShape
517
     * @param \DOMElement $oNodeParent
518
     * @param \DOMElement $oNodeParagraph
519
     */
520 1
    protected function readListItem(RichText $oShape, \DOMElement $oNodeParent, \DOMElement $oNodeParagraph)
521
    {
522 1
        $oParagraph = $oShape->createParagraph();
523 1
        if ($oNodeParagraph->hasAttribute('text:style-name')) {
524 1
            $keyStyle = $oNodeParagraph->getAttribute('text:style-name');
525 1
            if (isset($this->arrayStyles[$keyStyle])) {
526 1
                $oParagraph->setAlignment($this->arrayStyles[$keyStyle]['listStyle'][$this->levelParagraph]['alignment']);
527 1
                $oParagraph->setBulletStyle($this->arrayStyles[$keyStyle]['listStyle'][$this->levelParagraph]['bullet']);
528
            }
529
        }
530 1
        foreach ($this->oXMLReader->getElements('text:span', $oNodeParent) as $oNodeRichTextElement) {
531 1
            $this->readParagraphItem($oParagraph, $oNodeRichTextElement);
532
        }
533 1
    }
534
535
    /**
536
     * Load file 'styles.xml'
537
     */
538 3
    protected function loadStylesFile()
539
    {
540 3
        foreach ($this->oXMLReader->getElements('/office:document-styles/office:styles/*') as $oElement) {
541 3
            if ($oElement->nodeName == 'draw:fill-image') {
542
                $this->arrayCommonStyles[$oElement->getAttribute('draw:name')] = array(
543 3
                    'type' => 'image',
544
                    'path' => $oElement->hasAttribute('xlink:href') ? $oElement->getAttribute('xlink:href') : null
545
                );
546
            }
547
        }
548 3
    }
549
550
    /**
551
     * @param string $filename
552
     * @return bool
553
     * @throws \Exception
554
     */
555 3
    protected function loadFileFromODP($filename)
556
    {
557 3
        $bEncrypted = false;
558
559 3
        if (!$this->oXMLMetaInfManifest) {
560 3
            $this->oXMLMetaInfManifest = new XMLReader();
561 3
            if ($this->oXMLMetaInfManifest->getDomFromZip($this->filename, 'META-INF/manifest.xml') === false) {
562
                return false;
563
            }
564
        }
565
        // Search file in META-INF/manifest.xml
566 3
        $oElement = $this->oXMLMetaInfManifest->getElement('/manifest:manifest/manifest:file-entry[@manifest:full-path=\''.$filename.'\']');
567 3
        if (!$oElement) {
568
            return false;
569
        }
570
        // Has it some manifest:encryption-data ?
571 3
        $oElementEncryption = $this->oXMLMetaInfManifest->getElement('manifest:encryption-data', $oElement);
0 ignored issues
show
Documentation introduced by
$oElement is of type object<DOMNode>, but the function expects a null|object<DOMElement>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
572 3
        if ($oElementEncryption) {
573
            $bEncrypted = true;
574
        }
575
576 3
        $fileContent = $this->oZip->getFromName($filename);
577 3
        if (!$fileContent){
578
            return false;
579
        }
580
581
        // No Encrypted file
582 3
        if (!$bEncrypted) {
583 3
            $this->oXMLReader = new XMLReader();
584 3
            $this->oXMLReader->getDomFromString($fileContent);
585 3
            return true;
586
        }
587
588
        //return false;
589
        /*
590
          <manifest:encryption-data
591
                manifest:checksum-type="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#sha256-1k"
592
                manifest:checksum="BfB+taOY0kcVO/9WNi4DfqioRp3LMwVoNbqfAQ37yac=">
593
              <manifest:algorithm
594
                    manifest:algorithm-name="http://www.w3.org/2001/04/xmlenc#aes256-cbc"
595
                    manifest:initialisation-vector="I7rMXmvuynJFxJtm+EQ5qA=="/>
596
              <manifest:key-derivation
597
                    manifest:key-derivation-name="PBKDF2"
598
                    manifest:key-size="32"
599
                    manifest:iteration-count="1024"
600
                    manifest:salt="Mows9XX/YiNKNJ0qll3jgA=="/>
601
              <manifest:start-key-generation
602
                    manifest:start-key-generation-name="http://www.w3.org/2000/09/xmldsig#sha256"
603
                    manifest:key-size="32"/>
604
          </manifest:encryption-data>
605
         </manifest:file-entry>
606
         */
607
        return false;
608
        // Encrypted file
609
        $checksum = $oElementEncryption->getAttribute('manifest:checksum');
0 ignored issues
show
Unused Code introduced by
// Encrypted file $check...e('manifest:checksum'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
Unused Code introduced by
$checksum is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
610
611
        $oEltKeyDerivation = $this->oXMLMetaInfManifest->getElement('manifest:key-derivation', $oElementEncryption);
612
        $salt = $oEltKeyDerivation->getAttribute('manifest:salt');
613
        //$salt = base64_decode($salt);
614
        echo 'manifest:salt : ';
615
        var_dump($salt);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($salt); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
616
        $iterationCount = $oEltKeyDerivation->getAttribute('manifest:iteration-count');
617
        echo 'manifest:iteration-count : ';
618
        var_dump($iterationCount);
619
        $keySize = $oEltKeyDerivation->getAttribute('manifest:key-size');
620
        echo 'manifest:key-size : ';
621
        var_dump($keySize);
622
623
        $oEltAlgorithm = $this->oXMLMetaInfManifest->getElement('manifest:algorithm', $oElementEncryption);
624
        $iv = $oEltAlgorithm->getAttribute('manifest:initialisation-vector');
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $iv. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
625
        $iv = base64_decode($iv);
626
        echo 'manifest:initialisation-vector : ';
627
        var_dump($iv);
628
629
        $pwdHash = hash('sha256', $this->getPassword());
630
        echo 'sha256('.$this->getPassword().'): ';
631
        var_dump($pwdHash);
632
        //$pwdHash = substr($pwdHash, 0 , 32);
633
        //var_dump($pwdHash);
634
635
        $key = hash_pbkdf2('sha1', $pwdHash, $salt, $iterationCount, $keySize, true);
636
        echo 'hash_pbkdf2 (sha1, hash, salt, iterationCount, $iterationCount) : ';
637
        var_dump($key);
638
        //$key = $this->hash_pbkdf2('sha1', $pwdHash, $salt, $iterationCount, $keySize, true);
639
        //echo 'hash_pbkdf2 (sha1, hash, salt, iterationCount, $iterationCount) : ';
640
        //var_dump($key);
641
642
        $data = openssl_decrypt($fileContent, 'AES-256-CBC', $key, 0, $iv);
643
        if(!$data) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
644
            while ($msg = openssl_error_string())
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
Coding Style introduced by
Expected 0 spaces before semicolon; newline found
Loading history...
645
                var_dump($msg);
646
            die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method loadFileFromODP() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
647
        } else {
648
            var_dump($data);
649
            $data = gzinflate($data);
650
            var_dump($data);
651
        }
652
653
        /*$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $fileContent, MCRYPT_MODE_CBC, $iv);
654
        var_dump($data);
655
        $data = gzinflate($data);
656
        if($data) {
657
            var_dump($data);
658
        }*/
659
660
        return false;
661
    }
662
663
    protected function hash_pbkdf2($a = 'sha256', $password, $salt, $rounds = 5000, $key_length = 32, $raw_output = false)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $a. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Coding Style Naming introduced by
The method hash_pbkdf2 is not named in camelCase.

This check marks method names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $key_length is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The parameter $raw_output is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The variable $key_length is not named in camelCase.

This check marks variable names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Naming introduced by
The variable $raw_output is not named in camelCase.

This check marks variable names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style introduced by
Method name "ODPresentation::hash_pbkdf2" is not in camel caps format
Loading history...
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
664
    {
665
        // Derived key
666
        $dk = '';
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $dk. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
667
        // Create key
668
        for ($block=1; $block<=$key_length; $block++)
669
        {
670
            // Initial hash for this block
671
            $ib = $h = hash_hmac($a, $salt . pack('N', $block), $password, true);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ib. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Comprehensibility introduced by
Avoid variables with short names like $h. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
672
            // Perform block iterations
673
            for ($i=1; $i<$rounds; $i++)
674
            {
675
                // XOR each iteration
676
                $ib ^= ($h = hash_hmac($a, $h, $password, true));
677
            }
678
            // Append iterated block
679
            $dk .= $ib;
680
        }
681
        // Return derived key of correct length
682
        $key = substr($dk, 0, $key_length);
683
        return $raw_output ? $key : base64_encode($key);
684
    }
685
686
}
687