Total Complexity | 110 |
Total Lines | 824 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like DeviceConfig often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use DeviceConfig, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
58 | abstract class DeviceConfig extends \core\common\Entity |
||
59 | { |
||
60 | |||
61 | /** |
||
62 | * stores the path to the temporary working directory for a module instance |
||
63 | * @var string $FPATH |
||
64 | */ |
||
65 | public $FPATH; |
||
66 | |||
67 | /** |
||
68 | * array of specialities - will be displayed on the admin download as "footnote" |
||
69 | * @var array specialities |
||
70 | */ |
||
71 | public $specialities; |
||
72 | |||
73 | /** |
||
74 | * list of supported EAP methods |
||
75 | * @var array EAP methods |
||
76 | */ |
||
77 | public $supportedEapMethods; |
||
78 | |||
79 | /** |
||
80 | * |
||
81 | * @var string the realm attached to the profile (possibly substituted with fallback value |
||
82 | */ |
||
83 | public $realm = NULL; |
||
84 | |||
85 | /** |
||
86 | * sets the supported EAP methods for a device |
||
87 | * |
||
88 | * @param array $eapArray the list of EAP methods the device supports |
||
89 | * @return void |
||
90 | */ |
||
91 | protected function setSupportedEapMethods($eapArray) |
||
92 | { |
||
93 | $this->supportedEapMethods = $eapArray; |
||
94 | $this->loggerInstance->debug(4, "This device (" . __CLASS__ . ") supports the following EAP methods: "); |
||
95 | $this->loggerInstance->debug(4, $this->supportedEapMethods); |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * device module constructor should be defined by each module. |
||
100 | * The one important thing to do is to call setSupportedEapMethods with an |
||
101 | * array of EAP methods the device supports |
||
102 | */ |
||
103 | public function __construct() |
||
104 | { |
||
105 | parent::__construct(); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * given one or more server name strings, calculate the suffix that is common |
||
110 | * to all of them |
||
111 | * |
||
112 | * Examples: |
||
113 | * |
||
114 | * ["host.somewhere.com", "gost.somewhere.com"] => "ost.somewhere.com" |
||
115 | * ["my.server.name"] => "my.server.name" |
||
116 | * ["foo.bar.de", "baz.bar.ge"] => "e" |
||
117 | * ["server1.example.com", "server2.example.com", "serverN.example.com"] => ".example.com" |
||
118 | |||
119 | * @return string |
||
120 | */ |
||
121 | public function longestNameSuffix() |
||
122 | { |
||
123 | // for all configured server names, find the string that is the longest |
||
124 | // suffix to all of them |
||
125 | $longestSuffix = ""; |
||
126 | if (!isset($this->attributes["eap:server_name"])) { |
||
127 | return ""; |
||
128 | } |
||
129 | $numStrings = count($this->attributes["eap:server_name"]); |
||
130 | if ($numStrings == 0) { |
||
131 | return ""; |
||
132 | } |
||
133 | // always take the candidate character from the first array element, and |
||
134 | // verify whether the other elements have that character in the same |
||
135 | // position, too |
||
136 | while (TRUE) { |
||
137 | if ($longestSuffix == $this->attributes["eap:server_name"][0]) { |
||
138 | break; |
||
139 | } |
||
140 | $candidate = substr($this->attributes["eap:server_name"][0], -(strlen($longestSuffix) + 1), 1); |
||
141 | for ($iterator = 1; $iterator < $numStrings; $iterator++) { |
||
142 | if (substr($this->attributes["eap:server_name"][$iterator], -(strlen($longestSuffix) + 1), 1) != $candidate) { |
||
143 | break 2; |
||
144 | } |
||
145 | } |
||
146 | $longestSuffix = $candidate.$longestSuffix; |
||
147 | } |
||
148 | return $longestSuffix; |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Set up working environment for a device module |
||
153 | * |
||
154 | * Sets up the device module environment taking into account the actual profile |
||
155 | * selected by the user in the GUI. The selected profile is passed as the |
||
156 | * Profile $profile argument. |
||
157 | * |
||
158 | * This method needs to be called after the device instance has been created (the GUI class does that) |
||
159 | * |
||
160 | * setup performs the following tasks: |
||
161 | * - collect profile attributes and pass them as the attributes property; |
||
162 | * - create the temporary working directory |
||
163 | * - process CA certificates and store them as 'internal:CAs' attribute |
||
164 | * - process and save optional info files and store references to them in |
||
165 | * 'internal:info_file' attribute |
||
166 | * @param AbstractProfile $profile the profile object which will be passed by the caller |
||
167 | * @param string $token the invitation token for silverbullet requests |
||
168 | * @param string $importPassword the PIN for the installer for silverbullet requests |
||
169 | * @return void |
||
170 | * @throws Exception |
||
171 | * @final not to be redefined |
||
172 | */ |
||
173 | final public function setup(AbstractProfile $profile, $token = NULL, $importPassword = NULL, $openRoaming = 0) |
||
174 | { |
||
175 | $this->loggerInstance->debug(4, "module setup start\n"); |
||
176 | common\Entity::intoThePotatoes(); |
||
177 | $purpose = 'installer'; |
||
178 | $eaps = $profile->getEapMethodsinOrderOfPreference(1); |
||
179 | $this->calculatePreferredEapType($eaps); |
||
180 | if (count($this->selectedEap) == 0) { |
||
181 | throw new Exception("No EAP type available."); |
||
182 | } |
||
183 | $this->attributes = $this->getProfileAttributes($profile); |
||
184 | $this->deviceUUID = common\Entity::uuid('', 'CAT'.$profile->institution."-".$profile->identifier."-".$this->device_id); |
||
185 | |||
186 | if (isset($this->attributes['internal:use_anon_outer']) && $this->attributes['internal:use_anon_outer'][0] == "1" && isset($this->attributes['internal:realm'])) { |
||
187 | $this->realm = $this->attributes['internal:realm'][0]; |
||
188 | } |
||
189 | // if we are instantiating a Silverbullet profile AND have been given |
||
190 | // a token, attempt to create the client certificate NOW |
||
191 | // then, this is the only instance of the device ever which knows the |
||
192 | // cert and private key. It's not saved anywhere, so it's gone forever |
||
193 | // after code execution! |
||
194 | |||
195 | $this->loggerInstance->debug(5, "DeviceConfig->setup() - preliminaries done.\n"); |
||
196 | if ($profile instanceof ProfileSilverbullet && $token !== NULL && $importPassword !== NULL) { |
||
197 | $this->clientCert = SilverbulletCertificate::issueCertificate($token, $importPassword, $this->options['clientcert']); |
||
198 | // we need to drag this along; ChromeOS needs it outside the P12 container to encrypt the entire *config* with it. |
||
199 | // Because encrypted private keys are not supported as per spec! |
||
200 | $purpose = 'silverbullet'; |
||
201 | // let's keep a record for which device type this token was consumed |
||
202 | $dbInstance = DBConnection::handle("INST"); |
||
203 | $certId = $this->clientCert['certObject']->dbId; |
||
204 | $this->attributes['internal:username'] = [$this->clientCert['CN']]; |
||
205 | $dbInstance->exec("UPDATE `silverbullet_certificate` SET `device` = ? WHERE `id` = ?", "si", $this->device_id, $certId); |
||
206 | } |
||
207 | $this->loggerInstance->debug(5, "DeviceConfig->setup() - silverbullet checks done.\n"); |
||
208 | // create temporary directory, its full path will be saved in $this->FPATH; |
||
209 | $tempDir = \core\common\Entity::createTemporaryDirectory($purpose); |
||
210 | $this->FPATH = $tempDir['dir']; |
||
211 | mkdir($tempDir['dir'].'/tmp'); |
||
212 | chdir($tempDir['dir'].'/tmp'); |
||
213 | $caList = []; |
||
214 | $x509 = new \core\common\X509(); |
||
215 | if (isset($this->attributes['eap:ca_file'])) { |
||
216 | foreach ($this->attributes['eap:ca_file'] as $ca) { |
||
217 | $processedCert = $x509->processCertificate($ca); |
||
218 | if (is_array($processedCert)) { |
||
219 | // add a UUID for convenience (some devices refer to their CAs by a UUID value) |
||
220 | $processedCert['uuid'] = common\Entity::uuid("", $processedCert['pem']); |
||
221 | $caList[] = $processedCert; |
||
222 | } |
||
223 | } |
||
224 | $this->attributes['internal:CAs'][0] = $caList; |
||
225 | } |
||
226 | |||
227 | if (isset($this->attributes['support:info_file'])) { |
||
228 | $this->attributes['internal:info_file'][0] = $this->saveInfoFile($this->attributes['support:info_file'][0]); |
||
229 | } |
||
230 | if (isset($this->attributes['general:logo_file'])) { |
||
231 | $this->loggerInstance->debug(5, "saving IDP logo\n"); |
||
232 | $this->attributes['internal:logo_file'] = $this->saveLogoFile($this->attributes['general:logo_file'], 'idp'); |
||
233 | } |
||
234 | if (isset($this->attributes['fed:logo_file'])) { |
||
235 | $this->loggerInstance->debug(5, "saving FED logo\n"); |
||
236 | $this->attributes['fed:logo_file'] = $this->saveLogoFile($this->attributes['fed:logo_file'], 'fed'); |
||
237 | } |
||
238 | $this->attributes['internal:SSID'] = $this->getSSIDs()['add']; |
||
239 | |||
240 | $this->attributes['internal:remove_SSID'] = $this->getSSIDs()['del']; |
||
241 | |||
242 | $this->attributes['internal:consortia'] = $this->getConsortia(); |
||
243 | if ($openRoaming == 1 && isset($this->attributes['media:openroaming'])) { |
||
244 | $this->attributes['internal:openroaming'] = TRUE; |
||
245 | } |
||
246 | |||
247 | $this->attributes['internal:networks'] = $this->getNetworks(); |
||
248 | |||
249 | $this->support_email_substitute = sprintf(_("your local %s support"), \config\ConfAssistant::CONSORTIUM['display_name']); |
||
250 | $this->support_url_substitute = sprintf(_("your local %s support page"), \config\ConfAssistant::CONSORTIUM['display_name']); |
||
251 | |||
252 | if ($this->signer && $this->options['sign']) { |
||
253 | $this->sign = ROOT.'/signer/'.$this->signer; |
||
254 | } |
||
255 | $this->installerBasename = $this->getInstallerBasename(); |
||
256 | common\Entity::outOfThePotatoes(); |
||
257 | } |
||
258 | |||
259 | /** |
||
260 | * Selects the preferred eap method based on profile EAP configuration and device EAP capabilities |
||
261 | * |
||
262 | * @param array $eapArrayofObjects an array of eap methods supported by a given device |
||
263 | * @return void |
||
264 | */ |
||
265 | public function calculatePreferredEapType($eapArrayofObjects) |
||
266 | { |
||
267 | $this->selectedEap = []; |
||
268 | foreach ($eapArrayofObjects as $eap) { |
||
269 | if (in_array($eap->getArrayRep(), $this->supportedEapMethods)) { |
||
270 | $this->selectedEap = $eap->getArrayRep(); |
||
271 | break; |
||
272 | } |
||
273 | } |
||
274 | if ($this->selectedEap != []) { |
||
275 | $this->selectedEapObject = new common\EAP($this->selectedEap); |
||
276 | } |
||
277 | } |
||
278 | |||
279 | /** |
||
280 | * prepare usage information for the installer |
||
281 | * every device module should override this method |
||
282 | * |
||
283 | * @return string HTML text to be displayed |
||
284 | */ |
||
285 | public function writeDeviceInfo() |
||
286 | { |
||
287 | common\Entity::intoThePotatoes(); |
||
288 | $retval = _("Sorry, this should not happen - no additional information is available"); |
||
289 | common\Entity::outOfThePotatoes(); |
||
290 | return $retval; |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * function to return exactly one attribute type |
||
295 | * |
||
296 | * @param string $attrName the attribute to retrieve |
||
297 | * @return array|NULL the attributes |
||
298 | */ |
||
299 | public function getAttribute($attrName) |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * some modules have a complex directory structure. This helper finds resources |
||
306 | * in that structure. Mostly used in the Windows modules. |
||
307 | * |
||
308 | * @param string $file the filename to search for (without path) |
||
309 | * @return string|boolean the filename as found, with path, or FALSE if it does not exist |
||
310 | */ |
||
311 | protected function findSourceFile($file) |
||
312 | { |
||
313 | if (is_file($this->module_path.'/Files/'.$this->device_id.'/'.$file)) { |
||
314 | return $this->module_path.'/Files/'.$this->device_id.'/'.$file; |
||
315 | } elseif (is_file($this->module_path.'/Files/'.$file)) { |
||
316 | return $this->module_path.'/Files/'.$file; |
||
317 | } else { |
||
318 | $this->loggerInstance->debug(2, "requested file $file does not exist\n"); |
||
319 | return FALSE; |
||
320 | } |
||
321 | } |
||
322 | |||
323 | /** |
||
324 | * Copy a file from the module location to the temporary directory. |
||
325 | * |
||
326 | * If the second argument is provided then the file will be saved under the name |
||
327 | * taken form this argument. If only one parameter is given, source and destination |
||
328 | * filenames are the same |
||
329 | * Source file can be located either in the Files subdirectory or in the sibdirectory of Files |
||
330 | * named the same as device_id. The second option takes precedence. |
||
331 | * |
||
332 | * @param string $source_name The source file name |
||
333 | * @param string $output_name The destination file name |
||
334 | * |
||
335 | * @return boolean result of the copy operation |
||
336 | * @final not to be redefined |
||
337 | */ |
||
338 | final protected function copyFile($source_name, $output_name = NULL) |
||
354 | } |
||
355 | |||
356 | /** |
||
357 | * Save certificate files in either DER or PEM format |
||
358 | * |
||
359 | * Certificate files will be saved in the module working directory. |
||
360 | * |
||
361 | * saved certificate file names are available under the 'file' index |
||
362 | * additional array entries are indexed as 'sha1', 'md5', and 'root'. |
||
363 | * sha1 and md5 are corresponding certificate hashes |
||
364 | * root is set to 1 for the CA roor certificate and 0 otherwise |
||
365 | * |
||
366 | * @param string $format only "der" and "pem" are currently allowed |
||
367 | * @return array an array of arrays or empty array on error |
||
368 | * @throws Exception |
||
369 | */ |
||
370 | final protected function saveCertificateFiles($format) |
||
371 | { |
||
372 | switch ($format) { |
||
373 | case "der": // fall-thorugh, same treatment |
||
374 | case "pem": |
||
375 | $iterator = 0; |
||
376 | $caFiles = []; |
||
377 | $caArray = $this->attributes['internal:CAs'][0]; |
||
378 | if (!$caArray) { |
||
379 | return([]); |
||
380 | } |
||
381 | foreach ($caArray as $certAuthority) { |
||
382 | $fileHandle = fopen("cert-$iterator.crt", "w"); |
||
383 | if (!$fileHandle) { |
||
384 | throw new Exception("problem opening the file"); |
||
385 | } |
||
386 | if ($format === "pem") { |
||
387 | fwrite($fileHandle, $certAuthority['pem']); |
||
388 | } else { |
||
389 | fwrite($fileHandle, $certAuthority['der']); |
||
390 | } |
||
391 | fclose($fileHandle); |
||
392 | $certAuthorityProps = []; |
||
393 | $certAuthorityProps['file'] = "cert-$iterator.crt"; |
||
394 | $certAuthorityProps['sha1'] = $certAuthority['sha1']; |
||
395 | $certAuthorityProps['md5'] = $certAuthority['md5']; |
||
396 | $certAuthorityProps['root'] = $certAuthority['root']; |
||
397 | $caFiles[] = $certAuthorityProps; |
||
398 | $iterator++; |
||
399 | } |
||
400 | return($caFiles); |
||
401 | default: |
||
402 | $this->loggerInstance->debug(2, 'incorrect format value specified'); |
||
403 | return([]); |
||
404 | } |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * set of characters to remove from filename strings |
||
409 | */ |
||
410 | private const TRANSLIT_SCRUB = '/[ ()\/\'"]+/'; |
||
411 | |||
412 | /** |
||
413 | * Does a transliteration from UTF-8 to ASCII to get a sane filename |
||
414 | * Takes special characters into account, and always uses English CTYPE |
||
415 | * to avoid introduction of funny characters due to "flying accents" |
||
416 | * |
||
417 | * @param string $input the input string that is to be transliterated |
||
418 | * @return string the transliterated string |
||
419 | */ |
||
420 | private function customTranslit($input) |
||
427 | } |
||
428 | |||
429 | /** |
||
430 | * Generate installer filename base. |
||
431 | * Device module should use this name adding an extension. |
||
432 | * Normally the device identifier follows the Consortium name. |
||
433 | * The string taken for the device identifier equals (by default) to the index in the listDevices array, |
||
434 | * but can be overridden with the 'device_id' device option. |
||
435 | * |
||
436 | * @return string |
||
437 | */ |
||
438 | private function getInstallerBasename() |
||
439 | { |
||
440 | $baseName = $this->customTranslit(\config\ConfAssistant::CONSORTIUM['name'])."-".$this->getDeviceId(); |
||
441 | if (isset($this->attributes['profile:customsuffix'][1])) { |
||
442 | // this string will end up as a filename on a filesystem, so always |
||
443 | // take a latin-based language variant if available |
||
444 | // and then scrub non-ASCII just in case |
||
445 | return $baseName.$this->customTranslit($this->attributes['profile:customsuffix'][1]); |
||
446 | } |
||
447 | // Okay, no custom suffix. |
||
448 | // Use the configured inst name and apply shortening heuristics |
||
449 | // if an instshortname is set, base on that, otherwise, the normal instname |
||
450 | $attribToUse = (isset($this->attributes['general:instshortname']) ? 'general:instshortname' : 'general:instname'); |
||
451 | $lang_pointer = \config\Master::LANGUAGES[$this->languageInstance->getLang()]['latin_based'] == TRUE ? 0 : 1; |
||
452 | $this->loggerInstance->debug(5, "getInstallerBasename1:".$this->attributes[$attribToUse][$lang_pointer]."\n"); |
||
453 | $inst = $this->customTranslit($this->attributes[$attribToUse][$lang_pointer]); |
||
454 | $this->loggerInstance->debug(4, "getInstallerBasename2:$inst\n"); |
||
455 | $Inst_a = explode('_', $inst); |
||
456 | if (count($Inst_a) > 2) { |
||
457 | $inst = ''; |
||
458 | foreach ($Inst_a as $i) { |
||
459 | $inst .= $i[0]; |
||
460 | } |
||
461 | } |
||
462 | // and if the inst has multiple profiles, add the profile name behin |
||
463 | if ($this->attributes['internal:profile_count'][0] > 1) { |
||
464 | if (!empty($this->attributes['profile:name']) && !empty($this->attributes['profile:name'][$lang_pointer])) { |
||
465 | $profTemp = $this->customTranslit($this->attributes['profile:name'][$lang_pointer]); |
||
466 | $prof = preg_replace('/_+$/', '', $profTemp); |
||
467 | return $baseName.$inst.'-'.$prof; |
||
468 | } |
||
469 | } |
||
470 | return $baseName . $inst; |
||
471 | } |
||
472 | |||
473 | /** |
||
474 | * returns the device_id of the current device |
||
475 | * |
||
476 | * @return string |
||
477 | */ |
||
478 | private function getDeviceId() |
||
488 | } |
||
489 | |||
490 | /** |
||
491 | * returns the list of SSIDs that installers should treat. |
||
492 | * |
||
493 | * Includes both SSIDs to be set up (and whether it's a TKIP-mixed or AES-only SSID) and SSIDs to be deleted |
||
494 | * |
||
495 | * @return array |
||
496 | */ |
||
497 | private function getSSIDs() |
||
498 | { |
||
499 | $ssidList = []; |
||
500 | $ssidList['add'] = []; |
||
501 | $ssidList['del'] = []; |
||
502 | |||
503 | if (isset(\config\ConfAssistant::CONSORTIUM['ssid'])) { |
||
504 | foreach (\config\ConfAssistant::CONSORTIUM['ssid'] as $ssid) { |
||
505 | $ssidList['add'][$ssid] = 'AES'; |
||
506 | $ssidList['del'][$ssid] = 'TKIP'; |
||
507 | } |
||
508 | } |
||
509 | if (isset($this->attributes['media:SSID'])) { |
||
510 | $ssidWpa2 = $this->attributes['media:SSID']; |
||
511 | |||
512 | foreach ($ssidWpa2 as $ssid) { |
||
513 | $ssidList['add'][$ssid] = 'AES'; |
||
514 | } |
||
515 | } |
||
516 | if (isset($this->attributes['media:remove_SSID'])) { |
||
517 | $ssidRemove = $this->attributes['media:remove_SSID']; |
||
518 | foreach ($ssidRemove as $ssid) { |
||
519 | $ssidList['del'][$ssid] = 'DEL'; |
||
520 | } |
||
521 | } |
||
522 | return $ssidList; |
||
523 | } |
||
524 | |||
525 | /** |
||
526 | * returns the list of Hotspot 2.0 / Passpoint roaming consortia to set up |
||
527 | * |
||
528 | * @return array |
||
529 | */ |
||
530 | private function getConsortia() |
||
545 | } |
||
546 | |||
547 | /** |
||
548 | * return a list of SSIDs defined in the Config networks block |
||
549 | * |
||
550 | * @return array $ssids |
||
551 | */ |
||
552 | private function getConfigSSIDs() |
||
553 | { |
||
554 | $ssids = []; |
||
555 | if (!isset(\config\ConfAssistant::CONSORTIUM['networks'])) { |
||
556 | return []; |
||
557 | } |
||
558 | foreach (\config\ConfAssistant::CONSORTIUM['networks'] as $oneNetwork) { |
||
559 | if (!empty($oneNetwork['ssid'])) { |
||
560 | $ssids = array_merge($ssids, $oneNetwork['ssid']); |
||
561 | } |
||
562 | } |
||
563 | return $ssids; |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * return a list of OIs defined in the Config networks block |
||
568 | * |
||
569 | * @return array $ois |
||
570 | */ |
||
571 | private function getConfigOIs() |
||
572 | { |
||
573 | $ois = []; |
||
574 | if (!isset(\config\ConfAssistant::CONSORTIUM['networks'])) { |
||
575 | return []; |
||
576 | } |
||
577 | foreach (\config\ConfAssistant::CONSORTIUM['networks'] as $oneNetwork) { |
||
578 | if (!empty($oneNetwork['oi'])) { |
||
579 | $ois = array_merge($ois, $oneNetwork['oi']); |
||
580 | } |
||
581 | } |
||
582 | return $ois; |
||
583 | } |
||
584 | |||
585 | /** |
||
586 | * returns the list of parameters for predefined networks to be configured |
||
587 | * |
||
588 | * @return array |
||
589 | */ |
||
590 | private function getNetworks() |
||
591 | { |
||
592 | $additionalConsortia = []; |
||
593 | $additionalSSIDs = []; |
||
594 | $ssids = $this->getConfigSSIDs(); |
||
595 | $ois = $this->getConfigOIs(); |
||
596 | $networks = []; |
||
597 | $realm = $this->realm === NULL ? \config\ConfAssistant::CONSORTIUM['interworking-domainname-fallback'] : $this->realm; |
||
598 | foreach (\config\ConfAssistant::CONSORTIUM['networks'] ?? [] as $netName => $netDetails) { |
||
599 | $netName = preg_replace('/%REALM%/', $this->realm, $netName); |
||
600 | // only add network blocks if their respective condition is met in this profile |
||
601 | if ($netDetails['condition'] === TRUE || (isset($this->attributes[$netDetails['condition']]) && $this->attributes[$netDetails['condition']] === TRUE)) { |
||
602 | $networks[$netName] = $netDetails; |
||
603 | $this->loggerInstance->debug(5,$netName, "\nAdding network: "); |
||
604 | } |
||
605 | } |
||
606 | // add locally defined SSIDs |
||
607 | if (isset($this->attributes['media:SSID'])) { |
||
608 | foreach ($this->attributes['media:SSID'] as $ssid) { |
||
609 | if (!in_array($ssid, $ssids)) { |
||
610 | $additionalSSIDs[] = $ssid; |
||
611 | } |
||
612 | } |
||
613 | } |
||
614 | // add locally defined OIs |
||
615 | if (isset($this->attributes['media:consortium_OI'])) { |
||
616 | foreach ($this->attributes['media:consortium_OI'] as $new_oi) { |
||
617 | if (!in_array($new_oi, $ois)) { |
||
618 | $additionalConsortia[] = $new_oi; |
||
619 | } |
||
620 | } |
||
621 | } |
||
622 | if (!empty($additionalConsortia) || !empty($additionalSSIDs)) { |
||
623 | $networks[sprintf('%s Custom Network', CAT::$nomenclature_participant)] = ['ssid' => $additionalSSIDs, 'oi' => $additionalConsortia, 'condition' => 'locally_defined']; |
||
624 | } |
||
625 | return $networks; |
||
626 | } |
||
627 | |||
628 | /** |
||
629 | * An array with shorthand definitions for MIME types |
||
630 | * @var array |
||
631 | */ |
||
632 | private $mime_extensions = [ |
||
633 | 'text/plain' => 'txt', |
||
634 | 'text/rtf' => 'rtf', |
||
635 | 'application/pdf' => 'pdf', |
||
636 | ]; |
||
637 | |||
638 | /** |
||
639 | * saves a number of logos to a cache directory on disk. |
||
640 | * |
||
641 | * @param array $logos list of logos (binary strings each) |
||
642 | * @param string $type a qualifier what type of logo this is |
||
643 | * @return array list of filenames and the mime types |
||
644 | * @throws Exception |
||
645 | */ |
||
646 | private function saveLogoFile($logos, $type) |
||
672 | } |
||
673 | |||
674 | /** |
||
675 | * saves the Terms of Use file onto disk |
||
676 | * |
||
677 | * @param string $blob the Terms of Use |
||
678 | * @return array with one entry, containing the filename and mime type |
||
679 | * @throws Exception |
||
680 | */ |
||
681 | private function saveInfoFile($blob) |
||
682 | { |
||
683 | $finfo = new \finfo(FILEINFO_MIME_TYPE); |
||
684 | $mime = $finfo->buffer($blob); |
||
685 | $ext = isset($this->mime_extensions[$mime]) ? $this->mime_extensions[$mime] : 'usupported'; |
||
686 | $this->loggerInstance->debug(5, "saveInfoFile: $mime : $ext\n"); |
||
687 | $fileHandle = fopen('local-info.'.$ext, "w"); |
||
688 | if ($fileHandle === FALSE) { |
||
689 | throw new Exception("problem opening the file"); |
||
690 | } |
||
691 | fwrite($fileHandle, $blob); |
||
692 | fclose($fileHandle); |
||
693 | return(['name' => 'local-info.'.$ext, 'mime' => $ext]); |
||
694 | } |
||
695 | |||
696 | /** |
||
697 | * returns the attributes of the profile for which to generate an installer |
||
698 | * |
||
699 | * In condensed notion, and most specific level only (i.e. ignores overridden attributes from a higher level) |
||
700 | * @param \core\AbstractProfile $profile the Profile in question |
||
701 | * @return array |
||
702 | */ |
||
703 | private function getProfileAttributes(AbstractProfile $profile) |
||
714 | } |
||
715 | |||
716 | /** |
||
717 | * dumps attributes for debugging purposes |
||
718 | * |
||
719 | * dumpAttributes method is supplied for debugging purposes, it simply dumps the attribute array |
||
720 | * to a file with name passed in the attribute. |
||
721 | * @param string $file the output file name |
||
722 | * @return void |
||
723 | */ |
||
724 | protected function dumpAttributes($file) |
||
730 | } |
||
731 | |||
732 | /** |
||
733 | * placeholder for the main device method |
||
734 | * @return string |
||
735 | */ |
||
736 | abstract public function writeInstaller(); |
||
737 | |||
738 | /** |
||
739 | * collates the string to use as EAP outer ID |
||
740 | * |
||
741 | * @return string|NULL |
||
742 | */ |
||
743 | protected function determineOuterIdString() |
||
753 | } |
||
754 | |||
755 | /** |
||
756 | * Array passing all options to the device module. |
||
757 | * |
||
758 | * $attributes array contains option values defined for the institution and a particular |
||
759 | * profile (possibly overriding one another) ready for the device module to consume. |
||
760 | * |
||
761 | * For each of the options the value is another array of vales (even if only one value is present). |
||
762 | * Some attributes may be missing if they have not been configured for a viven institution or profile. |
||
763 | * |
||
764 | * The following attributes are meant to be used by device modules: |
||
765 | * - <b>general:geo_coordinates</b> - geographical coordinates of the institution or a campus |
||
766 | * - <b>support:info_file</b> - consent file displayed to the users |
||
767 | * - <b>general:logo_file</b> - file data containing institution logo |
||
768 | * - <b>support:eap_types</b> - URL to a local support page for a specific eap methiod, not to be confused with general:url |
||
769 | * - <b>support:email</b> - email for users to contact for local instructions |
||
770 | * - <b>support:phone</b> - telephone number for users to contact for local instructions |
||
771 | * - <b>support:url</b> - URL where the user will find local instructions |
||
772 | * - <b>internal:info_file</b> - the pathname of the info_file saved in the working directory |
||
773 | * - <b>internal:logo_file</b> - array of pathnames of logo_files saved in the working directory |
||
774 | * - <b>internal:CAs</b> - the value is an array produced by X509::processCertificate() with the following filds |
||
775 | * - <b>internal:consortia</b> an array of consortion IO as declared in the Confassistant config |
||
776 | * - <b>internal:networks</b> - an array of network parameters as declared in the Confassistant config |
||
777 | * - <b>internal:profile_count</b> - the number of profiles for the associated IdP |
||
778 | * |
||
779 | * |
||
780 | * these attributes are available and can be used, but the "internal" attributes are better suited for modules |
||
781 | * - eap:ca_file - certificate of the CA signing the RADIUS server key |
||
782 | * - <b>media:SSID</b> - additional SSID to configure, WPA2/AES only (device modules should use internal:networks) |
||
783 | * |
||
784 | * @var array $attributes |
||
785 | * @see \core\common\X509::processCertificate() |
||
786 | * |
||
787 | */ |
||
788 | public $attributes; |
||
789 | |||
790 | /** |
||
791 | * stores the path to the module source location and is used |
||
792 | * by copyFile and translateFile |
||
793 | * the only reason for it to be a public variable ies that it is set by the DeviceFactory class |
||
794 | * module_path should not be used by module drivers. |
||
795 | * |
||
796 | * @var string |
||
797 | */ |
||
798 | public $module_path; |
||
799 | |||
800 | /** |
||
801 | * The optimal EAP type selected given profile and device |
||
802 | * |
||
803 | * @var array |
||
804 | */ |
||
805 | public $selectedEap; |
||
806 | |||
807 | /** |
||
808 | * The optimal EAP type selected given profile and device, as object |
||
809 | * |
||
810 | * @var \core\common\EAP |
||
811 | */ |
||
812 | public $selectedEapObject; |
||
813 | |||
814 | /** |
||
815 | * the full path to the profile signing program |
||
816 | * device modules which require signing should use this property to exec the signer |
||
817 | * the signer program must accept two arguments - input and output file names |
||
818 | * the signer program mus operate in the local directory and filenames are relative to this |
||
819 | * directory |
||
820 | * |
||
821 | * @var string |
||
822 | */ |
||
823 | public $sign; |
||
824 | |||
825 | /** |
||
826 | * the name of the signer program (without full path) |
||
827 | * |
||
828 | * @var string |
||
829 | */ |
||
830 | public $signer; |
||
831 | |||
832 | /** |
||
833 | * The string identifier of the device (don't show this to users) |
||
834 | * |
||
835 | * @var string |
||
836 | */ |
||
837 | public $device_id; |
||
838 | |||
839 | /** |
||
840 | * See devices-template.php for a list of available options |
||
841 | * |
||
842 | * @var array |
||
843 | */ |
||
844 | public $options; |
||
845 | |||
846 | /** |
||
847 | * This string will be shown if no support email was configured by the admin |
||
848 | * |
||
849 | * @var string |
||
850 | */ |
||
851 | public $support_email_substitute; |
||
852 | |||
853 | /** |
||
854 | * This string will be shown if no support URL was configured by the admin |
||
855 | * |
||
856 | * @var string |
||
857 | */ |
||
858 | public $support_url_substitute; |
||
859 | |||
860 | /** |
||
861 | * This string should be used by all installer modules to set the |
||
862 | * installer file basename. |
||
863 | * |
||
864 | * @var string |
||
865 | */ |
||
866 | public $installerBasename; |
||
867 | |||
868 | /** |
||
869 | * stores the PKCS#12 DER representation of a client certificate for |
||
870 | * SilverBullet along with some metadata in an array |
||
871 | * |
||
872 | * @var array |
||
873 | */ |
||
874 | protected $clientCert = []; |
||
875 | |||
876 | /** |
||
877 | * stores identifier used by GEANTLink profiles |
||
878 | * |
||
879 | * @var string |
||
880 | */ |
||
881 | public $deviceUUID; |
||
882 | } |
||
883 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths