static function update() { $salt = Piwik_Common::generateUniqId(); if (!isset(Piwik_Config::getInstance()->superuser['salt'])) { try { if (is_writable(Piwik_Config::getLocalConfigPath())) { Piwik_Config::getInstance()->setConfigOption('superuser', 'salt', $salt); Piwik_Config::getInstance()->forceSave(); } else { throw new Exception('mandatory update failed'); } } catch (Exception $e) { throw new Piwik_Updater_UpdateErrorException("Please edit your config/config.ini.php file and add below <code>[superuser]</code> the following line: <br /><code>salt = {$salt}</code>"); } } $plugins = Piwik_Config::getInstance()->Plugins; if (!in_array('MultiSites', $plugins)) { try { if (is_writable(Piwik_Config::getLocalConfigPath())) { $plugins[] = 'MultiSites'; Piwik_Config::getInstance()->setConfigSection('Plugins', $plugins); Piwik_Config::getInstance()->forceSave(); } else { throw new Exception('optional update failed'); } } catch (Exception $e) { throw new Exception("You can now enable the new MultiSites plugin in the Plugins screen in the Piwik admin!"); } } Piwik_Updater::updateDatabase(__FILE__, self::getSql()); }
static function update() { $config = Zend_Registry::get('config'); $salt = Piwik_Common::generateUniqId(); try { if(isset($config->superuser->salt)) { return; } if(is_writable( Piwik_Config::getDefaultUserConfigPath() )) { $superuser_info = $config->superuser->toArray(); $superuser_info['salt'] = $salt; $config->superuser = $superuser_info; $config->__destruct(); Piwik::createConfigObject(); return; } } catch(Exception $e) { } throw new Piwik_Updater_UpdateErrorException("Edit config.ini.php and add below <code>[superuser]</code> the following line <br/><code>salt = $salt</code>"); }
static function update() { $config = Zend_Registry::get('config'); $salt = Piwik_Common::generateUniqId(); if(!isset($config->superuser->salt)) { try { if(is_writable( Piwik_Config::getDefaultUserConfigPath() )) { $superuser_info = $config->superuser->toArray(); $superuser_info['salt'] = $salt; $config->superuser = $superuser_info; $config->__destruct(); Piwik::createConfigObject(); } else { throw new Exception('mandatory update failed'); } } catch(Exception $e) { throw new Piwik_Updater_UpdateErrorException("Please edit your config/config.ini.php file and add below <code>[superuser]</code> the following line: <br/><code>salt = $salt</code>"); } } $config = Zend_Registry::get('config'); $plugins = $config->Plugins->toArray(); if(!in_array('MultiSites', $plugins)) { try { if(is_writable( Piwik_Config::getDefaultUserConfigPath() )) { $plugins[] = 'MultiSites'; $config->Plugins = $plugins; $config->__destruct(); Piwik::createConfigObject(); } else { throw new Exception('optional update failed'); } } catch(Exception $e) { throw new Exception("You can now enable the new MultiSites plugin in the Plugins screen in the Piwik admin!"); } } Piwik_Updater::updateDatabase(__FILE__, array( 'ALTER TABLE `'. Piwik::prefixTable('log_action') .'` CHANGE `name` `name` TEXT' => false, )); }
function __construct($logToFileFilename, $fileFormatter, $screenFormatter, $logToDatabaseTableName, $logToDatabaseColumnMapping) { parent::__construct(); $this->currentRequestKey = substr(Piwik_Common::generateUniqId(), 0, 8); $log_dir = Piwik_Config::getInstance()->log['logger_file_path']; if ($log_dir[0] != '/' && $log_dir[0] != DIRECTORY_SEPARATOR) { $log_dir = PIWIK_USER_PATH . '/' . $log_dir; } $this->logToFileFilename = $log_dir . '/' . $logToFileFilename; $this->fileFormatter = $fileFormatter; $this->screenFormatter = $screenFormatter; $this->logToDatabaseTableName = Piwik_Common::prefixTable($logToDatabaseTableName); $this->logToDatabaseColumnMapping = $logToDatabaseColumnMapping; }
/** * Generate nonce * * @param string $id Unique id to avoid namespace conflicts, e.g., ModuleName.ActionName * @param int $ttl Optional time-to-live in seconds; default is 5 minutes * @return string Nonce */ public static function getNonce($id, $ttl = 300) { // save session-dependent nonce $ns = new Piwik_Session_Namespace($id); $nonce = $ns->nonce; // re-use an unexpired nonce (a small deviation from the "used only once" principle, so long as we do not reset the expiration) // to handle browser pre-fetch or double fetch caused by some browser add-ons/extensions if (empty($nonce)) { // generate a new nonce $nonce = md5(Piwik_Common::getSalt() . time() . Piwik_Common::generateUniqId()); $ns->nonce = $nonce; $ns->setExpirationSeconds($ttl, 'nonce'); } return $nonce; }
/** * Installation Step 6: General Set-up (superuser login/password/email and subscriptions) */ function generalSetup() { $this->checkPreviousStepIsValid( __FUNCTION__ ); $view = new Piwik_Installation_View( $this->pathView . 'generalSetup.tpl', $this->getInstallationSteps(), __FUNCTION__ ); $this->skipThisStep( __FUNCTION__ ); $form = new Piwik_Installation_FormGeneralSetup(); if($form->validate()) { $superUserInfos = array( 'login' => $form->getSubmitValue('login'), 'password' => md5( $form->getSubmitValue('password') ), 'email' => $form->getSubmitValue('email'), 'salt' => Piwik_Common::generateUniqId(), ); $this->session->superuser_infos = $superUserInfos; $url = Zend_Registry::get('config')->General->api_service_url; $url .= '/1.0/subscribeNewsletter/'; $params = array( 'email' => $form->getSubmitValue('email'), 'security' => $form->getSubmitValue('subscribe_newsletter_security'), 'community' => $form->getSubmitValue('subscribe_newsletter_community'), 'url' => Piwik_Url::getCurrentUrlWithoutQueryString(), ); if($params['security'] == '1' || $params['community'] == '1') { if( !isset($params['security'])) { $params['security'] = '0'; } if( !isset($params['community'])) { $params['community'] = '0'; } $url .= '?' . http_build_query($params, '', '&'); try { Piwik_Http::sendHttpRequest($url, $timeout = 2); } catch(Exception $e) { // e.g., disable_functions = fsockopen; allow_url_open = Off } } $this->redirectToNextStep( __FUNCTION__ ); } $view->addForm($form); echo $view->render(); }
/** * Returns either * - "-1" for a known visitor * - a unique 32 char identifier @see Piwik_Common::generateUniqId() */ protected function getVisitorUniqueId() { if ($this->isVisitorKnown()) { return -1; } else { return Piwik_Common::generateUniqId(); } }
/** * Performs a batch insert into a specific table using either LOAD DATA INFILE or plain INSERTs, * as a fallback. On MySQL, LOAD DATA INFILE is 20x faster than a series of plain INSERTs. * * @param string $tableName PREFIXED table name! you must call Piwik_Common::prefixTable() before passing the table name * @param array $fields array of unquoted field names * @param array $values array of data to be inserted * @return bool True if the bulk LOAD was used, false if we fallback to plain INSERTs */ public static function tableInsertBatch($tableName, $fields, $values) { $filePath = PIWIK_USER_PATH . '/' . Piwik_AssetManager::MERGED_FILE_DIR . $tableName . '-' . Piwik_Common::generateUniqId() . '.csv'; if (Zend_Registry::get('db')->hasBulkLoader()) { try { // throw new Exception(''); $fileSpec = array('delim' => "\t", 'quote' => '"', 'escape' => '\\\\', 'escapespecial_cb' => create_function('$str', 'return str_replace(array(chr(92), chr(34)), array(chr(92).chr(92), chr(92).chr(34)), $str);'), 'eol' => "\r\n", 'null' => 'NULL'); // hack for charset mismatch if (!self::isDatabaseConnectionUTF8() && !isset(Zend_Registry::get('config')->database->charset)) { $fileSpec['charset'] = 'latin1'; } self::createCSVFile($filePath, $fileSpec, $values); $rc = self::createTableFromCSVFile($tableName, $fields, $filePath, $fileSpec); if ($rc) { unlink($filePath); return true; } throw new Exception('unknown cause'); } catch (Exception $e) { Piwik::log("LOAD DATA INFILE failed or not supported, falling back to normal INSERTs... Error was:" . $e->getMessage()); } } // if all else fails, fallback to a series of INSERTs @unlink($filePath); self::tableInsertBatchIterate($tableName, $fields, $values); return false; }
/** * Performs a batch insert into a specific table using either LOAD DATA INFILE or plain INSERTs, * as a fallback. On MySQL, LOAD DATA INFILE is 20x faster than a series of plain INSERTs. * * @param string $tableName PREFIXED table name! you must call Piwik_Common::prefixTable() before passing the table name * @param array $fields array of unquoted field names * @param array $values array of data to be inserted * @return bool True if the bulk LOAD was used, false if we fallback to plain INSERTs */ public static function tableInsertBatch($tableName, $fields, $values) { $fieldList = '(' . join(',', $fields) . ')'; try { // throw new Exception(''); $filePath = PIWIK_USER_PATH . '/' . Piwik_AssetManager::MERGED_FILE_DIR . $tableName . '-' . Piwik_Common::generateUniqId() . '.csv'; if (Piwik_Common::isWindows()) { // On windows, MySQL expects slashes as directory separators $filePath = str_replace('\\', '/', $filePath); } // Set up CSV delimiters, quotes, etc $delim = "\t"; $quote = '"'; $eol = "\r\n"; $null = 'NULL'; $escape = '\\\\'; $fp = fopen($filePath, 'wb'); if (!$fp) { throw new Exception('Error creating the tmp file ' . $filePath . ', please check that the webserver has write permission to write this file.'); } @chmod($filePath, 0777); foreach ($values as $row) { $output = ''; foreach ($row as $value) { if (!isset($value) || is_null($value) || $value === false) { $output .= $null . $delim; } else { $output .= $quote . self::escapeString($value) . $quote . $delim; } } // Replace delim with eol unset($row[strlen($output) - strlen($delim)]); $output .= $eol; $ret = fwrite($fp, $output); if (!$ret) { fclose($fp); unlink($filePath); throw new Exception('Error writing to the tmp file ' . $filePath . ' containing the batch INSERTs.'); } } fclose($fp); $query = "\n\t\t\t\t\t'{$filePath}'\n\t\t\t\tREPLACE\n\t\t\t\tINTO TABLE\n\t\t\t\t\t" . $tableName; // hack for charset mismatch if (!self::isDatabaseConnectionUTF8() && !isset(Zend_Registry::get('config')->database->charset)) { $query .= ' CHARACTER SET latin1'; } $query .= "\n\t\t\t\tFIELDS TERMINATED BY\n\t\t\t\t\t'" . $delim . "'\n\t\t\t\tENCLOSED BY\n\t\t\t\t\t'" . $quote . "'\n\t\t\t\tESCAPED BY\n\t\t\t\t\t'" . $escape . "'\n\t\t\t\tLINES TERMINATED BY\n\t\t\t\t\t\"" . $eol . "\"\n\t\t\t\t{$fieldList}\n\t\t\t"; // initial attempt with LOCAL keyword // note: 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 try { $result = @Piwik_Exec('LOAD DATA LOCAL INFILE' . $query); if (empty($result)) { throw new Exception("LOAD DATA LOCAL INFILE failed!"); } unlink($filePath); return true; } catch (Exception $e) { } // second attempt without LOCAL keyword if MySQL server appears to be on the same box // note: 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 $dbHost = Zend_Registry::get('config')->database->host; $localHosts = array('127.0.0.1', 'localhost', 'localhost.local', 'localhost.localdomain', 'localhost.localhost'); $hostName = @php_uname('n'); if (!empty($hostName)) { $localHosts = array_merge($localHosts, array($hostName, $hostName . '.local', $hostName . '.localdomain', $hostName . '.localhost')); } if (!empty($dbHost) && !in_array($dbHost, $localHosts)) { throw new Exception("MYSQL appears to be on a remote server"); } $result = @Piwik_Exec('LOAD DATA INFILE' . $query); if (empty($result)) { throw new Exception("LOAD DATA INFILE failed!"); } unlink($filePath); return true; } catch (Exception $e) { Piwik::log("LOAD DATA INFILE failed or not supported, falling back to normal INSERTs... Error was:" . $e->getMessage(), Piwik_Log::WARN); // if all else fails, fallback to a series of INSERTs unlink($filePath); self::tableInsertBatchIterate($tableName, $fields, $values); } return false; }
/** * Returns the idArchive we will use for the current archive * * @return int IdArchive to use when saving the current Archive */ protected function loadNextIdarchive() { $table = $this->tableArchiveNumeric->getTableName(); $dbLockName = "loadNextIdArchive.{$table}"; $db = Zend_Registry::get('db'); $locked = self::PREFIX_SQL_LOCK . Piwik_Common::generateUniqId(); $date = date("Y-m-d H:i:s"); if (Piwik_GetDbLock($dbLockName, $maxRetries = 30) === false) { throw new Exception("loadNextIdArchive: Cannot get named lock for table {$table}."); } $db->exec("INSERT INTO {$table} " . " SELECT ifnull(max(idarchive),0)+1, \n\t\t\t\t\t\t\t\t'" . $locked . "',\n\t\t\t\t\t\t\t\t" . (int) $this->idsite . ",\n\t\t\t\t\t\t\t\t'" . $date . "',\n\t\t\t\t\t\t\t\t'" . $date . "',\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t'" . $date . "',\n\t\t\t\t\t\t\t\t0 " . " FROM {$table} as tb1"); Piwik_ReleaseDbLock($dbLockName); $id = $db->fetchOne("SELECT idarchive FROM {$table} WHERE name = ? LIMIT 1", $locked); $this->idArchive = $id; }
/** * Generate nonce -- a cryptographic "number used only once", often recommended as part of a robust defense against cross-site request forgery (CSRF/XSRF). * Characteristics: limited lifetime, uniqueness, unpredictability (pseudo-randomness). * * @param string $id Unique id to avoid namespace conflicts, e.g., ModuleName.ActionName * @param int $ttl Optional time-to-live in seconds; default is 5 minutes * @return string Nonce */ public static function getNonce($id, $ttl = 300) { // the ingredients to our secret sauce? a dash of private salt and a flavorful mix of PRNGs, making it less predictable in nature, yet retaining a subtle hint of more entropy $nonce = md5(Piwik_Common::getSalt() . time() . Piwik_Common::generateUniqId()); // save session-dependent nonce $ns = new Zend_Session_Namespace($id); $ns->nonce = $nonce; $ns->setExpirationSeconds($ttl, 'nonce'); return $nonce; }