diff --git a/src/messenger/webim/b.php b/src/messenger/webim/b.php index 5a886328..f83310a4 100644 --- a/src/messenger/webim/b.php +++ b/src/messenger/webim/b.php @@ -25,7 +25,7 @@ if($referer && isset($_SESSION['threadid'])) { $link = connect(); $thread = thread_by_id_($_SESSION['threadid'], $link); if ($thread && $thread['istate'] != $state_closed) { - $msg = getstring2_("chat.client.visited.page", array($referer), $thread['locale']); + $msg = getstring2_("chat.client.visited.page", array($referer), $thread['locale'], true); post_message_($thread['threadid'], $kind_for_agent,$msg,$link); } mysql_close($link); diff --git a/src/messenger/webim/client.php b/src/messenger/webim/client.php index 8d6c1595..84f56e06 100644 --- a/src/messenger/webim/client.php +++ b/src/messenger/webim/client.php @@ -131,14 +131,14 @@ if( !isset($_GET['token']) || !isset($_GET['thread']) ) { $_SESSION['threadid'] = $thread['threadid']; if( $referrer ) { - post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.came.from',array($referrer)),$link); + post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.came.from',array($referrer),true),$link); } - post_message_($thread['threadid'],$kind_info,getstring('chat.wait'),$link); + post_message_($thread['threadid'],$kind_info,getstring('chat.wait', true),$link); if($email) { - post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.email',array($email)),$link); + post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.email',array($email),true),$link); } if($info) { - post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.info',array($info)),$link); + post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.info',array($info),true),$link); } if($firstmessage) { $postedid = post_message_($thread['threadid'],$kind_user,$firstmessage,$link,$visitor['name']); diff --git a/src/messenger/webim/leavemessage.php b/src/messenger/webim/leavemessage.php index f4bbb0bf..58c4dd5d 100644 --- a/src/messenger/webim/leavemessage.php +++ b/src/messenger/webim/leavemessage.php @@ -33,13 +33,13 @@ function store_message($name, $email, $info, $message,$groupid,$referrer) { $link = connect(); $thread = create_thread($groupid,$name,$remoteHost,$referrer,$current_locale,$visitor['id'], $userbrowser,$state_left,$link); if( $referrer ) { - post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.came.from',array($referrer)),$link); + post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.came.from',array($referrer),true),$link); } if($email) { - post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.email',array($email)),$link); + post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.email',array($email),true),$link); } if($info) { - post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.info',array($info)),$link); + post_message_($thread['threadid'],$kind_for_agent,getstring2('chat.visitor.info',array($info),true),$link); } post_message_($thread['threadid'],$kind_user,$message,$link,$name); mysql_close($link); @@ -102,8 +102,8 @@ if(!locale_exists($message_locale)) { store_message($visitor_name, $email, $info, $message, $groupid, $referrer); -$subject = getstring2_("leavemail.subject", array($visitor_name), $message_locale); -$body = getstring2_("leavemail.body", array($visitor_name,$email,$message,$info ? "$info\n" : ""), $message_locale); +$subject = getstring2_("leavemail.subject", array($visitor_name), $message_locale,true); +$body = getstring2_("leavemail.body", array($visitor_name,$email,$message,$info ? "$info\n" : ""), $message_locale,true); if (isset($group) && !empty($group['vcemail'])) { $inbox_mail = $group['vcemail']; diff --git a/src/messenger/webim/libs/chat.php b/src/messenger/webim/libs/chat.php index 0efdd9e9..039885b1 100644 --- a/src/messenger/webim/libs/chat.php +++ b/src/messenger/webim/libs/chat.php @@ -166,7 +166,7 @@ function print_thread_messages($thread, $token, $lastid, $isuser, $format, $agen $output = get_messages($threadid, "xml", $isuser, $lastid); start_xml_output(); - print(""); + print(""); foreach ($output as $msg) { print $msg; } @@ -176,13 +176,13 @@ function print_thread_messages($thread, $token, $lastid, $isuser, $format, $agen $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"); + $url = "$webimroot/thread.php?act=refresh&thread=" . htmlspecialchars($threadid) . "&token=" . htmlspecialchars($token) . "&html=on&user=" . ($isuser ? "true" : "false"); print( "" . "\n\n" . "\n" . - "\n" . + "\n" . "\n" . "chat\n" . "\n" . @@ -290,9 +290,9 @@ 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']); + $page['ct.company.name'] = htmlspecialchars(topage($settings['title'])); + $page['ct.company.chatLogoURL'] = htmlspecialchars(topage($settings['logo'])); + $page['webimHost'] = htmlspecialchars(topage($settings['hosturl'])); } function setup_leavemessage($name, $email, $message, $groupid, $groupname, $info, $referrer, $canshowcaptcha) @@ -337,7 +337,7 @@ function setup_survey($name, $email, $groupid, $info, $referrer, $canshowcaptcha $groupname .= " (offline)"; } $isselected = $k['groupid'] == $groupid; - $val .= ""; + $val .= ""; } $page['groups'] = $val; } @@ -359,11 +359,11 @@ function setup_chatview_for_user($thread, $level) $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.chatThreadId'] = htmlspecialchars($thread['threadid']); + $page['ct.token'] = htmlspecialchars($thread['ltoken']); $page['ct.user.name'] = htmlspecialchars(topage($thread['userName'])); $page['canChangeName'] = $settings['usercanchangename'] == "1"; - $page['chat.title'] = topage($settings['chattitle']); + $page['chat.title'] = htmlspecialchars(topage($settings['chattitle'])); setup_logo(); if ($settings['sendmessagekey'] == 'enter') { @@ -374,11 +374,11 @@ function setup_chatview_for_user($thread, $level) $page['ignorectrl'] = 0; } - $params = "thread=" . $thread['threadid'] . "&token=" . $thread['ltoken']; - $page['mailLink'] = "$webimroot/client.php?" . $params . "&level=$level&act=mailthread"; + $params = "thread=" . $thread['threadid'] . "&token=" . $thread['ltoken']; + $page['mailLink'] = htmlspecialchars("$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['sslLink'] = htmlspecialchars(get_app_location(true, true) . "/client.php?" . $params . "&level=$level"); } $page['isOpera95'] = is_agent_opera95(); @@ -420,10 +420,10 @@ function setup_chatview_for_operator($thread, $operator) $page['agent'] = true; $page['user'] = false; $page['canpost'] = $thread['agentId'] == $operator['operatorid']; - $page['ct.chatThreadId'] = $thread['threadid']; - $page['ct.token'] = $thread['ltoken']; + $page['ct.chatThreadId'] = htmlspecialchars($thread['threadid']); + $page['ct.token'] = htmlspecialchars($thread['ltoken']); $page['ct.user.name'] = htmlspecialchars(topage(get_user_name($thread['userName'], $thread['remote'], $thread['userid']))); - $page['chat.title'] = topage($settings['chattitle']); + $page['chat.title'] = htmlspecialchars(topage($settings['chattitle'])); setup_logo(); if ($settings['sendmessagekey'] == 'enter') { @@ -435,20 +435,20 @@ function setup_chatview_for_operator($thread, $operator) } if ($settings['enablessl'] == "1" && !is_secure_request()) { - $page['sslLink'] = get_app_location(true, true) . "/operator/agent.php?thread=" . $thread['threadid'] . "&token=" . $thread['ltoken']; + $page['sslLink'] = htmlspecialchars(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']); + $page['historyParamsLink'] = htmlspecialchars(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"; + $params = "thread=" . $thread['threadid'] . "&token=" . $thread['ltoken']; + $page['redirectLink'] = htmlspecialchars("$webimroot/operator/agent.php?" . $params . "&act=redirect"); $page['namePostfix'] = ""; $page['frequency'] = $settings['updatefrequency_chat']; @@ -527,7 +527,7 @@ function rename_user($thread, $newname) if ($thread['userName'] != $newname) { post_message_($thread['threadid'], $kind_events, - getstring2_("chat.status.user.changedname", array($thread['userName'], $newname), $thread['locale']), $link); + getstring2_("chat.status.user.changedname", array($thread['userName'], $newname), $thread['locale'], true), $link); } mysql_close($link); } @@ -542,8 +542,8 @@ function close_thread($thread, $isuser) 'messageCount' => "(SELECT COUNT(*) FROM ${mysqlprefix}chatmessage WHERE ${mysqlprefix}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']); + $message = $isuser ? getstring2_("chat.status.user.left", array($thread['userName']), $thread['locale'], true) + : getstring2_("chat.status.operator.left", array($thread['agentName']), $thread['locale'], true); post_message_($thread['threadid'], $kind_events, $message, $link); mysql_close($link); } @@ -642,7 +642,7 @@ function reopen_thread($threadid) array("istate" => $state_waiting, "nextagent" => 0), $link); } - post_message_($thread['threadid'], $kind_events, getstring_("chat.status.user.reopenedthread", $thread['locale']), $link); + post_message_($thread['threadid'], $kind_events, getstring_("chat.status.user.reopenedthread", $thread['locale'], true), $link); mysql_close($link); return $thread; } @@ -662,17 +662,17 @@ function take_thread($thread, $operator) if ($state == $state_waiting) { if ($operatorName != $thread['agentName']) { - $message_to_post = getstring2_("chat.status.operator.changed", array($operatorName, $thread['agentName']), $thread['locale']); + $message_to_post = getstring2_("chat.status.operator.changed", array($operatorName, $thread['agentName']), $thread['locale'], true); } else { - $message_to_post = getstring2_("chat.status.operator.returned", array($operatorName), $thread['locale']); + $message_to_post = getstring2_("chat.status.operator.returned", array($operatorName), $thread['locale'], true); } } else { - $message_to_post = getstring2_("chat.status.operator.joined", array($operatorName), $thread['locale']); + $message_to_post = getstring2_("chat.status.operator.joined", array($operatorName), $thread['locale'], true); } } 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']); + $message_to_post = getstring2_("chat.status.operator.changed", array($operatorName, $thread['agentName']), $thread['locale'], true); } } else { die("cannot take thread"); @@ -693,9 +693,9 @@ function check_for_reassign($thread, $operator) || $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']); + $message_to_post = getstring2_("chat.status.operator.changed", array($operatorName, $thread['agentName']), $thread['locale'], true); } else { - $message_to_post = getstring2_("chat.status.operator.returned", array($operatorName), $thread['locale']); + $message_to_post = getstring2_("chat.status.operator.returned", array($operatorName), $thread['locale'], true); } post_message($thread['threadid'], $kind_events, $message_to_post); @@ -719,13 +719,13 @@ function notify_operators($thread, $firstmessage, $link) $text = getstring2_("notify.new.text", array( get_app_location(true, $settings['enablessl'] == '1' && $settings['forcessl'] == '1') . "/operator/agent.php?thread=" . $thread['threadid'], $thread['userName'] - ), $thread['locale']); + ), $thread['locale'], true); if ($firstmessage) { $text .= "\n$firstmessage"; } foreach ($result as $op) { if ($op['time'] < $settings['online_timeout'] && is_valid_email($op['vcjabbername'])) { - webim_xmpp($op['vcjabbername'], getstring2("notify.new.subject", array($thread['userName'])), $text, $link); + webim_xmpp($op['vcjabbername'], getstring2("notify.new.subject", array($thread['userName']), true), $text, $link); } } } diff --git a/src/messenger/webim/libs/common.php b/src/messenger/webim/libs/common.php index 4377efbd..b5396519 100644 --- a/src/messenger/webim/libs/common.php +++ b/src/messenger/webim/libs/common.php @@ -59,7 +59,7 @@ function verifyparam($name, $regexp, $default = null) if (isset($default)) return $default; } - echo "Wrong parameter used or absent: " . $name . ""; + echo "Wrong parameter used or absent: " . htmlspecialchars($name) . ""; exit; } @@ -197,7 +197,7 @@ function getoutputenc() return isset($output_encoding[$current_locale]) ? $output_encoding[$current_locale] : $webim_encoding; } -function getstring_($text, $locale) +function getstring_($text, $locale, $raw = false) { global $messages; if (!isset($messages[$locale])) @@ -205,30 +205,33 @@ function getstring_($text, $locale) $localized = $messages[$locale]; if (isset($localized[$text])) - return $localized[$text]; + return $raw ? $localized[$text] : sanitize_string($localized[$text], 'low', 'moderate'); if ($locale != 'en') { - return getstring_($text, 'en'); + return getstring_($text, 'en', $raw); } - return "!" . $text; + return "!" . ($raw ? $text : sanitize_string($text, 'low', 'moderate')); } -function getstring($text) +function getstring($text, $raw = false) { global $current_locale; - return getstring_($text, $current_locale); + $string = getstring_($text, $current_locale, true); + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } -function getlocal($text) +function getlocal($text, $raw = false) { global $current_locale, $webim_encoding; - return myiconv($webim_encoding, getoutputenc(), getstring_($text, $current_locale)); + $string = myiconv($webim_encoding, getoutputenc(), getstring_($text, $current_locale), true); + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } -function getlocal_($text, $locale) +function getlocal_($text, $locale, $raw = false) { global $webim_encoding; - return myiconv($webim_encoding, getoutputenc(), getstring_($text, $locale)); + $string = myiconv($webim_encoding, getoutputenc(), getstring_($text, $locale), true); + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } function topage($text) @@ -237,41 +240,42 @@ function topage($text) return myiconv($webim_encoding, getoutputenc(), $text); } -function getstring2_($text, $params, $locale) +function getstring2_($text, $params, $locale, $raw = false) { - $string = getstring_($text, $locale); + $string = getstring_($text, $locale, true); for ($i = 0; $i < count($params); $i++) { $string = str_replace("{" . $i . "}", $params[$i], $string); } - return $string; + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } -function getstring2($text, $params) +function getstring2($text, $params, $raw = false) { global $current_locale; - return getstring2_($text, $params, $current_locale); + $string = getstring2_($text, $params, $current_locale, true); + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } -function getlocal2($text, $params) +function getlocal2($text, $params, $raw = false) { global $current_locale, $webim_encoding; - $string = myiconv($webim_encoding, getoutputenc(), getstring_($text, $current_locale)); + $string = myiconv($webim_encoding, getoutputenc(), getstring_($text, $current_locale, true)); for ($i = 0; $i < count($params); $i++) { $string = str_replace("{" . $i . "}", $params[$i], $string); } - return $string; + return $raw ? $string : sanitize_string($string, 'low', 'moderate'); } /* prepares for Javascript string */ function getlocalforJS($text, $params) { global $current_locale, $webim_encoding; - $string = myiconv($webim_encoding, getoutputenc(), getstring_($text, $current_locale)); + $string = myiconv($webim_encoding, getoutputenc(), getstring_($text, $current_locale, true)); $string = str_replace("\"", "\\\"", str_replace("\n", "\\n", $string)); for ($i = 0; $i < count($params); $i++) { $string = str_replace("{" . $i . "}", $params[$i], $string); } - return $string; + return sanitize_string($string, 'low', 'moderate'); } /* ajax server actions use utf-8 */ @@ -450,7 +454,7 @@ function no_field($key) function failed_uploading_file($filename, $key) { return getlocal2("errors.failed.uploading.file", - array($filename, getlocal($key))); + array(htmlspecialchars($filename), getlocal($key))); } function wrong_field($key) @@ -469,8 +473,8 @@ function get_popup($href, $jshref, $message, $title, $wndName, $options) function get_image($href, $width, $height) { if ($width != 0 && $height != 0) - return "\"\"/"; - return "\"\"/"; + return "\"\"/"; + return "\"\"/"; } function get_gifimage_size($filename) @@ -730,4 +734,82 @@ function setcsrftoken() } } +/* simple HTML sanitation + * + * includes some code from the PHP Strip Attributes Class For XML and HTML + * Copyright 2009 David (semlabs.co.uk) + * Available under the MIT License. + * + * http://semlabs.co.uk/journal/php-strip-attributes-class-for-xml-and-html + * + */ + +function sanitize_string($string, $tags_level = 'high', $attr_level = 'high') +{ + $sanitize_tags = array( + 'high' => '', + 'moderate' => '
', + 'low' => '