Completed
Push — master ( 937117...931dfe )
by Michael
05:45 queued 02:42
created

XoopsGTicket::issue()   D

Complexity

Conditions 10
Paths 96

Size

Total Lines 44
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 22
nc 96
nop 3
dl 0
loc 44
rs 4.8196
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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 9 and the first side effect is on line 271.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
// GIJOE's Ticket Class (based on Marijuana's Oreteki XOOPS)
3
// nobunobu's suggestions are applied
4
5
if (!class_exists('XoopsGTicket')) {
6
    /**
7
     * Class XoopsGTicket
8
     */
9
    class XoopsGTicket
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...
10
    {
11
        private $_errors       = array();
12
        private $_latest_token = '';
13
14
        // render form as plain html
15
16
        /**
17
         * @param  string $salt
18
         * @param  int    $timeout
19
         * @param  string $area
20
         * @return string
21
         */
22
        public function getTicketHtml($salt = '', $timeout = 1800, $area = '')
23
        {
24
            return '<input type="hidden" name="XOOPS_G_TICKET" value="' . $this->issue($salt, $timeout, $area) . '" />';
25
        }
26
27
        // returns an object of XoopsFormHidden including theh ticket
28
29
        /**
30
         * @param  string $salt
31
         * @param  int    $timeout
32
         * @param  string $area
33
         * @return XoopsFormHidden
34
         */
35
        public function getTicketXoopsForm($salt = '', $timeout = 1800, $area = '')
36
        {
37
            return new XoopsFormHidden('XOOPS_G_TICKET', $this->issue($salt, $timeout, $area));
38
        }
39
40
        // add a ticket as Hidden Element into XoopsForm
41
42
        /**
43
         * @param        $form
44
         * @param string $salt
45
         * @param int    $timeout
46
         * @param string $area
47
         */
48
        public function addTicketXoopsFormElement($form, $salt = '', $timeout = 1800, $area = '')
49
        {
50
            $form->addElement(new XoopsFormHidden('XOOPS_G_TICKET', $this->issue($salt, $timeout, $area)));
51
        }
52
53
        // returns an array for xoops_confirm() ;
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
54
55
        /**
56
         * @param  string $salt
57
         * @param  int    $timeout
58
         * @param  string $area
59
         * @return array
60
         */
61
        public function getTicketArray($salt = '', $timeout = 1800, $area = '')
62
        {
63
            return array('XOOPS_G_TICKET' => $this->issue($salt, $timeout, $area));
64
        }
65
66
        // return GET parameter string.
67
68
        /**
69
         * @param  string $salt
70
         * @param  bool   $noamp
71
         * @param  int    $timeout
72
         * @param  string $area
73
         * @return string
74
         */
75
        public function getTicketParamString($salt = '', $noamp = false, $timeout = 1800, $area = '')
76
        {
77
            return ($noamp ? '' : '&amp;') . 'XOOPS_G_TICKET=' . $this->issue($salt, $timeout, $area);
78
        }
79
80
        // issue a ticket
81
82
        /**
83
         * @param  string $salt
84
         * @param  int    $timeout
85
         * @param  string $area
86
         * @return string
87
         */
88
        public function issue($salt = '', $timeout = 1800, $area = '')
0 ignored issues
show
Coding Style introduced by
issue 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...
Coding Style introduced by
issue uses the super-global variable $_SESSION 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...
89
        {
90
            global $xoopsModule;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
91
92
            if ('' === $salt) {
93
                if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
94
                    // $salt = '$2y$07$' . strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
0 ignored issues
show
Unused Code Comprehensibility introduced by
52% 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...
95
                    $salt = '$2y$07$' . str_replace('+', '.', base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)));
96
                }
97
            }
98
            // create a token
99
            list($usec, $sec) = explode(' ', microtime());
100
            $appendix_salt       = empty($_SERVER['PATH']) ? XOOPS_DB_NAME : $_SERVER['PATH'];
101
            $token               = crypt($salt . $usec . $appendix_salt . $sec, $salt);
102
            $this->_latest_token = $token;
103
104
            if (empty($_SESSION['XOOPS_G_STUBS'])) {
105
                $_SESSION['XOOPS_G_STUBS'] = array();
106
            }
107
108
            // limit max stubs 10
109
            if (count($_SESSION['XOOPS_G_STUBS']) > 10) {
110
                $_SESSION['XOOPS_G_STUBS'] = array_slice($_SESSION['XOOPS_G_STUBS'], -10);
111
            }
112
113
            // record referer if browser send it
114
            $referer = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['REQUEST_URI'];
115
116
            // area as module's dirname
117
            if (!$area && is_object(@$xoopsModule)) {
118
                $area = $xoopsModule->getVar('dirname');
119
            }
120
121
            // store stub
122
            $_SESSION['XOOPS_G_STUBS'][] = array(
123
                'expire'  => time() + $timeout,
124
                'referer' => $referer,
125
                'area'    => $area,
126
                'token'   => $token
127
            );
128
129
            // paid md5ed token as a ticket
130
            return md5($token . XOOPS_DB_PREFIX);
131
        }
132
133
        // check a ticket
134
135
        /**
136
         * @param  bool   $post
137
         * @param  string $area
138
         * @return bool
139
         */
140
        public function check($post = true, $area = '')
0 ignored issues
show
Coding Style introduced by
check uses the super-global variable $_SESSION 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
check 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
check 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
check 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...
141
        {
142
            global $xoopsModule;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
143
144
            $this->_errors = array();
145
146
            // CHECK: stubs are not stored in session
147
            if (empty($_SESSION['XOOPS_G_STUBS']) || !is_array($_SESSION['XOOPS_G_STUBS'])) {
148
                $this->clear();
149
                $this->_errors[] = 'Invalid Session';
150
151
                return false;
152
            }
153
154
            // get key&val of the ticket from a user's query
155
            if ($post) {
156
                $ticket = empty($_POST['XOOPS_G_TICKET']) ? '' : $_POST['XOOPS_G_TICKET'];
157
            } else {
158
                $ticket = empty($_GET['XOOPS_G_TICKET']) ? '' : $_GET['XOOPS_G_TICKET'];
159
            }
160
161
            // CHECK: no tickets found
162
            if (empty($ticket)) {
163
                $this->clear();
164
                $this->_errors[] = 'Irregular post found';
165
166
                return false;
167
            }
168
169
            // gargage collection & find a right stub
170
            $stubs_tmp                 = $_SESSION['XOOPS_G_STUBS'];
171
            $_SESSION['XOOPS_G_STUBS'] = array();
172
            foreach ($stubs_tmp as $stub) {
173
                // default lifetime 30min
174
                if ($stub['expire'] >= time()) {
175
                    if (md5($stub['token'] . XOOPS_DB_PREFIX) === $ticket) {
176
                        $found_stub = $stub;
177
                    } else {
178
                        // store the other valid stubs into session
179
                        $_SESSION['XOOPS_G_STUBS'][] = $stub;
180
                    }
181
                } else {
182
                    if (md5($stub['token'] . XOOPS_DB_PREFIX) === $ticket) {
183
                        // not CSRF but Time-Out
184
                        $timeout_flag = true;
185
                    }
186
                }
187
            }
188
189
            // CHECK: the right stub found or not
190
            if (empty($found_stub)) {
191
                $this->clear();
192
                if (empty($timeout_flag)) {
193
                    $this->_errors[] = 'Invalid Session';
194
                } else {
195
                    $this->_errors[] = 'Time out';
196
                }
197
198
                return false;
199
            }
200
201
            // set area if necessary
202
            // area as module's dirname
203
            if (!$area && is_object(@$xoopsModule)) {
204
                $area = $xoopsModule->getVar('dirname');
205
            }
206
207
            // check area or referer
208
            if (@$found_stub['area'] === $area) {
209
                $area_check = true;
210
            }
211
            if (!empty($found_stub['referer']) && false !== strpos(@$_SERVER['HTTP_REFERER'], $found_stub['referer'])) {
212
                $referer_check = true;
213
            }
214
215
            // if ( empty( $area_check ) || empty( $referer_check ) ) { // restrict
0 ignored issues
show
Unused Code Comprehensibility introduced by
52% 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...
216
            if (empty($area_check) && empty($referer_check)) { // loose
217
                $this->clear();
218
                $this->_errors[] = 'Invalid area or referer';
219
220
                return false;
221
            }
222
223
            // all green
224
            return true;
225
        }
226
227
        // clear all stubs
228
        public function clear()
0 ignored issues
show
Coding Style introduced by
clear uses the super-global variable $_SESSION 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...
229
        {
230
            $_SESSION['XOOPS_G_STUBS'] = array();
231
        }
232
233
        // Ticket Using
234
235
        /**
236
         * @return bool
237
         */
238
        public function using()
0 ignored issues
show
Coding Style introduced by
using uses the super-global variable $_SESSION 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...
239
        {
240
            if (!empty($_SESSION['XOOPS_G_STUBS'])) {
241
                return true;
242
            } else {
243
                return false;
244
            }
245
        }
246
247
        // return errors
248
249
        /**
250
         * @param  bool $ashtml
251
         * @return array|string
252
         */
253
        public function getErrors($ashtml = true)
254
        {
255
            if ($ashtml) {
256
                $ret = '';
257
                foreach ($this->_errors as $msg) {
258
                    $ret .= "$msg<br>\n";
259
                }
260
            } else {
261
                $ret = $this->_errors;
262
            }
263
264
            return $ret;
265
        }
266
267
        // end of class
268
    }
269
270
    // create a instance in global scope
271
    $GLOBALS['xoopsGTicket'] = new XoopsGTicket();
272
}
273
274
if (!function_exists('admin_refcheck')) {
275
276
    //Admin Referer Check By Marijuana(Rev.011)
277
    /**
278
     * @param  string $chkref
279
     * @return bool
280
     */
281
    function admin_refcheck($chkref = '')
0 ignored issues
show
Coding Style introduced by
admin_refcheck 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...
282
    {
283
        if (empty($_SERVER['HTTP_REFERER'])) {
284
            return true;
285
        } else {
286
            $ref = $_SERVER['HTTP_REFERER'];
287
        }
288
        $cr = XOOPS_URL;
289
        if ($chkref !== '') {
290
            $cr .= $chkref;
291
        }
292
        if (strpos($ref, $cr) !== 0) {
293
            return false;
294
        }
295
296
        return true;
297
    }
298
}
299