Guest User

Untitled

a guest
Jan 18th, 2015
519
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 47.15 KB | None | 0 0
  1. <?php
  2. /**
  3.  * MyBB 1.8
  4.  * Copyright 2014 MyBB Group, All Rights Reserved
  5.  *
  6.  * Website: http://www.mybb.com
  7.  * License: http://www.mybb.com/about/license
  8.  *
  9.  */
  10.  
  11. // Disallow direct access to this file for security reasons
  12. if(!defined("IN_MYBB"))
  13. {
  14.     die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined.");
  15. }
  16.  
  17. /**
  18.  * User handling class, provides common structure to handle user data.
  19.  *
  20.  */
  21. class UserDataHandler extends DataHandler
  22. {
  23.     /**
  24.     * The language file used in the data handler.
  25.     *
  26.     * @var string
  27.     */
  28.     public $language_file = 'datahandler_user';
  29.  
  30.     /**
  31.     * The prefix for the language variables used in the data handler.
  32.     *
  33.     * @var string
  34.     */
  35.     public $language_prefix = 'userdata';
  36.  
  37.     /**
  38.      * Array of data inserted in to a user.
  39.      *
  40.      * @var array
  41.      */
  42.     public $user_insert_data = array();
  43.  
  44.     /**
  45.      * Array of data used to update a user.
  46.      *
  47.      * @var array
  48.      */
  49.     public $user_update_data = array();
  50.  
  51.     /**
  52.      * User ID currently being manipulated by the datahandlers.
  53.      *
  54.      * @var int
  55.      */
  56.     public $uid = 0;
  57.  
  58.     /**
  59.      * Values to be returned after inserting/deleting an user.
  60.      *
  61.      * @var array
  62.      */
  63.     public $return_values = array();
  64.  
  65.     /**
  66.      * Verifies if a username is valid or invalid.
  67.      *
  68.      * @param boolean True when valid, false when invalid.
  69.      */
  70.     function verify_username()
  71.     {
  72.         global $mybb;
  73.  
  74.         $username = &$this->data['username'];
  75.         require_once MYBB_ROOT.'inc/functions_user.php';
  76.  
  77.         // Fix bad characters
  78.         $username = trim_blank_chrs($username);
  79.         $username = str_replace(array(unichr(160), unichr(173), unichr(0xCA), dec_to_utf8(8238), dec_to_utf8(8237), dec_to_utf8(8203)), array(" ", "-", "", "", "", ""), $username);
  80.  
  81.         // Remove multiple spaces from the username
  82.         $username = preg_replace("#\s{2,}#", " ", $username);
  83.  
  84.         // Check if the username is not empty.
  85.         if($username == '')
  86.         {
  87.             $this->set_error('missing_username');
  88.             return false;
  89.         }
  90.  
  91.         // Check if the username belongs to the list of banned usernames.
  92.         if(is_banned_username($username, true))
  93.         {
  94.             $this->set_error('banned_username');
  95.             return false;
  96.         }
  97.  
  98.         // Check for certain characters in username (<, >, &, commas and slashes)
  99.         if(strpos($username, "<") !== false || strpos($username, ">") !== false || strpos($username, "&") !== false || my_strpos($username, "\\") !== false || strpos($username, ";") !== false || strpos($username, ",") !== false || !validate_utf8_string($username, false, false))
  100.         {
  101.             $this->set_error("bad_characters_username");
  102.             return false;
  103.         }
  104.  
  105.         // Check if the username is of the correct length.
  106.         if(($mybb->settings['maxnamelength'] != 0 && my_strlen($username) > $mybb->settings['maxnamelength']) || ($mybb->settings['minnamelength'] != 0 && my_strlen($username) < $mybb->settings['minnamelength']))
  107.         {
  108.             $this->set_error('invalid_username_length', array($mybb->settings['minnamelength'], $mybb->settings['maxnamelength']));
  109.             return false;
  110.         }
  111.  
  112.         return true;
  113.     }
  114.  
  115.     /**
  116.      * Verifies if a usertitle is valid or invalid.
  117.      *
  118.      * @param boolean True when valid, false when invalid.
  119.      */
  120.     function verify_usertitle()
  121.     {
  122.         global $mybb;
  123.  
  124.         $usertitle = &$this->data['usertitle'];
  125.  
  126.         // Check if the usertitle is of the correct length.
  127.         if($mybb->settings['customtitlemaxlength'] != 0 && my_strlen($usertitle) > $mybb->settings['customtitlemaxlength'])
  128.         {
  129.             $this->set_error('invalid_usertitle_length', $mybb->settings['customtitlemaxlength']);
  130.             return false;
  131.         }
  132.  
  133.         return true;
  134.     }
  135.  
  136.     /**
  137.      * Verifies if a username is already in use or not.
  138.      *
  139.      * @return boolean False when the username is not in use, true when it is.
  140.      */
  141.     function verify_username_exists()
  142.     {
  143.         $username = &$this->data['username'];
  144.  
  145.         $user = get_user_by_username(trim($username));
  146.  
  147.         if(!empty($this->data['uid']) && !empty($user['uid']) && $user['uid'] == $this->data['uid'])
  148.         {
  149.             unset($user);
  150.         }
  151.  
  152.         if(!empty($user['uid']))
  153.         {
  154.             $this->set_error("username_exists", array($username));
  155.             return true;
  156.         }
  157.  
  158.         return false;
  159.     }
  160.  
  161.     /**
  162.     * Verifies if a new password is valid or not.
  163.     *
  164.     * @return boolean True when valid, false when invalid.
  165.     */
  166.     function verify_password()
  167.     {
  168.         global $mybb;
  169.  
  170.         $user = &$this->data;
  171.  
  172.         // Always check for the length of the password.
  173.         if(my_strlen($user['password']) < $mybb->settings['minpasswordlength'] || my_strlen($user['password']) > $mybb->settings['maxpasswordlength'])
  174.         {
  175.             $this->set_error('invalid_password_length', array($mybb->settings['minpasswordlength'], $mybb->settings['maxpasswordlength']));
  176.             return false;
  177.         }
  178.  
  179.         // Has the user tried to use their email address or username as a password?
  180.         if($user['email'] == $user['password'] || $user['username'] == $user['password'])
  181.         {
  182.             $this->set_error('bad_password_security');
  183.             return false;
  184.         }
  185.  
  186.         // See if the board has "require complex passwords" enabled.
  187.         if($mybb->settings['requirecomplexpasswords'] == 1)
  188.         {
  189.             // Complex passwords required, do some extra checks.
  190.             // First, see if there is one or more complex character(s) in the password.
  191.             if(!preg_match("/^.*(?=.{".$mybb->settings['minpasswordlength'].",})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/", $user['password']))
  192.             {
  193.                 $this->set_error('no_complex_characters', array($mybb->settings['minpasswordlength']));
  194.                 return false;
  195.             }
  196.         }
  197.  
  198.         // If we have a "password2" check if they both match
  199.         if(isset($user['password2']) && $user['password'] != $user['password2'])
  200.         {
  201.             $this->set_error("passwords_dont_match");
  202.             return false;
  203.         }
  204.  
  205.         // MD5 the password
  206.         $user['md5password'] = $user['password'];
  207.  
  208.         // Generate our salt
  209.         $user['salt'] = generate_salt();
  210.  
  211.         // Combine the password and salt
  212.         $user['saltedpw'] = salt_password($user['md5password'], $user['salt']);
  213.  
  214.         // Generate the user login key
  215.         $user['loginkey'] = generate_loginkey();
  216.  
  217.         return true;
  218.     }
  219.  
  220.     /**
  221.     * Verifies usergroup selections and other group details.
  222.     *
  223.     * @return boolean True when valid, false when invalid.
  224.     */
  225.     function verify_usergroup()
  226.     {
  227.         $user = &$this->data;
  228.         return true;
  229.     }
  230.     /**
  231.     * Verifies if an email address is valid or not.
  232.     *
  233.     * @return boolean True when valid, false when invalid.
  234.     */
  235.     function verify_email()
  236.     {
  237.         global $mybb;
  238.  
  239.         $user = &$this->data;
  240.  
  241.         // Check if an email address has actually been entered.
  242.         if(trim_blank_chrs($user['email']) == '')
  243.         {
  244.             $this->set_error('missing_email');
  245.             return false;
  246.         }
  247.  
  248.         // Check if this is a proper email address.
  249.         if(!validate_email_format($user['email']))
  250.         {
  251.             $this->set_error('invalid_email_format');
  252.             return false;
  253.         }
  254.  
  255.         // Check banned emails
  256.         if(is_banned_email($user['email'], true))
  257.         {
  258.             $this->set_error('banned_email');
  259.             return false;
  260.         }
  261.  
  262.         // Check signed up emails
  263.         // Ignore the ACP because the Merge System sometimes produces users with duplicate email addresses (Not A Bug)
  264.         if($mybb->settings['allowmultipleemails'] == 0 && !defined("IN_ADMINCP"))
  265.         {
  266.             $uid = 0;
  267.             if(isset($user['uid']))
  268.             {
  269.                 $uid = $user['uid'];
  270.             }
  271.             if(email_already_in_use($user['email'], $uid))
  272.             {
  273.                 $this->set_error('email_already_in_use');
  274.                 return false;
  275.             }
  276.         }
  277.  
  278.         // If we have an "email2", verify it matches the existing email
  279.         if(isset($user['email2']) && $user['email'] != $user['email2'])
  280.         {
  281.             $this->set_error("emails_dont_match");
  282.             return false;
  283.         }
  284.  
  285.         return true;
  286.     }
  287.  
  288.     /**
  289.     * Verifies if a website is valid or not.
  290.     *
  291.     * @return boolean True when valid, false when invalid.
  292.     */
  293.     function verify_website()
  294.     {
  295.         $website = &$this->data['website'];
  296.  
  297.         if(empty($website) || my_strtolower($website) == 'http://' || my_strtolower($website) == 'https://')
  298.         {
  299.             $website = '';
  300.             return true;
  301.         }
  302.  
  303.         // Does the website start with http(s)://?
  304.         if(my_strtolower(substr($website, 0, 4)) != "http")
  305.         {
  306.             // Website does not start with http://, let's see if the user forgot.
  307.             $website = "http://".$website;
  308.         }
  309.  
  310.         if(!filter_var($website, FILTER_VALIDATE_URL))
  311.         {
  312.             $this->set_error('invalid_website');
  313.             return false;
  314.         }
  315.  
  316.         return true;
  317.     }
  318.  
  319.     /**
  320.      * Verifies if an ICQ number is valid or not.
  321.      *
  322.      * @return boolean True when valid, false when invalid.
  323.      */
  324.     function verify_icq()
  325.     {
  326.         $icq = &$this->data['icq'];
  327.  
  328.         if($icq != '' && !is_numeric($icq))
  329.         {
  330.             $this->set_error("invalid_icq_number");
  331.             return false;
  332.         }
  333.         $icq = (int)$icq;
  334.         return true;
  335.     }
  336.  
  337.     /**
  338.     * Verifies if a birthday is valid or not.
  339.     *
  340.     * @return boolean True when valid, false when invalid.
  341.     */
  342.     function verify_birthday()
  343.     {
  344.         global $mybb;
  345.  
  346.         $user = &$this->data;
  347.         $birthday = &$user['birthday'];
  348.  
  349.         if(!is_array($birthday))
  350.         {
  351.             return true;
  352.         }
  353.  
  354.         // Sanitize any input we have
  355.         $birthday['day'] = (int)$birthday['day'];
  356.         $birthday['month'] = (int)$birthday['month'];
  357.         $birthday['year'] = (int)$birthday['year'];
  358.  
  359.         // Error if a day and month exists, and the birthday day and range is not in range
  360.         if($birthday['day'] != 0 || $birthday['month'] != 0)
  361.         {
  362.             if($birthday['day'] < 1 || $birthday['day'] > 31 || $birthday['month'] < 1 || $birthday['month'] > 12 || ($birthday['month'] == 2 && $birthday['day'] > 29))
  363.             {
  364.                 $this->set_error("invalid_birthday");
  365.                 return false;
  366.             }
  367.         }
  368.  
  369.         // Check if the day actually exists.
  370.         $months = get_bdays($birthday['year']);
  371.         if($birthday['month'] != 0 && $birthday['day'] > $months[$birthday['month']-1])
  372.         {
  373.             $this->set_error("invalid_birthday");
  374.             return false;
  375.         }
  376.  
  377.         // Error if a year exists and the year is out of range
  378.         if($birthday['year'] != 0 && ($birthday['year'] < (date("Y")-100)) || $birthday['year'] > date("Y"))
  379.         {
  380.             $this->set_error("invalid_birthday");
  381.             return false;
  382.         }
  383.         else if($birthday['year'] == date("Y"))
  384.         {
  385.             // Error if birth date is in future
  386.             if($birthday['month'] > date("m") || ($birthday['month'] == date("m") && $birthday['day'] > date("d")))
  387.             {
  388.                 $this->set_error("invalid_birthday");
  389.                 return false;
  390.             }
  391.         }
  392.  
  393.         // Error if COPPA is on, and the user hasn't verified their age / under 13
  394.         if($mybb->settings['coppa'] == "enabled" && ($birthday['year'] == 0 || !$birthday['year']))
  395.         {
  396.             $this->set_error("invalid_birthday_coppa");
  397.             return false;
  398.         }
  399.         elseif(($mybb->settings['coppa'] == "deny" && $birthday['year'] > (date("Y")-13)) && !is_moderator())
  400.         {
  401.             $this->set_error("invalid_birthday_coppa2");
  402.             return false;
  403.         }
  404.  
  405.         // Make the user's birthday field
  406.         if($birthday['year'] != 0)
  407.         {
  408.             // If the year is specified, put together a d-m-y string
  409.             $user['bday'] = $birthday['day']."-".$birthday['month']."-".$birthday['year'];
  410.         }
  411.         elseif($birthday['day'] && $birthday['month'])
  412.         {
  413.             // If only a day and month are specified, put together a d-m string
  414.             $user['bday'] = $birthday['day']."-".$birthday['month']."-";
  415.         }
  416.         else
  417.         {
  418.             // No field is specified, so return an empty string for an unknown birthday
  419.             $user['bday'] = '';
  420.         }
  421.         return true;
  422.     }
  423.  
  424.     /**
  425.      * Verifies if the birthday privacy option is valid or not.
  426.      *
  427.      * @return boolean True when valid, false when invalid.
  428.      */
  429.     function verify_birthday_privacy()
  430.     {
  431.         $birthdayprivacy = &$this->data['birthdayprivacy'];
  432.         $accepted = array(
  433.                     'none',
  434.                     'age',
  435.                     'all');
  436.  
  437.         if(!in_array($birthdayprivacy, $accepted))
  438.         {
  439.             $this->set_error("invalid_birthday_privacy");
  440.             return false;
  441.         }
  442.         return true;
  443.     }
  444.  
  445.     /**
  446.     * Verifies if the post count field is filled in correctly.
  447.     *
  448.     * @return boolean True when valid, false when invalid.
  449.     */
  450.     function verify_postnum()
  451.     {
  452.         $user = &$this->data;
  453.  
  454.         if(isset($user['postnum']) && $user['postnum'] < 0)
  455.         {
  456.             $this->set_error("invalid_postnum");
  457.             return false;
  458.         }
  459.  
  460.         return true;
  461.     }
  462.  
  463.     /**
  464.     * Verifies if the thread count field is filled in correctly.
  465.     *
  466.     * @return boolean True when valid, false when invalid.
  467.     */
  468.     function verify_threadnum()
  469.     {
  470.         $user = &$this->data;
  471.  
  472.         if(isset($user['threadnum']) && $user['threadnum'] < 0)
  473.         {
  474.             $this->set_error("invalid_threadnum");
  475.             return false;
  476.         }
  477.  
  478.         return true;
  479.     }
  480.  
  481.     /**
  482.     * Verifies if a profile fields are filled in correctly.
  483.     *
  484.     * @return boolean True when valid, false when invalid.
  485.     */
  486.     function verify_profile_fields()
  487.     {
  488.         global $db, $cache;
  489.  
  490.         $user = &$this->data;
  491.         $profile_fields = &$this->data['profile_fields'];
  492.  
  493.         // Loop through profile fields checking if they exist or not and are filled in.
  494.         $userfields = array();
  495.         $comma = '';
  496.  
  497.         // Fetch all profile fields first.
  498.         $pfcache = $cache->read('profilefields');
  499.  
  500.         if(is_array($pfcache))
  501.         {
  502.             // Then loop through the profile fields.
  503.             foreach($pfcache as $profilefield)
  504.             {
  505.                 if(isset($this->data['profile_fields_editable']) || isset($this->data['registration']) && ($profilefield['required'] == 1 || $profilefield['registration'] == 1))
  506.                 {
  507.                     $profilefield['editableby'] = -1;
  508.                 }
  509.  
  510.                 if(empty($profilefield['editableby']) || ($profilefield['editableby'] != -1 && !is_member($profilefield['editableby'], array('usergroup' => $user['usergroup'], 'additionalgroups' => $user['additionalgroups']))))
  511.                 {
  512.                     continue;
  513.                 }
  514.  
  515.                 // Does this field have a minimum post count?
  516.                 if(!isset($this->data['profile_fields_editable']) && !empty($profilefield['postnum']) && $profilefield['postnum'] > $user['postnum'])
  517.                 {
  518.                     continue;
  519.                 }
  520.  
  521.                 $profilefield['type'] = htmlspecialchars_uni($profilefield['type']);
  522.                 $thing = explode("\n", $profilefield['type'], "2");
  523.                 $type = trim($thing[0]);
  524.                 $field = "fid{$profilefield['fid']}";
  525.  
  526.                 if(!isset($profile_fields[$field]))
  527.                 {
  528.                     $profile_fields[$field] = '';
  529.                 }
  530.  
  531.                 // If the profile field is required, but not filled in, present error.
  532.                 if($type != "multiselect" && $type != "checkbox")
  533.                 {
  534.                     if(trim($profile_fields[$field]) == "" && $profilefield['required'] == 1 && !defined('IN_ADMINCP') && THIS_SCRIPT != "modcp.php")
  535.                     {
  536.                         $this->set_error('missing_required_profile_field', array($profilefield['name']));
  537.                     }
  538.                 }
  539.                 elseif(($type == "multiselect" || $type == "checkbox") && $profile_fields[$field] == "" && $profilefield['required'] == 1 && !defined('IN_ADMINCP') && THIS_SCRIPT != "modcp.php")
  540.                 {
  541.                     $this->set_error('missing_required_profile_field', array($profilefield['name']));
  542.                 }
  543.  
  544.                 // Sort out multiselect/checkbox profile fields.
  545.                 $options = '';
  546.                 if(($type == "multiselect" || $type == "checkbox") && is_array($profile_fields[$field]))
  547.                 {
  548.                     $expoptions = explode("\n", $thing[1]);
  549.                     $expoptions = array_map('trim', $expoptions);
  550.                     foreach($profile_fields[$field] as $value)
  551.                     {
  552.                         if(!in_array(htmlspecialchars_uni($value), $expoptions))
  553.                         {
  554.                             $this->set_error('bad_profile_field_values', array($profilefield['name']));
  555.                         }
  556.                         if($options)
  557.                         {
  558.                             $options .= "\n";
  559.                         }
  560.                         $options .= $db->escape_string($value);
  561.                     }
  562.                 }
  563.                 elseif($type == "select" || $type == "radio")
  564.                 {
  565.                     $expoptions = explode("\n", $thing[1]);
  566.                     $expoptions = array_map('trim', $expoptions);
  567.                     if(!in_array(htmlspecialchars_uni($profile_fields[$field]), $expoptions) && trim($profile_fields[$field]) != "")
  568.                     {
  569.                         $this->set_error('bad_profile_field_values', array($profilefield['name']));
  570.                     }
  571.                     $options = $db->escape_string($profile_fields[$field]);
  572.                 }
  573.                 else
  574.                 {
  575.                     if($profilefield['maxlength'] > 0 && my_strlen($profile_fields[$field]) > $profilefield['maxlength'])
  576.                     {
  577.                         $this->set_error('max_limit_reached', array($profilefield['name'], $profilefield['maxlength']));
  578.                     }
  579.  
  580.                     if(!empty($profilefield['regex']) && !preg_match("#".$profilefield['regex']."#i", $profile_fields[$field]))
  581.                     {
  582.                         $this->set_error('bad_profile_field_value', array($profilefield['name']));
  583.                     }
  584.  
  585.                     $options = $db->escape_string($profile_fields[$field]);
  586.                 }
  587.                 $user['user_fields'][$field] = $options;
  588.             }
  589.         }
  590.  
  591.         return true;
  592.     }
  593.  
  594.     /**
  595.     * Verifies if an optionally entered referrer exists or not.
  596.     *
  597.     * @return boolean True when valid, false when invalid.
  598.     */
  599.     function verify_referrer()
  600.     {
  601.         global $db, $mybb;
  602.  
  603.         $user = &$this->data;
  604.  
  605.         // Does the referrer exist or not?
  606.         if($mybb->settings['usereferrals'] == 1 && $user['referrer'] != '')
  607.         {
  608.             $referrer = get_user_by_username($user['referrer']);
  609.  
  610.             if(empty($referrer['uid']))
  611.             {
  612.                 $this->set_error('invalid_referrer', array($user['referrer']));
  613.                 return false;
  614.             }
  615.  
  616.             $user['referrer_uid'] = $referrer['uid'];
  617.         }
  618.         else
  619.         {
  620.             $user['referrer_uid'] = 0;
  621.         }
  622.  
  623.         return true;
  624.     }
  625.  
  626.     /**
  627.     * Verifies user options.
  628.     *
  629.     * @return boolean True when valid, false when invalid.
  630.     */
  631.     function verify_options()
  632.     {
  633.         global $mybb;
  634.  
  635.         $options = &$this->data['options'];
  636.  
  637.         // Verify yes/no options.
  638.         $this->verify_yesno_option($options, 'allownotices', 1);
  639.         $this->verify_yesno_option($options, 'hideemail', 0);
  640.         $this->verify_yesno_option($options, 'receivepms', 1);
  641.         $this->verify_yesno_option($options, 'receivefrombuddy', 0);
  642.         $this->verify_yesno_option($options, 'pmnotice', 1);
  643.         $this->verify_yesno_option($options, 'pmnotify', 1);
  644.         $this->verify_yesno_option($options, 'invisible', 0);
  645.         $this->verify_yesno_option($options, 'showimages', 1);
  646.         $this->verify_yesno_option($options, 'showvideos', 1);
  647.         $this->verify_yesno_option($options, 'showsigs', 1);
  648.         $this->verify_yesno_option($options, 'showavatars', 1);
  649.         $this->verify_yesno_option($options, 'showquickreply', 1);
  650.         $this->verify_yesno_option($options, 'showredirect', 1);
  651.         $this->verify_yesno_option($options, 'showcodebuttons', 1);
  652.         $this->verify_yesno_option($options, 'sourceeditor', 1);
  653.  
  654.         if($mybb->settings['postlayout'] == 'classic')
  655.         {
  656.             $this->verify_yesno_option($options, 'classicpostbit', 1);
  657.         }
  658.         else
  659.         {
  660.             $this->verify_yesno_option($options, 'classicpostbit', 0);
  661.         }
  662.  
  663.         if(array_key_exists('subscriptionmethod', $options))
  664.         {
  665.             // Value out of range
  666.             $options['subscriptionmethod'] = (int)$options['subscriptionmethod'];
  667.             if($options['subscriptionmethod'] < 0 || $options['subscriptionmethod'] > 3)
  668.             {
  669.                 $options['subscriptionmethod'] = 0;
  670.             }
  671.         }
  672.  
  673.         if(array_key_exists('dstcorrection', $options))
  674.         {
  675.             // Value out of range
  676.             $options['dstcorrection'] = (int)$options['dstcorrection'];
  677.             if($options['dstcorrection'] < 0 || $options['dstcorrection'] > 2)
  678.             {
  679.                 $options['dstcorrection'] = 0;
  680.             }
  681.         }
  682.  
  683.         if($options['dstcorrection'] == 1)
  684.         {
  685.             $options['dst'] = 1;
  686.         }
  687.         else if($options['dstcorrection'] == 0)
  688.         {
  689.             $options['dst'] = 0;
  690.         }
  691.  
  692.         if($this->method == "insert" || (isset($options['threadmode']) && $options['threadmode'] != "linear" && $options['threadmode'] != "threaded"))
  693.         {
  694.             if($mybb->settings['threadusenetstyle'])
  695.             {
  696.                 $options['threadmode'] = 'threaded';
  697.             }
  698.             else
  699.             {
  700.                 $options['threadmode'] = 'linear';
  701.             }
  702.         }
  703.  
  704.         // Verify the "threads per page" option.
  705.         if($this->method == "insert" || (array_key_exists('tpp', $options) && $mybb->settings['usertppoptions']))
  706.         {
  707.             if(!isset($options['tpp']))
  708.             {
  709.                 $options['tpp'] = 0;
  710.             }
  711.             $explodedtpp = explode(",", $mybb->settings['usertppoptions']);
  712.             if(is_array($explodedtpp))
  713.             {
  714.                 @asort($explodedtpp);
  715.                 $biggest = $explodedtpp[count($explodedtpp)-1];
  716.                 // Is the selected option greater than the allowed options?
  717.                 if($options['tpp'] > $biggest)
  718.                 {
  719.                     $options['tpp'] = $biggest;
  720.                 }
  721.             }
  722.             $options['tpp'] = (int)$options['tpp'];
  723.         }
  724.         // Verify the "posts per page" option.
  725.         if($this->method == "insert" || (array_key_exists('ppp', $options) && $mybb->settings['userpppoptions']))
  726.         {
  727.             if(!isset($options['ppp']))
  728.             {
  729.                 $options['ppp'] = 0;
  730.             }
  731.             $explodedppp = explode(",", $mybb->settings['userpppoptions']);
  732.             if(is_array($explodedppp))
  733.             {
  734.                 @asort($explodedppp);
  735.                 $biggest = $explodedppp[count($explodedppp)-1];
  736.                 // Is the selected option greater than the allowed options?
  737.                 if($options['ppp'] > $biggest)
  738.                 {
  739.                     $options['ppp'] = $biggest;
  740.                 }
  741.             }
  742.             $options['ppp'] = (int)$options['ppp'];
  743.         }
  744.         // Is our selected "days prune" option valid or not?
  745.         if($this->method == "insert" || array_key_exists('daysprune', $options))
  746.         {
  747.             if(!isset($options['daysprune']))
  748.             {
  749.                 $options['daysprune'] = 0;
  750.             }
  751.             $options['daysprune'] = (int)$options['daysprune'];
  752.             if($options['daysprune'] < 0)
  753.             {
  754.                 $options['daysprune'] = 0;
  755.             }
  756.         }
  757.         $this->data['options'] = $options;
  758.     }
  759.  
  760.     /**
  761.      * Verifies if a registration date is valid or not.
  762.      *
  763.      * @return boolean True when valid, false when invalid.
  764.      */
  765.     function verify_regdate()
  766.     {
  767.         $regdate = &$this->data['regdate'];
  768.  
  769.         $regdate = (int)$regdate;
  770.         // If the timestamp is below 0, set it to the current time.
  771.         if($regdate <= 0)
  772.         {
  773.             $regdate = TIME_NOW;
  774.         }
  775.         return true;
  776.     }
  777.  
  778.     /**
  779.      * Verifies if a last visit date is valid or not.
  780.      *
  781.      * @return boolean True when valid, false when invalid.
  782.      */
  783.     function verify_lastvisit()
  784.     {
  785.         $lastvisit = &$this->data['lastvisit'];
  786.  
  787.         $lastvisit = (int)$lastvisit;
  788.         // If the timestamp is below 0, set it to the current time.
  789.         if($lastvisit <= 0)
  790.         {
  791.             $lastvisit = TIME_NOW;
  792.         }
  793.         return true;
  794.  
  795.     }
  796.  
  797.     /**
  798.      * Verifies if a last active date is valid or not.
  799.      *
  800.      * @return boolean True when valid, false when invalid.
  801.      */
  802.     function verify_lastactive()
  803.     {
  804.         $lastactive = &$this->data['lastactive'];
  805.  
  806.         $lastactive = (int)$lastactive;
  807.         // If the timestamp is below 0, set it to the current time.
  808.         if($lastactive <= 0)
  809.         {
  810.             $lastactive = TIME_NOW;
  811.         }
  812.         return true;
  813.  
  814.     }
  815.  
  816.     /**
  817.      * Verifies if an away mode status is valid or not.
  818.      *
  819.      * @return boolean True when valid, false when invalid.
  820.      */
  821.     function verify_away()
  822.     {
  823.         global $mybb;
  824.  
  825.         $user = &$this->data;
  826.         // If the board does not allow "away mode" or the user is marking as not away, set defaults.
  827.         if($mybb->settings['allowaway'] == 0 || !isset($user['away']['away']) || $user['away']['away'] != 1)
  828.         {
  829.             $user['away']['away'] = 0;
  830.             $user['away']['date'] = 0;
  831.             $user['away']['returndate'] = 0;
  832.             $user['away']['awayreason'] = '';
  833.             return true;
  834.         }
  835.         else if($user['away']['returndate'])
  836.         {
  837.             list($returnday, $returnmonth, $returnyear) = explode('-', $user['away']['returndate']);
  838.             if(!$returnday || !$returnmonth || !$returnyear)
  839.             {
  840.                 $this->set_error("missing_returndate");
  841.                 return false;
  842.             }
  843.  
  844.             // Validate the return date lengths
  845.             $user['away']['returndate'] = substr($returnday, 0, 2).'-'.substr($returnmonth, 0, 2).'-'.substr($returnyear, 0, 4);
  846.         }
  847.         return true;
  848.     }
  849.  
  850.     /**
  851.      * Verifies if a langage is valid for this user or not.
  852.      *
  853.      * @return boolean True when valid, false when invalid.
  854.      */
  855.     function verify_language()
  856.     {
  857.         global $lang;
  858.  
  859.         $language = &$this->data['language'];
  860.  
  861.         // An invalid language has been specified?
  862.         if($language != '' && !$lang->language_exists($language))
  863.         {
  864.             $this->set_error("invalid_language");
  865.             return false;
  866.         }
  867.         return true;
  868.     }
  869.  
  870.     /**
  871.      * Verifies if this is coming from a spam bot or not
  872.      *
  873.      * @return boolean True when valid, false when invalid.
  874.      */
  875.     function verify_checkfields()
  876.     {
  877.         $user = &$this->data;
  878.  
  879.         // An invalid language has been specified?
  880.         if($user['regcheck1'] !== "" || $user['regcheck2'] !== "true")
  881.         {
  882.             $this->set_error("invalid_checkfield");
  883.             return false;
  884.         }
  885.         return true;
  886.     }
  887.  
  888.     /**
  889.     * Validate all user assets.
  890.     *
  891.     * @return boolean True when valid, false when invalid.
  892.     */
  893.     function validate_user()
  894.     {
  895.         global $mybb, $plugins;
  896.  
  897.         $user = &$this->data;
  898.  
  899.         // First, grab the old user details if this user exists
  900.         if(!empty($user['uid']))
  901.         {
  902.             $old_user = get_user($user['uid']);
  903.         }
  904.  
  905.         if($this->method == "insert" || array_key_exists('username', $user))
  906.         {
  907.             // If the username is the same - no need to verify
  908.             if(!isset($old_user['username']) || $user['username'] != $old_user['username'])
  909.             {
  910.                 $this->verify_username();
  911.                 $this->verify_username_exists();
  912.             }
  913.             else
  914.             {
  915.                 unset($user['username']);
  916.             }
  917.         }
  918.         if($this->method == "insert" || array_key_exists('usertitle', $user))
  919.         {
  920.             $this->verify_usertitle();
  921.         }
  922.         if($this->method == "insert" || array_key_exists('password', $user))
  923.         {
  924.             $this->verify_password();
  925.         }
  926.         if($this->method == "insert" || array_key_exists('usergroup', $user))
  927.         {
  928.             $this->verify_usergroup();
  929.         }
  930.         if($this->method == "insert" || array_key_exists('email', $user))
  931.         {
  932.             $this->verify_email();
  933.         }
  934.         if($this->method == "insert" || array_key_exists('website', $user))
  935.         {
  936.             $this->verify_website();
  937.         }
  938.         if($this->method == "insert" || array_key_exists('icq', $user))
  939.         {
  940.             $this->verify_icq();
  941.         }
  942.         if($this->method == "insert" || (isset($user['birthday']) && is_array($user['birthday'])))
  943.         {
  944.             $this->verify_birthday();
  945.         }
  946.         if($this->method == "insert" || array_key_exists('postnum', $user))
  947.         {
  948.             $this->verify_postnum();
  949.         }
  950.         if($this->method == "insert" || array_key_exists('threadnum', $user))
  951.         {
  952.             $this->verify_threadnum();
  953.         }
  954.         if($this->method == "insert" || array_key_exists('profile_fields', $user))
  955.         {
  956.             $this->verify_profile_fields();
  957.         }
  958.         if($this->method == "insert" || array_key_exists('referrer', $user))
  959.         {
  960.             $this->verify_referrer();
  961.         }
  962.         if($this->method == "insert" || array_key_exists('options', $user))
  963.         {
  964.             $this->verify_options();
  965.         }
  966.         if($this->method == "insert" || array_key_exists('regdate', $user))
  967.         {
  968.             $this->verify_regdate();
  969.         }
  970.         if($this->method == "insert" || array_key_exists('lastvisit', $user))
  971.         {
  972.             $this->verify_lastvisit();
  973.         }
  974.         if($this->method == "insert" || array_key_exists('lastactive', $user))
  975.         {
  976.             $this->verify_lastactive();
  977.         }
  978.         if($this->method == "insert" || array_key_exists('away', $user))
  979.         {
  980.             $this->verify_away();
  981.         }
  982.         if($this->method == "insert" || array_key_exists('language', $user))
  983.         {
  984.             $this->verify_language();
  985.         }
  986.         if($this->method == "insert" && array_key_exists('regcheck1', $user) && array_key_exists('regcheck2', $user))
  987.         {
  988.             $this->verify_checkfields();
  989.         }
  990.         if(array_key_exists('birthdayprivacy', $user))
  991.         {
  992.             $this->verify_birthday_privacy();
  993.         }
  994.  
  995.         $plugins->run_hooks("datahandler_user_validate", $this);
  996.  
  997.         // We are done validating, return.
  998.         $this->set_validated(true);
  999.         if(count($this->get_errors()) > 0)
  1000.         {
  1001.             return false;
  1002.         }
  1003.         else
  1004.         {
  1005.             return true;
  1006.         }
  1007.     }
  1008.  
  1009.     /**
  1010.     * Inserts a user into the database.
  1011.     */
  1012.     function insert_user()
  1013.     {
  1014.         global $db, $cache, $plugins;
  1015.  
  1016.         // Yes, validating is required.
  1017.         if(!$this->get_validated())
  1018.         {
  1019.             die("The user needs to be validated before inserting it into the DB.");
  1020.         }
  1021.         if(count($this->get_errors()) > 0)
  1022.         {
  1023.             die("The user is not valid.");
  1024.         }
  1025.  
  1026.         $user = &$this->data;
  1027.  
  1028.         $array = array('postnum', 'threadnum', 'avatar', 'avatartype', 'additionalgroups', 'displaygroup', 'icq', 'aim', 'yahoo', 'skype', 'google', 'bday', 'signature', 'style', 'dateformat', 'timeformat', 'notepad');
  1029.         foreach($array as $value)
  1030.         {
  1031.             if(!isset($user[$value]))
  1032.             {
  1033.                 $user[$value] = '';
  1034.             }
  1035.         }
  1036.  
  1037.         $this->user_insert_data = array(
  1038.             "username" => $db->escape_string($user['username']),
  1039.             "password" => $user['saltedpw'],
  1040.             "salt" => $user['salt'],
  1041.             "loginkey" => $user['loginkey'],
  1042.             "email" => $db->escape_string($user['email']),
  1043.             "postnum" => (int)$user['postnum'],
  1044.             "threadnum" => (int)$user['threadnum'],
  1045.             "avatar" => $db->escape_string($user['avatar']),
  1046.             "avatartype" => $db->escape_string($user['avatartype']),
  1047.             "usergroup" => (int)$user['usergroup'],
  1048.             "additionalgroups" => $db->escape_string($user['additionalgroups']),
  1049.             "displaygroup" => (int)$user['displaygroup'],
  1050.             "usertitle" => $db->escape_string(htmlspecialchars_uni($user['usertitle'])),
  1051.             "regdate" => (int)$user['regdate'],
  1052.             "lastactive" => (int)$user['lastactive'],
  1053.             "lastvisit" => (int)$user['lastvisit'],
  1054.             "website" => $db->escape_string($user['website']),
  1055.             "icq" => (int)$user['icq'],
  1056.             "aim" => $db->escape_string($user['aim']),
  1057.             "yahoo" => $db->escape_string($user['yahoo']),
  1058.             "skype" => $db->escape_string($user['skype']),
  1059.             "google" => $db->escape_string($user['google']),
  1060.             "birthday" => $user['bday'],
  1061.             "signature" => $db->escape_string($user['signature']),
  1062.             "allownotices" => $user['options']['allownotices'],
  1063.             "hideemail" => $user['options']['hideemail'],
  1064.             "subscriptionmethod" => (int)$user['options']['subscriptionmethod'],
  1065.             "receivepms" => $user['options']['receivepms'],
  1066.             "receivefrombuddy" => $user['options']['receivefrombuddy'],
  1067.             "pmnotice" => $user['options']['pmnotice'],
  1068.             "pmnotify" => $user['options']['pmnotify'],
  1069.             "showimages" => $user['options']['showimages'],
  1070.             "showvideos" => $user['options']['showvideos'],
  1071.             "showsigs" => $user['options']['showsigs'],
  1072.             "showavatars" => $user['options']['showavatars'],
  1073.             "showquickreply" => $user['options']['showquickreply'],
  1074.             "showredirect" => $user['options']['showredirect'],
  1075.             "tpp" => (int)$user['options']['tpp'],
  1076.             "ppp" => (int)$user['options']['ppp'],
  1077.             "invisible" => $user['options']['invisible'],
  1078.             "style" => (int)$user['style'],
  1079.             "timezone" => $db->escape_string($user['timezone']),
  1080.             "dstcorrection" => (int)$user['options']['dstcorrection'],
  1081.             "threadmode" => $user['options']['threadmode'],
  1082.             "daysprune" => (int)$user['options']['daysprune'],
  1083.             "dateformat" => $db->escape_string($user['dateformat']),
  1084.             "timeformat" => $db->escape_string($user['timeformat']),
  1085.             "regip" => $db->escape_binary($user['regip']),
  1086.             "language" => $db->escape_string($user['language']),
  1087.             "showcodebuttons" => $user['options']['showcodebuttons'],
  1088.             "sourceeditor" => $user['options']['sourceeditor'],
  1089.             "away" => $user['away']['away'],
  1090.             "awaydate" => $user['away']['date'],
  1091.             "returndate" => $user['away']['returndate'],
  1092.             "awayreason" => $db->escape_string($user['away']['awayreason']),
  1093.             "notepad" => $db->escape_string($user['notepad']),
  1094.             "referrer" => (int)$user['referrer_uid'],
  1095.             "referrals" => 0,
  1096.             "buddylist" => '',
  1097.             "ignorelist" => '',
  1098.             "pmfolders" => '',
  1099.             "notepad" => '',
  1100.             "warningpoints" => 0,
  1101.             "moderateposts" => 0,
  1102.             "moderationtime" => 0,
  1103.             "suspendposting" => 0,
  1104.             "suspensiontime" => 0,
  1105.             "coppauser" => (int)$user['coppa_user'],
  1106.             "classicpostbit" => $user['options']['classicpostbit'],
  1107.             "usernotes" => ''
  1108.         );
  1109.  
  1110.         if($user['options']['dstcorrection'] == 1)
  1111.         {
  1112.             $this->user_insert_data['dst'] = 1;
  1113.         }
  1114.         else if($user['options']['dstcorrection'] == 0)
  1115.         {
  1116.             $this->user_insert_data['dst'] = 0;
  1117.         }
  1118.  
  1119.         $plugins->run_hooks("datahandler_user_insert", $this);
  1120.  
  1121.         $this->uid = $db->insert_query("users", $this->user_insert_data);
  1122.  
  1123.         $user['user_fields']['ufid'] = $this->uid;
  1124.  
  1125.         $pfcache = $cache->read('profilefields');
  1126.  
  1127.         if(is_array($pfcache))
  1128.         {
  1129.             foreach($pfcache as $profile_field)
  1130.             {
  1131.                 if(array_key_exists("fid{$profile_field['fid']}", $user['user_fields']))
  1132.                 {
  1133.                     continue;
  1134.                 }
  1135.                 $user['user_fields']["fid{$profile_field['fid']}"] = '';
  1136.             }
  1137.         }
  1138.  
  1139.         $db->insert_query("userfields", $user['user_fields'], false);
  1140.  
  1141.         if($this->user_insert_data['referrer'] != 0)
  1142.         {
  1143.             $db->write_query("
  1144.                 UPDATE ".TABLE_PREFIX."users
  1145.                 SET referrals=referrals+1
  1146.                 WHERE uid='{$this->user_insert_data['referrer']}'
  1147.             ");
  1148.         }
  1149.  
  1150.         // Update forum stats
  1151.         update_stats(array('numusers' => '+1'));
  1152.  
  1153.         if((int)$user['usergroup'] == 5)
  1154.         {
  1155.             $cache->update_awaitingactivation();
  1156.         }
  1157.  
  1158.         $this->return_values = array(
  1159.             "uid" => $this->uid,
  1160.             "username" => $user['username'],
  1161.             "loginkey" => $user['loginkey'],
  1162.             "email" => $user['email'],
  1163.             "password" => $user['password'],
  1164.             "usergroup" => $user['usergroup']
  1165.         );
  1166.  
  1167.         $plugins->run_hooks("datahandler_user_insert_end", $this);
  1168.  
  1169.         return $this->return_values;
  1170.     }
  1171.  
  1172.     /**
  1173.     * Updates a user in the database.
  1174.     */
  1175.     function update_user()
  1176.     {
  1177.         global $db, $plugins, $cache;
  1178.  
  1179.         // Yes, validating is required.
  1180.         if(!$this->get_validated())
  1181.         {
  1182.             die("The user needs to be validated before inserting it into the DB.");
  1183.         }
  1184.         if(count($this->get_errors()) > 0)
  1185.         {
  1186.             die("The user is not valid.");
  1187.         }
  1188.  
  1189.         $user = &$this->data;
  1190.         $user['uid'] = (int)$user['uid'];
  1191.         $this->uid = $user['uid'];
  1192.  
  1193.         // Set up the update data.
  1194.         if(isset($user['username']))
  1195.         {
  1196.             $this->user_update_data['username'] = $db->escape_string($user['username']);
  1197.         }
  1198.         if(isset($user['saltedpw']))
  1199.         {
  1200.             $this->user_update_data['password'] = $user['saltedpw'];
  1201.             $this->user_update_data['salt'] = $user['salt'];
  1202.             $this->user_update_data['loginkey'] = $user['loginkey'];
  1203.         }
  1204.         if(isset($user['email']))
  1205.         {
  1206.             $this->user_update_data['email'] = $user['email'];
  1207.         }
  1208.         if(isset($user['postnum']))
  1209.         {
  1210.             $this->user_update_data['postnum'] = (int)$user['postnum'];
  1211.         }
  1212.         if(isset($user['threadnum']))
  1213.         {
  1214.             $this->user_update_data['threadnum'] = (int)$user['threadnum'];
  1215.         }
  1216.         if(isset($user['avatar']))
  1217.         {
  1218.             $this->user_update_data['avatar'] = $db->escape_string($user['avatar']);
  1219.             $this->user_update_data['avatartype'] = $db->escape_string($user['avatartype']);
  1220.         }
  1221.         if(isset($user['usergroup']))
  1222.         {
  1223.             $this->user_update_data['usergroup'] = (int)$user['usergroup'];
  1224.         }
  1225.         if(isset($user['additionalgroups']))
  1226.         {
  1227.             $this->user_update_data['additionalgroups'] = $db->escape_string($user['additionalgroups']);
  1228.         }
  1229.         if(isset($user['displaygroup']))
  1230.         {
  1231.             $this->user_update_data['displaygroup'] = (int)$user['displaygroup'];
  1232.         }
  1233.         if(isset($user['usertitle']))
  1234.         {
  1235.             $this->user_update_data['usertitle'] = $db->escape_string($user['usertitle']);
  1236.         }
  1237.         if(isset($user['regdate']))
  1238.         {
  1239.             $this->user_update_data['regdate'] = (int)$user['regdate'];
  1240.         }
  1241.         if(isset($user['lastactive']))
  1242.         {
  1243.             $this->user_update_data['lastactive'] = (int)$user['lastactive'];
  1244.         }
  1245.         if(isset($user['lastvisit']))
  1246.         {
  1247.             $this->user_update_data['lastvisit'] = (int)$user['lastvisit'];
  1248.         }
  1249.         if(isset($user['signature']))
  1250.         {
  1251.             $this->user_update_data['signature'] = $db->escape_string($user['signature']);
  1252.         }
  1253.         if(isset($user['website']))
  1254.         {
  1255.             $this->user_update_data['website'] = $db->escape_string($user['website']);
  1256.         }
  1257.         if(isset($user['icq']))
  1258.         {
  1259.             $this->user_update_data['icq'] = (int)$user['icq'];
  1260.         }
  1261.         if(isset($user['aim']))
  1262.         {
  1263.             $this->user_update_data['aim'] = $db->escape_string($user['aim']);
  1264.         }
  1265.         if(isset($user['yahoo']))
  1266.         {
  1267.             $this->user_update_data['yahoo'] = $db->escape_string($user['yahoo']);
  1268.         }
  1269.         if(isset($user['skype']))
  1270.         {
  1271.             $this->user_update_data['skype'] = $db->escape_string($user['skype']);
  1272.         }
  1273.         if(isset($user['google']))
  1274.         {
  1275.             $this->user_update_data['google'] = $db->escape_string($user['google']);
  1276.         }
  1277.         if(isset($user['bday']))
  1278.         {
  1279.             $this->user_update_data['birthday'] = $user['bday'];
  1280.         }
  1281.         if(isset($user['birthdayprivacy']))
  1282.         {
  1283.             $this->user_update_data['birthdayprivacy'] = $db->escape_string($user['birthdayprivacy']);
  1284.         }
  1285.         if(isset($user['style']))
  1286.         {
  1287.             $this->user_update_data['style'] = (int)$user['style'];
  1288.         }
  1289.         if(isset($user['timezone']))
  1290.         {
  1291.             $this->user_update_data['timezone'] = $db->escape_string($user['timezone']);
  1292.         }
  1293.         if(isset($user['dateformat']))
  1294.         {
  1295.             $this->user_update_data['dateformat'] = $db->escape_string($user['dateformat']);
  1296.         }
  1297.         if(isset($user['timeformat']))
  1298.         {
  1299.             $this->user_update_data['timeformat'] = $db->escape_string($user['timeformat']);
  1300.         }
  1301.         if(isset($user['regip']))
  1302.         {
  1303.             $this->user_update_data['regip'] = $db->escape_string($user['regip']);
  1304.         }
  1305.         if(isset($user['language']))
  1306.         {
  1307.             $this->user_update_data['language'] = $db->escape_string($user['language']);
  1308.         }
  1309.         if(isset($user['away']))
  1310.         {
  1311.             $this->user_update_data['away'] = $user['away']['away'];
  1312.             $this->user_update_data['awaydate'] = $db->escape_string($user['away']['date']);
  1313.             $this->user_update_data['returndate'] = $db->escape_string($user['away']['returndate']);
  1314.             $this->user_update_data['awayreason'] = $db->escape_string($user['away']['awayreason']);
  1315.         }
  1316.         if(isset($user['notepad']))
  1317.         {
  1318.             $this->user_update_data['notepad'] = $db->escape_string($user['notepad']);
  1319.         }
  1320.         if(isset($user['usernotes']))
  1321.         {
  1322.             $this->user_update_data['usernotes'] = $db->escape_string($user['usernotes']);
  1323.         }
  1324.         if(isset($user['options']) && is_array($user['options']))
  1325.         {
  1326.             foreach($user['options'] as $option => $value)
  1327.             {
  1328.                 $this->user_update_data[$option] = $value;
  1329.             }
  1330.         }
  1331.         if(array_key_exists('coppa_user', $user))
  1332.         {
  1333.             $this->user_update_data['coppauser'] = (int)$user['coppa_user'];
  1334.         }
  1335.         // First, grab the old user details for later use.
  1336.         $old_user = get_user($user['uid']);
  1337.  
  1338.         // If old user has new pmnotice and new user has = yes, keep old value
  1339.         if($old_user['pmnotice'] == "2" && $this->user_update_data['pmnotice'] == 1)
  1340.         {
  1341.             unset($this->user_update_data['pmnotice']);
  1342.         }
  1343.  
  1344.         $plugins->run_hooks("datahandler_user_update", $this);
  1345.  
  1346.         if(count($this->user_update_data) < 1 && empty($user['user_fields']))
  1347.         {
  1348.             return false;
  1349.         }
  1350.  
  1351.         if(count($this->user_update_data) > 0)
  1352.         {
  1353.             // Actual updating happens here.
  1354.             $db->update_query("users", $this->user_update_data, "uid='{$user['uid']}'");
  1355.         }
  1356.  
  1357.         $cache->update_moderators();
  1358.         if(isset($user['bday']) || isset($user['username']))
  1359.         {
  1360.             $cache->update_birthdays();
  1361.         }
  1362.  
  1363.         if(isset($user['usergroup']) && (int)$user['usergroup'] == 5)
  1364.         {
  1365.             $cache->update_awaitingactivation();
  1366.         }
  1367.  
  1368.         // Maybe some userfields need to be updated?
  1369.         if(isset($user['user_fields']) && is_array($user['user_fields']))
  1370.         {
  1371.             $query = $db->simple_select("userfields", "*", "ufid='{$user['uid']}'");
  1372.             $fields = $db->fetch_array($query);
  1373.             if(!$fields['ufid'])
  1374.             {
  1375.                 $user_fields = array(
  1376.                     'ufid' => $user['uid']
  1377.                 );
  1378.  
  1379.                 $fields_array = $db->show_fields_from("userfields");
  1380.                 foreach($fields_array as $field)
  1381.                 {
  1382.                     if($field['Field'] == 'ufid')
  1383.                     {
  1384.                         continue;
  1385.                     }
  1386.                     $user_fields[$field['Field']] = '';
  1387.                 }
  1388.                 $db->insert_query("userfields", $user_fields);
  1389.             }
  1390.             $db->update_query("userfields", $user['user_fields'], "ufid='{$user['uid']}'", false);
  1391.         }
  1392.  
  1393.         // Let's make sure the user's name gets changed everywhere in the db if it changed.
  1394.         if(!empty($this->user_update_data['username']) && $this->user_update_data['username'] != $old_user['username'])
  1395.         {
  1396.             $username_update = array(
  1397.                 "username" => $this->user_update_data['username']
  1398.             );
  1399.             $lastposter_update = array(
  1400.                 "lastposter" => $this->user_update_data['username']
  1401.             );
  1402.  
  1403.             $db->update_query("posts", $username_update, "uid='{$user['uid']}'");
  1404.             $db->update_query("threads", $username_update, "uid='{$user['uid']}'");
  1405.             $db->update_query("threads", $lastposter_update, "lastposteruid='{$user['uid']}'");
  1406.             $db->update_query("forums", $lastposter_update, "lastposteruid='{$user['uid']}'");
  1407.  
  1408.             $stats = $cache->read("stats");
  1409.             if($stats['lastuid'] == $user['uid'])
  1410.             {
  1411.                 // User was latest to register, update stats
  1412.                 update_stats(array("numusers" => "+0"));
  1413.             }
  1414.         }
  1415.  
  1416.         return true;
  1417.     }
  1418.  
  1419.     /**
  1420.      * Provides a method to completely delete a user.
  1421.      *
  1422.      * @param array Array of user information
  1423.      * @param integer Whether if delete threads/posts or not
  1424.      * @return boolean True when successful, false if fails
  1425.      */
  1426.     function delete_user($delete_uids, $prunecontent=0)
  1427.     {
  1428.         global $db, $plugins, $mybb, $cache;
  1429.  
  1430.         // Yes, validating is required.
  1431.         if(count($this->get_errors()) > 0)
  1432.         {
  1433.             die('The user is not valid.');
  1434.         }
  1435.  
  1436.         $this->delete_uids = array_map('intval', (array)$delete_uids);
  1437.  
  1438.         foreach($this->delete_uids as $key => $uid)
  1439.         {
  1440.             if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid'])
  1441.             {
  1442.                 // Remove super admins
  1443.                 unset($this->delete_uids[$key]);
  1444.             }
  1445.         }
  1446.  
  1447.         $plugins->run_hooks('datahandler_user_delete_start', $this);
  1448.  
  1449.         $this->delete_uids = '\''.implode('\',\'', $this->delete_uids).'\'';
  1450.        
  1451.         $this->delete_content();
  1452.  
  1453.         // Delete the user
  1454.         $query = $db->delete_query('users', 'uid IN('.$this->delete_uids.')');
  1455.         $this->deleted_users = (int)$db->affected_rows($query);
  1456.  
  1457.         // Are we removing the posts/threads of a user?
  1458.         if((int)$prunecontent == 1)
  1459.         {
  1460.             $this->delete_posts();
  1461.         }
  1462.         else
  1463.         {
  1464.             // We're just updating the UID
  1465.             $db->update_query('posts', array('uid' => 0), 'uid IN('.$this->delete_uids.')');
  1466.             $db->update_query('threads', array('uid' => 0), 'uid IN('.$this->delete_uids.')');
  1467.         }
  1468.  
  1469.         // Update thread ratings
  1470.         $query = $db->query("
  1471.             SELECT r.*, t.numratings, t.totalratings
  1472.             FROM ".TABLE_PREFIX."threadratings r
  1473.             LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=r.tid)
  1474.             WHERE r.uid IN({$this->delete_uids})
  1475.         ");
  1476.         while($rating = $db->fetch_array($query))
  1477.         {
  1478.             $update_thread = array(
  1479.                 "numratings" => $rating['numratings'] - 1,
  1480.                 "totalratings" => $rating['totalratings'] - $rating['rating']
  1481.             );
  1482.             $db->update_query("threads", $update_thread, "tid='{$rating['tid']}'");
  1483.         }
  1484.  
  1485.         $db->delete_query('threadratings', 'uid IN('.$this->delete_uids.')');
  1486.  
  1487.         // Update forums & threads if user is the lastposter
  1488.         $db->update_query('forums', array('lastposteruid' => 0), 'lastposteruid IN('.$this->delete_uids.')');
  1489.         $db->update_query('threads', array('lastposteruid' => 0), 'lastposteruid IN('.$this->delete_uids.')');
  1490.  
  1491.         $cache->update_banned();
  1492.         $cache->update_moderators();
  1493.  
  1494.         // Update forum stats
  1495.         update_stats(array('numusers' => '-'.(int)$this->deleted_users));
  1496.  
  1497.         $this->return_values = array(
  1498.             "deleted_users" => $this->deleted_users
  1499.         );
  1500.        
  1501.         // Update reports cache
  1502.         $cache->update_reportedcontent();
  1503.  
  1504.         $cache->update_awaitingactivation();
  1505.  
  1506.         $plugins->run_hooks("datahandler_user_delete_end", $this);
  1507.  
  1508.         return $this->return_values;
  1509.     }
  1510.  
  1511.     /**
  1512.      * Provides a method to delete an users content
  1513.      *
  1514.      * @param array Array of user ids, false if they're already set (eg when using the delete_user function)
  1515.      */
  1516.     function delete_content($delete_uids=false)
  1517.     {
  1518.         global $db, $plugins;
  1519.  
  1520.         if($delete_uids != false)
  1521.         {
  1522.             $this->delete_uids = array_map('intval', (array)$delete_uids);
  1523.        
  1524.             foreach($this->delete_uids as $key => $uid)
  1525.             {
  1526.                 if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid'])
  1527.                 {
  1528.                     // Remove super admins
  1529.                     unset($this->delete_uids[$key]);
  1530.                 }
  1531.             }
  1532.        
  1533.             $this->delete_uids = '\''.implode('\',\'', $this->delete_uids).'\'';
  1534.         }
  1535.  
  1536.         $plugins->run_hooks('datahandler_user_delete_content', $this);
  1537.  
  1538.         $db->delete_query('userfields', 'ufid IN('.$this->delete_uids.')');
  1539.         $db->delete_query('privatemessages', 'uid IN('.$this->delete_uids.')');
  1540.         $db->delete_query('events', 'uid IN('.$this->delete_uids.')');
  1541.         $db->delete_query('moderators', 'id IN('.$this->delete_uids.') AND isgroup=\'0\'');
  1542.         $db->delete_query('forumsubscriptions', 'uid IN('.$this->delete_uids.')');
  1543.         $db->delete_query('threadsubscriptions', 'uid IN('.$this->delete_uids.')');
  1544.         $db->delete_query('sessions', 'uid IN('.$this->delete_uids.')');
  1545.         $db->delete_query('banned', 'uid IN('.$this->delete_uids.')');
  1546.         $db->delete_query('joinrequests', 'uid IN('.$this->delete_uids.')');
  1547.         $db->delete_query('awaitingactivation', 'uid IN('.$this->delete_uids.')');
  1548.         $db->delete_query('warnings', 'uid IN('.$this->delete_uids.')');
  1549.         $db->delete_query('reputation', 'uid IN('.$this->delete_uids.') OR adduid IN('.$this->delete_uids.')');
  1550.         $db->delete_query('posts', 'uid IN('.$this->delete_uids.') AND visible=\'-2\'');
  1551.         $db->delete_query('threads', 'uid IN('.$this->delete_uids.') AND visible=\'-2\'');
  1552.         $db->delete_query('moderators', 'id IN('.$this->delete_uids.') AND isgroup=\'0\'');
  1553.  
  1554.         // Delete reports made to the profile or reputation of the deleted users (i.e. made by them)
  1555.         $db->delete_query('reportedcontent', 'type=\'reputation\' AND id3 IN('.$this->delete_uids.') OR type=\'reputation\' AND id2 IN('.$this->delete_uids.')');
  1556.         $db->delete_query('reportedcontent', 'type=\'profile\' AND id IN('.$this->delete_uids.')');
  1557.  
  1558.         // Update the reports made by the deleted users by setting the uid to 0
  1559.         $db->update_query('reportedcontent', array('uid' => 0), 'uid IN('.$this->delete_uids.')');
  1560.  
  1561.         // Remove any of the user(s) uploaded avatars
  1562.         $query = $db->simple_select('users', 'avatar', 'uid IN ('.$this->delete_uids.') AND avatartype=\'upload\'');
  1563.         while($avatar = $db->fetch_field($query, 'avatar'))
  1564.         {
  1565.             $avatar = substr($avatar, 2, -20);
  1566.             @unlink(MYBB_ROOT.$avatar);
  1567.         }
  1568.  
  1569.     }
  1570.  
  1571.     /**
  1572.      * Provides a method to delete an users posts and threads
  1573.      *
  1574.      * @param array Array of user ids, false if they're already set (eg when using the delete_user function)
  1575.      */
  1576.     function delete_posts($delete_uids=false)
  1577.     {
  1578.         global $db, $plugins;
  1579.  
  1580.         if($delete_uids != false)
  1581.         {
  1582.             $this->delete_uids = array_map('intval', (array)$delete_uids);
  1583.  
  1584.             foreach($this->delete_uids as $key => $uid)
  1585.             {
  1586.                 if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid'])
  1587.                 {
  1588.                     // Remove super admins
  1589.                     unset($this->delete_uids[$key]);
  1590.                 }
  1591.             }
  1592.  
  1593.             $this->delete_uids = '\''.implode('\',\'', $this->delete_uids).'\'';
  1594.         }
  1595.  
  1596.         require_once MYBB_ROOT.'inc/class_moderation.php';
  1597.         $moderation = new Moderation();
  1598.  
  1599.         $plugins->run_hooks('datahandler_user_delete_posts', $this);
  1600.  
  1601.         // Threads
  1602.         $query = $db->simple_select('threads', 'tid', 'uid IN('.$this->delete_uids.')');
  1603.         while($tid = $db->fetch_field($query, 'tid'))
  1604.         {
  1605.             $moderation->delete_thread($tid);
  1606.         }
  1607.  
  1608.         // Posts
  1609.         $pids = array();
  1610.         $query = $db->simple_select('posts', 'pid', 'uid IN('.$this->delete_uids.')');
  1611.         while($pid = $db->fetch_field($query, 'pid'))
  1612.         {
  1613.             $moderation->delete_post($pid);
  1614.             $pids[] = (int)$pid;
  1615.         }
  1616.  
  1617.         // Delete Reports made to users's posts/threads
  1618.         if(!empty($pids))
  1619.         {
  1620.             $db->delete_query('reportedcontent', 'type=\'posts\' AND id IN('.implode(',', $pids).')');
  1621.         }
  1622.     }
  1623.  
  1624.     /**
  1625.      * Provides a method to clear an users profile (note that this doesn't delete the custom profilefields)
  1626.      *
  1627.      * @param array Array of user ids, false if they're already set (eg when using the delete_user function)
  1628.      * @param int The new usergroup if the users should be moved (additional usergroups are always removed)
  1629.      */
  1630.     function clear_profile($delete_uids=false, $gid=0)
  1631.     {
  1632.         global $db, $plugins;
  1633.  
  1634.         // delete_uids isn't a nice name, but it's used as the functions above use the same
  1635.         if($delete_uids != false)
  1636.         {
  1637.             $this->delete_uids = array_map('intval', (array)$delete_uids);
  1638.  
  1639.             foreach($this->delete_uids as $key => $uid)
  1640.             {
  1641.                 if(!$uid || is_super_admin($uid) || $uid == $mybb->user['uid'])
  1642.                 {
  1643.                     // Remove super admins
  1644.                     unset($this->delete_uids[$key]);
  1645.                 }
  1646.             }
  1647.  
  1648.             $this->delete_uids = '\''.implode('\',\'', $this->delete_uids).'\'';
  1649.         }
  1650.  
  1651.         $update = array(
  1652.             "website" => "",
  1653.             "birthday" => "",
  1654.             "icq" => "",
  1655.             "aim" => "",
  1656.             "yahoo" => "",
  1657.             "skype" => "",
  1658.             "google" => "",
  1659.             "usertitle" => "",
  1660.             "away" => 0,
  1661.             "awaydate" => 0,
  1662.             "returndate" => "",
  1663.             "awayreason" => "",
  1664.             "additionalgroups" => "",
  1665.             "displaygroup" => 0,
  1666.             "signature" => "",
  1667.             "avatar" => ""
  1668.         );
  1669.  
  1670.         if($gid > 0)
  1671.         {
  1672.             $update["usergroup"] = (int)$gid;
  1673.  
  1674.         }
  1675.  
  1676.         $plugins->run_hooks('datahandler_user_clear_profile', $this);
  1677.  
  1678.         $db->update_query("users", $update, 'uid IN('.$this->delete_uids.')');
  1679.     }
  1680. }
Advertisement
Add Comment
Please, Sign In to add comment