Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'js/piwik.js')
-rw-r--r--js/piwik.js212
1 files changed, 207 insertions, 5 deletions
diff --git a/js/piwik.js b/js/piwik.js
index fa9d9f57e5..344e5436e9 100644
--- a/js/piwik.js
+++ b/js/piwik.js
@@ -1021,7 +1021,7 @@ if (typeof JSON2 !== 'object' && typeof window.JSON === 'object' && window.JSON.
trackVisibleContentImpressions, isTrackOnlyVisibleContentEnabled, port, isUrlToCurrentDomain,
isNodeAuthorizedToTriggerInteraction, replaceHrefIfInternalLink, getConfigDownloadExtensions, disableLinkTracking,
substr, setAnyAttribute, wasContentTargetAttrReplaced, max, abs, childNodes, compareDocumentPosition, body,
- getConfigVisitorCookieTimeout, getRemainingVisitorCookieTimeout,
+ getConfigVisitorCookieTimeout, getRemainingVisitorCookieTimeout, getDomains, getConfigCookiePath,
newVisitor, uuid, createTs, visitCount, currentVisitTs, lastVisitTs, lastEcommerceOrderTs,
"", "\b", "\t", "\n", "\f", "\r", "\"", "\\", apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, parse, prototype, push, replace,
@@ -1593,6 +1593,10 @@ if (typeof Piwik !== 'object') {
domain = domain.slice(1);
}
+ if (domain.indexOf('/') !== -1) {
+ domain = domain.substr(0, domain.indexOf('/'));
+ }
+
return domain;
}
@@ -3012,10 +3016,115 @@ if (typeof Piwik !== 'object') {
return baseUrl + url;
}
+ function isSameHost (hostName, alias) {
+ var offset;
+
+ hostName = String(hostName).toLowerCase();
+ alias = String(alias).toLowerCase();
+
+ if (hostName === alias) {
+ return true;
+ }
+
+ if (alias.slice(0, 1) === '.') {
+ if (hostName === alias.slice(1)) {
+ return true;
+ }
+
+ offset = hostName.length - alias.length;
+
+ if ((offset > 0) && (hostName.slice(offset) === alias)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function stringEndsWith(str, suffix) {
+ str = String(str);
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+ }
+
+ function removeCharactersFromEndOfString(str, numCharactersToRemove) {
+ str = String(str);
+ return str.substr(0, str.length - numCharactersToRemove);
+ }
+
+ /*
+ * Extract pathname from URL. element.pathname is actually supported by pretty much all browsers including
+ * IE6 apart from some rare very old ones
+ */
+ function getPathName(url) {
+ var parser = document.createElement('a');
+ if (url.indexOf('//') !== 0 && url.indexOf('http') !== 0) {
+ url = 'http://' + url;
+ }
+
+ parser.href = content.toAbsoluteUrl(url);
+ if (parser.pathname) {
+ return parser.pathname;
+ }
+
+ return '';
+ }
+
+ function isSitePath (path, pathAlias)
+ {
+ var matchesAnyPath = (!pathAlias || pathAlias === '/');
+
+ if (matchesAnyPath) {
+ return true;
+ }
+
+ if (path === pathAlias) {
+ return true;
+ }
+
+ if (!path) {
+ return false;
+ }
+
+ pathAlias = String(pathAlias).toLowerCase();
+ path = String(path).toLowerCase();
+
+ // we need to append slashes so /foobarbaz won't match a site /foobar
+ if (!stringEndsWith(path, '/')) {
+ path += '/';
+ }
+
+ if (!stringEndsWith(pathAlias, '/')) {
+ pathAlias += '/';
+ }
+
+ return path.indexOf(pathAlias) === 0;
+ }
+
+ function isSiteHostPath(host, path)
+ {
+ var i,
+ alias,
+ configAlias,
+ aliasHost,
+ aliasPath;
+
+ for (i = 0; i < configHostsAlias.length; i++) {
+ aliasHost = domainFixup(configHostsAlias[i]);
+ aliasPath = getPathName(configHostsAlias[i]);
+
+ if (isSameHost(host, aliasHost) && isSitePath(path, aliasPath)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/*
* Is the host local? (i.e., not an outlink)
*/
function isSiteHostName(hostName) {
+
var i,
alias,
offset;
@@ -4004,6 +4113,8 @@ if (typeof Piwik !== 'object') {
return;
}
+ var originalSourcePath = sourceElement.pathname || getPathName(sourceElement.href);
+
// browsers, such as Safari, don't downcase hostname and href
var originalSourceHostName = sourceElement.hostname || getHostName(sourceElement.href);
var sourceHostName = originalSourceHostName.toLowerCase();
@@ -4014,7 +4125,7 @@ if (typeof Piwik !== 'object') {
if (!scriptProtocol.test(sourceHref)) {
// track outlinks and all downloads
- var linkType = getLinkType(sourceElement.className, sourceHref, isSiteHostName(sourceHostName), query.hasNodeAttribute(sourceElement, 'download'));
+ var linkType = getLinkType(sourceElement.className, sourceHref, isSiteHostPath(sourceHostName, originalSourcePath), query.hasNodeAttribute(sourceElement, 'download'));
if (linkType) {
return {
@@ -4780,6 +4891,60 @@ if (typeof Piwik !== 'object') {
});
}
+ /**
+ * Note: While we check whether the user is on a configHostAlias path we do not check whether the user is
+ * actually on the configHostAlias domain. This is already done where this method is called and for
+ * simplicity we do not check this again.
+ *
+ * Also we currently assume that all configHostAlias domains start with the same wild card of '*.', '.' or
+ * none. Eg either all like '*.piwik.org' or '.piwik.org' or 'piwik.org'. Piwik always adds '*.' so it
+ * should be fine.
+ */
+ function findConfigCookiePathToUse(configHostAlias, currentUrl)
+ {
+ var aliasPath = getPathName(configHostAlias);
+ var currentPath = getPathName(currentUrl);
+
+ if (!aliasPath || aliasPath === '/' || !currentPath || currentPath === '/') {
+ // no path set that would be useful for cookiePath
+ return;
+ }
+
+ var aliasDomain = domainFixup(configHostAlias);
+
+ if (isSiteHostPath(aliasDomain, '/')) {
+ // there is another configHostsAlias having same domain that allows all paths
+ // eg this alias is for piwik.org/support but there is another alias allowing
+ // piwik.org
+ return;
+ }
+
+ if (stringEndsWith(aliasPath, '/')) {
+ aliasPath = removeCharactersFromEndOfString(aliasPath, 1);
+ }
+
+ // eg if we're in the case of "apache.piwik/foo/bar" we check whether there is maybe
+ // also a config alias allowing "apache.piwik/foo". In this case we're not allowed to set
+ // the cookie for "/foo/bar" but "/foo"
+ var pathAliasParts = aliasPath.split('/');
+ var i;
+ for (i = 2; i < pathAliasParts.length; i++) {
+ var lessRestrctivePath = pathAliasParts.slice(0, i).join('/');
+ if (isSiteHostPath(aliasDomain, lessRestrctivePath)) {
+ aliasPath = lessRestrctivePath;
+ break;
+ }
+ }
+
+ if (!isSitePath(currentPath, aliasPath)) {
+ // current path of current URL does not match the alias
+ // eg user is on piwik.org/demo but configHostAlias is for piwik.org/support
+ return;
+ }
+
+ return aliasPath;
+ }
+
/*
* Browser features (plugins, resolution, cookies)
*/
@@ -4917,6 +5082,12 @@ if (typeof Piwik !== 'object') {
internalIsNodeVisible: isVisible,
isNodeAuthorizedToTriggerInteraction: isNodeAuthorizedToTriggerInteraction,
replaceHrefIfInternalLink: replaceHrefIfInternalLink,
+ getDomains: function () {
+ return configHostsAlias;
+ },
+ getConfigCookiePath: function () {
+ return configCookiePath;
+ },
getConfigDownloadExtensions: function () {
return configDownloadExtensions;
},
@@ -5347,13 +5518,44 @@ if (typeof Piwik !== 'object') {
},
/**
- * Set array of domains to be treated as local
+ * Set array of domains to be treated as local. Also supports path, eg '.piwik.org/subsite1'. In this
+ * case all links that don't go to '*.piwik.org/subsite1/ *' would be treated as outlinks.
+ * For example a link to 'piwik.org/' or 'piwik.org/subsite2' both would be treated as outlinks.
+ *
+ * We might automatically set a cookieConfigPath to avoid creating several cookies under one domain
+ * if there is a hostAlias defined with a path. Say a user is visiting 'http://piwik.org/subsite1'
+ * and '.piwik.org/subsite1' is set as a hostsAlias. Piwik will automatically use '/subsite1' as
+ * cookieConfigPath.
*
* @param string|array hostsAlias
*/
setDomains: function (hostsAlias) {
configHostsAlias = isString(hostsAlias) ? [hostsAlias] : hostsAlias;
- configHostsAlias.push(domainAlias);
+
+ var hasDomainAliasAlready = false, i;
+ for (i in configHostsAlias) {
+ if (Object.prototype.hasOwnProperty.call(configHostsAlias, i)
+ && isSameHost(domainAlias, domainFixup(String(configHostsAlias[i])))) {
+ hasDomainAliasAlready = true;
+
+ if (!configCookiePath) {
+ var path = findConfigCookiePathToUse(configHostsAlias[i], locationHrefAlias);
+ if (path) {
+ this.setCookiePath(path);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (!hasDomainAliasAlready) {
+ /**
+ * eg if domainAlias = 'piwik.org' and someone set hostsAlias = ['piwik.org/foo'] then we should
+ * not add piwik.org as it would increase the allowed scope.
+ */
+ configHostsAlias.push(domainAlias);
+ }
},
/**
@@ -6195,7 +6397,7 @@ if (typeof Piwik !== 'object') {
asyncTracker = new Tracker();
- var applyFirst = ['disableCookies', 'setTrackerUrl', 'setAPIUrl', 'setCookiePath', 'setCookieDomain', 'setUserId', 'setSiteId', 'enableLinkTracking'];
+ var applyFirst = ['disableCookies', 'setTrackerUrl', 'setAPIUrl', 'setCookiePath', 'setCookieDomain', 'setDomains', 'setUserId', 'setSiteId', 'enableLinkTracking'];
_paq = applyMethodsInOrder(_paq, applyFirst);
// apply the queue of actions