Passed
Push — master ( d09326...e58d73 )
by Tomasz
14:59
created

SimpleGUI::displayDeviceDownload()   C

Complexity

Conditions 12
Paths 38

Size

Total Lines 45
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 32
nc 38
nop 0
dl 0
loc 45
rs 5.1612
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* 
3
 *******************************************************************************
4
 * Copyright 2011-2017 DANTE Ltd. and GÉANT on behalf of the GN3, GN3+, GN4-1 
5
 * and GN4-2 consortia
6
 *
7
 * License: see the web/copyright.php file in the file structure
8
 *******************************************************************************
9
 */
10
?>
11
<?php
12
// error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
13
/**
14
 * This file contains the implementation of the simple CAT user interface
15
 * 
16
 * @author Tomasz Wolniewicz <[email protected]>
17
 * 
18
 * @package UserGUI
19
 * 
20
 */
21
22
$loggerInstance = new \core\common\Logging();
23
$loggerInstance->debug(4, "basic.php\n");
24
25
/**
26
 * SimpleGUI defines extensions of the GUI class used only in the simple interface
27
 * this class does not define its own constructor.
28
 */
29
class SimpleGUI extends \core\UserAPI {
30
    /**
31
     *  create the SimpleGUI object calling CAT constructor first
32
     *
33
     *  sets up all public prperties of the object
34
     */
35
    public function __construct() {
36
        parent::__construct();
37
        $validator = new \web\lib\common\InputValidation();
38
        $this->args = [];
39
        $this->page = 0;
40
        $this->languageInstance->setTextDomain('core');
41
        $this->args['lang'] = $this->languageInstance->getLang();
42
43
        /*
44
          The request may contain identifiers of country, idp, profile, device
45
          We require that if an identifiet of a lower level exists then all higher identifiers must also
46
          be present and match. If a mismatch occures that the lower level identifiers are dropped
47
         */
48
49
        if (isset($_REQUEST['reset_dev']) && $_REQUEST['reset_dev'] == 1) {
50
            unset($_REQUEST['device']);
51
        }
52
53
        /* Start with checking if we have the country code if not then use geolocation..
54
         */
55
        $federations = array_keys($this->printCountryList(1));
56
        if (isset($_REQUEST['country']) && $_REQUEST['country']) {
57
            $country = strtoupper($_REQUEST['country']);
58
        } else {
59
            $location = $this->locateUser();
60
            if ($location['status'] == 'ok') {
61
                $country = strtoupper($location['country']);
62
            } else {
63
                $this->loggerInstance->debug(2, "No coutry provided and unable to locate the address\n");
64
                $country = 'NONE';
65
            }
66
        }
67
        if (!in_array($country, $federations)) {
68
            $country = array_shift($federations);
69
        }
70
        $this->country = $validator->Federation($country);
71
        $this->args['country'] = $this->country->tld;
72
        $this->page = 1;
73
74
// If we have IdP identifier then match country to this identifier
75
// if the request contians a country code and an IdP code that do nat match
76
// then drop the IdP code and just leave the country 
77
// If we have Profile identifier then test if we also have IdP identifier, if we do
78
// and they do not match then drop the profile code and just leave the IdP
79
80
        if (isset($_REQUEST['idp']) && $_REQUEST['idp']) {
81
            $this->page = 2;
82
            try {
83
                $this->idp = $validator->IdP($_REQUEST['idp']);
84
            } catch (Exception $fail) {
85
                $this->page = 1;
86
                $this->languageInstance->setTextDomain("web_user");
87
                return;
88
            }
89
            $countryTemp = new \core\Federation($this->idp->federation);
90
            if (strtoupper($this->country->tld) !== strtoupper($countryTemp->tld)) {
91
                unset($this->idp);
92
                $this->page = 1;
93
                $this->languageInstance->setTextDomain("web_user");
94
                return;
95
            }
96
            $this->args['idp'] = $this->idp->identifier;
97
            $this->profileCount = $this->idp->profileCount();
98
            if (!isset($_REQUEST['profile'])) {
99
                $this->languageInstance->setTextDomain("web_user");
100
                return;
101
            }
102
            $this->page = 3;
103
            try {
104
                $this->profile = $validator->Profile($_REQUEST['profile']);
105
            } catch (Exception $fail) {
106
                $this->page = 2;
107
                $this->languageInstance->setTextDomain("web_user");
108
                return;
109
            }
110
            if ($this->profile->institution != $this->idp->identifier) {
111
                unset($this->profile);
112
                $this->page = 2;
113
                $this->languageInstance->setTextDomain("web_user");
114
                return;
115
            }
116
            $this->args['profile'] = $this->profile->identifier;
117
            if (isset($_REQUEST['device'])) {
118
                $this->args['device'] = $validator->Device($_REQUEST['device']);
119
            }
120
        }
121
        $this->languageInstance->setTextDomain("web_user");
122
    }
123
124
// print country selection
125
    public function listCountries() {
126
        $out = '';
127
        $federations = $this->printCountryList(1);
128
        $out .= _('Select your country') . '<br>';
129
        $out .= '<select name="country" onchange="submit_form(this)">' . "\n";
130
        foreach ($federations as $fedId => $fedName) {
131
            $out .= '<option value="' . $fedId . '"';
132
            if ($fedId === $this->country->tld) {
133
                $out .= ' selected';
134
            }
135
            $out .= '>' . $fedName . '</option>' . "\n";
136
        }
137
        $out .= '</select>';
138
        return $out;
139
    }
140
141
    public function listIdPs() {
142
        $instList = $this->orderIdentityProviders($this->country->tld);
143
        $out = '';
144
        $out .= sprintf(_("Select your %s"), $this->nomenclature_inst );
145
        $out .= '<select name="idp" onchange="submit_form(this)">';
146
        if (!empty($instList)) {
147
            if (!isset($this->idp)) {
148
                $this->idp = new \core\IdP($instList[0]['idp']);
149
            }
150
            $idpId = $this->idp->identifier;
151
        }
152
        foreach ($instList as $oneInst) {
153
            $out .= '<option value="' . $oneInst['idp'] . '"';
154
            if ($oneInst['idp'] == $idpId) {
0 ignored issues
show
Bug introduced by
The variable $idpId does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
155
                $out .= ' selected';
156
            }
157
            $out .= '>' . $oneInst['title'] . '</option>';
158
        }
159
        $out .= '</select>';
160
        return $out;
161
    }
162
163
    public function listProfiles() {
164
        if (empty($this->idp)) {
165
            return('');
166
        }
167
        $profiles = $this->idp->listProfiles(TRUE);
168
        if (!isset($this->profile)) {
169
            $this->profile = $profiles[0];
170
        }
171
        $profileId = $this->profile->identifier;
172
        $this->args['profile'] = $profileId;
173
        $out = '';
174
        if (count($profiles) > 1) {
175
            $out .= _("Select the user group") . '<br>';
176
            $out .= '<select name="profile" onchange="submit_form(this)">';
177
            foreach ($profiles as $profile) {
178
                $out .= '<option value="' . $profile->identifier . '"';
179
                if ($profile->identifier == $profileId) {
180
                    $out .= ' selected';
181
                }
182
                $out .= '>' . $profile->name . '</option>';
183
            }
184
            $out .= '</select>';
185
        } else {
186
            $out .= $this->passArgument('profile');
187
        }
188
        return $out;
189
    }
190
191
    public function listProfileDevices() {
192
        if (!isset($this->profile)) {
193
            return '';
194
        }
195
        $detectedOs = $this->detectOS();
196
        $deviceName = $detectedOs['device'];
197
        $this->args['device'] = $deviceName;
198
        $profileRedirect = 0;
199
        $redirectTarget = '';
200
        $deviceRedirects = '';
201
        $selectedOs = 0;
202
        $unsupportedMessage = '<div id="unsupported_os">' . sprintf(_("Your operating system was not properly detected, is not supported yet or cannot be configured with settings provided by your %s"), $this->nomenclature_inst) . "</div><br>";
203
204
        $attributes = $this->profileAttributes($this->profile->identifier);
205
        $thedevices = $attributes['devices'];
206
        $message = '';
207
        if (!$deviceName) {
208
            $message = $unsupportedMessage;
209
        }
210
        if ($attributes['silverbullet']) {
211
            $out = _("You can download your eduroam installer via a personalised invitation link sent from your IT support. Please talk to the IT department to get this link.");
212
            return $out;
213
        }
214
        $out = _("Choose an installer to download") . '<br>';
215
        $out .= '<select name="device" onchange="set_device(this)">';
216
        $iterator = 0;
217
        foreach ($thedevices as $oneDevice) {
218
            if ((isset($oneDevice['options']) && isset($oneDevice['options']['hidden']) && $oneDevice['options']['hidden']) || $oneDevice['status']) {
219
                continue;
220
            }
221
            if (!$deviceName) {
222
                $deviceName = $oneDevice['id'];
223
            }
224
            $disp = $oneDevice['display'];
225
            if ($oneDevice['id'] === '0') {
226
                $profileRedirect = 1;
227
                $redirectTarget = $oneDevice['redirect'];
228
            }
229
            $out .= '<option value="' . $oneDevice['id'] . '"';
230
            if ($oneDevice['id'] == $deviceName) {
231
                $out .= ' selected';
232
                $selectedOs = 1;
233
                if ($oneDevice['redirect']) {
234
                    $redirectTarget = $oneDevice['redirect'];
235
                }
236
            }
237
            $out .= '>' . $disp . '</option>';
238
            $deviceRedirects .= 'redirects[' . $iterator . '] = ' . ( $oneDevice['redirect'] ? 1 : 0 ) . ';';
239
            $iterator++;
240
        }
241
        $out .= '</select>';
242
        if ($selectedOs == 0) {
243
            $message = $unsupportedMessage;
244
        }
245
        $out = $message . $out;
246
        if ($profileRedirect) {
247
            $out = '';
248
        }
249
        if ($redirectTarget) {
250
            $deviceRedirects .= 'is_redirected = 1;';
251
            $out .= _("Your local administrator has specified a redirect to a local support page.") . '<br>' . _("When you click <b>CONTINUE</b> this support page will be opened.");
252
            $action = 'window.location.href=\'' . $redirectTarget . '\'; return(false);';
253
            $out .= "<p><button id='devices' name='devices' style='width:100%;' onclick=\"" . $action . '">' . _("CONTINUE to local support page") . "</button>";
254
        } else {
255
            $deviceRedirects .= 'is_redirected = 0;';
256
            $action = 'submit_form(this)';
257
            $out .= "<p><button id='devices' name='devices' style='width:100%;' onclick=\"" . $action . '">' . sprintf(_("Do you have an account at this %s?"), $this->nomenclature_inst) . '<br>' . _("If so and if the other settings above are OK then click here to download...") . "</button>";
258
        }
259
        $out .= '<script type="text/javascript">' . $deviceRedirects . '</script>';
260
        return $out;
261
    }
262
    
263
    private function displayDownloadHeader() {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
264
        $attributes = $this->profileAttributes($this->profile->identifier);
265
        $out1 = '';
266
        $out = '';
267
        if (!empty($attributes['description'])) {
268
           $out1 .= '<div>' . $attributes['description'] . '</div>';
269
        }
270 View Code Duplication
        if (!empty($attributes['local_email'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
            $out .= '<p>Email: <a href="mailto:' . $attributes['local_email'] . '">' . $attributes['local_email'] . '</a>';
272
        }
273
        if (!empty($attributes['local_url'])) {
274
            $out .= '<p>WWW: <a href="' . $attributes['local_url'] . '">' . $attributes['local_url'] . '</a>';
275
        }
276 View Code Duplication
        if (!empty($attributes['local_phone'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
277
            $out .= '<p>Tel: <a href="' . $attributes['local_phone'] . '">' . $attributes['local_phone'] . '</a>';
278
        }
279
        if ($out !== '') {
280
            $out1 .= '<div class="user_info">';
281
            $out1 .=  sprintf(_("If you encounter problems you should ask for help at your %s"), $this->nomenclature_inst);
282
            $out1 .=  $out;
283
            $out1 .=  "</div>\n";
284
        }
285
        return($out1);
286
    }
287
288
    private function processDevices() {
289
        $this->languageInstance->setTextDomain('devices');
290
        $attributes = $this->profileAttributes($this->profile->identifier);
291
        $thedevices = $attributes['devices'];
292
        $this->languageInstance->setTextDomain("web_user");
293
        $oneDevice = NULL;
294
        foreach ($thedevices as $oneDevice) {
295
            if (\core\common\Entity::getAttributeValue($oneDevice, 'options', 'hidden') === 1) {
296
                continue;
297
            }
298
            if ($oneDevice['id'] === '0') {
299
                print _("Your local administrator has specified a redirect to a local support page.") . ' ' . _("Click on the link below to continue.");
300
                print '<div style="width:100%; text-align:center"><a href ="' . $oneDevice['redirect'] . '">' . $oneDevice['redirect'] . '</a></div>';
301
                exit;
302
            }
303
            if ($oneDevice['id'] === $this->args['device']) {
304
                break;
305
            }
306
        }
307
        return($oneDevice);
308
    }
309
310
    public function displayDeviceDownload() {
311
        $this->languageInstance->setTextDomain("web_user");
312
        print $this->displayDownloadHeader();
313
        $oneDevice = $this->processDevices();
314
        if ($oneDevice === NULL) {
315
            throw new Exception("No useable device found");
316
        }
317
        $this->languageInstance->setTextDomain("web_user");
318
319
        $installer = $this->generateInstaller($this->args['device'], $this->profile->identifier);
320
        if (!$installer['link']) {
321
            print _("This is embarrassing. Generation of your installer failed. System admins have been notified. We will try to take care of the problem as soon as possible.");
322
            return;
323
        }
324
        $extraText = '';
325
        if (isset($oneDevice['message']) && $oneDevice['message']) {
326
            $extraText = $oneDevice['message'];
327
        }
328
        if (isset($oneDevice['device_customtext']) && $oneDevice['device_customtext']) {
329
            if ($extraText) {
330
                $extraText .= '<p>';
331
            }
332
            $extraText .= $oneDevice['device_customtext'];
333
        }
334
        if (isset($oneDevice['eap_customtext']) && $oneDevice['eap_customtext']) {
335
            if ($extraText) {
336
                $extraText .= '<p>';
337
            }
338
            $extraText .= $oneDevice['eap_customtext'];
339
        }
340
        if ($extraText) {
341
            $extraText .= '<p>';
342
        }
343
        print $extraText;
344
345
        $downloadLink = 'user/API.php?action=downloadInstaller&api_version=2&generatedfor=user&lang=' . $this->languageInstance->getLang() . '&device=' . $installer['device'] . '&profile=' . $installer['profile'];
346
347
        print '<p><button id="download_button" onclick="window.location.href=\'' . rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/' . $downloadLink . '\'; return(false)"><div>' . _("Download installer for") . '<br><span style="color:yellow; font-weight: bold">' . $oneDevice['display'] . '</span></div></button>';
348
349
        print '<p><button id="start_over" name="start_over" onclick="submit_form(this)">' . _("Start over") . '</button>';
350
        print $this->passArgument('country');
351
        print $this->passArgument('idp');
352
        print $this->passArgument('profile');
353
        print $this->passArgument('device');
354
    }
355
356
    public function langSelection() {
357
        $out = _("View this page in") . " ";
358
        $out .= '<select onchange="submit_form(this)" name="lang">';
359
        foreach (CONFIG['LANGUAGES'] as $lang => $value) {
360
            $out .= '<option value="' . $lang . '"';
361
            if ($lang === $this->languageInstance->getLang()) {
362
                $out .= ' selected';
363
            }
364
            $out .= '>' . $value['display'] . '</option>';
365
        }
366
        $out .= '</select>';
367
        return $out;
368
    }
369
370
    /**
371
     * displays the navigation bar showing the current location of the page
372
     */
373
    public function yourChoice() {
374
        $capitalisedCountry = strtoupper($this->country->tld);
375
        $countryName = isset($this->knownFederations[$capitalisedCountry]) ? $this->knownFederations[$capitalisedCountry] : $capitalisedCountry;
0 ignored issues
show
Unused Code introduced by
$countryName is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
376
        $countryName = preg_replace('/ +/', '&nbsp;', $name);
0 ignored issues
show
Bug introduced by
The variable $name seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
377
        $out = "$countryName; ";
378
        $name = $this->idp->name;
379
        $name = preg_replace('/ +/', '&nbsp;', $name);
380
        $out .= "$name";
381
        if ($this->profileCount > 1) {
382
            $name = '; ' . $this->profile->name;
383
            $name = preg_replace('/ +/', '&nbsp;', $name);
384
            $out .= "$name";
385
        }
386
        return $out;
387
    }
388
389
    /**
390
     * generates a hidden input field with the given argName
391
     * 
392
     * @param string $argName name of the hidden input field
393
     * @return string
394
     */
395
    public function passArgument($argName) {
396
        return '<input type="hidden" name="' . $argName . '" value="' . $this->args[$argName] . '">';
397
    }
398
399
    public $country;
400
    public $idp;
401
    public $profile;
402
    public $args;
403
    public $profileCount;
404
    public $page;
405
406
}
407
408
$Gui = new SimpleGUI();
409
410
$loggerInstance->debug(4, "\n----------------------------------SIMPLE.PHP------------------------\n");
411
?>
412
<!DOCTYPE html>
413
<?php
414
$langObject = new \core\common\Language();
415
?>
416
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php echo $langObject->getLang() ?>">
417
    <head lang="<?php echo $langObject->getLang() ?>"> 
418
        <title><?php echo CONFIG['APPEARANCE']['productname_long']; ?></title>
419
        <link rel="stylesheet" media="screen" type="text/css" href="<?php echo $skinObject->findResourceUrl("CSS", "cat-basic.css.php"); ?>" />
420
        <meta charset="utf-8" /> 
421
        <script type="text/javascript">
422
            var redirects = new Array();
423
            var is_redirected = 0;
424
            function set_device(s) {
425
                if (redirects[s.selectedIndex] || is_redirected) {
426
                    my_form.submit();
427
                } else {
428
                    return;
429
                }
430
            }
431
            function submit_form(id) {
432
                if (id.name === 'country')
433
                    document.getElementById('reset_dev').value = 1;
434
                if (id.name === 'profile')
435
                    document.getElementById('reset_dev').value = 1;
436
                if (id.name === 'idp')
437
                    document.getElementById('reset_dev').value = 1;
438
                if (id.name === 'start_over')
439
                    document.getElementById('devices_h').value = 0;
440
                if (id.name === 'devices')
441
                    document.getElementById('devices_h').value = 1;
442
                my_form.submit();
443
            }
444
        </script>
445
    </head>
446
    <body style="">
447
        <?php print '<div id="motd">' . ( isset(CONFIG['APPEARANCE']['MOTD']) ? CONFIG['APPEARANCE']['MOTD'] : '&nbsp' ) . '</div>'; ?>
448
        <form name="my_form" method="POST" action="<?php echo $_SERVER['SCRIPT_NAME'] ?>" accept-charset='UTF-8'>
449
            <img src="<?php echo $skinObject->findResourceUrl("IMAGES", "consortium_logo.png"); ?>" style="width: 20%; padding-right:20px; padding-top:0px; float:right" alt="logo" />
450
            <?php
451
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
452
              if($Gui->page == 0) {
453
              print "<h1 style='color:red'>"._("no matching data found")."</h1>";
454
              $Gui->page = 2;
455
              }
456
             */
457
            $langObject = new \core\common\Language();
458
            print '<h1><a href="' . $_SERVER['SCRIPT_NAME'] . '?lang=' . $langObject->getLang() . '">' . CONFIG['APPEARANCE']['productname'] . '</a></h1>';
459
            print $Gui->langSelection();
460
            if (!isset($_REQUEST['devices_h']) || $_REQUEST['devices_h'] == 0 || isset($_REQUEST['start_over'])) {
461
                print "<p>\n";
462
                print $Gui->listCountries();
463
                if ($Gui->page == 2 && !isset($FED[strtoupper($Gui->country->tld)])) {
464
                    $Gui->page = 1;
465
                }
466
                print "<p>" . $Gui->listIdPs();
467
                print "<p>" . $Gui->listProfiles();
468
                print "<p>" . $Gui->listProfileDevices();
469
                print '<input type="hidden" name="devices_h" id="devices_h" value="0">';
470
            } else {
471
                if ($Gui->page != 3) {
472
                    print "Arguments missmatch error.";
473
                    exit;
474
                }
475
                print '<div id="user_choice">' . $Gui->yourChoice() . '</div><p>';
476
                $Gui->displayDeviceDownload();
477
                print '<input type="hidden" name="devices_h" id="devices_h" value="1">';
478
            }
479
            ?>
480
            <input type="hidden" name="reset_dev" id="reset_dev" value="0">
481
        </form>
482
        <div class='footer'><hr />
483
            <?php
484
            print('<a href="tou.php">' . _("Terms of use") . "</a><p>");
485
            echo $Gui->CAT_COPYRIGHT;
486
            echo "</div>";
487
            ?>
488
    </body>
489
</html>
490