1<?php 2 3/** 4 * The main admin backend index file. 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 * @author Bastian Poettner <bastian@poettner.net> 13 * @author Meikel Katzengreis <meikel@katzengreis.com> 14 * @author Minoru TODA <todam@netjapan.co.jp> 15 * @author Matteo Scaramuccia <matteo@phpmyfaq.de> 16 * @copyright 2002-2020 phpMyFAQ Team 17 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 18 * @link https://www.phpmyfaq.de 19 * @since 2002-09-16 20 */ 21 22use phpMyFAQ\Attachment\AttachmentFactory; 23use phpMyFAQ\Auth\AuthLdap; 24use phpMyFAQ\Auth\AuthSso; 25use phpMyFAQ\Faq; 26use phpMyFAQ\Filter; 27use phpMyFAQ\Helper\HttpHelper; 28use phpMyFAQ\Language; 29use phpMyFAQ\Logging; 30use phpMyFAQ\Permission\MediumPermission; 31use phpMyFAQ\Strings; 32use phpMyFAQ\System; 33use phpMyFAQ\Template; 34use phpMyFAQ\User\CurrentUser; 35 36define('PMF_ROOT_DIR', dirname(__DIR__)); 37 38// 39// Define the named constant used as a check by any included PHP file 40// 41define('IS_VALID_PHPMYFAQ', null); 42 43// 44// Bootstrapping 45// 46require PMF_ROOT_DIR.'/src/Bootstrap.php'; 47 48// get language (default: english) 49$Language = new Language($faqConfig); 50$faqLangCode = $Language->setLanguage($faqConfig->get('main.languageDetection'), $faqConfig->get('main.language')); 51// Preload English strings 52require PMF_ROOT_DIR.'/lang/language_en.php'; 53$faqConfig->setLanguage($Language); 54 55if (isset($faqLangCode) && Language::isASupportedLanguage($faqLangCode)) { 56 // Overwrite English strings with the ones we have in the current language 57 if (!file_exists(PMF_ROOT_DIR.'/lang/language_'.$faqLangCode.'.php')) { 58 $faqLangCode = 'en'; 59 } 60 require PMF_ROOT_DIR.'/lang/language_'.$faqLangCode.'.php'; 61} else { 62 $faqLangCode = 'en'; 63} 64 65// 66// Initalizing static string wrapper 67// 68Strings::init($faqLangCode); 69 70// 71// Set actual template set name 72// 73Template::setTplSetName($faqConfig->get('main.templateSet')); 74 75// 76// Initialize attachment factory 77// 78AttachmentFactory::init( 79 $faqConfig->get('records.attachmentsStorageType'), 80 $faqConfig->get('records.defaultAttachmentEncKey'), 81 $faqConfig->get('records.enableAttachmentEncryption') 82); 83 84// 85// Create a new phpMyFAQ system object 86// 87$faqSystem = new System(); 88 89// 90// Create a new HTTP Helper 91// 92$http = new HttpHelper(); 93 94// 95// Create a new FAQ object 96// 97$faq = new Faq($faqConfig); 98 99// 100// use mbstring extension if available and when possible 101// 102$validMbStrings = array('ja', 'en', 'uni'); 103$mbLanguage = ($PMF_LANG['metaLanguage'] != 'ja') ? 'uni' : $PMF_LANG['metaLanguage']; 104if (function_exists('mb_language') && in_array($mbLanguage, $validMbStrings)) { 105 mb_language($mbLanguage); 106 mb_internal_encoding('utf-8'); 107} 108 109// 110// Get user action 111// 112$action = Filter::filterInput(INPUT_GET, 'action', FILTER_SANITIZE_STRING); 113if (is_null($action)) { 114 $action = Filter::filterInput(INPUT_POST, 'action', FILTER_SANITIZE_STRING); 115} 116 117// 118// Get possible redirect action 119// 120$redirectAction = Filter::filterInput(INPUT_POST, 'redirect-action', FILTER_SANITIZE_STRING); 121if (is_null($action) && '' !== $redirectAction && 'logout' !== $redirectAction) { 122 $action = $redirectAction; 123} 124 125// authenticate current user 126$auth = null; 127$error = ''; 128$faqusername = Filter::filterInput(INPUT_POST, 'faqusername', FILTER_SANITIZE_STRING); 129$faqpassword = Filter::filterInput(INPUT_POST, 'faqpassword', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES); 130$faqremember = Filter::filterInput(INPUT_POST, 'faqrememberme', FILTER_SANITIZE_STRING); 131 132// Set username via SSO 133if ($faqConfig->get('security.ssoSupport') && isset($_SERVER['REMOTE_USER'])) { 134 $faqusername = trim($_SERVER['REMOTE_USER']); 135 $faqpassword = ''; 136} 137 138// Login via local DB or LDAP or SSO 139if (!is_null($faqusername) && !is_null($faqpassword)) { 140 $user = new CurrentUser($faqConfig); 141 if (!is_null($faqremember) && 'rememberMe' === $faqremember) { 142 $user->enableRememberMe(); 143 } 144 if ($faqConfig->get('ldap.ldapSupport') && function_exists('ldap_connect')) { 145 try { 146 $authLdap = new AuthLdap($faqConfig); 147 $user->addAuth($authLdap, 'ldap'); 148 } catch (Exception $e) { 149 $error = $e->getMessage().'<br>'; 150 } 151 } 152 if ($faqConfig->get('security.ssoSupport')) { 153 $authSso = new AuthSso($faqConfig); 154 $user->addAuth($authSso, 'sso'); 155 } 156 if ($user->login($faqusername, $faqpassword)) { 157 // login, if user account is NOT blocked 158 if ($user->getStatus() != 'blocked') { 159 $auth = true; 160 } else { 161 $error = $error.$PMF_LANG['ad_auth_fail']; 162 } 163 } else { 164 // error 165 $logging = new Logging($faqConfig); 166 $logging->logAdmin($user, 'Loginerror\nLogin: '.$faqusername.'\nErrors: '.implode(', ', $user->errors)); 167 $error = $error.$PMF_LANG['ad_auth_fail']; 168 } 169} else { 170 // Try to authenticate with cookie information 171 $user = CurrentUser::getFromCookie($faqConfig); 172 // authenticate with session information 173 if (!$user instanceof CurrentUser) { 174 $user = CurrentUser::getFromSession($faqConfig); 175 } 176 if ($user instanceof CurrentUser) { 177 $auth = true; 178 } else { 179 $user = new CurrentUser($faqConfig); 180 } 181} 182 183// logout 184if ($action == 'logout' && $auth) { 185 $user->deleteFromSession(true); 186 $auth = null; 187 $ssoLogout = $faqConfig->get('security.ssoLogoutRedirect'); 188 if ($faqConfig->get('security.ssoSupport') && !empty($ssoLogout)) { 189 $http->redirect($ssoLogout); 190 } 191} 192 193// 194// Get current admin user and group id - default: -1 195// 196if (isset($user) && is_object($user)) { 197 $currentAdminUser = $user->getUserId(); 198 if ($user->perm instanceof MediumPermission) { 199 $currentAdminGroups = $user->perm->getUserGroups($currentAdminUser); 200 } else { 201 $currentAdminGroups = array(-1); 202 } 203 if (0 === count($currentAdminGroups)) { 204 $currentAdminGroups = array(-1); 205 } 206} 207 208// 209// Get action from _GET and _POST first 210$ajax = Filter::filterInput(INPUT_GET, 'ajax', FILTER_SANITIZE_STRING); 211if (is_null($ajax)) { 212 $ajax = Filter::filterInput(INPUT_POST, 'ajax', FILTER_SANITIZE_STRING); 213} 214 215// if performing AJAX operation, needs to branch before header.php 216if (isset($auth) && (count($user->perm->getAllUserRights($user->getUserId())) > 0 || $user->isSuperAdmin())) { 217 if (isset($action) && isset($ajax)) { 218 if ('ajax' === $action) { 219 switch ($ajax) { 220 // Attachments 221 case 'att': require 'ajax.attachment.php'; break; 222 // Link verification 223 case 'verifyURL': require 'ajax.verifyurl.php'; break; 224 case 'onDemandURL': require 'ajax.ondemandurl.php'; break; 225 // Categories 226 case 'categories': require 'ajax.category.php'; break; 227 // Configuration management 228 case 'config_list': require 'ajax.config_list.php'; break; 229 case 'config': require 'ajax.config.php'; break; 230 case 'elasticsearch': require 'ajax.elasticsearch.php'; break; 231 // Tags management 232 case 'tags': require 'ajax.tags.php'; break; 233 // Comments 234 case 'comment': require 'ajax.comment.php'; break; 235 // Records 236 case 'records': require 'ajax.records.php'; break; 237 case 'recordSave': require 'record.save.php'; break; 238 case 'recordAdd': require 'record.add.php'; break; 239 case 'autosave': require 'ajax.autosave.php'; break; 240 case 'markdown': require 'ajax.markdown.php'; break; 241 // Search 242 case 'search': require 'ajax.search.php'; break; 243 // Users 244 case 'user': require 'ajax.user.php'; break; 245 // Groups 246 case 'group': require 'ajax.group.php'; break; 247 // Sections 248 case 'section': require 'ajax.section.php'; break; 249 // Interface translation 250 case 'trans': require 'ajax.trans.php'; break; 251 // Image upload 252 case 'image': require 'ajax.image.php'; break; 253 } 254 exit(); 255 } 256 } 257} 258 259// are we running a PMF export file request? 260switch ($action) { 261 case 'exportfile': 262 require 'export.file.php'; 263 exit(); 264 break; 265 case 'reportexport': 266 require 'report.export.php'; 267 exit(); 268 break; 269} 270 271// Header of the admin page including the navigation 272require 'header.php'; 273 274$numRights = count($user->perm->getAllUserRights($user->getUserId())); 275 276// User is authenticated 277if (isset($auth) && ($numRights > 0 || $user->isSuperAdmin())) { 278 if (!is_null($action)) { 279 // the various sections of the admin area 280 switch ($action) { 281 // functions for user administration 282 case 'user': require 'user.php'; break; 283 case 'group': require 'group.php'; break; 284 case 'section': require 'section.php'; break; 285 // functions for content administration 286 case 'viewinactive': 287 case 'viewactive': 288 case 'view': require 'record.show.php'; break; 289 case 'searchfaqs': require 'record.search.php'; break; 290 case 'takequestion': 291 case 'editentry': 292 case 'copyentry': 293 case 'editpreview': require 'record.edit.php'; break; 294 case 'insertentry': require 'record.add.php'; break; 295 case 'saveentry': require 'record.save.php'; break; 296 case 'delatt': require 'record.delatt.php'; break; 297 case 'question': require 'record.questions.php'; break; 298 case 'comments': require 'record.comments.php'; break; 299 // functions for tags 300 case 'tags': 301 case 'delete-tag': require 'tags.php'; break; 302 // news administration 303 case 'news': 304 case 'add-news': 305 case 'edit-news': 306 case 'save-news': 307 case 'update-news': 308 case 'delete-news': require 'news.php'; break; 309 // category administration 310 case 'content': 311 case 'category': 312 case 'savecategory': 313 case 'updatecategory': 314 case 'removecategory': 315 case 'changecategory': 316 case 'pastecategory': require 'category.main.php'; break; 317 case 'addcategory': require 'category.add.php'; break; 318 case 'editcategory': require 'category.edit.php'; break; 319 case 'translatecategory': require 'category.translate.php'; break; 320 case 'deletecategory': require 'category.delete.php'; break; 321 case 'cutcategory': require 'category.cut.php'; break; 322 case 'movecategory': require 'category.move.php'; break; 323 case 'showcategory': require 'category.showstructure.php'; break; 324 // glossary 325 case 'glossary': 326 case 'saveglossary': 327 case 'updateglossary': 328 case 'deleteglossary': require 'glossary.main.php'; break; 329 case 'addglossary': require 'glossary.add.php'; break; 330 case 'editglossary': require 'glossary.edit.php'; break; 331 // functions for password administration 332 case 'passwd': require 'pwd.change.php'; break; 333 // functions for session administration 334 case 'adminlog': 335 case 'deleteadminlog': require 'stat.adminlog.php'; break; 336 case 'viewsessions': 337 case 'clear-visits': require 'stat.main.php'; break; 338 case 'sessionbrowse': require 'stat.browser.php'; break; 339 case 'viewsession': require 'stat.show.php'; break; 340 case 'clear-statistics': 341 case 'statistics': require 'stat.ratings.php'; break; 342 case 'truncatesearchterms': 343 case 'searchstats': require 'stat.search.php'; break; 344 // Reports 345 case 'reports': require 'report.main.php'; break; 346 case 'reportview': require 'report.view.php'; break; 347 // Config administration 348 case 'config': require 'configuration.php'; break; 349 case 'system': require 'system.php'; break; 350 case 'updateinstance': 351 case 'instances': require 'instances.php'; break; 352 case 'editinstance': require 'instances.edit.php'; break; 353 case 'stopwordsconfig': require 'stopwords.php'; break; 354 case 'elasticsearch': require 'elasticsearch.php'; break; 355 case 'meta': 356 case 'meta.update'; require 'meta.php'; break; 357 case 'meta.edit': require 'meta.edit.php'; break; 358 // functions for backup administration 359 case 'backup': require 'backup.main.php'; break; 360 case 'restore': require 'backup.import.php'; break; 361 // functions for FAQ export 362 case 'export': require 'export.main.php'; break; 363 // attachment administration 364 case 'attachments': require 'attachments.php'; break; 365 366 default: echo 'Dave, this conversation can serve no purpose anymore. Goodbye.'; break; 367 } 368 } else { 369 require 'dashboard.php'; 370 } 371// User is authenticated, but has no rights 372} elseif (isset($auth) && $numRights === 0) { 373 require 'noperm.php'; 374// User is NOT authenticated 375} else { 376 require 'loginform.php'; 377} 378 379require 'footer.php'; 380 381$faqConfig->getDb()->close(); 382