Issues (371)

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.
1
<?php declare(strict_types=1);
2
/*
3
                XOOPS - PHP Content Management System
4
                    Copyright (c) 2000-2020 XOOPS.org
5
                       <https://xoops.org>
6
  This program is free software; you can redistribute it and/or modify
7
  it under the terms of the GNU General Public License as published by
8
  the Free Software Foundation; either version 2 of the License, or
9
  (at your option) any later version.
10
11
  You may not change or alter any portion of this comment or credits
12
  of supporting developers from this source code or any supporting
13
  source code which is considered copyrighted (c) material of the
14
  original comment or credit authors.
15
16
  This program is distributed in the hope that it will be useful,
17
  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
  GNU General Public License for more details.
20
21
  You should have received a copy of the GNU General Public License
22
  along with this program; if not, write to the Free Software
23
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
24
*/
25
26
/**
27
 * XOOPS Poll main index page
28
 *
29
 * @copyright::  {@link https://xoops.org XOOPS Project}
30
 * @license  ::    {@link https://www.gnu.org/licenses/gpl-2.0.html GNU GPL 2.0 or later}
31
 * @since    ::      1.0
32
 *
33
 * @uses     xoops_load() method used to load classes
34
 * @uses     CriteriaCompo
35
 * @uses     Criteria
36
 * @uses     mixed $GLOBALS['xoops']::path gets XOOPS directory information
37
 * @uses     string $GLOBALS['xoops']::url gets XOOPS URL/URI information
38
 * @uses     mixed $GLOBALS['xoopsUser'] gets information about the currently logged-in user
39
 * @uses     xoops_getenv() function to retrieve XOOPS environment variables
40
 * @uses     xoops_getUserTimestamp() function to convert time to user timestamp
41
 * @uses     formatTimestamp() function to convert timestamp to human-readable form
42
 * @uses     xoops_getModuleHandler() to load handler for this module's class(es)
43
 * @uses     redirect_header() function used to send user to another location after completing task(s)
44
 */
45
46
use Xmf\Module\Admin;
47
use Xmf\Request;
48
use XoopsModules\Newbb;
49
use XoopsModules\Xoopspoll\{
50
    Constants,
51
    Helper,
52
    Poll,
53
    Renderer,
54
    Utility
55
};
56
57
require_once \dirname(__DIR__, 2) . '/mainfile.php';
58
59
$helper      = Helper::getInstance();
60
$myts        = \MyTextSanitizer::getInstance();
61
$pollHandler = $helper->getHandler('Poll');
62
$logHandler  = $helper->getHandler('Log');
63
64
$pollId = Request::getInt('poll_id', 0);
65
$url    = Request::getString('url', '');
66
67
if (empty($pollId)) {
68
    $GLOBALS['xoopsOption']['template_main'] = 'xoopspoll_index.tpl';
69
    require $GLOBALS['xoops']->path('header.php');
70
    $GLOBALS['xoopsTpl']->assign(
71
        [
72
            'lang_pollslist'      => _MD_XOOPSPOLL_POLLSLIST,
73
            'lang_pollquestion'   => _MD_XOOPSPOLL_POLLQUESTION,
74
            'lang_pollvoters'     => _MD_XOOPSPOLL_VOTERS,
75
            'lang_votes'          => _MD_XOOPSPOLL_VOTES,
76
            'lang_expiration'     => _MD_XOOPSPOLL_EXPIRATION,
77
            'lang_results'        => _MD_XOOPSPOLL_RESULTS,
78
            'lang_mustlogin'      => _MD_XOOPSPOLL_MUSTLOGIN,
79
            'disp_votes'          => $GLOBALS['xoopsModuleConfig']['disp_vote_nums'],
80
            'results_link_icon'   => Admin::iconUrl('', '16') . '/open12.gif',
81
            'obscured_icon'       => $GLOBALS['xoops']->url('modules/xoopspoll/assets/images/icons/obscured.png'),
82
            'lang_obscured_alt'   => _MD_XOOPSPOLL_OBSCURED,
83
            'lang_obscured_title' => _MD_XOOPSPOLL_OBSCURED,
84
        ]
85
    );
86
87
    /* get polls to display on this page */
88
    $limit    = Request::getInt('limit', Constants::DEFAULT_POLL_PAGE_LIMIT);
89
    $start    = Request::getInt('start', 0);
90
    $criteria = new \CriteriaCompo();
91
    $criteria->add(new \Criteria('start_time', time(), '<='));  // only display polls that have started
92
93
    /* check to see if forum module is installed and
94
     * exclude polls created from a forum
95
     */
96
    if ($GLOBALS['xoopsModuleConfig']['hide_forum_polls']) {
97
        /** @var \XoopsModuleHandler $moduleHandler */
98
        $moduleHandler = xoops_getHandler('module');
99
        $newbbModule   = $moduleHandler->getByDirname('newbb');
100
        if ($newbbModule instanceof \XoopsModule && $newbbModule->isactive()) {
101
            /** @var Newbb\TopicHandler $topicHandler */
102
            $topicHandler = Newbb\Helper::getInstance()->getHandler('Topic');
103
            $tFields      = ['topic_id', 'poll_id'];
104
            $tArray       = $topicHandler->getAll(new \Criteria('topic_haspoll', 0, '>'), $tFields, false);
105
            if (!empty($tArray)) {
106
                $tcriteria = [];
107
                foreach ($tArray as $t) {
108
                    $tcriteria[] = $t['poll_id'];
109
                }
110
                if (!empty($tcriteria)) {
111
                    $tstring = '(' . implode(',', $tcriteria) . ')';
112
                    $criteria->add(new \Criteria('poll_id', $tstring, 'NOT IN'));
113
                }
114
            }
115
            unset($topicHandler, $tFields, $tArray);
116
        }
117
        unset($newbbModule);
118
    }
119
    $criteria->setLimit($limit);
120
    $criteria->setStart($start);
121
    $criteria->setSort('weight ASC, end_time');  // trick criteria to allow 2 sort criteria
122
    $criteria->setOrder('DESC');
123
    $pollObjs = $pollHandler->getAll($criteria);
124
125
    foreach ($pollObjs as $pollObj) {
126
        $polls                 = [];
127
        $id                    = $pollObj->getVar('poll_id');
128
        $polls['pollId']       = $id;
129
        $polls['pollQuestion'] = $pollObj->getVar('question');
130
131
        if ($pollObj->getVar('end_time') > time()) {
132
            $polls['hasEnded'] = false;
133
            $polls['pollEnd']  = formatTimestamp($pollObj->getVar('end_time'), 'm');
134
            $uid               = (($GLOBALS['xoopsUser'] instanceof \XoopsUser)
135
                                  && ($GLOBALS['xoopsUser']->getVar('uid') > 0)) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
136
            /**
137
             * {@internal DEBUG CODE
138
             * echo "<br>ID[{$id}] IP[" . xoops_getenv('REMOTE_ADDR') . "] UID[{$uid}]<br>";
139
             * $vp = (!empty($_COOKIE['voted_polls'])) ? $_COOKIE['voted_polls'] : array();
140
             * $cook = (!array_key_exists($id, $vp)) ? "NO COOKIE KEY" : "FOUND COOKIE KEY";
141
             * $cv = (!$pollObj->isAllowedToVote()) ? "Not ALLOWED" :  "ALLOWED";
142
             * $lv = ($logHandler->hasVoted($id, xoops_getenv('REMOTE_ADDR'), $uid)) ? "HAS VOTED" : "HAS NOT VOTED";
143
             * if (!$pollObj->isAllowedToVote() || ($logHandler->hasVoted($id, xoops_getenv('REMOTE_ADDR'), $uid))) {
144
             * echo "NO: {$cv} {$lv} {$cook}<br>\n";
145
             * } else {
146
             * echo "YES: {$cv} {$lv} {$cook}<br>\n";
147
             * }
148
             * } */
149
            if (!$pollObj->isAllowedToVote() || $logHandler->hasVoted($id, xoops_getenv('REMOTE_ADDR'), $uid)) {
150
                $polls['canVote'] = false;
151
            } else {
152
                $polls['canVote'] = true;
153
            }
154
        } else {
155
            /* poll has ended */
156
            $polls['hasEnded'] = true;
157
            $polls['pollEnd']  = _MD_XOOPSPOLL_EXPIRED;
158
            $polls['canVote']  = false; /* force so user can't vote */
159
        }
160
        $polls['pollVoters'] = (int)$pollObj->getVar('voters');
161
        $polls['pollVotes']  = (int)$pollObj->getVar('votes');
162
        $polls['visible']    = true === $pollObj->isResultVisible();
163
        $GLOBALS['xoopsTpl']->append('polls', $polls);
164
    }
165
    unset($pollObjs);
166
    require $GLOBALS['xoops']->path('footer.php');
167
} elseif (!empty($_POST['option_id'])) {
168
    /* user just tried to vote */
169
    //    $option_id   = Request::getInt('option_id', 0, 'POST');
170
    $mail_author = false;
171
    $pollObj     = $pollHandler->get($pollId);
172
    if ($pollObj instanceof Poll) {
173
        if ($pollObj->getVar('multiple')) {
174
            $optionId = Request::getArray('option_id', [], 'POST');
175
            $optionId = array_map('\intval', $optionId); // make sure values are integers
176
        } else {
177
            $optionId = Request::getInt('option_id', 0, 'POST');
178
        }
179
        if ($pollObj->hasExpired()) {
180
            /* poll has expired so just show the results */
181
            $msg = _MD_XOOPSPOLL_SORRYEXPIRED;
182
        } else {
183
            $msg = _MD_XOOPSPOLL_MUSTLOGIN;
184
            //@todo:: add $url to all redirects
185
            //            $url = $GLOBALS['xoops']->buildUrl("index.php", array('poll_id' => $pollId));
186
            if ($pollObj->isAllowedToVote()) {
187
                $thisVoter     = (!empty($GLOBALS['xoopsUser'])
188
                                  && ($GLOBALS['xoopsUser'] instanceof \XoopsUser)) ? $GLOBALS['xoopsUser']->getVar('uid') : null;
189
                $votedThisPoll = $logHandler->hasVoted($pollId, xoops_getenv('REMOTE_ADDR'), (int)$thisVoter);
190
                if (!$votedThisPoll) {
191
                    /* user that hasn't voted before in this poll or module preferences allow it */
192
                    $voteTime = time();
193
                    if ($pollObj->vote($optionId, xoops_getenv('REMOTE_ADDR'), $voteTime)) {
194
                        if (!$pollHandler->updateCount($pollObj)) { // update the count and save in db
0 ignored issues
show
Bug Best Practice introduced by
The expression $pollHandler->updateCount($pollObj) of type false|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
195
                            echo $pollObj->getHtmlErrors();
196
                            exit();
197
                        }
198
                        $msg = _MD_XOOPSPOLL_THANKSFORVOTE;
199
                    } else {
200
                        /* there was a problem registering the vote */
201
                        redirect_header($GLOBALS['xoops']->buildUrl('index.php', ['poll_id' => $pollId]), Constants::REDIRECT_DELAY_MEDIUM, _MD_XOOPSPOLL_VOTE_ERROR);
202
                    }
203
                } else {
204
                    $msg = _MD_XOOPSPOLL_ALREADYVOTED;
205
                }
206
                /* set anon user vote (and the time they voted) */
207
                if (!$GLOBALS['xoopsUser'] instanceof \XoopsUser) {
208
                    Utility::setVoteCookie($pollId, (string)$voteTime, 0);
209
                }
210
            } else {
211
                $msg = _MD_XOOPSPOLL_CANNOTVOTE;
212
            }
213
        }
214
    } else {
215
        $msg = _MD_XOOPSPOLL_ERROR_INVALID_POLLID;
216
    }
217
    if ('' !== $url) {
218
        redirect_header($url, Constants::REDIRECT_DELAY_MEDIUM, $msg);
219
    } else {
220
        redirect_header($GLOBALS['xoops']->buildUrl('pollresults.php', ['poll_id' => $pollId]), Constants::REDIRECT_DELAY_MEDIUM, $msg);
221
    }
222
} else {
223
    $pollObj = $pollHandler->get($pollId);
224
    if ($pollObj->hasExpired()) {
225
        redirect_header($GLOBALS['xoops']->buildUrl('pollresults.php', ['poll_id' => $pollId]), Constants::REDIRECT_DELAY_SHORT, _MD_XOOPSPOLL_SORRYEXPIRED);
226
    }
227
    $GLOBALS['xoopsOption']['template_main'] = 'xoopspoll_view.tpl';
228
    require $GLOBALS['xoops']->path('header.php');
229
230
    $renderer = new Renderer($pollObj, $helper);
231
    $renderer->assignForm($GLOBALS['xoopsTpl']);
232
233
    $voteCount = $logHandler->getTotalVotesByPollId($pollId);
234
235
    $canVote    = false;
236
    $lang_multi = '';
237
    if ($pollObj->isAllowedToVote()) {
238
        $thisVoter  = (!empty($GLOBALS['xoopsUser'])
239
                       && ($GLOBALS['xoopsUser'] instanceof \XoopsUser)) ? $GLOBALS['xoopsUser']->getVar('uid') : null;
240
        $canVote    = !$logHandler->hasVoted($pollId, xoops_getenv('REMOTE_ADDR'), $thisVoter);
241
        $multiple   = $pollObj->getVar('multiple');
242
        $multiLimit = (int)$pollObj->getVar('multilimit');
243
        if ($multiple && ($multiLimit > 0)) {
244
            $lang_multi = sprintf(_MD_XOOPSPOLL_MULTITEXT, $multiLimit);
245
        }
246
    }
247
248
    $GLOBALS['xoopsTpl']->assign(
249
        [
250
            'voteCount'    => $voteCount,
251
            'lang_vote'    => _MD_XOOPSPOLL_VOTE,
252
            'lang_results' => _MD_XOOPSPOLL_RESULTS,
253
            'disp_votes'   => $GLOBALS['xoopsModuleConfig']['disp_vote_nums'],
254
            'can_vote'     => $canVote,
255
            'lang_multi'   => $lang_multi,
256
        ]
257
    );
258
    require $GLOBALS['xoops']->path('footer.php');
259
}
260