Вход Регистрация
Файл: qa-include/qa-app-users-edit.php
Строк: 415
<?php

/*
    Question2Answer (c) Gideon Greenspan

    http://www.question2answer.org/

    
    File: qa-include/qa-app-users-edit.php
    Version: See define()s at top of qa-include/qa-base.php
    Description: User management (application level) for creating/modifying users


    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    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
        
header('Location: ../');
        exit;
    }

    @
define('QA_MIN_PASSWORD_LEN'4);
    @
define('QA_NEW_PASSWORD_LEN'8); // when resetting password


    
function qa_handle_email_filter(&$handle, &$email$olduser=null)
/*
    Return $errors fields for any invalid aspect of user-entered $handle (username) and $email. Works by calling through
    to all filter modules and also rejects existing values in database unless they belongs to $olduser (if set).
*/
    
{
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        
        
$errors=array();
        
        
$filtermodules=qa_load_modules_with('filter''filter_handle');
        
        foreach (
$filtermodules as $filtermodule) {
            
$error=$filtermodule->filter_handle($handle$olduser);
            if (isset(
$error)) {
                
$errors['handle']=$error;
                break;
            }
        }

        if (!isset(
$errors['handle'])) { // first test through filters, then check for duplicates here
            
$handleusers=qa_db_user_find_by_handle($handle);
            if (
count($handleusers) && ( (!isset($olduser['userid'])) || (array_search($olduser['userid'], $handleusers)===false) ) )
                
$errors['handle']=qa_lang('users/handle_exists');
        }
        
        
$filtermodules=qa_load_modules_with('filter''filter_email');
        
        
$error=null;
        foreach (
$filtermodules as $filtermodule) {
            
$error=$filtermodule->filter_email($email$olduser);
            if (isset(
$error)) {
                
$errors['email']=$error;
                break;
            }
        }

        if (!isset(
$errors['email'])) {
            
$emailusers=qa_db_user_find_by_email($email);
            if (
count($emailusers) && ( (!isset($olduser['userid'])) || (array_search($olduser['userid'], $emailusers)===false) ) )
                
$errors['email']=qa_lang('users/email_exists');
        }
        
        return 
$errors;
    }
    
    
    function 
qa_handle_make_valid($handle)
/*
    Make $handle valid and unique in the database - if $allowuserid is set, allow it to match that user only
*/
    
{
        require_once 
QA_INCLUDE_DIR.'qa-util-string.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-maxima.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        
        if (!
strlen($handle))
            
$handle=qa_lang('users/registered_user');

        
$handle=preg_replace('/[\@\+\/]/'' '$handle);

        for (
$attempt=0$attempt<=99$attempt++) {
            
$suffix=$attempt ? (' '.$attempt) : '';
            
$tryhandle=qa_substr($handle0QA_DB_MAX_HANDLE_LENGTH-strlen($suffix)).$suffix;

            
$filtermodules=qa_load_modules_with('filter''filter_handle');
            foreach (
$filtermodules as $filtermodule)
                
$filtermodule->filter_handle($tryhandlenull); // filter first without worrying about errors, since our goal is to get a valid one
            
            
$haderror=false;
            
            foreach (
$filtermodules as $filtermodule) {
                
$error=$filtermodule->filter_handle($tryhandlenull); // now check for errors after we've filtered
                
if (isset($error))
                    
$haderror=true;
            }
            
            if (!
$haderror) {
                
$handleusers=qa_db_user_find_by_handle($tryhandle);
                if (!
count($handleusers))
                    return 
$tryhandle;
            }
        }
        
        
qa_fatal_error('Could not create a valid and unique handle from: '.$handle);
    }


    function 
qa_password_validate($password$olduser=null)
/*
    Return an array with a single element (key 'password') if user-entered $password is valid, otherwise an empty array.
    Works by calling through to all filter modules.
*/
    
{
        
$error=null;
        
$filtermodules=qa_load_modules_with('filter''validate_password');
        
        foreach (
$filtermodules as $filtermodule) {
            
$error=$filtermodule->validate_password($password$olduser);
            if (isset(
$error))
                break;
        }
        
        if (!isset(
$error)) {
            
$minpasslen=max(QA_MIN_PASSWORD_LEN1);
            if (
qa_strlen($password)<$minpasslen)
                
$error=qa_lang_sub('users/password_min'$minpasslen);
        }        

        if (isset(
$error))
            return array(
'password' => $error);

        return array();
    }

    
    function 
qa_create_new_user($email$password$handle$level=QA_USER_LEVEL_BASIC$confirmed=false)
/*
    Create a new user (application level) with $email, $password, $handle and $level.
    Set $confirmed to true if the email address has been confirmed elsewhere.
    Handles user points, notification and optional email confirmation.
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-points.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-options.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-emails.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-cookies.php';

        
$userid=qa_db_user_create($email$password$handle$levelqa_remote_ip_address());
        
qa_db_points_update_ifuser($useridnull);
        
        if (
$confirmed)
            
qa_db_user_set_flag($useridQA_USER_FLAGS_EMAIL_CONFIRMEDtrue);
            
        if (
qa_opt('show_notice_welcome'))
            
qa_db_user_set_flag($useridQA_USER_FLAGS_WELCOME_NOTICEtrue);
        
        
$custom=qa_opt('show_custom_welcome') ? trim(qa_opt('custom_welcome')) : '';
        
        if (
qa_opt('confirm_user_emails') && ($level<QA_USER_LEVEL_EXPERT) && !$confirmed) {
            
$confirm=strtr(qa_lang('emails/welcome_confirm'), array(
                
'^url' => qa_get_new_confirm_url($userid$handle)
            ));
            
            if (
qa_opt('confirm_user_required'))
                
qa_db_user_set_flag($useridQA_USER_FLAGS_MUST_CONFIRMtrue);
                
        } else
            
$confirm='';
        
        
qa_send_notification($userid$email$handleqa_lang('emails/welcome_subject'), qa_lang('emails/welcome_body'), array(
            
'^password' => isset($password) ? $password qa_lang('users/password_to_set'),
            
'^url' => qa_opt('site_url'),
            
'^custom' => strlen($custom) ? ($custom."nn") : '',
            
'^confirm' => $confirm,
        ));
        
        
qa_report_event('u_register'$userid$handleqa_cookie_get(), array(
            
'email' => $email,
            
'level' => $level,
        ));
        
        return 
$userid;
    }
    
    
    function 
qa_delete_user($userid)
/*
    Delete $userid and all their votes and flags. Their posts will become anonymous.
    Handles recalculations of votes and flags for posts this user has affected.
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-db-votes.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-post-update.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-points.php';
        
        
$postids=qa_db_uservoteflag_user_get($userid); // posts this user has flagged or voted on, whose counts need updating
        
        
qa_db_user_delete($userid);
        
        foreach (
$postids as $postid) { // hoping there aren't many of these - saves a lot of new SQL code...
            
qa_db_post_recount_votes($postid);
            
qa_db_post_recount_flags($postid);
        }
        
        
$postuserids=qa_db_posts_get_userids($postids);
            
        foreach (
$postuserids as $postuserid)
            
qa_db_points_update_ifuser($postuserid, array('avoteds','qvoteds''upvoteds''downvoteds'));
    }

    
    function 
qa_send_new_confirm($userid)
/*
    Set a new email confirmation code for the user and send it out
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-selects.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-emails.php';

        
$userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($useridtrue));
        
        if (!
qa_send_notification($userid$userinfo['email'], $userinfo['handle'], qa_lang('emails/confirm_subject'), qa_lang('emails/confirm_body'), array(
            
'^url' => qa_get_new_confirm_url($userid$userinfo['handle']),
        )))
            
qa_fatal_error('Could not send email confirmation');
    }

    
    function 
qa_get_new_confirm_url($userid$handle)
/*
    Set a new email confirmation code for the user and return the corresponding link
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        
        
$emailcode=qa_db_user_rand_emailcode();
        
qa_db_user_set($userid'emailcode'$emailcode);
        
        return 
qa_path('confirm', array('c' => $emailcode'u' => $handle), qa_opt('site_url'));
    }

    
    function 
qa_complete_confirm($userid$email$handle)
/*
    Complete the email confirmation process for the user
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-cookies.php';
        
        
qa_db_user_set_flag($useridQA_USER_FLAGS_EMAIL_CONFIRMEDtrue);
        
qa_db_user_set_flag($useridQA_USER_FLAGS_MUST_CONFIRMfalse);
        
qa_db_user_set($userid'emailcode'''); // to prevent re-use of the code

        
qa_report_event('u_confirmed'$userid$handleqa_cookie_get(), array(
            
'email' => $email,
        ));
    }

    
    function 
qa_start_reset_user($userid)
/*
    Start the 'I forgot my password' process for $userid, sending reset code
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-db-users.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-options.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-emails.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-selects.php';

        
qa_db_user_set($userid'emailcode'qa_db_user_rand_emailcode());

        
$userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($useridtrue));

        if (!
qa_send_notification($userid$userinfo['email'], $userinfo['handle'], qa_lang('emails/reset_subject'), qa_lang('emails/reset_body'), array(
            
'^code' => $userinfo['emailcode'],
            
'^url' => qa_path('reset', array('c' => $userinfo['emailcode'], 'e' => $userinfo['email']), qa_opt('site_url')),
        )))
            
qa_fatal_error('Could not send reset password email');
    }

    
    function 
qa_complete_reset_user($userid)
/*
    Successfully finish the 'I forgot my password' process for $userid, sending new password
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-util-string.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-options.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-emails.php';
        require_once 
QA_INCLUDE_DIR.'qa-app-cookies.php';
        require_once 
QA_INCLUDE_DIR.'qa-db-selects.php';
    
        
$password=qa_random_alphanum(max(QA_MIN_PASSWORD_LENQA_NEW_PASSWORD_LEN));
        
        
$userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($useridtrue));
        
        if (!
qa_send_notification($userid$userinfo['email'], $userinfo['handle'], qa_lang('emails/new_password_subject'), qa_lang('emails/new_password_body'), array(
            
'^password' => $password,
            
'^url' => qa_opt('site_url'),
        )))
            
qa_fatal_error('Could not send new password - password not reset');
        
        
qa_db_user_set_password($userid$password); // do this last, to be safe
        
qa_db_user_set($userid'emailcode'''); // so can't be reused

        
qa_report_event('u_reset'$userid$userinfo['handle'], qa_cookie_get(), array(
            
'email' => $userinfo['email'],
        ));
    }

    
    function 
qa_logged_in_user_flush()
/*
    Flush any information about the currently logged in user, so it is retrieved from database again
*/
    
{
        global 
$qa_cached_logged_in_user;
        
        
$qa_cached_logged_in_user=null;
    }
    
    
    function 
qa_set_user_avatar($userid$imagedata$oldblobid=null)
/*
    Set the avatar of $userid to the image in $imagedata, and remove $oldblobid from the database if not null
*/
    
{
        if (
qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__$args); }
        
        require_once 
QA_INCLUDE_DIR.'qa-util-image.php';
        
        
$imagedata=qa_image_constrain_data($imagedata$width$heightqa_opt('avatar_store_size'));
        
        if (isset(
$imagedata)) {
            require_once 
QA_INCLUDE_DIR.'qa-db-blobs.php';

            
$newblobid=qa_db_blob_create($imagedata'jpeg'null$useridnullqa_remote_ip_address());
            
            if (isset(
$newblobid)) {
                
qa_db_user_set($userid'avatarblobid'$newblobid);
                
qa_db_user_set($userid'avatarwidth'$width);
                
qa_db_user_set($userid'avatarheight'$height);
                
qa_db_user_set_flag($useridQA_USER_FLAGS_SHOW_AVATARtrue);
                
qa_db_user_set_flag($useridQA_USER_FLAGS_SHOW_GRAVATARfalse);

                if (isset(
$oldblobid))
                    
qa_db_blob_delete($oldblobid);

                return 
true;
            }
        }
        
        return 
false;
    }


/*
    Omit PHP closing tag to help avoid accidental output
*/
Онлайн: 0
Реклама