|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* ***************************************************************************** |
|
5
|
|
|
* Contributions to this work were made on behalf of the GÉANT project, a |
|
6
|
|
|
* project that has received funding from the European Union’s Framework |
|
7
|
|
|
* Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus), |
|
8
|
|
|
* Horizon 2020 research and innovation programme under Grant Agreements No. |
|
9
|
|
|
* 691567 (GN4-1) and No. 731122 (GN4-2). |
|
10
|
|
|
* On behalf of the aforementioned projects, GEANT Association is the sole owner |
|
11
|
|
|
* of the copyright in all material which was developed by a member of the GÉANT |
|
12
|
|
|
* project. GÉANT Vereniging (Association) is registered with the Chamber of |
|
13
|
|
|
* Commerce in Amsterdam with registration number 40535155 and operates in the |
|
14
|
|
|
* UK as a branch of GÉANT Vereniging. |
|
15
|
|
|
* |
|
16
|
|
|
* Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. |
|
17
|
|
|
* UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK |
|
18
|
|
|
* |
|
19
|
|
|
* License: see the web/copyright.inc.php file in the file structure or |
|
20
|
|
|
* <base_url>/copyright.php after deploying the software |
|
21
|
|
|
*/ |
|
22
|
|
|
|
|
23
|
|
|
namespace web\lib\admin; |
|
24
|
|
|
|
|
25
|
|
|
use Exception; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* This class provides various HTML snippets and other UI-related convenience functions. |
|
29
|
|
|
* |
|
30
|
|
|
* @author Stefan Winter <[email protected]> |
|
31
|
|
|
*/ |
|
32
|
|
|
class UIElements { |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* the custom displayable variant of the term 'federation' |
|
36
|
|
|
* |
|
37
|
|
|
* @var string |
|
38
|
|
|
*/ |
|
39
|
|
|
public $nomenclature_fed; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* the custom displayable variant of the term 'institution' |
|
43
|
|
|
* |
|
44
|
|
|
* @var string |
|
45
|
|
|
*/ |
|
46
|
|
|
public $nomenclature_inst; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* Initialises the class. |
|
50
|
|
|
* |
|
51
|
|
|
* Mainly fetches various nomenclature from the config and attempts to translate those into local language. Needs pre-loading some terms. |
|
52
|
|
|
*/ |
|
53
|
|
|
public function __construct() { |
|
54
|
|
|
// pick up the nomenclature translations from core - no need to repeat |
|
55
|
|
|
// them here in this catalogue |
|
56
|
|
|
|
|
57
|
|
|
new \core\CAT(); // initialises Entity static members, in correct langauge |
|
58
|
|
|
$this->nomenclature_fed = \core\common\Entity::$nomenclature_fed; |
|
59
|
|
|
$this->nomenclature_inst = \core\common\Entity::$nomenclature_inst; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* provides human-readable text for the various option names as stored in DB. |
|
64
|
|
|
* |
|
65
|
|
|
* @param string $input raw text in need of a human-readable display variant |
|
66
|
|
|
* @return string the human-readable variant |
|
67
|
|
|
* @throws Exception |
|
68
|
|
|
*/ |
|
69
|
|
|
public function displayName($input) { |
|
70
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
71
|
|
|
$ssidText = _("SSID"); |
|
72
|
|
|
$ssidLegacyText = _("SSID (with WPA/TKIP)"); |
|
73
|
|
|
$passpointOiText = _("HS20 Consortium OI"); |
|
74
|
|
|
|
|
75
|
|
|
if (count(CONFIG_CONFASSISTANT['CONSORTIUM']['ssid']) > 0) { |
|
76
|
|
|
$ssidText = _("Additional SSID"); |
|
77
|
|
|
$ssidLegacyText = _("Additional SSID (with WPA/TKIP)"); |
|
78
|
|
|
} |
|
79
|
|
|
if (!empty(CONFIG_CONFASSISTANT['CONSORTIUM']['interworking-consortium-oi']) && count(CONFIG_CONFASSISTANT['CONSORTIUM']['interworking-consortium-oi']) > 0) { |
|
80
|
|
|
$passpointOiText = _("Additional HS20 Consortium OI"); |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
$displayNames = [_("Support: Web") => "support:url", |
|
84
|
|
|
_("Support: EAP Types") => "support:eap_types", |
|
85
|
|
|
_("Support: Phone") => "support:phone", |
|
86
|
|
|
_("Support: E-Mail") => "support:email", |
|
87
|
|
|
sprintf(_("%s Name"), $this->nomenclature_inst) => "general:instname", |
|
88
|
|
|
_("Location") => "general:geo_coordinates", |
|
89
|
|
|
_("Logo URL") => "general:logo_url", |
|
90
|
|
|
_("Logo image") => "general:logo_file", |
|
91
|
|
|
_("Configure Wired Ethernet") => "media:wired", |
|
92
|
|
|
_("Name (CN) of Authentication Server") => "eap:server_name", |
|
93
|
|
|
_("Enable device assessment") => "eap:enable_nea", |
|
94
|
|
|
_("Terms of Use") => "support:info_file", |
|
95
|
|
|
_("CA Certificate URL") => "eap:ca_url", |
|
96
|
|
|
_("CA Certificate File") => "eap:ca_file", |
|
97
|
|
|
_("Profile Display Name") => "profile:name", |
|
98
|
|
|
_("Production-Ready") => "profile:production", |
|
99
|
|
|
_("Admin Accepted Terms of Use") => 'hiddenprofile:tou_accepted', |
|
100
|
|
|
_("Extra text on downloadpage for device") => "device-specific:customtext", |
|
101
|
|
|
_("Redirection Target") => "device-specific:redirect", |
|
102
|
|
|
_("Extra text on downloadpage for EAP method") => "eap-specific:customtext", |
|
103
|
|
|
_("Turn on selection of EAP-TLS User-Name") => "eap-specific:tls_use_other_id", |
|
104
|
|
|
_("Use GEANTlink TTLS supplicant for W8") => "device-specific:geantlink", |
|
105
|
|
|
_("Use builtin TTLS supplicant for Windows 10") => "device-specific:builtin_ttls", |
|
106
|
|
|
_("Profile Description") => "profile:description", |
|
107
|
|
|
_("Custom Installer Name Suffix") => "profile:customsuffix", |
|
108
|
|
|
sprintf(_("%s Administrator"), $this->nomenclature_fed) => "user:fedadmin", |
|
109
|
|
|
_("Real Name") => "user:realname", |
|
110
|
|
|
_("E-Mail Address") => "user:email", |
|
111
|
|
|
_("Remove/Disable SSID") => "media:remove_SSID", |
|
112
|
|
|
_("Mandatory Content Filtering Proxy") => "media:force_proxy", |
|
113
|
|
|
_("Custom CSS file for User Area") => "fed:css_file", |
|
114
|
|
|
sprintf(_("%s Logo"), $this->nomenclature_fed) => "fed:logo_file", |
|
115
|
|
|
_("Preferred Skin for User Area") => "fed:desired_skin", |
|
116
|
|
|
sprintf(_("Include %s branding in installers"), $this->nomenclature_fed) => "fed:include_logo_installers", |
|
117
|
|
|
sprintf(_("%s Name"), $this->nomenclature_fed) => "fed:realname", |
|
118
|
|
|
sprintf(_("%s Homepage"), $this->nomenclature_fed) => "fed:url", |
|
119
|
|
|
sprintf(_("Custom text in %s Invitations"), $this->nomenclature_inst) => "fed:custominvite", |
|
120
|
|
|
sprintf(_("Enable %s"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet", |
|
121
|
|
|
sprintf(_("%s: Do not terminate EAP"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet-noterm", |
|
122
|
|
|
sprintf(_("%s: max users per profile"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet-maxusers", |
|
123
|
|
|
sprintf(_("Mint %s with CA on creation"), $this->nomenclature_inst) => "fed:minted_ca_file", |
|
124
|
|
|
$ssidText => "media:SSID", |
|
125
|
|
|
$ssidLegacyText => "media:SSID_with_legacy", |
|
126
|
|
|
$passpointOiText => "media:consortium_OI", |
|
127
|
|
|
]; |
|
128
|
|
|
|
|
129
|
|
|
$find = array_keys($displayNames, $input, TRUE); |
|
130
|
|
|
|
|
131
|
|
|
if (count($find) == 0) { // this is an error! throw an Exception |
|
132
|
|
|
throw new \Exception("The translation of an option name was requested, but the option is not known to the system: " . htmlentities($input)); |
|
133
|
|
|
} |
|
134
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
135
|
|
|
return $find[0]; |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
/** |
|
139
|
|
|
* creates an HTML information block with a list of options from a given category and level |
|
140
|
|
|
* @param array $optionlist list of options |
|
141
|
|
|
* @param string $class option class of interest |
|
142
|
|
|
* @param string $level option level of interest |
|
143
|
|
|
* @return string HTML code |
|
144
|
|
|
*/ |
|
145
|
|
|
public function infoblock(array $optionlist, string $class, string $level) { |
|
146
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
147
|
|
|
$locationMarkers = []; |
|
148
|
|
|
$retval = ""; |
|
149
|
|
|
$optioninfo = \core\Options::instance(); |
|
150
|
|
|
|
|
151
|
|
|
foreach ($optionlist as $option) { |
|
152
|
|
|
$type = $optioninfo->optionType($option['name']); |
|
153
|
|
|
if (preg_match('/^' . $class . '/', $option['name']) && $option['level'] == "$level") { |
|
154
|
|
|
// all non-multilang attribs get this assignment ... |
|
155
|
|
|
$language = ""; |
|
156
|
|
|
$content = $option['value']; |
|
157
|
|
|
// ... override them with multilang tags if needed |
|
158
|
|
|
if ($type["flag"] == "ML") { |
|
159
|
|
|
$language = _("default/other languages"); |
|
160
|
|
|
if ($option['lang'] != 'C') { |
|
161
|
|
|
$language = CONFIG['LANGUAGES'][$option['lang']]['display'] ?? "(unsupported language)"; |
|
162
|
|
|
} |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
switch ($type["type"]) { |
|
166
|
|
|
case "coordinates": |
|
167
|
|
|
$coords = json_decode($option['value'], true); |
|
168
|
|
|
$locationMarkers[] = $coords; |
|
169
|
|
|
break; |
|
170
|
|
|
case "file": |
|
171
|
|
|
$retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td>"; |
|
172
|
|
|
switch ($option['name']) { |
|
173
|
|
|
case "general:logo_file": |
|
174
|
|
|
case "fed:logo_file": |
|
175
|
|
|
$retval .= $this->previewImageinHTML('ROWID-' . $option['level'] . '-' . $option['row']); |
|
176
|
|
|
break; |
|
177
|
|
|
case "eap:ca_file": |
|
178
|
|
|
// fall-through intended: display both the same way |
|
179
|
|
|
case "fed:minted_ca_file": |
|
180
|
|
|
$retval .= $this->previewCAinHTML('ROWID-' . $option['level'] . '-' . $option['row']); |
|
181
|
|
|
break; |
|
182
|
|
|
case "support:info_file": |
|
183
|
|
|
$retval .= $this->previewInfoFileinHTML('ROWID-' . $option['level'] . '-' . $option['row']); |
|
184
|
|
|
break; |
|
185
|
|
|
default: |
|
186
|
|
|
} |
|
187
|
|
|
break; |
|
188
|
|
|
case "boolean": |
|
189
|
|
|
if ($option['name'] == "fed:silverbullet" && CONFIG['FUNCTIONALITY_LOCATIONS']['CONFASSISTANT_SILVERBULLET'] == "LOCAL" && CONFIG['FUNCTIONALITY_LOCATIONS']['CONFASSISTANT_RADIUS'] != "LOCAL") { |
|
190
|
|
|
// do not display the option at all; it gets auto-set by the ProfileSilverbullet constructor and doesn't have to be seen |
|
191
|
|
|
break; |
|
192
|
|
|
} |
|
193
|
|
|
$retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td><strong>" . ($content == "on" ? _("on") : _("off") ) . "</strong></td></tr>"; |
|
194
|
|
|
break; |
|
195
|
|
|
default: |
|
196
|
|
|
$retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td><strong>$content</strong></td></tr>"; |
|
197
|
|
|
} |
|
198
|
|
|
} |
|
199
|
|
|
} |
|
200
|
|
|
if (count($locationMarkers)) { |
|
201
|
|
|
$marker = '<markers>'; |
|
202
|
|
|
$locationCount = 0; |
|
203
|
|
|
foreach ($locationMarkers as $g) { |
|
204
|
|
|
$locationCount++; |
|
205
|
|
|
$marker .= '<marker name="' . $locationCount . '" lat="' . $g['lat'] . '" lng="' . $g['lon'] . '" />'; |
|
206
|
|
|
} |
|
207
|
|
|
$marker .= '<\/markers>'; // some validator says this should be escaped |
|
208
|
|
|
$jMarker = json_encode($locationMarkers); |
|
209
|
|
|
$retval .= '<tr><td><script>markers=\'' . $marker . '\'; jmarkers = \'' . $jMarker . '\';</script></td><td></td><td></td></tr>'; |
|
210
|
|
|
} |
|
211
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
212
|
|
|
return $retval; |
|
213
|
|
|
} |
|
214
|
|
|
|
|
215
|
|
|
/** |
|
216
|
|
|
* creates HTML code to display all information boxes for an IdP |
|
217
|
|
|
* |
|
218
|
|
|
* @param \core\IdP $myInst the IdP in question |
|
219
|
|
|
* @return string HTML code |
|
220
|
|
|
*/ |
|
221
|
|
|
public function instLevelInfoBoxes(\core\IdP $myInst) { |
|
222
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
223
|
|
|
$idpoptions = $myInst->getAttributes(); |
|
224
|
|
|
$retval = "<div class='infobox'> |
|
225
|
|
|
<h2>" . sprintf(_("General %s details"), $this->nomenclature_inst) . "</h2> |
|
226
|
|
|
<table> |
|
227
|
|
|
<tr> |
|
228
|
|
|
<td> |
|
229
|
|
|
" . _("Country:") . " |
|
230
|
|
|
</td> |
|
231
|
|
|
<td> |
|
232
|
|
|
</td> |
|
233
|
|
|
<td> |
|
234
|
|
|
<strong>"; |
|
235
|
|
|
$myFed = new \core\Federation($myInst->federation); |
|
236
|
|
|
$retval .= $myFed->name; |
|
237
|
|
|
$retval .= "</strong> |
|
238
|
|
|
</td> |
|
239
|
|
|
</tr>" . $this->infoblock($idpoptions, "general", "IdP") . " |
|
240
|
|
|
</table> |
|
241
|
|
|
</div>"; |
|
242
|
|
|
|
|
243
|
|
|
$blocks = [["support", _("Global Helpdesk Details")], ["media", _("Media Properties")]]; |
|
244
|
|
|
foreach ($blocks as $block) { |
|
245
|
|
|
$retval .= "<div class='infobox'> |
|
246
|
|
|
<h2>" . $block[1] . "</h2> |
|
247
|
|
|
<table>" . |
|
248
|
|
|
$this->infoblock($idpoptions, $block[0], "IdP") . |
|
249
|
|
|
"</table> |
|
250
|
|
|
</div>"; |
|
251
|
|
|
} |
|
252
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
253
|
|
|
return $retval; |
|
254
|
|
|
} |
|
255
|
|
|
|
|
256
|
|
|
/** |
|
257
|
|
|
* pretty-prints a file size number in SI "bi" units |
|
258
|
|
|
* @param int $number the size of the file |
|
259
|
|
|
* @return string the pretty-print representation of the file size |
|
260
|
|
|
*/ |
|
261
|
|
|
private function displaySize(int $number) { |
|
262
|
|
|
if ($number > 1024 * 1024) { |
|
263
|
|
|
return round($number / 1024 / 1024, 2) . " MiB"; |
|
264
|
|
|
} |
|
265
|
|
|
if ($number > 1024) { |
|
266
|
|
|
return round($number / 1024, 2) . " KiB"; |
|
267
|
|
|
} |
|
268
|
|
|
return $number . " B"; |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
/** |
|
272
|
|
|
* |
|
273
|
|
|
* @param string $ref the database reference string |
|
274
|
|
|
* @param boolean $checkpublic should we check if the requested piece of data is public? |
|
275
|
|
|
* @return string|boolean the requested data, or FALSE if something went wrong |
|
276
|
|
|
*/ |
|
277
|
|
|
public static function getBlobFromDB($ref, $checkpublic) { |
|
278
|
|
|
$validator = new \web\lib\common\InputValidation(); |
|
279
|
|
|
$reference = $validator->databaseReference($ref); |
|
280
|
|
|
|
|
281
|
|
|
if ($reference === FALSE) { |
|
|
|
|
|
|
282
|
|
|
return FALSE; |
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
// the data is either public (just give it away) or not; in this case, only |
|
286
|
|
|
// release if the data belongs to admin himself |
|
287
|
|
|
if ($checkpublic) { |
|
288
|
|
|
|
|
289
|
|
|
$owners = \core\EntityWithDBProperties::isDataRestricted($reference["table"], $reference["rowindex"]); |
|
290
|
|
|
|
|
291
|
|
|
$ownersCondensed = []; |
|
292
|
|
|
|
|
293
|
|
|
if ($owners !== FALSE) { // restricted data, see if we're authenticated and owners of the data |
|
294
|
|
|
$auth = new \web\lib\admin\Authentication(); |
|
295
|
|
|
if (!$auth->isAuthenticated()) { |
|
296
|
|
|
return FALSE; // admin-only, but we are not an admin |
|
297
|
|
|
} |
|
298
|
|
|
// we might be called without session context (filepreview) so get the |
|
299
|
|
|
// context if needed |
|
300
|
|
|
CAT_session_start(); |
|
301
|
|
|
|
|
302
|
|
|
foreach ($owners as $oneowner) { |
|
303
|
|
|
$ownersCondensed[] = $oneowner['ID']; |
|
304
|
|
|
} |
|
305
|
|
|
if (array_search($_SESSION['user'], $ownersCondensed) === FALSE) { |
|
306
|
|
|
return FALSE; // wrong guy |
|
307
|
|
|
} |
|
308
|
|
|
// carry on and get the data |
|
309
|
|
|
} |
|
310
|
|
|
} |
|
311
|
|
|
|
|
312
|
|
|
$blob = \core\EntityWithDBProperties::fetchRawDataByIndex($reference["table"], $reference["rowindex"]); |
|
313
|
|
|
return $blob; // this means we might return FALSE here if something was wrong with the original requested reference |
|
314
|
|
|
} |
|
315
|
|
|
|
|
316
|
|
|
/** |
|
317
|
|
|
* |
|
318
|
|
|
* @param string $reference a reference pointer to a database entry |
|
319
|
|
|
* @return void |
|
320
|
|
|
* @throws Exception |
|
321
|
|
|
*/ |
|
322
|
|
|
private function checkROWIDpresence($reference) { |
|
323
|
|
|
$found = preg_match("/^ROWID-.*/", $reference); |
|
324
|
|
|
if ($found != 1) { // get excited on not-found AND on execution error |
|
325
|
|
|
throw new Exception("Error, ROWID expected."); |
|
326
|
|
|
} |
|
327
|
|
|
} |
|
328
|
|
|
|
|
329
|
|
|
/** |
|
330
|
|
|
* creates HTML code to display a nice UI representation of a CA |
|
331
|
|
|
* |
|
332
|
|
|
* @param string $cAReference ROWID pointer to the CA to display |
|
333
|
|
|
* @return string HTML code |
|
334
|
|
|
*/ |
|
335
|
|
|
public function previewCAinHTML($cAReference) { |
|
336
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
337
|
|
|
$this->checkROWIDpresence($cAReference); |
|
338
|
|
|
$rawResult = UIElements::getBlobFromDB($cAReference, FALSE); |
|
339
|
|
|
if (is_bool($rawResult)) { // we didn't actually get a CA! |
|
|
|
|
|
|
340
|
|
|
$retval = "<div class='ca-summary'>" . _("There was an error while retrieving the certificate from the database!") . "</div>"; |
|
341
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
342
|
|
|
return $retval; |
|
343
|
|
|
} |
|
344
|
|
|
$cAblob = base64_decode($rawResult); |
|
345
|
|
|
|
|
346
|
|
|
$func = new \core\common\X509; |
|
347
|
|
|
$details = $func->processCertificate($cAblob); |
|
348
|
|
|
if ($details === FALSE) { |
|
349
|
|
|
$retval = _("There was an error processing the certificate!"); |
|
350
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
351
|
|
|
return $retval; |
|
352
|
|
|
} |
|
353
|
|
|
|
|
354
|
|
|
$details['name'] = preg_replace('/(.)\/(.)/', "$1<br/>$2", $details['name']); |
|
355
|
|
|
$details['name'] = preg_replace('/\//', "", $details['name']); |
|
356
|
|
|
$certstatus = ( $details['root'] == 1 ? "R" : "I"); |
|
357
|
|
|
if ($details['ca'] == 0 && $details['root'] != 1) { |
|
358
|
|
|
$retval = "<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>"; |
|
359
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
360
|
|
|
return $retval; |
|
361
|
|
|
} |
|
362
|
|
|
$retval = "<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>"; |
|
363
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
364
|
|
|
return $retval; |
|
365
|
|
|
} |
|
366
|
|
|
|
|
367
|
|
|
/** |
|
368
|
|
|
* creates HTML code to display a nice UI representation of an image |
|
369
|
|
|
* |
|
370
|
|
|
* @param string $imageReference ROWID pointer to the image to display |
|
371
|
|
|
* @return string HTML code |
|
372
|
|
|
*/ |
|
373
|
|
|
public function previewImageinHTML($imageReference) { |
|
374
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
375
|
|
|
$this->checkROWIDpresence($imageReference); |
|
376
|
|
|
$retval = "<img style='max-width:150px' src='inc/filepreview.php?id=" . $imageReference . "' alt='" . _("Preview of logo file") . "'/>"; |
|
377
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
378
|
|
|
return $retval; |
|
379
|
|
|
} |
|
380
|
|
|
|
|
381
|
|
|
/** |
|
382
|
|
|
* creates HTML code to display a nice UI representation of a TermsOfUse file |
|
383
|
|
|
* |
|
384
|
|
|
* @param string $fileReference ROWID pointer to the file to display |
|
385
|
|
|
* @return string HTML code |
|
386
|
|
|
*/ |
|
387
|
|
|
public function previewInfoFileinHTML($fileReference) { |
|
388
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
389
|
|
|
$this->checkROWIDpresence($fileReference); |
|
390
|
|
|
$fileBlob = UIElements::getBlobFromDB($fileReference, FALSE); |
|
391
|
|
|
if (is_bool($fileBlob)) { // we didn't actually get a file! |
|
|
|
|
|
|
392
|
|
|
$retval = "<div class='ca-summary'>" . _("There was an error while retrieving the file from the database!") . "</div>"; |
|
393
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
394
|
|
|
return $retval; |
|
395
|
|
|
} |
|
396
|
|
|
$decodedFileBlob = base64_decode($fileBlob); |
|
397
|
|
|
$fileinfo = new \finfo(); |
|
398
|
|
|
$retval = "<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>"; |
|
399
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
400
|
|
|
return $retval; |
|
401
|
|
|
} |
|
402
|
|
|
|
|
403
|
|
|
/** |
|
404
|
|
|
* creates HTML code for a UI element which informs the user about something. |
|
405
|
|
|
* |
|
406
|
|
|
* @param int $level what kind of information is to be displayed? |
|
407
|
|
|
* @param string $text the text to display |
|
408
|
|
|
* @param string $caption the caption to display |
|
409
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
410
|
|
|
* @return string |
|
411
|
|
|
*/ |
|
412
|
|
|
public function boxFlexible(int $level, string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
413
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
414
|
|
|
$uiMessages = [ |
|
415
|
|
|
\core\common\Entity::L_OK => ['icon' => '../resources/images/icons/Quetto/check-icon.png', 'text' => _("OK")], |
|
416
|
|
|
\core\common\Entity::L_REMARK => ['icon' => '../resources/images/icons/Quetto/info-icon.png', 'text' => _("Remark")], |
|
417
|
|
|
\core\common\Entity::L_WARN => ['icon' => '../resources/images/icons/Quetto/danger-icon.png', 'text' => _("Warning!")], |
|
418
|
|
|
\core\common\Entity::L_ERROR => ['icon' => '../resources/images/icons/Quetto/no-icon.png', 'text' => _("Error!")], |
|
419
|
|
|
]; |
|
420
|
|
|
|
|
421
|
|
|
$retval = ""; |
|
422
|
|
|
if (!$omittabletags) { |
|
423
|
|
|
$retval .= "<tr><td>"; |
|
424
|
|
|
} |
|
425
|
|
|
$finalCaption = ($caption !== NULL ? $caption : $uiMessages[$level]['text']); |
|
426
|
|
|
$retval .= "<img class='icon' src='" . $uiMessages[$level]['icon'] . "' alt='" . $finalCaption . "' title='" . $finalCaption . "'/>"; |
|
427
|
|
|
if (!$omittabletags) { |
|
428
|
|
|
$retval .= "</td><td>"; |
|
429
|
|
|
} |
|
430
|
|
|
if ($text !== NULL) { |
|
431
|
|
|
$retval .= $text; |
|
432
|
|
|
} |
|
433
|
|
|
if (!$omittabletags) { |
|
434
|
|
|
$retval .= "</td></tr>"; |
|
435
|
|
|
} |
|
436
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
437
|
|
|
return $retval; |
|
438
|
|
|
} |
|
439
|
|
|
|
|
440
|
|
|
/** |
|
441
|
|
|
* creates HTML code to display an "all is okay" message |
|
442
|
|
|
* |
|
443
|
|
|
* @param string $text the text to display |
|
444
|
|
|
* @param string $caption the caption to display |
|
445
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
446
|
|
|
* @return string HTML: the box |
|
447
|
|
|
*/ |
|
448
|
|
|
public function boxOkay(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
449
|
|
|
return $this->boxFlexible(\core\common\Entity::L_OK, $text, $caption, $omittabletags); |
|
450
|
|
|
} |
|
451
|
|
|
|
|
452
|
|
|
/** |
|
453
|
|
|
* creates HTML code to display a "smartass comment" message |
|
454
|
|
|
* |
|
455
|
|
|
* @param string $text the text to display |
|
456
|
|
|
* @param string $caption the caption to display |
|
457
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
458
|
|
|
* @return string HTML: the box |
|
459
|
|
|
*/ |
|
460
|
|
|
public function boxRemark(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
461
|
|
|
return $this->boxFlexible(\core\common\Entity::L_REMARK, $text, $caption, $omittabletags); |
|
462
|
|
|
} |
|
463
|
|
|
|
|
464
|
|
|
/** |
|
465
|
|
|
* creates HTML code to display a "something's a bit wrong" message |
|
466
|
|
|
* |
|
467
|
|
|
* @param string $text the text to display |
|
468
|
|
|
* @param string $caption the caption to display |
|
469
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
470
|
|
|
* @return string HTML: the box |
|
471
|
|
|
*/ |
|
472
|
|
|
public function boxWarning(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
473
|
|
|
return $this->boxFlexible(\core\common\Entity::L_WARN, $text, $caption, $omittabletags); |
|
474
|
|
|
} |
|
475
|
|
|
|
|
476
|
|
|
/** |
|
477
|
|
|
* creates HTML code to display a "Whoa! Danger, Will Robinson!" message |
|
478
|
|
|
* |
|
479
|
|
|
* @param string $text the text to display |
|
480
|
|
|
* @param string $caption the caption to display |
|
481
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
482
|
|
|
* @return string HTML: the box |
|
483
|
|
|
*/ |
|
484
|
|
|
public function boxError(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
485
|
|
|
return $this->boxFlexible(\core\common\Entity::L_ERROR, $text, $caption, $omittabletags); |
|
486
|
|
|
} |
|
487
|
|
|
|
|
488
|
|
|
/** |
|
489
|
|
|
* Injects the consortium logo in the middle of a given PNG. |
|
490
|
|
|
* |
|
491
|
|
|
* Usually used on QR code PNGs - the parameters inform about the structure of |
|
492
|
|
|
* the QR code so that the logo does not prevent parsing of the QR code. |
|
493
|
|
|
* |
|
494
|
|
|
* @param string $inputpngstring the PNG to edit |
|
495
|
|
|
* @param int $symbolsize size in pixels of one QR "pixel" |
|
496
|
|
|
* @param int $marginsymbols size in pixels of border around the actual QR |
|
497
|
|
|
* @return string the image with logo centered in the middle |
|
498
|
|
|
*/ |
|
499
|
|
|
public function pngInjectConsortiumLogo(string $inputpngstring, int $symbolsize, int $marginsymbols = 4) { |
|
500
|
|
|
$loggerInstance = new \core\common\Logging(); |
|
501
|
|
|
$inputgd = imagecreatefromstring($inputpngstring); |
|
502
|
|
|
|
|
503
|
|
|
$loggerInstance->debug(4, "Consortium logo is at: " . ROOT . "/web/resources/images/consortium_logo_large.png"); |
|
504
|
|
|
$logogd = imagecreatefrompng(ROOT . "/web/resources/images/consortium_logo_large.png"); |
|
505
|
|
|
|
|
506
|
|
|
$sizeinput = [imagesx($inputgd), imagesy($inputgd)]; |
|
507
|
|
|
$sizelogo = [imagesx($logogd), imagesy($logogd)]; |
|
508
|
|
|
// Q level QR-codes can sustain 25% "damage" |
|
509
|
|
|
// make our logo cover approx 15% of area to be sure; mind that there's a $symbolsize * $marginsymbols pixel white border around each edge |
|
510
|
|
|
$totalpixels = ($sizeinput[0] - $symbolsize * $marginsymbols) * ($sizeinput[1] - $symbolsize * $marginsymbols); |
|
511
|
|
|
$totallogopixels = ($sizelogo[0]) * ($sizelogo[1]); |
|
512
|
|
|
$maxoccupy = $totalpixels * 0.04; |
|
513
|
|
|
// find out how much we have to scale down logo to reach 10% QR estate |
|
514
|
|
|
$scale = sqrt($maxoccupy / $totallogopixels); |
|
515
|
|
|
$loggerInstance->debug(4, "Scaling info: $scale, $maxoccupy, $totallogopixels\n"); |
|
516
|
|
|
// determine final pixel size - round to multitude of $symbolsize to match exact symbol boundary |
|
517
|
|
|
$targetwidth = $symbolsize * (int) round($sizelogo[0] * $scale / $symbolsize); |
|
|
|
|
|
|
518
|
|
|
$targetheight = $symbolsize * (int) round($sizelogo[1] * $scale / $symbolsize); |
|
|
|
|
|
|
519
|
|
|
// paint white below the logo, in case it has transparencies (looks bad) |
|
520
|
|
|
// have one symbol in each direction extra white space |
|
521
|
|
|
$whiteimage = imagecreate($targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize); |
|
522
|
|
|
imagecolorallocate($whiteimage, 255, 255, 255); |
|
523
|
|
|
// also make sure the initial placement is a multitude of 12; otherwise "two half" symbols might be affected |
|
524
|
|
|
$targetplacementx = $symbolsize * (int) round(($sizeinput[0] / 2 - ($targetwidth - $symbolsize) / 2) / $symbolsize); |
|
|
|
|
|
|
525
|
|
|
$targetplacementy = $symbolsize * (int) round(($sizeinput[1] / 2 - ($targetheight - $symbolsize) / 2) / $symbolsize); |
|
|
|
|
|
|
526
|
|
|
imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize); |
|
527
|
|
|
imagecopyresized($inputgd, $logogd, $targetplacementx, $targetplacementy, 0, 0, $targetwidth, $targetheight, $sizelogo[0], $sizelogo[1]); |
|
528
|
|
|
ob_start(); |
|
529
|
|
|
imagepng($inputgd); |
|
530
|
|
|
return ob_get_clean(); |
|
531
|
|
|
} |
|
532
|
|
|
|
|
533
|
|
|
} |
|
534
|
|
|
|