 mambax7    /
                    smartfaq
                      mambax7    /
                    smartfaq
                
                            This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
                                via PHP's auto-loading mechanism.
                                                    | 1 | <?php declare(strict_types=1); | ||
| 2 | |||
| 3 | /** | ||
| 4 | * Module: SmartFAQ | ||
| 5 | * Author: The SmartFactory <www.smartfactory.ca> | ||
| 6 | * Licence: GNU | ||
| 7 | */ | ||
| 8 | |||
| 9 | use Xmf\Request; | ||
| 10 | use XoopsModules\Smartfaq; | ||
| 11 | use XoopsModules\Smartfaq\Constants; | ||
| 12 | use XoopsModules\Smartfaq\Helper; | ||
| 13 | |||
| 14 | require_once __DIR__ . '/admin_header.php'; | ||
| 15 | |||
| 16 | /** @var Smartfaq\Helper $helper */ | ||
| 17 | $helper = Helper::getInstance(); | ||
| 18 | |||
| 19 | $op = Request::getCmd('op', Request::getCmd('op', '', 'GET'), 'POST'); | ||
| 20 | |||
| 21 | // Creating the answer handler object | ||
| 22 | /** @var \XoopsModules\Smartfaq\AnswerHandler $answerHandler */ | ||
| 23 | $answerHandler = Helper::getInstance()->getHandler('Answer'); | ||
| 24 | |||
| 25 | /** | ||
| 26 | * @param string $faqid | ||
| 27 | */ | ||
| 28 | function editfaq(string $faqid = ''): void | ||
| 29 | { | ||
| 30 | global $answerHandler, $xoopsUser, $xoopsConfig, $xoopsDB, $modify, $xoopsModule, $XOOPS_URL, $myts, $pathIcon16; | ||
| 31 | /** @var Smartfaq\Helper $helper */ | ||
| 32 | $helper = Helper::getInstance(); | ||
| 33 | $smartModuleConfig = $helper->getConfig(); | ||
| 34 | |||
| 35 | require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php'; | ||
| 36 | |||
| 37 | // Creating the FAQ object | ||
| 38 | $faqObj = new Smartfaq\Faq($faqid); | ||
| 39 | |||
| 40 | // Creating the category object | ||
| 41 | $categoryObj = $faqObj->category(); | ||
| 42 | |||
| 43 |     if ($faqObj->notLoaded()) { | ||
| 44 |         redirect_header('index.php', 1, _AM_SF_NOFAQSELECTED); | ||
| 45 | } | ||
| 46 | |||
| 47 |     switch ($faqObj->status()) { | ||
| 48 | case Constants::SF_STATUS_ANSWERED: | ||
| 49 | $breadcrumb_action1 = _AM_SF_SUBMITTED; | ||
| 0 ignored issues–
                            show             Unused Code
    
    
    
        introduced 
                            by  
  Loading history... | |||
| 50 | $breadcrumb_action2 = _AM_SF_APPROVING; | ||
| 0 ignored issues–
                            show | |||
| 51 | $collapsableBar_title = _AM_SF_SUBMITTED_TITLE; | ||
| 0 ignored issues–
                            show | |||
| 52 | $collapsableBar_info = _AM_SF_SUBMITTED_INFO; | ||
| 0 ignored issues–
                            show | |||
| 53 | $button_caption = _AM_SF_APPROVE; | ||
| 0 ignored issues–
                            show | |||
| 54 | $an_status = Constants::SF_AN_STATUS_PROPOSED; | ||
| 0 ignored issues–
                            show | |||
| 55 | break; | ||
| 56 | } | ||
| 57 | |||
| 58 |     $module_id = $xoopsModule->getVar('mid'); | ||
| 59 | /** @var \XoopsGroupPermHandler $grouppermHandler */ | ||
| 60 |     $grouppermHandler = xoops_getHandler('groupperm'); | ||
| 61 | $groups = $xoopsUser ? $xoopsUser->getGroups() : XOOPS_GROUP_ANONYMOUS; | ||
| 62 | |||
| 63 | if (!Smartfaq\Utility::userIsAdmin() | ||
| 64 |         && (!$grouppermHandler->checkRight('category_admin', $faqObj->categoryid(), $groups, $module_id))) { | ||
| 65 |         redirect_header('<script>javascript:history.go(-1)</script>', 1, _NOPERM); | ||
| 66 | } | ||
| 67 | // Retreiving the official answer | ||
| 68 | $official_answer = $faqObj->answer(); | ||
| 69 | |||
| 70 |     Smartfaq\Utility::collapsableBar('bottomtable', 'bottomtableicon'); | ||
| 71 | echo "<img id='bottomtableicon' src=" . XOOPS_URL . '/modules/' . $xoopsModule->dirname() . "/assets/images/icon/close12.gif alt=''></a> " . _AM_SF_SUBMITTED_ANSWER . '</h3>'; | ||
| 72 | echo "<div id='bottomtable'>"; | ||
| 73 | echo '<span style="color: #567; margin: 3px 0 12px 0; font-size: small; display: block; ">' . _AM_SF_SUBMITTED_ANSWER_INFO . '</span>'; | ||
| 74 | |||
| 75 | $proposed_answers = $answerHandler->getAllAnswers($faqid, Constants::SF_AN_STATUS_PROPOSED); | ||
| 76 | |||
| 77 |     if (0 === count($proposed_answers)) { | ||
| 78 |         redirect_header('index.php', 1, _AM_SF_NOANSWERS); | ||
| 79 | } | ||
| 80 | |||
| 81 | echo "<table width='100%' cellspacing=1 cellpadding=3 border=0 class = outer> | ||
| 82 | <tr> | ||
| 83 | <td class='head' width='100px'>" . _AM_SF_CATEGORY . "</td> | ||
| 84 | <td class='even'>" . $categoryObj->name() . "</td> | ||
| 85 | </tr> | ||
| 86 | <tr> | ||
| 87 | <td class='head' width='100px'>" . _AM_SF_QUESTION . "</td> | ||
| 88 | <td class='even'>" . $faqObj->question() . '</td> | ||
| 89 | </tr>'; | ||
| 90 |     if ($official_answer) { | ||
| 91 | echo " | ||
| 92 | <tr> | ||
| 93 | <td class='head' width='100px'>" . _AM_SF_ANSWER_OFFICIAL . "</td> | ||
| 94 | <td class='even'>" . $official_answer->answer() . '</td> | ||
| 95 | </tr>'; | ||
| 96 | } | ||
| 97 | echo "</table><br>\n"; | ||
| 98 | |||
| 99 | echo "<table width='100%' cellspacing=1 cellpadding=3 border=0 class = outer>"; | ||
| 100 | echo '<tr>'; | ||
| 101 | echo "<th width='40' class='bg3' align='center'><b>" . _AM_SF_ARTID . '</b></td>'; | ||
| 102 | echo "<th class='bg3' class='bg3' align='center'><b>" . _AM_SF_ANSWER . '</b></td>'; | ||
| 103 | |||
| 104 | echo "<th width='90' class='bg3' align='center'><b>" . _AM_SF_ANSWERED . '</b></td>'; | ||
| 105 | |||
| 106 | echo "<th width='180' class='bg3' align='center'><b>" . _AM_SF_CREATED . '</b></td>'; | ||
| 107 | echo "<th width='120' class='bg3' align='center'><b>" . _AM_SF_ACTION . '</b></td>'; | ||
| 108 | echo '</tr>'; | ||
| 109 | |||
| 110 | $merge = ''; | ||
| 111 | $modify = ''; | ||
| 112 | $approve = ''; | ||
| 113 |     foreach ($proposed_answers as $proposed_answer) { | ||
| 114 |         if (Constants::SF_STATUS_NEW_ANSWER == $faqObj->status()) { | ||
| 115 | $merge = "<a href='faq.php?op=merge&faqid=" | ||
| 116 | . $faqObj->faqid() | ||
| 117 | . '&answerid=' | ||
| 118 | . $proposed_answer->answerid() | ||
| 119 | . "'><img src='" | ||
| 120 | . XOOPS_URL | ||
| 121 | . '/modules/' | ||
| 122 | . $xoopsModule->dirname() | ||
| 123 | . "/assets/images/icon/merge.gif' title='" | ||
| 124 | . _AM_SF_FAQ_MERGE | ||
| 125 | . "' alt='" | ||
| 126 | . _AM_SF_FAQ_MERGE | ||
| 127 | . "'></a> "; | ||
| 128 | $approve = "<a href='answer.php?op=selectanswer&faqid=" . $faqid . '&answerid=' . $proposed_answer->answerid() . "'><img src='" . $pathIcon16 . '/on.png' . "' title='" . _AM_SF_FAQ_APPROVE_NEW_ANSWER . "' alt='" . _AM_SF_APPROVESUB . "'></a>"; | ||
| 129 | } | ||
| 130 | $modify = "<a href='faq.php?op=mod&faqid=" . $faqObj->faqid() . '&answerid=' . $proposed_answer->answerid() . "'><img src='" . $pathIcon16 . '/edit.png' . "' title='" . _AM_SF_FAQ_REVIEW . "' alt='" . _AM_SF_FAQ_REVIEW . "'></a> "; | ||
| 131 | $delete = "<a href='answer.php?op=del&faqid=" . $faqObj->faqid() . '&answerid=' . $proposed_answer->answerid() . "'><img src='" . $pathIcon16 . '/delete.png' . "' title='" . _AM_SF_DELETESUBM . "' alt='" . _AM_SF_DELETESUBM . "'></a>"; | ||
| 132 | echo '<tr>'; | ||
| 133 | echo "<td class='head' align='center'>" . $proposed_answer->answerid() . '</td>'; | ||
| 134 | echo "<td class='even' align='left'>" . $proposed_answer->answer() . '</td>'; | ||
| 135 | |||
| 136 | //show name of the answer submitter | ||
| 137 | $submitter = Smartfaq\Utility::getLinkedUnameFromId($proposed_answer->uid(), $smartModuleConfig['userealname']); | ||
| 138 | echo "<td class='even' align='center'>" . $submitter . '</td>'; | ||
| 139 | |||
| 140 | echo "<td class='even' align='center'>" . $proposed_answer->datesub() . '</td>'; | ||
| 141 | echo "<td class='even' align='center'> $merge $modify $approve $delete </td>"; | ||
| 142 | echo '</tr>'; | ||
| 143 | } | ||
| 144 | |||
| 145 | echo "</table>\n<br>"; | ||
| 146 | } | ||
| 147 | |||
| 148 | $redirect_msg = ''; | ||
| 149 | $redirect_page = ''; | ||
| 150 | |||
| 151 | /* -- Available operations -- */ | ||
| 152 | switch ($op) { | ||
| 153 | case 'mod': | ||
| 154 | xoops_cp_header(); | ||
| 155 | require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php'; | ||
| 156 | global $xoopsUser, $xoopsConfig, $xoopsDB, $xoopsModule, $modify, $myts; | ||
| 157 |         $faqid = Request::getInt('faqid', 0, 'GET'); | ||
| 158 | editfaq($faqid); | ||
| 159 | break; | ||
| 160 | case 'selectanswer': | ||
| 161 | global $xoopsUser; | ||
| 162 | |||
| 163 |         $faqid    = Request::getInt('faqid', 0, 'GET'); | ||
| 164 |         $answerid = Request::getInt('answerid', 0, 'GET'); | ||
| 165 | |||
| 166 | // Creating the FAQ object | ||
| 167 | $faqObj = new Smartfaq\Faq($faqid); | ||
| 168 | |||
| 169 |         if ($faqObj->notLoaded()) { | ||
| 170 |             redirect_header('index.php', 1, _AM_SF_NOFAQSELECTED); | ||
| 171 | } | ||
| 172 | |||
| 173 | // Creating the answer object | ||
| 174 | $answerObj = new Smartfaq\Answer($answerid); | ||
| 175 | |||
| 176 |         if ($answerObj->notLoaded()) { | ||
| 177 |             redirect_header('index.php', 1, _AM_SF_NOFAQSELECTED); | ||
| 178 | } | ||
| 179 | |||
| 180 |         $answerObj->setVar('status', Constants::SF_AN_STATUS_APPROVED); | ||
| 181 | |||
| 182 | $notifToDo_answer = null; | ||
| 183 | $notifToDo_faq = null; | ||
| 184 | |||
| 185 |         switch ($faqObj->status()) { | ||
| 186 | // This was an Open Question that became a Submitted FAQ | ||
| 187 | case Constants::SF_STATUS_ANSWERED: | ||
| 188 |                 if (1 === $helper->getConfig('autoapprove_submitted_faq')) { | ||
| 189 | // We automatically approve Submitted Q&A | ||
| 190 | $redirect_msg = _AM_SF_ANSWER_APPROVED_PUBLISHED; | ||
| 191 |                     $faqObj->setVar('status', Constants::SF_STATUS_PUBLISHED); | ||
| 192 |                     $answerObj->setVar('status', Constants::SF_AN_STATUS_APPROVED); | ||
| 193 | $notifToDo_faq = [Constants::SF_NOT_FAQ_PUBLISHED]; | ||
| 194 |                 } else { | ||
| 195 | // Submitted Q&A need approbation | ||
| 196 | $redirect_msg = _AM_SF_ANSWER_APPROVED_NEED_APPROVED; | ||
| 197 |                     $faqObj->setVar('status', Constants::SF_STATUS_SUBMITTED); | ||
| 198 |                     $answerObj->setVar('status', Constants::SF_AN_STATUS_APPROVED); | ||
| 199 | $notifToDo_faq = [Constants::SF_NOT_FAQ_SUBMITTED]; | ||
| 200 | } | ||
| 201 | break; | ||
| 202 | // This is a published FAQ for which a user submitted a new answer and we just accepeted one | ||
| 203 | case Constants::SF_STATUS_NEW_ANSWER: | ||
| 204 | $redirect_msg = _AM_SF_FAQ_NEW_ANSWER_PUBLISHED; | ||
| 205 |                 $faqObj->setVar('status', Constants::SF_STATUS_PUBLISHED); | ||
| 206 |                 $answerObj->setVar('status', Constants::SF_AN_STATUS_APPROVED); | ||
| 207 | $notifToDo_answer = [Constants::SF_NOT_ANSWER_APPROVED]; | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | |||
| 211 | // Storing the FAQ object in the database | ||
| 212 |         if (!$faqObj->store()) { | ||
| 213 |             redirect_header('<script>javascript:history.go(-1)</script>', 2, _AM_SF_ERROR_FAQ_NOT_SAVED); | ||
| 214 | } | ||
| 215 | |||
| 216 | // Storing the answer object in the database | ||
| 217 |         if (!$answerObj->store()) { | ||
| 218 |             redirect_header('<script>javascript:history.go(-1)</script>', 2, _AM_SF_ERROR_ANSWER_NOT_SAVED); | ||
| 219 | } | ||
| 220 | |||
| 221 | // Send FAQ notifications | ||
| 222 |         if (!empty($notifToDo_faq)) { | ||
| 223 | $faqObj->sendNotifications($notifToDo_faq); | ||
| 224 | } | ||
| 225 | |||
| 226 | // Send answer notifications | ||
| 227 |         if (!empty($notifToDo_answer)) { | ||
| 228 | $answerObj->sendNotifications($notifToDo_answer); | ||
| 229 | } | ||
| 230 | |||
| 231 |         redirect_header('index.php', 2, $redirect_msg); | ||
| 232 | break; | ||
| 233 | case 'del': | ||
| 234 | global $xoopsUser, $xoopsConfig, $xoopsDB; | ||
| 235 | |||
| 236 |         $faqid     = Request::getInt('faqid', 0, 'POST'); | ||
| 237 |         $faqid     = Request::getInt('faqid', $faqid, 'GET'); | ||
| 238 |         $answerid  = Request::getInt('answerid', 0, 'POST'); | ||
| 239 |         $answerid  = Request::getInt('answerid', $answerid, 'GET'); | ||
| 240 |         $confirm   = Request::getInt('confirm', 0, 'POST'); | ||
| 241 | $faqObj = new Smartfaq\Faq($faqid); | ||
| 242 | $answerObj = new Smartfaq\Answer($answerid); | ||
| 243 |         if ($confirm) { | ||
| 244 |             $answerObj->setVar('status', Constants::SF_AN_STATUS_REJECTED); | ||
| 245 | $answerObj->store(); | ||
| 246 | |||
| 247 |             switch ($faqObj->status()) { | ||
| 248 | // Open Question for which we are rejecting an answer | ||
| 249 | case Constants::SF_STATUS_ANSWERED: | ||
| 250 | $redirect_page = 'index.php'; | ||
| 251 | $redirect_msg = _AM_SF_ANSWER_REJECTED_OPEN_QUESTION; | ||
| 252 |                     $faqObj->setVar('status', Constants::SF_STATUS_OPENED); | ||
| 253 | break; | ||
| 254 | case Constants::SF_STATUS_NEW_ANSWER: | ||
| 255 | $proposed_answers = $answerHandler->getAllAnswers($faqid, Constants::SF_AN_STATUS_PROPOSED); | ||
| 256 |                     if (count($proposed_answers) > 0) { | ||
| 257 | // This question has other proposed answer | ||
| 258 | $redirect_page = 'answer.php?op=mod&faqid=' . $faqid; | ||
| 259 | $redirect_msg = _AM_SF_ANSWER_REJECTED; | ||
| 260 |                     } else { | ||
| 261 | // The question has no other proposed answer | ||
| 262 | $redirect_page = 'index.php'; | ||
| 263 | $redirect_msg = _AM_SF_ANSWER_REJECTED; | ||
| 264 |                         $faqObj->setVar('status', Constants::SF_STATUS_PUBLISHED); | ||
| 265 | } | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | $faqObj->store(); | ||
| 269 | redirect_header($redirect_page, 3, $redirect_msg); | ||
| 270 |         } else { | ||
| 271 | xoops_cp_header(); | ||
| 272 | xoops_confirm(['op' => 'del', 'answerid' => $answerid, 'confirm' => 1, 'faqid' => $faqid], 'answer.php', _AM_SF_DELETETHISANSWER, _AM_SF_DELETE); | ||
| 273 | xoops_cp_footer(); | ||
| 274 | } | ||
| 275 | exit(); | ||
| 276 | case 'default': | ||
| 277 | default: | ||
| 278 | xoops_cp_header(); | ||
| 279 | |||
| 280 | require_once XOOPS_ROOT_PATH . '/class/xoopsformloader.php'; | ||
| 281 | global $xoopsUser, $xoopsConfig, $xoopsDB, $xoopsModule; | ||
| 282 | $helper = Helper::getInstance(); | ||
| 283 | |||
| 284 | editfaq(); | ||
| 285 | break; | ||
| 286 | } | ||
| 287 | |||
| 288 | require_once __DIR__ . '/admin_footer.php'; | ||
| 289 | 
