File names beginning with anything but a-Z or 0-9 will be rejected (including .htaccess for example).
File names containing anything other than above mentioned will also be rejected (file names with spaces won't be accepted).
public static isValidFilename ( string $filename ) : boolean | ||
$filename | string | |
return | boolean |
/** * @param InputInterface $input * @param OutputInterface $output * @return array * @throws \RunTimeException */ protected function getPluginName(InputInterface $input, OutputInterface $output) { $self = $this; $validate = function ($pluginName) use($self) { if (empty($pluginName)) { throw new \RunTimeException('You have to enter a plugin name'); } if (!Filesystem::isValidFilename($pluginName)) { throw new \RunTimeException(sprintf('The plugin name %s is not valid', $pluginName)); } $pluginPath = $self->getPluginPath($pluginName); if (file_exists($pluginPath)) { throw new \RunTimeException('A plugin with this name already exists'); } return $pluginName; }; $pluginName = $input->getOption('name'); if (empty($pluginName)) { $dialog = $this->getHelperSet()->get('dialog'); $pluginName = $dialog->askAndValidate($output, 'Enter a plugin name: ', $validate); } else { $validate($pluginName); } $pluginName = ucfirst($pluginName); return $pluginName; }
protected function cleanupId($id) { if (!Filesystem::isValidFilename($id)) { throw new Exception("Invalid cache ID request {$id}"); } return $id; }
public function __construct($outputId) { if (!Filesystem::isValidFilename($outputId)) { throw new \Exception('The given output id has an invalid format'); } $dir = CliMulti::getTmpPath(); Filesystem::mkdir($dir); $this->tmpFile = $dir . '/' . $outputId . '.output'; }
public function __construct($pid) { if (!Filesystem::isValidFilename($pid)) { throw new \Exception('The given pid has an invalid format'); } $pidDir = CliMulti::getTmpPath(); Filesystem::mkdir($pidDir); $this->isSupported = self::isSupported(); $this->pidFile = $pidDir . '/' . $pid . '.pid'; $this->timeCreation = time(); $this->markAsNotStarted(); }
private static function loadCoreTranslationFile($language) { $path = PIWIK_INCLUDE_PATH . '/lang/' . $language . '.json'; if (!Filesystem::isValidFilename($language) || !is_readable($path)) { throw new Exception(Piwik::translate('General_ExceptionLanguageFileNotFound', array($language))); } $data = file_get_contents($path); $translations = json_decode($data, true); self::mergeTranslationArray($translations); self::setLocale(); self::$loadedLanguage = $language; }
function validateOwner() { $prefix = $this->owner->getValue(); return empty($prefix) || Filesystem::isValidFilename($prefix); }
/** * @param $pluginName * @return Plugin * @throws \Exception */ protected function makePluginClass($pluginName) { $pluginFileName = sprintf("%s/%s.php", $pluginName, $pluginName); $pluginClassName = $pluginName; if (!Filesystem::isValidFilename($pluginName)) { throw new \Exception(sprintf("The plugin filename '%s' is not a valid filename", $pluginFileName)); } $path = self::getPluginsDirectory() . $pluginFileName; if (!file_exists($path)) { // Create the smallest minimal Piwik Plugin // Eg. Used for Morpheus default theme which does not have a Morpheus.php file return new Plugin($pluginName); } require_once $path; $namespacedClass = $this->getClassNamePlugin($pluginName); if (!class_exists($namespacedClass, false)) { throw new \Exception("The class {$pluginClassName} couldn't be found in the file '{$path}'"); } $newPlugin = new $namespacedClass(); if (!$newPlugin instanceof Plugin) { throw new \Exception("The plugin {$pluginClassName} in the file {$path} must inherit from Plugin."); } return $newPlugin; }
public function testIsValidFilenameNotValidValues() { $notvalid = array("../test", "/etc/htpasswd", '$var', ';test', '[bizarre]', '', false, ".htaccess", "very long long eogaioge ageja geau ghaeihieg heiagie aiughaeui hfilename", "WHITE SPACE"); foreach ($notvalid as $toTest) { $this->assertFalse(Filesystem::isValidFilename($toTest), $toTest . " valid but shouldn't!"); } }
/** * If set, Piwik will use the hostname config no matter if it exists or not. Useful for instance if you want to * create a new hostname config: * * $config = Config::getInstance(); * $config->forceUsageOfHostnameConfig('piwik.example.com'); * $config->save(); * * @param string $hostname eg piwik.example.com * * @throws \Exception In case the domain contains not allowed characters */ public function forceUsageOfLocalHostnameConfig($hostname) { $hostConfig = static::getLocalConfigInfoForHostname($hostname); if (!Filesystem::isValidFilename($hostConfig['file'])) { throw new Exception('Hostname is not valid'); } $this->pathLocal = $hostConfig['path']; $this->configLocal = array(); $this->initialized = false; return $this->pathLocal; }
/** * Returns true if specified language is available * * @param string $languageCode * @return bool true if language available; false otherwise */ public function isLanguageAvailable($languageCode) { return $languageCode !== false && Filesystem::isValidFilename($languageCode) && in_array($languageCode, $this->getAvailableLanguages()); }
public function get($idSite, $period, $date, $apiModule, $apiAction, $graphType = false, $outputType = API::GRAPH_OUTPUT_INLINE, $columns = false, $labels = false, $showLegend = true, $width = false, $height = false, $fontSize = API::DEFAULT_FONT_SIZE, $legendFontSize = false, $aliasedGraph = true, $idGoal = false, $colors = false, $textColor = API::DEFAULT_TEXT_COLOR, $backgroundColor = API::DEFAULT_BACKGROUND_COLOR, $gridColor = API::DEFAULT_GRID_COLOR, $idSubtable = false, $legendAppendMetric = true, $segment = false) { Piwik::checkUserHasViewAccess($idSite); // Health check - should we also test for GD2 only? if (!SettingsServer::isGdExtensionEnabled()) { throw new Exception('Error: To create graphs in Piwik, please enable GD php extension (with Freetype support) in php.ini, and restart your web server.'); } $useUnicodeFont = array('am', 'ar', 'el', 'fa', 'fi', 'he', 'ja', 'ka', 'ko', 'te', 'th', 'zh-cn', 'zh-tw'); $languageLoaded = Translate::getLanguageLoaded(); $font = self::getFontPath(self::DEFAULT_FONT); if (in_array($languageLoaded, $useUnicodeFont)) { $unicodeFontPath = self::getFontPath(self::UNICODE_FONT); $font = file_exists($unicodeFontPath) ? $unicodeFontPath : $font; } // save original GET to reset after processing. Important for API-in-API-call $savedGET = $_GET; try { $apiParameters = array(); if (!empty($idGoal)) { $apiParameters = array('idGoal' => $idGoal); } // Fetch the metadata for given api-action $metadata = APIMetadata::getInstance()->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $languageLoaded, $period, $date, $hideMetricsDoc = false, $showSubtableReports = true); if (!$metadata) { throw new Exception('Invalid API Module and/or API Action'); } $metadata = $metadata[0]; $reportHasDimension = !empty($metadata['dimension']); $constantRowsCount = !empty($metadata['constantRowsCount']); $isMultiplePeriod = Period::isMultiplePeriod($date, $period); if (!$reportHasDimension && !$isMultiplePeriod) { throw new Exception('The graph cannot be drawn for this combination of \'date\' and \'period\' parameters.'); } if (empty($legendFontSize)) { $legendFontSize = (int) $fontSize + self::DEFAULT_LEGEND_FONT_SIZE_OFFSET; } if (empty($graphType)) { if ($isMultiplePeriod) { $graphType = StaticGraph::GRAPH_TYPE_BASIC_LINE; } else { if ($constantRowsCount) { $graphType = StaticGraph::GRAPH_TYPE_VERTICAL_BAR; } else { $graphType = StaticGraph::GRAPH_TYPE_HORIZONTAL_BAR; } } $reportUniqueId = $metadata['uniqueId']; if (isset(self::$DEFAULT_GRAPH_TYPE_OVERRIDE[$reportUniqueId][$isMultiplePeriod])) { $graphType = self::$DEFAULT_GRAPH_TYPE_OVERRIDE[$reportUniqueId][$isMultiplePeriod]; } } else { $availableGraphTypes = StaticGraph::getAvailableStaticGraphTypes(); if (!in_array($graphType, $availableGraphTypes)) { throw new Exception(Piwik::translate('General_ExceptionInvalidStaticGraphType', array($graphType, implode(', ', $availableGraphTypes)))); } } $width = (int) $width; $height = (int) $height; if (empty($width)) { $width = self::$DEFAULT_PARAMETERS[$graphType][self::WIDTH_KEY]; } if (empty($height)) { $height = self::$DEFAULT_PARAMETERS[$graphType][self::HEIGHT_KEY]; } // Cap width and height to a safe amount $width = min($width, self::MAX_WIDTH); $height = min($height, self::MAX_HEIGHT); $reportColumns = array_merge(!empty($metadata['metrics']) ? $metadata['metrics'] : array(), !empty($metadata['processedMetrics']) ? $metadata['processedMetrics'] : array(), !empty($metadata['metricsGoal']) ? $metadata['metricsGoal'] : array(), !empty($metadata['processedMetricsGoal']) ? $metadata['processedMetricsGoal'] : array()); $ordinateColumns = array(); if (empty($columns)) { $ordinateColumns[] = empty($reportColumns[self::DEFAULT_ORDINATE_METRIC]) ? key($metadata['metrics']) : self::DEFAULT_ORDINATE_METRIC; } else { $ordinateColumns = explode(',', $columns); foreach ($ordinateColumns as $column) { if (empty($reportColumns[$column])) { throw new Exception(Piwik::translate('ImageGraph_ColumnOrdinateMissing', array($column, implode(',', array_keys($reportColumns))))); } } } $ordinateLabels = array(); foreach ($ordinateColumns as $column) { $ordinateLabels[$column] = $reportColumns[$column]; } // sort and truncate filters $defaultFilterTruncate = self::$DEFAULT_PARAMETERS[$graphType][self::TRUNCATE_KEY]; switch ($graphType) { case StaticGraph::GRAPH_TYPE_3D_PIE: case StaticGraph::GRAPH_TYPE_BASIC_PIE: if (count($ordinateColumns) > 1) { // pChart doesn't support multiple series on pie charts throw new Exception("Pie charts do not currently support multiple series"); } $_GET['filter_sort_column'] = reset($ordinateColumns); $this->setFilterTruncate($defaultFilterTruncate); break; case StaticGraph::GRAPH_TYPE_VERTICAL_BAR: case StaticGraph::GRAPH_TYPE_BASIC_LINE: if (!$isMultiplePeriod && !$constantRowsCount) { $this->setFilterTruncate($defaultFilterTruncate); } break; } $ordinateLogos = array(); // row evolutions if ($isMultiplePeriod && $reportHasDimension) { $plottedMetric = reset($ordinateColumns); // when no labels are specified, getRowEvolution returns the top N=filter_limit row evolutions // rows are sorted using filter_sort_column (see DataTableGenericFilter for more info) if (!$labels) { $savedFilterSortColumnValue = Common::getRequestVar('filter_sort_column', ''); $_GET['filter_sort_column'] = $plottedMetric; $savedFilterLimitValue = Common::getRequestVar('filter_limit', -1, 'int'); if ($savedFilterLimitValue == -1 || $savedFilterLimitValue > self::MAX_NB_ROW_LABELS) { $_GET['filter_limit'] = self::DEFAULT_NB_ROW_EVOLUTIONS; } } $processedReport = APIMetadata::getInstance()->getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $plottedMetric, $languageLoaded, $idGoal, $legendAppendMetric, $labelUseAbsoluteUrl = false); //@review this test will need to be updated after evaluating the @review comment in API/API.php if (!$processedReport) { throw new Exception(Piwik::translate('General_NoDataForGraph')); } // restoring generic filter parameters if (!$labels) { $_GET['filter_sort_column'] = $savedFilterSortColumnValue; if ($savedFilterLimitValue != -1) { $_GET['filter_limit'] = $savedFilterLimitValue; } } // retrieve metric names & labels $metrics = $processedReport['metadata']['metrics']; $ordinateLabels = array(); // getRowEvolution returned more than one label if (!array_key_exists($plottedMetric, $metrics)) { $ordinateColumns = array(); $i = 0; foreach ($metrics as $metric => $info) { $ordinateColumn = $plottedMetric . '_' . $i++; $ordinateColumns[] = $metric; $ordinateLabels[$ordinateColumn] = $info['name']; if (isset($info['logo'])) { $ordinateLogo = $info['logo']; // @review pChart does not support gifs in graph legends, would it be possible to convert all plugin pictures (cookie.gif, flash.gif, ..) to png files? if (!strstr($ordinateLogo, '.gif')) { $absoluteLogoPath = self::getAbsoluteLogoPath($ordinateLogo); if (file_exists($absoluteLogoPath)) { $ordinateLogos[$ordinateColumn] = $absoluteLogoPath; } } } } } else { $ordinateLabels[$plottedMetric] = $processedReport['label'] . ' (' . $metrics[$plottedMetric]['name'] . ')'; } } else { $processedReport = APIMetadata::getInstance()->getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment, $apiParameters = false, $idGoal, $languageLoaded, $showTimer = true, $hideMetricsDoc = false, $idSubtable, $showRawMetrics = false); } // prepare abscissa and ordinate series $abscissaSeries = array(); $abscissaLogos = array(); $ordinateSeries = array(); /** @var \Piwik\DataTable\Simple|\Piwik\DataTable\Map $reportData */ $reportData = $processedReport['reportData']; $hasData = false; $hasNonZeroValue = false; if (!$isMultiplePeriod) { $reportMetadata = $processedReport['reportMetadata']->getRows(); $i = 0; // $reportData instanceof DataTable foreach ($reportData->getRows() as $row) { // $row instanceof Row $rowData = $row->getColumns(); // Associative Array $abscissaSeries[] = Common::unsanitizeInputValue($rowData['label']); foreach ($ordinateColumns as $column) { $parsedOrdinateValue = $this->parseOrdinateValue($rowData[$column]); $hasData = true; if ($parsedOrdinateValue != 0) { $hasNonZeroValue = true; } $ordinateSeries[$column][] = $parsedOrdinateValue; } if (isset($reportMetadata[$i])) { $rowMetadata = $reportMetadata[$i]->getColumns(); if (isset($rowMetadata['logo'])) { $absoluteLogoPath = self::getAbsoluteLogoPath($rowMetadata['logo']); if (file_exists($absoluteLogoPath)) { $abscissaLogos[$i] = $absoluteLogoPath; } } } $i++; } } else { // $periodsData instanceof Simple[] $periodsData = array_values($reportData->getDataTables()); $periodsCount = count($periodsData); for ($i = 0; $i < $periodsCount; $i++) { // $periodsData[$i] instanceof Simple // $rows instanceof Row[] if (empty($periodsData[$i])) { continue; } $rows = $periodsData[$i]->getRows(); if (array_key_exists(0, $rows)) { $rowData = $rows[0]->getColumns(); // associative Array foreach ($ordinateColumns as $column) { $ordinateValue = $rowData[$column]; $parsedOrdinateValue = $this->parseOrdinateValue($ordinateValue); $hasData = true; if (!empty($parsedOrdinateValue)) { $hasNonZeroValue = true; } $ordinateSeries[$column][] = $parsedOrdinateValue; } } else { foreach ($ordinateColumns as $column) { $ordinateSeries[$column][] = 0; } } $rowId = $periodsData[$i]->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX)->getLocalizedShortString(); $abscissaSeries[] = Common::unsanitizeInputValue($rowId); } } if (!$hasData || !$hasNonZeroValue) { throw new Exception(Piwik::translate('General_NoDataForGraph')); } //Setup the graph $graph = StaticGraph::factory($graphType); $graph->setWidth($width); $graph->setHeight($height); $graph->setFont($font); $graph->setFontSize($fontSize); $graph->setLegendFontSize($legendFontSize); $graph->setOrdinateLabels($ordinateLabels); $graph->setShowLegend($showLegend); $graph->setAliasedGraph($aliasedGraph); $graph->setAbscissaSeries($abscissaSeries); $graph->setAbscissaLogos($abscissaLogos); $graph->setOrdinateSeries($ordinateSeries); $graph->setOrdinateLogos($ordinateLogos); $graph->setColors(!empty($colors) ? explode(',', $colors) : array()); $graph->setTextColor($textColor); $graph->setBackgroundColor($backgroundColor); $graph->setGridColor($gridColor); // when requested period is day, x-axis unit is time and all date labels can not be displayed // within requested width, force labels to be skipped every 6 days to delimit weeks if ($period == 'day' && $isMultiplePeriod) { $graph->setForceSkippedLabels(6); } // render graph $graph->renderGraph(); } catch (\Exception $e) { $graph = new \Piwik\Plugins\ImageGraph\StaticGraph\Exception(); $graph->setWidth($width); $graph->setHeight($height); $graph->setFont($font); $graph->setFontSize($fontSize); $graph->setBackgroundColor($backgroundColor); $graph->setTextColor($textColor); $graph->setException($e); $graph->renderGraph(); } // restoring get parameters $_GET = $savedGET; switch ($outputType) { case self::GRAPH_OUTPUT_FILE: if ($idGoal != '') { $idGoal = '_' . $idGoal; } $fileName = self::$DEFAULT_PARAMETERS[$graphType][self::FILENAME_KEY] . '_' . $apiModule . '_' . $apiAction . $idGoal . ' ' . str_replace(',', '-', $date) . ' ' . $idSite . '.png'; $fileName = str_replace(array(' ', '/'), '_', $fileName); if (!Filesystem::isValidFilename($fileName)) { throw new Exception('Error: Image graph filename ' . $fileName . ' is not valid.'); } return $graph->sendToDisk($fileName); case self::GRAPH_OUTPUT_PHP: return $graph->getRenderedImage(); case self::GRAPH_OUTPUT_INLINE: default: $graph->sendToBrowser(); exit; } }
/** * If set, Piwik will use the hostname config no matter if it exists or not. Useful for instance if you want to * create a new hostname config: * * $config = Config::getInstance(); * $config->forceUsageOfHostnameConfig('piwik.example.com'); * $config->save(); * * @param string $hostname eg piwik.example.com * @return string * @throws \Exception In case the domain contains not allowed characters * @internal */ public function forceUsageOfLocalHostnameConfig($hostname) { $hostConfig = self::getLocalConfigInfoForHostname($hostname); $filename = $hostConfig['file']; if (!Filesystem::isValidFilename($filename)) { throw new Exception('Piwik domain is not a valid looking hostname (' . $filename . ').'); } $pathLocal = $hostConfig['path']; try { $this->reload($pathLocal); } catch (Exception $ex) { // pass (not required for local file to exist at this point) } return $pathLocal; }
/** * If set, Piwik will use the hostname config no matter if it exists or not. Useful for instance if you want to * create a new hostname config: * * $config = Config::getInstance(); * $config->forceUsageOfHostnameConfig('piwik.example.com'); * $config->save(); * * @param string $hostname eg piwik.example.com * @return string * @throws \Exception In case the domain contains not allowed characters */ public function forceUsageOfLocalHostnameConfig($hostname) { $hostConfig = self::getLocalConfigInfoForHostname($hostname); $filename = $hostConfig['file']; if (!Filesystem::isValidFilename($filename)) { throw new Exception('Piwik domain is not a valid looking hostname (' . $filename . ').'); } $this->pathLocal = $hostConfig['path']; $this->configLocal = array(); $this->initialized = false; return $this->pathLocal; }