Passed
Push — master ( 5c87ed...e4bb53 )
by Stefan
04:05
created

UIElements::boxWarning()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 2
c 0
b 0
f 0
rs 10
cc 1
eloc 1
nc 1
nop 3
1
<?php
2
3
/*
4
 * ******************************************************************************
5
 * Copyright 2011-2017 DANTE Ltd. and GÉANT on behalf of the GN3, GN3+, GN4-1 
6
 * and GN4-2 consortia
7
 *
8
 * License: see the web/copyright.php file in the file structure
9
 * ******************************************************************************
10
 */
11
12
namespace web\lib\admin;
13
use Exception;
14
15
/**
16
 * This class provides various HTML snippets and other UI-related convenience functions.
17
 * 
18
 * @author Stefan Winter <[email protected]>
19
 */
20
class UIElements {
21
22
    /**
23
     * the custom displayable variant of the term 'federation'
24
     * 
25
     * @var string
26
     */
27
    public $nomenclature_fed;
28
29
    /**
30
     * the custom displayable variant of the term 'institution'
31
     * 
32
     * @var string
33
     */
34
    public $nomenclature_inst;
35
36
    /**
37
     * Initialises the class.
38
     * 
39
     * Mainly fetches various nomenclature from the config and attempts to translate those into local language. Needs pre-loading some terms.
40
     */
41
    public function __construct() {
42
        // some config elements are displayable. We need some dummies to 
43
        // translate the common values for them. If a deployment chooses a 
44
        // different wording, no translation, sorry
45
46
        $dummy_NRO = _("National Roaming Operator");
47
        $dummy_inst1 = _("identity provider");
48
        $dummy_inst2 = _("organisation");
49
        // and do something useless with the strings so that there's no "unused" complaint
50
        if ( $dummy_NRO . $dummy_inst1 . $dummy_inst2 == "") {
51
            // Oh well.
52
            explode(' ',$dummy_NRO);
53
        }
54
        $this->nomenclature_fed = _(CONFIG_CONFASSISTANT['CONSORTIUM']['nomenclature_federation']);
0 ignored issues
show
Bug introduced by
The constant web\lib\admin\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
55
        $this->nomenclature_inst = _(CONFIG_CONFASSISTANT['CONSORTIUM']['nomenclature_institution']);
56
    }
57
58
    /**
59
     * provides human-readable text for the various option names as stored in DB.
60
     * 
61
     * @param string $input raw text in need of a human-readable display variant
62
     * @return string the human-readable variant
63
     * @throws Exception
64
     */
65
    public function displayName($input) {
66
67
        $ssidText = _("SSID");
68
        $ssidLegacyText = _("SSID (with WPA/TKIP)");
69
        $passpointOiText = _("HS20 Consortium OI");
70
71
        if (count(CONFIG_CONFASSISTANT['CONSORTIUM']['ssid']) > 0) {
0 ignored issues
show
Bug introduced by
The constant web\lib\admin\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
72
            $ssidText = _("Additional SSID");
73
            $ssidLegacyText = _("Additional SSID (with WPA/TKIP)");
74
        }
75
        if (!empty(CONFIG_CONFASSISTANT['CONSORTIUM']['interworking-consortium-oi']) && count(CONFIG_CONFASSISTANT['CONSORTIUM']['interworking-consortium-oi']) > 0) {
76
            $passpointOiText = _("Additional HS20 Consortium OI");
77
        }
78
79
        $displayNames = [_("Support: Web") => "support:url",
80
            _("Support: EAP Types") => "support:eap_types",
81
            _("Support: Phone") => "support:phone",
82
            _("Support: E-Mail") => "support:email",
83
            sprintf(_("Name of %s"), $this->nomenclature_inst) => "general:instname",
84
            _("Location") => "general:geo_coordinates",
85
            _("Logo URL") => "general:logo_url",
86
            _("Logo image") => "general:logo_file",
87
            _("Configure Wired Ethernet") => "media:wired",
88
            _("Name (CN) of Authentication Server") => "eap:server_name",
89
            _("Enable device assessment") => "eap:enable_nea",
90
            _("Terms of Use") => "support:info_file",
91
            _("CA Certificate URL") => "eap:ca_url",
92
            _("CA Certificate File") => "eap:ca_file",
93
            _("Profile Display Name") => "profile:name",
94
            _("Production-Ready") => "profile:production",
95
            _("Admin Accepted Terms of Use") => 'hiddenprofile:tou_accepted',
96
            _("Extra text on downloadpage for device") => "device-specific:customtext",
97
            _("Redirection Target") => "device-specific:redirect",
98
            _("Extra text on downloadpage for EAP method") => "eap-specific:customtext",
99
            _("Turn on selection of EAP-TLS User-Name") => "eap-specific:tls_use_other_id",
100
            _("Profile Description") => "profile:description",
101
            _("Custom Installer Name Suffix") => "profile:customsuffix",
102
            sprintf(_("%s Administrator"), $this->nomenclature_fed) => "user:fedadmin",
103
            _("Real Name") => "user:realname",
104
            _("E-Mail Address") => "user:email",
105
            _("Remove/Disable SSID") => "media:remove_SSID",
106
            _("Custom CSS file for User Area") => "fed:css_file",
107
            sprintf(_("%s Logo"), $this->nomenclature_fed) => "fed:logo_file",
108
            _("Preferred Skin for User Area") => "fed:desired_skin",
109
            _("Include NRO branding in installers") => "fed:include_logo_installers",
110
            sprintf(_("%s Name"), $this->nomenclature_fed) => "fed:realname",
111
            _("Custom text in IdP Invitations") => "fed:custominvite",
112
            sprintf(_("Enable %s"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet",
113
            sprintf(_("%s: Do not terminate EAP"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet-noterm",
114
            sprintf(_("%s: max users per profile"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet-maxusers",
115
            $ssidText => "media:SSID",
116
            $ssidLegacyText => "media:SSID_with_legacy",
117
            $passpointOiText => "media:consortium_OI",
118
        ];
119
120
        $find = array_keys($displayNames, $input, TRUE);
121
122
        if (count($find) == 0) { // this is an error! throw an Exception
123
            throw new \Exception("The translation of an option name was requested, but the option is not known to the system: " . htmlentities($input));
124
        }
125
        return $find[0];
126
    }
127
128
    public function tooltip($input) {
129
        $descriptions = [];
130
        if (count(CONFIG_CONFASSISTANT['CONSORTIUM']['ssid']) > 0) {
0 ignored issues
show
Bug introduced by
The constant web\lib\admin\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
131
            $descriptions[sprintf(_("This attribute can be set if you want to configure an additional SSID besides the default SSIDs for %s. It is almost always a bad idea not to use the default SSIDs. The only exception is if you have premises with an overlap of the radio signal with another %s hotspot. Typical misconceptions about additional SSIDs include: I want to have a local SSID for my own users. It is much better to use the default SSID and separate user groups with VLANs. That approach has two advantages: 1) your users will configure %s properly because it is their everyday SSID; 2) if you use a custom name and advertise this one as extra secure, your users might at some point roam to another place which happens to have the same SSID name. They might then be misled to believe that they are connecting to an extra secure network while they are not."), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'], CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'], CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'])] = "media:SSID";
132
        }
133
134
        $find = array_search($input, $descriptions);
135
136
        if ($find === FALSE) {
137
            return "";
138
        }
139
        return "<span class='tooltip' onclick='alert(\"" . $find . "\")'><img src='../resources/images/icons/question-mark-icon.png" . "'></span>";
140
    }
141
142
    /**
143
     * creates an HTML information block with a list of options from a given category and level
144
     * @param array $optionlist list of options
145
     * @param string $class option class of interest
146
     * @param string $level option level of interest
147
     * @return string HTML code
148
     */
149
    public function infoblock(array $optionlist, string $class, string $level) {
150
        $googleMarkers = [];
151
        $retval = "";
152
        $optioninfo = \core\Options::instance();
153
154
        foreach ($optionlist as $option) {
155
            $type = $optioninfo->optionType($option['name']);
156
            if (preg_match('/^' . $class . '/', $option['name']) && $option['level'] == "$level") {
157
                // all non-multilang attribs get this assignment ...
158
                $language = "";
159
                $content = $option['value'];
160
                // ... override them with multilang tags if needed
161
                if ($type["flag"] == "ML") {
162
                    $language = _("default/other languages");
163
                    if ($option['lang'] != 'C') {
164
                        $language = CONFIG['LANGUAGES'][$option['lang']]['display'] ?? "(unsupported language)";
0 ignored issues
show
Bug introduced by
The constant web\lib\admin\CONFIG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
165
                    }
166
                }
167
168
                switch ($type["type"]) {
169
                    case "coordinates":
170
                        $coords = json_decode($option['value'], true);
171
                        $googleMarkers[] = $coords;
172
                        break;
173
                    case "file":
174
                        $retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td>";
175
                        switch ($option['name']) {
176
                            case "general:logo_file":
177
                            case "fed:logo_file":
178
                                $retval .= $this->previewImageinHTML('ROWID-' . $option['level'] . '-' . $option['row']);
179
                                break;
180
                            case "eap:ca_file":
181
                                $retval .= $this->previewCAinHTML('ROWID-' . $option['level'] . '-' . $option['row']);
182
                                break;
183
                            case "support:info_file":
184
                                $retval .= $this->previewInfoFileinHTML('ROWID-' . $option['level'] . '-' . $option['row']);
185
                                break;
186
                            default:
187
                        }
188
                        break;
189
                    case "boolean":
190
                        $retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td><strong>" . ($content == "on" ? _("on") : _("off") ) . "</strong></td></tr>";
191
                        break;
192
                    default:
193
                        $retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td><strong>$content</strong></td></tr>";
194
                }
195
            }
196
        }
197
        if (count($googleMarkers)) {
198
            $marker = '<markers>';
199
            $locationCount = 0;
200
            foreach ($googleMarkers as $g) {
201
                $locationCount++;
202
                $marker .= '<marker name="' . $locationCount . '" lat="' . $g['lat'] . '" lng="' . $g['lon'] . '" />';
203
            }
204
            $marker .= '</markers>';
205
            $retval .= '<tr><td><script>markers=\'' . $marker . '\';</script></td><td></td><td></td></tr>';
206
        }
207
        return $retval;
208
    }
209
210
    /**
211
     * creates HTML code to display all information boxes for an IdP
212
     * 
213
     * @param \core\IdP $myInst the IdP in question
214
     * @return string HTML code
215
     */
216
    public function instLevelInfoBoxes(\core\IdP $myInst) {
217
        $idpoptions = $myInst->getAttributes();
218
        $retval = "<div class='infobox'>
219
        <h2>" . sprintf(_("General %s details"), $this->nomenclature_inst) . "</h2>
220
        <table>
221
            <tr>
222
                <td>
223
                    " . _("Country:") . "
224
                </td>
225
                <td>
226
                </td>
227
                <td>
228
                    <strong>";
229
        $myFed = new \core\Federation($myInst->federation);
230
        $retval .= $myFed->name;
231
        $retval .= "</strong>
232
                </td>
233
            </tr>" . $this->infoblock($idpoptions, "general", "IdP") . "
234
        </table>
235
    </div>";
236
237
        $blocks = [["support", _("Global Helpdesk Details")], ["media", _("Media Properties")]];
238
        foreach ($blocks as $block) {
239
            $retval .= "<div class='infobox'>
240
            <h2>" . $block[1] . "</h2>
241
            <table>" .
242
                    $this->infoblock($idpoptions, $block[0], "IdP") .
243
                    "</table>
244
        </div>";
245
        }
246
        return $retval;
247
    }
248
249
    /**
250
     * pretty-prints a file size number in SI "bi" units
251
     * @param int $number the size of the file
252
     * @return string the pretty-print representation of the file size
253
     */
254
    private function displaySize(int $number) {
255
        if ($number > 1024 * 1024) {
256
            return round($number / 1024 / 1024, 2) . " MiB";
257
        }
258
        if ($number > 1024) {
259
            return round($number / 1024, 2) . " KiB";
260
        }
261
        return $number . " B";
262
    }
263
264
    /**
265
     * 
266
     * @param string $ref the database reference string
267
     * @param boolean $checkpublic should we check if the requested piece of data is public?
268
     * @return string|FALSE the requested data, or FALSE if something went wrong
269
     */
270
    public static function getBlobFromDB($ref, $checkpublic) {
271
        $validator = new \web\lib\common\InputValidation();
272
        $reference = $validator->databaseReference($ref);
273
274
        if ($reference == FALSE) {
275
            return FALSE;
276
        }
277
278
        // the data is either public (just give it away) or not; in this case, only
279
        // release if the data belongs to admin himself
280
        if ($checkpublic) {
281
            // we might be called without session context (filepreview) so get the
282
            // context if needed
283
            if (session_status() != PHP_SESSION_ACTIVE) {
284
                session_start();
285
            }
286
            $owners = \core\EntityWithDBProperties::isDataRestricted($reference["table"], $reference["rowindex"]);
287
288
            $ownersCondensed = [];
289
290
            if ($owners !== FALSE) { // restricted datam see if we're authenticated and owners of the data
291
                $auth = new \web\lib\admin\Authentication();
292
                if (!$auth->isAuthenticated()) {
293
                    return FALSE; // admin-only, but we are not an admin
294
                }
295
                foreach ($owners as $oneowner) {
296
                    $ownersCondensed[] = $oneowner['ID'];
297
                }
298
                if (array_search($_SESSION['user'], $ownersCondensed) === FALSE) {
299
                    return FALSE; // wrong guy
300
                }
301
                // carry on and get the data
302
            }
303
        }
304
305
        $blob = \core\EntityWithDBProperties::fetchRawDataByIndex($reference["table"], $reference["rowindex"]);
306
        return $blob; // this means we might return FALSE here if something was wrong with the original requested reference
307
    }
308
309
    /**
310
     * 
311
     * @param string $reference a reference pointer to a database entry
312
     * @throws Exception
313
     */
314
    
315
    private function checkROWIDpresence($reference) {
316
        $found = preg_match("/^ROWID-.*/", $reference);
317
        if ($found  != 1) { // get excited on not-found AND on execution error
318
            throw new Exception("Error, ROWID expected.");
319
        }
320
    }
321
    
322
    /**
323
     * creates HTML code to display a nice UI representation of a CA
324
     * 
325
     * @param string $cAReference ROWID pointer to the CA to display
326
     * @return string HTML code
327
     */
328
    public function previewCAinHTML($cAReference) {
329
        $this->checkROWIDpresence($cAReference);
330
        $cAblob = base64_decode(UIElements::getBlobFromDB($cAReference, FALSE));
0 ignored issues
show
Bug introduced by
web\lib\admin\UIElements...DB($cAReference, FALSE) of type false is incompatible with the type string expected by parameter $data of base64_decode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

330
        $cAblob = base64_decode(/** @scrutinizer ignore-type */ UIElements::getBlobFromDB($cAReference, FALSE));
Loading history...
331
332
        $func = new \core\common\X509;
333
        $details = $func->processCertificate($cAblob);
334
        if ($details === FALSE) {
335
            return _("There was an error processing the certificate!");
336
        }
337
338
        $details['name'] = preg_replace('/(.)\/(.)/', "$1<br/>$2", $details['name']);
339
        $details['name'] = preg_replace('/\//', "", $details['name']);
340
        $certstatus = ( $details['root'] == 1 ? "R" : "I");
341
        if ($details['ca'] == 0 && $details['root'] != 1) {
342
            return "<div class='ca-summary' style='background-color:red'><div style='position:absolute; right: 0px; width:20px; height:20px; background-color:maroon;  border-radius:10px; text-align: center;'><div style='padding-top:3px; font-weight:bold; color:#ffffff;'>S</div></div>" . _("This is a <strong>SERVER</strong> certificate!") . "<br/>" . $details['name'] . "</div>";
343
        }
344
        return "<div class='ca-summary'                                ><div style='position:absolute; right: 0px; width:20px; height:20px; background-color:#0000ff; border-radius:10px; text-align: center;'><div style='padding-top:3px; font-weight:bold; color:#ffffff;'>$certstatus</div></div>" . $details['name'] . "</div>";
345
    }
346
347
    /**
348
     * creates HTML code to display a nice UI representation of an image
349
     * 
350
     * @param string $imageReference ROWID pointer to the image to display
351
     * @return string HTML code
352
     */
353
    public function previewImageinHTML($imageReference) {
354
        $this->checkROWIDpresence($imageReference);
355
        return "<img style='max-width:150px' src='inc/filepreview.php?id=" . $imageReference . "' alt='" . _("Preview of logo file") . "'/>";
356
    }
357
358
    /**
359
     * creates HTML code to display a nice UI representation of a TermsOfUse file
360
     * 
361
     * @param string $fileReference ROWID pointer to the file to display
362
     * @return string HTML code
363
     */
364
    public function previewInfoFileinHTML($fileReference) {
365
        $this->checkROWIDpresence($fileReference);
366
        $fileBlob = UIElements::getBlobFromDB($fileReference, FALSE);
367
        $decodedFileBlob = base64_decode($fileBlob);
0 ignored issues
show
Bug introduced by
$fileBlob of type false is incompatible with the type string expected by parameter $data of base64_decode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

367
        $decodedFileBlob = base64_decode(/** @scrutinizer ignore-type */ $fileBlob);
Loading history...
368
        $fileinfo = new \finfo();
0 ignored issues
show
Bug introduced by
The call to finfo::finfo() has too few arguments starting with options. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

368
        $fileinfo = /** @scrutinizer ignore-call */ new \finfo();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
369
        return "<div class='ca-summary'>" . _("File exists") . " (" . $fileinfo->buffer($decodedFileBlob, FILEINFO_MIME_TYPE) . ", " . $this->displaySize(strlen($decodedFileBlob)) . ")<br/><a href='inc/filepreview.php?id=$fileReference'>" . _("Preview") . "</a></div>";
370
    }
371
372
    /**
373
     * creates HTML code for a UI element which informs the user about something.
374
     * 
375
     * @param int $level what kind of information is to be displayed?
376
     * @param string $text the text to display
377
     * @param string $caption the caption to display
378
     * @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them
379
     * @return string
380
     */
381
    public function boxFlexible(int $level, string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) {
382
383
        $uiMessages = [
384
            \core\common\Entity::L_OK => ['icon' => '../resources/images/icons/Quetto/check-icon.png', 'text' => _("OK")],
385
            \core\common\Entity::L_REMARK => ['icon' => '../resources/images/icons/Quetto/info-icon.png', 'text' => _("Remark")],
386
            \core\common\Entity::L_WARN => ['icon' => '../resources/images/icons/Quetto/danger-icon.png', 'text' => _("Warning!")],
387
            \core\common\Entity::L_ERROR => ['icon' => '../resources/images/icons/Quetto/no-icon.png', 'text' => _("Error!")],
388
        ];
389
390
        $retval = "";
391
        if (!$omittabletags) {
392
            $retval .= "<tr><td>";
393
        }
394
        $finalCaption = ($caption !== NULL ? $caption : $uiMessages[$level]['text']);
395
        $retval .= "<img class='icon' src='" . $uiMessages[$level]['icon'] . "' alt='" . $finalCaption . "' title='" . $finalCaption . "'/>";
396
        if (!$omittabletags) {
397
            $retval .= "</td><td>";
398
        }
399
        if ($text !== NULL) {
400
            $retval .= $text;
401
        }
402
        if (!$omittabletags) {
403
            $retval .= "</td></tr>";
404
        }
405
        return $retval;
406
    }
407
408
    /**
409
     * creates HTML code to display an "all is okay" message
410
     * 
411
     * @param string $text the text to display
412
     * @param string $caption the caption to display
413
     * @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them
414
     * @return string HTML: the box
415
     */
416
    public function boxOkay(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) {
417
        return $this->boxFlexible(\core\common\Entity::L_OK, $text, $caption, $omittabletags);
418
    }
419
420
    /**
421
     * creates HTML code to display a "smartass comment" message
422
     * 
423
     * @param string $text the text to display
424
     * @param string $caption the caption to display
425
     * @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them
426
     * @return string HTML: the box
427
     */
428
    public function boxRemark(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) {
429
        return $this->boxFlexible(\core\common\Entity::L_REMARK, $text, $caption, $omittabletags);
430
    }
431
432
    /**
433
     * creates HTML code to display a "something's a bit wrong" message
434
     * 
435
     * @param string $text the text to display
436
     * @param string $caption the caption to display
437
     * @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them
438
     * @return string HTML: the box
439
     */
440
    public function boxWarning(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) {
441
        return $this->boxFlexible(\core\common\Entity::L_WARN, $text, $caption, $omittabletags);
442
    }
443
444
    /**
445
     * creates HTML code to display a "Whoa! Danger, Will Robinson!" message
446
     * 
447
     * @param string $text the text to display
448
     * @param string $caption the caption to display
449
     * @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them
450
     * @return string HTML: the box
451
     */
452
    public function boxError(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) {
453
        return $this->boxFlexible(\core\common\Entity::L_ERROR, $text, $caption, $omittabletags);
454
    }
455
456
    /**
457
     * Injects the consortium logo in the middle of a given PNG.
458
     * 
459
     * Usually used on QR code PNGs - the parameters inform about the structure of
460
     * the QR code so that the logo does not prevent parsing of the QR code.
461
     * 
462
     * @param string $inputpngstring the PNG to edit
463
     * @param int $symbolsize size in pixels of one QR "pixel"
464
     * @param int $marginsymbols size in pixels of border around the actual QR
465
     * @return string the image with logo centered in the middle
466
     */
467
    public function pngInjectConsortiumLogo(string $inputpngstring, int $symbolsize, int $marginsymbols = 4) {
468
        $loggerInstance = new \core\common\Logging();
469
        $inputgd = imagecreatefromstring($inputpngstring);
470
471
        $loggerInstance->debug(4, "Consortium logo is at: " . ROOT . "/web/resources/images/consortium_logo_large.png");
472
        $logogd = imagecreatefrompng(ROOT . "/web/resources/images/consortium_logo_large.png");
473
474
        $sizeinput = [imagesx($inputgd), imagesy($inputgd)];
475
        $sizelogo = [imagesx($logogd), imagesy($logogd)];
476
        // Q level QR-codes can sustain 25% "damage"
477
        // make our logo cover approx 15% of area to be sure; mind that there's a $symbolsize * $marginsymbols pixel white border around each edge
478
        $totalpixels = ($sizeinput[0] - $symbolsize * $marginsymbols) * ($sizeinput[1] - $symbolsize * $marginsymbols);
479
        $totallogopixels = ($sizelogo[0]) * ($sizelogo[1]);
480
        $maxoccupy = $totalpixels * 0.04;
481
        // find out how much we have to scale down logo to reach 10% QR estate
482
        $scale = sqrt($maxoccupy / $totallogopixels);
483
        $loggerInstance->debug(4, "Scaling info: $scale, $maxoccupy, $totallogopixels\n");
484
        // determine final pixel size - round to multitude of $symbolsize to match exact symbol boundary
485
        $targetwidth = $symbolsize * round($sizelogo[0] * $scale / $symbolsize);
486
        $targetheight = $symbolsize * round($sizelogo[1] * $scale / $symbolsize);
487
        // paint white below the logo, in case it has transparencies (looks bad)
488
        // have one symbol in each direction extra white space
489
        $whiteimage = imagecreate($targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
0 ignored issues
show
Bug introduced by
$targetheight + 2 * $symbolsize of type double is incompatible with the type integer expected by parameter $height of imagecreate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

489
        $whiteimage = imagecreate($targetwidth + 2 * $symbolsize, /** @scrutinizer ignore-type */ $targetheight + 2 * $symbolsize);
Loading history...
Bug introduced by
$targetwidth + 2 * $symbolsize of type double is incompatible with the type integer expected by parameter $width of imagecreate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

489
        $whiteimage = imagecreate(/** @scrutinizer ignore-type */ $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
Loading history...
490
        imagecolorallocate($whiteimage, 255, 255, 255);
491
        // also make sure the initial placement is a multitude of 12; otherwise "two half" symbols might be affected
492
        $targetplacementx = $symbolsize * round(($sizeinput[0] / 2 - ($targetwidth - $symbolsize) / 2) / $symbolsize);
493
        $targetplacementy = $symbolsize * round(($sizeinput[1] / 2 - ($targetheight - $symbolsize) / 2) / $symbolsize);
494
        imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
0 ignored issues
show
Bug introduced by
$targetheight + 2 * $symbolsize of type double is incompatible with the type integer expected by parameter $src_h of imagecopyresized(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

494
        imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, /** @scrutinizer ignore-type */ $targetheight + 2 * $symbolsize);
Loading history...
Bug introduced by
$targetheight + 2 * $symbolsize of type double is incompatible with the type integer expected by parameter $dst_h of imagecopyresized(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

494
        imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, /** @scrutinizer ignore-type */ $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
Loading history...
Bug introduced by
$targetwidth + 2 * $symbolsize of type double is incompatible with the type integer expected by parameter $dst_w of imagecopyresized(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

494
        imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, /** @scrutinizer ignore-type */ $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
Loading history...
Bug introduced by
$targetplacementy - $symbolsize of type double is incompatible with the type integer expected by parameter $dst_y of imagecopyresized(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

494
        imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, /** @scrutinizer ignore-type */ $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
Loading history...
Bug introduced by
$targetwidth + 2 * $symbolsize of type double is incompatible with the type integer expected by parameter $src_w of imagecopyresized(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

494
        imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, /** @scrutinizer ignore-type */ $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
Loading history...
Bug introduced by
$targetplacementx - $symbolsize of type double is incompatible with the type integer expected by parameter $dst_x of imagecopyresized(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

494
        imagecopyresized($inputgd, $whiteimage, /** @scrutinizer ignore-type */ $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize);
Loading history...
495
        imagecopyresized($inputgd, $logogd, $targetplacementx, $targetplacementy, 0, 0, $targetwidth, $targetheight, $sizelogo[0], $sizelogo[1]);
496
        ob_start();
497
        imagepng($inputgd);
498
        return ob_get_clean();
499
    }
500
501
}
502