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:
authorThomas Steur <thomas.steur@googlemail.com>2014-09-12 19:42:39 +0400
committerThomas Steur <thomas.steur@googlemail.com>2014-09-12 19:42:39 +0400
commit19d5f67005fcb513253139ea149255c9ceb4320c (patch)
tree3de112844e749a241e62b81145cbf356f73767aa
parent0aea1092d32050dfb0b0f6791061536a6777acbc (diff)
refs #4996 redirect only to trusted hosts (will have to remove this most likely again as you would have to register subdomains etc as well). Also added some missing test files
-rw-r--r--core/Tracker.php31
-rw-r--r--core/Url.php40
-rw-r--r--plugins/SitesManager/API.php37
-rw-r--r--plugins/SitesManager/Model.php57
-rw-r--r--tests/PHPUnit/Core/UrlTest.php50
-rw-r--r--tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentNames_day.xml21
-rw-r--r--tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentPieces_day.xml48
7 files changed, 245 insertions, 39 deletions
diff --git a/core/Tracker.php b/core/Tracker.php
index d9e8a04278..a690a31225 100644
--- a/core/Tracker.php
+++ b/core/Tracker.php
@@ -10,6 +10,7 @@ namespace Piwik;
use Exception;
use Piwik\Plugins\PrivacyManager\Config as PrivacyManagerConfig;
+use Piwik\Plugins\SitesManager\Model;
use Piwik\Tracker\Cache;
use Piwik\Tracker\Db\DbException;
use Piwik\Tracker\Db\Mysqli;
@@ -912,7 +913,6 @@ class Tracker
private function getRedirectUrl()
{
- // TODO only redirecti if domain is trusted in config?
return Common::getRequestVar('redirecturl', false, 'string');
}
@@ -925,10 +925,33 @@ class Tracker
private function performRedirectToUrlIfSet()
{
- if ($this->hasRedirectUrl()) {
- $redirectUrl = $this->getRedirectUrl();
- header('Location: ' . $redirectUrl);
+ if (!$this->hasRedirectUrl()) {
+ return;
+ }
+
+ $redirectUrl = $this->getRedirectUrl();
+ $host = Url::getHostFromUrl($redirectUrl);
+
+ if (empty($host)) {
+ return;
+ }
+
+ $model = new Model();
+ $siteIds = $model->getSitesId();
+
+ foreach ($siteIds as $siteId) {
+ $siteUrls = $model->getSiteUrlsFromId($siteId);
+
+ if (Url::isHostInUrls($host, $siteUrls)) {
+ Url::redirectToUrl($redirectUrl);
+ }
+ }
+
+ $trustedHosts = Url::getTrustedHosts();
+ if (Url::isHostInUrls($host, $trustedHosts)) {
+ Url::redirectToUrl($redirectUrl);
}
}
+
}
diff --git a/core/Url.php b/core/Url.php
index 269c3ef6d1..3a52cc9806 100644
--- a/core/Url.php
+++ b/core/Url.php
@@ -598,4 +598,44 @@ class Url
}
return $hosts;
}
+
+ public static function getHostFromUrl($url)
+ {
+ $parsedUrl = parse_url($url);
+
+ if (empty($parsedUrl['host'])) {
+ return;
+ }
+
+ return Common::mb_strtolower($parsedUrl['host']);
+ }
+
+ public static function isHostInUrls($host, $urls)
+ {
+ if (empty($host)) {
+ return false;
+ }
+
+ $host = Common::mb_strtolower($host);
+
+ if (!empty($urls)) {
+ foreach ($urls as $url) {
+ if (Common::mb_strtolower($url) === $host) {
+ return true;
+ }
+
+ $siteHost = self::getHostFromUrl($url);
+
+ if ($siteHost === $host) {
+ return true;
+ }
+
+ if (Common::stringEndsWith($siteHost, $host)) {
+ return;
+ }
+ }
+ }
+
+ return in_array($host, self::$alwaysTrustedHosts);
+ }
}
diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php
index 8eca58f47b..c65a9f4259 100644
--- a/plugins/SitesManager/API.php
+++ b/plugins/SitesManager/API.php
@@ -193,26 +193,6 @@ class API extends \Piwik\Plugin\API
}
/**
- * Returns the list of alias URLs registered for the given idSite.
- * The website ID must be valid when calling this method!
- *
- * @param int $idSite
- * @return array list of alias URLs
- */
- private function getAliasSiteUrlsFromId($idSite)
- {
- $db = Db::get();
- $result = $db->fetchAll("SELECT url
- FROM " . Common::prefixTable("site_url") . "
- WHERE idsite = ?", $idSite);
- $urls = array();
- foreach ($result as $url) {
- $urls[] = $url['url'];
- }
- return $urls;
- }
-
- /**
* Returns the list of all URLs registered for the given idSite (main_url + alias URLs).
*
* @throws Exception if the website ID doesn't exist or the user doesn't have access to it
@@ -222,25 +202,12 @@ class API extends \Piwik\Plugin\API
public function getSiteUrlsFromId($idSite)
{
Piwik::checkUserHasViewAccess($idSite);
- $site = new Site($idSite);
- $urls = $this->getAliasSiteUrlsFromId($idSite);
- return array_merge(array($site->getMainUrl()), $urls);
+ return $this->getModel()->getSiteUrlsFromId($idSite);
}
- /**
- * Returns the list of all the website IDs registered.
- * Caller must check access.
- *
- * @return array The list of website IDs
- */
private function getSitesId()
{
- $result = Db::fetchAll("SELECT idsite FROM " . Common::prefixTable('site'));
- $idSites = array();
- foreach ($result as $idSite) {
- $idSites[] = $idSite['idsite'];
- }
- return $idSites;
+ return $this->getModel()->getSitesId();
}
/**
diff --git a/plugins/SitesManager/Model.php b/plugins/SitesManager/Model.php
index 9e77f48888..207f59bdfd 100644
--- a/plugins/SitesManager/Model.php
+++ b/plugins/SitesManager/Model.php
@@ -11,6 +11,7 @@ namespace Piwik\Plugins\SitesManager;
use Piwik\Db;
use Piwik\Common;
use Exception;
+use Piwik\Site;
class Model
{
@@ -59,4 +60,60 @@ class Model
return $site;
}
+
+ /**
+ * Returns the list of all the website IDs registered.
+ * Caller must check access.
+ *
+ * @return array The list of website IDs
+ */
+ public function getSitesId()
+ {
+ $result = Db::fetchAll("SELECT idsite FROM " . Common::prefixTable('site'));
+ $idSites = array();
+ foreach ($result as $idSite) {
+ $idSites[] = $idSite['idsite'];
+ }
+ return $idSites;
+ }
+
+ /**
+ * Returns the list of all URLs registered for the given idSite (main_url + alias URLs).
+ *
+ * @throws Exception if the website ID doesn't exist or the user doesn't have access to it
+ * @param int $idSite
+ * @return array list of URLs
+ */
+ public function getSiteUrlsFromId($idSite)
+ {
+ $urls = $this->getAliasSiteUrlsFromId($idSite);
+
+ $site = $this->getSiteFromId($idSite);
+
+ if (empty($site)) {
+ return $urls;
+ }
+
+ return array_merge(array($site['main_url']), $urls);
+ }
+
+ /**
+ * Returns the list of alias URLs registered for the given idSite.
+ * The website ID must be valid when calling this method!
+ *
+ * @param int $idSite
+ * @return array list of alias URLs
+ */
+ public function getAliasSiteUrlsFromId($idSite)
+ {
+ $db = Db::get();
+ $result = $db->fetchAll("SELECT url
+ FROM " . Common::prefixTable("site_url") . "
+ WHERE idsite = ?", $idSite);
+ $urls = array();
+ foreach ($result as $url) {
+ $urls[] = $url['url'];
+ }
+ return $urls;
+ }
}
diff --git a/tests/PHPUnit/Core/UrlTest.php b/tests/PHPUnit/Core/UrlTest.php
index fe4261854f..2620b9a5c9 100644
--- a/tests/PHPUnit/Core/UrlTest.php
+++ b/tests/PHPUnit/Core/UrlTest.php
@@ -280,4 +280,54 @@ class UrlTest extends PHPUnit_Framework_TestCase
);
}
+ /**
+ * @group Core
+ *
+ * @dataProvider getHostsFromUrl
+ */
+ public function testGetHostsFromUrl($url, $expectedHost)
+ {
+ $this->assertEquals($expectedHost, Url::getHostFromUrl($url));
+ }
+
+ public function getHostsFromUrl()
+ {
+ return array(
+ array(null, null),
+ array('http://', null),
+ array('http://www.example.com', 'www.example.com'),
+ array('http://www.ExaMplE.cOm', 'www.example.com'),
+ array('http://www.example.com/test/foo?bar=xy', 'www.example.com'),
+ array('http://127.0.0.1', '127.0.0.1'),
+ array('example.com', null),
+ );
+ }
+
+ /**
+ * @group Core
+ *
+ * @dataProvider getIsHostInUrls
+ */
+ public function testIsHostInUrlsl($isHost, $host, $urls)
+ {
+ $this->assertEquals($isHost, Url::isHostInUrls($host, $urls));
+ }
+
+ public function getIsHostInUrls()
+ {
+ return array(
+ array(false, null, null),
+ array(false, 'http://', array()),
+ array(false, 'example.com', array()),
+ array(false, 'www.example.com', array()),
+ array(false, 'example.com', array('www.example.com')),
+ array(false, 'example.com', array('http://www.example.com')),
+ array(true, 'example.com', array('example.com')),
+ array(true, 'eXamPle.com', array('exaMple.com')),
+ array(true, 'eXamPle.com', array('http://exaMple.com')),
+ array(true, 'example.com', array('http://example.com/test')),
+ array(true, '127.0.0.1', array()), // always trusted host
+ );
+ }
+
}
diff --git a/tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentNames_day.xml b/tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentNames_day.xml
new file mode 100644
index 0000000000..17b781db1c
--- /dev/null
+++ b/tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentNames_day.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <row>
+ <label>ImageAd</label>
+ <nb_uniq_visitors>8</nb_uniq_visitors>
+ <nb_visits>8</nb_visits>
+ <nb_impressions>8</nb_impressions>
+ <nb_interactions>2</nb_interactions>
+ <interaction_rate>25%</interaction_rate>
+ <contentTarget>http://www.example.com</contentTarget>
+ </row>
+ <row>
+ <label>Text Ad</label>
+ <nb_uniq_visitors>4</nb_uniq_visitors>
+ <nb_visits>4</nb_visits>
+ <nb_impressions>4</nb_impressions>
+ <nb_interactions>2</nb_interactions>
+ <interaction_rate>50%</interaction_rate>
+ <contentTarget>http://piwik.org/download</contentTarget>
+ </row>
+</result> \ No newline at end of file
diff --git a/tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentPieces_day.xml b/tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentPieces_day.xml
new file mode 100644
index 0000000000..7df6e4f0e1
--- /dev/null
+++ b/tests/PHPUnit/Integration/expected/test_ContentscontentNameOrPieceMatch__Contents.getContentPieces_day.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<result>
+ <row>
+ <label>Click to download Piwik now</label>
+ <nb_uniq_visitors>4</nb_uniq_visitors>
+ <nb_visits>4</nb_visits>
+ <nb_impressions>4</nb_impressions>
+ <nb_interactions>2</nb_interactions>
+ <interaction_rate>50%</interaction_rate>
+ <contentTarget>http://piwik.org/download</contentTarget>
+ </row>
+ <row>
+ <label>/path/ad.jpg</label>
+ <nb_uniq_visitors>2</nb_uniq_visitors>
+ <nb_visits>2</nb_visits>
+ <nb_impressions>2</nb_impressions>
+ <nb_interactions>2</nb_interactions>
+ <interaction_rate>100%</interaction_rate>
+ <contentTarget>http://www.example.com</contentTarget>
+ </row>
+ <row>
+ <label>/path/ad2.jpg</label>
+ <nb_uniq_visitors>2</nb_uniq_visitors>
+ <nb_visits>2</nb_visits>
+ <nb_impressions>2</nb_impressions>
+ <nb_interactions>0</nb_interactions>
+ <interaction_rate>0%</interaction_rate>
+ <contentTarget>http://www.example.com</contentTarget>
+ </row>
+ <row>
+ <label>Content Piece not defined</label>
+ <nb_uniq_visitors>2</nb_uniq_visitors>
+ <nb_visits>2</nb_visits>
+ <nb_impressions>2</nb_impressions>
+ <nb_interactions>0</nb_interactions>
+ <interaction_rate>0%</interaction_rate>
+ <contentTarget />
+ </row>
+ <row>
+ <label>Unknown</label>
+ <nb_uniq_visitors>2</nb_uniq_visitors>
+ <nb_visits>2</nb_visits>
+ <nb_impressions>2</nb_impressions>
+ <nb_interactions>0</nb_interactions>
+ <interaction_rate>0%</interaction_rate>
+ <contentTarget />
+ </row>
+</result> \ No newline at end of file