/* @edition:pro */
var x2WebTracker = {};
/**
* Constructs the weblistener url
* @return string
*/
x2WebTracker.getSendKeyUrl = function () {
return 'https://www.wisharts.com.au/crm/index.php/api/webListener';
};
/**
* Structures the parameters which will get sent to the weblistener action, either as a query
* string or as a dictionary
* @param object args
* @param string method ('GET'|'POST')
* @return object|string
*/
x2WebTracker.getSendKeyParams = function (args, method) {
var x2GETKey = args['x2KeyGetParam'];
var url = args['url'];
/* x2plastart */
var attributes;
var fingerprint = args['fingerprint']
if (typeof fingerprint !== 'undefined') {
// Ensure fingerprint data has valid keys: these will not be set
// at this point if the client has DNT set
if (typeof fingerprint['attributes'] !== 'undefined')
attributes = fingerprint['attributes'];
if (typeof fingerprint['fingerprint'] !== 'undefined')
fingerprint = fingerprint['fingerprint'];
}
/* x2plaend */
var params = {
url: (method === 'GET') ? encodeURIComponent (url) : url/* x2plastart */,
fingerprint: fingerprint,
/*attributes: (method === 'GET') ? encodeURIComponent (fingerprint['attributes']) :
fingerprint['attributes'],*/
/* x2plaend */
};
if (x2GETKey !== null)
params['get_key'] = (method === 'GET') ? encodeURIComponent (x2GETKey) : x2GETKey
/* x2plastart */
for (var fingerprintAttr in attributes) {
params[fingerprintAttr] = (method === 'GET' ?
encodeURIComponent (attributes[fingerprintAttr]) :
attributes[fingerprintAttr]);
}
/* x2plaend */
if (method === 'GET') {
var queryString = '';
var i = 0;
for (var paramName in params) {
if (i++ === 0) {
queryString += '?';
} else {
queryString += '&';
}
queryString += paramName + '=' + params[paramName];
}
return queryString;
} else {
return params;
}
};
/**
* Sends the tracking information to the server using a script tag
*/
x2WebTracker.sendKeyNoCORS = function (args) {
var sendKeyScript = document.createElement ('script');
sendKeyScript.setAttribute (
'src', x2WebTracker.getSendKeyUrl () + x2WebTracker.getSendKeyParams (args, 'GET'),
true);
document.getElementsByTagName("head")[0].appendChild(sendKeyScript);
};
/**
* Sends tracking information to the server using an AJAX request if CORS is supported by browser.
* Falls back on sendKey ().
*/
x2WebTracker.sendKey = function (args) {
x2WebTracker.sendKeyNoCORS (args);
};
x2WebTracker.generateKey = function () {
var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
var key = '';
for(var i = 0; i < 32; ++i) {
key += chars.charAt (parseInt (Math.floor (Math.random () * chars.length)));
}
//console.log ('key = ' + key);
return key;
};
x2WebTracker.setKeyCookie = function (key) {
// Remove a subdomain if present
if (document.domain.split('.').length > 2)
var domain = document.domain.replace (/^[^.]*/, '');
else
var domain = document.domain;
document.cookie = "x2_key=" + key +
";expires=" + (new Date (+new Date () + 31556940000)).toGMTString () +
";path=/;domain=" + domain;
};
x2WebTracker.setKeyCookieHiddenField = function (key) {
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
var hiddenFields = document.getElementsByName ('x2_key');
if (hiddenFields.length > 0) {
var hiddenField = hiddenFields[0];
hiddenField.setAttribute ('value', key);
}
}
}
};
(x2WebTracker.main = function () {
var url = window.location.href;
var fingerprint;
/**
* JavaScript code to detect available availability of a
* particular font in a browser using JavaScript and CSS.
*
* Author : Lalit Patel
* Website: http://www.lalit.org/lab/javascript-css-font-detect/
* License: Apache Software License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
* Version: 0.15 (21 Sep 2009)
* Changed comparision font to default from sans-default-default,
* as in FF3.0 font of child element didn't fallback
* to parent element if the font is missing.
* Version: 0.2 (04 Mar 2012)
* Comparing font against all the 3 generic font families ie,
* 'monospace', 'sans-serif' and 'sans'. If it doesn't match all 3
* then that font is 100% not available in the system
* Version: 0.3 (24 Mar 2012)
* Replaced sans with serif in the list of baseFonts
*/
/**
* Usage: d = new Detector();
* d.detect('font name');
*/
var Detector = function() {
// a font will be compared against all the three default fonts.
// and if it doesn't match all 3 then that font is not available.
var baseFonts = ['monospace', 'sans-serif', 'serif'];
//we use m or w because these two characters take up the maximum width.
// And we use a LLi so that the same matching fonts can get separated
var testString = "mmmmmmmmmmlli";
//we test using 72px font size, we may use any size. I guess larger the better.
var testSize = '72px';
var h = document.getElementsByTagName("body")[0];
// create a SPAN in the document to get the width of the text we use to test
var s = document.createElement("span");
s.style.fontSize = testSize;
s.innerHTML = testString;
var defaultWidth = {};
var defaultHeight = {};
for (var index in baseFonts) {
//get the default width for the three base fonts
s.style.fontFamily = baseFonts[index];
h.appendChild(s);
defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font
defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font
h.removeChild(s);
}
function detect(font) {
var detected = false;
for (var index in baseFonts) {
s.style.fontFamily = font + ',' + baseFonts[index]; // name of the font along with the base font for fallback.
h.appendChild(s);
var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]);
h.removeChild(s);
detected = detected || matched;
}
return detected;
}
this.detect = detect;
};
/*********************************************************************************
* Copyright (C) 2011-2014 X2Engine Inc. All Rights Reserved.
*
* X2Engine Inc.
* P.O. Box 66752
* Scotts Valley, California 95067 USA
*
* Company website: http://www.x2engine.com
* Community and support website: http://www.x2community.com
*
* X2Engine Inc. grants you a perpetual, non-exclusive, non-transferable license
* to install and use this Software for your internal business purposes.
* You shall not modify, distribute, license or sublicense the Software.
* Title, ownership, and all intellectual property rights in the Software belong
* exclusively to X2Engine.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT.
********************************************************************************/
/* @edition:pla */
var x2Identity = {};
/**
* JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
*
* @author Gary Court
* @see http://github.com/garycourt/murmurhash-js
* @author Austin Appleby
* @see http://sites.google.com/site/murmurhash/
*
* @param {string} key ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
x2Identity.murmurhash3 = function(key, seed) {
var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i;
remainder = key.length & 3; // key.length % 4
bytes = key.length - remainder;
h1 = seed;
c1 = 0xcc9e2d51;
c2 = 0x1b873593;
i = 0;
while (i < bytes) {
k1 =
((key.charCodeAt(i) & 0xff)) |
((key.charCodeAt(++i) & 0xff) << 8) |
((key.charCodeAt(++i) & 0xff) << 16) |
((key.charCodeAt(++i) & 0xff) << 24);
++i;
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
}
k1 = 0;
switch (remainder) {
case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
case 1: k1 ^= (key.charCodeAt(i) & 0xff);
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
h1 ^= key.length;
h1 ^= h1 >>> 16;
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
};
/**
* Gather information about the clients browser and hash it to form the fingerprint.
*/
x2Identity.fingerprint = function (options) {
var fingerprint = [],
attributes = {},
plugins = [],
fonts = [],
ua, res, req, headers, cookieEnabled;
if (navigator.appName === "Microsoft Internet Explorer" ||
(navigator.appName === 'Netscape' && /Trident/.test(navigator.userAgent))) {
// Internet Explorer
var testPlugins = ['ShockwaveFlash.ShockwaveFlash', 'AcroPDF.PDF', 'PDF.PdfCtrl', 'QuickTime.QuickTime', 'rmocx.RealPlayer G2 Control',
'rmocx.RealPlayer G2 Control.1', 'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)', 'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',
'RealPlayer', 'SWCtl.SWCtl', 'WMPlayer.OCX', 'AgControl.AgControl', 'Skype.Detection'];
for (var plugin in testPlugins) {
var found = false;
if (navigator.plugins[plugin])
found = true;
try {
new ActiveXObject(plugin);
found = true;
} catch(e) {
// Plugin does not exist
}
if (found)
plugins.push(plugin);
}
} else {
// Non-IE Browsers
for (var i = 0; i < navigator.plugins.length; i++) {
var plugin = navigator.plugins[i];
var pluginString = plugin.name;
if (plugin.description.length > 0)
pluginString += " (" + plugin.description + ")";
plugins.push( pluginString );
};
}
if (plugins.length > 0) {
var pluginString = plugins.join(',');
fingerprint.push( pluginString );
attributes['plugins'] = x2Identity.murmurhash3 (pluginString, 31);
}
ua = navigator.userAgent;
if (typeof ua !== 'undefined') {
fingerprint.push( ua );
attributes['userAgent'] = ua;
}
fingerprint.push( navigator.language );
attributes['language'] = navigator.language;
if (typeof screen.height !== 'undefined' && screen.width !== 'undefined') {
res = screen.height + 'x' + screen.width + 'x' + screen.colorDepth;
}else if (typeof screen.availHeight !== 'undefined' && screen.availWidth !== 'undefined') {
res = screen.availHeight + 'x' + screen.availWidth + 'x' + screen.colorDepth;
}
if (res !== 'undefined') {
fingerprint.push( res );
attributes['screenRes'] = res;
}
var tz = new Date().getTimezoneOffset()
fingerprint.push( tz );
attributes['timezone'] = tz;
cookieEnabled = (navigator.cookieEnabled) ? 1 : 0;
if (typeof navigator.cookieEnabled === 'undefined' && !cookieEnabled) {
document.cookie = "testcookie";
cookieEnabled = (document.cookie.indexOf('testcookie') != -1)? 1 : 0;
}
fingerprint.push( cookieEnabled );
attributes['cookiesEnabled'] = cookieEnabled;
try { // attempt to access indexedDB throws an error in ff selenium tests
if (typeof window.indexedDB !== 'undefined') {
fingerprint.push( true );
attributes['indexedDB'] = 1;
} else {
attributes['indexedDB'] = 0;
}
} catch (e) {
attributes['indexedDB'] = 1;
}
if (typeof document.body !== 'undefined' && typeof document.body.addBehavior !== 'undefined') {
fingerprint.push( true );
attributes['addBehavior'] = 1;
} else
attributes['addBehavior'] = 0;
if (typeof navigator.javaEnabled() !== 'undefined') {
fingerprint.push( true );
attributes['javaEnabled'] = 1;
} else
attributes['javaEnabled'] = 0;
// Build an HTML5 Canvas fingerprint
var canvas = document.createElement('canvas');
if (typeof canvas.getContext !== 'undefined') {
// https://www.browserleaks.com/canvas#how-does-it-work
var ctx = canvas.getContext('2d');
var txt = "BrowserLeaks,com