Advertisement
Guest User

vanillaocportal

a guest
Oct 6th, 2012
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 43.24 KB | None | 0 0
  1. <?php /*
  2.  
  3.  ocPortal
  4.  Copyright (c) ocProducts, 2004-2012
  5.  
  6.  See text/EN/licence.txt for full licencing information.
  7.  
  8.  
  9.  NOTE TO PROGRAMMERS:
  10.    Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
  11.    **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****
  12.  
  13. */
  14.  
  15. /**
  16.  * @license     http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
  17.  * @copyright   ocProducts Ltd
  18.  * @package     core_forum_drivers
  19.  */
  20.  
  21. /**
  22.  * Forum Driver.
  23.  * @package     core_forum_drivers
  24.  */
  25. class forum_driver_phpbb2 extends forum_driver_base
  26. {
  27.     /**
  28.      * Check the connected DB is valid for this forum driver.
  29.      *
  30.      * @return boolean      Whether it is valid
  31.      */
  32.     function check_db()
  33.     {
  34.         $test=$this->connection->query('SELECT COUNT(*) FROM '.$this->connection->get_table_prefix().'users',NULL,NULL,true);
  35.         return !is_null($test);
  36.     }
  37.  
  38.     /**
  39.      * Get the rows for the top given number of posters on the forum.
  40.      *
  41.      * @param  integer      The limit to the number of top posters to fetch
  42.      * @return array            The rows for the given number of top posters in the forum
  43.      */
  44.     function get_top_posters($limit)
  45.     {
  46.         return $this->connection->query('SELECT * FROM '.$this->connection->get_table_prefix().'users WHERE user_id<>'.strval((integer)$this->get_guest_id()).' ORDER BY user_posts DESC',$limit);
  47.     }
  48.  
  49.     /**
  50.      * Attempt to to find the member's language from their forum profile. It converts between language-identifiers using a map (lang/map.ini).
  51.      *
  52.      * @param  MEMBER               The member who's language needs to be fetched
  53.      * @return ?LANGUAGE_NAME   The member's language (NULL: unknown)
  54.      */
  55.     function forum_get_lang($member)
  56.     {
  57.         return $this->get_member_row_field($member,'user_lang');
  58.     }
  59.  
  60.     /**
  61.      * Find if the login cookie contains the login name instead of the member id.
  62.      *
  63.      * @return boolean      Whether the login cookie contains a login name or a member id
  64.      */
  65.     function is_cookie_login_name()
  66.     {
  67.         return false;
  68.     }
  69.  
  70.     /**
  71.      * Find if login cookie is md5-hashed.
  72.      *
  73.      * @return boolean      Whether the login cookie is md5-hashed
  74.      */
  75.     function is_hashed()
  76.     {
  77.         return false;
  78.     }
  79.  
  80.     /**
  81.      * Find the member id of the forum guest member.
  82.      *
  83.      * @return MEMBER           The member id of the forum guest member
  84.      */
  85.     function get_guest_id()
  86.     {
  87.         return (-1);
  88.     }
  89.  
  90.     /**
  91.      * Get the forums' table prefix for the database.
  92.      *
  93.      * @return string           The forum database table prefix
  94.      */
  95.     function get_drivered_table_prefix()
  96.     {
  97.         global $SITE_INFO;
  98.         return $SITE_INFO['phpbb_table_prefix'];
  99.     }
  100.  
  101.     /**
  102.      * Add the specified custom field to the forum (some forums implemented this using proper custom profile fields, others through adding a new field).
  103.      *
  104.      * @param  string           The name of the new custom field
  105.      * @param  integer      The length of the new custom field
  106.      * @return boolean      Whether the custom field was created successfully
  107.      */
  108.     function install_create_custom_field($name,$length)
  109.     {
  110.         unset($length);
  111.         $this->connection->query('ALTER TABLE '.$this->connection->get_table_prefix().'users ADD ocp_'.$name.' TEXT',NULL,NULL,true);
  112.         return true;
  113.     }
  114.  
  115.     /**
  116.      * Get an array of attributes to take in from the installer. Almost all forums require a table prefix, which the requirement there-of is defined through this function.
  117.      * The attributes have 4 values in an array
  118.      * - name, the name of the attribute for info.php
  119.      * - default, the default value (perhaps obtained through autodetection from forum config)
  120.      * - description, a textual description of the attributes
  121.      * - title, a textual title of the attribute
  122.      *
  123.      * @return array            The attributes for the forum
  124.      */
  125.     function install_specifics()
  126.     {
  127.         global $INFO;
  128.         $a=array();
  129.         $a['name']='phpbb_table_prefix';
  130.         $a['default']=array_key_exists('sql_tbl_prefix',$INFO)?$INFO['sql_tbl_prefix']:'phpbb_';
  131.         $a['description']=do_lang('MOST_DEFAULT');
  132.         $a['title']='phpBB '.do_lang('TABLE_PREFIX');
  133.         return array($a);
  134.     }
  135.  
  136.     /**
  137.      * Searches for forum auto-config at this path.
  138.      *
  139.      * @param  PATH         The path in which to search
  140.      * @return boolean      Whether the forum auto-config could be found
  141.      */
  142.     function install_test_load_from($path)
  143.     {
  144.         global $INFO;
  145.         if (@file_exists($path.'/config.php'))
  146.         {
  147.             $dbname='';
  148.             $dbuser='';
  149.             $dbpasswd='';
  150.             $table_prefix='';
  151.             @include($path.'/config.php');
  152.             $INFO['sql_database']=$dbname;
  153.             $INFO['sql_user']=$dbuser;
  154.             $INFO['sql_pass']=$dbpasswd;
  155.             $INFO['board_url']='';
  156.             $INFO['sql_tbl_prefix']=$table_prefix;
  157.             $INFO['cookie_member_id']='phpbb2mysql_data:userid';
  158.             $INFO['cookie_member_hash']='phpbb2mysql_data:autologinid';
  159.             return true;
  160.         }
  161.         return false;
  162.     }
  163.  
  164.     /**
  165.      * Get an array of paths to search for config at.
  166.      *
  167.      * @return array            The paths in which to search for the forum config
  168.      */
  169.     function install_get_path_search_list()
  170.     {
  171.         return array(
  172.         0=>'forums',
  173.         1=>'forum',
  174.         2=>'boards',
  175.         3=>'board',
  176.         4=>'phpBB',
  177.         5=>'phpBB2',
  178.         6=>'upload',
  179.         7=>'uploads',
  180.         8=>'phpbb',
  181.         9=>'phpbb2',
  182.         10=>'../forums',
  183.         11=>'../forum',
  184.         12=>'../boards',
  185.         13=>'../board',
  186.         14=>'../phpBB',
  187.         15=>'../phpBB2',
  188.         16=>'../upload',
  189.         17=>'../uploads',
  190.         18=>'../phpbb',
  191.         19=>'../phpbb2');
  192.     }
  193.  
  194.     /**
  195.      * Get an emoticon chooser template.
  196.      *
  197.      * @param  string           The ID of the form field the emoticon chooser adds to
  198.      * @return tempcode     The emoticon chooser template
  199.      */
  200.     function get_emoticon_chooser($field_name='post')
  201.     {
  202.         require_code('comcode_text');
  203.         $emoticons=$this->connection->query_select('smilies',array('*'),NULL,'GROUP BY code');
  204.         $em=new ocp_tempcode();
  205.         foreach ($emoticons as $emo)
  206.         {
  207.             $code=$emo['code'];
  208.             $em->attach(do_template('EMOTICON_CLICK_CODE',array('_GUID'=>'37ca734c4aea443920632e36e48fabc0','FIELD_NAME'=>$field_name,'CODE'=>$code,'IMAGE'=>apply_emoticons($code))));
  209.         }
  210.  
  211.         return $em;
  212.     }
  213.  
  214.     /**
  215.      * Pin a topic.
  216.      *
  217.      * @param  AUTO_LINK        The topic ID
  218.      */
  219.     function pin_topic($id)
  220.     {
  221.         $this->connection->query_update('topics',array('topic_type'=>1),array('topic_id'=>$id),'',1);
  222.     }
  223.  
  224.     /**
  225.      * Set a custom profile fields value. It should not be called directly.
  226.      *
  227.      * @param  MEMBER           The member id
  228.      * @param  string           The field name
  229.      * @param  string           The value
  230.      */
  231.     function set_custom_field($member,$field,$amount)
  232.     {
  233.         $this->connection->query_update('users',array('ocp_'.$field=>$amount),array('user_id'=>$member),'',NULL,NULL,false,true);
  234.     }
  235.  
  236.     /**
  237.      * Get custom profile fields values for all 'ocp_' prefixed keys.
  238.      *
  239.      * @param  MEMBER           The member id
  240.      * @return ?array           A map of the custom profile fields, key_suffix=>value (NULL: no fields)
  241.      */
  242.     function get_custom_fields($member)
  243.     {
  244.         $row=$this->get_member_row($member);
  245.         $out=array();
  246.         foreach ($row as $attribute=>$value)
  247.         {
  248.             if (substr($attribute,0,4)=='ocp_') $out[substr($attribute,4)]=$value;
  249.         }
  250.         return $out;
  251.     }
  252.  
  253.     /**
  254.      * Get a member profile-row for the member of the given name.
  255.      *
  256.      * @param  SHORT_TEXT   The member name
  257.      * @return ?array           The profile-row (NULL: not found)
  258.      */
  259.     function pget_row($name)
  260.     {
  261.         $rows=$this->connection->query_select('users',array('*'),array('username'=>$name),'',1);
  262.         if (!array_key_exists(0,$rows)) return NULL;
  263.         return $rows[0];
  264.     }
  265.  
  266.     /**
  267.      * From a member profile-row, get the member's primary usergroup.
  268.      *
  269.      * @param  array            The profile-row
  270.      * @return GROUP            The member's primary usergroup
  271.      */
  272.     function pname_group($r)
  273.     {
  274.         $id=$r['user_id'];
  275.  
  276.         // The first usergroup they're joined to
  277.         $group=$this->connection->query_value_null_ok('user_group u LEFT JOIN '.$this->connection->get_table_prefix().'groups g ON u.group_id=g.group_id','g.group_id AS group_id',array('user_id'=>$id,'user_pending'=>0,'group_single_user'=>0));
  278.         return $group;
  279.     }
  280.  
  281.     /**
  282.      * From a member profile-row, get the member's member id.
  283.      *
  284.      * @param  array            The profile-row
  285.      * @return MEMBER           The member id
  286.      */
  287.     function pname_id($r)
  288.     {
  289.         return $r['user_id'];
  290.     }
  291.  
  292.     /**
  293.      * From a member profile-row, get the member's last visit date.
  294.      *
  295.      * @param  array            The profile-row
  296.      * @return TIME         The last visit date
  297.      */
  298.     function pnamelast_visit($r)
  299.     {
  300.         return $r['user_lastvisit'];
  301.     }
  302.  
  303.     /**
  304.      * From a member profile-row, get the member's name.
  305.      *
  306.      * @param  array            The profile-row
  307.      * @return string           The member name
  308.      */
  309.     function pname_name($r)
  310.     {
  311.         return $r['username'];
  312.     }
  313.  
  314.     /**
  315.      * From a member profile-row, get the member's e-mail address.
  316.      *
  317.      * @param  array            The profile-row
  318.      * @return SHORT_TEXT   The member e-mail address
  319.      */
  320.     function pname_email($r)
  321.     {
  322.         return $r['user_email'];
  323.     }
  324.  
  325.     /**
  326.      * Get a URL to the specified member's home (control panel).
  327.      *
  328.      * @param  MEMBER           The member id
  329.      * @return URLPATH      The URL to the members home
  330.      */
  331.     function member_home_url($id)
  332.     {
  333.         unset($id);
  334.         return get_forum_base_url().'/profile.php?mode=editprofile';
  335.     }
  336.  
  337.     /**
  338.      * Get the photo thumbnail URL for the specified member id.
  339.      *
  340.      * @param  MEMBER           The member id
  341.      * @return URLPATH      The URL (blank: none)
  342.      */
  343.     function get_member_photo_url($member)
  344.     {
  345.         unset($member);
  346.  
  347.         return '';
  348.     }
  349.  
  350.     /**
  351.      * Get the avatar URL for the specified member id.
  352.      *
  353.      * @param  MEMBER           The member id
  354.      * @return URLPATH      The URL (blank: none)
  355.      */
  356.     function get_member_avatar_url($member)
  357.     {
  358.         $options=$this->connection->query('SELECT * FROM '.$this->connection->get_table_prefix().'config WHERE '.db_string_equal_to('config_name','avatar_path').' OR '.db_string_equal_to('config_name','avatar_gallery_path'));
  359.         $avatar_path=$options[0]['config_value'];
  360.         $avatar_gallery_path=$options[1]['config_value'];
  361.  
  362.         $type=$this->get_member_row_field($member,'user_avatar_type');
  363.         $filename=$this->get_member_row_field($member,'user_avatar');
  364.  
  365.         switch ($type)
  366.         {
  367.             case '1': // Upload
  368.                 return get_forum_base_url().'/'.$avatar_path.'/'.$filename;
  369.             case '2': // Remote
  370.                 return $filename;
  371.             case '3': // Gallery
  372.                 return get_forum_base_url().'/'.$avatar_gallery_path.'/'.$filename;
  373.         }
  374.         return '';
  375.     }
  376.  
  377.     /**
  378.      * Get a URL to the specified member's profile.
  379.      *
  380.      * @param  MEMBER           The member id
  381.      * @return URLPATH      The URL to the member profile
  382.      */
  383.     function _member_profile_url($id)
  384.     {
  385.         return get_forum_base_url().'/profile.php?mode=viewprofile&u='.strval($id);
  386.     }
  387.  
  388.     /**
  389.      * Get a URL to the registration page (for people to create member accounts).
  390.      *
  391.      * @return URLPATH      The URL to the registration page
  392.      */
  393.     function _join_url()
  394.     {
  395.         return get_forum_base_url().'/profile.php?mode=register';
  396.     }
  397.  
  398.     /**
  399.      * Get a URL to the members-online page.
  400.      *
  401.      * @return URLPATH      The URL to the members-online page
  402.      */
  403.     function _online_members_url()
  404.     {
  405.         return get_forum_base_url().'/viewonline.php';
  406.     }
  407.  
  408.     /**
  409.      * Get a URL to send a private/personal message to the given member.
  410.      *
  411.      * @param  MEMBER           The member id
  412.      * @return URLPATH      The URL to the private/personal message page
  413.      */
  414.     function _member_pm_url($id)
  415.     {
  416.         return get_forum_base_url().'/privmsg.php?mode=post&u='.strval($id);
  417.     }
  418.  
  419.     /**
  420.      * Get a URL to the specified forum.
  421.      *
  422.      * @param  integer      The forum ID
  423.      * @return URLPATH      The URL to the specified forum
  424.      */
  425.     function _forum_url($id)
  426.     {
  427.         return get_forum_base_url().'/viewforum.php?f='.strval($id);
  428.     }
  429.  
  430.     /**
  431.      * Get the forum ID from a forum name.
  432.      *
  433.      * @param  SHORT_TEXT   The forum name
  434.      * @return integer      The forum ID
  435.      */
  436.     function forum_id_from_name($forum_name)
  437.     {
  438.         return is_numeric($forum_name)?intval($forum_name):$this->connection->query_value_null_ok('forums','forum_id',array('forum_name'=>$forum_name));
  439.     }
  440.  
  441.     /**
  442.      * Convert an IP address into phpBB hexadecimal string format.
  443.      *
  444.      * @param  IP               The normal IP address
  445.      * @return string           The phpBB IP address
  446.      */
  447.     function _phpbb_ip($ip)
  448.     {
  449.         $ip_apart=explode('.',$ip);
  450.         $_ip=dechex($ip_apart[0]).dechex($ip_apart[1]).dechex($ip_apart[2]).dechex($ip_apart[3]);
  451.         return $_ip;
  452.     }
  453.  
  454.     /**
  455.      * Convert an IP address from phpBB hexadecimal string format.
  456.      *
  457.      * @param  string           The phpBB IP address
  458.      * @return IP               The normal IP address
  459.      */
  460.     function _un_phpbb_ip($ip)
  461.     {
  462.         $_ip=strval(hexdec($ip[0].$ip[1])).'.'.strval(hexdec($ip[2].$ip[3])).'.'.strval(hexdec($ip[4].$ip[5])).'.'.strval(hexdec($ip[6].$ip[7]));
  463.         return $_ip;
  464.     }
  465.  
  466.     /**
  467.      * Makes a post in the specified forum, in the specified topic according to the given specifications. If the topic doesn't exist, it is created along with a spacer-post.
  468.      * Spacer posts exist in order to allow staff to delete the first true post in a topic. Without spacers, this would not be possible with most forum systems. They also serve to provide meta information on the topic that cannot be encoded in the title (such as a link to the content being commented upon).
  469.      *
  470.      * @param  SHORT_TEXT   The forum name
  471.      * @param  SHORT_TEXT   The topic identifier (usually <content-type>_<content-id>)
  472.      * @param  MEMBER           The member ID
  473.      * @param  LONG_TEXT        The post title
  474.      * @param  LONG_TEXT        The post content in Comcode format
  475.      * @param  string           The topic title; must be same as content title if this is for a comment topic
  476.      * @param  string           This is put together with the topic identifier to make a more-human-readable topic title or topic description (hopefully the latter and a $content_title title, but only if the forum supports descriptions)
  477.      * @param  ?URLPATH     URL to the content (NULL: do not make spacer post)
  478.      * @param  ?TIME            The post time (NULL: use current time)
  479.      * @param  ?IP              The post IP address (NULL: use current members IP address)
  480.      * @param  ?BINARY      Whether the post is validated (NULL: unknown, find whether it needs to be marked unvalidated initially). This only works with the OCF driver.
  481.      * @param  ?BINARY      Whether the topic is validated (NULL: unknown, find whether it needs to be marked unvalidated initially). This only works with the OCF driver.
  482.      * @param  boolean      Whether to skip post checks
  483.      * @param  SHORT_TEXT   The name of the poster
  484.      * @param  ?AUTO_LINK   ID of post being replied to (NULL: N/A)
  485.      * @param  boolean      Whether the reply is only visible to staff
  486.      * @return array            Topic ID (may be NULL), and whether a hidden post has been made
  487.      */
  488.     function make_post_forum_topic($forum_name,$topic_identifier,$member,$post_title,$_post,$content_title,$topic_identifier_encapsulation_prefix,$content_url=NULL,$time=NULL,$ip=NULL,$validated=NULL,$topic_validated=1,$skip_post_checks=false,$poster_name_if_guest='',$parent_id=NULL,$staff_only=false)
  489.     {
  490.         $__post=comcode_to_tempcode($_post);
  491.         $post=$__post->evaluate();
  492.  
  493.         if (is_null($time)) $time=time();
  494.         if (is_null($ip)) $ip=get_ip_address();
  495.         $forum_id=$this->forum_id_from_name($forum_name);
  496.         if (is_null($forum_id)) warn_exit(do_lang_tempcode('MISSING_FORUM',escape_html($forum_name)));
  497.         $test=$this->connection->query_select('forums',array('*'),NULL,'',1);
  498.         $fm=array_key_exists('hide_forum_in_cat',$test[0]);
  499.         $topic_id=$this->find_topic_id_for_topic_identifier($forum_name,$topic_identifier);
  500.         $ip_address=$this->_phpbb_ip($ip);
  501.         $local_ip_address=$this->_phpbb_ip('127.0.0.1');
  502.         if (is_null($topic_id))
  503.         {
  504.             $map=array('forum_id'=>$forum_id,'topic_title'=>$content_title.', '.$topic_identifier_encapsulation_prefix.': #'.$topic_identifier,'topic_poster'=>$member,'topic_time'=>$time,'topic_views'=>0,'topic_replies'=>0,'topic_status'=>0,'topic_vote'=>0,'topic_type'=>0,'topic_first_post_id'=>0,'topic_last_post_id'=>0,'topic_moved_id'=>0);
  505.             if ($fm) $map=array_merge($map,array('answer_status'=>0,'topic_attachment'=>0,'topic_icon'=>0,'rating_rank_id'=>0,'title_compl_infos'=>NULL,'topic_priority'=>0));
  506.             $topic_id=$this->connection->query_insert('topics',$map,true);
  507.             $map=array('topic_id'=>$topic_id,'forum_id'=>$forum_id,'poster_id'=>-1,'post_time'=>$time,'poster_ip'=>$local_ip_address,'post_username'=>NULL,'enable_bbcode'=>1,'enable_html'=>0,'enable_smilies'=>1,'enable_sig'=>1,'post_edit_time'=>NULL,'post_edit_count'=>0);
  508.             if ($fm) $map=array_merge($map,array('post_attachment'=>0,'post_edit_user'=>NULL,'post_icon'=>0,'post_bluecard'=>NULL,'rating_rank_id'=>0,'user_avatar'=>NULL,'user_avatar_type'=>0,'urgent_post'=>0));
  509.             $post_id=$this->connection->query_insert('posts',$map,true);
  510.             $home_link=hyperlink($content_url,escape_html($content_title));
  511.             $map=array('post_id'=>$post_id,'bbcode_uid'=>'','post_subject'=>'','post_text'=>do_lang('SPACER_POST',$home_link->evaluate(),'','',get_site_default_lang()));
  512.             $this->connection->query_insert('posts_text',$map);
  513.             $this->connection->query('UPDATE '.$this->connection->get_table_prefix().'topics SET topic_first_post_id='.strval((integer)$post_id).' WHERE topic_id='.strval((integer)$topic_id),1);
  514.             $this->connection->query('UPDATE '.$this->connection->get_table_prefix().'forums SET forum_topics=(forum_topics+1),forum_posts=(forum_posts+1) WHERE forum_id='.strval((integer)$forum_id),1);
  515.         }
  516.  
  517.         if ($post=='') return array($topic_id,false);
  518.  
  519.         $map=array('topic_id'=>$topic_id,'forum_id'=>$forum_id,'poster_id'=>$member,'post_time'=>$time,'poster_ip'=>$ip_address,'post_username'=>NULL,'enable_bbcode'=>1,'enable_html'=>0,'enable_smilies'=>1,'enable_sig'=>1,'post_edit_time'=>NULL,'post_edit_count'=>0);
  520.         if ($fm) $map=array_merge($map,array('post_attachment'=>0,'post_edit_user'=>NULL,'post_icon'=>0,'post_bluecard'=>NULL,'rating_rank_id'=>0,'user_avatar'=>NULL,'user_avatar_type'=>0,'urgent_post'=>0));
  521.         $post_id=$this->connection->query_insert('posts',$map,true);
  522.         $map=array('post_id'=>$post_id,'bbcode_uid'=>'','post_subject'=>$post_title,'post_text'=>$post);
  523.         $this->connection->query_insert('posts_text',$map);
  524.         $this->connection->query('UPDATE '.$this->connection->get_table_prefix().'forums SET forum_posts=(forum_posts+1), forum_last_post_id='.strval((integer)$post_id).' WHERE forum_id='.strval((integer)$forum_id),1);
  525.         $this->connection->query('UPDATE '.$this->connection->get_table_prefix().'topics SET topic_replies=(topic_replies+1), topic_last_post_id='.strval((integer)$post_id).' WHERE topic_id='.strval((integer)$topic_id),1);
  526.  
  527.         return array($topic_id,false);
  528.     }
  529.  
  530.     /**
  531.      * Get an array of maps for the topic in the given forum.
  532.      *
  533.      * @param  integer      The topic ID
  534.      * @param  integer      The comment count will be returned here by reference
  535.      * @param  integer      Maximum comments to returned
  536.      * @param  integer      Comment to start at
  537.      * @param  boolean      Whether to mark the topic read (ignored for this forum driver)
  538.      * @param  boolean      Whether to show in reverse
  539.      * @return mixed            The array of maps (Each map is: title, message, member, date) (-1 for no such forum, -2 for no such topic)
  540.      */
  541.     function get_forum_topic_posts($topic_id,&$count,$max=100,$start=0,$mark_read=true,$reverse=false)
  542.     {
  543.         if (is_null($topic_id)) return (-2);
  544.         $order=$reverse?'post_time DESC':'post_time';
  545.         $rows=$this->connection->query('SELECT * FROM '.$this->connection->get_table_prefix().'posts p LEFT JOIN '.$this->connection->get_table_prefix().'posts_text d ON p.post_id=d.post_id WHERE topic_id='.strval((integer)$topic_id).' AND post_text NOT LIKE \''.db_encode_like(substr(do_lang('SPACER_POST','','','',get_site_default_lang()),0,20).'%').'\' ORDER BY '.$order,$max,$start);
  546.         $count=$this->connection->query_value_null_ok_full('SELECT COUNT(*) FROM '.$this->connection->get_table_prefix().'posts p LEFT JOIN '.$this->connection->get_table_prefix().'posts_text d ON p.post_id=d.post_id WHERE topic_id='.strval((integer)$topic_id).' AND post_text NOT LIKE \''.db_encode_like(substr(do_lang('SPACER_POST','','','',get_site_default_lang()),0,20).'%').'\'');
  547.         $out=array();
  548.         foreach ($rows as $myrow)
  549.         {
  550.             $temp=array();
  551.             $temp['title']=$myrow['post_subject'];
  552.             if (is_null($temp['title'])) $temp['title']='';
  553.             global $LAX_COMCODE;
  554.             $temp2=$LAX_COMCODE;
  555.             $LAX_COMCODE=true;
  556.             $temp['message']=($myrow['bbcode_uid']!='')?comcode_to_tempcode($myrow['post_text'],$myrow['poster_id']):$myrow['post_text'];
  557.             $LAX_COMCODE=$temp2;
  558.             $temp['user']=$myrow['poster_id'];
  559.             $temp['date']=$myrow['post_time'];
  560.  
  561.             $out[]=$temp;
  562.         }
  563.  
  564.         return $out;
  565.     }
  566.  
  567.     /**
  568.      * Get a URL to the specified topic ID. Most forums don't require the second parameter, but some do, so it is required in the interface.
  569.      *
  570.      * @param  integer      The topic ID
  571.      * @param string            The forum ID
  572.      * @return URLPATH      The URL to the topic
  573.      */
  574.     function topic_url($id,$forum)
  575.     {
  576.         unset($forum);
  577.         return get_forum_base_url().'/viewtopic.php?t='.strval($id);
  578.     }
  579.  
  580.     /**
  581.      * Get a URL to the specified post id.
  582.      *
  583.      * @param  integer      The post id
  584.      * @param string            The forum ID
  585.      * @return URLPATH      The URL to the post
  586.      */
  587.     function post_url($id,$forum)
  588.     {
  589.         unset($forum);
  590.         $topic_id=$this->connection->query_value_null_ok('posts','tid',array('pid'=>$id));
  591.         if (is_null($topic_id)) return '?';
  592.         $url=get_forum_base_url().'/viewtopic.php?t='.strval($topic_id).'#'.strval($id);
  593.         return $url;
  594.     }
  595.  
  596.     /**
  597.      * Get the topic ID from a topic identifier in the specified forum. It is used by comment topics, which means that the unique-topic-name assumption holds valid.
  598.      *
  599.      * @param  string           The forum name / ID
  600.      * @param  SHORT_TEXT   The topic identifier
  601.      * @return integer      The topic ID
  602.      */
  603.     function find_topic_id_for_topic_identifier($forum,$topic_identifier)
  604.     {
  605.         if (is_integer($forum)) $forum_id=$forum;
  606.         else $forum_id=$this->forum_id_from_name($forum);
  607.         return $this->connection->query_value_null_ok_full('SELECT topic_id FROM '.$this->connection->get_table_prefix().'topics WHERE forum_id='.strval((integer)$forum_id).' AND ('.db_string_equal_to('topic_title',$topic_identifier).' OR topic_title LIKE \'%: #'.db_encode_like($topic_identifier).'\')');
  608.     }
  609.  
  610.     /**
  611.      * Get an array of topics in the given forum. Each topic is an array with the following attributes:
  612.      * - id, the topic ID
  613.      * - title, the topic title
  614.      * - lastusername, the username of the last poster
  615.      * - lasttime, the timestamp of the last reply
  616.      * - closed, a Boolean for whether the topic is currently closed or not
  617.      * - firsttitle, the title of the first post
  618.      * - firstpost, the first post (only set if $show_first_posts was true)
  619.      *
  620.      * @param  mixed            The forum name or an array of forum IDs
  621.      * @param  integer      The limit
  622.      * @param  integer      The start position
  623.      * @param  integer      The total rows (not a parameter: returns by reference)
  624.      * @param  SHORT_TEXT   The topic title filter
  625.      * @param  boolean      Whether to show the first posts
  626.      * @param  string           The date key to sort by
  627.      * @set    lasttime firsttime
  628.      * @param  boolean      Whether to limit to hot topics
  629.      * @param  SHORT_TEXT   The topic description filter
  630.      * @return ?array           The array of topics (NULL: error)
  631.      */
  632.     function show_forum_topics($name,$limit,$start,&$max_rows,$filter_topic_title='',$show_first_posts=false,$date_key='lasttime',$hot=false,$filter_topic_description='')
  633.     {
  634.         if (is_integer($name)) $id_list='forum_id='.strval((integer)$name);
  635.         elseif (!is_array($name))
  636.         {
  637.             $id=$this->forum_id_from_name($name);
  638.             if (is_null($id)) return NULL;
  639.             $id_list='forum_id='.strval((integer)$id);
  640.         } else
  641.         {
  642.             $id_list='';
  643.             foreach (array_keys($name) as $id)
  644.             {
  645.                 if ($id_list!='') $id_list.=' OR ';
  646.                 $id_list.='forum_id='.strval((integer)$id);
  647.             }
  648.             if ($id_list=='') return NULL;
  649.         }
  650.  
  651.         $topic_filter=($filter_topic_title!='')?'AND topic_title LIKE \''.db_encode_like($filter_topic_title).'\'':'';
  652.         $topic_filter.=' ORDER BY '.(($date_key=='lasttime')?'topic_last_post_id':'topic_time').' DESC';
  653.         $rows=$this->connection->query('SELECT * FROM '.$this->connection->get_table_prefix().'topics WHERE ('.$id_list.') '.$topic_filter,$limit,$start);
  654.         $max_rows=$this->connection->query_value_null_ok_full('SELECT COUNT(*) FROM '.$this->connection->get_table_prefix().'topics WHERE ('.$id_list.') '.$topic_filter);
  655.         $i=0;
  656.         $firsttime=array();
  657.         $username=array();
  658.         $memberid=array();
  659.         $datetimes=array();
  660.         $rs=array();
  661.         while (array_key_exists($i,$rows))
  662.         {
  663.             $r=$rows[$i];
  664.  
  665.             $id=$r['topic_id'];
  666.             $firsttime[$id]=$r['topic_time'];
  667.  
  668.             $post_rows=$this->connection->query('SELECT * FROM '.$this->connection->get_table_prefix().'posts p LEFT JOIN '.$this->connection->get_table_prefix().'posts_text t ON p.post_id=t.post_id WHERE topic_id='.strval((integer)$id).' AND post_text NOT LIKE \''.db_encode_like(substr(do_lang('SPACER_POST','','','',get_site_default_lang()),0,20).'%').'\' ORDER BY post_time DESC',1);
  669.             if (!array_key_exists(0,$post_rows))
  670.             {
  671.                 $i++;
  672.                 continue;
  673.             }
  674.             $r2=$post_rows[0];
  675.  
  676.             $username[$id]=$this->get_username($r2['poster_id']);
  677.             $memberid[$id]=$r2['poster_id'];
  678.             $datetimes[$id]=$r2['post_time'];
  679.             $rs[$id]=$r;
  680.  
  681.             $i++;
  682.         }
  683.         if ($i>0)
  684.         {
  685.             arsort($datetimes);
  686.             $i=0;
  687.             $out=array();
  688.             if (count($datetimes)>0)
  689.             {
  690.                 foreach ($datetimes as $id=>$datetime)
  691.                 {
  692.                     $r=$rs[$id];
  693.  
  694.                     $out[$i]=array();
  695.                     $out[$i]['id']=$id;
  696.                     $out[$i]['num']=$r['topic_replies']+1;
  697.                     $out[$i]['title']=$r['topic_title'];
  698.                     $out[$i]['description']=$r['topic_title'];
  699.                     $out[$i]['firsttime']=$r['topic_time'];
  700.                     $out[$i]['firstusername']=$this->get_username($r['topic_poster']);
  701.                     $out[$i]['lastusername']=$username[$id];
  702.                     $out[$i]['firstmemberid']=$r['topic_poster'];
  703.                     $out[$i]['lastmemberid']=$memberid[$id];
  704.                     $out[$i]['lasttime']=$datetime;
  705.                     $out[$i]['closed']=($r['topic_status']==1);
  706.  
  707.                     $fp_rows=$this->connection->query('SELECT post_subject,post_text,bbcode_uid,poster_id FROM '.$this->connection->get_table_prefix().'posts p LEFT JOIN '.$this->connection->get_table_prefix().'posts_text t ON p.post_id=t.post_id WHERE post_text NOT LIKE \''.db_encode_like(substr(do_lang('SPACER_POST','','','',get_site_default_lang()),0,20).'%').'\' AND post_time='.strval((integer)$firsttime[$id]).' AND topic_id='.strval((integer)$id),1);
  708.                     if (!array_key_exists(0,$fp_rows))
  709.                     {
  710.                         unset($out[$i]);
  711.                         continue;
  712.                     }
  713.                     $out[$i]['firsttitle']=$fp_rows[0]['post_subject'];
  714.                     if ($show_first_posts)
  715.                     {
  716.                         global $LAX_COMCODE;
  717.                         $temp=$LAX_COMCODE;
  718.                         $LAX_COMCODE=true;
  719.                         $out[$i]['firstpost']=($fp_rows[0]['bbcode_uid']!='')?comcode_to_tempcode($fp_rows[0]['post_text'],$fp_rows[0]['poster_id']):$fp_rows[0]['post_text'];
  720.                         $LAX_COMCODE=$temp;
  721.                     }
  722.  
  723.                     $i++;
  724.                     if ($i==$limit) break;
  725.                 }
  726.             }
  727.  
  728.             return $out;
  729.         }
  730.         return NULL;
  731.     }
  732.  
  733.     /**
  734.      * Get an array of members who are in at least one of the given array of usergroups.
  735.      *
  736.      * @param  array            The array of usergroups
  737.      * @param  ?integer     Return up to this many entries for primary members and this many entries for secondary members (NULL: no limit, only use no limit if querying very restricted usergroups!)
  738.      * @param  integer      Return primary members after this offset and secondary members after this offset
  739.      * @return ?array           The array of members (NULL: no members)
  740.      */
  741.     function member_group_query($groups,$max=NULL,$start=0)
  742.     {
  743.         $_groups='';
  744.         foreach ($groups as $group)
  745.         {
  746.             if ($_groups!='') $_groups.=' OR ';
  747.             $_groups.='g.group_id='.strval((integer)$group);
  748.         }
  749.         if ($_groups=='') return array();
  750.         return $this->connection->query('SELECT * FROM '.$this->connection->get_table_prefix().'user_group g LEFT JOIN '.$this->connection->get_table_prefix().'users u ON u.user_id=g.user_id WHERE '.$_groups.' AND user_pending=0 ORDER BY g.group_id ASC',$max,$start);
  751.     }
  752.  
  753.     /**
  754.      * This is the opposite of the get_next_member function.
  755.      *
  756.      * @param  MEMBER           The member id to decrement
  757.      * @return ?MEMBER      The previous member id (NULL: no previous member)
  758.      */
  759.     function get_previous_member($member)
  760.     {
  761.         $tempid=$this->connection->query_value_null_ok_full('SELECT user_id FROM '.$this->connection->get_table_prefix().'users WHERE user_id<'.strval((integer)$member).' AND user_id>0 ORDER BY user_id DESC');
  762.         return $tempid;
  763.     }
  764.  
  765.     /**
  766.      * Get the member id of the next member after the given one, or NULL.
  767.      * It cannot be assumed there are no gaps in member ids, as members may be deleted.
  768.      *
  769.      * @param  MEMBER           The member id to increment
  770.      * @return ?MEMBER      The next member id (NULL: no next member)
  771.      */
  772.     function get_next_member($member)
  773.     {
  774.         $tempid=$this->connection->query_value_null_ok_full('SELECT user_id FROM '.$this->connection->get_table_prefix().'users WHERE user_id>'.strval((integer)$member).' ORDER BY user_id');
  775.         return $tempid;
  776.     }
  777.  
  778.     /**
  779.      * Try to find a member with the given IP address
  780.      *
  781.      * @param  IP               The IP address
  782.      * @return array            The distinct rows found
  783.      */
  784.     function probe_ip($ip)
  785.     {
  786.         $_ip=$this->_phpbb_ip($ip);
  787.         return $this->connection->query_select('posts',array('DISTINCT poster_id AS id'),array('poster_ip'=>$_ip));
  788.     }
  789.  
  790.     /**
  791.      * Get the name relating to the specified member id.
  792.      * If this returns NULL, then the member has been deleted. Always take potential NULL output into account.
  793.      *
  794.      * @param  MEMBER           The member id
  795.      * @return ?SHORT_TEXT  The member name (NULL: member deleted)
  796.      */
  797.     function _get_username($member)
  798.     {
  799.         if ($member==$this->get_guest_id()) return do_lang('GUEST');
  800.         return $this->get_member_row_field($member,'username');
  801.     }
  802.  
  803.     /**
  804.      * Get the e-mail address for the specified member id.
  805.      *
  806.      * @param  MEMBER           The member id
  807.      * @return SHORT_TEXT   The e-mail address
  808.      */
  809.     function _get_member_email_address($member)
  810.     {
  811.         return $this->get_member_row_field($member,'user_email');
  812.     }
  813.  
  814.     /**
  815.      * Find if this member may have e-mails sent to them
  816.      *
  817.      * @param  MEMBER           The member id
  818.      * @return boolean      Whether the member may have e-mails sent to them
  819.      */
  820.     function get_member_email_allowed($member)
  821.     {
  822.         $v=$this->get_member_row_field($member,'user_viewemail');
  823.         if ($v==1) return true;
  824.         return false;
  825.     }
  826.  
  827.     /**
  828.      * Get the timestamp of a member's join date.
  829.      *
  830.      * @param  MEMBER           The member id
  831.      * @return TIME         The timestamp
  832.      */
  833.     function get_member_join_timestamp($member)
  834.     {
  835.         return $this->get_member_row_field($member,'user_regdate');
  836.     }
  837.  
  838.     /**
  839.      * Find all members with a name matching the given SQL LIKE string.
  840.      *
  841.      * @param  string           The pattern
  842.      * @param  ?integer     Maximum number to return (limits to the most recent active) (NULL: no limit)
  843.      * @return ?array           The array of matched members (NULL: none found)
  844.      */
  845.     function get_matching_members($pattern,$limit=NULL)
  846.     {
  847.         $rows=$this->connection->query('SELECT * FROM '.$this->connection->get_table_prefix().'users WHERE username LIKE \''.db_encode_like($pattern).'\' AND user_id<>'.strval($this->get_guest_id()).' ORDER BY user_lastvisit DESC',$limit);
  848.         global $M_SORT_KEY;
  849.         $M_SORT_KEY='username';
  850.         uasort($rows,'multi_sort');
  851.         return $rows;
  852.     }
  853.  
  854.     /**
  855.      * Get the given member's post count.
  856.      *
  857.      * @param  MEMBER           The member id
  858.      * @return integer      The post count
  859.      */
  860.     function get_post_count($member)
  861.     {
  862.         return $this->get_member_row_field($member,'user_posts');
  863.     }
  864.  
  865.     /**
  866.      * Get the given member's topic count.
  867.      *
  868.      * @param  MEMBER           The member id
  869.      * @return integer      The topic count
  870.      */
  871.     function get_topic_count($member)
  872.     {
  873.         return $this->connection->query_value('topics','COUNT(*)',array('topic_poster'=>$member));
  874.     }
  875.  
  876.     /**
  877.      * Find out if the given member id is banned.
  878.      *
  879.      * @param  MEMBER           The member id
  880.      * @return boolean      Whether the member is banned
  881.      */
  882.     function is_banned($member)
  883.     {
  884.         $banned=$this->connection->query_value_null_ok('banlist','ban_userid',array('ban_userid'=>$member));
  885.         if (!is_null($banned)) return true;
  886.         return false;
  887.     }
  888.  
  889.     /**
  890.      * Find the base URL to the emoticons.
  891.      *
  892.      * @return URLPATH      The base URL
  893.      */
  894.     function get_emo_dir()
  895.     {
  896.         return get_forum_base_url().'/images/smiles/';
  897.     }
  898.  
  899.     /**
  900.      * Get a map between smiley codes and templates representing the HTML-image-code for this smiley. The smilies present of course depend on the forum involved.
  901.      *
  902.      * @return array            The map
  903.      */
  904.     function find_emoticons()
  905.     {
  906.         global $EMOTICON_CACHE;
  907.         if (!is_null($EMOTICON_CACHE)) return $EMOTICON_CACHE;
  908.         $rows=$this->connection->query_select('smilies',array('*'));
  909.         $EMOTICON_CACHE=array();
  910.         foreach ($rows as $myrow)
  911.         {
  912.             $src=$myrow['smile_url'];
  913.             if (url_is_local($src)) $src=$this->get_emo_dir().$src;
  914.             $EMOTICON_CACHE[$myrow['code']]=array('EMOTICON_IMG_CODE_DIR',$src,$myrow['code']);
  915.         }
  916.         uksort($EMOTICON_CACHE,'strlen_sort');
  917.         $EMOTICON_CACHE=array_reverse($EMOTICON_CACHE);
  918.         return $EMOTICON_CACHE;
  919.     }
  920.  
  921.     /**
  922.      * Find a list of all forum skins (aka themes).
  923.      *
  924.      * @return array            The list of skins
  925.      */
  926.     function get_skin_list()
  927.     {
  928.         $table='themes';
  929.         $codename='style_name';
  930.  
  931.         $rows=$this->connection->query_select($table,array($codename));
  932.         return collapse_1d_complexity($codename,$rows);
  933.     }
  934.  
  935.     /**
  936.      * Try to find the theme that the logged-in/guest member is using, and map it to an ocPortal theme.
  937.      * The themes/map.ini file functions to provide this mapping between forum themes, and ocPortal themes, and has a slightly different meaning for different forum drivers. For example, some drivers map the forum themes theme directory to the ocPortal theme name, whilst others made the humanly readeable name.
  938.      *
  939.      * @param  boolean      Whether to avoid member-specific lookup
  940.      * @return ID_TEXT      The theme
  941.      */
  942.     function _get_theme($skip_member_specific=false)
  943.     {
  944.         $def='';
  945.  
  946.         // Load in remapper
  947.         $map=file_exists(get_file_base().'/themes/map.ini')?better_parse_ini_file(get_file_base().'/themes/map.ini'):array();
  948.  
  949.         // Work out
  950.         if (!$skip_member_specific)
  951.         {
  952.             $member=get_member();
  953.             if ($member>0)
  954.                 $skin=$this->get_member_row_field($member,'user_style'); else $skin=0;
  955.             if ($skin>0) // User has a custom theme
  956.             {
  957.                 $phpbb=$this->connection->query_value_null_ok('themes','style_name',array('themes_id'=>$skin));
  958.                 if (!is_null($phpbb))
  959.                     $def=array_key_exists($phpbb,$map)?$map[$phpbb]:$phpbb;
  960.             }
  961.         }
  962.  
  963.         // Look for a skin according to our site name (we bother with this instead of 'default' because ocPortal itself likes to never choose a theme when forum-theme integration is on: all forum [via map] or all ocPortal seems cleaner, although it is complex)
  964.         if ((!(strlen($def)>0)) || (!file_exists(get_custom_file_base().'/themes/'.$def)))
  965.         {
  966.             $phpbb=$this->connection->query_value_null_ok('themes','style_name',array('style_name'=>get_site_name()));
  967.             if (!is_null($phpbb)) $def=array_key_exists($phpbb,$map)?$map[$phpbb]:$phpbb;
  968.         }
  969.  
  970.         // Default then!
  971.         if ((!(strlen($def)>0)) || (!file_exists(get_custom_file_base().'/themes/'.$def)))
  972.             $def=array_key_exists('default',$map)?$map['default']:'default';
  973.  
  974.         return $def;
  975.     }
  976.  
  977.     /**
  978.      * Find if the specified member id is marked as staff or not.
  979.      *
  980.      * @param  MEMBER           The member id
  981.      * @return boolean      Whether the member is staff
  982.      */
  983.     function _is_staff($member)
  984.     {
  985.         $user_level=$this->get_member_row_field($member,'user_level');
  986.         if ($user_level==1) return true;
  987.         return false;
  988.     }
  989.  
  990.     /**
  991.      * Find if the specified member id is marked as a super admin or not.
  992.      *
  993.      * @param  MEMBER           The member id
  994.      * @return boolean      Whether the member is a super admin
  995.      */
  996.     function _is_super_admin($member)
  997.     {
  998.         $user_level=$this->get_member_row_field($member,'user_level');
  999.         if ($user_level==1) return true;
  1000.         return false;
  1001.     }
  1002.  
  1003.     /**
  1004.      * If we can't get a list of admins via a usergroup query, we have to disable the staff filter - else the staff filtering can cause disaster at the point of being turned on (because it can't automatically sync).
  1005.      *
  1006.      * @return boolean      Whether to disable the staff filter
  1007.      */
  1008.     function _disable_staff_filter()
  1009.     {
  1010.         return true;
  1011.     }
  1012.  
  1013.     /**
  1014.      * Get the number of members currently online on the forums.
  1015.      *
  1016.      * @return integer      The number of members
  1017.      */
  1018.     function get_num_users_forums()
  1019.     {
  1020.         return $this->connection->query_value_null_ok_full('SELECT COUNT(*) FROM '.$this->connection->get_table_prefix().'sessions WHERE session_time>'.strval(time()-60*intval(get_option('users_online_time'))));
  1021.     }
  1022.  
  1023.     /**
  1024.      * Get the number of members registered on the forum.
  1025.      *
  1026.      * @return integer      The number of members
  1027.      */
  1028.     function get_members()
  1029.     {
  1030.         return $this->connection->query_value('users','COUNT(*)')-1;
  1031.     }
  1032.  
  1033.     /**
  1034.      * Get the total topics ever made on the forum.
  1035.      *
  1036.      * @return integer      The number of topics
  1037.      */
  1038.     function get_topics()
  1039.     {
  1040.         return $this->connection->query_value('topics','COUNT(*)');
  1041.     }
  1042.  
  1043.     /**
  1044.      * Get the total posts ever made on the forum.
  1045.      *
  1046.      * @return integer      The number of posts
  1047.      */
  1048.     function get_num_forum_posts()
  1049.     {
  1050.         return $this->connection->query_value('posts','COUNT(*)');
  1051.     }
  1052.  
  1053.     /**
  1054.      * Get the number of new forum posts.
  1055.      *
  1056.      * @return integer      The number of posts
  1057.      */
  1058.     function _get_num_new_forum_posts()
  1059.     {
  1060.         return $this->connection->query_value_null_ok_full('SELECT COUNT(*) FROM '.$this->connection->get_table_prefix().'posts WHERE post_time>'.strval(time()-60*60*24));
  1061.     }
  1062.  
  1063.     /**
  1064.      * Get a member id from the given member's username.
  1065.      *
  1066.      * @param  SHORT_TEXT   The member name
  1067.      * @return MEMBER           The member id
  1068.      */
  1069.     function get_member_from_username($name)
  1070.     {
  1071.         return $this->connection->query_value_null_ok('users','user_id',array('username'=>$name));
  1072.     }
  1073.  
  1074.     /**
  1075.      * Get the ids of the admin usergroups.
  1076.      *
  1077.      * @return array            The admin usergroup ids
  1078.      */
  1079.     function _get_super_admin_groups()
  1080.     {
  1081.         $admin_group=$this->connection->query_value_null_ok('groups','group_id',array('group_name'=>'Administrators'),'ORDER BY group_single_user DESC');
  1082.         if (is_null($admin_group)) return array();
  1083.         return array($admin_group);
  1084.     }
  1085.  
  1086.     /**
  1087.      * Get the ids of the moderator usergroups.
  1088.      * It should not be assumed that a member only has one usergroup - this depends upon the forum the driver works for. It also does not take the staff site filter into account.
  1089.      *
  1090.      * @return array            The moderator usergroup ids
  1091.      */
  1092.     function _get_moderator_groups()
  1093.     {
  1094.         $moderator_group=$this->connection->query_value_null_ok_full('SELECT group_id FROM '.$this->connection->get_table_prefix().'groups WHERE group_single_user=0 AND (group_name=\'Moderator\' OR group_name=\'Moderators\')');
  1095.         if (is_null($moderator_group)) return array();
  1096.         return array($moderator_group);
  1097.     }
  1098.  
  1099.     /**
  1100.      * Get the forum usergroup list.
  1101.      *
  1102.      * @return array            The usergroup list
  1103.      */
  1104.     function _get_usergroup_list()
  1105.     {
  1106.         $results=$this->connection->query('SELECT group_id,group_name FROM '.$this->connection->get_table_prefix().'groups WHERE group_single_user=0 OR group_id=1');
  1107.         $results2=collapse_2d_complexity('group_id','group_name',$results);
  1108.         return $results2;
  1109.     }
  1110.  
  1111.     /**
  1112.      * Get the forum usergroup relating to the specified member id.
  1113.      *
  1114.      * @param  MEMBER           The member id
  1115.      * @return array            The array of forum usergroups
  1116.      */
  1117.     function _get_members_groups($member)
  1118.     {
  1119.         if ($member==$this->get_guest_id()) return array(1);
  1120.  
  1121.         $groups=collapse_1d_complexity('group_id',$this->connection->query_select('user_group',array('group_id'),array('user_pending'=>0,'user_id'=>$member)));
  1122.         if (count($groups)<=1)
  1123.         {
  1124.             $all_groups=$this->get_usergroup_list();
  1125.             if (!array_key_exists($groups[0],$all_groups)) $groups[]=1;
  1126.         }
  1127.         return $groups;
  1128.     }
  1129.  
  1130.     /**
  1131.      * Create a member login cookie.
  1132.      *
  1133.      * @param  MEMBER           The member id
  1134.      * @param  ?SHORT_TEXT  The username (NULL: lookup)
  1135.      * @param  string           The password
  1136.      */
  1137.     function forum_create_cookie($id,$name,$password)
  1138.     {
  1139.         unset($name);
  1140.         unset($password);
  1141.  
  1142.         $member_cookie_name=get_member_cookie();
  1143.         $colon_pos=strpos($member_cookie_name,':');
  1144.         $base=substr($member_cookie_name,0,$colon_pos);
  1145.         $real_member_cookie=substr($member_cookie_name,$colon_pos+1);
  1146.         $real_pass_cookie=substr(get_pass_cookie(),$colon_pos+1);
  1147.  
  1148.         $hash=substr(uniqid(strval(mt_rand(0,32000)),true),0,17);
  1149.         $cookie=serialize(array($real_member_cookie=>strval($id),$real_pass_cookie=>$hash));
  1150.         $this->connection->query_insert('sessions',array('session_id'=>md5($hash),'session_user_id'=>$id,'session_ip'=>ip2long(get_ip_address()),'session_time'=>time()));
  1151.  
  1152.         ocp_setcookie($base,$cookie);
  1153.         $_COOKIE[$base]=$cookie;
  1154.     }
  1155.  
  1156.     /**
  1157.      * Find if the given member id and password is valid. If username is NULL, then the member id is used instead.
  1158.      * All authorisation, cookies, and form-logins, are passed through this function.
  1159.      * Some forums do cookie logins differently, so a Boolean is passed in to indicate whether it is a cookie login.
  1160.      *
  1161.      * @param  ?SHORT_TEXT  The member username (NULL: don't use this in the authentication - but look it up using the ID if needed)
  1162.      * @param  MEMBER           The member id
  1163.      * @param  MD5              The md5-hashed password
  1164.      * @param  string           The raw password
  1165.      * @param  boolean      Whether this is a cookie login
  1166.      * @return array            A map of 'id' and 'error'. If 'id' is NULL, an error occurred and 'error' is set
  1167.      */
  1168.     function forum_authorise_login($username,$userid,$password_hashed,$password_raw,$cookie_login=false)
  1169.     {
  1170.         $out=array();
  1171.         $out['id']=NULL;
  1172.  
  1173.         if (is_null($userid))
  1174.         {
  1175.             $rows=$this->connection->query_select('users',array('*'),array('username'=>$username),'',1);
  1176.             if (array_key_exists(0,$rows))
  1177.             {
  1178.                 $this->MEMBER_ROWS_CACHED[$rows[0]['user_id']]=$rows[0];
  1179.             }
  1180.         } else
  1181.         {
  1182.             $rows[0]=$this->get_member_row($userid);
  1183.         }
  1184.  
  1185.         if (!array_key_exists(0,$rows)) // All hands to lifeboats
  1186.         {
  1187.             $out['error']=(do_lang_tempcode('_USER_NO_EXIST',$username));
  1188.             return $out;
  1189.         }
  1190.         $row=$rows[0];
  1191.         if ($this->is_banned($row['user_id'])) // All hands to the guns
  1192.         {
  1193.             $out['error']=(do_lang_tempcode('USER_BANNED'));
  1194.             return $out;
  1195.         }
  1196.         if ($cookie_login)
  1197.         {
  1198.             $lookup=$this->connection->query_value_null_ok('sessions','session_user_id',array('session_id'=>md5($password_raw)));
  1199.             if ($row['user_id']!==$lookup)
  1200.             {
  1201.                 $out['error']=(do_lang_tempcode('USER_BAD_PASSWORD'));
  1202.                 return $out;
  1203.             }
  1204.         } else
  1205.         {
  1206.             if ($row['user_password']!=$password_hashed)
  1207.             {
  1208.                 $out['error']=(do_lang_tempcode('USER_BAD_PASSWORD'));
  1209.                 return $out;
  1210.             }
  1211.         }
  1212.  
  1213.         $pos=strpos(get_member_cookie(),'_data:userid');
  1214.         ocp_eatcookie(substr(get_member_cookie(),0,$pos).'_sid');
  1215.  
  1216.         $out['id']=$row['user_id'];
  1217.         return $out;
  1218.     }
  1219.  
  1220.     /**
  1221.      * Get a first known IP address of the given member.
  1222.      *
  1223.      * @param  MEMBER           The member id
  1224.      * @return IP               The IP address
  1225.      */
  1226.     function get_member_ip($member)
  1227.     {
  1228.         $ip=$this->connection->query_value_null_ok('posts','poster_ip',array('poster_id'=>$member));
  1229.         if (!is_null($ip)) return $this->_un_phpbb_ip($ip);
  1230.         return '';
  1231.     }
  1232.  
  1233.     /**
  1234.      * Gets a whole member row from the database.
  1235.      *
  1236.      * @param  MEMBER           The member id
  1237.      * @return ?array           The member row (NULL: no such member)
  1238.      */
  1239.     function get_member_row($member)
  1240.     {
  1241.         if (array_key_exists($member,$this->MEMBER_ROWS_CACHED)) return $this->MEMBER_ROWS_CACHED[$member];
  1242.  
  1243.         $rows=$this->connection->query_select('users',array('*'),array('user_id'=>$member),'',1);
  1244.         if (!array_key_exists(0,$rows)) return NULL;
  1245.         $this->MEMBER_ROWS_CACHED[$member]=$rows[0];
  1246.         return $this->MEMBER_ROWS_CACHED[$member];
  1247.     }
  1248.  
  1249.     /**
  1250.      * Gets a named field of a member row from the database.
  1251.      *
  1252.      * @param  MEMBER           The member id
  1253.      * @param  string           The field identifier
  1254.      * @return mixed            The field
  1255.      */
  1256.     function get_member_row_field($member,$field)
  1257.     {
  1258.         $row=$this->get_member_row($member);
  1259.         return is_null($row)?NULL:$row[$field];
  1260.     }
  1261.  
  1262. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement