Test Failed
Push — master ( 65d59c...ffd6b9 )
by Stefan
06:48
created

WindowsCommon::getSupport()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 2
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
/*
3
 * *****************************************************************************
4
 * Contributions to this work were made on behalf of the GÉANT project, a 
5
 * project that has received funding from the European Union’s Framework 
6
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
7
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
8
 * 691567 (GN4-1) and No. 731122 (GN4-2).
9
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
10
 * of the copyright in all material which was developed by a member of the GÉANT
11
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
12
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
13
 * UK as a branch of GÉANT Vereniging.
14
 * 
15
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
16
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
17
 *
18
 * License: see the web/copyright.inc.php file in the file structure or
19
 *          <base_url>/copyright.php after deploying the software
20
 */
21
22
/**
23
 * This file contains common functions needed by all Windows installers
24
 * @author Tomasz Wolniewicz <[email protected]>
25
 *
26
 * @package ModuleWriting
27
 */
28
29
namespace devices\ms;
30
use \Exception;
31
32
/**
33
 * This class defines common functions needed by all Windows installers
34
 * @author Tomasz Wolniewicz <[email protected]>
35
 *
36
 * @package ModuleWriting
37
 */
38
abstract class WindowsCommon extends \core\DeviceConfig {
39
40
    public function copyBasicFiles() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
41
        if (!($this->copyFile('wlan_test.exe') &&
42
                $this->copyFile('check_wired.cmd') &&
43
                $this->copyFile('install_wired.cmd') &&
44
                $this->copyFile('cat_bg.bmp') &&
45
                $this->copyFile('base64.nsh'))) {
46
            throw new Exception("Copying needed files (part 1) failed for at least one file!");
47
        }
48
49
        if (!($this->copyFile('cat32.ico') &&
50
                $this->copyFile('cat_150.bmp') &&
51
                $this->copyFile('WLANSetEAPUserData/WLANSetEAPUserData32.exe', 'WLANSetEAPUserData32.exe') &&
52
                $this->copyFile('WLANSetEAPUserData/WLANSetEAPUserData64.exe', 'WLANSetEAPUserData64.exe'))) {
53
            throw new Exception("Copying needed files (part 2) failed for at least one file!");
54
        }
55
        if (!$this->translateFile('common.inc', 'common.nsh', $this->codePage)) {
56
            throw new Exception("Translating needed file common.inc failed!");
57
        }
58
        return;
59
    }
60
61
    public function copyPwdFiles() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
62
        if (!($this->copyFile('Aruba_Networks_EAP-pwd_x32.msi') &&
63
                $this->copyFile('Aruba_Networks_EAP-pwd_x64.msi'))) {
64
            throw new Exception("Copying needed files (EAP-pwd) failed for at least one file!");
65
        }
66
        if (!$this->translateFile('pwd.inc', 'cat.NSI', $this->codePage)) {
67
            throw new Exception("Translating needed file pwd.inc failed!");
68
        }
69
    }
70
71
    public function copyGeantLinkFiles() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
72
        if (!($this->copyFile('GEANTLink/GEANTLink-x86.msi', 'GEANTLink-x86.msi') &&
73
                $this->copyFile('GEANTLink/GEANTLink-x64.msi', 'GEANTLink-x64.msi') &&
74
                $this->copyFile('GEANTLink/GEANTLink-ARM64.msi', 'GEANTLink-ARM64.msi') &&
75
                $this->copyFile('GEANTLink/CredWrite.exe', 'CredWrite.exe') &&
76
                $this->copyFile('GEANTLink/MsiUseFeature.exe', 'MsiUseFeature.exe'))) {
77
            throw new Exception("Copying needed files (GEANTLink) failed for at least one file!");
78
        }
79
        if (!$this->translateFile('geant_link.inc', 'cat.NSI', $this->codePage)) {
80
            throw new Exception("Translating needed file geant_link.inc failed!");
81
        }
82
    }
83
84
85
    /**
86
     * function to escape double quotes in a special NSI-compatible way
87
     * 
88
     * @param string $in input string
89
     * @return string
90
     */
91
    public static function echo_nsi($in) {
0 ignored issues
show
Coding Style introduced by
Method name "WindowsCommon::echo_nsi" is not in camel caps format
Loading history...
92
        echo preg_replace('/"/', '$\"', $in);
93
    }
94
95
    /**
96
     * @param string $input input string
97
     * @return string
98
     */
99
    public static function sprint_nsi($input) {
0 ignored issues
show
Coding Style introduced by
Method name "WindowsCommon::sprint_nsi" is not in camel caps format
Loading history...
100
        return preg_replace('/"/', '$\"', $input);
101
    }
102
103
    public function __construct() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
104
        parent::__construct();
105
        $this->useGeantLink = (isset($this->options['args']) && $this->options['args'] == 'gl') ? 1 : 0;
106
    }
107
108
    protected function prepareInstallerLang() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
109
        if (isset($this->LANGS[$this->languageInstance->getLang()])) {
110
            $language = $this->LANGS[$this->languageInstance->getLang()];
111
            $this->lang = $language['nsis'];
112
            $this->codePage = 'cp' . $language['cp'];
113
        } else {
114
            $this->lang = 'English';
115
            $this->codePage = 'cp1252';
116
        }
117
    }
118
119
    public function writeDeviceInfo() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
120
        $ssids = $this->getAttribute('internal:SSID');
121
        $ssidCount = count($ssids);
122
        $out = "<p>";
123
        $out .= sprintf(_("%s installer will be in the form of an EXE file. It will configure %s on your device, by creating wireless network profiles.<p>When you click the download button, the installer will be saved by your browser. Copy it to the machine you want to configure and execute."), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'], CONFIG_CONFASSISTANT['CONSORTIUM']['display_name']);
124
        $out .= "<p>";
125
        if ($ssidCount > 1) {
126
            if ($ssidCount > 2) {
127
                $out .= sprintf(_("In addition to <strong>%s</strong> the installer will also configure access to the following networks:"), implode(', ', CONFIG_CONFASSISTANT['CONSORTIUM']['ssid'])) . " ";
128
            } else {
129
                $out .= sprintf(_("In addition to <strong>%s</strong> the installer will also configure access to:"), implode(', ', CONFIG_CONFASSISTANT['CONSORTIUM']['ssid'])) . " ";
130
            }
131
            $out .= '<strong>' . join('</strong>, <strong>', array_diff(array_keys($ssids), CONFIG_CONFASSISTANT['CONSORTIUM']['ssid'])) . '</strong>';
0 ignored issues
show
Bug introduced by
It seems like $ssids can also be of type null; however, parameter $input of array_keys() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

131
            $out .= '<strong>' . join('</strong>, <strong>', array_diff(array_keys(/** @scrutinizer ignore-type */ $ssids), CONFIG_CONFASSISTANT['CONSORTIUM']['ssid'])) . '</strong>';
Loading history...
132
            $out .= "<p>";
133
        }
134
// TODO - change this below
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
135
        if ($this->selectedEapObject->isClientCertRequired()) {
136
            $out .= _("In order to connect to the network you will need an a personal certificate in the form of a p12 file. You should obtain this certificate from your organisation. Consult the support page to find out how this certificate can be obtained. Such certificate files are password protected. You should have both the file and the password available during the installation process.");
137
            return($out);
138
        }
139
        // not EAP-TLS
140
        $out .= _("In order to connect to the network you will need an account from your organisation. You should consult the support page to find out how this account can be obtained. It is very likely that your account is already activated.");
141
142
        if (!$this->useGeantLink && $this->selectedEap['OUTER'] == \core\common\EAP::TTLS) {
143
            $out .= "<p>";
144
            $out .= _("When you are connecting to the network for the first time, Windows will pop up a login box, where you should enter your user name and password. This information will be saved so that you will reconnect to the network automatically each time you are in the range.");
145
            if ($ssidCount > 1) {
146
                $out .= "<p>";
147
                $out .= _("You will be required to enter the same credentials for each of the configured networks:") . " ";
148
                $out .= '<strong>' . join('</strong>, <strong>', array_keys($ssids)) . '</strong>';
149
            }
150
        }
151
        return($out);
152
    }    
153
    
154
    private function scaleLogo($imagePath, $maxSize) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
155
        $imageObject = new \Imagick($imagePath);
156
        $imageSize = $imageObject->getImageGeometry();
157
        $imageMax = max($imageSize);
158
        $this->loggerInstance->debug(5, "Logo size: ");
159
        $this->loggerInstance->debug(5, $imageSize);
160
        $this->loggerInstance->debug(5, "max=$imageMax\n");
161
// resize logo if necessary
162
        if ($imageMax > $maxSize) {
163
            if ($imageMax == $imageSize['width']) {
164
                $imageObject->scaleImage($maxSize, 0);
165
            } else {
166
                $imageObject->scaleImage(0, $maxSize);
167
            }
168
        }
169
        $imageSize = $imageObject->getImageGeometry();
170
        $this->background['freeHeight'] -= $imageSize['height'];
171
        return($imageObject);
172
    }
173
174
    protected function combineLogo($logos = NULL, $fedLogo = NULL) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
175
        // maximum size to which we want to resize the logos
176
        
177
        $maxSize = 120;
178
        // $freeTop is set to how much vertical space we need to leave at the top
179
        // this will depend on the design of the background
180
        $freeTop = 70;
181
        // $freeBottom is set to how much vertical space we need to leave at the bottom
182
        // this will depend on the design of the background
183
        $freeBottom = 30;
184
        
185
        $bgImage = new \Imagick('cat_bg.bmp');
186
        $bgImage->setFormat('BMP3');
187
        $bgImageSize = $bgImage->getImageGeometry();
188
        $logosToPlace = [];
189
        $this->background = [];
190
        $this->background['freeHeight'] = $bgImageSize['height'] - $freeTop - $freeBottom;
191
192
        if ($this->getAttribute('fed:include_logo_installers') === NULL) {
193
            $fedLogo = NULL;
194
        }
195
        if ($fedLogo != NULL) {
196
            $logosToPlace[] = $this->scaleLogo($fedLogo[0]['name'], $maxSize);
197
        }
198
        if ($logos != NULL) {
199
            $logosToPlace[] = $this->scaleLogo($logos[0]['name'], $maxSize);
200
        }
201
202
        $logoCount = count($logosToPlace);
203
        if ($logoCount > 0) {
204
            $voffset = $freeTop;
205
            $freeSpace = (int)round($this->background['freeHeight'] / ($logoCount + 1));
206
            foreach ($logosToPlace as $logo) {
207
                $voffset += $freeSpace;
208
                $logoSize = $logo->getImageGeometry();
209
                $hoffset = (int)round(($bgImageSize['width'] - $logoSize['width']) / 2);
210
                $bgImage->compositeImage($logo, $logo->getImageCompose(), $hoffset, $voffset);
211
                $voffset += $logoSize['height'];
212
                }
213
        }
214
//new image is saved as the background
215
        $bgImage->writeImage('BMP3:cat_bg.bmp');
216
    }
217
218
    protected function signInstaller() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
219
        $fileName = $this->installerBasename . '.exe';
220
        if (!$this->sign) {
221
            rename("installer.exe", $fileName);
222
            return $fileName;
223
        }
224
        // are actually signing
225
        $outputFromSigning = system($this->sign . " installer.exe '$fileName' > /dev/null");
226
        if ($outputFromSigning === FALSE) {
227
            $this->loggerInstance->debug(2, "Signing the WindowsCommon installer $fileName FAILED!\n");
228
        }
229
        return $fileName;
230
    }
231
232
    protected function compileNSIS() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
233
        if (CONFIG_CONFASSISTANT['NSIS_VERSION'] >= 3) {
234
            $makensis = CONFIG_CONFASSISTANT['PATHS']['makensis'] . " -INPUTCHARSET UTF8";
235
        } else {
236
            $makensis = CONFIG_CONFASSISTANT['PATHS']['makensis'];
237
        }
238
        $lcAll = getenv("LC_ALL");
239
        putenv("LC_ALL=en_US.UTF-8");
240
        $command = $makensis . ' -V4 cat.NSI > nsis.log 2>&1';
241
        system($command);
242
        putenv("LC_ALL=" . $lcAll);
243
        $this->loggerInstance->debug(4, "compileNSIS:$command\n");
244
    }
245
246
    private function getSupport($attr, $type) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
247
        $supportString = [
248
            'email' => 'SUPPORT',
249
            'url' => 'URL',
250
        ];
251
        $s = "support_" . $type . "_substitute";
252
        $substitute = $this->translateString($this->$s, $this->codePage);
253
        $returnValue = !empty($attr['support:' . $type][0]) ? $attr['support:' .  $type][0] : $substitute;
254
        return('!define ' . $supportString[$type] . ' "' . $returnValue . '"' . "\n");
255
    }
256
    
257
    
258
    protected function writeNsisDefines($attr) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
259
        $fcontents = "\n" . '!define NSIS_MAJOR_VERSION ' . CONFIG_CONFASSISTANT['NSIS_VERSION'];
260
        if ($attr['internal:profile_count'][0] > 1) {
261
            $fcontents .= "\n" . '!define USER_GROUP "' . $this->translateString(str_replace('"', '$\\"', $attr['profile:name'][0]), $this->codePage) . '"
262
';
263
        }
264
        $fcontents .=  '
265
Caption "' . $this->translateString(sprintf(WindowsCommon::sprint_nsi(_("%s installer for %s")), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'], $attr['general:instname'][0]), $this->codePage) . '"
266
!define APPLICATION "' . $this->translateString(sprintf(WindowsCommon::sprint_nsi(_("%s installer for %s")), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'], $attr['general:instname'][0]), $this->codePage) . '"
267
!define VERSION "' . \core\CAT::VERSION_MAJOR . '.' . \core\CAT::VERSION_MINOR . '"
268
!define INSTALLER_NAME "installer.exe"
269
!define LANG "' . $this->lang . '"
270
!define LOCALE "' . preg_replace('/\..*$/', '', CONFIG['LANGUAGES'][$this->languageInstance->getLang()]['locale']) . '"
271
;--------------------------------
272
!define ORGANISATION "' . $this->translateString($attr['general:instname'][0], $this->codePage) . '"
273
';
274
        $fcontents .= $this->getSupport($attr, 'email');
275
        $fcontents .= $this->getSupport($attr, 'url');                
276
        if (\core\common\Entity::getAttributeValue($attr, 'media:wired', 0) == 'on') {
277
            $fcontents .= '!define WIRED
278
        ';
279
        }
280
        $fcontents .= '!define PROVIDERID "urn:UUID:' . $this->deviceUUID . '"
281
';
282
        if (!empty($attr['internal:realm'][0])) {
283
            $fcontents .= '!define REALM "' . $attr['internal:realm'][0] . '"
284
';
285
        }
286
        if(!empty($attr['internal:hint_userinput_suffix'][0]) && $attr['internal:hint_userinput_suffix'][0] == 1) {
287
            $fcontents .= '!define HINT_USER_INPUT "' . $attr['internal:hint_userinput_suffix'][0] . '"
288
';
289
        }
290
        if(!empty($attr['internal:verify_userinput_suffix'][0]) && $attr['internal:verify_userinput_suffix'][0] == 1) {
291
            $fcontents .= '!define VERIFY_USER_REALM_INPUT "' . $attr['internal:verify_userinput_suffix'][0] . '"
292
';
293
        }
294
        $fcontents .= $this->msInfoFile($attr);
295
        return($fcontents);
296
           
297
    }
298
    
299
    protected function msInfoFile($attr) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
300
        $out = '';
301
        if (isset($attr['support:info_file'])) {
302
            $out .= '!define EXTERNAL_INFO "';
303
//  $this->loggerInstance->debug(4,"Info file type ".$attr['support:info_file'][0]['mime']."\n");
304
            if ($attr['internal:info_file'][0]['mime'] == 'rtf') {
305
                $out = '!define LICENSE_FILE "' . $attr['internal:info_file'][0]['name'];
306
            } elseif ($attr['internal:info_file'][0]['mime'] == 'txt') {
307
                $infoFile = file_get_contents($attr['internal:info_file'][0]['name']);
308
                if ($infoFile === FALSE) {
309
                    throw new Exception("We were told this file exists. Failing to read it is not really possible.");
310
                }
311
                if (CONFIG_CONFASSISTANT['NSIS_VERSION'] >= 3) {
312
                    $infoFileConverted = $infoFile;
313
                } else {
314
                    $infoFileConverted = iconv('UTF-8', $this->codePage . '//TRANSLIT', $infoFile);
315
                }
316
                if ($infoFileConverted !== FALSE && strlen($infoFileConverted) > 0) {
317
                    file_put_contents('info_f.txt', $infoFileConverted);
318
                    $out = '!define LICENSE_FILE " info_f.txt';
319
                }
320
            } else {
321
                $out = '!define EXTERNAL_INFO "' . $attr['internal:info_file'][0]['name'];
322
            }
323
324
            $out .= "\"\n";
325
        }
326
        $this->loggerInstance->debug(4, "Info file returned: $out");
327
        return $out;
328
    }
329
330
    protected function writeAdditionalDeletes($profiles) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
331
        if (count($profiles) == 0) {
332
            return;
333
        }
334
        $fileHandle = fopen('profiles.nsh', 'a');
335
        if ($fileHandle === FALSE) {
336
            throw new Exception("Unable to open possibly pre-existing profiles.nsh to append additional deletes.");
337
        }
338
        fwrite($fileHandle, "!define AdditionalDeletes\n");
339
        foreach ($profiles as $profile) {
340
            fwrite($fileHandle, "!insertmacro define_delete_profile \"$profile\"\n");
341
        }
342
        fclose($fileHandle);
343
    }
344
345
    protected function writeClientP12File() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
346
        if (!is_array($this->clientCert)) {
347
            throw new Exception("the client block was called but there is no client certificate!");
348
        }
349
        file_put_contents('SB_cert.p12', $this->clientCert["certdata"]);
350
    }
351
352
    protected function writeTlsUserProfile() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
353
        
354
    }
355
356
    public $LANGS = [
357
        'fr' => ['nsis' => "French", 'cp' => '1252'],
358
        'de' => ['nsis' => "German", 'cp' => '1252'],
359
        'es' => ['nsis' => "SpanishInternational", 'cp' => '1252'],
360
        'it' => ['nsis' => "Italian", 'cp' => '1252'],
361
        'nl' => ['nsis' => "Dutch", 'cp' => '1252'],
362
        'sv' => ['nsis' => "Swedish", 'cp' => '1252'],
363
        'fi' => ['nsis' => "Finnish", 'cp' => '1252'],
364
        'pl' => ['nsis' => "Polish", 'cp' => '1250'],
365
        'ca' => ['nsis' => "Catalan", 'cp' => '1252'],
366
        'sr' => ['nsis' => "SerbianLatin", 'cp' => '1250'],
367
        'hr' => ['nsis' => "Croatian", 'cp' => '1250'],
368
        'sl' => ['nsis' => "Slovenian", 'cp' => '1250'],
369
        'da' => ['nsis' => "Danish", 'cp' => '1252'],
370
        'nb' => ['nsis' => "Norwegian", 'cp' => '1252'],
371
        'nn' => ['nsis' => "NorwegianNynorsk", 'cp' => '1252'],
372
        'el' => ['nsis' => "Greek", 'cp' => '1253'],
373
        'ru' => ['nsis' => "Russian", 'cp' => '1251'],
374
        'pt' => ['nsis' => "Portuguese", 'cp' => '1252'],
375
        'uk' => ['nsis' => "Ukrainian", 'cp' => '1251'],
376
        'cs' => ['nsis' => "Czech", 'cp' => '1250'],
377
        'sk' => ['nsis' => "Slovak", 'cp' => '1250'],
378
        'bg' => ['nsis' => "Bulgarian", 'cp' => '1251'],
379
        'hu' => ['nsis' => "Hungarian", 'cp' => '1250'],
380
        'ro' => ['nsis' => "Romanian", 'cp' => '1250'],
381
        'lv' => ['nsis' => "Latvian", 'cp' => '1257'],
382
        'mk' => ['nsis' => "Macedonian", 'cp' => '1251'],
383
        'et' => ['nsis' => "Estonian", 'cp' => '1257'],
384
        'tr' => ['nsis' => "Turkish", 'cp' => '1254'],
385
        'lt' => ['nsis' => "Lithuanian", 'cp' => '1257'],
386
        'ar' => ['nsis' => "Arabic", 'cp' => '1256'],
387
        'he' => ['nsis' => "Hebrew", 'cp' => '1255'],
388
        'id' => ['nsis' => "Indonesian", 'cp' => '1252'],
389
        'mn' => ['nsis' => "Mongolian", 'cp' => '1251'],
390
        'sq' => ['nsis' => "Albanian", 'cp' => '1252'],
391
        'br' => ['nsis' => "Breton", 'cp' => '1252'],
392
        'be' => ['nsis' => "Belarusian", 'cp' => '1251'],
393
        'is' => ['nsis' => "Icelandic", 'cp' => '1252'],
394
        'ms' => ['nsis' => "Malay", 'cp' => '1252'],
395
        'bs' => ['nsis' => "Bosnian", 'cp' => '1250'],
396
        'ga' => ['nsis' => "Irish", 'cp' => '1250'],
397
        'uz' => ['nsis' => "Uzbek", 'cp' => '1251'],
398
        'gl' => ['nsis' => "Galician", 'cp' => '1252'],
399
        'af' => ['nsis' => "Afrikaans", 'cp' => '1252'],
400
        'ast' => ['nsis' => "Asturian", 'cp' => '1252'],
401
    ];
402
    public $codePage;
403
    public $lang;
404
    public $useGeantLink;
405
    private $background;
406
407
}
408