XoopsUserUtility::validate()   F
last analyzed

Complexity

Conditions 41
Paths > 20000

Size

Total Lines 139
Code Lines 92

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 41
eloc 92
nc 6496257
nop 0
dl 0
loc 139
rs 0
c 0
b 0
f 0

How to fix   Long Method    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
 *  Xoops Form Class Elements
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright       (c) 2000-2025 XOOPS Project (https://xoops.org)
13
 * @license             GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
14
 * @package             kernel
15
 * @since               2.3.0
16
 * @author              Taiwen Jiang <[email protected]>
17
 */
18
19
defined('XOOPS_ROOT_PATH') || exit('Restricted access');
20
21
/**
22
 * XoopsUserUtility
23
 *
24
 * @package Kernel
25
 * @author  Taiwen Jiang <[email protected]>
26
 */
27
class XoopsUserUtility
28
{
29
    /**
30
     * XoopsUserUtility::sendWelcome
31
     *
32
     * @param mixed $user
33
     *
34
     * @return bool
35
     */
36
    public static function sendWelcome($user)
37
    {
38
        global $xoopsConfigUser, $xoopsConfig;
39
40
        if (empty($xoopsConfigUser)) {
41
            /** @var XoopsConfigHandler $config_handler */
42
            $config_handler  = xoops_getHandler('config');
43
            $xoopsConfigUser = $config_handler->getConfigsByCat(XOOPS_CONF_USER);
44
        }
45
        if (empty($xoopsConfigUser['welcome_type'])) {
46
            return true;
47
        }
48
49
        if (!empty($user) && !is_object($user)) {
50
            /** @var XoopsMemberHandler $member_handler */
51
            $member_handler = xoops_getHandler('member');
52
            $user           = $member_handler->getUser($user);
53
        }
54
        if (!is_object($user)) {
55
            return false;
56
        }
57
58
        xoops_loadLanguage('user');
59
        $xoopsMailer = xoops_getMailer();
60
        if ($xoopsConfigUser['welcome_type'] == 1 || $xoopsConfigUser['welcome_type'] == 3) {
61
            $xoopsMailer->useMail();
62
        }
63
        if ($xoopsConfigUser['welcome_type'] == 2 || $xoopsConfigUser['welcome_type'] == 3) {
64
            $xoopsMailer->usePM();
65
        }
66
        $xoopsMailer->setTemplate('welcome.tpl');
67
        $xoopsMailer->setSubject(sprintf(_US_WELCOME_SUBJECT, $xoopsConfig['sitename']));
68
        $xoopsMailer->setToUsers($user);
69
        if ($xoopsConfigUser['reg_dispdsclmr'] && $xoopsConfigUser['reg_disclaimer']) {
70
            $xoopsMailer->assign('TERMSOFUSE', $xoopsConfigUser['reg_disclaimer']);
71
        } else {
72
            $xoopsMailer->assign('TERMSOFUSE', '');
73
        }
74
75
        return $xoopsMailer->send();
76
    }
77
    /**
78
     * $uname, $email, $pass = null, $vpass = null
79
     */
80
    /**
81
     * XoopsUserUtility::validate
82
     *
83
     * @return bool|string
84
     */
85
    public static function validate()
86
    {
87
        global $xoopsUser;
88
89
        $args     = func_get_args();
90
        $args_num = func_num_args();
91
92
        $user  = null;
93
        $uname = null;
94
        $email = null;
95
        $pass  = null;
96
        $vpass = null;
97
98
        switch ($args_num) {
99
            case 1:
100
                $user = $args[0];
101
                break;
102
            case 2:
103
                [$uname, $email] = $args;
104
                break;
105
            case 3:
106
                [$user, $pass, $vpass] = $args;
107
                break;
108
            case 4:
109
                [$uname, $email, $pass, $vpass] = $args;
110
                break;
111
            default:
112
                return false;
113
        }
114
        if (is_object($user)) {
115
            $uname = $user->getVar('uname', 'n');
116
            $email = $user->getVar('email', 'n');
117
        }
118
        /** @var XoopsConfigHandler $config_handler */
119
        $config_handler  = xoops_getHandler('config');
120
        $xoopsConfigUser = $config_handler->getConfigsByCat(XOOPS_CONF_USER);
121
122
        xoops_loadLanguage('user');
123
        $myts = \MyTextSanitizer::getInstance();
0 ignored issues
show
Unused Code introduced by
The assignment to $myts is dead and can be removed.
Loading history...
124
125
        $xoopsUser_isAdmin = is_object($xoopsUser) && $xoopsUser->isAdmin();
126
        $stop              = '';
127
        // Invalid email address
128
        if (!checkEmail($email)) {
129
            $stop .= _US_INVALIDMAIL . '<br>';
130
        }
131
        if (strrpos($email, ' ') > 0) {
132
            $stop .= _US_EMAILNOSPACES . '<br>';
133
        }
134
        // Check forbidden email address if current operator is not an administrator
135
        if (!$xoopsUser_isAdmin) {
136
            foreach ($xoopsConfigUser['bad_emails'] as $be) {
137
                if (!empty($be) && preg_match('/' . $be . '/i', $email)) {
138
                    $stop .= _US_INVALIDMAIL . '<br>';
139
                    break;
140
                }
141
            }
142
        }
143
        $uname = xoops_trim($uname);
144
        switch ($xoopsConfigUser['uname_test_level']) {
145
            case 0:
146
                // strict
147
                $restriction = '/[^a-zA-Z0-9\_\-]/';
148
                break;
149
            case 1:
150
                // medium
151
                $restriction = '/[^a-zA-Z0-9\_\-\<\>\,\.\$\%\#\@\!\\\'\']/';
152
                break;
153
            case 2:
154
                // loose
155
                $restriction = '/[\000-\040]/';
156
                break;
157
        }
158
        if (empty($uname) || preg_match($restriction, $uname)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $restriction does not seem to be defined for all execution paths leading up to this point.
Loading history...
159
            $stop .= _US_INVALIDNICKNAME . '<br>';
160
        }
161
        // Check uname settings if current operator is not an administrator
162
        if (!$xoopsUser_isAdmin) {
163
            if (strlen($uname) > $xoopsConfigUser['maxuname']) {
164
                $stop .= sprintf(_US_NICKNAMETOOLONG, $xoopsConfigUser['maxuname']) . '<br>';
165
            }
166
            if (strlen($uname) < $xoopsConfigUser['minuname']) {
167
                $stop .= sprintf(_US_NICKNAMETOOSHORT, $xoopsConfigUser['minuname']) . '<br>';
168
            }
169
            foreach ($xoopsConfigUser['bad_unames'] as $bu) {
170
                if (!empty($bu) && preg_match('/' . $bu . '/i', $uname)) {
171
                    $stop .= _US_NAMERESERVED . '<br>';
172
                    break;
173
                }
174
            }
175
            /**
176
             * if (strrpos($uname, ' ') > 0) {
177
             * $stop .= _US_NICKNAMENOSPACES . '<br>';
178
             * }
179
             */
180
        }
181
        /** @var XoopsMySQLDatabase $xoopsDB */
182
        $xoopsDB = XoopsDatabaseFactory::getDatabaseConnection();
183
        // Check if uname/email already exists if the user is a new one
184
        $uid    = is_object($user) ? $user->getVar('uid') : 0;
185
        $sql    = 'SELECT COUNT(*) FROM `' . $xoopsDB->prefix('users') . '` WHERE `uname` = ' . $xoopsDB->quote(addslashes($uname)) . (($uid > 0) ? " AND `uid` <> {$uid}" : '');
186
        $result = $xoopsDB->query($sql);
187
        if (!$xoopsDB->isResultSet($result)) {
188
            throw new \RuntimeException(
189
                \sprintf(_DB_QUERY_ERROR, $sql) . $xoopsDB->error(),
190
                E_USER_ERROR,
191
            );
192
        }
193
        [$count] = $xoopsDB->fetchRow($result);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchRow() does only seem to accept mysqli_result, 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

193
        [$count] = $xoopsDB->fetchRow(/** @scrutinizer ignore-type */ $result);
Loading history...
194
        if ((int) $count > 0) {
195
            $stop .= _US_NICKNAMETAKEN . '<br>';
196
        }
197
        $sql    = 'SELECT COUNT(*) FROM `' . $xoopsDB->prefix('users') . '` WHERE `email` = ' . $xoopsDB->quote(addslashes($email)) . (($uid > 0) ? " AND `uid` <> {$uid}" : '');
198
        $result = $xoopsDB->query($sql);
199
        if (!$xoopsDB->isResultSet($result)) {
200
            throw new \RuntimeException(
201
                \sprintf(_DB_QUERY_ERROR, $sql) . $xoopsDB->error(),
202
                E_USER_ERROR,
203
            );
204
        }
205
        [$count] = $xoopsDB->fetchRow($result);
206
        if ((int) $count > 0) {
207
            $stop .= _US_EMAILTAKEN . '<br>';
208
        }
209
        // If password is not set, skip password validation
210
        if ($pass === null && $vpass === null) {
211
            return $stop;
212
        }
213
214
        if (!isset($pass) || $pass == '' || !isset($vpass) || $vpass == '') {
215
            $stop .= _US_ENTERPWD . '<br>';
216
        }
217
        if (isset($pass) && ($pass != $vpass)) {
218
            $stop .= _US_PASSNOTSAME . '<br>';
219
        } elseif (($pass != '') && (strlen($pass) < $xoopsConfigUser['minpass'])) {
220
            $stop .= sprintf(_US_PWDTOOSHORT, $xoopsConfigUser['minpass']) . '<br>';
221
        }
222
223
        return $stop;
224
    }
225
226
    /**
227
     * Get client IP
228
     *
229
     * Adapted from PMA_getIp() [phpmyadmin project]
230
     *
231
     * @param  bool $asString requiring integer or dotted string
232
     * @return mixed string or integer value for the IP
233
     */
234
    public static function getIP($asString = false)
235
    {
236
        // Gets the proxy ip sent by the user
237
        $proxy_ip = '';
238
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
239
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
240
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED'])) {
241
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED'];
242
        } elseif (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
243
            $proxy_ip = $_SERVER['HTTP_FORWARDED_FOR'];
244
        } elseif (!empty($_SERVER['HTTP_FORWARDED'])) {
245
            $proxy_ip = $_SERVER['HTTP_FORWARDED'];
246
        } elseif (!empty($_SERVER['HTTP_VIA'])) {
247
            $proxy_ip = $_SERVER['HTTP_VIA'];
248
        } elseif (!empty($_SERVER['HTTP_X_COMING_FROM'])) {
249
            $proxy_ip = $_SERVER['HTTP_X_COMING_FROM'];
250
        } elseif (!empty($_SERVER['HTTP_COMING_FROM'])) {
251
            $proxy_ip = $_SERVER['HTTP_COMING_FROM'];
252
        }
253
        if (!empty($proxy_ip)) {
254
            $ip = new \Xmf\IPAddress($proxy_ip);
255
            if (false === $ip->asReadable()) {
0 ignored issues
show
introduced by
The condition false === $ip->asReadable() is always false.
Loading history...
256
                $ip = \Xmf\IPAddress::fromRequest();
257
            }
258
        } else {
259
            $ip = \Xmf\IPAddress::fromRequest();
260
        }
261
262
        // this really should return $ip->asBinary() instead of ip2long, but for IPv6, this will
263
        // return false when the ip2long() fails. Callers are not expecting binary strings.
264
        $the_IP = $asString ? $ip->asReadable() : ip2long($ip->asReadable());
265
266
        return $the_IP;
267
    }
268
269
    /**
270
     * XoopsUserUtility::getUnameFromIds()
271
     *
272
     * @param  mixed $uid
273
     * @param  mixed $usereal
274
     * @param  mixed $linked
275
     * @return array
276
     */
277
    public static function getUnameFromIds($uid, $usereal = false, $linked = false)
278
    {
279
        if (!is_array($uid)) {
280
            $uid = [$uid];
281
        }
282
        $userid = array_map('intval', array_filter($uid));
283
284
        $myts  = \MyTextSanitizer::getInstance();
285
        $users = [];
286
        if (count($userid) > 0) {
287
            /** @var XoopsMySQLDatabase $xoopsDB */
288
            $xoopsDB = XoopsDatabaseFactory::getDatabaseConnection();
289
            $sql     = 'SELECT uid, uname, name FROM ' . $xoopsDB->prefix('users') . ' WHERE level > 0 AND uid IN(' . implode(',', array_unique($userid)) . ')';
290
            $result = $xoopsDB->query($sql);
291
            if (!$xoopsDB->isResultSet($result)) {
292
                return $users;
293
            }
294
295
            while (false !== ($row = $xoopsDB->fetchArray($result))) {
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type boolean; however, parameter $result of XoopsMySQLDatabase::fetchArray() does only seem to accept mysqli_result, 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

295
            while (false !== ($row = $xoopsDB->fetchArray(/** @scrutinizer ignore-type */ $result))) {
Loading history...
296
                $uid = $row['uid'];
297
                if ($usereal && $row['name']) {
298
                    $users[$uid] = $myts->htmlSpecialChars($row['name']);
299
                } else {
300
                    $users[$uid] = $myts->htmlSpecialChars($row['uname']);
301
                }
302
                if ($linked) {
303
                    $users[$uid] = '<a href="' . XOOPS_URL . '/userinfo.php?uid=' . $uid . '" title="' . $users[$uid] . '">' . $users[$uid] . '</a>';
304
                }
305
            }
306
        }
307
        if (in_array(0, $users, true)) {
308
            $users[0] = $myts->htmlSpecialChars($GLOBALS['xoopsConfig']['anonymous']);
309
        }
310
311
        return $users;
312
    }
313
314
    /**
315
     * XoopsUserUtility::getUnameFromId()
316
     *
317
     * @param  mixed $userid
318
     * @param  mixed $usereal
319
     * @param  mixed $linked
320
     * @return string
321
     */
322
    public static function getUnameFromId($userid, $usereal = false, $linked = false)
323
    {
324
        $myts     = \MyTextSanitizer::getInstance();
325
        $userid   = (int) $userid;
326
        $username = '';
327
        if ($userid > 0) {
328
            /** @var XoopsMemberHandler $member_handler */
329
            $member_handler = xoops_getHandler('member');
330
            $user           = $member_handler->getUser($userid);
331
            if (is_object($user)) {
332
                if ($usereal && $user->getVar('name')) {
333
                    $username = $user->getVar('name');
334
                } else {
335
                    $username = $user->getVar('uname');
336
                }
337
                if (!empty($linked)) {
338
                    $username = '<a href="' . XOOPS_URL . '/userinfo.php?uid=' . $userid . '" title="' . $username . '">' . $username . '</a>';
339
                }
340
            }
341
        }
342
        if (empty($username)) {
343
            $username = $myts->htmlSpecialChars($GLOBALS['xoopsConfig']['anonymous']);
344
        }
345
346
        return $username;
347
    }
348
}
349