Skip to content

Instantly share code, notes, and snippets.

@chrisboulton
Created February 25, 2010 02:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisboulton/314154 to your computer and use it in GitHub Desktop.
Save chrisboulton/314154 to your computer and use it in GitHub Desktop.
<?php
/**
* Several improvements to the visitor HTML tracking code in Kayako SupportSuite
* (replaces modules/livechat/visitor_htmlcode.php)
*
* - Automatic updates of live chat status images/text when the operator status changes in Kayako - no longer needs a page refresh.
* - Clean up the indicator Javascript, keep all instances under a clean single class rather than a heap of variableSuffix based functions.
* - Have Firefox browser version detected correctly instead of Gecko/Mozilla.
* - Have several other browsers also correctly identified.
* - Replace <img> tag status updating/footprint updating with an AJAX request (or <script> tags across domains)
*
*/
if (!defined("INSWIFT")) {
trigger_error("Unable to process " . htmlentities($_SERVER['PHP_SELF']), E_USER_ERROR);
}
$template->cache(array('proactivechatdiv', 'chatimage'));
$template->loadLanguageSection("livesupportclient");
header("Content-Type: text/javascript");
if ($_SWIFT["settings"]["livesupport_cachehtmljscode"] == "1")
{
headerCache();
} else {
headerNoCache();
}
// ======= Load Up the functions file =======
require_once ("./modules/livesupport/functions_livesupport.php");
$_staffstatus = isStaffMonitorOnline(intval($_GET["departmentid"]));
if ($_staffstatus == STATUS_ONLINE)
{
$template->assign("staffstatus", "online");
$template->assign("staffstatustext", $_SWIFT["language"]["clickforlivesupport"]);
} else if ($_staffstatus == STATUS_AWAY) {
$template->assign("staffstatus", "away");
$template->assign("staffstatustext", $_SWIFT["language"]["lsisaway"]);
} else if ($_staffstatus == STATUS_BACK) {
$template->assign("staffstatus", "back");
$template->assign("staffstatustext", $_SWIFT["language"]["lsbacksoon"]);
} else {
$template->assign("staffstatus", "offline");
$template->assign("staffstatustext", $_SWIFT["language"]["clickleavemessage"]);
}
if ($_GET["nolink"] == 1)
{
$template->assign("nolink", 1);
}
// Does this user have a session id set?
$cookiesessionid = $cookie->getSCookie("sessionid".SESSION_VISITOR);
if (trim($cookiesessionid) == "")
{
$sessionid = $session->insertSession(SESSION_VISITOR);
} else {
$sessionid = $cookiesessionid;
}
$cookiebuild = false;
$cookie->parseCookie("visitor");
// Does this person have a country code set in cookie? This allows us to restrict country fetching query to just one per session, neat huh? ;)
$countrycode = $cookie->getKey("visitor", "countrycode");
if (trim($countrycode) == "none") {
// No country was available for this user so do nothing
$country["countrycode"] = "";
$country["country"] = "";
} else if (trim($countrycode) != "none" && trim($countrycode) != "") {
// We have a country set
$country["countrycode"] = $countrycode;
$country["country"] = $cookie->getKey("visitor", "countryname");
} else {
// No Country set
$countrydata = getCountry($_SERVER["REMOTE_ADDR"]);
if (trim($countrydata["countrycode2"]) != "") {
$cookie->addCookie("visitor", "countrycode", strtolower($countrydata["countrycode2"]));
$cookie->addCookie("visitor", "countryname", $countrydata["countryname"]);
$country["countrycode"] = strtolower($countrydata["countrycode2"]);
$country["country"] = $countrydata["countryname"];
} else {
// No country available for this ip, set to none so this query isnt executed for any other page this visitor loads
$cookie->addCookie("visitor", "countrycode", "none");
$cookie->addCookie("visitor", "countryname", "none");
$country["countrycode"] = "";
$country["country"] = "";
}
$cookiebuild = true;
}
// We only execute the note query if we havent checked for that already
if ($cookie->getKey("visitor", "notecheck") != "1")
{
// Does this visitor have a note attached to him?
$_note = $dbCore->queryFetch("SELECT COUNT(*) as totalnotes FROM `". TABLE_PREFIX ."visitornotes` WHERE ipaddress = '". $dbCore->escape($_SERVER["REMOTE_ADDR"]) ."' LIMIT 1;");
if ($_note["totalnotes"] > 0)
{
$hasnotes = "1";
} else {
$hasnotes = "0";
}
$cookie->addCookie("visitor", "notecheck", "1");
$cookiebuild = true;
}
$_campaign = array();
$campaignid = $cookie->getKey("visitor", "campaignid");
if (!empty($campaignid))
{
$_campaign["campaignid"] = $cookie->getKey("visitor", "campaignid");
$_campaign["title"] = $cookie->getKey("visitor", "campaigntitle");
}
if ($cookiebuild == true)
{
$cookie->buildCookie("visitor");
}
// Update this session last activity
$dbCore->shutdownQuery("UPDATE `". TABLE_PREFIX ."sessions` SET `lastactivity` = '". DATENOW ."' WHERE `sessionid` = '". $dbCore->escape($sessionid) ."';");
$_variablesuffix = substr(buildHash(), 0, 8);
$template->assign("variablesuffix", $_variablesuffix);
if($isbanned == true) {
exit;
}
if ($_GET["custom"] != "")
{
$dataarray = unserialize(base64_decode($_GET["custom"]));
if (is_array($dataarray))
{
$template->assign("iscustomcode", "true");
$template->assign("onlinetext", $dataarray[0]);
$template->assign("offlinetext", $dataarray[1]);
} else {
$template->assign("iscustomcode", "false");
}
}
// Fetch the proactive template
$proactiveTemplate = HTML2JS($template->displayTemplate('proactivechatdiv'), '', false, false);
$chatImageTemplate = HTML2JS($template->displayTemplate('chatimage'), '', false, false);
ob_start();
?>
var LiveSupport_<?php echo $_variablesuffix; ?> = {
variableSuffix: '<?php echo $_variablesuffix; ?>',
sessionId: '<?php echo $sessionid; ?>',
country: '<?php echo $country['country']; ?>',
countryCode: '<?php echo $country['countrycode']; ?>',
hasNotes: '<?php echo $hasnotes; ?>',
campaignId: '<?php echo $_campaign['campaignid']; ?>',
campaignTitle: '<?php echo $_campaign['title']; ?>',
isFirstTime: 1,
timer: 0,
imageFetch: <?php echo $_SWIFT['settings']['livesupport_clientpagerefresh']-1; ?>,
currentStatus: <?php echo $_staffstatus; ?>,
timeNow: new Date(),
referrer: document.referrer,
isChatRunning: 0,
title: document.title,
chatWidth: <?php echo $_SWIFT['settings']['livesupport_chatwidth']; ?>,
chatHeight: <?php echo $_SWIFT['settings']['livesupport_chatheight']; ?>,
departmentId: <?php if(!empty($_GET['departmentid'])) { echo (int)$_GET['departmentid']; } else { echo '0'; } ?>,
fullName: '<?php if(!empty($_GET['fullname'])) { echo addslashes($_GET['fullname']); } ?>',
email: '<?php if(!empty($_GET['email'])) { echo addslashes($_GET['email']); } ?>',
proactiveContainer: null,
baseUrl: "<?php echo $_SWIFT['swiftpath']; ?>",
Init: function()
{
var helpLine = <?php echo $chatImageTemplate; ?>
document.write('<span id="LiveSupport_<?php echo $_variablesuffix; ?>">'+helpLine+'</span>');
this.DetectBrowser();
this.TimerInterval();
},
TimerInterval: function()
{
if(this.timer > 3600) {
return;
}
++this.timer;
++this.imageFetch;
if(this.imageFetch > <?php echo $_SWIFT['settings']['livesupport_clientpagerefresh']; ?>) {
this.imageFetch = 0;
this.DoStatusLoop();
}
setTimeout('LiveSupport_<?php echo $_variablesuffix; ?>.TimerInterval()', 1000);
},
DetectBrowser: function()
{
if(navigator.appVersion.match(/win/i) && !navigator.appVersion.match(/darwin/i)) {
this.operatingSystem = 'Windows';
}
else if(navigator.appVersion.match(/mac(?!hine)/i)) {
this.operatingSystem = 'Mac';
}
else if(navigator.appVersion.match(/linux/i)) {
this.operatingSystem = 'Linux';
}
else {
this.operatingSystem = 'Unknown';
}
var regexp = /(safari|firefox|flock|camino|konqueror|opera|netscape)( |\/|) ?v?([0-9.]*)/i;
if(regexp.test(navigator.userAgent)) {
match = regexp.exec(navigator.userAgent)
this.browserName = match[1];
this.browserVersion = match[3];
if(match[1].toLowerCase() == 'safari') {
this.browserCode = 'SF';
}
else if(match[1].toLowerCase() == 'opera') {
this.browserCode = 'OP';
}
else if(match[1] == 'konqueror') {
this.browserCode = 'KO';
}
else {
this.browserCode = 'MO';
}
return;
}
// Match Generic Mozilla
var regexp = /gecko/i;
if(regexp.test(navigator.userAgent)) {
this.browseCode = 'MO';
this.browserName = 'Mozilla';
matches = /rv[:\/ ]([0-9.]*)/i.exec(navigator.userAgent);
if(matches[1]) {
this.browserVersion = matches[1];
}
else {
this.browserVersion = navigator.appVersion;
}
return false;
}
// Match IE
var regexp = /(msie)( |\/|) ?v?([0-9.]*)/i;
if(regexp.test(navigator.userAgent)) {
match = regexp.exec(navigator.userAgent)
this.browserName = 'Internet Explorer';
this.browserVersion = match[1];
this.browserCode = 'IE';
return;
}
},
DoStatusLoop: function()
{
requestVars = {
_m: 'livesupport',
_a: 'updatefootprint',
time: new Date().getTime(),
rand: new Date().getSeconds(),
url: window.location,
isfirsttime: this.isFirstTime,
sessionid: this.sessionId,
referrer: document.referrer,
resolution: window.screen.availWidth+'x'+window.screen.availHeight,
colordepth: window.screen.colorDepth,
platform: navigator.platform,
appversion: navigator.appVersion,
appname: navigator.appName,
browsercode: this.browserCode,
browserversion: this.browserVersion,
browsername: this.browserName,
operatingsys: this.operatingSystem,
pagetitle: document.title,
country: this.country,
countrycode: this.countryCode,
hasnotes: this.hasNotes,
campaignid: this.campaignId,
campaigntitle: this.campaignTitle,
variablesuffix: this.variableSuffix,
currentStatus: this.currentStatus
};
requestUrl = this.baseUrl+'visitor/index.php?'+this.BuildRequestUrl(requestVars);
this.SendRequest(requestUrl);
this.isFirstTime = 0;
},
SendRequest: function(url)
{
requestPathStart = url.indexOf('/', url.indexOf('://') + 3) + 1;
requestDomain = url.substring(0, requestPathStart);
currentPathStart = window.location.href.indexOf('/', window.location.href.indexOf('://') + 3) + 1;
currentDomain = window.location.href.substring(0, currentPathStart);
ajaxSupport = false;
if(requestDomain.toLowerCase() == currentDomain.toLowerCase()) {
ajaxSupport = true;
}
if(ajaxSupport) {
transport = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try { transport = new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e) { try { transport = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { transport = false; } }
@end @*/
if(!transport && XMLHttpRequest != undefined) {
transport = new XMLHttpRequest();
}
if(transport) {
transport.onreadystatechange = function() {
if(transport.readyState == 4 && transport.status == 200) {
eval(transport.responseText);
}
}
transport.open('GET', url, false);
transport.send(null);
return true;
}
return false;
}
else {
head = document.getElementsByTagName('head')[0];
script = document.createElement('script');
script.src = url;
script.type = 'text/javascript';
loaded = false;
script.onload = script.onreadystatechange = function() {
if(!loaded && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
loaded = true;
script.onload = script.onreadystatechange = null;
// head.removeChild(script);
}
};
head.appendChild(script);
}
},
BuildRequestUrl: function(vars)
{
var url = '';
for(x in vars) {
var value = vars[x];
url = url + '&'+encodeURIComponent(x)+'='+encodeURIComponent(value);
}
return url;
},
GetWindowDimensions: function()
{
windowWidth = 0;
windowHeight = 0;
if(typeof window.innerWidth != undefined) {
windowWidth = window.innerWidth;
windowHeight = window.innerHeight;
}
else if(document.documentElement && document.documentElement.clientWidth) {
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight
}
else if(document.body && document.body.clientWidth) {
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}
return {
width: windowWidth,
height: windowHeight
};
},
StartChat: function(isProactive)
{
this.isChatRunning = 1;
chatLeft = (this.GetWindowDimensions().width - this.chatWidth)/2;
chatTop = (this.GetWindowDimensions().height - this.chatHeight)/2;
requestVars = {
_m: 'livesupport',
_a: 'startclientchat',
sessionid: this.sessionId,
proactive: isProactive,
departmentid: this.departmentId,
randno: new Date().getSeconds(),
fullname: this.fullName,
email: this.email,
}
chatUrl = this.baseUrl+'visitor/index.php?'+this.BuildRequestUrl(requestVars);
window.open(chatUrl, 'toolbar=0,location=0,directories=0,status=1,menubar=0,scrollbars=0,resizable=1,width='+this.chatWidth+',height='+this.chatHeight+',left='+chatLeft+',top='+chatTop);
},
DisplayProactiveChat: function()
{
this.HideProactiveChat();
this.proactiveContainer = document.createElement('div');
container = this.proactiveContainer;
container.style.display = 'none';
container.style.cssFloat = 'left';
container.style.position = 'absolute';
container.style.top = (this.GetWindowDimensions().height - 450)/2;
container.style.left = (this.GetWindowDimensions().width - 400)/2;
container.style.width = '450px';
container.style.height = '400px';
container.style.zIndex = 500;
container.innerHTML = <?php echo $proactiveTemplate; ?>;
document.getElementsByTagName('body')[0].appendChild(container);
},
StartProactiveChat: function()
{
this.HideProactiveChat();
this.StartChat(<?php echo PROACTIVE_FORCED; ?>);
},
DoProactiveRequest: function()
{
this.StartChat(<?php echo PROACTIVE_REQUEST; ?>);
},
HideProactiveChat: function()
{
if(this.proactiveContainer === null) {
return;
}
this.proactiveContainer.parentNode.removeChild(this.proactiveContainer);
this.proactiveContainer = null;
},
CloseProactiveChat: function()
{
this.HideProactiveChat();
requestVars = {
_m: 'livesupport',
_a: 'resetproactivestatus',
time: new Date().getTime(),
rand: new Date().getSeconds(),
sessionid: this.sessionId
};
requestUrl = this.baseUrl+'visitor/index.php'+this.BuildRequestUrl(requestVars);
this.SendRequest(requestUrl);
},
}
LiveSupport_<?php echo $_variablesuffix; ?>.Init();
LiveSupport_<?php echo $_variablesuffix; ?>.DoStatusLoop();
<?php
ob_flush();
In modules/livechat/visitor_updatefootprint.php
Find:
--
if ($_SWIFT["session"]["status"] == PROACTIVE_FORCED)
{
echoImage("2");
resetVisitorStatus($_SWIFT["session"]["sessionid"]);
} else if ($_SWIFT["session"]["status"] == PROACTIVE_REQUEST) {
echoImage("3");
resetVisitorStatus($_SWIFT["session"]["sessionid"]);
} else {
echoImage("1");
}
--
ABOVE it, add:
--
if(isset($_REQUEST['variablesuffix'])) {
$variableSuffix = preg_replace('#[^a-z0-9\-_]#i', '', $_REQUEST['variablesuffix']);
$departmentId = 0;
if(!empty($_REQUEST['departmentid'])) {
$departmentId = (int)$_REQUEST['departmentid'];
}
$_staffstatus = isStaffMonitorOnline($departmentId);
header('Content-type: text/javascript');
if($_REQUEST['currentStatus'] != $_staffstatus) {
if ($_staffstatus == STATUS_ONLINE) {
$template->assign("staffstatus", "online");
$template->assign("staffstatustext", $_SWIFT["language"]["clickforlivesupport"]);
} else if ($_staffstatus == STATUS_AWAY) {
$template->assign("staffstatus", "away");
$template->assign("staffstatustext", $_SWIFT["language"]["lsisaway"]);
} else if ($_staffstatus == STATUS_BACK) {
$template->assign("staffstatus", "back");
$template->assign("staffstatustext", $_SWIFT["language"]["lsbacksoon"]);
} else {
$template->assign("staffstatus", "offline");
$template->assign("staffstatustext", $_SWIFT["language"]["clickleavemessage"]);
}
if ($_GET["nolink"] == 1) {
$template->assign("nolink", 1);
}
$template->assign("variablesuffix", $variableSuffix);
if ($_GET["custom"] != "") {
$dataarray = unserialize(base64_decode($_GET["custom"]));
if (is_array($dataarray)) {
$template->assign("iscustomcode", "true");
$template->assign("onlinetext", $dataarray[0]);
$template->assign("offlinetext", $dataarray[1]);
} else {
$template->assign("iscustomcode", "false");
}
}
$chatImageTemplate = HTML2JS($template->displayTemplate('chatimage'), '', false, false);
echo 'var helpLine = '.$chatImageTemplate;
echo 'document.getElementById("LiveSupport_'.$variableSuffix.'").innerHTML = helpLine;';
echo 'LiveSupport_'.$variableSuffix.'.currentStatus = '.$_staffstatus.';';
}
if($_SWIFT['session']['status'] == PROACTIVE_FORCED) {
echo 'LiveSupport_'.$variableSuffix.'.StartProactiveChat();';
resetVisitorStatus($_SWIFT["session"]["sessionid"]);
}
else if($_SWIFT['session']['status'] == PROACTIVE_REQUEST) {
echo 'LiveSupport_'.$variableSuffix.'.DoProactiveRequest();';
resetVisitorStatus($_SWIFT["session"]["sessionid"]);
}
exit;
}
--
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment