* @copyright Copyright (c) 2002-2026, Oliver Georgi
* @license http://opensource.org/licenses/GPL-2.0 GNU GPL-2
*
**/
$phpwcms = array('SESSION_START' => true);
$BL = array();
// Check if config is still at the old position
if(!is_file(__DIR__.'/include/config/conf.inc.php') && is_file(__DIR__.'/config/phpwcms/conf.inc.php')):
if(!@rename(__DIR__.'/config/phpwcms', __DIR__.'/include/config')):
?>
phpwcms configuration error
Your configuration is placed at the wrong position.
Beginning with phpwcms v1.7.8 base config files were moved from
directory config/phpwcms to directory include/config. The fallback
to do it automatically has failed. Please do it manually before you continue.
".intval($phpwcms["max_time"]);
_dbQuery($sql, 'UPDATE');
//load default language EN
require_once PHPWCMS_ROOT.'/include/inc_lang/backend/en/lang.inc.php';
// flash notice for successfully executed revision updates
if ($revision_status && !empty($GLOBALS['phpwcms']['revision_success'])) {
$_SESSION['wcs_revision_notice'] = $BL['login_revision_success'] . ': ' . implode(', ', $GLOBALS['phpwcms']['revision_success']) . '.';
}
/**
* Brute-force throttle: count failed login attempts in the session and
* delay each retry with exponential backoff (capped at 8 seconds).
* The counter is reset on every successful authentication.
*/
function register_failed_login($login_name = '') {
$fails = empty($_SESSION['wcs_login_fails']) ? 0 : (int)$_SESSION['wcs_login_fails'];
$fails++;
$_SESSION['wcs_login_fails'] = $fails;
// Send security alert notification after 5 failed attempts
if ($fails === 5 && !empty($login_name)) {
$u_sql = 'SELECT usr_id, usr_login, usr_email, usr_name, usr_lang FROM ' . DB_PREPEND . 'user WHERE usr_login = ' . _dbEscape($login_name) . ' AND usr_aktiv = 1 LIMIT 1';
$u_res = _dbQuery($u_sql);
if (!empty($u_res[0]['usr_email']) && is_valid_email($u_res[0]['usr_email'])) {
$u_row = $u_res[0];
$u_lang = !empty($u_row['usr_lang']) ? $u_row['usr_lang'] : ($_SESSION['wcs_user_lang'] ?? 'en');
$rendered_alert = render_system_email('account_locked', [
'{NAME}' => empty($u_row['usr_name']) ? $u_row['usr_login'] : $u_row['usr_name'],
'{LOGIN}' => $u_row['usr_login'],
'{IP}' => PHPWCMS_GDPR_MODE ? getAnonymizedIp() : getRemoteIP(),
'{DATE}' => date('Y-m-d H:i:s'),
'{SITE}' => PHPWCMS_HOST,
'{SITE_URL}' => PHPWCMS_URL,
'{LOGIN_PAGE}' => PHPWCMS_URL . get_login_file(),
'{RESET_LINK}' => PHPWCMS_URL . get_login_file() . '?reset=1',
'{ADMIN_EMAIL}'=> $GLOBALS['phpwcms']['admin_email'] ?? $GLOBALS['phpwcms']['SMTP_FROM_EMAIL'] ?? ''
], $u_lang);
sendEmail([
'recipient' => $u_row['usr_email'],
'toName' => $u_row['usr_name'],
'subject' => $rendered_alert['subject'],
'isHTML' => true,
'html' => $rendered_alert['html'],
'text' => $rendered_alert['text'],
'from' => $GLOBALS['phpwcms']['admin_email'] ?? $GLOBALS['phpwcms']['SMTP_FROM_EMAIL'] ?? '',
'fromName' => get_brand_name()
]);
}
}
usleep(min(100000 * (2 ** min($fails, 6)), 8000000));
}
function reset_failed_login_count() {
unset($_SESSION['wcs_login_fails']);
}
$lang_aliases = ['cz' => 'cs', 'se' => 'sv', 'vn' => 'vi', 'el' => 'gr', 'uk' => 'ua', 'zh' => 'zh-cn', 'in' => 'id', 'my' => 'ms'];
//define language and check if language file is available
if(isset($_COOKIE['phpwcmsBELang'])) {
$temp_lang = strtolower(trim($_COOKIE['phpwcmsBELang']));
if (isset($lang_aliases[$temp_lang])) {
$temp_lang = $lang_aliases[$temp_lang];
}
if (preg_match('/^[a-z]{2}(?:-[a-z]{2})?$/', $temp_lang) && is_file(PHPWCMS_ROOT.'/include/inc_lang/backend/'.$temp_lang.'/lang.inc.php')) {
$_SESSION["wcs_user_lang"] = $temp_lang;
} else {
setcookie('phpwcmsBELang', '', time() - 3600, '/', getCookieDomain(), PHPWCMS_SSL, true);
}
}
if(isset($_POST['form_lang'])) {
$temp_lang = strtolower(trim(clean_slweg($_POST['form_lang'])));
if (isset($lang_aliases[$temp_lang])) {
$temp_lang = $lang_aliases[$temp_lang];
}
if (preg_match('/^[a-z]{2}(?:-[a-z]{2})?$/', $temp_lang) && is_file(PHPWCMS_ROOT.'/include/inc_lang/backend/'.$temp_lang.'/lang.inc.php')) {
$_SESSION["wcs_user_lang"] = $temp_lang;
set_language_cookie($temp_lang);
}
}
if(empty($_SESSION["wcs_user_lang"])) {
$detected_lang = '';
if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$accepted = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach ($accepted as $al) {
$al_parts = explode(';', trim($al));
$al_code = strtolower(trim($al_parts[0]));
if ($al_code === '') {
continue;
}
if (isset($lang_aliases[$al_code])) {
$al_code = $lang_aliases[$al_code];
}
if (is_file(PHPWCMS_ROOT.'/include/inc_lang/backend/'.$al_code.'/lang.inc.php')) {
$detected_lang = $al_code;
break;
}
$base_code = substr($al_code, 0, 2);
if (isset($lang_aliases[$base_code])) {
$base_code = $lang_aliases[$base_code];
}
if (is_file(PHPWCMS_ROOT.'/include/inc_lang/backend/'.$base_code.'/lang.inc.php')) {
$detected_lang = $base_code;
break;
}
}
}
if ($detected_lang === '') {
$default_lang = strtolower($phpwcms['default_lang'] ?? 'en');
if (isset($lang_aliases[$default_lang])) {
$default_lang = $lang_aliases[$default_lang];
}
if (is_file(PHPWCMS_ROOT.'/include/inc_lang/backend/'.$default_lang.'/lang.inc.php')) {
$detected_lang = $default_lang;
} else {
$detected_lang = 'en';
}
}
$_SESSION["wcs_user_lang"] = $detected_lang;
}
if(is_file(PHPWCMS_ROOT.'/include/inc_lang/backend/'.$_SESSION["wcs_user_lang"].'/lang.inc.php')) {
$_SESSION["wcs_user_lang_custom"] = 1;
} else {
$_SESSION["wcs_user_lang"] = 'en';
$_SESSION["wcs_user_lang_custom"] = 0;
}
if(!empty($_SESSION["wcs_user_lang_custom"])) {
//use custom lang if available -> was set in login.php
$BL['merge_lang_array'][0] = $BL['be_admin_optgroup_label'];
$BL['merge_lang_array'][1] = $BL['be_cnt_field'];
include_once PHPWCMS_ROOT.'/include/inc_lang/backend/'.$_SESSION["wcs_user_lang"].'/lang.inc.php';
$BL['be_admin_optgroup_label'] = array_merge($BL['merge_lang_array'][0], $BL['be_admin_optgroup_label']);
$BL['be_cnt_field'] = array_merge($BL['merge_lang_array'][1], $BL['be_cnt_field']);
}
$BL = apply_brand_replacements($BL);
//WYSIWYG EDITOR:
//0 = no wysiwyg editor (default)
//1 = CKEditor
//2 = TinyMCE
/** @phpstan-ignore-next-line */
$phpwcms["wysiwyg_editor"] = empty($phpwcms["wysiwyg_editor"]) ? 0 : intval($phpwcms["wysiwyg_editor"]);
$_SESSION["WYSIWYG_EDITOR"] = $phpwcms["wysiwyg_editor"];
destroyBackendSessionData();
$json_check = isset($_POST['json']) ? intval($_POST['json']) : 0;
$step_2fa = false;
$backup_code_used = false;
// Handle Step 2: 2FA Verification
if (isset($_POST['form_aktion']) && $_POST['form_aktion'] === 'verify_2fa' && !empty($_SESSION['wcs_2fa_pending_uid'])) {
$pending_uid = (int)$_SESSION['wcs_2fa_pending_uid'];
$submitted_2fa_code = slweg($_POST['form_2fa_code'] ?? '');
if (!$csrf_error && $revision_status && $submitted_2fa_code !== '') {
$sql_query = 'SELECT * FROM ' . DB_PREPEND . 'user WHERE usr_id=' . $pending_uid . ' AND usr_aktiv=1 AND (usr_fe=1 OR usr_fe=2) LIMIT 1';
$result = _dbQuery($sql_query);
if (isset($result[0]['usr_id'])) {
$user_vars = @unserialize($result[0]['usr_vars'], ['allowed_classes' => false]);
if (!is_array($user_vars)) {
$user_vars = [];
}
$tfa_valid = false;
// 1. Check standard 6-digit TOTP
if (!empty($result[0]['usr_2fa_secret']) && strlen($submitted_2fa_code) === 6 && ctype_digit($submitted_2fa_code)) {
$tfa_valid = PhpwcmsTwoFactor::verifyCode($result[0]['usr_2fa_secret'], $submitted_2fa_code);
}
// 2. Check backup recovery codes
if (!$tfa_valid && !empty($user_vars['2fa_backup_codes']) && is_array($user_vars['2fa_backup_codes'])) {
if (PhpwcmsTwoFactor::verifyAndConsumeBackupCode($user_vars['2fa_backup_codes'], $submitted_2fa_code)) {
$tfa_valid = true;
$backup_code_used = true;
_dbUpdate('user', ['usr_vars' => serialize($user_vars)], 'WHERE usr_id=' . $pending_uid);
}
}
if ($tfa_valid) {
$wcs_user = $result[0]['usr_login'];
unset($_SESSION['wcs_2fa_pending_uid'], $_SESSION['wcs_2fa_user_row'], $_SESSION['wcs_2fa_ref_url'], $_SESSION['wcs_2fa_customlang']);
$_SESSION['wcs_user'] = $wcs_user;
$_SESSION['wcs_user_name'] = empty($result[0]['usr_name']) ? $wcs_user : $result[0]['usr_name'];
$_SESSION['wcs_user_id'] = $result[0]['usr_id'];
$_SESSION['wcs_user_aktiv'] = $result[0]['usr_aktiv'];
$_SESSION['wcs_user_rechte'] = $result[0]['usr_rechte'];
$_SESSION['wcs_user_email'] = $result[0]['usr_email'];
$_SESSION['wcs_user_avatar'] = $result[0]['usr_avatar'];
$_SESSION['wcs_user_logtime'] = time();
$_SESSION['wcs_user_admin'] = intval($result[0]['usr_admin']);
$_SESSION['wcs_user_thumb'] = 1;
if (empty($_POST['customlang']) && !empty($result[0]['usr_lang'])) {
$usr_lang = strtolower($result[0]['usr_lang']);
if (isset($lang_aliases[$usr_lang])) {
$usr_lang = $lang_aliases[$usr_lang];
}
$_SESSION['wcs_user_lang'] = $usr_lang;
set_language_cookie($usr_lang);
} elseif (!empty($_SESSION['wcs_user_lang'])) {
set_language_cookie($_SESSION['wcs_user_lang']);
} else {
set_language_cookie();
}
$_SESSION['structure'] = @unserialize($result[0]['usr_var_structure'], ['allowed_classes' => false]);
$_SESSION['klapp'] = @unserialize($result[0]['usr_var_privatefile'], ['allowed_classes' => false]);
$_SESSION['pklapp'] = @unserialize($result[0]['usr_var_publicfile'], ['allowed_classes' => false]);
if (!is_array($_SESSION['structure'])) {
$_SESSION['structure'] = [];
}
if (!is_array($_SESSION['klapp'])) {
$_SESSION['klapp'] = [];
}
if (!is_array($_SESSION['pklapp'])) {
$_SESSION['pklapp'] = [];
}
$_SESSION['WYSIWYG_EDITOR'] = empty($result[0]['usr_wysiwyg']) ? $phpwcms['wysiwyg_editor'] : intval($result[0]['usr_wysiwyg']);
$_SESSION['wcs_user_theme'] = isset($user_vars['theme']) && in_array($user_vars['theme'], ['auto', 'light', 'dark'], true) ? $user_vars['theme'] : (!empty($_COOKIE['phpwcmsBETheme']) && in_array($_COOKIE['phpwcmsBETheme'], ['auto', 'light', 'dark'], true) ? $_COOKIE['phpwcmsBETheme'] : 'auto');
set_theme_cookie($_SESSION['wcs_user_theme']);
$_SESSION['wcs_user_cp'] = isset($user_vars['selected_cp']) && is_array($user_vars['selected_cp']) ? $user_vars['selected_cp'] : [];
$_SESSION['wcs_allowed_cp'] = isset($user_vars['allowed_cp']) && is_array($user_vars['allowed_cp']) ? $user_vars['allowed_cp'] : [];
if (count($_SESSION['wcs_allowed_cp'])) {
if (count($_SESSION['wcs_user_cp'])) {
foreach ($_SESSION['wcs_user_cp'] as $key => $value) {
if (!isset($_SESSION['wcs_allowed_cp'][$key])) {
unset($_SESSION['wcs_user_cp'][$key]);
}
}
} else {
$_SESSION['wcs_user_cp'] = $_SESSION['wcs_allowed_cp'];
}
}
// Store login information in DB
if (!($check = _dbQuery('SELECT COUNT(*) FROM ' . DB_PREPEND . 'userlog WHERE logged_user=' . _dbEscape($wcs_user) . ' AND logged_in=1', 'COUNT'))) {
$sql = 'INSERT INTO ' . DB_PREPEND . 'userlog (logged_user, logged_username, logged_start, logged_change, logged_in, logged_ip) VALUES (';
$sql .= _dbEscape($wcs_user) . ', ' . _dbEscape($_SESSION['wcs_user_name']) . ', ' . time() . ', ' . time() . ', 1, ' . _dbEscape(PHPWCMS_GDPR_MODE ? getAnonymizedIp() : getRemoteIP()) . ')';
_dbQuery($sql, 'INSERT');
}
$_SESSION['PHPWCMS_ROOT'] = PHPWCMS_ROOT;
$welcome_msg = $BL['login_welcome'] . ', ' . $wcs_user . '!' . ($backup_code_used ? ' (' . ($BL['login_2fa_backup_used'] ?? 'Backup code used') . ')' : '');
if (!empty($_SESSION['wcs_revision_notice'])) {
$welcome_msg .= "\n" . $_SESSION['wcs_revision_notice'];
unset($_SESSION['wcs_revision_notice']);
}
set_status_message($welcome_msg);
if ($ref_url) {
if (($token_position = strpos($ref_url, 'csrftoken')) !== false) {
$ref_url = substr_replace($ref_url, '', $token_position, 42);
$ref_url = str_replace('?&', '?', $ref_url);
$ref_url = str_replace('&&', '&', $ref_url);
}
$backend_redirect = $ref_url . '&';
} else {
$backend_redirect = PHPWCMS_URL . 'phpwcms.php?';
}
$_SESSION['PHPWCMS_BROWSER_HASH'] = $phpwcms['USER_AGENT']['hash'];
// new session id after successful auth (prevent session fixation)
session_regenerate_id(true);
reset_failed_login_count();
headerRedirect($backend_redirect . get_token_get_string());
}
}
}
register_failed_login();
$err = 1;
$step_2fa = true;
} elseif (isset($_POST['form_aktion']) && $_POST['form_aktion'] == 'login' && $json_check === 1) {
$login_passed = 0;
$wysiwyg_template = '';
$wcs_user = slweg($_POST['form_loginname']);
$wcs_pass = slweg($_POST['md5pass']);
$plain_pass = isset($_POST['form_password']) ? slweg($_POST['form_password']) : '';
$sql_query = "SELECT * FROM " . DB_PREPEND . "user WHERE usr_login=" . _dbEscape($wcs_user) . " AND usr_aktiv=1 AND (usr_fe=1 OR usr_fe=2)";
if(!$csrf_error && $revision_status) {
$result = _dbQuery($sql_query);
if(isset($result[0]['usr_id'])) {
$db_pass = $result[0]['usr_pass'];
if ($plain_pass !== '') {
if (str_starts_with($db_pass, '$')) {
if (password_verify($plain_pass, $db_pass)) {
$login_passed = 1;
} else {
$md5_pass = md5(makeCharsetConversion($plain_pass, PHPWCMS_CHARSET, 'utf-8'));
if (password_verify($md5_pass, $db_pass)) {
$login_passed = 1;
$new_hash = password_hash($plain_pass, PASSWORD_DEFAULT);
_dbQuery('UPDATE ' . DB_PREPEND . 'user SET usr_pass=' . _dbEscape($new_hash) . ' WHERE usr_id=' . (int)$result[0]['usr_id'], 'UPDATE');
}
}
} else {
$md5_pass = md5(makeCharsetConversion($plain_pass, PHPWCMS_CHARSET, 'utf-8'));
if ($md5_pass === $db_pass) {
$login_passed = 1;
$new_hash = password_hash($plain_pass, PASSWORD_DEFAULT);
_dbQuery('UPDATE ' . DB_PREPEND . 'user SET usr_pass=' . _dbEscape($new_hash) . ' WHERE usr_id=' . (int)$result[0]['usr_id'], 'UPDATE');
}
}
} else {
if (str_starts_with($db_pass, '$')) {
if (password_verify($wcs_pass, $db_pass)) {
$login_passed = 1;
}
} else {
if ($wcs_pass === $db_pass) {
$login_passed = 1;
$new_hash = password_hash($wcs_pass, PASSWORD_DEFAULT);
_dbQuery('UPDATE ' . DB_PREPEND . 'user SET usr_pass=' . _dbEscape($new_hash) . ' WHERE usr_id=' . (int)$result[0]['usr_id'], 'UPDATE');
}
}
}
if ($login_passed) {
// Check if Two-Factor Authentication is enabled for this account
if (!empty($result[0]['usr_2fa_enabled']) && !empty($result[0]['usr_2fa_secret'])) {
$_SESSION['wcs_2fa_pending_uid'] = (int)$result[0]['usr_id'];
$_SESSION['wcs_2fa_user_row'] = $result[0];
$_SESSION['wcs_2fa_ref_url'] = $ref_url;
$_SESSION['wcs_2fa_customlang'] = !empty($_POST['customlang']) ? 1 : 0;
$step_2fa = true;
} else {
$_SESSION["wcs_user"] = $wcs_user;
$_SESSION["wcs_user_name"] = empty($result[0]["usr_name"]) ? $wcs_user : $result[0]["usr_name"];
$_SESSION["wcs_user_id"] = $result[0]["usr_id"];
$_SESSION["wcs_user_aktiv"] = $result[0]["usr_aktiv"];
$_SESSION["wcs_user_rechte"] = $result[0]["usr_rechte"];
$_SESSION["wcs_user_email"] = $result[0]["usr_email"];
$_SESSION["wcs_user_avatar"] = $result[0]["usr_avatar"];
$_SESSION["wcs_user_logtime"] = time();
$_SESSION["wcs_user_admin"] = intval($result[0]["usr_admin"]);
$_SESSION["wcs_user_thumb"] = 1;
if(empty($_POST['customlang']) && !empty($result[0]["usr_lang"])) {
$usr_lang = strtolower($result[0]["usr_lang"]);
if (isset($lang_aliases[$usr_lang])) {
$usr_lang = $lang_aliases[$usr_lang];
}
$_SESSION["wcs_user_lang"] = $usr_lang;
set_language_cookie($usr_lang);
} elseif (!empty($_SESSION["wcs_user_lang"])) {
set_language_cookie($_SESSION["wcs_user_lang"]);
} else {
set_language_cookie();
}
$_SESSION["structure"] = @unserialize($result[0]["usr_var_structure"], ['allowed_classes' => false]);
$_SESSION["klapp"] = @unserialize($result[0]["usr_var_privatefile"], ['allowed_classes' => false]);
$_SESSION["pklapp"] = @unserialize($result[0]["usr_var_publicfile"], ['allowed_classes' => false]);
$result[0]["usr_vars"] = @unserialize($result[0]["usr_vars"], ['allowed_classes' => false]);
if(!is_array($_SESSION["structure"])) {
$_SESSION["structure"] = array();
}
if(!is_array($_SESSION["klapp"])) {
$_SESSION["klapp"] = array();
}
if(!is_array($_SESSION["pklapp"])) {
$_SESSION["pklapp"] = array();
}
if(!is_array($result[0]["usr_vars"])) {
$result[0]["usr_vars"] = array();
}
// Fallback to configured global editor
$_SESSION['WYSIWYG_EDITOR'] = empty($result[0]['usr_wysiwyg']) ? $phpwcms['wysiwyg_editor'] : intval($result[0]['usr_wysiwyg']);
if (isset($_POST['form_theme']) && in_array($_POST['form_theme'], array('auto', 'light', 'dark'), true)) {
$_SESSION['wcs_user_theme'] = $_POST['form_theme'];
if (!isset($result[0]['usr_vars']['theme']) || $result[0]['usr_vars']['theme'] !== $_POST['form_theme']) {
$result[0]['usr_vars']['theme'] = $_POST['form_theme'];
_dbUpdate('user', array('usr_vars' => serialize($result[0]['usr_vars'])), 'WHERE usr_id=' . intval($result[0]['usr_id']));
}
} else {
$_SESSION['wcs_user_theme'] = isset($result[0]['usr_vars']['theme']) && in_array($result[0]['usr_vars']['theme'], array('auto', 'light', 'dark'), true) ? $result[0]['usr_vars']['theme'] : (!empty($_COOKIE['phpwcmsBETheme']) && in_array($_COOKIE['phpwcmsBETheme'], array('auto', 'light', 'dark'), true) ? $_COOKIE['phpwcmsBETheme'] : 'auto');
}
set_theme_cookie($_SESSION['wcs_user_theme']);
$_SESSION['wcs_user_cp'] = isset($result[0]['usr_vars']['selected_cp']) && is_array($result[0]['usr_vars']['selected_cp']) ? $result[0]['usr_vars']['selected_cp'] : array();
$_SESSION['wcs_allowed_cp'] = isset($result[0]['usr_vars']['allowed_cp']) && is_array($result[0]['usr_vars']['allowed_cp']) ? $result[0]['usr_vars']['allowed_cp'] : array();
// Test if there are CPs that use had choosen but no longer available for
if(count($_SESSION["wcs_allowed_cp"])) {
if(count($_SESSION["wcs_user_cp"])) {
// Remove selected CP if not allowed CP
foreach($_SESSION["wcs_user_cp"] as $key => $value) {
if(!isset($_SESSION["wcs_allowed_cp"][$key])) {
unset($_SESSION["wcs_user_cp"][$key]);
}
}
} else {
$_SESSION["wcs_user_cp"] = $_SESSION["wcs_allowed_cp"];
}
}
}
}
}
}
if($login_passed && !$step_2fa) {
// Store login information in DB
if(!($check = _dbQuery("SELECT COUNT(*) FROM ".DB_PREPEND."userlog WHERE logged_user="._dbEscape($wcs_user)." AND logged_in=1", 'COUNT'))) {
// User not yet logged in, create new
$sql = "INSERT INTO ".DB_PREPEND."userlog (logged_user, logged_username, logged_start, logged_change, logged_in, logged_ip) VALUES (";
$sql .= _dbEscape($wcs_user).", "._dbEscape($_SESSION["wcs_user_name"]).", ".time().", ".time().", 1, "._dbEscape(PHPWCMS_GDPR_MODE ? getAnonymizedIp() : getRemoteIP()).")";
_dbQuery($sql, 'INSERT');
}
$_SESSION['PHPWCMS_ROOT'] = PHPWCMS_ROOT;
$welcome_msg = $BL["login_welcome"].', '.$wcs_user.'!';
if (!empty($_SESSION['wcs_revision_notice'])) {
$welcome_msg .= "\n" . $_SESSION['wcs_revision_notice'];
unset($_SESSION['wcs_revision_notice']);
}
set_status_message($welcome_msg);
if($ref_url) {
if(($token_position = strpos($ref_url, 'csrftoken')) !== false) {
$ref_url = substr_replace($ref_url, '', $token_position, 42);
$ref_url = str_replace('?&', '?', $ref_url);
$ref_url = str_replace('&&', '&', $ref_url);
}
$backend_redirect = $ref_url . '&';
} else {
$backend_redirect = PHPWCMS_URL.'phpwcms.php?';
}
$_SESSION['PHPWCMS_BROWSER_HASH'] = $phpwcms['USER_AGENT']['hash'];
// new session id after successful auth (prevent session fixation)
session_regenerate_id(true);
reset_failed_login_count();
headerRedirect($backend_redirect . get_token_get_string());
} elseif (!$step_2fa) {
register_failed_login($wcs_user);
$err = 1;
}
} elseif(isset($_POST['form_loginname']) && $json_check !== 2) {
register_failed_login(slweg($_POST['form_loginname']));
$err = 1;
}
$step_reset_request = false;
$step_reset_set = false;
$reset_sent_success = false;
$reset_done_success = false;
$reset_error_msg = '';
$reset_token_valid = false;
$reset_user_row = null;
// Handle Password Reset Request
if (isset($_GET['reset']) && $_GET['reset'] === '1' && empty($_POST['form_aktion'])) {
$step_reset_request = true;
}
// Process Password Reset Request (send email with reset token)
if (isset($_POST['form_aktion']) && $_POST['form_aktion'] === 'send_reset_link') {
$step_reset_request = true;
$reset_account = slweg($_POST['form_reset_account'] ?? '');
if (!$csrf_error && $reset_account !== '') {
$sql = 'SELECT usr_id, usr_login, usr_email, usr_name, usr_vars FROM ' . DB_PREPEND . 'user WHERE (usr_login = ' . _dbEscape($reset_account) . ' OR LOWER(usr_email) = ' . _dbEscape(strtolower($reset_account)) . ') AND usr_aktiv = 1 AND (usr_fe = 1 OR usr_fe = 2) LIMIT 1';
$user_res = _dbQuery($sql);
if (!empty($user_res[0]['usr_id']) && !empty($user_res[0]['usr_email']) && is_valid_email($user_res[0]['usr_email'])) {
$user = $user_res[0];
$u_vars = @unserialize($user['usr_vars'], ['allowed_classes' => false]);
if (!is_array($u_vars)) {
$u_vars = [];
}
$raw_token = bin2hex(random_bytes(32));
$token_hash = hash('sha256', $raw_token);
$token_expires = time() + 3600; // 1 hour validity
$u_vars['password_reset'] = [
'token_hash' => $token_hash,
'expires' => $token_expires,
'ip' => PHPWCMS_GDPR_MODE ? getAnonymizedIp() : getRemoteIP()
];
_dbUpdate('user', ['usr_vars' => serialize($u_vars)], 'WHERE usr_id = ' . (int)$user['usr_id']);
$reset_link = PHPWCMS_URL . get_login_file() . '?reset_token=' . rawurlencode($raw_token) . '&u=' . (int)$user['usr_id'];
$rendered_mail = render_system_email('password_reset', [
'{NAME}' => empty($user['usr_name']) ? $user['usr_login'] : $user['usr_name'],
'{LOGIN}' => $user['usr_login'],
'{SITE}' => PHPWCMS_HOST,
'{SITE_URL}' => PHPWCMS_URL,
'{RESET_LINK}' => $reset_link,
'{EXPIRES}' => '1 hour'
]);
sendEmail([
'recipient' => $user['usr_email'],
'toName' => $user['usr_name'],
'subject' => $rendered_mail['subject'],
'isHTML' => true,
'html' => $rendered_mail['html'],
'text' => $rendered_mail['text'],
'from' => $phpwcms['admin_email'] ?? $phpwcms['SMTP_FROM_EMAIL'] ?? '',
'fromName' => get_brand_name()
]);
}
// Always show the same neutral success message to prevent user enumeration
$reset_sent_success = true;
} else {
$err = 1;
}
}
// Verify Reset Token and Load Reset Password View
if (!empty($_GET['reset_token']) && !empty($_GET['u'])) {
$token_param = slweg($_GET['reset_token']);
$user_id_param = (int)$_GET['u'];
$sql = 'SELECT usr_id, usr_login, usr_name, usr_vars FROM ' . DB_PREPEND . 'user WHERE usr_id = ' . $user_id_param . ' AND usr_aktiv = 1 AND (usr_fe = 1 OR usr_fe = 2) LIMIT 1';
$user_res = _dbQuery($sql);
if (!empty($user_res[0]['usr_id'])) {
$u_vars = @unserialize($user_res[0]['usr_vars'], ['allowed_classes' => false]);
if (is_array($u_vars) && !empty($u_vars['password_reset'])) {
$reset_info = $u_vars['password_reset'];
if (!empty($reset_info['expires']) && $reset_info['expires'] >= time()) {
if (hash_equals($reset_info['token_hash'], hash('sha256', $token_param))) {
$reset_token_valid = true;
$step_reset_set = true;
$reset_user_row = $user_res[0];
}
}
}
}
if (!$reset_token_valid) {
$step_reset_set = true;
$reset_error_msg = $BL['login_reset_invalid_token'] ?? 'This password reset link is invalid or has expired. Please request a new one.';
}
}
// Process Set New Password
if (isset($_POST['form_aktion']) && $_POST['form_aktion'] === 'set_new_password') {
$token_param = slweg($_POST['form_reset_token'] ?? '');
$user_id_param = (int)($_POST['form_reset_uid'] ?? 0);
$new_pw = slweg($_POST['form_new_password'] ?? '');
$repeat_pw = slweg($_POST['form_repeat_password'] ?? '');
$step_reset_set = true;
if ($csrf_error) {
$reset_error_msg = $BL['CSRF_POST_INVALID'] ?? 'Security token mismatch. Please try again.';
} elseif ($new_pw === '') {
$reset_error_msg = $BL['login_reset_password_empty'] ?? 'Password cannot be empty!';
} elseif ($new_pw !== $repeat_pw) {
$reset_error_msg = $BL['login_reset_password_mismatch'] ?? 'Passwords do not match!';
} else {
$sql = 'SELECT usr_id, usr_login, usr_email, usr_name, usr_vars FROM ' . DB_PREPEND . 'user WHERE usr_id = ' . $user_id_param . ' AND usr_aktiv = 1 AND (usr_fe = 1 OR usr_fe = 2) LIMIT 1';
$user_res = _dbQuery($sql);
if (!empty($user_res[0]['usr_id'])) {
$u_vars = @unserialize($user_res[0]['usr_vars'], ['allowed_classes' => false]);
if (is_array($u_vars) && !empty($u_vars['password_reset'])) {
$reset_info = $u_vars['password_reset'];
if (!empty($reset_info['expires']) && $reset_info['expires'] >= time()) {
if (hash_equals($reset_info['token_hash'], hash('sha256', $token_param))) {
// Reset valid -> update password
unset($u_vars['password_reset']);
$hashed_password = password_hash($new_pw, PASSWORD_DEFAULT);
_dbUpdate('user', [
'usr_pass' => $hashed_password,
'usr_vars' => serialize($u_vars)
], 'WHERE usr_id = ' . (int)$user_res[0]['usr_id']);
$reset_done_success = true;
$step_reset_set = false;
// Send confirmation email
if (!empty($user_res[0]['usr_email']) && is_valid_email($user_res[0]['usr_email'])) {
$rendered_mail = render_system_email('password_changed', [
'{NAME}' => empty($user_res[0]['usr_name']) ? $user_res[0]['usr_login'] : $user_res[0]['usr_name'],
'{LOGIN}' => $user_res[0]['usr_login'],
'{SITE}' => PHPWCMS_HOST,
'{SITE_URL}' => PHPWCMS_URL,
'{LOGIN_PAGE}' => PHPWCMS_URL . get_login_file(),
'{ADMIN_EMAIL}'=> $phpwcms['admin_email'] ?? $phpwcms['SMTP_FROM_EMAIL'] ?? ''
]);
sendEmail([
'recipient' => $user_res[0]['usr_email'],
'toName' => $user_res[0]['usr_name'],
'subject' => $rendered_mail['subject'],
'isHTML' => true,
'html' => $rendered_mail['html'],
'text' => $rendered_mail['text'],
'from' => $phpwcms['admin_email'] ?? $phpwcms['SMTP_FROM_EMAIL'] ?? '',
'fromName' => get_brand_name()
]);
}
}
}
}
}
if (!$reset_done_success) {
$reset_error_msg = $BL['login_reset_invalid_token'] ?? 'This password reset link is invalid or has expired. Please request a new one.';
}
}
}
$reason_types = array(
'default' => 'alert-default',
'info' => 'alert-info',
'error' => 'alert-error',
'warning' => 'alert-warning',
'success' => 'alert-success',
'danger' => 'alert-danger'
);
?>
>
isset($phpwcms['browser_check']['insecure']) ? boolval($phpwcms['browser_check']['insecure']) : true);
if(!empty($phpwcms['browser_check']['vs'])) {
$buoop['vs'] = $phpwcms['browser_check']['vs'];
}
if(!empty($phpwcms['browser_check']['required'])) {
$buoop['required'] = '{' . trim($phpwcms['browser_check']['required'], '{}') . '}';
}
?>
var $buoop = ;