Advertisement
Guest User

Untitled

a guest
Feb 19th, 2012
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 100.70 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4.  * MyBBIntegrator - The integration class for MyBB and your website
  5.  *
  6.  * The MyBBIntegrator is a useful collection of variables and functions for easy MyBB integration
  7.  * into the own website
  8.  *
  9.  * @author: David Olah (aka PHPDave - http://phpdave.com)
  10.  * @version 1.3.1
  11.  * @date July 2010
  12.  * @copyright Copyright (c) 2009, David Olah
  13.  *
  14.  *
  15.  *
  16.  *  This program is free software: you can redistribute it and/or modify
  17.  *  it under the terms of the GNU General Public License as published by
  18.  *  the Free Software Foundation, either version 3 of the License, or
  19.  *  (at your option) any later version.
  20.  
  21.  *  This program is distributed in the hope that it will be useful,
  22.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  *  GNU General Public License for more details.
  25.  
  26.  *  You should have received a copy of the GNU General Public License
  27.  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  28.  
  29. */
  30.  
  31. class MyBBIntegrator
  32. {  
  33.     /**
  34.      * Cache Handler of MyBB
  35.      *
  36.      * @var object
  37.     */
  38.     var $cache;
  39.    
  40.     /**
  41.      * Config Data of MyBB
  42.      *
  43.      * @var array
  44.     */
  45.     var $config;
  46.    
  47.     /**
  48.      * Database Handler of MyBB
  49.      *
  50.      * @var object
  51.     */
  52.     var $db;
  53.    
  54.     /**
  55.      * MyBB Super Variable containing a whole lot of information
  56.      *
  57.      * @var object
  58.     */
  59.     var $mybb;
  60.    
  61.     /**
  62.      * MyBB's Post Parser
  63.      *
  64.      * @var object
  65.     */
  66.     var $parser;
  67.    
  68.     /**
  69.      * Shows a message for errors occuring in this class.
  70.      * Afterwards it stops the script
  71.      *
  72.      * @param string $message The error message
  73.     */
  74.     function _errorAndDie($message)
  75.     {
  76.         echo '<div style="width:92%; margin:4px auto; border:1px #DDD solid; background:#F1F1F1; padding:5px; color:#C00; font-weight:bold;">An error occured during script run.<br />'.$message.'</div>';
  77.         die;
  78.     }
  79.    
  80.     /**
  81.      * Let's see if the correct password is given for a forum!
  82.      * Possible Todo: Pass passowrds in an array for defining passwords for parent categories (so far this only works when parent foums have same pass)
  83.      *
  84.      * @param integer $forum_id ID of Forum
  85.      * @param string $password Wow, what might this be??
  86.      * @return boolean
  87.     */
  88.     function checkForumPassword($forum_id, $password = '', $pid = 0)
  89.     {
  90.         global $forum_cache;
  91.        
  92.         if(!is_array($forum_cache))
  93.         {
  94.             $forum_cache = cache_forums();
  95.             if(!$forum_cache)
  96.             {
  97.                 return false;
  98.             }
  99.         }
  100.        
  101.         // Loop through each of parent forums to ensure we have a password for them too
  102.         $parents = explode(',', $forum_cache[$fid]['parentlist']);
  103.         rsort($parents);
  104.         if(!empty($parents))
  105.         {
  106.             foreach($parents as $parent_id)
  107.             {
  108.                 if($parent_id == $forum_id || $parent_id == $pid)
  109.                 {
  110.                     continue;
  111.                 }
  112.                
  113.                 if($forum_cache[$parent_id]['password'] != "")
  114.                 {
  115.                     if (!$this->checkForumPassword($parent_id, $password))
  116.                     {
  117.                         return false;
  118.                     }
  119.                 }
  120.                
  121.             }
  122.         }
  123.        
  124.         $forum_password = $forum_cache[$forum_id]['password'];
  125.        
  126.         // A password is required
  127.         if ($forum_password)
  128.         {
  129.             if (empty($password))
  130.             {
  131.                 if (!$this->mybb->cookies['forumpass'][$forum_id] || ($this->mybb->cookies['forumpass'][$forum_id] && md5($this->mybb->user['uid'].$forum_password) != $this->mybb->cookies['forumpass'][$forum_id]))
  132.                 {
  133.                     return false;
  134.                 }
  135.                 else
  136.                 {
  137.                     return true;
  138.                 }
  139.             }
  140.             else
  141.             {          
  142.                 if ($forum_password == $password)
  143.                 {
  144.                     $this->setCookie('forumpass['.$forum_id.']', md5($this->mybb->user['uid'].$password), NULL, true);
  145.                     return true;
  146.                 }
  147.                 else
  148.                 {
  149.                     return false;
  150.                 }
  151.             }
  152.         }
  153.         else
  154.         {
  155.             return true;
  156.         }  
  157.     }
  158.    
  159.     /**
  160.      * Enables you to close one or more threads
  161.      * One thread: $thread_id is int
  162.      * More threads: $thread_id is array with ints
  163.      *
  164.      * @param integer|array $thread_id See above
  165.      * @param integer $forum_id This can be filled for a nice moderator log!
  166.      * @return boolean
  167.     */
  168.     function closeThread($thread_id, $forum_id = 0)
  169.     {
  170.         if (!is_moderator($fid, "canopenclosethreads"))
  171.         {
  172.             return false;
  173.         }
  174.        
  175.         $this->lang->load('moderation');
  176.        
  177.         $this->MyBBIntegratorClassObject('moderation', 'Moderation', MYBB_ROOT.'/inc/class_moderation.php');
  178.        
  179.         $this->moderation->close_threads($thread_id);
  180.        
  181.         $modlogdata['fid'] = $forum_id;
  182.        
  183.         $this->logModeratorAction($modlogdata, $this->lang->mod_process);
  184.        
  185.         return true;
  186.     }
  187.    
  188.     /**
  189.      * Insert a new Category into Database
  190.      *
  191.      * @param array $data Array with keys according to database layout, which holds the data of the forum
  192.      * @param array $permissions Array with Permission entries (structure: array( 'canview' => array( 'usergroupid' => 1 ) )) (an example)
  193.      * @param array $default_permissions Array which defines, if default permissions shall be used (structure: array( usergroupid => 0 / 1 )
  194.      *                                   Can be left empty, then this function will take care of it
  195.      * @return $data with more values, like fid and parentlist
  196.     */
  197.     function createCategory($data, $permissions = array(), $default_permissions = array())
  198.     {      
  199.         require_once MYBB_ADMIN_DIR.'inc/functions.php';
  200.        
  201.         if (!isset($data['name']))
  202.         {
  203.             $this->_errorAndDie('A new forum needs to have a name and a type');
  204.         }
  205.        
  206.         $data['type'] = 'c';
  207.        
  208.         // Let's leave the parentlist creation to the script and let's not trust the dev :)
  209.         if ($data['parentlist'] != '')
  210.         {
  211.             $data['parentlist'] = '';
  212.         }
  213.        
  214.         // If there is no defined Parent ID, parent ID will be set to 0
  215.         if (!isset($data['pid']) || $data['pid'] < 0)
  216.         {
  217.             $data['pid'] = 0;
  218.         }
  219.         else
  220.         {
  221.             $data['pid'] = intval($data['pid']);
  222.         }
  223.        
  224.         if (!empty($permissions))
  225.         {      
  226.             if (
  227.                 (!isset($permissions['canview']) || empty($permissions['canview'])) ||
  228.                 (!isset($permissions['canpostthreads']) || empty($permissions['canpostthreads'])) ||
  229.                 (!isset($permissions['canpostreplys']) || empty($permissions['canpostreplys'])) ||
  230.                 (!isset($permissions['canpostpolls']) || empty($permissions['canpostpolls'])) ||
  231.                 (!isset($permissions['canpostattachments']) || empty($permissions['canpostattachments']))
  232.                )
  233.             {
  234.                 $this->_errorAndDie('The $permissions Parameter does not have the correct format. It requires following keys: <i>canview, canpostthreads, canpostreplys, canpostpolls and canpostattachments</i>');
  235.             }
  236.            
  237.             /**
  238.              * If no default permissions are given, we will initiate them, default: yes
  239.              * Since there is the possibility of additional usergroups, we will get the usergroups from the permissions array!
  240.              * The structure of the inherit array is: keys = groupid
  241.              * If the value of an inherit array item is 1, this means that the default_permissions shall be used
  242.             */
  243.             if (empty($default_permissions))
  244.             {
  245.                 foreach ($permissions['canview'] as $gid)
  246.                 {
  247.                     $default_permissions[$gid] = 1;
  248.                 }
  249.             }
  250.         }
  251.        
  252.         $data['fid'] = $this->db->insert_query("forums", $data);
  253.        
  254.         $data['parentlist'] = make_parent_list($data['fid']);
  255.         $this->db->update_query("forums", array("parentlist" => $data['parentlist']), 'fid=\''.$data['fid'].'\'');
  256.        
  257.         $this->cache->update_forums();
  258.        
  259.         if (!empty($permissions))
  260.         {
  261.             $inherit = $default_permissions;
  262.            
  263.             /**
  264.              * $permissions['canview'][1] = 1 OR $permissions['canview'][1] = 0
  265.              * --> $permissions[$name][$gid] = yes / no
  266.             */
  267.                
  268.             $canview = $permissions['canview'];
  269.             $canpostthreads = $permissions['canpostthreads'];
  270.             $canpostpolls = $permissions['canpostpolls'];
  271.             $canpostattachments = $permissions['canpostattachments'];
  272.             $canpostreplies = $permissions['canpostreplys'];
  273.             save_quick_perms($data['fid']);
  274.         }
  275.        
  276.         return $data;
  277.     }
  278.    
  279.     /**
  280.      * Insert a new Forum into Database
  281.      *
  282.      * @param array $data Array with keys according to database layout, which holds the data of the forum
  283.      * @param array $permissions Array with Permission entries (structure: array( 'canview' => array( 'usergroupid' => 1 ) )) (an example)
  284.      * @param array $default_permissions Array which defines, if default permissions shall be used (structure: array( usergroupid => 0 / 1 )
  285.      *                                   Can be left empty, then this function will take care of it
  286.      * @return $data with more values, like fid and parentlist
  287.     */
  288.     function createForum($data, $permissions = array(), $default_permissions = array())
  289.     {      
  290.         require_once MYBB_ADMIN_DIR.'inc/functions.php';
  291.        
  292.         if (!isset($data['name']))
  293.         {
  294.             $this->_errorAndDie('A new forum needs to have a name and a type');
  295.         }
  296.        
  297.         $data['type'] = 'f';
  298.        
  299.         // Let's leave the parentlist creation to the script and let's not trust the dev :)
  300.         if ($data['parentlist'] != '')
  301.         {
  302.             $data['parentlist'] = '';
  303.         }
  304.        
  305.         // If there is no defined Parent ID, parent ID will be set to 0
  306.         if (!isset($data['pid']) || $data['pid'] < 0)
  307.         {
  308.             $data['pid'] = 0;
  309.         }
  310.         else
  311.         {
  312.             $data['pid'] = intval($data['pid']);
  313.         }
  314.        
  315.         if (!empty($permissions))
  316.         {      
  317.             if (
  318.                 (!isset($permissions['canview']) || empty($permissions['canview'])) ||
  319.                 (!isset($permissions['canpostthreads']) || empty($permissions['canpostthreads'])) ||
  320.                 (!isset($permissions['canpostreplys']) || empty($permissions['canpostreplys'])) ||
  321.                 (!isset($permissions['canpostpolls']) || empty($permissions['canpostpolls'])) ||
  322.                 (!isset($permissions['canpostattachments']) || empty($permissions['canpostattachments']))
  323.                )
  324.             {
  325.                 $this->_errorAndDie('The $permissions Parameter does not have the correct format. It requires following keys: <i>canview, canpostthreads, canpostreplys, canpostpolls and canpostattachments</i>');
  326.             }
  327.            
  328.             /**
  329.              * If no default permissions are given, we will initiate them, default: yes
  330.              * Since there is the possibility of additional usergroups, we will get the usergroups from the permissions array!
  331.              * The structure of the inherit array is: keys = groupid
  332.              * If the value of an inherit array item is 1, this means that the default_permissions shall be used
  333.             */
  334.             if (empty($default_permissions))
  335.             {
  336.                 foreach ($permissions['canview'] as $gid)
  337.                 {
  338.                     $default_permissions[$gid] = 1;
  339.                 }
  340.             }
  341.         }
  342.        
  343.         $data['fid'] = $this->db->insert_query("forums", $data);
  344.        
  345.         $data['parentlist'] = make_parent_list($data['fid']);
  346.         $this->db->update_query("forums", array("parentlist" => $data['parentlist']), 'fid=\''.$data['fid'].'\'');
  347.        
  348.         $this->cache->update_forums();
  349.        
  350.         if (!empty($permissions))
  351.         {
  352.             $inherit = $default_permissions;
  353.            
  354.             /**
  355.              * $permissions['canview'][1] = 1 OR $permissions['canview'][1] = 0
  356.              * --> $permissions[$name][$gid] = yes / no
  357.             */
  358.                
  359.             $canview = $permissions['canview'];
  360.             $canpostthreads = $permissions['canpostthreads'];
  361.             $canpostpolls = $permissions['canpostpolls'];
  362.             $canpostattachments = $permissions['canpostattachments'];
  363.             $canpostreplies = $permissions['canpostreplys'];
  364.             save_quick_perms($data['fid']);
  365.         }
  366.        
  367.         return $data;
  368.     }
  369.    
  370.     /**
  371.      * Create a new poll and assign it to a thread
  372.      * Taken frm polls.php
  373.      *
  374.      * @param integer $thread_id ID of Thread where the poll should be assigned to
  375.      * @param array $data The Data
  376.     */
  377.     function createPoll($thread_id, $data)
  378.     {
  379.         // Required keys in data array: options, question
  380.         if (!isset($data['options']) || !isset($data['question']))
  381.         {
  382.             $this->_errorAndDie('One or more required array keys in parameter <i>$data</i> missing. Required keys are: <i>options</i>, <i>question</i>');
  383.         }
  384.        
  385.         $this->lang->load('polls');
  386.        
  387.         $this->plugins->run_hooks("polls_do_newpoll_start");
  388.  
  389.         $query = $this->db->simple_select("threads", "*", "tid='".(int) $thread_id."'");
  390.         $thread = $this->db->fetch_array($query);
  391.         $fid = $thread['fid'];
  392.         $forumpermissions = forum_permissions($fid);
  393.        
  394.         if (!$thread['tid'])
  395.         {
  396.             return $this->lang->error_invalidthread;
  397.         }
  398.         // No permission if: Not thread author; not moderator; no forum perms to view, post threads, post polls
  399.         if (($thread['uid'] != $this->mybb->user['uid'] && !is_moderator($fid)) || ($forumpermissions['canview'] == 0 || $forumpermissions['canpostthreads'] == 0 || $forumpermissions['canpostpolls'] == 0))
  400.         {
  401.             return false;
  402.         }
  403.    
  404.         if ($thread['poll'])
  405.         {
  406.             return $this->lang->error_pollalready;
  407.         }
  408.    
  409.         $polloptions = count($data['options']);
  410.         if($this->mybb->settings['maxpolloptions'] && $polloptions > $this->mybb->settings['maxpolloptions'])
  411.         {
  412.             $polloptions = $this->mybb->settings['maxpolloptions'];
  413.         }
  414.        
  415.         if (!isset($data['postoptions']))
  416.         {
  417.             $data['postoptions'] = array('multiple', 'public');
  418.         }
  419.        
  420.         $postoptions = $data['postoptions'];
  421.        
  422.         if ($postoptions['multiple'] != '1')
  423.         {
  424.             $postoptions['multiple'] = 0;
  425.         }
  426.    
  427.         if ($postoptions['public'] != '1')
  428.         {
  429.             $postoptions['public'] = 0;
  430.         }
  431.        
  432.         if ($polloptions < 2)
  433.         {
  434.             $polloptions = "2";
  435.         }
  436.        
  437.         $optioncount = "0";
  438.        
  439.         $options = $data['options'];
  440.        
  441.         for($i = 0; $i < $polloptions; ++$i)
  442.         {
  443.             if (trim($options[$i]) != "")
  444.             {
  445.                 $optioncount++;
  446.             }
  447.            
  448.             if (my_strlen($options[$i]) > $this->mybb->settings['polloptionlimit'] && $this->mybb->settings['polloptionlimit'] != 0)
  449.             {
  450.                 $lengtherror = 1;
  451.                 break;
  452.             }
  453.         }
  454.        
  455.         if ($lengtherror)
  456.         {
  457.             return $this->lang->error_polloptiontoolong;
  458.         }
  459.        
  460.         if (empty($data['question']) || $optioncount < 2)
  461.         {
  462.             return $this->lang->error_noquestionoptions;
  463.         }
  464.        
  465.         $optionslist = '';
  466.         $voteslist = '';
  467.         for($i = 0; $i < $optioncount; ++$i)
  468.         {
  469.             if(trim($options[$i]) != '')
  470.             {
  471.                 if($i > 0)
  472.                 {
  473.                     $optionslist .= '||~|~||';
  474.                     $voteslist .= '||~|~||';
  475.                 }
  476.                 $optionslist .= $options[$i];
  477.                 $voteslist .= '0';
  478.             }
  479.         }
  480.        
  481.         if (!isset($data['timeout']))
  482.         {
  483.             $data['timeout'] = 0;
  484.         }
  485.        
  486.         if($data['timeout'] > 0)
  487.         {
  488.             $timeout = intval($data['timeout']);
  489.         }
  490.         else
  491.         {
  492.             $timeout = 0;
  493.         }
  494.        
  495.         $newpoll = array(
  496.             "tid" => $thread['tid'],
  497.             "question" => $this->db->escape_string($data['question']),
  498.             "dateline" => TIME_NOW,
  499.             "options" => $this->db->escape_string($optionslist),
  500.             "votes" => $this->db->escape_string($voteslist),
  501.             "numoptions" => intval($optioncount),
  502.             "numvotes" => 0,
  503.             "timeout" => $timeout,
  504.             "closed" => 0,
  505.             "multiple" => $postoptions['multiple'],
  506.             "public" => $postoptions['public']
  507.         );
  508.    
  509.         $this->plugins->run_hooks("polls_do_newpoll_process");
  510.    
  511.         $pid = $this->db->insert_query("polls", $newpoll);
  512.    
  513.         $this->db->update_query("threads", array('poll' => $pid), "tid='".$thread['tid']."'");
  514.    
  515.         $this->plugins->run_hooks("polls_do_newpoll_end");
  516.        
  517.         return true;
  518.     }
  519.    
  520.     /**
  521.      * Insert a new post into Database
  522.      *
  523.      * @param array $data Post Data
  524.      * @return array|string When true it will return an array with postID and status of being visible - false = error array or inline string
  525.     */
  526.     function createPost($data, $inline_errors = true)
  527.     {
  528.         require_once MYBB_ROOT.'inc/functions_post.php';
  529.         require_once MYBB_ROOT.'/inc/datahandlers/post.php';
  530.         $posthandler = new PostDataHandler('insert');
  531.        
  532.         $this->plugins->run_hooks('newreply_do_newreply_start');
  533.        
  534.         $posthandler->set_data($data);
  535.        
  536.         if (!$posthandler->validate_post())
  537.         {
  538.             $errors = $posthandler->get_friendly_errors();
  539.             return ($inline_errors === true) ? inline_error($errors) : $errors;
  540.         }
  541.        
  542.         $this->plugins->run_hooks('newreply_do_newreply_end');
  543.        
  544.         return $posthandler->insert_post();
  545.     }
  546.    
  547.     /**
  548.      * Inserts a thread into the database
  549.      *
  550.      * @param array $data Thread data
  551.      * @param boolean $inline_errors Defines if we want a formatted error string or an array
  552.      * @return array|string
  553.      * @return array|string When true it will return an array with threadID, postID and status of being visible - false = error array or inline string
  554.     */
  555.     function createThread($data, $inline_errors = true)
  556.     {
  557.         require_once MYBB_ROOT.'inc/functions_post.php';
  558.         require_once MYBB_ROOT.'/inc/datahandlers/post.php';
  559.         $posthandler = new PostDataHandler('insert');
  560.         $posthandler->action = 'thread';
  561.         $posthandler->set_data($data);
  562.         if (!$posthandler->validate_thread())
  563.         {
  564.             $errors = $posthandler->get_friendly_errors();
  565.             return ($inline_errors === true) ? inline_error($errors) : $errors;
  566.         }
  567.         return $posthandler->insert_thread();
  568.     }
  569.    
  570.     /**
  571.      * Insert a new user into Database
  572.      *
  573.      * @param array $data User data
  574.      * @param boolean $inline_errors Defines if we want a formatted error string or an array
  575.      * @return array|string When true it will return an array with some user data - false = error array or inline string
  576.     */
  577.     function createUser($data, $inline_errors = true)
  578.     {
  579.         require_once MYBB_ROOT.'inc/functions_user.php';
  580.         require_once MYBB_ROOT.'/inc/datahandlers/user.php';
  581.         $userhandler = new UserDataHandler('insert');
  582.        
  583.         $this->plugins->run_hooks('admin_user_users_add');
  584.        
  585.         $userhandler->set_data($data);
  586.        
  587.         if (!$userhandler->validate_user())
  588.         {
  589.             $errors = $userhandler->get_friendly_errors();
  590.             return ($inline_errors === true) ? inline_error($errors) : $errors;
  591.         }
  592.        
  593.         $this->plugins->run_hooks('admin_user_users_add_commit');
  594.        
  595.         return $userhandler->insert_user();
  596.     }
  597.    
  598.     /**
  599.      * Escapes a value for DB usage
  600.      *
  601.      * @param mixed $value Any value to use with the database
  602.      * @return string
  603.     */
  604.     function dbEscape($value)
  605.     {
  606.         return $this->db->escape_string($value);
  607.     }
  608.    
  609.     /**
  610.      * Remove a poll
  611.      * Taken from moderation.php
  612.      *
  613.      * @param integer $poll_id ID of Poll to be deleted
  614.      * @return boolean|string
  615.     */
  616.     function deletePoll($poll_id)
  617.     {
  618.         $this->lang->load('moderation');
  619.        
  620.         $this->MyBBIntegratorClassObject('moderation', 'Moderation', MYBB_ROOT.'/inc/class_moderation.php');
  621.        
  622.         $query = $this->db->simple_select("polls", "*", "pid='$poll_id'");
  623.         $poll = $this->db->fetch_array($query);
  624.         if(!$poll['pid'])
  625.         {
  626.             return $this->lang->error_invalidpoll;
  627.         }
  628.        
  629.         $thread = $this->getThread($poll['tid']);
  630.        
  631.         if(!is_moderator($thread['fid'], "candeleteposts"))
  632.         {
  633.             if($permissions['candeletethreads'] != 1 || $this->mybb->user['uid'] != $thread['uid'])
  634.             {
  635.                 return false;
  636.             }
  637.         }
  638.        
  639.         $modlogdata = array();
  640.         $modlogdata['tid'] = $poll['tid'];
  641.  
  642.         $this->plugins->run_hooks("moderation_do_deletepoll");
  643.  
  644.         $this->lang->poll_deleted = $this->lang->sprintf($this->lang->poll_deleted, $thread['subject']);
  645.         $this->logModeratorAction($modlogdata, $this->lang->poll_deleted);
  646.  
  647.         $this->moderation->delete_poll($poll['pid']);
  648.        
  649.         return true;
  650.     }
  651.    
  652.     /**
  653.      * Delete the poll of a thread
  654.      * Taken from moderation.php
  655.      *
  656.      * @param integer $thread_id Thread-ID where the poll is located
  657.      * @return boolean|string
  658.     */
  659.     function deletePollOfThread($thread_id)
  660.     {
  661.         $this->lang->load('polls');
  662.         $this->lang->load('moderation');
  663.        
  664.         $this->MyBBIntegratorClassObject('moderation', 'Moderation', MYBB_ROOT.'/inc/class_moderation.php');
  665.        
  666.         $thread = $this->getThread($thread_id);
  667.         $permissions = forum_permissions($thread['fid']);
  668.        
  669.         if (!is_moderator($thread['fid'], "candeleteposts"))
  670.         {
  671.             if($permissions['candeletethreads'] != 1 || $this->mybb->user['uid'] != $thread['uid'])
  672.             {
  673.                 return false;
  674.             }
  675.         }
  676.        
  677.         $query = $this->db->simple_select("polls", "*", "tid='$thread_id'");
  678.         $poll = $this->db->fetch_array($query);
  679.         if(!$poll['pid'])
  680.         {
  681.             return $this->lang->error_invalidpoll;
  682.         }
  683.        
  684.         $modlogdata = array();
  685.         $modlogdata['tid'] = $poll['tid'];
  686.  
  687.         $this->plugins->run_hooks("moderation_do_deletepoll");
  688.  
  689.         $this->lang->poll_deleted = $this->lang->sprintf($this->lang->poll_deleted, $thread['subject']);
  690.         $this->logModeratorAction($modlogdata, $this->lang->poll_deleted);
  691.  
  692.         $this->moderation->delete_poll($poll['pid']);
  693.        
  694.         return true;
  695.     }
  696.    
  697.     /**
  698.      * Flag private messages as deleted
  699.      *
  700.      * @param integer|array $pm_id ID(s) of Private Messages (many IDs require an array)
  701.     */
  702.     function deletePrivateMessage($pm_id)
  703.     {
  704.         require_once MYBB_ROOT.'inc/functions_user.php';
  705.        
  706.         $this->plugins->run_hooks('private_delete_start');
  707.        
  708.         $data = array(
  709.             'folder' => 4,
  710.             'deletetime' => TIME_NOW
  711.         );
  712.        
  713.         if (is_array($pm_id))
  714.         {
  715.             $this->db->update_query('privatemessages', $data, 'pmid IN ('.implode(',', array_map('intval', $pm_id)).')');
  716.         }
  717.         else
  718.         {
  719.             $this->db->update_query('privatemessages', $data, 'pmid = '.intval($pm_id));
  720.         }
  721.        
  722.         update_pm_count();
  723.        
  724.         $this->plugins->run_hooks('private_delete_end');
  725.        
  726.     }
  727.    
  728.     /**
  729.      * Flag all private messages of a user as deleted
  730.      * It is also possible to flag pms as deleted of multiple users, when paramater is an array with IDs
  731.      *
  732.      * @param integer|array $pm_id ID(s) of User IDs (many IDs require an array)
  733.     */
  734.     function deletePrivateMessagesOfUser($user_id)
  735.     {
  736.         require_once MYBB_ROOT.'inc/functions_user.php';
  737.        
  738.         $this->plugins->run_hooks('private_delete_start');
  739.        
  740.         $data = array(
  741.             'folder' => 4,
  742.             'deletetime' => TIME_NOW
  743.         );
  744.        
  745.         if (is_array($user_id))
  746.         {
  747.             $this->db->update_query('privatemessages', $data, 'uid IN ('.implode(',', array_map('intval', $user_id)).')');
  748.         }
  749.         else
  750.         {
  751.             $this->db->update_query('privatemessages', $data, 'uid = '.intval($user_id));
  752.         }
  753.        
  754.         update_pm_count();
  755.        
  756.         $this->plugins->run_hooks('private_delete_end');
  757.     }
  758.    
  759.     /**
  760.      * Generates a Captcha
  761.      *
  762.      * @return array
  763.     */
  764.     function generateCaptcha()
  765.     {
  766.         $randomstr = random_str(5);
  767.         $imagehash = md5(random_str(12));
  768.         $imagearray = array(
  769.             "imagehash" => $imagehash,
  770.             "imagestring" => $randomstr,
  771.             "dateline" => TIME_NOW
  772.         );
  773.         $this->db->insert_query("captcha", $imagearray);
  774.         return array_merge($imagearray, array(
  775.             'captcha' => '<img src="'.$this->mybb->settings['bburl'].'/captcha.php?imagehash='.$imagehash.'" />'
  776.         ));
  777.     }
  778.    
  779.     /**
  780.      * Generates a posthash
  781.      *
  782.      * @param integer $user_id User-ID
  783.      * @return string MD5
  784.     */
  785.     function generatePosthash($user_id = 0)
  786.     {
  787.         mt_srand((double) microtime() * 1000000);
  788.         if ($user_id == 0)
  789.         {
  790.             return md5($this->mybb->user['uid'].mt_rand());
  791.         }
  792.         else
  793.         {
  794.             return md5($user_id.mt_rand());
  795.         }
  796.     }
  797.    
  798.     /**
  799.      * Get the Hottest Threads within a defined timespan
  800.      *
  801.      * @param integer $timespan The timespan you want to use for fetching the hottest topics (in seconds)
  802.      * @param string $post_sort_order Sort Order to the posts you are fetching (ordered by the dateline)
  803.      * @param string $postamount_sort_order Sort order of the threads (ordered by the amount of posts)
  804.      * @return array
  805.     */
  806.     function getBusyThreadsWithinTimespan($timespan = 86400, $post_sort_order = 'DESC', $postamount_sort_order = 'DESC')
  807.     {
  808.         $threads = array();
  809.        
  810.         // Make sure the parameters have correct values
  811.         $post_sort_order = ($post_sort_order == 'DESC') ? 'DESC' : 'ASC';
  812.         $postamount_sort_order = ($postamount_sort_order == 'DESC') ? 'DESC' : 'ASC';
  813.        
  814.         $query = $this->db->query('
  815.             SELECT p.`pid`, p.`message`, p.`uid` as postuid, p.`username` as postusername, p.`dateline`,
  816.                    t.`tid`, t.`fid`, t.`subject`, t.`uid` as threaduid, t.`username` as threadusername, t.`lastpost`, t.`lastposter`, t.`lastposteruid`, t.`views`, t.`replies`
  817.             FROM '.TABLE_PREFIX.'posts p
  818.             INNER JOIN '.TABLE_PREFIX.'threads t ON t.`tid` = p.`tid`
  819.             WHERE p.`dateline` >= '.(TIME_NOW - $timespan).'
  820.             ORDER BY p.`dateline` '.$post_sort_order.'
  821.         ');
  822.  
  823.         while ($post = $this->db->fetch_array($query))
  824.         {
  825.             /**
  826.              * The return array we are building is being filled with the thread itself, but also with the posts
  827.              * We will later increase the Postamount, so we can sort it
  828.             */
  829.             if (!isset($threads[$post['tid']]))
  830.             {
  831.                 $threads[$post['tid']] = array(
  832.                     'tid' => $post['tid'],
  833.                     'fid' => $post['fid'],
  834.                     'subject' => $post['subject'],
  835.                     'uid' => $post['threaduid'],
  836.                     'username' => $post['threadusername'],
  837.                     'lastpost' => $post['lastpost'],
  838.                     'lastposter' => $post['lastposter'],
  839.                     'lastposteruid' => $post['lastposteruid'],
  840.                     'views' => $post['views'],
  841.                     'replies' => $post['replies'],
  842.                     'postamount' => 1,
  843.                     'posts' => array()
  844.                 );
  845.                
  846.                 // The first run of one thread also brings a post, so we assign this post
  847.                 $threads[$post['tid']]['posts'][] = array(
  848.                     'pid' => $post['pid'],
  849.                     'message' => $post['message'],
  850.                     'uid' => $post['postuid'],
  851.                     'username' => $post['postusername'],
  852.                     'dateline' => $post['dateline']
  853.                 );
  854.             }
  855.             else
  856.             {
  857.                 // The thread array key exists already, so we increment the postamount and save another post
  858.                 $threads[$post['tid']]['postamount']++;
  859.                 $threads[$post['tid']]['posts'][] = array(
  860.                     'pid' => $post['pid'],
  861.                     'message' => $post['message'],
  862.                     'uid' => $post['postuid'],
  863.                     'username' => $post['postusername'],
  864.                     'dateline' => $post['dateline']
  865.                 );
  866.             }
  867.         }
  868.        
  869.         // Sort function for ascending posts
  870.         function arraySortByPostamountASC($item1, $item2)
  871.         {
  872.             if ($item1['postamount'] == $item2['postamount'])
  873.             {
  874.                 return 0;
  875.             }
  876.            
  877.             if ($item1['postamount'] > $item2['postamount'])
  878.             {
  879.                 return 1;
  880.             }
  881.             else
  882.             {
  883.                 return -1;
  884.             }
  885.         }
  886.        
  887.         // Sort function for descending posts
  888.         function arraySortByPostamountDESC($item1, $item2)
  889.         {
  890.             if ($item1['postamount'] == $item2['postamount'])
  891.             {
  892.                 return 0;
  893.             }
  894.            
  895.             if ($item1['postamount'] > $item2['postamount'])
  896.             {
  897.                 return -1;
  898.             }
  899.             else
  900.             {
  901.                 return 1;
  902.             }
  903.         }
  904.        
  905.         // Let's sort the threads now
  906.         usort($threads, 'arraySortByPostamount'.$postamount_sort_order);
  907.        
  908.         return $threads;
  909.     }
  910.    
  911.     /**
  912.      * Returns data of a specified forum
  913.      * Refers to: inc/functions.php
  914.      *
  915.      * @param integer $forum_id ID of forum to fetch data from
  916.      * @param integer $active_override If set to 1, will override the active forum status
  917.      * @return array|boolean If unsuccessful, it returns false - Otherwise the Database row
  918.     */
  919.     function getForum($forum_id, $active_override = 0)
  920.     {
  921.         $forum = get_forum($forum_id, $active_override);
  922.        
  923.         // Do we have permission?
  924.         $forumpermissions = forum_permissions($forum['fid']);
  925.         if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  926.         {
  927.             // error_no_permission();
  928.             return false;
  929.         }
  930.         else
  931.         {
  932.             return $forum;
  933.         }
  934.     }
  935.    
  936.     /**
  937.      * Return members of the board with administrative function
  938.      * Taken from /showteam.php
  939.      *
  940.      * @return array
  941.     */
  942.     function getForumStaff()
  943.     {
  944.         $this->lang->load('showteam');
  945.        
  946.         $usergroups = array();
  947.         $moderators = array();
  948.         $users = array();
  949.  
  950.         // Fetch the list of groups which are to be shown on the page
  951.         $query = $this->db->simple_select("usergroups", "gid, title, usertitle", "showforumteam=1", array('order_by' => 'disporder'));
  952.        
  953.         while($usergroup = $this->db->fetch_array($query))
  954.         {
  955.             $usergroups[$usergroup['gid']] = $usergroup;
  956.         }
  957.        
  958.         if (empty($usergroups))
  959.         {
  960.             return $this->lang->error_noteamstoshow;
  961.         }
  962.        
  963.         // Fetch specific forum moderator details
  964.         if ($usergroups[6]['gid'])
  965.         {
  966.             $query = $this->db->query("
  967.                 SELECT m.*, f.name
  968.                 FROM ".TABLE_PREFIX."moderators m
  969.                 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=m.uid)
  970.                 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=m.fid)
  971.                 WHERE f.active = 1
  972.                 ORDER BY u.username
  973.             ");
  974.            
  975.             while($moderator = $this->db->fetch_array($query))
  976.             {
  977.                 $moderators[$moderator['uid']][] = $moderator;
  978.             }
  979.         }
  980.        
  981.         // Now query the users of those specific groups
  982.         $groups_in = implode(",", array_keys($usergroups));
  983.         $users_in = implode(",", array_keys($moderators));
  984.         if (!$groups_in)
  985.         {
  986.             $groups_in = 0;
  987.         }
  988.         if (!$users_in)
  989.         {
  990.             $users_in = 0;
  991.         }
  992.        
  993.         $forum_permissions = forum_permissions();
  994.        
  995.         $query = $this->db->simple_select("users", "uid, username, displaygroup, usergroup, ignorelist, hideemail, receivepms", "displaygroup IN ($groups_in) OR (displaygroup='0' AND usergroup IN ($groups_in)) OR uid IN ($users_in)", array('order_by' => 'username'));
  996.        
  997.         while ($user = $this->db->fetch_array($query))
  998.         {
  999.             // If this user is a moderator
  1000.             if (isset($moderators[$user['uid']]))
  1001.             {
  1002.                 foreach ($moderators[$user['uid']] as $forum)
  1003.                 {
  1004.                     if ($forum_permissions[$forum['fid']]['canview'] == 1)
  1005.                     {
  1006.                         $forum_url = get_forum_link($forum['fid']);
  1007.                     }
  1008.                 }
  1009.                 $usergroups[6]['user_list'][$user['uid']] = $user;
  1010.             }
  1011.            
  1012.             if ($user['displaygroup'] == '6' || $user['usergroup'] == '6')
  1013.             {
  1014.                 $usergroups[6]['user_list'][$user['uid']] = $user;
  1015.             }
  1016.            
  1017.             // Are they also in another group which is being shown on the list?
  1018.             if ($user['displaygroup'] != 0)
  1019.             {
  1020.                 $group = $user['displaygroup'];
  1021.             }
  1022.             else
  1023.             {
  1024.                 $group = $user['usergroup'];
  1025.             }
  1026.            
  1027.             if ($usergroups[$group] && $group != 6)
  1028.             {
  1029.                 $usergroups[$group]['user_list'][$user['uid']] = $user;
  1030.             }
  1031.         }
  1032.        
  1033.         return $usergroups;
  1034.     }
  1035.    
  1036.     /**
  1037.      * Return the latest threads of one forum, where a post has been posted
  1038.      *
  1039.      * @param integer $forum_id Forum ID to fetch threads from
  1040.      * @param integer $limit Amount of threads to get
  1041.      * @param boolean $excluse_invisible Shall we also get invisible threads?
  1042.      * @return array
  1043.     */
  1044.     function getLatestActiveThreads($forum_id = 0, $limit = 7, $exclude_invisible = true)
  1045.     {
  1046.         if ($forum_id == 0)
  1047.         {
  1048.             $this->_errorAndDie('Specified forum ID cannot be 0!');
  1049.         }
  1050.         else
  1051.         {
  1052.             // Do we have permission?
  1053.             $forumpermissions = forum_permissions($forum_id);
  1054.             if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  1055.             {
  1056.                 // error_no_permission();
  1057.                 return false;
  1058.             }
  1059.         }
  1060.        
  1061.         // This will be the array, where we can save the threads
  1062.         $threads = array();
  1063.        
  1064.         // We want to get a list of threads, starting with the newest one
  1065.         $query_params = array(
  1066.             'order_by' => 'lastpost',
  1067.             'order_dir' => 'DESC',
  1068.             'limit' => intval($limit)
  1069.         );
  1070.        
  1071.         /**
  1072.          * If defined forum id is 0, we do not fetch threads from only one forum,
  1073.          * but we fetch the latest threads of all forums
  1074.          * Therefore we add the forum_id in the where condition
  1075.          * We only fetch visible threads, if there is anything we want to hide ;)
  1076.          * However we can also define that we want the invisible threads as well
  1077.         */
  1078.         $fetch_invisible_threads = ($exclude_invisible == true) ? '1' : '0';
  1079.         $condition = ($forum_id != 0) ? ' `visible` = '.$fetch_invisible_threads.' AND `fid` = '.intval($forum_id) : '';
  1080.        
  1081.         // Run the Query
  1082.         $query = $this->db->simple_select('threads', '*', $condition, $query_params);
  1083.        
  1084.         // Now let's iterate through the fetched threads to create the return array
  1085.         while ($thread = $this->db->fetch_array($query))
  1086.         {
  1087.             $threads[] = $thread;
  1088.         }
  1089.        
  1090.         return $threads;
  1091.     }
  1092.    
  1093.     /**
  1094.      * Return newly created threads, regardless of replies
  1095.      *
  1096.      * @param integer|array $forum_id Forum ID / Forum IDs to fetch threads from
  1097.      * @param string $fields Name of fields if you want to fetch specific fields
  1098.      * @param integer $limit Amount of threads to get
  1099.      * @param boolean $excluse_invisible Shall we also get invisible threads?
  1100.      * @param boolean $join_forums Shall we also get the information from the forums where the threads are located in?
  1101.      * @param boolean $join_first_post Shall we get the first post of this thread as well?
  1102.      * @return array
  1103.     */
  1104.     function getLatestThreads($forum_id = 0, $fields = '*', $limit = 7, $exclude_invisible = true, $join_forums = true, $join_first_post = true)
  1105.     {
  1106.         if ($forum_id != 0)
  1107.         {
  1108.             // If we have multiple values, we have to check permission for each forum!
  1109.             if (is_array($forum_id))
  1110.             {
  1111.                 foreach ($forum_id as $single_forum_id)
  1112.                 {
  1113.                     $forum_permissions = forum_permissions($single_forum_id);
  1114.                     if ($forum_permissions['canview'] != 1 || $forum_permissions['canviewthreads'] != 1)
  1115.                     {
  1116.                         // error_no_permission();
  1117.                         return false;
  1118.                     }
  1119.                 }
  1120.             }
  1121.             else
  1122.             {
  1123.                 // Do we have permission?
  1124.                 $forumpermissions = forum_permissions($forum_id);
  1125.                 if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  1126.                 {
  1127.                     // error_no_permission();
  1128.                     return false;
  1129.                 }
  1130.             }
  1131.         }
  1132.        
  1133.         // This is what we will be returning
  1134.         $threads = array();
  1135.        
  1136.         // Do we want to get invisible threads as well?
  1137.         $fetch_invisible_threads = ($exclude_invisible == true) ? '1' : '0';
  1138.         $condition = 't.`visible` = '.$fetch_invisible_threads;
  1139.        
  1140.         // Are we fetching threads from multiple forums?
  1141.         if (is_array($forum_id) || is_object($forum_id))
  1142.         {
  1143.             $condition .= ' AND t.`fid` IN ('.implode(', ', $forum_id).')';
  1144.            
  1145.         }
  1146.         // Or are we just fetching threads from one forum?
  1147.         else
  1148.         {
  1149.             $condition .= ($forum_id == 0) ? '' : ' AND t.`fid` = '.$forum_id;
  1150.         }
  1151.        
  1152.         // Do we want to get information of the forum where the thread is located in?
  1153.         $forum_join = ($join_forums == true) ? 'INNER JOIN '.TABLE_PREFIX.'forums f ON f.`fid` = t.`fid`' : '';
  1154.        
  1155.         // Do we want to get the first post from the thread?
  1156.         $first_post_join = ($join_first_post == true) ? 'INNER JOIN '.TABLE_PREFIX.'posts p ON p.`pid` = t.`firstpost`' : '';
  1157.        
  1158.         // Run the Query
  1159.         $query = $this->db->query('
  1160.             SELECT '.$fields.'
  1161.             FROM '.TABLE_PREFIX.'threads t
  1162.             '.$forum_join.'
  1163.             '.$first_post_join.'
  1164.             WHERE '.$condition.'
  1165.             ORDER BY t.`dateline` DESC
  1166.             LIMIT '.intval($limit).'
  1167.         ');
  1168.        
  1169.         // Iterate through the results and assign it to our returning array
  1170.         while ($thread = $this->db->fetch_array($query))
  1171.         {
  1172.             $threads[] = $thread;
  1173.         }
  1174.        
  1175.         return $threads;
  1176.     }
  1177.    
  1178.     /**
  1179.      * Return recently posted posts
  1180.      *
  1181.      * @param integer|array Either a single Thread ID or an array containing thread IDs
  1182.      * @param string Fields, which shall be fetched from the posts table
  1183.      * @param integer How many posts shall be fetched?
  1184.      * @param boolean Shall we also return invisible ones?
  1185.      * @return array
  1186.     */
  1187.     function getLatestPosts($thread_id = 0, $fields = '*', $limit = 7, $exclude_invisible = true)
  1188.     {        
  1189.         // Posts will be stored in this array
  1190.         $posts = array();
  1191.        
  1192.         // Posts will be returned in descending order, starting with the newest
  1193.         $query_params = array(
  1194.             'order_by' => 'dateline',
  1195.             'order_dir' => 'DESC',
  1196.             'limit' => intval($limit)
  1197.         );
  1198.        
  1199.         // We want to fetch posts from multiple threads
  1200.         if (is_array($thread_id) || is_object($thread_id))
  1201.         {
  1202.             // Multiple threads = IN (...) Operator
  1203.             $condition = '`fid` IN ('.implode(', ', $thread_id).')';
  1204.         }
  1205.         else
  1206.         {
  1207.             // Single thread = normal WHERE X = Y - if set 0 we fetch posts from all threads
  1208.             $condition = ($thread_id == 0) ? '1 = 1' : '`fid` = '.intval($thread_id);
  1209.         }
  1210.        
  1211.         /**
  1212.          * If defined forum id is 0, we do not fetch threads from only one forum,
  1213.          * but we fetch the latest threads of all forums
  1214.          * Therefore we add the forum_id in the where condition
  1215.          * We only fetch visible threads, if there is anything we want to hide ;)
  1216.          * However we can also define that we want the invisible threads as well
  1217.         */
  1218.         $fetch_invisible_threads = ($exclude_invisible == true) ? '1' : '0';
  1219.         $condition .= ' AND `visible` = '.$fetch_invisible_threads;
  1220.        
  1221.         // Run the Query
  1222.         $query = $this->db->simple_select('posts', $fields, $condition, $query_params);
  1223.        
  1224.         // Now let's iterate through the fetched posts to create the return array
  1225.         while ($post = $this->db->fetch_array($query))
  1226.         {
  1227.             $posts[] = $post;
  1228.         }
  1229.        
  1230.         return $posts;
  1231.     }
  1232.    
  1233.     /**
  1234.      * Retrieve member list
  1235.      * Ideal to offer a multi-page member list
  1236.      *
  1237.      * @param array $data Contains data affecting the member query - List of Array keys below
  1238.      *                    - orderby: What table column will the member list be sorted by?
  1239.      *                    - orderdir: Ascending or Descending order direction
  1240.      *                    - perpage: Amount of members to fetch (set 0 for all members)
  1241.      *                    - letter: Beginning character of member name
  1242.      *                    - username: Searching for a matching username
  1243.      *                    - username_match: Set this to "begins" when username shall being with given token - otherwise it goes or "contains"
  1244.      *                    - website: String contained in website
  1245.      *                    - aim: Search for an AIM
  1246.      *                    - icq: Search for an ICQ number
  1247.      *                    - msn: Search for a MSN ID
  1248.      *                    - yahoo: Search for a Yahoo ID
  1249.      *                    - page: Which page of the list will we be retrieving
  1250.      * @return array
  1251.     */
  1252.     function getMembers($data = array())
  1253.     {
  1254.         /**
  1255.          *  Make sure we have initial values in the data array 
  1256.         */
  1257.        
  1258.         $data['orderby'] = (!isset($data['orderby'])) ? 'u.`username`' : $data['orderby'];     
  1259.         $data['orderdir'] = (!isset($data['orderdir'])) ? 'ASC' : strtoupper($data['orderdir']);
  1260.         $data['orderdir'] = ($data['orderdir'] == 'ASC') ? 'ASC' : 'DESC';     
  1261.         $data['perpage'] = (!isset($data['perpage'])) ? (int) $this->mybb->settings['membersperpage'] : (int) $data['perpage'];    
  1262.         $data['letter'] = (!isset($data['letter'])) ? '' : $data['letter'];        
  1263.         $data['username'] = (!isset($data['username'])) ? '' : $data['username'];
  1264.         $data['username_match'] = (!isset($data['username_match'])) ? 'begins' : $data['username_match'];  
  1265.         $data['website'] = (!isset($data['website'])) ? '' : $data['website'];     
  1266.         $data['aim'] = (!isset($data['aim'])) ? '' : $data['aim'];
  1267.         $data['icq'] = (!isset($data['icq'])) ? '' : $data['icq'];     
  1268.         $data['msn'] = (!isset($data['msn'])) ? '' : $data['msn'];     
  1269.         $data['yahoo'] = (!isset($data['yahoo'])) ? '' : $data['yahoo'];
  1270.         $data['page'] = (!isset($data['page'])) ? 1 : (int) $data['page'];
  1271.        
  1272.         /**
  1273.          * Let's build the DB query now!
  1274.         */
  1275.        
  1276.         $sql_where = 'WHERE 1 = 1';
  1277.        
  1278.         // Username begins with a letter or number
  1279.         if (strlen($data['letter']) == 1)
  1280.         {
  1281.             $data['letter'] = chr(ord($data['letter']));
  1282.             // Letter is 0: Shall start with number
  1283.             if ($data['letter'] == '0')
  1284.             {
  1285.                 $sql_where .= " AND u.`username` NOT REGEXP('[a-zA-Z]')";
  1286.             }
  1287.             // letter is not 0, so it will be fetching names according to first char
  1288.             else
  1289.             {
  1290.                 $sql_where .= " AND u.`username` LIKE '".$this->db->escape_string($data['letter'])."%'";
  1291.             }
  1292.         }
  1293.        
  1294.         // Search for matching username
  1295.         if (strlen($data['username']) > 0)
  1296.         {
  1297.             $data['username'] = htmlspecialchars_uni($data['username']);
  1298.             if ($data['username_match'] == 'begins')
  1299.             {
  1300.                 $sql_where .= " AND u.`username` LIKE '".$this->db->escape_string_like($data['username'])."%'";
  1301.             }
  1302.             else
  1303.             {
  1304.                 $sql_where .= " AND u.`username` LIKE '%".$this->db->escape_string_like($data['username'])."%'";
  1305.             }
  1306.         }
  1307.        
  1308.         // Search for website
  1309.         if (strlen($data['website']) > 0)
  1310.         {
  1311.             $data['website'] = trim(htmlspecialchars_uni($data['website']));
  1312.             $sql_where .= " AND u.`website` LIKE '%".$this->db->escape_string_like($data['website'])."%'";
  1313.         }
  1314.        
  1315.         // Search for AIM
  1316.         if (strlen($data['aim']) > 0)
  1317.         {
  1318.             $sql_where .= " AND u.`aim` LIKE '%".$this->db->escape_string_like($data['aim'])."%'";
  1319.         }
  1320.        
  1321.         // Search for ICQ
  1322.         if (strlen($data['icq']) > 0)
  1323.         {
  1324.             $sql_where .= " AND u.`icq` LIKE '%".$this->db->escape_string_like($data['icq'])."%'";
  1325.         }
  1326.        
  1327.         // Search for MSN
  1328.         if (strlen($data['msn']) > 0)
  1329.         {
  1330.             $sql_where .= " AND u.`msn` LIKE '%".$this->db->escape_string_like($data['msn'])."%'";
  1331.         }
  1332.        
  1333.         // Search for Yahoo
  1334.         if (strlen($data['yahoo']) > 0)
  1335.         {
  1336.             $sql_where .= " AND u.`yahoo` LIKE '%".$this->db->escape_string_like($data['yahoo'])."%'";
  1337.         }
  1338.        
  1339.         // Build the LIMIT-part of the query here
  1340.         if ($data['perpage'] == 0)
  1341.         {
  1342.             $limit_string = '';
  1343.         }
  1344.         else
  1345.         {
  1346.             if ($data['page'] > 0)
  1347.             {
  1348.                 $limit_string = 'LIMIT '.(($data['page'] - 1) * $data['perpage']).', '.$data['perpage'];
  1349.             }
  1350.             else
  1351.             {
  1352.                 $limit_string = 'LIMIT '.$data['perpage'];
  1353.             }
  1354.         }
  1355.        
  1356.         $sql .= '
  1357.             SELECT u.*, f.*
  1358.             FROM '.TABLE_PREFIX.'users u
  1359.             LEFT JOIN '.TABLE_PREFIX.'userfields f ON f.`ufid` = u.`uid`
  1360.             '.$sql_where.'
  1361.             ORDER BY '.$data['orderby'].' '.$data['orderdir'].'
  1362.             '.$limit_string.'
  1363.         ';
  1364.        
  1365.         $query = $this->db->query($sql);
  1366.        
  1367.         $arr = array();
  1368.        
  1369.         while ($member = $this->db->fetch_array($query))
  1370.         {
  1371.             $arr[] = $member;
  1372.         }
  1373.        
  1374.         return $arr;
  1375.     }
  1376.    
  1377.     /**
  1378.      * Read some info about a poll
  1379.      *
  1380.      * @param integer $poll_id ID of Poll to fetch infos from
  1381.      * @return array
  1382.     */
  1383.     function getPoll($poll_id)
  1384.     {
  1385.         if ($poll_id == 0)
  1386.         {
  1387.             $this->_errorAndDie('Specified poll ID cannot be 0!');
  1388.         }
  1389.        
  1390.         $query = $this->db->query('
  1391.             SELECT *
  1392.             FROM '.TABLE_PREFIX.'polls
  1393.             WHERE `pid` = '.(int) $poll_id.'
  1394.             LIMIT 1
  1395.         ');
  1396.        
  1397.         $poll = $this->db->fetch_array($query);
  1398.        
  1399.         $separator = '||~|~||';
  1400.        
  1401.         $poll['optionsarray'] = explode($separator, $poll['options']);
  1402.         $poll['votesarray'] = explode($separator, $poll['votes']);
  1403.        
  1404.         /**
  1405.          * At this point we are doing another query, so it is easier
  1406.          * Little Todo: Include an INNER JOIN in the initial Poll-fetching query to save one query
  1407.          * YOu have to make sure that columns of "thread" won't override columns of "poll"
  1408.          * Therefore the solution right now at hand will be sufficient, until people start to moan :)
  1409.         */
  1410.         $poll['thread'] = $this->getThread($poll['tid']);
  1411.        
  1412.         $poll['whovoted'] = $this->getWhoVoted($poll_id);
  1413.        
  1414.         return $poll;
  1415.     }
  1416.    
  1417.     /**
  1418.      * Returns post data of specified post
  1419.      * Refers to: inc/functions.php & inc/class_parser.php
  1420.      *
  1421.      * @param integer $post_id Post ID to fetch data from
  1422.      * @param boolean $parsed Shall the Post message be parsed?
  1423.      * @param array $parse_options Array of yes/no options - allow_html,filter_badwords,allow_mycode,allow_smilies,nl2br,me_username
  1424.      * @param array $override_forum_parse_options Whether parse options should be defined by forum or by the script.
  1425.                                                     If they are being overridden, the array will contain the options
  1426.      * @return array|boolean: If unsuccessful, it returns false - Otherwise the Database row
  1427.     */
  1428.     function getPost($post_id, $parsed = false, $override_forum_parse_options = array())
  1429.     {
  1430.         if ($post_id == 0)
  1431.         {
  1432.             $this->_errorAndDie('Specified post ID cannot be 0!');
  1433.         }
  1434.        
  1435.         // Get the Post data
  1436.         $post = get_post($post_id);
  1437.        
  1438.         // Post not found? --> False
  1439.         if (empty($post))
  1440.         {
  1441.             return false;
  1442.         }
  1443.        
  1444.         // Do we have permission?
  1445.         $forumpermissions = forum_permissions($post['fid']);
  1446.         if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  1447.         {
  1448.             // error_no_permission();
  1449.             return false;
  1450.         }
  1451.        
  1452.         // If the post shall not be parsed, we can already return it at this point
  1453.         if ($parsed == false || empty($post))
  1454.         {
  1455.             return $post;
  1456.         }
  1457.        
  1458.         // So we want to parse the message
  1459.        
  1460.         /**
  1461.          * We don't want to override the parse options defined by the forum,
  1462.          * so we have first to get these options defined for the forum
  1463.         */
  1464.         if (count($override_forum_parse_options) == 0)
  1465.         {
  1466.             // Get the Forum data according to the forum id stored with the post
  1467.             $forum = $this->getForum($post['fid']);
  1468.            
  1469.             // Set up the parser options.
  1470.             $parser_options = array(
  1471.                 "allow_html" => $forum['allowhtml'],
  1472.                 "allow_mycode" => $forum['allowmycode'],
  1473.                 "allow_smilies" => $forum['allowsmilies'],
  1474.                 "allow_imgcode" => $forum['allowimgcode'],
  1475.                 "filter_badwords" => 1
  1476.             );
  1477.            
  1478.         }
  1479.         else
  1480.         {
  1481.             // Self-defined options given in the function parameter
  1482.             $parser_options = array(
  1483.                 'allow_html' => (isset($override_forum_parse_options['allow_html']) && $override_forum_parse_options['allow_html'] == 1) ? 1 : 0,
  1484.                 'allow_mycode' => (isset($override_forum_parse_options['allow_mycode']) && $override_forum_parse_options['allow_mycode'] == 1) ? 1 : 0,
  1485.                 'allow_smilies' => (isset($override_forum_parse_options['allow_smilies']) && $override_forum_parse_options['allow_smilies'] == 1) ? 1 : 0,
  1486.                 'allow_imgcode' => (isset($override_forum_parse_options['allow_imgcode']) && $override_forum_parse_options['allow_imgcode'] == 1) ? 1 : 0,
  1487.                 'filter_badwords' => (isset($override_forum_parse_options['filter_badwords']) && $override_forum_parse_options['filter_badwords'] == 1) ? 1 : 0,
  1488.             );
  1489.         }
  1490.        
  1491.         // Overwrite the message with the parsed message
  1492.         $post['message'] = $this->parser->parse_message($post['message'], $parser_options);
  1493.        
  1494.         return $post;
  1495.     }
  1496.    
  1497.     /**
  1498.      * Get posts which match the given criteria
  1499.      *
  1500.      * @param array $params Parameters for the query
  1501.      * @return array
  1502.     */
  1503.     function getPosts($params = array('fields' => '*', 'order_by' => 'dateline', 'order_dir' => 'DESC', 'limit_start' => 0, 'limit' => 0, 'where' => ''))
  1504.     {
  1505.         // We will store the posts in here
  1506.         $posts = array();
  1507.        
  1508.         // No matter what parameters will be given, the query starts with the following
  1509.         $sql = 'SELECT '.$params['fields'].'
  1510.                 FROM '.TABLE_PREFIX.'posts';
  1511.        
  1512.         // Get all posts or just (hopefully) posts which match certain criteria?
  1513.         $sql .= ($params['where'] != '') ? ' WHERE '.$params['where'] : '';
  1514.        
  1515.         // Are the posts going to be ordered by a field?
  1516.         if ($params['order_by'] != '')
  1517.         {
  1518.             $sql .= ' ORDER BY '.$params['order_by'];
  1519.             if ($params['order_dir'] != '')
  1520.             {
  1521.                 $sql .= ' '.$params['order_dir'];
  1522.             }
  1523.             else
  1524.             {
  1525.                 $sql .= ' ASC';
  1526.             }
  1527.         }
  1528.        
  1529.         // Get all posts or (hopefully) just a few?
  1530.         if ($params['limit'] != 0)
  1531.         {
  1532.             $sql .= ' LIMIT ';
  1533.             if (isset($params['limit_start']))
  1534.             {
  1535.                 $sql .= $params['limit_start'].', '.$params['limit'];
  1536.             }
  1537.             else
  1538.             {
  1539.                 $sql .= $params['limit'];
  1540.             }
  1541.         }
  1542.        
  1543.         // Run the query
  1544.         $query = $this->db->query($sql);
  1545.        
  1546.         // Store the returned data in the array we return
  1547.         while ($post = $this->db->fetch_array($query))
  1548.         {
  1549.             $posts[] = $post;
  1550.         }
  1551.        
  1552.         return $posts;
  1553.     }
  1554.    
  1555.     /**
  1556.      * Get the Posts of a particular thread
  1557.      *
  1558.      * @param integer $thread_id
  1559.      * @param string $fields If you want to fetch certain fields, define them as a string here (separated by comma)
  1560.      * @param array $options Options for the query [ array('limit_start', 'limit', 'orderby', 'order_dir') ]
  1561.      * @return array
  1562.     */
  1563.     function getPostsOfThread($thread_id, $fields = '*', $options = array())
  1564.     {
  1565.         // This is what we will be returning
  1566.         $arr = array();
  1567.        
  1568.         $query_thread = $this->db->query('SELECT `fid` FROM '.TABLE_PREFIX.'threads WHERE `tid` = '.intval($thread_id).' LIMIT 1');
  1569.         $thread_forumid = $this->db->fetch_field($query_thread, 'fid');
  1570.        
  1571.         // Do we have permission?
  1572.         $forumpermissions = forum_permissions($thread_forumid);
  1573.         if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  1574.         {
  1575.             // error_no_permission();
  1576.             return false;
  1577.         }
  1578.        
  1579.         // Let's request the posts from the database
  1580.         $query = $this->db->simple_select('posts', $fields, '`tid` = '.intval($thread_id), $options);
  1581.        
  1582.         // All we need to do now is to assign them to our returning array
  1583.         while ($post = $this->db->fetch_array($query))
  1584.         {
  1585.             $arr[] = $post;
  1586.         }
  1587.        
  1588.         return $arr;
  1589.     }
  1590.    
  1591.     /**
  1592.      * Read the messages from database of a user
  1593.      *
  1594.      * @param integer $user_id ID of user
  1595.      * @param array $params Array with options for SQL Query (orderby, sort)
  1596.      * @param boolean $translate_folders If the folders should be turned into readable format ŕ la "inbox"
  1597.      * @return array
  1598.     */
  1599.     function getPrivateMessagesOfUser($user_id, $params = array('orderby' => 'pm.dateline', 'sort' => 'DESC'), $translate_folders = true)
  1600.     {      
  1601.         /**
  1602.          * This is what we will be returning
  1603.          * Structure of the array to return:
  1604.          * array(
  1605.          *    'Inbox' => array( ... Messages ... )
  1606.          * )
  1607.          *
  1608.          * 'Inbox' is the translated folder of folder #1
  1609.         */
  1610.         $arr = array();
  1611.        
  1612.         // If we want to translate the folder names, we need to include the file which contains the translation function
  1613.         if ($translate_folders == true)
  1614.         {
  1615.             include_once MYBB_ROOT.'inc/functions_user.php';
  1616.         }
  1617.        
  1618.         // Run the Query for Private Messages
  1619.         $query = $this->db->query('
  1620.             SELECT pm.*, fu.username AS fromusername, tu.username as tousername
  1621.             FROM '.TABLE_PREFIX.'privatemessages pm
  1622.             LEFT JOIN '.TABLE_PREFIX.'users fu ON (fu.uid=pm.fromid)
  1623.             LEFT JOIN '.TABLE_PREFIX.'users tu ON (tu.uid=pm.toid)
  1624.             WHERE pm.uid = '.intval($user_id).'
  1625.             ORDER BY '.$params['orderby'].' '.$params['sort'].'
  1626.         ');
  1627.        
  1628.         // Do we have messages?
  1629.         if ($this->db->num_rows($query) > 0)
  1630.         {
  1631.             // Uhh, let's iterate the messages!
  1632.             while ($message = $this->db->fetch_array($query))
  1633.             {
  1634.                 // If we translate the folder names, our array index will be the translated folder name
  1635.                 if ($translate_folders == true)
  1636.                 {
  1637.                     $arr[get_pm_folder_name($message['folder'])][] = $message;
  1638.                 }
  1639.                 // If we don't want translated folder names, our array index will be the folder number
  1640.                 else
  1641.                 {
  1642.                     $arr[$message['folder']][] = $message;
  1643.                 }
  1644.             }
  1645.         }
  1646.        
  1647.         return $arr;
  1648.     }
  1649.    
  1650.     /**
  1651.      * Returns data of a specified thread
  1652.      * Refers to: inc/functions.php
  1653.      *
  1654.      * @param integer $thread_id ID of the thread to fetch data from
  1655.      * @return array|boolean If unsuccessful, it returns false - Otherwise the Database row
  1656.     */
  1657.     function getThread($thread_id)
  1658.     {
  1659.         $thread = get_thread($thread_id);
  1660.        
  1661.         // Do we have permission?
  1662.         $forumpermissions = forum_permissions($thread['fid']);
  1663.         if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  1664.         {
  1665.             // error_no_permission();
  1666.             return false;
  1667.         }
  1668.         else
  1669.         {
  1670.             return $thread;
  1671.         }
  1672.     }
  1673.    
  1674.     /**
  1675.      * Get Threads of one or more forums
  1676.      *
  1677.      * @param integer $forum_id IDs of Forums to fetch threads from
  1678.      * @param string $fields If you want to fetch certain fields, define a string with them
  1679.      * @param string $where Additional WHERE constellation if needed
  1680.      * @pararm array $query_params Parameters for the Query to run in the database
  1681.                                    (order_by, order_dir, limit_start, limit [limit will only be acknowledged if both limit vars are defined])
  1682.      * @param boolean $excluse_invisible Shall we get invisible threads too?
  1683.      * @param boolean $join_forums Do we also want to get the forum information of where the threads are located?
  1684.      * @param boolean $join_first_post Shall we get the first post of the thread? (= initial post)
  1685.      * @return array
  1686.     */
  1687.     function getThreads($forum_id, $fields = '*', $where = '', $query_params = array('order_by' => 't.`subject`', 'order_dir' => 'ASC'), $exclude_invisible = true, $join_forums = false, $join_first_post = false)
  1688.     {
  1689.         // Do we have permission?
  1690.         if (!is_array($forum_id))
  1691.         {
  1692.             $forumpermissions = forum_permissions($forum_id);
  1693.             if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  1694.             {
  1695.                 // error_no_permission();
  1696.                 return false;
  1697.             }
  1698.         }
  1699.         else
  1700.         {
  1701.             // Check for every single forum
  1702.             foreach ($forum_id as $forum_id_single)
  1703.             {
  1704.                 $forumpermissions = forum_permissions($forum_id_single);
  1705.                 if ($forumpermissions['canview'] != 1 || $forumpermissions['canviewthreads'] != 1)
  1706.                 {
  1707.                     // error_no_permission();
  1708.                     return false;
  1709.                 }
  1710.             }
  1711.         }
  1712.        
  1713.         // This is what we will be returning
  1714.         $threads = array();
  1715.        
  1716.         // Do we want to get invisible threads as well?
  1717.         $fetch_invisible_threads = ($exclude_invisible == true) ? '1' : '0';
  1718.         $condition = 't.`visible` = '.$fetch_invisible_threads;
  1719.        
  1720.         // Are we fetching threads from multiple forums?
  1721.         if (is_array($forum_id))
  1722.         {
  1723.             $condition .= ' AND t.`fid` IN ('.implode(', ', $forum_id).')';
  1724.         }
  1725.         // Or are we just fetching threads from one forum?
  1726.         else
  1727.         {
  1728.             $condition .= ($forum_id == 0) ? '' : ' AND t.`fid` = '.$forum_id;
  1729.         }
  1730.        
  1731.         // An additional WHERE clause has been added
  1732.         if ($where != '')
  1733.         {
  1734.             $condition .= ' AND '.$where;
  1735.         }
  1736.        
  1737.         // Do we want to get information of the forum where the thread is located in?
  1738.         $forum_join = ($join_forums == true) ? 'INNER JOIN '.TABLE_PREFIX.'forums f ON f.`fid` = t.`fid`' : '';
  1739.        
  1740.         // Do we want to get the first post from the thread?
  1741.         $first_post_join = ($join_first_post == true) ? 'INNER JOIN '.TABLE_PREFIX.'posts p ON p.`pid` = t.`firstpost`' : '';
  1742.        
  1743.         // Is a Limit defined?
  1744.         $limit = (isset($query_params['limit_start']) && isset($query_params['limit'])) ? 'LIMIT '.intval($query_params['limit_start']).', '.intval($query_params['limit']) : '';
  1745.        
  1746.         // Run the Query
  1747.         $query = $this->db->query('
  1748.             SELECT '.$fields.'
  1749.             FROM '.TABLE_PREFIX.'threads t
  1750.             '.$forum_join.'
  1751.             '.$first_post_join.'
  1752.             WHERE '.$condition.'
  1753.             ORDER BY '.$query_params['order_by'].' '.$query_params['order_dir'].'
  1754.             '.$limit.'
  1755.         ');
  1756.        
  1757.         // Iterate through the results and assign it to our returning array
  1758.         while ($thread = $this->db->fetch_array($query))
  1759.         {
  1760.             $threads[] = $thread;
  1761.         }
  1762.        
  1763.         return $threads;
  1764.     }
  1765.    
  1766.     /**
  1767.      * Return array with unread threads of a forum
  1768.      *
  1769.      * @param integer $forum_id
  1770.      * @return array
  1771.     */
  1772.     function getUnreadThreadsOfForum($forum_id)
  1773.     {
  1774.         $threads = $this->getThreads($forum_id);
  1775.         $tids = array();
  1776.         // Thread array keys shall be thread IDs
  1777.         foreach ($threads as $key => $thread)
  1778.         {
  1779.             $tids[] = $thread['tid'];
  1780.             $threads[$thread['tid']] = $thread;
  1781.             unset($threads[$key]);
  1782.         }
  1783.         $tids = implode(',', $tids);
  1784.         $query = $this->db->simple_select("threadsread", "*", "uid='{$this->mybb->user['uid']}' AND tid IN ({$tids})");
  1785.         while ($readthread = $this->db->fetch_array($query))
  1786.         {
  1787.             // Dateline of checking forum is past of last activity - so we delete the entry in array
  1788.             if ($readthread['dateline'] > $threads[$readthread['tid']]['lastpost'])
  1789.             {
  1790.                 unset($threads[$readthread['tid']]);
  1791.             }
  1792.         }
  1793.         return $threads;
  1794.     }
  1795.    
  1796.     /**
  1797.      * Returns data of a user
  1798.      * Refers to: inc/functions.php
  1799.      *
  1800.      * @param integer $user_id ID of User to fetch data from (0 = own user)
  1801.      * @return array
  1802.     */
  1803.     function getUser($user_id = 0)
  1804.     {
  1805.         // If given user id is 0, we use the own User ID
  1806.         if ($user_id == 0)
  1807.         {
  1808.             return get_user($this->mybb->user['uid']);
  1809.         }
  1810.         // Otherwise we fetch info from given User ID
  1811.         else
  1812.         {
  1813.             return get_user($user_id);
  1814.         }
  1815.     }
  1816.    
  1817.     /**
  1818.      * Fetch the users being online
  1819.      * Refers to: index.php
  1820.      *
  1821.      * @param boolean $colored_usernames Define if we want to return formatted usernames (color)
  1822.      * @return array
  1823.     */
  1824.     function getWhoIsOnline($colored_usernames = true)
  1825.     {
  1826.         // This is what we are going to return
  1827.         $arr = array(
  1828.             'bots' => array(),
  1829.             'count_anonymous' => 0,
  1830.             'count_bots' => 0,
  1831.             'count_guests' => 0,
  1832.             'count_members' => 0,
  1833.             'members' => array()
  1834.         );
  1835.        
  1836.         // We only fetch the Who's Online list if the setting tells us that we can
  1837.         if($this->mybb->settings['showwol'] != 0 && $this->mybb->usergroup['canviewonline'] != 0)
  1838.         {
  1839.             // Get the online users.
  1840.             $timesearch = TIME_NOW - $this->mybb->settings['wolcutoff'];
  1841.             $comma = '';
  1842.             $query = $this->db->query("
  1843.                 SELECT s.sid, s.ip, s.uid, s.time, s.location, s.location1, u.username, u.invisible, u.usergroup, u.displaygroup
  1844.                 FROM ".TABLE_PREFIX."sessions s
  1845.                 LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid=u.uid)
  1846.                 WHERE s.time>'$timesearch'
  1847.                 ORDER BY u.username ASC, s.time DESC
  1848.             ");
  1849.            
  1850.             // Iterated users will be stored here to prevent double iterating one user
  1851.             $doneusers = array();
  1852.        
  1853.             // Fetch spiders
  1854.             $spiders = $this->cache->read("spiders");
  1855.        
  1856.             // Loop through all users.
  1857.             while($user = $this->db->fetch_array($query))
  1858.             {              
  1859.                 // Create a key to test if this user is a search bot.
  1860.                 $botkey = my_strtolower(str_replace("bot=", '', $user['sid']));
  1861.        
  1862.                 // Decide what type of user we are dealing with.
  1863.                 if($user['uid'] > 0)
  1864.                 {
  1865.                     // The user is registered.
  1866.                     if($doneusers[$user['uid']] < $user['time'] || !$doneusers[$user['uid']])
  1867.                     {
  1868.                         // If the user is logged in anonymously, update the count for that.
  1869.                         if($user['invisible'] == 1)
  1870.                         {
  1871.                             ++$arr['count_anonymous'];
  1872.                         }
  1873.                        
  1874.                         if($user['invisible'] != 1 || $this->mybb->usergroup['canviewwolinvis'] == 1 || $user['uid'] == $this->mybb->user['uid'])
  1875.                         {      
  1876.                             // Maybe we don't want colored usernames
  1877.                             if ($colored_usernames == true)
  1878.                             {
  1879.                                 // Properly format the username and assign the template.
  1880.                                 $user['username'] = format_name($user['username'], $user['usergroup'], $user['displaygroup']);
  1881.                             }
  1882.  
  1883.                             $user['profilelink'] = build_profile_link($user['username'], $user['uid']);
  1884.                         }
  1885.                        
  1886.                         // This user has been handled.
  1887.                         $doneusers[$user['uid']] = $user['time'];
  1888.                        
  1889.                         // Add the user to the members, since he is registered and logged in
  1890.                         $arr['members'][]= $user;
  1891.                        
  1892.                         // Increase member counter
  1893.                         ++$arr['count_members'];
  1894.                     }
  1895.                 }
  1896.                
  1897.                 // The user is a search bot.
  1898.                 elseif(my_strpos($user['sid'], "bot=") !== false && $spiders[$botkey])
  1899.                 {
  1900.                     ++$arr['count_bots'];
  1901.                     $arr['bots'][] = $spiders[$botkey];
  1902.                 }
  1903.                
  1904.                 // The user is a guest
  1905.                 else
  1906.                 {
  1907.                     ++$arr['count_guests'];
  1908.                 }
  1909.             }
  1910.         }
  1911.        
  1912.         return $arr;
  1913.     }
  1914.    
  1915.     /**
  1916.      * Return members which have posted in a thread
  1917.      *
  1918.      * @param integer $thread_id ID of Thread
  1919.      * @return array|false
  1920.     */
  1921.     function getWhoPosted($thread_id, $sort_by_posts = true)
  1922.     {
  1923.         $thread = $this->getThread($thread_id); // No need to check for permissions, the function already does it
  1924.         $forum = $this->getForum($thread['fid']); // No need to check for permissions, the function already does it
  1925.         if (!$this->checkForumPassword($forum['fid']))
  1926.         {
  1927.             return false;
  1928.         }
  1929.         if($sort_by_posts === true)
  1930.         {
  1931.             $sort_sql = ' ORDER BY posts DESC';
  1932.         }
  1933.         else
  1934.         {
  1935.             $sort_sql = ' ORDER BY p.username ASC';
  1936.         }
  1937.         $query = $this->db->query('
  1938.             SELECT COUNT(p.pid) AS posts, p.username AS postusername, u.uid, u.username, u.usergroup, u.displaygroup
  1939.             FROM '.TABLE_PREFIX.'posts p
  1940.             LEFT JOIN '.TABLE_PREFIX.'users u ON (u.uid=p.uid)
  1941.             WHERE tid='.intval($thread_id).' AND p.visible = 1
  1942.             GROUP BY u.uid
  1943.             '.$sortsql.'
  1944.         ');
  1945.         $i = 0;
  1946.         $arr = array();
  1947.         $arr['total_posts'] = 0;
  1948.         while ($poster = $this->db->fetch_array($query))
  1949.         {
  1950.             if($poster['username'] == '')
  1951.             {
  1952.                 $poster['username'] = $poster['postusername'];
  1953.             }
  1954.             $poster_name = format_name($poster['username'], $poster['usergroup'], $poster['displaygroup']);
  1955.             $arr[$i]['username']= $poster['username'];
  1956.             $arr[$i]['profile_link'] = build_profile_link($poster_name, $poster['uid'], '_blank', $onclick);
  1957.             $arr[$i]['posts'] = $poster['posts'];
  1958.             ++$i;
  1959.             $arr['total_posts'] += $poster['posts'];
  1960.         }
  1961.         return $arr;
  1962.     }
  1963.    
  1964.     /**
  1965.      * Returns users which have voted in a poll
  1966.      *
  1967.      * @param integer $poll_id ID of Poll
  1968.      * @return array
  1969.     */
  1970.     function getWhoVoted($poll_id)
  1971.     {
  1972.         if ($poll_id == 0)
  1973.         {
  1974.             $this->_errorAndDie('Specified post ID cannot be 0!');
  1975.         }
  1976.        
  1977.         $query = $this->db->query('
  1978.             SELECT pv.`vid`, pv.`uid`, pv.`voteoption`, pv.`dateline`,
  1979.                    u.`username`, u.`usergroup`, u.`displaygroup`
  1980.             FROM '.TABLE_PREFIX.'pollvotes pv
  1981.             LEFT JOIN '.TABLE_PREFIX.'users u ON u.`uid` = pv.`uid`
  1982.             WHERE pv.`pid` = '.(int) $poll_id.'
  1983.         ');
  1984.        
  1985.         $arr = array();
  1986.         $i = 0;
  1987.         while ($voter = $this->db->fetch_array($query))
  1988.         {
  1989.             $voter_name = format_name($voter['username'], $voter['usergroup'], $voter['displaygroup']);
  1990.             $arr[$i] = array(
  1991.                 'vid' => $voter['vid'],
  1992.                 'username' => $voter['username'],
  1993.                 'profile_link' => build_profile_link($voter_name, $voter['uid'], '_blank', $onclick),
  1994.                 'voteoption' => $voter['voteoption'],
  1995.                 'dateline' => $voter['dateline']
  1996.             );
  1997.             ++$i;
  1998.         }
  1999.        
  2000.         return $arr;
  2001.     }
  2002.    
  2003.     /**
  2004.      * Increases the Amount of Views of a thread
  2005.      *
  2006.      * @param integer $thread_id ID of Thread
  2007.     */
  2008.     function incViews($thread_id)
  2009.     {
  2010.         // All we do here is to run the increment query
  2011.         $this->db->query('
  2012.             UPDATE '.TABLE_PREFIX.'threads
  2013.             SET `views` = `views` + 1
  2014.             WHERE `tid` = '.intval($thread_id).'
  2015.         ');
  2016.     }
  2017.    
  2018.     /**
  2019.      * Is the user logged in?
  2020.      *
  2021.      * @return boolean
  2022.     */
  2023.     function isLoggedIn()
  2024.     {
  2025.         // If the user is logged in, he has an UID
  2026.         return ($this->mybb->user['uid'] != 0) ? true : false;
  2027.     }
  2028.    
  2029.     /**
  2030.      * Is the user a moderator?
  2031.      * This function checks if the user has certain rights to perform an action in a forum
  2032.      * Refers to: inc/functions.php
  2033.      *
  2034.      * @param integer $forum_id ID of the forum to check permissions for
  2035.      * @param string $action Action which shall be checked for
  2036.      * @param integer $user_id ID of User
  2037.     */
  2038.     function isModerator($forum_id = 0, $action = '', $user_id = 0)
  2039.     {
  2040.         // If we aren't logged in, we cannot possibly a moderator
  2041.         if ($this->isLoggedIn())
  2042.         {
  2043.             return false;
  2044.         }
  2045.        
  2046.         // If given user_id is 0 we tak the user_id of the current user --> Check if own user is mod
  2047.         return is_moderator($forum_id, $action, ($user_id == 0) ? $this->mybb->user['uid'] : $user_id);
  2048.     }
  2049.    
  2050.     /**
  2051.      * Returns if a user has super admin permission
  2052.      * Refers to: inc/functions.php
  2053.      *
  2054.      * @param integer $user_id User-ID
  2055.      * @return boolean
  2056.     */
  2057.     function isSuperAdmin($user_id = 0)
  2058.     {
  2059.         // If specified user_id is 0, we want to know if current user is Super Admin
  2060.         return is_super_admin(($user_id == 0) ? $this->mybb->user['uid'] : $user_id);
  2061.     }
  2062.    
  2063.     /**
  2064.      * Login procedure for a user + password
  2065.      * Possible ToDo: Return error messages / array / whatever
  2066.      *
  2067.      * @param string $username Username
  2068.      * @param string $password Password of User
  2069.      * @return boolean
  2070.     */
  2071.     function login($username, $password, $captcha_hash = '', $captcha_string = '')
  2072.     {
  2073.         $this->lang->load('member');
  2074.        
  2075.         /**
  2076.          * If we are already logged in, we do not have to perform the login procedure
  2077.          * However, we can make believe that the login did succeed
  2078.          * It certainly did a while ago ;)
  2079.         */
  2080.         if ($this->isLoggedIn())
  2081.         {
  2082.             return true;
  2083.         }
  2084.        
  2085.         // by default, login is good!
  2086.         $bad_login = false;
  2087.        
  2088.         /**
  2089.          * Let's see how many logins we have already tried
  2090.         */
  2091.         $logins = login_attempt_check(NON_FATAL);
  2092.        
  2093.         // We need a few functions from the user function collection for the login procedur
  2094.         require_once MYBB_ROOT.'inc/functions_user.php';
  2095.        
  2096.         // If the username does not exist, login fails
  2097.         if (!username_exists($username))
  2098.         {
  2099.             my_setcookie('loginattempts', $logins + 1);
  2100.             return false;
  2101.         }
  2102.        
  2103.         /**
  2104.          * Let's get a database version of the login attempts
  2105.          * Previous login attempt call relied on cookies
  2106.         */
  2107.         $query = $this->db->simple_select("users", "loginattempts", "LOWER(username)='".$this->db->escape_string(my_strtolower($username))."'", array('limit' => 1));
  2108.         $loginattempts = $this->db->fetch_field($query, "loginattempts");
  2109.        
  2110.         // Let's call the handy MyBB validation function and see if we find a user
  2111.         $user = validate_password_from_username($username, $password);
  2112.         if (!$user['uid'])
  2113.         {
  2114.             my_setcookie('loginattempts', $logins + 1);
  2115.             $this->db->write_query("UPDATE ".TABLE_PREFIX."users SET `loginattempts` = `loginattempts` + 1 WHERE LOWER(`username`) = '".$this->db->escape_string(my_strtolower($username))."'");
  2116.             $bad_login = true;
  2117.         }
  2118.        
  2119.         /**
  2120.          * Possible ToDo:
  2121.          * If we have had more than 3 login attemps a captcha is shown in MyBB
  2122.          * Maybe provide the same functionality in MyBBIntegrator ?
  2123.         */
  2124.         if ($loginattempts > 3 || intval($mybb->cookies['loginattempts']) > 3)
  2125.         {
  2126.             // Captcha input is given, let's validate the captcha and see if we can login
  2127.             if (!empty($captcha_hash) && !empty($captcha_string))
  2128.             {
  2129.                 if (!$this->validateCaptcha($captcha_hash, $captcha_string) || $bad_login === true)
  2130.                 {
  2131.                     return $this->generateCaptcha();
  2132.                 }
  2133.             }
  2134.             else
  2135.             {
  2136.                 // Show captcha image for guests if enabled
  2137.                 if ($this->mybb->settings['captchaimage'] == 1 && function_exists("imagepng") && !$this->mybb->user['uid'])
  2138.                 {
  2139.                     return $this->generateCaptcha();
  2140.                 }
  2141.             }
  2142.         }
  2143.         else
  2144.         {
  2145.             if ($bad_login === true)
  2146.             {
  2147.                 return false;
  2148.             }
  2149.         }
  2150.        
  2151.         // COPPA users always fail :D
  2152.         if ($user['coppauser'])
  2153.         {
  2154.             return false;
  2155.         }
  2156.        
  2157.         // Reset both login attempts counter (cookie + database)
  2158.         my_setcookie('loginattempts', 1);
  2159.         $this->db->update_query("users", array("loginattempts" => 1), "uid='{$user['uid']}'");
  2160.        
  2161.         // Delete old session entry
  2162.         $this->db->delete_query("sessions", "ip='".$this->db->escape_string($this->mybb->session->ipaddress)."' AND sid != '".$this->mybb->session->sid."'");
  2163.        
  2164.         // Create a new session and save it in the database
  2165.         $newsession = array(
  2166.             "uid" => $user['uid'],
  2167.         );
  2168.         $this->db->update_query("sessions", $newsession, "sid='".$this->mybb->session->sid."'");
  2169.        
  2170.         // Temporarily set the cookie remember option for the login cookies
  2171.         $this->mybb->user['remember'] = $user['remember'];
  2172.        
  2173.         // Set essential login cookies
  2174.         my_setcookie("mybbuser", $user['uid']."_".$user['loginkey'], null, true);
  2175.         my_setcookie("sid", $this->mybb->session->sid, -1, true);
  2176.        
  2177.         // If there are hooks defined for the end of the login procedure, call them
  2178.         $this->plugins->run_hooks("member_do_login_end");
  2179.        
  2180.         return true;
  2181.     }
  2182.    
  2183.     /**
  2184.      * Logs an administrator action taking any arguments as log data.
  2185.      * Taken from admin/inc/functions.php
  2186.      *
  2187.      * NEEDS MODULE AND ACTION AS PARAMS! DONT FORGET TO PUT THIS INTO DOCUMENTATION
  2188.      */
  2189.     function logAdminAction()
  2190.     {
  2191.         $data = func_get_args();
  2192.  
  2193.         if(count($data) == 1 && is_array($data[0]))
  2194.         {
  2195.             $data = $data[0];
  2196.         }
  2197.    
  2198.         if(!is_array($data))
  2199.         {
  2200.             $data = array($data);
  2201.         }
  2202.    
  2203.         $log_entry = array(
  2204.             "uid" => $this->mybb->user['uid'],
  2205.             "ipaddress" => $this->db->escape_string(get_ip()),
  2206.             "dateline" => TIME_NOW,
  2207.             "module" => $this->db->escape_string($this->mybb->input['module']),
  2208.             "action" => $this->db->escape_string($this->mybb->input['action']),
  2209.             "data" => $this->db->escape_string(@serialize($data))
  2210.         );
  2211.    
  2212.         $this->db->insert_query("adminlog", $log_entry);
  2213.     }
  2214.    
  2215.     /**
  2216.      * Log an action taken by a user with moderator rights
  2217.      *
  2218.      * @param array $data Data array with information necessary to pass onto the log
  2219.      * @param string $action Name of the action
  2220.     */
  2221.     function logModeratorAction($data, $action = '')
  2222.     {
  2223.         // If the fid or tid is not set, set it at 0 so MySQL doesn't choke on it.
  2224.         if($data['fid'] == '')
  2225.         {
  2226.             $fid = 0;
  2227.         }
  2228.         else
  2229.         {
  2230.             $fid = $data['fid'];
  2231.             unset($data['fid']);
  2232.         }
  2233.    
  2234.         if($data['tid'] == '')
  2235.         {
  2236.             $tid = 0;
  2237.         }
  2238.         else
  2239.         {
  2240.             $tid = $data['tid'];
  2241.             unset($data['tid']);
  2242.         }
  2243.    
  2244.         // Any remaining extra data - we serialize and insert in to its own column
  2245.         if(is_array($data))
  2246.         {
  2247.             $data = serialize($data);
  2248.         }
  2249.    
  2250.         $sql_array = array(
  2251.             "uid" => $this->mybb->user['uid'],
  2252.             "dateline" => TIME_NOW,
  2253.             "fid" => $fid,
  2254.             "tid" => $tid,
  2255.             "action" => $this->db->escape_string($action),
  2256.             "data" => $this->db->escape_string($data),
  2257.             "ipaddress" => $this->db->escape_string($this->session->ipaddress)
  2258.         );
  2259.         $this->db->insert_query("moderatorlog", $sql_array);
  2260.     }
  2261.    
  2262.     /**
  2263.      * Logout procedure
  2264.      *
  2265.      * @return boolean
  2266.     */
  2267.     function logout()
  2268.     {
  2269.         // If the user is not logged in at all, we make him believe that the logout procedure workedjust fine
  2270.         if (!$this->isLoggedIn())
  2271.         {
  2272.             return true;
  2273.         }
  2274.  
  2275.         // Check session ID if we have one
  2276.         if($this->mybb->input['sid'] && $this->mybb->input['sid'] != $this->mybb->session->sid)
  2277.         {
  2278.             return false;
  2279.         }
  2280.         // Otherwise, check logoutkey
  2281.         else if (!$this->mybb->input['sid'] && $this->mybb->input['logoutkey'] != $this->mybb->user['logoutkey'])
  2282.         {
  2283.             return false;
  2284.         }
  2285.        
  2286.         // Clear essential login cookies
  2287.         my_unsetcookie("mybbuser");
  2288.         my_unsetcookie("sid");
  2289.        
  2290.         // The logged in user data will be updated
  2291.         if($this->mybb->user['uid'])
  2292.         {
  2293.             $time = TIME_NOW;
  2294.             $lastvisit = array(
  2295.                 "lastactive" => $time-900,
  2296.                 "lastvisit" => $time,
  2297.             );
  2298.             $this->db->update_query("users", $lastvisit, "uid='".$this->mybb->user['uid']."'");
  2299.             $this->db->delete_query("sessions", "sid='".$this->mybb->session->sid."'");
  2300.         }
  2301.        
  2302.         // If there are any hooks to run, we call them here
  2303.         $this->plugins->run_hooks("member_logout_end");
  2304.        
  2305.         return true;
  2306.     }
  2307.    
  2308.     /**
  2309.      * Marks one or more forums read
  2310.      *
  2311.      * @param integer $forum_id If Forum ID is set to 0 all forums will be marked as read
  2312.      * @param string $redirect_url If there should be a redirection afterwards, define the URL here
  2313.      * @return boolean Only returns false if it fails, otherwise, if it does not redirect, it returns true
  2314.     */
  2315.     function markRead($id = 0, $redirect_url = '')
  2316.     {
  2317.         // "Mark-Read" functions are located in inc/functions_indicators.php
  2318.         require_once MYBB_ROOT."/inc/functions_indicators.php";
  2319.        
  2320.         // Make sure the ID is a number
  2321.         $id = intval($id);
  2322.        
  2323.         // If the given Forum ID is 0, it tells us that we shall mark all forums as read
  2324.         if ($id == 0)
  2325.         {
  2326.             mark_all_forums_read();
  2327.            
  2328.             // If we want to redirect to an url, we do so
  2329.             if ($redirect_url != '')
  2330.             {
  2331.                 redirect($redirect_url, $this->lang->redirect_markforumsread);
  2332.             }
  2333.         }
  2334.        
  2335.         // If a specific ID has been defined, we certainly want to mark ONE forum as read
  2336.         else
  2337.         {
  2338.             // Does the Forum exist?
  2339.             $validforum = $this->getForum($id);
  2340.            
  2341.             // If the forum is invalid, marking as read failed
  2342.             if (!$validforum)
  2343.             {
  2344.                 return false;
  2345.             }
  2346.            
  2347.             // If we want to redirect to an url, we do so
  2348.             if ($redirect_url != '')
  2349.             {
  2350.                 redirect($redirect_url, $this->lang->redirect_markforumsread);
  2351.             }
  2352.         }
  2353.        
  2354.         return true;
  2355.     }
  2356.    
  2357.     /**
  2358.      * Constructor
  2359.      * If we include the global.php of MyBB in the constructor,
  2360.      * weird error messages popup
  2361.      * --> This sounds like a ToDo: Find out why?????? - My guess: Some evil eval() functions
  2362.      *
  2363.      * @param object $mybb Pass the Super MyBB Object as a reference so we can work with it
  2364.      * @param object $db Pass the MyBB Database Handler as a reference so we can work with is
  2365.     */
  2366.     function MyBBIntegrator(&$mybb, &$db, &$cache, &$plugins, &$lang, &$config)
  2367.     {
  2368.         $this->mybb =& $mybb;
  2369.         $this->db =& $db;
  2370.         $this->cache = $cache;
  2371.         $this->plugins =& $plugins;
  2372.         $this->lang =& $lang;
  2373.         $this->config =& $config;
  2374.        
  2375.         define('MYBB_ADMIN_DIR', MYBB_ROOT.$this->config['admin_dir'].'/');
  2376.        
  2377.         // Some Constants for non-magic-numbers
  2378.         define('NON_FATAL', false);
  2379.        
  2380.         require_once MYBB_ROOT.'inc/class_parser.php';
  2381.         $this->parser = new postParser;
  2382.     }
  2383.    
  2384.     /**
  2385.      * This function creates a class object if it is necessary
  2386.      * This is needed, if we want to use classes, which are not included in the init routine of mybb (example: Moderation)
  2387.      *
  2388.      * @param string $object Name of the class object
  2389.      * @param string $class_name Name of the Class
  2390.      * @param string $include_path The Path where we can find the class
  2391.     */
  2392.     function MyBBIntegratorClassObject($object, $class_name, $include_path)
  2393.     {
  2394.         if (isset($this->{$object}))
  2395.         {
  2396.             return;
  2397.         }
  2398.         else
  2399.         {
  2400.             require_once $include_path;
  2401.             $this->{$object} = new $class_name;
  2402.         }
  2403.     }
  2404.    
  2405.     /**
  2406.      * Enables you to close one or more threads
  2407.      * One thread: $thread_id is int
  2408.      * More threads: $thread_id is array with ints
  2409.      *
  2410.      * @param integer|array $thread_id See above
  2411.      * @param integer $forum_id This can be filled for a nice moderator log!
  2412.      * @return boolean
  2413.     */
  2414.     function openThread($thread_id, $forum_id = 0)
  2415.     {
  2416.         if (!is_moderator($fid, "canopenclosethreads"))
  2417.         {
  2418.             return false;
  2419.         }
  2420.        
  2421.         $this->lang->load('moderation');
  2422.        
  2423.         $this->MyBBIntegratorClassObject('moderation', 'Moderation', MYBB_ROOT.'/inc/class_moderation.php');
  2424.        
  2425.         $this->moderation->open_threads($thread_id);
  2426.        
  2427.         $modlogdata['fid'] = $forum_id;
  2428.        
  2429.         $this->logModeratorAction($modlogdata, $this->lang->mod_process);
  2430.        
  2431.         return true;
  2432.     }
  2433.    
  2434.     /**
  2435.      * Parses a string/message with the MyBB Parser Class
  2436.      * Refers to: /inc/class_parser.php
  2437.      *
  2438.      * @param string $message The String which shall be parsed
  2439.      * @param array $options Options the parser can accept: filter_badwords, allow_html, allow_mycode, me_username, allow_smilies, nl2br,
  2440.      * @return string Parsed string
  2441.     */
  2442.     function parseString($message, $options = array())
  2443.     {
  2444.         // Set base URL for parsing smilies
  2445.         $base_url= $this->mybb->settings['bburl'];
  2446.  
  2447.         if($base_url!= "")
  2448.         {
  2449.             if(my_substr($base_url, my_strlen($base_url) -1) != "/")
  2450.             {
  2451.                 $base_url= $base_url."/";
  2452.             }
  2453.         }
  2454.  
  2455.         $message = $this->plugins->run_hooks("parse_message_start", $message);
  2456.  
  2457.         // Get rid of cartridge returns for they are the workings of the devil
  2458.         $message = str_replace("\r", "", $message);
  2459.  
  2460.         // Filter bad words if requested.
  2461.         if($options['filter_badwords'])
  2462.         {
  2463.             $message = $this->parser->parse_badwords($message);
  2464.         }
  2465.  
  2466.         if($options['allow_html'] != 1)
  2467.         {
  2468.             $message = $this->parser->parse_html($message);
  2469.         }
  2470.         else
  2471.         {      
  2472.             while(preg_match("#<script(.*)>(.*)</script(.*)>#is", $message))
  2473.             {
  2474.                 $message = preg_replace("#<script(.*)>(.*)</script(.*)>#is", "&lt;script$1&gt;$2&lt;/script$3&gt;", $message);
  2475.             }
  2476.             // Remove these completely
  2477.             $message = preg_replace("#\s*<base[^>]*>\s*#is", "", $message);
  2478.             $message = preg_replace("#\s*<meta[^>]*>\s*#is", "", $message);
  2479.             $message = str_replace(array('<?php', '<!--', '-->', '?>', "<br />\n", "<br>\n"), array('&lt;?php', '&lt;!--', '--&gt;', '?&gt;', "\n", "\n"), $message);
  2480.         }
  2481.        
  2482.         // If MyCode needs to be replaced, first filter out [code] and [php] tags.
  2483.         if($options['allow_mycode'])
  2484.         {
  2485.             // First we split up the contents of code and php tags to ensure they're not parsed.
  2486.             preg_match_all("#\[(code|php)\](.*?)\[/\\1\](\r\n?|\n?)#si", $message, $code_matches, PREG_SET_ORDER);
  2487.             $message = preg_replace("#\[(code|php)\](.*?)\[/\\1\](\r\n?|\n?)#si", "<mybb-code>\n", $message);
  2488.         }
  2489.  
  2490.         // Always fix bad Javascript in the message.
  2491.         $message = $this->parser->fix_javascript($message);
  2492.        
  2493.         // Replace "me" code and slaps if we have a username
  2494.         if($options['me_username'])
  2495.         {          
  2496.             $message = preg_replace('#(>|^|\r|\n)/me ([^\r\n<]*)#i', "\\1<span style=\"color: red;\">* {$options['me_username']} \\2</span>", $message);
  2497.             $message = preg_replace('#(>|^|\r|\n)/slap ([^\r\n<]*)#i', "\\1<span style=\"color: red;\">* {$options['me_username']} {$this->lang->slaps} \\2 {$this->lang->with_trout}</span>", $message);
  2498.         }
  2499.        
  2500.         // If we can, parse smilies
  2501.         if($options['allow_smilies'])
  2502.         {
  2503.             $message = $this->parser->parse_smilies($message, $options['allow_html']);
  2504.         }
  2505.  
  2506.         // Replace MyCode if requested.
  2507.         if($options['allow_mycode'])
  2508.         {
  2509.             $message = $this->parser->parse_mycode($message, $options);
  2510.         }
  2511.  
  2512.         // Run plugin hooks
  2513.         $message = $this->plugins->run_hooks("parse_message", $message);
  2514.        
  2515.         if($options['allow_mycode'])
  2516.         {
  2517.             // Now that we're done, if we split up any code tags, parse them and glue it all back together
  2518.             if(count($code_matches) > 0)
  2519.             {
  2520.                 foreach($code_matches as $text)
  2521.                 {
  2522.                     // Fix up HTML inside the code tags so it is clean
  2523.                     if($options['allow_html'] != 0)
  2524.                     {
  2525.                         $text[2] = $this->parser->parse_html($text[2]);
  2526.                     }
  2527.                    
  2528.                     if(my_strtolower($text[1]) == "code")
  2529.                     {
  2530.                         $code = $this->parser->mycode_parse_code($text[2]);
  2531.                     }
  2532.                     elseif(my_strtolower($text[1]) == "php")
  2533.                     {
  2534.                         $code = $this->parser->mycode_parse_php($text[2]);
  2535.                     }
  2536.                     $message = preg_replace("#\<mybb-code>\n?#", $code, $message, 1);
  2537.                 }
  2538.             }
  2539.         }
  2540.  
  2541.         if($options['nl2br'] !== 0)
  2542.         {
  2543.             $message = nl2br($message);
  2544.             // Fix up new lines and block level elements
  2545.             $message = preg_replace("#(</?(?:html|head|body|div|p|form|table|thead|tbody|tfoot|tr|td|th|ul|ol|li|div|p|blockquote|cite|hr)[^>]*>)\s*<br />#i", "$1", $message);
  2546.             $message = preg_replace("#(&nbsp;)+(</?(?:html|head|body|div|p|form|table|thead|tbody|tfoot|tr|td|th|ul|ol|li|div|p|blockquote|cite|hr)[^>]*>)#i", "$2", $message);
  2547.         }
  2548.  
  2549.         $message = my_wordwrap($message);
  2550.    
  2551.         $message = $this->plugins->run_hooks("parse_message_end", $message);
  2552.                
  2553.         return $message;
  2554.     }
  2555.    
  2556.     /**
  2557.      * Register procedure
  2558.      * Refers to: /member.php
  2559.      *
  2560.      * @param array $info Contains user information of the User to be registered
  2561.      * @return array|string If registration fails, we return an array containing the error message,
  2562.      *                      If registration is successful, we return the string, which notifies the user of what will be the next action
  2563.     */
  2564.     function register($info = array())
  2565.     {
  2566.         // Load the language phrases we need for the registration
  2567.         $this->lang->load('member');
  2568.        
  2569.         /**
  2570.          * $info contains the given user information for the registration
  2571.          * We need to make sure that every possible key is given, so we do not generate ugly E_NOIICE errors
  2572.         */
  2573.         $possible_info_keys = array(
  2574.             'username', 'password', 'password2', 'email', 'email2', 'referrer', 'timezone', 'language',
  2575.             'profile_fields', 'allownotices', 'hideemail', 'subscriptionmethod',
  2576.             'receivepms', 'pmnotice', 'emailpmnotify', 'invisible', 'dstcorrection'
  2577.         );
  2578.        
  2579.         // Iterate the possible info keys to create the array entry in $info if it does not exist
  2580.         foreach ($possible_info_keys as $possible_info_key)
  2581.         {
  2582.             if (!isset($info[$possible_info_key]))
  2583.             {
  2584.                 $info[$possible_info_key] = '';
  2585.             }
  2586.         }
  2587.        
  2588.         // Run whatever hook specified at the beginning of the registration    
  2589.         $this->plugins->run_hooks('member_do_register_start');
  2590.        
  2591.         // If register type is random password, we generate one
  2592.         if($this->mybb->settings['regtype'] == "randompass")
  2593.         {
  2594.             $info['password'] = random_str();
  2595.             $info['password2'] = $info['password'];
  2596.         }
  2597.        
  2598.         if($this->mybb->settings['regtype'] == "verify" || $this->mybb->settings['regtype'] == "admin" || $info['coppa'] == 1)
  2599.         {
  2600.             $usergroup = 5;
  2601.         }
  2602.         else
  2603.         {
  2604.             $usergroup = 2;
  2605.         }
  2606.        
  2607.         // Set up user handler.
  2608.         require_once MYBB_ROOT."inc/datahandlers/user.php";
  2609.         $userhandler = new UserDataHandler("insert");
  2610.        
  2611.         // Set the data for the new user.
  2612.         $user = array(
  2613.             "username" => $info['username'],
  2614.             "password" => $info['password'],
  2615.             "password2" => $info['password2'],
  2616.             "email" => $info['email'],
  2617.             "email2" => $info['email2'],
  2618.             "usergroup" => $usergroup,
  2619.             "referrer" => $info['referrername'],
  2620.             "timezone" => $info['timezone'],
  2621.             "language" => $info['language'],
  2622.             "profile_fields" => $info['profile_fields'],
  2623.             "regip" => $this->mybb->session->ipaddress,
  2624.             "longregip" => ip2long($this->mybb->session->ipaddress),
  2625.             "coppa_user" => intval($this->mybb->cookies['coppauser']),
  2626.         );
  2627.        
  2628.         if(isset($info['regcheck1']) && isset($info['regcheck2']))
  2629.         {
  2630.             $user['regcheck1'] = $info['regcheck1'];
  2631.             $user['regcheck2'] = $info['regcheck2'];
  2632.         }
  2633.        
  2634.         // Do we have a saved COPPA DOB?
  2635.         if($this->mybb->cookies['coppadob'])
  2636.         {
  2637.             list($dob_day, $dob_month, $dob_year) = explode("-", $this->mybb->cookies['coppadob']);
  2638.             $user['birthday'] = array(
  2639.                 "day" => $dob_day,
  2640.                 "month" => $dob_month,
  2641.                 "year" => $dob_year
  2642.             );
  2643.         }
  2644.        
  2645.         // Generate the options array of the user
  2646.         $user['options'] = array(
  2647.             "allownotices" => $info['allownotices'],
  2648.             "hideemail" => $info['hideemail'],
  2649.             "subscriptionmethod" => $info['subscriptionmethod'],
  2650.             "receivepms" => $info['receivepms'],
  2651.             "pmnotice" => $info['pmnotice'],
  2652.             "emailpmnotify" => $info['emailpmnotify'],
  2653.             "invisible" => $info['invisible'],
  2654.             "dstcorrection" => $info['dstcorrection']
  2655.         );
  2656.        
  2657.         // Assign data to the data handler
  2658.         $userhandler->set_data($user);
  2659.        
  2660.         // If the validation of the user failed, we return nice (friendly) errors
  2661.         if(!$userhandler->validate_user())
  2662.         {
  2663.             $errors = $userhandler->get_friendly_errors();
  2664.             return $errors;
  2665.         }
  2666.        
  2667.         // Create the User in the database
  2668.         $user_info = $userhandler->insert_user();
  2669.        
  2670.         // We need to set a cookie, if we don't want a random password (and it is no COPPA user), so he is instantly logged in
  2671.         if($this->mybb->settings['regtype'] != "randompass" && !$this->mybb->cookies['coppauser'])
  2672.         {
  2673.             // Log them in
  2674.             my_setcookie("mybbuser", $user_info['uid']."_".$user_info['loginkey'], null, true);
  2675.         }
  2676.        
  2677.         /**
  2678.          * Coppa User
  2679.          * Nothing special, just return that the coppa user will be redirected
  2680.         */
  2681.         if($this->mybb->cookies['coppauser'])
  2682.         {
  2683.             $this->lang->redirect_registered_coppa_activate = $this->lang->sprintf($this->lang->redirect_registered_coppa_activate, $this->mybb->settings['bbname'], $user_info['username']);
  2684.             my_unsetcookie("coppauser");
  2685.             my_unsetcookie("coppadob");
  2686.            
  2687.             // Run whatever hook is defined at the end of a registration
  2688.             $this->plugins->run_hooks("member_do_register_end");
  2689.            
  2690.             return $this->lang->redirect_registered_coppa_activate;
  2691.         }
  2692.        
  2693.         /**
  2694.          * Register Mode: Email Verification
  2695.          * A mail is dispatched containing an activation link.
  2696.          * The activation link is a reference to the newly created database entry
  2697.         */
  2698.         else if($this->mybb->settings['regtype'] == "verify")
  2699.         {
  2700.             // Generate and save the activation code in the database
  2701.             $activationcode = random_str();
  2702.             $now = TIME_NOW;
  2703.             $activationarray = array(
  2704.                 "uid" => $user_info['uid'],
  2705.                 "dateline" => TIME_NOW,
  2706.                 "code" => $activationcode,
  2707.                 "type" => "r"
  2708.             );
  2709.             $this->db->insert_query("awaitingactivation", $activationarray);
  2710.            
  2711.             // Generate and send the email
  2712.             $emailsubject = $this->lang->sprintf($this->lang->emailsubject_activateaccount, $this->mybb->settings['bbname']);
  2713.             $emailmessage = $this->lang->sprintf($this->lang->email_activateaccount, $user_info['username'], $this->mybb->settings['bbname'], $this->mybb->settings['bburl'], $user_info['uid'], $activationcode);
  2714.             my_mail($user_info['email'], $emailsubject, $emailmessage);
  2715.            
  2716.             // Build the message to return
  2717.             $this->lang->redirect_registered_activation = $this->lang->sprintf($this->lang->redirect_registered_activation, $this->mybb->settings['bbname'], $user_info['username']);
  2718.            
  2719.             // Run whatever hook is defined at the end of a registration
  2720.             $this->plugins->run_hooks("member_do_register_end");
  2721.            
  2722.             return $this->lang->redirect_registered_activation;
  2723.         }
  2724.        
  2725.         /**
  2726.          * Register Mode: Send Random Password
  2727.          * A mail is dispatched, containing the random password for the user
  2728.         */
  2729.         else if($this->mybb->settings['regtype'] == "randompass")
  2730.         {
  2731.             // Generate and send the email
  2732.             $emailsubject = $this->lang->sprintf($this->lang->emailsubject_randompassword, $this->mybb->settings['bbname']);
  2733.             $emailmessage = $this->lang->sprintf($this->lang->email_randompassword, $user['username'], $this->mybb->settings['bbname'], $user_info['username'], $user_info['password']);
  2734.             my_mail($user_info['email'], $emailsubject, $emailmessage);
  2735.            
  2736.             // Run whatever hook is defined at the end of a registration
  2737.             $this->plugins->run_hooks("member_do_register_end");
  2738.            
  2739.             return $this->lang->redirect_registered_passwordsent;
  2740.         }
  2741.        
  2742.         /**
  2743.          * Register Mode: Admin Activation
  2744.          * Return the message that the user will need to be authorized by an admin
  2745.         */
  2746.         else if($this->mybb->settings['regtype'] == "admin")
  2747.         {
  2748.             // Build the message to return
  2749.             $this->lang->redirect_registered_admin_activate = $this->lang->sprintf($this->lang->redirect_registered_admin_activate, $this->mybb->settings['bbname'], $user_info['username']);
  2750.            
  2751.             // Run whatever hook is defined at the end of a registration
  2752.             $this->plugins->run_hooks("member_do_register_end");
  2753.            
  2754.             return $this->lang->redirect_registered_admin_activate;
  2755.         }
  2756.        
  2757.         /**
  2758.          * No activation required whatsoever,
  2759.          * directly registered
  2760.         */
  2761.         else
  2762.         {
  2763.             // Build the message to return
  2764.             $this->lang->redirect_registered = $this->lang->sprintf($this->lang->redirect_registered, $this->mybb->settings['bbname'], $user_info['username']);
  2765.            
  2766.             // Run whatever hook is defined at the end of a registration
  2767.             $this->plugins->run_hooks('member_do_register_end');
  2768.            
  2769.             return $this->lang->redirect_registered;
  2770.         }
  2771.     }
  2772.    
  2773.     /**
  2774.      * Will remove a Forum/Category and everything related to it
  2775.      * Taken from admin/modules/forum/management.php
  2776.      *
  2777.      * @param integer $forum_id ID of Forum/Category
  2778.      * @return boolean
  2779.     */
  2780.     function removeForumOrCategory($forum_id)
  2781.     {
  2782.         $this->plugins->run_hooks("admin_forum_management_delete");
  2783.        
  2784.         $query = $this->db->simple_select("forums", "*", "fid='{$forum_id}'");
  2785.         $forum = $this->db->fetch_array($query);
  2786.        
  2787.         // Does the forum not exist?
  2788.         if (!$forum['fid'])
  2789.         {
  2790.             return false;
  2791.         }
  2792.        
  2793.         $fid = intval($forum_id);
  2794.         $forum_info = $this->getForum($fid);
  2795.        
  2796.         // Delete the forum
  2797.         $this->db->delete_query("forums", "fid='$fid'");
  2798.         switch ($this->db->type)
  2799.         {
  2800.             case "pgsql":
  2801.             case "sqlite3":
  2802.             case "sqlite2":
  2803.                 $query = $this->db->simple_select("forums", "*", "','|| parentlist|| ',' LIKE '%,$fid,%'");
  2804.                 break;
  2805.             default:
  2806.                 $query = $this->db->simple_select("forums", "*", "CONCAT(',', parentlist, ',') LIKE '%,$fid,%'");
  2807.         }      
  2808.         while ($forum = $this->db->fetch_array($query))
  2809.         {
  2810.             $fids[$forum['fid']] = $fid;
  2811.             $delquery .= " OR fid='{$forum['fid']}'";
  2812.         }
  2813.  
  2814.         /**
  2815.          * This slab of code pulls out the moderators for this forum,
  2816.          * checks if they moderate any other forums, and if they don't
  2817.          * it moves them back to the registered usergroup
  2818.          */
  2819.  
  2820.         $query = $this->db->simple_select("moderators", "*", "fid='$fid'");
  2821.         while ($mod = $this->db->fetch_array($query))
  2822.         {
  2823.             $moderators[$mod['uid']] = $mod['uid'];
  2824.         }
  2825.        
  2826.         if (is_array($moderators))
  2827.         {
  2828.             $mod_list = implode(",", $moderators);
  2829.             $query = $this->db->simple_select("moderators", "*", "fid != '$fid' AND uid IN ($mod_list)");
  2830.             while ($mod = $this->db->fetch_array($query))
  2831.             {
  2832.                 unset($moderators[$mod['uid']]);
  2833.             }
  2834.         }
  2835.        
  2836.         if (is_array($moderators))
  2837.         {
  2838.             $mod_list = implode(",", $moderators);
  2839.             if($mod_list)
  2840.             {
  2841.                 $updatequery = array(
  2842.                     "usergroup" => "2"
  2843.                 );
  2844.                 $this->db->update_query("users", $updatequery, "uid IN ($mod_list) AND usergroup='6'");
  2845.             }
  2846.         }
  2847.        
  2848.         switch($this->db->type)
  2849.         {
  2850.             case "pgsql":
  2851.             case "sqlite3":
  2852.             case "sqlite2":
  2853.                 $this->db->delete_query("forums", "','||parentlist||',' LIKE '%,$fid,%'");
  2854.                 break;
  2855.             default:
  2856.                 $this->db->delete_query("forums", "CONCAT(',',parentlist,',') LIKE '%,$fid,%'");
  2857.         }
  2858.        
  2859.         $this->db->delete_query("threads", "fid='{$fid}' {$delquery}");
  2860.         $this->db->delete_query("posts", "fid='{$fid}' {$delquery}");
  2861.         $this->db->delete_query("moderators", "fid='{$fid}' {$delquery}");
  2862.         $this->db->delete_query("forumsubscriptions", "fid='{$fid}' {$delquery}");
  2863.  
  2864.         $this->cache->update_forums();
  2865.         $this->cache->update_moderators();
  2866.         $this->cache->update_forumpermissions();
  2867.        
  2868.         // Log admin action - Need to add 2 params in input array so logging contains correct info
  2869.         $this->mybb->input['module'] = 'forum/management';
  2870.         $this->mybb->input['action'] = 'delete';
  2871.         $this->logAdminAction($forum_info['fid'], $forum_info['name']);
  2872.        
  2873.         $this->plugins->run_hooks("admin_forum_management_delete_commit");
  2874.        
  2875.         return true;
  2876.     }
  2877.    
  2878.     /**
  2879.      * Delete a post
  2880.      *
  2881.      * @param integer $post_id ID of Post
  2882.      * @return ?
  2883.     */
  2884.     function removePost($post_id)
  2885.     {
  2886.         require_once MYBB_ROOT."inc/functions_post.php";
  2887.         require_once MYBB_ROOT."inc/functions_upload.php";
  2888.        
  2889.         $this->lang->load('editpost');
  2890.  
  2891.         $post = $this->getPost($post_id);
  2892.        
  2893.         $tid = $post['tid'];
  2894.         $fid = $post['fid'];
  2895.         $pid = $post['pid'];
  2896.        
  2897.         $forumpermissions = forum_permissions($fid);
  2898.        
  2899.         $this->plugins->run_hooks("editpost_deletepost");
  2900.        
  2901.         $query = $this->db->simple_select("posts", "pid", "tid='{$tid}'", array("limit" => 1, "order_by" => "dateline", "order_dir" => "asc"));
  2902.         $firstcheck = $this->db->fetch_array($query);
  2903.         if ($firstcheck['pid'] == $pid)
  2904.         {
  2905.             $firstpost = 1;
  2906.         }
  2907.         else
  2908.         {
  2909.             $firstpost = 0;
  2910.         }
  2911.        
  2912.         $modlogdata['fid'] = $fid;
  2913.         $modlogdata['tid'] = $tid;
  2914.        
  2915.         if ($firstpost)
  2916.         {
  2917.             if ($forumpermissions['candeletethreads'] == 1 || is_moderator($fid, "candeleteposts"))
  2918.             {
  2919.                 delete_thread($tid);
  2920.                 mark_reports($tid, "thread");
  2921.                 $this->logModeratorAction($modlogdata, $this->lang->thread_deleted);
  2922.                 return true;
  2923.             }
  2924.             else
  2925.             {
  2926.                 return false;
  2927.             }
  2928.         }
  2929.         else
  2930.         {
  2931.             if ($forumpermissions['candeleteposts'] == 1 || is_moderator($fid, "candeleteposts"))
  2932.             {
  2933.                 // Select the first post before this
  2934.                 delete_post($pid, $tid);
  2935.                 mark_reports($pid, "post");
  2936.                 $this->logModeratorAction($modlogdata, $this->lang->post_deleted);
  2937.                 $query = $this->db->simple_select("posts", "pid", "tid='{$tid}' AND dateline <= '{$post['dateline']}'", array("limit" => 1, "order_by" => "dateline", "order_dir" => "desc"));
  2938.                 $next_post = $this->db->fetch_array($query);
  2939.                 return true;
  2940.             }
  2941.             else
  2942.             {
  2943.                 return false;
  2944.             }
  2945.         }
  2946.     }
  2947.  
  2948.     /**
  2949.      * Delete a user in the database
  2950.      *
  2951.      * @param integer $thread Thread ID
  2952.      * @return boolean
  2953.     */
  2954.     function removeThread($thread)
  2955.     {
  2956.         $tid = intval($thread);
  2957.  
  2958.         $this->lang->load('editpost');
  2959.  
  2960.         $deleted = delete_thread($tid);
  2961.         mark_reports($tid, "thread");
  2962.  
  2963.         $modlogdata['tid'] = $tid;
  2964.         $this->logModeratorAction($modlogdata, $this->lang->thread_deleted);
  2965.  
  2966.         return $deleted;
  2967.     }
  2968.  
  2969.     /**
  2970.      * Delete a user in the database
  2971.      *
  2972.      * @param integer|string $user User ID or username
  2973.      * @return boolean
  2974.     */
  2975.     function removeUser($user)
  2976.     {
  2977.         // If no ID is given, we check if there is a user with the specified username
  2978.         if (!is_numeric($user))
  2979.         {
  2980.             $query = $this->db->simple_select('users', 'uid', 'username=\''.$this->dbEscape($user).'\'');
  2981.             $user_id = $this->db->fetch_field($query, 'uid', 0);
  2982.            
  2983.             // User does not exist? --> False
  2984.             if (empty($user_id))
  2985.             {
  2986.                 return false;
  2987.             }
  2988.            
  2989.             $user_id = intval($user_id);
  2990.         }
  2991.         else
  2992.         {      
  2993.             $user_id = intval($user);
  2994.         }
  2995.        
  2996.         $this->plugins->run_hooks('admin_user_users_delete');
  2997.        
  2998.         // Delete the user
  2999.         $this->db->update_query("posts", array('uid' => 0), "uid='{$user_id}'");
  3000.         $this->db->delete_query("userfields", "ufid='{$user_id}'");
  3001.         $this->db->delete_query("privatemessages", "uid='{$user_id}'");
  3002.         $this->db->delete_query("events", "uid='{$user_id}'");
  3003.         $this->db->delete_query("moderators", "uid='{$user_id}'");
  3004.         $this->db->delete_query("forumsubscriptions", "uid='{$user_id}'");
  3005.         $this->db->delete_query("threadsubscriptions", "uid='{$user_id}'");
  3006.         $this->db->delete_query("sessions", "uid='{$user_id}'");
  3007.         $this->db->delete_query("banned", "uid='{$user_id}'");
  3008.         $this->db->delete_query("threadratings", "uid='{$user_id}'");
  3009.         $this->db->delete_query("users", "uid='{$user_id}'");
  3010.         $this->db->delete_query("joinrequests", "uid='{$user_id}'");
  3011.         $this->db->delete_query("warnings", "uid='{$user_id}'");
  3012.  
  3013.         // Update forum stats
  3014.         update_stats(array('numusers' => '-1'));
  3015.        
  3016.         $this->plugins->run_hooks('admin_user_users_delete_commit');
  3017.        
  3018.         return true;
  3019.     }
  3020.    
  3021.     /**
  3022.      * Send a private message from someone to someone
  3023.     */
  3024.     function sendPrivateMessage($data = array())
  3025.     {
  3026.         // Let's do default values and check if all required data keys are passed
  3027.         $default_data = array(
  3028.             'fromid' => 0,
  3029.             'subject' => '',
  3030.             'message' => '',
  3031.             'icon' => 0,
  3032.             'to_username' => ''
  3033.         );
  3034.        
  3035.         // Set default values if they are missing!
  3036.         foreach ($default_data as $default_data_key => $default_data_val)
  3037.         {
  3038.             if (!isset($data[$default_data_key]))
  3039.             {
  3040.                 $data[$default_data_key] = $default_data_val;
  3041.             }
  3042.         }
  3043.        
  3044.         $this->lang->load('private');
  3045.        
  3046.         $this->plugins->run_hooks('private_send_do_send');
  3047.        
  3048.         // Attempt to see if this PM is a duplicate or not
  3049.         $time_cutoff = TIME_NOW - (5 * 60 * 60);
  3050.         $query = $this->db->query("
  3051.             SELECT pm.pmid
  3052.             FROM ".TABLE_PREFIX."privatemessages pm
  3053.             LEFT JOIN ".TABLE_PREFIX."users u ON(u.uid=pm.toid)
  3054.             WHERE u.username='".$this->db->escape_string($data['to_uername'])."' AND pm.dateline > {$time_cutoff} AND pm.fromid='{".$data['fromid']."}' AND pm.subject='".$this->db->escape_string($data['subject'])."' AND pm.message='".$this->db->escape_string($data['message'])."' AND pm.folder!='3'
  3055.         ");
  3056.         $duplicate_check = $this->db->fetch_field($query, "pmid");
  3057.         if ($duplicate_check)
  3058.         {
  3059.             return $this->lang->error_pm_already_submitted;
  3060.         }
  3061.        
  3062.         require_once MYBB_ROOT."inc/datahandlers/pm.php";
  3063.         $pmhandler = new PMDataHandler();
  3064.        
  3065.         // Split up any recipients we have
  3066.         $data['to'] = explode(",", $data['to_username']);
  3067.         $data['to'] = array_map("trim", $data['to']);
  3068.         if (!empty($data['bcc']))
  3069.         {
  3070.             $data['bcc'] = explode(",", $data['bcc']);
  3071.             $data['bcc'] = array_map("trim", $data['bcc']);
  3072.         }
  3073.        
  3074.         $data['options'] = array(
  3075.             "signature" => (isset($data['options']['signature'])) ? $data['options']['signature'] : NULL,
  3076.             "disablesmilies" => (isset($data['options']['disablesmilies'])) ? $data['options']['disablesmilies'] : NULL,
  3077.             "savecopy" => (isset($data['options']['savecopy'])) ? $data['options']['savecopy'] : NULL,
  3078.             "readreceipt" => (isset($data['options']['readreceipt'])) ? $data['options']['readreceipt'] : NULL
  3079.         );
  3080.        
  3081.         /* Unnecessary
  3082.         if($data['saveasdraft'])
  3083.         {
  3084.             $data['saveasdraft'] = 1;
  3085.         } */
  3086.        
  3087.         $pmhandler->set_data($data);
  3088.        
  3089.         // Now let the pm handler do all the hard work.
  3090.         if(!$pmhandler->validate_pm())
  3091.         {
  3092.             $pm_errors = $pmhandler->get_friendly_errors();
  3093.             return inline_error($pm_errors);
  3094.            
  3095.         }
  3096.         else
  3097.         {
  3098.             $pminfo = $pmhandler->insert_pm();
  3099.             $this->plugins->run_hooks("private_do_send_end");
  3100.    
  3101.             if (isset($pminfo['draftsaved']))
  3102.             {
  3103.                 return $this->lang->redirect_pmsaved;
  3104.             }
  3105.             else
  3106.             {
  3107.                 return $this->lang->redirect_pmsent;
  3108.             }
  3109.         }
  3110.     }
  3111.    
  3112.     /**
  3113.      * Use built-in set-cookie function of MyBB
  3114.      *
  3115.      * @param string $name Cookie Name
  3116.      * @param mixed $value Cookie Value
  3117.      * @param integer $expires Timestamp of Expiry
  3118.      * @param boolean Use cookie for HTTP only?
  3119.     */
  3120.     function setCookie($name, $value = '', $expires = NULL, $httponly = false)
  3121.     {
  3122.         my_setcookie($name, $value, $expires, $httponly);
  3123.     }
  3124.    
  3125.     /**
  3126.      * Set a new password for a user
  3127.      *
  3128.      * @param integer User-ID
  3129.      * @param string New Password
  3130.      * @param boolean Return errors as MyBB array or nicely formated?
  3131.      * @return boolean|array
  3132.     */
  3133.     function updatePasswordOfUser($user_id, $password, $inline_error = true)
  3134.     {
  3135.         include_once MYBB_ROOT.'inc/functions_user.php';
  3136.         require_once MYBB_ROOT.'inc/datahandlers/user.php';
  3137.         $userhandler = new UserDataHandler('update');
  3138.        
  3139.         $data = array(
  3140.             'uid' => intval($user_id),
  3141.             'password' => $password
  3142.         );
  3143.        
  3144.         $userhandler->set_data($data);
  3145.        
  3146.         if (!$userhandler->validate_user())
  3147.         {
  3148.             $errors = $userhandler->get_friendly_errors();
  3149.             return ($inline_error === true) ? inline_error($errors) : $errors;
  3150.         }
  3151.        
  3152.         $userhandler->update_user();
  3153.        
  3154.         return true;
  3155.     }
  3156.    
  3157.     /**
  3158.      * Update content and information of a single post
  3159.      *
  3160.      * @param array $data Post-Data
  3161.      * @param boolean|array|string $inline_errors Return arrays as array or string or return bool true when all good
  3162.     */
  3163.     function updatePost($data, $inline_errors)
  3164.     {
  3165.         require_once MYBB_ROOT.'inc/functions_post.php';
  3166.         require_once MYBB_ROOT.'/inc/datahandlers/post.php';
  3167.         $posthandler = new PostDataHandler('update');
  3168.         $posthandler->action = 'post';
  3169.        
  3170.         $this->plugins->run_hooks('editpost_do_editpost_start');
  3171.        
  3172.         $posthandler->set_data($data);
  3173.        
  3174.         if (!$posthandler->validate_post())
  3175.         {
  3176.             $errors = $posthandler->get_friendly_errors();
  3177.             return ($inline_errors === true) ? inline_error($errors) : $errors;
  3178.         }
  3179.        
  3180.         $this->plugins->run_hooks('editpost_do_editpost_end');
  3181.        
  3182.         return $posthandler->update_post();
  3183.     }
  3184.    
  3185.     /**
  3186.      * Updates a thread in the database
  3187.      *
  3188.      * @param array $data Thread data
  3189.      * @param boolean $inline_errors Defines if we want a formatted error string or an array
  3190.      * @return array|string
  3191.      * @return array|string When true it will return an array with threadID, postID and status of being visible - false = error array or inline string
  3192.     */
  3193.     function updateThread($data, $inline_errors = true)
  3194.     {
  3195.         if (!isset($data['tid']))
  3196.         {
  3197.             $this->_errorAndDie('Function <i>updateThread</i>: Must pass thread id in array parameter - Required array key is <i>tid</i>');
  3198.         }
  3199.        
  3200.         // Posthandler is used for a post, so let's fetch the thread-post
  3201.         $thread = $this->getThread($data['tid']);
  3202.         $data['pid'] = $thread['firstpost'];
  3203.        
  3204.         require_once MYBB_ROOT.'inc/functions_post.php';
  3205.         require_once MYBB_ROOT.'/inc/datahandlers/post.php';
  3206.         $posthandler = new PostDataHandler('update');
  3207.         $posthandler->action = 'post';
  3208.         $posthandler->set_data($data);
  3209.         if (!$posthandler->validate_post())
  3210.         {
  3211.             $errors = $posthandler->get_friendly_errors();
  3212.             return ($inline_errors === true) ? inline_error($errors) : $errors;
  3213.         }
  3214.         return $posthandler->update_post();
  3215.     }
  3216.    
  3217.     /**
  3218.      * Updates userdata
  3219.      *
  3220.      * @param array $userdata Data of the User (uid is required as index)
  3221.      * @param boolean Return errors as MyBB array or nicely formated?
  3222.      * @return boolean|array
  3223.     */
  3224.     function updateUser($userdata = array(), $inline_error = true)
  3225.     {
  3226.         // Userdata Array needs to contain the UserID
  3227.         if (!isset($userdata['uid']))
  3228.         {
  3229.             $this->_errorAndDie('A UserID (Array-Key: <i>uid</i>) is required to update a user');
  3230.         }
  3231.        
  3232.         require_once MYBB_ROOT.'inc/functions_user.php';
  3233.         require_once MYBB_ROOT.'inc/datahandlers/user.php';
  3234.         $userhandler = new UserDataHandler('update');
  3235.         $userhandler->set_data($userdata);
  3236.        
  3237.         if (!$userhandler->validate_user())
  3238.         {
  3239.             $errors = $userhandler->get_friendly_errors();
  3240.             return ($inline_error === true) ? inline_error($errors) : $errors;
  3241.         }
  3242.        
  3243.         $userhandler->update_user();
  3244.        
  3245.         return true;
  3246.     }
  3247.    
  3248.     /**
  3249.      * Checks if given captcha is correct
  3250.      *
  3251.      * @param string $hash Captcha-Hash
  3252.      * @param string $string the Letters of the captcha
  3253.      * @return boolean
  3254.     */
  3255.     function validateCaptcha($hash, $string)
  3256.     {
  3257.         $imagehash = $this->dbEscape($hash);
  3258.         $imagestring = $this->dbEscape($string);
  3259.         $query = $this->db->simple_select("captcha", "*", "imagehash='{$imagehash}' AND imagestring='{$imagestring}'");
  3260.         $imgcheck = $this->db->fetch_array($query);
  3261.         if($imgcheck['dateline'] > 0)
  3262.         {      
  3263.             return true;
  3264.         }
  3265.         else
  3266.         {
  3267.             $this->db->delete_query("captcha", "imagehash='{$imagehash}'");
  3268.             return false;
  3269.         }
  3270.     }
  3271.    
  3272.     /**
  3273.      * Perform a vote in a poll
  3274.      *
  3275.      * @param integer $poll_id ID of Poll
  3276.      * @param integer $user_id ID of User
  3277.      * @param integer|array Vote option (basically what you vote!) - if multiple, you can define more options in an array
  3278.     */
  3279.     function vote($poll_id, $user_id = 0, $option = NULL)
  3280.     {
  3281.         // Load the Language Phrases
  3282.         $this->lang->load('polls');
  3283.        
  3284.         // A bit sanitizing...
  3285.         $poll_id = (int) $poll_id;
  3286.         $user_id = (int) $user_id;
  3287.        
  3288.         // Let's fetch infos of the poll
  3289.         $query = $this->db->simple_select("polls", "*", "pid='".intval($poll_id)."'");
  3290.         $poll = $this->db->fetch_array($query);
  3291.         $poll['timeout'] = $poll['timeout']*60*60*24;
  3292.        
  3293.         $this->plugins->run_hooks("polls_vote_start");
  3294.        
  3295.         // Does the poll exist?
  3296.         if (!$poll['pid'])
  3297.         {
  3298.             return $this->lang->error_invalidpoll;
  3299.         }
  3300.        
  3301.         // Does the poll exist in a valid thread?
  3302.         $query = $this->db->simple_select("threads", "*", "poll='".$poll['pid']."'");
  3303.         $thread = $this->db->fetch_array($query);
  3304.         if (!$thread['tid'])
  3305.         {
  3306.             return $this->lang->error_invalidthread;
  3307.         }
  3308.        
  3309.         // Do we have the permissino to vote?
  3310.         $fid = $thread['fid'];
  3311.         $forumpermissions = forum_permissions($fid);
  3312.         if ($forumpermissions['canvotepolls'] == 0)
  3313.         {
  3314.             return false;
  3315.         }
  3316.        
  3317.         // Has the poll expired?
  3318.         $expiretime = $poll['dateline'] + $poll['timeout'];
  3319.         if ($poll['closed'] == 1 || $thread['closed'] == 1 || ($expiretime < TIME_NOW && $poll['timeout']))
  3320.         {
  3321.             return $this->lang->error_pollclosed;
  3322.         }
  3323.        
  3324.         // Did we pass an option to vote for?
  3325.         if (empty($option))
  3326.         {
  3327.             return $this->lang->error_nopolloptions;
  3328.         }
  3329.        
  3330.         // Check if the user has voted before...
  3331.         if ($user_id > 0)
  3332.         {
  3333.             $query = $this->db->simple_select("pollvotes", "*", "uid='".$user_id."' AND pid='".$poll['pid']."'");
  3334.             $votecheck = $this->db->fetch_array($query);
  3335.         }
  3336.        
  3337.         if ($votecheck['vid'] || $this->mybb->cookies['pollvotes'][$poll['pid']])
  3338.         {
  3339.             return $this->lang->error_alreadyvoted;
  3340.         }
  3341.         elseif ($user_id == 0)
  3342.         {
  3343.             // Give a cookie to guests to inhibit revotes
  3344.             my_setcookie("pollvotes[{$poll['pid']}]", '1');
  3345.         }
  3346.        
  3347.         $votesql = '';
  3348.         $votesarray = explode("||~|~||", $poll['votes']);
  3349.         $numvotes = $poll['numvotes'];
  3350.         if ($poll['multiple'] == 1)
  3351.         {
  3352.             foreach ($option as $voteoption => $vote)
  3353.             {
  3354.                 if ($vote == 1 && isset($votesarray[$voteoption-1]))
  3355.                 {
  3356.                     if ($votesql)
  3357.                     {
  3358.                         $votesql .= ",";
  3359.                     }
  3360.                     $votesql .= "('".$poll['pid']."','".$user_id."','".$this->db->escape_string($voteoption)."', ".TIME_NOW.")";
  3361.                     $votesarray[$voteoption-1]++;
  3362.                     $numvotes = $numvotes+1;
  3363.                 }
  3364.             }
  3365.         }
  3366.         else
  3367.         {
  3368.             if (!isset($votesarray[$option-1]))
  3369.             {
  3370.                 return $this->lang->error_nopolloptions;
  3371.             }
  3372.             $votesql = "('".$poll['pid']."','".$user_id."','".$this->db->escape_string($option)."', ".TIME_NOW.")";
  3373.             $votesarray[$option-1]++;
  3374.             $numvotes = $numvotes+1;
  3375.         }
  3376.        
  3377.         // Save the fact that we voted
  3378.         $this->db->write_query("
  3379.             INSERT INTO
  3380.             ".TABLE_PREFIX."pollvotes (pid,uid,voteoption,dateline)
  3381.             VALUES $votesql
  3382.         ");
  3383.         $voteslist = '';
  3384.         for ($i = 1; $i <= $poll['numoptions']; ++$i)
  3385.         {
  3386.             if ($i > 1)
  3387.             {
  3388.                 $voteslist .= "||~|~||";
  3389.             }
  3390.             $voteslist .= $votesarray[$i-1];
  3391.         }
  3392.         $updatedpoll = array(
  3393.             "votes" => $this->db->escape_string($voteslist),
  3394.             "numvotes" => intval($numvotes),
  3395.         );
  3396.    
  3397.         $this->plugins->run_hooks("polls_vote_process");
  3398.    
  3399.         $this->db->update_query("polls", $updatedpoll, "pid='".$poll['pid']."'");
  3400.    
  3401.         $this->plugins->run_hooks("polls_vote_end");
  3402.    
  3403.         return true;
  3404.     }
  3405. }
  3406.  
  3407. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement