Issues (340)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

search.php (3 issues)

Labels
Severity
1
<?php declare(strict_types=1);
2
3
/*
4
 * You may not change or alter any portion of this comment or credits
5
 * of supporting developers from this source code or any supporting source code
6
 * which is considered copyrighted (c) material of the original comment or credit authors.
7
 *
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
//  ------------------------------------------------------------------------ //
13
//  Author: phppp (D.J., [email protected])                                  //
14
//  URL: https://xoops.org                                                    //
15
//  Project: Article Project                                                 //
16
//  ------------------------------------------------------------------------ //
17
18
use Xmf\Highlighter;
19
use Xmf\Metagen;
20
use Xmf\Request;
21
use XoopsModules\Newbb\{
22
    Forum,
23
    OnlineHandler
24
};
25
26
/** @var OnlineHandler $onlineHandler */
27
28
require_once __DIR__ . '/header.php';
29
xoops_loadLanguage('search');
30
/** @var \XoopsConfigHandler $configHandler */
31
$configHandler     = xoops_getHandler('config');
32
$xoopsConfigSearch = $configHandler->getConfigsByCat(XOOPS_CONF_SEARCH);
33
if (1 !== $xoopsConfigSearch['enable_search']) {
34
    redirect_header(XOOPS_URL . '/modules/newbb/index.php', 2, _MD_NEWBB_SEARCHDISABLED);
35
}
36
37
$GLOBALS['xoopsConfig']['module_cache'][$xoopsModule->getVar('mid')] = 0;
38
$xoopsOption['template_main']                                        = 'newbb_search.tpl';
39
require_once $GLOBALS['xoops']->path('header.php');
40
41
require_once __DIR__ . '/include/functions.render.php';
42
require_once __DIR__ . '/include/functions.forum.php';
43
require_once __DIR__ . '/include/functions.time.php';
44
45
require_once $GLOBALS['xoops']->path('modules/newbb/include/search.inc.php');
46
$limit = $GLOBALS['xoopsModuleConfig']['topics_per_page'];
47
48
$queries              = [];
49
$andor                = '';
50
$start                = 0;
51
$uid                  = 0;
52
$forum                = 0;
53
$sortby               = 'p.post_time'; // irmtfan remove DESC
54
$criteriaExtra        = new \CriteriaCompo(); // irmtfan new \Criteria
55
$searchin             = 'both';
56
$sort                 = '';
57
$since                = Request::getInt('since', 0);
58
$next_search['since'] = $since;
59
$term                 = Request::getString('term', '');
60
$uname                = Request::getString('uname', '');
61
// irmtfan add select parameters
62
$selectlength = Request::getInt('selectlength', 200);
63
64
// irmtfan assign default values to variables
65
$show_search     = 'post_text';
66
$search_username = trim((string) $uname);
67
68
if ($GLOBALS['xoopsModuleConfig']['wol_enabled']) {
69
    //    $onlineHandler = \XoopsModules\Newbb\Helper::getInstance()->getHandler('Online');
70
    $onlineHandler->init(0);
71
}
72
73
$xoopsTpl->assign('forumindex', sprintf(_MD_NEWBB_FORUMINDEX, htmlspecialchars((string)$GLOBALS['xoopsConfig']['sitename'], ENT_QUOTES)));
74
//$xoopsTpl->assign("img_folder", newbbDisplayImage($forumImage['topic']));
75
76
$paras = null;
77
$search_url_next = null;
78
$search_url_prev = null;
79
if (!empty($uname) || Request::getString('submit', '') || !empty($term)) {
80
    // irmtfan filter positive numbers
81
    $selectlength = !empty($selectlength) ? abs($selectlength) : 200;
82
    // irmtfan add select parameters for next search
83
    $next_search['selectlength'] = $selectlength;
84
85
    $start = Request::getInt('start', 0);
86
    /** @var array|string $forum */
87
    $forum = Request::getInt('forum', 0);
88
    if (empty($forum) || 'all' === $forum || (is_array($forum) && in_array('all', $forum, true))) {
89
        $forum = [];
90
    } elseif (!is_array($forum)) {
91
        $forum = array_map('\intval', explode('|', $forum));
92
    }
93
    $next_search['forum'] = implode('|', $forum);
94
    // START irmtfan topic search
95
    $topic                = Request::getString('topic', '');
96
    $next_search['topic'] = $topic;
97
    // END irmtfan topic search
98
    // START irmtfan add show search
99
    $show_search                = Request::getString('show_search', 'post_text');
100
    $next_search['show_search'] = $show_search;
101
    // START irmtfan add show search
102
103
    $addterms             = Request::getString('andor', 'AND');
104
    $next_search['andor'] = $addterms;
105
    $andor                = \mb_strtoupper((string) $addterms);
106
    if (!in_array($addterms, ['OR', 'AND'], true)) {
107
        $andor = 'AND';
108
    }
109
110
    $uname_required       = false;
111
    $next_search['uname'] = $search_username;
112
    if (!empty($search_username)) {
113
        $uname_required  = true;
114
        $search_username = $GLOBALS['xoopsDB']->escape($search_username);
115
        $sql = 'SELECT uid FROM ' . $GLOBALS['xoopsDB']->prefix('users') . " WHERE uname LIKE '%$search_username%'";
116
117
        $result = $GLOBALS['xoopsDB']->query($sql);
118
        if (!$GLOBALS['xoopsDB']->isResultSet($result)) {
119
            //                \trigger_error("Query Failed! SQL: $sql- Error: " . $GLOBALS['xoopsDB']->error(), E_USER_ERROR);
120
            redirect_header(XOOPS_URL . '/search.php', 1, _MD_NEWBB_ERROROCCURED);
121
        }
122
        $uid = [];
123
        while (false !== ($row = $GLOBALS['xoopsDB']->fetchArray($result))) {
124
            $uid[] = $row['uid'];
125
        }
126
    } else {
127
        $uid = 0;
128
    }
129
130
    $next_search['term'] = htmlspecialchars((string) $term, ENT_QUOTES);
131
    $query               = trim((string) $term);
132
133
    if ('EXACT' !== $andor) {
134
        $ignored_queries = []; // holds keywords that are shorter than allowed minimum length
135
        $temp_queries    = str_getcsv($query, ' ', '"');
136
        foreach ($temp_queries as $q) {
137
            $q = trim($q);
138
            if (mb_strlen($q) >= $xoopsConfigSearch['keyword_min']) {
139
                $queries[] = $q;
140
            } else {
141
                $ignored_queries[] = $q;
142
            }
143
        }
144
        if (!$uname_required && 0 === count($queries)) {
145
            redirect_header(XOOPS_URL . '/search.php', 2, sprintf(_SR_KEYTOOSHORT, $xoopsConfigSearch['keyword_min']));
146
        }
147
    } else {
148
        //$query = trim($query);
149
        if (!$uname_required && (mb_strlen($query) < $xoopsConfigSearch['keyword_min'])) {
150
            redirect_header(XOOPS_URL . '/search.php', 2, sprintf(_SR_KEYTOOSHORT, $xoopsConfigSearch['keyword_min']));
151
        }
152
        $queries = [$query];
153
    }
154
155
    // entries must be lowercase
156
    $allowed = ['p.post_time', 'p.subject']; // irmtfan just post time and subject
157
158
    /** @var string $sortby */
159
    $sortby                = Request::getString('sortby', 'p.post_time');
160
    $next_search['sortby'] = $sortby;
161
    //$sortby = (in_array(strtolower($sortby), $allowed)) ? $sortby :  't.topic_last_post_id';
162
    $sortby                  = in_array(mb_strtolower($sortby), $allowed, true) ? $sortby : 'p.post_time';
163
    $searchin                = Request::getString('searchin', 'both');
164
    $next_search['searchin'] = $searchin;
165
    // START irmtfan use criteria - add since and topic search
166
    if (!empty($since)) {
167
        $criteriaExtra->add(new \Criteria('p.post_time', (string)(time() - newbbGetSinceTime($since)), '>='), 'OR');
168
    }
169
    if (is_numeric($topic) && !empty($topic)) {
170
        $criteriaExtra->add(new \Criteria('p.topic_id', $topic), 'OR');
171
    }
172
    // END irmtfan use criteria -  add since and topic search
173
174
    if ($uname_required && (!$uid || count($uid) < 1)) {
0 ignored issues
show
It seems like $uid can also be of type integer; however, parameter $value of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

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

174
    if ($uname_required && (!$uid || count(/** @scrutinizer ignore-type */ $uid) < 1)) {
Loading history...
175
        $results = [];
176
    } // irmtfan bug fix array()
177
    else {
178
        $results = newbb_search($queries, $andor, $limit, $start, $uid, $forum, $sortby, $searchin, $criteriaExtra);
0 ignored issues
show
It seems like $uid can also be of type array and array; however, parameter $userid of newbb_search() does only seem to accept integer, 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

178
        $results = newbb_search($queries, $andor, $limit, $start, /** @scrutinizer ignore-type */ $uid, $forum, $sortby, $searchin, $criteriaExtra);
Loading history...
179
    } // irmtfan $criteriaExtra
180
181
    $search_info_keywords = Highlighter::apply(htmlspecialchars((string) $term, ENT_QUOTES), implode(' ', $queries), '<mark>', '</mark>');
182
    $num_results          = count($results);
183
    if ($num_results < 1) {
184
        $xoopsTpl->assign('lang_nomatch', _SR_NOMATCH);
185
    } else {
186
        $skipresults = 0;
187
        foreach ($results as $row) {
188
            $post_text_select    = '';
189
            $post_subject_select = Highlighter::apply($queries, $row['title'], '<mark>', '</mark>');
190
            if ('post_text' === $show_search) {
191
                $post_text_select = Metagen::getSearchSummary($row['post_text'], $queries, $selectlength);
0 ignored issues
show
It seems like $selectlength can also be of type double; however, parameter $length of Xmf\Metagen::getSearchSummary() does only seem to accept integer, 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

191
                $post_text_select = Metagen::getSearchSummary($row['post_text'], $queries, /** @scrutinizer ignore-type */ $selectlength);
Loading history...
192
                $post_text_select = Highlighter::apply($queries, $post_text_select, '<mark>', '</mark>');
193
            }
194
            // if no text remained after select text continue
195
            if (empty($post_text_select) && empty($post_subject_select)) {
196
                ++$skipresults;
197
                continue;
198
            }
199
            $xoopsTpl->append(
200
                'results',
201
                [
202
                    'forum_name' => $row['forum_name'],
203
                    'forum_link' => $row['forum_link'],
204
                    'link'       => $row['link'],
205
                    'title'      => $post_subject_select,
206
                    'poster'     => $row['poster'],
207
                    'post_time'  => formatTimestamp($row['time'], 'm'),
208
                    'post_text'  => $post_text_select,
209
                ]
210
            );
211
        }
212
        unset($results);
213
214
        if ((is_countable($next_search) ? count($next_search) : 0) > 0) {
215
            $items = [];
216
            foreach ($next_search as $para => $val) {
217
                $items[] = "{$para}=" . urlencode((string) $val);
218
            }
219
            if (count($items) > 0) {
220
                $paras = implode('&', $items);
221
            }
222
            unset($next_search, $items);
223
        }
224
        $search_url = XOOPS_URL . '/modules/' . $xoopsModule->getVar('dirname') . '/search.php?' . $paras;
225
        // irmtfan remove to have just one query and appropriate next and prev links
226
        //$next_results = newbb_search($queries, $andor, 1, $start + $limit, $uid, $forum, $sortby, $searchin, $subquery);
227
        //$next_count = count($next_results);
228
        //$has_next = false;
229
        //if (is_array($next_results) && $next_count >0) {
230
        //$has_next = true;
231
        //}
232
        // irmtfan if $results < $limit => it is impossible to have next
233
        if ($num_results == $limit) {
234
            $next            = $start + $limit;
235
            $queries         = implode(',', $queries);
236
            $search_url_next = htmlspecialchars($search_url . "&direction=next&start={$next}", ENT_QUOTES | ENT_HTML5);
237
            $search_next     = '<a href="' . $search_url_next . '">' . _SR_NEXT . '</a>';
238
            $xoopsTpl->assign('search_next', $search_next);
239
            $xoopsTpl->assign('search_next_url', $search_url_next);
240
        }
241
        if ($start > 0) {
242
            $prev            = $start - $limit;
243
            $search_url_prev = htmlspecialchars($search_url . "&direction=previous&start={$prev}", ENT_QUOTES | ENT_HTML5);
244
            $search_prev     = '<a href="' . $search_url_prev . '">' . _SR_PREVIOUS . '</a>';
245
            $xoopsTpl->assign('search_prev', $search_prev);
246
            $xoopsTpl->assign('search_prev_url', $search_url_prev);
247
        }
248
        // irmtfan if all results skipped then redirect to the next/previous page
249
        if ($num_results == $skipresults) {
250
            $direction           = Request::getString('direction', 'next');
251
            $search_url_redirect = ('next' === \mb_strtolower((string) $direction)) ? $search_url_next : $search_url_prev;
252
            redirect_header($search_url_redirect, 1, constant(mb_strtoupper("_SR_{$direction}")));
253
        }
254
    }
255
    $search_info = _SR_KEYWORDS . ': ' . $search_info_keywords;
256
    if ($uname_required) {
257
        if ($search_info) {
258
            $search_info .= '<br>';
259
        }
260
        $search_info .= _MD_NEWBB_USERNAME . ': ' . htmlspecialchars((string)$search_username, ENT_QUOTES | ENT_HTML5);
261
    }
262
    // add num_results
263
    $search_info .= '<br>' . sprintf(_SR_SHOWING, $start + 1, $start + $num_results);
264
    // if any result skip show the counter
265
    if (!empty($skipresults)) {
266
        $search_info .= ' - ' . sprintf(_SR_FOUND, $num_results - $skipresults);
267
    }
268
    $xoopsTpl->assign('search_info', $search_info);
269
}
270
// assign template vars for search
271
/* term */
272
$xoopsTpl->assign('search_term', htmlspecialchars((string) $term, ENT_QUOTES));
273
274
/* andor */
275
$andor_select = '<select name="andor" id="andor" class="form-control">';
276
$andor_select .= '<option value="OR"';
277
if ('OR' === $andor) {
278
    $andor_select .= ' selected="selected"';
279
}
280
$andor_select .= '>' . _SR_ANY . '</option>';
281
$andor_select .= '<option value="AND"';
282
if ('AND' === $andor || ($andor === '' || $andor === '0')) {
283
    $andor_select .= ' selected="selected"';
284
}
285
$andor_select .= '>' . _SR_ALL . '</option>';
286
$andor_select .= '</select>';
287
$xoopsTpl->assign('andor_selection_box', $andor_select);
288
289
/* forum */
290
$select_forum = '<select class="form-control" name="forum[]" id="forum" size="5" multiple="multiple">';
291
$select_forum .= '<option value="all">' . _MD_NEWBB_SEARCHALLFORUMS . '</option>';
292
$select_forum .= newbbForumSelectBox($forum);
293
$select_forum .= '</select>';
294
$xoopsTpl->assign_by_ref('forum_selection_box', $select_forum);
295
296
/* searchin */
297
$searchin_select = '';
298
$searchin_select .= '<label class="radio-inline"><input type="radio" name="searchin" value="title"';
299
if ('title' === $searchin) {
300
    $searchin_select .= ' checked';
301
}
302
$searchin_select .= ' >' . _MD_NEWBB_SUBJECT . ' </label>';
303
$searchin_select .= '<label class="radio-inline"><input type="radio" name="searchin" value="text"';
304
if ('text' === $searchin) {
305
    $searchin_select .= ' checked';
306
}
307
$searchin_select .= ' >' . _MD_NEWBB_BODY . ' </label>';
308
$searchin_select .= '<label class="radio-inline"><input type="radio" name="searchin" value="both"';
309
if ('both' === $searchin || empty($searchin)) {
310
    $searchin_select .= ' checked';
311
}
312
$searchin_select .= ' >' . _MD_NEWBB_SUBJECT . ' & ' . _MD_NEWBB_BODY . ' </label>';
313
$xoopsTpl->assign('searchin_radio', $searchin_select);
314
315
/* show_search */
316
$show_search_select = '';
317
$show_search_select .= '<label class="radio-inline"><input type="radio" name="show_search" value="post"';
318
if ('post' === $show_search) {
319
    $show_search_select .= ' checked';
320
}
321
$show_search_select .= ' >' . _MD_NEWBB_POSTS . ' </label>';
322
$show_search_select .= '<label class="radio-inline"><input type="radio" name="show_search" value="post_text"';
323
if ('post_text' === $show_search || empty($show_search)) {
324
    $show_search_select .= ' checked';
325
}
326
$show_search_select .= ' >' . _MD_NEWBB_SEARCHPOSTTEXT . ' </label>';
327
$xoopsTpl->assign('show_search_radio', $show_search_select);
328
329
/* author */
330
$xoopsTpl->assign('author_select', $search_username);
331
332
/* sortby */
333
$sortby_select = '<select name="sortby" id="sortby" class="form-control">';
334
$sortby_select .= '<option value=\'p.post_time\'';
335
if ('p.post_time' === $sortby || ($sortby === '' || $sortby === '0')) {
336
    $sortby_select .= ' selected=\'selected\'';
337
}
338
$sortby_select .= '>' . _MD_NEWBB_DATE . '</option>';
339
$sortby_select .= '<option value=\'p.subject\'';
340
if ('p.subject' === $sortby) {
341
    $sortby_select .= ' selected="selected"';
342
}
343
$sortby_select .= '>' . _MD_NEWBB_TOPIC . '</option>';
344
$sortby_select .= '</select>';
345
$xoopsTpl->assign('sortby_selection_box', $sortby_select);
346
347
/* selectlength */
348
$xoopsTpl->assign('selectlength_select', $selectlength);
349
350
// irmtfan get since from the user for selction box
351
$since        = Request::getInt('since', $GLOBALS['xoopsModuleConfig']['since_default']);
352
$select_since = newbbSinceSelectBox($since);
353
$xoopsTpl->assign_by_ref('since_selection_box', $select_since);
354
355
if ($xoopsConfigSearch['keyword_min'] > 0) {
356
    $xoopsTpl->assign('search_rule', sprintf(_SR_KEYIGNORE, $xoopsConfigSearch['keyword_min']));
357
}
358
// irmtfan move to footer.php
359
require_once __DIR__ . '/footer.php';
360
require_once $GLOBALS['xoops']->path('footer.php');
361