diff options
author | sgiehl <stefan@piwik.org> | 2014-11-15 23:09:57 +0300 |
---|---|---|
committer | sgiehl <stefan@piwik.org> | 2014-11-15 23:09:57 +0300 |
commit | dff3519bc9152076062b1cd046594103756a5d42 (patch) | |
tree | 2cb1f8397b5311a26ecfa2261d2cce8a2174464a /core | |
parent | a45c6b956f1828a1a9a209a7bd72a6816e907de7 (diff) | |
parent | d78c73e305aa1bd8c2f0e01a0b9f17292f6b0c88 (diff) |
Merge branch 'master' into deprecate_usersettings
Diffstat (limited to 'core')
-rw-r--r-- | core/Common.php | 92 | ||||
-rw-r--r-- | core/DataArray.php | 5 | ||||
-rw-r--r-- | core/Exception/AuthenticationFailedException.php | 13 | ||||
-rw-r--r-- | core/Exception/Exception.php (renamed from core/Exceptions/HtmlMessageException.php) | 24 | ||||
-rw-r--r-- | core/Exception/MissingFilePermissionException.php | 13 | ||||
-rw-r--r-- | core/Exception/NoPrivilegesException.php | 13 | ||||
-rw-r--r-- | core/Exception/NoWebsiteFoundException.php | 13 | ||||
-rw-r--r-- | core/Filechecks.php | 9 | ||||
-rw-r--r-- | core/FrontController.php | 23 | ||||
-rw-r--r-- | core/Plugin/Controller.php | 15 | ||||
-rw-r--r-- | core/Plugin/MetadataLoader.php | 2 | ||||
-rw-r--r-- | core/Session.php | 7 | ||||
-rw-r--r-- | core/Tracker.php | 29 | ||||
-rw-r--r-- | core/Translate.php | 2 | ||||
-rwxr-xr-x | core/Twig.php | 3 | ||||
-rw-r--r-- | core/Updates/1.8.3-b1.php | 4 | ||||
-rw-r--r-- | core/Version.php | 2 |
17 files changed, 204 insertions, 65 deletions
diff --git a/core/Common.php b/core/Common.php index 6dfa2d22fa..a3e7515a24 100644 --- a/core/Common.php +++ b/core/Common.php @@ -34,6 +34,7 @@ class Common /* * Database */ + const LANGUAGE_CODE_INVALID = 'xx'; /** * Hashes a string into an integer which should be very low collision risks @@ -461,7 +462,7 @@ class Common // we deal w/ json differently if ($varType == 'json') { $value = self::undoMagicQuotes($requestArrayToUse[$varName]); - $value = self::json_decode($value, $assoc = true); + $value = json_decode($value, $assoc = true); return self::sanitizeInputValues($value, $alreadyStripslashed = true); } @@ -937,8 +938,8 @@ class Common */ public static function getCountry($lang, $enableLanguageToCountryGuess, $ip) { - if (empty($lang) || strlen($lang) < 2 || $lang == 'xx') { - return 'xx'; + if (empty($lang) || strlen($lang) < 2 || $lang == self::LANGUAGE_CODE_INVALID) { + return self::LANGUAGE_CODE_INVALID; } $validCountries = self::getCountriesList(); @@ -974,35 +975,73 @@ class Common } } } - return 'xx'; + return self::LANGUAGE_CODE_INVALID; } /** - * Returns the visitor language based only on the Browser 'accepted language' information + * Returns the language and region string, based only on the Browser 'accepted language' information. + * * The language tag is defined by ISO 639-1 * * @param string $browserLanguage Browser's accepted langauge header * @param array $validLanguages array of valid language codes - * @return string 2 letter ISO 639 code + * @return string 2 letter ISO 639 code 'es' (Spanish) */ - public static function extractLanguageCodeFromBrowserLanguage($browserLanguage, $validLanguages) + public static function extractLanguageCodeFromBrowserLanguage($browserLanguage, $validLanguages = array()) { - // assumes language preference is sorted; - // does not handle language-script-region tags or language range (*) - if (!empty($validLanguages) && preg_match_all('/(?:^|,)([a-z]{2,3})([-][a-z]{2})?/', $browserLanguage, $matches, PREG_SET_ORDER)) { - foreach ($matches as $parts) { - if (count($parts) == 3) { - // match locale (language and location) - if (in_array($parts[1] . $parts[2], $validLanguages)) { - return $parts[1] . $parts[2]; - } + $validLanguages = self::checkValidLanguagesIsSet($validLanguages); + $languageRegionCode = self::extractLanguageAndRegionCodeFromBrowserLanguage($browserLanguage, $validLanguages); + + if(strlen($languageRegionCode) == 2) { + $languageCode = $languageRegionCode; + } else { + $languageCode = substr($languageRegionCode, 0, 2); + } + if(in_array($languageCode, $validLanguages)) { + return $languageCode; + } + return self::LANGUAGE_CODE_INVALID; + } + + /** + * Returns the language and region string, based only on the Browser 'accepted language' information. + * * The language tag is defined by ISO 639-1 + * * The region tag is defined by ISO 3166-1 + * + * @param string $browserLanguage Browser's accepted langauge header + * @param array $validLanguages array of valid language codes. Note that if the array includes "fr" then it will consider all regional variants of this language valid, such as "fr-ca" etc. + * @return string 2 letter ISO 639 code 'es' (Spanish) or if found, includes the region as well: 'es-ar' + */ + public static function extractLanguageAndRegionCodeFromBrowserLanguage($browserLanguage, $validLanguages = array() ) + { + $validLanguages = self::checkValidLanguagesIsSet($validLanguages); + + if(!preg_match_all('/(?:^|,)([a-z]{2,3})([-][a-z]{2})?/', $browserLanguage, $matches, PREG_SET_ORDER)) { + return self::LANGUAGE_CODE_INVALID; + } + foreach ($matches as $parts) { + $langIso639 = $parts[1]; + if(empty($langIso639)) { + continue; + } + + // If a region tag is found eg. "fr-ca" + if (count($parts) == 3) { + $regionIso3166 = $parts[2]; // eg. "-ca" + + if (in_array($langIso639 . $regionIso3166, $validLanguages)) { + return $langIso639 . $regionIso3166; } - // match language only (where no region provided) - if (in_array($parts[1], $validLanguages)) { - return $parts[1]; + + if (in_array($langIso639, $validLanguages)) { + return $langIso639 . $regionIso3166; } } + // eg. "fr" or "es" + if (in_array($langIso639, $validLanguages)) { + return $langIso639; + } } - return 'xx'; + return self::LANGUAGE_CODE_INVALID; } /** @@ -1161,4 +1200,17 @@ class Common } } } + + /** + * @param $validLanguages + * @return array + */ + protected static function checkValidLanguagesIsSet($validLanguages) + { + if (empty($validLanguages)) { + $validLanguages = array_keys(Common::getLanguagesList()); + return $validLanguages; + } + return $validLanguages; + } } diff --git a/core/DataArray.php b/core/DataArray.php index 7515ef8699..2eab0bbab5 100644 --- a/core/DataArray.php +++ b/core/DataArray.php @@ -99,6 +99,11 @@ class DataArray return; } + // Edge case fail safe + if(!isset($oldRowToUpdate[Metrics::INDEX_NB_VISITS])) { + return; + } + $oldRowToUpdate[Metrics::INDEX_NB_VISITS] += $newRowToAdd[Metrics::INDEX_NB_VISITS]; $oldRowToUpdate[Metrics::INDEX_NB_ACTIONS] += $newRowToAdd[Metrics::INDEX_NB_ACTIONS]; $oldRowToUpdate[Metrics::INDEX_NB_UNIQ_VISITORS] += $newRowToAdd[Metrics::INDEX_NB_UNIQ_VISITORS]; diff --git a/core/Exception/AuthenticationFailedException.php b/core/Exception/AuthenticationFailedException.php new file mode 100644 index 0000000000..ca3efc25c1 --- /dev/null +++ b/core/Exception/AuthenticationFailedException.php @@ -0,0 +1,13 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Exception; + +class AuthenticationFailedException extends Exception +{ +}
\ No newline at end of file diff --git a/core/Exceptions/HtmlMessageException.php b/core/Exception/Exception.php index 243a0f1726..106034bf5a 100644 --- a/core/Exceptions/HtmlMessageException.php +++ b/core/Exception/Exception.php @@ -6,25 +6,25 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later * */ -namespace Piwik\Exceptions; +namespace Piwik\Exception; -use Exception; +use Exception as PhpException; /** * An exception whose message has HTML content. When these exceptions are caught * the message will not be sanitized before being displayed to the user. - * - * @api */ -class HtmlMessageException extends Exception +abstract class Exception extends PhpException { - /** - * Returns the exception message. - * - * @return string - */ - public function getHtmlMessage() + private $isHtmlMessage = false; + + public function setIsHtmlMessage() + { + $this->isHtmlMessage = true; + } + + public function isHtmlMessage() { - return $this->getMessage(); + return $this->isHtmlMessage; } }
\ No newline at end of file diff --git a/core/Exception/MissingFilePermissionException.php b/core/Exception/MissingFilePermissionException.php new file mode 100644 index 0000000000..268725c70b --- /dev/null +++ b/core/Exception/MissingFilePermissionException.php @@ -0,0 +1,13 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Exception; + +class MissingFilePermissionException extends Exception +{ +}
\ No newline at end of file diff --git a/core/Exception/NoPrivilegesException.php b/core/Exception/NoPrivilegesException.php new file mode 100644 index 0000000000..3ee8c9ce2b --- /dev/null +++ b/core/Exception/NoPrivilegesException.php @@ -0,0 +1,13 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Exception; + +class NoPrivilegesException extends Exception +{ +}
\ No newline at end of file diff --git a/core/Exception/NoWebsiteFoundException.php b/core/Exception/NoWebsiteFoundException.php new file mode 100644 index 0000000000..eb97cad37a --- /dev/null +++ b/core/Exception/NoWebsiteFoundException.php @@ -0,0 +1,13 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Exception; + +class NoWebsiteFoundException extends Exception +{ +}
\ No newline at end of file diff --git a/core/Filechecks.php b/core/Filechecks.php index eab93fd260..0c37680fc4 100644 --- a/core/Filechecks.php +++ b/core/Filechecks.php @@ -8,7 +8,7 @@ */ namespace Piwik; -use Piwik\Exceptions\HtmlMessageException; +use Piwik\Exception\MissingFilePermissionException; class Filechecks { @@ -96,7 +96,7 @@ class Filechecks } } - $directoryMessage = "<p><b>Piwik couldn't write to some directories $optionalUserInfo</b>.</p>"; + $directoryMessage = "<p><b>Piwik couldn't write to some directories $optionalUserInfo</b>.</p>"; $directoryMessage .= "<p>Try to Execute the following commands on your server, to allow Write access on these directories" . ":</p>" . "<blockquote>$directoryList</blockquote>" @@ -104,7 +104,10 @@ class Filechecks . "<p>After applying the modifications, you can <a href='index.php'>refresh the page</a>.</p>" . "<p>If you need more help, try <a href='?module=Proxy&action=redirect&url=http://piwik.org'>Piwik.org</a>.</p>"; - throw new HtmlMessageException($directoryMessage); + $ex = new MissingFilePermissionException($directoryMessage); + $ex->setIsHtmlMessage(); + + throw $ex; } /** diff --git a/core/FrontController.php b/core/FrontController.php index 16d5930fe2..25e56cc4f9 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -12,7 +12,7 @@ namespace Piwik; use Exception; use Piwik\API\Request; use Piwik\API\ResponseBuilder; -use Piwik\Exceptions\HtmlMessageException; +use Piwik\Exception\AuthenticationFailedException; use Piwik\Http\Router; use Piwik\Plugin\Controller; use Piwik\Plugin\Report; @@ -420,10 +420,15 @@ class FrontController extends Singleton try { $authAdapter = Registry::get('auth'); } catch (Exception $e) { - throw new HtmlMessageException("Authentication object cannot be found in the Registry. Maybe the Login plugin is not activated? - <br />You can activate the plugin by adding:<br /> - <code>Plugins[] = Login</code><br /> - under the <code>[Plugins]</code> section in your config/config.ini.php"); + $message = "Authentication object cannot be found in the Registry. Maybe the Login plugin is not activated? + <br />You can activate the plugin by adding:<br /> + <code>Plugins[] = Login</code><br /> + under the <code>[Plugins]</code> section in your config/config.ini.php"; + + $ex = new AuthenticationFailedException($message); + $ex->setIsHtmlMessage(); + + throw $ex; } Access::getInstance()->reloadAccess($authAdapter); @@ -614,10 +619,10 @@ class FrontController extends Singleton { $debugTrace = $ex->getTraceAsString(); - if (method_exists($ex, 'getHtmlMessage')) { - $message = $ex->getHtmlMessage(); - } else { - $message = Common::sanitizeInputValue($ex->getMessage()); + $message = $ex->getMessage(); + + if (!method_exists($ex, 'isHtmlMessage') || !$ex->isHtmlMessage()) { + $message = Common::sanitizeInputValue($message); } $logo = new CustomLogo(); diff --git a/core/Plugin/Controller.php b/core/Plugin/Controller.php index 9985c100d5..4afcbf25ad 100644 --- a/core/Plugin/Controller.php +++ b/core/Plugin/Controller.php @@ -17,7 +17,8 @@ use Piwik\Config as PiwikConfig; use Piwik\Config; use Piwik\DataTable\Filter\CalculateEvolutionFilter; use Piwik\Date; -use Piwik\Exceptions\HtmlMessageException; +use Piwik\Exception\NoPrivilegesException; +use Piwik\Exception\NoWebsiteFoundException; use Piwik\FrontController; use Piwik\Menu\MenuTop; use Piwik\Menu\MenuUser; @@ -841,16 +842,22 @@ abstract class Controller $message = "Error: no website was found in this Piwik installation. <br />Check the table '$siteTableName' in your database, it should contain your Piwik websites."; - throw new HtmlMessageException($message); + $ex = new NoWebsiteFoundException($message); + $ex->setIsHtmlMessage(); + + throw $ex; } if (!Piwik::isUserIsAnonymous()) { $currentLogin = Piwik::getCurrentUserLogin(); $emails = implode(',', Piwik::getAllSuperUserAccessEmailAddresses()); - $errorMessage = sprintf(Piwik::translate('CoreHome_NoPrivilegesAskPiwikAdmin'), $currentLogin, "<br/><a href='mailto:" . $emails . "?subject=Access to Piwik for user $currentLogin'>", "</a>"); + $errorMessage = sprintf(Piwik::translate('CoreHome_NoPrivilegesAskPiwikAdmin'), $currentLogin, "<br/><a href='mailto:" . $emails . "?subject=Access to Piwik for user $currentLogin'>", "</a>"); $errorMessage .= "<br /><br /> <b><a href='index.php?module=" . Registry::get('auth')->getName() . "&action=logout'>› " . Piwik::translate('General_Logout') . "</a></b><br />"; - throw new HtmlMessageException($errorMessage); + $ex = new NoPrivilegesException($errorMessage); + $ex->setIsHtmlMessage(); + + throw $ex; } echo FrontController::getInstance()->dispatch(Piwik::getLoginPluginName(), false); diff --git a/core/Plugin/MetadataLoader.php b/core/Plugin/MetadataLoader.php index 34bb90dcdc..e75bc58338 100644 --- a/core/Plugin/MetadataLoader.php +++ b/core/Plugin/MetadataLoader.php @@ -95,7 +95,7 @@ class MetadataLoader return array(); } - $info = Common::json_decode($json, $assoc = true); + $info = json_decode($json, $assoc = true); if (!is_array($info) || empty($info) ) { diff --git a/core/Session.php b/core/Session.php index d8fa47b4d2..f67b2e4caf 100644 --- a/core/Session.php +++ b/core/Session.php @@ -9,7 +9,7 @@ namespace Piwik; use Exception; -use Piwik\Exceptions\HtmlMessageException; +use Piwik\Exception\MissingFilePermissionException; use Piwik\Session\SaveHandler\DbTable; use Zend_Session; @@ -132,7 +132,10 @@ class Session extends Zend_Session $e->getMessage() ); - throw new HtmlMessageException($message, $e->getCode(), $e); + $ex = new MissingFilePermissionException($message, $e->getCode(), $e); + $ex->setIsHtmlMessage(); + + throw $ex; } } diff --git a/core/Tracker.php b/core/Tracker.php index ed911e55f6..a84afd9632 100644 --- a/core/Tracker.php +++ b/core/Tracker.php @@ -436,7 +436,7 @@ class Tracker $result['message'] = $this->getMessageFromException($e); } Common::sendHeader('Content-Type: application/json'); - echo Common::json_encode($result); + echo json_encode($result); die(1); exit; } @@ -454,7 +454,7 @@ class Tracker Common::sendHeader('Content-Type: text/html; charset=utf-8'); echo $this->getMessageFromException($e); } else { - $this->outputTransparentGif(); + $this->sendResponse(); } die(1); exit; @@ -496,12 +496,12 @@ class Tracker $this->outputAccessControlHeaders(); Common::sendHeader('Content-Type: application/json'); - echo Common::json_encode($result); + echo json_encode($result); exit; } switch ($this->getState()) { case self::STATE_LOGGING_DISABLE: - $this->outputTransparentGif (); + $this->sendResponse(); Common::printDebug("Logging disabled, display transparent logo"); break; @@ -513,7 +513,7 @@ class Tracker case self::STATE_NOSCRIPT_REQUEST: case self::STATE_NOTHING_TO_NOTICE: default: - $this->outputTransparentGif (); + $this->sendResponse(); Common::printDebug("Nothing to notice => default behaviour"); break; } @@ -648,7 +648,7 @@ class Tracker return $visit; } - protected function outputTransparentGif () + private function sendResponse() { if (isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG'] @@ -660,11 +660,24 @@ class Tracker // If there was an error during tracker, return so errors can be flushed return; } - $transGifBase64 = "R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="; - Common::sendHeader('Content-Type: image/gif'); $this->outputAccessControlHeaders(); + $request = $_GET + $_POST; + + if (array_key_exists('send_image', $request) && $request['send_image'] === '0') { + Common::sendHeader("HTTP/1.1 204 No Response"); + return; + } + + $this->outputTransparentGif(); + } + + protected function outputTransparentGif () + { + $transGifBase64 = "R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="; + Common::sendHeader('Content-Type: image/gif'); + print(base64_decode($transGifBase64)); } diff --git a/core/Translate.php b/core/Translate.php index 65381c0a2d..c29d0f0339 100644 --- a/core/Translate.php +++ b/core/Translate.php @@ -173,7 +173,7 @@ class Translate $clientSideTranslations[$key] = $translations[$plugin][$stringName]; } - $js = 'var translations = ' . Common::json_encode($clientSideTranslations) . ';'; + $js = 'var translations = ' . json_encode($clientSideTranslations) . ';'; $js .= "\n" . 'if (typeof(piwik_translations) == \'undefined\') { var piwik_translations = new Object; }' . 'for(var i in translations) { piwik_translations[i] = translations[i];} '; return $js; diff --git a/core/Twig.php b/core/Twig.php index 2e0ef95844..b15efe088f 100755 --- a/core/Twig.php +++ b/core/Twig.php @@ -10,7 +10,6 @@ namespace Piwik; use Exception; use Piwik\DataTable\Filter\SafeDecodeLabel; -use Piwik\Period\Range; use Piwik\Translate; use Piwik\View\RenderTokenParser; use Piwik\Visualization\Sparkline; @@ -245,7 +244,7 @@ class Twig protected function addFilter_prettyDate() { $prettyDate = new Twig_SimpleFilter('prettyDate', function ($dateString, $period) { - return Range::factory($period, $dateString)->getLocalizedShortString(); + return Period\Factory::build($period, $dateString)->getLocalizedShortString(); }); $this->twig->addFilter($prettyDate); } diff --git a/core/Updates/1.8.3-b1.php b/core/Updates/1.8.3-b1.php index 7a00ec20b3..ee8e6c4d00 100644 --- a/core/Updates/1.8.3-b1.php +++ b/core/Updates/1.8.3-b1.php @@ -98,8 +98,8 @@ class Updates_1_8_3_b1 extends Updates is_null($period) ? ScheduledReports::DEFAULT_PERIOD : $period, ScheduledReports::EMAIL_TYPE, is_null($format) ? ScheduledReports::DEFAULT_REPORT_FORMAT : $format, - Common::json_encode(preg_split('/,/', $reports)), - Common::json_encode($parameters), + json_encode(preg_split('/,/', $reports)), + json_encode($parameters), $ts_created, $ts_last_sent, $deleted diff --git a/core/Version.php b/core/Version.php index b4545cacac..fa7f0f29b7 100644 --- a/core/Version.php +++ b/core/Version.php @@ -20,5 +20,5 @@ final class Version * The current Piwik version. * @var string */ - const VERSION = '2.9.0-b9'; + const VERSION = '2.9.0'; } |