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 <thorsten@phpmyfaq.de> 12 * @copyright 2010-2020 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 18define('IS_VALID_PHPMYFAQ', null); 19 20use phpMyFAQ\Captcha; 21use phpMyFAQ\Category; 22use phpMyFAQ\Comments; 23use phpMyFAQ\Entity\Comment; 24use phpMyFAQ\Entity\CommentType; 25use phpMyFAQ\Faq; 26use phpMyFAQ\Filter; 27use phpMyFAQ\Helper\FaqHelper; 28use phpMyFAQ\Helper\HttpHelper; 29use phpMyFAQ\Helper\QuestionHelper; 30use phpMyFAQ\Language; 31use phpMyFAQ\Language\Plurals; 32use phpMyFAQ\Link; 33use phpMyFAQ\Mail; 34use phpMyFAQ\Network; 35use phpMyFAQ\News; 36use phpMyFAQ\Question; 37use phpMyFAQ\Rating; 38use phpMyFAQ\Search; 39use phpMyFAQ\Search\SearchResultSet; 40use phpMyFAQ\Session; 41use phpMyFAQ\Stopwords; 42use phpMyFAQ\Strings; 43use phpMyFAQ\User; 44use phpMyFAQ\User\CurrentUser; 45use phpMyFAQ\Utils; 46use phpMyFAQ\Visits; 47 48// 49// Bootstrapping 50// 51require 'src/Bootstrap.php'; 52 53$action = Filter::filterInput(INPUT_GET, 'action', FILTER_SANITIZE_STRING); 54$ajaxLang = Filter::filterInput(INPUT_POST, 'lang', FILTER_SANITIZE_STRING); 55$code = Filter::filterInput(INPUT_POST, 'captcha', FILTER_SANITIZE_STRING); 56$currentToken = Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING); 57 58$Language = new Language($faqConfig); 59$languageCode = $Language->setLanguage($faqConfig->get('main.languageDetection'), $faqConfig->get('main.language')); 60require_once 'lang/language_en.php'; 61$faqConfig->setLanguage($Language); 62 63if (Language::isASupportedLanguage($ajaxLang)) { 64 $languageCode = trim($ajaxLang); 65 require_once 'lang/language_' . $languageCode . '.php'; 66} else { 67 $languageCode = 'en'; 68 require_once 'lang/language_en.php'; 69} 70 71// 72// Load plurals support for selected language 73// 74$plr = new Plurals($PMF_LANG); 75 76// 77// Initializing static string wrapper 78// 79Strings::init($languageCode); 80 81// 82// Send headers 83// 84$http = new HttpHelper(); 85$http->setContentType('application/json'); 86 87$faqSession = new Session($faqConfig); 88$network = new Network($faqConfig); 89$stopWords = new Stopwords($faqConfig); 90 91if (!$network->checkIp($_SERVER['REMOTE_ADDR'])) { 92 $message = ['error' => $PMF_LANG['err_bannedIP']]; 93} 94 95// 96// Check, if user is logged in 97// 98$user = CurrentUser::getFromCookie($faqConfig); 99if (!$user instanceof CurrentUser) { 100 $user = CurrentUser::getFromSession($faqConfig); 101} 102if ($user instanceof CurrentUser) { 103 $isLoggedIn = true; 104} else { 105 $isLoggedIn = false; 106} 107 108// 109// Check captcha 110// 111$captcha = new Captcha($faqConfig); 112$captcha->setUserIsLoggedIn($isLoggedIn); 113 114if ('savevoting' !== $action && 'saveuserdata' !== $action && 'changepassword' !== $action && 115 !$captcha->checkCaptchaCode($code)) { 116 $message = ['error' => $PMF_LANG['msgCaptcha']]; 117} 118 119// 120// Check if logged in if FAQ is completely secured 121// 122if (false === $isLoggedIn && $faqConfig->get('security.enableLoginOnly') && 123 'changepassword' !== $action && 'saveregistration' !== $action) { 124 $message = ['error' => $PMF_LANG['ad_msg_noauth']]; 125} 126 127if (isset($message['error'])) { 128 $http->sendJsonWithHeaders($message); 129 exit(); 130} 131 132// Save user generated content 133switch ($action) { 134 // 135 // Comments 136 // 137 case 'savecomment': 138 139 if (!$faqConfig->get('records.allowCommentsForGuests') && 140 !$user->perm->checkRight($user->getUserId(), 'addcomment')) { 141 $message = ['error' => $PMF_LANG['err_NotAuth']]; 142 break; 143 } 144 145 $faq = new Faq($faqConfig); 146 $oComment = new Comments($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 $mailer = Filter::filterInput(INPUT_POST, 'mail', FILTER_VALIDATE_EMAIL); 153 $comment = Filter::filterInput(INPUT_POST, 'comment_text', FILTER_SANITIZE_STRING); 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($mailer)) { 166 $mailer = $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($mailer)) { 173 echo json_encode(['error' => $PMF_LANG['err_SaveComment']]); 174 break; 175 } 176 } 177 178 if (!is_null($username) && !is_null($mailer) && !is_null($comment) && $stopWords->checkBannedWord( 179 $comment 180 ) && !$faq->commentDisabled( 181 $id, 182 $languageCode, 183 $type 184 )) { 185 try { 186 $faqSession->userTracking('save_comment', $id); 187 } catch (Exception $e) { 188 // @todo handle the exception 189 } 190 191 $commentEntity = new Comment(); 192 $commentEntity 193 ->setRecordId($id) 194 ->setType($type) 195 ->setUsername($username) 196 ->setEmail($mailer) 197 ->setComment(nl2br($comment)) 198 ->setDate($_SERVER['REQUEST_TIME']); 199 200 if ($oComment->addComment($commentEntity)) { 201 $emailTo = $faqConfig->get('main.administrationMail'); 202 $title = ''; 203 $urlToContent = ''; 204 if ('faq' == $type) { 205 $faq->getRecord($id); 206 if ($faq->faqRecord['email'] != '') { 207 $emailTo = $faq->faqRecord['email']; 208 } 209 210 $title = $faq->getRecordTitle($id); 211 212 $faqUrl = sprintf( 213 '%s?action=faq&cat=%d&id=%d&artlang=%s', 214 $faqConfig->getDefaultUrl(), 215 $category->getCategoryIdFromFaq($faq->faqRecord['id']), 216 $faq->faqRecord['id'], 217 $faq->faqRecord['lang'] 218 ); 219 $oLink = new Link($faqUrl, $faqConfig); 220 $oLink->itemTitle = $faq->faqRecord['title']; 221 $urlToContent = $oLink->toString(); 222 } else { 223 $news = new News($faqConfig); 224 $newsData = $news->getNewsEntry($id); 225 if ($newsData['authorEmail'] != '') { 226 $emailTo = $newsData['authorEmail']; 227 } 228 229 $title = $newsData['header']; 230 231 $link = sprintf( 232 '%s?action=news&newsid=%d&newslang=%s', 233 $faqConfig->getDefaultUrl(), 234 $newsData['id'], 235 $newsData['lang'] 236 ); 237 $oLink = new Link($link, $faqConfig); 238 $oLink->itemTitle = $newsData['header']; 239 $urlToContent = $oLink->toString(); 240 } 241 242 $commentMail = 243 'User: ' . $commentEntity->getUsername() . ', mailto:' . $commentEntity->getEmail() . "\n" . 244 'Title: ' . $title . "\n" . 245 'New comment posted here: ' . $urlToContent . 246 "\n\n" . 247 wordwrap($comment, 72); 248 249 $send = []; 250 $mailer = new Mail($faqConfig); 251 $mailer->setReplyTo($commentEntity->getEmail(), $commentEntity->getUsername()); 252 $mailer->addTo($emailTo); 253 254 $send[$emailTo] = 1; 255 $send[$faqConfig->get('main.administrationMail')] = 1; 256 257 if ($type === CommentType::FAQ) { 258 // Let the category owner of a FAQ get a copy of the message 259 $category = new Category($faqConfig); 260 $categories = $category->getCategoryIdsFromFaq($faq->faqRecord['id']); 261 foreach ($categories as $_category) { 262 $userId = $category->getOwner($_category); 263 $catUser = new User($faqConfig); 264 $catUser->getUserById($userId); 265 $catOwnerEmail = $catUser->getUserData('email'); 266 267 if ($catOwnerEmail !== '') { 268 if (!isset($send[$catOwnerEmail]) && $catOwnerEmail !== $emailTo) { 269 $mailer->addCc($catOwnerEmail); 270 $send[$catOwnerEmail] = 1; 271 } 272 } 273 } 274 } 275 276 $mailer->subject = $faqConfig->get('main.titleFAQ') . ': New comment for "' . $title . '"'; 277 $mailer->message = strip_tags($commentMail); 278 279 $result = $mailer->send(); 280 unset($mailer); 281 282 $message = ['success' => $PMF_LANG['msgCommentThanks']]; 283 } else { 284 try { 285 $faqSession->userTracking('error_save_comment', $id); 286 } catch (Exception $e) { 287 // @todo handle the exception 288 } 289 $message = ['error' => $PMF_LANG['err_SaveComment']]; 290 } 291 } else { 292 $message = ['error' => 'Please add your name, your e-mail address and a comment!']; 293 } 294 break; 295 296 case 'savefaq': 297 298 if (!$faqConfig->get('records.allowNewFaqsForGuests') && 299 !$user->perm->checkRight($user->getUserId(), 'addfaq')) { 300 $message = ['error' => $PMF_LANG['err_NotAuth']]; 301 break; 302 } 303 304 $faq = new Faq($faqConfig); 305 $category = new Category($faqConfig); 306 $questionObject = new Question($faqConfig); 307 $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING); 308 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 309 $faqId = Filter::filterInput(INPUT_POST, 'faqid', FILTER_VALIDATE_INT); 310 $faqLanguage = Filter::filterInput(INPUT_POST, 'faqlanguage', FILTER_SANITIZE_STRING); 311 $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED); 312 if ($faqConfig->get('main.enableWysiwygEditorFrontend')) { 313 $answer = Filter::filterInput(INPUT_POST, 'answer', FILTER_SANITIZE_SPECIAL_CHARS); 314 $answer = html_entity_decode($answer); 315 } else { 316 $answer = Filter::filterInput(INPUT_POST, 'answer', FILTER_SANITIZE_STRIPPED); 317 $answer = nl2br($answer); 318 } 319 $translatedAnswer = Filter::filterInput(INPUT_POST, 'translated_answer', FILTER_SANITIZE_STRING); 320 $contentLink = Filter::filterInput(INPUT_POST, 'contentlink', FILTER_SANITIZE_STRING); 321 $contentLink = Filter::filterVar($contentLink, FILTER_VALIDATE_URL); 322 $keywords = Filter::filterInput(INPUT_POST, 'keywords', FILTER_SANITIZE_STRIPPED); 323 $categories = Filter::filterInputArray( 324 INPUT_POST, 325 [ 326 'rubrik' => [ 327 'filter' => FILTER_VALIDATE_INT, 328 'flags' => FILTER_REQUIRE_ARRAY, 329 ], 330 ] 331 ); 332 333 // Check on translation 334 if (empty($answer) && !is_null($translatedAnswer)) { 335 $answer = $translatedAnswer; 336 } 337 338 if (!is_null($author) && !is_null($email) && !is_null($question) && $stopWords->checkBannedWord(strip_tags($question)) && 339 !is_null($answer) && $stopWords->checkBannedWord(strip_tags($answer)) && 340 ((is_null($faqId) && !is_null($categories['rubrik'])) || (!is_null($faqId) && !is_null($faqLanguage) && 341 Language::isASupportedLanguage($faqLanguage)))) { 342 $isNew = true; 343 if (!is_null($faqId)) { 344 $isNew = false; 345 try { 346 $faqSession->userTracking('save_new_translation_entry', 0); 347 } catch (Exception $e) { 348 // @todo handle the exception 349 } 350 } else { 351 try { 352 $faqSession->userTracking('save_new_entry', 0); 353 } catch (Exception $e) { 354 // @todo handle the exception 355 } 356 } 357 358 $isTranslation = false; 359 if (!is_null($faqLanguage)) { 360 $isTranslation = true; 361 $newLanguage = $faqLanguage; 362 } 363 364 if (Strings::substr($contentLink, 7) != '') { 365 $answer = sprintf( 366 '%s<br><div id="newFAQContentLink">%s<a href="http://%s" target="_blank">%s</a></div>', 367 $answer, 368 $PMF_LANG['msgInfo'], 369 Strings::substr($contentLink, 7), 370 $contentLink 371 ); 372 } 373 374 $autoActivate = $faqConfig->get('records.defaultActivation'); 375 376 $newData = [ 377 'lang' => ($isTranslation === true ? $newLanguage : $languageCode), 378 'thema' => $question, 379 'active' => ($autoActivate ? FAQ_SQL_ACTIVE_YES : FAQ_SQL_ACTIVE_NO), 380 'sticky' => 0, 381 'content' => $answer, 382 'keywords' => $keywords, 383 'author' => $author, 384 'email' => $email, 385 'comment' => 'y', 386 'date' => date('YmdHis'), 387 'dateStart' => '00000000000000', 388 'dateEnd' => '99991231235959', 389 'linkState' => '', 390 'linkDateCheck' => 0, 391 'notes' => '' 392 ]; 393 394 if ($isNew) { 395 $categories = $categories['rubrik']; 396 } else { 397 $newData['id'] = $faqId; 398 $categories = $category->getCategoryIdsFromFaq($newData['id']); 399 } 400 401 $recordId = $faq->addRecord($newData, $isNew); 402 403 $faq->addCategoryRelations($categories, $recordId, $newData['lang']); 404 405 $openQuestionId = Filter::filterInput(INPUT_POST, 'openQuestionID', FILTER_VALIDATE_INT); 406 if ($openQuestionId) { 407 if ($faqConfig->get('records.enableDeleteQuestion')) { 408 $questionObject->deleteQuestion($openQuestionId); 409 } else { // adds this faq record id to the related open question 410 $questionObject->updateQuestionAnswer($openQuestionId, $recordId, $categories[0]); 411 } 412 } 413 414 // Activate visits 415 $visits = new Visits($faqConfig); 416 $visits->logViews($recordId); 417 418 // Set permissions 419 $userPermissions = $category->getPermissions('user', $categories); 420 // Add user permissions 421 $faq->addPermission('user', $recordId, $userPermissions); 422 $category->addPermission('user', $categories, $userPermissions); 423 // Add group permission 424 if ($faqConfig->get('security.permLevel') !== 'basic') { 425 $groupPermissions = $category->getPermissions('group', $categories); 426 $faq->addPermission('group', $recordId, $groupPermissions); 427 $category->addPermission('group', $categories, $groupPermissions); 428 } 429 430 // Let the PMF Administrator and the Entity Owner to be informed by email of this new entry 431 $send = []; 432 $mailer = new Mail($faqConfig); 433 $mailer->setReplyTo($email, $author); 434 $mailer->addTo($faqConfig->get('main.administrationMail')); 435 $send[$faqConfig->get('main.administrationMail')] = 1; 436 437 foreach ($categories as $_category) { 438 $userId = $category->getOwner($_category); 439 $groupId = $category->getModeratorGroupId($_category); 440 441 // @todo Move this code to Entityhp 442 $oUser = new User($faqConfig); 443 $oUser->getUserById($userId); 444 $catOwnerEmail = $oUser->getUserData('email'); 445 446 // Avoid to send multiple emails to the same owner 447 if (!empty($catOwnerEmail) && !isset($send[$catOwnerEmail])) { 448 $mailer->addCc($catOwnerEmail); 449 $send[$catOwnerEmail] = 1; 450 } 451 452 if ($groupId > 0) { 453 $moderators = $oUser->perm->getGroupMembers($groupId); 454 foreach ($moderators as $moderator) { 455 $oUser->getUserById($moderator); 456 $moderatorEmail = $oUser->getUserData('email'); 457 458 // Avoid to send multiple emails to the same moderator 459 if (!empty($moderatorEmail) && !isset($send[$moderatorEmail])) { 460 $mailer->addCc($moderatorEmail); 461 $send[$moderatorEmail] = 1; 462 } 463 } 464 } 465 } 466 467 $mailer->subject = $faqConfig->get('main.titleFAQ') . ': New FAQ was added.'; 468 469 // @todo let the email contains the faq article both as plain text and as HTML 470 $mailer->message = html_entity_decode( 471 $PMF_LANG['msgMailCheck'] 472 ) . "\n\n" . 473 $faqConfig->get('main.titleFAQ') . ': ' . 474 $faqConfig->getDefaultUrl() . 'admin/?action=editentry&id=' . $recordId . '&lang=' . $faqLanguage; 475 $result = $mailer->send(); 476 unset($mailer); 477 478 $message = [ 479 'success' => ($isNew ? $PMF_LANG['msgNewContentThanks'] : $PMF_LANG['msgNewTranslationThanks']), 480 ]; 481 } else { 482 $message = [ 483 'error' => $PMF_LANG['err_SaveEntries'] 484 ]; 485 } 486 487 break; 488 489 // 490 // Add question 491 // 492 case 'savequestion': 493 494 if (!$faqConfig->get('records.allowQuestionsForGuests') && 495 !$user->perm->checkRight($user->getUserId(), 'addquestion')) { 496 $message = ['error' => $PMF_LANG['err_NotAuth']]; 497 break; 498 } 499 500 $faq = new Faq($faqConfig); 501 $cat = new Category($faqConfig); 502 $categories = $cat->getAllCategories(); 503 $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING); 504 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 505 $ucategory = Filter::filterInput(INPUT_POST, 'category', FILTER_VALIDATE_INT); 506 $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED); 507 $save = Filter::filterInput(INPUT_POST, 'save', FILTER_VALIDATE_INT, 0); 508 509 // If e-mail address is set to optional 510 if (!$faqConfig->get('main.optionalMailAddress') && is_null($email)) { 511 $email = $faqConfig->get('main.administrationMail'); 512 } 513 514 // If smart answering is disabled, save question immediately 515 if (false === $faqConfig->get('main.enableSmartAnswering')) { 516 $save = true; 517 } 518 519 if (!is_null($author) && !is_null($email) && !is_null($question) && $stopWords->checkBannedWord( 520 Strings::htmlspecialchars($question) 521 )) { 522 if ($faqConfig->get('records.enableVisibilityQuestions')) { 523 $visibility = 'N'; 524 } else { 525 $visibility = 'Y'; 526 } 527 528 $questionData = [ 529 'username' => $author, 530 'email' => $email, 531 'category_id' => $ucategory, 532 'question' => $question, 533 'is_visible' => $visibility 534 ]; 535 536 if (false === (boolean)$save) { 537 $cleanQuestion = $stopWords->clean($question); 538 539 $user = new CurrentUser($faqConfig); 540 $faqSearch = new Search($faqConfig); 541 $faqSearch->setCategory(new Category($faqConfig)); 542 $faqSearch->setCategoryId($ucategory); 543 $faqSearchResult = new SearchResultSet($user, $faq, $faqConfig); 544 $searchResult = []; 545 $mergedResult = []; 546 547 foreach ($cleanQuestion as $word) { 548 if (!empty($word)) { 549 $searchResult[] = $faqSearch->search($word, false); 550 } 551 } 552 foreach ($searchResult as $resultSet) { 553 foreach ($resultSet as $result) { 554 $mergedResult[] = $result; 555 } 556 } 557 $faqSearchResult->reviewResultSet($mergedResult); 558 559 if (0 < $faqSearchResult->getNumberOfResults()) { 560 $response = sprintf( 561 '<p>%s</p>', 562 $plr->getMsg('plmsgSearchAmount', $faqSearchResult->getNumberOfResults()) 563 ); 564 565 $response .= '<ul>'; 566 567 $faqHelper = new FaqHelper($faqConfig); 568 foreach ($faqSearchResult->getResultSet() as $result) { 569 $url = sprintf( 570 '%sindex.php?action=faq&cat=%d&id=%d&artlang=%s', 571 $faqConfig->getDefaultUrl(), 572 $result->category_id, 573 $result->id, 574 $result->lang 575 ); 576 $oLink = new Link($url, $faqConfig); 577 $oLink->text = Utils::chopString($result->question, 15); 578 $oLink->itemTitle = $result->question; 579 580 try { 581 $response .= sprintf( 582 '<li>%s<br><div class="searchpreview">%s...</div></li>', 583 $oLink->toHtmlAnchor(), 584 $faqHelper->renderAnswerPreview($result->answer, 10) 585 ); 586 } catch (Exception $e) { 587 // handle exception 588 } 589 } 590 $response .= '</ul>'; 591 592 $message = ['result' => $response]; 593 } else { 594 $questionHelper = new QuestionHelper($faqConfig, $cat); 595 $questionHelper->sendSuccessMail($questionData, $categories); 596 $message = ['success' => $PMF_LANG['msgAskThx4Mail']]; 597 } 598 } else { 599 $questionHelper = new QuestionHelper($faqConfig, $cat); 600 $questionHelper->sendSuccessMail($questionData, $categories); 601 $message = ['success' => $PMF_LANG['msgAskThx4Mail']]; 602 } 603 } else { 604 $message = ['error' => $PMF_LANG['err_SaveQuestion']]; 605 } 606 607 break; 608 609 case 'saveregistration': 610 611 $realname = Filter::filterInput(INPUT_POST, 'realname', FILTER_SANITIZE_STRING); 612 $loginName = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING); 613 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 614 615 if (!is_null($loginName) && !is_null($email) && !is_null($realname)) { 616 $message = []; 617 $user = new User($faqConfig); 618 619 // Create user account (login and password) 620 // Note: password be automatically generated and sent by email as soon if admin switch user to "active" 621 if (!$user->createUser($loginName, null)) { 622 $message = ['error' => $user->error()]; 623 } else { 624 $user->userdata->set( 625 ['display_name', 'email'], 626 [$realname, $email] 627 ); 628 // set user status 629 $user->setStatus('blocked'); 630 631 if (!$faqConfig->get('spam.manualActivation')) { 632 $isNowActive = $user->activateUser(); 633 } else { 634 $isNowActive = false; 635 } 636 637 if ($isNowActive) { 638 $adminMessage = 'This user has been automatically activated, you can still' . 639 ' modify the users permissions or decline membership by visiting the admin section'; 640 } else { 641 $adminMessage = 'To activate this user please use'; 642 } 643 644 $text = sprintf( 645 "New user has been registrated:\n\nName: %s\nLogin name: %s\n\n" . 646 '%s the administration interface at %s.', 647 $realname, 648 $loginName, 649 $adminMessage, 650 $faqConfig->getDefaultUrl() 651 ); 652 653 $mailer = new Mail($faqConfig); 654 $mailer->setReplyTo($email, $realname); 655 $mailer->addTo($faqConfig->get('main.administrationMail')); 656 $mailer->subject = Utils::resolveMarkers($PMF_LANG['emailRegSubject'], $faqConfig); 657 $mailer->message = $text; 658 $result = $mailer->send(); 659 unset($mailer); 660 661 $message = [ 662 'success' => trim($PMF_LANG['successMessage']) . 663 ' ' . 664 trim($PMF_LANG['msgRegThankYou']), 665 ]; 666 } 667 } else { 668 $message = ['error' => $PMF_LANG['err_sendMail']]; 669 } 670 break; 671 672 case 'savevoting': 673 674 $faq = new Faq($faqConfig); 675 $rating = new Rating($faqConfig); 676 $type = Filter::filterInput(INPUT_POST, 'type', FILTER_SANITIZE_STRING, 'faq'); 677 $recordId = Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT, 0); 678 $vote = Filter::filterInput(INPUT_POST, 'vote', FILTER_VALIDATE_INT); 679 $userIp = Filter::filterVar($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP); 680 681 if (isset($vote) && $rating->check($recordId, $userIp) && $vote > 0 && $vote < 6) { 682 try { 683 $faqSession->userTracking('save_voting', $recordId); 684 } catch (Exception $e) { 685 // @todo handle the exception 686 } 687 688 $votingData = [ 689 'record_id' => $recordId, 690 'vote' => $vote, 691 'user_ip' => $userIp, 692 ]; 693 694 if (!$rating->getNumberOfVotings($recordId)) { 695 $rating->addVoting($votingData); 696 } else { 697 $rating->update($votingData); 698 } 699 $message = [ 700 'success' => $PMF_LANG['msgVoteThanks'], 701 'rating' => $rating->getVotingResult($recordId), 702 ]; 703 } elseif (!$rating->check($recordId, $userIp)) { 704 try { 705 $faqSession->userTracking('error_save_voting', $recordId); 706 } catch (Exception $e) { 707 // @todo handle the exception 708 } 709 $message = ['error' => $PMF_LANG['err_VoteTooMuch']]; 710 } else { 711 try { 712 $faqSession->userTracking('error_save_voting', $recordId); 713 } catch (Exception $e) { 714 // @todo handle the exception 715 } 716 $message = ['error' => $PMF_LANG['err_noVote']]; 717 } 718 719 break; 720 721 // Send user generated mails 722 case 'sendcontact': 723 724 $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING); 725 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 726 $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED); 727 728 // If e-mail address is set to optional 729 if (!$faqConfig->get('main.optionalMailAddress') && is_null($email)) { 730 $email = $faqConfig->get('main.administrationMail'); 731 } 732 733 if (!is_null($author) && !is_null($email) && !is_null($question) && 734 !empty($question) && $stopWords->checkBannedWord(Strings::htmlspecialchars($question))) { 735 $question = sprintf( 736 "%s %s\n%s %s\n\n %s", 737 $PMF_LANG['msgNewContentName'], 738 $author, 739 $PMF_LANG['msgNewContentMail'], 740 $email, 741 $question 742 ); 743 744 $mailer = new Mail($faqConfig); 745 $mailer->setReplyTo($email, $author); 746 $mailer->addTo($faqConfig->get('main.administrationMail')); 747 $mailer->subject = Utils::resolveMarkers('Feedback: %sitename%', $faqConfig); 748 $mailer->message = $question; 749 $result = $mailer->send(); 750 751 unset($mailer); 752 753 if ($result) { 754 $message = ['success' => $PMF_LANG['msgMailContact']]; 755 } else { 756 $message = ['error' => $PMF_LANG['err_sendMail']]; 757 } 758 } else { 759 $message = ['error' => $PMF_LANG['err_sendMail']]; 760 } 761 break; 762 763 // Send mails to friends 764 case 'sendtofriends': 765 766 $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING); 767 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 768 $link = Filter::filterInput(INPUT_POST, 'link', FILTER_VALIDATE_URL); 769 $attached = Filter::filterInput(INPUT_POST, 'message', FILTER_SANITIZE_STRIPPED); 770 $mailto = Filter::filterInputArray( 771 INPUT_POST, 772 [ 773 'mailto' => [ 774 'filter' => FILTER_VALIDATE_EMAIL, 775 'flags' => FILTER_REQUIRE_ARRAY | FILTER_NULL_ON_FAILURE, 776 ], 777 ] 778 ); 779 780 if (!is_null($author) && !is_null($email) && is_array($mailto) && !empty($mailto['mailto'][0]) && 781 $stopWords->checkBannedWord(Strings::htmlspecialchars($attached))) { 782 foreach ($mailto['mailto'] as $recipient) { 783 $recipient = trim(strip_tags($recipient)); 784 if (!empty($recipient)) { 785 $mailer = new Mail($faqConfig); 786 $mailer->setReplyTo($email, $author); 787 $mailer->addTo($recipient); 788 $mailer->subject = $PMF_LANG['msgS2FMailSubject'] . $author; 789 $mailer->message = sprintf( 790 "%s\r\n\r\n%s\r\n%s\r\n\r\n%s", 791 $faqConfig->get('main.send2friendText'), 792 $PMF_LANG['msgS2FText2'], 793 $link, 794 $attached 795 ); 796 797 // Send the email 798 $result = $mailer->send(); 799 unset($mailer); 800 usleep(250); 801 } 802 } 803 804 $message = ['success' => $PMF_LANG['msgS2FThx']]; 805 } else { 806 $message = ['error' => $PMF_LANG['err_sendMail']]; 807 } 808 break; 809 810 // Save user data from UCP 811 case 'saveuserdata': 812 813 if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $currentToken) { 814 $message = ['error' => $PMF_LANG['ad_msg_noauth']]; 815 break; 816 } 817 818 $userId = Filter::filterInput(INPUT_POST, 'userid', FILTER_VALIDATE_INT); 819 $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING); 820 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 821 $password = Filter::filterInput(INPUT_POST, 'password', FILTER_SANITIZE_STRING); 822 $confirm = Filter::filterInput(INPUT_POST, 'password_confirm', FILTER_SANITIZE_STRING); 823 824 $user = CurrentUser::getFromSession($faqConfig); 825 826 if ($userId !== $user->getUserId()) { 827 $message = ['error' => 'User ID mismatch!']; 828 break; 829 } 830 831 if ($password !== $confirm) { 832 $message = ['error' => $PMF_LANG['ad_user_error_passwordsDontMatch']]; 833 break; 834 } 835 836 $userData = [ 837 'display_name' => $author, 838 'email' => $email, 839 ]; 840 $success = $user->setUserData($userData); 841 842 if (0 !== strlen($password) && 0 !== strlen($confirm)) { 843 foreach ($user->getAuthContainer() as $author => $auth) { 844 if ($auth->setReadOnly()) { 845 continue; 846 } 847 if (!$auth->changePassword($user->getLogin(), $password)) { 848 $message = ['error' => $auth->error()]; 849 $success = false; 850 } else { 851 $success = true; 852 } 853 } 854 } 855 856 if ($success) { 857 $message = ['success' => $PMF_LANG['ad_entry_savedsuc']]; 858 } else { 859 $message = ['error' => $PMF_LANG['ad_entry_savedfail']]; 860 } 861 break; 862 863 case 'changepassword': 864 865 $username = Filter::filterInput(INPUT_POST, 'username', FILTER_SANITIZE_STRING); 866 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 867 868 if (!is_null($username) && !is_null($email)) { 869 $user = new CurrentUser($faqConfig); 870 $loginExist = $user->getUserByLogin($username); 871 872 if ($loginExist && ($email == $user->getUserData('email'))) { 873 $newPassword = $user->createPassword(); 874 $user->changePassword($newPassword); 875 $text = $PMF_LANG['lostpwd_text_1'] . "\nUsername: " . $username . "\nNew Password: " . $newPassword . "\n\n" . $PMF_LANG['lostpwd_text_2']; 876 877 $mailer = new Mail($faqConfig); 878 $mailer->addTo($email); 879 $mailer->subject = Utils::resolveMarkers('[%sitename%] Username / password request', $faqConfig); 880 $mailer->message = $text; 881 $result = $mailer->send(); 882 unset($mailer); 883 // Trust that the email has been sent 884 $message = ['success' => $PMF_LANG['lostpwd_mail_okay']]; 885 } else { 886 $message = ['error' => $PMF_LANG['lostpwd_err_1']]; 887 } 888 } else { 889 $message = ['error' => $PMF_LANG['lostpwd_err_2']]; 890 } 891 break; 892 893 case 'request-removal': 894 895 $author = Filter::filterInput(INPUT_POST, 'name', FILTER_SANITIZE_STRING); 896 $loginName = Filter::filterInput(INPUT_POST, 'loginname', FILTER_SANITIZE_STRING); 897 $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); 898 $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_STRIPPED); 899 900 // If e-mail address is set to optional 901 if (!$faqConfig->get('main.optionalMailAddress') && is_null($email)) { 902 $email = $faqConfig->get('main.administrationMail'); 903 } 904 905 if (!is_null($author) && !is_null($email) && !is_null($question) && 906 !empty($question) && $stopWords->checkBannedWord(Strings::htmlspecialchars($question))) { 907 $question = sprintf( 908 "%s %s\n%s %s\n%s %s\n\n %s", 909 $PMF_LANG['ad_user_loginname'], 910 $loginName, 911 $PMF_LANG['msgNewContentName'], 912 $author, 913 $PMF_LANG['msgNewContentMail'], 914 $email, 915 $question 916 ); 917 918 $mailer = new Mail($faqConfig); 919 $mailer->setReplyTo($email, $author); 920 $mailer->addTo($faqConfig->get('main.administrationMail')); 921 $mailer->subject = $faqConfig->get('main.titleFAQ') . ': Remove User Request'; 922 $mailer->message = $question; 923 $result = $mailer->send(); 924 unset($mailer); 925 926 $message = ['success' => $PMF_LANG['msgMailContact']]; 927 } else { 928 $message = ['error' => $PMF_LANG['err_sendMail']]; 929 } 930 break; 931} 932 933$http->sendJsonWithHeaders($message); 934exit(); 935