|
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 extends \core\common\Entity { |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* the custom displayable variant of the term 'federation' |
|
36
|
|
|
* |
|
37
|
|
|
* @var string |
|
38
|
|
|
*/ |
|
39
|
|
|
public $nomenclatureFed; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* the custom displayable variant of the term 'institution' |
|
43
|
|
|
* |
|
44
|
|
|
* @var string |
|
45
|
|
|
*/ |
|
46
|
|
|
public $nomenclatureIdP; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* the custom displayable variant of the term 'hotspot' |
|
50
|
|
|
* |
|
51
|
|
|
* @var string |
|
52
|
|
|
*/ |
|
53
|
|
|
public $nomenclatureHotspot; |
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* the custom displayable variant of the term 'hotspot' |
|
57
|
|
|
* |
|
58
|
|
|
* @var string |
|
59
|
|
|
*/ |
|
60
|
|
|
public $nomenclatureParticipant; |
|
61
|
|
|
|
|
62
|
|
|
/** |
|
63
|
|
|
* Initialises the class. |
|
64
|
|
|
* |
|
65
|
|
|
* Mainly fetches various nomenclature from the config and attempts to translate those into local language. Needs pre-loading some terms. |
|
66
|
|
|
*/ |
|
67
|
|
|
public function __construct() { |
|
68
|
|
|
// pick up the nomenclature translations from core - no need to repeat |
|
69
|
|
|
// them here in this catalogue |
|
70
|
|
|
parent::__construct(); |
|
71
|
|
|
$this->nomenclatureFed = \core\common\Entity::$nomenclature_fed; |
|
72
|
|
|
$this->nomenclatureIdP = \core\common\Entity::$nomenclature_idp; |
|
73
|
|
|
$this->nomenclatureHotspot = \core\common\Entity::$nomenclature_hotspot; |
|
74
|
|
|
$this->nomenclatureParticipant = \core\common\Entity::$nomenclature_participant; |
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
|
|
/** |
|
78
|
|
|
* provides human-readable text for the various option names as stored in DB. |
|
79
|
|
|
* |
|
80
|
|
|
* @param string $input raw text in need of a human-readable display variant |
|
81
|
|
|
* @return string the human-readable variant |
|
82
|
|
|
* @throws \Exception |
|
83
|
|
|
*/ |
|
84
|
|
|
public function displayName($input) { |
|
85
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
86
|
|
|
$ssidText = _("SSID"); |
|
87
|
|
|
$passpointOiText = _("HS20 Consortium OI"); |
|
88
|
|
|
|
|
89
|
|
|
if (!empty(\config\ConfAssistant::CONSORTIUM['interworking-consortium-oi']) && count(\config\ConfAssistant::CONSORTIUM['interworking-consortium-oi']) > 0) { |
|
90
|
|
|
$passpointOiText = _("Additional HS20 Consortium OI"); |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
$displayNames = [_("Support: Web") => "support:url", |
|
94
|
|
|
_("Support: EAP Types") => "support:eap_types", |
|
95
|
|
|
_("Support: Phone") => "support:phone", |
|
96
|
|
|
_("Support: E-Mail") => "support:email", |
|
97
|
|
|
sprintf(_("%s Name"), $this->nomenclatureParticipant) => "general:instname", |
|
98
|
|
|
sprintf(_("%s Acronym"), $this->nomenclatureParticipant) => "general:instshortname", |
|
99
|
|
|
_("Location") => "general:geo_coordinates", |
|
100
|
|
|
_("Logo URL") => "general:logo_url", |
|
101
|
|
|
_("Logo image") => "general:logo_file", |
|
102
|
|
|
_("Configure Wired Ethernet") => "media:wired", |
|
103
|
|
|
_("Name (CN) of Authentication Server") => "eap:server_name", |
|
104
|
|
|
_("Valid until") => "eap:ca_vailduntil", |
|
105
|
|
|
_("Enable device assessment") => "eap:enable_nea", |
|
106
|
|
|
_("Terms of Use") => "support:info_file", |
|
107
|
|
|
_("CA Certificate URL") => "eap:ca_url", |
|
108
|
|
|
_("CA Certificate File") => "eap:ca_file", |
|
109
|
|
|
_("Profile Display Name") => "profile:name", |
|
110
|
|
|
_("Production-Ready") => "profile:production", |
|
111
|
|
|
_("Admin Accepted IdP Terms of Use") => 'hiddenprofile:tou_accepted', |
|
112
|
|
|
_("Admin Accepted SP Terms of Use") => 'hiddenmanagedsp:tou_accepted', |
|
113
|
|
|
_("Extra text on downloadpage for device") => "device-specific:customtext", |
|
114
|
|
|
_("Redirection Target") => "device-specific:redirect", |
|
115
|
|
|
_("Extra text on downloadpage for EAP method") => "eap-specific:customtext", |
|
116
|
|
|
_("Turn on selection of EAP-TLS User-Name") => "eap-specific:tls_use_other_id", |
|
117
|
|
|
_("Use GEANTlink for TTLS (Windows 8 and 10)") => "device-specific:geantlink", |
|
118
|
|
|
_("Show the dedicated geteduroam download page for this device") => "device-specific:geteduroam", |
|
119
|
|
|
_("Profile Description") => "profile:description", |
|
120
|
|
|
_("Custom Installer Name Suffix") => "profile:customsuffix", |
|
121
|
|
|
_("OpenRoaming") => "media:openroaming", |
|
122
|
|
|
sprintf(_("%s Administrator"), $this->nomenclatureFed) => "user:fedadmin", |
|
123
|
|
|
_("Real Name") => "user:realname", |
|
124
|
|
|
_("E-Mail Address") => "user:email", |
|
125
|
|
|
_("Remove/Disable SSID") => "media:remove_SSID", |
|
126
|
|
|
_("Mandatory Content Filtering Proxy") => "media:force_proxy", |
|
127
|
|
|
_("Custom CSS file for User Area") => "fed:css_file", |
|
128
|
|
|
sprintf(_("%s Logo"), $this->nomenclatureFed) => "fed:logo_file", |
|
129
|
|
|
_("Preferred Skin for User Area") => "fed:desired_skin", |
|
130
|
|
|
sprintf(_("Include %s branding in installers"), $this->nomenclatureFed) => "fed:include_logo_installers", |
|
131
|
|
|
sprintf(_("%s Name"), $this->nomenclatureFed) => "fed:realname", |
|
132
|
|
|
sprintf(_("%s Homepage"), $this->nomenclatureFed) => "fed:url", |
|
133
|
|
|
sprintf(_("Custom text in %s Invitations"), $this->nomenclatureParticipant) => "fed:custominvite", |
|
134
|
|
|
sprintf(_("Enable %s"), \config\ConfAssistant::SILVERBULLET['product_name']) => "fed:silverbullet", |
|
135
|
|
|
sprintf(_("%s: Do not terminate EAP"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet-noterm", |
|
136
|
|
|
sprintf(_("%s: max users per profile"), \core\ProfileSilverbullet::PRODUCTNAME) => "fed:silverbullet-maxusers", |
|
137
|
|
|
sprintf(_("Mint %s with CA on creation"), $this->nomenclatureIdP) => "fed:minted_ca_file", |
|
138
|
|
|
sprintf(_("OpenRoaming: Allow %s Opt-In"),$this->nomenclatureParticipant) => "fed:openroaming", |
|
139
|
|
|
_("OpenRoaming: Custom NAPTR Target") => "fed:openroaming_customtarget", |
|
140
|
|
|
$ssidText => "media:SSID", |
|
141
|
|
|
$passpointOiText => "media:consortium_OI", |
|
142
|
|
|
_("VLAN for own users") => "managedsp:vlan", |
|
143
|
|
|
_("Realm to be considered own users") => "managedsp:realmforvlan", |
|
144
|
|
|
_("Custom Operator-Name attribute") => "managedsp:operatorname", |
|
145
|
|
|
]; |
|
146
|
|
|
|
|
147
|
|
|
$find = array_keys($displayNames, $input, TRUE); |
|
148
|
|
|
|
|
149
|
|
|
if (count($find) == 0) { // this is an error! throw an Exception |
|
150
|
|
|
throw new \Exception("The translation of an option name was requested, but the option is not known to the system: " . htmlentities($input)); |
|
151
|
|
|
} |
|
152
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
153
|
|
|
// none of the strings have HTML in them, only translators can provide own text for it -> no threat, but complained about by the security review |
|
154
|
|
|
return htmlspecialchars($find[0]); |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
|
|
/** |
|
158
|
|
|
* creates an HTML information block with a list of options from a given category and level |
|
159
|
|
|
* @param array $optionlist list of options |
|
160
|
|
|
* @param string $class option class of interest |
|
161
|
|
|
* @param string $level option level of interest |
|
162
|
|
|
* @return string HTML code |
|
163
|
|
|
*/ |
|
164
|
|
|
public function infoblock(array $optionlist, string $class, string $level) { |
|
165
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
166
|
|
|
$locationMarkers = []; |
|
167
|
|
|
$retval = ""; |
|
168
|
|
|
$optioninfo = \core\Options::instance(); |
|
169
|
|
|
|
|
170
|
|
|
foreach ($optionlist as $option) { |
|
171
|
|
|
$type = $optioninfo->optionType($option['name']); |
|
172
|
|
|
if (preg_match('/^' . $class . '/', $option['name']) && $option['level'] == "$level") { |
|
173
|
|
|
// all non-multilang attribs get this assignment ... |
|
174
|
|
|
$language = ""; |
|
175
|
|
|
$content = $option['value']; |
|
176
|
|
|
// ... override them with multilang tags if needed |
|
177
|
|
|
if ($type["flag"] == "ML") { |
|
178
|
|
|
$language = _("default/other languages"); |
|
179
|
|
|
if ($option['lang'] != 'C') { |
|
180
|
|
|
$language = \config\Master::LANGUAGES[$option['lang']]['display'] ?? "(unsupported language)"; |
|
181
|
|
|
} |
|
182
|
|
|
} |
|
183
|
|
|
|
|
184
|
|
|
switch ($type["type"]) { |
|
185
|
|
|
case "coordinates": |
|
186
|
|
|
$coords = json_decode($option['value'], true); |
|
187
|
|
|
$locationMarkers[] = $coords; |
|
188
|
|
|
break; |
|
189
|
|
|
case "file": |
|
190
|
|
|
$retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td>"; |
|
191
|
|
|
switch ($option['name']) { |
|
192
|
|
|
case "general:logo_file": |
|
193
|
|
|
case "fed:logo_file": |
|
194
|
|
|
$retval .= $this->previewImageinHTML('ROWID-' . $option['level'] . '-' . $option['row_id']); |
|
195
|
|
|
break; |
|
196
|
|
|
case "eap:ca_file": |
|
197
|
|
|
// fall-through intended: display both the same way |
|
198
|
|
|
case "fed:minted_ca_file": |
|
199
|
|
|
$retval .= $this->previewCAinHTML('ROWID-' . $option['level'] . '-' . $option['row_id']); |
|
200
|
|
|
break; |
|
201
|
|
|
case "support:info_file": |
|
202
|
|
|
$retval .= $this->previewInfoFileinHTML('ROWID-' . $option['level'] . '-' . $option['row_id']); |
|
203
|
|
|
break; |
|
204
|
|
|
default: |
|
205
|
|
|
} |
|
206
|
|
|
break; |
|
207
|
|
|
case "boolean": |
|
208
|
|
|
if ($option['name'] == "fed:silverbullet" && \config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_SILVERBULLET'] == "LOCAL" && \config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_RADIUS'] != "LOCAL") { |
|
209
|
|
|
// do not display the option at all; it gets auto-set by the ProfileSilverbullet constructor and doesn't have to be seen |
|
210
|
|
|
break; |
|
211
|
|
|
} |
|
212
|
|
|
$retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td><strong>" . ($content == "on" ? _("on") : _("off") ) . "</strong></td></tr>"; |
|
213
|
|
|
break; |
|
214
|
|
|
default: |
|
215
|
|
|
$retval .= "<tr><td>" . $this->displayName($option['name']) . "</td><td>$language</td><td><strong>$content</strong></td></tr>"; |
|
216
|
|
|
} |
|
217
|
|
|
} |
|
218
|
|
|
} |
|
219
|
|
|
if (count($locationMarkers)) { |
|
220
|
|
|
$marker = '<markers>'; |
|
221
|
|
|
$locationCount = 0; |
|
222
|
|
|
foreach ($locationMarkers as $g) { |
|
223
|
|
|
$locationCount++; |
|
224
|
|
|
$marker .= '<marker name="' . $locationCount . '" lat="' . $g['lat'] . '" lng="' . $g['lon'] . '" />'; |
|
225
|
|
|
} |
|
226
|
|
|
$marker .= '<\/markers>'; // some validator says this should be escaped |
|
227
|
|
|
$jMarker = json_encode($locationMarkers); |
|
228
|
|
|
$retval .= '<tr><td><script>markers=\'' . $marker . '\'; jmarkers = \'' . $jMarker . '\';</script></td><td></td><td></td></tr>'; |
|
229
|
|
|
} |
|
230
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
231
|
|
|
return $retval; |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
/** |
|
235
|
|
|
* creates HTML code to display all information boxes for an IdP |
|
236
|
|
|
* |
|
237
|
|
|
* @param \core\IdP $myInst the IdP in question |
|
238
|
|
|
* @return string HTML code |
|
239
|
|
|
*/ |
|
240
|
|
|
public function instLevelInfoBoxes(\core\IdP $myInst) { |
|
241
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
242
|
|
|
$idpoptions = $myInst->getAttributes(); |
|
243
|
|
|
$retval = "<div class='infobox'> |
|
244
|
|
|
<h2>" . sprintf(_("General %s details"), $this->nomenclatureParticipant) . "</h2> |
|
245
|
|
|
<table> |
|
246
|
|
|
<tr> |
|
247
|
|
|
<td> |
|
248
|
|
|
" . _("Country:") . " |
|
249
|
|
|
</td> |
|
250
|
|
|
<td> |
|
251
|
|
|
</td> |
|
252
|
|
|
<td> |
|
253
|
|
|
<strong>"; |
|
254
|
|
|
$myFed = new \core\Federation($myInst->federation); |
|
255
|
|
|
$retval .= $myFed->name; |
|
256
|
|
|
$retval .= "</strong> |
|
257
|
|
|
</td> |
|
258
|
|
|
</tr>" . $this->infoblock($idpoptions, "general", "IdP") . " |
|
259
|
|
|
</table> |
|
260
|
|
|
</div>"; |
|
261
|
|
|
|
|
262
|
|
|
$blocks = [["support", _("Global Helpdesk Details")], ["media", _("Media Properties")]]; |
|
263
|
|
|
foreach ($blocks as $block) { |
|
264
|
|
|
$retval .= "<div class='infobox'> |
|
265
|
|
|
<h2>" . $block[1] . "</h2> |
|
266
|
|
|
<table>" . |
|
267
|
|
|
$this->infoblock($idpoptions, $block[0], "IdP") . |
|
268
|
|
|
"</table> |
|
269
|
|
|
</div>"; |
|
270
|
|
|
} |
|
271
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
272
|
|
|
return $retval; |
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
|
|
/** |
|
276
|
|
|
* pretty-prints a file size number in SI "bi" units |
|
277
|
|
|
* @param int $number the size of the file |
|
278
|
|
|
* @return string the pretty-print representation of the file size |
|
279
|
|
|
*/ |
|
280
|
|
|
private function displaySize(int $number) { |
|
281
|
|
|
if ($number > 1024 * 1024) { |
|
282
|
|
|
return round($number / 1024 / 1024, 2) . " MiB"; |
|
283
|
|
|
} |
|
284
|
|
|
if ($number > 1024) { |
|
285
|
|
|
return round($number / 1024, 2) . " KiB"; |
|
286
|
|
|
} |
|
287
|
|
|
return $number . " B"; |
|
288
|
|
|
} |
|
289
|
|
|
|
|
290
|
|
|
/** |
|
291
|
|
|
* |
|
292
|
|
|
* @param string $table the database table |
|
293
|
|
|
* @param integer $rowindex the database row_id |
|
294
|
|
|
* @param boolean $checkpublic should we check if the requested piece of data is public? |
|
295
|
|
|
* @return string|boolean the requested data, or FALSE if something went wrong |
|
296
|
|
|
*/ |
|
297
|
|
|
public static function getBlobFromDB($table, $rowindex, $checkpublic) { |
|
298
|
|
|
// the data is either public (just give it away) or not; in this case, only |
|
299
|
|
|
// release if the data belongs to admin himself |
|
300
|
|
|
if ($checkpublic) { |
|
301
|
|
|
|
|
302
|
|
|
$owners = \core\EntityWithDBProperties::isDataRestricted($table, $rowindex); |
|
303
|
|
|
|
|
304
|
|
|
$ownersCondensed = []; |
|
305
|
|
|
|
|
306
|
|
|
if ($owners !== FALSE) { // restricted data, see if we're authenticated and owners of the data |
|
307
|
|
|
$auth = new \web\lib\admin\Authentication(); |
|
308
|
|
|
if (!$auth->isAuthenticated()) { |
|
309
|
|
|
return FALSE; // admin-only, but we are not an admin |
|
310
|
|
|
} |
|
311
|
|
|
// we might be called without session context (filepreview) so get the |
|
312
|
|
|
// context if needed |
|
313
|
|
|
\core\CAT::sessionStart(); |
|
314
|
|
|
|
|
315
|
|
|
foreach ($owners as $oneowner) { |
|
316
|
|
|
$ownersCondensed[] = $oneowner['ID']; |
|
317
|
|
|
} |
|
318
|
|
|
if (array_search($_SESSION['user'], $ownersCondensed) === FALSE) { |
|
319
|
|
|
return FALSE; // wrong guy |
|
320
|
|
|
} |
|
321
|
|
|
// carry on and get the data |
|
322
|
|
|
} |
|
323
|
|
|
} |
|
324
|
|
|
|
|
325
|
|
|
$blob = \core\EntityWithDBProperties::fetchRawDataByIndex($table, $rowindex); |
|
326
|
|
|
return $blob; // this means we might return FALSE here if something was wrong with the original requested reference |
|
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
|
|
|
$validator = new \web\lib\common\InputValidation(); |
|
338
|
|
|
$ref = $validator->databaseReference($cAReference); |
|
339
|
|
|
$caExpiryTrashhold = \config\ConfAssistant::CERT_WARNINGS['expiry_warning']; |
|
340
|
|
|
$rawResult = UIElements::getBlobFromDB($ref['table'], $ref['rowindex'], FALSE); |
|
341
|
|
|
if (is_bool($rawResult)) { // we didn't actually get a CA! |
|
342
|
|
|
$retval = "<div class='ca-summary'>" . _("There was an error while retrieving the certificate from the database!") . "</div>"; |
|
343
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
344
|
|
|
return $retval; |
|
345
|
|
|
} |
|
346
|
|
|
$cAblob = base64_decode($rawResult); |
|
347
|
|
|
|
|
348
|
|
|
$func = new \core\common\X509; |
|
349
|
|
|
$details = $func->processCertificate($cAblob); |
|
350
|
|
|
if ($details === FALSE) { |
|
351
|
|
|
$retval = _("There was an error processing the certificate!"); |
|
352
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
353
|
|
|
return $retval; |
|
354
|
|
|
} |
|
355
|
|
|
|
|
356
|
|
|
$details['name'] = preg_replace('/(.)\/(.)/', "$1<br/>$2", $details['name']); |
|
357
|
|
|
$details['name'] = preg_replace('/\//', "", $details['name']); |
|
358
|
|
|
$certstatus = ( $details['root'] == 1 ? "R" : "I"); |
|
359
|
|
|
$certTooltip = ( $details['root'] == 1 ? _("Root CA") : _("Intermediate CA")); |
|
360
|
|
|
$innerbgColor = "#0000ff"; |
|
361
|
|
|
$leftBorderColor = "#00ff00"; |
|
362
|
|
|
$message = ""; |
|
363
|
|
|
if ($details['ca'] == 0 && $details['root'] != 1) { |
|
364
|
|
|
$leftBorderColor = "red"; |
|
365
|
|
|
$message = _("This is a <strong>SERVER</strong> certificate!"); |
|
366
|
|
|
if (\config\ConfAssistant::CERT_GUIDELINES !== '') { |
|
367
|
|
|
$message .= "<br/><a target='_blank' href='".\config\ConfAssistant::CERT_GUIDELINES."'>". _("more info")."</a>"; |
|
368
|
|
|
} |
|
369
|
|
|
$message .= "<br/>"; |
|
370
|
|
|
$retval = "<div class='ca-summary' style='border-left-color: $leftBorderColor'><div style='position:absolute; right: -15px; width:20px; height:20px; background-color:$innerbgColor; border-radius:10px; text-align: center;'><div style='padding-top:3px; font-weight:bold; color:#ffffff;'>S</div></div>" . $message . $details['name'] . "</div>"; |
|
371
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
372
|
|
|
return $retval; |
|
373
|
|
|
} |
|
374
|
|
|
$now = time(); |
|
375
|
|
|
if ($now + \config\ConfAssistant::CERT_WARNINGS['expiry_critical'] > $details['full_details']['validTo_time_t']) { |
|
376
|
|
|
$leftBorderColor = "red"; |
|
377
|
|
|
$message = _("Certificate expired!") . "<br>"; |
|
378
|
|
|
} elseif($now + \config\ConfAssistant::CERT_WARNINGS['expiry_warning'] > $details['full_details']['validTo_time_t'] - $caExpiryTrashhold) { |
|
379
|
|
|
if ($leftBorderColor == "#00ff00") { |
|
380
|
|
|
$leftBorderColor = "yellow"; |
|
381
|
|
|
} |
|
382
|
|
|
$message = _("Certificate close to expiry!") . "<br/>"; |
|
383
|
|
|
} |
|
384
|
|
|
|
|
385
|
|
|
if ($details['root'] == 1 && $details['basicconstraints_set'] == 0) { |
|
386
|
|
|
if ($leftBorderColor == "#00ff00") { |
|
387
|
|
|
$leftBorderColor = "yellow"; |
|
388
|
|
|
} |
|
389
|
|
|
$message .= "<div style='max-width: 25em'><strong>" . _("Improper root certificate, required critical CA extension missing, will not reliably install!") . "</strong>"; |
|
390
|
|
|
if (\config\ConfAssistant::CERT_GUIDELINES !== '') { |
|
391
|
|
|
$message .= "<br/><a target='_blank' href='".\config\ConfAssistant::CERT_GUIDELINES."'>". _("more info")."</a>"; |
|
392
|
|
|
} |
|
393
|
|
|
$message .= "</div><br/>"; |
|
394
|
|
|
} |
|
395
|
|
|
$retval = "<div class='ca-summary' style='border-left-color: $leftBorderColor'><div style='position:absolute; right: -15px; width:20px; height:20px; background-color:$innerbgColor; border-radius:10px; text-align: center;'><div title='$certTooltip' style='padding-top:3px; font-weight:bold; color:#ffffff;'>$certstatus</div></div>" . $message . $details['name'] . "<br>" . $this->displayName('eap:ca_vailduntil') . " " . gmdate('Y-m-d H:i:s', $details['full_details']['validTo_time_t']) . " UTC</div>"; |
|
396
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
397
|
|
|
return $retval; |
|
398
|
|
|
} |
|
399
|
|
|
|
|
400
|
|
|
/** |
|
401
|
|
|
* creates HTML code to display a nice UI representation of an image |
|
402
|
|
|
* |
|
403
|
|
|
* @param string $imageReference ROWID pointer to the image to display |
|
404
|
|
|
* @return string HTML code |
|
405
|
|
|
*/ |
|
406
|
|
|
public function previewImageinHTML($imageReference) { |
|
407
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
408
|
|
|
$retval = "<img style='max-width:150px' src='inc/filepreview.php?id=" . $imageReference . "' alt='" . _("Preview of logo file") . "'/>"; |
|
409
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
410
|
|
|
return $retval; |
|
411
|
|
|
} |
|
412
|
|
|
|
|
413
|
|
|
/** |
|
414
|
|
|
* creates HTML code to display a nice UI representation of a TermsOfUse file |
|
415
|
|
|
* |
|
416
|
|
|
* @param string $fileReference ROWID pointer to the file to display |
|
417
|
|
|
* @return string HTML code |
|
418
|
|
|
*/ |
|
419
|
|
|
public function previewInfoFileinHTML($fileReference) { |
|
420
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
421
|
|
|
$validator = new \web\lib\common\InputValidation(); |
|
422
|
|
|
$ref = $validator->databaseReference($fileReference); |
|
423
|
|
|
$fileBlob = UIElements::getBlobFromDB($ref['table'], $ref['rowindex'], FALSE); |
|
424
|
|
|
if (is_bool($fileBlob)) { // we didn't actually get a file! |
|
425
|
|
|
$retval = "<div class='ca-summary'>" . _("There was an error while retrieving the file from the database!") . "</div>"; |
|
426
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
427
|
|
|
return $retval; |
|
428
|
|
|
} |
|
429
|
|
|
$decodedFileBlob = base64_decode($fileBlob); |
|
430
|
|
|
$fileinfo = new \finfo(); |
|
431
|
|
|
$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>"; |
|
432
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
433
|
|
|
return $retval; |
|
434
|
|
|
} |
|
435
|
|
|
|
|
436
|
|
|
/** |
|
437
|
|
|
* creates HTML code for a UI element which informs the user about something. |
|
438
|
|
|
* |
|
439
|
|
|
* @param int $level what kind of information is to be displayed? |
|
440
|
|
|
* @param string $text the text to display |
|
441
|
|
|
* @param string $caption the caption to display |
|
442
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
443
|
|
|
* @return string |
|
444
|
|
|
*/ |
|
445
|
|
|
public function boxFlexible(int $level, string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
446
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
447
|
|
|
$uiMessages = [ |
|
448
|
|
|
\core\common\Entity::L_OK => ['img' => 'Tabler/square-rounded-check-filled-green.svg', 'text' => _("OK")], |
|
449
|
|
|
\core\common\Entity::L_REMARK => ['img' => 'Tabler/info-square-rounded-filled-blue.svg', 'text' => _("Remark")], |
|
450
|
|
|
\core\common\Entity::L_WARN => ['img' => 'Tabler/alert-square-rounded-filled-yellow.svg', 'text' => _("Warning!")], |
|
451
|
|
|
\core\common\Entity::L_ERROR => ['img' => 'Tabler/square-rounded-x-filled-red.svg', 'text' => _("Error!")], |
|
452
|
|
|
\core\common\Entity::L_CERT_OK => ['img' => 'Tabler/certificate-green.svg', 'text' => _("OK")], |
|
453
|
|
|
\core\common\Entity::L_CERT_WARN => ['img' => 'Tabler/certificate-red.svg', 'text' => _("Warning!")], |
|
454
|
|
|
\core\common\Entity::L_CERT_ERROR => ['img' => 'Tabler/certificate-off.svg', 'text' => _("Warning!")], |
|
455
|
|
|
]; |
|
456
|
|
|
|
|
457
|
|
|
$retval = ""; |
|
458
|
|
|
if (!$omittabletags) { |
|
459
|
|
|
$retval .= "<tr><td>"; |
|
460
|
|
|
} |
|
461
|
|
|
// $finalCaption = ($caption !== NULL ? $caption : $uiMessages[$level]['text']); |
|
462
|
|
|
// $retval .= "<img class='icon cat-icon' src='" . $uiMessages[$level]['icon'] . "' alt='" . $finalCaption . "' title='" . $finalCaption . "'/>"; |
|
463
|
|
|
$iconData = $uiMessages[$level]; |
|
464
|
|
|
if ($caption !== NULL) { |
|
465
|
|
|
$iconData['text'] = $caption; |
|
466
|
|
|
} |
|
467
|
|
|
|
|
468
|
|
|
|
|
469
|
|
|
$retval .= $this->catIcon($iconData); |
|
470
|
|
|
|
|
471
|
|
|
if (!$omittabletags) { |
|
472
|
|
|
$retval .= "</td><td>"; |
|
473
|
|
|
} |
|
474
|
|
|
if ($text !== NULL) { |
|
475
|
|
|
$retval .= $text; |
|
476
|
|
|
} |
|
477
|
|
|
if (!$omittabletags) { |
|
478
|
|
|
$retval .= "</td></tr>"; |
|
479
|
|
|
} |
|
480
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
481
|
|
|
return $retval; |
|
482
|
|
|
} |
|
483
|
|
|
|
|
484
|
|
|
/** |
|
485
|
|
|
* creates HTML code to display an "all is okay" message |
|
486
|
|
|
* |
|
487
|
|
|
* @param string $text the text to display |
|
488
|
|
|
* @param string $caption the caption to display |
|
489
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
490
|
|
|
* @return string HTML: the box |
|
491
|
|
|
*/ |
|
492
|
|
|
public function boxOkay(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
493
|
|
|
return $this->boxFlexible(\core\common\Entity::L_OK, $text, $caption, $omittabletags); |
|
494
|
|
|
} |
|
495
|
|
|
|
|
496
|
|
|
/** |
|
497
|
|
|
* creates HTML code to display a "smartass comment" message |
|
498
|
|
|
* |
|
499
|
|
|
* @param string $text the text to display |
|
500
|
|
|
* @param string $caption the caption to display |
|
501
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
502
|
|
|
* @return string HTML: the box |
|
503
|
|
|
*/ |
|
504
|
|
|
public function boxRemark(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
505
|
|
|
return $this->boxFlexible(\core\common\Entity::L_REMARK, $text, $caption, $omittabletags); |
|
506
|
|
|
} |
|
507
|
|
|
|
|
508
|
|
|
/** |
|
509
|
|
|
* creates HTML code to display a "something's a bit wrong" message |
|
510
|
|
|
* |
|
511
|
|
|
* @param string $text the text to display |
|
512
|
|
|
* @param string $caption the caption to display |
|
513
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
514
|
|
|
* @return string HTML: the box |
|
515
|
|
|
*/ |
|
516
|
|
|
public function boxWarning(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
517
|
|
|
return $this->boxFlexible(\core\common\Entity::L_WARN, $text, $caption, $omittabletags); |
|
518
|
|
|
} |
|
519
|
|
|
|
|
520
|
|
|
/** |
|
521
|
|
|
* creates HTML code to display a "Whoa! Danger, Will Robinson!" message |
|
522
|
|
|
* |
|
523
|
|
|
* @param string $text the text to display |
|
524
|
|
|
* @param string $caption the caption to display |
|
525
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
526
|
|
|
* @return string HTML: the box |
|
527
|
|
|
*/ |
|
528
|
|
|
public function boxError(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
529
|
|
|
return $this->boxFlexible(\core\common\Entity::L_ERROR, $text, $caption, $omittabletags); |
|
530
|
|
|
} |
|
531
|
|
|
|
|
532
|
|
|
/** |
|
533
|
|
|
* creates HTML code to display a "All fine" message |
|
534
|
|
|
* |
|
535
|
|
|
* @param string $text the text to display |
|
536
|
|
|
* @param string $caption the caption to display |
|
537
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
538
|
|
|
* @return string HTML: the box |
|
539
|
|
|
*/ |
|
540
|
|
|
public function boxCertOK(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
541
|
|
|
return $this->boxFlexible(\core\common\Entity::L_CERT_OK, $text, $caption, $omittabletags); |
|
542
|
|
|
} |
|
543
|
|
|
|
|
544
|
|
|
/** |
|
545
|
|
|
* creates HTML code to display a "A certificate close to expiry" message |
|
546
|
|
|
* |
|
547
|
|
|
* @param string $text the text to display |
|
548
|
|
|
* @param string $caption the caption to display |
|
549
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
550
|
|
|
* @return string HTML: the box |
|
551
|
|
|
*/ |
|
552
|
|
|
public function boxCertWarning(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
553
|
|
|
return $this->boxFlexible(\core\common\Entity::L_CERT_WARN, $text, $caption, $omittabletags); |
|
554
|
|
|
} |
|
555
|
|
|
/** |
|
556
|
|
|
* creates HTML code to display a "A certificate expired or dangerously close to expiry" message |
|
557
|
|
|
* |
|
558
|
|
|
* @param string $text the text to display |
|
559
|
|
|
* @param string $caption the caption to display |
|
560
|
|
|
* @param bool $omittabletags the output usually has tr/td table tags, this option suppresses them |
|
561
|
|
|
* @return string HTML: the box |
|
562
|
|
|
*/ |
|
563
|
|
|
public function boxCertError(string $text = NULL, string $caption = NULL, bool $omittabletags = FALSE) { |
|
564
|
|
|
return $this->boxFlexible(\core\common\Entity::L_CERT_ERROR, $text, $caption, $omittabletags); |
|
565
|
|
|
} |
|
566
|
|
|
|
|
567
|
|
|
|
|
568
|
|
|
const QRCODE_PIXELS_PER_SYMBOL = 12; |
|
569
|
|
|
|
|
570
|
|
|
/** |
|
571
|
|
|
* Injects the consortium logo in the middle of a given PNG. |
|
572
|
|
|
* |
|
573
|
|
|
* Usually used on QR code PNGs - the parameters inform about the structure of |
|
574
|
|
|
* the QR code so that the logo does not prevent parsing of the QR code. |
|
575
|
|
|
* |
|
576
|
|
|
* @param string $inputpngstring the PNG to edit |
|
577
|
|
|
* @param int $symbolsize size in pixels of one QR "pixel" |
|
578
|
|
|
* @param int $marginsymbols size in pixels of border around the actual QR |
|
579
|
|
|
* @return string the image with logo centered in the middle |
|
580
|
|
|
*/ |
|
581
|
|
|
public function pngInjectConsortiumLogo(string $inputpngstring, int $symbolsize, int $marginsymbols = 4) { |
|
582
|
|
|
$loggerInstance = new \core\common\Logging(); |
|
583
|
|
|
$inputgd = imagecreatefromstring($inputpngstring); |
|
584
|
|
|
if ($inputgd === FALSE) { // source image is bogus; don't do anything |
|
585
|
|
|
return ""; |
|
586
|
|
|
} |
|
587
|
|
|
|
|
588
|
|
|
$loggerInstance->debug(4, "Consortium logo is at: " . ROOT . "/web/resources/images/consortium_logo_large.png"); |
|
589
|
|
|
$logogd = imagecreatefrompng(ROOT . "/web/resources/images/consortium_logo_large.png"); |
|
590
|
|
|
if ($logogd === FALSE) { // consortium logo is bogus; don't do anything |
|
591
|
|
|
return ""; |
|
592
|
|
|
} |
|
593
|
|
|
$sizeinput = [imagesx($inputgd), imagesy($inputgd)]; |
|
594
|
|
|
$sizelogo = [imagesx($logogd), imagesy($logogd)]; |
|
595
|
|
|
// Q level QR-codes can sustain 25% "damage" |
|
596
|
|
|
// make our logo cover approx 15% of area to be sure; mind that there's a $symbolsize * $marginsymbols pixel white border around each edge |
|
597
|
|
|
$totalpixels = ($sizeinput[0] - $symbolsize * $marginsymbols) * ($sizeinput[1] - $symbolsize * $marginsymbols); |
|
598
|
|
|
$totallogopixels = ($sizelogo[0]) * ($sizelogo[1]); |
|
599
|
|
|
$maxoccupy = $totalpixels * 0.04; |
|
600
|
|
|
// find out how much we have to scale down logo to reach 10% QR estate |
|
601
|
|
|
$scale = sqrt($maxoccupy / $totallogopixels); |
|
602
|
|
|
$loggerInstance->debug(4, "Scaling info: $scale, $maxoccupy, $totallogopixels\n"); |
|
603
|
|
|
// determine final pixel size - round to multitude of $symbolsize to match exact symbol boundary |
|
604
|
|
|
$targetwidth = (int) ($symbolsize * round($sizelogo[0] * $scale / $symbolsize)); |
|
605
|
|
|
$targetheight = (int) ($symbolsize * round($sizelogo[1] * $scale / $symbolsize)); |
|
606
|
|
|
// paint white below the logo, in case it has transparencies (looks bad) |
|
607
|
|
|
// have one symbol in each direction extra white space |
|
608
|
|
|
$whiteimage = imagecreate($targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize); |
|
609
|
|
|
if ($whiteimage === FALSE) { // we can't create an empty canvas. Weird. Stop processing. |
|
610
|
|
|
return ""; |
|
611
|
|
|
} |
|
612
|
|
|
imagecolorallocate($whiteimage, 255, 255, 255); |
|
613
|
|
|
// also make sure the initial placement is a multitude of 12; otherwise "two half" symbols might be affected |
|
614
|
|
|
$targetplacementx = (int) ($symbolsize * round(($sizeinput[0] / 2 - ($targetwidth - $symbolsize + 1) / 2) / $symbolsize)); |
|
615
|
|
|
$targetplacementy = (int) ($symbolsize * round(($sizeinput[1] / 2 - ($targetheight - $symbolsize + 1 ) / 2) / $symbolsize)); |
|
616
|
|
|
imagecopyresized($inputgd, $whiteimage, $targetplacementx - $symbolsize, $targetplacementy - $symbolsize, 0, 0, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize, $targetwidth + 2 * $symbolsize, $targetheight + 2 * $symbolsize); |
|
617
|
|
|
imagecopyresized($inputgd, $logogd, $targetplacementx, $targetplacementy, 0, 0, $targetwidth, $targetheight, $sizelogo[0], $sizelogo[1]); |
|
618
|
|
|
ob_start(); |
|
619
|
|
|
imagepng($inputgd); |
|
620
|
|
|
return ob_get_clean(); |
|
621
|
|
|
} |
|
622
|
|
|
|
|
623
|
|
|
/** |
|
624
|
|
|
* Something went wrong. We display the error cause and then throw an Exception. |
|
625
|
|
|
* |
|
626
|
|
|
* @param string $headerDisplay error to put in the page header |
|
627
|
|
|
* @param string $uiDisplay error string to display |
|
628
|
|
|
* @return void direct output |
|
629
|
|
|
* @throws Exception |
|
630
|
|
|
*/ |
|
631
|
|
|
public function errorPage($headerDisplay, $uiDisplay) { |
|
632
|
|
|
$decoObject = new PageDecoration(); |
|
633
|
|
|
echo $decoObject->pageheader($headerDisplay, "ADMIN-IDP"); |
|
634
|
|
|
echo "<h1>$uiDisplay</h1>"; |
|
635
|
|
|
echo $decoObject->footer(); |
|
636
|
|
|
throw new Exception("Error page raised: $headerDisplay - $uiDisplay."); |
|
637
|
|
|
} |
|
638
|
|
|
|
|
639
|
|
|
/** |
|
640
|
|
|
* creates the HTML code displaying the result of a test that was run previously |
|
641
|
|
|
* |
|
642
|
|
|
* @param \core\SanityTests $test the test that was run |
|
643
|
|
|
* @return string |
|
644
|
|
|
* @throws Exception |
|
645
|
|
|
*/ |
|
646
|
|
|
public function sanityTestResultHTML($test) { |
|
647
|
|
|
$out = ''; |
|
648
|
|
|
switch ($test->test_result['global']) { |
|
649
|
|
|
case \core\common\Entity::L_OK: |
|
650
|
|
|
$message = "Your configuration appears to be fine."; |
|
651
|
|
|
break; |
|
652
|
|
|
case \core\common\Entity::L_WARN: |
|
653
|
|
|
$message = "There were some warnings, but your configuration should work."; |
|
654
|
|
|
break; |
|
655
|
|
|
case \core\common\Entity::L_ERROR: |
|
656
|
|
|
$message = "Your configuration appears to be broken, please fix the errors."; |
|
657
|
|
|
if ($test->fatalError) { |
|
658
|
|
|
$message .= "<br>Some of the errors prevented running additional tests so rerun after fixing."; |
|
659
|
|
|
} |
|
660
|
|
|
break; |
|
661
|
|
|
case \core\common\Entity::L_REMARK: |
|
662
|
|
|
$message = "Your configuration appears to be fine."; |
|
663
|
|
|
break; |
|
664
|
|
|
default: |
|
665
|
|
|
throw new Exception("The result code level " . $test->test_result['global'] . " is not defined!"); |
|
666
|
|
|
} |
|
667
|
|
|
$out .= $this->boxFlexible($test->test_result['global'], "<br><strong>Test Summary</strong><br>" . $message . "<br>See below for details<br><hr>"); |
|
668
|
|
|
foreach ($test->out as $testValue) { |
|
669
|
|
|
foreach ($testValue as $o) { |
|
670
|
|
|
$out .= $this->boxFlexible($o['level'], $o['message']); |
|
671
|
|
|
} |
|
672
|
|
|
} |
|
673
|
|
|
return($out); |
|
674
|
|
|
} |
|
675
|
|
|
/** |
|
676
|
|
|
* prepares data for icons |
|
677
|
|
|
* |
|
678
|
|
|
* @param string $index |
|
679
|
|
|
* @return array |
|
680
|
|
|
*/ |
|
681
|
|
|
public function iconData($index) { |
|
682
|
|
|
\core\common\Entity::intoThePotatoes(); |
|
683
|
|
|
$icons = [ |
|
684
|
|
|
'CERT_STATUS_OK' => ['img' => 'Tabler/certificate-green.svg', 'text' => _("All certificates are valid long enough")], |
|
685
|
|
|
'CERT_STATUS_WARN' => ['img' => 'Tabler/certificate-red.svg', 'text' => _("At least one certificate is close to expiry")], |
|
686
|
|
|
'CERT_STATUS_ERROR' => ['img' => 'Tabler/certificate-off.svg', 'text' => _("At least one certificate either has expired or is very close to expiry")], |
|
687
|
|
|
'OVERALL_OPENROAMING_LEVEL_GOOD' => ['img' => 'Tabler/square-rounded-check-green.svg', 'text' => _("OpenRoaming appears to be configured properly")], |
|
688
|
|
|
'OVERALL_OPENROAMING_LEVEL_NOTE' => ['img' => 'Tabler/info-square-rounded-blue.svg', 'text' => _("There are some minor OpenRoaming configuration issues")], |
|
689
|
|
|
'OVERALL_OPENROAMING_LEVEL_WARN' => ['img' => 'Tabler/info-square-rounded-blue.svg', 'text' => _("There are some avarage level OpenRoaming configuration issues")], |
|
690
|
|
|
'OVERALL_OPENROAMING_LEVEL_ERROR' => ['img' => 'Tabler/alert-square-rounded-red.svg', 'text' => _("There are some critical OpenRoaming configuration issues")], |
|
691
|
|
|
'PROFILES_SHOWTIME' => ['img' => 'Tabler/checks-green.svg', 'text' => _("At least one profile is fully configured and visible in the user interface")], |
|
692
|
|
|
'PROFILES_CONFIGURED' => ['img' => 'Tabler/check-green.svg', 'text' => _("At least one profile is fully configured but none are set as production-ready therefore the institution is not visible in the user interface")], |
|
693
|
|
|
'PROFILES_INCOMPLETE' => ['img' => 'Tabler/access-point-off-red.svg', 'text' => _("No configured profiles")], |
|
694
|
|
|
'PROFILES_REDIRECTED' => ['img' => 'Tabler/external-link.svg', 'text' => _("All active profiles redirected")], |
|
695
|
|
|
'IDP_LINKED' => ['img' => 'Tabler/database-green.svg', 'text' => _("Linked")], |
|
696
|
|
|
'IDP_NOT_LINKED' => ['img' => 'Tabler/database-off-red.svg', 'text' => _("NOT linked")], |
|
697
|
|
|
'CERTS_NOT_SHOWN' => ['img' => 'Tabler/question-mark-blue.svg', 'text' => _("Not showing cert info if no profiles are visible")], |
|
698
|
|
|
]; |
|
699
|
|
|
\core\common\Entity::outOfThePotatoes(); |
|
700
|
|
|
return($icons[$index]); |
|
701
|
|
|
} |
|
702
|
|
|
|
|
703
|
|
|
/** |
|
704
|
|
|
* the HTML img element produced 0n the basis of a simple [src,title] array |
|
705
|
|
|
* @param type array |
|
706
|
|
|
* @return string the img element |
|
707
|
|
|
*/ |
|
708
|
|
|
public function catIcon($data) { |
|
709
|
|
|
return "<img src='../resources/images/icons/".$data['img']."' alt='".$data['text']."' title = '".$data['text']."' class='cat-icon'>"; |
|
710
|
|
|
} |
|
711
|
|
|
} |
|
712
|
|
|
|