Completed
Pull Request — develop (#208)
by Franck
08:10
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 11
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\Hyperlink;
25
use PhpOffice\PhpPresentation\Shape\MemoryDrawing;
26
use PhpOffice\PhpPresentation\Style\Bullet;
27
use PhpOffice\PhpPresentation\Style\Color;
28
use PhpOffice\PhpPresentation\Style\Font;
29
use PhpOffice\PhpPresentation\Style\Shadow;
30
use PhpOffice\PhpPresentation\Style\Alignment;
31
use PhpOffice\PhpPresentation\Style\PhpOffice\PhpPresentation\Style;
32
use PhpOffice\PhpPresentation\Shape\RichText;
33
use PhpOffice\PhpPresentation\Shape\RichText\Paragraph;
34
use PhpOffice\Common\PhpOffice\Common;
35
36
/**
37
 * Serialized format reader
38
 */
39
class ODPresentation extends AbstractReader implements ReaderInterface
40
{
41
    /**
42
     * Output Object
43
     * @var PhpPresentation
44
     */
45
    protected $oPhpPresentation;
46
47
    /**
48
     * Output Object
49
     * @var \ZipArchive
50
     */
51
    protected $oZip;
52
53
    /**
54
     * @var string
55
     */
56
    protected $filename;
57
58
    /**
59
     * @var array[]
60
     */
61
    protected $arrayStyles = array();
62
63
    /**
64
     * @var array[]
65
     */
66
    protected $arrayCommonStyles = array();
67
68
    /**
69
     * @var \PhpOffice\Common\XMLReader
70
     */
71
    protected $oXMLReader;
72
73
    /**
74
     * @var \PhpOffice\Common\XMLReader
75
     */
76
    protected $oXMLMetaInfManifest;
77
78
    /**
79
     * Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file?
80
     *
81
     * @param  string $pFilename
82
     * @throws \Exception
83
     * @return boolean
84
     */
85 2
    public function canRead($pFilename)
86
    {
87 2
        return $this->fileSupportsUnserializePhpPresentation($pFilename);
88
    }
89
90
    /**
91
     * Does a file support UnserializePhpPresentation ?
92
     *
93
     * @param  string    $pFilename
94
     * @throws \Exception
95
     * @return boolean
96
     */
97 8
    public function fileSupportsUnserializePhpPresentation($pFilename = '')
98
    {
99
        // Check if file exists
100 8
        if (!file_exists($pFilename)) {
101 2
            throw new \Exception("Could not open " . $pFilename . " for reading! File does not exist.");
102
        }
103
        
104 6
        $oZip = new ZipArchive();
105
        // Is it a zip ?
106 6
        if ($oZip->open($pFilename) === true) {
107
            // Is it an OpenXML Document ?
108
            // Is it a Presentation ?
109 4
            if (is_array($oZip->statName('META-INF/manifest.xml')) && is_array($oZip->statName('mimetype')) && $oZip->getFromName('mimetype') == 'application/vnd.oasis.opendocument.presentation') {
110 4
                return true;
111
            }
112 1
        }
113 3
        return false;
114
    }
115
116
    /**
117
     * Loads PhpPresentation Serialized file
118
     *
119
     * @param  string        $pFilename
120
     * @return \PhpOffice\PhpPresentation\PhpPresentation
121
     * @throws \Exception
122
     */
123 5
    public function load($pFilename)
124
    {
125
        // Unserialize... First make sure the file supports it!
126 5
        if (!$this->fileSupportsUnserializePhpPresentation($pFilename)) {
127 1
            throw new \Exception("Invalid file format for PhpOffice\PhpPresentation\Reader\ODPresentation: " . $pFilename . ".");
128
        }
129
130 3
        return $this->loadFile($pFilename);
131
    }
132
133
    /**
134
     * Load PhpPresentation Serialized file
135
     *
136
     * @param  string        $pFilename
137
     * @return \PhpOffice\PhpPresentation\PhpPresentation
138
     */
139 3
    protected function loadFile($pFilename)
140
    {
141 3
        $this->filename = $pFilename;
142
143 3
        $this->oPhpPresentation = new PhpPresentation();
144 3
        $this->oPhpPresentation->removeSlideByIndex();
145
        
146 3
        $this->oZip = new ZipArchive();
147 3
        $this->oZip->open($this->filename);
148
149 3
        if ($this->loadFileFromODP('meta.xml') !== false) {
150 3
            $this->loadDocumentProperties();
151 3
        }
152 3
        if ($this->loadFileFromODP('styles.xml') !== false) {
153 3
            $this->loadStylesFile();
154 3
        }
155 3
        if ($this->loadFileFromODP('content.xml') !== false) {
156 3
            $this->loadSlides();
157 3
        }
158
159 3
        return $this->oPhpPresentation;
160
    }
161
    
162
    /**
163
     * Read Document Properties
164
     */
165 3
    protected function loadDocumentProperties()
166
    {
167
        $arrayProperties = array(
168 3
            '/office:document-meta/office:meta/meta:initial-creator' => 'setCreator',
169 3
            '/office:document-meta/office:meta/dc:creator' => 'setLastModifiedBy',
170 3
            '/office:document-meta/office:meta/dc:title' => 'setTitle',
171 3
            '/office:document-meta/office:meta/dc:description' => 'setDescription',
172 3
            '/office:document-meta/office:meta/dc:subject' => 'setSubject',
173 3
            '/office:document-meta/office:meta/meta:keyword' => 'setKeywords',
174 3
            '/office:document-meta/office:meta/meta:creation-date' => 'setCreated',
175 3
            '/office:document-meta/office:meta/dc:date' => 'setModified',
176 3
        );
177 3
        $oProperties = $this->oPhpPresentation->getDocumentProperties();
178 3
        foreach ($arrayProperties as $path => $property) {
179 3
            if (is_object($oElement = $this->oXMLReader->getElement($path))) {
180 3
                if (in_array($property, array('setCreated', 'setModified'))) {
181 3
                    $oDateTime = new \DateTime();
182 3
                    $oDateTime->createFromFormat(\DateTime::W3C, $oElement->nodeValue);
183 3
                    $oProperties->{$property}($oDateTime->getTimestamp());
184 3
                } else {
185 1
                    $oProperties->{$property}($oElement->nodeValue);
186
                }
187 3
            }
188 3
        }
189 3
    }
190
    
191
    /**
192
     * Extract all slides
193
     */
194 3
    protected function loadSlides()
195
    {
196 3
        foreach ($this->oXMLReader->getElements('/office:document-content/office:automatic-styles/*') as $oElement) {
197 3
            if ($oElement->hasAttribute('style:name')) {
198 3
                $this->loadStyle($oElement);
199 3
            }
200 3
        }
201 3
        foreach ($this->oXMLReader->getElements('/office:document-content/office:body/office:presentation/draw:page') as $oElement) {
202 3
            if ($oElement->nodeName == 'draw:page') {
203 3
                $this->loadSlide($oElement);
204 3
            }
205 3
        }
206 3
    }
207
    
208
    /**
209
     * Extract style
210
     * @param \DOMElement $nodeStyle
211
     */
212 3
    protected function loadStyle(\DOMElement $nodeStyle)
213
    {
214 3
        $keyStyle = $nodeStyle->getAttribute('style:name');
215
216 3
        $nodeDrawingPageProps = $this->oXMLReader->getElement('style:drawing-page-properties', $nodeStyle);
217 3
        if ($nodeDrawingPageProps) {
218
            // Read Background Color
219 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...
220
                $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Color();
221
                $oColor = new Color();
222
                $oColor->setRGB(substr($nodeDrawingPageProps->getAttribute('draw:fill-color'), -6));
223
                $oBackground->setColor($oColor);
224
            }
225
            // Read Background Image
226 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...
227
                $nameStyle = $nodeDrawingPageProps->getAttribute('draw:fill-image-name');
228
                if (!empty($this->arrayCommonStyles[$nameStyle]) && $this->arrayCommonStyles[$nameStyle]['type'] == 'image' && !empty($this->arrayCommonStyles[$nameStyle]['path'])) {
229
                    $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderODPBkg');
230
                    $contentImg = $this->oZip->getFromName($this->arrayCommonStyles[$nameStyle]['path']);
231
                    file_put_contents($tmpBkgImg, $contentImg);
232
233
                    $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Image();
234
                    $oBackground->setPath($tmpBkgImg);
235
                }
236
            }
237 3
        }
238
239 3
        $nodeGraphicProps = $this->oXMLReader->getElement('style:graphic-properties', $nodeStyle);
240 3
        if ($nodeGraphicProps) {
241
            // Read Shadow
242 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...
243 1
                $oShadow = new Shadow();
244 1
                $oShadow->setVisible(true);
245 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...
246 1
                    $oShadow->getColor()->setRGB(substr($nodeGraphicProps->getAttribute('draw:shadow-color'), -6));
247 1
                }
248 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...
249 1
                    $oShadow->setAlpha(100 - (int)substr($nodeGraphicProps->getAttribute('draw:shadow-opacity'), 0, -1));
250 1
                }
251 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...
252 1
                    $offsetX = substr($nodeGraphicProps->getAttribute('draw:shadow-offset-x'), 0, -2);
253 1
                    $offsetY = substr($nodeGraphicProps->getAttribute('draw:shadow-offset-y'), 0, -2);
254 1
                    $distance = 0;
255 1
                    if ($offsetX != 0) {
256 1
                        $distance = ($offsetX < 0 ? $offsetX * -1 : $offsetX);
257 1
                    } elseif ($offsetY != 0) {
258
                        $distance = ($offsetY < 0 ? $offsetY * -1 : $offsetY);
259
                    }
260 1
                    $oShadow->setDirection(rad2deg(atan2($offsetY, $offsetX)));
261 1
                    $oShadow->setDistance(CommonDrawing::centimetersToPixels($distance));
262 1
                }
263 1
            }
264 3
        }
265
        
266 3
        $nodeTextProperties = $this->oXMLReader->getElement('style:text-properties', $nodeStyle);
267 3
        if ($nodeTextProperties) {
268 1
            $oFont = new Font();
269 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...
270 1
                $oFont->getColor()->setRGB(substr($nodeTextProperties->getAttribute('fo:color'), -6));
271 1
            }
272 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...
273 1
                $oFont->setName($nodeTextProperties->getAttribute('fo:font-family'));
274 1
            }
275 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...
276 1
                $oFont->setBold(true);
277 1
            }
278 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...
279 1
                $oFont->setSize(substr($nodeTextProperties->getAttribute('fo:font-size'), 0, -2));
280 1
            }
281 1
        }
282
283 3
        $nodeParagraphProps = $this->oXMLReader->getElement('style:paragraph-properties', $nodeStyle);
284 3
        if ($nodeParagraphProps) {
285 2
            $oAlignment = new Alignment();
286 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...
287 2
                $oAlignment->setHorizontal($nodeParagraphProps->getAttribute('fo:text-align'));
288 2
            }
289 2
        }
290
        
291 3
        if ($nodeStyle->nodeName == 'text:list-style') {
292 2
            $arrayListStyle = array();
293 2
            foreach ($this->oXMLReader->getElements('text:list-level-style-bullet', $nodeStyle) as $oNodeListLevel) {
294 2
                $oAlignment = new Alignment();
295 2
                $oBullet = new Bullet();
296 2
                $oBullet->setBulletType(Bullet::TYPE_NONE);
297 2
                if ($oNodeListLevel->hasAttribute('text:level')) {
298 2
                    $oAlignment->setLevel((int) $oNodeListLevel->getAttribute('text:level') - 1);
299 2
                }
300 2
                if ($oNodeListLevel->hasAttribute('text:bullet-char')) {
301 2
                    $oBullet->setBulletChar($oNodeListLevel->getAttribute('text:bullet-char'));
302 2
                    $oBullet->setBulletType(Bullet::TYPE_BULLET);
303 2
                }
304
                
305 2
                $oNodeListProperties = $this->oXMLReader->getElement('style:list-level-properties', $oNodeListLevel);
306 2
                if ($oNodeListProperties) {
307 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...
308 2
                        $oAlignment->setIndent((int)round(CommonDrawing::centimetersToPixels(substr($oNodeListProperties->getAttribute('text:min-label-width'), 0, -2))));
309 2
                    }
310 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...
311 2
                        $iSpaceBefore = CommonDrawing::centimetersToPixels(substr($oNodeListProperties->getAttribute('text:space-before'), 0, -2));
312 2
                        $iMarginLeft = $iSpaceBefore + $oAlignment->getIndent();
313 2
                        $oAlignment->setMarginLeft($iMarginLeft);
314 2
                    }
315 2
                }
316 2
                $oNodeTextProperties = $this->oXMLReader->getElement('style:text-properties', $oNodeListLevel);
317 2
                if ($oNodeTextProperties) {
318 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...
319 2
                        $oBullet->setBulletFont($oNodeTextProperties->getAttribute('fo:font-family'));
320 2
                    }
321 2
                }
322
                
323 2
                $arrayListStyle[$oAlignment->getLevel()] = array(
324 2
                    'alignment' => $oAlignment,
325 2
                    'bullet' => $oBullet,
326
                );
327 2
            }
328 2
        }
329
        
330 3
        $this->arrayStyles[$keyStyle] = array(
331 3
            'alignment' => isset($oAlignment) ? $oAlignment : null,
332 3
            'background' => isset($oBackground) ? $oBackground : null,
333 3
            'font' => isset($oFont) ? $oFont : null,
334 3
            'shadow' => isset($oShadow) ? $oShadow : null,
335 3
            'listStyle' => isset($arrayListStyle) ? $arrayListStyle : null,
336
        );
337
        
338 3
        return true;
339
    }
340
341
    /**
342
     * Read Slide
343
     *
344
     * @param \DOMElement $nodeSlide
345
     */
346 3
    protected function loadSlide(\DOMElement $nodeSlide)
347
    {
348
        // Core
349 3
        $this->oPhpPresentation->createSlide();
350 3
        $this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1);
351 3
        if ($nodeSlide->hasAttribute('draw:name')) {
352 3
            $this->oPhpPresentation->getActiveSlide()->setName($nodeSlide->getAttribute('draw:name'));
353 3
        }
354 3
        if ($nodeSlide->hasAttribute('draw:style-name')) {
355 3
            $keyStyle = $nodeSlide->getAttribute('draw:style-name');
356 3
            if (isset($this->arrayStyles[$keyStyle])) {
357 3
                $this->oPhpPresentation->getActiveSlide()->setBackground($this->arrayStyles[$keyStyle]['background']);
358 3
            }
359 3
        }
360 3
        foreach ($this->oXMLReader->getElements('draw:frame', $nodeSlide) as $oNodeFrame) {
361 3
            if ($this->oXMLReader->getElement('draw:image', $oNodeFrame)) {
362 2
                $this->loadShapeDrawing($oNodeFrame);
363 2
                continue;
364
            }
365 3
            if ($this->oXMLReader->getElement('draw:text-box', $oNodeFrame)) {
366 3
                $this->loadShapeRichText($oNodeFrame);
367 3
                continue;
368
            }
369 3
        }
370 3
        return true;
371
    }
372
    
373
    /**
374
     * Read Shape Drawing
375
     *
376
     * @param \DOMElement $oNodeFrame
377
     */
378 2
    protected function loadShapeDrawing(\DOMElement $oNodeFrame)
379
    {
380
        // Core
381 2
        $oShape = new MemoryDrawing();
382 2
        $oShape->getShadow()->setVisible(false);
383
        
384 2
        $oNodeImage = $this->oXMLReader->getElement('draw:image', $oNodeFrame);
385 2
        if ($oNodeImage) {
386 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...
387 2
                $sFilename = $oNodeImage->getAttribute('xlink:href');
388
                // svm = StarView Metafile
389 2
                if (pathinfo($sFilename, PATHINFO_EXTENSION) == 'svm') {
390 1
                    return;
391
                }
392 2
                $imageFile = $this->oZip->getFromName($sFilename);
393 2
                if (!empty($imageFile)) {
394 2
                    $oShape->setImageResource(imagecreatefromstring($imageFile));
395 2
                }
396 2
            }
397 2
        }
398
        
399 2
        $oShape->setName($oNodeFrame->hasAttribute('draw:name') ? $oNodeFrame->getAttribute('draw:name') : '');
400 2
        $oShape->setDescription($oNodeFrame->hasAttribute('draw:name') ? $oNodeFrame->getAttribute('draw:name') : '');
401 2
        $oShape->setResizeProportional(false);
402 2
        $oShape->setWidth($oNodeFrame->hasAttribute('svg:width') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:width'), 0, -2))) : '');
403 2
        $oShape->setHeight($oNodeFrame->hasAttribute('svg:height') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:height'), 0, -2))) : '');
404 2
        $oShape->setResizeProportional(true);
405 2
        $oShape->setOffsetX($oNodeFrame->hasAttribute('svg:x') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:x'), 0, -2))) : '');
406 2
        $oShape->setOffsetY($oNodeFrame->hasAttribute('svg:y') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:y'), 0, -2))) : '');
407
        
408 2
        if ($oNodeFrame->hasAttribute('draw:style-name')) {
409 2
            $keyStyle = $oNodeFrame->getAttribute('draw:style-name');
410 2
            if (isset($this->arrayStyles[$keyStyle])) {
411 2
                $oShape->setShadow($this->arrayStyles[$keyStyle]['shadow']);
412 2
            }
413 2
        }
414
        
415 2
        $this->oPhpPresentation->getActiveSlide()->addShape($oShape);
416 2
    }
417
418
    /**
419
     * Read Shape RichText
420
     *
421
     * @param \DOMElement $oNodeFrame
422
     */
423 3
    protected function loadShapeRichText(\DOMElement $oNodeFrame)
424
    {
425
        // Core
426 3
        $oShape = $this->oPhpPresentation->getActiveSlide()->createRichTextShape();
427 3
        $oShape->setParagraphs(array());
428
        
429 3
        $oShape->setWidth($oNodeFrame->hasAttribute('svg:width') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:width'), 0, -2))) : '');
430 3
        $oShape->setHeight($oNodeFrame->hasAttribute('svg:height') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:height'), 0, -2))) : '');
431 3
        $oShape->setOffsetX($oNodeFrame->hasAttribute('svg:x') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:x'), 0, -2))) : '');
432 3
        $oShape->setOffsetY($oNodeFrame->hasAttribute('svg:y') ? (int)round(CommonDrawing::centimetersToPixels(substr($oNodeFrame->getAttribute('svg:y'), 0, -2))) : '');
433
        
434 3
        foreach ($this->oXMLReader->getElements('draw:text-box/*', $oNodeFrame) as $oNodeParagraph) {
435 2
            $this->levelParagraph = 0;
436 2
            if ($oNodeParagraph->nodeName == 'text:p') {
437 2
                $this->readParagraph($oShape, $oNodeParagraph);
438 2
            }
439 2
            if ($oNodeParagraph->nodeName == 'text:list') {
440 1
                $this->readList($oShape, $oNodeParagraph);
441 1
            }
442 3
        }
443
        
444 3
        if (count($oShape->getParagraphs()) > 0) {
445 2
            $oShape->setActiveParagraph(0);
446 2
        }
447 3
    }
448
    
449
    protected $levelParagraph = 0;
450
    
451
    /**
452
     * Read Paragraph
453
     * @param RichText $oShape
454
     * @param \DOMElement $oNodeParent
455
     */
456 2
    protected function readParagraph(RichText $oShape, \DOMElement $oNodeParent)
457
    {
458 2
        $oParagraph = $oShape->createParagraph();
459 2
        $oDomList = $this->oXMLReader->getElements('text:span', $oNodeParent);
460 2
        if ($oDomList->length == 0) {
461 1
            $this->readParagraphItem($oParagraph, $oNodeParent);
462 1
        } else {
463 1
            foreach ($oDomList as $oNodeRichTextElement) {
464 1
                $this->readParagraphItem($oParagraph, $oNodeRichTextElement);
465 1
            }
466
        }
467 2
    }
468
    
469
    /**
470
     * Read Paragraph Item
471
     * @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...
472
     * @param \DOMElement $oNodeParent
473
     */
474 2
    protected function readParagraphItem(Paragraph $oParagraph, \DOMElement $oNodeParent)
475
    {
476 2
        if ($this->oXMLReader->elementExists('text:line-break', $oNodeParent)) {
477 1
            $oParagraph->createBreak();
478 1
        } else {
479 2
            $oTextRun = $oParagraph->createTextRun();
480 2
            if ($oNodeParent->hasAttribute('text:style-name')) {
481 1
                $keyStyle = $oNodeParent->getAttribute('text:style-name');
482 1
                if (isset($this->arrayStyles[$keyStyle])) {
483 1
                    $oTextRun->setFont($this->arrayStyles[$keyStyle]['font']);
484 1
                }
485 1
            }
486 2
            if ($oTextRunLink = $this->oXMLReader->getElement('text:a', $oNodeParent)) {
487 1
                $oTextRun->setText($oTextRunLink->nodeValue);
488 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...
489 1
                    $oTextRun->getHyperlink()->setUrl($oTextRunLink->getAttribute('xlink:href'));
490 1
                }
491 1
            } else {
492 2
                $oTextRun->setText($oNodeParent->nodeValue);
493
            }
494
        }
495 2
    }
496
497
    /**
498
     * Read List
499
     *
500
     * @param RichText $oShape
501
     * @param \DOMElement $oNodeParent
502
     */
503 1
    protected function readList(RichText $oShape, \DOMElement $oNodeParent)
504
    {
505 1
        foreach ($this->oXMLReader->getElements('text:list-item/*', $oNodeParent) as $oNodeListItem) {
506 1
            if ($oNodeListItem->nodeName == 'text:p') {
507 1
                $this->readListItem($oShape, $oNodeListItem, $oNodeParent);
508 1
            }
509 1
            if ($oNodeListItem->nodeName == 'text:list') {
510 1
                $this->levelParagraph++;
511 1
                $this->readList($oShape, $oNodeListItem);
512 1
                $this->levelParagraph--;
513 1
            }
514 1
        }
515 1
    }
516
    
517
    /**
518
     * Read List Item
519
     * @param RichText $oShape
520
     * @param \DOMElement $oNodeParent
521
     * @param \DOMElement $oNodeParagraph
522
     */
523 1
    protected function readListItem(RichText $oShape, \DOMElement $oNodeParent, \DOMElement $oNodeParagraph)
524
    {
525 1
        $oParagraph = $oShape->createParagraph();
526 1
        if ($oNodeParagraph->hasAttribute('text:style-name')) {
527 1
            $keyStyle = $oNodeParagraph->getAttribute('text:style-name');
528 1
            if (isset($this->arrayStyles[$keyStyle])) {
529 1
                $oParagraph->setAlignment($this->arrayStyles[$keyStyle]['listStyle'][$this->levelParagraph]['alignment']);
530 1
                $oParagraph->setBulletStyle($this->arrayStyles[$keyStyle]['listStyle'][$this->levelParagraph]['bullet']);
531 1
            }
532 1
        }
533 1
        foreach ($this->oXMLReader->getElements('text:span', $oNodeParent) as $oNodeRichTextElement) {
534 1
            $this->readParagraphItem($oParagraph, $oNodeRichTextElement);
535 1
        }
536 1
    }
537
538
    /**
539
     * Load file 'styles.xml'
540
     */
541 3
    protected function loadStylesFile()
542
    {
543 3
        foreach ($this->oXMLReader->getElements('/office:document-styles/office:styles/*') as $oElement) {
544 3
            if ($oElement->nodeName == 'draw:fill-image') {
545
                $this->arrayCommonStyles[$oElement->getAttribute('draw:name')] = array(
546
                    'type' => 'image',
547
                    'path' => $oElement->hasAttribute('xlink:href') ? $oElement->getAttribute('xlink:href') : null
548
                );
549
            }
550 3
        }
551 3
    }
552
553
    /**
554
     * @param string $filename
555
     * @return bool
556
     * @throws \Exception
557
     */
558 3
    protected function loadFileFromODP($filename)
559
    {
560 3
        $bEncrypted = false;
561
562 3
        if (!$this->oXMLMetaInfManifest) {
563 3
            $this->oXMLMetaInfManifest = new XMLReader();
564 3
            if ($this->oXMLMetaInfManifest->getDomFromZip($this->filename, 'META-INF/manifest.xml') === false) {
565
                return false;
566
            }
567 3
        }
568
        // Search file in META-INF/manifest.xml
569 3
        $oElement = $this->oXMLMetaInfManifest->getElement('/manifest:manifest/manifest:file-entry[@manifest:full-path=\''.$filename.'\']');
570 3
        if (!$oElement) {
571
            return false;
572
        }
573
        // Has it some manifest:encryption-data ?
574 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...
575 3
        if ($oElementEncryption) {
576
            $bEncrypted = true;
577
        }
578
579 3
        $fileContent = $this->oZip->getFromName($filename);
580 3
        if (!$fileContent){
581
            return false;
582
        }
583
584
        // No Encrypted file
585 3
        if (!$bEncrypted) {
586 3
            $this->oXMLReader = new XMLReader();
587 3
            $this->oXMLReader->getDomFromString($fileContent);
588 3
            return true;
589
        }
590
591
        //return false;
592
        /*
593
          <manifest:encryption-data
594
                manifest:checksum-type="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#sha256-1k"
595
                manifest:checksum="BfB+taOY0kcVO/9WNi4DfqioRp3LMwVoNbqfAQ37yac=">
596
              <manifest:algorithm
597
                    manifest:algorithm-name="http://www.w3.org/2001/04/xmlenc#aes256-cbc"
598
                    manifest:initialisation-vector="I7rMXmvuynJFxJtm+EQ5qA=="/>
599
              <manifest:key-derivation
600
                    manifest:key-derivation-name="PBKDF2"
601
                    manifest:key-size="32"
602
                    manifest:iteration-count="1024"
603
                    manifest:salt="Mows9XX/YiNKNJ0qll3jgA=="/>
604
              <manifest:start-key-generation
605
                    manifest:start-key-generation-name="http://www.w3.org/2000/09/xmldsig#sha256"
606
                    manifest:key-size="32"/>
607
          </manifest:encryption-data>
608
         </manifest:file-entry>
609
         */
610
        return false;
611
        // Encrypted file
612
        $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...
613
614
        $oEltKeyDerivation = $this->oXMLMetaInfManifest->getElement('manifest:key-derivation', $oElementEncryption);
615
        $salt = $oEltKeyDerivation->getAttribute('manifest:salt');
616
        //$salt = base64_decode($salt);
617
        echo 'manifest:salt : ';
618
        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...
619
        $iterationCount = $oEltKeyDerivation->getAttribute('manifest:iteration-count');
620
        echo 'manifest:iteration-count : ';
621
        var_dump($iterationCount);
622
        $keySize = $oEltKeyDerivation->getAttribute('manifest:key-size');
623
        echo 'manifest:key-size : ';
624
        var_dump($keySize);
625
626
        $oEltAlgorithm = $this->oXMLMetaInfManifest->getElement('manifest:algorithm', $oElementEncryption);
627
        $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...
628
        $iv = base64_decode($iv);
629
        echo 'manifest:initialisation-vector : ';
630
        var_dump($iv);
631
632
        $pwdHash = hash('sha256', $this->getPassword());
633
        echo 'sha256('.$this->getPassword().'): ';
634
        var_dump($pwdHash);
635
        //$pwdHash = substr($pwdHash, 0 , 32);
636
        //var_dump($pwdHash);
637
638
        $key = hash_pbkdf2('sha1', $pwdHash, $salt, $iterationCount, $keySize, true);
639
        echo 'hash_pbkdf2 (sha1, hash, salt, iterationCount, $iterationCount) : ';
640
        var_dump($key);
641
        //$key = $this->hash_pbkdf2('sha1', $pwdHash, $salt, $iterationCount, $keySize, true);
642
        //echo 'hash_pbkdf2 (sha1, hash, salt, iterationCount, $iterationCount) : ';
643
        //var_dump($key);
644
645
        $data = openssl_decrypt($fileContent, 'AES-256-CBC', $key, 0, $iv);
646
        if(!$data) {
0 ignored issues
show
Bug introduced by
The variable $data seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
647
            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...
648
                var_dump($msg);
649
            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...
650
        } else {
651
            var_dump($data);
652
            $data = gzinflate($data);
653
            var_dump($data);
654
        }
655
656
        /*$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $fileContent, MCRYPT_MODE_CBC, $iv);
657
        var_dump($data);
658
        $data = gzinflate($data);
659
        if($data) {
660
            var_dump($data);
661
        }*/
662
663
        return false;
664
    }
665
666
    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...
667
    {
668
        // Derived key
669
        $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...
670
        // Create key
671
        for ($block=1; $block<=$key_length; $block++)
672
        {
673
            // Initial hash for this block
674
            $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...
675
            // Perform block iterations
676
            for ($i=1; $i<$rounds; $i++)
677
            {
678
                // XOR each iteration
679
                $ib ^= ($h = hash_hmac($a, $h, $password, true));
680
            }
681
            // Append iterated block
682
            $dk .= $ib;
683
        }
684
        // Return derived key of correct length
685
        $key = substr($dk, 0, $key_length);
686
        return $raw_output ? $key : base64_encode($key);
687
    }
688
689
}
690