array(permission_array_for_editing_OWN_profile, permission_array_for_editing_ANY_profile[, require_validation]),
...
);
*/
$sa_allowed = array(
'summary' => array(array('profile_view_any', 'profile_view_own'), array('profile_view_any')),
'statPanel' => array(array('profile_view_any', 'profile_view_own'), array('profile_view_any')),
'showPosts' => array(array('profile_view_any', 'profile_view_own'), array('profile_view_any')),
'editBuddies' => array(array('profile_extra_any', 'profile_extra_own'), array()),
'trackUser' => array(array('moderate_forum'), array('moderate_forum')),
'trackIP' => array(array('moderate_forum'), array('moderate_forum')),
'showPermissions' => array(array('manage_permissions'), array('manage_permissions')),
'account' => array(array('manage_membergroups', 'profile_identity_any', 'profile_identity_own'), array('manage_membergroups', 'profile_identity_any')),
'forumProfile' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any')),
'theme' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any')),
'notification' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any')),
'pmprefs' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any')),
'deleteAccount' => array(array('profile_remove_any', 'profile_remove_own'), array('profile_remove_any')),
);
// Set the profile layer to be displayed.
$context['template_layers'][] = 'profile';
// Did we get the user by name...
if (isset($_REQUEST['user']))
$memberResult = loadMemberData($_REQUEST['user'], true, 'profile');
// ... or by ID_MEMBER?
elseif (!empty($_REQUEST['u']))
$memberResult = loadMemberData((int) $_REQUEST['u'], false, 'profile');
// If it was just ?action=profile, edit your own profile.
else
$memberResult = loadMemberData($ID_MEMBER, false, 'profile');
// Check if loadMemberData() has returned a valid result.
if (!is_array($memberResult))
fatal_lang_error(453, false);
// If all went well, we have a valid member ID!
list ($memID) = $memberResult;
// Is this the profile of the user himself or herself?
$context['user']['is_owner'] = $memID == $ID_MEMBER;
// No Subaction?
if (!isset($_REQUEST['sa']) || !isset($sa_allowed[$_REQUEST['sa']]))
{
// Pick the first subaction you're allowed to see.
if ((allowedTo('profile_view_own') && $context['user']['is_owner']) || allowedTo('profile_view_any'))
$_REQUEST['sa'] = 'summary';
elseif (allowedTo('moderate_forum'))
$_REQUEST['sa'] = 'trackUser';
elseif (allowedTo('manage_permissions'))
$_REQUEST['sa'] = 'showPermissions';
elseif ((allowedTo('profile_identity_own') && $context['user']['is_owner']) || allowedTo('profile_identity_any') || allowedTo('manage_membergroups'))
$_REQUEST['sa'] = 'account';
elseif ((allowedTo('profile_extra_own') && $context['user']['is_owner']) || allowedTo('profile_extra_any'))
$_REQUEST['sa'] = 'forumProfile';
elseif ((allowedTo('profile_remove_own') && $context['user']['is_owner']) || allowedTo('profile_remove_any'))
$_REQUEST['sa'] = 'deleteAccount';
else
isAllowedTo('profile_view_' . ($context['user']['is_owner'] ? 'own' : 'any'));
}
// Check the permissions for the given sub action.
isAllowedTo($sa_allowed[$_REQUEST['sa']][$context['user']['is_owner'] ? 0 : 1]);
// Make sure the user is who he claims to be, before any important account stuff is changed.
if (!empty($sa_allowed[$_REQUEST['sa']][2]))
validateSession();
// No need for this anymore.
unset($sa_allowed);
$context['profile_areas'] = array();
// Set the menu items in the left bar...
if (!$user_info['is_guest'] && (($context['user']['is_owner'] && allowedTo('profile_view_own')) || allowedTo(array('profile_view_any', 'moderate_forum', 'manage_permissions'))))
{
$context['profile_areas']['info'] = array(
'title' => $txt['profileInfo'],
'areas' => array()
);
if (($context['user']['is_owner'] && allowedTo('profile_view_own')) || allowedTo('profile_view_any'))
{
$context['profile_areas']['info']['areas']['summary'] = '' . $txt['summary'] . '';
$context['profile_areas']['info']['areas']['statPanel'] = '' . $txt['statPanel'] . '';
$context['profile_areas']['info']['areas']['showPosts'] = '' . $txt['showPosts'] . '';
}
// Groups with moderator permissions can also....
if (allowedTo('moderate_forum'))
{
$context['profile_areas']['info']['areas']['trackUser'] = '' . $txt['trackUser'] . '';
$context['profile_areas']['info']['areas']['trackIP'] = '' . $txt['trackIP'] . '';
}
if (allowedTo('manage_permissions'))
$context['profile_areas']['info']['areas']['showPermissions'] = '' . $txt['showPermissions'] . '';
}
// Edit your/this person's profile?
if (($context['user']['is_owner'] && (allowedTo(array('profile_identity_own', 'profile_extra_own')))) || allowedTo(array('profile_identity_any', 'profile_extra_any', 'manage_membergroups')))
{
$context['profile_areas']['edit_profile'] = array(
'title' => $txt['profileEdit'],
'areas' => array()
);
if (($context['user']['is_owner'] && allowedTo('profile_identity_own')) || allowedTo(array('profile_identity_any', 'manage_membergroups')))
$context['profile_areas']['edit_profile']['areas']['account'] = '' . $txt['account'] . '';
if (($context['user']['is_owner'] && allowedTo('profile_extra_own')) || allowedTo('profile_extra_any'))
{
$context['profile_areas']['edit_profile']['areas']['forumProfile'] = '' . $txt['forumProfile'] . '';
$context['profile_areas']['edit_profile']['areas']['theme'] = '' . $txt['theme'] . '';
$context['profile_areas']['edit_profile']['areas']['notification'] = '' . $txt['notification'] . '';
$context['profile_areas']['edit_profile']['areas']['pmprefs'] = '' . $txt['pmprefs'] . '';
}
// !!! I still don't think this warrants a new section by any means, but it's definitely not part of viewing a person's profile, if only the owner can do it.
if (!empty($modSettings['enable_buddylist']) && $context['user']['is_owner'] && allowedTo(array('profile_extra_own', 'profile_extra_any')))
$context['profile_areas']['edit_profile']['areas']['editBuddies'] = '' . $txt['editBuddies'] . '';
}
// If you have permission to do something with this profile, you'll see one or more actions.
if (($context['user']['is_owner'] && allowedTo('profile_remove_own')) || allowedTo('profile_remove_any') || (!$context['user']['is_owner'] && allowedTo('pm_send')))
{
// Initialize the action menu group...
$context['profile_areas']['profile_action'] = array(
'title' => $txt['profileAction'],
'areas' => array()
);
// You shouldn't PM (or ban really..) yourself!! (only administrators see this because it's not in the menu.)
if (!$context['user']['is_owner'] && allowedTo('pm_send'))
$context['profile_areas']['profile_action']['areas']['send_pm'] = '' . $txt['profileSendIm'] . '';
// We don't wanna ban admins, do we?
if (allowedTo('manage_bans') && $user_profile[$memID]['ID_GROUP'] != 1 && !in_array(1, explode(',', $user_profile[$memID]['additionalGroups'])))
$context['profile_areas']['profile_action']['areas']['banUser'] = '' . $txt['profileBanUser'] . '';
// You may remove your own account 'cuz it's yours or you're an admin.
if (($context['user']['is_owner'] && allowedTo('profile_remove_own')) || allowedTo('profile_remove_any'))
$context['profile_areas']['profile_action']['areas']['deleteAccount'] = '' . $txt['deleteAccount'] . '';
}
// This is here so the menu won't be shown unless it's actually needed.
if (!isset($context['profile_areas']['info']['areas']['trackUser']) && !isset($context['profile_areas']['info']['areas']['showPermissions']) && !isset($context['profile_areas']['edit_profile']) && !isset($context['profile_areas']['profile_action']['areas']['banUser']) && !isset($context['profile_areas']['profile_action']['areas']['deleteAccount']))
$context['profile_areas'] = array();
// Set the selected items.
$context['menu_item_selected'] = $_REQUEST['sa'];
$context['sub_template'] = $_REQUEST['sa'];
// All the subactions that require a user password in order to validate.
$context['require_password'] = in_array($context['menu_item_selected'], array('account'));
$context['member'] = array(
'id' => $memID,
'username' => $user_profile[$memID]['memberName'],
'name' => !isset($user_profile[$memID]['realName']) || $user_profile[$memID]['realName'] == '' ? '' : $user_profile[$memID]['realName'],
'email' => $user_profile[$memID]['emailAddress'],
'posts' => empty($user_profile[$memID]['posts']) ? 0: (int) $user_profile[$memID]['posts'],
'hide_email' => empty($user_profile[$memID]['hideEmail']) ? 0 : $user_profile[$memID]['hideEmail'],
'show_online' => empty($user_profile[$memID]['showOnline']) ? 0 : $user_profile[$memID]['showOnline'],
'registered' => empty($user_profile[$memID]['dateRegistered']) ? $txt[470] : strftime('%Y-%m-%d', $user_profile[$memID]['dateRegistered'] + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600),
'group' => $user_profile[$memID]['ID_GROUP'],
'gender' => array('name' => empty($user_profile[$memID]['gender']) ? '' : ($user_profile[$memID]['gender'] == 2 ? 'f' : 'm')),
'karma' => array(
'good' => empty($user_profile[$memID]['karmaGood']) ? '0' : $user_profile[$memID]['karmaGood'],
'bad' => empty($user_profile[$memID]['karmaBad']) ? '0' : $user_profile[$memID]['karmaBad'],
),
'avatar' => array(
'name' => &$user_profile[$memID]['avatar'],
'href' => empty($user_profile[$memID]['ID_ATTACH']) ? '' : (empty($user_profile[$memID]['attachmentType']) ? $scripturl . '?action=dlattach;attach=' . $user_profile[$memID]['ID_ATTACH'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $user_profile[$memID]['filename']),
'custom' => stristr($user_profile[$memID]['avatar'], 'http://') ? $user_profile[$memID]['avatar'] : 'http://',
'selection' => $user_profile[$memID]['avatar'] == '' || stristr($user_profile[$memID]['avatar'], 'http://') ? '' : $user_profile[$memID]['avatar'],
'ID_ATTACH' => &$user_profile[$memID]['ID_ATTACH'],
'filename' => &$user_profile[$memID]['filename'],
'allow_server_stored' => allowedTo('profile_server_avatar') || !$context['user']['is_owner'],
'allow_upload' => allowedTo('profile_upload_avatar') || !$context['user']['is_owner'],
'allow_external' => allowedTo('profile_remote_avatar') || !$context['user']['is_owner'],
),
'icq' => array('name' => !isset($user_profile[$memID]['ICQ']) ? '' : $user_profile[$memID]['ICQ']),
'aim' => array('name' => empty($user_profile[$memID]['AIM']) ? '' : str_replace('+', ' ', $user_profile[$memID]['AIM'])),
'yim' => array('name' => empty($user_profile[$memID]['YIM']) ? '' : $user_profile[$memID]['YIM']),
'msn' => array('name' => empty($user_profile[$memID]['MSN']) ? '' : $user_profile[$memID]['MSN']),
'website' => array(
'title' => !isset($user_profile[$memID]['websiteTitle']) ? '' : $user_profile[$memID]['websiteTitle'],
'url' => !isset($user_profile[$memID]['websiteUrl']) ? '' : $user_profile[$memID]['websiteUrl'],
),
);
// Call the appropriate subaction function.
$_REQUEST['sa']($memID);
if (!empty($post_errors))
{
// Set all the errors so the template knows what went wrong.
foreach ($post_errors as $error_type)
$context['modify_error'][$error_type] = true;
rememberPostData();
}
// Set the page title if it's not already set...
if (!isset($context['page_title']))
$context['page_title'] = $txt[79] . ' - ' . $txt[$_REQUEST['sa']];
}
// Execute the modifications!
function ModifyProfile2()
{
global $txt, $modSettings;
global $cookiename, $context;
global $sourcedir, $scripturl, $db_prefix;
global $ID_MEMBER, $user_info;
global $context, $newpassemail, $user_profile, $validationCode;
loadLanguage('Profile');
/* Set allowed sub-actions.
The format of $sa_allowed is as follows:
$sa_allowed = array(
'sub-action' => array(permission_array_for_editing_OWN_profile, permission_array_for_editing_ANY_profile, session_validation_method[, require_password]),
...
);
*/
$sa_allowed = array(
'account' => array(array('manage_membergroups', 'profile_identity_any', 'profile_identity_own'), array('manage_membergroups', 'profile_identity_any'), 'post', true),
'forumProfile' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any'), 'post'),
'theme' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any'), 'post'),
'notification' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any'), 'post'),
'pmprefs' => array(array('profile_extra_any', 'profile_extra_own'), array('profile_extra_any'), 'post'),
'deleteAccount' => array(array('profile_remove_any', 'profile_remove_own'), array('profile_remove_any'), 'post', true),
'activateAccount' => array(array(), array('moderate_forum'), 'get'),
);
// Is the current sub-action allowed?
if (empty($_REQUEST['sa']) || !isset($sa_allowed[$_REQUEST['sa']]))
fatal_lang_error(453, false);
checkSession($sa_allowed[$_REQUEST['sa']][2]);
// Start with no updates and no errors.
$profile_vars = array();
$post_errors = array();
// Normally, don't send an email.
$newpassemail = false;
// Clean up the POST variables.
$_POST = htmltrim__recursive($_POST);
$_POST = stripslashes__recursive($_POST);
$_POST = htmlspecialchars__recursive($_POST);
$_POST = addslashes__recursive($_POST);
// Search for the member being edited and put the information in $user_profile.
$memberResult = loadMemberData((int) $_REQUEST['userID'], false, 'profile');
if (!is_array($memberResult))
fatal_lang_error(453, false);
list ($memID) = $memberResult;
// Are you modifying your own, or someone else's?
if ($ID_MEMBER == $memID)
$context['user']['is_owner'] = true;
else
{
$context['user']['is_owner'] = false;
validateSession();
}
// Check profile editing permissions.
isAllowedTo($sa_allowed[$_REQUEST['sa']][$context['user']['is_owner'] ? 0 : 1]);
// If this is yours, check the password.
if ($context['user']['is_owner'] && !empty($sa_allowed[$_REQUEST['sa']][3]))
{
// You didn't even enter a password!
if (trim($_POST['oldpasswrd']) == '')
$post_errors[] = 'no_password';
// Since the password got modified due to all the $_POST cleaning, lets undo it so we can get the correct password
$_POST['oldpasswrd'] = addslashes(un_htmlspecialchars(stripslashes($_POST['oldpasswrd'])));
// Does the integration want to check passwords?
$good_password = false;
if (isset($modSettings['integrate_verify_password']) && function_exists($modSettings['integrate_verify_password']))
if (call_user_func($modSettings['integrate_verify_password'], $user_profile[$memID]['memberName'], $_POST['oldpasswrd'], false) === true)
$good_password = true;
// Bad password!!!
if (!$good_password && $user_info['passwd'] != sha1(strtolower($user_profile[$memID]['memberName']) . $_POST['oldpasswrd']))
$post_errors[] = 'bad_password';
}
// No need for the sub action array.
unset($sa_allowed);
// If the user is an admin - see if they are resetting someones username.
if ($user_info['is_admin'] && isset($_POST['memberName']))
{
// We'll need this...
require_once($sourcedir . '/Subs-Auth.php');
// Do the reset... this will send them an email too.
resetPassword($memID, $_POST['memberName']);
}
// Change the IP address in the database.
if ($context['user']['is_owner'])
$profile_vars['memberIP'] = "'$user_info[ip]'";
// Now call the sub-action function...
if (isset($_POST['sa']) && $_POST['sa'] == 'deleteAccount')
{
deleteAccount2($profile_vars, $post_errors, $memID);
if (empty($post_errors))
redirectexit();
}
else
saveProfileChanges($profile_vars, $post_errors, $memID);
// There was a problem, let them try to re-enter.
if (!empty($post_errors))
{
// Load the language file so we can give a nice explanation of the errors.
loadLanguage('Errors');
$context['post_errors'] = $post_errors;
$_REQUEST['sa'] = $_POST['sa'];
$_REQUEST['u'] = $memID;
return ModifyProfile($post_errors);
}
if (!empty($profile_vars))
{
// If we've changed the password, notify any integration that may be listening in.
if (isset($profile_vars['passwd']) && isset($modSettings['integrate_reset_pass']) && function_exists($modSettings['integrate_reset_pass']))
call_user_func($modSettings['integrate_reset_pass'], $user_profile[$memID]['memberName'], $user_profile[$memID]['memberName'], $_POST['passwrd1']);
updateMemberData($memID, $profile_vars);
}
// What if this is the newest member?
if ($modSettings['latestMember'] == $memID)
updateStats('member');
elseif (isset($profile_vars['realName']))
updateSettings(array('memberlist_updated' => time()));
// If the member changed his/her birthdate, update calendar statistics.
if (isset($profile_vars['birthdate']) || isset($profile_vars['realName']))
updateStats('calendar');
// Send an email?
if ($newpassemail)
{
require_once($sourcedir . '/Subs-Post.php');
// Send off the email.
sendmail($_POST['emailAddress'], $txt['activate_reactivate_title'] . ' ' . $context['forum_name'],
"$txt[activate_reactivate_mail]\n\n" .
"$scripturl?action=activate;u=$memID;code=$validationCode\n\n" .
"$txt[activate_code]: $validationCode\n\n" .
$txt[130]);
// Log the user out.
db_query("
DELETE FROM {$db_prefix}log_online
WHERE ID_MEMBER = $memID", __FILE__, __LINE__);
$_SESSION['log_time'] = 0;
$_SESSION['login_' . $cookiename] = serialize(array(0, '', 0));
if (isset($_COOKIE[$cookiename]))
$_COOKIE[$cookiename] = '';
loadUserSettings();
$context['user']['is_logged'] = false;
$context['user']['is_guest'] = true;
// Send them to the done-with-registration-login screen.
loadTemplate('Register');
$context += array(
'page_title' => &$txt[79],
'sub_template' => 'after',
'description' => &$txt['activate_changed_email']
);
return;
}
elseif ($context['user']['is_owner'])
{
// Log them back in.
if (isset($_POST['passwrd1']) && $_POST['passwrd1'] != '')
{
require_once($sourcedir . '/Subs-Auth.php');
setLoginCookie(60 * $modSettings['cookieTime'], $memID, sha1(sha1(strtolower($user_profile[$memID]['memberName']) . un_htmlspecialchars(stripslashes($_POST['passwrd1']))) . $user_profile[$memID]['passwordSalt']));
}
loadUserSettings();
writeLog();
}
// Back to same subaction page..
redirectexit('action=profile;u=' . $memID . ';sa=' . $_REQUEST['sa'], (isset($_POST['passwrd1']) && $context['server']['needs_login_fix']) || ($context['browser']['is_ie'] && isset($_FILES['attachment'])));
}
// Save the profile changes....
function saveProfileChanges(&$profile_vars, &$post_errors, $memID)
{
global $db_prefix, $user_info, $txt, $modSettings, $user_profile;
global $newpassemail, $validationCode, $context, $settings, $sourcedir;
global $func;
// These make life easier....
$old_profile = &$user_profile[$memID];
// Permissions...
if ($context['user']['is_owner'])
{
$changeIdentity = allowedTo(array('profile_identity_any', 'profile_identity_own'));
$changeOther = allowedTo(array('profile_extra_any', 'profile_extra_own'));
}
else
{
$changeIdentity = allowedTo('profile_identity_any');
$changeOther = allowedTo('profile_extra_any');
}
// Arrays of all the changes - makes things easier.
$profile_bools = array(
'notifyAnnouncements', 'notifyOnce', 'notifySendBody',
);
$profile_ints = array(
'pm_email_notify',
'notifyTypes',
'ICQ',
'gender',
'ID_THEME',
);
$profile_floats = array(
'timeOffset',
);
$profile_strings = array(
'websiteUrl', 'websiteTitle',
'AIM', 'YIM',
'location', 'birthdate',
'timeFormat',
'buddy_list',
'pm_ignore_list',
'smileySet',
'signature', 'personalText', 'avatar',
);
// Fix the spaces in messenger screennames...
$fix_spaces = array('MSN', 'AIM', 'YIM');
foreach ($fix_spaces as $var)
{
// !!! Why?
if (isset($_POST[$var]))
$_POST[$var] = strtr($_POST[$var], ' ', '+');
}
// Make sure the MSN one is an email address, not something like 'none' :P.
if (isset($_POST['MSN']) && ($_POST['MSN'] == '' || preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $_POST['MSN']) != 0))
$profile_strings[] = 'MSN';
// Validate the title...
if (!empty($modSettings['titlesEnable']) && (allowedTo('profile_title_any') || (allowedTo('profile_title_own') && $context['user']['is_owner'])))
$profile_strings[] = 'usertitle';
// Validate the timeOffset...
if (isset($_POST['timeOffset']))
{
$_POST['timeOffset'] = strtr($_POST['timeOffset'], ',', '.');
if ($_POST['timeOffset'] < -23.5 || $_POST['timeOffset'] > 23.5)
$post_errors[] = 'bad_offset';
}
// Fix the URL...
if (isset($_POST['websiteUrl']))
{
if (strlen(trim($_POST['websiteUrl'])) > 0 && strpos($_POST['websiteUrl'], '://') === false)
$_POST['websiteUrl'] = 'http://' . $_POST['websiteUrl'];
if (strlen($_POST['websiteUrl']) < 8)
$_POST['websiteUrl'] = '';
}
// !!! Should we check for this year and tell them they made a mistake :P? (based on coppa at least?)
if (isset($_POST['birthdate']))
{
if (preg_match('/(\d{4})[\-\., ](\d{2})[\-\., ](\d{2})/', $_POST['birthdate'], $dates) === 1)
$_POST['birthdate'] = checkdate($dates[2], $dates[3], $dates[1] < 4 ? 4 : $dates[1]) ? sprintf('%04d-%02d-%02d', $dates[1] < 4 ? 4 : $dates[1], $dates[2], $dates[3]) : '0001-01-01';
else
unset($_POST['birthdate']);
}
elseif (isset($_POST['bday1'], $_POST['bday2'], $_POST['bday3']) && $_POST['bday1'] > 0 && $_POST['bday2'] > 0)
$_POST['birthdate'] = checkdate($_POST['bday1'], $_POST['bday2'], $_POST['bday3'] < 4 ? 4 : $_POST['bday3']) ? sprintf('%04d-%02d-%02d', $_POST['bday3'] < 4 ? 4 : $_POST['bday3'], $_POST['bday1'], $_POST['bday2']) : '0001-01-01';
elseif (isset($_POST['bday1']) || isset($_POST['bday2']) || isset($_POST['bday3']))
$_POST['birthdate'] = '0001-01-01';
if (isset($_POST['im_email_notify']))
$_POST['pm_email_notify'] = $_POST['im_email_notify'];
// Validate and set the ignorelist...
if (isset($_POST['pm_ignore_list']) || isset($_POST['im_ignore_list']))
{
if (!isset($_POST['pm_ignore_list']))
$_POST['pm_ignore_list'] = $_POST['im_ignore_list'];
$_POST['pm_ignore_list'] = strtr($func['htmltrim']($_POST['pm_ignore_list']), array('\\\'' => ''', "\n" => "', '", "\r" => '', '"' => ''));
if (preg_match('~(\A|,)\*(\Z|,)~s', $_POST['pm_ignore_list']) == 0)
{
$result = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE memberName IN ('$_POST[pm_ignore_list]') OR realName IN ('$_POST[pm_ignore_list]')
LIMIT " . (substr_count($_POST['pm_ignore_list'], '\', \'') + 1), __FILE__, __LINE__);
$_POST['pm_ignore_list'] = '';
while ($row = mysql_fetch_assoc($result))
$_POST['pm_ignore_list'] .= $row['ID_MEMBER'] . ',';
mysql_free_result($result);
// !!! Did we find all the members?
$_POST['pm_ignore_list'] = substr($_POST['pm_ignore_list'], 0, -1);
}
else
$_POST['pm_ignore_list'] = '*';
}
// Similarly, do the same for the buddy list
if (isset($_POST['buddy_list']))
{
$_POST['buddy_list'] = strtr(trim($_POST['buddy_list']), array('\\\'' => ''', "\n" => "', '", "\r" => '', '"' => ''));
if (trim($_POST['buddy_list']) != '')
{
$result = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE memberName IN ('$_POST[buddy_list]') OR realName IN ('$_POST[buddy_list]')
LIMIT " . (substr_count($_POST['buddy_list'], '\', \'') + 1), __FILE__, __LINE__);
$_POST['buddy_list'] = '';
while ($row = mysql_fetch_assoc($result))
$_POST['buddy_list'] .= $row['ID_MEMBER'] . ',';
mysql_free_result($result);
// !!! Did we find all the members?
$_POST['buddy_list'] = substr($_POST['buddy_list'], 0, -1);
}
}
// Validate the smiley set.
if (isset($_POST['smileySet']))
{
$smiley_sets = explode(',', $modSettings['smiley_sets_known']);
if (!in_array($_POST['smileySet'], $smiley_sets) && $_POST['smileySet'] != 'none')
$_POST['smileySet'] = '';
}
// Make sure the signature isn't too long.
if (isset($_POST['signature']))
{
require_once($sourcedir . '/Subs-Post.php');
if (!empty($modSettings['max_signatureLength']) && $func['strlen']($_POST['signature']) > $modSettings['max_signatureLength'])
$_POST['signature'] = addslashes($func['substr'](stripslashes($_POST['signature']), 0, $modSettings['max_signatureLength']));
if (strlen($_POST['signature']) > 65534)
$_POST['signature'] = addslashes($func['truncate'](stripslashes($_POST['signature']), 65534));
$_POST['signature'] = strtr($_POST['signature'], array('"' => '\\"', ''' => '\\'', ''' => '\\''));
preparsecode($_POST['signature']);
}
// Identity-only changes...
if ($changeIdentity)
{
// This block is only concerned with display name validation.
if (isset($_POST['realName']) && (!empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum')) && trim($_POST['realName']) != $old_profile['realName'])
{
$_POST['realName'] = trim(preg_replace('~[\s]~' . ($context['utf8'] ? 'u' : ''), ' ', $_POST['realName']));
if (trim($_POST['realName']) == '')
$post_errors[] = 'no_name';
elseif ($func['strlen']($_POST['realName']) > 60)
$post_errors[] = 'name_too_long';
else
{
require_once($sourcedir . '/Subs-Members.php');
if (isReservedName($_POST['realName'], $memID))
$post_errors[] = 'name_taken';
}
if (isset($_POST['realName']))
$profile_vars['realName'] = '\'' . $_POST['realName'] . '\'';
}
// Change the registration date.
if (!empty($_POST['dateRegistered']) && allowedTo('admin_forum'))
{
// Bad date! Go try again - please?
if (($_POST['dateRegistered'] = strtotime($_POST['dateRegistered'])) === -1)
fatal_error($txt['smf233'] . ' ' . strftime('%d %b %Y ' . (strpos($user_info['time_format'], '%H') !== false ? '%I:%M:%S %p' : '%H:%M:%S'), forum_time(false)), false);
// As long as it doesn't equal 'N/A'...
elseif ($_POST['dateRegistered'] != $txt[470] && $_POST['dateRegistered'] != strtotime(strftime('%Y-%m-%d', $user_profile[$memID]['dateRegistered'] + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600)))
$profile_vars['dateRegistered'] = $_POST['dateRegistered'] - ($user_info['time_offset'] + $modSettings['time_offset']) * 3600;
}
// Change the number of posts.
if (isset($_POST['posts']) && allowedTo('moderate_forum'))
$profile_vars['posts'] = $_POST['posts'] != '' ? (int) strtr($_POST['posts'], array(',' => '', '.' => '', ' ' => '')) : '\'\'';
// This block is only concerned with email address validation..
if (isset($_POST['emailAddress']) && strtolower($_POST['emailAddress']) != strtolower($old_profile['emailAddress']))
{
$_POST['emailAddress'] = strtr($_POST['emailAddress'], array(''' => '\\\''));
// Prepare the new password, or check if they want to change their own.
if (!empty($modSettings['send_validation_onChange']) && !allowedTo('moderate_forum'))
{
require_once($sourcedir . '/Subs-Members.php');
$validationCode = generateValidationCode();
$profile_vars['validation_code'] = '\'' . $validationCode . '\'';
$profile_vars['is_activated'] = '2';
$newpassemail = true;
}
// Check the name and email for validity.
if (trim($_POST['emailAddress']) == '')
$post_errors[] = 'no_email';
if (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', stripslashes($_POST['emailAddress'])) == 0)
$post_errors[] = 'bad_email';
// Email addresses should be and stay unique.
$request = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE ID_MEMBER != $memID
AND emailAddress = '$_POST[emailAddress]'
LIMIT 1", __FILE__, __LINE__);
if (mysql_num_rows($request) > 0)
$post_errors[] = 'email_taken';
mysql_free_result($request);
$profile_vars['emailAddress'] = '\'' . $_POST['emailAddress'] . '\'';
}
// Hide email address?
if (isset($_POST['hideEmail']) && (!empty($modSettings['allow_hideEmail']) || allowedTo('moderate_forum')))
$profile_vars['hideEmail'] = empty($_POST['hideEmail']) ? '0' : '1';
// Are they allowed to change their hide status?
if (isset($_POST['showOnline']) && (!empty($modSettings['allow_hideOnline']) || allowedTo('moderate_forum')))
$profile_vars['showOnline'] = empty($_POST['showOnline']) ? '0' : '1';
// If they're trying to change the password, let's check they pick a sensible one.
if (isset($_POST['passwrd1']) && $_POST['passwrd1'] != '')
{
// Do the two entries for the password even match?
if ($_POST['passwrd1'] != $_POST['passwrd2'])
$post_errors[] = 'bad_new_password';
// Let's get the validation function into play...
require_once($sourcedir . '/Subs-Auth.php');
$passwordErrors = validatePassword($_POST['passwrd1'], $user_info['username'], array($user_info['name'], $user_info['email']));
// Were there errors?
if ($passwordErrors != null)
$post_errors[] = 'password_' . $passwordErrors;
// Set up the new password variable... ready for storage.
$profile_vars['passwd'] = '\'' . sha1(strtolower($old_profile['memberName']) . un_htmlspecialchars(stripslashes($_POST['passwrd1']))) . '\'';
}
if (isset($_POST['secretQuestion']))
$profile_vars['secretQuestion'] = '\'' . $_POST['secretQuestion'] . '\'';
// Do you have a *secret* password?
if (isset($_POST['secretAnswer']) && $_POST['secretAnswer'] != '')
$profile_vars['secretAnswer'] = '\'' . md5($_POST['secretAnswer']) . '\'';
}
// Things they can do if they are a forum moderator.
if (allowedTo('moderate_forum'))
{
if (($_REQUEST['sa'] == 'activateAccount' || !empty($_POST['is_activated'])) && isset($old_profile['is_activated']) && $old_profile['is_activated'] != 1)
{
// If we are approving the deletion of an account, we do something special ;)
if ($old_profile['is_activated'] == 4)
{
require_once($sourcedir . '/Subs-Members.php');
deleteMembers($memID);
redirectexit();
}
if (isset($modSettings['integrate_activate']) && function_exists($modSettings['integrate_activate']))
call_user_func($modSettings['integrate_activate'], $old_profile['memberName']);
// Actually update this member now, as it guarantees the unapproved count can't get corrupted.
updateMemberData($memID, array('is_activated' => $old_profile['is_activated'] >= 10 ? '11' : '1', 'validation_code' => '\'\''));
// If we are doing approval, update the stats for the member just incase.
if (in_array($old_profile['is_activated'], array(3, 4, 13, 14)))
updateSettings(array('unapprovedMembers' => ($modSettings['unapprovedMembers'] > 1 ? $modSettings['unapprovedMembers'] - 1 : 0)));
// Make sure we update the stats too.
updateStats('member', false);
}
if (isset($_POST['karmaGood']))
$profile_vars['karmaGood'] = $_POST['karmaGood'] != '' ? (int) $_POST['karmaGood'] : '\'\'';
if (isset($_POST['karmaBad']))
$profile_vars['karmaBad'] = $_POST['karmaBad'] != '' ? (int) $_POST['karmaBad'] : '\'\'';
}
// Assigning membergroups (you need admin_forum permissions to change an admins' membergroups).
if (allowedTo('manage_membergroups'))
{
// The account page allows the change of your ID_GROUP - but not to admin!.
if (isset($_POST['ID_GROUP']) && (allowedTo('admin_forum') || ((int) $_POST['ID_GROUP'] != 1 && $old_profile['ID_GROUP'] != 1)))
$profile_vars['ID_GROUP'] = (int) $_POST['ID_GROUP'];
// Find the additional membergroups (if any)
if (isset($_POST['additionalGroups']) && is_array($_POST['additionalGroups']))
{
foreach ($_POST['additionalGroups'] as $i => $group_id)
{
if ((int) $group_id == 0 || (!allowedTo('admin_forum') && (int) $group_id == 1))
unset($_POST['additionalGroups'][$i], $_POST['additionalGroups'][$i]);
else
$_POST['additionalGroups'][$i] = (int) $group_id;
}
// Put admin back in there if you don't have permission to take it away.
if (!allowedTo('admin_forum') && in_array(1, explode(',', $old_profile['additionalGroups'])))
$_POST['additionalGroups'][] = 1;
$profile_vars['additionalGroups'] = '\'' . implode(',', $_POST['additionalGroups']) . '\'';
}
// Too often, people remove delete their own account, or something.
if (in_array(1, explode(',', $old_profile['additionalGroups'])) || $old_profile['ID_GROUP'] == 1)
{
$stillAdmin = !isset($profile_vars['ID_GROUP']) || $profile_vars['ID_GROUP'] == 1 || (isset($_POST['additionalGroups']) && in_array(1, $_POST['additionalGroups']));
// If they would no longer be an admin, look for any other...
if (!$stillAdmin)
{
$request = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE (ID_GROUP = 1 OR FIND_IN_SET(1, additionalGroups))
AND ID_MEMBER != $memID
LIMIT 1", __FILE__, __LINE__);
list ($another) = mysql_fetch_row($request);
mysql_free_result($request);
if (empty($another))
fatal_lang_error('at_least_one_admin');
}
}
}
// Validate the language file...
if (($changeIdentity || $changeOther) && isset($_POST['lngfile']) && !empty($modSettings['userLanguage']))
{
$language_directories = array(
$settings['default_theme_dir'] . '/languages',
$settings['actual_theme_dir'] . '/languages',
);
if (!empty($settings['base_theme_dir']))
$language_directories[] = $settings['base_theme_dir'] . '/languages';
$language_directories = array_unique($language_directories);
foreach ($language_directories as $language_dir)
{
if (!file_exists($language_dir))
continue;
$dir = dir($language_dir);
while ($entry = $dir->read())
if (preg_match('~^index\.(.+)\.php$~', $entry, $matches) && $matches[1] == $_POST['lngfile'])
{
$profile_vars['lngfile'] = "'$_POST[lngfile]'";
// If they are the owner, make this persist even after they log out.
if ($context['user']['is_owner'])
$_SESSION['language'] = $_POST['lngfile'];
}
$dir->close();
}
}
// Here's where we sort out all the 'other' values...
if ($changeOther)
{
makeThemeChanges($memID, isset($_POST['ID_THEME']) ? (int) $_POST['ID_THEME'] : $old_profile['ID_THEME']);
makeAvatarChanges($memID, $post_errors);
makeNotificationChanges($memID);
foreach ($profile_bools as $var)
if (isset($_POST[$var]))
$profile_vars[$var] = empty($_POST[$var]) ? '0' : '1';
foreach ($profile_ints as $var)
if (isset($_POST[$var]))
$profile_vars[$var] = $_POST[$var] != '' ? (int) $_POST[$var] : '\'\'';
foreach ($profile_floats as $var)
if (isset($_POST[$var]))
$profile_vars[$var] = (float) $_POST[$var];
foreach ($profile_strings as $var)
if (isset($_POST[$var]))
$profile_vars[$var] = '\'' . $_POST[$var] . '\'';
}
if (isset($profile_vars['ICQ']) && $profile_vars['ICQ'] == '0')
$profile_vars['ICQ'] = '\'\'';
}
// Make any theme changes that are sent with the profile..
function makeThemeChanges($memID, $ID_THEME)
{
global $db_prefix, $modSettings;
$reservedVars = array(
'actual_theme_url',
'actual_images_url',
'base_theme_dir',
'base_theme_url',
'default_images_url',
'default_theme_dir',
'default_theme_url',
'default_template',
'images_url',
'number_recent_posts',
'smiley_sets_default',
'theme_dir',
'theme_id',
'theme_layers',
'theme_templates',
'theme_url',
);
// Can't change reserved vars.
if ((isset($_POST['options']) && array_intersect(array_keys($_POST['options']), $reservedVars) != array()) || (isset($_POST['default_options']) && array_intersect(array_keys($_POST['default_options']), $reservedVars) != array()))
fatal_lang_error(1);
// These are the theme changes...
$themeSetArray = array();
if (isset($_POST['options']) && is_array($_POST['options']))
{
foreach ($_POST['options'] as $opt => $val)
$themeSetArray[] = '(' . $memID . ', ' . $ID_THEME . ", SUBSTRING('" . addslashes($opt) . "', 1, 255), SUBSTRING('" . (is_array($val) ? implode(',', $val) : $val) . "', 1, 65534))";
}
$erase_options = array();
if (isset($_POST['default_options']) && is_array($_POST['default_options']))
foreach ($_POST['default_options'] as $opt => $val)
{
$themeSetArray[] = "($memID, 1, SUBSTRING('" . addslashes($opt) . "', 1, 255), SUBSTRING('" . (is_array($val) ? implode(',', $val) : $val) . "', 1, 65534))";
$erase_options[] = addslashes($opt);
}
// If themeSetArray isn't still empty, send it to the database.
if (!empty($themeSetArray))
{
db_query("
REPLACE INTO {$db_prefix}themes
(ID_MEMBER, ID_THEME, variable, value)
VALUES " . implode(",
", $themeSetArray), __FILE__, __LINE__);
}
if (!empty($erase_options))
{
db_query("
DELETE FROM {$db_prefix}themes
WHERE ID_THEME != 1
AND variable IN ('" . implode("', '", $erase_options) . "')
AND ID_MEMBER = $memID", __FILE__, __LINE__);
}
$themes = explode(',', $modSettings['knownThemes']);
foreach ($themes as $t)
cache_put_data('theme_settings-' . $t . ':' . $memID, null, 60);
}
// Make any notification changes that need to be made.
function makeNotificationChanges($memID)
{
global $db_prefix;
// Update the boards they are being notified on.
if (isset($_POST['edit_notify_boards']) && !empty($_POST['notify_boards']))
{
// Make sure only integers are deleted.
foreach ($_POST['notify_boards'] as $index => $id)
$_POST['notify_boards'][$index] = (int) $id;
// ID_BOARD = 0 is reserved for topic notifications.
$_POST['notify_boards'] = array_diff($_POST['notify_boards'], array(0));
db_query("
DELETE FROM {$db_prefix}log_notify
WHERE ID_BOARD IN (" . implode(', ', $_POST['notify_boards']) . ")
AND ID_MEMBER = $memID", __FILE__, __LINE__);
}
// We are editing topic notifications......
elseif (isset($_POST['edit_notify_topics']) && !empty($_POST['notify_topics']))
{
foreach ($_POST['notify_topics'] as $index => $id)
$_POST['notify_topics'][$index] = (int) $id;
// Make sure there are no zeros left.
$_POST['notify_topics'] = array_diff($_POST['notify_topics'], array(0));
db_query("
DELETE FROM {$db_prefix}log_notify
WHERE ID_TOPIC IN (" . implode(', ', $_POST['notify_topics']) . ")
AND ID_MEMBER = $memID", __FILE__, __LINE__);
}
}
// The avatar is incredibly complicated, what with the options... and what not.
function makeAvatarChanges($memID, &$post_errors)
{
global $modSettings, $sourcedir, $db_prefix;
if (!isset($_POST['avatar_choice']) || empty($memID))
return;
require_once($sourcedir . '/ManageAttachments.php');
$uploadDir = empty($modSettings['custom_avatar_enabled']) ? $modSettings['attachmentUploadDir'] : $modSettings['custom_avatar_dir'];
$downloadedExternalAvatar = false;
if ($_POST['avatar_choice'] == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && strlen($_POST['userpicpersonal']) > 7 && !empty($modSettings['avatar_download_external']))
{
if (!is_writable($uploadDir))
fatal_lang_error('attachments_no_write');
require_once($sourcedir . '/Subs-Package.php');
$url = parse_url($_POST['userpicpersonal']);
$contents = fetch_web_data('http://' . $url['host'] . (empty($url['port']) ? '' : ':' . $url['port']) . $url['path']);
if ($contents != false && $tmpAvatar = fopen($uploadDir . '/avatar_tmp_' . $memID, 'wb'))
{
fwrite($tmpAvatar, $contents);
fclose($tmpAvatar);
$downloadedExternalAvatar = true;
$_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
}
}
if ($_POST['avatar_choice'] == 'server_stored' && allowedTo('profile_server_avatar'))
{
$_POST['avatar'] = strtr(empty($_POST['file']) ? (empty($_POST['cat']) ? '' : $_POST['cat']) : $_POST['file'], array('&' => '&'));
$_POST['avatar'] = preg_match('~^([\w _!@%*=\-#()\[\]&.,]+/)?[\w _!@%*=\-#()\[\]&.,]+$~', $_POST['avatar']) != 0 && preg_match('/\.\./', $_POST['avatar']) == 0 && file_exists($modSettings['avatar_directory'] . '/' . $_POST['avatar']) ? ($_POST['avatar'] == 'blank.gif' ? '' : $_POST['avatar']) : '';
// Get rid of their old avatar. (if uploaded.)
removeAttachments('a.ID_MEMBER = ' . $memID);
}
elseif ($_POST['avatar_choice'] == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && empty($modSettings['avatar_download_external']))
{
// Remove any attached avatar...
removeAttachments('a.ID_MEMBER = ' . $memID);
$_POST['avatar'] = preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $_POST['userpicpersonal']);
if ($_POST['avatar'] == 'http://' || $_POST['avatar'] == 'http:///')
$_POST['avatar'] = '';
// Trying to make us do something we'll regret?
elseif (substr($_POST['avatar'], 0, 7) != 'http://')
$post_errors[] = 'bad_avatar';
// Should we check dimensions?
elseif (!empty($modSettings['avatar_max_height_external']) || !empty($modSettings['avatar_max_width_external']))
{
// Now let's validate the avatar.
$sizes = url_image_size($_POST['avatar']);
if (is_array($sizes) && (($sizes[0] > $modSettings['avatar_max_width_external'] && !empty($modSettings['avatar_max_width_external'])) || ($sizes[1] > $modSettings['avatar_max_height_external'] && !empty($modSettings['avatar_max_height_external']))))
{
// Houston, we have a problem. The avatar is too large!!
if ($modSettings['avatar_action_too_large'] == 'option_refuse')
$post_errors[] = 'bad_avatar';
elseif ($modSettings['avatar_action_too_large'] == 'option_download_and_resize')
{
require_once($sourcedir . '/Subs-Graphics.php');
if (downloadAvatar($_POST['avatar'], $memID, $modSettings['avatar_max_width_external'], $modSettings['avatar_max_height_external']))
$_POST['avatar'] = '';
else
$post_errors[] = 'bad_avatar';
}
}
}
}
elseif (($_POST['avatar_choice'] == 'upload' && allowedTo('profile_upload_avatar') ) || $downloadedExternalAvatar)
{
if ((isset($_FILES['attachment']['name']) && $_FILES['attachment']['name'] != '') || $downloadedExternalAvatar)
{
// Get the dimensions of the image.
if (!$downloadedExternalAvatar)
{
if (!is_writable($uploadDir))
fatal_lang_error('attachments_no_write');
if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadDir . '/avatar_tmp_' . $memID))
fatal_lang_error('smf124');
$_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
}
$sizes = @getimagesize($_FILES['attachment']['tmp_name']);
// No size, then it's probably not a valid pic.
if ($sizes === false)
$post_errors[] = 'bad_avatar';
// Check whether the image is too large.
elseif ((!empty($modSettings['avatar_max_width_upload']) && $sizes[0] > $modSettings['avatar_max_width_upload']) || (!empty($modSettings['avatar_max_height_upload']) && $sizes[1] > $modSettings['avatar_max_height_upload']))
{
if (!empty($modSettings['avatar_resize_upload']))
{
// Attempt to chmod it.
@chmod($uploadDir . '/avatar_tmp_' . $memID, 0644);
require_once($sourcedir . '/Subs-Graphics.php');
downloadAvatar($uploadDir . '/avatar_tmp_' . $memID, $memID, $modSettings['avatar_max_width_upload'], $modSettings['avatar_max_height_upload']);
}
else
$post_errors[] = 'bad_avatar';
}
elseif (is_array($sizes))
{
// Though not an exhaustive list, better safe than sorry.
$fp = fopen($_FILES['attachment']['tmp_name'], 'rb');
if (!$fp)
fatal_lang_error('smf124');
// Now try to find an infection.
while (!feof($fp))
{
if (preg_match('~(iframe|\\<\\?php|\\<\\?[\s=]|\\<%[\s=]|html|eval|body|script\W)~', fgets($fp, 4096)) === 1)
{
if (file_exists($uploadDir . '/avatar_tmp_' . $memID))
@unlink($uploadDir . '/avatar_tmp_' . $memID);
fatal_lang_error('smf124');
}
}
fclose($fp);
$extensions = array(
'1' => '.gif',
'2' => '.jpg',
'3' => '.png',
'6' => '.bmp'
);
$extension = isset($extensions[$sizes[2]]) ? $extensions[$sizes[2]] : '.bmp';
$destName = 'avatar_' . $memID . $extension;
list ($width, $height) = getimagesize($_FILES['attachment']['tmp_name']);
// Remove previous attachments this member might have had.
removeAttachments('a.ID_MEMBER = ' . $memID);
$file_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, true) : '';
db_query("
INSERT INTO {$db_prefix}attachments
(ID_MEMBER, attachmentType, filename, file_hash, size, width, height)
VALUES ($memID, " . (empty($modSettings['custom_avatar_enabled']) ? '0' : '1') . ", '$destName', '" . (empty($file_hash) ? "" : "$file_hash") . "', " . filesize($_FILES['attachment']['tmp_name']) . ", " . (int) $width . ", " . (int) $height . ")", __FILE__, __LINE__);
$attachID = db_insert_id();
// Try to move this avatar.
$destinationPath = $uploadDir . '/' . (empty($file_hash) ? $destName : $attachID . '_' . $file_hash);
if (!rename($_FILES['attachment']['tmp_name'], $destinationPath))
{
// The move failed, get rid of it and die.
db_query("
DELETE FROM {$db_prefix}attachments
WHERE ID_ATTACH = $attachID", __FILE__, __LINE__);
fatal_lang_error('smf124');
}
// Attempt to chmod it.
@chmod($destinationPath, 0644);
}
$_POST['avatar'] = '';
// Delete any temporary file.
if (file_exists($uploadDir . '/avatar_tmp_' . $memID))
@unlink($uploadDir . '/avatar_tmp_' . $memID);
}
// Selected the upload avatar option and had one already uploaded before or didn't upload one.
else
$_POST['avatar'] = '';
}
else
$_POST['avatar'] = '';
}
// View a summary.
function summary($memID)
{
global $context, $memberContext, $txt, $modSettings, $user_info, $user_profile, $sourcedir, $db_prefix, $scripturl;
// Attempt to load the member's profile data.
if (!loadMemberContext($memID) || !isset($memberContext[$memID]))
fatal_error($txt[453] . ' - ' . $memID, false);
// Set up the stuff and load the user.
$context += array(
'allow_hide_email' => !empty($modSettings['allow_hideEmail']),
'page_title' => $txt[92] . ' ' . $memberContext[$memID]['name'],
'can_send_pm' => allowedTo('pm_send'),
'can_have_buddy' => allowedTo('profile_identity_own') && !empty($modSettings['enable_buddylist']),
);
$context['member'] = &$memberContext[$memID];
// They haven't even been registered for a full day!?
$days_registered = (int) ((time() - $user_profile[$memID]['dateRegistered']) / (3600 * 24));
if (empty($user_profile[$memID]['dateRegistered']) || $days_registered < 1)
$context['member']['posts_per_day'] = $txt[470];
else
$context['member']['posts_per_day'] = comma_format($context['member']['real_posts'] / $days_registered, 3);
// Set the age...
if (empty($context['member']['birth_date']))
{
$context['member'] += array(
'age' => &$txt[470],
'today_is_birthday' => false
);
}
else
{
list ($birth_year, $birth_month, $birth_day) = sscanf($context['member']['birth_date'], '%d-%d-%d');
$datearray = getdate(forum_time());
$context['member'] += array(
'age' => $birth_year <= 4 ? $txt[470] : $datearray['year'] - $birth_year - (($datearray['mon'] > $birth_month || ($datearray['mon'] == $birth_month && $datearray['mday'] >= $birth_day)) ? 0 : 1),
'today_is_birthday' => $datearray['mon'] == $birth_month && $datearray['mday'] == $birth_day
);
}
if (allowedTo('moderate_forum'))
{
// Make sure it's a valid ip address; otherwise, don't bother...
if (preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $memberContext[$memID]['ip']) == 1 && empty($modSettings['disableHostnameLookup']))
$context['member']['hostname'] = host_from_ip($memberContext[$memID]['ip']);
else
$context['member']['hostname'] = '';
$context['can_see_ip'] = true;
}
else
$context['can_see_ip'] = false;
if (!empty($modSettings['who_enabled']))
{
include_once($sourcedir . '/Who.php');
$action = determineActions($user_profile[$memID]['url']);
if ($action !== false)
$context['member']['action'] = $action;
}
// If the user is awaiting activation, and the viewer has permission - setup some activation context messages.
if ($context['member']['is_activated'] % 10 != 1 && allowedTo('moderate_forum'))
{
$context['activate_type'] = $context['member']['is_activated'];
// What should the link text be?
$context['activate_link_text'] = in_array($context['member']['is_activated'], array(3, 4, 5, 13, 14, 15)) ? $txt['account_approve'] : $txt['account_activate'];
// Should we show a custom message?
$context['activate_message'] = isset($txt['account_activate_method_' . $context['member']['is_activated'] % 10]) ? $txt['account_activate_method_' . $context['member']['is_activated'] % 10] : $txt['account_not_activated'];
}
// How about, are they banned?
$context['member']['bans'] = array();
if (allowedTo('moderate_forum'))
{
// Can they edit the ban?
$context['can_edit_ban'] = allowedTo('manage_bans');
$ban_query = array();
$ban_query[] = "ID_MEMBER = " . $context['member']['id'];
// Valid IP?
if (preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $memberContext[$memID]['ip'], $ip_parts) == 1)
{
$ban_query[] = "(($ip_parts[1] BETWEEN bi.ip_low1 AND bi.ip_high1)
AND ($ip_parts[2] BETWEEN bi.ip_low2 AND bi.ip_high2)
AND ($ip_parts[3] BETWEEN bi.ip_low3 AND bi.ip_high3)
AND ($ip_parts[4] BETWEEN bi.ip_low4 AND bi.ip_high4))";
// Do we have a hostname already?
if (!empty($context['member']['hostname']))
$ban_query[] = "('" . addslashes($context['member']['hostname']) . "' LIKE hostname)";
}
// Use '255.255.255.255' for 'unknown' - it's not valid anyway.
elseif ($memberContext[$memID]['ip'] == 'unknown')
$ban_query[] = "(bi.ip_low1 = 255 AND bi.ip_high1 = 255
AND bi.ip_low2 = 255 AND bi.ip_high2 = 255
AND bi.ip_low3 = 255 AND bi.ip_high3 = 255
AND bi.ip_low4 = 255 AND bi.ip_high4 = 255)";
// Check their email as well...
if (strlen($context['member']['email']) != 0)
$ban_query[] = "('" . addslashes($context['member']['email']) . "' LIKE bi.email_address)";
// So... are they banned? Dying to know!
$request = db_query("
SELECT bg.ID_BAN_GROUP, bg.name, bg.cannot_access, bg.cannot_post, bg.cannot_register,
bg.cannot_login, bg.reason
FROM ({$db_prefix}ban_items AS bi, {$db_prefix}ban_groups AS bg)
WHERE bg.ID_BAN_GROUP = bi.ID_BAN_GROUP
AND (bg.expire_time IS NULL OR bg.expire_time > " . time() . ")
AND (" . implode(' OR ', $ban_query) . ')
GROUP BY bg.ID_BAN_GROUP', __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($request))
{
// Work out what restrictions we actually have.
$ban_restrictions = array();
foreach (array('access', 'register', 'login', 'post') as $type)
if ($row['cannot_' . $type])
$ban_restrictions[] = $txt['ban_type_' . $type];
// No actual ban in place?
if (empty($ban_restrictions))
continue;
// Prepare the link for context.
$ban_explanation = sprintf($txt['user_cannot_due_to'], implode(', ', $ban_restrictions), '' . $row['name'] . '');
$context['member']['bans'][] = array(
'reason' => empty($row['reason']) ? '' : '
' . $txt['ban_reason'] . ': ' . $row['reason'],
'cannot' => array(
'access' => !empty($row['cannot_access']),
'register' => !empty($row['cannot_register']),
'post' => !empty($row['cannot_post']),
'login' => !empty($row['cannot_login']),
),
'explanation' => $ban_explanation,
);
}
mysql_free_result($request);
}
}
// Show all posts by the current user
function showPosts($memID)
{
global $txt, $user_info, $scripturl, $modSettings, $db_prefix;
global $context, $user_profile, $ID_MEMBER, $sourcedir;
// If just deleting a message, do it and then redirect back.
if (isset($_GET['delete']))
{
checkSession('get');
// We can be lazy, since removeMessage() will check the permissions for us.
require_once($sourcedir . '/RemoveTopic.php');
removeMessage((int) $_GET['delete']);
// Back to... where we are now ;).
redirectexit('action=profile;u=' . $memID . ';sa=showPosts;start=' . $_GET['start']);
}
// Is the load average too high to allow searching just now?
if (!empty($context['load_average']) && !empty($modSettings['loadavg_show_posts']) && $context['load_average'] >= $modSettings['loadavg_show_posts'])
fatal_lang_error('loadavg_show_posts_disabled', false);
// Default to 10.
if (empty($_REQUEST['viewscount']) || !is_numeric($_REQUEST['viewscount']))
$_REQUEST['viewscount'] = '10';
$request = db_query("
SELECT COUNT(*)
FROM ({$db_prefix}messages AS m, {$db_prefix}boards AS b)
WHERE m.ID_MEMBER = $memID
AND b.ID_BOARD = m.ID_BOARD
AND $user_info[query_see_board]", __FILE__, __LINE__);
list ($msgCount) = mysql_fetch_row($request);
mysql_free_result($request);
$request = db_query("
SELECT MIN(ID_MSG), MAX(ID_MSG)
FROM {$db_prefix}messages AS m
WHERE m.ID_MEMBER = $memID", __FILE__, __LINE__);
list ($min_msg_member, $max_msg_member) = mysql_fetch_row($request);
mysql_free_result($request);
$reverse = false;
$range_limit = '';
$maxIndex = (int) $modSettings['defaultMaxMessages'];
// Make sure the starting place makes sense and construct our friend the page index.
$context['start'] = (int) $_REQUEST['start'];
$context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';sa=showPosts', $context['start'], $msgCount, $maxIndex);
$context['current_page'] = $context['start'] / $maxIndex;
$context['current_member'] = $memID;
// Reverse the query if we're past 50% of the pages for better performance.
$start = $context['start'];
$reverse = $_REQUEST['start'] > $msgCount / 2;
if ($reverse)
{
$maxIndex = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 && $msgCount > $context['start'] ? $msgCount - $context['start'] : (int) $modSettings['defaultMaxMessages'];
$start = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 || $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] ? 0 : $msgCount - $context['start'] - $modSettings['defaultMaxMessages'];
}
// Guess the range of messages to be shown.
if ($msgCount > 1000)
{
$margin = floor(($max_msg_member - $min_msg_member) * (($start + $modSettings['defaultMaxMessages']) / $msgCount) + .1 * ($max_msg_member - $min_msg_member));
$range_limit = $reverse ? 'ID_MSG < ' . ($min_msg_member + $margin) : 'ID_MSG > ' . ($max_msg_member - $margin);
}
$context['page_title'] = $txt[458] . ' ' . $user_profile[$memID]['realName'];
// Find this user's posts. The left join on categories somehow makes this faster, weird as it looks.
$looped = false;
while (true)
{
$request = db_query("
SELECT
b.ID_BOARD, b.name AS bname, c.ID_CAT, c.name AS cname, m.ID_TOPIC, m.ID_MSG,
t.ID_MEMBER_STARTED, t.ID_FIRST_MSG, t.ID_LAST_MSG, m.body, m.smileysEnabled,
m.subject, m.posterTime
FROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t, {$db_prefix}boards AS b)
LEFT JOIN {$db_prefix}categories AS c ON (c.ID_CAT = b.ID_CAT)
WHERE m.ID_MEMBER = $memID
AND m.ID_TOPIC = t.ID_TOPIC
AND t.ID_BOARD = b.ID_BOARD" . (empty($range_limit) ? '' : "
AND $range_limit") . "
AND $user_info[query_see_board]
ORDER BY m.ID_MSG " . ($reverse ? 'ASC' : 'DESC') . "
LIMIT $start, $maxIndex", __FILE__, __LINE__);
// Make sure we quit this loop.
if (mysql_num_rows($request) === $maxIndex || $looped)
break;
$looped = true;
$range_limit = '';
}
// Start counting at the number of the first message displayed.
$counter = $reverse ? $context['start'] + $maxIndex + 1 : $context['start'];
$context['posts'] = array();
$board_ids = array('own' => array(), 'any' => array());
while ($row = mysql_fetch_assoc($request))
{
// Censor....
censorText($row['body']);
censorText($row['subject']);
// Do the code.
$row['body'] = parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']);
// And the array...
$context['posts'][$counter += $reverse ? -1 : 1] = array(
'body' => $row['body'],
'counter' => $counter,
'category' => array(
'name' => $row['cname'],
'id' => $row['ID_CAT']
),
'board' => array(
'name' => $row['bname'],
'id' => $row['ID_BOARD']
),
'topic' => $row['ID_TOPIC'],
'subject' => $row['subject'],
'start' => 'msg' . $row['ID_MSG'],
'time' => timeformat($row['posterTime']),
'timestamp' => forum_time(true, $row['posterTime']),
'id' => $row['ID_MSG'],
'can_reply' => false,
'can_mark_notify' => false,
'can_delete' => false,
'delete_possible' => ($row['ID_FIRST_MSG'] != $row['ID_MSG'] || $row['ID_LAST_MSG'] == $row['ID_MSG']) && (empty($modSettings['edit_disable_time']) || $row['posterTime'] + $modSettings['edit_disable_time'] * 60 >= time()),
);
if ($ID_MEMBER == $row['ID_MEMBER_STARTED'])
$board_ids['own'][$row['ID_BOARD']][] = $counter;
$board_ids['any'][$row['ID_BOARD']][] = $counter;
}
mysql_free_result($request);
// All posts were retrieved in reverse order, get them right again.
if ($reverse)
$context['posts'] = array_reverse($context['posts'], true);
// These are all the permissions that are different from board to board..
$permissions = array(
'own' => array(
'post_reply_own' => 'can_reply',
'delete_own' => 'can_delete',
),
'any' => array(
'post_reply_any' => 'can_reply',
'mark_any_notify' => 'can_mark_notify',
'delete_any' => 'can_delete',
)
);
// For every permission in the own/any lists...
foreach ($permissions as $type => $list)
{
foreach ($list as $permission => $allowed)
{
// Get the boards they can do this on...
$boards = boardsAllowedTo($permission);
// Hmm, they can do it on all boards, can they?
if (!empty($boards) && $boards[0] == 0)
$boards = array_keys($board_ids[$type]);
// Now go through each board they can do the permission on.
foreach ($boards as $board_id)
{
// There aren't any posts displayed from this board.
if (!isset($board_ids[$type][$board_id]))
continue;
// Set the permission to true ;).
foreach ($board_ids[$type][$board_id] as $counter)
$context['posts'][$counter][$allowed] = true;
}
}
}
// Clean up after posts that cannot be deleted.
foreach ($context['posts'] as $counter => $dummy)
$context['posts'][$counter]['can_delete'] &= $context['posts'][$counter]['delete_possible'];
}
// Show all the users buddies, as well as a add/delete interface.
function editBuddies($memID)
{
global $txt, $scripturl, $modSettings, $db_prefix;
global $context, $user_profile, $memberContext, $func;
// Do a quick check to ensure people aren't getting here illegally!
if (!$context['user']['is_owner'] || empty($modSettings['enable_buddylist']))
fatal_lang_error(1, false);
// !!! No page_title.
// For making changes!
$buddiesArray = explode(',', $user_profile[$memID]['buddy_list']);
foreach ($buddiesArray as $k => $dummy)
if ($dummy == '')
unset($buddiesArray[$k]);
// Removing a buddy?
if (isset($_GET['remove']))
{
// Heh, I'm lazy, do it the easy way...
foreach ($buddiesArray as $key => $buddy)
if ($buddy == (int) $_GET['remove'])
unset($buddiesArray[$key]);
// Make the changes.
$user_profile[$memID]['buddy_list'] = implode(',', $buddiesArray);
updateMemberData($memID, array('buddy_list' => "'" . $user_profile[$memID]['buddy_list'] . "'"));
// Redirect off the page because we don't like all this ugly query stuff to stick in the history.
redirectexit('action=profile;u=' . $memID . ';sa=editBuddies');
}
elseif (isset($_POST['new_buddy']))
{
// Prepare the string for extraction...
$_POST['new_buddy'] = strtr(addslashes($func['htmlspecialchars'](stripslashes($_POST['new_buddy']), ENT_QUOTES)), array('"' => '"'));
preg_match_all('~"([^"]+)"~', $_POST['new_buddy'], $matches);
$new_buddies = array_unique(array_merge($matches[1], explode(',', preg_replace('~"([^"]+)"~', '', $_POST['new_buddy']))));
foreach ($new_buddies as $k => $dummy)
{
$new_buddies[$k] = strtr(trim($new_buddies[$k]), array('\\\'' => '''));
if (strlen($new_buddies[$k]) == 0)
unset($new_buddies[$k]);
}
if (!empty($new_buddies))
{
// Now find out the ID_MEMBER of the buddy.
$request = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE memberName IN ('" . implode("','", $new_buddies) . "') OR realName IN ('" . implode("','", $new_buddies) . "')
LIMIT " . count($new_buddies), __FILE__, __LINE__);
// Add the new member to the buddies array.
while ($row = mysql_fetch_assoc($request))
$buddiesArray[] = (int) $row['ID_MEMBER'];
mysql_free_result($request);
// Now update the current users buddy list.
$user_profile[$memID]['buddy_list'] = implode(',', $buddiesArray);
updateMemberData($memID, array('buddy_list' => "'" . $user_profile[$memID]['buddy_list'] . "'"));
}
// Back to the buddy list!
redirectexit('action=profile;u=' . $memID . ';sa=editBuddies');
}
// Get all the users "buddies"...
$buddies = array();
if (!empty($buddiesArray))
{
$result = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE ID_MEMBER IN (" . implode(', ', $buddiesArray) . ")
ORDER BY realName
LIMIT " . (substr_count($user_profile[$memID]['buddy_list'], ',') + 1), __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($result))
$buddies[] = $row['ID_MEMBER'];
mysql_free_result($result);
}
$context['buddy_count'] = count($buddies);
// Load all the members up.
loadMemberData($buddies, false, 'profile');
// Setup the context for each buddy.
$context['buddies'] = array();
foreach ($buddies as $buddy)
{
loadMemberContext($buddy);
$context['buddies'][$buddy] = $memberContext[$buddy];
}
}
function statPanel($memID)
{
global $txt, $scripturl, $db_prefix, $context, $user_profile, $user_info, $modSettings;
$context['page_title'] = $txt['statPanel_showStats'] . ' ' . $user_profile[$memID]['realName'];
// General user statistics.
$timeDays = floor($user_profile[$memID]['totalTimeLoggedIn'] / 86400);
$timeHours = floor(($user_profile[$memID]['totalTimeLoggedIn'] % 86400) / 3600);
$context['time_logged_in'] = ($timeDays > 0 ? $timeDays . $txt['totalTimeLogged2'] : '') . ($timeHours > 0 ? $timeHours . $txt['totalTimeLogged3'] : '') . floor(($user_profile[$memID]['totalTimeLoggedIn'] % 3600) / 60) . $txt['totalTimeLogged4'];
$context['num_posts'] = comma_format($user_profile[$memID]['posts']);
// Number of topics started.
// !!!SLOW This query is sorta slow...
$result = db_query("
SELECT COUNT(*)
FROM {$db_prefix}topics
WHERE ID_MEMBER_STARTED = $memID" . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? "
AND ID_BOARD != $modSettings[recycle_board]" : ''), __FILE__, __LINE__);
list ($context['num_topics']) = mysql_fetch_row($result);
mysql_free_result($result);
// Number polls started.
$result = db_query("
SELECT COUNT(*)
FROM {$db_prefix}topics
WHERE ID_MEMBER_STARTED = $memID" . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? "
AND ID_BOARD != $modSettings[recycle_board]" : '') . "
AND ID_POLL != 0", __FILE__, __LINE__);
list ($context['num_polls']) = mysql_fetch_row($result);
mysql_free_result($result);
// Number polls voted in.
$result = db_query("
SELECT COUNT(DISTINCT ID_POLL)
FROM {$db_prefix}log_polls
WHERE ID_MEMBER = $memID", __FILE__, __LINE__);
list ($context['num_votes']) = mysql_fetch_row($result);
mysql_free_result($result);
// Format the numbers...
$context['num_topics'] = comma_format($context['num_topics']);
$context['num_polls'] = comma_format($context['num_polls']);
$context['num_votes'] = comma_format($context['num_votes']);
// Grab the board this member posted in most often.
$result = db_query("
SELECT
b.ID_BOARD, b.name, b.numPosts, COUNT(*) AS messageCount
FROM ({$db_prefix}messages AS m, {$db_prefix}boards AS b)
WHERE m.ID_MEMBER = $memID
AND b.ID_BOARD = m.ID_BOARD
AND $user_info[query_see_board]
GROUP BY b.ID_BOARD
ORDER BY messageCount DESC
LIMIT 10", __FILE__, __LINE__);
$context['popular_boards'] = array();
$maxPosts = 0;
while ($row = mysql_fetch_assoc($result))
{
if ($row['messageCount'] > $maxPosts)
$maxPosts = $row['messageCount'];
$context['popular_boards'][$row['ID_BOARD']] = array(
'id' => $row['ID_BOARD'],
'posts' => $row['messageCount'],
'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
'link' => '' . $row['name'] . '',
'posts_percent' => 0,
'total_posts' => $row['numPosts'],
);
}
mysql_free_result($result);
// Now that we know the total, calculate the percentage.
foreach ($context['popular_boards'] as $ID_BOARD => $board_data)
$context['popular_boards'][$ID_BOARD]['posts_percent'] = $board_data['total_posts'] == 0 ? 0 : comma_format(($board_data['posts'] * 100) / $board_data['total_posts'], 2);
// Now get the 10 boards this user has most often participated in.
$result = db_query("
SELECT
b.ID_BOARD, b.name, IF(COUNT(*) > b.numPosts, 1, COUNT(*) / b.numPosts) * 100 AS percentage
FROM ({$db_prefix}messages AS m, {$db_prefix}boards AS b)
WHERE m.ID_MEMBER = $memID
AND b.ID_BOARD = m.ID_BOARD
AND $user_info[query_see_board]
GROUP BY b.ID_BOARD
ORDER BY percentage DESC
LIMIT 10", __FILE__, __LINE__);
$context['board_activity'] = array();
while ($row = mysql_fetch_assoc($result))
{
$context['board_activity'][$row['ID_BOARD']] = array(
'id' => $ID_BOARD,
'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
'link' => '' . $row['name'] . '',
'percent' => $row['percentage'],
);
}
mysql_free_result($result);
// Posting activity by time.
$result = db_query("
SELECT
HOUR(FROM_UNIXTIME(posterTime + " . (($user_info['time_offset'] + $modSettings['time_offset']) * 3600) . ")) AS hour,
COUNT(*) AS postCount
FROM {$db_prefix}messages
WHERE ID_MEMBER = $memID" . ($modSettings['totalMessages'] > 100000 ? "
AND ID_TOPIC > " . ($modSettings['totalTopics'] - 10000) : '') . "
GROUP BY hour", __FILE__, __LINE__);
$maxPosts = 0;
$context['posts_by_time'] = array();
while ($row = mysql_fetch_assoc($result))
{
if ($row['postCount'] > $maxPosts)
$maxPosts = $row['postCount'];
$context['posts_by_time'][$row['hour']] = array(
'hour' => $row['hour'],
'posts_percent' => $row['postCount']
);
}
mysql_free_result($result);
if ($maxPosts > 0)
for ($hour = 0; $hour < 24; $hour++)
{
if (!isset($context['posts_by_time'][$hour]))
$context['posts_by_time'][$hour] = array(
'hour' => $hour,
'posts_percent' => 0,
);
else
$context['posts_by_time'][$hour]['posts_percent'] = round(($context['posts_by_time'][$hour]['posts_percent'] * 100) / $maxPosts);
}
// Put it in the right order.
ksort($context['posts_by_time']);
}
function trackUser($memID)
{
global $scripturl, $txt, $db_prefix, $modSettings;
global $user_profile, $context;
// Verify if the user has sufficient permissions.
isAllowedTo('moderate_forum');
$context['page_title'] = $txt['trackUser'] . ' - ' . $user_profile[$memID]['realName'];
$context['last_ip'] = $user_profile[$memID]['memberIP'];
$context['member']['name'] = $user_profile[$memID]['realName'];
// If this is a big forum, or a large posting user, let's limit the search.
if ($modSettings['totalMessages'] > 50000 && $user_profile[$memID]['posts'] > 500)
{
$request = db_query("
SELECT MAX(ID_MSG)
FROM {$db_prefix}messages AS m
WHERE m.ID_MEMBER = $memID", __FILE__, __LINE__);
list ($max_msg_member) = mysql_fetch_row($request);
mysql_free_result($request);
// There's no point worrying ourselves with messages made yonks ago, just get recent ones!
$min_msg_member = max(0, $max_msg_member - $user_profile[$memID]['posts'] * 3);
}
// Default to at least the ones we know about.
$ips = array(
$user_profile[$memID]['memberIP'],
$user_profile[$memID]['memberIP2'],
);
// Get all IP addresses this user has used for his messages.
$request = db_query("
SELECT posterIP
FROM {$db_prefix}messages
WHERE ID_MEMBER = $memID
" . (isset($min_msg_member) ? "
AND ID_MSG >= $min_msg_member AND ID_MSG <= $max_msg_member" : '') . "
GROUP BY posterIP", __FILE__, __LINE__);
$context['ips'] = array();
while ($row = mysql_fetch_assoc($request))
{
$context['ips'][] = '' . $row['posterIP'] . '';
$ips[] = $row['posterIP'];
}
mysql_free_result($request);
// Now also get the IP addresses from the error messages.
$request = db_query("
SELECT COUNT(*) AS errorCount, ip
FROM {$db_prefix}log_errors
WHERE ID_MEMBER = $memID
GROUP BY ip", __FILE__, __LINE__);
$context['error_ips'] = array();
$totalErrors = 0;
while ($row = mysql_fetch_assoc($request))
{
$context['error_ips'][] = '' . $row['ip'] . '';
$ips[] = $row['ip'];
$totalErrors += $row['errorCount'];
}
mysql_free_result($request);
// Create the page indexes.
$context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';sa=trackUser', $_REQUEST['start'], $totalErrors, 20);
$context['start'] = $_REQUEST['start'];
// Get a list of error messages from this ip (range).
$request = db_query("
SELECT
le.logTime, le.ip, le.url, le.message, IFNULL(mem.ID_MEMBER, 0) AS ID_MEMBER,
IFNULL(mem.realName, '$txt[28]') AS display_name, mem.memberName
FROM {$db_prefix}log_errors AS le
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = le.ID_MEMBER)
WHERE le.ID_MEMBER = $memID
ORDER BY le.ID_ERROR DESC
LIMIT $context[start], 20", __FILE__, __LINE__);
$context['error_messages'] = array();
while ($row = mysql_fetch_assoc($request))
$context['error_messages'][] = array(
'ip' => $row['ip'],
'message' => strtr($row['message'], array('<span class="remove">' => '', '</span>' => '')),
'url' => $row['url'],
'time' => timeformat($row['logTime']),
'timestamp' => forum_time(true, $row['logTime'])
);
mysql_free_result($request);
// Find other users that might use the same IP.
$ips = array_unique($ips);
$context['members_in_range'] = array();
if (!empty($ips))
{
$request = db_query("
SELECT ID_MEMBER, realName
FROM {$db_prefix}members
WHERE ID_MEMBER != $memID
AND memberIP IN ('" . implode("', '", $ips) . "')", __FILE__, __LINE__);
if (mysql_num_rows($request) > 0)
while ($row = mysql_fetch_assoc($request))
$context['members_in_range'][$row['ID_MEMBER']] = '' . $row['realName'] . '';
mysql_free_result($request);
$request = db_query("
SELECT mem.ID_MEMBER, mem.realName
FROM ({$db_prefix}messages AS m, {$db_prefix}members AS mem)
WHERE mem.ID_MEMBER = m.ID_MEMBER
AND mem.ID_MEMBER != $memID
AND m.posterIP IN ('" . implode("', '", $ips) . "')", __FILE__, __LINE__);
if (mysql_num_rows($request) > 0)
while ($row = mysql_fetch_assoc($request))
$context['members_in_range'][$row['ID_MEMBER']] = '' . $row['realName'] . '';
mysql_free_result($request);
}
}
function TrackIP($memID = 0)
{
global $user_profile, $scripturl, $txt, $user_info;
global $db_prefix, $context;
// Can the user do this?
isAllowedTo('moderate_forum');
if ($memID == 0)
{
$context['ip'] = isset($_REQUEST['searchip']) ? trim($_REQUEST['searchip']) : $user_info['ip'];
loadTemplate('Profile');
loadLanguage('Profile');
$context['sub_template'] = 'trackIP';
$context['page_title'] = $txt[79];
}
else
$context['ip'] = $user_profile[$memID]['memberIP'];
if (preg_match('/^\d{1,3}\.(\d{1,3}|\*)\.(\d{1,3}|\*)\.(\d{1,3}|\*)$/', $context['ip']) == 0)
fatal_error($txt['invalid_ip'], false);
$dbip = str_replace('*', '%', $context['ip']);
$dbip = strpos($dbip, '%') === false ? "= '$dbip'" : "LIKE '$dbip'";
$context['page_title'] = $txt['trackIP'] . ' - ' . $context['ip'];
// Get some totals for pagination.
$request = db_query("
SELECT COUNT(*)
FROM {$db_prefix}messages AS m
INNER JOIN {$db_prefix}boards AS b ON (b.ID_BOARD = m.ID_BOARD)
WHERE $user_info[query_see_board]
AND m.posterIP $dbip", __FILE__, __LINE__);
list ($totalMessages) = mysql_fetch_row($request);
mysql_free_result($request);
$request = db_query("
SELECT COUNT(*)
FROM {$db_prefix}log_errors
WHERE ip $dbip", __FILE__, __LINE__);
list ($totalErrors) = mysql_fetch_row($request);
mysql_free_result($request);
$context['message_start'] = isset($_GET['mesStart']) ? (int) $_GET['mesStart'] : 0;
$context['error_start'] = isset($_GET['errStart']) ? $_GET['errStart'] : 0;
$context['message_page_index'] = constructPageIndex($scripturl . '?action=' . ($memID == 0 ? 'trackip;searchip=' . $context['ip'] : 'profile;u=' . $memID . ';sa=trackIP') . ';mesStart=%d;errStart=' . $context['error_start'], $context['message_start'], $totalMessages, 20, true);
$context['error_page_index'] = constructPageIndex($scripturl . '?action=' . ($memID == 0 ? 'trackip;searchip=' . $context['ip'] : 'profile;u=' . $memID . ';sa=trackIP') . ';mesStart=' . $context['message_start'] . ';errStart=%d', $context['error_start'], $totalErrors, 20, true);
$request = db_query("
SELECT ID_MEMBER, realName AS display_name, memberIP
FROM {$db_prefix}members
WHERE memberIP $dbip", __FILE__, __LINE__);
$context['ips'] = array();
while ($row = mysql_fetch_assoc($request))
$context['ips'][$row['memberIP']][] = '' . $row['display_name'] . '';
mysql_free_result($request);
ksort($context['ips']);
// !!!SLOW This query is using a filesort.
$request = db_query("
SELECT
m.ID_MSG, m.posterIP, IFNULL(mem.realName, m.posterName) AS display_name, mem.ID_MEMBER,
m.subject, m.posterTime, m.ID_TOPIC, m.ID_BOARD
FROM {$db_prefix}messages AS m
INNER JOIN {$db_prefix}boards AS b ON (b.ID_BOARD = m.ID_BOARD)
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE $user_info[query_see_board]
AND m.posterIP $dbip
ORDER BY m.ID_MSG DESC
LIMIT $context[message_start], 20", __FILE__, __LINE__);
$context['messages'] = array();
while ($row = mysql_fetch_assoc($request))
$context['messages'][] = array(
'ip' => $row['posterIP'],
'member' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['display_name'],
'href' => $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
'link' => empty($row['ID_MEMBER']) ? $row['display_name'] : '' . $row['display_name'] . ''
),
'board' => array(
'id' => $row['ID_BOARD'],
'href' => $scripturl . '?board=' . $row['ID_BOARD']
),
'topic' => $row['ID_TOPIC'],
'id' => $row['ID_MSG'],
'subject' => $row['subject'],
'time' => timeformat($row['posterTime']),
'timestamp' => forum_time(true, $row['posterTime'])
);
mysql_free_result($request);
// !!!SLOW This query is using a filesort.
$request = db_query("
SELECT
le.logTime, le.ip, le.url, le.message, IFNULL(mem.ID_MEMBER, 0) AS ID_MEMBER,
IFNULL(mem.realName, '$txt[28]') AS display_name, mem.memberName
FROM {$db_prefix}log_errors AS le
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = le.ID_MEMBER)
WHERE le.ip $dbip
ORDER BY le.ID_ERROR DESC
LIMIT $context[error_start], 20", __FILE__, __LINE__);
$context['error_messages'] = array();
while ($row = mysql_fetch_assoc($request))
$context['error_messages'][] = array(
'ip' => $row['ip'],
'member' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['display_name'],
'href' => $row['ID_MEMBER'] > 0 ? $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] : '',
'link' => $row['ID_MEMBER'] > 0 ? '' . $row['display_name'] . '' : $row['display_name']
),
'message' => strtr($row['message'], array('<span class="remove">' => '', '</span>' => '')),
'url' => $row['url'],
'error_time' => timeformat($row['logTime'])
);
mysql_free_result($request);
$context['single_ip'] = strpos($context['ip'], '*') === false;
if ($context['single_ip'])
{
$context['whois_servers'] = array(
'afrinic' => array(
'name' => &$txt['whois_afrinic'],
'url' => 'http://www.afrinic.net/cgi-bin/whois?searchtext=' . $context['ip'],
'range' => array(),
),
'apnic' => array(
'name' => &$txt['whois_apnic'],
'url' => 'http://wq.apnic.net/apnic-bin/whois.pl?searchtext=' . $context['ip'],
'range' => array(58, 59, 60, 61, 124, 125, 126, 202, 203, 210, 211, 218, 219, 220, 221, 222),
),
'arin' => array(
'name' => &$txt['whois_arin'],
'url' => 'http://ws.arin.net/whois/?queryinput=' . $context['ip'],
'range' => array(63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 199, 204, 205, 206, 207, 208, 209, 216),
),
'lacnic' => array(
'name' => &$txt['whois_lacnic'],
'url' => 'http://lacnic.net/cgi-bin/lacnic/whois?query=' . $context['ip'],
'range' => array(200, 201),
),
'ripe' => array(
'name' => &$txt['whois_ripe'],
'url' => 'http://www.db.ripe.net/whois?searchtext=' . $context['ip'],
'range' => array(62, 80, 81, 82, 83, 84, 85, 86, 87, 88, 193, 194, 195, 212, 213, 217),
),
);
foreach ($context['whois_servers'] as $whois)
{
// Strip off the "decimal point" and anything following...
if (in_array((int) $context['ip'], $whois['range']))
$context['auto_whois_server'] = $whois;
}
}
}
function showPermissions($memID)
{
global $scripturl, $txt, $db_prefix, $board, $modSettings;
global $user_profile, $context, $user_info;
// Verify if the user has sufficient permissions.
isAllowedTo('manage_permissions');
loadLanguage('ManagePermissions');
loadLanguage('Admin');
loadTemplate('ManageMembers');
$context['member']['id'] = $memID;
$context['member']['name'] = $user_profile[$memID]['realName'];
$context['page_title'] = $txt['showPermissions'];
$board = empty($board) ? 0 : (int) $board;
$context['board'] = $board;
// Determine which groups this user is in.
if (empty($user_profile[$memID]['additionalGroups']))
$curGroups = array();
else
$curGroups = explode(',', $user_profile[$memID]['additionalGroups']);
$curGroups[] = $user_profile[$memID]['ID_GROUP'];
$curGroups[] = $user_profile[$memID]['ID_POST_GROUP'];
// Load a list of boards for the jump box (but only those that have separate local permissions).
$request = db_query("
SELECT b.ID_BOARD, b.name, b.permission_mode, b.memberGroups, b.permission_mode != 0 OR mods.ID_MEMBER IS NOT NULL AS show_board
FROM {$db_prefix}boards AS b
LEFT JOIN {$db_prefix}moderators AS mods ON (mods.ID_BOARD = b.ID_BOARD AND mods.ID_MEMBER = $memID)
WHERE $user_info[query_see_board]", __FILE__, __LINE__);
$context['boards'] = array();
$context['no_access_boards'] = array();
while ($row = mysql_fetch_assoc($request))
{
if (count(array_intersect($curGroups, explode(',', $row['memberGroups']))) === 0)
$context['no_access_boards'][] = array(
'id' => $row['ID_BOARD'],
'name' => $row['name'],
'is_last' => false,
);
elseif (!empty($row['show_board']))
$context['boards'][$row['ID_BOARD']] = array(
'id' => $row['ID_BOARD'],
'name' => $row['name'],
'selected' => $board == $row['ID_BOARD'],
'permission_mode' => $row['permission_mode'],
);
}
mysql_free_result($request);
if (!empty($context['no_access_boards']))
$context['no_access_boards'][count($context['no_access_boards']) - 1]['is_last'] = true;
$context['member']['permissions'] = array(
'general' => array(),
'board' => array()
);
// If you're an admin we know you can do everything, we might as well leave.
$context['member']['has_all_permissions'] = in_array(1, $curGroups);
if ($context['member']['has_all_permissions'])
return;
$denied = array();
// Get all general permissions.
$result = db_query("
SELECT p.permission, p.addDeny, mg.groupName, p.ID_GROUP
FROM {$db_prefix}permissions AS p
LEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = p.ID_GROUP)
WHERE p.ID_GROUP IN (" . implode(', ', $curGroups) . ")
ORDER BY p.addDeny DESC, p.permission, mg.minPosts, IF(mg.ID_GROUP < 4, mg.ID_GROUP, 4), mg.groupName", __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($result))
{
// We don't know about this permission, it doesn't exist :P.
if (!isset($txt['permissionname_' . $row['permission']]))
continue;
if (empty($row['addDeny']))
$denied[] = $row['permission'];
// Permissions that end with _own or _any consist of two parts.
if (in_array(substr($row['permission'], -4), array('_own', '_any')) && isset($txt['permissionname_' . substr($row['permission'], 0, -4)]))
$name = $txt['permissionname_' . substr($row['permission'], 0, -4)] . ' - ' . $txt['permissionname_' . $row['permission']];
else
$name = $txt['permissionname_' . $row['permission']];
// Add this permission if it doesn't exist yet.
if (!isset($context['member']['permissions']['general'][$row['permission']]))
$context['member']['permissions']['general'][$row['permission']] = array(
'id' => $row['permission'],
'groups' => array(
'allowed' => array(),
'denied' => array()
),
'name' => $name,
'is_denied' => false,
'is_global' => true,
);
// Add the membergroup to either the denied or the allowed groups.
$context['member']['permissions']['general'][$row['permission']]['groups'][empty($row['addDeny']) ? 'denied' : 'allowed'][] = $row['ID_GROUP'] == 0 ? $txt['membergroups_members'] : $row['groupName'];
// Once denied is always denied.
$context['member']['permissions']['general'][$row['permission']]['is_denied'] |= empty($row['addDeny']);
}
mysql_free_result($result);
$request = db_query("
SELECT
bp.addDeny, bp.permission, bp.ID_GROUP, mg.groupName" . (empty($board) ? '' : ',
b.permission_mode, IF(mods.ID_MEMBER IS NULL, 0, 1) AS is_moderator') . "
FROM ({$db_prefix}board_permissions AS bp" . (empty($board) ? ')' : ", {$db_prefix}boards AS b)
LEFT JOIN {$db_prefix}moderators AS mods ON (mods.ID_BOARD = b.ID_BOARD AND mods.ID_MEMBER = $memID)") . "
LEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = bp.ID_GROUP)
WHERE bp.ID_BOARD = " . (empty($modSettings['permission_enable_by_board']) || empty($board) ? '0' : 'IF(b.permission_mode = 1, b.ID_BOARD, 0)') . "
AND bp.ID_GROUP IN (" . implode(', ', $curGroups) . "" . (empty($board) ? ')' : ", 3)
AND b.ID_BOARD = $board
AND (mods.ID_MEMBER IS NOT NULL OR bp.ID_GROUP != 3)"), __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($request))
{
// We don't know about this permission, it doesn't exist :P.
if (!isset($txt['permissionname_' . $row['permission']]))
continue;
// Filter these special cases of board permissions out.
if (empty($modSettings['permission_enable_by_board']) && !empty($board) && $row['ID_GROUP'] != 3)
{
if (in_array($row['permission'], array('post_reply_own', 'post_reply_any')) && $row['permission_mode'] == 4)
continue;
elseif ($row['permission'] == 'post_new' && $row['permission_mode'] >= 3)
continue;
elseif ($row['permission'] == 'poll_post' && $row['permission_mode'] >= 2)
continue;
}
// The name of the permission using the format 'permission name' - 'own/any topic/event/etc.'.
if (in_array(substr($row['permission'], -4), array('_own', '_any')) && isset($txt['permissionname_' . substr($row['permission'], 0, -4)]))
$name = $txt['permissionname_' . substr($row['permission'], 0, -4)] . ' - ' . $txt['permissionname_' . $row['permission']];
else
$name = $txt['permissionname_' . $row['permission']];
// Create the structure for this permission.
if (!isset($context['member']['permissions']['board'][$row['permission']]))
$context['member']['permissions']['board'][$row['permission']] = array(
'id' => $row['permission'],
'groups' => array(
'allowed' => array(),
'denied' => array()
),
'name' => $name,
'is_denied' => false,
'is_global' => empty($board),
);
$context['member']['permissions']['board'][$row['permission']]['groups'][empty($row['addDeny']) ? 'denied' : 'allowed'][$row['ID_GROUP']] = $row['ID_GROUP'] == 0 ? $txt['membergroups_members'] : $row['groupName'];
$context['member']['permissions']['board'][$row['permission']]['is_denied'] |= empty($row['addDeny']);
}
mysql_free_result($request);
}
function account($memID)
{
global $context, $settings, $user_profile, $txt, $db_prefix;
global $scripturl, $membergroups, $modSettings, $language, $user_info;
global $func;
// Allow an administrator to edit the username?
$context['allow_edit_username'] = isset($_GET['changeusername']) && allowedTo('admin_forum');
// You might be allowed to only assign the membergroups, so let's check.
$context['allow_edit_membergroups'] = allowedTo('manage_membergroups');
$context['allow_edit_account'] = ($context['user']['is_owner'] && allowedTo('profile_identity_own')) || allowedTo('profile_identity_any');
// How about their email address... online status, and name?
$context['allow_hide_email'] = !empty($modSettings['allow_hideEmail']) || allowedTo('moderate_forum');
$context['allow_hide_online'] = !empty($modSettings['allow_hideOnline']) || allowedTo('moderate_forum');
$context['allow_edit_name'] = !empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum');
// Load up the existing contextual data.
$context['member'] += array(
'is_admin' => !empty($user_profile[$memID]['ID_GROUP']) && $user_profile[$memID]['ID_GROUP'] == 1,
'secret_question' => !isset($user_profile[$memID]['secretQuestion']) ? '' : $user_profile[$memID]['secretQuestion'],
);
// You need 'manage membergroups' permission for this.
if ($context['allow_edit_membergroups'])
{
$context['member_groups'] = array(
0 => array(
'id' => 0,
'name' => &$txt['no_primary_membergroup'],
'is_primary' => $user_profile[$memID]['ID_GROUP'] == 0,
'can_be_additional' => false,
)
);
$curGroups = explode(',', $user_profile[$memID]['additionalGroups']);
// Load membergroups, but only those groups the user can assign.
$request = db_query("
SELECT groupName, ID_GROUP
FROM {$db_prefix}membergroups
WHERE ID_GROUP != 3
AND minPosts = -1
ORDER BY minPosts, IF(ID_GROUP < 4, ID_GROUP, 4), groupName", __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($request))
{
// We should skip the administrator group if they don't have the admin_forum permission!
if ($row['ID_GROUP'] == 1 && !allowedTo('admin_forum'))
continue;
$context['member_groups'][$row['ID_GROUP']] = array(
'id' => $row['ID_GROUP'],
'name' => $row['groupName'],
'is_primary' => $user_profile[$memID]['ID_GROUP'] == $row['ID_GROUP'],
'is_additional' => in_array($row['ID_GROUP'], $curGroups),
'can_be_additional' => true,
);
}
mysql_free_result($request);
}
// Are languages user selectable? If so, get a list.
$context['languages'] = array();
if ($context['allow_edit_account'] && !empty($modSettings['userLanguage']))
{
// Select the default language if the user has no language selected yet.
$selectedLanguage = empty($user_profile[$memID]['lngfile']) ? $language : $user_profile[$memID]['lngfile'];
$language_directories = array(
$settings['default_theme_dir'] . '/languages',
$settings['actual_theme_dir'] . '/languages',
);
if (!empty($settings['base_theme_dir']))
$language_directories[] = $settings['base_theme_dir'] . '/languages';
$language_directories = array_unique($language_directories);
foreach ($language_directories as $language_dir)
{
if (!file_exists($language_dir))
continue;
$dir = dir($language_dir);
while ($entry = $dir->read())
{
// Each language file must *at least* have a 'index.LANGUAGENAME.php' file.
if (preg_match('~^index\.(.+)\.php$~', $entry, $matches) == 0)
continue;
$context['languages'][$matches[1]] = array(
'name' => $func['ucwords'](strtr($matches[1], array('_' => ' ', '-utf8' => ''))),
'selected' => $selectedLanguage == $matches[1],
'filename' => $matches[1],
);
}
$dir->close();
}
}
loadThemeOptions($memID);
}
function forumProfile($memID)
{
global $context, $user_profile;
global $user_info, $txt, $ID_MEMBER, $modSettings;
$context['avatar_url'] = $modSettings['avatar_url'];
$context['max_signature_length'] = $modSettings['max_signatureLength'];
$context['allow_edit_title'] = allowedTo('profile_title_any') || (allowedTo('profile_title_own') && $context['user']['is_owner']);
$context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new');
$context['member'] += array(
'birth_date' => empty($user_profile[$memID]['birthdate']) || $user_profile[$memID]['birthdate'] === '0001-01-01' ? '0000-00-00' : (substr($user_profile[$memID]['birthdate'], 0, 4) === '0004' ? '0000' . substr($user_profile[$memID]['birthdate'], 4) : $user_profile[$memID]['birthdate']),
'location' => !isset($user_profile[$memID]['location']) ? '' : $user_profile[$memID]['location'],
'title' => !isset($user_profile[$memID]['usertitle']) || $user_profile[$memID]['usertitle'] == '' ? '' : $user_profile[$memID]['usertitle'],
'blurb' => !isset($user_profile[$memID]['personalText']) ? '' : str_replace(array('<', '>', '''), array('<', '>', '''), $user_profile[$memID]['personalText']),
'signature' => !isset($user_profile[$memID]['signature']) ? '' : str_replace(array('
', '<', '>', '"', '\''), array("\n", '<', '>', '"', '''), $user_profile[$memID]['signature']),
);
// Split up the birthdate....
list ($uyear, $umonth, $uday) = explode('-', $context['member']['birth_date']);
$context['member']['birth_date'] = array(
'year' => $uyear,
'month' => $umonth,
'day' => $uday
);
if ($user_profile[$memID]['avatar'] == '' && $user_profile[$memID]['ID_ATTACH'] > 0 && $context['member']['avatar']['allow_upload'])
$context['member']['avatar'] += array(
'choice' => 'upload',
'server_pic' => 'blank.gif',
'external' => 'http://'
);
elseif (stristr($user_profile[$memID]['avatar'], 'http://') && $context['member']['avatar']['allow_external'])
$context['member']['avatar'] += array(
'choice' => 'external',
'server_pic' => 'blank.gif',
'external' => $user_profile[$memID]['avatar']
);
elseif (file_exists($modSettings['avatar_directory'] . '/' . $user_profile[$memID]['avatar']) && $context['member']['avatar']['allow_server_stored'])
$context['member']['avatar'] += array(
'choice' => 'server_stored',
'server_pic' => $user_profile[$memID]['avatar'] == '' ? 'blank.gif' : $user_profile[$memID]['avatar'],
'external' => 'http://'
);
else
$context['member']['avatar'] += array(
'choice' => 'server_stored',
'server_pic' => 'blank.gif',
'external' => 'http://'
);
// Get a list of all the avatars.
if ($context['member']['avatar']['allow_server_stored'])
{
$context['avatar_list'] = array();
$context['avatars'] = is_dir($modSettings['avatar_directory']) ? getAvatars('', 0) : array();
}
else
$context['avatars'] = array();
// Second level selected avatar...
$context['avatar_selected'] = substr(strrchr($context['member']['avatar']['server_pic'], '/'), 1);
loadThemeOptions($memID);
}
// Recursive function to retrieve avatar files
function getAvatars($directory, $level)
{
global $context, $txt, $modSettings;
$result = array();
// Open the directory..
$dir = dir($modSettings['avatar_directory'] . (!empty($directory) ? '/' : '') . $directory);
$dirs = array();
$files = array();
if (!$dir)
return array();
while ($line = $dir->read())
{
if (in_array($line, array('.', '..', 'blank.gif', 'index.php')))
continue;
if (is_dir($modSettings['avatar_directory'] . '/' . $directory . (!empty($directory) ? '/' : '') . $line))
$dirs[] = $line;
else
$files[] = $line;
}
$dir->close();
// Sort the results...
natcasesort($dirs);
natcasesort($files);
if ($level == 0)
{
$result[] = array(
'filename' => 'blank.gif',
'checked' => in_array($context['member']['avatar']['server_pic'], array('', 'blank.gif')),
'name' => &$txt[422],
'is_dir' => false
);
}
foreach ($dirs as $line)
{
$tmp = getAvatars($directory . (!empty($directory) ? '/' : '') . $line, $level + 1);
if (!empty($tmp))
$result[] = array(
'filename' => htmlspecialchars($line),
'checked' => strpos($context['member']['avatar']['server_pic'], $line . '/') !== false,
'name' => '[' . htmlspecialchars(str_replace('_', ' ', $line)) . ']',
'is_dir' => true,
'files' => $tmp
);
unset($tmp);
}
foreach ($files as $line)
{
$filename = substr($line, 0, (strlen($line) - strlen(strrchr($line, '.'))));
$extension = substr(strrchr($line, '.'), 1);
// Make sure it is an image.
if (strcasecmp($extension, 'gif') != 0 && strcasecmp($extension, 'jpg') != 0 && strcasecmp($extension, 'jpeg') != 0 && strcasecmp($extension, 'png') != 0 && strcasecmp($extension, 'bmp') != 0)
continue;
$result[] = array(
'filename' => htmlspecialchars($line),
'checked' => $line == $context['member']['avatar']['server_pic'],
'name' => htmlspecialchars(str_replace('_', ' ', $filename)),
'is_dir' => false
);
if ($level == 1)
$context['avatar_list'][] = $directory . '/' . $line;
}
return $result;
}
function theme($memID)
{
global $txt, $context, $user_profile, $db_prefix, $modSettings, $settings, $user_info;
$request = db_query("
SELECT value
FROM {$db_prefix}themes
WHERE ID_THEME = " . (int) $user_profile[$memID]['ID_THEME'] . "
AND variable = 'name'
LIMIT 1", __FILE__, __LINE__);
list ($name) = mysql_fetch_row($request);
mysql_free_result($request);
$context['member'] += array(
'theme' => array(
'id' => $user_profile[$memID]['ID_THEME'],
'name' => empty($user_profile[$memID]['ID_THEME']) ? $txt['theme_forum_default'] : $name
),
'smiley_set' => array(
'id' => empty($user_profile[$memID]['smileySet']) ? '' : $user_profile[$memID]['smileySet']
),
'time_format' => !isset($user_profile[$memID]['timeFormat']) ? '' : $user_profile[$memID]['timeFormat'],
'time_offset' => empty($user_profile[$memID]['timeOffset']) ? '0' : $user_profile[$memID]['timeOffset'],
);
$context['easy_timeformats'] = array(
array('format' => '', 'title' => $txt['timeformat_easy0']),
array('format' => '%B %d, %Y, %I:%M:%S %p', 'title' => $txt['timeformat_easy1']),
array('format' => '%B %d, %Y, %H:%M:%S', 'title' => $txt['timeformat_easy2']),
array('format' => '%Y-%m-%d, %H:%M:%S', 'title' => $txt['timeformat_easy3']),
array('format' => '%d %B %Y, %H:%M:%S', 'title' => $txt['timeformat_easy4']),
array('format' => '%d-%m-%Y, %H:%M:%S', 'title' => $txt['timeformat_easy5'])
);
$context['current_forum_time'] = timeformat(time() - $user_info['time_offset'] * 3600, false);
$context['current_forum_time_hour'] = (int) strftime('%H', forum_time(false));
$context['smiley_sets'] = explode(',', 'none,,' . $modSettings['smiley_sets_known']);
$set_names = explode("\n", $txt['smileys_none'] . "\n" . $txt['smileys_forum_board_default'] . "\n" . $modSettings['smiley_sets_names']);
foreach ($context['smiley_sets'] as $i => $set)
{
$context['smiley_sets'][$i] = array(
'id' => $set,
'name' => $set_names[$i],
'selected' => $set == $context['member']['smiley_set']['id']
);
if ($context['smiley_sets'][$i]['selected'])
$context['member']['smiley_set']['name'] = $set_names[$i];
}
loadThemeOptions($memID);
loadLanguage('Settings');
}
// Display the notifications and settings for changes.
function notification($memID)
{
global $txt, $db_prefix, $scripturl, $user_profile, $user_info, $context, $ID_MEMBER, $modSettings;
// All the boards with notification on..
$request = db_query("
SELECT b.ID_BOARD, b.name, IFNULL(lb.ID_MSG, 0) AS boardRead, b.ID_MSG_UPDATED
FROM ({$db_prefix}log_notify AS ln, {$db_prefix}boards AS b)
LEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = b.ID_BOARD AND lb.ID_MEMBER = $ID_MEMBER)
WHERE ln.ID_MEMBER = $memID
AND b.ID_BOARD = ln.ID_BOARD
AND $user_info[query_see_board]
ORDER BY b.boardOrder", __FILE__, __LINE__);
$context['board_notifications'] = array();
while ($row = mysql_fetch_assoc($request))
$context['board_notifications'][] = array(
'id' => $row['ID_BOARD'],
'name' => $row['name'],
'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
'link' => '' . $row['name'] . '',
'new' => $row['boardRead'] < $row['ID_MSG_UPDATED']
);
mysql_free_result($request);
$request = db_query("
SELECT COUNT(*)
FROM ({$db_prefix}log_notify AS ln, {$db_prefix}boards AS b, {$db_prefix}topics AS t)
WHERE ln.ID_MEMBER = $memID
AND t.ID_TOPIC = ln.ID_TOPIC
AND b.ID_BOARD = t.ID_BOARD
AND $user_info[query_see_board]", __FILE__, __LINE__);
list ($num_topics) = mysql_fetch_row($request);
mysql_free_result($request);
$context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';sa=notification', $_REQUEST['start'], $num_topics, $modSettings['defaultMaxMessages']);
// All the topics with notification on...
$request = db_query("
SELECT
IFNULL(lt.ID_MSG, IFNULL(lmr.ID_MSG, -1)) + 1 AS new_from, b.ID_BOARD, b.name,
t.ID_TOPIC, ms.subject, ms.ID_MEMBER, IFNULL(mem.realName, ms.posterName) AS realName,
ml.ID_MSG_MODIFIED
FROM ({$db_prefix}log_notify AS ln, {$db_prefix}boards AS b, {$db_prefix}topics AS t, {$db_prefix}messages AS ms, {$db_prefix}messages AS ml)
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = ms.ID_MEMBER)
LEFT JOIN {$db_prefix}log_topics AS lt ON (lt.ID_TOPIC = t.ID_TOPIC AND lt.ID_MEMBER = $ID_MEMBER)
LEFT JOIN {$db_prefix}log_mark_read AS lmr ON (lmr.ID_BOARD = b.ID_BOARD AND lmr.ID_MEMBER = $ID_MEMBER)
WHERE ln.ID_MEMBER = $memID
AND t.ID_TOPIC = ln.ID_TOPIC
AND ms.ID_MSG = t.ID_FIRST_MSG
AND ml.ID_MSG = t.ID_LAST_MSG
AND b.ID_BOARD = t.ID_BOARD
AND $user_info[query_see_board]
ORDER BY ms.ID_MSG DESC
LIMIT $_REQUEST[start], $modSettings[defaultMaxMessages]", __FILE__, __LINE__);
$context['topic_notifications'] = array();
while ($row = mysql_fetch_assoc($request))
{
censorText($row['subject']);
$context['topic_notifications'][] = array(
'id' => $row['ID_TOPIC'],
'poster' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['realName'],
'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
'link' => empty($row['ID_MEMBER']) ? $row['realName'] : '' . $row['realName'] . ''
),
'subject' => $row['subject'],
'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0',
'link' => '' . $row['subject'] . '',
'new' => $row['new_from'] <= $row['ID_MSG_MODIFIED'],
'new_from' => $row['new_from'],
'new_href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.msg' . $row['new_from'] . '#new',
'new_link' => '' . $row['subject'] . '',
'board' => array(
'id' => $row['ID_BOARD'],
'name' => $row['name'],
'href' => $scripturl . '?board=' . $row['ID_BOARD'] . '.0',
'link' => '' . $row['name'] . ''
)
);
}
mysql_free_result($request);
// What options are set?
$context['member'] += array(
'notify_announcements' => $user_profile[$memID]['notifyAnnouncements'],
'notify_once' => $user_profile[$memID]['notifyOnce'],
'notify_send_body' => $user_profile[$memID]['notifySendBody'],
'notify_types' => $user_profile[$memID]['notifyTypes'],
);
// How many rows can we expect?
$context['num_rows'] = array(
'topic' => count($context['topic_notifications']) + 3,
'board' => count($context['board_notifications']) + 2
);
loadThemeOptions($memID);
}
function pmprefs($memID)
{
global $txt, $user_profile, $db_prefix, $context, $db_prefix;
// Tell the template what they are....
$context['send_email'] = $user_profile[$memID]['pm_email_notify'];
if ($user_profile[$memID]['pm_ignore_list'] != '*')
{
$result = db_query("
SELECT realName
FROM {$db_prefix}members
WHERE FIND_IN_SET(ID_MEMBER, '" . $user_profile[$memID]['pm_ignore_list'] . "')
LIMIT " . (substr_count($user_profile[$memID]['pm_ignore_list'], ',') + 1), __FILE__, __LINE__);
$pm_ignore_list = '';
while ($row = mysql_fetch_assoc($result))
$pm_ignore_list .= "\n" . $row['realName'];
mysql_free_result($result);
$pm_ignore_list = substr($pm_ignore_list, 1);
}
else
$pm_ignore_list = '*';
// Get all their "buddies"...
$result = db_query("
SELECT realName
FROM {$db_prefix}members
WHERE FIND_IN_SET(ID_MEMBER, '" . $user_profile[$memID]['buddy_list'] . "')
LIMIT " . (substr_count($user_profile[$memID]['buddy_list'], ',') + 1), __FILE__, __LINE__);
$buddy_list = '';
while ($row = mysql_fetch_assoc($result))
$buddy_list .= "\n" . $row['realName'];
mysql_free_result($result);
$context['buddy_list'] = substr($buddy_list, 1);
$context['ignore_list'] = $pm_ignore_list;
$context['page_title'] = $txt['pmprefs'] . ': ' . $txt[144];
loadThemeOptions($memID);
}
// Present a screen to make sure the user wants to be deleted
function deleteAccount($memID)
{
global $txt, $context, $ID_MEMBER, $modSettings, $user_profile;
if (!$context['user']['is_owner'])
isAllowedTo('profile_remove_any');
elseif (!allowedTo('profile_remove_any'))
isAllowedTo('profile_remove_own');
// Permissions for removing stuff...
$context['can_delete_posts'] = !$context['user']['is_owner'] && allowedTo('moderate_forum');
// Can they do this, or will they need approval?
$context['needs_approval'] = $context['user']['is_owner'] && !empty($modSettings['approveAccountDeletion']) && !allowedTo('moderate_forum');
$context['page_title'] = $txt['deleteAccount'] . ': ' . $user_profile[$memID]['realName'];
}
function deleteAccount2($profile_vars, $post_errors, $memID)
{
global $ID_MEMBER, $user_info, $sourcedir, $context, $db_prefix, $user_profile, $modSettings;
// !!! Add a way to delete pms as well?
if (!$context['user']['is_owner'])
isAllowedTo('profile_remove_any');
elseif (!allowedTo('profile_remove_any'))
isAllowedTo('profile_remove_own');
checkSession();
$old_profile = &$user_profile[$memID];
// Too often, people remove/delete their own only account.
if (in_array(1, explode(',', $old_profile['additionalGroups'])) || $old_profile['ID_GROUP'] == 1)
{
// Are you allowed to administrate the forum, as they are?
isAllowedTo('admin_forum');
$request = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}members
WHERE (ID_GROUP = 1 OR FIND_IN_SET(1, additionalGroups))
AND ID_MEMBER != $memID
LIMIT 1", __FILE__, __LINE__);
list ($another) = mysql_fetch_row($request);
mysql_free_result($request);
if (empty($another))
fatal_lang_error('at_least_one_admin');
}
// This file is needed for the deleteMembers function.
require_once($sourcedir . '/Subs-Members.php');
// Do you have permission to delete others profiles, or is that your profile you wanna delete?
if ($memID != $ID_MEMBER)
{
isAllowedTo('profile_remove_any');
// Now, have you been naughty and need your posts deleting?
// !!! Should this check board permissions?
if ($_POST['remove_type'] != 'none' && allowedTo('moderate_forum'))
{
// Include RemoveTopics - essential for this type of work!
require_once($sourcedir . '/RemoveTopic.php');
// First off we delete any topics the member has started - if they wanted topics being done.
if ($_POST['remove_type'] == 'topics')
{
// Fetch all topics started by this user within the time period.
$request = db_query("
SELECT t.ID_TOPIC
FROM {$db_prefix}topics AS t
WHERE t.ID_MEMBER_STARTED = $memID", __FILE__, __LINE__);
$topicIDs = array();
while ($row = mysql_fetch_assoc($request))
$topicIDs[] = $row['ID_TOPIC'];
mysql_free_result($request);
// Actually remove the topics.
// !!! This needs to check permissions, but we'll let it slide for now because of moderate_forum already being had.
removeTopics($topicIDs);
}
// Now delete the remaining messages.
$request = db_query("
SELECT m.ID_MSG
FROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t)
WHERE m.ID_MEMBER = $memID
AND m.ID_TOPIC = t.ID_TOPIC
AND t.ID_FIRST_MSG != m.ID_MSG", __FILE__, __LINE__);
// This could take a while... but ya know it's gonna be worth it in the end.
while ($row = mysql_fetch_assoc($request))
removeMessage($row['ID_MSG']);
mysql_free_result($request);
}
// Only delete this poor members account if they are actually being booted out of camp.
if (isset($_POST['deleteAccount']))
deleteMembers($memID);
}
// Do they need approval to delete?
elseif (empty($post_errors) && !empty($modSettings['approveAccountDeletion']) && !allowedTo('moderate_forum'))
{
// Setup their account for deletion ;)
updateMemberData($memID, array('is_activated' => 4));
// Another account needs approval...
updateSettings(array('unapprovedMembers' => true), true);
}
// Also check if you typed your password correctly.
elseif (empty($post_errors))
deleteMembers($memID);
}
// This function 'remembers' the profile changes a user made after erronious input.
function rememberPostData()
{
global $context, $scripturl, $txt, $modSettings, $ID_MEMBER, $user_profile, $user_info;
// Overwrite member settings with the ones you selected.
$context['member'] = array(
'is_owner' => $_REQUEST['userID'] == $ID_MEMBER,
'username' => $user_profile[$_REQUEST['userID']]['memberName'],
'name' => !isset($_POST['realName']) || $_POST['realName'] == '' ? $user_profile[$_REQUEST['userID']]['memberName'] : stripslashes($_POST['realName']),
'id' => (int) $_REQUEST['userID'],
'title' => !isset($_POST['usertitle']) || $_POST['usertitle'] == '' ? '' : stripslashes($_POST['usertitle']),
'email' => isset($_POST['emailAddress']) ? $_POST['emailAddress'] : '',
'hide_email' => empty($_POST['hideEmail']) ? 0 : 1,
'show_online' => empty($_POST['showOnline']) ? 0 : 1,
'registered' => empty($_POST['dateRegistered']) || $_POST['dateRegistered'] == '0001-01-01' ? $txt[470] : strftime('%Y-%m-%d', $_POST['dateRegistered']),
'blurb' => !isset($_POST['personalText']) ? '' : str_replace(array('<', '>', '''), array('<', '>', '''), stripslashes($_POST['personalText'])),
'gender' => array(
'name' => empty($_POST['gender']) ? '' : ($_POST['gender'] == 2 ? 'f' : 'm')
),
'website' => array(
'title' => !isset($_POST['websiteTitle']) ? '' : stripslashes($_POST['websiteTitle']),
'url' => !isset($_POST['websiteUrl']) ? '' : stripslashes($_POST['websiteUrl']),
),
'birth_date' => array(
'month' => empty($_POST['bday1']) ? '00' : (int) $_POST['bday1'],
'day' => empty($_POST['bday2']) ? '00' : (int) $_POST['bday2'],
'year' => empty($_POST['bday3']) ? '0000' : (int) $_POST['bday3']
),
'signature' => !isset($_POST['signature']) ? '' : str_replace(array('<', '>'), array('<', '>'), $_POST['signature']),
'location' => !isset($_POST['location']) ? '' : stripslashes($_POST['location']),
'icq' => array(
'name' => !isset($_POST['icq']) ? '' : stripslashes($_POST['ICQ'])
),
'aim' => array(
'name' => empty($_POST['aim']) ? '' : str_replace('+', ' ', $_POST['AIM'])
),
'yim' => array(
'name' => empty($_POST['yim']) ? '' : stripslashes($_POST['YIM'])
),
'msn' => array(
'name' => empty($_POST['msn']) ? '' : stripslashes($_POST['MSN'])
),
'posts' => empty($_POST['posts']) ? 0 : (int) $_POST['posts'],
'avatar' => array(
'name' => &$_POST['avatar'],
'href' => empty($user_profile[$_REQUEST['userID']]['ID_ATTACH']) ? '' : (empty($user_profile[$_REQUEST['userID']]['attachmentType']) ? $scripturl . '?action=dlattach;attach=' . $user_profile[$_REQUEST['userID']]['ID_ATTACH'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $user_profile[$_REQUEST['userID']]['filename']),
'custom' => stristr($_POST['avatar'], 'http://') ? $_POST['avatar'] : 'http://',
'selection' => $_POST['avatar'] == '' || stristr($_POST['avatar'], 'http://') ? '' : $_POST['avatar'],
'choice' => empty($_POST['avatar_choice']) ? 'server_stored' : $_POST['avatar_choice'],
'external' => empty($_POST['userpicpersonal']) ? 'http://' : $_POST['userpicpersonal'],
'ID_ATTACH' => empty($_POST['ID_ATTACH']) ? '0' : $_POST['ID_ATTACH'],
'allow_server_stored' => allowedTo('profile_server_avatar') || !$context['user']['is_owner'],
'allow_upload' => allowedTo('profile_upload_avatar') || !$context['user']['is_owner'],
'allow_external' => allowedTo('profile_remote_avatar') || !$context['user']['is_owner'],
),
'karma' => array(
'good' => empty($_POST['karmaGood']) ? '0' : $_POST['karmaGood'],
'bad' => empty($_POST['karmaBad']) ? '0' : $_POST['karmaBad'],
),
'time_format' => !isset($_POST['timeFormat']) ? '' : stripslashes($_POST['timeFormat']),
'time_offset' => empty($_POST['timeOffset']) ? '0' : $_POST['timeOffset'],
'secret_question' => !isset($_POST['secretQuestion']) ? '' : stripslashes($_POST['secretQuestion']),
'theme' => array(
'id' => isset($context['member']['theme']['id']) ? $context['member']['theme']['id'] : 0,
'name' => isset($context['member']['theme']['name']) ? $context['member']['theme']['name'] : '',
),
'notify_announcements' => empty($_POST['notifyAnnouncements']) ? 0 : 1,
'notify_once' => empty($_POST['notifyOnce']) ? 0 : 1,
'notify_send_body' => empty($_POST['notifySendBody']) ? 0 : (int) $_POST['notifySendBody'],
'notify_types' => empty($_POST['notifyTypes']) ? 0 : (int) $_POST['notifyTypes'],
'group' => isset($_POST['ID_GROUP']) ? $_POST['ID_GROUP'] : 0,
'smiley_set' => array(
'id' => isset($_POST['smileySet']) ? $_POST['smileySet'] : (isset($context['member']['smiley_set']) ? $context['member']['smiley_set']['id'] : ''),
'name' => isset($context['member']['smiley_set']) ? $context['member']['smiley_set']['name'] : ''
),
);
// Overwrite the currently set membergroups with those you just selected.
if (allowedTo('manage_membergroups') && isset($_POST['ID_GROUP']))
{
foreach ($context['member_groups'] as $ID_GROUP => $dummy)
{
$context['member_groups'][$ID_GROUP]['is_primary'] = $ID_GROUP == $_POST['ID_GROUP'];
$context['member_groups'][$ID_GROUP]['is_additional'] = !empty($_POST['additionalGroups']) && in_array($ID_GROUP, $_POST['additionalGroups']);
}
}
loadThemeOptions((int) $_REQUEST['userID']);
}
function loadThemeOptions($memID)
{
global $context, $options, $db_prefix, $user_profile;
if (isset($_POST['options'], $_POST['default_options']))
$_POST['options'] += $_POST['default_options'];
if ($context['user']['is_owner'])
$context['member']['options'] = $options;
else
{
$request = db_query("
SELECT ID_MEMBER, variable, value
FROM {$db_prefix}themes
WHERE ID_THEME IN (1, " . (int) $user_profile[$memID]['ID_THEME'] . ")
AND ID_MEMBER IN (-1, $memID)", __FILE__, __LINE__);
$temp = array();
while ($row = mysql_fetch_assoc($request))
{
if ($row['ID_MEMBER'] == -1)
{
$temp[$row['variable']] = $row['value'];
continue;
}
if (isset($_POST['options'][$row['variable']]))
$row['value'] = $_POST['options'][$row['variable']];
$context['member']['options'][$row['variable']] = $row['value'];
}
mysql_free_result($request);
// Load up the default theme options for any missing.
foreach ($temp as $k => $v)
{
if (!isset($context['member']['options'][$k]))
$context['member']['options'][$k] = $v;
}
}
}
?>