Commit e449b233 by Scott

Coding style (user pages)

parent b0af268c
...@@ -20,479 +20,473 @@ ...@@ -20,479 +20,473 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
require_once QA_INCLUDE_DIR.'db/users.php'; require_once QA_INCLUDE_DIR . 'db/users.php';
require_once QA_INCLUDE_DIR.'app/format.php'; require_once QA_INCLUDE_DIR . 'app/format.php';
require_once QA_INCLUDE_DIR.'app/users.php'; require_once QA_INCLUDE_DIR . 'app/users.php';
require_once QA_INCLUDE_DIR.'db/selects.php'; require_once QA_INCLUDE_DIR . 'db/selects.php';
require_once QA_INCLUDE_DIR.'util/image.php'; require_once QA_INCLUDE_DIR . 'util/image.php';
// Check we're not using single-sign on integration, that we're logged in // Check we're not using single-sign on integration, that we're logged in
if (QA_FINAL_EXTERNAL_USERS) if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User accounts are handled by external code'); qa_fatal_error('User accounts are handled by external code');
$userid = qa_get_logged_in_userid(); $userid = qa_get_logged_in_userid();
if (!isset($userid)) if (!isset($userid))
qa_redirect('login'); qa_redirect('login');
// Get current information on user // Get current information on user
list($useraccount, $userprofile, $userpoints, $userfields)=qa_db_select_with_pending( list($useraccount, $userprofile, $userpoints, $userfields) = qa_db_select_with_pending(
qa_db_user_account_selectspec($userid, true), qa_db_user_account_selectspec($userid, true),
qa_db_user_profile_selectspec($userid, true), qa_db_user_profile_selectspec($userid, true),
qa_db_user_points_selectspec($userid, true), qa_db_user_points_selectspec($userid, true),
qa_db_userfields_selectspec() qa_db_userfields_selectspec()
); );
$changehandle = qa_opt('allow_change_usernames') || (!$userpoints['qposts'] && !$userpoints['aposts'] && !$userpoints['cposts']);
$doconfirms = qa_opt('confirm_user_emails') && $useraccount['level'] < QA_USER_LEVEL_EXPERT;
$isconfirmed = ($useraccount['flags'] & QA_USER_FLAGS_EMAIL_CONFIRMED) ? true : false;
$haspasswordold = isset($useraccount['passsalt']) && isset($useraccount['passcheck']);
if (QA_PASSWORD_HASH) {
$haspassword = isset($useraccount['passhash']);
} else {
$haspassword = $haspasswordold;
}
$permit_error = qa_user_permit_error();
$isblocked = $permit_error !== false;
$pending_confirmation = $doconfirms && $permit_error == 'confirm';
$changehandle = qa_opt('allow_change_usernames') || (!$userpoints['qposts'] && !$userpoints['aposts'] && !$userpoints['cposts']); // Process profile if saved
$doconfirms = qa_opt('confirm_user_emails') && $useraccount['level'] < QA_USER_LEVEL_EXPERT;
$isconfirmed = ($useraccount['flags'] & QA_USER_FLAGS_EMAIL_CONFIRMED) ? true : false;
$haspasswordold = isset($useraccount['passsalt']) && isset($useraccount['passcheck']); // If the post_max_size is exceeded then the $_POST array is empty so no field processing can be done
if (QA_PASSWORD_HASH) { if (qa_post_limit_exceeded())
$haspassword = isset($useraccount['passhash']); $errors['avatar'] = qa_lang('main/file_upload_limit_exceeded');
} else { else {
$haspassword = $haspasswordold; require_once QA_INCLUDE_DIR . 'app/users-edit.php';
}
$permit_error = qa_user_permit_error(); if (qa_clicked('dosaveprofile') && !$isblocked) {
$isblocked = $permit_error !== false; $inhandle = $changehandle ? qa_post_text('handle') : $useraccount['handle'];
$pending_confirmation = $doconfirms && $permit_error == 'confirm'; $inemail = qa_post_text('email');
$inmessages = qa_post_text('messages');
$inwallposts = qa_post_text('wall');
$inmailings = qa_post_text('mailings');
$inavatar = qa_post_text('avatar');
$inprofile = array();
foreach ($userfields as $userfield)
$inprofile[$userfield['fieldid']] = qa_post_text('field_' . $userfield['fieldid']);
if (!qa_check_form_security_code('account', qa_post_text('code')))
$errors['page'] = qa_lang_html('misc/form_security_again');
else {
$errors = qa_handle_email_filter($inhandle, $inemail, $useraccount);
if (!isset($errors['handle']))
qa_db_user_set($userid, 'handle', $inhandle);
if (!isset($errors['email']) && $inemail !== $useraccount['email']) {
qa_db_user_set($userid, 'email', $inemail);
qa_db_user_set_flag($userid, QA_USER_FLAGS_EMAIL_CONFIRMED, false);
$isconfirmed = false;
if ($doconfirms)
qa_send_new_confirm($userid);
}
// Process profile if saved if (qa_opt('allow_private_messages'))
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MESSAGES, !$inmessages);
// If the post_max_size is exceeded then the $_POST array is empty so no field processing can be done if (qa_opt('allow_user_walls'))
if (qa_post_limit_exceeded()) qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_WALL_POSTS, !$inwallposts);
$errors['avatar'] = qa_lang('main/file_upload_limit_exceeded');
else {
require_once QA_INCLUDE_DIR.'app/users-edit.php';
if (qa_clicked('dosaveprofile') && !$isblocked) {
$inhandle = $changehandle ? qa_post_text('handle') : $useraccount['handle'];
$inemail = qa_post_text('email');
$inmessages = qa_post_text('messages');
$inwallposts = qa_post_text('wall');
$inmailings = qa_post_text('mailings');
$inavatar = qa_post_text('avatar');
$inprofile=array();
foreach ($userfields as $userfield)
$inprofile[$userfield['fieldid']] = qa_post_text('field_' . $userfield['fieldid']);
if (!qa_check_form_security_code('account', qa_post_text('code')))
$errors['page'] = qa_lang_html('misc/form_security_again');
else {
$errors = qa_handle_email_filter($inhandle, $inemail, $useraccount);
if (!isset($errors['handle']))
qa_db_user_set($userid, 'handle', $inhandle);
if (!isset($errors['email']) && $inemail !== $useraccount['email']) {
qa_db_user_set($userid, 'email', $inemail);
qa_db_user_set_flag($userid, QA_USER_FLAGS_EMAIL_CONFIRMED, false);
$isconfirmed = false;
if ($doconfirms)
qa_send_new_confirm($userid);
}
if (qa_opt('allow_private_messages')) if (qa_opt('mailing_enabled'))
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MESSAGES, !$inmessages); qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MAILINGS, !$inmailings);
if (qa_opt('allow_user_walls')) qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_AVATAR, ($inavatar == 'uploaded'));
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_WALL_POSTS, !$inwallposts); qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_GRAVATAR, ($inavatar == 'gravatar'));
if (qa_opt('mailing_enabled')) if (is_array(@$_FILES['file'])) {
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MAILINGS, !$inmailings); $avatarfileerror = $_FILES['file']['error'];
qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_AVATAR, ($inavatar == 'uploaded')); // Note if $_FILES['file']['error'] === 1 then upload_max_filesize has been exceeded
qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_GRAVATAR, ($inavatar == 'gravatar')); if ($avatarfileerror === 1)
$errors['avatar'] = qa_lang('main/file_upload_limit_exceeded');
elseif ($avatarfileerror === 0 && $_FILES['file']['size'] > 0) {
require_once QA_INCLUDE_DIR . 'app/limits.php';
if (is_array(@$_FILES['file'])) { switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS)) {
$avatarfileerror = $_FILES['file']['error']; case 'limit':
$errors['avatar'] = qa_lang('main/upload_limit');
break;
// Note if $_FILES['file']['error'] === 1 then upload_max_filesize has been exceeded default:
if ($avatarfileerror === 1) $errors['avatar'] = qa_lang('users/no_permission');
$errors['avatar'] = qa_lang('main/file_upload_limit_exceeded'); break;
elseif ($avatarfileerror === 0 && $_FILES['file']['size'] > 0) {
require_once QA_INCLUDE_DIR.'app/limits.php';
switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS)) { case false:
case 'limit': qa_limits_increment($userid, QA_LIMIT_UPLOADS);
$errors['avatar'] = qa_lang('main/upload_limit'); $toobig = qa_image_file_too_big($_FILES['file']['tmp_name'], qa_opt('avatar_store_size'));
break;
default: if ($toobig)
$errors['avatar'] = qa_lang('users/no_permission'); $errors['avatar'] = qa_lang_sub('main/image_too_big_x_pc', (int)($toobig * 100));
break; elseif (!qa_set_user_avatar($userid, file_get_contents($_FILES['file']['tmp_name']), $useraccount['avatarblobid']))
$errors['avatar'] = qa_lang_sub('main/image_not_read', implode(', ', qa_gd_image_formats()));
break;
}
} // There shouldn't be any need to catch any other error
}
case false: if (count($inprofile)) {
qa_limits_increment($userid, QA_LIMIT_UPLOADS); $filtermodules = qa_load_modules_with('filter', 'filter_profile');
foreach ($filtermodules as $filtermodule)
$filtermodule->filter_profile($inprofile, $errors, $useraccount, $userprofile);
}
$toobig = qa_image_file_too_big($_FILES['file']['tmp_name'], qa_opt('avatar_store_size')); foreach ($userfields as $userfield) {
if (!isset($errors[$userfield['fieldid']]))
qa_db_user_profile_set($userid, $userfield['title'], $inprofile[$userfield['fieldid']]);
}
if ($toobig) list($useraccount, $userprofile) = qa_db_select_with_pending(
$errors['avatar'] = qa_lang_sub('main/image_too_big_x_pc', (int) ($toobig * 100)); qa_db_user_account_selectspec($userid, true), qa_db_user_profile_selectspec($userid, true)
elseif (!qa_set_user_avatar($userid, file_get_contents($_FILES['file']['tmp_name']), $useraccount['avatarblobid'])) );
$errors['avatar'] = qa_lang_sub('main/image_not_read', implode(', ', qa_gd_image_formats()));
break;
}
} // There shouldn't be any need to catch any other error
}
if (count($inprofile)) { qa_report_event('u_save', $userid, $useraccount['handle'], qa_cookie_get());
$filtermodules = qa_load_modules_with('filter', 'filter_profile');
foreach ($filtermodules as $filtermodule)
$filtermodule->filter_profile($inprofile, $errors, $useraccount, $userprofile);
}
foreach ($userfields as $userfield) { if (empty($errors))
if (!isset($errors[$userfield['fieldid']])) qa_redirect('account', array('state' => 'profile-saved'));
qa_db_user_profile_set($userid, $userfield['title'], $inprofile[$userfield['fieldid']]);
} qa_logged_in_user_flush();
}
} else if (qa_clicked('dosaveprofile') && $pending_confirmation) {
// only allow user to update email if they are not confirmed yet
$inemail = qa_post_text('email');
list($useraccount, $userprofile) = qa_db_select_with_pending( if (!qa_check_form_security_code('account', qa_post_text('code')))
qa_db_user_account_selectspec($userid, true), qa_db_user_profile_selectspec($userid, true) $errors['page'] = qa_lang_html('misc/form_security_again');
);
qa_report_event('u_save', $userid, $useraccount['handle'], qa_cookie_get()); else {
$errors = qa_handle_email_filter($useraccount['handle'], $inemail, $useraccount);
if (empty($errors)) if (!isset($errors['email']) && $inemail !== $useraccount['email']) {
qa_redirect('account', array('state' => 'profile-saved')); qa_db_user_set($userid, 'email', $inemail);
qa_db_user_set_flag($userid, QA_USER_FLAGS_EMAIL_CONFIRMED, false);
$isconfirmed = false;
qa_logged_in_user_flush(); if ($doconfirms)
qa_send_new_confirm($userid);
} }
} else if (qa_clicked('dosaveprofile') && $pending_confirmation) {
// only allow user to update email if they are not confirmed yet
$inemail = qa_post_text('email');
if (!qa_check_form_security_code('account', qa_post_text('code'))) qa_report_event('u_save', $userid, $useraccount['handle'], qa_cookie_get());
$errors['page'] = qa_lang_html('misc/form_security_again');
else { if (empty($errors))
$errors = qa_handle_email_filter($useraccount['handle'], $inemail, $useraccount); qa_redirect('account', array('state' => 'profile-saved'));
if (!isset($errors['email']) && $inemail !== $useraccount['email']) { qa_logged_in_user_flush();
qa_db_user_set($userid, 'email', $inemail); }
qa_db_user_set_flag($userid, QA_USER_FLAGS_EMAIL_CONFIRMED, false); }
$isconfirmed = false;
// Process change password if clicked
if ($doconfirms) if (qa_clicked('dochangepassword')) {
qa_send_new_confirm($userid); $inoldpassword = qa_post_text('oldpassword');
$innewpassword1 = qa_post_text('newpassword1');
$innewpassword2 = qa_post_text('newpassword2');
if (!qa_check_form_security_code('password', qa_post_text('code')))
$errors['page'] = qa_lang_html('misc/form_security_again');
else {
$errors = array();
$legacyPassError = !hash_equals(strtolower($useraccount['passcheck']), strtolower(qa_db_calc_passcheck($inoldpassword, $useraccount['passsalt'])));
if (QA_PASSWORD_HASH) {
$passError = !password_verify($inoldpassword, $useraccount['passhash']);
if (($haspasswordold && $legacyPassError) || (!$haspasswordold && $haspassword && $passError)) {
$errors['oldpassword'] = qa_lang('users/password_wrong');
} }
} else {
if ($haspassword && $legacyPassError) {
$errors['oldpassword'] = qa_lang('users/password_wrong');
}
}
$useraccount['password'] = $inoldpassword;
$errors = $errors + qa_password_validate($innewpassword1, $useraccount); // array union
if ($innewpassword1 != $innewpassword2)
$errors['newpassword2'] = qa_lang('users/password_mismatch');
qa_report_event('u_save', $userid, $useraccount['handle'], qa_cookie_get()); if (empty($errors)) {
qa_db_user_set_password($userid, $innewpassword1);
qa_db_user_set($userid, 'sessioncode', ''); // stop old 'Remember me' style logins from still working
qa_set_logged_in_user($userid, $useraccount['handle'], false, $useraccount['sessionsource']); // reinstate this specific session
if (empty($errors)) qa_report_event('u_password', $userid, $useraccount['handle'], qa_cookie_get());
qa_redirect('account', array('state' => 'profile-saved'));
qa_logged_in_user_flush(); qa_redirect('account', array('state' => 'password-changed'));
} }
} }
}
}
// Prepare content for theme
// Process change password if clicked $qa_content = qa_content_prepare();
if (qa_clicked('dochangepassword')) {
$inoldpassword = qa_post_text('oldpassword');
$innewpassword1 = qa_post_text('newpassword1');
$innewpassword2 = qa_post_text('newpassword2');
if (!qa_check_form_security_code('password', qa_post_text('code'))) $qa_content['title'] = qa_lang_html('profile/my_account_title');
$errors['page'] = qa_lang_html('misc/form_security_again'); $qa_content['error'] = @$errors['page'];
else { $qa_content['form_profile'] = array(
$errors = array(); 'tags' => 'enctype="multipart/form-data" method="post" action="' . qa_self_html() . '"',
$legacyPassError = !hash_equals(strtolower($useraccount['passcheck']), strtolower(qa_db_calc_passcheck($inoldpassword, $useraccount['passsalt'])));
if (QA_PASSWORD_HASH) { 'style' => 'wide',
$passError = !password_verify($inoldpassword,$useraccount['passhash']);
if (($haspasswordold && $legacyPassError) || (!$haspasswordold && $haspassword && $passError)) {
$errors['oldpassword'] = qa_lang('users/password_wrong');
}
} else {
if ($haspassword && $legacyPassError) {
$errors['oldpassword'] = qa_lang('users/password_wrong');
}
}
$useraccount['password'] = $inoldpassword; 'fields' => array(
$errors = $errors + qa_password_validate($innewpassword1, $useraccount); // array union 'duration' => array(
'type' => 'static',
'label' => qa_lang_html('users/member_for'),
'value' => qa_time_to_string(qa_opt('db_time') - $useraccount['created']),
),
if ($innewpassword1 != $innewpassword2) 'type' => array(
$errors['newpassword2'] = qa_lang('users/password_mismatch'); 'type' => 'static',
'label' => qa_lang_html('users/member_type'),
'value' => qa_html(qa_user_level_string($useraccount['level'])),
'note' => $isblocked ? qa_lang_html('users/user_blocked') : null,
),
if (empty($errors)) { 'handle' => array(
qa_db_user_set_password($userid, $innewpassword1); 'label' => qa_lang_html('users/handle_label'),
qa_db_user_set($userid, 'sessioncode', ''); // stop old 'Remember me' style logins from still working 'tags' => 'name="handle"',
qa_set_logged_in_user($userid, $useraccount['handle'], false, $useraccount['sessionsource']); // reinstate this specific session 'value' => qa_html(isset($inhandle) ? $inhandle : $useraccount['handle']),
'error' => qa_html(@$errors['handle']),
'type' => ($changehandle && !$isblocked) ? 'text' : 'static',
),
qa_report_event('u_password', $userid, $useraccount['handle'], qa_cookie_get()); 'email' => array(
'label' => qa_lang_html('users/email_label'),
'tags' => 'name="email"',
'value' => qa_html(isset($inemail) ? $inemail : $useraccount['email']),
'error' => isset($errors['email']) ? qa_html($errors['email']) :
($pending_confirmation ? qa_insert_login_links(qa_lang_html('users/email_please_confirm')) : null),
'type' => $pending_confirmation ? 'text' : ($isblocked ? 'static' : 'text'),
),
qa_redirect('account', array('state' => 'password-changed')); 'messages' => array(
} 'label' => qa_lang_html('users/private_messages'),
} 'tags' => 'name="messages"' . ($pending_confirmation ? ' disabled' : ''),
} 'type' => 'checkbox',
} 'value' => !($useraccount['flags'] & QA_USER_FLAGS_NO_MESSAGES),
'note' => qa_lang_html('users/private_messages_explanation'),
),
// Prepare content for theme 'wall' => array(
'label' => qa_lang_html('users/wall_posts'),
'tags' => 'name="wall"' . ($pending_confirmation ? ' disabled' : ''),
'type' => 'checkbox',
'value' => !($useraccount['flags'] & QA_USER_FLAGS_NO_WALL_POSTS),
'note' => qa_lang_html('users/wall_posts_explanation'),
),
$qa_content=qa_content_prepare(); 'mailings' => array(
'label' => qa_lang_html('users/mass_mailings'),
$qa_content['title']=qa_lang_html('profile/my_account_title'); 'tags' => 'name="mailings"',
$qa_content['error']=@$errors['page']; 'type' => 'checkbox',
'value' => !($useraccount['flags'] & QA_USER_FLAGS_NO_MAILINGS),
$qa_content['form_profile']=array( 'note' => qa_lang_html('users/mass_mailings_explanation'),
'tags' => 'enctype="multipart/form-data" method="post" action="'.qa_self_html().'"',
'style' => 'wide',
'fields' => array(
'duration' => array(
'type' => 'static',
'label' => qa_lang_html('users/member_for'),
'value' => qa_time_to_string(qa_opt('db_time')-$useraccount['created']),
),
'type' => array(
'type' => 'static',
'label' => qa_lang_html('users/member_type'),
'value' => qa_html(qa_user_level_string($useraccount['level'])),
'note' => $isblocked ? qa_lang_html('users/user_blocked') : null,
),
'handle' => array(
'label' => qa_lang_html('users/handle_label'),
'tags' => 'name="handle"',
'value' => qa_html(isset($inhandle) ? $inhandle : $useraccount['handle']),
'error' => qa_html(@$errors['handle']),
'type' => ($changehandle && !$isblocked) ? 'text' : 'static',
),
'email' => array(
'label' => qa_lang_html('users/email_label'),
'tags' => 'name="email"',
'value' => qa_html(isset($inemail) ? $inemail : $useraccount['email']),
'error' => isset($errors['email']) ? qa_html($errors['email']) :
($pending_confirmation ? qa_insert_login_links(qa_lang_html('users/email_please_confirm')) : null),
'type' => $pending_confirmation ? 'text' : ($isblocked ? 'static' : 'text'),
),
'messages' => array(
'label' => qa_lang_html('users/private_messages'),
'tags' => 'name="messages"' . ($pending_confirmation ? ' disabled' : ''),
'type' => 'checkbox',
'value' => !($useraccount['flags'] & QA_USER_FLAGS_NO_MESSAGES),
'note' => qa_lang_html('users/private_messages_explanation'),
),
'wall' => array(
'label' => qa_lang_html('users/wall_posts'),
'tags' => 'name="wall"' . ($pending_confirmation ? ' disabled' : ''),
'type' => 'checkbox',
'value' => !($useraccount['flags'] & QA_USER_FLAGS_NO_WALL_POSTS),
'note' => qa_lang_html('users/wall_posts_explanation'),
),
'mailings' => array(
'label' => qa_lang_html('users/mass_mailings'),
'tags' => 'name="mailings"',
'type' => 'checkbox',
'value' => !($useraccount['flags'] & QA_USER_FLAGS_NO_MAILINGS),
'note' => qa_lang_html('users/mass_mailings_explanation'),
),
'avatar' => null, // for positioning
), ),
'buttons' => array( 'avatar' => null, // for positioning
'save' => array( ),
'tags' => 'onclick="qa_show_waiting_after(this, false);"',
'label' => qa_lang_html('users/save_profile'), 'buttons' => array(
), 'save' => array(
'tags' => 'onclick="qa_show_waiting_after(this, false);"',
'label' => qa_lang_html('users/save_profile'),
), ),
),
'hidden' => array( 'hidden' => array(
'dosaveprofile' => array( 'dosaveprofile' => array(
'tags' => 'name="dosaveprofile"', 'tags' => 'name="dosaveprofile"',
'value' => '1', 'value' => '1',
),
'code' => array(
'tags' => 'name="code"',
'value' => qa_get_form_security_code('account'),
),
), ),
); 'code' => array(
'tags' => 'name="code"',
'value' => qa_get_form_security_code('account'),
),
),
);
if (qa_get_state()=='profile-saved') if (qa_get_state() == 'profile-saved')
$qa_content['form_profile']['ok']=qa_lang_html('users/profile_saved'); $qa_content['form_profile']['ok'] = qa_lang_html('users/profile_saved');
if (!qa_opt('allow_private_messages')) if (!qa_opt('allow_private_messages'))
unset($qa_content['form_profile']['fields']['messages']); unset($qa_content['form_profile']['fields']['messages']);
if (!qa_opt('allow_user_walls')) if (!qa_opt('allow_user_walls'))
unset($qa_content['form_profile']['fields']['wall']); unset($qa_content['form_profile']['fields']['wall']);
if (!qa_opt('mailing_enabled')) if (!qa_opt('mailing_enabled'))
unset($qa_content['form_profile']['fields']['mailings']); unset($qa_content['form_profile']['fields']['mailings']);
if ($isblocked && !$pending_confirmation) { if ($isblocked && !$pending_confirmation) {
unset($qa_content['form_profile']['buttons']['save']); unset($qa_content['form_profile']['buttons']['save']);
$qa_content['error']=qa_lang_html('users/no_permission'); $qa_content['error'] = qa_lang_html('users/no_permission');
} }
// Avatar upload stuff // Avatar upload stuff
if (qa_opt('avatar_allow_gravatar') || qa_opt('avatar_allow_upload')) { if (qa_opt('avatar_allow_gravatar') || qa_opt('avatar_allow_upload')) {
$avataroptions=array(); $avataroptions = array();
if (qa_opt('avatar_default_show') && strlen(qa_opt('avatar_default_blobid'))) { if (qa_opt('avatar_default_show') && strlen(qa_opt('avatar_default_blobid'))) {
$avataroptions['']='<span style="margin:2px 0; display:inline-block;">'. $avataroptions[''] = '<span style="margin:2px 0; display:inline-block;">' .
qa_get_avatar_blob_html(qa_opt('avatar_default_blobid'), qa_opt('avatar_default_width'), qa_opt('avatar_default_height'), 32). qa_get_avatar_blob_html(qa_opt('avatar_default_blobid'), qa_opt('avatar_default_width'), qa_opt('avatar_default_height'), 32) .
'</span> '.qa_lang_html('users/avatar_default'); '</span> ' . qa_lang_html('users/avatar_default');
} else } else
$avataroptions['']=qa_lang_html('users/avatar_none'); $avataroptions[''] = qa_lang_html('users/avatar_none');
$avatarvalue=$avataroptions['']; $avatarvalue = $avataroptions[''];
if (qa_opt('avatar_allow_gravatar') && !$pending_confirmation) { if (qa_opt('avatar_allow_gravatar') && !$pending_confirmation) {
$avataroptions['gravatar']='<span style="margin:2px 0; display:inline-block;">'. $avataroptions['gravatar'] = '<span style="margin:2px 0; display:inline-block;">' .
qa_get_gravatar_html($useraccount['email'], 32).' '.strtr(qa_lang_html('users/avatar_gravatar'), array( qa_get_gravatar_html($useraccount['email'], 32) . ' ' . strtr(qa_lang_html('users/avatar_gravatar'), array(
'^1' => '<a href="http://www.gravatar.com/" target="_blank">', '^1' => '<a href="http://www.gravatar.com/" target="_blank">',
'^2' => '</a>', '^2' => '</a>',
)).'</span>'; )) . '</span>';
if ($useraccount['flags'] & QA_USER_FLAGS_SHOW_GRAVATAR) if ($useraccount['flags'] & QA_USER_FLAGS_SHOW_GRAVATAR)
$avatarvalue=$avataroptions['gravatar']; $avatarvalue = $avataroptions['gravatar'];
} }
if (qa_has_gd_image() && qa_opt('avatar_allow_upload') && !$pending_confirmation) { if (qa_has_gd_image() && qa_opt('avatar_allow_upload') && !$pending_confirmation) {
$avataroptions['uploaded']='<input name="file" type="file">'; $avataroptions['uploaded'] = '<input name="file" type="file">';
if (isset($useraccount['avatarblobid'])) if (isset($useraccount['avatarblobid']))
$avataroptions['uploaded']='<span style="margin:2px 0; display:inline-block;">'. $avataroptions['uploaded'] = '<span style="margin:2px 0; display:inline-block;">' .
qa_get_avatar_blob_html($useraccount['avatarblobid'], $useraccount['avatarwidth'], $useraccount['avatarheight'], 32). qa_get_avatar_blob_html($useraccount['avatarblobid'], $useraccount['avatarwidth'], $useraccount['avatarheight'], 32) .
'</span>'.$avataroptions['uploaded']; '</span>' . $avataroptions['uploaded'];
if ($useraccount['flags'] & QA_USER_FLAGS_SHOW_AVATAR) if ($useraccount['flags'] & QA_USER_FLAGS_SHOW_AVATAR)
$avatarvalue=$avataroptions['uploaded']; $avatarvalue = $avataroptions['uploaded'];
} }
$qa_content['form_profile']['fields']['avatar']=array( $qa_content['form_profile']['fields']['avatar'] = array(
'type' => 'select-radio', 'type' => 'select-radio',
'label' => qa_lang_html('users/avatar_label'), 'label' => qa_lang_html('users/avatar_label'),
'tags' => 'name="avatar"', 'tags' => 'name="avatar"',
'options' => $avataroptions, 'options' => $avataroptions,
'value' => $avatarvalue, 'value' => $avatarvalue,
'error' => qa_html(@$errors['avatar']), 'error' => qa_html(@$errors['avatar']),
); );
} else } else {
unset($qa_content['form_profile']['fields']['avatar']); unset($qa_content['form_profile']['fields']['avatar']);
}
// Other profile fields // Other profile fields
foreach ($userfields as $userfield) { foreach ($userfields as $userfield) {
$value=@$inprofile[$userfield['fieldid']]; $value = @$inprofile[$userfield['fieldid']];
if (!isset($value)) if (!isset($value))
$value=@$userprofile[$userfield['title']]; $value = @$userprofile[$userfield['title']];
$label=trim(qa_user_userfield_label($userfield), ':'); $label = trim(qa_user_userfield_label($userfield), ':');
if (strlen($label)) if (strlen($label))
$label.=':'; $label .= ':';
$qa_content['form_profile']['fields'][$userfield['title']]=array( $qa_content['form_profile']['fields'][$userfield['title']] = array(
'label' => qa_html($label), 'label' => qa_html($label),
'tags' => 'name="field_'.$userfield['fieldid'].'"', 'tags' => 'name="field_' . $userfield['fieldid'] . '"',
'value' => qa_html($value), 'value' => qa_html($value),
'error' => qa_html(@$errors[$userfield['fieldid']]), 'error' => qa_html(@$errors[$userfield['fieldid']]),
'rows' => ($userfield['flags'] & QA_FIELD_FLAGS_MULTI_LINE) ? 8 : null, 'rows' => ($userfield['flags'] & QA_FIELD_FLAGS_MULTI_LINE) ? 8 : null,
'type' => $isblocked ? 'static' : 'text', 'type' => $isblocked ? 'static' : 'text',
); );
} }
// Raw information for plugin layers to access // Raw information for plugin layers to access
$qa_content['raw']['account']=$useraccount; $qa_content['raw']['account'] = $useraccount;
$qa_content['raw']['profile']=$userprofile; $qa_content['raw']['profile'] = $userprofile;
$qa_content['raw']['points']=$userpoints; $qa_content['raw']['points'] = $userpoints;
// Change password form // Change password form
$qa_content['form_password']=array( $qa_content['form_password'] = array(
'tags' => 'method="post" action="'.qa_self_html().'"', 'tags' => 'method="post" action="' . qa_self_html() . '"',
'style' => 'wide', 'style' => 'wide',
'title' => qa_lang_html('users/change_password'), 'title' => qa_lang_html('users/change_password'),
'fields' => array( 'fields' => array(
'old' => array( 'old' => array(
'label' => qa_lang_html('users/old_password'), 'label' => qa_lang_html('users/old_password'),
'tags' => 'name="oldpassword"', 'tags' => 'name="oldpassword"',
'value' => qa_html(@$inoldpassword), 'value' => qa_html(@$inoldpassword),
'type' => 'password', 'type' => 'password',
'error' => qa_html(@$errors['oldpassword']), 'error' => qa_html(@$errors['oldpassword']),
),
'new_1' => array(
'label' => qa_lang_html('users/new_password_1'),
'tags' => 'name="newpassword1"',
'type' => 'password',
'error' => qa_html(@$errors['password']),
),
'new_2' => array(
'label' => qa_lang_html('users/new_password_2'),
'tags' => 'name="newpassword2"',
'type' => 'password',
'error' => qa_html(@$errors['newpassword2']),
),
), ),
'buttons' => array( 'new_1' => array(
'change' => array( 'label' => qa_lang_html('users/new_password_1'),
'label' => qa_lang_html('users/change_password'), 'tags' => 'name="newpassword1"',
), 'type' => 'password',
'error' => qa_html(@$errors['password']),
), ),
'hidden' => array( 'new_2' => array(
'dochangepassword' => array( 'label' => qa_lang_html('users/new_password_2'),
'tags' => 'name="dochangepassword"', 'tags' => 'name="newpassword2"',
'value' => '1', 'type' => 'password',
), 'error' => qa_html(@$errors['newpassword2']),
'code' => array(
'tags' => 'name="code"',
'value' => qa_get_form_security_code('password'),
),
), ),
); ),
if (!$haspassword && !$haspasswordold) { 'buttons' => array(
$qa_content['form_password']['fields']['old']['type']='static'; 'change' => array(
$qa_content['form_password']['fields']['old']['value']=qa_lang_html('users/password_none'); 'label' => qa_lang_html('users/change_password'),
} ),
),
if (qa_get_state()=='password-changed') 'hidden' => array(
$qa_content['form_profile']['ok']=qa_lang_html('users/password_changed'); 'dochangepassword' => array(
'tags' => 'name="dochangepassword"',
'value' => '1',
),
'code' => array(
'tags' => 'name="code"',
'value' => qa_get_form_security_code('password'),
),
),
);
if (!$haspassword && !$haspasswordold) {
$qa_content['form_password']['fields']['old']['type'] = 'static';
$qa_content['form_password']['fields']['old']['value'] = qa_lang_html('users/password_none');
}
$qa_content['navigation']['sub']=qa_user_sub_navigation($useraccount['handle'], 'account', true); if (qa_get_state() == 'password-changed')
$qa_content['form_profile']['ok'] = qa_lang_html('users/password_changed');
return $qa_content; $qa_content['navigation']['sub'] = qa_user_sub_navigation($useraccount['handle'], 'account', true);
/* return $qa_content;
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,136 +20,131 @@ ...@@ -20,136 +20,131 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
// Check we're not using single-sign on integration, that we're not already confirmed, and that we're not blocked // Check we're not using single-sign on integration, that we're not already confirmed, and that we're not blocked
if (QA_FINAL_EXTERNAL_USERS) if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User login is handled by external code'); qa_fatal_error('User login is handled by external code');
// Check if we've been asked to send a new link or have a successful email confirmation // Check if we've been asked to send a new link or have a successful email confirmation
$incode=trim(qa_get('c')); // trim to prevent passing in blank values to match uninitiated DB rows $incode = trim(qa_get('c')); // trim to prevent passing in blank values to match uninitiated DB rows
$inhandle=qa_get('u'); $inhandle = qa_get('u');
$loginuserid=qa_get_logged_in_userid(); $loginuserid = qa_get_logged_in_userid();
$useremailed=false; $useremailed = false;
$userconfirmed=false; $userconfirmed = false;
if (isset($loginuserid) && qa_clicked('dosendconfirm')) { // button clicked to send a link if (isset($loginuserid) && qa_clicked('dosendconfirm')) { // button clicked to send a link
require_once QA_INCLUDE_DIR.'app/users-edit.php'; require_once QA_INCLUDE_DIR . 'app/users-edit.php';
if (!qa_check_form_security_code('confirm', qa_post_text('code'))) if (!qa_check_form_security_code('confirm', qa_post_text('code')))
$pageerror=qa_lang_html('misc/form_security_again'); $pageerror = qa_lang_html('misc/form_security_again');
else { else {
qa_send_new_confirm($loginuserid); qa_send_new_confirm($loginuserid);
$useremailed=true; $useremailed = true;
} }
} elseif (strlen($incode)) { // non-empty code detected from the URL } elseif (strlen($incode)) { // non-empty code detected from the URL
require_once QA_INCLUDE_DIR.'db/selects.php'; require_once QA_INCLUDE_DIR . 'db/selects.php';
require_once QA_INCLUDE_DIR.'app/users-edit.php'; require_once QA_INCLUDE_DIR . 'app/users-edit.php';
if (!empty($inhandle)) { // match based on code and handle provided on URL if (!empty($inhandle)) { // match based on code and handle provided on URL
$userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($inhandle, false)); $userinfo = qa_db_select_with_pending(qa_db_user_account_selectspec($inhandle, false));
if (strtolower(trim(@$userinfo['emailcode']))==strtolower($incode)) { if (strtolower(trim(@$userinfo['emailcode'])) == strtolower($incode)) {
qa_complete_confirm($userinfo['userid'], $userinfo['email'], $userinfo['handle']); qa_complete_confirm($userinfo['userid'], $userinfo['email'], $userinfo['handle']);
$userconfirmed=true; $userconfirmed = true;
}
} }
}
if ((!$userconfirmed) && isset($loginuserid)) { // as a backup, also match code on URL against logged in user if ((!$userconfirmed) && isset($loginuserid)) { // as a backup, also match code on URL against logged in user
$userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($loginuserid, true)); $userinfo = qa_db_select_with_pending(qa_db_user_account_selectspec($loginuserid, true));
$flags=$userinfo['flags']; $flags = $userinfo['flags'];
if ( ($flags & QA_USER_FLAGS_EMAIL_CONFIRMED) && !($flags & QA_USER_FLAGS_MUST_CONFIRM) ) if (($flags & QA_USER_FLAGS_EMAIL_CONFIRMED) && !($flags & QA_USER_FLAGS_MUST_CONFIRM))
$userconfirmed=true; // if they confirmed before, just show message as if it happened now $userconfirmed = true; // if they confirmed before, just show message as if it happened now
elseif (strtolower(trim($userinfo['emailcode']))==strtolower($incode)) { elseif (strtolower(trim($userinfo['emailcode'])) == strtolower($incode)) {
qa_complete_confirm($userinfo['userid'], $userinfo['email'], $userinfo['handle']); qa_complete_confirm($userinfo['userid'], $userinfo['email'], $userinfo['handle']);
$userconfirmed=true; $userconfirmed = true;
}
} }
} }
}
// Prepare content for theme // Prepare content for theme
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['title']=qa_lang_html('users/confirm_title'); $qa_content['title'] = qa_lang_html('users/confirm_title');
$qa_content['error']=@$pageerror; $qa_content['error'] = @$pageerror;
if ($useremailed) if ($useremailed) {
$qa_content['error']=qa_lang_html('users/confirm_emailed'); // not an error, but display it prominently anyway $qa_content['error'] = qa_lang_html('users/confirm_emailed'); // not an error, but display it prominently anyway
elseif ($userconfirmed) { } elseif ($userconfirmed) {
$qa_content['error']=qa_lang_html('users/confirm_complete'); $qa_content['error'] = qa_lang_html('users/confirm_complete');
if (!isset($loginuserid)) if (!isset($loginuserid)) {
$qa_content['suggest_next']=strtr( $qa_content['suggest_next'] = strtr(
qa_lang_html('users/log_in_to_access'), qa_lang_html('users/log_in_to_access'),
array(
array( '^1' => '<a href="' . qa_path_html('login', array('e' => $inhandle)) . '">',
'^1' => '<a href="'.qa_path_html('login', array('e' => $inhandle)).'">', '^2' => '</a>',
'^2' => '</a>', )
) );
); }
} elseif (isset($loginuserid)) { // if logged in, allow sending a fresh link } elseif (isset($loginuserid)) { // if logged in, allow sending a fresh link
require_once QA_INCLUDE_DIR.'util/string.php'; require_once QA_INCLUDE_DIR . 'util/string.php';
if (strlen($incode)) if (strlen($incode))
$qa_content['error']=qa_lang_html('users/confirm_wrong_resend'); $qa_content['error'] = qa_lang_html('users/confirm_wrong_resend');
$email=qa_get_logged_in_email(); $email = qa_get_logged_in_email();
$qa_content['form']=array( $qa_content['form'] = array(
'tags' => 'method="post" action="'.qa_path_html('confirm').'"', 'tags' => 'method="post" action="' . qa_path_html('confirm') . '"',
'style' => 'tall', 'style' => 'tall',
'fields' => array( 'fields' => array(
'email' => array( 'email' => array(
'label' => qa_lang_html('users/email_label'), 'label' => qa_lang_html('users/email_label'),
'value' => qa_html($email).strtr(qa_lang_html('users/change_email_link'), array( 'value' => qa_html($email) . strtr(qa_lang_html('users/change_email_link'), array(
'^1' => '<a href="'.qa_path_html('account').'">', '^1' => '<a href="' . qa_path_html('account') . '">',
'^2' => '</a>', '^2' => '</a>',
)), )),
'type' => 'static', 'type' => 'static',
),
), ),
),
'buttons' => array( 'buttons' => array(
'send' => array( 'send' => array(
'tags' => 'name="dosendconfirm"', 'tags' => 'name="dosendconfirm"',
'label' => qa_lang_html('users/send_confirm_button'), 'label' => qa_lang_html('users/send_confirm_button'),
),
), ),
),
'hidden' => array( 'hidden' => array(
'code' => qa_get_form_security_code('confirm'), 'code' => qa_get_form_security_code('confirm'),
), ),
); );
if (!qa_email_validate($email)) {
$qa_content['error']=qa_lang_html('users/email_invalid');
unset($qa_content['form']['buttons']['send']);
}
} else
$qa_content['error']=qa_insert_login_links(qa_lang_html('users/confirm_wrong_log_in'), 'confirm');
if (!qa_email_validate($email)) {
$qa_content['error'] = qa_lang_html('users/email_invalid');
unset($qa_content['form']['buttons']['send']);
}
return $qa_content; } else
$qa_content['error'] = qa_insert_login_links(qa_lang_html('users/confirm_wrong_log_in'), 'confirm');
/* return $qa_content;
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,177 +20,176 @@ ...@@ -20,177 +20,176 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
// Check we're not using Q2A's single-sign on integration and that we're not logged in // Check we're not using Q2A's single-sign on integration and that we're not logged in
if (QA_FINAL_EXTERNAL_USERS) if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User login is handled by external code'); qa_fatal_error('User login is handled by external code');
if (qa_is_logged_in()) if (qa_is_logged_in())
qa_redirect(''); qa_redirect('');
// Process submitted form after checking we haven't reached rate limit // Process submitted form after checking we haven't reached rate limit
$passwordsent=qa_get('ps'); $passwordsent = qa_get('ps');
$emailexists=qa_get('ee'); $emailexists = qa_get('ee');
$inemailhandle=qa_post_text('emailhandle');
$inpassword=qa_post_text('password');
$inremember=qa_post_text('remember');
if (qa_clicked('dologin') && (strlen($inemailhandle) || strlen($inpassword)) ) { $inemailhandle = qa_post_text('emailhandle');
require_once QA_INCLUDE_DIR.'app/limits.php'; $inpassword = qa_post_text('password');
$inremember = qa_post_text('remember');
if (qa_user_limits_remaining(QA_LIMIT_LOGINS)) { if (qa_clicked('dologin') && (strlen($inemailhandle) || strlen($inpassword))) {
require_once QA_INCLUDE_DIR.'db/users.php'; require_once QA_INCLUDE_DIR . 'app/limits.php';
require_once QA_INCLUDE_DIR.'db/selects.php';
if (!qa_check_form_security_code('login', qa_post_text('code'))) if (qa_user_limits_remaining(QA_LIMIT_LOGINS)) {
$pageerror=qa_lang_html('misc/form_security_again'); require_once QA_INCLUDE_DIR . 'db/users.php';
require_once QA_INCLUDE_DIR . 'db/selects.php';
else { if (!qa_check_form_security_code('login', qa_post_text('code'))) {
qa_limits_increment(null, QA_LIMIT_LOGINS); $pageerror = qa_lang_html('misc/form_security_again');
}
else {
qa_limits_increment(null, QA_LIMIT_LOGINS);
$errors=array(); $errors = array();
if (qa_opt('allow_login_email_only') || (strpos($inemailhandle, '@')!==false)) // handles can't contain @ symbols if (qa_opt('allow_login_email_only') || strpos($inemailhandle, '@') !== false) { // handles can't contain @ symbols
$matchusers=qa_db_user_find_by_email($inemailhandle); $matchusers = qa_db_user_find_by_email($inemailhandle);
else } else {
$matchusers=qa_db_user_find_by_handle($inemailhandle); $matchusers = qa_db_user_find_by_handle($inemailhandle);
}
if (count($matchusers)==1) { // if matches more than one (should be impossible), don't log in if (count($matchusers) == 1) { // if matches more than one (should be impossible), don't log in
$inuserid=$matchusers[0]; $inuserid = $matchusers[0];
$userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($inuserid, true)); $userinfo = qa_db_select_with_pending(qa_db_user_account_selectspec($inuserid, true));
$legacyPassOk = hash_equals(strtolower($userinfo['passcheck']), strtolower(qa_db_calc_passcheck($inpassword, $userinfo['passsalt']))); $legacyPassOk = hash_equals(strtolower($userinfo['passcheck']), strtolower(qa_db_calc_passcheck($inpassword, $userinfo['passsalt'])));
if (QA_PASSWORD_HASH) { if (QA_PASSWORD_HASH) {
$haspassword = isset($userinfo['passhash']); $haspassword = isset($userinfo['passhash']);
$haspasswordold = isset($userinfo['passsalt']) && isset($userinfo['passcheck']); $haspasswordold = isset($userinfo['passsalt']) && isset($userinfo['passcheck']);
$passOk = password_verify($inpassword,$userinfo['passhash']); $passOk = password_verify($inpassword, $userinfo['passhash']);
if (($haspasswordold && $legacyPassOk) || ($haspassword && $passOk)) { if (($haspasswordold && $legacyPassOk) || ($haspassword && $passOk)) {
// upgrade password or rehash, when options like the cost parameter changed // upgrade password or rehash, when options like the cost parameter changed
if ($haspasswordold || password_needs_rehash($userinfo['passhash'], PASSWORD_BCRYPT)) { if ($haspasswordold || password_needs_rehash($userinfo['passhash'], PASSWORD_BCRYPT)) {
qa_db_user_set_password($inuserid, $inpassword); qa_db_user_set_password($inuserid, $inpassword);
}
} else {
$errors['password']=qa_lang('users/password_wrong');
} }
} else { } else {
if (!$legacyPassOk) { $errors['password'] = qa_lang('users/password_wrong');
$errors['password']=qa_lang('users/password_wrong');
}
} }
} else {
if (!$legacyPassOk) {
$errors['password'] = qa_lang('users/password_wrong');
}
}
if (!isset($errors['password'])) { if (!isset($errors['password'])) {
// login and redirect // login and redirect
require_once QA_INCLUDE_DIR.'app/users.php'; require_once QA_INCLUDE_DIR . 'app/users.php';
qa_set_logged_in_user($inuserid, $userinfo['handle'], !empty($inremember)); qa_set_logged_in_user($inuserid, $userinfo['handle'], !empty($inremember));
$topath=qa_get('to'); $topath = qa_get('to');
if (isset($topath)) if (isset($topath))
qa_redirect_raw(qa_path_to_root().$topath); // path already provided as URL fragment qa_redirect_raw(qa_path_to_root() . $topath); // path already provided as URL fragment
elseif ($passwordsent) elseif ($passwordsent)
qa_redirect('account'); qa_redirect('account');
else else
qa_redirect(''); qa_redirect('');
} }
} else } else {
$errors['emailhandle']=qa_lang('users/user_not_found'); $errors['emailhandle'] = qa_lang('users/user_not_found');
} }
}
} else } else {
$pageerror=qa_lang('users/login_limit'); $pageerror = qa_lang('users/login_limit');
}
} else } else {
$inemailhandle=qa_get('e'); $inemailhandle = qa_get('e');
}
// Prepare content for theme // Prepare content for theme
$qa_content=qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['title']=qa_lang_html('users/login_title'); $qa_content['title'] = qa_lang_html('users/login_title');
$qa_content['error']=@$pageerror; $qa_content['error'] = @$pageerror;
if (empty($inemailhandle) || isset($errors['emailhandle'])) if (empty($inemailhandle) || isset($errors['emailhandle']))
$forgotpath=qa_path('forgot'); $forgotpath = qa_path('forgot');
else else
$forgotpath=qa_path('forgot', array('e' => $inemailhandle)); $forgotpath = qa_path('forgot', array('e' => $inemailhandle));
$forgothtml='<a href="'.qa_html($forgotpath).'">'.qa_lang_html('users/forgot_link').'</a>'; $forgothtml = '<a href="' . qa_html($forgotpath) . '">' . qa_lang_html('users/forgot_link') . '</a>';
$qa_content['form']=array( $qa_content['form'] = array(
'tags' => 'method="post" action="'.qa_self_html().'"', 'tags' => 'method="post" action="' . qa_self_html() . '"',
'style' => 'tall', 'style' => 'tall',
'ok' => $passwordsent ? qa_lang_html('users/password_sent') : ($emailexists ? qa_lang_html('users/email_exists') : null), 'ok' => $passwordsent ? qa_lang_html('users/password_sent') : ($emailexists ? qa_lang_html('users/email_exists') : null),
'fields' => array( 'fields' => array(
'email_handle' => array( 'email_handle' => array(
'label' => qa_opt('allow_login_email_only') ? qa_lang_html('users/email_label') : qa_lang_html('users/email_handle_label'), 'label' => qa_opt('allow_login_email_only') ? qa_lang_html('users/email_label') : qa_lang_html('users/email_handle_label'),
'tags' => 'name="emailhandle" id="emailhandle" dir="auto"', 'tags' => 'name="emailhandle" id="emailhandle" dir="auto"',
'value' => qa_html(@$inemailhandle), 'value' => qa_html(@$inemailhandle),
'error' => qa_html(@$errors['emailhandle']), 'error' => qa_html(@$errors['emailhandle']),
),
'password' => array(
'type' => 'password',
'label' => qa_lang_html('users/password_label'),
'tags' => 'name="password" id="password" dir="auto"',
'value' => qa_html(@$inpassword),
'error' => empty($errors['password']) ? '' : (qa_html(@$errors['password']).' - '.$forgothtml),
'note' => $passwordsent ? qa_lang_html('users/password_sent') : $forgothtml,
),
'remember' => array(
'type' => 'checkbox',
'label' => qa_lang_html('users/remember_label'),
'tags' => 'name="remember"',
'value' => !empty($inremember),
),
), ),
'buttons' => array( 'password' => array(
'login' => array( 'type' => 'password',
'label' => qa_lang_html('users/login_button'), 'label' => qa_lang_html('users/password_label'),
), 'tags' => 'name="password" id="password" dir="auto"',
'value' => qa_html(@$inpassword),
'error' => empty($errors['password']) ? '' : (qa_html(@$errors['password']) . ' - ' . $forgothtml),
'note' => $passwordsent ? qa_lang_html('users/password_sent') : $forgothtml,
), ),
'hidden' => array( 'remember' => array(
'dologin' => '1', 'type' => 'checkbox',
'code' => qa_get_form_security_code('login'), 'label' => qa_lang_html('users/remember_label'),
'tags' => 'name="remember"',
'value' => !empty($inremember),
), ),
); ),
$loginmodules=qa_load_modules_with('login', 'login_html'); 'buttons' => array(
'login' => array(
'label' => qa_lang_html('users/login_button'),
),
),
foreach ($loginmodules as $module) { 'hidden' => array(
ob_start(); 'dologin' => '1',
$module->login_html(qa_opt('site_url').qa_get('to'), 'login'); 'code' => qa_get_form_security_code('login'),
$html=ob_get_clean(); ),
);
if (strlen($html)) $loginmodules = qa_load_modules_with('login', 'login_html');
@$qa_content['custom'].='<br>'.$html.'<br>';
}
$qa_content['focusid']=(isset($inemailhandle) && !isset($errors['emailhandle'])) ? 'password' : 'emailhandle'; foreach ($loginmodules as $module) {
ob_start();
$module->login_html(qa_opt('site_url') . qa_get('to'), 'login');
$html = ob_get_clean();
if (strlen($html))
@$qa_content['custom'] .= '<br>' . $html . '<br>';
}
return $qa_content; $qa_content['focusid'] = (isset($inemailhandle) && !isset($errors['emailhandle'])) ? 'password' : 'emailhandle';
/* return $qa_content;
Omit PHP closing tag to help avoid accidental output
*/
...@@ -20,21 +20,16 @@ ...@@ -20,21 +20,16 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
if (QA_FINAL_EXTERNAL_USERS) if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User logout is handled by external code'); qa_fatal_error('User logout is handled by external code');
if (qa_is_logged_in()) if (qa_is_logged_in())
qa_set_logged_in_user(null); qa_set_logged_in_user(null);
qa_redirect(''); // back to home page qa_redirect(''); // back to home page
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
...@@ -20,230 +20,223 @@ ...@@ -20,230 +20,223 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
require_once QA_INCLUDE_DIR.'app/captcha.php'; require_once QA_INCLUDE_DIR . 'app/captcha.php';
require_once QA_INCLUDE_DIR.'db/users.php'; require_once QA_INCLUDE_DIR . 'db/users.php';
// Check we're not using single-sign on integration, that we're not logged in, and we're not blocked // Check we're not using single-sign on integration, that we're not logged in, and we're not blocked
if (QA_FINAL_EXTERNAL_USERS) if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User registration is handled by external code'); qa_fatal_error('User registration is handled by external code');
if (qa_is_logged_in()) if (qa_is_logged_in())
qa_redirect(''); qa_redirect('');
// Get information about possible additional fields // Get information about possible additional fields
$show_terms = qa_opt('show_register_terms'); $show_terms = qa_opt('show_register_terms');
$userfields = qa_db_select_with_pending( $userfields = qa_db_select_with_pending(
qa_db_userfields_selectspec() qa_db_userfields_selectspec()
); );
foreach ($userfields as $index => $userfield) { foreach ($userfields as $index => $userfield) {
if (!($userfield['flags'] & QA_FIELD_FLAGS_ON_REGISTER)) if (!($userfield['flags'] & QA_FIELD_FLAGS_ON_REGISTER))
unset($userfields[$index]); unset($userfields[$index]);
} }
// Check we haven't suspended registration, and this IP isn't blocked // Check we haven't suspended registration, and this IP isn't blocked
if (qa_opt('suspend_register_users')) { if (qa_opt('suspend_register_users')) {
$qa_content = qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['error'] = qa_lang_html('users/register_suspended'); $qa_content['error'] = qa_lang_html('users/register_suspended');
return $qa_content; return $qa_content;
} }
if (qa_user_permit_error()) { if (qa_user_permit_error()) {
$qa_content = qa_content_prepare(); $qa_content = qa_content_prepare();
$qa_content['error'] = qa_lang_html('users/no_permission'); $qa_content['error'] = qa_lang_html('users/no_permission');
return $qa_content; return $qa_content;
} }
// Process submitted form // Process submitted form
if (qa_clicked('doregister')) { if (qa_clicked('doregister')) {
require_once QA_INCLUDE_DIR.'app/limits.php'; require_once QA_INCLUDE_DIR . 'app/limits.php';
if (qa_user_limits_remaining(QA_LIMIT_REGISTRATIONS)) { if (qa_user_limits_remaining(QA_LIMIT_REGISTRATIONS)) {
require_once QA_INCLUDE_DIR.'app/users-edit.php'; require_once QA_INCLUDE_DIR . 'app/users-edit.php';
$inemail = qa_post_text('email');
$inpassword = qa_post_text('password');
$inhandle = qa_post_text('handle');
$interms = (int)qa_post_text('terms');
$inprofile = array();
foreach ($userfields as $userfield)
$inprofile[$userfield['fieldid']] = qa_post_text('field_' . $userfield['fieldid']);
if (!qa_check_form_security_code('register', qa_post_text('code'))) {
$pageerror = qa_lang_html('misc/form_security_again');
} else {
// core validation
$errors = array_merge(
qa_handle_email_filter($inhandle, $inemail),
qa_password_validate($inpassword)
);
// T&Cs validation
if ($show_terms && !$interms)
$errors['terms'] = qa_lang_html('users/terms_not_accepted');
// filter module validation
if (count($inprofile)) {
$filtermodules = qa_load_modules_with('filter', 'filter_profile');
foreach ($filtermodules as $filtermodule)
$filtermodule->filter_profile($inprofile, $errors, null, null);
}
$inemail = qa_post_text('email'); if (qa_opt('captcha_on_register'))
$inpassword = qa_post_text('password'); qa_captcha_validate_post($errors);
$inhandle = qa_post_text('handle');
$interms = (int) qa_post_text('terms');
$inprofile = array(); if (empty($errors)) {
foreach ($userfields as $userfield) // register and redirect
$inprofile[$userfield['fieldid']] = qa_post_text('field_'.$userfield['fieldid']); qa_limits_increment(null, QA_LIMIT_REGISTRATIONS);
if (!qa_check_form_security_code('register', qa_post_text('code'))) { $userid = qa_create_new_user($inemail, $inpassword, $inhandle);
$pageerror = qa_lang_html('misc/form_security_again');
}
else {
// core validation
$errors = array_merge(
qa_handle_email_filter($inhandle, $inemail),
qa_password_validate($inpassword)
);
// T&Cs validation foreach ($userfields as $userfield)
if ($show_terms && !$interms) qa_db_user_profile_set($userid, $userfield['title'], $inprofile[$userfield['fieldid']]);
$errors['terms'] = qa_lang_html('users/terms_not_accepted');
// filter module validation qa_set_logged_in_user($userid, $inhandle);
if (count($inprofile)) {
$filtermodules = qa_load_modules_with('filter', 'filter_profile');
foreach ($filtermodules as $filtermodule)
$filtermodule->filter_profile($inprofile, $errors, null, null);
}
if (qa_opt('captcha_on_register')) $topath = qa_get('to');
qa_captcha_validate_post($errors);
if (empty($errors)) { if (isset($topath))
// register and redirect qa_redirect_raw(qa_path_to_root() . $topath); // path already provided as URL fragment
qa_limits_increment(null, QA_LIMIT_REGISTRATIONS); else
qa_redirect('');
}
}
$userid = qa_create_new_user($inemail, $inpassword, $inhandle); } else
$pageerror = qa_lang('users/register_limit');
}
foreach ($userfields as $userfield)
qa_db_user_profile_set($userid, $userfield['title'], $inprofile[$userfield['fieldid']]);
qa_set_logged_in_user($userid, $inhandle); // Prepare content for theme
$topath = qa_get('to'); $qa_content = qa_content_prepare();
if (isset($topath)) $qa_content['title'] = qa_lang_html('users/register_title');
qa_redirect_raw(qa_path_to_root().$topath); // path already provided as URL fragment
else
qa_redirect('');
}
}
} $qa_content['error'] = @$pageerror;
else
$pageerror = qa_lang('users/register_limit');
}
$qa_content['form'] = array(
'tags' => 'method="post" action="' . qa_self_html() . '"',
// Prepare content for theme 'style' => 'tall',
$qa_content = qa_content_prepare(); 'fields' => array(
'handle' => array(
'label' => qa_lang_html('users/handle_label'),
'tags' => 'name="handle" id="handle" dir="auto"',
'value' => qa_html(@$inhandle),
'error' => qa_html(@$errors['handle']),
),
$qa_content['title'] = qa_lang_html('users/register_title'); 'password' => array(
'type' => 'password',
$qa_content['error'] = @$pageerror; 'label' => qa_lang_html('users/password_label'),
'tags' => 'name="password" id="password" dir="auto"',
$qa_content['form'] = array( 'value' => qa_html(@$inpassword),
'tags' => 'method="post" action="'.qa_self_html().'"', 'error' => qa_html(@$errors['password']),
'style' => 'tall',
'fields' => array(
'handle' => array(
'label' => qa_lang_html('users/handle_label'),
'tags' => 'name="handle" id="handle" dir="auto"',
'value' => qa_html(@$inhandle),
'error' => qa_html(@$errors['handle']),
),
'password' => array(
'type' => 'password',
'label' => qa_lang_html('users/password_label'),
'tags' => 'name="password" id="password" dir="auto"',
'value' => qa_html(@$inpassword),
'error' => qa_html(@$errors['password']),
),
'email' => array(
'label' => qa_lang_html('users/email_label'),
'tags' => 'name="email" id="email" dir="auto"',
'value' => qa_html(@$inemail),
'note' => qa_opt('email_privacy'),
'error' => qa_html(@$errors['email']),
),
), ),
'buttons' => array( 'email' => array(
'register' => array( 'label' => qa_lang_html('users/email_label'),
'tags' => 'onclick="qa_show_waiting_after(this, false);"', 'tags' => 'name="email" id="email" dir="auto"',
'label' => qa_lang_html('users/register_button'), 'value' => qa_html(@$inemail),
), 'note' => qa_opt('email_privacy'),
'error' => qa_html(@$errors['email']),
), ),
),
'hidden' => array( 'buttons' => array(
'doregister' => '1', 'register' => array(
'code' => qa_get_form_security_code('register'), 'tags' => 'onclick="qa_show_waiting_after(this, false);"',
'label' => qa_lang_html('users/register_button'),
), ),
),
'hidden' => array(
'doregister' => '1',
'code' => qa_get_form_security_code('register'),
),
);
// prepend custom message
$custom = qa_opt('show_custom_register') ? trim(qa_opt('custom_register')) : '';
if (strlen($custom)) {
array_unshift($qa_content['form']['fields'], array(
'type' => 'custom',
'note' => $custom,
));
}
foreach ($userfields as $userfield) {
$value = @$inprofile[$userfield['fieldid']];
$label = trim(qa_user_userfield_label($userfield), ':');
if (strlen($label))
$label .= ':';
$qa_content['form']['fields'][$userfield['title']] = array(
'label' => qa_html($label),
'tags' => 'name="field_' . $userfield['fieldid'] . '"',
'value' => qa_html($value),
'error' => qa_html(@$errors[$userfield['fieldid']]),
'rows' => ($userfield['flags'] & QA_FIELD_FLAGS_MULTI_LINE) ? 8 : null,
);
}
if (qa_opt('captcha_on_register'))
qa_set_up_captcha_field($qa_content, $qa_content['form']['fields'], @$errors);
// show T&Cs checkbox
if ($show_terms) {
$qa_content['form']['fields']['terms'] = array(
'type' => 'checkbox',
'label' => trim(qa_opt('register_terms')),
'tags' => 'name="terms" id="terms"',
'value' => qa_html(@$interms),
'error' => qa_html(@$errors['terms']),
); );
}
// prepend custom message $loginmodules = qa_load_modules_with('login', 'login_html');
$custom = qa_opt('show_custom_register') ? trim(qa_opt('custom_register')) : '';
if (strlen($custom)) {
array_unshift($qa_content['form']['fields'], array(
'type' => 'custom',
'note' => $custom,
));
}
foreach ($userfields as $userfield) {
$value = @$inprofile[$userfield['fieldid']];
$label = trim(qa_user_userfield_label($userfield), ':');
if (strlen($label))
$label .= ':';
$qa_content['form']['fields'][$userfield['title']] = array(
'label' => qa_html($label),
'tags' => 'name="field_'.$userfield['fieldid'].'"',
'value' => qa_html($value),
'error' => qa_html(@$errors[$userfield['fieldid']]),
'rows' => ($userfield['flags'] & QA_FIELD_FLAGS_MULTI_LINE) ? 8 : null,
);
}
if (qa_opt('captcha_on_register'))
qa_set_up_captcha_field($qa_content, $qa_content['form']['fields'], @$errors);
// show T&Cs checkbox
if ($show_terms) {
$qa_content['form']['fields']['terms'] = array(
'type' => 'checkbox',
'label' => trim(qa_opt('register_terms')),
'tags' => 'name="terms" id="terms"',
'value' => qa_html(@$interms),
'error' => qa_html(@$errors['terms']),
);
}
$loginmodules = qa_load_modules_with('login', 'login_html');
foreach ($loginmodules as $module) {
ob_start();
$module->login_html(qa_opt('site_url').qa_get('to'), 'register');
$html = ob_get_clean();
if (strlen($html))
@$qa_content['custom'] .= '<br>'.$html.'<br>';
}
// prioritize 'handle' for keyboard focus
$qa_content['focusid'] = isset($errors['handle']) ? 'handle'
: (isset($errors['password']) ? 'password'
: (isset($errors['email']) ? 'email' : 'handle'));
foreach ($loginmodules as $module) {
ob_start();
$module->login_html(qa_opt('site_url') . qa_get('to'), 'register');
$html = ob_get_clean();
return $qa_content; if (strlen($html))
@$qa_content['custom'] .= '<br>' . $html . '<br>';
}
// prioritize 'handle' for keyboard focus
$qa_content['focusid'] = isset($errors['handle']) ? 'handle'
: (isset($errors['password']) ? 'password'
: (isset($errors['email']) ? 'email' : 'handle'));
/*
Omit PHP closing tag to help avoid accidental output return $qa_content;
*/
\ No newline at end of file
...@@ -20,120 +20,116 @@ ...@@ -20,120 +20,116 @@
More about this license: http://www.question2answer.org/license.php More about this license: http://www.question2answer.org/license.php
*/ */
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../'); header('Location: ../');
exit; exit;
} }
// Check we're not using single-sign on integration and that we're not logged in // Check we're not using single-sign on integration and that we're not logged in
if (QA_FINAL_EXTERNAL_USERS) if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User login is handled by external code'); qa_fatal_error('User login is handled by external code');
if (qa_is_logged_in()) if (qa_is_logged_in())
qa_redirect(''); qa_redirect('');
// Process incoming form // Process incoming form
if (qa_clicked('doreset')) { if (qa_clicked('doreset')) {
require_once QA_INCLUDE_DIR.'app/users-edit.php'; require_once QA_INCLUDE_DIR . 'app/users-edit.php';
require_once QA_INCLUDE_DIR.'db/users.php'; require_once QA_INCLUDE_DIR . 'db/users.php';
$inemailhandle=qa_post_text('emailhandle');
$incode=trim(qa_post_text('code')); // trim to prevent passing in blank values to match uninitiated DB rows
$errors=array(); $inemailhandle = qa_post_text('emailhandle');
$incode = trim(qa_post_text('code')); // trim to prevent passing in blank values to match uninitiated DB rows
if (!qa_check_form_security_code('reset', qa_post_text('formcode'))) $errors = array();
$errors['page']=qa_lang_html('misc/form_security_again');
else { if (!qa_check_form_security_code('reset', qa_post_text('formcode')))
if (qa_opt('allow_login_email_only') || (strpos($inemailhandle, '@')!==false)) // handles can't contain @ symbols $errors['page'] = qa_lang_html('misc/form_security_again');
$matchusers=qa_db_user_find_by_email($inemailhandle);
else
$matchusers=qa_db_user_find_by_handle($inemailhandle);
if (count($matchusers)==1) { // if match more than one (should be impossible), consider it a non-match else {
require_once QA_INCLUDE_DIR.'db/selects.php'; if (qa_opt('allow_login_email_only') || (strpos($inemailhandle, '@') !== false)) // handles can't contain @ symbols
$matchusers = qa_db_user_find_by_email($inemailhandle);
else
$matchusers = qa_db_user_find_by_handle($inemailhandle);
$inuserid=$matchusers[0]; if (count($matchusers) == 1) { // if match more than one (should be impossible), consider it a non-match
$userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($inuserid, true)); require_once QA_INCLUDE_DIR . 'db/selects.php';
// strlen() check is vital otherwise we can reset code for most users by entering the empty string $inuserid = $matchusers[0];
if (strlen($incode) && (strtolower(trim($userinfo['emailcode'])) == strtolower($incode))) { $userinfo = qa_db_select_with_pending(qa_db_user_account_selectspec($inuserid, true));
qa_complete_reset_user($inuserid);
qa_redirect('login', array('e' => $inemailhandle, 'ps' => '1')); // redirect to login page
} else // strlen() check is vital otherwise we can reset code for most users by entering the empty string
$errors['code']=qa_lang('users/reset_code_wrong'); if (strlen($incode) && strtolower(trim($userinfo['emailcode'])) == strtolower($incode)) {
qa_complete_reset_user($inuserid);
qa_redirect('login', array('e' => $inemailhandle, 'ps' => '1')); // redirect to login page
} else {
$errors['code'] = qa_lang('users/reset_code_wrong');
}
} else } else {
$errors['emailhandle']=qa_lang('users/user_not_found'); $errors['emailhandle'] = qa_lang('users/user_not_found');
} }
} else {
$inemailhandle=qa_get('e');
$incode=qa_get('c');
} }
} else {
$inemailhandle = qa_get('e');
$incode = qa_get('c');
}
// Prepare content for theme
$qa_content=qa_content_prepare(); // Prepare content for theme
$qa_content['title']=qa_lang_html('users/reset_title'); $qa_content = qa_content_prepare();
$qa_content['error']=@$errors['page'];
if (empty($inemailhandle) || isset($errors['emailhandle'])) $qa_content['title'] = qa_lang_html('users/reset_title');
$forgotpath=qa_path('forgot'); $qa_content['error'] = @$errors['page'];
else
$forgotpath=qa_path('forgot', array('e' => $inemailhandle));
$qa_content['form']=array( if (empty($inemailhandle) || isset($errors['emailhandle']))
'tags' => 'method="post" action="'.qa_self_html().'"', $forgotpath = qa_path('forgot');
else
$forgotpath = qa_path('forgot', array('e' => $inemailhandle));
'style' => 'tall', $qa_content['form'] = array(
'tags' => 'method="post" action="' . qa_self_html() . '"',
'ok' => empty($incode) ? qa_lang_html('users/reset_code_emailed') : null, 'style' => 'tall',
'fields' => array( 'ok' => empty($incode) ? qa_lang_html('users/reset_code_emailed') : null,
'email_handle' => array(
'label' => qa_opt('allow_login_email_only') ? qa_lang_html('users/email_label') : qa_lang_html('users/email_handle_label'),
'tags' => 'name="emailhandle" id="emailhandle"',
'value' => qa_html(@$inemailhandle),
'error' => qa_html(@$errors['emailhandle']),
),
'code' => array( 'fields' => array(
'label' => qa_lang_html('users/reset_code_label'), 'email_handle' => array(
'tags' => 'name="code" id="code"', 'label' => qa_opt('allow_login_email_only') ? qa_lang_html('users/email_label') : qa_lang_html('users/email_handle_label'),
'value' => qa_html(@$incode), 'tags' => 'name="emailhandle" id="emailhandle"',
'error' => qa_html(@$errors['code']), 'value' => qa_html(@$inemailhandle),
'note' => qa_lang_html('users/reset_code_emailed').' - '. 'error' => qa_html(@$errors['emailhandle']),
'<a href="'.qa_html($forgotpath).'">'.qa_lang_html('users/reset_code_another').'</a>',
),
), ),
'buttons' => array( 'code' => array(
'reset' => array( 'label' => qa_lang_html('users/reset_code_label'),
'label' => qa_lang_html('users/send_password_button'), 'tags' => 'name="code" id="code"',
), 'value' => qa_html(@$incode),
'error' => qa_html(@$errors['code']),
'note' => qa_lang_html('users/reset_code_emailed') . ' - ' .
'<a href="' . qa_html($forgotpath) . '">' . qa_lang_html('users/reset_code_another') . '</a>',
), ),
),
'hidden' => array( 'buttons' => array(
'doreset' => '1', 'reset' => array(
'formcode' => qa_get_form_security_code('reset'), 'label' => qa_lang_html('users/send_password_button'),
), ),
); ),
$qa_content['focusid']=(isset($errors['emailhandle']) || !strlen(@$inemailhandle)) ? 'emailhandle' : 'code';
'hidden' => array(
'doreset' => '1',
'formcode' => qa_get_form_security_code('reset'),
),
);
return $qa_content; $qa_content['focusid'] = (isset($errors['emailhandle']) || !strlen(@$inemailhandle)) ? 'emailhandle' : 'code';
/* return $qa_content;
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment