"user", $kind_agent => "agent", $kind_for_agent => "hidden", $kind_info => "inf", $kind_conn => "conn", $kind_events => "event", $kind_avatar => "avatar" ); function get_user_id() { return (time() + microtime()).rand(0,99999999); } function next_token() { return rand(99999,99999999); } function next_revision($link) { perform_query("update chatrevision set id=LAST_INSERT_ID(id+1)",$link); $val = mysql_insert_id($link); return $val; } function post_message_($threadid,$kind,$message,$link,$from=null,$utime=null,$opid=null) { $query = sprintf( "insert into chatmessage (threadid,ikind,tmessage,tname,agentId,dtmcreated) values (%s, %s,'%s',%s,%s,%s)", $threadid, $kind, mysql_real_escape_string($message,$link), $from ? "'".mysql_real_escape_string($from,$link)."'" : "null", $opid ? $opid : "0", $utime ? "FROM_UNIXTIME($utime)" : "CURRENT_TIMESTAMP" ); perform_query($query,$link); return mysql_insert_id($link); } function post_message($threadid,$kind,$message,$from=null,$agentid=null) { $link = connect(); $id = post_message_($threadid,$kind,$message,$link,$from,null,$agentid); mysql_close($link); return $id; } function prepare_html_message($text) { $escaped_text = htmlspecialchars($text); $text_w_links = preg_replace('/(http|ftp):\/\/\S*/','$0',$escaped_text); $multiline = str_replace("\n","
",$text_w_links); return $multiline; } function message_to_html($msg) { global $kind_to_string, $kind_avatar; if( $msg['ikind'] == $kind_avatar ) return ""; $message = "".date("H:i:s",$msg['created'])." "; $kind = $kind_to_string{$msg['ikind']}; if( $msg['tname'] ) $message.= "".htmlspecialchars($msg['tname']).": "; $message.= "".prepare_html_message($msg['tmessage'])."
"; return $message; } function message_to_text($msg) { global $kind_user, $kind_agent, $kind_info, $kind_avatar; if( $msg['ikind'] == $kind_avatar ) return ""; $message_time = date("H:i:s ",$msg['created']); if($msg['ikind'] == $kind_user || $msg['ikind'] == $kind_agent) { if( $msg['tname'] ) return $message_time.$msg['tname'].": ".$msg['tmessage']."\n"; else return $message_time.$msg['tmessage']."\n"; } else if($msg['ikind'] == $kind_info ) { return $message_time.$msg['tmessage']."\n"; } else { return $message_time."[".$msg['tmessage']."]\n"; } } function get_messages($threadid,$meth,$isuser,&$lastid) { global $kind_for_agent, $kind_avatar, $webim_encoding; $link = connect(); $query = sprintf( "select messageid,ikind,unix_timestamp(dtmcreated) as created,tname,tmessage from chatmessage ". "where threadid = %s and messageid > %s %s order by messageid", $threadid, $lastid, $isuser ? "and ikind <> $kind_for_agent" : "" ); $messages = array(); $msgs = select_multi_assoc($query, $link); foreach ($msgs as $msg) { $message = ""; if ($meth == 'xml') { switch ($msg['ikind']) { case $kind_avatar: $message = "".myiconv($webim_encoding,"utf-8",escape_with_cdata($msg['tmessage'])).""; break; default: $message = "".myiconv($webim_encoding,"utf-8",escape_with_cdata(message_to_html($msg)))."\n"; } } else { if ($msg['ikind'] != $kind_avatar) { $message = (($meth == 'text') ? message_to_text($msg) : topage(message_to_html($msg))); } } $messages[] = $message; if( $msg['messageid'] > $lastid ) { $lastid = $msg['messageid']; } } mysql_close($link); return $messages; } function print_thread_messages($thread, $token, $lastid, $isuser, $format, $agentid=null) { global $webim_encoding, $webimroot, $connection_timeout, $settings; $threadid = $thread['threadid']; $istyping = abs($thread['current']-$thread[$isuser ? "lpagent" : "lpuser"]) < $connection_timeout && $thread[$isuser?"agentTyping":"userTyping"] == "1" ? "1" : "0"; if( $format == "xml" ) { $output = get_messages($threadid,"xml",$isuser,$lastid); start_xml_output(); print(""); foreach( $output as $msg ) { print $msg; } print(""); } else if( $format == "html" ) { loadsettings(); $output = get_messages($threadid,"html",$isuser,$lastid); start_html_output(); $url = "$webimroot/thread.php?act=refresh&thread=$threadid&token=$token&html=on&user=".($isuser?"true":"false"); print( "". "\n\n". "\n". "\n". "\n". "chat\n". "\n". "". "
" ); foreach( $output as $msg ) { print $msg; } print( "
". "" ); } } function get_user_name($username, $addr, $id) { global $settings; loadsettings(); return str_replace("{addr}", $addr, str_replace("{id}", $id, str_replace("{name}", $username, $settings['usernamepattern']))); } function is_ajax_browser($browserid,$ver,$useragent) { if( $browserid == "opera" ) return $ver >= 8.02; if( $browserid == "safari" ) return $ver >= 125; if( $browserid == "msie" ) return $ver >= 5.5 && !strstr($useragent, "powerpc"); if( $browserid == "netscape" ) return $ver >= 7.1; if( $browserid == "mozilla") return $ver >= 1.4; if( $browserid == "firefox") return $ver >= 1.0; if( $browserid == "chrome") return true; return false; } function is_old_browser($browserid,$ver) { if( $browserid == "opera" ) return $ver < 7.0; if( $browserid == "msie" ) return $ver < 5.0; return false; } $knownAgents = array("opera","msie","chrome","safari","firefox","netscape","mozilla"); function get_remote_level($useragent) { global $knownAgents; $useragent = strtolower($useragent); foreach( $knownAgents as $agent ) { if( strstr($useragent,$agent) ) { if( preg_match( "/".$agent."[\\s\/]?(\\d+(\\.\\d+)?)/", $useragent, $matches ) ) { $ver = $matches[1]; if( is_ajax_browser($agent,$ver,$useragent) ) return "ajaxed"; else if( is_old_browser($agent,$ver) ) return "old"; return "simple"; } } } return "simple"; } function is_agent_opera95() { $useragent = strtolower($_SERVER['HTTP_USER_AGENT']); if( strstr($useragent,"opera") ) { if( preg_match( "/opera[\\s\/]?(\\d+(\\.\\d+)?)/", $useragent, $matches ) ) { $ver = $matches[1]; if ($ver >= "9.5") return true; } } return false; } function is_mac_opera() { $useragent = strtolower($_SERVER['HTTP_USER_AGENT']); return strstr($useragent,"opera") && strstr($useragent, "mac"); } function needsFramesrc() { $useragent = strtolower($_SERVER['HTTP_USER_AGENT']); return strstr($useragent,"safari/"); } function setup_logo() { global $page, $settings; loadsettings(); $page['ct.company.name'] = topage($settings['title']); $page['ct.company.chatLogoURL'] = topage($settings['logo']); $page['webimHost'] = topage($settings['hosturl']); } function setup_leavemessage($name, $email, $message, $groupid, $groupname, $info, $referrer,$canshowcaptcha) { global $settings, $page; $page['formname'] = topage($name); $page['formemail'] = topage($email); $page['formmessage'] = $message ? topage($message) : ""; $page['showcaptcha'] = $settings["enablecaptcha"] == "1" && $canshowcaptcha ? "1" : ""; $page['formgroupid'] = $groupid; $page['formgroupname'] = $groupname; $page['info'] = topage($info); $page['referrer'] = urlencode(topage($referrer)); } function setup_survey($name, $email, $groupid, $info, $referrer) { global $settings, $page; $page['formname'] = topage($name); $page['formemail'] = topage($email); $page['formgroupid'] = $groupid; $page['forminfo'] = topage($info); $page['referrer'] = urlencode(topage($referrer)); if($settings['enablegroups'] == '1' && $settings["surveyaskgroup"] == "1") { $link = connect(); $allgroups = get_groups($link,false); mysql_close($link); $val = ""; foreach($allgroups as $k) { $groupname = $k['vclocalname']; if($k['inumofagents'] == 0) { continue; } if($k['ilastseen'] !== NULL && $k['ilastseen'] < $settings['online_timeout']) { if(!$groupid) { $groupid = $k['groupid']; // select first online group } } else { $groupname .= " (offline)"; } $isselected = $k['groupid'] == $groupid; $val .= ""; } $page['groups'] = $val; } $page['showemail'] = $settings["surveyaskmail"] == "1" ? "1" : ""; $page['showmessage'] = $settings["surveyaskmessage"] == "1" ? "1" : ""; $page['showname'] = $settings['usercanchangename'] == "1" ? "1" : ""; } function setup_chatview_for_user($thread,$level) { global $page, $webimroot, $settings; loadsettings(); $page = array(); $page['agent'] = false; $page['user'] = true; $page['canpost'] = true; $nameisset = getstring("chat.default.username") != $thread['userName']; $page['displ1'] = $nameisset ? "none" : "inline"; $page['displ2'] = $nameisset ? "inline" : "none"; $page['level'] = $level; $page['ct.chatThreadId'] = $thread['threadid']; $page['ct.token'] = $thread['ltoken']; $page['ct.user.name'] = htmlspecialchars(topage($thread['userName'])); $page['canChangeName'] = $settings['usercanchangename'] == "1"; $page['chat.title'] = topage($settings['chattitle']); setup_logo(); if($settings['sendmessagekey'] == 'enter') { $page['send_shortcut'] = "Enter"; $page['ignorectrl'] = 1; } else { $page['send_shortcut'] = is_mac_opera() ? "⌘-Enter" : "Ctrl-Enter"; $page['ignorectrl'] = 0; } $params = "thread=".$thread['threadid']."&token=".$thread['ltoken']; $page['mailLink'] = "$webimroot/client.php?".$params."&level=$level&act=mailthread"; if($settings['enablessl'] == "1" && !is_secure_request()) { $page['sslLink'] = get_app_location(true, true)."/client.php?".$params."&level=$level"; } $page['isOpera95'] = is_agent_opera95(); $page['neediframesrc'] = needsFramesrc(); $page['frequency'] = $settings['updatefrequency_chat']; } function load_canned_messages($locale, $groupid) { $link = connect(); $result = select_multi_assoc( "select vcvalue from chatresponses where locale = '".$locale."' ". "AND (groupid is NULL OR groupid = 0) order by vcvalue", $link); if(count($result) == 0) { foreach(explode("\n", getstring_('chat.predefined_answers', $locale)) as $answer) { $result[] = array('vcvalue' => $answer); } } if($groupid) { $result2 = select_multi_assoc( "select vcvalue from chatresponses where locale = '".$locale."' ". "AND groupid = $groupid order by vcvalue", $link); foreach($result as $r) { $result2[] = $r; } $result = $result2; } mysql_close($link); return $result; } function setup_chatview_for_operator($thread,$operator) { global $page, $webimroot, $company_logo_link, $company_name, $settings; loadsettings(); $page = array(); $page['agent'] = true; $page['user'] = false; $page['canpost'] = $thread['agentId'] == $operator['operatorid']; $page['ct.chatThreadId'] = $thread['threadid']; $page['ct.token'] = $thread['ltoken']; $page['ct.user.name'] = htmlspecialchars(topage(get_user_name($thread['userName'],$thread['remote'],$thread['userid']))); $page['chat.title'] = topage($settings['chattitle']); setup_logo(); if($settings['sendmessagekey'] == 'enter') { $page['send_shortcut'] = "Enter"; $page['ignorectrl'] = 1; } else { $page['send_shortcut'] = is_mac_opera() ? "⌘-Enter" : "Ctrl-Enter"; $page['ignorectrl'] = 0; } if($settings['enablessl'] == "1" && !is_secure_request()) { $page['sslLink'] = get_app_location(true, true)."/operator/agent.php?thread=".$thread['threadid']."&token=".$thread['ltoken']; } $page['isOpera95'] = is_agent_opera95(); $page['neediframesrc'] = needsFramesrc(); $page['historyParams'] = array("userid" => "".$thread['userid']); $page['historyParamsLink'] = add_params($webimroot."/operator/userhistory.php",$page['historyParams']); $predefinedres = ""; $canned_messages = load_canned_messages($thread['locale'], $thread['groupid']); foreach($canned_messages as $answer) { $predefinedres .= ""; } $page['predefinedAnswers'] = $predefinedres; $params = "thread=".$thread['threadid']."&token=".$thread['ltoken']; $page['redirectLink'] = "$webimroot/operator/agent.php?".$params."&act=redirect"; $page['namePostfix'] = ""; $page['frequency'] = $settings['updatefrequency_chat']; } function update_thread_access($threadid, $params, $link) { $clause = ""; foreach( $params as $k => $v ) { if( strlen($clause) > 0 ) $clause .= ", "; $clause .= $k."=".$v; } perform_query( "update chatthread set $clause ". "where threadid = ".$threadid,$link); } function ping_thread($thread, $isuser,$istyping) { global $kind_for_agent, $state_queue, $state_loading, $state_chatting, $state_waiting, $kind_conn, $connection_timeout; $link = connect(); $params = array(($isuser ? "lastpinguser" : "lastpingagent") => "CURRENT_TIMESTAMP", ($isuser ? "userTyping" : "agentTyping") => ($istyping? "1" : "0") ); $lastping = $thread[$isuser ? "lpagent" : "lpuser"]; $current = $thread['current']; if( $thread['istate'] == $state_loading && $isuser) { $params['istate'] = $state_queue; commit_thread($thread['threadid'], $params, $link); mysql_close($link); return; } if( $lastping > 0 && abs($current-$lastping) > $connection_timeout ) { $params[$isuser ? "lastpingagent" : "lastpinguser"] = "0"; if( !$isuser ) { $message_to_post = getstring_("chat.status.user.dead", $thread['locale']); post_message_($thread['threadid'],$kind_for_agent,$message_to_post,$link,null,$lastping+$connection_timeout); } else if( $thread['istate'] == $state_chatting ) { $message_to_post = getstring_("chat.status.operator.dead", $thread['locale']); post_message_($thread['threadid'],$kind_conn,$message_to_post,$link,null,$lastping+$connection_timeout); $params['istate'] = $state_waiting; $params['nextagent'] = 0; commit_thread($thread['threadid'], $params, $link); mysql_close($link); return; } } update_thread_access($thread['threadid'], $params, $link); mysql_close($link); } function commit_thread($threadid,$params,$link) { $query = "update chatthread t set lrevision = ".next_revision($link).", dtmmodified = CURRENT_TIMESTAMP"; foreach( $params as $k => $v ) { $query .= ", ".$k."=".$v; } $query .= " where threadid = ".$threadid; perform_query($query,$link); } function rename_user($thread, $newname) { global $kind_events; $link = connect(); commit_thread( $thread['threadid'], array('userName' => "'".mysql_real_escape_string($newname,$link)."'"), $link); if( $thread['userName'] != $newname ) { post_message_($thread['threadid'],$kind_events, getstring2_("chat.status.user.changedname",array($thread['userName'], $newname), $thread['locale']), $link); } mysql_close($link); } function close_thread($thread,$isuser) { global $state_closed, $kind_events; $link = connect(); if( $thread['istate'] != $state_closed ) { commit_thread( $thread['threadid'], array('istate' => $state_closed, 'messageCount' => '(SELECT COUNT(*) FROM chatmessage WHERE chatmessage.threadid = t.threadid AND ikind = 1)'), $link); } $message = $isuser ? getstring2_("chat.status.user.left", array($thread['userName']), $thread['locale']) : getstring2_("chat.status.operator.left", array($thread['agentName']), $thread['locale']); post_message_($thread['threadid'], $kind_events, $message, $link); mysql_close($link); } function thread_by_id_($id,$link) { return select_one_row("select threadid,userName,agentName,agentId,lrevision,istate,ltoken,userTyping,agentTyping". ",unix_timestamp(dtmmodified) as modified, unix_timestamp(dtmcreated) as created". ",remote,referer,locale,unix_timestamp(lastpinguser) as lpuser,unix_timestamp(lastpingagent) as lpagent, unix_timestamp(CURRENT_TIMESTAMP) as current,nextagent,shownmessageid,userid,userAgent,groupid". " from chatthread where threadid = ". $id, $link ); } function ban_for_addr_($addr,$link) { return select_one_row("select banid,comment from chatban where unix_timestamp(dtmtill) > unix_timestamp(CURRENT_TIMESTAMP) AND address = '".mysql_real_escape_string($addr,$link)."'", $link ); } function thread_by_id($id) { $link = connect(); $thread = thread_by_id_($id,$link); mysql_close($link); return $thread; } function create_thread($groupid,$username,$remoteHost,$referer,$lang,$userid,$userbrowser,$initialState,$link) { $query = sprintf( "insert into chatthread (userName,userid,ltoken,remote,referer,lrevision,locale,userAgent,dtmcreated,dtmmodified,istate".($groupid?",groupid":"").") values ". "('%s','%s',%s,'%s','%s',%s,'%s','%s',CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,$initialState".($groupid?",$groupid":"").")", mysql_real_escape_string($username, $link), mysql_real_escape_string($userid, $link), next_token(), mysql_real_escape_string($remoteHost, $link), mysql_real_escape_string($referer, $link), next_revision($link), mysql_real_escape_string($lang, $link), mysql_real_escape_string($userbrowser, $link)); perform_query($query,$link); $id = mysql_insert_id($link); $newthread = thread_by_id_($id,$link); return $newthread; } function do_take_thread($threadid,$operatorId,$operatorName) { global $state_chatting; $link = connect(); commit_thread( $threadid, array("istate" => $state_chatting, "nextagent" => 0, "agentId" => $operatorId, "agentName" => "'".mysql_real_escape_string($operatorName, $link)."'"), $link); mysql_close($link); } function reopen_thread($threadid) { global $state_queue,$state_loading,$state_waiting,$state_chatting,$state_closed,$state_left,$kind_events; $link = connect(); $thread = thread_by_id_($threadid, $link); if( !$thread ) return FALSE; if( $thread['istate'] == $state_closed || $thread['istate'] == $state_left ) return FALSE; if( $thread['istate'] != $state_chatting && $thread['istate'] != $state_queue && $thread['istate'] != $state_loading ) { commit_thread( $threadid, array("istate" => $state_waiting, "nextagent" => 0), $link); } post_message_($thread['threadid'], $kind_events, getstring_("chat.status.user.reopenedthread", $thread['locale']), $link); mysql_close($link); return $thread; } function take_thread($thread,$operator) { global $state_queue, $state_loading, $state_waiting, $state_chatting, $kind_events, $kind_avatar, $home_locale; $state = $thread['istate']; $threadid = $thread['threadid']; $message_to_post = ""; $operatorName = ($thread['locale'] == $home_locale) ? $operator['vclocalename'] : $operator['vccommonname']; if( $state == $state_queue || $state == $state_waiting || $state == $state_loading) { do_take_thread($threadid, $operator['operatorid'], $operatorName); if( $state == $state_waiting ) { if( $operatorName != $thread['agentName'] ) { $message_to_post = getstring2_("chat.status.operator.changed", array($operatorName, $thread['agentName']), $thread['locale']); } else { $message_to_post = getstring2_("chat.status.operator.returned", array($operatorName), $thread['locale']); } } else { $message_to_post = getstring2_("chat.status.operator.joined", array($operatorName), $thread['locale']); } } else if( $state == $state_chatting ) { if( $operator['operatorid'] != $thread['agentId'] ) { do_take_thread($threadid, $operator['operatorid'], $operatorName); $message_to_post = getstring2_("chat.status.operator.changed", array($operatorName, $thread['agentName']), $thread['locale']); } } else { die("cannot take thread"); } if( $message_to_post ) { post_message($threadid,$kind_events,$message_to_post); post_message($threadid,$kind_avatar,$operator['vcavatar'] ? $operator['vcavatar'] : ""); } } function check_for_reassign($thread,$operator) { global $state_waiting, $home_locale, $kind_events, $kind_avatar; $operatorName = ($thread['locale'] == $home_locale) ? $operator['vclocalename'] : $operator['vccommonname']; if( $thread['istate'] == $state_waiting && ( $thread['nextagent'] == $operator['operatorid'] || $thread['agentId'] == $operator['operatorid'] )) { do_take_thread($thread['threadid'], $operator['operatorid'], $operatorName); if( $operatorName != $thread['agentName'] ) { $message_to_post = getstring2_("chat.status.operator.changed", array($operatorName, $thread['agentName']), $thread['locale']); } else { $message_to_post = getstring2_("chat.status.operator.returned", array($operatorName), $thread['locale']); } post_message($thread['threadid'],$kind_events,$message_to_post); post_message($thread['threadid'],$kind_avatar,$operator['vcavatar'] ? $operator['vcavatar'] : ""); } } function check_connections_from_remote($remote,$link) { global $settings, $state_closed, $state_left; if($settings['max_connections_from_one_host'] == 0) { return true; } $result = select_one_row( "select count(*) as opened from chatthread ". "where remote = '". mysql_real_escape_string($remote, $link)."' AND istate <> $state_closed AND istate <> $state_left", $link ); if($result && isset($result['opened'])) { return $result['opened'] < $settings['max_connections_from_one_host']; } return true; } function visitor_from_request() { global $namecookie, $webim_encoding, $usercookie; $defaultName = getstring("chat.default.username"); $userName = $defaultName; if( isset($_COOKIE[$namecookie]) ) { $data = base64_decode(strtr($_COOKIE[$namecookie],'-_,', '+/=')); if( strlen($data) > 0 ) { $userName = myiconv("utf-8",$webim_encoding,$data); } } if($userName == $defaultName) { $userName = getgetparam('name', $userName); } $userId = ""; if (isset($_COOKIE[$usercookie])) { $userId = $_COOKIE[$usercookie]; } else { $userId = get_user_id(); setcookie($usercookie, $userId, time()+60*60*24*365); } return array( 'id' => $userId, 'name' => $userName ); } function get_remote_host() { $extAddr = $_SERVER['REMOTE_ADDR']; if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] != $_SERVER['REMOTE_ADDR']) { $extAddr = $_SERVER['REMOTE_ADDR'].' ('.$_SERVER['HTTP_X_FORWARDED_FOR'].')'; } return isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : $extAddr; } ?>