GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (421)

Security Analysis    not enabled

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

  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.
  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.
  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.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  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.
  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.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
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.

phpmyfaq/ajaxservice.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * The Ajax Service Layer.
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public License,
7
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8
 * obtain one at http://mozilla.org/MPL/2.0/.
9
 *
10
 * @package phpMyFAQ
11
 * @author Thorsten Rinne <[email protected]>
12
 * @copyright 2010-2019 phpMyFAQ Team
13
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14
 * @link https://www.phpmyfaq.de
15
 * @since 2010-09-15
16
 */
17
18
define('IS_VALID_PHPMYFAQ', null);
19
20
use phpMyFAQ\Captcha;
21
use phpMyFAQ\Category;
22
use phpMyFAQ\Comment;
23
use phpMyFAQ\Faq;
24
use phpMyFAQ\Filter;
25
use phpMyFAQ\Helper\HttpHelper;
26
use phpMyFAQ\Helper\FaqHelper;
27
use phpMyFAQ\Language;
28
use phpMyFAQ\Language\Plurals;
29
use phpMyFAQ\Link;
30
use phpMyFAQ\Mail;
31
use phpMyFAQ\Network;
32
use phpMyFAQ\News;
33
use phpMyFAQ\Rating;
34
use phpMyFAQ\Search;
35
use phpMyFAQ\Search\Resultset;
36
use phpMyFAQ\Session;
37
use phpMyFAQ\Stopwords;
38
use phpMyFAQ\Strings;
39
use phpMyFAQ\User;
40
use phpMyFAQ\User\CurrentUser;
41
use phpMyFAQ\Utils;
42
use phpMyFAQ\Visits;
43
44
//
45
// Bootstrapping
46
//
47
require 'src/Bootstrap.php';
48
49
$action = Filter::filterInput(INPUT_GET, 'action', FILTER_SANITIZE_STRING);
50
$ajaxLang = Filter::filterInput(INPUT_POST, 'lang', FILTER_SANITIZE_STRING);
51
$code = Filter::filterInput(INPUT_POST, 'captcha', FILTER_SANITIZE_STRING);
52
$currentToken = Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
53
54
$Language = new Language($faqConfig);
55
$languageCode = $Language->setLanguage($faqConfig->get('main.languageDetection'), $faqConfig->get('main.language'));
56
require_once 'lang/language_en.php';
57
$faqConfig->setLanguage($Language);
58
59 View Code Duplication
if (Language::isASupportedLanguage($ajaxLang)) {
60
    $languageCode = trim($ajaxLang);
61
    require_once 'lang/language_'.$languageCode.'.php';
62
} else {
63
    $languageCode = 'en';
64
    require_once 'lang/language_en.php';
65
}
66
67
//
68
// Load plurals support for selected language
69
//
70
$plr = new Plurals($PMF_LANG);
71
72
//
73
// Initalizing static string wrapper
74
//
75
Strings::init($languageCode);
76
77
//
78
// Check captcha
79
//
80
$captcha = new Captcha($faqConfig);
81
$captcha->setSessionId(
82
    Filter::filterInput(INPUT_COOKIE, Session::PMF_COOKIE_NAME_SESSIONID, FILTER_VALIDATE_INT)
83
);
84
85
//
86
// Send headers
87
//
88
$http = new HttpHelper();
89
$http->setContentType('application/json');
90
91
//
92
// Set session
93
//
94
$faqSession = new Session($faqConfig);
95
$network = new Network($faqConfig);
96
$stopWords = new Stopwords($faqConfig);
97
98
if (!$network->checkIp($_SERVER['REMOTE_ADDR'])) {
99
    $message = array('error' => $PMF_LANG['err_bannedIP']);
100
}
101
102
//
103
// Check, if user is logged in
104
//
105
$user = CurrentUser::getFromCookie($faqConfig);
106
if (!$user instanceof CurrentUser) {
107
    $user = CurrentUser::getFromSession($faqConfig);
108
}
109
if ($user instanceof CurrentUser) {
110
    $isLoggedIn = true;
111
} else {
112
    $isLoggedIn = false;
113
}
114
115
if ('savevoting' !== $action && 'saveuserdata' !== $action && 'changepassword' !== $action &&
116
    !$captcha->checkCaptchaCode($code) && !$isLoggedIn) {
117
    $message = ['error' => $PMF_LANG['msgCaptcha']];
118
}
119
120
//
121
// Check if logged in if FAQ is completely secured
122
//
123
if (false === $isLoggedIn && $faqConfig->get('security.enableLoginOnly') &&
124
    'changepassword' !== $action && 'saveregistration' !== $action) {
125
    $message = ['error' => $PMF_LANG['ad_msg_noauth']];
126
}
127
128
if (isset($message['error'])) {
129
    $http->sendJsonWithHeaders($message);
130
    exit();
131
}
132
133
// Save user generated content
134
switch ($action) {
135
136
    // Comments
137
    case 'savecomment':
138
139 View Code Duplication
        if (!$faqConfig->get('records.allowCommentsForGuests') &&
140
            !$user->perm->checkRight($user->getUserId(), 'addcomment')) {
141
            $message = array('error' => $PMF_LANG['err_NotAuth']);
142
            break;
143
        }
144
145
        $faq = new Faq($faqConfig);
146
        $oComment = new Comment($faqConfig);
147
        $category = new Category($faqConfig);
148
        $type = Filter::filterInput(INPUT_POST, 'type', FILTER_SANITIZE_STRING);
149
        $faqId = Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT, 0);
150
        $newsId = Filter::filterInput(INPUT_POST, 'newsid', FILTER_VALIDATE_INT);
151
        $username = Filter::filterInput(INPUT_POST, 'user', FILTER_SANITIZE_STRING);
152
        $mail = Filter::filterInput(INPUT_POST, 'mail', FILTER_VALIDATE_EMAIL);
153
        $comment = Filter::filterInput(INPUT_POST, 'comment_text', FILTER_SANITIZE_SPECIAL_CHARS);
154
155
        switch ($type) {
156
            case 'news':
157
                $id = $newsId;
158
                break;
159
            case 'faq';
160
                $id = $faqId;
161
                break;
162
        }
163
164
        // If e-mail address is set to optional
165
        if (!$faqConfig->get('main.optionalMailAddress') && is_null($mail)) {
166
            $mail = $faqConfig->get('main.administrationMail');
167
        }
168
169
        // Check display name and e-mail address for not logged in users
170
        if (false === $isLoggedIn) {
171
            $user = new User($faqConfig);
172
            if (true === $user->checkDisplayName($username) && true === $user->checkMailAddress($mail)) {
173
                echo json_encode(array('error' => $PMF_LANG['err_SaveComment']));
174
                break;
175
            }
176
        }
177
178
        if (!is_null($username) && !empty($username) && !empty($mail) && !is_null($mail) && !is_null($comment) &&
179
            !empty($comment) && $stopWords->checkBannedWord($comment) && !$faq->commentDisabled($id, $languageCode, $type)) {
180
            try {
181
                $faqSession->userTracking('save_comment', $id);
182
            } catch (Exception $e) {
183
                // @todo handle the exception
184
            }
185
186
            $commentData = [
187
                'record_id' => $id,
188
                'type' => $type,
189
                'username' => $username,
190
                'usermail' => $mail,
191
                'comment' => nl2br($comment),
192
                'date' => $_SERVER['REQUEST_TIME'],
193
                'helped' => '',
194
            ];
195
196
            if ($oComment->addComment($commentData)) {
197
                $emailTo = $faqConfig->get('main.administrationMail');
198
                $urlToContent = '';
199
                if ('faq' == $type) {
200
                    $faq->getRecord($id);
201
                    if ($faq->faqRecord['email'] != '') {
202
                        $emailTo = $faq->faqRecord['email'];
203
                    }
204
                    $faqUrl = sprintf(
205
                        '%s?action=faq&cat=%d&id=%d&artlang=%s',
206
                        $faqConfig->getDefaultUrl(),
207
                        $category->getCategoryIdFromFaq($faq->faqRecord['id']),
208
                        $faq->faqRecord['id'],
209
                        $faq->faqRecord['lang']
210
                    );
211
212
                    $oLink = new Link($faqUrl, $faqConfig);
213
                    $oLink->itemTitle = $faq->faqRecord['title'];
214
                    $urlToContent = $oLink->toString();
215
                } else {
216
                    $oNews = new News($faqConfig);
217
                    $news = $oNews->getNewsEntry($id);
218
                    if ($news['authorEmail'] != '') {
219
                        $emailTo = $news['authorEmail'];
220
                    }
221
                    $link = sprintf('%s?action=news&newsid=%d&newslang=%s',
222
                        $faqConfig->getDefaultUrl(),
223
                        $news['id'],
224
                        $news['lang']
225
                    );
226
                    $oLink = new Link($link, $faqConfig);
227
                    $oLink->itemTitle = $news['header'];
228
                    $urlToContent = $oLink->toString();
229
                }
230
231
                $commentMail =
232
                    'User: '.$commentData['username'].', mailto:'.$commentData['usermail']."\n".
233
                    'New comment posted on: '.$urlToContent.
234
                    "\n\n".
235
                    wordwrap($comment, 72);
236
237
                $send = [];
238
                $mail = new Mail($faqConfig);
239
                $mail->setReplyTo($commentData['usermail'], $commentData['username']);
240
                $mail->addTo($emailTo);
241
242
                $send[$emailTo] = 1;
243
                $send[$faqConfig->get('main.administrationMail')] = 1;
244
245
                // Let the category owner get a copy of the message
246
                $category = new Category($faqConfig);
247
                $categories = $category->getCategoryIdsFromFaq($faq->faqRecord['id']);
248
                foreach ($categories as $_category) {
249
                    $userId = $category->getOwner($_category);
250
                    $catUser = new User($faqConfig);
251
                    $catUser->getUserById($userId);
252
                    $catOwnerEmail = $catUser->getUserData('email');
253
254
                    if ($catOwnerEmail !== '') {
255
                        if (!isset($send[$catOwnerEmail]) && $catOwnerEmail !== $emailTo) {
256
                            $mail->addCc($catOwnerEmail);
257
                            $send[$catOwnerEmail] = 1;
258
                        }
259
                    }
260
                }
261
262
                $mail->subject = '%sitename%';
263
                $mail->message = strip_tags($commentMail);
264
                $result = $mail->send();
265
                unset($mail);
266
267
                $message = array('success' => $PMF_LANG['msgCommentThanks']);
268
            } else {
269
                try {
270
                    $faqSession->userTracking('error_save_comment', $id);
271
                } catch (Exception $e) {
272
                    // @todo handle the exception
273
                }
274
                $message = array('error' => $PMF_LANG['err_SaveComment']);
275
            }
276
        } else {
277
            $message = array('error' => 'Please add your name, your e-mail address and a comment!');
278
        }
279
        break;
280
281
    case 'savefaq':
282
283 View Code Duplication
        if (!$faqConfig->get('records.allowNewFaqsForGuests') &&
284
            !$user->perm->checkRight($user->getUserId(), 'addfaq')) {
285
            $message = array('error' => $PMF_LANG['err_NotAuth']);
286
            break;
287
        }
288
289
        $faq = new Faq($faqConfig);
290
        $category = new Category($faqConfig);
291
        $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
292
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
293
        $faqId = Filter::filterInput(INPUT_POST, 'faqid', FILTER_VALIDATE_INT);
294
        $faqLanguage = Filter::filterInput(INPUT_POST, 'faqlanguage', FILTER_SANITIZE_STRING);
295
        $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED);
296
        if ($faqConfig->get('main.enableWysiwygEditorFrontend')) {
297
            $answer = Filter::filterInput(INPUT_POST, 'answer', FILTER_SANITIZE_SPECIAL_CHARS);
298
            $answer = html_entity_decode($answer);
299
        } else {
300
            $answer = Filter::filterInput(INPUT_POST, 'answer', FILTER_SANITIZE_STRIPPED);
301
            $answer = nl2br($answer);
302
        }
303
        $translatedAnswer = Filter::filterInput(INPUT_POST, 'translated_answer', FILTER_SANITIZE_STRING);
304
        $contentLink = Filter::filterInput(INPUT_POST, 'contentlink', FILTER_SANITIZE_STRING);
305
        $contentLink = Filter::filterVar($contentLink, FILTER_VALIDATE_URL);
306
        $keywords = Filter::filterInput(INPUT_POST, 'keywords', FILTER_SANITIZE_STRIPPED);
307
        $categories = Filter::filterInputArray(
308
            INPUT_POST,
309
            array(
310
                'rubrik' => array(
311
                    'filter' => FILTER_VALIDATE_INT,
312
                    'flags' => FILTER_REQUIRE_ARRAY,
313
                ),
314
            )
315
        );
316
317
        // Check on translation
318
        if (empty($answer) && !is_null($translatedAnswer)) {
319
            $answer = $translatedAnswer;
320
        }
321
322
        if (!is_null($author) && !empty($author) && !is_null($email) && !empty($email) &&
323
            !is_null($question) && !empty($question) && $stopWords->checkBannedWord(strip_tags($question)) &&
324
            !is_null($answer) && !empty($answer) && $stopWords->checkBannedWord(strip_tags($answer)) &&
325
            ((is_null($faqId) && !is_null($categories['rubrik'])) || (!is_null($faqId) && !is_null($faqLanguage) &&
326
            Language::isASupportedLanguage($faqLanguage)))) {
327
            $isNew = true;
328
            if (!is_null($faqId)) {
329
                $isNew = false;
330
                try {
331
                    $faqSession->userTracking('save_new_translation_entry', 0);
332
                } catch (Exception $e) {
333
                    // @todo handle the exception
334
                }
335
            } else {
336
                try {
337
                    $faqSession->userTracking('save_new_entry', 0);
338
                } catch (Exception $e) {
339
                    // @todo handle the exception
340
                }
341
            }
342
343
            $isTranslation = false;
344
            if (!is_null($faqLanguage)) {
345
                $isTranslation = true;
346
                $newLanguage = $faqLanguage;
347
            }
348
349
            if (Strings::substr($contentLink, 7) != '') {
350
                $answer = sprintf(
351
                    '%s<br /><div id="newFAQContentLink">%s<a href="http://%s" target="_blank">%s</a></div>',
352
                    $answer,
353
                    $PMF_LANG['msgInfo'],
354
                    Strings::substr($contentLink, 7),
355
                    $contentLink
356
                );
357
            }
358
359
            $autoActivate = $faqConfig->get('records.defaultActivation');
360
361
            $newData = [
362
                'lang' => ($isTranslation === true ? $newLanguage : $languageCode),
363
                'thema' => $question,
364
                'active' => ($autoActivate ? FAQ_SQL_ACTIVE_YES : FAQ_SQL_ACTIVE_NO),
365
                'sticky' => 0,
366
                'content' => $answer,
367
                'keywords' => $keywords,
368
                'author' => $author,
369
                'email' => $email,
370
                'comment' => 'y',
371
                'date' => date('YmdHis'),
372
                'dateStart' => '00000000000000',
373
                'dateEnd' => '99991231235959',
374
                'linkState' => '',
375
                'linkDateCheck' => 0
376
            ];
377
378
            if ($isNew) {
379
                $categories = $categories['rubrik'];
380
            } else {
381
                $newData['id'] = $faqId;
382
                $categories = $category->getCategoryIdsFromFaq($newData['id']);
383
            }
384
385
            $recordId = $faq->addRecord($newData, $isNew);
386
387
            $faq->addCategoryRelations($categories, $recordId, $newData['lang']);
388
389
            $openQuestionId = Filter::filterInput(INPUT_POST, 'openQuestionID', FILTER_VALIDATE_INT);
390 View Code Duplication
            if ($openQuestionId) {
391
                if ($faqConfig->get('records.enableDeleteQuestion')) {
392
                    $faq->deleteQuestion($openQuestionId);
393
                } else { // adds this faq record id to the related open question
394
                    $faq->updateQuestionAnswer($openQuestionId, $recordId, $categories[0]);
395
                }
396
            }
397
398
            // Activate visits
399
            $visits = new Visits($faqConfig);
400
            $visits->logViews($recordId);
401
402
            // Set permissions
403
            $userPermissions = $category->getPermissions('user', $categories);
404
            // Add user permissions
405
            $faq->addPermission('user', $recordId, $userPermissions);
406
            $category->addPermission('user', $categories, $userPermissions);
407
            // Add group permission
408
            if ($faqConfig->get('security.permLevel') !== 'basic') {
409
                $groupPermissions = $category->getPermissions('group', $categories);
410
                $faq->addPermission('group', $recordId, $groupPermissions);
411
                $category->addPermission('group', $categories, $groupPermissions);
412
            }
413
414
            // Let the PMF Administrator and the Entity Owner to be informed by email of this new entry
415
            $send = [];
416
            $mail = new Mail($faqConfig);
417
            $mail->setReplyTo($email, $author);
418
            $mail->addTo($faqConfig->get('main.administrationMail'));
419
            $send[$faqConfig->get('main.administrationMail')] = 1;
420
421
            foreach ($categories as $_category) {
422
                $userId = $category->getOwner($_category);
423
                $groupId = $category->getModeratorGroupId($_category);
424
425
                // @todo Move this code to Entityhp
426
                $oUser = new User($faqConfig);
427
                $oUser->getUserById($userId);
428
                $catOwnerEmail = $oUser->getUserData('email');
429
430
                // Avoid to send multiple emails to the same owner
431
                if (!empty($catOwnerEmail) && !isset($send[$catOwnerEmail])) {
432
                    $mail->addCc($catOwnerEmail);
433
                    $send[$catOwnerEmail] = 1;
434
                }
435
436
                if ($groupId > 0) {
437
                    $moderators = $oUser->perm->getGroupMembers($groupId);
0 ignored issues
show
The method getGroupMembers does only exist in phpMyFAQ\Permission\MediumPermission, but not in phpMyFAQ\Permission\BasicPermission.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
438
                    foreach ($moderators as $moderator) {
439
                        $oUser->getUserById($moderator);
440
                        $moderatorEmail = $oUser->getUserData('email');
441
442
                        // Avoid to send multiple emails to the same moderator
443
                        if (!empty($moderatorEmail) && !isset($send[$moderatorEmail])) {
444
                            $mail->addCc($moderatorEmail);
445
                            $send[$moderatorEmail] = 1;
446
                        }
447
                    }
448
                }
449
            }
450
451
            $mail->subject = '%sitename%';
452
453
            // @todo let the email contains the faq article both as plain text and as HTML
454
            $mail->message = html_entity_decode(
455
                $PMF_LANG['msgMailCheck'])."\n\n".
456
                $faqConfig->get('main.titleFAQ').': '.
457
                $faqConfig->getDefaultUrl().'admin/?action=editentry&id='.$recordId.'&lang='.$faqLanguage;
458
            $result = $mail->send();
459
            unset($mail);
460
461
            $message = [
462
                'success' => ($isNew ? $PMF_LANG['msgNewContentThanks'] : $PMF_LANG['msgNewTranslationThanks']),
463
            ];
464
        } else {
465
            $message = [
466
                'error' => $PMF_LANG['err_SaveEntries']
467
            ];
468
        }
469
470
        break;
471
472
    case 'savequestion':
473
474 View Code Duplication
        if (!$faqConfig->get('records.allowQuestionsForGuests') &&
475
            !$user->perm->checkRight($user->getUserId(), 'addquestion')) {
476
            $message = ['error' => $PMF_LANG['err_NotAuth']];
477
            break;
478
        }
479
480
        $faq = new Faq($faqConfig);
481
        $cat = new Category($faqConfig);
482
        $categories = $cat->getAllCategories();
483
        $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
484
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
485
        $ucategory = Filter::filterInput(INPUT_POST, 'category', FILTER_VALIDATE_INT);
486
        $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED);
487
        $save = Filter::filterInput(INPUT_POST, 'save', FILTER_VALIDATE_INT, 0);
488
489
        // If e-mail address is set to optional
490
        if (!$faqConfig->get('main.optionalMailAddress') && is_null($email)) {
491
            $email = $faqConfig->get('main.administrationMail');
492
        }
493
494
        // If smart answering is disabled, save question immediately
495
        if (false === $faqConfig->get('main.enableSmartAnswering')) {
496
            $save = true;
497
        }
498
499
        if (!is_null($author) && !empty($author) && !is_null($email) && !empty($email) &&
500
            !is_null($question) && !empty($question) && $stopWords->checkBannedWord(Strings::htmlspecialchars($question))) {
501
            if ($faqConfig->get('records.enableVisibilityQuestions')) {
502
                $visibility = 'N';
503
            } else {
504
                $visibility = 'Y';
505
            }
506
507
            $questionData = [
508
                'username' => $author,
509
                'email' => $email,
510
                'category_id' => $ucategory,
511
                'question' => $question,
512
                'is_visible' => $visibility
513
            ];
514
515
            if (false === (boolean)$save) {
516
517
                $cleanQuestion = $stopWords->clean($question);
518
519
                $user = new CurrentUser($faqConfig);
520
                $faqSearch = new Search($faqConfig);
521
                $faqSearch->setCategory(new Category($faqConfig));
522
                $faqSearch->setCategoryId($ucategory);
523
                $faqSearchResult = new Resultset($user, $faq, $faqConfig);
524
                $searchResult = [];
525
                $mergedResult = [];
526
527
                foreach ($cleanQuestion as $word) {
528
                    if (!empty($word)) {
529
                        $searchResult[] = $faqSearch->search($word, false);
530
                    }
531
                }
532
                foreach ($searchResult as $resultSet) {
533
                    foreach ($resultSet as $result) {
534
                        $mergedResult[] = $result;
535
                    }
536
                }
537
                $faqSearchResult->reviewResultset($mergedResult);
538
539
                if (0 < $faqSearchResult->getNumberOfResults()) {
540
                    $response = sprintf(
541
                        '<p>%s</p>',
542
                        $plr->GetMsg('plmsgSearchAmount', $faqSearchResult->getNumberOfResults())
543
                    );
544
545
                    $response .= '<ul>';
546
547
                    $faqHelper = new FaqHelper($faqConfig);
548
                    foreach ($faqSearchResult->getResultset() as $result) {
549
                        $url = sprintf(
550
                            '%sindex.php?action=faq&cat=%d&id=%d&artlang=%s',
551
                            $faqConfig->getDefaultUrl(),
552
                            $result->category_id,
553
                            $result->id,
554
                            $result->lang
555
                        );
556
                        $oLink = new Link($url, $faqConfig);
557
                        $oLink->text = Utils::chopString($result->question, 15);
558
                        $oLink->itemTitle = $result->question;
559
560
                        $response .= sprintf(
561
                            '<li>%s<br /><div class="searchpreview">%s...</div></li>',
562
                            $oLink->toHtmlAnchor(),
563
                            $faqHelper->renderAnswerPreview($result->answer, 10)
564
                        );
565
                    }
566
                    $response .= '</ul>';
567
568
                    $message = array('result' => $response);
569 View Code Duplication
                } else {
570
571
                    $faq->addQuestion($questionData);
572
573
                    $questionMail = 'User: '.$questionData['username'].
574
                                ', mailto:'.$questionData['email']."\n".$PMF_LANG['msgCategory'].
575
                                ': '.$categories[$questionData['category_id']]['name']."\n\n".
576
                                wordwrap($question, 72)."\n\n".
577
                                $faqConfig->getDefaultUrl().'admin/';
578
579
                    $userId = $cat->getOwner($questionData['category_id']);
580
                    $oUser  = new User($faqConfig);
581
                    $oUser->getUserById($userId);
582
583
                    $userEmail = $oUser->getUserData('email');
584
                    $mainAdminEmail = $faqConfig->get('main.administrationMail');
585
586
                    $mail = new Mail($faqConfig);
587
                    $mail->setReplyTo($questionData['email'], $questionData['username']);
588
                    $mail->addTo($mainAdminEmail);
589
                    // Let the category owner get a copy of the message
590
                    if (!empty($userEmail) && $mainAdminEmail != $userEmail) {
591
                        $mail->addCc($userEmail);
592
                    }
593
                    $mail->subject = '%sitename%';
594
                    $mail->message = $questionMail;
595
                    $mail->send();
596
                    unset($mail);
597
598
                    $message = array('success' => $PMF_LANG['msgAskThx4Mail']);
599
                }
600 View Code Duplication
            } else {
601
                $faq->addQuestion($questionData);
602
603
                $questionMail = 'User: '.$questionData['username'].
604
                                ', mailto:'.$questionData['email']."\n".$PMF_LANG['msgCategory'].
605
                                ': '.$categories[$questionData['category_id']]['name']."\n\n".
606
                                wordwrap($question, 72)."\n\n".
607
                                $faqConfig->getDefaultUrl().'admin/';
608
609
                $userId = $cat->getOwner($questionData['category_id']);
610
                $oUser  = new User($faqConfig);
611
                $oUser->getUserById($userId);
612
613
                $userEmail = $oUser->getUserData('email');
614
                $mainAdminEmail = $faqConfig->get('main.administrationMail');
615
616
                $mail = new Mail($faqConfig);
617
                $mail->setReplyTo($questionData['email'], $questionData['username']);
618
                $mail->addTo($mainAdminEmail);
619
                // Let the category owner get a copy of the message
620
                if (!empty($userEmail) && $mainAdminEmail != $userEmail) {
621
                    $mail->addCc($userEmail);
622
                }
623
                $mail->subject = '%sitename%';
624
                $mail->message = $questionMail;
625
                $mail->send();
626
                unset($mail);
627
628
                $message = array('success' => $PMF_LANG['msgAskThx4Mail']);
629
            }
630
        } else {
631
            $message = array('error' => $PMF_LANG['err_SaveQuestion']);
632
        }
633
634
        break;
635
636
    case 'saveregistration':
637
638
        $realname = Filter::filterInput(INPUT_POST, 'realname', FILTER_SANITIZE_STRING);
639
        $loginName = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
640
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
641
642
        if (!is_null($loginName) && !empty($loginName) && !is_null($email) && !empty($email) &&
643
            !is_null($realname) && !empty($realname)) {
644
            $message = [];
645
            $user = new User($faqConfig);
646
647
            // Create user account (login and password)
648
            // Note: password be automatically generated and sent by email as soon if admin switch user to "active"
649
            if (!$user->createUser($loginName, null)) {
650
                $message = array('error' => $user->error());
651
            } else {
652
                $user->userdata->set(
653
                    array('display_name', 'email'),
654
                    array($realname, $email)
655
                );
656
                // set user status
657
                $user->setStatus('blocked');
658
659
                if (!$faqConfig->get('spam.manualActivation')) {
660
                    $isNowActive = $user->activateUser();
661
                } else {
662
                    $isNowActive = false;
663
                }
664
665
                if ($isNowActive) {
666
                    $adminMessage = 'This user has been automatically activated, you can still'.
667
                                    ' modify the users permissions or decline membership by visiting the admin section';
668
                } else {
669
                    $adminMessage = 'To activate this user please use';
670
                }
671
672
                $text = sprintf(
673
                    "New user has been registrated:\n\nName: %s\nLogin name: %s\n\n".
674
                    '%s the administration interface at %s.',
675
                    $realname,
676
                    $loginName,
677
                    $adminMessage,
678
                    $faqConfig->getDefaultUrl()
679
                );
680
681
                $mail = new Mail($faqConfig);
682
                $mail->setReplyTo($email, $realname);
683
                $mail->addTo($faqConfig->get('main.administrationMail'));
684
                $mail->subject = Utils::resolveMarkers($PMF_LANG['emailRegSubject'], $faqConfig);
685
                $mail->message = $text;
686
                $result = $mail->send();
687
                unset($mail);
688
689
                $message = array(
690
                    'success' => trim($PMF_LANG['successMessage']).
691
                                    ' '.
692
                                    trim($PMF_LANG['msgRegThankYou']),
693
                );
694
            }
695
        } else {
696
            $message = array('error' => $PMF_LANG['err_sendMail']);
697
        }
698
        break;
699
700
    case 'savevoting':
701
702
        $faq = new Faq($faqConfig);
703
        $rating = new Rating($faqConfig);
704
        $type = Filter::filterInput(INPUT_POST, 'type', FILTER_SANITIZE_STRING, 'faq');
705
        $recordId = Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT, 0);
706
        $vote = Filter::filterInput(INPUT_POST, 'vote', FILTER_VALIDATE_INT);
707
        $userIp = Filter::filterVar($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP);
708
709
        if (isset($vote) && $rating->check($recordId, $userIp) && $vote > 0 && $vote < 6) {
710
            try {
711
                $faqSession->userTracking('save_voting', $recordId);
712
            } catch (Exception $e) {
713
                // @todo handle the exception
714
            }
715
716
            $votingData = array(
717
                'record_id' => $recordId,
718
                'vote' => $vote,
719
                'user_ip' => $userIp,);
720
721
            if (!$rating->getNumberOfVotings($recordId)) {
722
                $rating->addVoting($votingData);
723
            } else {
724
                $rating->update($votingData);
725
            }
726
            $message = array(
727
                'success' => $PMF_LANG['msgVoteThanks'],
728
                'rating' => $rating->getVotingResult($recordId),
729
            );
730
        } elseif (!$rating->check($recordId, $userIp)) {
731
            try {
732
                $faqSession->userTracking('error_save_voting', $recordId);
733
            } catch (Exception $e) {
734
                // @todo handle the exception
735
            }
736
            $message = array('error' => $PMF_LANG['err_VoteTooMuch']);
737
        } else {
738
            try {
739
                $faqSession->userTracking('error_save_voting', $recordId);
740
            } catch (Exception $e) {
741
                // @todo handle the exception
742
            }
743
            $message = array('error' => $PMF_LANG['err_noVote']);
744
        }
745
746
        break;
747
748
    // Send user generated mails
749
    case 'sendcontact':
750
751
        $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
752
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
753
        $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED);
754
755
        // If e-mail address is set to optional
756
        if (!$faqConfig->get('main.optionalMailAddress') && is_null($email)) {
757
            $email = $faqConfig->get('main.administrationMail');
758
        }
759
760 View Code Duplication
        if (!is_null($author) && !empty($author) && !is_null($email) && !empty($email) && !is_null($question) &&
761
            !empty($question) && $stopWords->checkBannedWord(Strings::htmlspecialchars($question))) {
762
            $question = sprintf(
763
                "%s %s\n%s %s\n\n %s",
764
                $PMF_LANG['msgNewContentName'],
765
                $author,
766
                $PMF_LANG['msgNewContentMail'],
767
                $email,
768
                $question
769
            );
770
771
            $mail = new Mail($faqConfig);
772
            $mail->setReplyTo($email, $author);
773
            $mail->addTo($faqConfig->get('main.administrationMail'));
774
            $mail->subject = 'Feedback: %sitename%';
775
            $mail->message = $question;
776
            $result = $mail->send();
777
            unset($mail);
778
779
            $message = array('success' => $PMF_LANG['msgMailContact']);
780
        } else {
781
            $message = array('error' => $PMF_LANG['err_sendMail']);
782
        }
783
        break;
784
785
    // Send mails to friends
786
    case 'sendtofriends':
787
788
        $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
789
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
790
        $link = Filter::filterInput(INPUT_POST, 'link', FILTER_VALIDATE_URL);
791
        $attached = Filter::filterInput(INPUT_POST, 'message', FILTER_SANITIZE_STRIPPED);
792
        $mailto = Filter::filterInputArray(INPUT_POST,
793
            array('mailto' => array('filter' => FILTER_VALIDATE_EMAIL,
794
                        'flags' => FILTER_REQUIRE_ARRAY | FILTER_NULL_ON_FAILURE,
795
                ),
796
            )
797
        );
798
799
        if (!is_null($author) && !empty($author) && !is_null($email) && !empty($email) &&
800
            is_array($mailto) && !empty($mailto['mailto'][0]) &&
801
                $stopWords->checkBannedWord(Strings::htmlspecialchars($attached))) {
802
            foreach ($mailto['mailto'] as $recipient) {
803
                $recipient = trim(strip_tags($recipient));
804
                if (!empty($recipient)) {
805
                    $mail = new Mail($faqConfig);
806
                    $mail->setReplyTo($email, $author);
807
                    $mail->addTo($recipient);
808
                    $mail->subject = $PMF_LANG['msgS2FMailSubject'].$author;
809
                    $mail->message = sprintf("%s\r\n\r\n%s\r\n%s\r\n\r\n%s",
810
                        $faqConfig->get('main.send2friendText'),
811
                        $PMF_LANG['msgS2FText2'],
812
                        $link,
813
                        $attached);
814
815
                    // Send the email
816
                    $result = $mail->send();
817
                    unset($mail);
818
                    usleep(250);
819
                }
820
            }
821
822
            $message = array('success' => $PMF_LANG['msgS2FThx']);
823
        } else {
824
            $message = array('error' => $PMF_LANG['err_sendMail']);
825
        }
826
        break;
827
828
    // Save user data from UCP
829
    case 'saveuserdata':
830
831
        if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $currentToken) {
832
            $message = array('error' => $PMF_LANG['ad_msg_noauth']);
833
            break;
834
        }
835
836
        $userId = Filter::filterInput(INPUT_POST, 'userid', FILTER_VALIDATE_INT);
837
        $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
838
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
839
        $password = Filter::filterInput(INPUT_POST, 'password', FILTER_SANITIZE_STRING);
840
        $confirm = Filter::filterInput(INPUT_POST, 'password_confirm', FILTER_SANITIZE_STRING);
841
842
        $user = CurrentUser::getFromSession($faqConfig);
843
844
        if ($userId !== $user->getUserId()) {
845
            $message = array('error' => 'User ID mismatch!');
846
            break;
847
        }
848
849
        if ($password !== $confirm) {
850
            $message = array('error' => $PMF_LANG['ad_user_error_passwordsDontMatch']);
851
            break;
852
        }
853
854
        $userData = array(
855
            'display_name' => $author,
856
            'email' => $email,);
857
        $success = $user->setUserData($userData);
858
859
        if (0 !== strlen($password) && 0 !== strlen($confirm)) {
860
            foreach ($user->getAuthContainer() as $author => $auth) {
861
                if ($auth->setReadOnly()) {
862
                    continue;
863
                }
864
                if (!$auth->changePassword($user->getLogin(), $password)) {
865
                    $message = array('error' => $auth->error());
866
                    $success = false;
867
                } else {
868
                    $success = true;
869
                }
870
            }
871
        }
872
873
        if ($success) {
874
            $message = array('success' => $PMF_LANG['ad_entry_savedsuc']);
875
        } else {
876
            $message = array('error' => $PMF_LANG['ad_entry_savedfail']);
877
        }
878
        break;
879
880
    case 'changepassword':
881
882
        $username = Filter::filterInput(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
883
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
884
885
        if (!is_null($username) && !is_null($email)) {
886
            $user = new CurrentUser($faqConfig);
887
            $loginExist = $user->getUserByLogin($username);
888
889
            if ($loginExist && ($email == $user->getUserData('email'))) {
890
                $consonants = array(
891
                    'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z',
892
                );
893
                $vowels = array(
894
                    'a', 'e', 'i', 'o', 'u',
895
                );
896
                $newPassword = '';
897
                for ($i = 1; $i <= 4; ++$i) {
898
                    $newPassword .= $consonants[Utils::createRandomNumber(0, 19)];
899
                    $newPassword .= $vowels[Utils::createRandomNumber(0, 4)];
900
                }
901
                $user->changePassword($newPassword);
902
                $text = $PMF_LANG['lostpwd_text_1']."\nUsername: ".$username."\nNew Password: ".$newPassword."\n\n".$PMF_LANG['lostpwd_text_2'];
903
904
                $mail = new Mail($faqConfig);
905
                $mail->addTo($email);
906
                $mail->subject = '[%sitename%] Username / password request';
907
                $mail->message = $text;
908
                $result = $mail->send();
909
                unset($mail);
910
                // Trust that the email has been sent
911
                $message = array('success' => $PMF_LANG['lostpwd_mail_okay']);
912
            } else {
913
                $message = array('error' => $PMF_LANG['lostpwd_err_1']);
914
            }
915
        } else {
916
            $message = array('error' => $PMF_LANG['lostpwd_err_2']);
917
        }
918
        break;
919
920
    case 'request-removal':
921
922
        $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
923
        $loginName = Filter::filterInput(INPUT_POST, 'loginname', FILTER_SANITIZE_STRING);
924
        $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
925
        $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED);
926
927
        // If e-mail address is set to optional
928
        if (!$faqConfig->get('main.optionalMailAddress') && is_null($email)) {
929
            $email = $faqConfig->get('main.administrationMail');
930
        }
931
932 View Code Duplication
        if (!is_null($author) && !empty($author) && !is_null($email) && !empty($email) && !is_null($question) &&
933
            !empty($question) && $stopWords->checkBannedWord(Strings::htmlspecialchars($question))) {
934
            $question = sprintf(
935
                "%s %s\n%s %s\n%s %s\n\n %s",
936
                $PMF_LANG['ad_user_loginname'],
937
                $loginName,
938
                $PMF_LANG['msgNewContentName'],
939
                $author,
940
                $PMF_LANG['msgNewContentMail'],
941
                $email,
942
                $question
943
            );
944
945
            $mail = new Mail($faqConfig);
946
            $mail->setReplyTo($email, $author);
947
            $mail->addTo($faqConfig->get('main.administrationMail'));
948
            $mail->subject = 'Remove User Request: %sitename%';
949
            $mail->message = $question;
950
            $result = $mail->send();
951
            unset($mail);
952
953
            $message = ['success' => $PMF_LANG['msgMailContact']];
954
        } else {
955
            $message = ['error' => $PMF_LANG['err_sendMail']];
956
        }
957
        break;
958
}
959
960
$http->sendJsonWithHeaders($message);
961