phpBMS

root/trunk/phpbms/fpdf/fpdi.php

Revision 712, 16.1 KB (checked in by brieb, 2 years ago)
  • fixed #393 - issue wth FPDI and php5.3 using depreciated object pointers during creation.
  • added link to phpBMS registration. Doing this in hopes to collect valuable information about phpBMS users and where to guide the project in the future
  • Property svn:executable set to *
Line 
1<?php
2//
3//  FPDI - Version 1.3.1
4//
5//    Copyright 2004-2009 Setasign - Jan Slabon
6//
7//  Licensed under the Apache License, Version 2.0 (the "License");
8//  you may not use this file except in compliance with the License.
9//  You may obtain a copy of the License at
10//
11//      http://www.apache.org/licenses/LICENSE-2.0
12//
13//  Unless required by applicable law or agreed to in writing, software
14//  distributed under the License is distributed on an "AS IS" BASIS,
15//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16//  See the License for the specific language governing permissions and
17//  limitations under the License.
18//
19
20define('FPDI_VERSION','1.3.1');
21
22// Check for TCPDF and remap TCPDF to FPDF
23if (class_exists('TCPDF')) {
24    require_once('fpdi2tcpdf_bridge.php');
25}
26
27
28class FPDI extends FPDF_TPL {
29    /**
30     * Actual filename
31     * @var string
32     */
33    var $current_filename;
34
35    /**
36     * Parser-Objects
37     * @var array
38     */
39    var $parsers;
40
41    /**
42     * Current parser
43     * @var object
44     */
45    var $current_parser;
46
47    /**
48     * object stack
49     * @var array
50     */
51    var $_obj_stack;
52
53    /**
54     * done object stack
55     * @var array
56     */
57    var $_don_obj_stack;
58
59    /**
60     * Current Object Id.
61     * @var integer
62     */
63    var $_current_obj_id;
64
65    /**
66     * The name of the last imported page box
67     * @var string
68     */
69    var $lastUsedPageBox;
70
71    var $_importedPages = array();
72
73
74    /**
75     * Set a source-file
76     *
77     * @param string $filename a valid filename
78     * @return int number of available pages
79     */
80    function setSourceFile($filename) {
81        $this->current_filename = $filename;
82        $fn =& $this->current_filename;
83
84        if (!isset($this->parsers[$fn]))
85            $this->parsers[$fn] = new fpdi_pdf_parser($fn, $this);
86        $this->current_parser =& $this->parsers[$fn];
87
88        return $this->parsers[$fn]->getPageCount();
89    }
90
91    /**
92     * Import a page
93     *
94     * @param int $pageno pagenumber
95     * @return int Index of imported page - to use with fpdf_tpl::useTemplate()
96     */
97    function importPage($pageno, $boxName='/CropBox') {
98        if ($this->_intpl) {
99            return $this->error('Please import the desired pages before creating a new template.');
100        }
101
102        $fn =& $this->current_filename;
103
104        // check if page already imported
105        $pageKey = $fn.((int)$pageno).$boxName;
106        if (isset($this->_importedPages[$pageKey]))
107            return $this->_importedPages[$pageKey];
108
109        $parser =& $this->parsers[$fn];
110        $parser->setPageno($pageno);
111
112        $this->tpl++;
113        $this->tpls[$this->tpl] = array();
114        $tpl =& $this->tpls[$this->tpl];
115        $tpl['parser'] =& $parser;
116        $tpl['resources'] = $parser->getPageResources();
117        $tpl['buffer'] = $parser->getContent();
118
119        if (!in_array($boxName, $parser->availableBoxes))
120            return $this->Error(sprintf('Unknown box: %s', $boxName));
121        $pageboxes = $parser->getPageBoxes($pageno);
122
123        /**
124         * MediaBox
125         * CropBox: Default -> MediaBox
126         * BleedBox: Default -> CropBox
127         * TrimBox: Default -> CropBox
128         * ArtBox: Default -> CropBox
129         */
130        if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox'))
131            $boxName = '/CropBox';
132        if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox')
133            $boxName = '/MediaBox';
134
135        if (!isset($pageboxes[$boxName]))
136            return false;
137        $this->lastUsedPageBox = $boxName;
138
139        $box = $pageboxes[$boxName];
140        $tpl['box'] = $box;
141
142        // To build an array that can be used by PDF_TPL::useTemplate()
143        $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl],$box);
144
145        // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects()
146        $tpl['x'] = 0;
147        $tpl['y'] = 0;
148
149        $page =& $parser->pages[$parser->pageno];
150
151        // handle rotated pages
152        $rotation = $parser->getPageRotation($pageno);
153        $tpl['_rotationAngle'] = 0;
154        if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) {
155            $steps = $angle / 90;
156
157            $_w = $tpl['w'];
158            $_h = $tpl['h'];
159            $tpl['w'] = $steps % 2 == 0 ? $_w : $_h;
160            $tpl['h'] = $steps % 2 == 0 ? $_h : $_w;
161
162            $tpl['_rotationAngle'] = $angle*-1;
163        }
164
165        $this->_importedPages[$pageKey] = $this->tpl;
166
167        return $this->tpl;
168    }
169
170    function getLastUsedPageBox() {
171        return $this->lastUsedPageBox;
172    }
173
174    function useTemplate($tplidx, $_x=null, $_y=null, $_w=0, $_h=0, $adjustPageSize=false) {
175        if ($adjustPageSize == true && is_null($_x) && is_null($_y)) {
176            $size = $this->getTemplateSize($tplidx, $_w, $_h);
177            $format = array($size['w'], $size['h']);
178            if ($format[0]!=$this->CurPageFormat[0] || $format[1]!=$this->CurPageFormat[1]) {
179                $this->w=$format[0];
180                $this->h=$format[1];
181                $this->wPt=$this->w*$this->k;
182                        $this->hPt=$this->h*$this->k;
183                        $this->PageBreakTrigger=$this->h-$this->bMargin;
184                        $this->CurPageFormat=$format;
185                        $this->PageSizes[$this->page]=array($this->wPt, $this->hPt);
186            }
187        }
188
189        $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values
190        $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h);
191        $this->_out('Q');
192        return $s;
193    }
194
195    /**
196     * Private method, that rebuilds all needed objects of source files
197     */
198    function _putimportedobjects() {
199        if (is_array($this->parsers) && count($this->parsers) > 0) {
200            foreach($this->parsers AS $filename => $p) {
201                $this->current_parser =& $this->parsers[$filename];
202                if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) {
203                    while(($n = key($this->_obj_stack[$filename])) !== null) {
204                        $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c,$this->_obj_stack[$filename][$n][1]);
205
206                        $this->_newobj($this->_obj_stack[$filename][$n][0]);
207
208                        if ($nObj[0] == PDF_TYPE_STREAM) {
209                                                        $this->pdf_write_value ($nObj);
210                        } else {
211                            $this->pdf_write_value ($nObj[1]);
212                        }
213
214                        $this->_out('endobj');
215                        $this->_obj_stack[$filename][$n] = null; // free memory
216                        unset($this->_obj_stack[$filename][$n]);
217                        reset($this->_obj_stack[$filename]);
218                    }
219                }
220            }
221        }
222    }
223
224
225    /**
226     * Private Method that writes the form xobjects
227     */
228    function _putformxobjects() {
229        $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
230            reset($this->tpls);
231        foreach($this->tpls AS $tplidx => $tpl) {
232            $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer'];
233                $this->_newobj();
234                $cN = $this->n; // TCPDF/Protection: rem current "n"
235
236                $this->tpls[$tplidx]['n'] = $this->n;
237                $this->_out('<<'.$filter.'/Type /XObject');
238            $this->_out('/Subtype /Form');
239            $this->_out('/FormType 1');
240
241            $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]',
242                (isset($tpl['box']['llx']) ? $tpl['box']['llx'] : $tpl['x'])*$this->k,
243                (isset($tpl['box']['lly']) ? $tpl['box']['lly'] : -$tpl['y'])*$this->k,
244                (isset($tpl['box']['urx']) ? $tpl['box']['urx'] : $tpl['w'] + $tpl['x'])*$this->k,
245                (isset($tpl['box']['ury']) ? $tpl['box']['ury'] : $tpl['h']-$tpl['y'])*$this->k
246            ));
247
248            $c = 1;
249            $s = 0;
250            $tx = 0;
251            $ty = 0;
252
253            if (isset($tpl['box'])) {
254                $tx = -$tpl['box']['llx'];
255                $ty = -$tpl['box']['lly'];
256
257                if ($tpl['_rotationAngle'] <> 0) {
258                    $angle = $tpl['_rotationAngle'] * M_PI/180;
259                    $c=cos($angle);
260                    $s=sin($angle);
261
262                    switch($tpl['_rotationAngle']) {
263                        case -90:
264                           $tx = -$tpl['box']['lly'];
265                           $ty = $tpl['box']['urx'];
266                           break;
267                        case -180:
268                            $tx = $tpl['box']['urx'];
269                            $ty = $tpl['box']['ury'];
270                            break;
271                        case -270:
272                            $tx = $tpl['box']['ury'];
273                            $ty = 0;
274                            break;
275                    }
276                }
277            } else if ($tpl['x'] != 0 || $tpl['y'] != 0) {
278                $tx = -$tpl['x']*2;
279                $ty = $tpl['y']*2;
280            }
281
282            $tx *= $this->k;
283            $ty *= $this->k;
284
285            if ($c != 1 || $s != 0 || $tx != 0 || $ty != 0) {
286                $this->_out(sprintf('/Matrix [%.5F %.5F %.5F %.5F %.5F %.5F]',
287                    $c, $s, -$s, $c, $tx, $ty
288                ));
289            }
290
291            $this->_out('/Resources ');
292
293            if (isset($tpl['resources'])) {
294                $this->current_parser =& $tpl['parser'];
295                $this->pdf_write_value($tpl['resources']); // "n" will be changed
296            } else {
297                $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
298                if (isset($this->_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) {
299                        $this->_out('/Font <<');
300                    foreach($this->_res['tpl'][$tplidx]['fonts'] as $font)
301                                $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
302                        $this->_out('>>');
303                }
304                if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) ||
305                   isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls']))
306                {
307                    $this->_out('/XObject <<');
308                    if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) {
309                        foreach($this->_res['tpl'][$tplidx]['images'] as $image)
310                                        $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
311                    }
312                    if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) {
313                        foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl)
314                            $this->_out($this->tplprefix.$i.' '.$tpl['n'].' 0 R');
315                    }
316                    $this->_out('>>');
317                }
318                $this->_out('>>');
319            }
320
321            $nN = $this->n; // TCPDF: rem new "n"
322            $this->n = $cN; // TCPDF: reset to current "n"
323            $this->_out('/Length '.strlen($p).' >>');
324                $this->_putstream($p);
325                $this->_out('endobj');
326                $this->n = $nN; // TCPDF: reset to new "n"
327        }
328
329        $this->_putimportedobjects();
330    }
331
332    /**
333     * Rewritten to handle existing own defined objects
334     */
335    function _newobj($obj_id=false,$onlynewobj=false) {
336        if (!$obj_id) {
337            $obj_id = ++$this->n;
338        }
339
340        //Begin a new object
341        if (!$onlynewobj) {
342            $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer);
343            $this->_out($obj_id.' 0 obj');
344            $this->_current_obj_id = $obj_id; // for later use with encryption
345        }
346        return $obj_id;
347    }
348
349    /**
350     * Writes a value
351     * Needed to rebuild the source document
352     *
353     * @param mixed $value A PDF-Value. Structure of values see cases in this method
354     */
355    function pdf_write_value(&$value)
356    {
357        if (is_subclass_of($this, 'TCPDF')) {
358            parent::pdf_write_value($value);
359        }
360
361        switch ($value[0]) {
362
363                case PDF_TYPE_TOKEN :
364                $this->_straightOut($value[1] . ' ');
365                        break;
366                    case PDF_TYPE_NUMERIC :
367                case PDF_TYPE_REAL :
368                if (is_float($value[1]) && $value[1] != 0) {
369                            $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') .' ');
370                        } else {
371                                $this->_straightOut($value[1] . ' ');
372                        }
373                        break;
374
375                case PDF_TYPE_ARRAY :
376
377                        // An array. Output the proper
378                        // structure and move on.
379
380                        $this->_straightOut('[');
381                for ($i = 0; $i < count($value[1]); $i++) {
382                                $this->pdf_write_value($value[1][$i]);
383                        }
384
385                        $this->_out(']');
386                        break;
387
388                case PDF_TYPE_DICTIONARY :
389
390                        // A dictionary.
391                        $this->_straightOut('<<');
392
393                        reset ($value[1]);
394
395                        while (list($k, $v) = each($value[1])) {
396                                $this->_straightOut($k . ' ');
397                                $this->pdf_write_value($v);
398                        }
399
400                        $this->_straightOut('>>');
401                        break;
402
403                case PDF_TYPE_OBJREF :
404
405                        // An indirect object reference
406                        // Fill the object stack if needed
407                        $cpfn =& $this->current_parser->filename;
408
409                        if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) {
410                            $this->_newobj(false,true);
411                            $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value);
412                    $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!!
413                }
414                $objid = $this->_don_obj_stack[$cpfn][$value[1]][0];
415
416                        $this->_out($objid.' 0 R');
417                        break;
418
419                case PDF_TYPE_STRING :
420
421                        // A string.
422                $this->_straightOut('('.$value[1].')');
423
424                        break;
425
426                case PDF_TYPE_STREAM :
427
428                        // A stream. First, output the
429                        // stream dictionary, then the
430                        // stream data itself.
431                $this->pdf_write_value($value[1]);
432                        $this->_out('stream');
433                        $this->_out($value[2][1]);
434                        $this->_out('endstream');
435                        break;
436            case PDF_TYPE_HEX :
437                $this->_straightOut('<'.$value[1].'>');
438                break;
439
440            case PDF_TYPE_BOOLEAN :
441                    $this->_straightOut($value[1] ? 'true ' : 'false ');
442                    break;
443
444                case PDF_TYPE_NULL :
445                // The null object.
446
447                        $this->_straightOut('null ');
448                        break;
449        }
450    }
451
452
453    /**
454     * Modified so not each call will add a newline to the output.
455     */
456    function _straightOut($s) {
457        if (!is_subclass_of($this, 'TCPDF')) {
458            if($this->state==2)
459                        $this->pages[$this->page] .= $s;
460                else
461                        $this->buffer .= $s;
462        } else {
463            if ($this->state == 2) {
464                                if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
465                                        // puts data before page footer
466                                        $page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]);
467                                        $footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]);
468                                        $this->setPageBuffer($this->page, $page.' '.$s."\n".$footer);
469                                } else {
470                                        $this->setPageBuffer($this->page, $s, true);
471                                }
472                        } else {
473                                $this->setBuffer($s);
474                        }
475        }
476    }
477
478    /**
479     * rewritten to close opened parsers
480     *
481     */
482    function _enddoc() {
483        parent::_enddoc();
484        $this->_closeParsers();
485    }
486
487    /**
488     * close all files opened by parsers
489     */
490    function _closeParsers() {
491        if ($this->state > 2 && count($this->parsers) > 0) {
492                foreach ($this->parsers as $k => $_){
493                $this->parsers[$k]->closeFile();
494                $this->parsers[$k] = null;
495                unset($this->parsers[$k]);
496            }
497            return true;
498        }
499        return false;
500    }
501
502}
Note: See TracBrowser for help on using the browser.
phpBMS vulnerability assesment provided by Orvant Inc. Copyright © 2010 Kreotek, LLC. All Rights reserved.