Example #1
0
 public function validate()
 {
     $inTrackerRequest = SettingsServer::isTrackerApiRequest();
     $inConsole = Common::isPhpCliMode();
     $this->checkConfigFileExists($this->settingsProvider->getPathGlobal());
     $this->checkConfigFileExists($this->settingsProvider->getPathLocal(), $startInstaller = !$inTrackerRequest && !$inConsole);
 }
Example #2
0
 private function makeTrackerInstance()
 {
     SettingsServer::setIsTrackerApiRequest();
     $storage = Factory::make('PluginName');
     SettingsServer::setIsNotTrackerApiRequest();
     return $storage;
 }
Example #3
0
 /**
  * Update Piwik codebase by downloading and installing the latest version.
  *
  * @param bool $https Whether to use HTTPS if supported of not. If false, will use HTTP.
  * @return string[] Return an array of messages for the user.
  * @throws ArchiveDownloadException
  * @throws UpdaterException
  * @throws Exception
  */
 public function updatePiwik($https = true)
 {
     if (!$this->isNewVersionAvailable()) {
         throw new Exception($this->translator->translate('CoreUpdater_ExceptionAlreadyLatestVersion', Version::VERSION));
     }
     SettingsServer::setMaxExecutionTime(0);
     $newVersion = $this->getLatestVersion();
     $url = $this->getArchiveUrl($newVersion, $https);
     $messages = array();
     try {
         $archiveFile = $this->downloadArchive($newVersion, $url);
         $messages[] = $this->translator->translate('CoreUpdater_DownloadingUpdateFromX', $url);
         $extractedArchiveDirectory = $this->decompressArchive($archiveFile);
         $messages[] = $this->translator->translate('CoreUpdater_UnpackingTheUpdate');
         $this->verifyDecompressedArchive($extractedArchiveDirectory);
         $messages[] = $this->translator->translate('CoreUpdater_VerifyingUnpackedFiles');
         $disabledPluginNames = $this->disableIncompatiblePlugins($newVersion);
         if (!empty($disabledPluginNames)) {
             $messages[] = $this->translator->translate('CoreUpdater_DisablingIncompatiblePlugins', implode(', ', $disabledPluginNames));
         }
         $this->installNewFiles($extractedArchiveDirectory);
         $messages[] = $this->translator->translate('CoreUpdater_InstallingTheLatestVersion');
     } catch (ArchiveDownloadException $e) {
         throw $e;
     } catch (Exception $e) {
         throw new UpdaterException($e, $messages);
     }
     return $messages;
 }
Example #4
0
    private function getLongErrorMessage()
    {
        $message = '<p>';

        if (SettingsServer::isWindows()) {
            $message .= $this->translator->translate(
                'Installation_SystemCheckWinPdoAndMysqliHelp',
                array('<br /><br /><code>extension=php_mysqli.dll</code><br /><code>extension=php_pdo.dll</code><br /><code>extension=php_pdo_mysql.dll</code><br />')
            );
        } else {
            $message .= $this->translator->translate(
                'Installation_SystemCheckPdoAndMysqliHelp',
                array(
                    '<br /><br /><code>--with-mysqli</code><br /><code>--with-pdo-mysql</code><br /><br />',
                    '<br /><br /><code>extension=mysqli.so</code><br /><code>extension=pdo.so</code><br /><code>extension=pdo_mysql.so</code><br />'
                )
            );
        }

        $message .= $this->translator->translate('Installation_RestartWebServer') . '<br/><br/>';
        $message .= $this->translator->translate('Installation_SystemCheckPhpPdoAndMysqli', array(
            '<a style="color:red" href="http://php.net/pdo">',
            '</a>',
            '<a style="color:red" href="http://php.net/mysqli">',
            '</a>',
        ));
        $message .= '</p>';

        return $message;
    }
    /**
     * Generate IIS web.config files to restrict access
     *
     * Note: for IIS 7 and above
     */
    public static function createWebConfigFiles()
    {
        if (!SettingsServer::isIIS()) {
            return;
        }
        @file_put_contents(PIWIK_INCLUDE_PATH . '/web.config', '<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <hiddenSegments>
          <add segment="config" />
          <add segment="core" />
          <add segment="lang" />
          <add segment="tmp" />
        </hiddenSegments>
        <fileExtensions>
          <add fileExtension=".tpl" allowed="false" />
          <add fileExtension=".twig" allowed="false" />
          <add fileExtension=".php4" allowed="false" />
          <add fileExtension=".php5" allowed="false" />
          <add fileExtension=".inc" allowed="false" />
          <add fileExtension=".in" allowed="false" />
          <add fileExtension=".csv" allowed="false" />
          <add fileExtension=".pdf" allowed="false" />
          <add fileExtension=".log" allowed="false" />
        </fileExtensions>
      </requestFiltering>
    </security>
    <directoryBrowse enabled="false" />
    <defaultDocument>
      <files>
        <remove value="index.php" />
        <add value="index.php" />
      </files>
    </defaultDocument>
    <staticContent>
      <remove fileExtension=".svg" />
      <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
    </staticContent>
  </system.webServer>
</configuration>');
        // deny direct access to .php files
        $directoriesToProtect = array('/libs', '/vendor', '/plugins');
        foreach ($directoriesToProtect as $directoryToProtect) {
            @file_put_contents(PIWIK_INCLUDE_PATH . $directoryToProtect . '/web.config', '<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <denyUrlSequences>
          <add sequence=".php" />
        </denyUrlSequences>
      </requestFiltering>
    </security>
  </system.webServer>
</configuration>');
        }
    }
 public function execute()
 {
     $label = $this->translator->translate('Installation_SystemCheckGDFreeType');
     if (SettingsServer::isGdExtensionEnabled()) {
         return array(DiagnosticResult::singleResult($label, DiagnosticResult::STATUS_OK));
     }
     $comment = sprintf('%s<br />%s', $this->translator->translate('Installation_SystemCheckGDFreeType'), $this->translator->translate('Installation_SystemCheckGDHelp'));
     return array(DiagnosticResult::singleResult($label, DiagnosticResult::STATUS_WARNING, $comment));
 }
Example #7
0
 public static function make($pluginName)
 {
     if (SettingsServer::isTrackerApiRequest()) {
         $storage = new SettingsStorage($pluginName);
     } else {
         $storage = new Storage($pluginName);
     }
     return $storage;
 }
Example #8
0
 public function execute()
 {
     $label = $this->translator->translate('SitesManager_Timezone');
     if (SettingsServer::isTimezoneSupportEnabled()) {
         return array(DiagnosticResult::singleResult($label, DiagnosticResult::STATUS_OK));
     }
     $comment = sprintf('%s<br />%s.', $this->translator->translate('SitesManager_AdvancedTimezoneSupportNotFound'), '<a href="http://php.net/manual/en/datetime.installation.php" rel="noreferrer" target="_blank">Timezone PHP documentation</a>');
     return array(DiagnosticResult::singleResult($label, DiagnosticResult::STATUS_WARNING, $comment));
 }
 /**
  * Create .htaccess file in specified directory
  *
  * Apache-specific; for IIS @see web.config
  *
  * @param string $path without trailing slash
  * @param bool $overwrite whether to overwrite an existing file or not
  * @param string $content
  */
 public static function createHtAccess($path, $overwrite = true, $content = "<Files \"*\">\n<IfModule mod_access.c>\nDeny from all\n</IfModule>\n<IfModule !mod_access_compat>\n<IfModule mod_authz_host.c>\nDeny from all\n</IfModule>\n</IfModule>\n<IfModule mod_access_compat>\nDeny from all\n</IfModule>\n</Files>\n")
 {
     if (SettingsServer::isApache()) {
         $file = $path . '/.htaccess';
         if ($overwrite || !file_exists($file)) {
             @file_put_contents($file, $content);
         }
     }
 }
Example #10
0
 /**
  * Returns the database connection and creates it if it hasn't been already.
  *
  * @return \Piwik\Tracker\Db|\Piwik\Db\AdapterInterface|\Piwik\Db
  */
 public static function get()
 {
     if (SettingsServer::isTrackerApiRequest()) {
         return Tracker::getDatabase();
     }
     if (!self::hasDatabaseObject()) {
         self::createDatabaseObject();
     }
     return self::$connection;
 }
Example #11
0
 /**
  * @return string
  */
 protected static function getPythonBinary()
 {
     if (\Piwik\SettingsServer::isWindows()) {
         return "C:\\Python27\\python.exe";
     }
     if (IntegrationTestCase::isTravisCI()) {
         return 'python2.6';
     }
     return 'python';
 }
Example #12
0
 public function execute()
 {
     $label = $this->translator->translate('Installation_SystemCheckMemoryLimit');
     SettingsServer::raiseMemoryLimitIfNecessary();
     $memoryLimit = SettingsServer::getMemoryLimitValue();
     $comment = $memoryLimit . 'M';
     if ($memoryLimit >= $this->minimumMemoryLimit) {
         $status = DiagnosticResult::STATUS_OK;
     } else {
         $status = DiagnosticResult::STATUS_WARNING;
         $comment .= sprintf('<br />%s<br />%s', $this->translator->translate('Installation_SystemCheckMemoryLimitHelp'), $this->translator->translate('Installation_RestartWebServer'));
     }
     return array(DiagnosticResult::singleResult($label, $status, $comment));
 }
Example #13
0
 public function execute()
 {
     $label = $this->translator->translate('CustomPiwikJs_DiagnosticPiwikJsWritable');
     $file = new File(PIWIK_DOCUMENT_ROOT . '/piwik.js');
     if ($file->hasWriteAccess()) {
         return array(DiagnosticResult::singleResult($label, DiagnosticResult::STATUS_OK, ''));
     }
     $comment = $this->translator->translate('CustomPiwikJs_DiagnosticPiwikJsNotWritable');
     if (!SettingsServer::isWindows()) {
         $realpath = Filesystem::realpath(PIWIK_INCLUDE_PATH . '/piwik.js');
         $command = "<br/><code> chmod +w {$realpath}<br/> chown " . Filechecks::getUserAndGroup() . " " . $realpath . "</code><br />";
         $comment .= $this->translator->translate('CustomPiwikJs_DiagnosticPiwikJsMakeWritable', $command);
     }
     return array(DiagnosticResult::singleResult($label, DiagnosticResult::STATUS_WARNING, $comment));
 }
Example #14
0
 public function getSelectQueryString(SegmentExpression $segmentExpression, $select, $from, $where, $bind, $groupBy, $orderBy, $limit)
 {
     $result = parent::getSelectQueryString($segmentExpression, $select, $from, $where, $bind, $groupBy, $orderBy, $limit);
     $prefixParts = array();
     if (SettingsServer::isArchivePhpTriggered()) {
         $prefixParts[] = 'trigger = CronArchive';
     }
     $idSegments = $this->getSegmentIdOfExpression($segmentExpression);
     if (!empty($idSegments)) {
         $prefixParts[] = "idSegments = [" . implode(', ', $idSegments) . "]";
     }
     if (!empty($prefixParts)) {
         $result['sql'] = "/* " . implode(', ', $prefixParts) . " */\n" . $result['sql'];
     }
     return $result;
 }
Example #15
0
 /**
  * Main view showing listing of websites and settings
  */
 public function index()
 {
     $view = new View('@SitesManager/index');
     Site::clearCache();
     if (Piwik::isUserIsSuperUser()) {
         $sitesRaw = API::getInstance()->getAllSites();
     } else {
         $sitesRaw = API::getInstance()->getSitesWithAdminAccess();
     }
     // Gets sites after Site.setSite hook was called
     $sites = array_values(Site::getSites());
     if (count($sites) != count($sitesRaw)) {
         throw new Exception("One or more website are missing or invalid.");
     }
     foreach ($sites as &$site) {
         $site['alias_urls'] = API::getInstance()->getSiteUrlsFromId($site['idsite']);
         $site['excluded_ips'] = explode(',', $site['excluded_ips']);
         $site['excluded_parameters'] = explode(',', $site['excluded_parameters']);
         $site['excluded_user_agents'] = explode(',', $site['excluded_user_agents']);
     }
     $view->adminSites = $sites;
     $view->adminSitesCount = count($sites);
     $timezones = API::getInstance()->getTimezonesList();
     $view->timezoneSupported = SettingsServer::isTimezoneSupportEnabled();
     $view->timezones = Common::json_encode($timezones);
     $view->defaultTimezone = API::getInstance()->getDefaultTimezone();
     $view->currencies = Common::json_encode(API::getInstance()->getCurrencyList());
     $view->defaultCurrency = API::getInstance()->getDefaultCurrency();
     $view->utcTime = Date::now()->getDatetime();
     $excludedIpsGlobal = API::getInstance()->getExcludedIpsGlobal();
     $view->globalExcludedIps = str_replace(',', "\n", $excludedIpsGlobal);
     $excludedQueryParametersGlobal = API::getInstance()->getExcludedQueryParametersGlobal();
     $view->globalExcludedQueryParameters = str_replace(',', "\n", $excludedQueryParametersGlobal);
     $globalExcludedUserAgents = API::getInstance()->getExcludedUserAgentsGlobal();
     $view->globalExcludedUserAgents = str_replace(',', "\n", $globalExcludedUserAgents);
     $view->globalSearchKeywordParameters = API::getInstance()->getSearchKeywordParametersGlobal();
     $view->globalSearchCategoryParameters = API::getInstance()->getSearchCategoryParametersGlobal();
     $view->isSearchCategoryTrackingEnabled = \Piwik\Plugin\Manager::getInstance()->isPluginActivated('CustomVariables');
     $view->allowSiteSpecificUserAgentExclude = API::getInstance()->isSiteSpecificUserAgentExcludeEnabled();
     $view->globalKeepURLFragments = API::getInstance()->getKeepURLFragmentsGlobal();
     $view->currentIpAddress = IP::getIpFromHeader();
     $view->showAddSite = (bool) Common::getRequestVar('showaddsite', false);
     $this->setBasicVariablesView($view);
     return $view->render();
 }
Example #16
0
 public function validate()
 {
     $this->checkConfigFileExists($this->settingsProvider->getPathGlobal());
     if (SettingsPiwik::isPiwikInstalled()) {
         $this->checkConfigFileExists($this->settingsProvider->getPathLocal(), $startInstaller = false);
         return;
     }
     $startInstaller = true;
     if (SettingsServer::isTrackerApiRequest()) {
         // if Piwik is not installed yet, the piwik.php should do nothing and not return an error
         throw new NotYetInstalledException("As Piwik is not installed yet, the Tracking API cannot proceed and will exit without error.");
     }
     if (Common::isPhpCliMode()) {
         // in CLI, do not start/redirect to installer, simply output the exception at the top
         $startInstaller = false;
     }
     // Start the installation when config file not found
     $this->checkConfigFileExists($this->settingsProvider->getPathLocal(), $startInstaller);
 }
Example #17
0
 /**
  * test of validity of an archive, for today's archive with toronto's timezone
  * @group Core
  */
 public function testInitTodayToronto()
 {
     if (!SettingsServer::isTimezoneSupportEnabled()) {
         $this->markTestSkipped('timezones needs to be supported');
     }
     $now = time();
     $siteTimezone = 'America/Toronto';
     $timestamp = Date::factory('now', $siteTimezone)->getTimestamp();
     $dateLabel = date('Y-m-d', $timestamp);
     Rules::setBrowserTriggerArchiving(true);
     $archiveProcessor = $this->_createArchiveProcessor('day', $dateLabel, $siteTimezone);
     $archiveProcessor->time = $now;
     // we look at anything processed within the time to live range
     $dateMinArchived = $now - Rules::getTodayArchiveTimeToLive();
     $this->compareTimestamps($dateMinArchived, $archiveProcessor->public_getMinTimeArchiveProcessed());
     $this->assertTrue($archiveProcessor->public_isArchiveTemporary());
     // when browsers don't trigger archives...
     Rules::setBrowserTriggerArchiving(false);
     // ...we force ArchiveProcessor to fetch any of the most recent archive
     $dateMinArchived = false;
     $this->compareTimestamps($dateMinArchived, $archiveProcessor->public_getMinTimeArchiveProcessed());
     // this test varies with DST
     $this->assertTrue($archiveProcessor->getParams()->getDateStart()->getDateStartUTC() == date('Y-m-d', $timestamp) . ' 04:00:00' || $archiveProcessor->getParams()->getDateStart()->getDateStartUTC() == date('Y-m-d', $timestamp) . ' 05:00:00');
     $this->assertTrue($archiveProcessor->getParams()->getDateEnd()->getDateEndUTC() == date('Y-m-d', $timestamp + 86400) . ' 03:59:59' || $archiveProcessor->getParams()->getDateEnd()->getDateEndUTC() == date('Y-m-d', $timestamp + 86400) . ' 04:59:59');
     $this->assertTrue($archiveProcessor->public_isArchiveTemporary());
 }
Example #18
0
 public function runUpdaterAndExit($doDryRun = null)
 {
     $updater = new Updater();
     $componentsWithUpdateFile = CoreUpdater::getComponentUpdates($updater);
     if (empty($componentsWithUpdateFile)) {
         throw new NoUpdatesFoundException("Everything is already up to date.");
     }
     SettingsServer::setMaxExecutionTime(0);
     $cli = Common::isPhpCliMode() ? '_cli' : '';
     $welcomeTemplate = '@CoreUpdater/runUpdaterAndExit_welcome' . $cli;
     $doneTemplate = '@CoreUpdater/runUpdaterAndExit_done' . $cli;
     $viewWelcome = new View($welcomeTemplate);
     $this->addCustomLogoInfo($viewWelcome);
     $viewDone = new View($doneTemplate);
     $this->addCustomLogoInfo($viewDone);
     $doExecuteUpdates = Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1;
     if (is_null($doDryRun)) {
         $doDryRun = !$doExecuteUpdates;
     }
     if ($doDryRun) {
         $viewWelcome->queries = $updater->getSqlQueriesToExecute();
         $viewWelcome->isMajor = $updater->hasMajorDbUpdate();
         $this->doWelcomeUpdates($viewWelcome, $componentsWithUpdateFile);
         return $viewWelcome->render();
     }
     // CLI
     if (Common::isPhpCliMode()) {
         $this->doWelcomeUpdates($viewWelcome, $componentsWithUpdateFile);
         $output = $viewWelcome->render();
         // Proceed with upgrade in CLI only if user specifically asked for it, or if running console command
         $isUpdateRequested = Common::isRunningConsoleCommand() || Piwik::getModule() == 'CoreUpdater';
         if (!$this->coreError && $isUpdateRequested) {
             $this->doExecuteUpdates($viewDone, $updater, $componentsWithUpdateFile);
             $output .= $viewDone->render();
         }
         return $output;
     }
     // Web
     if ($doExecuteUpdates) {
         $this->warningMessages = array();
         $this->doExecuteUpdates($viewDone, $updater, $componentsWithUpdateFile);
         $this->redirectToDashboardWhenNoError($updater);
         return $viewDone->render();
     }
     exit;
 }
Example #19
0
 /**
  * Batch insert into table from CSV (or other delimited) file.
  *
  * @param string $tableName Name of table
  * @param array $fields Field names
  * @param string $filePath Path name of a file.
  * @param array $fileSpec File specifications (delimiter, line terminator, etc)
  *
  * @throws Exception
  * @return bool  True if successful; false otherwise
  */
 public static function createTableFromCSVFile($tableName, $fields, $filePath, $fileSpec)
 {
     // Chroot environment: prefix the path with the absolute chroot path
     $chrootPath = Config::getInstance()->General['absolute_chroot_path'];
     if (!empty($chrootPath)) {
         $filePath = $chrootPath . $filePath;
     }
     // On Windows, MySQL expects forward slashes as directory separators
     if (SettingsServer::isWindows()) {
         $filePath = str_replace('\\', '/', $filePath);
     }
     $query = "\n\t\t\t\t'{$filePath}'\n\t\t\tREPLACE\n\t\t\tINTO TABLE\n\t\t\t\t`" . $tableName . "`";
     if (isset($fileSpec['charset'])) {
         $query .= ' CHARACTER SET ' . $fileSpec['charset'];
     }
     $fieldList = '(' . join(',', $fields) . ')';
     $query .= "\n\t\t\tFIELDS TERMINATED BY\n\t\t\t\t'" . $fileSpec['delim'] . "'\n\t\t\tENCLOSED BY\n\t\t\t\t'" . $fileSpec['quote'] . "'\n\t\t";
     if (isset($fileSpec['escape'])) {
         $query .= " ESCAPED BY '" . $fileSpec['escape'] . "'";
     }
     $query .= "\n\t\t\tLINES TERMINATED BY\n\t\t\t\t'" . $fileSpec['eol'] . "'\n\t\t\t{$fieldList}\n\t\t";
     /*
      * First attempt: assume web server and MySQL server are on the same machine;
      * this requires that the db user have the FILE privilege; however, since this is
      * a global privilege, it may not be granted due to security concerns
      */
     $keywords = array('');
     /*
      * Second attempt: using the LOCAL keyword means the client reads the file and sends it to the server;
      * the LOCAL keyword may trigger a known PHP PDO\MYSQL bug when MySQL not built with --enable-local-infile
      * @see http://bugs.php.net/bug.php?id=54158
      */
     $openBaseDir = ini_get('open_basedir');
     $safeMode = ini_get('safe_mode');
     if (empty($openBaseDir) && empty($safeMode)) {
         // php 5.x - LOAD DATA LOCAL INFILE is disabled if open_basedir restrictions or safe_mode enabled
         $keywords[] = 'LOCAL ';
     }
     $exceptions = array();
     foreach ($keywords as $keyword) {
         $queryStart = 'LOAD DATA ' . $keyword . 'INFILE ';
         $sql = $queryStart . $query;
         try {
             $result = @Db::exec($sql);
             if (empty($result) || $result < 0) {
                 continue;
             }
             return true;
         } catch (Exception $e) {
             //				echo $sql . ' ---- ' .  $e->getMessage();
             $code = $e->getCode();
             $message = $e->getMessage() . ($code ? "[{$code}]" : '');
             if (!Db::get()->isErrNo($e, '1148')) {
                 Log::info("LOAD DATA INFILE failed... Error was: %s", $message);
             }
             $exceptions[] = "\n  Try #" . (count($exceptions) + 1) . ': ' . $queryStart . ": " . $message;
         }
     }
     if (count($exceptions)) {
         throw new Exception(implode(",", $exceptions));
     }
     return false;
 }
Example #20
0
 /**
  * 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;
 }
Example #21
0
 public function init()
 {
     SettingsServer::setMaxExecutionTime(0);
     $this->archivingStartingTime = time();
     // Note: the order of methods call matters here.
     $this->initStateFromParameters();
     $this->logInitInfo();
     $this->logArchiveTimeoutInfo();
     // record archiving start time
     Option::set(self::OPTION_ARCHIVING_STARTED_TS, time());
     $this->segments = $this->initSegmentsToArchive();
     $this->allWebsites = APISitesManager::getInstance()->getAllSitesId();
     if (!empty($this->shouldArchiveOnlySpecificPeriods)) {
         $this->logger->info("- Will only process the following periods: " . implode(", ", $this->shouldArchiveOnlySpecificPeriods) . " (--force-periods)");
     }
     $this->invalidateArchivedReportsForSitesThatNeedToBeArchivedAgain();
     $websitesIds = $this->initWebsiteIds();
     $this->filterWebsiteIds($websitesIds);
     $this->websites = $this->createSitesToArchiveQueue($websitesIds);
     if ($this->websites->getInitialSiteIds() != $websitesIds) {
         $this->logger->info('Will ignore websites and help finish a previous started queue instead. IDs: ' . implode(', ', $this->websites->getInitialSiteIds()));
     }
     $this->logForcedSegmentInfo();
     /**
      * This event is triggered after a CronArchive instance is initialized.
      *
      * @param array $websiteIds The list of website IDs this CronArchive instance is processing.
      *                          This will be the entire list of IDs regardless of whether some have
      *                          already been processed.
      */
     Piwik::postEvent('CronArchive.init.finish', array($this->websites->getInitialSiteIds()));
 }
Example #22
0
 public function processReports(&$processedReports, $reportType, $outputType, $report)
 {
     if (!self::manageEvent($reportType)) {
         return;
     }
     $displayFormat = $report['parameters'][self::DISPLAY_FORMAT_PARAMETER];
     $evolutionGraph = $report['parameters'][self::EVOLUTION_GRAPH_PARAMETER];
     foreach ($processedReports as &$processedReport) {
         $metadata = $processedReport['metadata'];
         $isAggregateReport = !empty($metadata['dimension']);
         $processedReport['displayTable'] = $displayFormat != self::DISPLAY_FORMAT_GRAPHS_ONLY;
         $processedReport['displayGraph'] = ($isAggregateReport ? $displayFormat == self::DISPLAY_FORMAT_GRAPHS_ONLY || $displayFormat == self::DISPLAY_FORMAT_TABLES_AND_GRAPHS : $displayFormat != self::DISPLAY_FORMAT_TABLES_ONLY) && \Piwik\SettingsServer::isGdExtensionEnabled() && \Piwik\Plugin\Manager::getInstance()->isPluginActivated('ImageGraph') && !empty($metadata['imageGraphUrl']);
         $processedReport['evolutionGraph'] = $evolutionGraph;
         // remove evolution metrics from MultiSites.getAll
         if ($metadata['module'] == 'MultiSites') {
             $columns = $processedReport['columns'];
             foreach (\Piwik\Plugins\MultiSites\API::getApiMetrics($enhanced = true) as $metricSettings) {
                 unset($columns[$metricSettings[\Piwik\Plugins\MultiSites\API::METRIC_EVOLUTION_COL_NAME_KEY]]);
             }
             $processedReport['metadata'] = $metadata;
             $processedReport['columns'] = $columns;
         }
     }
 }
Example #23
0
/**
 * readfile() replacement.
 * Behaves similar to readfile($filename);
 *
 * @author anthon (dot) pang (at) gmail (dot) com
 *
 * @param string $filename
 * @param bool $useIncludePath
 * @param resource $context
 * @return int the number of bytes read from the file, or false if an error occurs
 */
function _readfile($filename, $byteStart, $byteEnd, $useIncludePath = false, $context = null)
{
    $count = @filesize($filename);
    // built-in function has a 2 MB limit when using mmap
    if (function_exists('readfile') && $count <= 2 * 1024 * 1024 && $byteStart == 0 && $byteEnd == $count) {
        return @readfile($filename, $useIncludePath, $context);
    }
    // when in doubt (or when readfile() function is disabled)
    $handle = @fopen($filename, SettingsServer::isWindows() ? "rb" : "r");
    if ($handle) {
        fseek($handle, $byteStart);
        for ($pos = $byteStart; $pos < $byteEnd && !feof($handle); $pos = ftell($handle)) {
            echo fread($handle, min(8192, $byteEnd - $pos));
            ob_flush();
            flush();
        }
        fclose($handle);
        return $byteEnd - $byteStart;
    }
    return false;
}
Example #24
0
 public function runUpdaterAndExit($doDryRun = null)
 {
     $updater = new DbUpdater();
     $componentsWithUpdateFile = $updater->getComponentUpdates();
     if (empty($componentsWithUpdateFile)) {
         throw new NoUpdatesFoundException("Everything is already up to date.");
     }
     SettingsServer::setMaxExecutionTime(0);
     $welcomeTemplate = '@CoreUpdater/runUpdaterAndExit_welcome';
     $doneTemplate = '@CoreUpdater/runUpdaterAndExit_done';
     $viewWelcome = new View($welcomeTemplate);
     $this->addCustomLogoInfo($viewWelcome);
     $this->setBasicVariablesView($viewWelcome);
     $viewDone = new View($doneTemplate);
     $this->addCustomLogoInfo($viewDone);
     $this->setBasicVariablesView($viewDone);
     $doExecuteUpdates = Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1;
     if (is_null($doDryRun)) {
         $doDryRun = !$doExecuteUpdates;
     }
     if ($doDryRun) {
         $viewWelcome->queries = $updater->getSqlQueriesToExecute();
         $viewWelcome->isMajor = $updater->hasMajorDbUpdate();
         $this->doWelcomeUpdates($viewWelcome, $componentsWithUpdateFile);
         return $viewWelcome->render();
     }
     // Web
     if ($doExecuteUpdates) {
         $this->warningMessages = array();
         $this->doExecuteUpdates($viewDone, $updater, $componentsWithUpdateFile);
         $this->redirectToDashboardWhenNoError($updater);
         return $viewDone->render();
     }
     exit;
 }
Example #25
0
 /**
  * Used to initialize core Piwik components on a piwik.php request
  * Eg. when cache is missed and we will be calling some APIs to generate cache
  */
 public static function initCorePiwikInTrackerMode()
 {
     if (SettingsServer::isTrackerApiRequest() && self::$initTrackerMode === false) {
         self::$initTrackerMode = true;
         require_once PIWIK_INCLUDE_PATH . '/core/Option.php';
         Access::getInstance();
         Config::getInstance();
         try {
             Db::get();
         } catch (Exception $e) {
             Db::createDatabaseObject();
         }
         \Piwik\Plugin\Manager::getInstance()->loadCorePluginsDuringTracker();
     }
 }
Example #26
0
 /**
  * Returns the help text displayed to suggest which command to run to give writable access to a file or directory
  *
  * @param string $realpath
  * @return string
  */
 private static function getMakeWritableCommand($realpath)
 {
     if (SettingsServer::isWindows()) {
         return "<code>cacls {$realpath} /t /g " . self::getUser() . ":f</code><br />\n";
     }
     return "<code>chmod -R 0755 {$realpath}</code><br />";
 }
 /**
  * Must be called before dispatch()
  * - checks that directories are writable,
  * - loads the configuration file,
  * - loads the plugin,
  * - inits the DB connection,
  * - etc.
  *
  * @throws Exception
  * @return void
  */
 public function init()
 {
     static $initialized = false;
     if ($initialized) {
         return;
     }
     $initialized = true;
     $tmpPath = StaticContainer::get('path.tmp');
     $directoriesToCheck = array($tmpPath, $tmpPath . '/assets/', $tmpPath . '/cache/', $tmpPath . '/logs/', $tmpPath . '/tcpdf/', $tmpPath . '/templates_c/');
     Filechecks::dieIfDirectoriesNotWritable($directoriesToCheck);
     $this->handleMaintenanceMode();
     $this->handleProfiler();
     $this->handleSSLRedirection();
     Plugin\Manager::getInstance()->loadPluginTranslations();
     Plugin\Manager::getInstance()->loadActivatedPlugins();
     // try to connect to the database
     try {
         Db::createDatabaseObject();
         Db::fetchAll("SELECT DATABASE()");
     } catch (Exception $exception) {
         if (self::shouldRethrowException()) {
             throw $exception;
         }
         Log::debug($exception);
         /**
          * Triggered when Piwik cannot connect to the database.
          *
          * This event can be used to start the installation process or to display a custom error
          * message.
          *
          * @param Exception $exception The exception thrown from creating and testing the database
          *                             connection.
          */
         Piwik::postEvent('Db.cannotConnectToDb', array($exception), $pending = true);
         throw $exception;
     }
     // try to get an option (to check if data can be queried)
     try {
         Option::get('TestingIfDatabaseConnectionWorked');
     } catch (Exception $exception) {
         if (self::shouldRethrowException()) {
             throw $exception;
         }
         Log::debug($exception);
         /**
          * Triggered when Piwik cannot access database data.
          *
          * This event can be used to start the installation process or to display a custom error
          * message.
          *
          * @param Exception $exception The exception thrown from trying to get an option value.
          */
         Piwik::postEvent('Config.badConfigurationFile', array($exception), $pending = true);
         throw $exception;
     }
     // Init the Access object, so that eg. core/Updates/* can enforce Super User and use some APIs
     Access::getInstance();
     /**
      * Triggered just after the platform is initialized and plugins are loaded.
      *
      * This event can be used to do early initialization.
      *
      * _Note: At this point the user is not authenticated yet._
      */
     Piwik::postEvent('Request.dispatchCoreAndPluginUpdatesScreen');
     $this->throwIfPiwikVersionIsOlderThanDBSchema();
     \Piwik\Plugin\Manager::getInstance()->installLoadedPlugins();
     // ensure the current Piwik URL is known for later use
     if (method_exists('Piwik\\SettingsPiwik', 'getPiwikUrl')) {
         SettingsPiwik::getPiwikUrl();
     }
     /**
      * Triggered before the user is authenticated, when the global authentication object
      * should be created.
      *
      * Plugins that provide their own authentication implementation should use this event
      * to set the global authentication object (which must derive from {@link Piwik\Auth}).
      *
      * **Example**
      *
      *     Piwik::addAction('Request.initAuthenticationObject', function() {
      *         StaticContainer::getContainer()->set('Piwik\Auth', new MyAuthImplementation());
      *     });
      */
     Piwik::postEvent('Request.initAuthenticationObject');
     try {
         $authAdapter = StaticContainer::get('Piwik\\Auth');
     } catch (Exception $e) {
         $message = "Authentication object cannot be found in the container. Maybe the Login plugin is not activated?\n                        <br />You can activate the plugin by adding:<br />\n                        <code>Plugins[] = Login</code><br />\n                        under the <code>[Plugins]</code> section in your config/config.ini.php";
         $ex = new AuthenticationFailedException($message);
         $ex->setIsHtmlMessage();
         throw $ex;
     }
     Access::getInstance()->reloadAccess($authAdapter);
     // Force the auth to use the token_auth if specified, so that embed dashboard
     // and all other non widgetized controller methods works fine
     if (Common::getRequestVar('token_auth', false, 'string') !== false) {
         Request::reloadAuthUsingTokenAuth();
     }
     SettingsServer::raiseMemoryLimitIfNecessary();
     \Piwik\Plugin\Manager::getInstance()->postLoadPlugins();
     /**
      * Triggered after the platform is initialized and after the user has been authenticated, but
      * before the platform has handled the request.
      *
      * Piwik uses this event to check for updates to Piwik.
      */
     Piwik::postEvent('Platform.initialized');
 }
Example #28
0
 /**
  * Returns the list of timezones supported.
  * Used for addSite and updateSite
  *
  * @return array of timezone strings
  */
 public function getTimezonesList()
 {
     if (!SettingsServer::isTimezoneSupportEnabled()) {
         return array('UTC' => $this->getTimezonesListUTCOffsets());
     }
     $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
     $timezones = timezone_identifiers_list();
     $return = array();
     foreach ($timezones as $timezone) {
         // filter out timezones not recognized by strtotime()
         // @see http://bugs.php.net/46111
         $testDate = '2008-09-18 13:00:00 ' . $timezone;
         if (!strtotime($testDate)) {
             continue;
         }
         $timezoneExploded = explode('/', $timezone);
         $continent = $timezoneExploded[0];
         // only display timezones that are grouped by continent
         if (!in_array($continent, $continents)) {
             continue;
         }
         $city = $timezoneExploded[1];
         if (!empty($timezoneExploded[2])) {
             $city .= ' - ' . $timezoneExploded[2];
         }
         $city = str_replace('_', ' ', $city);
         $return[$continent][$timezone] = $city;
     }
     foreach ($continents as $continent) {
         if (!empty($return[$continent])) {
             ksort($return[$continent]);
         }
     }
     $return['UTC'] = $this->getTimezonesListUTCOffsets();
     return $return;
 }
Example #29
0
 /**
  * Load translation
  *
  * @param Plugin $plugin
  * @param string $langCode
  * @throws \Exception
  * @return bool whether the translation was found and loaded
  */
 private function loadTranslation($plugin, $langCode)
 {
     // we are in Tracker mode if Loader is not (yet) loaded
     if (SettingsServer::isTrackerApiRequest()) {
         return false;
     }
     if (is_string($plugin)) {
         $pluginName = $plugin;
     } else {
         $pluginName = $plugin->getPluginName();
     }
     $path = self::getPluginsDirectory() . $pluginName . '/lang/%s.json';
     $defaultLangPath = sprintf($path, $langCode);
     $defaultEnglishLangPath = sprintf($path, 'en');
     $translationsLoaded = false;
     // merge in english translations as default first
     if (file_exists($defaultEnglishLangPath)) {
         $translations = $this->getTranslationsFromFile($defaultEnglishLangPath);
         $translationsLoaded = true;
         if (isset($translations[$pluginName])) {
             // only merge translations of plugin - prevents overwritten strings
             Translate::mergeTranslationArray(array($pluginName => $translations[$pluginName]));
         }
     }
     // merge in specific language translations (to overwrite english defaults)
     if (!empty($langCode) && $defaultEnglishLangPath != $defaultLangPath && file_exists($defaultLangPath)) {
         $translations = $this->getTranslationsFromFile($defaultLangPath);
         $translationsLoaded = true;
         if (isset($translations[$pluginName])) {
             // only merge translations of plugin - prevents overwritten strings
             Translate::mergeTranslationArray(array($pluginName => $translations[$pluginName]));
         }
     }
     return $translationsLoaded;
 }
Example #30
0
 public function test_loadTrackerEnvironment_shouldNotThrow_whenConfigNotFound()
 {
     $this->assertTrue(!array_key_exists('PIWIK_TRACKER_DEBUG', $GLOBALS));
     $this->assertFalse(SettingsServer::isTrackerApiRequest());
     $this->assertTrue(is_readable(Config::getInstance()->getLocalPath()));
     $this->removeConfigFile();
     $this->assertFalse(is_readable(Config::getInstance()->getLocalPath()));
     Tracker::loadTrackerEnvironment();
     $this->assertTrue(SettingsServer::isTrackerApiRequest());
     //always reset on the test itself
     $this->restoreConfigFile();
 }