Completed
Push — next ( 3cfa04...53c79d )
by Thomas
07:00
created

OcSmarty::acceptsAndPurifiesHtmlInput()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/***************************************************************************
3
 * for license information see LICENSE.md
4
 *  Inherit Smarty-Class and extend it
5
 ***************************************************************************/
6
7
use Oc\Util\CBench;
8
9
require_once __DIR__ . '/../vendor/autoload.php';
10
require_once __DIR__ . '/db.inc.php';
11
require_once __DIR__ . '/logic/labels.inc.php';
12
13
/**
14
 * Class OcSmarty
15
 */
16
class OcSmarty extends Smarty
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
17
{
18
    public $name = 'sys_nothing';
19
    public $main_template = 'sys_main';
20
    public $bench = null;
21
    public $compile_id = null;
22
    public $cache_id = null;    // This is a smarty caching ID, not a caches.cache_id.
23
    public $title = '';
24
    public $menuitem = null;
25
    public $nowpsearch = false;
26
    public $change_country_inpage = false;
27
28
    // no header, menu or footer
29
    public $popup = false;
30
31
    // show a thin border when using popup
32
    // disable popupmargin to appear fullscreen
33
    public $popupmargin = true;
34
35
    // url to call if login is required
36
    public $target = '';
37
38
    public $header_javascript = [];
39
    public $body_load = [];
40
    public $body_unload = [];
41
42
    /**
43
     * OcSmarty constructor.
44
     */
45
    public function __construct()
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
46
    {
47
        global $opt;
48
        $this->bench = new CBench();
49
        $this->bench->start();
50
51
        // configuration
52
        $this->template_dir = $opt['stylepath'];
53
        $this->compile_dir = __DIR__ . '/../var/cache2/smarty/compiled/';
54
        $this->cache_dir = __DIR__ . '/../var/cache2/smarty/cache/';
55
        $this->plugins_dir = [
56
            'plugins',
57
            __DIR__ . '/../src/OcLegacy/SmartyPlugins'
58
        ];
59
60
        // disable caching ... if caching is enabled, 1 hour is default
61
        $this->caching = false;
0 ignored issues
show
Documentation Bug introduced by
The property $caching was declared of type integer, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
62
        $this->cache_lifetime = 3600; // default
63
64
        // register additional functions
65
        require_once __DIR__ . '/../src/OcLegacy/SmartyPlugins/block.nocache.php';
66
        $this->register_block('nocache', 'smarty_block_nocache', false);
67
        $this->load_filter('pre', 't');
68
69
        if ($opt['session']['mode'] == SAVE_SESSION) {
70
            $this->load_filter('output', 'session');
71
        }
72
73
        // cache control
74
        if (($opt['debug'] & DEBUG_TEMPLATES) == DEBUG_TEMPLATES) {
75
            $this->force_compile = true;
76
        }
77
78
        // site maintenance
79
        if (($opt['debug'] & DEBUG_OUTOFSERVICE) == DEBUG_OUTOFSERVICE) {
80
            $this->name = 'sys_outofservice';
81
            $this->display();
82
        }
83
84
        /* set login target
85
         */
86
        if (isset($_REQUEST['target'])) {
87
            $this->target = trim($_REQUEST['target']);
88
            if (preg_match("/^https?:/i", $this->target)) {
89
                $this->target = '';
90
            }
91
        } else {
92
            $target = basename($_SERVER['PHP_SELF']) . '?';
93
94
            // REQUEST-Variablen durchlaufen und an target anhaengen
95
            reset($_REQUEST);
96
            while (list($varname, $varvalue) = each($_REQUEST)) {
97
                if (in_array($varname, $opt['logic']['targetvars'])) {
98
                    $target .= urlencode($varname) . '=' . urlencode($varvalue) . '&';
99
                }
100
            }
101
            reset($_REQUEST);
102
103 View Code Duplication
            if (mb_substr($target, -1) == '?' || mb_substr($target, -1) == '&') {
104
                $target = mb_substr($target, 0, -1);
105
            }
106
107
            $this->target = $target;
108
        }
109
    }
110
111
    /* ATTENTION: copied from internal implementation!
112
     */
113
    /**
114
     * @param string $resource_name
115
     * @param string $compile_id
116
     */
117
    public function compile($resource_name, $compile_id = null)
118
    {
119
        if (!isset($compile_id)) {
120
            $compile_id = $this->compile_id;
121
        }
122
123
        $this->_compile_id = $compile_id;
124
125
        // load filters that are marked as autoload
126
        if (count($this->autoload_filters)) {
127
            foreach ($this->autoload_filters as $_filter_type => $_filters) {
128
                foreach ($_filters as $_filter) {
129
                    $this->load_filter($_filter_type, $_filter);
130
                }
131
            }
132
        }
133
134
        $_smarty_compile_path = $this->_get_compile_path($resource_name);
135
136
        // if we just need to display the results, don't perform output
137
        // buffering - for speed
138
        $_cache_including = $this->_cache_including;
139
        $this->_cache_including = false;
0 ignored issues
show
Documentation Bug introduced by
The property $_cache_including was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
140
141
        // compile the resource
142
        if (!$this->_is_compiled($resource_name, $_smarty_compile_path)) {
143
            $this->_compile_resource($resource_name, $_smarty_compile_path);
144
        }
145
146
        $this->_cache_including = $_cache_including;
147
    }
148
149
    /**
150
     * @param null $dummy1
151
     * @param null $dummy2
152
     * @param null $dummy3
153
     */
154
    public function display($dummy1 = null, $dummy2 = null, $dummy3 = null)
0 ignored issues
show
Coding Style introduced by
display uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
display uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
display uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
155
    {
156
        global $opt, $db, $cookie, $login, $menu, $sqldebugger, $translate, $useragent_msie;
157
        $cookie->close();
158
159
        // if the user is an admin, don't cache the content
160
        if (isset($login)) {
161
            if ($login->admin) {
162
                $this->caching = false;
0 ignored issues
show
Documentation Bug introduced by
The property $caching was declared of type integer, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
163
            }
164
        }
165
166
        //Give Smarty access to the whole options array.
167
        $this->assign('siteSettings', $opt);
168
169
        //Should we remove this whole block since we now have
170
        //access using the siteSettings above?
171
        // assign main template vars
172
        // ... and some of the $opt
173
        $locale = $opt['template']['locale'];
174
175
        $optn['debug'] = $opt['debug'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$optn was never initialized. Although not strictly required by PHP, it is generally a good practice to add $optn = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
176
        $optn['template']['locales'] = $opt['template']['locales'];
177
        $optn['template']['locale'] = $opt['template']['locale'];
178
        $optn['template']['style'] = $opt['template']['style'];
179
        $optn['template']['country'] = $login->getUserCountry();
0 ignored issues
show
Bug introduced by
The method getUserCountry cannot be called on $login (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
180
        $optn['page']['subtitle1'] = isset($opt['locale'][$locale]['page']['subtitle1']) ? $opt['locale'][$locale]['page']['subtitle1'] : $opt['page']['subtitle1'];
181
        $optn['page']['subtitle2'] = isset($opt['locale'][$locale]['page']['subtitle2']) ? $opt['locale'][$locale]['page']['subtitle2'] : $opt['page']['subtitle2'];
182
        $optn['page']['sitename'] = $opt['page']['sitename'];
183
        $optn['page']['headimagepath'] = $opt['page']['headimagepath'];
184
        $optn['page']['headoverlay'] = $opt['page']['headoverlay'];
185
        $optn['page']['max_logins_per_hour'] = $opt['page']['max_logins_per_hour'];
186
        $optn['page']['absolute_url'] = $opt['page']['absolute_url'];
187
        $optn['page']['absolute_urlpath'] = parse_url($opt['page']['absolute_url'], PHP_URL_PATH);
188
        $optn['page']['absolute_http_url'] = $opt['page']['absolute_http_url'];
189
        $optn['page']['default_absolute_url'] = $opt['page']['default_absolute_url'];
190
        $optn['page']['login_url'] = ($opt['page']['https']['force_login'] ? $opt['page']['absolute_https_url'] : '') . 'login.php';
191
        $optn['page']['target'] = $this->target;
192
        $optn['page']['showdonations'] = $opt['page']['showdonations'];
193
        $optn['page']['title'] = $opt['page']['title'];
194
        $optn['page']['nowpsearch'] = $this->nowpsearch;
195
        $optn['page']['header_javascript'] = $this->header_javascript;
196
        $optn['page']['body_load'] = $this->body_load;
197
        $optn['page']['body_unload'] = $this->body_unload;
198
        $optn['page']['sponsor'] = $opt['page']['sponsor'];
199
        $optn['page']['showsocialmedia'] = $opt['page']['showsocialmedia'];
200
        $optn['page']['main_country'] = $opt['page']['main_country'];
201
        $optn['page']['main_locale'] = $opt['page']['main_locale'];
202
        $optn['page']['meta'] = $opt['page']['meta'];
203
        $optn['page']['teampic_url'] = $opt['page']['teampic_url'];
204
        $optn['page']['teammember_url'] = $opt['page']['teammember_url'];
205
        $optn['template']['title'] = $this->title;
206
        $optn['template']['caching'] = $this->caching;
207
        $optn['template']['popup'] = $this->popup;
208
        $optn['template']['popupmargin'] = $this->popupmargin;
209
        $optn['format'] = $opt['locale'][$opt['template']['locale']]['format'];
210
        $optn['mail'] = $opt['mail'];
211
        $optn['lib'] = $opt['lib'];
212
        $optn['tracking'] = $opt['tracking'];
213
        $optn['geokrety'] = $opt['geokrety'];
214
        $optn['template']['usercountrieslist'] = labels::getLabels('usercountrieslist');
215
        $optn['help']['oconly'] = helppagelink('oconly', 'OConly');
0 ignored issues
show
Unused Code introduced by
The call to helppagelink() has too many arguments starting with 'OConly'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
216
        $optn['msie'] = $useragent_msie;
217
218
        // url-sessions? (for session timout display)
219
        $optn['session']['url'] = false;
220
        if ($opt['session']['mode'] == SAVE_SESSION && $login->userid != 0) {
221
            if (isset($_GET['SESSION']) || isset($_POST['SESSION'])) {
222
                $optn['session']['url'] = true;
223
            }
224
225
            $optn['session']['id'] = session_id();
226
        }
227
228
        if (isset($login)) {
229
            $loginn['username'] = $login->username;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$loginn was never initialized. Although not strictly required by PHP, it is generally a good practice to add $loginn = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
230
            $loginn['userid'] = $login->userid;
231
            $loginn['admin'] = $login->admin;
232
        } else {
233
            $loginn['username'] = '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$loginn was never initialized. Although not strictly required by PHP, it is generally a good practice to add $loginn = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
234
            $loginn['userid'] = '';
235
            $loginn['admin'] = '';
236
        }
237
238
        // build menu
239
        if ($this->menuitem == null) {
240
            $menu->SetSelectItem(MNU_ROOT);
241
        } else {
242
            $menu->SetSelectItem($this->menuitem);
243
        }
244
245
        $this->assign('topmenu', $menu->getTopMenu());
246
        $this->assign('submenu', $menu->getSubMenu());
247
        $this->assign('breadcrumb', $menu->getBreadcrumb());
248
        $this->assign('menucolor', $menu->getMenuColor());
249
        $this->assign('helplink', helppagelink($this->name));
250
        $this->assign('change_country_inpage', $this->change_country_inpage);
251
252
        if ($this->title == '') {
253
            $optn['template']['title'] = $menu->GetMenuTitle();
254
        }
255
256
        // build address for switching locales and countries
257
        $base_pageadr = $_SERVER['REQUEST_URI'];
258
259
        // workaround for http://redmine.opencaching.de/issues/703
260
        $strange_things_pos = strpos($base_pageadr, '.php/');
261
        if ($strange_things_pos) {
262
            $base_pageadr = substr($base_pageadr, 0, $strange_things_pos + 4);
263
        }
264
        $lpos = strpos($base_pageadr, 'locale=');
265
        if ($this->change_country_inpage) {
266
            if (!$lpos) {
267
                $lpos = strpos($base_pageadr, 'usercountry=');
268
            }
269
            if (!$lpos) {
270
                $lpos = strpos($base_pageadr, 'country=');
271
            }
272
        }
273
        if ($lpos) {
274
            $base_pageadr = substr($base_pageadr, 0, $lpos);
275
        } else {
276
            $urx = explode('#', $base_pageadr);
277
            $base_pageadr = $urx[0];
278
            if (strpos($base_pageadr, '?') == 0) {
279
                $base_pageadr .= '?';
280
            } else {
281
                $base_pageadr .= '&';
282
            }
283
        }
284
        $this->assign('base_pageadr', $base_pageadr);
285
286
        if ($opt['logic']['license']['disclaimer']) {
287 View Code Duplication
            if (isset($opt['locale'][$locale]['page']['license_url'])) {
288
                $lurl = $opt['locale'][$locale]['page']['license_url'];
289
            } else {
290
                $lurl = $opt['locale']['EN']['page']['license_url'];
291
            }
292
293
            if (isset($opt['locale'][$locale]['page']['license'])) {
294
                $ltext = mb_ereg_replace(
295
                    '{site}',
296
                    $opt['page']['sitename'],
297
                    $opt['locale'][$locale]['page']['license']
298
                );
299
            } else {
300
                $ltext = $opt['locale']['EN']['page']['license'];
301
            }
302
303
            $this->assign('license_disclaimer', mb_ereg_replace('%1', $lurl, $ltext));
304
        } else {
305
            $this->assign('license_disclaimer', '');
306
        }
307
308
        $this->assign('opt', $optn);
309
        $this->assign('login', $loginn);
310
311
        if ($db['connected'] == true) {
312
            $this->assign('sys_dbconnected', true);
313
        } else {
314
            $this->assign('sys_dbconnected', false);
315
        }
316
        $this->assign('sys_dbslave', ($db['slave_id'] != -1));
317
318
        if ($this->template_exists($this->name . '.tpl')) {
319
            $this->assign('template', $this->name);
320
        } elseif ($this->name != 'sys_error') {
321
            $this->error(ERROR_TEMPLATE_NOT_FOUND);
322
        }
323
324
        $this->bench->stop();
325
        $this->assign('sys_runtime', $this->bench->diff());
326
327
        $this->assign(
328
            'screen_css_time',
329
            filemtime(__DIR__ . '/../resource2/' . $opt['template']['style'] . '/css/style_screen.css')
330
        );
331
        $this->assign(
332
            'screen_msie_css_time',
333
            filemtime(__DIR__ . '/../resource2/' . $opt['template']['style'] . '/css/style_screen_msie.css')
334
        );
335
        $this->assign(
336
            'print_css_time',
337
            filemtime(__DIR__ . '/../resource2/' . $opt['template']['style'] . '/css/style_print.css')
338
        );
339
340
        // check if the template is compiled
341
        // if not, check if translation works correct
342
        $_smarty_compile_path = $this->_get_compile_path($this->name);
343
        if (!$this->_is_compiled($this->name, $_smarty_compile_path) && $this->name != 'error') {
344
            $internal_lang = $translate->t('INTERNAL_LANG', 'all', 'OcSmarty.class.php', '');
345
            if (($internal_lang != $opt['template']['locale']) && ($internal_lang != 'INTERNAL_LANG')) {
346
                $this->error(ERROR_COMPILATION_FAILED);
347
            }
348
        }
349
350
        if ($this->is_cached() == true) {
351
            $this->assign('sys_cached', true);
352
        } else {
353
            $this->assign('sys_cached', false);
354
        }
355
356
        if ($db['debug'] === true) {
357
            parent::fetch($this->main_template . '.tpl', $this->get_cache_id(), $this->get_compile_id());
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (fetch() instead of display()). Are you sure this is correct? If so, you might want to change this to $this->fetch().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
358
359
            $this->clear_all_assign();
360
            $this->main_template = 'sys_sqldebugger';
361
            $this->assign('commands', $sqldebugger->getCommands());
362
            $this->assign('cancel', $sqldebugger->getCancel());
363
            unset($sqldebugger);
364
365
            $this->assign('opt', $optn);
366
            $this->assign('login', $loginn);
367
368
            $this->caching = false;
369
370
            // unset sqldebugger to allow proper translation of sqldebugger template
371
            $opt['debug'] = $opt['debug'] & ~DEBUG_SQLDEBUGGER;
372
373
            $this->header();
374
            parent::display($this->main_template . '.tpl');
375
        } else {
376
            $this->header();
377
            parent::display($this->main_template . '.tpl', $this->get_cache_id(), $this->get_compile_id());
378
        }
379
380
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method display() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
381
    }
382
383
    /**
384
     * show an error dialog
385
     *
386
     * @param integer $id
387
     */
388
    public function error($id)
389
    {
390
        $this->clear_all_assign();
391
        $this->caching = false;
0 ignored issues
show
Documentation Bug introduced by
The property $caching was declared of type integer, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
392
393
        $this->assign('page', $this->name);
394
        $this->assign('id', $id);
395
396
        if ($this->menuitem == null) {
397
            $this->menuitem = MNU_ERROR;
398
        }
399
400
        $args = func_get_args();
401
        unset($args[0]);
402
        for ($i = 1; isset($args[$i]); $i++) {
403
            $this->assign('p' . $i, $args[$i]);
404
        }
405
406
        $this->name = 'error';
407
        $this->display();
408
    }
409
410
    // check if this template is valid
411
    /**
412
     * @param null $dummy1
413
     * @param null $dummy2
414
     * @param null $dummy3
415
     * @return bool|false|string
416
     */
417
    public function is_cached($dummy1 = null, $dummy2 = null, $dummy3 = null)
418
    {
419
        global $login;
420
421
        // if the user is an admin, dont cache the content
422
        if (isset($login)) {
423
            if ($login->admin) {
424
                return false;
425
            }
426
        }
427
428
        return parent::is_cached($this->main_template . '.tpl', $this->get_cache_id(), $this->get_compile_id());
429
    }
430
431
    /**
432
     * @return string
433
     */
434
    public function get_cache_id()
435
    {
436
        // $cache_id can be directly supplied from unverified user input (URL params).
437
        // Probably this is no safety or stability issue, but to be sure we restrict
438
        // the ID to a reasonable set of characters:
439
440
        return $this->name . '|' . mb_ereg_replace('/[^A-Za-z0-9_\|\-\.]/', '', $this->cache_id);
441
    }
442
443
    /**
444
     * @return string
445
     */
446
    public function get_compile_id()
447
    {
448
        global $opt;
449
450
        return $opt['template']['style'] . '|' . $opt['template']['locale'] . '|' . $this->compile_id;
451
    }
452
453
    /**
454
     * @param string $page
455
     */
456
    public function redirect($page)
457
    {
458
        global $cookie, $opt;
459
        $cookie->close();
460
461
        // close db-connection
462
        sql_disconnect();
463
464
        $this->header();
465
466
        if (strpos($page, "\n") !== false) {
467
            $page = substr($page, 0, strpos($page, "\n"));
468
        }
469
470
        // redirect
471
        if (!preg_match("/^https?:/i", $page)) {
472
            if (substr($page, 0, 1) == '/') {
473
                $page = substr($page, 1);
474
            }
475
            $page = $opt['page']['absolute_url'] . $page;
476
        }
477
478
        if ($opt['session']['mode'] == SAVE_SESSION) {
479
            if (defined('SID') && SID != '' && session_id() != '') {
480
                if (strpos($page, '?') === false) {
481
                    header("Location: " . $page . '?' . urlencode(session_name()) . '=' . urlencode(session_id()));
482
                } else {
483
                    header("Location: " . $page . '&' . urlencode(session_name()) . '=' . urlencode(session_id()));
484
                }
485
            } else {
486
                header("Location: " . $page);
487
            }
488
        } else {
489
            header("Location: " . $page);
490
        }
491
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method redirect() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
492
    }
493
494
    /**
495
     * redirect login function
496
     */
497
    public function redirect_login()
0 ignored issues
show
Coding Style introduced by
redirect_login uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
redirect_login uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
498
    {
499
        global $opt;
500
501
        // we cannot redirect the POST-data
502
        if (count($_POST) > 0) {
503
            $this->error(ERROR_LOGIN_REQUIRED);
504
        }
505
506
        // ok ... redirect the get-data
507
        $target = ($opt['page']['https']['force_login'] ? 'https' : $opt['page']['protocol'])
508
            . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
509
        $this->redirect('login.php?target=' . urlencode($target));
510
    }
511
512
    /**
513
     * @param $name
514
     * @param $rs
515
     */
516 View Code Duplication
    public function assign_rs($name, $rs)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
517
    {
518
        $items = [];
519
        while ($r = sql_fetch_assoc($rs)) {
520
            $items[] = $r;
521
        }
522
        $this->assign($name, $items);
523
    }
524
525
    /**
526
     * @param $src
527
     */
528
    public function add_header_javascript($src)
529
    {
530
        $this->header_javascript[] = $src;
531
    }
532
533
    /**
534
     * @param $script
535
     */
536
    public function add_body_load($script)
537
    {
538
        $this->body_load[] = $script;
539
    }
540
541
    /**
542
     * @param $script
543
     */
544
    public function add_body_unload($script)
545
    {
546
        $this->body_unload[] = $script;
547
    }
548
549
    /**
550
     * setting http header
551
     */
552
    public function header()
553
    {
554
        global $opt;
555
        global $cookie;
556
557
        if ($opt['gui'] == GUI_HTML) {
558
            // charset setzen
559
            header('Content-type: text/html; charset=utf-8');
560
561
            // HTTP/1.1
562
            header('Cache-Control: no-store, no-cache, must-revalidate');
563
            header('Cache-Control: post-check=0, pre-check=0', false);
564
            // HTTP/1.0
565
            header('Pragma: no-cache');
566
            // Date in the past
567
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
568
            // always modified
569
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
570
571
            // set the cookie
572
            $cookie->header();
573
        }
574
    }
575
576
    /**
577
     * - trim target and strip newlines
578
     * - use sDefault if sTarget is absolute and sDefault!=null
579
     *
580
     * @param $sTarget
581
     * @param null $sDefault
582
     * @return null|string
583
     */
584
    public function checkTarget($sTarget, $sDefault = null)
585
    {
586
        if (mb_strpos($sTarget, "\n") !== false) {
587
            $sTarget = mb_substr($sTarget, 0, mb_strpos($sTarget, "\n"));
588
        }
589
590
        $sTarget = mb_trim($sTarget);
591
592
        if (mb_strtolower(mb_substr($sTarget, 0, 7)) == 'http://' || $sTarget == '') {
593
            if ($sDefault != null) {
594
                return $sDefault;
595
            }
596
        }
597
598
        return $sTarget;
599
    }
600
601
     public function acceptsAndPurifiesHtmlInput()
602
     {
603
        // Prevent false XSS detection of harmless HTML code
604
        // see https://redmine.opencaching.de/issues/1137
605
        // see https://stackoverflow.com/questions/43249998/chrome-err-blocked-by-xss-auditor-details
606
607
        // XSS protection can be safely disabled if user-supplied content cannot inject JavaScript,
608
        // see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
609
        // This is ensured by HTMLpurifier in OC code.
610
611
        header('X-XSS-Protection: 0');
612
     }
613
}
614