Completed
Push — development ( 6a24df...5afdf5 )
by Nils
07:52
created

tFPDF::GetStringWidth()   B

Complexity

Conditions 10
Paths 5

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 13
nc 5
nop 1
dl 0
loc 19
rs 7.2765
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*******************************************************************************
3
* tFPDF (based on FPDF 1.7)                                                    *
4
*                                                                              *
5
* Version:  1.24                                                               *
6
* Date:     2011-09-24                                                         *
7
* Author:   Ian Back <[email protected]>                                           *
8
* License:  LGPL                                                               *
9
*******************************************************************************/
10
11
define('tFPDF_VERSION', '1.24');
12
13
class tFPDF
14
{
15
16
var $unifontSubset;
17
var $page; // current page number
18
var $n; // current object number
19
var $offsets; // array of object offsets
20
var $buffer; // buffer holding in-memory PDF
21
var $pages; // array containing pages
22
var $state; // current document state
23
var $compress; // compression flag
24
var $k; // scale factor (number of points in user unit)
25
var $DefOrientation; // default orientation
26
var $CurOrientation; // current orientation
27
var $StdPageSizes; // standard page sizes
28
var $DefPageSize; // default page size
29
var $CurPageSize; // current page size
30
var $PageSizes; // used for pages with non default sizes or orientations
31
var $wPt, $hPt; // dimensions of current page in points
32
var $w, $h; // dimensions of current page in user unit
33
var $lMargin; // left margin
34
var $tMargin; // top margin
35
var $rMargin; // right margin
36
var $bMargin; // page break margin
37
var $cMargin; // cell margin
38
var $x, $y; // current position in user unit
39
var $lasth; // height of last printed cell
40
var $LineWidth; // line width in user unit
41
var $fontpath; // path containing fonts
42
var $CoreFonts; // array of core font names
43
var $fonts; // array of used fonts
44
var $FontFiles; // array of font files
45
var $diffs; // array of encoding differences
46
var $FontFamily; // current font family
47
var $FontStyle; // current font style
48
var $underline; // underlining flag
49
var $CurrentFont; // current font info
50
var $FontSizePt; // current font size in points
51
var $FontSize; // current font size in user unit
52
var $DrawColor; // commands for drawing color
53
var $FillColor; // commands for filling color
54
var $TextColor; // commands for text color
55
var $ColorFlag; // indicates whether fill and text colors are different
56
var $ws; // word spacing
57
var $images; // array of used images
58
var $PageLinks; // array of links in pages
59
var $links; // array of internal links
60
var $AutoPageBreak; // automatic page breaking
61
var $PageBreakTrigger; // threshold used to trigger page breaks
62
var $InHeader; // flag set when processing header
63
var $InFooter; // flag set when processing footer
64
var $ZoomMode; // zoom display mode
65
var $LayoutMode; // layout display mode
66
var $title; // title
67
var $subject; // subject
68
var $author; // author
69
var $keywords; // keywords
70
var $creator; // creator
71
var $AliasNbPages; // alias for total number of pages
72
var $PDFVersion; // PDF version number
73
74
/*******************************************************************************
75
*                                                                              *
76
*                               Public methods                                 *
77
*                                                                              *
78
*******************************************************************************/
79
function __construct($orientation = 'P', $unit = 'mm', $size = 'A4', $footer_text_1 = "Page")
0 ignored issues
show
Unused Code introduced by
The parameter $footer_text_1 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
80
{
81
    // Some checks
82
    $this->_dochecks();
83
    // Initialization of properties
84
    $this->page = 0;
85
    $this->n = 2;
86
    $this->buffer = '';
87
    $this->pages = array();
88
    $this->PageSizes = array();
89
    $this->state = 0;
90
    $this->fonts = array();
91
    $this->FontFiles = array();
92
    $this->diffs = array();
93
    $this->images = array();
94
    $this->links = array();
95
    $this->InHeader = false;
96
    $this->InFooter = false;
97
    $this->lasth = 0;
98
    $this->FontFamily = '';
99
    $this->FontStyle = '';
100
    $this->FontSizePt = 12;
101
    $this->underline = false;
102
    $this->DrawColor = '0 G';
103
    $this->FillColor = '0 g';
104
    $this->TextColor = '0 g';
105
    $this->ColorFlag = false;
106
    $this->ws = 0;
107
    // Font path
108
    if (defined('FPDF_FONTPATH'))
109
    {
110
        $this->fontpath = FPDF_FONTPATH;
111
        if (substr($this->fontpath, -1) != '/' && substr($this->fontpath, -1) != '\\')
112
            $this->fontpath .= '/';
113
    }
114
    elseif (is_dir(dirname(__FILE__).'/font'))
115
        $this->fontpath = dirname(__FILE__).'/font/';
116
    else
117
        $this->fontpath = '';
118
    // Core fonts
119
    $this->CoreFonts = array('courier', 'helvetica', 'times', 'symbol', 'zapfdingbats');
120
    // Scale factor
121
    if ($unit == 'pt')
122
        $this->k = 1;
123
    elseif ($unit == 'mm')
124
        $this->k = 72 / 25.4;
125
    elseif ($unit == 'cm')
126
        $this->k = 72 / 2.54;
127
    elseif ($unit == 'in')
128
        $this->k = 72;
129
    else
130
        $this->Error('Incorrect unit: '.$unit);
131
    // Page sizes
132
    $this->StdPageSizes = array('a3'=>array(841.89, 1190.55), 'a4'=>array(595.28, 841.89), 'a5'=>array(420.94, 595.28),
133
        'letter'=>array(612, 792), 'legal'=>array(612, 1008));
134
    $size = $this->_getpagesize($size);
135
    $this->DefPageSize = $size;
136
    $this->CurPageSize = $size;
137
    // Page orientation
138
    $orientation = strtolower($orientation);
139
    if ($orientation == 'p' || $orientation == 'portrait')
140
    {
141
        $this->DefOrientation = 'P';
142
        $this->w = $size[0];
143
        $this->h = $size[1];
144
    }
145
    elseif ($orientation == 'l' || $orientation == 'landscape')
146
    {
147
        $this->DefOrientation = 'L';
148
        $this->w = $size[1];
149
        $this->h = $size[0];
150
    }
151
    else
152
        $this->Error('Incorrect orientation: '.$orientation);
153
    $this->CurOrientation = $this->DefOrientation;
154
    $this->wPt = $this->w * $this->k;
155
    $this->hPt = $this->h * $this->k;
156
    // Page margins (1 cm)
157
    $margin = 28.35 / $this->k;
158
    $this->SetMargins($margin, $margin);
159
    // Interior cell margin (1 mm)
160
    $this->cMargin = $margin / 10;
161
    // Line width (0.2 mm)
162
    $this->LineWidth = .567 / $this->k;
163
    // Automatic page break
164
    $this->SetAutoPageBreak(true, 2 * $margin);
165
    // Default display mode
166
    $this->SetDisplayMode('default');
167
    // Enable compression
168
    $this->SetCompression(true);
169
    // Set default PDF version number
170
    $this->PDFVersion = '1.3';
171
}
172
173
/**
174
 * @param double $left
175
 * @param double $top
176
 */
177
function SetMargins($left, $top, $right=null)
178
{
179
    // Set left, top and right margins
180
    $this->lMargin = $left;
181
    $this->tMargin = $top;
182
    if($right===null) {
183
            $right = $left;
184
    }
185
    $this->rMargin = $right;
186
}
187
188
function SetLeftMargin($margin)
189
{
190
    // Set left margin
191
    $this->lMargin = $margin;
192
    if ($this->page > 0 && $this->x < $margin)
193
        $this->x = $margin;
194
}
195
196
function SetTopMargin($margin)
197
{
198
    // Set top margin
199
    $this->tMargin = $margin;
200
}
201
202
function SetRightMargin($margin)
203
{
204
    // Set right margin
205
    $this->rMargin = $margin;
206
}
207
208
/**
209
 * @param boolean $auto
210
 */
211
function SetAutoPageBreak($auto, $margin=0)
212
{
213
    // Set auto page break mode and triggering margin
214
    $this->AutoPageBreak = $auto;
215
    $this->bMargin = $margin;
216
    $this->PageBreakTrigger = $this->h-$margin;
217
}
218
219
/**
220
 * @param string $zoom
221
 */
222
function SetDisplayMode($zoom, $layout='default')
223
{
224
    // Set display mode in viewer
225
    if($zoom=='fullpage' || $zoom=='fullwidth' || $zoom=='real' || $zoom=='default' || !is_string($zoom))
226
        $this->ZoomMode = $zoom;
227
    else
228
        $this->Error('Incorrect zoom display mode: '.$zoom);
229
    if($layout=='single' || $layout=='continuous' || $layout=='two' || $layout=='default')
230
        $this->LayoutMode = $layout;
231
    else
232
        $this->Error('Incorrect layout display mode: '.$layout);
233
}
234
235
/**
236
 * @param boolean $compress
237
 */
238
function SetCompression($compress)
239
{
240
    // Set page compression
241
    if (function_exists('gzcompress'))
242
        $this->compress = $compress;
243
    else
244
        $this->compress = false;
245
}
246
247
function SetTitle($title, $isUTF8 = false)
248
{
249
    // Title of document
250
    if ($isUTF8)
251
        $title = $this->_UTF8toUTF16($title);
252
    $this->title = $title;
253
}
254
255
function SetSubject($subject, $isUTF8 = false)
256
{
257
    // Subject of document
258
    if ($isUTF8)
259
        $subject = $this->_UTF8toUTF16($subject);
260
    $this->subject = $subject;
261
}
262
263
function SetAuthor($author, $isUTF8 = false)
264
{
265
    // Author of document
266
    if ($isUTF8)
267
        $author = $this->_UTF8toUTF16($author);
268
    $this->author = $author;
269
}
270
271
function SetKeywords($keywords, $isUTF8 = false)
272
{
273
    // Keywords of document
274
    if ($isUTF8)
275
        $keywords = $this->_UTF8toUTF16($keywords);
276
    $this->keywords = $keywords;
277
}
278
279
function SetCreator($creator, $isUTF8 = false)
280
{
281
    // Creator of document
282
    if ($isUTF8)
283
        $creator = $this->_UTF8toUTF16($creator);
284
    $this->creator = $creator;
285
}
286
287
function AliasNbPages($alias = '{nb}')
288
{
289
    // Define an alias for total number of pages
290
    $this->AliasNbPages = $alias;
291
}
292
293
function Error($msg)
294
{
295
    // Fatal error
296
    die('<b>FPDF error:</b> '.$msg);
297
}
298
299
function Open()
300
{
301
    // Begin document
302
    $this->state = 1;
303
}
304
305
function Close()
306
{
307
    // Terminate document
308
    if ($this->state == 3)
309
        return;
310
    if ($this->page == 0)
311
        $this->AddPage();
312
    // Page footer
313
    $this->InFooter = true;
314
    $this->Footer();
315
    $this->InFooter = false;
316
    // Close page
317
    $this->_endpage();
318
    // Close document
319
    $this->_enddoc();
320
}
321
322
function AddPage($orientation = '', $size = '')
323
{
324
    // Start a new page
325
    if ($this->state == 0)
326
        $this->Open();
327
    $family = $this->FontFamily;
328
    $style = $this->FontStyle.($this->underline ? 'U' : '');
329
    $fontsize = $this->FontSizePt;
330
    $lw = $this->LineWidth;
331
    $dc = $this->DrawColor;
332
    $fc = $this->FillColor;
333
    $tc = $this->TextColor;
334
    $cf = $this->ColorFlag;
335
    if ($this->page > 0)
336
    {
337
        // Page footer
338
        $this->InFooter = true;
339
        $this->Footer();
340
        $this->InFooter = false;
341
        // Close page
342
        $this->_endpage();
343
    }
344
    // Start new page
345
    $this->_beginpage($orientation, $size);
346
    // Set line cap style to square
347
    $this->_out('2 J');
348
    // Set line width
349
    $this->LineWidth = $lw;
350
    $this->_out(sprintf('%.2F w', $lw * $this->k));
351
    // Set font
352
    if ($family)
353
        $this->SetFont($family, $style, $fontsize);
354
    // Set colors
355
    $this->DrawColor = $dc;
356
    if ($dc != '0 G')
357
        $this->_out($dc);
358
    $this->FillColor = $fc;
359
    if ($fc != '0 g')
360
        $this->_out($fc);
361
    $this->TextColor = $tc;
362
    $this->ColorFlag = $cf;
363
    // Page header
364
    $this->InHeader = true;
365
    $this->Header();
366
    $this->InHeader = false;
367
    // Restore line width
368
    if ($this->LineWidth != $lw)
369
    {
370
        $this->LineWidth = $lw;
371
        $this->_out(sprintf('%.2F w', $lw * $this->k));
372
    }
373
    // Restore font
374
    if ($family)
375
        $this->SetFont($family, $style, $fontsize);
376
    // Restore colors
377
    if ($this->DrawColor != $dc)
378
    {
379
        $this->DrawColor = $dc;
380
        $this->_out($dc);
381
    }
382
    if ($this->FillColor != $fc)
383
    {
384
        $this->FillColor = $fc;
385
        $this->_out($fc);
386
    }
387
    $this->TextColor = $tc;
388
    $this->ColorFlag = $cf;
389
}
390
391
function Header()
392
{
393
    // To be implemented in your own inherited class
394
}
395
396
function Footer()
397
{
398
    // To be implemented in your own inherited class
399
}
400
401
function PageNo()
402
{
403
    // Get current page number
404
    return $this->page;
405
}
406
407 View Code Duplication
function SetDrawColor($r, $g=null, $b=null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
408
{
409
    // Set color for all stroking operations
410
    if(($r==0 && $g==0 && $b==0) || $g===null) {
411
            $this->DrawColor = sprintf('%.3F G',$r/255);
412
    } else {
413
            $this->DrawColor = sprintf('%.3F %.3F %.3F RG',$r/255,$g/255,$b/255);
414
    }
415
    if($this->page>0) {
416
            $this->_out($this->DrawColor);
417
    }
418
    }
419
420
function SetFillColor($r, $g=null, $b=null)
421
{
422
    // Set color for all filling operations
423
    if(($r==0 && $g==0 && $b==0) || $g===null) {
424
            $this->FillColor = sprintf('%.3F g',$r/255);
425
    } else {
426
            $this->FillColor = sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255);
427
    }
428
    $this->ColorFlag = ($this->FillColor!=$this->TextColor);
429
    if($this->page>0) {
430
            $this->_out($this->FillColor);
431
    }
432
    }
433
434 View Code Duplication
function SetTextColor($r, $g=null, $b=null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
435
{
436
    // Set color for text
437
    if(($r==0 && $g==0 && $b==0) || $g===null) {
438
            $this->TextColor = sprintf('%.3F g',$r/255);
439
    } else {
440
            $this->TextColor = sprintf('%.3F %.3F %.3F rg',$r/255,$g/255,$b/255);
441
    }
442
    $this->ColorFlag = ($this->FillColor!=$this->TextColor);
443
}
444
445
function GetStringWidth($s)
446
{
447
    // Get width of a string in the current font
448
    $s = (string)$s;
449
    $cw = &$this->CurrentFont['cw'];
450
    $w=0;
451
    if ($this->unifontSubset) {
452
        $unicode = $this->UTF8StringToArray($s);
453
        foreach($unicode as $char) {
454
            if (isset($cw[$char])) { $w += (ord($cw[2*$char])<<8) + ord($cw[2*$char+1]); } else if($char>0 && $char<128 && isset($cw[chr($char)])) { $w += $cw[chr($char)]; } else if(isset($this->CurrentFont['desc']['MissingWidth'])) { $w += $this->CurrentFont['desc']['MissingWidth']; } else if(isset($this->CurrentFont['MissingWidth'])) { $w += $this->CurrentFont['MissingWidth']; } else { $w += 500; }
455
        }
456
    } else {
457
        $l = strlen($s);
458
        for($i=0;$i<$l;$i++) {
459
                    $w += $cw[$s[$i]];
460
        }
461
    }
462
    return $w*$this->FontSize/1000;
463
}
464
465
function SetLineWidth($width)
466
{
467
    // Set line width
468
    $this->LineWidth = $width;
469
    if($this->page>0) {
470
            $this->_out(sprintf('%.2F w',$width*$this->k));
471
    }
472
    }
473
474
function Line($x1, $y1, $x2, $y2)
475
{
476
    // Draw a line
477
    $this->_out(sprintf('%.2F %.2F m %.2F %.2F l S',$x1*$this->k,($this->h-$y1)*$this->k,$x2*$this->k,($this->h-$y2)*$this->k));
478
}
479
480
function Rect($x, $y, $w, $h, $style='')
481
{
482
    // Draw a rectangle
483
    if($style=='F') {
484
            $op = 'f';
485
    } elseif($style=='FD' || $style=='DF') {
486
            $op = 'B';
487
    } else {
488
            $op = 'S';
489
    }
490
    $this->_out(sprintf('%.2F %.2F %.2F %.2F re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
491
}
492
493
/**
494
 * @param string $family
495
 */
496
function AddFont($family, $style='', $file='', $uni=false)
497
{
498
    // Add a TrueType, OpenType or Type1 font
499
    $family = strtolower($family);
500
    $style = strtoupper($style);
501
    if($style=='IB')
502
        $style='BI';
503
    if($file=='') {
504
        if ($uni) {
505
        $file = str_replace(' ','',$family).strtolower($style).'.ttf';
506
        }
507
        else {
508
        $file = str_replace(' ','',$family).strtolower($style).'.php';
509
        }
510
    }
511
    $fontkey = $family.$style;
512
    if(isset($this->fonts[$fontkey]))
513
        return;
514
515
    if ($uni) {
516
        if (defined("_SYSTEM_TTFONTS") && file_exists(_SYSTEM_TTFONTS.$file )) { $ttffilename = _SYSTEM_TTFONTS.$file ; }
517
        else { $ttffilename = $this->_getfontpath().'unifont/'.$file ; }
518
        $unifilename = $this->_getfontpath().'unifont/'.strtolower(substr($file ,0,(strpos($file ,'.'))));
519
        $name = '';
520
        $originalsize = 0;
521
        $ttfstat = stat($ttffilename);
522
        if (file_exists($unifilename.'.mtx.php')) {
523
            include($unifilename.'.mtx.php');
524
        }
525
        if (!isset($type) ||  !isset($name) || $originalsize != $ttfstat['size']) {
0 ignored issues
show
Bug introduced by
The variable $type seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
526
            $ttffile = $ttffilename;
527
            require_once($this->_getfontpath().'unifont/ttfonts.php');
528
            $ttf = new TTFontFile();
529
            $ttf->getMetrics($ttffile);
530
            $cw = $ttf->charWidths;
531
            $name = preg_replace('/[ ()]/','',$ttf->fullName);
532
533
            $desc= array('Ascent'=>round($ttf->ascent),
534
            'Descent'=>round($ttf->descent),
535
            'CapHeight'=>round($ttf->capHeight),
536
            'Flags'=>$ttf->flags,
537
            'FontBBox'=>'['.round($ttf->bbox[0])." ".round($ttf->bbox[1])." ".round($ttf->bbox[2])." ".round($ttf->bbox[3]).']',
538
            'ItalicAngle'=>$ttf->italicAngle,
539
            'StemV'=>round($ttf->stemV),
540
            'MissingWidth'=>round($ttf->defaultWidth));
541
            $up = round($ttf->underlinePosition);
542
            $ut = round($ttf->underlineThickness);
543
            $originalsize = $ttfstat['size'] + 0;
544
            $type = 'TTF';
545
            // Generate metrics .php file
546
            $s = '<?php'."\n";
547
            $s .= '$name=\''.$name."';\n";
548
            $s .= '$type=\''.$type."';\n";
549
            $s .= '$desc='.var_export($desc, true).";\n";
550
            $s .= '$up='.$up.";\n";
551
            $s .= '$ut='.$ut.";\n";
552
            $s .= '$ttffile=\''.$ttffile."';\n";
553
            $s .= '$originalsize='.$originalsize.";\n";
554
            $s .= '$fontkey=\''.$fontkey."';\n";
555
            $s .= "?>";
556
            if (is_writable(dirname($this->_getfontpath().'unifont/'.'x'))) {
557
                $fh = fopen($unifilename.'.mtx.php', "w");
558
                fwrite($fh, $s, strlen($s));
559
                fclose($fh);
560
                $fh = fopen($unifilename.'.cw.dat', "wb");
561
                fwrite($fh, $cw, strlen($cw));
562
                fclose($fh);
563
                @unlink($unifilename.'.cw127.php');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
564
            }
565
            unset($ttf);
566
        }
567
        else {
568
            $cw = @file_get_contents($unifilename.'.cw.dat');
569
        }
570
        $i = count($this->fonts) + 1;
571
        if (!empty($this->AliasNbPages))
572
            $sbarr = range(0, 57);
573
        else
574
            $sbarr = range(0, 32);
575
        $this->fonts[$fontkey] = array('i'=>$i, 'type'=>$type, 'name'=>$name, 'desc'=>$desc, 'up'=>$up, 'ut'=>$ut, 'cw'=>$cw, 'ttffile'=>$ttffile, 'fontkey'=>$fontkey, 'subset'=>$sbarr, 'unifilename'=>$unifilename);
0 ignored issues
show
Bug introduced by
The variable $desc does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $up does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $ut does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $ttffile does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
576
577
        $this->FontFiles[$fontkey] = array('length1'=>$originalsize, 'type'=>"TTF", 'ttffile'=>$ttffile);
578
        $this->FontFiles[$file] = array('type'=>"TTF");
579
        unset($cw);
580
    }
581
    else {
582
        $info = $this->_loadfont($file);
583
        $info['i'] = count($this->fonts) + 1;
584
        if (!empty($info['diff']))
585
        {
586
            // Search existing encodings
587
            $n = array_search($info['diff'], $this->diffs);
588
            if (!$n)
589
            {
590
                $n = count($this->diffs) + 1;
591
                $this->diffs[$n] = $info['diff'];
592
            }
593
            $info['diffn'] = $n;
594
        }
595
        if (!empty($info['file']))
596
        {
597
            // Embedded font
598
            if ($info['type'] == 'TrueType')
599
                $this->FontFiles[$info['file']] = array('length1'=>$info['originalsize']);
600
            else
601
                $this->FontFiles[$info['file']] = array('length1'=>$info['size1'], 'length2'=>$info['size2']);
602
        }
603
        $this->fonts[$fontkey] = $info;
604
    }
605
}
606
607
/**
608
 * @param string $family
609
 */
610
function SetFont($family, $style='', $size=0)
611
{
612
    // Select a font; size given in points
613
    if($family=='') {
614
            $family = $this->FontFamily;
615
    } else {
616
            $family = strtolower($family);
617
    }
618
    $style = strtoupper($style);
619
    if(strpos($style,'U')!==false)
620
    {
621
        $this->underline = true;
622
        $style = str_replace('U','',$style);
623
    } else {
624
            $this->underline = false;
625
    }
626
    if($style=='IB') {
627
            $style = 'BI';
628
    }
629
    if($size==0) {
630
            $size = $this->FontSizePt;
631
    }
632
    // Test if font is already selected
633
    if($this->FontFamily==$family && $this->FontStyle==$style && $this->FontSizePt==$size) {
634
            return;
635
    }
636
    // Test if font is already loaded
637
    $fontkey = $family.$style;
638
    if(!isset($this->fonts[$fontkey]))
639
    {
640
        // Test if one of the core fonts
641
        if($family=='arial') {
642
                    $family = 'helvetica';
643
        }
644
        if(in_array($family,$this->CoreFonts))
645
        {
646
            if($family=='symbol' || $family=='zapfdingbats') {
647
                            $style = '';
648
            }
649
            $fontkey = $family.$style;
650
            if(!isset($this->fonts[$fontkey])) {
651
                            $this->AddFont($family,$style);
652
            }
653
        } else {
654
                    $this->Error('Undefined font: '.$family.' '.$style);
655
        }
656
    }
657
    // Select it
658
    $this->FontFamily = $family;
659
    $this->FontStyle = $style;
660
    $this->FontSizePt = $size;
661
    $this->FontSize = $size / $this->k;
662
    $this->CurrentFont = &$this->fonts[$fontkey];
663
    if ($this->fonts[$fontkey]['type'] == 'TTF') { $this->unifontSubset = true; }
664
    else { $this->unifontSubset = false; }
665 View Code Duplication
    if ($this->page > 0)
666
        $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
667
}
668
669
function SetFontSize($size)
670
{
671
    // Set font size in points
672
    if ($this->FontSizePt == $size)
673
        return;
674
    $this->FontSizePt = $size;
675
    $this->FontSize = $size / $this->k;
676 View Code Duplication
    if ($this->page > 0)
677
        $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
678
}
679
680
function AddLink()
681
{
682
    // Create a new internal link
683
    $n = count($this->links) + 1;
684
    $this->links[$n] = array(0, 0);
685
    return $n;
686
}
687
688
function SetLink($link, $y = 0, $page = -1)
689
{
690
    // Set destination of internal link
691
    if ($y == -1)
692
        $y = $this->y;
693
    if ($page == -1)
694
        $page = $this->page;
695
    $this->links[$link] = array($page, $y);
696
}
697
698
/**
699
 * @param double $y
700
 * @param string $link
701
 */
702
function Link($x, $y, $w, $h, $link)
703
{
704
    // Put a link on the page
705
    $this->PageLinks[$this->page][] = array($x * $this->k, $this->hPt - $y * $this->k, $w * $this->k, $h * $this->k, $link);
706
}
707
708
function Text($x, $y, $txt)
709
{
710
    // Output a string
711
    if ($this->unifontSubset)
712
    {
713
        $txt2 = '('.$this->_escape($this->UTF8ToUTF16BE($txt, false)).')';
714
        foreach ($this->UTF8StringToArray($txt) as $uni)
715
            $this->CurrentFont['subset'][$uni] = $uni;
716
    }
717
    else
718
        $txt2 = '('.$this->_escape($txt).')';
719
    $s = sprintf('BT %.2F %.2F Td %s Tj ET', $x * $this->k, ($this->h - $y) * $this->k, $txt2);
720
    if ($this->underline && $txt != '')
721
        $s .= ' '.$this->_dounderline($x, $y, $txt);
722
    if ($this->ColorFlag)
723
        $s = 'q '.$this->TextColor.' '.$s.' Q';
724
    $this->_out($s);
725
}
726
727
function AcceptPageBreak()
728
{
729
    // Accept automatic page break or not
730
    return $this->AutoPageBreak;
731
}
732
733
function Cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = false, $link = '')
734
{
735
    // Output a cell
736
    $k = $this->k;
737
    if ($this->y + $h > $this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak())
738
    {
739
        // Automatic page break
740
        $x = $this->x;
741
        $ws = $this->ws;
742
        if ($ws > 0)
743
        {
744
            $this->ws = 0;
745
            $this->_out('0 Tw');
746
        }
747
        $this->AddPage($this->CurOrientation, $this->CurPageSize);
748
        $this->x = $x;
749
        if ($ws > 0)
750
        {
751
            $this->ws = $ws;
752
            $this->_out(sprintf('%.3F Tw', $ws * $k));
753
        }
754
    }
755
    if ($w == 0)
756
        $w = $this->w - $this->rMargin - $this->x;
757
    $s = '';
758
    if ($fill || $border == 1)
759
    {
760
        if ($fill)
761
            $op = ($border == 1) ? 'B' : 'f';
762
        else
763
            $op = 'S';
764
        $s = sprintf('%.2F %.2F %.2F %.2F re %s ', $this->x * $k, ($this->h - $this->y) * $k, $w * $k, -$h * $k, $op);
765
    }
766
    if (is_string($border))
767
    {
768
        $x = $this->x;
769
        $y = $this->y;
770 View Code Duplication
        if (strpos($border, 'L') !== false)
771
            $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x * $k, ($this->h - $y) * $k, $x * $k, ($this->h - ($y + $h)) * $k);
772 View Code Duplication
        if (strpos($border, 'T') !== false)
773
            $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x * $k, ($this->h - $y) * $k, ($x + $w) * $k, ($this->h - $y) * $k);
774 View Code Duplication
        if (strpos($border, 'R') !== false)
775
            $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', ($x + $w) * $k, ($this->h - $y) * $k, ($x + $w) * $k, ($this->h - ($y + $h)) * $k);
776 View Code Duplication
        if (strpos($border, 'B') !== false)
777
            $s .= sprintf('%.2F %.2F m %.2F %.2F l S ', $x * $k, ($this->h - ($y + $h)) * $k, ($x + $w) * $k, ($this->h - ($y + $h)) * $k);
778
    }
779
    if ($txt !== '')
780
    {
781
        if ($align == 'R')
782
            $dx = $w - $this->cMargin - $this->GetStringWidth($txt);
783
        elseif ($align == 'C')
784
            $dx = ($w - $this->GetStringWidth($txt)) / 2;
785
        else
786
            $dx = $this->cMargin;
787
        if ($this->ColorFlag)
788
            $s .= 'q '.$this->TextColor.' ';
789
790
        // If multibyte, Tw has no effect - do word spacing using an adjustment before each space
791
        if ($this->ws && $this->unifontSubset) {
792
            foreach ($this->UTF8StringToArray($txt) as $uni)
793
                $this->CurrentFont['subset'][$uni] = $uni;
794
            $space = $this->_escape($this->UTF8ToUTF16BE(' ', false));
795
            $s .= sprintf('BT 0 Tw %.2F %.2F Td [', ($this->x + $dx) * $k, ($this->h - ($this->y + .5 * $h + .3 * $this->FontSize)) * $k);
796
            $t = explode(' ', $txt);
797
            $numt = count($t);
798
            for ($i = 0; $i < $numt; $i++) {
799
                $tx = $t[$i];
800
                $tx = '('.$this->_escape($this->UTF8ToUTF16BE($tx, false)).')';
801
                $s .= sprintf('%s ', $tx);
802
                if (($i + 1) < $numt) {
803
                    $adj = -($this->ws * $this->k) * 1000 / $this->FontSizePt;
804
                    $s .= sprintf('%d(%s) ', $adj, $space);
805
                }
806
            }
807
            $s .= '] TJ';
808
            $s .= ' ET';
809
        }
810
        else {
811
            if ($this->unifontSubset)
812
            {
813
                $txt2 = '('.$this->_escape($this->UTF8ToUTF16BE($txt, false)).')';
814
                foreach ($this->UTF8StringToArray($txt) as $uni)
815
                    $this->CurrentFont['subset'][$uni] = $uni;
816
            }
817
            else
818
                $txt2 = '('.str_replace(')', '\\)', str_replace('(', '\\(', str_replace('\\', '\\\\', $txt))).')';
819
            $s .= sprintf('BT %.2F %.2F Td %s Tj ET', ($this->x + $dx) * $k, ($this->h - ($this->y + .5 * $h + .3 * $this->FontSize)) * $k, $txt2);
820
        }
821
        if ($this->underline)
822
            $s .= ' '.$this->_dounderline($this->x + $dx, $this->y + .5 * $h + .3 * $this->FontSize, $txt);
823
        if ($this->ColorFlag)
824
            $s .= ' Q';
825
        if ($link)
826
            $this->Link($this->x + $dx, $this->y + .5 * $h - .5 * $this->FontSize, $this->GetStringWidth($txt), $this->FontSize, $link);
827
    }
828
    if ($s)
829
        $this->_out($s);
830
    $this->lasth = $h;
831
    if ($ln > 0)
832
    {
833
        // Go to next line
834
        $this->y += $h;
835
        if ($ln == 1)
836
            $this->x = $this->lMargin;
837
    }
838
    else
839
        $this->x += $w;
840
}
841
842
function MultiCell($w, $h, $txt, $border = 0, $align = 'J', $fill = false)
843
{
844
    // Output text with automatic or explicit line breaks
845
    $cw = &$this->CurrentFont['cw'];
846
    if ($w == 0)
847
        $w = $this->w - $this->rMargin - $this->x;
848
    $wmax = ($w - 2 * $this->cMargin);
849
    $s = str_replace("\r", '', $txt);
850
    if ($this->unifontSubset) {
851
        $nb = mb_strlen($s, 'utf-8');
852
        while ($nb > 0 && mb_substr($s, $nb - 1, 1, 'utf-8') == "\n") $nb--;
853
    }
854
    else {
855
        $nb = strlen($s);
856
        if ($nb > 0 && $s[$nb - 1] == "\n")
857
            $nb--;
858
    }
859
    $b = 0;
860
    if ($border)
861
    {
862
        if ($border == 1)
863
        {
864
            $border = 'LTRB';
865
            $b = 'LRT';
866
            $b2 = 'LR';
867
        }
868
        else
869
        {
870
            $b2 = '';
871
            if (strpos($border, 'L') !== false)
872
                $b2 .= 'L';
873
            if (strpos($border, 'R') !== false)
874
                $b2 .= 'R';
875
            $b = (strpos($border, 'T') !== false) ? $b2.'T' : $b2;
876
        }
877
    }
878
    $sep = -1;
879
    $i = 0;
880
    $j = 0;
881
    $l = 0;
882
    $ns = 0;
883
    $nl = 1;
884
    while ($i < $nb)
885
    {
886
        // Get next character
887 View Code Duplication
        if ($this->unifontSubset) {
888
            $c = mb_substr($s, $i, 1, 'UTF-8');
889
        }
890
        else {
891
            $c = $s[$i];
892
        }
893
        if ($c == "\n")
894
        {
895
            // Explicit line break
896
            if ($this->ws > 0)
897
            {
898
                $this->ws = 0;
899
                $this->_out('0 Tw');
900
            }
901 View Code Duplication
            if ($this->unifontSubset) {
902
                $this->Cell($w, $h, mb_substr($s, $j, $i - $j, 'UTF-8'), $b, 2, $align, $fill);
903
            }
904
            else {
905
                $this->Cell($w, $h, substr($s, $j, $i - $j), $b, 2, $align, $fill);
906
            }
907
            $i++;
908
            $sep = -1;
909
            $j = $i;
910
            $l = 0;
911
            $ns = 0;
912
            $nl++;
913
            if ($border && $nl == 2)
914
                $b = $b2;
0 ignored issues
show
Bug introduced by
The variable $b2 does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
915
            continue;
916
        }
917
        if ($c == ' ')
918
        {
919
            $sep = $i;
920
            $ls = $l;
921
            $ns++;
922
        }
923
924 View Code Duplication
        if ($this->unifontSubset) { $l += $this->GetStringWidth($c); }
925
        else { $l += $cw[$c] * $this->FontSize / 1000; }
926
927
        if ($l > $wmax)
928
        {
929
            // Automatic line break
930
            if ($sep == -1)
931
            {
932
                if ($i == $j)
933
                    $i++;
934
                if ($this->ws > 0)
935
                {
936
                    $this->ws = 0;
937
                    $this->_out('0 Tw');
938
                }
939 View Code Duplication
                if ($this->unifontSubset) {
940
                    $this->Cell($w, $h, mb_substr($s, $j, $i - $j, 'UTF-8'), $b, 2, $align, $fill);
941
                }
942
                else {
943
                    $this->Cell($w, $h, substr($s, $j, $i - $j), $b, 2, $align, $fill);
944
                }
945
            }
946
            else
947
            {
948
                if ($align == 'J')
949
                {
950
                    $this->ws = ($ns > 1) ? ($wmax - $ls) / ($ns - 1) : 0;
0 ignored issues
show
Bug introduced by
The variable $ls does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
951
                    $this->_out(sprintf('%.3F Tw', $this->ws * $this->k));
952
                }
953 View Code Duplication
                if ($this->unifontSubset) {
954
                    $this->Cell($w, $h, mb_substr($s, $j, $sep - $j, 'UTF-8'), $b, 2, $align, $fill);
955
                }
956
                else {
957
                    $this->Cell($w, $h, substr($s, $j, $sep - $j), $b, 2, $align, $fill);
958
                }
959
                $i = $sep + 1;
960
            }
961
            $sep = -1;
962
            $j = $i;
963
            $l = 0;
964
            $ns = 0;
965
            $nl++;
966
            if ($border && $nl == 2)
967
                $b = $b2;
968
        }
969
        else
970
            $i++;
971
    }
972
    // Last chunk
973
    if ($this->ws > 0)
974
    {
975
        $this->ws = 0;
976
        $this->_out('0 Tw');
977
    }
978
    if ($border && strpos($border, 'B') !== false)
979
        $b .= 'B';
980 View Code Duplication
    if ($this->unifontSubset) {
981
        $this->Cell($w, $h, mb_substr($s, $j, $i - $j, 'UTF-8'), $b, 2, $align, $fill);
982
    }
983
    else {
984
        $this->Cell($w, $h, substr($s, $j, $i - $j), $b, 2, $align, $fill);
985
    }
986
    $this->x = $this->lMargin;
987
}
988
989
function Write($h, $txt, $link = '')
990
{
991
    // Output text in flowing mode
992
    $cw = &$this->CurrentFont['cw'];
993
    $w = $this->w - $this->rMargin - $this->x;
994
995
    $wmax = ($w - 2 * $this->cMargin);
996
    $s = str_replace("\r", '', $txt);
997
    if ($this->unifontSubset) {
998
        $nb = mb_strlen($s, 'UTF-8');
999
        if ($nb == 1 && $s == " ") {
1000
            $this->x += $this->GetStringWidth($s);
1001
            return;
1002
        }
1003
    } else {
1004
        $nb = strlen($s);
1005
    }
1006
    $sep = -1;
1007
    $i = 0;
1008
    $j = 0;
1009
    $l = 0;
1010
    $nl = 1;
1011
    while ($i < $nb)
1012
    {
1013
        // Get next character
1014 View Code Duplication
        if ($this->unifontSubset) {
1015
            $c = mb_substr($s, $i, 1, 'UTF-8');
1016
        }
1017
        else {
1018
            $c = $s[$i];
1019
        }
1020
        if ($c == "\n")
1021
        {
1022
            // Explicit line break
1023 View Code Duplication
            if ($this->unifontSubset) {
1024
                $this->Cell($w, $h, mb_substr($s, $j, $i - $j, 'UTF-8'), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1025
            }
1026
            else {
1027
                $this->Cell($w, $h, substr($s, $j, $i - $j), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1028
            }
1029
            $i++;
1030
            $sep = -1;
1031
            $j = $i;
1032
            $l = 0;
1033 View Code Duplication
            if ($nl == 1)
1034
            {
1035
                $this->x = $this->lMargin;
1036
                $w = $this->w - $this->rMargin - $this->x;
1037
                $wmax = ($w - 2 * $this->cMargin);
1038
            }
1039
            $nl++;
1040
            continue;
1041
        }
1042
        if ($c == ' ')
1043
            $sep = $i;
1044
1045 View Code Duplication
        if ($this->unifontSubset) { $l += $this->GetStringWidth($c); }
1046
        else { $l += $cw[$c] * $this->FontSize / 1000; }
1047
1048
        if ($l > $wmax)
1049
        {
1050
            // Automatic line break
1051
            if ($sep == -1)
1052
            {
1053
                if ($this->x > $this->lMargin)
1054
                {
1055
                    // Move to next line
1056
                    $this->x = $this->lMargin;
1057
                    $this->y += $h;
1058
                    $w = $this->w - $this->rMargin - $this->x;
1059
                    $wmax = ($w - 2 * $this->cMargin);
1060
                    $i++;
1061
                    $nl++;
1062
                    continue;
1063
                }
1064
                if ($i == $j)
1065
                    $i++;
1066 View Code Duplication
                if ($this->unifontSubset) {
1067
                    $this->Cell($w, $h, mb_substr($s, $j, $i - $j, 'UTF-8'), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1068
                }
1069
                else {
1070
                    $this->Cell($w, $h, substr($s, $j, $i - $j), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1071
                }
1072
            }
1073 View Code Duplication
            else
1074
            {
1075
                if ($this->unifontSubset) {
1076
                    $this->Cell($w, $h, mb_substr($s, $j, $sep - $j, 'UTF-8'), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1077
                }
1078
                else {
1079
                    $this->Cell($w, $h, substr($s, $j, $sep - $j), 0, 2, '', 0, $link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1080
                }
1081
                $i = $sep + 1;
1082
            }
1083
            $sep = -1;
1084
            $j = $i;
1085
            $l = 0;
1086 View Code Duplication
            if ($nl == 1)
1087
            {
1088
                $this->x = $this->lMargin;
1089
                $w = $this->w - $this->rMargin - $this->x;
1090
                $wmax = ($w - 2 * $this->cMargin);
1091
            }
1092
            $nl++;
1093
        } else {
1094
                    $i++;
1095
        }
1096
    }
1097
    // Last chunk
1098 View Code Duplication
    if($i!=$j) {
1099
        if ($this->unifontSubset) {
1100
            $this->Cell($l,$h,mb_substr($s,$j,$i-$j,'UTF-8'),0,0,'',0,$link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1101
        } else {
1102
            $this->Cell($l,$h,substr($s,$j),0,0,'',0,$link);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

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...
1103
        }
1104
    }
1105
}
1106
1107
/**
1108
 * @param integer $h
1109
 */
1110
function Ln($h=null)
1111
{
1112
    // Line feed; default value is last cell height
1113
    $this->x = $this->lMargin;
1114
    if($h===null) {
1115
            $this->y += $this->lasth;
1116
    } else {
1117
            $this->y += $h;
1118
    }
1119
    }
1120
1121
function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='')
1122
{
1123
    // Put an image on the page
1124
    if(!isset($this->images[$file]))
1125
    {
1126
        // First use of this image, get info
1127
        if($type=='')
1128
        {
1129
            $pos = strrpos($file,'.');
1130
            if(!$pos) {
1131
                            $this->Error('Image file has no extension and no type was specified: '.$file);
1132
            }
1133
            $type = substr($file,$pos+1);
1134
        }
1135
        $type = strtolower($type);
1136
        if($type=='jpeg') {
1137
                    $type = 'jpg';
1138
        }
1139
        $mtd = '_parse'.$type;
1140
        if(!method_exists($this,$mtd)) {
1141
                    $this->Error('Unsupported image type: '.$type);
1142
        }
1143
        $info = $this->$mtd($file);
1144
        $info['i'] = count($this->images)+1;
1145
        $this->images[$file] = $info;
1146
    } else {
1147
            $info = $this->images[$file];
1148
    }
1149
1150
    // Automatic width and height calculation if needed
1151
    if($w==0 && $h==0)
1152
    {
1153
        // Put image at 96 dpi
1154
        $w = -96;
1155
        $h = -96;
1156
    }
1157
    if($w<0) {
1158
            $w = -$info['w']*72/$w/$this->k;
1159
    }
1160
    if($h<0) {
1161
            $h = -$info['h']*72/$h/$this->k;
1162
    }
1163
    if($w==0) {
1164
            $w = $h*$info['w']/$info['h'];
1165
    }
1166
    if($h==0) {
1167
            $h = $w*$info['h']/$info['w'];
1168
    }
1169
1170
    // Flowing mode
1171
    if($y===null)
1172
    {
1173
        if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak())
1174
        {
1175
            // Automatic page break
1176
            $x2 = $this->x;
1177
            $this->AddPage($this->CurOrientation,$this->CurPageSize);
1178
            $this->x = $x2;
1179
        }
1180
        $y = $this->y;
1181
        $this->y += $h;
1182
    }
1183
1184
    if($x===null) {
1185
            $x = $this->x;
1186
    }
1187
    $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i']));
1188
    if($link) {
1189
            $this->Link($x,$y,$w,$h,$link);
1190
    }
1191
    }
1192
1193
function GetX()
1194
{
1195
    // Get x position
1196
    return $this->x;
1197
}
1198
1199
function SetX($x)
1200
{
1201
    // Set x position
1202
    if ($x >= 0)
1203
        $this->x = $x;
1204
    else
1205
        $this->x = $this->w + $x;
1206
}
1207
1208
function GetY()
1209
{
1210
    // Get y position
1211
    return $this->y;
1212
}
1213
1214
function SetY($y)
1215
{
1216
    // Set y position and reset x
1217
    $this->x = $this->lMargin;
1218
    if ($y >= 0)
1219
        $this->y = $y;
1220
    else
1221
        $this->y = $this->h + $y;
1222
}
1223
1224
function SetXY($x, $y)
1225
{
1226
    // Set x and y positions
1227
    $this->SetY($y);
1228
    $this->SetX($x);
1229
}
1230
1231
function Output($name = '', $dest = '')
1232
{
1233
    // Output PDF to some destination
1234
    if ($this->state < 3)
1235
        $this->Close();
1236
    $dest = strtoupper($dest);
1237
    if ($dest == '')
1238
    {
1239
        if ($name == '')
1240
        {
1241
            $name = 'doc.pdf';
1242
            $dest = 'I';
1243
        } else {
1244
                    $dest = 'F';
1245
        }
1246
    }
1247
    switch ($dest)
1248
    {
1249 View Code Duplication
        case 'I':
1250
            // Send to standard output
1251
            $this->_checkoutput();
1252
            if (PHP_SAPI != 'cli')
1253
            {
1254
                // We send to a browser
1255
                header('Content-Type: application/pdf');
1256
                header('Content-Disposition: inline; filename="'.$name.'"');
1257
                header('Cache-Control: private, max-age=0, must-revalidate');
1258
                header('Pragma: public');
1259
            }
1260
            echo $this->buffer;
0 ignored issues
show
Security Cross-Site Scripting introduced by
$this->buffer can contain request data and is used in output context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read from $_POST, and $_POST['pdf_password'] is passed to FPDF_Protection::SetProtection() in sources/export.queries.php on line 210
  1. Read from $_POST, and $_POST['pdf_password'] is passed to FPDF_Protection::SetProtection()
    in sources/export.queries.php on line 210
  2. $user_pass is passed to FPDF_Protection::_generateencryptionkey()
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 97
  3. $user_pass . $this->padding is passed through substr(), and $user_pass is assigned
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 201
  4. Data is passed through mcrypt_encrypt()
    in vendor/includes/libraries/Pdf/Tfpdf/fpdf.php on line 20
  5. FPDF_Protection::$Ovalue is assigned
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 204
  6. Tainted property FPDF_Protection::$Ovalue is read
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 151
  7. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1417
  8. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1418
  9. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1419
  10. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1420
  11. '/O (' . $this->_escape($this->Ovalue) . ')' is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 151
  12. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  13. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1260
  2. Path: Read from $_POST, and $_POST['date'] is passed to tFPDF::Cell() in sources/views.queries.php on line 108
  1. Read from $_POST, and $_POST['date'] is passed to tFPDF::Cell()
    in sources/views.queries.php on line 108
  2. $txt is passed through str_replace(), and str_replace('\\', '\\\\', $txt) is passed through str_replace(), and str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)) is passed through str_replace(), and $txt2 is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 818
  3. $txt2 is passed through sprintf(), and $s is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 819
  4. $s is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 829
  5. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  6. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1260
  3. Path: Read from $_POST, and $_POST['text'] is escaped by addslashes() for sql, xpath context(s), and addslashes($_POST['text']) is passed through explode(), and $line is assigned in sources/views.queries.php on line 724
  1. Read from $_POST, and $_POST['text'] is escaped by addslashes() for sql, xpath context(s), and addslashes($_POST['text']) is passed through explode(), and $line is assigned
    in sources/views.queries.php on line 724
  2. $line is passed through explode(), and $elem is assigned
    in sources/views.queries.php on line 725
  3. $elem[0] is passed to tFPDF::Cell()
    in sources/views.queries.php on line 727
  4. $txt is passed through str_replace(), and str_replace('\\', '\\\\', $txt) is passed through str_replace(), and str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)) is passed through str_replace(), and $txt2 is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 818
  5. $txt2 is passed through sprintf(), and $s is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 819
  6. $s is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 829
  7. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  8. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1260

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
1261
            break;
1262 View Code Duplication
        case 'D':
1263
            // Download file
1264
            $this->_checkoutput();
1265
            header('Content-Type: application/x-download');
1266
            header('Content-Disposition: attachment; filename="'.$name.'"');
1267
            header('Cache-Control: private, max-age=0, must-revalidate');
1268
            header('Pragma: public');
1269
            echo $this->buffer;
0 ignored issues
show
Security Cross-Site Scripting introduced by
$this->buffer can contain request data and is used in output context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read from $_POST, and $_POST['pdf_password'] is passed to FPDF_Protection::SetProtection() in sources/export.queries.php on line 210
  1. Read from $_POST, and $_POST['pdf_password'] is passed to FPDF_Protection::SetProtection()
    in sources/export.queries.php on line 210
  2. $user_pass is passed to FPDF_Protection::_generateencryptionkey()
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 97
  3. $user_pass . $this->padding is passed through substr(), and $user_pass is assigned
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 201
  4. Data is passed through mcrypt_encrypt()
    in vendor/includes/libraries/Pdf/Tfpdf/fpdf.php on line 20
  5. FPDF_Protection::$Ovalue is assigned
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 204
  6. Tainted property FPDF_Protection::$Ovalue is read
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 151
  7. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1417
  8. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1418
  9. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1419
  10. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1420
  11. '/O (' . $this->_escape($this->Ovalue) . ')' is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 151
  12. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  13. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1269
  2. Path: Read from $_POST, and $_POST['date'] is passed to tFPDF::Cell() in sources/views.queries.php on line 108
  1. Read from $_POST, and $_POST['date'] is passed to tFPDF::Cell()
    in sources/views.queries.php on line 108
  2. $txt is passed through str_replace(), and str_replace('\\', '\\\\', $txt) is passed through str_replace(), and str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)) is passed through str_replace(), and $txt2 is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 818
  3. $txt2 is passed through sprintf(), and $s is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 819
  4. $s is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 829
  5. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  6. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1269
  3. Path: Read from $_POST, and $_POST['text'] is escaped by addslashes() for sql, xpath context(s), and addslashes($_POST['text']) is passed through explode(), and $line is assigned in sources/views.queries.php on line 724
  1. Read from $_POST, and $_POST['text'] is escaped by addslashes() for sql, xpath context(s), and addslashes($_POST['text']) is passed through explode(), and $line is assigned
    in sources/views.queries.php on line 724
  2. $line is passed through explode(), and $elem is assigned
    in sources/views.queries.php on line 725
  3. $elem[0] is passed to tFPDF::Cell()
    in sources/views.queries.php on line 727
  4. $txt is passed through str_replace(), and str_replace('\\', '\\\\', $txt) is passed through str_replace(), and str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)) is passed through str_replace(), and $txt2 is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 818
  5. $txt2 is passed through sprintf(), and $s is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 819
  6. $s is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 829
  7. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  8. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1269

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
1270
            break;
1271
        case 'F':
1272
            // Save to local file
1273
            $f = fopen($name, 'wb');
1274
            if (!$f)
1275
                $this->Error('Unable to create output file: '.$name);
1276
            fwrite($f, $this->buffer, strlen($this->buffer));
0 ignored issues
show
Security File Manipulation introduced by
$this->buffer can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read from $_POST, and $_POST['pdf_password'] is passed to FPDF_Protection::SetProtection() in sources/export.queries.php on line 210
  1. Read from $_POST, and $_POST['pdf_password'] is passed to FPDF_Protection::SetProtection()
    in sources/export.queries.php on line 210
  2. $user_pass is passed to FPDF_Protection::_generateencryptionkey()
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 97
  3. $user_pass . $this->padding is passed through substr(), and $user_pass is assigned
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 201
  4. Data is passed through mcrypt_encrypt()
    in vendor/includes/libraries/Pdf/Tfpdf/fpdf.php on line 20
  5. FPDF_Protection::$Ovalue is assigned
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 204
  6. Tainted property FPDF_Protection::$Ovalue is read
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 151
  7. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1417
  8. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1418
  9. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1419
  10. Data is passed through str_replace()
    in vendor/includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1420
  11. '/O (' . $this->_escape($this->Ovalue) . ')' is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/fpdf.php on line 151
  12. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  13. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1276
  2. Path: Read from $_POST, and $_POST['date'] is passed to tFPDF::Cell() in sources/views.queries.php on line 108
  1. Read from $_POST, and $_POST['date'] is passed to tFPDF::Cell()
    in sources/views.queries.php on line 108
  2. $txt is passed through str_replace(), and str_replace('\\', '\\\\', $txt) is passed through str_replace(), and str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)) is passed through str_replace(), and $txt2 is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 818
  3. $txt2 is passed through sprintf(), and $s is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 819
  4. $s is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 829
  5. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  6. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1276
  3. Path: Read from $_POST, and $_POST['text'] is escaped by addslashes() for sql, xpath context(s), and addslashes($_POST['text']) is passed through explode(), and $line is assigned in sources/views.queries.php on line 724
  1. Read from $_POST, and $_POST['text'] is escaped by addslashes() for sql, xpath context(s), and addslashes($_POST['text']) is passed through explode(), and $line is assigned
    in sources/views.queries.php on line 724
  2. $line is passed through explode(), and $elem is assigned
    in sources/views.queries.php on line 725
  3. $elem[0] is passed to tFPDF::Cell()
    in sources/views.queries.php on line 727
  4. $txt is passed through str_replace(), and str_replace('\\', '\\\\', $txt) is passed through str_replace(), and str_replace('(', '\\(', str_replace('\\', '\\\\', $txt)) is passed through str_replace(), and $txt2 is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 818
  5. $txt2 is passed through sprintf(), and $s is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 819
  6. $s is passed to tFPDF::_out()
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 829
  7. tFPDF::$buffer is assigned
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1713
  8. Tainted property tFPDF::$buffer is read
    in includes/libraries/Pdf/Tfpdf/tfpdf.class.php on line 1276

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
1277
            fclose($f);
1278
            break;
1279
        case 'S':
1280
            // Return as a string
1281
            return $this->buffer;
1282
        default:
1283
            $this->Error('Incorrect output destination: '.$dest);
1284
    }
1285
    return '';
1286
}
1287
1288
/*******************************************************************************
1289
*                                                                              *
1290
*                              Protected methods                               *
1291
*                                                                              *
1292
*******************************************************************************/
1293
function _dochecks()
1294
{
1295
    // Check availability of %F
1296
    if (sprintf('%.1F', 1.0) != '1.0')
1297
        $this->Error('This version of PHP is not supported');
1298
    // Check availability of mbstring
1299
    if (!function_exists('mb_strlen'))
1300
        $this->Error('mbstring extension is not available');
1301
    // Check mbstring overloading
1302
    if (ini_get('mbstring.func_overload') & 2)
1303
        $this->Error('mbstring overloading must be disabled');
1304
    // Ensure runtime magic quotes are disabled
1305
    if (get_magic_quotes_runtime())
1306
        @set_magic_quotes_runtime(0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1307
}
1308
1309
function _getfontpath()
1310
{
1311
    return $this->fontpath;
1312
}
1313
1314
function _checkoutput()
1315
{
1316
    if (PHP_SAPI != 'cli')
1317
    {
1318
        if (headers_sent($file, $line))
1319
            $this->Error("Some data has already been output, can't send PDF file (output started at $file:$line)");
1320
    }
1321
    if (ob_get_length())
1322
    {
1323
        // The output buffer is not empty
1324
        if (preg_match('/^(\xEF\xBB\xBF)?\s*$/', ob_get_contents()))
1325
        {
1326
            // It contains only a UTF-8 BOM and/or whitespace, let's clean it
1327
            ob_clean();
1328
        } else {
1329
                    $this->Error("Some data has already been output, can't send PDF file");
1330
        }
1331
    }
1332
}
1333
1334
function _getpagesize($size)
1335
{
1336
    if (is_string($size))
1337
    {
1338
        $size = strtolower($size);
1339
        if (!isset($this->StdPageSizes[$size]))
1340
            $this->Error('Unknown page size: '.$size);
1341
        $a = $this->StdPageSizes[$size];
1342
        return array($a[0] / $this->k, $a[1] / $this->k);
1343
    }
1344
    else
1345
    {
1346
        if ($size[0] > $size[1])
1347
            return array($size[1], $size[0]);
1348
        else
1349
            return $size;
1350
    }
1351
}
1352
1353
/**
1354
 * @param string $orientation
1355
 * @param string $size
1356
 */
1357
function _beginpage($orientation, $size)
1358
{
1359
    $this->page++;
1360
    $this->pages[$this->page] = '';
1361
    $this->state = 2;
1362
    $this->x = $this->lMargin;
1363
    $this->y = $this->tMargin;
1364
    $this->FontFamily = '';
1365
    // Check page size and orientation
1366
    if ($orientation == '')
1367
        $orientation = $this->DefOrientation;
1368
    else
1369
        $orientation = strtoupper($orientation[0]);
1370
    if ($size == '')
1371
        $size = $this->DefPageSize;
1372
    else
1373
        $size = $this->_getpagesize($size);
1374
    if ($orientation != $this->CurOrientation || $size[0] != $this->CurPageSize[0] || $size[1] != $this->CurPageSize[1])
1375
    {
1376
        // New size or orientation
1377
        if ($orientation == 'P')
1378
        {
1379
            $this->w = $size[0];
1380
            $this->h = $size[1];
1381
        } else
1382
        {
1383
            $this->w = $size[1];
1384
            $this->h = $size[0];
1385
        }
1386
        $this->wPt = $this->w * $this->k;
1387
        $this->hPt = $this->h * $this->k;
1388
        $this->PageBreakTrigger = $this->h - $this->bMargin;
1389
        $this->CurOrientation = $orientation;
1390
        $this->CurPageSize = $size;
1391
    }
1392
    if ($orientation != $this->DefOrientation || $size[0] != $this->DefPageSize[0] || $size[1] != $this->DefPageSize[1])
1393
        $this->PageSizes[$this->page] = array($this->wPt, $this->hPt);
1394
}
1395
1396
function _endpage()
1397
{
1398
    $this->state = 1;
1399
}
1400
1401
/**
1402
 * @param string $font
1403
 */
1404
function _loadfont($font)
1405
{
1406
    // Load a font definition file from the font directory
1407
    include($this->fontpath.$font);
1408
    $a = get_defined_vars();
1409
    if (!isset($a['name']))
1410
        $this->Error('Could not include font definition file');
1411
    return $a;
1412
}
1413
1414
function _escape($s)
1415
{
1416
    // Escape special characters in strings
1417
    $s = str_replace('\\', '\\\\', $s);
1418
    $s = str_replace('(', '\\(', $s);
1419
    $s = str_replace(')', '\\)', $s);
1420
    $s = str_replace("\r", '\\r', $s);
1421
    return $s;
1422
}
1423
1424
function _textstring($s)
1425
{
1426
    // Format a text string
1427
    return '('.$this->_escape($s).')';
1428
}
1429
1430
function _UTF8toUTF16($s)
1431
{
1432
    // Convert UTF-8 to UTF-16BE with BOM
1433
    $res = "\xFE\xFF";
1434
    $nb = strlen($s);
1435
    $i = 0;
1436
    while ($i < $nb)
1437
    {
1438
        $c1 = ord($s[$i++]);
1439
        if ($c1 >= 224)
1440
        {
1441
            // 3-byte character
1442
            $c2 = ord($s[$i++]);
1443
            $c3 = ord($s[$i++]);
1444
            $res .= chr((($c1 & 0x0F) << 4) + (($c2 & 0x3C) >> 2));
1445
            $res .= chr((($c2 & 0x03) << 6) + ($c3 & 0x3F));
1446
        }
1447
        elseif ($c1 >= 192)
1448
        {
1449
            // 2-byte character
1450
            $c2 = ord($s[$i++]);
1451
            $res .= chr(($c1 & 0x1C) >> 2);
1452
            $res .= chr((($c1 & 0x03) << 6) + ($c2 & 0x3F));
1453
        }
1454
        else
1455
        {
1456
            // Single-byte character
1457
            $res .= "\0".chr($c1);
1458
        }
1459
    }
1460
    return $res;
1461
}
1462
1463
function _dounderline($x, $y, $txt)
1464
{
1465
    // Underline text
1466
    $up = $this->CurrentFont['up'];
1467
    $ut = $this->CurrentFont['ut'];
1468
    $w = $this->GetStringWidth($txt) + $this->ws * substr_count($txt, ' ');
1469
    return sprintf('%.2F %.2F %.2F %.2F re f', $x * $this->k, ($this->h - ($y - $up / 1000 * $this->FontSize)) * $this->k, $w * $this->k, -$ut / 1000 * $this->FontSizePt);
1470
}
1471
1472
function _parsejpg($file)
1473
{
1474
    // Extract info from a JPEG file
1475
    $a = getimagesize($file);
1476
    if (!$a)
0 ignored issues
show
Bug Best Practice introduced by
The expression $a of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1477
        $this->Error('Missing or incorrect image file: '.$file);
1478
    if ($a[2] != 2)
1479
        $this->Error('Not a JPEG file: '.$file);
1480
    if (!isset($a['channels']) || $a['channels'] == 3)
1481
        $colspace = 'DeviceRGB';
1482
    elseif ($a['channels'] == 4)
1483
        $colspace = 'DeviceCMYK';
1484
    else
1485
        $colspace = 'DeviceGray';
1486
    $bpc = isset($a['bits']) ? $a['bits'] : 8;
1487
    $data = file_get_contents($file);
1488
    return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data);
1489
}
1490
1491
/**
1492
 * @param string $file
1493
 */
1494
function _parsepng($file)
1495
{
1496
    // Extract info from a PNG file
1497
    $f = fopen($file, 'rb');
1498
    if (!$f)
1499
        $this->Error('Can\'t open image file: '.$file);
1500
    $info = $this->_parsepngstream($f, $file);
1501
    fclose($f);
1502
    return $info;
1503
}
1504
1505
function _parsepngstream($f, $file)
1506
{
1507
    // Check signature
1508
    if ($this->_readstream($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
1509
        $this->Error('Not a PNG file: '.$file);
1510
1511
    // Read header chunk
1512
    $this->_readstream($f, 4);
1513
    if ($this->_readstream($f, 4) != 'IHDR')
1514
        $this->Error('Incorrect PNG file: '.$file);
1515
    $w = $this->_readint($f);
1516
    $h = $this->_readint($f);
1517
    $bpc = ord($this->_readstream($f, 1));
1518
    if ($bpc > 8)
1519
        $this->Error('16-bit depth not supported: '.$file);
1520
    $ct = ord($this->_readstream($f, 1));
1521
    if ($ct == 0 || $ct == 4)
1522
        $colspace = 'DeviceGray';
1523
    elseif ($ct == 2 || $ct == 6)
1524
        $colspace = 'DeviceRGB';
1525
    elseif ($ct == 3)
1526
        $colspace = 'Indexed';
1527
    else
1528
        $this->Error('Unknown color type: '.$file);
1529
    if (ord($this->_readstream($f, 1)) != 0)
1530
        $this->Error('Unknown compression method: '.$file);
1531
    if (ord($this->_readstream($f, 1)) != 0)
1532
        $this->Error('Unknown filter method: '.$file);
1533
    if (ord($this->_readstream($f, 1)) != 0)
1534
        $this->Error('Interlacing not supported: '.$file);
1535
    $this->_readstream($f, 4);
1536
    $dp = '/Predictor 15 /Colors '.($colspace == 'DeviceRGB' ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w;
0 ignored issues
show
Bug introduced by
The variable $colspace does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1537
1538
    // Scan chunks looking for palette, transparency and image data
1539
    $pal = '';
1540
    $trns = '';
1541
    $data = '';
1542
    do
1543
    {
1544
        $n = $this->_readint($f);
1545
        $type = $this->_readstream($f, 4);
1546
        if ($type == 'PLTE')
1547
        {
1548
            // Read palette
1549
            $pal = $this->_readstream($f, $n);
1550
            $this->_readstream($f, 4);
1551
        }
1552
        elseif ($type == 'tRNS')
1553
        {
1554
            // Read transparency info
1555
            $t = $this->_readstream($f, $n);
1556
            if ($ct == 0)
1557
                $trns = array(ord(substr($t, 1, 1)));
1558
            elseif ($ct == 2)
1559
                $trns = array(ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1)));
1560
            else
1561
            {
1562
                $pos = strpos($t, chr(0));
1563
                if ($pos !== false)
1564
                    $trns = array($pos);
1565
            }
1566
            $this->_readstream($f, 4);
1567
        }
1568
        elseif ($type == 'IDAT')
1569
        {
1570
            // Read image data block
1571
            $data .= $this->_readstream($f, $n);
1572
            $this->_readstream($f, 4);
1573
        }
1574
        elseif ($type == 'IEND')
1575
            break;
1576
        else
1577
            $this->_readstream($f, $n + 4);
1578
    }
1579
    while ($n);
1580
1581
    if ($colspace == 'Indexed' && empty($pal))
1582
        $this->Error('Missing palette in '.$file);
1583
    $info = array('w'=>$w, 'h'=>$h, 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'FlateDecode', 'dp'=>$dp, 'pal'=>$pal, 'trns'=>$trns);
1584
    if ($ct >= 4)
1585
    {
1586
        // Extract alpha channel
1587
        if (!function_exists('gzuncompress'))
1588
            $this->Error('Zlib not available, can\'t handle alpha channel: '.$file);
1589
        $data = gzuncompress($data);
1590
        $color = '';
1591
        $alpha = '';
1592
        if ($ct == 4)
1593
        {
1594
            // Gray image
1595
            $len = 2 * $w;
1596 View Code Duplication
            for ($i = 0; $i < $h; $i++)
1597
            {
1598
                $pos = (1 + $len) * $i;
1599
                $color .= $data[$pos];
1600
                $alpha .= $data[$pos];
1601
                $line = substr($data, $pos + 1, $len);
1602
                $color .= preg_replace('/(.)./s', '$1', $line);
1603
                $alpha .= preg_replace('/.(.)/s', '$1', $line);
1604
            }
1605
        } else
1606
        {
1607
            // RGB image
1608
            $len = 4 * $w;
1609 View Code Duplication
            for ($i = 0; $i < $h; $i++)
1610
            {
1611
                $pos = (1 + $len) * $i;
1612
                $color .= $data[$pos];
1613
                $alpha .= $data[$pos];
1614
                $line = substr($data, $pos + 1, $len);
1615
                $color .= preg_replace('/(.{3})./s', '$1', $line);
1616
                $alpha .= preg_replace('/.{3}(.)/s', '$1', $line);
1617
            }
1618
        }
1619
        unset($data);
1620
        $data = gzcompress($color);
1621
        $info['smask'] = gzcompress($alpha);
1622
        if ($this->PDFVersion < '1.4')
1623
            $this->PDFVersion = '1.4';
1624
    }
1625
    $info['data'] = $data;
1626
    return $info;
1627
}
1628
1629
function _readstream($f, $n)
1630
{
1631
    // Read n bytes from stream
1632
    $res = '';
1633
    while ($n > 0 && !feof($f))
1634
    {
1635
        $s = fread($f, $n);
1636
        if ($s === false)
1637
            $this->Error('Error while reading stream');
1638
        $n -= strlen($s);
1639
        $res .= $s;
1640
    }
1641
    if ($n > 0)
1642
        $this->Error('Unexpected end of stream');
1643
    return $res;
1644
}
1645
1646
function _readint($f)
1647
{
1648
    // Read a 4-byte integer from stream
1649
    $a = unpack('Ni', $this->_readstream($f, 4));
1650
    return $a['i'];
1651
}
1652
1653
function _parsegif($file)
1654
{
1655
    // Extract info from a GIF file (via PNG conversion)
1656
    if (!function_exists('imagepng'))
1657
        $this->Error('GD extension is required for GIF support');
1658
    if (!function_exists('imagecreatefromgif'))
1659
        $this->Error('GD has no GIF read support');
1660
    $im = imagecreatefromgif($file);
1661
    if (!$im)
1662
        $this->Error('Missing or incorrect image file: '.$file);
1663
    imageinterlace($im, 0);
1664
    $f = @fopen('php://temp', 'rb+');
1665
    if ($f)
1666
    {
1667
        // Perform conversion in memory
1668
        ob_start();
1669
        imagepng($im);
1670
        $data = ob_get_clean();
1671
        imagedestroy($im);
1672
        fwrite($f, $data);
1673
        rewind($f);
1674
        $info = $this->_parsepngstream($f, $file);
1675
        fclose($f);
1676
    }
1677
    else
1678
    {
1679
        // Use temporary file
1680
        $tmp = tempnam('.', 'gif');
1681
        if (!$tmp)
1682
            $this->Error('Unable to create a temporary file');
1683
        if (!imagepng($im, $tmp))
1684
            $this->Error('Error while saving to temporary file');
1685
        imagedestroy($im);
1686
        $info = $this->_parsepng($tmp);
1687
        unlink($tmp);
1688
    }
1689
    return $info;
1690
}
1691
1692
function _newobj()
1693
{
1694
    // Begin a new object
1695
    $this->n++;
1696
    $this->offsets[$this->n] = strlen($this->buffer);
1697
    $this->_out($this->n.' 0 obj');
1698
}
1699
1700
function _putstream($s)
1701
{
1702
    $this->_out('stream');
1703
    $this->_out($s);
1704
    $this->_out('endstream');
1705
}
1706
1707
function _out($s)
1708
{
1709
    // Add a line to the document
1710
    if ($this->state == 2)
1711
        $this->pages[$this->page] .= $s."\n";
1712
    else
1713
        $this->buffer .= $s."\n";
1714
}
1715
1716
function _putpages()
1717
{
1718
    $nb = $this->page;
1719
    if (!empty($this->AliasNbPages))
1720
    {
1721
        // Replace number of pages in fonts using subsets
1722
        $alias = $this->UTF8ToUTF16BE($this->AliasNbPages, false);
1723
        $r = $this->UTF8ToUTF16BE("$nb", false);
1724 View Code Duplication
        for ($n = 1; $n <= $nb; $n++)
1725
            $this->pages[$n] = str_replace($alias, $r, $this->pages[$n]);
1726
        // Now repeat for no pages in non-subset fonts
1727 View Code Duplication
        for ($n = 1; $n <= $nb; $n++)
1728
            $this->pages[$n] = str_replace($this->AliasNbPages, $nb, $this->pages[$n]);
1729
    }
1730
    if ($this->DefOrientation == 'P')
1731
    {
1732
        $wPt = $this->DefPageSize[0] * $this->k;
1733
        $hPt = $this->DefPageSize[1] * $this->k;
1734
    }
1735
    else
1736
    {
1737
        $wPt = $this->DefPageSize[1] * $this->k;
1738
        $hPt = $this->DefPageSize[0] * $this->k;
1739
    }
1740
    $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
1741
    for ($n = 1; $n <= $nb; $n++)
1742
    {
1743
        // Page
1744
        $this->_newobj();
1745
        $this->_out('<</Type /Page');
1746
        $this->_out('/Parent 1 0 R');
1747
        if (isset($this->PageSizes[$n]))
1748
            $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]', $this->PageSizes[$n][0], $this->PageSizes[$n][1]));
1749
        $this->_out('/Resources 2 0 R');
1750
        if (isset($this->PageLinks[$n]))
1751
        {
1752
            // Links
1753
            $annots = '/Annots [';
1754
            foreach ($this->PageLinks[$n] as $pl)
1755
            {
1756
                $rect = sprintf('%.2F %.2F %.2F %.2F', $pl[0], $pl[1], $pl[0] + $pl[2], $pl[1] - $pl[3]);
1757
                $annots .= '<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
1758
                if (is_string($pl[4]))
1759
                    $annots .= '/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
1760
                else
1761
                {
1762
                    $l = $this->links[$pl[4]];
1763
                    $h = isset($this->PageSizes[$l[0]]) ? $this->PageSizes[$l[0]][1] : $hPt;
1764
                    $annots .= sprintf('/Dest [%d 0 R /XYZ 0 %.2F null]>>', 1 + 2 * $l[0], $h - $l[1] * $this->k);
1765
                }
1766
            }
1767
            $this->_out($annots.']');
1768
        }
1769
        if ($this->PDFVersion > '1.3')
1770
            $this->_out('/Group <</Type /Group /S /Transparency /CS /DeviceRGB>>');
1771
        $this->_out('/Contents '.($this->n + 1).' 0 R>>');
1772
        $this->_out('endobj');
1773
        // Page content
1774
        $p = ($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
1775
        $this->_newobj();
1776
        $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
1777
        $this->_putstream($p);
1778
        $this->_out('endobj');
1779
    }
1780
    // Pages root
1781
    $this->offsets[1] = strlen($this->buffer);
1782
    $this->_out('1 0 obj');
1783
    $this->_out('<</Type /Pages');
1784
    $kids = '/Kids [';
1785
    for($i=0;$i<$nb;$i++) {
1786
            $kids .= (3+2*$i).' 0 R ';
1787
    }
1788
    $this->_out($kids.']');
1789
    $this->_out('/Count '.$nb);
1790
    $this->_out(sprintf('/MediaBox [0 0 %.2F %.2F]',$wPt,$hPt));
1791
    $this->_out('>>');
1792
    $this->_out('endobj');
1793
}
1794
1795
function _putfonts()
1796
{
1797
    $nf=$this->n;
1798
    foreach($this->diffs as $diff)
1799
    {
1800
        // Encodings
1801
        $this->_newobj();
1802
        $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
1803
        $this->_out('endobj');
1804
    }
1805
    foreach($this->FontFiles as $file=>$info)
1806
    {
1807
        if (!isset($info['type']) || $info['type']!='TTF') {
1808
        // Font file embedding
1809
        $this->_newobj();
1810
        $this->FontFiles[$file]['n']=$this->n;
1811
        $font='';
1812
        $f=fopen($this->_getfontpath().$file,'rb',1);
1813
        if(!$f) {
1814
                    $this->Error('Font file not found');
1815
        }
1816
        while(!feof($f)) {
1817
                    $font.=fread($f,8192);
1818
        }
1819
        fclose($f);
1820
        $compressed=(substr($file,-2)=='.z');
1821
        if(!$compressed && isset($info['length2']))
1822
        {
1823
            $header=(ord($font[0])==128);
1824
            if($header)
1825
            {
1826
                // Strip first binary header
1827
                $font=substr($font,6);
1828
            }
1829
            if($header && ord($font[$info['length1']])==128)
1830
            {
1831
                // Strip second binary header
1832
                $font=substr($font,0,$info['length1']).substr($font,$info['length1']+6);
1833
            }
1834
        }
1835
        $this->_out('<</Length '.strlen($font));
1836
        if($compressed) {
1837
                    $this->_out('/Filter /FlateDecode');
1838
        }
1839
        $this->_out('/Length1 '.$info['length1']);
1840
        if(isset($info['length2'])) {
1841
                    $this->_out('/Length2 '.$info['length2'].' /Length3 0');
1842
        }
1843
        $this->_out('>>');
1844
        $this->_putstream($font);
1845
        $this->_out('endobj');
1846
        }
1847
    }
1848
    foreach($this->fonts as $k=>$font)
1849
    {
1850
        // Font objects
1851
        //$this->fonts[$k]['n']=$this->n+1;
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1852
        $type = $font['type'];
1853
        $name = $font['name'];
1854
        if($type=='Core')
1855
        {
1856
            // Standard font
1857
            $this->fonts[$k]['n']=$this->n+1;
1858
            $this->_newobj();
1859
            $this->_out('<</Type /Font');
1860
            $this->_out('/BaseFont /'.$name);
1861
            $this->_out('/Subtype /Type1');
1862
            if($name!='Symbol' && $name!='ZapfDingbats') {
1863
                            $this->_out('/Encoding /WinAnsiEncoding');
1864
            }
1865
            $this->_out('>>');
1866
            $this->_out('endobj');
1867
        } elseif($type=='Type1' || $type=='TrueType')
1868
        {
1869
            // Additional Type1 or TrueType font
1870
            $this->fonts[$k]['n']=$this->n+1;
1871
            $this->_newobj();
1872
            $this->_out('<</Type /Font');
1873
            $this->_out('/BaseFont /'.$name);
1874
            $this->_out('/Subtype /'.$type);
1875
            $this->_out('/FirstChar 32 /LastChar 255');
1876
            $this->_out('/Widths '.($this->n+1).' 0 R');
1877
            $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
1878
            if($font['enc'])
1879
            {
1880
                if(isset($font['diff'])) {
1881
                                    $this->_out('/Encoding '.($nf+$font['diff']).' 0 R');
1882
                } else {
1883
                                    $this->_out('/Encoding /WinAnsiEncoding');
1884
                }
1885
            }
1886
            $this->_out('>>');
1887
            $this->_out('endobj');
1888
            // Widths
1889
            $this->_newobj();
1890
            $cw = &$font['cw'];
1891
            $s = '[';
1892 View Code Duplication
            for ($i = 32; $i <= 255; $i++)
1893
                $s .= $cw[chr($i)].' ';
1894
            $this->_out($s.']');
1895
            $this->_out('endobj');
1896
            // Descriptor
1897
            $this->_newobj();
1898
            $s = '<</Type /FontDescriptor /FontName /'.$name;
1899
            foreach ($font['desc'] as $k=>$v)
1900
                $s .= ' /'.$k.' '.$v;
1901
            $file = $font['file'];
1902
            if ($file)
1903
                $s .= ' /FontFile'.($type == 'Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R';
1904
            $this->_out($s.'>>');
1905
            $this->_out('endobj');
1906
        }
1907
        // TrueType embedded SUBSETS or FULL
1908
        else if ($type == 'TTF') {
1909
            $this->fonts[$k]['n'] = $this->n + 1;
1910
            require_once($this->_getfontpath().'unifont/ttfonts.php');
1911
            $ttf = new TTFontFile();
1912
            $fontname = 'MPDFAA'.'+'.$font['name'];
1913
            $subset = $font['subset'];
1914
            unset($subset[0]);
1915
            $ttfontstream = $ttf->makeSubset($font['ttffile'], $subset);
1916
            $ttfontsize = strlen($ttfontstream);
1917
            $fontstream = gzcompress($ttfontstream);
1918
            $codeToGlyph = $ttf->codeToGlyph;
1919
            unset($codeToGlyph[0]);
1920
1921
            // Type0 Font
1922
            // A composite font - a font composed of other fonts, organized hierarchically
1923
            $this->_newobj();
1924
            $this->_out('<</Type /Font');
1925
            $this->_out('/Subtype /Type0');
1926
            $this->_out('/BaseFont /'.$fontname.'');
1927
            $this->_out('/Encoding /Identity-H');
1928
            $this->_out('/DescendantFonts ['.($this->n + 1).' 0 R]');
1929
            $this->_out('/ToUnicode '.($this->n + 2).' 0 R');
1930
            $this->_out('>>');
1931
            $this->_out('endobj');
1932
1933
            // CIDFontType2
1934
            // A CIDFont whose glyph descriptions are based on TrueType font technology
1935
            $this->_newobj();
1936
            $this->_out('<</Type /Font');
1937
            $this->_out('/Subtype /CIDFontType2');
1938
            $this->_out('/BaseFont /'.$fontname.'');
1939
            $this->_out('/CIDSystemInfo '.($this->n + 2).' 0 R');
1940
            $this->_out('/FontDescriptor '.($this->n + 3).' 0 R');
1941
            if (isset($font['desc']['MissingWidth'])) {
1942
                $this->_out('/DW '.$font['desc']['MissingWidth'].'');
1943
            }
1944
1945
            $this->_putTTfontwidths($font, $ttf->maxUni);
1946
1947
            $this->_out('/CIDToGIDMap '.($this->n + 4).' 0 R');
1948
            $this->_out('>>');
1949
            $this->_out('endobj');
1950
1951
            // ToUnicode
1952
            $this->_newobj();
1953
            $toUni = "/CIDInit /ProcSet findresource begin\n";
1954
            $toUni .= "12 dict begin\n";
1955
            $toUni .= "begincmap\n";
1956
            $toUni .= "/CIDSystemInfo\n";
1957
            $toUni .= "<</Registry (Adobe)\n";
1958
            $toUni .= "/Ordering (UCS)\n";
1959
            $toUni .= "/Supplement 0\n";
1960
            $toUni .= ">> def\n";
1961
            $toUni .= "/CMapName /Adobe-Identity-UCS def\n";
1962
            $toUni .= "/CMapType 2 def\n";
1963
            $toUni .= "1 begincodespacerange\n";
1964
            $toUni .= "<0000> <FFFF>\n";
1965
            $toUni .= "endcodespacerange\n";
1966
            $toUni .= "1 beginbfrange\n";
1967
            $toUni .= "<0000> <FFFF> <0000>\n";
1968
            $toUni .= "endbfrange\n";
1969
            $toUni .= "endcmap\n";
1970
            $toUni .= "CMapName currentdict /CMap defineresource pop\n";
1971
            $toUni .= "end\n";
1972
            $toUni .= "end";
1973
            $this->_out('<</Length '.(strlen($toUni)).'>>');
1974
            $this->_putstream($toUni);
1975
            $this->_out('endobj');
1976
1977
            // CIDSystemInfo dictionary
1978
            $this->_newobj();
1979
            $this->_out('<</Registry (Adobe)');
1980
            $this->_out('/Ordering (UCS)');
1981
            $this->_out('/Supplement 0');
1982
            $this->_out('>>');
1983
            $this->_out('endobj');
1984
1985
            // Font descriptor
1986
            $this->_newobj();
1987
            $this->_out('<</Type /FontDescriptor');
1988
            $this->_out('/FontName /'.$fontname);
1989
            foreach ($font['desc'] as $kd=>$v) {
1990
                if ($kd == 'Flags') { $v = $v | 4; $v = $v & ~32; } // SYMBOLIC font flag
1991
                $this->_out(' /'.$kd.' '.$v);
1992
            }
1993
            $this->_out('/FontFile2 '.($this->n + 2).' 0 R');
1994
            $this->_out('>>');
1995
            $this->_out('endobj');
1996
1997
            // Embed CIDToGIDMap
1998
            // A specification of the mapping from CIDs to glyph indices
1999
            $cidtogidmap = '';
0 ignored issues
show
Unused Code introduced by
$cidtogidmap 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...
2000
            $cidtogidmap = str_pad('', 256 * 256 * 2, "\x00");
2001
            foreach ($codeToGlyph as $cc=>$glyph) {
2002
                $cidtogidmap[$cc * 2] = chr($glyph >> 8);
2003
                $cidtogidmap[$cc * 2 + 1] = chr($glyph & 0xFF);
2004
            }
2005
            $cidtogidmap = gzcompress($cidtogidmap);
2006
            $this->_newobj();
2007
            $this->_out('<</Length '.strlen($cidtogidmap).'');
2008
            $this->_out('/Filter /FlateDecode');
2009
            $this->_out('>>');
2010
            $this->_putstream($cidtogidmap);
2011
            $this->_out('endobj');
2012
2013
            //Font file
2014
            $this->_newobj();
2015
            $this->_out('<</Length '.strlen($fontstream));
2016
            $this->_out('/Filter /FlateDecode');
2017
            $this->_out('/Length1 '.$ttfontsize);
2018
            $this->_out('>>');
2019
            $this->_putstream($fontstream);
2020
            $this->_out('endobj');
2021
            unset($ttf);
2022
        }
2023
        else
2024
        {
2025
            // Allow for additional types
2026
            $this->fonts[$k]['n'] = $this->n + 1;
2027
            $mtd = '_put'.strtolower($type);
2028
            if (!method_exists($this, $mtd))
2029
                $this->Error('Unsupported font type: '.$type);
2030
            $this->$mtd($font);
2031
        }
2032
    }
2033
}
2034
2035
/**
2036
 * @param integer $maxUni
2037
 */
2038
function _putTTfontwidths(&$font, $maxUni) {
2039
    if (file_exists($font['unifilename'].'.cw127.php')) {
2040
        include($font['unifilename'].'.cw127.php');
2041
        $startcid = 128;
2042
    } else {
2043
        $rangeid = 0;
2044
        $range = array();
2045
        $prevcid = -2;
2046
        $prevwidth = -1;
2047
        $interval = false;
2048
        $startcid = 1;
2049
    }
2050
    $cwlen = $maxUni + 1;
2051
2052
    // for each character
2053
    for ($cid = $startcid; $cid < $cwlen; $cid++) {
2054
        if ($cid == 128 && (!file_exists($font['unifilename'].'.cw127.php'))) {
2055
            if (is_writable(dirname($this->_getfontpath().'unifont/x'))) {
2056
                $fh = fopen($font['unifilename'].'.cw127.php', "wb");
2057
                $cw127 = '<?php'."\n";
2058
                $cw127 .= '$rangeid='.$rangeid.";\n";
0 ignored issues
show
Bug introduced by
The variable $rangeid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2059
                $cw127 .= '$prevcid='.$prevcid.";\n";
0 ignored issues
show
Bug introduced by
The variable $prevcid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2060
                $cw127 .= '$prevwidth='.$prevwidth.";\n";
0 ignored issues
show
Bug introduced by
The variable $prevwidth does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2061
                if ($interval) { $cw127 .= '$interval=true'.";\n"; }
0 ignored issues
show
Bug introduced by
The variable $interval does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2062
                else { $cw127 .= '$interval=false'.";\n"; }
2063
                $cw127 .= '$range='.var_export($range, true).";\n";
0 ignored issues
show
Bug introduced by
The variable $range does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2064
                $cw127 .= "?>";
2065
                fwrite($fh, $cw127, strlen($cw127));
2066
                fclose($fh);
2067
            }
2068
        }
2069
        if ($font['cw'][$cid * 2] == "\00" && $font['cw'][$cid * 2 + 1] == "\00") { continue; }
2070
        $width = (ord($font['cw'][$cid * 2]) << 8) + ord($font['cw'][$cid * 2 + 1]);
2071
        if ($width == 65535) { $width = 0; }
2072
        if ($cid > 255 && (!isset($font['subset'][$cid]) || !$font['subset'][$cid])) { continue; }
2073
        if (!isset($font['dw']) || (isset($font['dw']) && $width != $font['dw'])) {
2074
            if ($cid == ($prevcid + 1)) {
2075
                if ($width == $prevwidth) {
2076
                    if ($width == $range[$rangeid][0]) {
2077
                        $range[$rangeid][] = $width;
2078 View Code Duplication
                    } else {
2079
                        array_pop($range[$rangeid]);
2080
                        // new range
2081
                        $rangeid = $prevcid;
2082
                        $range[$rangeid] = array();
2083
                        $range[$rangeid][] = $prevwidth;
2084
                        $range[$rangeid][] = $width;
2085
                    }
2086
                    $interval = true;
2087
                    $range[$rangeid]['interval'] = true;
2088 View Code Duplication
                } else {
2089
                    if ($interval) {
2090
                        // new range
2091
                        $rangeid = $cid;
2092
                        $range[$rangeid] = array();
2093
                        $range[$rangeid][] = $width;
2094
                    } else { $range[$rangeid][] = $width; }
2095
                    $interval = false;
2096
                }
2097
            } else {
2098
                $rangeid = $cid;
2099
                $range[$rangeid] = array();
2100
                $range[$rangeid][] = $width;
2101
                $interval = false;
2102
            }
2103
            $prevcid = $cid;
2104
            $prevwidth = $width;
2105
        }
2106
    }
2107
    $prevk = -1;
2108
    $nextk = -1;
2109
    $prevint = false;
2110
    foreach ($range as $k => $ws) {
2111
        $cws = count($ws);
2112
        if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) {
2113
            if (isset($range[$k]['interval'])) { unset($range[$k]['interval']); }
2114
            $range[$prevk] = array_merge($range[$prevk], $range[$k]);
2115
            unset($range[$k]);
2116
        }
2117
        else { $prevk = $k; }
2118
        $nextk = $k + $cws;
2119
        if (isset($ws['interval'])) {
2120
            if ($cws > 3) { $prevint = true; }
2121
            else { $prevint = false; }
2122
            unset($range[$k]['interval']);
2123
            --$nextk;
2124
        }
2125
        else { $prevint = false; }
2126
    }
2127
    $w = '';
2128
    foreach ($range as $k => $ws) {
2129
        if (count(array_count_values($ws)) == 1) { $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0]; }
2130
        else { $w .= ' '.$k.' [ '.implode(' ', $ws).' ]'."\n"; }
2131
    }
2132
    $this->_out('/W ['.$w.' ]');
2133
}
2134
2135
function _putimages()
2136
{
2137
    foreach (array_keys($this->images) as $file)
2138
    {
2139
        $this->_putimage($this->images[$file]);
2140
        unset($this->images[$file]['data']);
2141
        unset($this->images[$file]['smask']);
2142
    }
2143
}
2144
2145
function _putimage(&$info)
2146
{
2147
    $this->_newobj();
2148
    $info['n'] = $this->n;
2149
    $this->_out('<</Type /XObject');
2150
    $this->_out('/Subtype /Image');
2151
    $this->_out('/Width '.$info['w']);
2152
    $this->_out('/Height '.$info['h']);
2153
    if ($info['cs'] == 'Indexed')
2154
        $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal']) / 3 - 1).' '.($this->n + 1).' 0 R]');
2155
    else
2156
    {
2157
        $this->_out('/ColorSpace /'.$info['cs']);
2158
        if ($info['cs'] == 'DeviceCMYK')
2159
            $this->_out('/Decode [1 0 1 0 1 0 1 0]');
2160
    }
2161
    $this->_out('/BitsPerComponent '.$info['bpc']);
2162
    if (isset($info['f']))
2163
        $this->_out('/Filter /'.$info['f']);
2164
    if (isset($info['dp']))
2165
        $this->_out('/DecodeParms <<'.$info['dp'].'>>');
2166
    if (isset($info['trns']) && is_array($info['trns']))
2167
    {
2168
        $trns = '';
2169
        for ($i = 0; $i < count($info['trns']); $i++)
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
2170
            $trns .= $info['trns'][$i].' '.$info['trns'][$i].' ';
2171
        $this->_out('/Mask ['.$trns.']');
2172
    }
2173
    if (isset($info['smask']))
2174
        $this->_out('/SMask '.($this->n + 1).' 0 R');
2175
    $this->_out('/Length '.strlen($info['data']).'>>');
2176
    $this->_putstream($info['data']);
2177
    $this->_out('endobj');
2178
    // Soft mask
2179
    if (isset($info['smask']))
2180
    {
2181
        $dp = '/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns '.$info['w'];
2182
        $smask = array('w'=>$info['w'], 'h'=>$info['h'], 'cs'=>'DeviceGray', 'bpc'=>8, 'f'=>$info['f'], 'dp'=>$dp, 'data'=>$info['smask']);
2183
        $this->_putimage($smask);
2184
    }
2185
    // Palette
2186
    if ($info['cs'] == 'Indexed')
2187
    {
2188
        $filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
2189
        $pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal'];
2190
        $this->_newobj();
2191
        $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
2192
        $this->_putstream($pal);
2193
        $this->_out('endobj');
2194
    }
2195
}
2196
2197
function _putxobjectdict()
2198
{
2199
    foreach ($this->images as $image)
2200
        $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
2201
}
2202
2203
function _putresourcedict()
2204
{
2205
    $this->_out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
2206
    $this->_out('/Font <<');
2207
    foreach ($this->fonts as $font) {
2208
        $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
2209
    }
2210
    $this->_out('>>');
2211
    $this->_out('/XObject <<');
2212
    $this->_putxobjectdict();
2213
    $this->_out('>>');
2214
}
2215
2216
function _putresources()
2217
{
2218
    $this->_putfonts();
2219
    $this->_putimages();
2220
    // Resource dictionary
2221
    $this->offsets[2] = strlen($this->buffer);
2222
    $this->_out('2 0 obj');
2223
    $this->_out('<<');
2224
    $this->_putresourcedict();
2225
    $this->_out('>>');
2226
    $this->_out('endobj');
2227
}
2228
2229
function _putinfo()
2230
{
2231
    $this->_out('/Producer '.$this->_textstring('tFPDF '.tFPDF_VERSION));
2232
    if (!empty($this->title))
2233
        $this->_out('/Title '.$this->_textstring($this->title));
2234
    if (!empty($this->subject))
2235
        $this->_out('/Subject '.$this->_textstring($this->subject));
2236
    if (!empty($this->author))
2237
        $this->_out('/Author '.$this->_textstring($this->author));
2238
    if (!empty($this->keywords))
2239
        $this->_out('/Keywords '.$this->_textstring($this->keywords));
2240
    if (!empty($this->creator))
2241
        $this->_out('/Creator '.$this->_textstring($this->creator));
2242
    $this->_out('/CreationDate '.$this->_textstring('D:'.@date('YmdHis')));
2243
}
2244
2245
function _putcatalog()
2246
{
2247
    $this->_out('/Type /Catalog');
2248
    $this->_out('/Pages 1 0 R');
2249
    if ($this->ZoomMode == 'fullpage')
2250
        $this->_out('/OpenAction [3 0 R /Fit]');
2251
    elseif ($this->ZoomMode == 'fullwidth')
2252
        $this->_out('/OpenAction [3 0 R /FitH null]');
2253
    elseif ($this->ZoomMode == 'real')
2254
        $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
2255
    elseif (!is_string($this->ZoomMode))
2256
        $this->_out('/OpenAction [3 0 R /XYZ null null '.sprintf('%.2F', $this->ZoomMode / 100).']');
2257
    if ($this->LayoutMode == 'single')
2258
        $this->_out('/PageLayout /SinglePage');
2259
    elseif ($this->LayoutMode == 'continuous')
2260
        $this->_out('/PageLayout /OneColumn');
2261
    elseif ($this->LayoutMode == 'two')
2262
        $this->_out('/PageLayout /TwoColumnLeft');
2263
}
2264
2265
function _putheader()
2266
{
2267
    $this->_out('%PDF-'.$this->PDFVersion);
2268
}
2269
2270
function _puttrailer()
2271
{
2272
    $this->_out('/Size '.($this->n + 1));
2273
    $this->_out('/Root '.$this->n.' 0 R');
2274
    $this->_out('/Info '.($this->n - 1).' 0 R');
2275
}
2276
2277
function _enddoc()
2278
{
2279
    $this->_putheader();
2280
    $this->_putpages();
2281
    $this->_putresources();
2282
    // Info
2283
    $this->_newobj();
2284
    $this->_out('<<');
2285
    $this->_putinfo();
2286
    $this->_out('>>');
2287
    $this->_out('endobj');
2288
    // Catalog
2289
    $this->_newobj();
2290
    $this->_out('<<');
2291
    $this->_putcatalog();
2292
    $this->_out('>>');
2293
    $this->_out('endobj');
2294
    // Cross-ref
2295
    $o = strlen($this->buffer);
2296
    $this->_out('xref');
2297
    $this->_out('0 '.($this->n + 1));
2298
    $this->_out('0000000000 65535 f ');
2299
    for ($i = 1; $i <= $this->n; $i++)
2300
        $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i]));
2301
    // Trailer
2302
    $this->_out('trailer');
2303
    $this->_out('<<');
2304
    $this->_puttrailer();
2305
    $this->_out('>>');
2306
    $this->_out('startxref');
2307
    $this->_out($o);
2308
    $this->_out('%%EOF');
2309
    $this->state = 3;
2310
}
2311
2312
// ********* NEW FUNCTIONS *********
2313
// Converts UTF-8 strings to UTF16-BE.
2314
function UTF8ToUTF16BE($str, $setbom = true) {
2315
    $outstr = "";
2316
    if ($setbom) {
2317
        $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM)
2318
    }
2319
    $outstr .= mb_convert_encoding($str, 'UTF-16BE', 'UTF-8');
2320
    return $outstr;
2321
}
2322
2323
// Converts UTF-8 strings to codepoints array
2324
function UTF8StringToArray($str) {
2325
    $out = array();
2326
    $len = strlen($str);
2327
    for ($i = 0; $i < $len; $i++) {
2328
    $uni = -1;
2329
        $h = ord($str[$i]);
2330
        if ( $h <= 0x7F )
2331
            $uni = $h;
2332
        elseif ( $h >= 0xC2 ) {
2333
            if ( ($h <= 0xDF) && ($i < $len -1) )
2334
            $uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
2335
            elseif ( ($h <= 0xEF) && ($i < $len -2) )
2336
            $uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6
2337
                                        | (ord($str[++$i]) & 0x3F);
2338
            elseif ( ($h <= 0xF4) && ($i < $len -3) )
2339
            $uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12
2340
                                        | (ord($str[++$i]) & 0x3F) << 6
2341
                                        | (ord($str[++$i]) & 0x3F);
2342
        }
2343
    if ($uni >= 0) {
2344
        $out[] = $uni;
2345
    }
2346
    }
2347
    return $out;
2348
}
2349
2350
2351
// End of class
2352
}
2353
2354
// Handle special IE contype request
2355
if (isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'contype')
2356
{
2357
    header('Content-Type: application/pdf');
2358
    exit;
2359
}