annotate forum/Sources/Profile-Modify.php @ 85:6d7b61434be7 website

Add a copy of this here, just in case!
author Chris Cannam
date Mon, 20 Jan 2014 11:02:36 +0000
parents e3e11437ecea
children
rev   line source
Chris@76 1 <?php
Chris@76 2
Chris@76 3 /**
Chris@76 4 * Simple Machines Forum (SMF)
Chris@76 5 *
Chris@76 6 * @package SMF
Chris@76 7 * @author Simple Machines http://www.simplemachines.org
Chris@76 8 * @copyright 2011 Simple Machines
Chris@76 9 * @license http://www.simplemachines.org/about/smf/license.php BSD
Chris@76 10 *
Chris@76 11 * @version 2.0.2
Chris@76 12 */
Chris@76 13
Chris@76 14 if (!defined('SMF'))
Chris@76 15 die('Hacking attempt...');
Chris@76 16
Chris@76 17 /* This file has the primary job of showing and editing people's profiles.
Chris@76 18 It also allows the user to change some of their or another's preferences,
Chris@76 19 and such things. It uses the following functions:
Chris@76 20
Chris@76 21 void loadProfileFields(bool force_reload = false)
Chris@76 22 // !!!
Chris@76 23
Chris@76 24 void setupProfileContext(array fields)
Chris@76 25 // !!!
Chris@76 26
Chris@76 27 void saveProfileFields()
Chris@76 28 // !!!
Chris@76 29
Chris@76 30 void saveProfileChanges(array &profile_variables, array &errors, int id_member)
Chris@76 31 // !!!
Chris@76 32
Chris@76 33 void makeThemeChanges(int id_member, int id_theme)
Chris@76 34 // !!!
Chris@76 35
Chris@76 36 void makeNotificationChanges(int id_member)
Chris@76 37 // !!!
Chris@76 38
Chris@76 39 void makeCustomFieldChanges(int id_member, string area, bool sanitize = true)
Chris@76 40 // !!!
Chris@76 41
Chris@76 42 void editBuddies(int id_member)
Chris@76 43 // !!!
Chris@76 44
Chris@76 45 void editIgnoreList(int id_member)
Chris@76 46 // !!!
Chris@76 47
Chris@76 48 void account(int id_member)
Chris@76 49 // !!!
Chris@76 50
Chris@76 51 void forumProfile(int id_member)
Chris@76 52 // !!!
Chris@76 53
Chris@76 54 void pmprefs(int id_member)
Chris@76 55 // !!!
Chris@76 56
Chris@76 57 array getAvatars(string directory, int level)
Chris@76 58 // !!!
Chris@76 59
Chris@76 60 void theme(int id_member)
Chris@76 61 // !!!
Chris@76 62
Chris@76 63 void authentication(int id_member, bool saving = false)
Chris@76 64 // !!!
Chris@76 65
Chris@76 66 void notification(int id_member)
Chris@76 67 // !!!
Chris@76 68
Chris@76 69 int list_getTopicNotificationCount(int memID)
Chris@76 70 // !!!
Chris@76 71
Chris@76 72 array list_getTopicNotifications(int start, int items_per_page, string sort, int memID)
Chris@76 73 // !!!
Chris@76 74
Chris@76 75 array list_getBoardNotifications(int start, int items_per_page, string sort, int memID)
Chris@76 76 // !!!
Chris@76 77
Chris@76 78 void loadThemeOptions(int id_member)
Chris@76 79 // !!!
Chris@76 80
Chris@76 81 void ignoreboards(int id_member)
Chris@76 82 // !!!
Chris@76 83
Chris@76 84 bool profileLoadLanguages()
Chris@76 85 // !!!
Chris@76 86
Chris@76 87 bool profileLoadGroups()
Chris@76 88 // !!!
Chris@76 89
Chris@76 90 bool profileLoadSignatureData()
Chris@76 91 // !!!
Chris@76 92
Chris@76 93 bool profileLoadAvatarData()
Chris@76 94 // !!!
Chris@76 95
Chris@76 96 bool profileSaveGroups(mixed &value)
Chris@76 97 // !!!
Chris@76 98
Chris@76 99 mixed profileSaveAvatarData(array &value)
Chris@76 100 // !!!
Chris@76 101
Chris@76 102 mixed profileValidateSignature(mixed &value)
Chris@76 103 // !!!
Chris@76 104
Chris@76 105 bool profileValidateEmail(string email, int id_member = none)
Chris@76 106 // !!!
Chris@76 107
Chris@76 108 void profileReloadUser()
Chris@76 109 // !!!
Chris@76 110
Chris@76 111 void profileSendActivation()
Chris@76 112 // !!!
Chris@76 113
Chris@76 114 void groupMembership(int id_member)
Chris@76 115 // !!!
Chris@76 116
Chris@76 117 mixed groupMembership2(array profile_vars, array post_erros, int id_member)
Chris@76 118 // !!!
Chris@76 119
Chris@76 120 Adding new fields to the profile:
Chris@76 121 ---------------------------------------------------------------------------
Chris@76 122 // !!!
Chris@76 123 */
Chris@76 124
Chris@76 125 // This defines every profile field known to man.
Chris@76 126 function loadProfileFields($force_reload = false)
Chris@76 127 {
Chris@76 128 global $context, $profile_fields, $txt, $scripturl, $modSettings, $user_info, $old_profile, $smcFunc, $cur_profile, $language;
Chris@76 129
Chris@76 130 // Don't load this twice!
Chris@76 131 if (!empty($profile_fields) && !$force_reload)
Chris@76 132 return;
Chris@76 133
Chris@76 134 /* This horrific array defines all the profile fields in the whole world!
Chris@76 135 In general each "field" has one array - the key of which is the database column name associated with said field. Each item
Chris@76 136 can have the following attributes:
Chris@76 137
Chris@76 138 string $type: The type of field this is - valid types are:
Chris@76 139 - callback: This is a field which has its own callback mechanism for templating.
Chris@76 140 - check: A simple checkbox.
Chris@76 141 - hidden: This doesn't have any visual aspects but may have some validity.
Chris@76 142 - password: A password box.
Chris@76 143 - select: A select box.
Chris@76 144 - text: A string of some description.
Chris@76 145
Chris@76 146 string $label: The label for this item - default will be $txt[$key] if this isn't set.
Chris@76 147 string $subtext: The subtext (Small label) for this item.
Chris@76 148 int $size: Optional size for a text area.
Chris@76 149 array $input_attr: An array of text strings to be added to the input box for this item.
Chris@76 150 string $value: The value of the item. If not set $cur_profile[$key] is assumed.
Chris@76 151 string $permission: Permission required for this item (Excluded _any/_own subfix which is applied automatically).
Chris@76 152 function $input_validate: A runtime function which validates the element before going to the database. It is passed
Chris@76 153 the relevant $_POST element if it exists and should be treated like a reference.
Chris@76 154
Chris@76 155 Return types:
Chris@76 156 - true: Element can be stored.
Chris@76 157 - false: Skip this element.
Chris@76 158 - a text string: An error occured - this is the error message.
Chris@76 159
Chris@76 160 function $preload: A function that is used to load data required for this element to be displayed. Must return
Chris@76 161 true to be displayed at all.
Chris@76 162
Chris@76 163 string $cast_type: If set casts the element to a certain type. Valid types (bool, int, float).
Chris@76 164 string $save_key: If the index of this element isn't the database column name it can be overriden
Chris@76 165 with this string.
Chris@76 166 bool $is_dummy: If set then nothing is acted upon for this element.
Chris@76 167 bool $enabled: A test to determine whether this is even available - if not is unset.
Chris@76 168 string $link_with: Key which links this field to an overall set.
Chris@76 169
Chris@76 170 Note that all elements that have a custom input_validate must ensure they set the value of $cur_profile correct to enable
Chris@76 171 the changes to be displayed correctly on submit of the form.
Chris@76 172
Chris@76 173 */
Chris@76 174
Chris@76 175 $profile_fields = array(
Chris@76 176 'aim' => array(
Chris@76 177 'type' => 'text',
Chris@76 178 'label' => $txt['aim'],
Chris@76 179 'subtext' => $txt['your_aim'],
Chris@76 180 'size' => 24,
Chris@76 181 'value' => strtr(empty($cur_profile['aim']) ? '' : $cur_profile['aim'], '+', ' '),
Chris@76 182 'permission' => 'profile_extra',
Chris@76 183 'input_validate' => create_function('&$value', '
Chris@76 184 $value = strtr($value, \' \', \'+\');
Chris@76 185 return true;
Chris@76 186 '),
Chris@76 187 ),
Chris@76 188 'avatar_choice' => array(
Chris@76 189 'type' => 'callback',
Chris@76 190 'callback_func' => 'avatar_select',
Chris@76 191 // This handles the permissions too.
Chris@76 192 'preload' => 'profileLoadAvatarData',
Chris@76 193 'input_validate' => 'profileSaveAvatarData',
Chris@76 194 'save_key' => 'avatar',
Chris@76 195 ),
Chris@76 196 'bday1' => array(
Chris@76 197 'type' => 'callback',
Chris@76 198 'callback_func' => 'birthdate',
Chris@76 199 'permission' => 'profile_extra',
Chris@76 200 'preload' => create_function('', '
Chris@76 201 global $cur_profile, $context;
Chris@76 202
Chris@76 203 // Split up the birthdate....
Chris@76 204 list ($uyear, $umonth, $uday) = explode(\'-\', empty($cur_profile[\'birthdate\']) || $cur_profile[\'birthdate\'] == \'0001-01-01\' ? \'0000-00-00\' : $cur_profile[\'birthdate\']);
Chris@76 205 $context[\'member\'][\'birth_date\'] = array(
Chris@76 206 \'year\' => $uyear == \'0004\' ? \'0000\' : $uyear,
Chris@76 207 \'month\' => $umonth,
Chris@76 208 \'day\' => $uday,
Chris@76 209 );
Chris@76 210
Chris@76 211 return true;
Chris@76 212 '),
Chris@76 213 'input_validate' => create_function('&$value', '
Chris@76 214 global $profile_vars, $cur_profile;
Chris@76 215
Chris@76 216 if (isset($_POST[\'bday2\'], $_POST[\'bday3\']) && $value > 0 && $_POST[\'bday2\'] > 0)
Chris@76 217 {
Chris@76 218 // Set to blank?
Chris@76 219 if ((int) $_POST[\'bday3\'] == 1 && (int) $_POST[\'bday2\'] == 1 && (int) $value == 1)
Chris@76 220 $value = \'0001-01-01\';
Chris@76 221 else
Chris@76 222 $value = checkdate($value, $_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\';
Chris@76 223 }
Chris@76 224 else
Chris@76 225 $value = \'0001-01-01\';
Chris@76 226
Chris@76 227 $profile_vars[\'birthdate\'] = $value;
Chris@76 228 $cur_profile[\'birthdate\'] = $value;
Chris@76 229 return false;
Chris@76 230 '),
Chris@76 231 ),
Chris@76 232 // Setting the birthdate the old style way?
Chris@76 233 'birthdate' => array(
Chris@76 234 'type' => 'hidden',
Chris@76 235 'permission' => 'profile_extra',
Chris@76 236 'input_validate' => create_function('&$value', '
Chris@76 237 global $cur_profile;
Chris@76 238 // !!! Should we check for this year and tell them they made a mistake :P? (based on coppa at least?)
Chris@76 239 if (preg_match(\'/(\d{4})[\-\., ](\d{2})[\-\., ](\d{2})/\', $value, $dates) === 1)
Chris@76 240 {
Chris@76 241 $value = 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\';
Chris@76 242 return true;
Chris@76 243 }
Chris@76 244 else
Chris@76 245 {
Chris@76 246 $value = empty($cur_profile[\'birthdate\']) ? \'0001-01-01\' : $cur_profile[\'birthdate\'];
Chris@76 247 return false;
Chris@76 248 }
Chris@76 249 '),
Chris@76 250 ),
Chris@76 251 'date_registered' => array(
Chris@76 252 'type' => 'text',
Chris@76 253 'value' => empty($cur_profile['date_registered']) ? $txt['not_applicable'] : strftime('%Y-%m-%d', $cur_profile['date_registered'] + ($user_info['time_offset'] + $modSettings['time_offset']) * 3600),
Chris@76 254 'label' => $txt['date_registered'],
Chris@76 255 'log_change' => true,
Chris@76 256 'permission' => 'moderate_forum',
Chris@76 257 'input_validate' => create_function('&$value', '
Chris@76 258 global $txt, $user_info, $modSettings, $cur_profile, $context;
Chris@76 259
Chris@76 260 // Bad date! Go try again - please?
Chris@76 261 if (($value = strtotime($value)) === -1)
Chris@76 262 {
Chris@76 263 $value = $cur_profile[\'date_registered\'];
Chris@76 264 return $txt[\'invalid_registration\'] . \' \' . strftime(\'%d %b %Y \' . (strpos($user_info[\'time_format\'], \'%H\') !== false ? \'%I:%M:%S %p\' : \'%H:%M:%S\'), forum_time(false));
Chris@76 265 }
Chris@76 266 // As long as it doesn\'t equal "N/A"...
Chris@76 267 elseif ($value != $txt[\'not_applicable\'] && $value != strtotime(strftime(\'%Y-%m-%d\', $cur_profile[\'date_registered\'] + ($user_info[\'time_offset\'] + $modSettings[\'time_offset\']) * 3600)))
Chris@76 268 $value = $value - ($user_info[\'time_offset\'] + $modSettings[\'time_offset\']) * 3600;
Chris@76 269 else
Chris@76 270 $value = $cur_profile[\'date_registered\'];
Chris@76 271
Chris@76 272 return true;
Chris@76 273 '),
Chris@76 274 ),
Chris@76 275 'email_address' => array(
Chris@76 276 'type' => 'text',
Chris@76 277 'label' => $txt['email'],
Chris@76 278 'subtext' => $txt['valid_email'],
Chris@76 279 'log_change' => true,
Chris@76 280 'permission' => 'profile_identity',
Chris@76 281 'input_validate' => create_function('&$value', '
Chris@76 282 global $context, $old_profile, $context, $profile_vars, $sourcedir, $modSettings;
Chris@76 283
Chris@76 284 if (strtolower($value) == strtolower($old_profile[\'email_address\']))
Chris@76 285 return false;
Chris@76 286
Chris@76 287 $isValid = profileValidateEmail($value, $context[\'id_member\']);
Chris@76 288
Chris@76 289 // Do they need to revalidate? If so schedule the function!
Chris@76 290 if ($isValid === true && !empty($modSettings[\'send_validation_onChange\']) && !allowedTo(\'moderate_forum\'))
Chris@76 291 {
Chris@76 292 require_once($sourcedir . \'/Subs-Members.php\');
Chris@76 293 $profile_vars[\'validation_code\'] = generateValidationCode();
Chris@76 294 $profile_vars[\'is_activated\'] = 2;
Chris@76 295 $context[\'profile_execute_on_save\'][] = \'profileSendActivation\';
Chris@76 296 unset($context[\'profile_execute_on_save\'][\'reload_user\']);
Chris@76 297 }
Chris@76 298
Chris@76 299 return $isValid;
Chris@76 300 '),
Chris@76 301 ),
Chris@76 302 'gender' => array(
Chris@76 303 'type' => 'select',
Chris@76 304 'cast_type' => 'int',
Chris@76 305 'options' => 'return array(0 => \'\', 1 => $txt[\'male\'], 2 => $txt[\'female\']);',
Chris@76 306 'label' => $txt['gender'],
Chris@76 307 'permission' => 'profile_extra',
Chris@76 308 ),
Chris@76 309 'hide_email' => array(
Chris@76 310 'type' => 'check',
Chris@76 311 'value' => empty($cur_profile['hide_email']) ? true : false,
Chris@76 312 'label' => $txt['allow_user_email'],
Chris@76 313 'permission' => 'profile_identity',
Chris@76 314 'input_validate' => create_function('&$value', '
Chris@76 315 $value = $value == 0 ? 1 : 0;
Chris@76 316
Chris@76 317 return true;
Chris@76 318 '),
Chris@76 319 ),
Chris@76 320 'icq' => array(
Chris@76 321 'type' => 'text',
Chris@76 322 'label' => $txt['icq'],
Chris@76 323 'subtext' => $txt['your_icq'],
Chris@76 324 'size' => 24,
Chris@76 325 'permission' => 'profile_extra',
Chris@76 326 // Need to make sure ICQ doesn't equal 0.
Chris@76 327 'input_validate' => create_function('&$value', '
Chris@76 328 if (empty($value))
Chris@76 329 $value = \'\';
Chris@76 330 else
Chris@76 331 $value = (int) $value;
Chris@76 332 return true;
Chris@76 333 '),
Chris@76 334 ),
Chris@76 335 // Selecting group membership is a complicated one so we treat it separate!
Chris@76 336 'id_group' => array(
Chris@76 337 'type' => 'callback',
Chris@76 338 'callback_func' => 'group_manage',
Chris@76 339 'permission' => 'manage_membergroups',
Chris@76 340 'preload' => 'profileLoadGroups',
Chris@76 341 'log_change' => true,
Chris@76 342 'input_validate' => 'profileSaveGroups',
Chris@76 343 ),
Chris@76 344 'id_theme' => array(
Chris@76 345 'type' => 'callback',
Chris@76 346 'callback_func' => 'theme_pick',
Chris@76 347 'permission' => 'profile_extra',
Chris@76 348 'enabled' => $modSettings['theme_allow'] || allowedTo('admin_forum'),
Chris@76 349 'preload' => create_function('', '
Chris@76 350 global $smcFunc, $context, $cur_profile, $txt;
Chris@76 351
Chris@76 352 $request = $smcFunc[\'db_query\'](\'\', \'
Chris@76 353 SELECT value
Chris@76 354 FROM {db_prefix}themes
Chris@76 355 WHERE id_theme = {int:id_theme}
Chris@76 356 AND variable = {string:variable}
Chris@76 357 LIMIT 1\', array(
Chris@76 358 \'id_theme\' => $cur_profile[\'id_theme\'],
Chris@76 359 \'variable\' => \'name\',
Chris@76 360 )
Chris@76 361 );
Chris@76 362 list ($name) = $smcFunc[\'db_fetch_row\']($request);
Chris@76 363 $smcFunc[\'db_free_result\']($request);
Chris@76 364
Chris@76 365 $context[\'member\'][\'theme\'] = array(
Chris@76 366 \'id\' => $cur_profile[\'id_theme\'],
Chris@76 367 \'name\' => empty($cur_profile[\'id_theme\']) ? $txt[\'theme_forum_default\'] : $name
Chris@76 368 );
Chris@76 369 return true;
Chris@76 370 '),
Chris@76 371 'input_validate' => create_function('&$value', '
Chris@76 372 $value = (int) $value;
Chris@76 373 return true;
Chris@76 374 '),
Chris@76 375 ),
Chris@76 376 'karma_good' => array(
Chris@76 377 'type' => 'callback',
Chris@76 378 'callback_func' => 'karma_modify',
Chris@76 379 'permission' => 'admin_forum',
Chris@76 380 // Set karma_bad too!
Chris@76 381 'input_validate' => create_function('&$value', '
Chris@76 382 global $profile_vars, $cur_profile;
Chris@76 383
Chris@76 384 $value = (int) $value;
Chris@76 385 if (isset($_POST[\'karma_bad\']))
Chris@76 386 {
Chris@76 387 $profile_vars[\'karma_bad\'] = $_POST[\'karma_bad\'] != \'\' ? (int) $_POST[\'karma_bad\'] : 0;
Chris@76 388 $cur_profile[\'karma_bad\'] = $_POST[\'karma_bad\'] != \'\' ? (int) $_POST[\'karma_bad\'] : 0;
Chris@76 389 }
Chris@76 390 return true;
Chris@76 391 '),
Chris@76 392 'preload' => create_function('', '
Chris@76 393 global $context, $cur_profile;
Chris@76 394
Chris@76 395 $context[\'member\'][\'karma\'][\'good\'] = $cur_profile[\'karma_good\'];
Chris@76 396 $context[\'member\'][\'karma\'][\'bad\'] = $cur_profile[\'karma_bad\'];
Chris@76 397
Chris@76 398 return true;
Chris@76 399 '),
Chris@76 400 'enabled' => !empty($modSettings['karmaMode']),
Chris@76 401 ),
Chris@76 402 'lngfile' => array(
Chris@76 403 'type' => 'select',
Chris@76 404 'options' => 'return $context[\'profile_languages\'];',
Chris@76 405 'label' => $txt['preferred_language'],
Chris@76 406 'permission' => 'profile_identity',
Chris@76 407 'preload' => 'profileLoadLanguages',
Chris@76 408 'enabled' => !empty($modSettings['userLanguage']),
Chris@76 409 'value' => empty($cur_profile['lngfile']) ? $language : $cur_profile['lngfile'],
Chris@76 410 'input_validate' => create_function('&$value', '
Chris@76 411 global $context, $cur_profile;
Chris@76 412
Chris@76 413 // Load the languages.
Chris@76 414 profileLoadLanguages();
Chris@76 415
Chris@76 416 if (isset($context[\'profile_languages\'][$value]))
Chris@76 417 {
Chris@76 418 if ($context[\'user\'][\'is_owner\'] && empty($context[\'password_auth_failed\']))
Chris@76 419 $_SESSION[\'language\'] = $value;
Chris@76 420 return true;
Chris@76 421 }
Chris@76 422 else
Chris@76 423 {
Chris@76 424 $value = $cur_profile[\'lngfile\'];
Chris@76 425 return false;
Chris@76 426 }
Chris@76 427 '),
Chris@76 428 ),
Chris@76 429 'location' => array(
Chris@76 430 'type' => 'text',
Chris@76 431 'label' => $txt['location'],
Chris@76 432 'log_change' => true,
Chris@76 433 'size' => 50,
Chris@76 434 'permission' => 'profile_extra',
Chris@76 435 ),
Chris@76 436 // The username is not always editable - so adjust it as such.
Chris@76 437 'member_name' => array(
Chris@76 438 'type' => allowedTo('admin_forum') && isset($_GET['changeusername']) ? 'text' : 'label',
Chris@76 439 'label' => $txt['username'],
Chris@76 440 'subtext' => allowedTo('admin_forum') && !isset($_GET['changeusername']) ? '(<a href="' . $scripturl . '?action=profile;u=' . $context['id_member'] . ';area=account;changeusername" style="font-style: italic;">' . $txt['username_change'] . '</a>)' : '',
Chris@76 441 'log_change' => true,
Chris@76 442 'permission' => 'profile_identity',
Chris@76 443 'prehtml' => allowedTo('admin_forum') && isset($_GET['changeusername']) ? '<div class="alert">' . $txt['username_warning'] . '</div>' : '',
Chris@76 444 'input_validate' => create_function('&$value', '
Chris@76 445 global $sourcedir, $context, $user_info, $cur_profile;
Chris@76 446
Chris@76 447 if (allowedTo(\'admin_forum\'))
Chris@76 448 {
Chris@76 449 // We\'ll need this...
Chris@76 450 require_once($sourcedir . \'/Subs-Auth.php\');
Chris@76 451
Chris@76 452 // Maybe they are trying to change their password as well?
Chris@76 453 $resetPassword = true;
Chris@76 454 if (isset($_POST[\'passwrd1\']) && $_POST[\'passwrd1\'] != \'\' && isset($_POST[\'passwrd2\']) && $_POST[\'passwrd1\'] == $_POST[\'passwrd2\'] && validatePassword($_POST[\'passwrd1\'], $value, array($cur_profile[\'real_name\'], $user_info[\'username\'], $user_info[\'name\'], $user_info[\'email\'])) == null)
Chris@76 455 $resetPassword = false;
Chris@76 456
Chris@76 457 // Do the reset... this will send them an email too.
Chris@76 458 if ($resetPassword)
Chris@76 459 resetPassword($context[\'id_member\'], $value);
Chris@76 460 elseif ($value !== null)
Chris@76 461 {
Chris@76 462 validateUsername($context[\'id_member\'], $value);
Chris@76 463 updateMemberData($context[\'id_member\'], array(\'member_name\' => $value));
Chris@76 464 }
Chris@76 465 }
Chris@76 466 return false;
Chris@76 467 '),
Chris@76 468 ),
Chris@76 469 'msn' => array(
Chris@76 470 'type' => 'text',
Chris@76 471 'label' => $txt['msn'],
Chris@76 472 'subtext' => $txt['msn_email_address'],
Chris@76 473 'size' => 24,
Chris@76 474 'permission' => 'profile_extra',
Chris@76 475 'input_validate' => create_function('&$value', '
Chris@76 476 global $cur_profile;
Chris@76 477 // Make sure the msn one is an email address, not something like \'none\' :P.
Chris@76 478 if ($value != \'\' && preg_match(\'~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\\\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~\', $value) == 0)
Chris@76 479 {
Chris@76 480 $value = $cur_profile[\'msn\'];
Chris@76 481 return false;
Chris@76 482 }
Chris@76 483 return true;
Chris@76 484 '),
Chris@76 485 ),
Chris@76 486 'passwrd1' => array(
Chris@76 487 'type' => 'password',
Chris@76 488 'label' => $txt['choose_pass'],
Chris@76 489 'subtext' => $txt['password_strength'],
Chris@76 490 'size' => 20,
Chris@76 491 'value' => '',
Chris@76 492 'enabled' => empty($cur_profile['openid_uri']),
Chris@76 493 'permission' => 'profile_identity',
Chris@76 494 'save_key' => 'passwd',
Chris@76 495 // Note this will only work if passwrd2 also exists!
Chris@76 496 'input_validate' => create_function('&$value', '
Chris@76 497 global $sourcedir, $user_info, $smcFunc, $cur_profile;
Chris@76 498
Chris@76 499 // If we didn\'t try it then ignore it!
Chris@76 500 if ($value == \'\')
Chris@76 501 return false;
Chris@76 502
Chris@76 503 // Do the two entries for the password even match?
Chris@76 504 if (!isset($_POST[\'passwrd2\']) || $value != $_POST[\'passwrd2\'])
Chris@76 505 return \'bad_new_password\';
Chris@76 506
Chris@76 507 // Let\'s get the validation function into play...
Chris@76 508 require_once($sourcedir . \'/Subs-Auth.php\');
Chris@76 509 $passwordErrors = validatePassword($value, $cur_profile[\'member_name\'], array($cur_profile[\'real_name\'], $user_info[\'username\'], $user_info[\'name\'], $user_info[\'email\']));
Chris@76 510
Chris@76 511 // Were there errors?
Chris@76 512 if ($passwordErrors != null)
Chris@76 513 return \'password_\' . $passwordErrors;
Chris@76 514
Chris@76 515 // Set up the new password variable... ready for storage.
Chris@76 516 $value = sha1(strtolower($cur_profile[\'member_name\']) . un_htmlspecialchars($value));
Chris@76 517 return true;
Chris@76 518 '),
Chris@76 519 ),
Chris@76 520 'passwrd2' => array(
Chris@76 521 'type' => 'password',
Chris@76 522 'label' => $txt['verify_pass'],
Chris@76 523 'enabled' => empty($cur_profile['openid_uri']),
Chris@76 524 'size' => 20,
Chris@76 525 'value' => '',
Chris@76 526 'permission' => 'profile_identity',
Chris@76 527 'is_dummy' => true,
Chris@76 528 ),
Chris@76 529 'personal_text' => array(
Chris@76 530 'type' => 'text',
Chris@76 531 'label' => $txt['personal_text'],
Chris@76 532 'log_change' => true,
Chris@76 533 'input_attr' => array('maxlength="50"'),
Chris@76 534 'size' => 50,
Chris@76 535 'permission' => 'profile_extra',
Chris@76 536 ),
Chris@76 537 // This does ALL the pm settings
Chris@76 538 'pm_prefs' => array(
Chris@76 539 'type' => 'callback',
Chris@76 540 'callback_func' => 'pm_settings',
Chris@76 541 'permission' => 'pm_read',
Chris@76 542 'preload' => create_function('', '
Chris@76 543 global $context, $cur_profile;
Chris@76 544
Chris@76 545 $context[\'display_mode\'] = $cur_profile[\'pm_prefs\'] & 3;
Chris@76 546 $context[\'send_email\'] = $cur_profile[\'pm_email_notify\'];
Chris@76 547 $context[\'receive_from\'] = !empty($cur_profile[\'pm_receive_from\']) ? $cur_profile[\'pm_receive_from\'] : 0;
Chris@76 548
Chris@76 549 return true;
Chris@76 550 '),
Chris@76 551 'input_validate' => create_function('&$value', '
Chris@76 552 global $cur_profile, $profile_vars;
Chris@76 553
Chris@76 554 // Simple validate and apply the two "sub settings"
Chris@76 555 $value = max(min($value, 2), 0);
Chris@76 556
Chris@76 557 $cur_profile[\'pm_email_notify\'] = $profile_vars[\'pm_email_notify\'] = max(min((int) $_POST[\'pm_email_notify\'], 2), 0);
Chris@76 558 $cur_profile[\'pm_receive_from\'] = $profile_vars[\'pm_receive_from\'] = max(min((int) $_POST[\'pm_receive_from\'], 4), 0);
Chris@76 559
Chris@76 560 return true;
Chris@76 561 '),
Chris@76 562 ),
Chris@76 563 'posts' => array(
Chris@76 564 'type' => 'int',
Chris@76 565 'label' => $txt['profile_posts'],
Chris@76 566 'log_change' => true,
Chris@76 567 'size' => 7,
Chris@76 568 'permission' => 'moderate_forum',
Chris@76 569 'input_validate' => create_function('&$value', '
Chris@76 570 $value = $value != \'\' ? strtr($value, array(\',\' => \'\', \'.\' => \'\', \' \' => \'\')) : 0;
Chris@76 571 return true;
Chris@76 572 '),
Chris@76 573 ),
Chris@76 574 'real_name' => array(
Chris@76 575 'type' => !empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum') ? 'text' : 'label',
Chris@76 576 'label' => $txt['name'],
Chris@76 577 'subtext' => $txt['display_name_desc'],
Chris@76 578 'log_change' => true,
Chris@76 579 'input_attr' => array('maxlength="60"'),
Chris@76 580 'permission' => 'profile_identity',
Chris@76 581 'enabled' => !empty($modSettings['allow_editDisplayName']) || allowedTo('moderate_forum'),
Chris@76 582 'input_validate' => create_function('&$value', '
Chris@76 583 global $context, $smcFunc, $sourcedir, $cur_profile;
Chris@76 584
Chris@76 585 $value = trim(preg_replace(\'~[\s]~\' . ($context[\'utf8\'] ? \'u\' : \'\'), \' \', $value));
Chris@76 586
Chris@76 587 if (trim($value) == \'\')
Chris@76 588 return \'no_name\';
Chris@76 589 elseif ($smcFunc[\'strlen\']($value) > 60)
Chris@76 590 return \'name_too_long\';
Chris@76 591 elseif ($cur_profile[\'real_name\'] != $value)
Chris@76 592 {
Chris@76 593 require_once($sourcedir . \'/Subs-Members.php\');
Chris@76 594 if (isReservedName($value, $context[\'id_member\']))
Chris@76 595 return \'name_taken\';
Chris@76 596 }
Chris@76 597 return true;
Chris@76 598 '),
Chris@76 599 ),
Chris@76 600 'secret_question' => array(
Chris@76 601 'type' => 'text',
Chris@76 602 'label' => $txt['secret_question'],
Chris@76 603 'subtext' => $txt['secret_desc'],
Chris@76 604 'size' => 50,
Chris@76 605 'permission' => 'profile_identity',
Chris@76 606 ),
Chris@76 607 'secret_answer' => array(
Chris@76 608 'type' => 'text',
Chris@76 609 'label' => $txt['secret_answer'],
Chris@76 610 'subtext' => $txt['secret_desc2'],
Chris@76 611 'size' => 20,
Chris@76 612 'postinput' => '<span class="smalltext" style="margin-left: 4ex;"><a href="' . $scripturl . '?action=helpadmin;help=secret_why_blank" onclick="return reqWin(this.href);">' . $txt['secret_why_blank'] . '</a></span>',
Chris@76 613 'value' => '',
Chris@76 614 'permission' => 'profile_identity',
Chris@76 615 'input_validate' => create_function('&$value', '
Chris@76 616 $value = $value != \'\' ? md5($value) : \'\';
Chris@76 617 return true;
Chris@76 618 '),
Chris@76 619 ),
Chris@76 620 'signature' => array(
Chris@76 621 'type' => 'callback',
Chris@76 622 'callback_func' => 'signature_modify',
Chris@76 623 'permission' => 'profile_extra',
Chris@76 624 'enabled' => substr($modSettings['signature_settings'], 0, 1) == 1,
Chris@76 625 'preload' => 'profileLoadSignatureData',
Chris@76 626 'input_validate' => 'profileValidateSignature',
Chris@76 627 ),
Chris@76 628 'show_online' => array(
Chris@76 629 'type' => 'check',
Chris@76 630 'label' => $txt['show_online'],
Chris@76 631 'permission' => 'profile_identity',
Chris@76 632 'enabled' => !empty($modSettings['allow_hideOnline']) || allowedTo('moderate_forum'),
Chris@76 633 ),
Chris@76 634 'smiley_set' => array(
Chris@76 635 'type' => 'callback',
Chris@76 636 'callback_func' => 'smiley_pick',
Chris@76 637 'enabled' => !empty($modSettings['smiley_sets_enable']),
Chris@76 638 'permission' => 'profile_extra',
Chris@76 639 'preload' => create_function('', '
Chris@76 640 global $modSettings, $context, $txt, $cur_profile;
Chris@76 641
Chris@76 642 $context[\'member\'][\'smiley_set\'][\'id\'] = empty($cur_profile[\'smiley_set\']) ? \'\' : $cur_profile[\'smiley_set\'];
Chris@76 643 $context[\'smiley_sets\'] = explode(\',\', \'none,,\' . $modSettings[\'smiley_sets_known\']);
Chris@76 644 $set_names = explode("\n", $txt[\'smileys_none\'] . "\n" . $txt[\'smileys_forum_board_default\'] . "\n" . $modSettings[\'smiley_sets_names\']);
Chris@76 645 foreach ($context[\'smiley_sets\'] as $i => $set)
Chris@76 646 {
Chris@76 647 $context[\'smiley_sets\'][$i] = array(
Chris@76 648 \'id\' => htmlspecialchars($set),
Chris@76 649 \'name\' => htmlspecialchars($set_names[$i]),
Chris@76 650 \'selected\' => $set == $context[\'member\'][\'smiley_set\'][\'id\']
Chris@76 651 );
Chris@76 652
Chris@76 653 if ($context[\'smiley_sets\'][$i][\'selected\'])
Chris@76 654 $context[\'member\'][\'smiley_set\'][\'name\'] = $set_names[$i];
Chris@76 655 }
Chris@76 656 return true;
Chris@76 657 '),
Chris@76 658 'input_validate' => create_function('&$value', '
Chris@76 659 global $modSettings;
Chris@76 660
Chris@76 661 $smiley_sets = explode(\',\', $modSettings[\'smiley_sets_known\']);
Chris@76 662 if (!in_array($value, $smiley_sets) && $value != \'none\')
Chris@76 663 $value = \'\';
Chris@76 664 return true;
Chris@76 665 '),
Chris@76 666 ),
Chris@76 667 // Pretty much a dummy entry - it populates all the theme settings.
Chris@76 668 'theme_settings' => array(
Chris@76 669 'type' => 'callback',
Chris@76 670 'callback_func' => 'theme_settings',
Chris@76 671 'permission' => 'profile_extra',
Chris@76 672 'is_dummy' => true,
Chris@76 673 'preload' => create_function('', '
Chris@76 674 loadLanguage(\'Settings\');
Chris@76 675 return true;
Chris@76 676 '),
Chris@76 677 ),
Chris@76 678 'time_format' => array(
Chris@76 679 'type' => 'callback',
Chris@76 680 'callback_func' => 'timeformat_modify',
Chris@76 681 'permission' => 'profile_extra',
Chris@76 682 'preload' => create_function('', '
Chris@76 683 global $context, $user_info, $txt, $cur_profile, $modSettings;
Chris@76 684
Chris@76 685 $context[\'easy_timeformats\'] = array(
Chris@76 686 array(\'format\' => \'\', \'title\' => $txt[\'timeformat_default\']),
Chris@76 687 array(\'format\' => \'%B %d, %Y, %I:%M:%S %p\', \'title\' => $txt[\'timeformat_easy1\']),
Chris@76 688 array(\'format\' => \'%B %d, %Y, %H:%M:%S\', \'title\' => $txt[\'timeformat_easy2\']),
Chris@76 689 array(\'format\' => \'%Y-%m-%d, %H:%M:%S\', \'title\' => $txt[\'timeformat_easy3\']),
Chris@76 690 array(\'format\' => \'%d %B %Y, %H:%M:%S\', \'title\' => $txt[\'timeformat_easy4\']),
Chris@76 691 array(\'format\' => \'%d-%m-%Y, %H:%M:%S\', \'title\' => $txt[\'timeformat_easy5\'])
Chris@76 692 );
Chris@76 693
Chris@76 694 $context[\'member\'][\'time_format\'] = $cur_profile[\'time_format\'];
Chris@76 695 $context[\'current_forum_time\'] = timeformat(time() - $user_info[\'time_offset\'] * 3600, false);
Chris@76 696 $context[\'current_forum_time_js\'] = strftime(\'%Y,\' . ((int) strftime(\'%m\', time() + $modSettings[\'time_offset\'] * 3600) - 1) . \',%d,%H,%M,%S\', time() + $modSettings[\'time_offset\'] * 3600);
Chris@76 697 $context[\'current_forum_time_hour\'] = (int) strftime(\'%H\', forum_time(false));
Chris@76 698 return true;
Chris@76 699 '),
Chris@76 700 ),
Chris@76 701 'time_offset' => array(
Chris@76 702 'type' => 'callback',
Chris@76 703 'callback_func' => 'timeoffset_modify',
Chris@76 704 'permission' => 'profile_extra',
Chris@76 705 'preload' => create_function('', '
Chris@76 706 global $context, $cur_profile;
Chris@76 707 $context[\'member\'][\'time_offset\'] = $cur_profile[\'time_offset\'];
Chris@76 708 return true;
Chris@76 709 '),
Chris@76 710 'input_validate' => create_function('&$value', '
Chris@76 711 // Validate the time_offset...
Chris@76 712 $value = (float) strtr($value, \',\', \'.\');
Chris@76 713
Chris@76 714 if ($value < -23.5 || $value > 23.5)
Chris@76 715 return \'bad_offset\';
Chris@76 716
Chris@76 717 return true;
Chris@76 718 '),
Chris@76 719 ),
Chris@76 720 'usertitle' => array(
Chris@76 721 'type' => 'text',
Chris@76 722 'label' => $txt['custom_title'],
Chris@76 723 'log_change' => true,
Chris@76 724 'size' => 50,
Chris@76 725 'permission' => 'profile_title',
Chris@76 726 'enabled' => !empty($modSettings['titlesEnable']),
Chris@76 727 ),
Chris@76 728 'website_title' => array(
Chris@76 729 'type' => 'text',
Chris@76 730 'label' => $txt['website_title'],
Chris@76 731 'subtext' => $txt['include_website_url'],
Chris@76 732 'size' => 50,
Chris@76 733 'permission' => 'profile_extra',
Chris@76 734 'link_with' => 'website',
Chris@76 735 ),
Chris@76 736 'website_url' => array(
Chris@76 737 'type' => 'text',
Chris@76 738 'label' => $txt['website_url'],
Chris@76 739 'subtext' => $txt['complete_url'],
Chris@76 740 'size' => 50,
Chris@76 741 'permission' => 'profile_extra',
Chris@76 742 // Fix the URL...
Chris@76 743 'input_validate' => create_function('&$value', '
Chris@76 744
Chris@76 745 if (strlen(trim($value)) > 0 && strpos($value, \'://\') === false)
Chris@76 746 $value = \'http://\' . $value;
Chris@76 747 if (strlen($value) < 8 || (substr($value, 0, 7) !== \'http://\' && substr($value, 0, 8) !== \'https://\'))
Chris@76 748 $value = \'\';
Chris@76 749 return true;
Chris@76 750 '),
Chris@76 751 'link_with' => 'website',
Chris@76 752 ),
Chris@76 753 'yim' => array(
Chris@76 754 'type' => 'text',
Chris@76 755 'label' => $txt['yim'],
Chris@76 756 'subtext' => $txt['your_yim'],
Chris@76 757 'size' => 24,
Chris@76 758 'input_attr' => array('maxlength="32"'),
Chris@76 759 'permission' => 'profile_extra',
Chris@76 760 ),
Chris@76 761 );
Chris@76 762
Chris@76 763 $disabled_fields = !empty($modSettings['disabled_profile_fields']) ? explode(',', $modSettings['disabled_profile_fields']) : array();
Chris@76 764 // For each of the above let's take out the bits which don't apply - to save memory and security!
Chris@76 765 foreach ($profile_fields as $key => $field)
Chris@76 766 {
Chris@76 767 // Do we have permission to do this?
Chris@76 768 if (isset($field['permission']) && !allowedTo(($context['user']['is_owner'] ? array($field['permission'] . '_own', $field['permission'] . '_any') : $field['permission'] . '_any')) && !allowedTo($field['permission']))
Chris@76 769 unset($profile_fields[$key]);
Chris@76 770
Chris@76 771 // Is it enabled?
Chris@76 772 if (isset($field['enabled']) && !$field['enabled'])
Chris@76 773 unset($profile_fields[$key]);
Chris@76 774
Chris@76 775 // Is it specifically disabled?
Chris@76 776 if (in_array($key, $disabled_fields) || (isset($field['link_with']) && in_array($field['link_with'], $disabled_fields)))
Chris@76 777 unset($profile_fields[$key]);
Chris@76 778 }
Chris@76 779 }
Chris@76 780
Chris@76 781 // Setup the context for a page load!
Chris@76 782 function setupProfileContext($fields)
Chris@76 783 {
Chris@76 784 global $profile_fields, $context, $cur_profile, $smcFunc, $txt;
Chris@76 785
Chris@76 786 // Make sure we have this!
Chris@76 787 loadProfileFields(true);
Chris@76 788
Chris@76 789 // First check for any linked sets.
Chris@76 790 foreach ($profile_fields as $key => $field)
Chris@76 791 if (isset($field['link_with']) && in_array($field['link_with'], $fields))
Chris@76 792 $fields[] = $key;
Chris@76 793
Chris@76 794 // Some default bits.
Chris@76 795 $context['profile_prehtml'] = '';
Chris@76 796 $context['profile_posthtml'] = '';
Chris@76 797 $context['profile_javascript'] = '';
Chris@76 798 $context['profile_onsubmit_javascript'] = '';
Chris@76 799
Chris@76 800 $i = 0;
Chris@76 801 $last_type = '';
Chris@76 802 foreach ($fields as $key => $field)
Chris@76 803 {
Chris@76 804 if (isset($profile_fields[$field]))
Chris@76 805 {
Chris@76 806 // Shortcut.
Chris@76 807 $cur_field = &$profile_fields[$field];
Chris@76 808
Chris@76 809 // Does it have a preload and does that preload succeed?
Chris@76 810 if (isset($cur_field['preload']) && !$cur_field['preload']())
Chris@76 811 continue;
Chris@76 812
Chris@76 813 // If this is anything but complex we need to do more cleaning!
Chris@76 814 if ($cur_field['type'] != 'callback' && $cur_field['type'] != 'hidden')
Chris@76 815 {
Chris@76 816 if (!isset($cur_field['label']))
Chris@76 817 $cur_field['label'] = isset($txt[$field]) ? $txt[$field] : $field;
Chris@76 818
Chris@76 819 // Everything has a value!
Chris@76 820 if (!isset($cur_field['value']))
Chris@76 821 {
Chris@76 822 $cur_field['value'] = isset($cur_profile[$field]) ? $cur_profile[$field] : '';
Chris@76 823 }
Chris@76 824
Chris@76 825 // Any input attributes?
Chris@76 826 $cur_field['input_attr'] = !empty($cur_field['input_attr']) ? implode(',', $cur_field['input_attr']) : '';
Chris@76 827 }
Chris@76 828
Chris@76 829 // Was there an error with this field on posting?
Chris@76 830 if (isset($context['profile_errors'][$field]))
Chris@76 831 $cur_field['is_error'] = true;
Chris@76 832
Chris@76 833 // Any javascript stuff?
Chris@76 834 if (!empty($cur_field['js_submit']))
Chris@76 835 $context['profile_onsubmit_javascript'] .= $cur_field['js_submit'];
Chris@76 836 if (!empty($cur_field['js']))
Chris@76 837 $context['profile_javascript'] .= $cur_field['js'];
Chris@76 838
Chris@76 839 // Any template stuff?
Chris@76 840 if (!empty($cur_field['prehtml']))
Chris@76 841 $context['profile_prehtml'] .= $cur_field['prehtml'];
Chris@76 842 if (!empty($cur_field['posthtml']))
Chris@76 843 $context['profile_posthtml'] .= $cur_field['posthtml'];
Chris@76 844
Chris@76 845 // Finally put it into context?
Chris@76 846 if ($cur_field['type'] != 'hidden')
Chris@76 847 {
Chris@76 848 $last_type = $cur_field['type'];
Chris@76 849 $context['profile_fields'][$field] = &$profile_fields[$field];
Chris@76 850 }
Chris@76 851 }
Chris@76 852 // Bodge in a line break - without doing two in a row ;)
Chris@76 853 elseif ($field == 'hr' && $last_type != 'hr' && $last_type != '')
Chris@76 854 {
Chris@76 855 $last_type = 'hr';
Chris@76 856 $context['profile_fields'][$i++]['type'] = 'hr';
Chris@76 857 }
Chris@76 858 }
Chris@76 859
Chris@76 860 // Free up some memory.
Chris@76 861 unset($profile_fields);
Chris@76 862 }
Chris@76 863
Chris@76 864 // Save the profile changes.
Chris@76 865 function saveProfileFields()
Chris@76 866 {
Chris@76 867 global $profile_fields, $profile_vars, $context, $old_profile, $post_errors, $sourcedir, $modSettings, $cur_profile, $smcFunc;
Chris@76 868
Chris@76 869 // Load them up.
Chris@76 870 loadProfileFields();
Chris@76 871
Chris@76 872 // This makes things easier...
Chris@76 873 $old_profile = $cur_profile;
Chris@76 874
Chris@76 875 // This allows variables to call activities when they save - by default just to reload their settings
Chris@76 876 $context['profile_execute_on_save'] = array();
Chris@76 877 if ($context['user']['is_owner'])
Chris@76 878 $context['profile_execute_on_save']['reload_user'] = 'profileReloadUser';
Chris@76 879
Chris@76 880 // Assume we log nothing.
Chris@76 881 $context['log_changes'] = array();
Chris@76 882
Chris@76 883 // Cycle through the profile fields working out what to do!
Chris@76 884 foreach ($profile_fields as $key => $field)
Chris@76 885 {
Chris@76 886 if (!isset($_POST[$key]) || !empty($field['is_dummy']))
Chris@76 887 continue;
Chris@76 888
Chris@76 889 // What gets updated?
Chris@76 890 $db_key = isset($field['save_key']) ? $field['save_key'] : $key;
Chris@76 891
Chris@76 892 // Right - we have something that is enabled, we can act upon and has a value posted to it. Does it have a validation function?
Chris@76 893 if (isset($field['input_validate']))
Chris@76 894 {
Chris@76 895 $is_valid = $field['input_validate']($_POST[$key]);
Chris@76 896 // An error occured - set it as such!
Chris@76 897 if ($is_valid !== true)
Chris@76 898 {
Chris@76 899 // Is this an actual error?
Chris@76 900 if ($is_valid !== false)
Chris@76 901 {
Chris@76 902 $post_errors[$key] = $is_valid;
Chris@76 903 $profile_fields[$key]['is_error'] = $is_valid;
Chris@76 904 }
Chris@76 905 // Retain the old value.
Chris@76 906 $cur_profile[$key] = $_POST[$key];
Chris@76 907 continue;
Chris@76 908 }
Chris@76 909 }
Chris@76 910
Chris@76 911 // Are we doing a cast?
Chris@76 912 $field['cast_type'] = empty($field['cast_type']) ? $field['type'] : $field['cast_type'];
Chris@76 913
Chris@76 914 // Finally, clean up certain types.
Chris@76 915 if ($field['cast_type'] == 'int')
Chris@76 916 $_POST[$key] = (int) $_POST[$key];
Chris@76 917 elseif ($field['cast_type'] == 'float')
Chris@76 918 $_POST[$key] = (float) $_POST[$key];
Chris@76 919 elseif ($field['cast_type'] == 'check')
Chris@76 920 $_POST[$key] = !empty($_POST[$key]) ? 1 : 0;
Chris@76 921
Chris@76 922 // If we got here we're doing OK.
Chris@76 923 if ($field['type'] != 'hidden' && (!isset($old_profile[$key]) || $_POST[$key] != $old_profile[$key]))
Chris@76 924 {
Chris@76 925 // Set the save variable.
Chris@76 926 $profile_vars[$db_key] = $_POST[$key];
Chris@76 927 // And update the user profile.
Chris@76 928 $cur_profile[$key] = $_POST[$key];
Chris@76 929
Chris@76 930 // Are we logging it?
Chris@76 931 if (!empty($field['log_change']) && isset($old_profile[$key]))
Chris@76 932 $context['log_changes'][$key] = array(
Chris@76 933 'previous' => $old_profile[$key],
Chris@76 934 'new' => $_POST[$key],
Chris@76 935 );
Chris@76 936 }
Chris@76 937
Chris@76 938 // Logging group changes are a bit different...
Chris@76 939 if ($key == 'id_group' && $field['log_change'])
Chris@76 940 {
Chris@76 941 profileLoadGroups();
Chris@76 942
Chris@76 943 // Any changes to primary group?
Chris@76 944 if ($_POST['id_group'] != $old_profile['id_group'])
Chris@76 945 {
Chris@76 946 $context['log_changes']['id_group'] = array(
Chris@76 947 'previous' => !empty($old_profile[$key]) && isset($context['member_groups'][$old_profile[$key]]) ? $context['member_groups'][$old_profile[$key]]['name'] : '',
Chris@76 948 'new' => !empty($_POST[$key]) && isset($context['member_groups'][$_POST[$key]]) ? $context['member_groups'][$_POST[$key]]['name'] : '',
Chris@76 949 );
Chris@76 950 }
Chris@76 951
Chris@76 952 // Prepare additional groups for comparison.
Chris@76 953 $additional_groups = array(
Chris@76 954 'previous' => !empty($old_profile['additional_groups']) ? explode(',', $old_profile['additional_groups']) : array(),
Chris@76 955 'new' => !empty($_POST['additional_groups']) ? array_diff($_POST['additional_groups'], array(0)) : array(),
Chris@76 956 );
Chris@76 957
Chris@76 958 sort($additional_groups['previous']);
Chris@76 959 sort($additional_groups['new']);
Chris@76 960
Chris@76 961 // What about additional groups?
Chris@76 962 if ($additional_groups['previous'] != $additional_groups['new'])
Chris@76 963 {
Chris@76 964 foreach ($additional_groups as $type => $groups)
Chris@76 965 {
Chris@76 966 foreach ($groups as $id => $group)
Chris@76 967 {
Chris@76 968 if (isset($context['member_groups'][$group]))
Chris@76 969 $additional_groups[$type][$id] = $context['member_groups'][$group]['name'];
Chris@76 970 else
Chris@76 971 unset($additional_groups[$type][$id]);
Chris@76 972 }
Chris@76 973 $additional_groups[$type] = implode(', ', $additional_groups[$type]);
Chris@76 974 }
Chris@76 975
Chris@76 976 $context['log_changes']['additional_groups'] = $additional_groups;
Chris@76 977 }
Chris@76 978 }
Chris@76 979 }
Chris@76 980
Chris@76 981 //!!! Temporary
Chris@76 982 if ($context['user']['is_owner'])
Chris@76 983 $changeOther = allowedTo(array('profile_extra_any', 'profile_extra_own'));
Chris@76 984 else
Chris@76 985 $changeOther = allowedTo('profile_extra_any');
Chris@76 986 if ($changeOther && empty($post_errors))
Chris@76 987 {
Chris@76 988 makeThemeChanges($context['id_member'], isset($_POST['id_theme']) ? (int) $_POST['id_theme'] : $old_profile['id_theme']);
Chris@76 989 if (!empty($_REQUEST['sa']))
Chris@76 990 makeCustomFieldChanges($context['id_member'], $_REQUEST['sa'], false);
Chris@76 991 }
Chris@76 992
Chris@76 993 // Free memory!
Chris@76 994 unset($profile_fields);
Chris@76 995 }
Chris@76 996
Chris@76 997 // Save the profile changes....
Chris@76 998 function saveProfileChanges(&$profile_vars, &$post_errors, $memID)
Chris@76 999 {
Chris@76 1000 global $user_info, $txt, $modSettings, $user_profile;
Chris@76 1001 global $context, $settings, $sourcedir;
Chris@76 1002 global $smcFunc;
Chris@76 1003
Chris@76 1004 // These make life easier....
Chris@76 1005 $old_profile = &$user_profile[$memID];
Chris@76 1006
Chris@76 1007 // Permissions...
Chris@76 1008 if ($context['user']['is_owner'])
Chris@76 1009 {
Chris@76 1010 $changeIdentity = allowedTo(array('profile_identity_any', 'profile_identity_own'));
Chris@76 1011 $changeOther = allowedTo(array('profile_extra_any', 'profile_extra_own'));
Chris@76 1012 }
Chris@76 1013 else
Chris@76 1014 {
Chris@76 1015 $changeIdentity = allowedTo('profile_identity_any');
Chris@76 1016 $changeOther = allowedTo('profile_extra_any');
Chris@76 1017 }
Chris@76 1018
Chris@76 1019 // Arrays of all the changes - makes things easier.
Chris@76 1020 $profile_bools = array(
Chris@76 1021 'notify_announcements', 'notify_send_body',
Chris@76 1022 );
Chris@76 1023 $profile_ints = array(
Chris@76 1024 'notify_regularity',
Chris@76 1025 'notify_types',
Chris@76 1026 );
Chris@76 1027 $profile_floats = array(
Chris@76 1028 );
Chris@76 1029 $profile_strings = array(
Chris@76 1030 'buddy_list',
Chris@76 1031 'ignore_boards',
Chris@76 1032 );
Chris@76 1033
Chris@76 1034 if (isset($_POST['sa']) && $_POST['sa'] == 'ignoreboards' && empty($_POST['ignore_brd']))
Chris@76 1035 $_POST['ignore_brd'] = array();
Chris@76 1036
Chris@76 1037 unset($_POST['ignore_boards']); // Whatever it is set to is a dirty fithy thing. Kinda like our minds.
Chris@76 1038 if (isset($_POST['ignore_brd']))
Chris@76 1039 {
Chris@76 1040 if (!is_array($_POST['ignore_brd']))
Chris@76 1041 $_POST['ignore_brd'] = array ($_POST['ignore_brd']);
Chris@76 1042
Chris@76 1043 foreach ($_POST['ignore_brd'] as $k => $d)
Chris@76 1044 {
Chris@76 1045 $d = (int) $d;
Chris@76 1046 if ($d != 0)
Chris@76 1047 $_POST['ignore_brd'][$k] = $d;
Chris@76 1048 else
Chris@76 1049 unset($_POST['ignore_brd'][$k]);
Chris@76 1050 }
Chris@76 1051 $_POST['ignore_boards'] = implode(',', $_POST['ignore_brd']);
Chris@76 1052 unset($_POST['ignore_brd']);
Chris@76 1053
Chris@76 1054 }
Chris@76 1055
Chris@76 1056 // Here's where we sort out all the 'other' values...
Chris@76 1057 if ($changeOther)
Chris@76 1058 {
Chris@76 1059 makeThemeChanges($memID, isset($_POST['id_theme']) ? (int) $_POST['id_theme'] : $old_profile['id_theme']);
Chris@76 1060 //makeAvatarChanges($memID, $post_errors);
Chris@76 1061 makeNotificationChanges($memID);
Chris@76 1062 if (!empty($_REQUEST['sa']))
Chris@76 1063 makeCustomFieldChanges($memID, $_REQUEST['sa'], false);
Chris@76 1064
Chris@76 1065 foreach ($profile_bools as $var)
Chris@76 1066 if (isset($_POST[$var]))
Chris@76 1067 $profile_vars[$var] = empty($_POST[$var]) ? '0' : '1';
Chris@76 1068 foreach ($profile_ints as $var)
Chris@76 1069 if (isset($_POST[$var]))
Chris@76 1070 $profile_vars[$var] = $_POST[$var] != '' ? (int) $_POST[$var] : '';
Chris@76 1071 foreach ($profile_floats as $var)
Chris@76 1072 if (isset($_POST[$var]))
Chris@76 1073 $profile_vars[$var] = (float) $_POST[$var];
Chris@76 1074 foreach ($profile_strings as $var)
Chris@76 1075 if (isset($_POST[$var]))
Chris@76 1076 $profile_vars[$var] = $_POST[$var];
Chris@76 1077 }
Chris@76 1078 }
Chris@76 1079
Chris@76 1080 // Make any theme changes that are sent with the profile..
Chris@76 1081 function makeThemeChanges($memID, $id_theme)
Chris@76 1082 {
Chris@76 1083 global $modSettings, $smcFunc, $context;
Chris@76 1084
Chris@76 1085 $reservedVars = array(
Chris@76 1086 'actual_theme_url',
Chris@76 1087 'actual_images_url',
Chris@76 1088 'base_theme_dir',
Chris@76 1089 'base_theme_url',
Chris@76 1090 'default_images_url',
Chris@76 1091 'default_theme_dir',
Chris@76 1092 'default_theme_url',
Chris@76 1093 'default_template',
Chris@76 1094 'images_url',
Chris@76 1095 'number_recent_posts',
Chris@76 1096 'smiley_sets_default',
Chris@76 1097 'theme_dir',
Chris@76 1098 'theme_id',
Chris@76 1099 'theme_layers',
Chris@76 1100 'theme_templates',
Chris@76 1101 'theme_url',
Chris@76 1102 );
Chris@76 1103
Chris@76 1104 // Can't change reserved vars.
Chris@76 1105 if ((isset($_POST['options']) && array_intersect($_POST['options'], $reservedVars) != array()) || (isset($_POST['default_options']) && array_intersect($_POST['default_options'], $reservedVars) != array()))
Chris@76 1106 fatal_lang_error('no_access', false);
Chris@76 1107
Chris@76 1108 // Don't allow any overriding of custom fields with default or non-default options.
Chris@76 1109 $request = $smcFunc['db_query']('', '
Chris@76 1110 SELECT col_name
Chris@76 1111 FROM {db_prefix}custom_fields
Chris@76 1112 WHERE active = {int:is_active}',
Chris@76 1113 array(
Chris@76 1114 'is_active' => 1,
Chris@76 1115 )
Chris@76 1116 );
Chris@76 1117 $custom_fields = array();
Chris@76 1118 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1119 $custom_fields[] = $row['col_name'];
Chris@76 1120 $smcFunc['db_free_result']($request);
Chris@76 1121
Chris@76 1122 // These are the theme changes...
Chris@76 1123 $themeSetArray = array();
Chris@76 1124 if (isset($_POST['options']) && is_array($_POST['options']))
Chris@76 1125 {
Chris@76 1126 foreach ($_POST['options'] as $opt => $val)
Chris@76 1127 {
Chris@76 1128 if (in_array($opt, $custom_fields))
Chris@76 1129 continue;
Chris@76 1130
Chris@76 1131 // These need to be controlled.
Chris@76 1132 if ($opt == 'topics_per_page' || $opt == 'messages_per_page')
Chris@76 1133 $val = max(0, min($val, 50));
Chris@76 1134
Chris@76 1135 $themeSetArray[] = array($memID, $id_theme, $opt, is_array($val) ? implode(',', $val) : $val);
Chris@76 1136 }
Chris@76 1137 }
Chris@76 1138
Chris@76 1139 $erase_options = array();
Chris@76 1140 if (isset($_POST['default_options']) && is_array($_POST['default_options']))
Chris@76 1141 foreach ($_POST['default_options'] as $opt => $val)
Chris@76 1142 {
Chris@76 1143 if (in_array($opt, $custom_fields))
Chris@76 1144 continue;
Chris@76 1145
Chris@76 1146 // These need to be controlled.
Chris@76 1147 if ($opt == 'topics_per_page' || $opt == 'messages_per_page')
Chris@76 1148 $val = max(0, min($val, 50));
Chris@76 1149
Chris@76 1150 $themeSetArray[] = array($memID, 1, $opt, is_array($val) ? implode(',', $val) : $val);
Chris@76 1151 $erase_options[] = $opt;
Chris@76 1152 }
Chris@76 1153
Chris@76 1154 // If themeSetArray isn't still empty, send it to the database.
Chris@76 1155 if (empty($context['password_auth_failed']))
Chris@76 1156 {
Chris@76 1157 if (!empty($themeSetArray))
Chris@76 1158 {
Chris@76 1159 $smcFunc['db_insert']('replace',
Chris@76 1160 '{db_prefix}themes',
Chris@76 1161 array('id_member' => 'int', 'id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'),
Chris@76 1162 $themeSetArray,
Chris@76 1163 array('id_member', 'id_theme', 'variable')
Chris@76 1164 );
Chris@76 1165 }
Chris@76 1166
Chris@76 1167 if (!empty($erase_options))
Chris@76 1168 {
Chris@76 1169 $smcFunc['db_query']('', '
Chris@76 1170 DELETE FROM {db_prefix}themes
Chris@76 1171 WHERE id_theme != {int:id_theme}
Chris@76 1172 AND variable IN ({array_string:erase_variables})
Chris@76 1173 AND id_member = {int:id_member}',
Chris@76 1174 array(
Chris@76 1175 'id_theme' => 1,
Chris@76 1176 'id_member' => $memID,
Chris@76 1177 'erase_variables' => $erase_options
Chris@76 1178 )
Chris@76 1179 );
Chris@76 1180 }
Chris@76 1181
Chris@76 1182 $themes = explode(',', $modSettings['knownThemes']);
Chris@76 1183 foreach ($themes as $t)
Chris@76 1184 cache_put_data('theme_settings-' . $t . ':' . $memID, null, 60);
Chris@76 1185 }
Chris@76 1186 }
Chris@76 1187
Chris@76 1188 // Make any notification changes that need to be made.
Chris@76 1189 function makeNotificationChanges($memID)
Chris@76 1190 {
Chris@76 1191 global $smcFunc;
Chris@76 1192
Chris@76 1193 // Update the boards they are being notified on.
Chris@76 1194 if (isset($_POST['edit_notify_boards']) && !empty($_POST['notify_boards']))
Chris@76 1195 {
Chris@76 1196 // Make sure only integers are deleted.
Chris@76 1197 foreach ($_POST['notify_boards'] as $index => $id)
Chris@76 1198 $_POST['notify_boards'][$index] = (int) $id;
Chris@76 1199
Chris@76 1200 // id_board = 0 is reserved for topic notifications.
Chris@76 1201 $_POST['notify_boards'] = array_diff($_POST['notify_boards'], array(0));
Chris@76 1202
Chris@76 1203 $smcFunc['db_query']('', '
Chris@76 1204 DELETE FROM {db_prefix}log_notify
Chris@76 1205 WHERE id_board IN ({array_int:board_list})
Chris@76 1206 AND id_member = {int:selected_member}',
Chris@76 1207 array(
Chris@76 1208 'board_list' => $_POST['notify_boards'],
Chris@76 1209 'selected_member' => $memID,
Chris@76 1210 )
Chris@76 1211 );
Chris@76 1212 }
Chris@76 1213
Chris@76 1214 // We are editing topic notifications......
Chris@76 1215 elseif (isset($_POST['edit_notify_topics']) && !empty($_POST['notify_topics']))
Chris@76 1216 {
Chris@76 1217 foreach ($_POST['notify_topics'] as $index => $id)
Chris@76 1218 $_POST['notify_topics'][$index] = (int) $id;
Chris@76 1219
Chris@76 1220 // Make sure there are no zeros left.
Chris@76 1221 $_POST['notify_topics'] = array_diff($_POST['notify_topics'], array(0));
Chris@76 1222
Chris@76 1223 $smcFunc['db_query']('', '
Chris@76 1224 DELETE FROM {db_prefix}log_notify
Chris@76 1225 WHERE id_topic IN ({array_int:topic_list})
Chris@76 1226 AND id_member = {int:selected_member}',
Chris@76 1227 array(
Chris@76 1228 'topic_list' => $_POST['notify_topics'],
Chris@76 1229 'selected_member' => $memID,
Chris@76 1230 )
Chris@76 1231 );
Chris@76 1232 }
Chris@76 1233 }
Chris@76 1234
Chris@76 1235 // Save any changes to the custom profile fields...
Chris@76 1236 function makeCustomFieldChanges($memID, $area, $sanitize = true)
Chris@76 1237 {
Chris@76 1238 global $context, $smcFunc, $user_profile, $user_info, $modSettings;
Chris@76 1239
Chris@76 1240 if ($sanitize && isset($_POST['customfield']))
Chris@76 1241 $_POST['customfield'] = htmlspecialchars__recursive($_POST['customfield']);
Chris@76 1242
Chris@76 1243 $where = $area == 'register' ? 'show_reg != 0' : 'show_profile = {string:area}';
Chris@76 1244
Chris@76 1245 // Load the fields we are saving too - make sure we save valid data (etc).
Chris@76 1246 $request = $smcFunc['db_query']('', '
Chris@76 1247 SELECT col_name, field_name, field_desc, field_type, field_length, field_options, default_value, show_reg, mask, private
Chris@76 1248 FROM {db_prefix}custom_fields
Chris@76 1249 WHERE ' . $where . '
Chris@76 1250 AND active = {int:is_active}',
Chris@76 1251 array(
Chris@76 1252 'is_active' => 1,
Chris@76 1253 'area' => $area,
Chris@76 1254 )
Chris@76 1255 );
Chris@76 1256 $changes = array();
Chris@76 1257 $log_changes = array();
Chris@76 1258 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1259 {
Chris@76 1260 /* This means don't save if:
Chris@76 1261 - The user is NOT an admin.
Chris@76 1262 - The data is not freely viewable and editable by users.
Chris@76 1263 - The data is not invisible to users but editable by the owner (or if it is the user is not the owner)
Chris@76 1264 - The area isn't registration, and if it is that the field is not suppossed to be shown there.
Chris@76 1265 */
Chris@76 1266 if ($row['private'] != 0 && !allowedTo('admin_forum') && ($memID != $user_info['id'] || $row['private'] != 2) && ($area != 'register' || $row['show_reg'] == 0))
Chris@76 1267 continue;
Chris@76 1268
Chris@76 1269 // Validate the user data.
Chris@76 1270 if ($row['field_type'] == 'check')
Chris@76 1271 $value = isset($_POST['customfield'][$row['col_name']]) ? 1 : 0;
Chris@76 1272 elseif ($row['field_type'] == 'select' || $row['field_type'] == 'radio')
Chris@76 1273 {
Chris@76 1274 $value = $row['default_value'];
Chris@76 1275 foreach (explode(',', $row['field_options']) as $k => $v)
Chris@76 1276 if (isset($_POST['customfield'][$row['col_name']]) && $_POST['customfield'][$row['col_name']] == $k)
Chris@76 1277 $value = $v;
Chris@76 1278 }
Chris@76 1279 // Otherwise some form of text!
Chris@76 1280 else
Chris@76 1281 {
Chris@76 1282 $value = isset($_POST['customfield'][$row['col_name']]) ? $_POST['customfield'][$row['col_name']] : '';
Chris@76 1283 if ($row['field_length'])
Chris@76 1284 $value = $smcFunc['substr']($value, 0, $row['field_length']);
Chris@76 1285
Chris@76 1286 // Any masks?
Chris@76 1287 if ($row['field_type'] == 'text' && !empty($row['mask']) && $row['mask'] != 'none')
Chris@76 1288 {
Chris@76 1289 //!!! We never error on this - just ignore it at the moment...
Chris@76 1290 if ($row['mask'] == 'email' && (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $value) === 0 || strlen($value) > 255))
Chris@76 1291 $value = '';
Chris@76 1292 elseif ($row['mask'] == 'number')
Chris@76 1293 {
Chris@76 1294 $value = (int) $value;
Chris@76 1295 }
Chris@76 1296 elseif (substr($row['mask'], 0, 5) == 'regex' && preg_match(substr($row['mask'], 5), $value) === 0)
Chris@76 1297 $value = '';
Chris@76 1298 }
Chris@76 1299 }
Chris@76 1300
Chris@76 1301 // Did it change?
Chris@76 1302 if (!isset($user_profile[$memID]['options'][$row['col_name']]) || $user_profile[$memID]['options'][$row['col_name']] != $value)
Chris@76 1303 {
Chris@76 1304 $log_changes[] = array(
Chris@76 1305 'action' => 'customfield_' . $row['col_name'],
Chris@76 1306 'id_log' => 2,
Chris@76 1307 'log_time' => time(),
Chris@76 1308 'id_member' => $memID,
Chris@76 1309 'ip' => $user_info['ip'],
Chris@76 1310 'extra' => serialize(array('previous' => !empty($user_profile[$memID]['options'][$row['col_name']]) ? $user_profile[$memID]['options'][$row['col_name']] : '', 'new' => $value, 'applicator' => $user_info['id'])),
Chris@76 1311 );
Chris@76 1312 $changes[] = array(1, $row['col_name'], $value, $memID);
Chris@76 1313 $user_profile[$memID]['options'][$row['col_name']] = $value;
Chris@76 1314 }
Chris@76 1315 }
Chris@76 1316 $smcFunc['db_free_result']($request);
Chris@76 1317
Chris@76 1318 // Make those changes!
Chris@76 1319 if (!empty($changes) && empty($context['password_auth_failed']))
Chris@76 1320 {
Chris@76 1321 $smcFunc['db_insert']('replace',
Chris@76 1322 '{db_prefix}themes',
Chris@76 1323 array('id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-65534', 'id_member' => 'int'),
Chris@76 1324 $changes,
Chris@76 1325 array('id_theme', 'variable', 'id_member')
Chris@76 1326 );
Chris@76 1327 if (!empty($log_changes) && !empty($modSettings['modlog_enabled']))
Chris@76 1328 $smcFunc['db_insert']('',
Chris@76 1329 '{db_prefix}log_actions',
Chris@76 1330 array(
Chris@76 1331 'action' => 'string', 'id_log' => 'int', 'log_time' => 'int', 'id_member' => 'int', 'ip' => 'string-16',
Chris@76 1332 'extra' => 'string-65534',
Chris@76 1333 ),
Chris@76 1334 $log_changes,
Chris@76 1335 array('id_action')
Chris@76 1336 );
Chris@76 1337 }
Chris@76 1338 }
Chris@76 1339
Chris@76 1340 // Show all the users buddies, as well as a add/delete interface.
Chris@76 1341 function editBuddyIgnoreLists($memID)
Chris@76 1342 {
Chris@76 1343 global $sourcedir, $context, $txt, $scripturl, $modSettings, $user_profile;
Chris@76 1344
Chris@76 1345 // Do a quick check to ensure people aren't getting here illegally!
Chris@76 1346 if (!$context['user']['is_owner'] || empty($modSettings['enable_buddylist']))
Chris@76 1347 fatal_lang_error('no_access', false);
Chris@76 1348
Chris@76 1349 // Can we email the user direct?
Chris@76 1350 $context['can_moderate_forum'] = allowedTo('moderate_forum');
Chris@76 1351
Chris@76 1352 $subActions = array(
Chris@76 1353 'buddies' => array('editBuddies', $txt['editBuddies']),
Chris@76 1354 'ignore' => array('editIgnoreList', $txt['editIgnoreList']),
Chris@76 1355 );
Chris@76 1356
Chris@76 1357 $context['list_area'] = isset($_GET['sa']) && isset($subActions[$_GET['sa']]) ? $_GET['sa'] : 'buddies';
Chris@76 1358
Chris@76 1359 // Create the tabs for the template.
Chris@76 1360 $context[$context['profile_menu_name']]['tab_data'] = array(
Chris@76 1361 'title' => $txt['editBuddyIgnoreLists'],
Chris@76 1362 'description' => $txt['buddy_ignore_desc'],
Chris@76 1363 'icon' => 'profile_sm.gif',
Chris@76 1364 'tabs' => array(
Chris@76 1365 'buddies' => array(),
Chris@76 1366 'ignore' => array(),
Chris@76 1367 ),
Chris@76 1368 );
Chris@76 1369
Chris@76 1370 // Pass on to the actual function.
Chris@76 1371 $context['sub_template'] = $subActions[$context['list_area']][0];
Chris@76 1372 $subActions[$context['list_area']][0]($memID);
Chris@76 1373 }
Chris@76 1374
Chris@76 1375 // Show all the users buddies, as well as a add/delete interface.
Chris@76 1376 function editBuddies($memID)
Chris@76 1377 {
Chris@76 1378 global $txt, $scripturl, $modSettings;
Chris@76 1379 global $context, $user_profile, $memberContext, $smcFunc;
Chris@76 1380
Chris@76 1381 // For making changes!
Chris@76 1382 $buddiesArray = explode(',', $user_profile[$memID]['buddy_list']);
Chris@76 1383 foreach ($buddiesArray as $k => $dummy)
Chris@76 1384 if ($dummy == '')
Chris@76 1385 unset($buddiesArray[$k]);
Chris@76 1386
Chris@76 1387 // Removing a buddy?
Chris@76 1388 if (isset($_GET['remove']))
Chris@76 1389 {
Chris@76 1390 checkSession('get');
Chris@76 1391
Chris@76 1392 // Heh, I'm lazy, do it the easy way...
Chris@76 1393 foreach ($buddiesArray as $key => $buddy)
Chris@76 1394 if ($buddy == (int) $_GET['remove'])
Chris@76 1395 unset($buddiesArray[$key]);
Chris@76 1396
Chris@76 1397 // Make the changes.
Chris@76 1398 $user_profile[$memID]['buddy_list'] = implode(',', $buddiesArray);
Chris@76 1399 updateMemberData($memID, array('buddy_list' => $user_profile[$memID]['buddy_list']));
Chris@76 1400
Chris@76 1401 // Redirect off the page because we don't like all this ugly query stuff to stick in the history.
Chris@76 1402 redirectexit('action=profile;area=lists;sa=buddies;u=' . $memID);
Chris@76 1403 }
Chris@76 1404 elseif (isset($_POST['new_buddy']))
Chris@76 1405 {
Chris@76 1406 // Prepare the string for extraction...
Chris@76 1407 $_POST['new_buddy'] = strtr($smcFunc['htmlspecialchars']($_POST['new_buddy'], ENT_QUOTES), array('&quot;' => '"'));
Chris@76 1408 preg_match_all('~"([^"]+)"~', $_POST['new_buddy'], $matches);
Chris@76 1409 $new_buddies = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_POST['new_buddy']))));
Chris@76 1410
Chris@76 1411 foreach ($new_buddies as $k => $dummy)
Chris@76 1412 {
Chris@76 1413 $new_buddies[$k] = strtr(trim($new_buddies[$k]), array('\'' => '&#039;'));
Chris@76 1414
Chris@76 1415 if (strlen($new_buddies[$k]) == 0 || in_array($new_buddies[$k], array($user_profile[$memID]['member_name'], $user_profile[$memID]['real_name'])))
Chris@76 1416 unset($new_buddies[$k]);
Chris@76 1417 }
Chris@76 1418
Chris@76 1419 if (!empty($new_buddies))
Chris@76 1420 {
Chris@76 1421 // Now find out the id_member of the buddy.
Chris@76 1422 $request = $smcFunc['db_query']('', '
Chris@76 1423 SELECT id_member
Chris@76 1424 FROM {db_prefix}members
Chris@76 1425 WHERE member_name IN ({array_string:new_buddies}) OR real_name IN ({array_string:new_buddies})
Chris@76 1426 LIMIT {int:count_new_buddies}',
Chris@76 1427 array(
Chris@76 1428 'new_buddies' => $new_buddies,
Chris@76 1429 'count_new_buddies' => count($new_buddies),
Chris@76 1430 )
Chris@76 1431 );
Chris@76 1432
Chris@76 1433 // Add the new member to the buddies array.
Chris@76 1434 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1435 $buddiesArray[] = (int) $row['id_member'];
Chris@76 1436 $smcFunc['db_free_result']($request);
Chris@76 1437
Chris@76 1438 // Now update the current users buddy list.
Chris@76 1439 $user_profile[$memID]['buddy_list'] = implode(',', $buddiesArray);
Chris@76 1440 updateMemberData($memID, array('buddy_list' => $user_profile[$memID]['buddy_list']));
Chris@76 1441 }
Chris@76 1442
Chris@76 1443 // Back to the buddy list!
Chris@76 1444 redirectexit('action=profile;area=lists;sa=buddies;u=' . $memID);
Chris@76 1445 }
Chris@76 1446
Chris@76 1447 // Get all the users "buddies"...
Chris@76 1448 $buddies = array();
Chris@76 1449
Chris@76 1450 if (!empty($buddiesArray))
Chris@76 1451 {
Chris@76 1452 $result = $smcFunc['db_query']('', '
Chris@76 1453 SELECT id_member
Chris@76 1454 FROM {db_prefix}members
Chris@76 1455 WHERE id_member IN ({array_int:buddy_list})
Chris@76 1456 ORDER BY real_name
Chris@76 1457 LIMIT {int:buddy_list_count}',
Chris@76 1458 array(
Chris@76 1459 'buddy_list' => $buddiesArray,
Chris@76 1460 'buddy_list_count' => substr_count($user_profile[$memID]['buddy_list'], ',') + 1,
Chris@76 1461 )
Chris@76 1462 );
Chris@76 1463 while ($row = $smcFunc['db_fetch_assoc']($result))
Chris@76 1464 $buddies[] = $row['id_member'];
Chris@76 1465 $smcFunc['db_free_result']($result);
Chris@76 1466 }
Chris@76 1467
Chris@76 1468 $context['buddy_count'] = count($buddies);
Chris@76 1469
Chris@76 1470 // Load all the members up.
Chris@76 1471 loadMemberData($buddies, false, 'profile');
Chris@76 1472
Chris@76 1473 // Setup the context for each buddy.
Chris@76 1474 $context['buddies'] = array();
Chris@76 1475 foreach ($buddies as $buddy)
Chris@76 1476 {
Chris@76 1477 loadMemberContext($buddy);
Chris@76 1478 $context['buddies'][$buddy] = $memberContext[$buddy];
Chris@76 1479 }
Chris@76 1480 }
Chris@76 1481
Chris@76 1482 // Allows the user to view their ignore list, as well as the option to manage members on it.
Chris@76 1483 function editIgnoreList($memID)
Chris@76 1484 {
Chris@76 1485 global $txt, $scripturl, $modSettings;
Chris@76 1486 global $context, $user_profile, $memberContext, $smcFunc;
Chris@76 1487
Chris@76 1488 // For making changes!
Chris@76 1489 $ignoreArray = explode(',', $user_profile[$memID]['pm_ignore_list']);
Chris@76 1490 foreach ($ignoreArray as $k => $dummy)
Chris@76 1491 if ($dummy == '')
Chris@76 1492 unset($ignoreArray[$k]);
Chris@76 1493
Chris@76 1494 // Removing a member from the ignore list?
Chris@76 1495 if (isset($_GET['remove']))
Chris@76 1496 {
Chris@76 1497 checkSession('get');
Chris@76 1498
Chris@76 1499 // Heh, I'm lazy, do it the easy way...
Chris@76 1500 foreach ($ignoreArray as $key => $id_remove)
Chris@76 1501 if ($id_remove == (int) $_GET['remove'])
Chris@76 1502 unset($ignoreArray[$key]);
Chris@76 1503
Chris@76 1504 // Make the changes.
Chris@76 1505 $user_profile[$memID]['pm_ignore_list'] = implode(',', $ignoreArray);
Chris@76 1506 updateMemberData($memID, array('pm_ignore_list' => $user_profile[$memID]['pm_ignore_list']));
Chris@76 1507
Chris@76 1508 // Redirect off the page because we don't like all this ugly query stuff to stick in the history.
Chris@76 1509 redirectexit('action=profile;area=lists;sa=ignore;u=' . $memID);
Chris@76 1510 }
Chris@76 1511 elseif (isset($_POST['new_ignore']))
Chris@76 1512 {
Chris@76 1513 // Prepare the string for extraction...
Chris@76 1514 $_POST['new_ignore'] = strtr($smcFunc['htmlspecialchars']($_POST['new_ignore'], ENT_QUOTES), array('&quot;' => '"'));
Chris@76 1515 preg_match_all('~"([^"]+)"~', $_POST['new_ignore'], $matches);
Chris@76 1516 $new_entries = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_POST['new_ignore']))));
Chris@76 1517
Chris@76 1518 foreach ($new_entries as $k => $dummy)
Chris@76 1519 {
Chris@76 1520 $new_entries[$k] = strtr(trim($new_entries[$k]), array('\'' => '&#039;'));
Chris@76 1521
Chris@76 1522 if (strlen($new_entries[$k]) == 0 || in_array($new_entries[$k], array($user_profile[$memID]['member_name'], $user_profile[$memID]['real_name'])))
Chris@76 1523 unset($new_entries[$k]);
Chris@76 1524 }
Chris@76 1525
Chris@76 1526 if (!empty($new_entries))
Chris@76 1527 {
Chris@76 1528 // Now find out the id_member for the members in question.
Chris@76 1529 $request = $smcFunc['db_query']('', '
Chris@76 1530 SELECT id_member
Chris@76 1531 FROM {db_prefix}members
Chris@76 1532 WHERE member_name IN ({array_string:new_entries}) OR real_name IN ({array_string:new_entries})
Chris@76 1533 LIMIT {int:count_new_entries}',
Chris@76 1534 array(
Chris@76 1535 'new_entries' => $new_entries,
Chris@76 1536 'count_new_entries' => count($new_entries),
Chris@76 1537 )
Chris@76 1538 );
Chris@76 1539
Chris@76 1540 // Add the new member to the buddies array.
Chris@76 1541 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 1542 $ignoreArray[] = (int) $row['id_member'];
Chris@76 1543 $smcFunc['db_free_result']($request);
Chris@76 1544
Chris@76 1545 // Now update the current users buddy list.
Chris@76 1546 $user_profile[$memID]['pm_ignore_list'] = implode(',', $ignoreArray);
Chris@76 1547 updateMemberData($memID, array('pm_ignore_list' => $user_profile[$memID]['pm_ignore_list']));
Chris@76 1548 }
Chris@76 1549
Chris@76 1550 // Back to the list of pityful people!
Chris@76 1551 redirectexit('action=profile;area=lists;sa=ignore;u=' . $memID);
Chris@76 1552 }
Chris@76 1553
Chris@76 1554 // Initialise the list of members we're ignoring.
Chris@76 1555 $ignored = array();
Chris@76 1556
Chris@76 1557 if (!empty($ignoreArray))
Chris@76 1558 {
Chris@76 1559 $result = $smcFunc['db_query']('', '
Chris@76 1560 SELECT id_member
Chris@76 1561 FROM {db_prefix}members
Chris@76 1562 WHERE id_member IN ({array_int:ignore_list})
Chris@76 1563 ORDER BY real_name
Chris@76 1564 LIMIT {int:ignore_list_count}',
Chris@76 1565 array(
Chris@76 1566 'ignore_list' => $ignoreArray,
Chris@76 1567 'ignore_list_count' => substr_count($user_profile[$memID]['pm_ignore_list'], ',') + 1,
Chris@76 1568 )
Chris@76 1569 );
Chris@76 1570 while ($row = $smcFunc['db_fetch_assoc']($result))
Chris@76 1571 $ignored[] = $row['id_member'];
Chris@76 1572 $smcFunc['db_free_result']($result);
Chris@76 1573 }
Chris@76 1574
Chris@76 1575 $context['ignore_count'] = count($ignored);
Chris@76 1576
Chris@76 1577 // Load all the members up.
Chris@76 1578 loadMemberData($ignored, false, 'profile');
Chris@76 1579
Chris@76 1580 // Setup the context for each buddy.
Chris@76 1581 $context['ignore_list'] = array();
Chris@76 1582 foreach ($ignored as $ignore_member)
Chris@76 1583 {
Chris@76 1584 loadMemberContext($ignore_member);
Chris@76 1585 $context['ignore_list'][$ignore_member] = $memberContext[$ignore_member];
Chris@76 1586 }
Chris@76 1587 }
Chris@76 1588
Chris@76 1589 function account($memID)
Chris@76 1590 {
Chris@76 1591 global $context, $txt;
Chris@76 1592
Chris@76 1593 loadThemeOptions($memID);
Chris@76 1594 if (allowedTo(array('profile_identity_own', 'profile_identity_any')))
Chris@76 1595 loadCustomFields($memID, 'account');
Chris@76 1596
Chris@76 1597 $context['sub_template'] = 'edit_options';
Chris@76 1598 $context['page_desc'] = $txt['account_info'];
Chris@76 1599
Chris@76 1600 setupProfileContext(
Chris@76 1601 array(
Chris@76 1602 'member_name', 'real_name', 'date_registered', 'posts', 'lngfile', 'hr',
Chris@76 1603 'id_group', 'hr',
Chris@76 1604 'email_address', 'hide_email', 'show_online', 'hr',
Chris@76 1605 'passwrd1', 'passwrd2', 'hr',
Chris@76 1606 'secret_question', 'secret_answer',
Chris@76 1607 )
Chris@76 1608 );
Chris@76 1609 }
Chris@76 1610
Chris@76 1611 function forumProfile($memID)
Chris@76 1612 {
Chris@76 1613 global $context, $user_profile, $user_info, $txt, $modSettings;
Chris@76 1614
Chris@76 1615 loadThemeOptions($memID);
Chris@76 1616 if (allowedTo(array('profile_extra_own', 'profile_extra_any')))
Chris@76 1617 loadCustomFields($memID, 'forumprofile');
Chris@76 1618
Chris@76 1619 $context['sub_template'] = 'edit_options';
Chris@76 1620 $context['page_desc'] = $txt['forumProfile_info'];
Chris@76 1621
Chris@76 1622 setupProfileContext(
Chris@76 1623 array(
Chris@76 1624 'avatar_choice', 'hr', 'personal_text', 'hr',
Chris@76 1625 'bday1', 'location', 'gender', 'hr',
Chris@76 1626 'icq', 'aim', 'msn', 'yim', 'hr',
Chris@76 1627 'usertitle', 'signature', 'hr',
Chris@76 1628 'karma_good', 'hr',
Chris@76 1629 'website_title', 'website_url',
Chris@76 1630 )
Chris@76 1631 );
Chris@76 1632 }
Chris@76 1633
Chris@76 1634 // Allow the edit of *someone elses* personal message settings.
Chris@76 1635 function pmprefs($memID)
Chris@76 1636 {
Chris@76 1637 global $sourcedir, $context, $txt, $scripturl;
Chris@76 1638
Chris@76 1639 loadThemeOptions($memID);
Chris@76 1640 loadCustomFields($memID, 'pmprefs');
Chris@76 1641
Chris@76 1642 $context['sub_template'] = 'edit_options';
Chris@76 1643 $context['page_desc'] = $txt['pm_settings_desc'];
Chris@76 1644
Chris@76 1645 setupProfileContext(
Chris@76 1646 array(
Chris@76 1647 'pm_prefs',
Chris@76 1648 )
Chris@76 1649 );
Chris@76 1650 }
Chris@76 1651
Chris@76 1652 // Recursive function to retrieve avatar files
Chris@76 1653 function getAvatars($directory, $level)
Chris@76 1654 {
Chris@76 1655 global $context, $txt, $modSettings;
Chris@76 1656
Chris@76 1657 $result = array();
Chris@76 1658
Chris@76 1659 // Open the directory..
Chris@76 1660 $dir = dir($modSettings['avatar_directory'] . (!empty($directory) ? '/' : '') . $directory);
Chris@76 1661 $dirs = array();
Chris@76 1662 $files = array();
Chris@76 1663
Chris@76 1664 if (!$dir)
Chris@76 1665 return array();
Chris@76 1666
Chris@76 1667 while ($line = $dir->read())
Chris@76 1668 {
Chris@76 1669 if (in_array($line, array('.', '..', 'blank.gif', 'index.php')))
Chris@76 1670 continue;
Chris@76 1671
Chris@76 1672 if (is_dir($modSettings['avatar_directory'] . '/' . $directory . (!empty($directory) ? '/' : '') . $line))
Chris@76 1673 $dirs[] = $line;
Chris@76 1674 else
Chris@76 1675 $files[] = $line;
Chris@76 1676 }
Chris@76 1677 $dir->close();
Chris@76 1678
Chris@76 1679 // Sort the results...
Chris@76 1680 natcasesort($dirs);
Chris@76 1681 natcasesort($files);
Chris@76 1682
Chris@76 1683 if ($level == 0)
Chris@76 1684 {
Chris@76 1685 $result[] = array(
Chris@76 1686 'filename' => 'blank.gif',
Chris@76 1687 'checked' => in_array($context['member']['avatar']['server_pic'], array('', 'blank.gif')),
Chris@76 1688 'name' => $txt['no_pic'],
Chris@76 1689 'is_dir' => false
Chris@76 1690 );
Chris@76 1691 }
Chris@76 1692
Chris@76 1693 foreach ($dirs as $line)
Chris@76 1694 {
Chris@76 1695 $tmp = getAvatars($directory . (!empty($directory) ? '/' : '') . $line, $level + 1);
Chris@76 1696 if (!empty($tmp))
Chris@76 1697 $result[] = array(
Chris@76 1698 'filename' => htmlspecialchars($line),
Chris@76 1699 'checked' => strpos($context['member']['avatar']['server_pic'], $line . '/') !== false,
Chris@76 1700 'name' => '[' . htmlspecialchars(str_replace('_', ' ', $line)) . ']',
Chris@76 1701 'is_dir' => true,
Chris@76 1702 'files' => $tmp
Chris@76 1703 );
Chris@76 1704 unset($tmp);
Chris@76 1705 }
Chris@76 1706
Chris@76 1707 foreach ($files as $line)
Chris@76 1708 {
Chris@76 1709 $filename = substr($line, 0, (strlen($line) - strlen(strrchr($line, '.'))));
Chris@76 1710 $extension = substr(strrchr($line, '.'), 1);
Chris@76 1711
Chris@76 1712 // Make sure it is an image.
Chris@76 1713 if (strcasecmp($extension, 'gif') != 0 && strcasecmp($extension, 'jpg') != 0 && strcasecmp($extension, 'jpeg') != 0 && strcasecmp($extension, 'png') != 0 && strcasecmp($extension, 'bmp') != 0)
Chris@76 1714 continue;
Chris@76 1715
Chris@76 1716 $result[] = array(
Chris@76 1717 'filename' => htmlspecialchars($line),
Chris@76 1718 'checked' => $line == $context['member']['avatar']['server_pic'],
Chris@76 1719 'name' => htmlspecialchars(str_replace('_', ' ', $filename)),
Chris@76 1720 'is_dir' => false
Chris@76 1721 );
Chris@76 1722 if ($level == 1)
Chris@76 1723 $context['avatar_list'][] = $directory . '/' . $line;
Chris@76 1724 }
Chris@76 1725
Chris@76 1726 return $result;
Chris@76 1727 }
Chris@76 1728
Chris@76 1729 function theme($memID)
Chris@76 1730 {
Chris@76 1731 global $txt, $context, $user_profile, $modSettings, $settings, $user_info, $smcFunc;
Chris@76 1732
Chris@76 1733 loadThemeOptions($memID);
Chris@76 1734 if (allowedTo(array('profile_extra_own', 'profile_extra_any')))
Chris@76 1735 loadCustomFields($memID, 'theme');
Chris@76 1736
Chris@76 1737 $context['sub_template'] = 'edit_options';
Chris@76 1738 $context['page_desc'] = $txt['theme_info'];
Chris@76 1739
Chris@76 1740 setupProfileContext(
Chris@76 1741 array(
Chris@76 1742 'id_theme', 'smiley_set', 'hr',
Chris@76 1743 'time_format', 'time_offset', 'hr',
Chris@76 1744 'theme_settings',
Chris@76 1745 )
Chris@76 1746 );
Chris@76 1747 }
Chris@76 1748
Chris@76 1749 // Changing authentication method? Only appropriate for people using OpenID.
Chris@76 1750 function authentication($memID, $saving = false)
Chris@76 1751 {
Chris@76 1752 global $context, $cur_profile, $sourcedir, $txt, $post_errors, $modSettings;
Chris@76 1753
Chris@76 1754 loadLanguage('Login');
Chris@76 1755
Chris@76 1756 // We are saving?
Chris@76 1757 if ($saving)
Chris@76 1758 {
Chris@76 1759 // Moving to password passed authentication?
Chris@76 1760 if ($_POST['authenticate'] == 'passwd')
Chris@76 1761 {
Chris@76 1762 // Didn't enter anything?
Chris@76 1763 if ($_POST['passwrd1'] == '')
Chris@76 1764 $post_errors[] = 'no_password';
Chris@76 1765 // Do the two entries for the password even match?
Chris@76 1766 elseif (!isset($_POST['passwrd2']) || $_POST['passwrd1'] != $_POST['passwrd2'])
Chris@76 1767 $post_errors[] = 'bad_new_password';
Chris@76 1768 // Is it valid?
Chris@76 1769 else
Chris@76 1770 {
Chris@76 1771 require_once($sourcedir . '/Subs-Auth.php');
Chris@76 1772 $passwordErrors = validatePassword($_POST['passwrd1'], $cur_profile['member_name'], array($cur_profile['real_name'], $cur_profile['email_address']));
Chris@76 1773
Chris@76 1774 // Were there errors?
Chris@76 1775 if ($passwordErrors != null)
Chris@76 1776 $post_errors[] = 'password_' . $passwordErrors;
Chris@76 1777 }
Chris@76 1778
Chris@76 1779 if (empty($post_errors))
Chris@76 1780 {
Chris@76 1781 // Integration?
Chris@76 1782 call_integration_hook('integrate_reset_pass', array($cur_profile['member_name'], $cur_profile['member_name'], $_POST['passwrd1']));
Chris@76 1783
Chris@76 1784 // Go then.
Chris@76 1785 $passwd = sha1(strtolower($cur_profile['member_name']) . un_htmlspecialchars($_POST['passwrd1']));
Chris@76 1786
Chris@76 1787 // Do the important bits.
Chris@76 1788 updateMemberData($memID, array('openid_uri' => '', 'passwd' => $passwd));
Chris@76 1789 if ($context['user']['is_owner'])
Chris@76 1790 setLoginCookie(60 * $modSettings['cookieTime'], $memID, sha1(sha1(strtolower($cur_profile['member_name']) . un_htmlspecialchars($_POST['passwrd2'])) . $cur_profile['password_salt']));
Chris@76 1791
Chris@76 1792 redirectexit('action=profile;u=' . $memID);
Chris@76 1793 }
Chris@76 1794
Chris@76 1795 return true;
Chris@76 1796 }
Chris@76 1797 // Not right yet!
Chris@76 1798 elseif ($_POST['authenticate'] == 'openid' && !empty($_POST['openid_identifier']))
Chris@76 1799 {
Chris@76 1800 require_once($sourcedir . '/Subs-OpenID.php');
Chris@76 1801 $_POST['openid_identifier'] = smf_openID_canonize($_POST['openid_identifier']);
Chris@76 1802
Chris@76 1803 if (smf_openid_member_exists($_POST['openid_identifier']))
Chris@76 1804 $post_errors[] = 'openid_in_use';
Chris@76 1805 elseif (empty($post_errors))
Chris@76 1806 {
Chris@76 1807 // Authenticate using the new OpenID URI first to make sure they didn't make a mistake.
Chris@76 1808 if ($context['user']['is_owner'])
Chris@76 1809 {
Chris@76 1810 $_SESSION['new_openid_uri'] = $_POST['openid_identifier'];
Chris@76 1811
Chris@76 1812 smf_openID_validate($_POST['openid_identifier'], false, null, 'change_uri');
Chris@76 1813 }
Chris@76 1814 else
Chris@76 1815 updateMemberData($memID, array('openid_uri' => $_POST['openid_identifier']));
Chris@76 1816 }
Chris@76 1817 }
Chris@76 1818 }
Chris@76 1819
Chris@76 1820 // Some stuff.
Chris@76 1821 $context['member']['openid_uri'] = $cur_profile['openid_uri'];
Chris@76 1822 $context['auth_method'] = empty($cur_profile['openid_uri']) ? 'password' : 'openid';
Chris@76 1823 $context['sub_template'] = 'authentication_method';
Chris@76 1824 }
Chris@76 1825
Chris@76 1826 // Display the notifications and settings for changes.
Chris@76 1827 function notification($memID)
Chris@76 1828 {
Chris@76 1829 global $txt, $scripturl, $user_profile, $user_info, $context, $modSettings, $smcFunc, $sourcedir, $settings;
Chris@76 1830
Chris@76 1831 // Gonna want this for the list.
Chris@76 1832 require_once($sourcedir . '/Subs-List.php');
Chris@76 1833
Chris@76 1834 // Fine, start with the board list.
Chris@76 1835 $listOptions = array(
Chris@76 1836 'id' => 'board_notification_list',
Chris@76 1837 'width' => '100%',
Chris@76 1838 'no_items_label' => $txt['notifications_boards_none'] . '<br /><br />' . $txt['notifications_boards_howto'],
Chris@76 1839 'no_items_align' => 'left',
Chris@76 1840 'base_href' => $scripturl . '?action=profile;u=' . $memID . ';area=notification',
Chris@76 1841 'default_sort_col' => 'board_name',
Chris@76 1842 'get_items' => array(
Chris@76 1843 'function' => 'list_getBoardNotifications',
Chris@76 1844 'params' => array(
Chris@76 1845 $memID,
Chris@76 1846 ),
Chris@76 1847 ),
Chris@76 1848 'columns' => array(
Chris@76 1849 'board_name' => array(
Chris@76 1850 'header' => array(
Chris@76 1851 'value' => $txt['notifications_boards'],
Chris@76 1852 'class' => 'lefttext first_th',
Chris@76 1853 ),
Chris@76 1854 'data' => array(
Chris@76 1855 'function' => create_function('$board', '
Chris@76 1856 global $settings, $txt;
Chris@76 1857
Chris@76 1858 $link = $board[\'link\'];
Chris@76 1859
Chris@76 1860 if ($board[\'new\'])
Chris@76 1861 $link .= \' <a href="\' . $board[\'href\'] . \'"><img src="\' . $settings[\'lang_images_url\'] . \'/new.gif" alt="\' . $txt[\'new\'] . \'" /></a>\';
Chris@76 1862
Chris@76 1863 return $link;
Chris@76 1864 '),
Chris@76 1865 ),
Chris@76 1866 'sort' => array(
Chris@76 1867 'default' => 'name',
Chris@76 1868 'reverse' => 'name DESC',
Chris@76 1869 ),
Chris@76 1870 ),
Chris@76 1871 'delete' => array(
Chris@76 1872 'header' => array(
Chris@76 1873 'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />',
Chris@76 1874 'style' => 'width: 4%;',
Chris@76 1875 ),
Chris@76 1876 'data' => array(
Chris@76 1877 'sprintf' => array(
Chris@76 1878 'format' => '<input type="checkbox" name="notify_boards[]" value="%1$d" class="input_check" />',
Chris@76 1879 'params' => array(
Chris@76 1880 'id' => false,
Chris@76 1881 ),
Chris@76 1882 ),
Chris@76 1883 'style' => 'text-align: center;',
Chris@76 1884 ),
Chris@76 1885 ),
Chris@76 1886 ),
Chris@76 1887 'form' => array(
Chris@76 1888 'href' => $scripturl . '?action=profile;area=notification;save',
Chris@76 1889 'include_sort' => true,
Chris@76 1890 'include_start' => true,
Chris@76 1891 'hidden_fields' => array(
Chris@76 1892 'u' => $memID,
Chris@76 1893 'sa' => $context['menu_item_selected'],
Chris@76 1894 $context['session_var'] => $context['session_id'],
Chris@76 1895 ),
Chris@76 1896 ),
Chris@76 1897 'additional_rows' => array(
Chris@76 1898 array(
Chris@76 1899 'position' => 'bottom_of_list',
Chris@76 1900 'value' => '<input type="submit" name="edit_notify_boards" value="' . $txt['notifications_update'] . '" class="button_submit" />',
Chris@76 1901 'align' => 'right',
Chris@76 1902 ),
Chris@76 1903 ),
Chris@76 1904 );
Chris@76 1905
Chris@76 1906 // Create the board notification list.
Chris@76 1907 createList($listOptions);
Chris@76 1908
Chris@76 1909 // Now do the topic notifications.
Chris@76 1910 $listOptions = array(
Chris@76 1911 'id' => 'topic_notification_list',
Chris@76 1912 'width' => '100%',
Chris@76 1913 'items_per_page' => $modSettings['defaultMaxMessages'],
Chris@76 1914 'no_items_label' => $txt['notifications_topics_none'] . '<br /><br />' . $txt['notifications_topics_howto'],
Chris@76 1915 'no_items_align' => 'left',
Chris@76 1916 'base_href' => $scripturl . '?action=profile;u=' . $memID . ';area=notification',
Chris@76 1917 'default_sort_col' => 'last_post',
Chris@76 1918 'get_items' => array(
Chris@76 1919 'function' => 'list_getTopicNotifications',
Chris@76 1920 'params' => array(
Chris@76 1921 $memID,
Chris@76 1922 ),
Chris@76 1923 ),
Chris@76 1924 'get_count' => array(
Chris@76 1925 'function' => 'list_getTopicNotificationCount',
Chris@76 1926 'params' => array(
Chris@76 1927 $memID,
Chris@76 1928 ),
Chris@76 1929 ),
Chris@76 1930 'columns' => array(
Chris@76 1931 'subject' => array(
Chris@76 1932 'header' => array(
Chris@76 1933 'value' => $txt['notifications_topics'],
Chris@76 1934 'class' => 'lefttext first_th',
Chris@76 1935 ),
Chris@76 1936 'data' => array(
Chris@76 1937 'function' => create_function('$topic', '
Chris@76 1938 global $settings, $txt;
Chris@76 1939
Chris@76 1940 $link = $topic[\'link\'];
Chris@76 1941
Chris@76 1942 if ($topic[\'new\'])
Chris@76 1943 $link .= \' <a href="\' . $topic[\'new_href\'] . \'"><img src="\' . $settings[\'lang_images_url\'] . \'/new.gif" alt="\' . $txt[\'new\'] . \'" /></a>\';
Chris@76 1944
Chris@76 1945 $link .= \'<br /><span class="smalltext"><em>\' . $txt[\'in\'] . \' \' . $topic[\'board_link\'] . \'</em></span>\';
Chris@76 1946
Chris@76 1947 return $link;
Chris@76 1948 '),
Chris@76 1949 ),
Chris@76 1950 'sort' => array(
Chris@76 1951 'default' => 'ms.subject',
Chris@76 1952 'reverse' => 'ms.subject DESC',
Chris@76 1953 ),
Chris@76 1954 ),
Chris@76 1955 'started_by' => array(
Chris@76 1956 'header' => array(
Chris@76 1957 'value' => $txt['started_by'],
Chris@76 1958 'class' => 'lefttext',
Chris@76 1959 ),
Chris@76 1960 'data' => array(
Chris@76 1961 'db' => 'poster_link',
Chris@76 1962 ),
Chris@76 1963 'sort' => array(
Chris@76 1964 'default' => 'real_name_col',
Chris@76 1965 'reverse' => 'real_name_col DESC',
Chris@76 1966 ),
Chris@76 1967 ),
Chris@76 1968 'last_post' => array(
Chris@76 1969 'header' => array(
Chris@76 1970 'value' => $txt['last_post'],
Chris@76 1971 'class' => 'lefttext',
Chris@76 1972 ),
Chris@76 1973 'data' => array(
Chris@76 1974 'sprintf' => array(
Chris@76 1975 'format' => '<span class="smalltext">%1$s<br />' . $txt['by'] . ' %2$s</span>',
Chris@76 1976 'params' => array(
Chris@76 1977 'updated' => false,
Chris@76 1978 'poster_updated_link' => false,
Chris@76 1979 ),
Chris@76 1980 ),
Chris@76 1981 ),
Chris@76 1982 'sort' => array(
Chris@76 1983 'default' => 'ml.id_msg DESC',
Chris@76 1984 'reverse' => 'ml.id_msg',
Chris@76 1985 ),
Chris@76 1986 ),
Chris@76 1987 'delete' => array(
Chris@76 1988 'header' => array(
Chris@76 1989 'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />',
Chris@76 1990 'style' => 'width: 4%;',
Chris@76 1991 ),
Chris@76 1992 'data' => array(
Chris@76 1993 'sprintf' => array(
Chris@76 1994 'format' => '<input type="checkbox" name="notify_topics[]" value="%1$d" class="input_check" />',
Chris@76 1995 'params' => array(
Chris@76 1996 'id' => false,
Chris@76 1997 ),
Chris@76 1998 ),
Chris@76 1999 'style' => 'text-align: center;',
Chris@76 2000 ),
Chris@76 2001 ),
Chris@76 2002 ),
Chris@76 2003 'form' => array(
Chris@76 2004 'href' => $scripturl . '?action=profile;area=notification;save',
Chris@76 2005 'include_sort' => true,
Chris@76 2006 'include_start' => true,
Chris@76 2007 'hidden_fields' => array(
Chris@76 2008 'u' => $memID,
Chris@76 2009 'sa' => $context['menu_item_selected'],
Chris@76 2010 $context['session_var'] => $context['session_id'],
Chris@76 2011 ),
Chris@76 2012 ),
Chris@76 2013 'additional_rows' => array(
Chris@76 2014 array(
Chris@76 2015 'position' => 'bottom_of_list',
Chris@76 2016 'value' => '<input type="submit" name="edit_notify_topics" value="' . $txt['notifications_update'] . '" class="button_submit" />',
Chris@76 2017 'align' => 'right',
Chris@76 2018 ),
Chris@76 2019 ),
Chris@76 2020 );
Chris@76 2021
Chris@76 2022 // Create the notification list.
Chris@76 2023 createList($listOptions);
Chris@76 2024
Chris@76 2025 // What options are set?
Chris@76 2026 $context['member'] += array(
Chris@76 2027 'notify_announcements' => $user_profile[$memID]['notify_announcements'],
Chris@76 2028 'notify_send_body' => $user_profile[$memID]['notify_send_body'],
Chris@76 2029 'notify_types' => $user_profile[$memID]['notify_types'],
Chris@76 2030 'notify_regularity' => $user_profile[$memID]['notify_regularity'],
Chris@76 2031 );
Chris@76 2032
Chris@76 2033 loadThemeOptions($memID);
Chris@76 2034 }
Chris@76 2035
Chris@76 2036 function list_getTopicNotificationCount($memID)
Chris@76 2037 {
Chris@76 2038 global $smcFunc, $user_info, $context, $modSettings;
Chris@76 2039
Chris@76 2040 $request = $smcFunc['db_query']('', '
Chris@76 2041 SELECT COUNT(*)
Chris@76 2042 FROM {db_prefix}log_notify AS ln' . (!$modSettings['postmod_active'] && $user_info['query_see_board'] === '1=1' ? '' : '
Chris@76 2043 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ln.id_topic)') . ($user_info['query_see_board'] === '1=1' ? '' : '
Chris@76 2044 INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)') . '
Chris@76 2045 WHERE ln.id_member = {int:selected_member}' . ($user_info['query_see_board'] === '1=1' ? '' : '
Chris@76 2046 AND {query_see_board}') . ($modSettings['postmod_active'] ? '
Chris@76 2047 AND t.approved = {int:is_approved}' : ''),
Chris@76 2048 array(
Chris@76 2049 'selected_member' => $memID,
Chris@76 2050 'is_approved' => 1,
Chris@76 2051 )
Chris@76 2052 );
Chris@76 2053 list ($totalNotifications) = $smcFunc['db_fetch_row']($request);
Chris@76 2054 $smcFunc['db_free_result']($request);
Chris@76 2055
Chris@76 2056 return $totalNotifications;
Chris@76 2057 }
Chris@76 2058
Chris@76 2059 function list_getTopicNotifications($start, $items_per_page, $sort, $memID)
Chris@76 2060 {
Chris@76 2061 global $smcFunc, $txt, $scripturl, $user_info, $context, $modSettings;
Chris@76 2062
Chris@76 2063 // All the topics with notification on...
Chris@76 2064 $request = $smcFunc['db_query']('', '
Chris@76 2065 SELECT
Chris@76 2066 IFNULL(lt.id_msg, IFNULL(lmr.id_msg, -1)) + 1 AS new_from, b.id_board, b.name,
Chris@76 2067 t.id_topic, ms.subject, ms.id_member, IFNULL(mem.real_name, ms.poster_name) AS real_name_col,
Chris@76 2068 ml.id_msg_modified, ml.poster_time, ml.id_member AS id_member_updated,
Chris@76 2069 IFNULL(mem2.real_name, ml.poster_name) AS last_real_name
Chris@76 2070 FROM {db_prefix}log_notify AS ln
Chris@76 2071 INNER JOIN {db_prefix}topics AS t ON (t.id_topic = ln.id_topic' . ($modSettings['postmod_active'] ? ' AND t.approved = {int:is_approved}' : '') . ')
Chris@76 2072 INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board AND {query_see_board})
Chris@76 2073 INNER JOIN {db_prefix}messages AS ms ON (ms.id_msg = t.id_first_msg)
Chris@76 2074 INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
Chris@76 2075 LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ms.id_member)
Chris@76 2076 LEFT JOIN {db_prefix}members AS mem2 ON (mem2.id_member = ml.id_member)
Chris@76 2077 LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
Chris@76 2078 LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = b.id_board AND lmr.id_member = {int:current_member})
Chris@76 2079 WHERE ln.id_member = {int:selected_member}
Chris@76 2080 ORDER BY {raw:sort}
Chris@76 2081 LIMIT {int:offset}, {int:items_per_page}',
Chris@76 2082 array(
Chris@76 2083 'current_member' => $user_info['id'],
Chris@76 2084 'is_approved' => 1,
Chris@76 2085 'selected_member' => $memID,
Chris@76 2086 'sort' => $sort,
Chris@76 2087 'offset' => $start,
Chris@76 2088 'items_per_page' => $items_per_page,
Chris@76 2089 )
Chris@76 2090 );
Chris@76 2091 $notification_topics = array();
Chris@76 2092 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 2093 {
Chris@76 2094 censorText($row['subject']);
Chris@76 2095
Chris@76 2096 $notification_topics[] = array(
Chris@76 2097 'id' => $row['id_topic'],
Chris@76 2098 'poster_link' => empty($row['id_member']) ? $row['real_name_col'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name_col'] . '</a>',
Chris@76 2099 'poster_updated_link' => empty($row['id_member_updated']) ? $row['last_real_name'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member_updated'] . '">' . $row['last_real_name'] . '</a>',
Chris@76 2100 'subject' => $row['subject'],
Chris@76 2101 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0',
Chris@76 2102 'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['subject'] . '</a>',
Chris@76 2103 'new' => $row['new_from'] <= $row['id_msg_modified'],
Chris@76 2104 'new_from' => $row['new_from'],
Chris@76 2105 'updated' => timeformat($row['poster_time']),
Chris@76 2106 'new_href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new',
Chris@76 2107 'new_link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['new_from'] . '#new">' . $row['subject'] . '</a>',
Chris@76 2108 'board_link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>',
Chris@76 2109 );
Chris@76 2110 }
Chris@76 2111 $smcFunc['db_free_result']($request);
Chris@76 2112
Chris@76 2113 return $notification_topics;
Chris@76 2114 }
Chris@76 2115
Chris@76 2116 function list_getBoardNotifications($start, $items_per_page, $sort, $memID)
Chris@76 2117 {
Chris@76 2118 global $smcFunc, $txt, $scripturl, $user_info;
Chris@76 2119
Chris@76 2120 $request = $smcFunc['db_query']('', '
Chris@76 2121 SELECT b.id_board, b.name, IFNULL(lb.id_msg, 0) AS board_read, b.id_msg_updated
Chris@76 2122 FROM {db_prefix}log_notify AS ln
Chris@76 2123 INNER JOIN {db_prefix}boards AS b ON (b.id_board = ln.id_board)
Chris@76 2124 LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})
Chris@76 2125 WHERE ln.id_member = {int:selected_member}
Chris@76 2126 AND {query_see_board}
Chris@76 2127 ORDER BY ' . $sort,
Chris@76 2128 array(
Chris@76 2129 'current_member' => $user_info['id'],
Chris@76 2130 'selected_member' => $memID,
Chris@76 2131 )
Chris@76 2132 );
Chris@76 2133 $notification_boards = array();
Chris@76 2134 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 2135 $notification_boards[] = array(
Chris@76 2136 'id' => $row['id_board'],
Chris@76 2137 'name' => $row['name'],
Chris@76 2138 'href' => $scripturl . '?board=' . $row['id_board'] . '.0',
Chris@76 2139 'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['name'] . '</a>',
Chris@76 2140 'new' => $row['board_read'] < $row['id_msg_updated']
Chris@76 2141 );
Chris@76 2142 $smcFunc['db_free_result']($request);
Chris@76 2143
Chris@76 2144 return $notification_boards;
Chris@76 2145 }
Chris@76 2146
Chris@76 2147 function loadThemeOptions($memID)
Chris@76 2148 {
Chris@76 2149 global $context, $options, $cur_profile, $smcFunc;
Chris@76 2150
Chris@76 2151 if (isset($_POST['default_options']))
Chris@76 2152 $_POST['options'] = isset($_POST['options']) ? $_POST['options'] + $_POST['default_options'] : $_POST['default_options'];
Chris@76 2153
Chris@76 2154 if ($context['user']['is_owner'])
Chris@76 2155 {
Chris@76 2156 $context['member']['options'] = $options;
Chris@76 2157 if (isset($_POST['options']) && is_array($_POST['options']))
Chris@76 2158 foreach ($_POST['options'] as $k => $v)
Chris@76 2159 $context['member']['options'][$k] = $v;
Chris@76 2160 }
Chris@76 2161 else
Chris@76 2162 {
Chris@76 2163 $request = $smcFunc['db_query']('', '
Chris@76 2164 SELECT id_member, variable, value
Chris@76 2165 FROM {db_prefix}themes
Chris@76 2166 WHERE id_theme IN (1, {int:member_theme})
Chris@76 2167 AND id_member IN (-1, {int:selected_member})',
Chris@76 2168 array(
Chris@76 2169 'member_theme' => (int) $cur_profile['id_theme'],
Chris@76 2170 'selected_member' => $memID,
Chris@76 2171 )
Chris@76 2172 );
Chris@76 2173 $temp = array();
Chris@76 2174 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 2175 {
Chris@76 2176 if ($row['id_member'] == -1)
Chris@76 2177 {
Chris@76 2178 $temp[$row['variable']] = $row['value'];
Chris@76 2179 continue;
Chris@76 2180 }
Chris@76 2181
Chris@76 2182 if (isset($_POST['options'][$row['variable']]))
Chris@76 2183 $row['value'] = $_POST['options'][$row['variable']];
Chris@76 2184 $context['member']['options'][$row['variable']] = $row['value'];
Chris@76 2185 }
Chris@76 2186 $smcFunc['db_free_result']($request);
Chris@76 2187
Chris@76 2188 // Load up the default theme options for any missing.
Chris@76 2189 foreach ($temp as $k => $v)
Chris@76 2190 {
Chris@76 2191 if (!isset($context['member']['options'][$k]))
Chris@76 2192 $context['member']['options'][$k] = $v;
Chris@76 2193 }
Chris@76 2194 }
Chris@76 2195 }
Chris@76 2196
Chris@76 2197 function ignoreboards($memID)
Chris@76 2198 {
Chris@76 2199 global $txt, $user_info, $context, $modSettings, $smcFunc, $cur_profile;
Chris@76 2200
Chris@76 2201 // Have the admins enabled this option?
Chris@76 2202 if (empty($modSettings['allow_ignore_boards']))
Chris@76 2203 fatal_lang_error('ignoreboards_disallowed', 'user');
Chris@76 2204
Chris@76 2205 // Find all the boards this user is allowed to see.
Chris@76 2206 $request = $smcFunc['db_query']('order_by_board_order', '
Chris@76 2207 SELECT b.id_cat, c.name AS cat_name, b.id_board, b.name, b.child_level,
Chris@76 2208 '. (!empty($cur_profile['ignore_boards']) ? 'b.id_board IN ({array_int:ignore_boards})' : '0') . ' AS is_ignored
Chris@76 2209 FROM {db_prefix}boards AS b
Chris@76 2210 LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
Chris@76 2211 WHERE {query_see_board}
Chris@76 2212 AND redirect = {string:empty_string}',
Chris@76 2213 array(
Chris@76 2214 'ignore_boards' => !empty($cur_profile['ignore_boards']) ? explode(',', $cur_profile['ignore_boards']) : array(),
Chris@76 2215 'empty_string' => '',
Chris@76 2216 )
Chris@76 2217 );
Chris@76 2218 $context['num_boards'] = $smcFunc['db_num_rows']($request);
Chris@76 2219 $context['categories'] = array();
Chris@76 2220 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 2221 {
Chris@76 2222 // This category hasn't been set up yet..
Chris@76 2223 if (!isset($context['categories'][$row['id_cat']]))
Chris@76 2224 $context['categories'][$row['id_cat']] = array(
Chris@76 2225 'id' => $row['id_cat'],
Chris@76 2226 'name' => $row['cat_name'],
Chris@76 2227 'boards' => array()
Chris@76 2228 );
Chris@76 2229
Chris@76 2230 // Set this board up, and let the template know when it's a child. (indent them..)
Chris@76 2231 $context['categories'][$row['id_cat']]['boards'][$row['id_board']] = array(
Chris@76 2232 'id' => $row['id_board'],
Chris@76 2233 'name' => $row['name'],
Chris@76 2234 'child_level' => $row['child_level'],
Chris@76 2235 'selected' => $row['is_ignored'],
Chris@76 2236 );
Chris@76 2237 }
Chris@76 2238 $smcFunc['db_free_result']($request);
Chris@76 2239
Chris@76 2240 // Now, let's sort the list of categories into the boards for templates that like that.
Chris@76 2241 $temp_boards = array();
Chris@76 2242 foreach ($context['categories'] as $category)
Chris@76 2243 {
Chris@76 2244 // Include a list of boards per category for easy toggling.
Chris@76 2245 $context['categories'][$category['id']]['child_ids'] = array_keys($category['boards']);
Chris@76 2246
Chris@76 2247 $temp_boards[] = array(
Chris@76 2248 'name' => $category['name'],
Chris@76 2249 'child_ids' => array_keys($category['boards'])
Chris@76 2250 );
Chris@76 2251 $temp_boards = array_merge($temp_boards, array_values($category['boards']));
Chris@76 2252 }
Chris@76 2253
Chris@76 2254 $max_boards = ceil(count($temp_boards) / 2);
Chris@76 2255 if ($max_boards == 1)
Chris@76 2256 $max_boards = 2;
Chris@76 2257
Chris@76 2258 // Now, alternate them so they can be shown left and right ;).
Chris@76 2259 $context['board_columns'] = array();
Chris@76 2260 for ($i = 0; $i < $max_boards; $i++)
Chris@76 2261 {
Chris@76 2262 $context['board_columns'][] = $temp_boards[$i];
Chris@76 2263 if (isset($temp_boards[$i + $max_boards]))
Chris@76 2264 $context['board_columns'][] = $temp_boards[$i + $max_boards];
Chris@76 2265 else
Chris@76 2266 $context['board_columns'][] = array();
Chris@76 2267 }
Chris@76 2268
Chris@76 2269 loadThemeOptions($memID);
Chris@76 2270 }
Chris@76 2271
Chris@76 2272 // Load all the languages for the profile.
Chris@76 2273 function profileLoadLanguages()
Chris@76 2274 {
Chris@76 2275 global $context, $modSettings, $settings, $cur_profile, $language, $smcFunc;
Chris@76 2276
Chris@76 2277 $context['profile_languages'] = array();
Chris@76 2278
Chris@76 2279 // Get our languages!
Chris@76 2280 getLanguages(true, true);
Chris@76 2281
Chris@76 2282 // Setup our languages.
Chris@76 2283 foreach ($context['languages'] as $lang)
Chris@76 2284 {
Chris@76 2285 $context['profile_languages'][$lang['filename']] = strtr($lang['name'], array('-utf8' => ''));
Chris@76 2286 }
Chris@76 2287 ksort($context['profile_languages']);
Chris@76 2288
Chris@76 2289 // Return whether we should proceed with this.
Chris@76 2290 return count($context['profile_languages']) > 1 ? true : false;
Chris@76 2291 }
Chris@76 2292
Chris@76 2293 // Load all the group info for the profile.
Chris@76 2294 function profileLoadGroups()
Chris@76 2295 {
Chris@76 2296 global $cur_profile, $txt, $context, $smcFunc, $user_settings;
Chris@76 2297
Chris@76 2298 $context['member_groups'] = array(
Chris@76 2299 0 => array(
Chris@76 2300 'id' => 0,
Chris@76 2301 'name' => $txt['no_primary_membergroup'],
Chris@76 2302 'is_primary' => $cur_profile['id_group'] == 0,
Chris@76 2303 'can_be_additional' => false,
Chris@76 2304 'can_be_primary' => true,
Chris@76 2305 )
Chris@76 2306 );
Chris@76 2307 $curGroups = explode(',', $cur_profile['additional_groups']);
Chris@76 2308
Chris@76 2309 // Load membergroups, but only those groups the user can assign.
Chris@76 2310 $request = $smcFunc['db_query']('', '
Chris@76 2311 SELECT group_name, id_group, hidden
Chris@76 2312 FROM {db_prefix}membergroups
Chris@76 2313 WHERE id_group != {int:moderator_group}
Chris@76 2314 AND min_posts = {int:min_posts}' . (allowedTo('admin_forum') ? '' : '
Chris@76 2315 AND group_type != {int:is_protected}') . '
Chris@76 2316 ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name',
Chris@76 2317 array(
Chris@76 2318 'moderator_group' => 3,
Chris@76 2319 'min_posts' => -1,
Chris@76 2320 'is_protected' => 1,
Chris@76 2321 'newbie_group' => 4,
Chris@76 2322 )
Chris@76 2323 );
Chris@76 2324 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 2325 {
Chris@76 2326 // We should skip the administrator group if they don't have the admin_forum permission!
Chris@76 2327 if ($row['id_group'] == 1 && !allowedTo('admin_forum'))
Chris@76 2328 continue;
Chris@76 2329
Chris@76 2330 $context['member_groups'][$row['id_group']] = array(
Chris@76 2331 'id' => $row['id_group'],
Chris@76 2332 'name' => $row['group_name'],
Chris@76 2333 'is_primary' => $cur_profile['id_group'] == $row['id_group'],
Chris@76 2334 'is_additional' => in_array($row['id_group'], $curGroups),
Chris@76 2335 'can_be_additional' => true,
Chris@76 2336 'can_be_primary' => $row['hidden'] != 2,
Chris@76 2337 );
Chris@76 2338 }
Chris@76 2339 $smcFunc['db_free_result']($request);
Chris@76 2340
Chris@76 2341 $context['member']['group_id'] = $user_settings['id_group'];
Chris@76 2342
Chris@76 2343 return true;
Chris@76 2344 }
Chris@76 2345
Chris@76 2346 // Load key signature context data.
Chris@76 2347 function profileLoadSignatureData()
Chris@76 2348 {
Chris@76 2349 global $modSettings, $context, $txt, $cur_profile, $smcFunc;
Chris@76 2350
Chris@76 2351 // Signature limits.
Chris@76 2352 list ($sig_limits, $sig_bbc) = explode(':', $modSettings['signature_settings']);
Chris@76 2353 $sig_limits = explode(',', $sig_limits);
Chris@76 2354
Chris@76 2355 $context['signature_enabled'] = isset($sig_limits[0]) ? $sig_limits[0] : 0;
Chris@76 2356 $context['signature_limits'] = array(
Chris@76 2357 'max_length' => isset($sig_limits[1]) ? $sig_limits[1] : 0,
Chris@76 2358 'max_lines' => isset($sig_limits[2]) ? $sig_limits[2] : 0,
Chris@76 2359 'max_images' => isset($sig_limits[3]) ? $sig_limits[3] : 0,
Chris@76 2360 'max_smileys' => isset($sig_limits[4]) ? $sig_limits[4] : 0,
Chris@76 2361 'max_image_width' => isset($sig_limits[5]) ? $sig_limits[5] : 0,
Chris@76 2362 'max_image_height' => isset($sig_limits[6]) ? $sig_limits[6] : 0,
Chris@76 2363 'max_font_size' => isset($sig_limits[7]) ? $sig_limits[7] : 0,
Chris@76 2364 'bbc' => !empty($sig_bbc) ? explode(',', $sig_bbc) : array(),
Chris@76 2365 );
Chris@76 2366 // Kept this line in for backwards compatibility!
Chris@76 2367 $context['max_signature_length'] = $context['signature_limits']['max_length'];
Chris@76 2368 // Warning message for signature image limits?
Chris@76 2369 $context['signature_warning'] = '';
Chris@76 2370 if ($context['signature_limits']['max_image_width'] && $context['signature_limits']['max_image_height'])
Chris@76 2371 $context['signature_warning'] = sprintf($txt['profile_error_signature_max_image_size'], $context['signature_limits']['max_image_width'], $context['signature_limits']['max_image_height']);
Chris@76 2372 elseif ($context['signature_limits']['max_image_width'] || $context['signature_limits']['max_image_height'])
Chris@76 2373 $context['signature_warning'] = sprintf($txt['profile_error_signature_max_image_' . ($context['signature_limits']['max_image_width'] ? 'width' : 'height')], $context['signature_limits'][$context['signature_limits']['max_image_width'] ? 'max_image_width' : 'max_image_height']);
Chris@76 2374
Chris@76 2375 $context['show_spellchecking'] = !empty($modSettings['enableSpellChecking']) && function_exists('pspell_new');
Chris@76 2376
Chris@76 2377 $context['member']['signature'] = empty($cur_profile['signature']) ? '' : str_replace(array('<br />', '<', '>', '"', '\''), array("\n", '&lt;', '&gt;', '&quot;', '&#039;'), $cur_profile['signature']);
Chris@76 2378
Chris@76 2379 return true;
Chris@76 2380 }
Chris@76 2381
Chris@76 2382 // Load avatar context data.
Chris@76 2383 function profileLoadAvatarData()
Chris@76 2384 {
Chris@76 2385 global $context, $cur_profile, $modSettings, $scripturl;
Chris@76 2386
Chris@76 2387 $context['avatar_url'] = $modSettings['avatar_url'];
Chris@76 2388
Chris@76 2389 // Default context.
Chris@76 2390 $context['member']['avatar'] += array(
Chris@76 2391 'custom' => stristr($cur_profile['avatar'], 'http://') ? $cur_profile['avatar'] : 'http://',
Chris@76 2392 'selection' => $cur_profile['avatar'] == '' || stristr($cur_profile['avatar'], 'http://') ? '' : $cur_profile['avatar'],
Chris@76 2393 'id_attach' => $cur_profile['id_attach'],
Chris@76 2394 'filename' => $cur_profile['filename'],
Chris@76 2395 'allow_server_stored' => allowedTo('profile_server_avatar') || (!$context['user']['is_owner'] && allowedTo('profile_extra_any')),
Chris@76 2396 'allow_upload' => allowedTo('profile_upload_avatar') || (!$context['user']['is_owner'] && allowedTo('profile_extra_any')),
Chris@76 2397 'allow_external' => allowedTo('profile_remote_avatar') || (!$context['user']['is_owner'] && allowedTo('profile_extra_any')),
Chris@76 2398 );
Chris@76 2399
Chris@76 2400 if ($cur_profile['avatar'] == '' && $cur_profile['id_attach'] > 0 && $context['member']['avatar']['allow_upload'])
Chris@76 2401 {
Chris@76 2402 $context['member']['avatar'] += array(
Chris@76 2403 'choice' => 'upload',
Chris@76 2404 'server_pic' => 'blank.gif',
Chris@76 2405 'external' => 'http://'
Chris@76 2406 );
Chris@76 2407 $context['member']['avatar']['href'] = empty($cur_profile['attachment_type']) ? $scripturl . '?action=dlattach;attach=' . $cur_profile['id_attach'] . ';type=avatar' : $modSettings['custom_avatar_url'] . '/' . $cur_profile['filename'];
Chris@76 2408 }
Chris@76 2409 elseif (stristr($cur_profile['avatar'], 'http://') && $context['member']['avatar']['allow_external'])
Chris@76 2410 $context['member']['avatar'] += array(
Chris@76 2411 'choice' => 'external',
Chris@76 2412 'server_pic' => 'blank.gif',
Chris@76 2413 'external' => $cur_profile['avatar']
Chris@76 2414 );
Chris@76 2415 elseif ($cur_profile['avatar'] != '' && file_exists($modSettings['avatar_directory'] . '/' . $cur_profile['avatar']) && $context['member']['avatar']['allow_server_stored'])
Chris@76 2416 $context['member']['avatar'] += array(
Chris@76 2417 'choice' => 'server_stored',
Chris@76 2418 'server_pic' => $cur_profile['avatar'] == '' ? 'blank.gif' : $cur_profile['avatar'],
Chris@76 2419 'external' => 'http://'
Chris@76 2420 );
Chris@76 2421 else
Chris@76 2422 $context['member']['avatar'] += array(
Chris@76 2423 'choice' => 'none',
Chris@76 2424 'server_pic' => 'blank.gif',
Chris@76 2425 'external' => 'http://'
Chris@76 2426 );
Chris@76 2427
Chris@76 2428 // Get a list of all the avatars.
Chris@76 2429 if ($context['member']['avatar']['allow_server_stored'])
Chris@76 2430 {
Chris@76 2431 $context['avatar_list'] = array();
Chris@76 2432 $context['avatars'] = is_dir($modSettings['avatar_directory']) ? getAvatars('', 0) : array();
Chris@76 2433 }
Chris@76 2434 else
Chris@76 2435 $context['avatars'] = array();
Chris@76 2436
Chris@76 2437 // Second level selected avatar...
Chris@76 2438 $context['avatar_selected'] = substr(strrchr($context['member']['avatar']['server_pic'], '/'), 1);
Chris@76 2439 return true;
Chris@76 2440 }
Chris@76 2441
Chris@76 2442 // Save a members group.
Chris@76 2443 function profileSaveGroups(&$value)
Chris@76 2444 {
Chris@76 2445 global $profile_vars, $old_profile, $context, $smcFunc, $cur_profile;
Chris@76 2446
Chris@76 2447 // Do we need to protect some groups?
Chris@76 2448 if (!allowedTo('admin_forum'))
Chris@76 2449 {
Chris@76 2450 $request = $smcFunc['db_query']('', '
Chris@76 2451 SELECT id_group
Chris@76 2452 FROM {db_prefix}membergroups
Chris@76 2453 WHERE group_type = {int:is_protected}',
Chris@76 2454 array(
Chris@76 2455 'is_protected' => 1,
Chris@76 2456 )
Chris@76 2457 );
Chris@76 2458 $protected_groups = array(1);
Chris@76 2459 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 2460 $protected_groups[] = $row['id_group'];
Chris@76 2461 $smcFunc['db_free_result']($request);
Chris@76 2462
Chris@76 2463 $protected_groups = array_unique($protected_groups);
Chris@76 2464 }
Chris@76 2465
Chris@76 2466 // The account page allows the change of your id_group - but not to a protected group!
Chris@76 2467 if (empty($protected_groups) || count(array_intersect(array((int) $value, $old_profile['id_group']), $protected_groups)) == 0)
Chris@76 2468 $value = (int) $value;
Chris@76 2469 // ... otherwise it's the old group sir.
Chris@76 2470 else
Chris@76 2471 $value = $old_profile['id_group'];
Chris@76 2472
Chris@76 2473 // Find the additional membergroups (if any)
Chris@76 2474 if (isset($_POST['additional_groups']) && is_array($_POST['additional_groups']))
Chris@76 2475 {
Chris@76 2476 $additional_groups = array();
Chris@76 2477 foreach ($_POST['additional_groups'] as $group_id)
Chris@76 2478 {
Chris@76 2479 $group_id = (int) $group_id;
Chris@76 2480 if (!empty($group_id) && (empty($protected_groups) || !in_array($group_id, $protected_groups)))
Chris@76 2481 $additional_groups[] = $group_id;
Chris@76 2482 }
Chris@76 2483
Chris@76 2484 // Put the protected groups back in there if you don't have permission to take them away.
Chris@76 2485 $old_additional_groups = explode(',', $old_profile['additional_groups']);
Chris@76 2486 foreach ($old_additional_groups as $group_id)
Chris@76 2487 {
Chris@76 2488 if (!empty($protected_groups) && in_array($group_id, $protected_groups))
Chris@76 2489 $additional_groups[] = $group_id;
Chris@76 2490 }
Chris@76 2491
Chris@76 2492 if (implode(',', $additional_groups) !== $old_profile['additional_groups'])
Chris@76 2493 {
Chris@76 2494 $profile_vars['additional_groups'] = implode(',', $additional_groups);
Chris@76 2495 $cur_profile['additional_groups'] = implode(',', $additional_groups);
Chris@76 2496 }
Chris@76 2497 }
Chris@76 2498
Chris@76 2499 // Too often, people remove delete their own account, or something.
Chris@76 2500 if (in_array(1, explode(',', $old_profile['additional_groups'])) || $old_profile['id_group'] == 1)
Chris@76 2501 {
Chris@76 2502 $stillAdmin = $value == 1 || (isset($additional_groups) && in_array(1, $additional_groups));
Chris@76 2503
Chris@76 2504 // If they would no longer be an admin, look for any other...
Chris@76 2505 if (!$stillAdmin)
Chris@76 2506 {
Chris@76 2507 $request = $smcFunc['db_query']('', '
Chris@76 2508 SELECT id_member
Chris@76 2509 FROM {db_prefix}members
Chris@76 2510 WHERE (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0)
Chris@76 2511 AND id_member != {int:selected_member}
Chris@76 2512 LIMIT 1',
Chris@76 2513 array(
Chris@76 2514 'admin_group' => 1,
Chris@76 2515 'selected_member' => $context['id_member'],
Chris@76 2516 )
Chris@76 2517 );
Chris@76 2518 list ($another) = $smcFunc['db_fetch_row']($request);
Chris@76 2519 $smcFunc['db_free_result']($request);
Chris@76 2520
Chris@76 2521 if (empty($another))
Chris@76 2522 fatal_lang_error('at_least_one_admin', 'critical');
Chris@76 2523 }
Chris@76 2524 }
Chris@76 2525
Chris@76 2526 // If we are changing group status, update permission cache as necessary.
Chris@76 2527 if ($value != $old_profile['id_group'] || isset($profile_vars['additional_groups']))
Chris@76 2528 {
Chris@76 2529 if ($context['user']['is_owner'])
Chris@76 2530 $_SESSION['mc']['time'] = 0;
Chris@76 2531 else
Chris@76 2532 updateSettings(array('settings_updated' => time()));
Chris@76 2533 }
Chris@76 2534
Chris@76 2535 return true;
Chris@76 2536 }
Chris@76 2537
Chris@76 2538 // The avatar is incredibly complicated, what with the options... and what not.
Chris@76 2539 function profileSaveAvatarData(&$value)
Chris@76 2540 {
Chris@76 2541 global $modSettings, $sourcedir, $smcFunc, $profile_vars, $cur_profile, $context;
Chris@76 2542
Chris@76 2543 $memID = $context['id_member'];
Chris@76 2544 if (empty($memID) && !empty($context['password_auth_failed']))
Chris@76 2545 return false;
Chris@76 2546
Chris@76 2547 require_once($sourcedir . '/ManageAttachments.php');
Chris@76 2548
Chris@76 2549 // We need to know where we're going to be putting it..
Chris@76 2550 if (!empty($modSettings['custom_avatar_enabled']))
Chris@76 2551 {
Chris@76 2552 $uploadDir = $modSettings['custom_avatar_dir'];
Chris@76 2553 $id_folder = 1;
Chris@76 2554 }
Chris@76 2555 elseif (!empty($modSettings['currentAttachmentUploadDir']))
Chris@76 2556 {
Chris@76 2557 if (!is_array($modSettings['attachmentUploadDir']))
Chris@76 2558 $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
Chris@76 2559
Chris@76 2560 // Just use the current path for temp files.
Chris@76 2561 $uploadDir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
Chris@76 2562 $id_folder = $modSettings['currentAttachmentUploadDir'];
Chris@76 2563 }
Chris@76 2564 else
Chris@76 2565 {
Chris@76 2566 $uploadDir = $modSettings['attachmentUploadDir'];
Chris@76 2567 $id_folder = 1;
Chris@76 2568 }
Chris@76 2569
Chris@76 2570 $downloadedExternalAvatar = false;
Chris@76 2571 if ($value == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && strlen($_POST['userpicpersonal']) > 7 && !empty($modSettings['avatar_download_external']))
Chris@76 2572 {
Chris@76 2573 if (!is_writable($uploadDir))
Chris@76 2574 fatal_lang_error('attachments_no_write', 'critical');
Chris@76 2575
Chris@76 2576 require_once($sourcedir . '/Subs-Package.php');
Chris@76 2577
Chris@76 2578 $url = parse_url($_POST['userpicpersonal']);
Chris@76 2579 $contents = fetch_web_data('http://' . $url['host'] . (empty($url['port']) ? '' : ':' . $url['port']) . str_replace(' ', '%20', trim($url['path'])));
Chris@76 2580
Chris@76 2581 if ($contents != false && $tmpAvatar = fopen($uploadDir . '/avatar_tmp_' . $memID, 'wb'))
Chris@76 2582 {
Chris@76 2583 fwrite($tmpAvatar, $contents);
Chris@76 2584 fclose($tmpAvatar);
Chris@76 2585
Chris@76 2586 $downloadedExternalAvatar = true;
Chris@76 2587 $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
Chris@76 2588 }
Chris@76 2589 }
Chris@76 2590
Chris@76 2591 if ($value == 'none')
Chris@76 2592 {
Chris@76 2593 $profile_vars['avatar'] = '';
Chris@76 2594
Chris@76 2595 // Reset the attach ID.
Chris@76 2596 $cur_profile['id_attach'] = 0;
Chris@76 2597 $cur_profile['attachment_type'] = 0;
Chris@76 2598 $cur_profile['filename'] = '';
Chris@76 2599
Chris@76 2600 removeAttachments(array('id_member' => $memID));
Chris@76 2601 }
Chris@76 2602 elseif ($value == 'server_stored' && allowedTo('profile_server_avatar'))
Chris@76 2603 {
Chris@76 2604 $profile_vars['avatar'] = strtr(empty($_POST['file']) ? (empty($_POST['cat']) ? '' : $_POST['cat']) : $_POST['file'], array('&amp;' => '&'));
Chris@76 2605 $profile_vars['avatar'] = preg_match('~^([\w _!@%*=\-#()\[\]&.,]+/)?[\w _!@%*=\-#()\[\]&.,]+$~', $profile_vars['avatar']) != 0 && preg_match('/\.\./', $profile_vars['avatar']) == 0 && file_exists($modSettings['avatar_directory'] . '/' . $profile_vars['avatar']) ? ($profile_vars['avatar'] == 'blank.gif' ? '' : $profile_vars['avatar']) : '';
Chris@76 2606
Chris@76 2607 // Clear current profile...
Chris@76 2608 $cur_profile['id_attach'] = 0;
Chris@76 2609 $cur_profile['attachment_type'] = 0;
Chris@76 2610 $cur_profile['filename'] = '';
Chris@76 2611
Chris@76 2612 // Get rid of their old avatar. (if uploaded.)
Chris@76 2613 removeAttachments(array('id_member' => $memID));
Chris@76 2614 }
Chris@76 2615 elseif ($value == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && empty($modSettings['avatar_download_external']))
Chris@76 2616 {
Chris@76 2617 // We need these clean...
Chris@76 2618 $cur_profile['id_attach'] = 0;
Chris@76 2619 $cur_profile['attachment_type'] = 0;
Chris@76 2620 $cur_profile['filename'] = '';
Chris@76 2621
Chris@76 2622 // Remove any attached avatar...
Chris@76 2623 removeAttachments(array('id_member' => $memID));
Chris@76 2624
Chris@76 2625 $profile_vars['avatar'] = str_replace('%20', '', preg_replace('~action(?:=|%3d)(?!dlattach)~i', 'action-', $_POST['userpicpersonal']));
Chris@76 2626
Chris@76 2627 if ($profile_vars['avatar'] == 'http://' || $profile_vars['avatar'] == 'http:///')
Chris@76 2628 $profile_vars['avatar'] = '';
Chris@76 2629 // Trying to make us do something we'll regret?
Chris@76 2630 elseif (substr($profile_vars['avatar'], 0, 7) != 'http://')
Chris@76 2631 return 'bad_avatar';
Chris@76 2632 // Should we check dimensions?
Chris@76 2633 elseif (!empty($modSettings['avatar_max_height_external']) || !empty($modSettings['avatar_max_width_external']))
Chris@76 2634 {
Chris@76 2635 // Now let's validate the avatar.
Chris@76 2636 $sizes = url_image_size($profile_vars['avatar']);
Chris@76 2637
Chris@76 2638 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']))))
Chris@76 2639 {
Chris@76 2640 // Houston, we have a problem. The avatar is too large!!
Chris@76 2641 if ($modSettings['avatar_action_too_large'] == 'option_refuse')
Chris@76 2642 return 'bad_avatar';
Chris@76 2643 elseif ($modSettings['avatar_action_too_large'] == 'option_download_and_resize')
Chris@76 2644 {
Chris@76 2645 require_once($sourcedir . '/Subs-Graphics.php');
Chris@76 2646 if (downloadAvatar($profile_vars['avatar'], $memID, $modSettings['avatar_max_width_external'], $modSettings['avatar_max_height_external']))
Chris@76 2647 {
Chris@76 2648 $profile_vars['avatar'] = '';
Chris@76 2649 $cur_profile['id_attach'] = $modSettings['new_avatar_data']['id'];
Chris@76 2650 $cur_profile['filename'] = $modSettings['new_avatar_data']['filename'];
Chris@76 2651 $cur_profile['attachment_type'] = $modSettings['new_avatar_data']['type'];
Chris@76 2652 }
Chris@76 2653 else
Chris@76 2654 return 'bad_avatar';
Chris@76 2655 }
Chris@76 2656 }
Chris@76 2657 }
Chris@76 2658 }
Chris@76 2659 elseif (($value == 'upload' && allowedTo('profile_upload_avatar')) || $downloadedExternalAvatar)
Chris@76 2660 {
Chris@76 2661 if ((isset($_FILES['attachment']['name']) && $_FILES['attachment']['name'] != '') || $downloadedExternalAvatar)
Chris@76 2662 {
Chris@76 2663 // Get the dimensions of the image.
Chris@76 2664 if (!$downloadedExternalAvatar)
Chris@76 2665 {
Chris@76 2666 if (!is_writable($uploadDir))
Chris@76 2667 fatal_lang_error('attachments_no_write', 'critical');
Chris@76 2668
Chris@76 2669 if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadDir . '/avatar_tmp_' . $memID))
Chris@76 2670 fatal_lang_error('attach_timeout', 'critical');
Chris@76 2671
Chris@76 2672 $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
Chris@76 2673 }
Chris@76 2674
Chris@76 2675 $sizes = @getimagesize($_FILES['attachment']['tmp_name']);
Chris@76 2676
Chris@76 2677 // No size, then it's probably not a valid pic.
Chris@76 2678 if ($sizes === false)
Chris@76 2679 return 'bad_avatar';
Chris@76 2680 // Check whether the image is too large.
Chris@76 2681 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']))
Chris@76 2682 {
Chris@76 2683 if (!empty($modSettings['avatar_resize_upload']))
Chris@76 2684 {
Chris@76 2685 // Attempt to chmod it.
Chris@76 2686 @chmod($uploadDir . '/avatar_tmp_' . $memID, 0644);
Chris@76 2687
Chris@76 2688 require_once($sourcedir . '/Subs-Graphics.php');
Chris@76 2689 if (!downloadAvatar($uploadDir . '/avatar_tmp_' . $memID, $memID, $modSettings['avatar_max_width_upload'], $modSettings['avatar_max_height_upload']))
Chris@76 2690 return 'bad_avatar';
Chris@76 2691
Chris@76 2692 // Reset attachment avatar data.
Chris@76 2693 $cur_profile['id_attach'] = $modSettings['new_avatar_data']['id'];
Chris@76 2694 $cur_profile['filename'] = $modSettings['new_avatar_data']['filename'];
Chris@76 2695 $cur_profile['attachment_type'] = $modSettings['new_avatar_data']['type'];
Chris@76 2696 }
Chris@76 2697 else
Chris@76 2698 return 'bad_avatar';
Chris@76 2699 }
Chris@76 2700 elseif (is_array($sizes))
Chris@76 2701 {
Chris@76 2702 // Now try to find an infection.
Chris@76 2703 require_once($sourcedir . '/Subs-Graphics.php');
Chris@76 2704 if (!checkImageContents($_FILES['attachment']['tmp_name'], !empty($modSettings['avatar_paranoid'])))
Chris@76 2705 {
Chris@76 2706 // It's bad. Try to re-encode the contents?
Chris@76 2707 if (empty($modSettings['avatar_reencode']) || (!reencodeImage($_FILES['attachment']['tmp_name'], $sizes[2])))
Chris@76 2708 return 'bad_avatar';
Chris@76 2709 // We were successful. However, at what price?
Chris@76 2710 $sizes = @getimagesize($_FILES['attachment']['tmp_name']);
Chris@76 2711 // Hard to believe this would happen, but can you bet?
Chris@76 2712 if ($sizes === false)
Chris@76 2713 return 'bad_avatar';
Chris@76 2714 }
Chris@76 2715
Chris@76 2716 $extensions = array(
Chris@76 2717 '1' => 'gif',
Chris@76 2718 '2' => 'jpg',
Chris@76 2719 '3' => 'png',
Chris@76 2720 '6' => 'bmp'
Chris@76 2721 );
Chris@76 2722
Chris@76 2723 $extension = isset($extensions[$sizes[2]]) ? $extensions[$sizes[2]] : 'bmp';
Chris@76 2724 $mime_type = 'image/' . ($extension === 'jpg' ? 'jpeg' : ($extension === 'bmp' ? 'x-ms-bmp' : $extension));
Chris@76 2725 $destName = 'avatar_' . $memID . '_' . time() . '.' . $extension;
Chris@76 2726 list ($width, $height) = getimagesize($_FILES['attachment']['tmp_name']);
Chris@76 2727 $file_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, null, true) : '';
Chris@76 2728
Chris@76 2729 // Remove previous attachments this member might have had.
Chris@76 2730 removeAttachments(array('id_member' => $memID));
Chris@76 2731
Chris@76 2732 $smcFunc['db_insert']('',
Chris@76 2733 '{db_prefix}attachments',
Chris@76 2734 array(
Chris@76 2735 'id_member' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'fileext' => 'string', 'size' => 'int',
Chris@76 2736 'width' => 'int', 'height' => 'int', 'mime_type' => 'string', 'id_folder' => 'int',
Chris@76 2737 ),
Chris@76 2738 array(
Chris@76 2739 $memID, (empty($modSettings['custom_avatar_enabled']) ? 0 : 1), $destName, $file_hash, $extension, filesize($_FILES['attachment']['tmp_name']),
Chris@76 2740 (int) $width, (int) $height, $mime_type, $id_folder,
Chris@76 2741 ),
Chris@76 2742 array('id_attach')
Chris@76 2743 );
Chris@76 2744
Chris@76 2745 $cur_profile['id_attach'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
Chris@76 2746 $cur_profile['filename'] = $destName;
Chris@76 2747 $cur_profile['attachment_type'] = empty($modSettings['custom_avatar_enabled']) ? 0 : 1;
Chris@76 2748
Chris@76 2749 $destinationPath = $uploadDir . '/' . (empty($file_hash) ? $destName : $cur_profile['id_attach'] . '_' . $file_hash);
Chris@76 2750 if (!rename($_FILES['attachment']['tmp_name'], $destinationPath))
Chris@76 2751 {
Chris@76 2752 // I guess a man can try.
Chris@76 2753 removeAttachments(array('id_member' => $memID));
Chris@76 2754 fatal_lang_error('attach_timeout', 'critical');
Chris@76 2755 }
Chris@76 2756
Chris@76 2757 // Attempt to chmod it.
Chris@76 2758 @chmod($uploadDir . '/' . $destinationPath, 0644);
Chris@76 2759 }
Chris@76 2760 $profile_vars['avatar'] = '';
Chris@76 2761
Chris@76 2762 // Delete any temporary file.
Chris@76 2763 if (file_exists($uploadDir . '/avatar_tmp_' . $memID))
Chris@76 2764 @unlink($uploadDir . '/avatar_tmp_' . $memID);
Chris@76 2765 }
Chris@76 2766 // Selected the upload avatar option and had one already uploaded before or didn't upload one.
Chris@76 2767 else
Chris@76 2768 $profile_vars['avatar'] = '';
Chris@76 2769 }
Chris@76 2770 else
Chris@76 2771 $profile_vars['avatar'] = '';
Chris@76 2772
Chris@76 2773 // Setup the profile variables so it shows things right on display!
Chris@76 2774 $cur_profile['avatar'] = $profile_vars['avatar'];
Chris@76 2775
Chris@76 2776 return false;
Chris@76 2777 }
Chris@76 2778
Chris@76 2779 // Validate the signature!
Chris@76 2780 function profileValidateSignature(&$value)
Chris@76 2781 {
Chris@76 2782 global $sourcedir, $modSettings, $smcFunc, $txt;
Chris@76 2783
Chris@76 2784 require_once($sourcedir . '/Subs-Post.php');
Chris@76 2785
Chris@76 2786 // Admins can do whatever they hell they want!
Chris@76 2787 if (!allowedTo('admin_forum'))
Chris@76 2788 {
Chris@76 2789 // Load all the signature limits.
Chris@76 2790 list ($sig_limits, $sig_bbc) = explode(':', $modSettings['signature_settings']);
Chris@76 2791 $sig_limits = explode(',', $sig_limits);
Chris@76 2792 $disabledTags = !empty($sig_bbc) ? explode(',', $sig_bbc) : array();
Chris@76 2793
Chris@76 2794 $unparsed_signature = strtr(un_htmlspecialchars($value), array("\r" => '', '&#039' => '\''));
Chris@76 2795 // Too long?
Chris@76 2796 if (!empty($sig_limits[1]) && $smcFunc['strlen']($unparsed_signature) > $sig_limits[1])
Chris@76 2797 {
Chris@76 2798 $_POST['signature'] = trim(htmlspecialchars($smcFunc['substr']($unparsed_signature, 0, $sig_limits[1]), ENT_QUOTES));
Chris@76 2799 $txt['profile_error_signature_max_length'] = sprintf($txt['profile_error_signature_max_length'], $sig_limits[1]);
Chris@76 2800 return 'signature_max_length';
Chris@76 2801 }
Chris@76 2802 // Too many lines?
Chris@76 2803 if (!empty($sig_limits[2]) && substr_count($unparsed_signature, "\n") >= $sig_limits[2])
Chris@76 2804 {
Chris@76 2805 $txt['profile_error_signature_max_lines'] = sprintf($txt['profile_error_signature_max_lines'], $sig_limits[2]);
Chris@76 2806 return 'signature_max_lines';
Chris@76 2807 }
Chris@76 2808 // Too many images?!
Chris@76 2809 if (!empty($sig_limits[3]) && (substr_count(strtolower($unparsed_signature), '[img') + substr_count(strtolower($unparsed_signature), '<img')) > $sig_limits[3])
Chris@76 2810 {
Chris@76 2811 $txt['profile_error_signature_max_image_count'] = sprintf($txt['profile_error_signature_max_image_count'], $sig_limits[3]);
Chris@76 2812 return 'signature_max_image_count';
Chris@76 2813 }
Chris@76 2814 // What about too many smileys!
Chris@76 2815 $smiley_parsed = $unparsed_signature;
Chris@76 2816 parsesmileys($smiley_parsed);
Chris@76 2817 $smiley_count = substr_count(strtolower($smiley_parsed), '<img') - substr_count(strtolower($unparsed_signature), '<img');
Chris@76 2818 if (!empty($sig_limits[4]) && $sig_limits[4] == -1 && $smiley_count > 0)
Chris@76 2819 return 'signature_allow_smileys';
Chris@76 2820 elseif (!empty($sig_limits[4]) && $sig_limits[4] > 0 && $smiley_count > $sig_limits[4])
Chris@76 2821 {
Chris@76 2822 $txt['profile_error_signature_max_smileys'] = sprintf($txt['profile_error_signature_max_smileys'], $sig_limits[4]);
Chris@76 2823 return 'signature_max_smileys';
Chris@76 2824 }
Chris@76 2825 // Maybe we are abusing font sizes?
Chris@76 2826 if (!empty($sig_limits[7]) && preg_match_all('~\[size=([\d\.]+)?(px|pt|em|x-large|larger)~i', $unparsed_signature, $matches) !== false && isset($matches[2]))
Chris@76 2827 {
Chris@76 2828 foreach ($matches[1] as $ind => $size)
Chris@76 2829 {
Chris@76 2830 $limit_broke = 0;
Chris@76 2831 // Attempt to allow all sizes of abuse, so to speak.
Chris@76 2832 if ($matches[2][$ind] == 'px' && $size > $sig_limits[7])
Chris@76 2833 $limit_broke = $sig_limits[7] . 'px';
Chris@76 2834 elseif ($matches[2][$ind] == 'pt' && $size > ($sig_limits[7] * 0.75))
Chris@76 2835 $limit_broke = ((int) $sig_limits[7] * 0.75) . 'pt';
Chris@76 2836 elseif ($matches[2][$ind] == 'em' && $size > ((float) $sig_limits[7] / 16))
Chris@76 2837 $limit_broke = ((float) $sig_limits[7] / 16) . 'em';
Chris@76 2838 elseif ($matches[2][$ind] != 'px' && $matches[2][$ind] != 'pt' && $matches[2][$ind] != 'em' && $sig_limits[7] < 18)
Chris@76 2839 $limit_broke = 'large';
Chris@76 2840
Chris@76 2841 if ($limit_broke)
Chris@76 2842 {
Chris@76 2843 $txt['profile_error_signature_max_font_size'] = sprintf($txt['profile_error_signature_max_font_size'], $limit_broke);
Chris@76 2844 return 'signature_max_font_size';
Chris@76 2845 }
Chris@76 2846 }
Chris@76 2847 }
Chris@76 2848 // The difficult one - image sizes! Don't error on this - just fix it.
Chris@76 2849 if ((!empty($sig_limits[5]) || !empty($sig_limits[6])))
Chris@76 2850 {
Chris@76 2851 // Get all BBC tags...
Chris@76 2852 preg_match_all('~\[img(\s+width=([\d]+))?(\s+height=([\d]+))?(\s+width=([\d]+))?\s*\](?:<br />)*([^<">]+?)(?:<br />)*\[/img\]~i', $unparsed_signature, $matches);
Chris@76 2853 // ... and all HTML ones.
Chris@76 2854 preg_match_all('~<img\s+src=(?:")?((?:http://|ftp://|https://|ftps://).+?)(?:")?(?:\s+alt=(?:")?(.*?)(?:")?)?(?:\s?/)?>~i', $unparsed_signature, $matches2, PREG_PATTERN_ORDER);
Chris@76 2855 // And stick the HTML in the BBC.
Chris@76 2856 if (!empty($matches2))
Chris@76 2857 {
Chris@76 2858 foreach ($matches2[0] as $ind => $dummy)
Chris@76 2859 {
Chris@76 2860 $matches[0][] = $matches2[0][$ind];
Chris@76 2861 $matches[1][] = '';
Chris@76 2862 $matches[2][] = '';
Chris@76 2863 $matches[3][] = '';
Chris@76 2864 $matches[4][] = '';
Chris@76 2865 $matches[5][] = '';
Chris@76 2866 $matches[6][] = '';
Chris@76 2867 $matches[7][] = $matches2[1][$ind];
Chris@76 2868 }
Chris@76 2869 }
Chris@76 2870
Chris@76 2871 $replaces = array();
Chris@76 2872 // Try to find all the images!
Chris@76 2873 if (!empty($matches))
Chris@76 2874 {
Chris@76 2875 foreach ($matches[0] as $key => $image)
Chris@76 2876 {
Chris@76 2877 $width = -1; $height = -1;
Chris@76 2878
Chris@76 2879 // Does it have predefined restraints? Width first.
Chris@76 2880 if ($matches[6][$key])
Chris@76 2881 $matches[2][$key] = $matches[6][$key];
Chris@76 2882 if ($matches[2][$key] && $sig_limits[5] && $matches[2][$key] > $sig_limits[5])
Chris@76 2883 {
Chris@76 2884 $width = $sig_limits[5];
Chris@76 2885 $matches[4][$key] = $matches[4][$key] * ($width / $matches[2][$key]);
Chris@76 2886 }
Chris@76 2887 elseif ($matches[2][$key])
Chris@76 2888 $width = $matches[2][$key];
Chris@76 2889 // ... and height.
Chris@76 2890 if ($matches[4][$key] && $sig_limits[6] && $matches[4][$key] > $sig_limits[6])
Chris@76 2891 {
Chris@76 2892 $height = $sig_limits[6];
Chris@76 2893 if ($width != -1)
Chris@76 2894 $width = $width * ($height / $matches[4][$key]);
Chris@76 2895 }
Chris@76 2896 elseif ($matches[4][$key])
Chris@76 2897 $height = $matches[4][$key];
Chris@76 2898
Chris@76 2899 // If the dimensions are still not fixed - we need to check the actual image.
Chris@76 2900 if (($width == -1 && $sig_limits[5]) || ($height == -1 && $sig_limits[6]))
Chris@76 2901 {
Chris@76 2902 $sizes = url_image_size($matches[7][$key]);
Chris@76 2903 if (is_array($sizes))
Chris@76 2904 {
Chris@76 2905 // Too wide?
Chris@76 2906 if ($sizes[0] > $sig_limits[5] && $sig_limits[5])
Chris@76 2907 {
Chris@76 2908 $width = $sig_limits[5];
Chris@76 2909 $sizes[1] = $sizes[1] * ($width / $sizes[0]);
Chris@76 2910 }
Chris@76 2911 // Too high?
Chris@76 2912 if ($sizes[1] > $sig_limits[6] && $sig_limits[6])
Chris@76 2913 {
Chris@76 2914 $height = $sig_limits[6];
Chris@76 2915 if ($width == -1)
Chris@76 2916 $width = $sizes[0];
Chris@76 2917 $width = $width * ($height / $sizes[1]);
Chris@76 2918 }
Chris@76 2919 elseif ($width != -1)
Chris@76 2920 $height = $sizes[1];
Chris@76 2921 }
Chris@76 2922 }
Chris@76 2923
Chris@76 2924 // Did we come up with some changes? If so remake the string.
Chris@76 2925 if ($width != -1 || $height != -1)
Chris@76 2926 $replaces[$image] = '[img' . ($width != -1 ? ' width=' . round($width) : '') . ($height != -1 ? ' height=' . round($height) : '') . ']' . $matches[7][$key] . '[/img]';
Chris@76 2927 }
Chris@76 2928 if (!empty($replaces))
Chris@76 2929 $value = str_replace(array_keys($replaces), array_values($replaces), $value);
Chris@76 2930 }
Chris@76 2931 }
Chris@76 2932 // Any disabled BBC?
Chris@76 2933 $disabledSigBBC = implode('|', $disabledTags);
Chris@76 2934 if (!empty($disabledSigBBC))
Chris@76 2935 {
Chris@76 2936 if (preg_match('~\[(' . $disabledSigBBC . ')~i', $unparsed_signature, $matches) !== false && isset($matches[1]))
Chris@76 2937 {
Chris@76 2938 $disabledTags = array_unique($disabledTags);
Chris@76 2939 $txt['profile_error_signature_disabled_bbc'] = sprintf($txt['profile_error_signature_disabled_bbc'], implode(', ', $disabledTags));
Chris@76 2940 return 'signature_disabled_bbc';
Chris@76 2941 }
Chris@76 2942 }
Chris@76 2943 }
Chris@76 2944
Chris@76 2945 preparsecode($value);
Chris@76 2946 return true;
Chris@76 2947 }
Chris@76 2948
Chris@76 2949 // Validate an email address.
Chris@76 2950 function profileValidateEmail($email, $memID = 0)
Chris@76 2951 {
Chris@76 2952 global $smcFunc, $context;
Chris@76 2953
Chris@76 2954 $email = strtr($email, array('&#039;' => '\''));
Chris@76 2955
Chris@76 2956 // Check the name and email for validity.
Chris@76 2957 if (trim($email) == '')
Chris@76 2958 return 'no_email';
Chris@76 2959 if (preg_match('~^[0-9A-Za-z=_+\-/][0-9A-Za-z=_\'+\-/\.]*@[\w\-]+(\.[\w\-]+)*(\.[\w]{2,6})$~', $email) == 0)
Chris@76 2960 return 'bad_email';
Chris@76 2961
Chris@76 2962 // Email addresses should be and stay unique.
Chris@76 2963 $request = $smcFunc['db_query']('', '
Chris@76 2964 SELECT id_member
Chris@76 2965 FROM {db_prefix}members
Chris@76 2966 WHERE ' . ($memID != 0 ? 'id_member != {int:selected_member} AND ' : '') . '
Chris@76 2967 email_address = {string:email_address}
Chris@76 2968 LIMIT 1',
Chris@76 2969 array(
Chris@76 2970 'selected_member' => $memID,
Chris@76 2971 'email_address' => $email,
Chris@76 2972 )
Chris@76 2973 );
Chris@76 2974 if ($smcFunc['db_num_rows']($request) > 0)
Chris@76 2975 return 'email_taken';
Chris@76 2976 $smcFunc['db_free_result']($request);
Chris@76 2977
Chris@76 2978 return true;
Chris@76 2979 }
Chris@76 2980
Chris@76 2981 // Reload a users settings.
Chris@76 2982 function profileReloadUser()
Chris@76 2983 {
Chris@76 2984 global $sourcedir, $modSettings, $context, $cur_profile, $smcFunc, $profile_vars;
Chris@76 2985
Chris@76 2986 // Log them back in - using the verify password as they must have matched and this one doesn't get changed by anyone!
Chris@76 2987 if (isset($_POST['passwrd2']) && $_POST['passwrd2'] != '')
Chris@76 2988 {
Chris@76 2989 require_once($sourcedir . '/Subs-Auth.php');
Chris@76 2990 setLoginCookie(60 * $modSettings['cookieTime'], $context['id_member'], sha1(sha1(strtolower($cur_profile['member_name']) . un_htmlspecialchars($_POST['passwrd2'])) . $cur_profile['password_salt']));
Chris@76 2991 }
Chris@76 2992
Chris@76 2993 loadUserSettings();
Chris@76 2994 writeLog();
Chris@76 2995 }
Chris@76 2996
Chris@76 2997 // Send the user a new activation email if they need to reactivate!
Chris@76 2998 function profileSendActivation()
Chris@76 2999 {
Chris@76 3000 global $sourcedir, $profile_vars, $txt, $context, $scripturl, $smcFunc, $cookiename, $cur_profile, $language, $modSettings;
Chris@76 3001
Chris@76 3002 require_once($sourcedir . '/Subs-Post.php');
Chris@76 3003
Chris@76 3004 // Shouldn't happen but just in case.
Chris@76 3005 if (empty($profile_vars['email_address']))
Chris@76 3006 return;
Chris@76 3007
Chris@76 3008 $replacements = array(
Chris@76 3009 'ACTIVATIONLINK' => $scripturl . '?action=activate;u=' . $context['id_member'] . ';code=' . $profile_vars['validation_code'],
Chris@76 3010 'ACTIVATIONCODE' => $profile_vars['validation_code'],
Chris@76 3011 'ACTIVATIONLINKWITHOUTCODE' => $scripturl . '?action=activate;u=' . $context['id_member'],
Chris@76 3012 );
Chris@76 3013
Chris@76 3014 // Send off the email.
Chris@76 3015 $emaildata = loadEmailTemplate('activate_reactivate', $replacements, empty($cur_profile['lngfile']) || empty($modSettings['userLanguage']) ? $language : $cur_profile['lngfile']);
Chris@76 3016 sendmail($profile_vars['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 0);
Chris@76 3017
Chris@76 3018 // Log the user out.
Chris@76 3019 $smcFunc['db_query']('', '
Chris@76 3020 DELETE FROM {db_prefix}log_online
Chris@76 3021 WHERE id_member = {int:selected_member}',
Chris@76 3022 array(
Chris@76 3023 'selected_member' => $context['id_member'],
Chris@76 3024 )
Chris@76 3025 );
Chris@76 3026 $_SESSION['log_time'] = 0;
Chris@76 3027 $_SESSION['login_' . $cookiename] = serialize(array(0, '', 0));
Chris@76 3028
Chris@76 3029 if (isset($_COOKIE[$cookiename]))
Chris@76 3030 $_COOKIE[$cookiename] = '';
Chris@76 3031
Chris@76 3032 loadUserSettings();
Chris@76 3033
Chris@76 3034 $context['user']['is_logged'] = false;
Chris@76 3035 $context['user']['is_guest'] = true;
Chris@76 3036
Chris@76 3037 // Send them to the done-with-registration-login screen.
Chris@76 3038 loadTemplate('Register');
Chris@76 3039
Chris@76 3040 $context['page_title'] = $txt['profile'];
Chris@76 3041 $context['sub_template'] = 'after';
Chris@76 3042 $context['title'] = $txt['activate_changed_email_title'];
Chris@76 3043 $context['description'] = $txt['activate_changed_email_desc'];
Chris@76 3044
Chris@76 3045 // We're gone!
Chris@76 3046 obExit();
Chris@76 3047 }
Chris@76 3048
Chris@76 3049 // Function to allow the user to choose group membership etc...
Chris@76 3050 function groupMembership($memID)
Chris@76 3051 {
Chris@76 3052 global $txt, $scripturl, $user_profile, $user_info, $context, $modSettings, $smcFunc;
Chris@76 3053
Chris@76 3054 $curMember = $user_profile[$memID];
Chris@76 3055 $context['primary_group'] = $curMember['id_group'];
Chris@76 3056
Chris@76 3057 // Can they manage groups?
Chris@76 3058 $context['can_manage_membergroups'] = allowedTo('manage_membergroups');
Chris@76 3059 $context['can_manage_protected'] = allowedTo('admin_forum');
Chris@76 3060 $context['can_edit_primary'] = $context['can_manage_protected'];
Chris@76 3061 $context['update_message'] = isset($_GET['msg']) && isset($txt['group_membership_msg_' . $_GET['msg']]) ? $txt['group_membership_msg_' . $_GET['msg']] : '';
Chris@76 3062
Chris@76 3063 // Get all the groups this user is a member of.
Chris@76 3064 $groups = explode(',', $curMember['additional_groups']);
Chris@76 3065 $groups[] = $curMember['id_group'];
Chris@76 3066
Chris@76 3067 // Ensure the query doesn't croak!
Chris@76 3068 if (empty($groups))
Chris@76 3069 $groups = array(0);
Chris@76 3070 // Just to be sure...
Chris@76 3071 foreach ($groups as $k => $v)
Chris@76 3072 $groups[$k] = (int) $v;
Chris@76 3073
Chris@76 3074 // Get all the membergroups they can join.
Chris@76 3075 $request = $smcFunc['db_query']('', '
Chris@76 3076 SELECT mg.id_group, mg.group_name, mg.description, mg.group_type, mg.online_color, mg.hidden,
Chris@76 3077 IFNULL(lgr.id_member, 0) AS pending
Chris@76 3078 FROM {db_prefix}membergroups AS mg
Chris@76 3079 LEFT JOIN {db_prefix}log_group_requests AS lgr ON (lgr.id_member = {int:selected_member} AND lgr.id_group = mg.id_group)
Chris@76 3080 WHERE (mg.id_group IN ({array_int:group_list})
Chris@76 3081 OR mg.group_type > {int:nonjoin_group_id})
Chris@76 3082 AND mg.min_posts = {int:min_posts}
Chris@76 3083 AND mg.id_group != {int:moderator_group}
Chris@76 3084 ORDER BY group_name',
Chris@76 3085 array(
Chris@76 3086 'group_list' => $groups,
Chris@76 3087 'selected_member' => $memID,
Chris@76 3088 'nonjoin_group_id' => 1,
Chris@76 3089 'min_posts' => -1,
Chris@76 3090 'moderator_group' => 3,
Chris@76 3091 )
Chris@76 3092 );
Chris@76 3093 // This beast will be our group holder.
Chris@76 3094 $context['groups'] = array(
Chris@76 3095 'member' => array(),
Chris@76 3096 'available' => array()
Chris@76 3097 );
Chris@76 3098 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 3099 {
Chris@76 3100 // Can they edit their primary group?
Chris@76 3101 if (($row['id_group'] == $context['primary_group'] && $row['group_type'] > 1) || ($row['hidden'] != 2 && $context['primary_group'] == 0 && in_array($row['id_group'], $groups)))
Chris@76 3102 $context['can_edit_primary'] = true;
Chris@76 3103
Chris@76 3104 // If they can't manage (protected) groups, and it's not publically joinable or already assigned, they can't see it.
Chris@76 3105 if (((!$context['can_manage_protected'] && $row['group_type'] == 1) || (!$context['can_manage_membergroups'] && $row['group_type'] == 0)) && $row['id_group'] != $context['primary_group'])
Chris@76 3106 continue;
Chris@76 3107
Chris@76 3108 $context['groups'][in_array($row['id_group'], $groups) ? 'member' : 'available'][$row['id_group']] = array(
Chris@76 3109 'id' => $row['id_group'],
Chris@76 3110 'name' => $row['group_name'],
Chris@76 3111 'desc' => $row['description'],
Chris@76 3112 'color' => $row['online_color'],
Chris@76 3113 'type' => $row['group_type'],
Chris@76 3114 'pending' => $row['pending'],
Chris@76 3115 'is_primary' => $row['id_group'] == $context['primary_group'],
Chris@76 3116 'can_be_primary' => $row['hidden'] != 2,
Chris@76 3117 // Anything more than this needs to be done through account settings for security.
Chris@76 3118 'can_leave' => $row['id_group'] != 1 && $row['group_type'] > 1 ? true : false,
Chris@76 3119 );
Chris@76 3120 }
Chris@76 3121 $smcFunc['db_free_result']($request);
Chris@76 3122
Chris@76 3123 // Add registered members on the end.
Chris@76 3124 $context['groups']['member'][0] = array(
Chris@76 3125 'id' => 0,
Chris@76 3126 'name' => $txt['regular_members'],
Chris@76 3127 'desc' => $txt['regular_members_desc'],
Chris@76 3128 'type' => 0,
Chris@76 3129 'is_primary' => $context['primary_group'] == 0 ? true : false,
Chris@76 3130 'can_be_primary' => true,
Chris@76 3131 'can_leave' => 0,
Chris@76 3132 );
Chris@76 3133
Chris@76 3134 // No changing primary one unless you have enough groups!
Chris@76 3135 if (count($context['groups']['member']) < 2)
Chris@76 3136 $context['can_edit_primary'] = false;
Chris@76 3137
Chris@76 3138 // In the special case that someone is requesting membership of a group, setup some special context vars.
Chris@76 3139 if (isset($_REQUEST['request']) && isset($context['groups']['available'][(int) $_REQUEST['request']]) && $context['groups']['available'][(int) $_REQUEST['request']]['type'] == 2)
Chris@76 3140 $context['group_request'] = $context['groups']['available'][(int) $_REQUEST['request']];
Chris@76 3141 }
Chris@76 3142
Chris@76 3143 // This function actually makes all the group changes...
Chris@76 3144 function groupMembership2($profile_vars, $post_errors, $memID)
Chris@76 3145 {
Chris@76 3146 global $user_info, $sourcedir, $context, $user_profile, $modSettings, $txt, $smcFunc, $scripturl, $language;
Chris@76 3147
Chris@76 3148 // Let's be extra cautious...
Chris@76 3149 if (!$context['user']['is_owner'] || empty($modSettings['show_group_membership']))
Chris@76 3150 isAllowedTo('manage_membergroups');
Chris@76 3151 if (!isset($_REQUEST['gid']) && !isset($_POST['primary']))
Chris@76 3152 fatal_lang_error('no_access', false);
Chris@76 3153
Chris@76 3154 checkSession(isset($_GET['gid']) ? 'get' : 'post');
Chris@76 3155
Chris@76 3156 $old_profile = &$user_profile[$memID];
Chris@76 3157 $context['can_manage_membergroups'] = allowedTo('manage_membergroups');
Chris@76 3158 $context['can_manage_protected'] = allowedTo('admin_forum');
Chris@76 3159
Chris@76 3160 // By default the new primary is the old one.
Chris@76 3161 $newPrimary = $old_profile['id_group'];
Chris@76 3162 $addGroups = array_flip(explode(',', $old_profile['additional_groups']));
Chris@76 3163 $canChangePrimary = $old_profile['id_group'] == 0 ? 1 : 0;
Chris@76 3164 $changeType = isset($_POST['primary']) ? 'primary' : (isset($_POST['req']) ? 'request' : 'free');
Chris@76 3165
Chris@76 3166 // One way or another, we have a target group in mind...
Chris@76 3167 $group_id = isset($_REQUEST['gid']) ? (int) $_REQUEST['gid'] : (int) $_POST['primary'];
Chris@76 3168 $foundTarget = $changeType == 'primary' && $group_id == 0 ? true : false;
Chris@76 3169
Chris@76 3170 // Sanity check!!
Chris@76 3171 if ($group_id == 1)
Chris@76 3172 isAllowedTo('admin_forum');
Chris@76 3173 // Protected groups too!
Chris@76 3174 else
Chris@76 3175 {
Chris@76 3176 $request = $smcFunc['db_query']('', '
Chris@76 3177 SELECT group_type
Chris@76 3178 FROM {db_prefix}membergroups
Chris@76 3179 WHERE id_group = {int:current_group}
Chris@76 3180 LIMIT {int:limit}',
Chris@76 3181 array(
Chris@76 3182 'current_group' => $group_id,
Chris@76 3183 'limit' => 1,
Chris@76 3184 )
Chris@76 3185 );
Chris@76 3186 list ($is_protected) = $smcFunc['db_fetch_row']($request);
Chris@76 3187 $smcFunc['db_free_result']($request);
Chris@76 3188
Chris@76 3189 if ($is_protected == 1)
Chris@76 3190 isAllowedTo('admin_forum');
Chris@76 3191 }
Chris@76 3192
Chris@76 3193 // What ever we are doing, we need to determine if changing primary is possible!
Chris@76 3194 $request = $smcFunc['db_query']('', '
Chris@76 3195 SELECT id_group, group_type, hidden, group_name
Chris@76 3196 FROM {db_prefix}membergroups
Chris@76 3197 WHERE id_group IN ({int:group_list}, {int:current_group})',
Chris@76 3198 array(
Chris@76 3199 'group_list' => $group_id,
Chris@76 3200 'current_group' => $old_profile['id_group'],
Chris@76 3201 )
Chris@76 3202 );
Chris@76 3203 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 3204 {
Chris@76 3205 // Is this the new group?
Chris@76 3206 if ($row['id_group'] == $group_id)
Chris@76 3207 {
Chris@76 3208 $foundTarget = true;
Chris@76 3209 $group_name = $row['group_name'];
Chris@76 3210
Chris@76 3211 // Does the group type match what we're doing - are we trying to request a non-requestable group?
Chris@76 3212 if ($changeType == 'request' && $row['group_type'] != 2)
Chris@76 3213 fatal_lang_error('no_access', false);
Chris@76 3214 // What about leaving a requestable group we are not a member of?
Chris@76 3215 elseif ($changeType == 'free' && $row['group_type'] == 2 && $old_profile['id_group'] != $row['id_group'] && !isset($addGroups[$row['id_group']]))
Chris@76 3216 fatal_lang_error('no_access', false);
Chris@76 3217 elseif ($changeType == 'free' && $row['group_type'] != 3 && $row['group_type'] != 2)
Chris@76 3218 fatal_lang_error('no_access', false);
Chris@76 3219
Chris@76 3220 // We can't change the primary group if this is hidden!
Chris@76 3221 if ($row['hidden'] == 2)
Chris@76 3222 $canChangePrimary = false;
Chris@76 3223 }
Chris@76 3224
Chris@76 3225 // If this is their old primary, can we change it?
Chris@76 3226 if ($row['id_group'] == $old_profile['id_group'] && ($row['group_type'] > 1 || $context['can_manage_membergroups']) && $canChangePrimary !== false)
Chris@76 3227 $canChangePrimary = 1;
Chris@76 3228
Chris@76 3229 // If we are not doing a force primary move, don't do it automatically if current primary is not 0.
Chris@76 3230 if ($changeType != 'primary' && $old_profile['id_group'] != 0)
Chris@76 3231 $canChangePrimary = false;
Chris@76 3232
Chris@76 3233 // If this is the one we are acting on, can we even act?
Chris@76 3234 if ((!$context['can_manage_protected'] && $row['group_type'] == 1) || (!$context['can_manage_membergroups'] && $row['group_type'] == 0))
Chris@76 3235 $canChangePrimary = false;
Chris@76 3236 }
Chris@76 3237 $smcFunc['db_free_result']($request);
Chris@76 3238
Chris@76 3239 // Didn't find the target?
Chris@76 3240 if (!$foundTarget)
Chris@76 3241 fatal_lang_error('no_access', false);
Chris@76 3242
Chris@76 3243 // Final security check, don't allow users to promote themselves to admin.
Chris@76 3244 if ($context['can_manage_membergroups'] && !allowedTo('admin_forum'))
Chris@76 3245 {
Chris@76 3246 $request = $smcFunc['db_query']('', '
Chris@76 3247 SELECT COUNT(permission)
Chris@76 3248 FROM {db_prefix}permissions
Chris@76 3249 WHERE id_group = {int:selected_group}
Chris@76 3250 AND permission = {string:admin_forum}
Chris@76 3251 AND add_deny = {int:not_denied}',
Chris@76 3252 array(
Chris@76 3253 'selected_group' => $group_id,
Chris@76 3254 'not_denied' => 1,
Chris@76 3255 'admin_forum' => 'admin_forum',
Chris@76 3256 )
Chris@76 3257 );
Chris@76 3258 list ($disallow) = $smcFunc['db_fetch_row']($request);
Chris@76 3259 $smcFunc['db_free_result']($request);
Chris@76 3260
Chris@76 3261 if ($disallow)
Chris@76 3262 isAllowedTo('admin_forum');
Chris@76 3263 }
Chris@76 3264
Chris@76 3265 // If we're requesting, add the note then return.
Chris@76 3266 if ($changeType == 'request')
Chris@76 3267 {
Chris@76 3268 $request = $smcFunc['db_query']('', '
Chris@76 3269 SELECT id_member
Chris@76 3270 FROM {db_prefix}log_group_requests
Chris@76 3271 WHERE id_member = {int:selected_member}
Chris@76 3272 AND id_group = {int:selected_group}',
Chris@76 3273 array(
Chris@76 3274 'selected_member' => $memID,
Chris@76 3275 'selected_group' => $group_id,
Chris@76 3276 )
Chris@76 3277 );
Chris@76 3278 if ($smcFunc['db_num_rows']($request) != 0)
Chris@76 3279 fatal_lang_error('profile_error_already_requested_group');
Chris@76 3280 $smcFunc['db_free_result']($request);
Chris@76 3281
Chris@76 3282 // Log the request.
Chris@76 3283 $smcFunc['db_insert']('',
Chris@76 3284 '{db_prefix}log_group_requests',
Chris@76 3285 array(
Chris@76 3286 'id_member' => 'int', 'id_group' => 'int', 'time_applied' => 'int', 'reason' => 'string-65534',
Chris@76 3287 ),
Chris@76 3288 array(
Chris@76 3289 $memID, $group_id, time(), $_POST['reason'],
Chris@76 3290 ),
Chris@76 3291 array('id_request')
Chris@76 3292 );
Chris@76 3293
Chris@76 3294 // Send an email to all group moderators etc.
Chris@76 3295 require_once($sourcedir . '/Subs-Post.php');
Chris@76 3296
Chris@76 3297 // Do we have any group moderators?
Chris@76 3298 $request = $smcFunc['db_query']('', '
Chris@76 3299 SELECT id_member
Chris@76 3300 FROM {db_prefix}group_moderators
Chris@76 3301 WHERE id_group = {int:selected_group}',
Chris@76 3302 array(
Chris@76 3303 'selected_group' => $group_id,
Chris@76 3304 )
Chris@76 3305 );
Chris@76 3306 $moderators = array();
Chris@76 3307 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 3308 $moderators[] = $row['id_member'];
Chris@76 3309 $smcFunc['db_free_result']($request);
Chris@76 3310
Chris@76 3311 // Otherwise this is the backup!
Chris@76 3312 if (empty($moderators))
Chris@76 3313 {
Chris@76 3314 require_once($sourcedir . '/Subs-Members.php');
Chris@76 3315 $moderators = membersAllowedTo('manage_membergroups');
Chris@76 3316 }
Chris@76 3317
Chris@76 3318 if (!empty($moderators))
Chris@76 3319 {
Chris@76 3320 $request = $smcFunc['db_query']('', '
Chris@76 3321 SELECT id_member, email_address, lngfile, member_name, mod_prefs
Chris@76 3322 FROM {db_prefix}members
Chris@76 3323 WHERE id_member IN ({array_int:moderator_list})
Chris@76 3324 AND notify_types != {int:no_notifications}
Chris@76 3325 ORDER BY lngfile',
Chris@76 3326 array(
Chris@76 3327 'moderator_list' => $moderators,
Chris@76 3328 'no_notifications' => 4,
Chris@76 3329 )
Chris@76 3330 );
Chris@76 3331 while ($row = $smcFunc['db_fetch_assoc']($request))
Chris@76 3332 {
Chris@76 3333 // Check whether they are interested.
Chris@76 3334 if (!empty($row['mod_prefs']))
Chris@76 3335 {
Chris@76 3336 list(,, $pref_binary) = explode('|', $row['mod_prefs']);
Chris@76 3337 if (!($pref_binary & 4))
Chris@76 3338 continue;
Chris@76 3339 }
Chris@76 3340
Chris@76 3341 $replacements = array(
Chris@76 3342 'RECPNAME' => $row['member_name'],
Chris@76 3343 'APPYNAME' => $old_profile['member_name'],
Chris@76 3344 'GROUPNAME' => $group_name,
Chris@76 3345 'REASON' => $_POST['reason'],
Chris@76 3346 'MODLINK' => $scripturl . '?action=moderate;area=groups;sa=requests',
Chris@76 3347 );
Chris@76 3348
Chris@76 3349 $emaildata = loadEmailTemplate('request_membership', $replacements, empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile']);
Chris@76 3350 sendmail($row['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 2);
Chris@76 3351 }
Chris@76 3352 $smcFunc['db_free_result']($request);
Chris@76 3353 }
Chris@76 3354
Chris@76 3355 return $changeType;
Chris@76 3356 }
Chris@76 3357 // Otherwise we are leaving/joining a group.
Chris@76 3358 elseif ($changeType == 'free')
Chris@76 3359 {
Chris@76 3360 // Are we leaving?
Chris@76 3361 if ($old_profile['id_group'] == $group_id || isset($addGroups[$group_id]))
Chris@76 3362 {
Chris@76 3363 if ($old_profile['id_group'] == $group_id)
Chris@76 3364 $newPrimary = 0;
Chris@76 3365 else
Chris@76 3366 unset($addGroups[$group_id]);
Chris@76 3367 }
Chris@76 3368 // ... if not, must be joining.
Chris@76 3369 else
Chris@76 3370 {
Chris@76 3371 // Can we change the primary, and do we want to?
Chris@76 3372 if ($canChangePrimary)
Chris@76 3373 {
Chris@76 3374 if ($old_profile['id_group'] != 0)
Chris@76 3375 $addGroups[$old_profile['id_group']] = -1;
Chris@76 3376 $newPrimary = $group_id;
Chris@76 3377 }
Chris@76 3378 // Otherwise it's an additional group...
Chris@76 3379 else
Chris@76 3380 $addGroups[$group_id] = -1;
Chris@76 3381 }
Chris@76 3382 }
Chris@76 3383 // Finally, we must be setting the primary.
Chris@76 3384 elseif ($canChangePrimary)
Chris@76 3385 {
Chris@76 3386 if ($old_profile['id_group'] != 0)
Chris@76 3387 $addGroups[$old_profile['id_group']] = -1;
Chris@76 3388 if (isset($addGroups[$group_id]))
Chris@76 3389 unset($addGroups[$group_id]);
Chris@76 3390 $newPrimary = $group_id;
Chris@76 3391 }
Chris@76 3392
Chris@76 3393 // Finally, we can make the changes!
Chris@76 3394 foreach ($addGroups as $id => $dummy)
Chris@76 3395 if (empty($id))
Chris@76 3396 unset($addGroups[$id]);
Chris@76 3397 $addGroups = implode(',', array_flip($addGroups));
Chris@76 3398
Chris@76 3399 // Ensure that we don't cache permissions if the group is changing.
Chris@76 3400 if ($context['user']['is_owner'])
Chris@76 3401 $_SESSION['mc']['time'] = 0;
Chris@76 3402 else
Chris@76 3403 updateSettings(array('settings_updated' => time()));
Chris@76 3404
Chris@76 3405 updateMemberData($memID, array('id_group' => $newPrimary, 'additional_groups' => $addGroups));
Chris@76 3406
Chris@76 3407 return $changeType;
Chris@76 3408 }
Chris@76 3409
Chris@76 3410 ?>