Sanitize a single input value and removes line breaks, tabs and null characters.
public static sanitizeInputValue ( string $value ) : string | ||
$value | string | |
return | string | sanitized input |
/** * Computes the output for the given data table * * @param DataTable $table * @return string * @throws Exception */ protected function renderTable($table) { if (!$table instanceof DataTable\Map || $table->getKeyName() != 'date') { throw new Exception("RSS feeds can be generated for one specific website &idSite=X." . "\nPlease specify only one idSite or consider using &format=XML instead."); } $idSite = Common::getRequestVar('idSite', 1, 'int'); $period = Common::getRequestVar('period'); $piwikUrl = SettingsPiwik::getPiwikUrl() . "?module=CoreHome&action=index&idSite=" . $idSite . "&period=" . $period; $out = ""; $moreRecentFirst = array_reverse($table->getDataTables(), true); foreach ($moreRecentFirst as $date => $subtable) { /** @var DataTable $subtable */ $timestamp = $subtable->getMetadata(Archive\DataTableFactory::TABLE_METADATA_PERIOD_INDEX)->getDateStart()->getTimestamp(); $site = $subtable->getMetadata(Archive\DataTableFactory::TABLE_METADATA_SITE_INDEX); $pudDate = date('r', $timestamp); $dateInSiteTimezone = Date::factory($timestamp); if ($site) { $dateInSiteTimezone = $dateInSiteTimezone->setTimezone($site->getTimezone()); } $dateInSiteTimezone = $dateInSiteTimezone->toString('Y-m-d'); $thisPiwikUrl = Common::sanitizeInputValue($piwikUrl . "&date={$dateInSiteTimezone}"); $siteName = $site ? $site->getName() : ''; $title = $siteName . " on " . $date; $out .= "\t<item>\n\t\t<pubDate>{$pudDate}</pubDate>\n\t\t<guid>{$thisPiwikUrl}</guid>\n\t\t<link>{$thisPiwikUrl}</link>\n\t\t<title>{$title}</title>\n\t\t<author>http://piwik.org</author>\n\t\t<description>"; $out .= Common::sanitizeInputValue($this->renderDataTable($subtable)); $out .= "</description>\n\t</item>\n"; } $header = $this->getRssHeader(); $footer = $this->getRssFooter(); return $header . $out . $footer; }
private static function getErrorResponse(Exception $ex) { $debugTrace = $ex->getTraceAsString(); $message = $ex->getMessage(); if (!method_exists($ex, 'isHtmlMessage') || !$ex->isHtmlMessage()) { $message = Common::sanitizeInputValue($message); } $logo = new CustomLogo(); $logoHeaderUrl = false; $logoFaviconUrl = false; try { $logoHeaderUrl = $logo->getHeaderLogoUrl(); $logoFaviconUrl = $logo->getPathUserFavicon(); } catch (Exception $ex) { Log::debug($ex); } $result = Piwik_GetErrorMessagePage($message, $debugTrace, true, true, $logoHeaderUrl, $logoFaviconUrl); /** * Triggered before a Piwik error page is displayed to the user. * * This event can be used to modify the content of the error page that is displayed when * an exception is caught. * * @param string &$result The HTML of the error page. * @param Exception $ex The Exception displayed in the error page. */ Piwik::postEvent('FrontController.modifyErrorPage', array(&$result, $ex)); return $result; }
/** * Constructor. */ public function __construct($idSite = false) { parent::__construct(); $this->jsClass = "SegmentSelectorControl"; $this->cssIdentifier = "segmentEditorPanel"; $this->cssClass = "piwikTopControl"; $this->idSite = $idSite ?: Common::getRequestVar('idSite', false, 'int'); $this->selectedSegment = Common::getRequestVar('segment', false, 'string'); $segments = APIMetadata::getInstance()->getSegmentsMetadata($this->idSite); $segmentsByCategory = $customVariablesSegments = array(); foreach ($segments as $segment) { if ($segment['category'] == Piwik::translate('General_Visit') && ($segment['type'] == 'metric' && $segment['segment'] != 'visitIp')) { $metricsLabel = Piwik::translate('General_Metrics'); $metricsLabel[0] = strtolower($metricsLabel[0]); $segment['category'] .= ' (' . $metricsLabel . ')'; } $segmentsByCategory[$segment['category']][] = $segment; } uksort($segmentsByCategory, array($this, 'sortSegmentCategories')); $this->createRealTimeSegmentsIsEnabled = Config::getInstance()->General['enable_create_realtime_segments']; $this->segmentsByCategory = $segmentsByCategory; $this->nameOfCurrentSegment = ''; $this->isSegmentNotAppliedBecauseBrowserArchivingIsDisabled = 0; $this->availableSegments = API::getInstance()->getAll($this->idSite); foreach ($this->availableSegments as &$savedSegment) { $savedSegment['name'] = Common::sanitizeInputValue($savedSegment['name']); if (!empty($this->selectedSegment) && $this->selectedSegment == $savedSegment['definition']) { $this->nameOfCurrentSegment = $savedSegment['name']; $this->isSegmentNotAppliedBecauseBrowserArchivingIsDisabled = $this->wouldApplySegment($savedSegment) ? 0 : 1; } } $this->authorizedToCreateSegments = SegmentEditorAPI::getInstance()->isUserCanAddNewSegment($this->idSite); $this->isUserAnonymous = Piwik::isUserIsAnonymous(); $this->segmentTranslations = $this->getTranslations(); }
public function getSelector() { $view = new View('@SegmentEditor/getSelector'); $idSite = Common::getRequestVar('idSite'); $this->setGeneralVariablesView($view); $segments = APIMetadata::getInstance()->getSegmentsMetadata($idSite); $segmentsByCategory = $customVariablesSegments = array(); foreach ($segments as $segment) { if ($segment['category'] == Piwik::translate('General_Visit') && ($segment['type'] == 'metric' && $segment['segment'] != 'visitIp')) { $metricsLabel = Piwik::translate('General_Metrics'); $metricsLabel[0] = strtolower($metricsLabel[0]); $segment['category'] .= ' (' . $metricsLabel . ')'; } $segmentsByCategory[$segment['category']][] = $segment; } uksort($segmentsByCategory, array($this, 'sortSegmentCategories')); $view->segmentsByCategory = $segmentsByCategory; $savedSegments = API::getInstance()->getAll($idSite); foreach ($savedSegments as &$savedSegment) { $savedSegment['name'] = Common::sanitizeInputValue($savedSegment['name']); } $view->savedSegmentsJson = Common::json_encode($savedSegments); $view->authorizedToCreateSegments = !Piwik::isUserIsAnonymous(); $view->segmentTranslations = Common::json_encode($this->getTranslations()); $out = $view->render(); return $out; }
/** * Returns, for a given parameter, the value of this parameter in the REQUEST array. * If not set, returns the default value for this parameter @see getDefault() * * @param string $nameVar * @return string|mixed Value of this parameter */ protected function getDefaultOrCurrent($nameVar) { if (isset($_GET[$nameVar])) { return Common::sanitizeInputValue($_GET[$nameVar]); } return $this->getDefault($nameVar); }
private function addGoalsWidgets(WidgetsList $widgetsList, $idSite) { $widgetsList->add('Goals_Goals', 'Goals_GoalsOverview', 'Goals', 'widgetGoalsOverview'); $goals = API::getInstance()->getGoals($idSite); if (count($goals) > 0) { foreach ($goals as $goal) { $widgetsList->add('Goals_Goals', Common::sanitizeInputValue($goal['name']), 'Goals', 'widgetGoalReport', array('idGoal' => $goal['idgoal'])); } } }
public function __construct() { parent::__construct(); $this->idSite = Common::getRequestVar('idSite', null, 'int'); $this->goals = API::getInstance()->getGoals($this->idSite); foreach ($this->goals as &$goal) { $goal['name'] = Common::sanitizeInputValue($goal['name']); if (isset($goal['pattern'])) { $goal['pattern'] = Common::sanitizeInputValue($goal['pattern']); } } }
protected function addReportMetadataForEachGoal(&$availableReports, $infos, $goalNameFormatter) { $idSite = $this->getIdSiteFromInfos($infos); $goals = $this->getGoalsForIdSite($idSite); foreach ($goals as $goal) { $goal['name'] = Common::sanitizeInputValue($goal['name']); $this->name = $goalNameFormatter($goal); $this->parameters = array('idGoal' => $goal['idgoal']); $this->order = $this->orderGoal + $goal['idgoal'] * 3; $availableReports[] = $this->buildReportMetadata(); } $this->init(); }
protected function init() { $this->addWidget('Goals_GoalsOverview', 'widgetGoalsOverview'); $idSite = $this->getIdSite(); $goals = API::getInstance()->getGoals($idSite); if (count($goals) > 0) { foreach ($goals as $goal) { $name = Common::sanitizeInputValue($goal['name']); $params = array('idGoal' => $goal['idgoal']); $this->addWidget($name, 'widgetGoalReport', $params); } } }
protected function getGoalName() { if ($this->idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) { return Piwik::translate('Goals_EcommerceOrder'); } if (isset($this->idSite)) { $allGoals = GoalsAPI::getInstance()->getGoals($this->idSite); $goalName = @$allGoals[$this->idGoal]['name']; return Common::sanitizeInputValue($goalName); } else { return ""; } }
protected function init() { $this->addWidget('Goals_GoalsOverview', 'widgetGoalsOverview'); $idSite = $this->getIdSite(); $goals = API::getInstance()->getGoals($idSite); if (count($goals) > 0) { foreach ($goals as $goal) { $name = Common::sanitizeInputValue($goal['name']); $params = array('idGoal' => $goal['idgoal']); $this->addWidget($name, 'widgetGoalReport', $params); } } $site = new Site($idSite); if ($site->isEcommerceEnabled()) { $this->addWidgetWithCustomCategory('Goals_Ecommerce', 'Goals_EcommerceOverview', 'widgetGoalReport', array('idGoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER)); $this->addWidgetWithCustomCategory('Goals_Ecommerce', 'Goals_EcommerceLog', 'getEcommerceLog'); } }
private static function getErrorResponse(Exception $ex) { $debugTrace = $ex->getTraceAsString(); $message = $ex->getMessage(); $isHtmlMessage = method_exists($ex, 'isHtmlMessage') && $ex->isHtmlMessage(); if (!$isHtmlMessage && Request::isApiRequest($_GET)) { $outputFormat = strtolower(Common::getRequestVar('format', 'xml', 'string', $_GET + $_POST)); $response = new ResponseBuilder($outputFormat); return $response->getResponseException($ex); } elseif (!$isHtmlMessage) { $message = Common::sanitizeInputValue($message); } $logo = new CustomLogo(); $logoHeaderUrl = false; $logoFaviconUrl = false; try { $logoHeaderUrl = $logo->getHeaderLogoUrl(); $logoFaviconUrl = $logo->getPathUserFavicon(); } catch (Exception $ex) { try { Log::debug($ex); } catch (\Exception $otherEx) { // DI container may not be setup at this point } } $result = Piwik_GetErrorMessagePage($message, $debugTrace, true, true, $logoHeaderUrl, $logoFaviconUrl); try { /** * Triggered before a Piwik error page is displayed to the user. * * This event can be used to modify the content of the error page that is displayed when * an exception is caught. * * @param string &$result The HTML of the error page. * @param Exception $ex The Exception displayed in the error page. */ Piwik::postEvent('FrontController.modifyErrorPage', array(&$result, $ex)); } catch (ContainerDoesNotExistException $ex) { // this can happen when an error occurs before the Piwik environment is created } return $result; }
/** * Constructor. */ public function __construct($idSite = false) { parent::__construct(); $this->jsClass = "SegmentSelectorControl"; $this->cssIdentifier = "segmentEditorPanel"; $this->cssClass = "piwikTopControl borderedControl piwikSelector"; $this->idSite = $idSite ?: Common::getRequestVar('idSite', false, 'int'); $this->selectedSegment = Common::getRequestVar('segment', false, 'string'); $formatter = StaticContainer::get('Piwik\\Plugins\\SegmentEditor\\SegmentFormatter'); $this->segmentDescription = $formatter->getHumanReadable(Request::getRawSegmentFromRequest(), $this->idSite); $this->isAddingSegmentsForAllWebsitesEnabled = SegmentEditor::isAddingSegmentsForAllWebsitesEnabled(); $segments = APIMetadata::getInstance()->getSegmentsMetadata($this->idSite); $visitTitle = Piwik::translate('General_Visit'); $segmentsByCategory = array(); foreach ($segments as $segment) { if ($segment['category'] == $visitTitle && ($segment['type'] == 'metric' && $segment['segment'] != 'visitIp')) { $metricsLabel = Piwik::translate('General_Metrics'); $metricsLabel[0] = Common::mb_strtolower($metricsLabel[0]); $segment['category'] .= ' (' . $metricsLabel . ')'; } $segmentsByCategory[$segment['category']][] = $segment; } $this->createRealTimeSegmentsIsEnabled = Config::getInstance()->General['enable_create_realtime_segments']; $this->segmentsByCategory = $segmentsByCategory; $this->nameOfCurrentSegment = ''; $this->isSegmentNotAppliedBecauseBrowserArchivingIsDisabled = 0; $this->availableSegments = API::getInstance()->getAll($this->idSite); foreach ($this->availableSegments as &$savedSegment) { $savedSegment['name'] = Common::sanitizeInputValue($savedSegment['name']); if (!empty($this->selectedSegment) && $this->selectedSegment == $savedSegment['definition']) { $this->nameOfCurrentSegment = $savedSegment['name']; $this->isSegmentNotAppliedBecauseBrowserArchivingIsDisabled = $this->wouldApplySegment($savedSegment) ? 0 : 1; } } $this->authorizedToCreateSegments = SegmentEditorAPI::getInstance()->isUserCanAddNewSegment($this->idSite); $this->isUserAnonymous = Piwik::isUserIsAnonymous(); $this->segmentTranslations = $this->getTranslations(); $this->segmentProcessedOnRequest = Rules::isBrowserArchivingAvailableForSegments(); $this->hideSegmentDefinitionChangeMessage = UsersManagerAPI::getInstance()->getUserPreference(Piwik::getCurrentUserLogin(), 'hideSegmentDefinitionChangeMessage'); }
/** * Returns a URL query string as an array. * * @param string $urlQuery The query string, eg, `'?param1=value1¶m2=value2'`. * @return array eg, `array('param1' => 'value1', 'param2' => 'value2')` * @api */ public static function getArrayFromQueryString($urlQuery) { if (strlen($urlQuery) == 0) { return array(); } // TODO: this method should not use a cache. callers should instead have their own cache, configured through DI. // one undesirable side effect of using a cache here, is that this method can now init the StaticContainer, which makes setting // test environment for RequestCommand more complicated. $cache = Cache::getTransientCache(); $cacheKey = 'arrayFromQuery' . $urlQuery; if ($cache->contains($cacheKey)) { return $cache->fetch($cacheKey); } if ($urlQuery[0] == '?') { $urlQuery = substr($urlQuery, 1); } $separator = '&'; $urlQuery = $separator . $urlQuery; // $urlQuery = str_replace(array('%20'), ' ', $urlQuery); $referrerQuery = trim($urlQuery); $values = explode($separator, $referrerQuery); $nameToValue = array(); foreach ($values as $value) { $pos = strpos($value, '='); if ($pos !== false) { $name = substr($value, 0, $pos); $value = substr($value, $pos + 1); if ($value === false) { $value = ''; } } else { $name = $value; $value = false; } if (!empty($name)) { $name = Common::sanitizeInputValue($name); } if (!empty($value)) { $value = Common::sanitizeInputValue($value); } // if array without indexes $count = 0; $tmp = preg_replace('/(\\[|%5b)(]|%5d)$/i', '', $name, -1, $count); if (!empty($tmp) && $count) { $name = $tmp; if (isset($nameToValue[$name]) == false || is_array($nameToValue[$name]) == false) { $nameToValue[$name] = array(); } array_push($nameToValue[$name], $value); } elseif (!empty($name)) { $nameToValue[$name] = $value; } } $cache->save($cacheKey, $nameToValue); return $nameToValue; }
public function test_filterDataTable_MatchesExactlyIntegration() { $date = Date::today()->addHour(10); $t = Fixture::getTracker($this->idSite, $date->getDatetime(), $defaultInit = true); $t->setUrlReferrer('http://www.google.com.vn/url?sa=t&rct=j&q=%3C%3E%26%5C%22the%20pdo%20extension%20is%20required%20for%20this%20adapter%20but%20the%20extension%20is%20not%20loaded&source=web&cd=4&ved=0FjAD&url=http%3A%2F%2Fforum.piwik.org%2Fread.php%3F2%2C1011&ei=y-HHAQ&usg=AFQjCN2-nt5_GgDeg&cad=rja'); $t->setUrl('http://example.org/%C3%A9%C3%A9%C3%A9%22%27...%20%3Cthis%20is%20cool%3E!'); $t->setGenerationTime(523); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.1)->getDatetime()); $t->setUrl('http://example.org/dir/file.php?foo=bar&foo2=bar'); $t->setGenerationTime(123); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.2)->getDatetime()); $t->setUrl('http://example.org/dir/file/xyz.php?foo=bar&foo2=bar'); $t->setGenerationTime(231); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.2)->getDatetime()); $t->setUrl('http://example.org/what-is-piwik'); $t->setGenerationTime(231); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.3)->getDatetime()); $t->setUrl('http://example.org/dir/file.php?foo=bar&foo2=bar'); $t->setGenerationTime(147); $t->doTrackPageView('incredible title! <>,;'); // for some reasons @dataProvider results in an "Mysql::getProfiler() undefined method" error $assertions = array(array('nb_hits', 'what-is-piwik', 1), array('nb_hits', '/what-is-piwik', null), array('nb_hits', 'foo', 3), array('nb_visits', 'foo', 2), array('nb_hits', 'i', 5), array('nb_hits', 'foo2=bar', 3), array('nb_hits', '/', 3), array('nb_hits', 'foo=bar&foo2=bar', 3), array('nb_hits', 'php?foo=bar&foo2=bar', 3), array('nb_hits', 'file.php?foo=bar&foo2=bar', 2), array('nb_hits', 'dir/file.php?foo=bar&foo2=bar', 2), array('nb_hits', 'dir', 3), array('avg_time_generation', 'dir/file.php?foo=bar&foo2=bar', 0.135), array('bounce_rate', 'php?foo=bar', 0)); foreach ($assertions as $assert) { $alert = array('report' => 'Actions_getPageUrls', 'metric' => $assert[0], 'period' => 'day', 'report_condition' => 'contains', 'report_matched' => Common::sanitizeInputValue($assert[1])); $value = $this->processor->getValueForAlertInPast($alert, $this->idSite, 0); $this->assertEquals($assert[2], $value, $assert[0] . ':' . $assert[1] . ' should return value ' . $assert[2] . ' but returns ' . $value); } }
/** * This function will sanitize or not if it's needed for the specified action type * * URLs (Download URL, Outlink URL) are stored raw (unsanitized) * while other action types are stored Sanitized * * @param $actionType * @param $actionString * @return string */ private static function normaliseActionString($actionType, $actionString) { $actionString = Common::unsanitizeInputValue($actionString); if (self::isActionTypeStoredUnsanitized($actionType)) { return $actionString; } return Common::sanitizeInputValue($actionString); }
/** * Use variations of the label to make it easier to specify the desired label * * Note: The HTML Encoded version must be tried first, since in ResponseBuilder the $label is unsanitized * via Common::unsanitizeLabelParameter. * * @param string $originalLabel * @return array */ private function getLabelVariations($originalLabel) { static $pageTitleReports = array('getPageTitles', 'getEntryPageTitles', 'getExitPageTitles'); $originalLabel = trim($originalLabel); $isTerminal = substr($originalLabel, 0, 1) == self::TERMINAL_OPERATOR; if ($isTerminal) { $originalLabel = substr($originalLabel, 1); } $variations = array(); $label = trim(urldecode($originalLabel)); $sanitizedLabel = Common::sanitizeInputValue($label); $variations[] = $sanitizedLabel; if ($this->apiModule == 'Actions' && in_array($this->apiMethod, $pageTitleReports)) { if ($isTerminal) { array_unshift($variations, ' ' . $sanitizedLabel); array_unshift($variations, ' ' . $label); } else { // special case: the Actions.getPageTitles report prefixes some labels with a blank. // the blank might be passed by the user but is removed in Request::getRequestArrayFromString. $variations[] = ' ' . $sanitizedLabel; $variations[] = ' ' . $label; } } $variations[] = $label; return $variations; }
public static function makeXssContent($type, $sanitize = false) { $result = "<script>\$('body').html('{$type} XSS!');</script>"; if ($sanitize) { $result = Common::sanitizeInputValue($result); } return $result; }
/** * Clean the parameter URLs: * - if the parameter is a string make it an array * - remove the trailing slashes if found * * @param string|array urls * @return array the array of cleaned URLs */ private function cleanParameterUrls($urls) { if (!is_array($urls)) { $urls = array($urls); } $urls = array_filter($urls); $urls = array_map('urldecode', $urls); foreach ($urls as &$url) { $url = $this->removeTrailingSlash($url); if (strpos($url, 'http') !== 0) { $url = 'http://' . $url; } $url = trim($url); $url = Common::sanitizeInputValue($url); } $urls = array_unique($urls); return $urls; }
private function getGoals($idSite) { // get all goals to display info for $allGoals = array(); // add the ecommerce goal if ecommerce is enabled for the site if (Site::isEcommerceEnabledFor($idSite)) { $ecommerceGoal = array('idgoal' => Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER, 'name' => Piwik::translate('Goals_EcommerceOrder'), 'quoted_name' => false); $allGoals[$ecommerceGoal['idgoal']] = $ecommerceGoal; } // add the site's goals (and escape all goal names) $siteGoals = APIGoals::getInstance()->getGoals($idSite); foreach ($siteGoals as &$goal) { $goal['name'] = Common::sanitizeInputValue($goal['name']); $goal['quoted_name'] = '"' . $goal['name'] . '"'; $allGoals[$goal['idgoal']] = $goal; } return $allGoals; }
/** * Convert segment expression to an action ID or an SQL expression. * * This method is used as a sqlFilter-callback for the segments of this plugin. * Usually, these callbacks only return a value that should be compared to the * column in the database. In this case, that doesn't work since multiple IDs * can match an expression (e.g. "pageUrl=@foo"). * @param string $valueToMatch * @param string $sqlField * @param string $matchType * @param string $segmentName * @throws \Exception * @return array|int|string */ public static function getIdActionFromSegment($valueToMatch, $sqlField, $matchType, $segmentName) { $actionType = self::guessActionTypeFromSegment($segmentName); if ($actionType == Action::TYPE_PAGE_URL) { // for urls trim protocol and www because it is not recorded in the db $valueToMatch = preg_replace('@^http[s]?://(www\\.)?@i', '', $valueToMatch); } $valueToMatch = Common::sanitizeInputValue(Common::unsanitizeInputValue($valueToMatch)); if ($matchType == SegmentExpression::MATCH_EQUAL || $matchType == SegmentExpression::MATCH_NOT_EQUAL) { $idAction = self::getIdActionMatchingNameAndType($valueToMatch, $actionType); // if the action is not found, we hack -100 to ensure it tries to match against an integer // otherwise binding idaction_name to "false" returns some rows for some reasons (in case &segment=pageTitle==Větrnásssssss) if (empty($idAction)) { $idAction = -100; } return $idAction; } // "name contains $string" match can match several idaction so we cannot return yet an idaction // special case $sql = TableLogAction::getSelectQueryWhereNameContains($matchType, $actionType); return array('SQL' => $sql, 'bind' => $valueToMatch); }
private function checkPiwikIsNotInstalled() { if (!SettingsPiwik::isPiwikInstalled()) { return; } \Piwik\Plugins\Login\Controller::clearSession(); $message = Piwik::translate('Installation_InvalidStateError', array('<br /><strong>', '</strong>', '<a href=\'' . Common::sanitizeInputValue(Url::getCurrentUrlWithoutFileName()) . '\'>', '</a>')); Piwik::exitWithErrorMessage($message); }
/** * @param int $idSite * @param string $piwikUrl http://path/to/piwik/site/ * @param bool $mergeSubdomains * @param bool $groupPageTitlesByDomain * @param bool $mergeAliasUrls * @param array $visitorCustomVariables * @param array $pageCustomVariables * @param string $customCampaignNameQueryParam * @param string $customCampaignKeywordParam * @param bool $doNotTrack * @param bool $disableCookies * @return string Javascript code. */ public function generate($idSite, $piwikUrl, $mergeSubdomains = false, $groupPageTitlesByDomain = false, $mergeAliasUrls = false, $visitorCustomVariables = null, $pageCustomVariables = null, $customCampaignNameQueryParam = null, $customCampaignKeywordParam = null, $doNotTrack = false, $disableCookies = false) { // changes made to this code should be mirrored in plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js var generateJsCode $jsCode = file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Morpheus/templates/javascriptCode.tpl"); $jsCode = htmlentities($jsCode); if (substr($piwikUrl, 0, 4) !== 'http') { $piwikUrl = 'http://' . $piwikUrl; } preg_match('~^(http|https)://(.*)$~D', $piwikUrl, $matches); $piwikUrl = rtrim(@$matches[2], "/"); // Build optional parameters to be added to text $options = ''; $optionsBeforeTrackerUrl = ''; if ($groupPageTitlesByDomain) { $options .= ' _paq.push(["setDocumentTitle", document.domain + "/" + document.title]);' . "\n"; } if ($mergeSubdomains || $mergeAliasUrls) { $options .= $this->getJavascriptTagOptions($idSite, $mergeSubdomains, $mergeAliasUrls); } $maxCustomVars = CustomVariables::getNumUsableCustomVariables(); if ($visitorCustomVariables && count($visitorCustomVariables) > 0) { $options .= ' // you can set up to ' . $maxCustomVars . ' custom variables for each visitor' . "\n"; $index = 1; foreach ($visitorCustomVariables as $visitorCustomVariable) { if (empty($visitorCustomVariable)) { continue; } $options .= sprintf(' _paq.push(["setCustomVariable", %d, %s, %s, "visit"]);%s', $index++, json_encode($visitorCustomVariable[0]), json_encode($visitorCustomVariable[1]), "\n"); } } if ($pageCustomVariables && count($pageCustomVariables) > 0) { $options .= ' // you can set up to ' . $maxCustomVars . ' custom variables for each action (page view, download, click, site search)' . "\n"; $index = 1; foreach ($pageCustomVariables as $pageCustomVariable) { if (empty($pageCustomVariable)) { continue; } $options .= sprintf(' _paq.push(["setCustomVariable", %d, %s, %s, "page"]);%s', $index++, json_encode($pageCustomVariable[0]), json_encode($pageCustomVariable[1]), "\n"); } } if ($customCampaignNameQueryParam) { $options .= ' _paq.push(["setCampaignNameKey", ' . json_encode($customCampaignNameQueryParam) . ']);' . "\n"; } if ($customCampaignKeywordParam) { $options .= ' _paq.push(["setCampaignKeywordKey", ' . json_encode($customCampaignKeywordParam) . ']);' . "\n"; } if ($doNotTrack) { $options .= ' _paq.push(["setDoNotTrack", true]);' . "\n"; } if ($disableCookies) { $options .= ' _paq.push(["disableCookies"]);' . "\n"; } $codeImpl = array('idSite' => $idSite, 'piwikUrl' => Common::sanitizeInputValue($piwikUrl), 'options' => $options, 'optionsBeforeTrackerUrl' => $optionsBeforeTrackerUrl, 'protocol' => '//'); $parameters = compact('mergeSubdomains', 'groupPageTitlesByDomain', 'mergeAliasUrls', 'visitorCustomVariables', 'pageCustomVariables', 'customCampaignNameQueryParam', 'customCampaignKeywordParam', 'doNotTrack'); /** * Triggered when generating JavaScript tracking code server side. Plugins can use * this event to customise the JavaScript tracking code that is displayed to the * user. * * @param array &$codeImpl An array containing snippets of code that the event handler * can modify. Will contain the following elements: * * - **idSite**: The ID of the site being tracked. * - **piwikUrl**: The tracker URL to use. * - **options**: A string of JavaScript code that customises * the JavaScript tracker. * - **optionsBeforeTrackerUrl**: A string of Javascript code that customises * the JavaScript tracker inside of anonymous function before * adding setTrackerUrl into paq. * - **protocol**: Piwik url protocol. * * The **httpsPiwikUrl** element can be set if the HTTPS * domain is different from the normal domain. * @param array $parameters The parameters supplied to `TrackerCodeGenerator::generate()`. */ Piwik::postEvent('Piwik.getJavascriptCode', array(&$codeImpl, $parameters)); $setTrackerUrl = 'var u="' . $codeImpl['protocol'] . '{$piwikUrl}/";'; if (!empty($codeImpl['httpsPiwikUrl'])) { $setTrackerUrl = 'var u=((document.location.protocol === "https:") ? "https://{$httpsPiwikUrl}/" : "http://{$piwikUrl}/");'; $codeImpl['httpsPiwikUrl'] = rtrim($codeImpl['httpsPiwikUrl'], "/"); } $codeImpl = array('setTrackerUrl' => htmlentities($setTrackerUrl)) + $codeImpl; foreach ($codeImpl as $keyToReplace => $replaceWith) { $jsCode = str_replace('{$' . $keyToReplace . '}', $replaceWith, $jsCode); } return $jsCode; }
/** * @param $level * @param $tag * @param $datetime * @param $message * @return string */ private function getMessageFormattedScreen($level, $tag, $datetime, $message) { static $currentRequestKey; if (empty($currentRequestKey)) { $currentRequestKey = substr(Common::generateUniqId(), 0, 5); } if (is_string($message)) { if (!defined('PIWIK_TEST_MODE')) { $message = '[' . $currentRequestKey . '] ' . $message; } $message = $this->formatMessage($level, $tag, $datetime, $message); if (!Common::isPhpCliMode()) { $message = Common::sanitizeInputValue($message); $message = '<pre>' . $message . '</pre>'; } } else { $logger = $this; /** * Triggered when trying to log an object to the screen. Plugins can use * this event to convert objects to strings before they are logged. * * The result of this callback can be HTML so no sanitization is done on the result. * This means **YOU MUST SANITIZE THE MESSAGE YOURSELF** if you use this event. * * **Example** * * public function formatScreenMessage(&$message, $level, $tag, $datetime, $logger) { * if ($message instanceof MyCustomDebugInfo) { * $message = Common::sanitizeInputValue($message->formatForScreen()); * } * } * * @param mixed &$message The object that is being logged. Event handlers should * check if the object is of a certain type and if it is, * set `$message` to the string that should be logged. * @param int $level The log level used with this log entry. * @param string $tag The current plugin that started logging (or if no plugin, * the current class). * @param string $datetime Datetime of the logging call. * @param Log $logger The Log singleton. */ Piwik::postEvent(self::FORMAT_SCREEN_MESSAGE_EVENT, array(&$message, $level, $tag, $datetime, $logger)); } return $message . "\n"; }
/** * Renders the current view. Also sends the stored 'Content-Type' HTML header. * See {@link setContentType()}. * * @return string Generated template. */ public function render() { try { $this->currentModule = Piwik::getModule(); $this->currentAction = Piwik::getAction(); $this->url = Common::sanitizeInputValue(Url::getCurrentUrl()); $this->token_auth = Piwik::getCurrentUserTokenAuth(); $this->userHasSomeAdminAccess = Piwik::isUserHasSomeAdminAccess(); $this->userIsAnonymous = Piwik::isUserIsAnonymous(); $this->userIsSuperUser = Piwik::hasUserSuperUserAccess(); $this->latest_version_available = UpdateCheck::isNewestVersionAvailable(); $this->disableLink = Common::getRequestVar('disableLink', 0, 'int'); $this->isWidget = Common::getRequestVar('widget', 0, 'int'); $piwikAds = StaticContainer::get('Piwik\\ProfessionalServices\\Advertising'); $this->areAdsForProfessionalServicesEnabled = $piwikAds->areAdsForProfessionalServicesEnabled(); if (Development::isEnabled()) { $cacheBuster = rand(0, 10000); } else { $cacheBuster = UIAssetCacheBuster::getInstance()->piwikVersionBasedCacheBuster(); } $this->cacheBuster = $cacheBuster; $this->loginModule = Piwik::getLoginPluginName(); $user = APIUsersManager::getInstance()->getUser($this->userLogin); $this->userAlias = $user['alias']; } catch (Exception $e) { Log::debug($e); // can fail, for example at installation (no plugin loaded yet) } ProxyHttp::overrideCacheControlHeaders('no-store'); Common::sendHeader('Content-Type: ' . $this->contentType); // always sending this header, sometimes empty, to ensure that Dashboard embed loads // - when calling sendHeader() multiple times, the last one prevails Common::sendHeader('X-Frame-Options: ' . (string) $this->xFrameOptions); return $this->renderTwigTemplate(); }
/** * Use variations of the label to make it easier to specify the desired label * * Note: The HTML Encoded version must be tried first, since in ResponseBuilder the $label is unsanitized * via Common::unsanitizeLabelParameter. * * @param string $label * @return array */ private function getLabelVariations($label) { static $pageTitleReports = array('getPageTitles', 'getEntryPageTitles', 'getExitPageTitles'); $variations = array(); $label = urldecode($label); $label = trim($label); $sanitizedLabel = Common::sanitizeInputValue($label); $variations[] = $sanitizedLabel; if ($this->apiModule == 'Actions' && in_array($this->apiMethod, $pageTitleReports)) { // special case: the Actions.getPageTitles report prefixes some labels with a blank. // the blank might be passed by the user but is removed in Request::getRequestArrayFromString. $variations[] = ' ' . $sanitizedLabel; $variations[] = ' ' . $label; } $variations[] = $label; return $variations; }
/** * Checks if the current host is valid and sets variables on the given view, including: * * - **isValidHost** - true if host is valid, false if otherwise * - **invalidHostMessage** - message to display if host is invalid (only set if host is invalid) * - **invalidHost** - the invalid hostname (only set if host is invalid) * - **mailLinkStart** - the open tag of a link to email the Super User of this problem (only set * if host is invalid) * * @param View $view * @api */ public static function setHostValidationVariablesView($view) { // check if host is valid $view->isValidHost = Url::isValidHost(); if (!$view->isValidHost) { // invalid host, so display warning to user $validHosts = Url::getTrustedHostsFromConfig(); $validHost = $validHosts[0]; $invalidHost = Common::sanitizeInputValue($_SERVER['HTTP_HOST']); $emailSubject = rawurlencode(Piwik::translate('CoreHome_InjectedHostEmailSubject', $invalidHost)); $emailBody = rawurlencode(Piwik::translate('CoreHome_InjectedHostEmailBody')); $superUserEmail = implode(',', Piwik::getAllSuperUserAccessEmailAddresses()); $mailToUrl = "mailto:{$superUserEmail}?subject={$emailSubject}&body={$emailBody}"; $mailLinkStart = "<a href=\"{$mailToUrl}\">"; $invalidUrl = Url::getCurrentUrlWithoutQueryString($checkIfTrusted = false); $validUrl = Url::getCurrentScheme() . '://' . $validHost . Url::getCurrentScriptName(); $invalidUrl = Common::sanitizeInputValue($invalidUrl); $validUrl = Common::sanitizeInputValue($validUrl); $changeTrustedHostsUrl = "index.php" . Url::getCurrentQueryStringWithParametersModified(array('module' => 'CoreAdminHome', 'action' => 'generalSettings')) . "#trustedHostsSection"; $warningStart = Piwik::translate('CoreHome_InjectedHostWarningIntro', array('<strong>' . $invalidUrl . '</strong>', '<strong>' . $validUrl . '</strong>')) . ' <br/>'; if (Piwik::hasUserSuperUserAccess()) { $view->invalidHostMessage = $warningStart . ' ' . Piwik::translate('CoreHome_InjectedHostSuperUserWarning', array("<a href=\"{$changeTrustedHostsUrl}\">", $invalidHost, '</a>', "<br/><a href=\"{$validUrl}\">", $validHost, '</a>')); } else { if (Piwik::isUserIsAnonymous()) { $view->invalidHostMessage = $warningStart . ' ' . Piwik::translate('CoreHome_InjectedHostNonSuperUserWarning', array("<br/><a href=\"{$validUrl}\">", '</a>', '<span style="display:none">', '</span>')); } else { $view->invalidHostMessage = $warningStart . ' ' . Piwik::translate('CoreHome_InjectedHostNonSuperUserWarning', array("<br/><a href=\"{$validUrl}\">", '</a>', $mailLinkStart, '</a>')); } } $view->invalidHostMessageHowToFix = '<p><b>How do I fix this problem and how do I login again?</b><br/> The Piwik Super User can manually edit the file piwik/config/config.ini.php and add the following lines: <pre>[General]' . "\n" . 'trusted_hosts[] = "' . $invalidHost . '"</pre>After making the change, you will be able to login again.</p> <p>You may also <i>disable this security feature (not recommended)</i>. To do so edit config/config.ini.php and add: <pre>[General]' . "\n" . 'enable_trusted_host_check=0</pre>'; $view->invalidHost = $invalidHost; // for UserSettings warning $view->invalidHostMailLinkStart = $mailLinkStart; } }
public function __construct($pluginName, $message) { $pluginName = Common::sanitizeInputValue($pluginName); $message = Common::sanitizeInputValue($message); parent::__construct("There was a problem installing the plugin {$pluginName}: <br /><br />\n {$message}\n <br /><br />\n If you want to hide this message you must remove the following line under the [Plugins] entry in your\n 'config/config.ini.php' file to disable this plugin.<br />\n Plugins[] = {$pluginName}\n <br /><br />If this plugin has already been installed, you must add the following line under the\n [PluginsInstalled] entry in your 'config/config.ini.php' file:<br />\n PluginsInstalled[] = {$pluginName}"); }
/** * Returns the URL to this Piwik instance, eg. **http://demo.piwik.org/** or **http://example.org/piwik/**. * * @return string * @api */ public static function getPiwikUrl() { $url = Option::get(self::OPTION_PIWIK_URL); $isPiwikCoreDispatching = defined('PIWIK_ENABLE_DISPATCH') && PIWIK_ENABLE_DISPATCH; if (Common::isPhpCliMode() || SettingsServer::isArchivePhpTriggered() || !$isPiwikCoreDispatching) { return $url; } $currentUrl = Common::sanitizeInputValue(Url::getCurrentUrlWithoutFileName()); // when script is called from /misc/cron/archive.php, Piwik URL is /index.php $currentUrl = str_replace("/misc/cron", "", $currentUrl); if (empty($url) || $currentUrl != $url) { if (strlen($currentUrl) >= strlen('http://a/')) { self::overwritePiwikUrl($currentUrl); } $url = $currentUrl; } if (ProxyHttp::isHttps()) { $url = str_replace("http://", "https://", $url); } return $url; }
/** * Returns the current host. * * @param string $default Default value to return if host unknown * @param bool $checkTrustedHost Whether to do trusted host check. Should ALWAYS be true, * except in Controller. * @return string eg, `"example.org"` if the current URL is * `"http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2"` * @api */ public static function getCurrentHost($default = 'unknown', $checkTrustedHost = true) { $hostHeaders = array(); $config = Config::getInstance()->General; if (isset($config['proxy_host_headers'])) { $hostHeaders = $config['proxy_host_headers']; } if (!is_array($hostHeaders)) { $hostHeaders = array(); } $host = self::getHost($checkTrustedHost); $default = Common::sanitizeInputValue($host ? $host : $default); return IP::getNonProxyIpFromHeader($default, $hostHeaders); }