Documentation is available at class.Chat.inc
- <?php //-*-php-*-
- /* ******************************************************************** **
- ** Copyright notice **
- ** **
- ** (c) 1995-2003 PHPOpenChat Development Team **
- ** http://phpopenchat.sourceforge.net/ **
- ** **
- ** All rights reserved **
- ** **
- ** This script is part of the PHPOpenChat project. The PHPOpenChat **
- ** project is free software; you can redistribute it and/or modify **
- ** it under the terms of the GNU General Public License as published by **
- ** the Free Software Foundation; either version 2 of the License, or **
- ** (at your option) any later version. **
- ** **
- ** The GNU General Public License can be found at **
- ** http://www.gnu.org/copyleft/gpl.html. **
- ** A copy is found in the textfile GPL and important notices to the **
- ** license from the team is found in the textfile LICENSE distributed **
- ** with these scripts. **
- ** **
- ** This script is distributed in the hope that it will be useful, **
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of **
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
- ** GNU General Public License for more details. **
- ** **
- ** This copyright notice MUST APPEAR in all copies of the script! **
- ** ******************************************************************** */
- //Get default values
- require_once(POC_BASE.'/config.inc.php');
- require_once(POC_INCLUDE_PATH.'/functions.inc');
- require_once(POC_INCLUDE_PATH.'/adodb/adodb.inc.php');
- require_once(POC_INCLUDE_PATH.'/class.Language.inc');
- require_once(POC_INCLUDE_PATH.'/class.Chatter.inc');
- require_once(POC_INCLUDE_PATH.'/class.Channel.inc');
- require_once(POC_INCLUDE_PATH.'/class.Line.inc');
- require_once(POC_INCLUDE_PATH.'/class.Channel_Buffer_'.CHANNEL_BUFFER_TYPE.'.inc');
- require_once(POC_INCLUDE_PATH.'/class.Logger.inc');
- require_once(POC_INCLUDE_PATH.'/class.Template.inc');
- /**
- * Chat describes the whole chat
- *
- * @package phpopenchat
- * @author Michael Oertel <michael@ortelius.de>
- * @access public
- * @version $Id: class.Chat.inc,v 1.91 2004/05/27 09:17:57 jjaeschke Exp $
- */
- class Chat {
- /**
- * @var string
- * @access public
- * @see Chat()
- */
- var $name = '';
- /**
- * @var integer
- * @see connect()
- * @see disconnect()
- */
- var $connection_count = 0;
- /**
- * Interface language of chat
- * @var string
- */
- var $language = '';
- /**
- * search string for nicknames
- * @var string
- */
- var $restrict = '';
- /**
- * referer
- * @var string
- */
- var $referer = '';
- /**
- * show profile flag
- * @var boolean
- */
- var $show_profile = true;
- /**
- * nicknames which will never die
- * @var array
- */
- var $deathless_chatters = array();
- /**
- * all supported languages
- * @var array
- */
- var $supported_languages = array();
- /**
- * Constructor.
- *
- * create a new chat object
- *
- * @param string $channel
- * @access public
- */
- function Chat( $name = CHAT_NAME, $supported_languages )
- {
- $lang = &new Language();
- //negotiate languages between HTTP_ACCEPT_LANGUAGE and $supported_languages
- //$possible_languages contains the result of negotiation
- $possible_languages = array();
- if( !$lang->get_list($supported_languages,$possible_languages) )
- {
- //no supported language in HTTP_ACCEPT_LANGUAGE found, so we take
- //the default language, the first entry in array $supported_languages,
- //defined in config.inc
- reset($supported_languages);
- $possible_languages = array();
- $possible_languages[current($supported_languages)] = '';
- }
- reset($possible_languages);
- $this->language = key($possible_languages);// $possible_languages are sorted by Q-factor and so we take the first one
- $this->name = $name;
- $this->supported_languages = $supported_languages;
- }
- /**
- * Gets language of the chat
- *
- * @access public
- * @return string interface language of chat
- */
- function get_language()
- {
- return $this->language;
- }
- /**
- * Provides the default language of the chat
- *
- * @access public
- * @return string
- */
- function get_default_language()
- {
- return $this->supported_languages[0];
- }
- function _check_flag( $lang )
- {
- $flag_dir = '/images/flags';
- $flag_path = $flag_dir.'/'.strtolower($lang).'.gif';
- if( file_exists($_SESSION['template']->get_tmpl_sys_path().$flag_path) )
- return '<img src="'.$_SESSION['template']->get_tmpl_web_path().$flag_path.'" align="middle" alt="'.$_SESSION['translator']->out('CHOOSE_LANGUAGE').'" width="24" hight="16" border="0" />';
- return $lang;
- }
- function get_lang_switch()
- {
- if( isset($_GET['language']) && in_array($_GET['language'], $this->supported_languages) )
- {
- $_SESSION['translator']->set_language($_GET['language']);
- $this->set_language($_GET['language']);
- }
- $content = '';
- reset($this->supported_languages);
- do
- {
- $cur_lang = current($this->supported_languages);
- if( $cur_lang == $this->get_language() )
- {/*$lang_switch .= '<strong>'.check_flag( $cur_lang ).'</strong> | ';*/}
- else
- $content .= '<a class="imageLink" href="'.$_SERVER['SCRIPT_NAME'].'?language='.$cur_lang.'&'.session_name().'='.session_id().'">'.$this->_check_flag( $cur_lang ).'</a> | ';
- }while(next($this->supported_languages));
- return substr( $content, 0, -2 );
- }
- /**
- * Sets primary language prefix of the chat
- *
- * @access public
- * @param string
- */
- function set_language( $primary_lang_prefix )
- {
- $this->language = $primary_lang_prefix;
- }
- /**
- * Gets referer
- *
- * @access public
- * @return string
- */
- function get_referer()
- {
- return $this->referer;
- }
- /**
- * Sets referer
- *
- * @access public
- * @param string
- */
- function set_referer( $referer )
- {
- $this->referer = $referer;
- }
- /**
- * Sets the show profile flag
- *
- * @access public
- * @param boolean
- */
- function set_show_profile( $bool = true )
- {
- $this->show_profile = $bool;
- }
- /**
- * Provides the show profile flag
- *
- * @access public
- * @return boolean
- */
- function get_show_profile()
- {
- return $this->show_profile;
- }
- /**
- * Sets dethless chatters
- *
- * @access public
- * @param array
- */
- function set_deathless_chatters( $deathless_chatters )
- {
- $this->deathless_chatters = $deathless_chatters;
- }
- /**
- * Connect to the database
- *
- * Establish a database connection
- *
- * @access public
- * @return boolean
- */
- function connect()
- {
- if( ++$this->connection_count > 1 )
- return true;
- //create a database object
- $this->db = &NewADOConnection( DATABASE_DRIVER );
- if( USE_PCONNECT )
- $status1 = $this->db->PConnect( DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, DATABASE_TABLESPACE );
- else
- $status1 = $this->db->Connect( DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, DATABASE_TABLESPACE );
- //$this->db->debug=1;
- $status2 = $this->db->Execute( 'SELECT THEME FROM poc_user_data' );
- return ( $status1 && $status2 );
- }
- /**
- * Creates a new instance of class channel within session
- *
- * @access public
- * @return boolean
- */
- function mkinstance_channel($post_channel)
- {
- $channel = &new Channel($post_channel);
- $_SESSION['channel'] = $channel;
- //test if someone posts a wrong channel name
- return ( is_null($_SESSION['channel']->get_name()) == false );
- }
- /**
- * Creates a new instance of class chatter
- *
- * @access public
- * @param string; a nickname of a chatter
- * @return mixed
- */
- function mkinstance_chatter($post_nickname, $force = false)
- {
- $_chatter = &new Chatter(STATUS_BOT_NAME);
- $_chatter->set_nick($post_nickname);
- return ( $_chatter->get_regTime() != '' || $force)? $_chatter:null;
- }
- /**
- * Writes a message from the system-bot to given recipient
- *
- * @access public
- * @param string; message to write
- * @param object; recipient
- * @return boolean
- */
- function write_sys_msg( $message, $recipient, $whispered = false, $hidden = false )
- {
- $_chatter = &new Chatter(STATUS_BOT_NAME);
- $line = &new Line( $_chatter, $message);
- unset($_chatter);
- if( is_object($recipient) )
- $line->set_recipient( $recipient );
- else return false;
- $line->filter_buffer_input();
- if($whispered) {
- $line->set_whispered();
- $line->set_info();
- }
- if( $hidden ) {
- //echo 'line is set to hidden';
- $line->set_hidden();
- }
- if( isset($_SESSION['channel_buffer']) && is_object($_SESSION['channel_buffer']) ) {
- $_SESSION['channel_buffer']->connect();
- $_SESSION['channel_buffer']->put_line($line);
- $_SESSION['channel_buffer']->disconnect();
- } else {
- return false;
- }
- return true;
- }
- /**
- * Writes javascript code to update clients
- *
- * @access public
- * @param string; message to write
- * @param object; recipient
- * @return boolean
- */
- function write_js_update( $message, $recipient = null )
- {
- /*
- if(!preg_match('/^.*$/', $message) ) {
- $_SESSION['logger']->warning(__CLASS__.'::'.__FUNCTION__.' was missused!');
- return false;
- }*/
- $message = preg_replace('#</script>#i', '<\\/script>', $message);
- $message = preg_replace('/\r\n|\n|\r/', '', $message);
- $_chatter = &new Chatter(STATUS_BOT_NAME);
- $line = &new Line( $_chatter, $message);
- if( $recipient == null ) {
- $line->set_hidden_javascript_update();//this will get every chatter in the same channel
- $line->set_recipient($_chatter);//recipient doesn't matter
- } else {
- $line->set_recipient($recipient);
- $line->set_whispered();
- $line->set_info();
- $line->set_hidden();
- }
- unset($_chatter);
- $line->filter_buffer_input();
- //
- if( isset($_SESSION['channel_buffer']) && is_object($_SESSION['channel_buffer']) ) {
- $_SESSION['channel_buffer']->connect();
- $_SESSION['channel_buffer']->put_line($line);
- $_SESSION['channel_buffer']->disconnect();
- } else {
- return false;
- }
- return true;
- }
- /**
- * Disconnect the database
- *
- * @access public
- * @see connect()
- */
- function disconnect()
- {
- if( --$this->connection_count == 0 ) {
- $this->db->Close();
- return true;
- }
- return null;
- }
- /**
- * Sets the confirm code to null
- *
- * @access public
- * @param string
- * @return boolean
- */
- function confirm( $code )
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- $record = array();
- $record[ 'CONFIRM_CODE' ] = 'null';
- $rs = $this->db->Execute( 'SELECT CONFIRM_CODE FROM poc_user_account WHERE CONFIRM_CODE=\''.$code.'\'' );
- $update_sql = $this->db->GetUpdateSQL( $rs, $record );
- unset($record);
- unset($rs);
- $this->db->Execute( $update_sql );
- unset($update_sql);
- return ( $this->db->Affected_Rows() === 1 );
- }
- function set_operator_passwd()
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- $rs = $this->db->Execute( 'SELECT USER FROM poc_user_account WHERE USER=\'operator\' AND PASSWORD=\'\'' );
- if( $rs->RecordCount() == 0 ) {
- return '';
- } else {
- $operator_passwd = substr(md5( strval(rand(10000,99999)) ),0,PASSWORD_MIN_LENGTH);
- $record = array();
- $record[ 'PASSWORD' ] =(MD5_PASSWORDS)? md5($operator_passwd):$operator_passwd;
- $rs = $this->db->Execute( 'SELECT PASSWORD FROM poc_user_account WHERE USER=\'operator\'' );
- $update_sql = $this->db->GetUpdateSQL( $rs, $record );
- unset($record);
- unset($rs);
- return ( $this->db->Execute( $update_sql ) )? $operator_passwd:'';
- }
- }
- /**
- * Creates a private channel
- *
- * @access public
- * @param string
- * @return void
- */
- function create_private_channel( $channel_name )
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- $record = array();
- $record[ 'NAME' ] = $channel_name;
- $record[ 'MAX_LINE_NUMBER' ] = CB_MAX_LINE;
- $record[ 'TYPE' ] = 2; //type=2 it's a private channel
- $rs = $this->db->Execute( 'SELECT NAME,MAX_LINE_NUMBER,TYPE FROM poc_channels' );
- $insert_sql = $this->db->GetInsertSQL( $rs, $record );
- unset($record);
- unset($rs);
- //Insert the records into the database
- $this->db->Execute( $insert_sql );
- unset($insert_sql);
- //initialize the channel buffer
- $_SESSION['channel_buffer']->init($channel_name);
- //invite the owner of this private channel
- $_SESSION['chatter']->invite( $_SESSION['chatter']->get_nick() );
- }
- /**
- * Creates a channel (default, moderated)
- *
- * @access public
- * @param string
- * @param integer
- * @return boolean
- */
- function create_channel( $name, $type, $passwd, $message )
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- if( $name == '' || $type > 1 ) return false;
- function create_channel_error($errno, $errmsg, $filename, $linenum, $vars)
- {
- $_SESSION['logger']->error('Could not create channel!', $filename, $linenum);
- return false;
- }
- $record = array();
- $record[ 'NAME' ] = $name;
- $record[ 'MAX_LINE_NUMBER' ] = CB_MAX_LINE;
- $record[ 'TYPE' ] = $type; //type=0 it's a default channel
- $record[ 'PASSWORD' ] = $passwd;
- $record[ 'MESSAGE' ] = $message;
- //type=1 it's a moderated channel
- $rs = $this->db->Execute( 'SELECT NAME,MAX_LINE_NUMBER,TYPE,PASSWORD,MESSAGE FROM poc_channels' );
- $insert_sql = $this->db->GetInsertSQL( $rs, $record );
- unset($record);
- unset($rs);
- //Insert the records into the database
- set_error_handler('create_channel_error');
- $this->db->Execute( $insert_sql );
- restore_error_handler();
- unset($insert_sql);
- //initialize the channel buffer
- $channel_buffer = &new Channel_Buffer($name);
- $channel_buffer->init();
- unset($channel_buffer);
- return true;
- }
- /**
- * Creates a channel (default, moderated)
- *
- * @access public
- * @param string
- * @param integer
- * @return void
- */
- function update_channel( $name, $type, $passwd, $message )
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- if( $type > 1 ) return false;
- function update_channel_error($errno, $errmsg, $filename, $linenum, $vars)
- {
- $_SESSION['logger']->error('Could not update channel!', $filename, $linenum);
- return false;
- }
- $record = array();
- $record[ 'TYPE' ] = $type; //type=0 it's a default channel
- $record[ 'PASSWORD' ] = $passwd;
- $record[ 'MESSAGE' ] = $message;
- //type=1 it's a moderated channel
- $rs = $this->db->Execute( 'SELECT TYPE, PASSWORD, MESSAGE FROM poc_channels WHERE NAME = \''.$name.'\'' );
- $update_sql = $this->db->GetUpdateSQL( $rs, $record );
- unset($record);
- unset($rs);
- //Insert the records into the database
- set_error_handler('update_channel_error');
- $this->db->Execute( $update_sql );
- restore_error_handler();
- unset($update_sql);
- return true;
- }
- /**
- * Deletes a channel
- *
- * @access public
- * @param string
- * @return boolean
- */
- function delete_channel( $channel_name )
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- //remove channel
- $rs = $this->db->Execute( 'DELETE FROM poc_channels WHERE NAME=\''.$channel_name.'\'' );
- $rows_effected = $this->db->Affected_Rows();
- if( CHANNEL_BUFFER_TYPE == 'DB' ) {
- //remove the dependent channel buffer if necessary
- $rs = $this->db->Execute( 'DELETE FROM poc_line_buffer WHERE NAME=\''.$channel_name.'\'' );
- $rows_effected += $this->db->Affected_Rows();
- unset($rs);
- return( $rows_effected == 2 );
- } elseif( CHANNEL_BUFFER_TYPE == 'MEM' ) {
- //TODO: cleanup the shared memory, if necessary...
- unset($rs);
- return ( $rows_effected == 1 );
- } else {
- //other buffer types may doesn't need any clean up
- unset($rs);
- return ( $rows_effected == 1 );
- }
- }
- /**
- * initialisation of channel_buffers
- *
- * @access public
- * @return void
- * @see create_channel()
- * @see create_private_channel()
- */
- function init_channel_buffers()
- {
- return null;
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- $channels = array();
- $channels = $this->get_channels();
- reset($channels);
- do{
- $_SESSION['channel_buffer']->init( current($channels) );
- }while( next($channels) );
- }
- function move_channel_to_top( $channel )
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- $channels = array();
- $channels = $this->get_channels();
- unset( $channels[array_search($channel,$channels)] );
- $channels=array_reverse ($channels);
- $channels[]=$channel;
- $channels=array_reverse($channels);
- foreach($channels as $key => $value)
- {
- $rs = $this->db->Execute( 'UPDATE poc_channels SET ORDER_IDX = '.$key.' WHERE NAME=\''.$value.'\'' );
- }
- }
- /**
- * Gets all the channels as an option list specially for select boxes in the chat
- *
- * @param int $current_channel
- * @access public
- * @return string
- */
- function get_channels_option_list( $current_channel = '')
- {
- if( $this->connection_count == 0 )
- die('Not connected! Use connect() first!');
- //Get a list of all channels except for private channels
- //ordinary channel: TYPE = NULL
- //moderated channel: TYPE = 1
- //private channel: TYPE = 2
- $rs1 = $this->db->Execute( 'SELECT NAME,INVITED,TYPE, 0 AS COUNT FROM poc_channels ORDER BY ORDER_IDX' );
- $rs2 = $this->db->Execute( 'SELECT c.NAME AS NAME,
- c.INVITED AS INVITED,
- c.TYPE AS TYPE,
- COUNT(c.NAME) AS COUNT
- FROM poc_user_data d,
- poc_channels c
- WHERE ONLINE = \'1\'
- AND LAST_CHANNEL = c.NAME
- GROUP BY c.NAME
- ORDER BY ORDER_IDX');
- $channels = array_merge($rs1->GetAssoc(),$rs2->GetAssoc());
- $rs1->Close();
- $rs2->Close();
- unset($rs1);
- unset($rs2);
- $option_list = '';
- $option_list_of_public_channels = '';
- $option_list_of_moderated_channels = '';
- $option_list_of_private_channels = '';
- foreach ( $channels as $current )
- {
- $occupancy = ' ('.$current['COUNT'].'/'.MAX_CONCURRENT_CHATTER.')';
- $current_value = $current['NAME'];
- $disabled = '';
- if( $current['COUNT'] >= MAX_CONCURRENT_CHATTER )
- {
- $occupancy = ' ('.$_SESSION['translator']->out('FULL').')';
- if( isset($_SESSION['channel'])
- && $_SESSION['channel']->get_name() == $current['NAME'] )
- {}
- elseif(!isset($_SESSION['channel_buffer'])) continue;
- else
- {
- $current_value = '';
- $disabled = 'disabled="disabled"';
- }
- }
- if( $current['NAME'] == $current_channel )
- $selected = 'selected="selected"';
- else
- $selected = '';
- $chatters_invited_into = array();
- if( $current['TYPE'] == 2 && is_string($current['INVITED']) ) {
- $chatters_invited_into = unserialize($current['INVITED']);
- if( !is_array($chatters_invited_into) ) $chatters_invited_into = array();
- }
- //add private channels if invited and it's not a call from the login form
- //if( !is_null($chatters_invited_into) &&
- if( $current_channel != '' &&
- isset($_SESSION['chatter']) && in_array($_SESSION['chatter']->get_nick(),$chatters_invited_into) )
- {
- $option_list_of_private_channels .= TAB.'<option value="'.$current_value.'" '.$selected.' '.$disabled.'>';
- $option_list_of_private_channels .= preg_replace( "/\#{3}([^#]*)\#{3}/e", "\$_SESSION['translator']->out('\\1')", $current['NAME'] );
- $option_list_of_private_channels .= $occupancy.'</option>'.NL;
- }
- //if( is_null($chatters_invited_into) )
- if( count($chatters_invited_into) == 0 && $current['TYPE'] < 2 )
- {
- if( isset($_SESSION['chatter']) && $_SESSION['chatter']->is_banned( $current['NAME']) )
- {}
- elseif( $current['TYPE'] == 1 )
- $option_list_of_moderated_channels .= TAB.'<option value="'.$current_value.'" '.$selected.' '.$disabled.'>'.$current['NAME'].$occupancy.'</option>'.NL;
- else
- $option_list_of_public_channels .= TAB.'<option value="'.$current_value.'" '.$selected.' '.$disabled.'>'.$current['NAME'].$occupancy.'</option>'.NL;
- }
- }
- unset($selected);
- if( $option_list_of_public_channels != '' )
- {
- $option_list .= '<optgroup label="'.$_SESSION['translator']->out('PUBLIC_CHANNEL').'">'.NL;
- $option_list .= $option_list_of_public_channels;
- $option_list .= TAB.TAB.'</optgroup>'.NL;
- }
- if( $option_list_of_moderated_channels != '' )
- {
- $option_list .= '<optgroup label="'.$_SESSION['translator']->out('MODERATED_CHANNEL').'">'.NL;
- $option_list .= $option_list_of_moderated_channels;
- $option_list .= TAB.TAB.'</optgroup>'.NL;
- }
- if( $option_list_of_private_channels != '' )
- {
- $option_list .= '<optgroup label="'.$_SESSION['translator']->out('PRIVATE_CHANNEL').'">'.NL;
- $option_list .= $option_list_of_private_channels;
- $option_list .=