Skip to content

Commit

Permalink
Standardize user.php functions
Browse files Browse the repository at this point in the history
The file htdocs/user.php is the gateway to user functions
such as login, forgot password. If the profile module is
installed, then htdocs/modules/profile/user.php takes over.
In certain circumstances htdocs/modules/profile/index.php
is called upon with the expectation it will mimic user.php.

These three programs have nearly identical definitions, and
yet have diverged, the most significant concern is with
handing of security considerations.

This commit standardizes the approach to input validation
across all the variants, and eliminates the code separation
within the profile module user.php and index.php scripts.
  • Loading branch information
geekwright committed Feb 20, 2021
1 parent 3f8cafe commit e07319d
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 235 deletions.
131 changes: 6 additions & 125 deletions htdocs/modules/profile/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,134 +9,15 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
* @license GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
* @copyright (c) 2000-2021 XOOPS Project (https://xoops.org)
* @license GNU GPL 2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
* @package profile
* @since 2.3.0
* @author Jan Pedersen
* @author Taiwen Jiang <phppp@users.sourceforge.net>
*/

$xoopsOption['pagetype'] = 'user';
include __DIR__ . '/header.php';

$op = 'main';

if (isset($_POST['op'])) {
$op = trim($_POST['op']);
} elseif (isset($_GET['op'])) {
$op = trim($_GET['op']);
}

if ($op === 'main') {
if (!is_object($GLOBALS['xoopsUser'])) {
$GLOBALS['xoopsOption']['template_main'] = 'profile_userform.tpl';
include $GLOBALS['xoops']->path('header.php');
$GLOBALS['xoopsTpl']->assign('lang_login', _LOGIN);
$GLOBALS['xoopsTpl']->assign('lang_username', _USERNAME);
if (isset($_GET['xoops_redirect'])) {
$GLOBALS['xoopsTpl']->assign('redirect_page', htmlspecialchars(trim($_GET['xoops_redirect']), ENT_QUOTES));
}
xoops_loadLanguage('user');
if ($GLOBALS['xoopsConfig']['usercookie']) {
$GLOBALS['xoopsTpl']->assign('lang_rememberme', _US_REMEMBERME);
}
$GLOBALS['xoopsTpl']->assign('lang_password', _PASSWORD);
$GLOBALS['xoopsTpl']->assign('lang_notregister', _US_NOTREGISTERED);
$GLOBALS['xoopsTpl']->assign('lang_lostpassword', _US_LOSTPASSWORD);
$GLOBALS['xoopsTpl']->assign('lang_noproblem', _US_NOPROBLEM);
$GLOBALS['xoopsTpl']->assign('lang_youremail', _US_YOUREMAIL);
$GLOBALS['xoopsTpl']->assign('lang_sendpassword', _US_SENDPASSWORD);
$GLOBALS['xoopsTpl']->assign('mailpasswd_token', $GLOBALS['xoopsSecurity']->createToken());
include __DIR__ . '/footer.php';
exit();
}

$redirect = \Xmf\Request::getUrl('xoops_redirect', '', 'get');
if (!empty($redirect)) {
$urlParts = parse_url($redirect);
$xoopsUrlParts = parse_url(XOOPS_URL);
if (false !== $urlParts) {
if (false !== $urlParts) {
// make sure $redirect is somewhere inside XOOPS_URL
// catch https:example.com (no //)
$badScheme = (isset($urlParts['path']) && !isset($urlParts['host']) && isset($urlParts['scheme']));
// no host or matching host
$hostMatch = (!isset($urlParts['host'])) || (0 === strcasecmp($urlParts['host'], $xoopsUrlParts['host']));
// path only, or path matches
$pathMatch = (isset($urlParts['path']) && !isset($urlParts['host']) && !isset($urlParts['scheme']))
|| ($hostMatch && isset($urlParts['path']) && isset($xoopsUrlParts['path'])
&& 0 === strncmp($urlParts['path'], $xoopsUrlParts['path'], strlen($xoopsUrlParts['path'])));
if ($badScheme || !($hostMatch && $pathMatch)) {
$redirect = XOOPS_URL;
}
}
header('Location: ' . $redirect);
exit();
}
}

header('Location: ./userinfo.php?uid=' . $GLOBALS['xoopsUser']->getVar('uid'));
exit();
}

if ($op === 'login') {
include_once $GLOBALS['xoops']->path('include/checklogin.php');
exit();
}

if ($op === 'logout') {
$message = '';
$_SESSION = array();
session_destroy();
setcookie($GLOBALS['xoopsConfig']['usercookie'], null, time() - 3600, '/', XOOPS_COOKIE_DOMAIN, 0);
setcookie($GLOBALS['xoopsConfig']['usercookie'], null, time() - 3600, '/');
// clear entry from online users table
if (is_object($GLOBALS['xoopsUser'])) {
/* @var XoopsOnlineHandler $online_handler */
$online_handler = xoops_getHandler('online');
$online_handler->destroy($GLOBALS['xoopsUser']->getVar('uid'));
}
$message = _US_LOGGEDOUT . '<br>' . _US_THANKYOUFORVISIT;
redirect_header(XOOPS_URL . '/', 1, $message);
}

if ($op === 'actv') {
$id = (int)$_GET['id'];
$actkey = trim($_GET['actkey']);
redirect_header("activate.php?op=actv&amp;id={$id}&amp;actkey={$actkey}", 1, '');
}

if ($op === 'delete') {
/* @var XoopsConfigHandler $config_handler */
$config_handler = xoops_getHandler('config');
$GLOBALS['xoopsConfigUser'] = $config_handler->getConfigsByCat(XOOPS_CONF_USER);
if (!$GLOBALS['xoopsUser'] || $GLOBALS['xoopsConfigUser']['self_delete'] != 1) {
redirect_header(XOOPS_URL . '/', 5, _US_NOPERMISS);
} else {
$groups = $GLOBALS['xoopsUser']->getGroups();
if (in_array(XOOPS_GROUP_ADMIN, $groups)) {
// users in the webmasters group may not be deleted
redirect_header(XOOPS_URL . '/', 5, _US_ADMINNO);
}
$ok = !isset($_POST['ok']) ? 0 : (int)$_POST['ok'];
if ($ok != 1) {
include $GLOBALS['xoops']->path('header.php');
xoops_confirm(array('op' => 'delete', 'ok' => 1), 'user.php', _US_SURETODEL . '<br>' . _US_REMOVEINFO);
include __DIR__ . '/footer.php';
} else {
$del_uid = $GLOBALS['xoopsUser']->getVar('uid');
/* @var XoopsMemberHandler $member_handler */
$member_handler = xoops_getHandler('member');
if (false !== $member_handler->deleteUser($GLOBALS['xoopsUser'])) {
/* @var XoopsOnlineHandler $online_handler */
$online_handler = xoops_getHandler('online');
$online_handler->destroy($del_uid);
xoops_notification_deletebyuser($del_uid);
redirect_header(XOOPS_URL . '/', 5, _US_BEENDELED);
}
redirect_header(XOOPS_URL . '/', 5, _US_NOPERMISS);
}
exit();
}
}
/* Direct hits to pm module will be handled with same code as user.php.
Including rather than duplicating will make maintenance simpler.
*/
require __DIR__ . '/user.php';
56 changes: 31 additions & 25 deletions htdocs/modules/profile/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,31 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
* @license GNU GPL 2 (https://www.gnu.org/licenses/gpl-2.0.html)
* @copyright (c) 2000-2021 XOOPS Project (https://xoops.org)
* @license GNU GPL 2 or later (https://www.gnu.org/licenses/gpl-2.0.html)
* @package profile
* @since 2.3.0
* @author Jan Pedersen
* @author Taiwen Jiang <phppp@users.sourceforge.net>
*/

use Xmf\Request;

$xoopsOption['pagetype'] = 'user';
include __DIR__ . '/header.php';

XoopsLoad::load('XoopsFilterInput');
$op = 'main';
xoops_loadLanguage('user');

if (isset($_POST['op'])) {
$op = trim($_POST['op']);
} elseif (isset($_GET['op'])) {
$op = trim($_GET['op']);
}
$op = Request::getString('op', 'main');

if ($op === 'main') {
if (!$GLOBALS['xoopsUser']) {
if (!is_object($GLOBALS['xoopsUser'])) {
$GLOBALS['xoopsOption']['template_main'] = 'profile_userform.tpl';
include $GLOBALS['xoops']->path('header.php');
$GLOBALS['xoopsTpl']->assign('lang_login', _LOGIN);
$GLOBALS['xoopsTpl']->assign('lang_username', _USERNAME);
if (isset($_GET['xoops_redirect'])) {
$clean_redirect = XoopsFilterInput::clean($_GET['xoops_redirect'], 'WEBURL');
$GLOBALS['xoopsTpl']->assign('redirect_page', $clean_redirect);
if (Request::hasVar('xoops_redirect', 'GET')) {
$GLOBALS['xoopsTpl']->assign('redirect_page', htmlspecialchars(Request::getUrl('xoops_redirect', 'GET'), ENT_QUOTES));
}
if ($GLOBALS['xoopsConfig']['usercookie']) {
$GLOBALS['xoopsTpl']->assign('lang_rememberme', _US_REMEMBERME);
Expand All @@ -52,20 +48,29 @@
include __DIR__ . '/footer.php';
exit();
}
if (!empty($_GET['xoops_redirect'])) {
$redirect = trim($_GET['xoops_redirect']);
$isExternal = false;
if ($pos = strpos($redirect, '://')) {
$xoopsLocation = substr(XOOPS_URL, strpos(XOOPS_URL, '://') + 3);
if (strcasecmp(substr($redirect, $pos + 3, strlen($xoopsLocation)), $xoopsLocation)) {
$isExternal = true;

$redirect = Request::getUrl('xoops_redirect', '', 'GET');
if (!empty($redirect)) {
$urlParts = parse_url($redirect);
$xoopsUrlParts = parse_url(XOOPS_URL);
if (false !== $urlParts) {
// make sure $redirect is somewhere inside XOOPS_URL
// catch https:example.com (no //)
$badScheme = (isset($urlParts['path']) && !isset($urlParts['host']) && isset($urlParts['scheme']));
// no host or matching host
$hostMatch = (!isset($urlParts['host'])) || (0 === strcasecmp($urlParts['host'], $xoopsUrlParts['host']));
// path only, or path matches
$pathMatch = (isset($urlParts['path']) && !isset($urlParts['host']) && !isset($urlParts['scheme']))
|| ($hostMatch && isset($urlParts['path']) && isset($xoopsUrlParts['path'])
&& 0 === strncmp($urlParts['path'], $xoopsUrlParts['path'], strlen($xoopsUrlParts['path'])));
if ($badScheme || !($hostMatch && $pathMatch)) {
$redirect = XOOPS_URL;
}
}
if (!$isExternal) {
header('Location: ' . $redirect);
exit();
}
}

header('Location: ./userinfo.php?uid=' . $GLOBALS['xoopsUser']->getVar('uid'));
exit();
}
Expand Down Expand Up @@ -95,8 +100,8 @@
}

if ($op === 'actv') {
$id = (int)$_GET['id'];
$actkey = trim($_GET['actkey']);
$id = Request::getInt('id', 0, 'GET');
$actkey = Request::getString('actkey', '', 'GET');
redirect_header("activate.php?op=actv&amp;id={$id}&amp;actkey={$actkey}", 1, '');
}

Expand All @@ -112,8 +117,9 @@
// users in the webmasters group may not be deleted
redirect_header(XOOPS_URL . '/', 5, _US_ADMINNO);
}
$ok = !isset($_POST['ok']) ? 0 : (int)$_POST['ok'];
$ok = Request::getInt('ok', 0, 'POST');
if ($ok != 1) {
include $GLOBALS['xoops']->path('header.php');
include __DIR__ . '/header.php';
xoops_confirm(array('op' => 'delete', 'ok' => 1), 'user.php', _US_SURETODEL . '<br>' . _US_REMOVEINFO);
include __DIR__ . '/footer.php';
Expand Down

0 comments on commit e07319d

Please sign in to comment.