Skip to content
Extraits de code Groupes Projets
Valider 19d5f670 rédigé par Thomas Steur's avatar Thomas Steur
Parcourir les fichiers

refs #4996 redirect only to trusted hosts (will have to remove this most...

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
parent 0aea1092
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -10,6 +10,7 @@ namespace Piwik; ...@@ -10,6 +10,7 @@ namespace Piwik;
use Exception; use Exception;
use Piwik\Plugins\PrivacyManager\Config as PrivacyManagerConfig; use Piwik\Plugins\PrivacyManager\Config as PrivacyManagerConfig;
use Piwik\Plugins\SitesManager\Model;
use Piwik\Tracker\Cache; use Piwik\Tracker\Cache;
use Piwik\Tracker\Db\DbException; use Piwik\Tracker\Db\DbException;
use Piwik\Tracker\Db\Mysqli; use Piwik\Tracker\Db\Mysqli;
...@@ -912,7 +913,6 @@ class Tracker ...@@ -912,7 +913,6 @@ class Tracker
private function getRedirectUrl() private function getRedirectUrl()
{ {
// TODO only redirecti if domain is trusted in config?
return Common::getRequestVar('redirecturl', false, 'string'); return Common::getRequestVar('redirecturl', false, 'string');
} }
...@@ -925,10 +925,33 @@ class Tracker ...@@ -925,10 +925,33 @@ class Tracker
private function performRedirectToUrlIfSet() private function performRedirectToUrlIfSet()
{ {
if ($this->hasRedirectUrl()) { if (!$this->hasRedirectUrl()) {
$redirectUrl = $this->getRedirectUrl(); return;
header('Location: ' . $redirectUrl); }
$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);
} }
} }
} }
...@@ -598,4 +598,44 @@ class Url ...@@ -598,4 +598,44 @@ class Url
} }
return $hosts; 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);
}
} }
...@@ -192,26 +192,6 @@ class API extends \Piwik\Plugin\API ...@@ -192,26 +192,6 @@ class API extends \Piwik\Plugin\API
return new Model(); return new Model();
} }
/**
* 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). * Returns the list of all URLs registered for the given idSite (main_url + alias URLs).
* *
...@@ -222,25 +202,12 @@ class API extends \Piwik\Plugin\API ...@@ -222,25 +202,12 @@ class API extends \Piwik\Plugin\API
public function getSiteUrlsFromId($idSite) public function getSiteUrlsFromId($idSite)
{ {
Piwik::checkUserHasViewAccess($idSite); Piwik::checkUserHasViewAccess($idSite);
$site = new Site($idSite); return $this->getModel()->getSiteUrlsFromId($idSite);
$urls = $this->getAliasSiteUrlsFromId($idSite);
return array_merge(array($site->getMainUrl()), $urls);
} }
/**
* Returns the list of all the website IDs registered.
* Caller must check access.
*
* @return array The list of website IDs
*/
private function getSitesId() private function getSitesId()
{ {
$result = Db::fetchAll("SELECT idsite FROM " . Common::prefixTable('site')); return $this->getModel()->getSitesId();
$idSites = array();
foreach ($result as $idSite) {
$idSites[] = $idSite['idsite'];
}
return $idSites;
} }
/** /**
......
...@@ -11,6 +11,7 @@ namespace Piwik\Plugins\SitesManager; ...@@ -11,6 +11,7 @@ namespace Piwik\Plugins\SitesManager;
use Piwik\Db; use Piwik\Db;
use Piwik\Common; use Piwik\Common;
use Exception; use Exception;
use Piwik\Site;
class Model class Model
{ {
...@@ -59,4 +60,60 @@ class Model ...@@ -59,4 +60,60 @@ class Model
return $site; 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;
}
} }
...@@ -280,4 +280,54 @@ class UrlTest extends PHPUnit_Framework_TestCase ...@@ -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
);
}
} }
<?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
<?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
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter