function test_saveTranslation() { $path = Piwik_TranslationWriter::getTranslationPath('en', 'tmp'); $translations = array('General_Locale' => 'en_CA.UTF-8', 'General_Id' => 'Id', 'Goals_Goals' => 'Goals', 'Plugin_Body' => "Message\nBody"); @unlink($path); $rc = Piwik_TranslationWriter::saveTranslation($translations, $path); $this->assertTrue($rc !== false); $contents = file_get_contents($path); $expected = "<?php\n\$translations = array(\n\t'General_Locale' => 'en_CA.UTF-8',\n\t'General_Id' => 'Id',\n\t'Goals_Goals' => 'Goals',\n\n\t// FOR REVIEW\n\t'Plugin_Body' => 'Message\nBody',\n);\n"; if (Piwik_Common::isWindows()) { $expected = str_replace("\r\n", "\n", $expected); } $this->assertEqual($contents, $expected); }
/** * Logs a couple visits for Aug 9, Aug 10, Aug 11 of 2012. */ protected function trackVisits() { //FIXMETODO return; $pwd = Zend_Registry::get('config')->superuser->password; if (strlen($pwd) != 32) { $pwd = md5($pwd); } $token_auth = Piwik_UsersManager_API::getInstance()->getTokenAuth(Zend_Registry::get('config')->superuser->login, $pwd); $python = Piwik_Common::isWindows() ? "C:\\Python27\\python.exe" : 'python'; $cmd = $python . ' "' . PIWIK_INCLUDE_PATH . '/misc/log-analytics/import_logs.py" ' . '--url="' . $this->getRootUrl() . 'tests/PHPUnit/proxy/" ' . '--idsite=' . $this->idSite . ' ' . '--token-auth="' . $token_auth . '" ' . '--recorders=4 ' . '--enable-http-errors ' . '--enable-http-redirects ' . '--enable-static ' . '--enable-bots "' . PIWIK_INCLUDE_PATH . '/tests/resources/fake_logs.log" ' . '2>&1'; echo $cmd; exec($cmd, $output, $result); if ($result !== 0) { echo "<pre>command: {$cmd}\nresult: {$result}\noutput: " . implode("\n", $output) . "</pre>"; throw new Exception("log importer failed"); } }
* @version $Id: IP.php 4754 2011-05-22 05:07:24Z vipsoft $ * * @category Piwik * @package Piwik */ if(Piwik_Common::isWindows() || !function_exists('inet_ntop')) { function _inet_ntop($in_addr) { return php_compat_inet_ntop($in_addr); } } else { function _inet_ntop($in_addr) { return inet_ntop($in_addr); } } if(Piwik_Common::isWindows() || !function_exists('inet_pton')) { function _inet_pton($address) { return php_compat_inet_pton($address); } } else { function _inet_pton($address) { return inet_pton($address); } } /** * Handling IP addresses (both IPv4 and IPv6). * * As of Piwik 1.3, IP addresses are stored in the DB has VARBINARY(16), * and passed around in network address format which has the advantage of * being in big-endian byte order, allowing for binary-safe string
/** * 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, $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) { return @readfile($filename, $useIncludePath, $context); } // when in doubt (or when readfile() function is disabled) $handle = @fopen($filename, Piwik_Common::isWindows() ? "rb" : "r"); if ($handle) { while (!feof($handle)) { echo fread($handle, 8192); ob_flush(); flush(); } fclose($handle); return $count; } return false; }
function test_svnEolStyle() { if (Piwik_Common::isWindows()) { // SVN native does not make this work on windows return; } foreach (Piwik::globr(PIWIK_DOCUMENT_ROOT, '*') as $file) { // skip files in these folders if (strpos($file, '/.svn/') !== false || strpos($file, '/documentation/') !== false || strpos($file, '/tests/') !== false || strpos($file, '/tmp/') !== false) { continue; } // skip files with these file extensions if (preg_match('/\\.(bmp|fdf|gif|deflate|gz|ico|jar|jpg|p12|pdf|png|rar|swf|vsd|z|zip|ttf)$/', $file)) { continue; } if (!is_dir($file)) { $contents = file_get_contents($file); // expect CRLF if (preg_match('/\\.(bat|ps1)$/', $file)) { $contents = str_replace("\r\n", '', $contents); $this->assertTrue(strpos($contents, "\n") === false, $file); } else { // expect native $this->assertTrue(strpos($contents, "\r\n") === false, $file); } } } }
/** * Get system information */ public static function getSystemInformation() { global $piwik_minimumPHPVersion; $minimumMemoryLimit = Zend_Registry::get('config')->General->minimum_memory_limit; $infos = array(); $infos['general_infos'] = array(); $infos['directories'] = Piwik::checkDirectoriesWritable(); $infos['can_auto_update'] = Piwik::canAutoUpdate(); if(Piwik_Common::isIIS()) { Piwik::createWebConfigFiles(); } else { Piwik::createHtAccessFiles(); } Piwik::createWebRootFiles(); $infos['phpVersion_minimum'] = $piwik_minimumPHPVersion; $infos['phpVersion'] = PHP_VERSION; $infos['phpVersion_ok'] = version_compare( $piwik_minimumPHPVersion, $infos['phpVersion']) === -1; // critical errors $extensions = @get_loaded_extensions(); $needed_extensions = array( 'zlib', 'SPL', 'iconv', 'Reflection', ); $infos['needed_extensions'] = $needed_extensions; $infos['missing_extensions'] = array(); foreach($needed_extensions as $needed_extension) { if(!in_array($needed_extension, $extensions)) { $infos['missing_extensions'][] = $needed_extension; } } $infos['pdo_ok'] = false; if(in_array('PDO', $extensions)) { $infos['pdo_ok'] = true; } $infos['adapters'] = Piwik_Db_Adapter::getAdapters(); $needed_functions = array( 'debug_backtrace', 'create_function', 'eval', 'gzcompress', 'gzuncompress', 'pack', ); $infos['needed_functions'] = $needed_functions; $infos['missing_functions'] = array(); foreach($needed_functions as $needed_function) { if(!self::functionExists($needed_function)) { $infos['missing_functions'][] = $needed_function; } } // warnings $desired_extensions = array( 'json', 'libxml', 'dom', 'SimpleXML', ); $infos['desired_extensions'] = $desired_extensions; $infos['missing_desired_extensions'] = array(); foreach($desired_extensions as $desired_extension) { if(!in_array($desired_extension, $extensions)) { $infos['missing_desired_extensions'][] = $desired_extension; } } $desired_functions = array( 'set_time_limit', 'mail', 'parse_ini_file', 'glob', ); $infos['desired_functions'] = $desired_functions; $infos['missing_desired_functions'] = array(); foreach($desired_functions as $desired_function) { if(!self::functionExists($desired_function)) { $infos['missing_desired_functions'][] = $desired_function; } } $infos['openurl'] = Piwik_Http::getTransportMethod(); $infos['gd_ok'] = false; if (in_array('gd', $extensions)) { $gdInfo = gd_info(); $infos['gd_version'] = $gdInfo['GD Version']; preg_match('/([0-9]{1})/', $gdInfo['GD Version'], $gdVersion); if($gdVersion[0] >= 2) { $infos['gd_ok'] = true; } } $infos['hasMbstring'] = false; $infos['multibyte_ok'] = true; if(function_exists('mb_internal_encoding')) { $infos['hasMbstring'] = true; if (((int) ini_get('mbstring.func_overload')) != 0) { $infos['multibyte_ok'] = false; } } $serverSoftware = isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : ''; $infos['serverVersion'] = addslashes($serverSoftware); $infos['serverOs'] = @php_uname(); $infos['serverTime'] = date('H:i:s'); $infos['registerGlobals_ok'] = ini_get('register_globals') == 0; $infos['memoryMinimum'] = $minimumMemoryLimit; $infos['memory_ok'] = true; $infos['memoryCurrent'] = ''; $raised = Piwik::raiseMemoryLimitIfNecessary(); if(($memoryValue = Piwik::getMemoryLimitValue()) > 0) { $infos['memoryCurrent'] = $memoryValue.'M'; $infos['memory_ok'] = $memoryValue >= $minimumMemoryLimit; } $infos['isWindows'] = Piwik_Common::isWindows(); $integrityInfo = Piwik::getFileIntegrityInformation(); $infos['integrity'] = $integrityInfo[0]; $infos['integrityErrorMessages'] = array(); if(isset($integrityInfo[1])) { if($infos['integrity'] == false) { $infos['integrityErrorMessages'][] = '<b>'.Piwik_Translate('General_FileIntegrityWarningExplanation').'</b>'; } $infos['integrityErrorMessages'] = array_merge($infos['integrityErrorMessages'], array_slice($integrityInfo, 1)); } $infos['timezone'] = Piwik::isTimezoneSupportEnabled(); $infos['tracker_status'] = Piwik_Common::getRequestVar('trackerStatus', 0, 'int'); $infos['protocol'] = Piwik_ProxyHeaders::getProtocolInformation(); if(Piwik_Url::getCurrentScheme() == 'http' && $infos['protocol'] !== null) { $infos['general_infos']['secure_protocol'] = '1'; } if(count($headers = Piwik_ProxyHeaders::getProxyClientHeaders()) > 0) { $infos['general_infos']['proxy_client_headers'] = $headers; } if(count($headers = Piwik_ProxyHeaders::getProxyHostHeaders()) > 0) { $infos['general_infos']['proxy_host_headers'] = $headers; } return $infos; }
/** * 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) * @return bool True if successful; false otherwise */ public static function createTableFromCSVFile($tableName, $fields, $filePath, $fileSpec) { // On Windows, MySQL expects forward slashes as directory separators if (Piwik_Common::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'; } foreach ($keywords as $keyword) { try { $sql = 'LOAD DATA ' . $keyword . ' INFILE ' . $query; $result = @Piwik_Exec($sql); if (empty($result) || $result < 0) { continue; } return true; } catch (Exception $e) { if (!Zend_Registry::get('db')->isErrNo($e, '1148')) { Piwik::log("LOAD DATA INFILE failed... Error was:" . $e->getMessage()); } } } return false; }
/** * Checks that "HTTP/1.0 505 Internal server error" is returned when Piwik::serveStaticFile is called with a * non-readable file */ public function test_nonReadableFile() { /** * This test would fail on a windows environment because it is not possible to remove reading rights on a * windows file using PHP. */ if (Piwik_Common::isWindows()) { return; } // Setting mode so the testing file is non-readable chmod(TEST_FILE_LOCATION, 0200); $curlHandle = curl_init(); curl_setopt($curlHandle, CURLOPT_URL, $url = $this->getTestFileSrvModeUrl()); curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); curl_exec($curlHandle); $responseInfo = curl_getinfo($curlHandle); curl_close($curlHandle); // Restoring file mode chmod(TEST_FILE_LOCATION, 0644); $this->assertEqual($responseInfo["http_code"], 505); }
/** * 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; }
/** * @group Core * @group IP * @dataProvider getInetPtonTestData */ public function testPhpCompatInetPton($k, $v) { $this->assertEquals($v, bin2hex(php_compat_inet_pton($k))); if (!Piwik_Common::isWindows()) { $this->assertEquals($v, bin2hex(@inet_pton($k))); } }
function test_php_compat_inet_pton() { $adds = array('127.0.0.1' => '7f000001', '192.232.131.222' => 'c0e883de', '255.0.0.0' => 'ff000000', '255.255.255.255' => 'ffffffff', '::' => '00000000000000000000000000000000', '::0' => '00000000000000000000000000000000', '0::' => '00000000000000000000000000000000', '0::0' => '00000000000000000000000000000000', '::1' => '00000000000000000000000000000001', '2001:260:0:10::1' => '20010260000000100000000000000001', '2001:5c0:1000:b::90f8' => '200105c01000000b00000000000090f8', 'fe80::200:4cff:fe43:172f' => 'fe8000000000000002004cfffe43172f', '::ffff:127.0.0.1' => '00000000000000000000ffff7f000001', '::127.0.0.1' => '0000000000000000000000007f000001', '00000::' => '00000000000000000000000000000000', '1:2:3:4:5:ffff:127.0.0.1' => '00010002000300040005ffff7f000001', null => false, false => false, true => false, '' => false, '0' => false, '07.07.07.07' => false, '1.' => false, '.1' => false, '1.1' => false, '.1.1.' => false, '1.1.1.' => false, '.1.1.1' => false, '1.2.3.4.' => false, '.1.2.3.4' => false, '1.2.3.256' => false, 'a.b.c.d' => false, '::1::' => false, '1:2:3:4:::5:6' => false, '1:2:3:4:5:6:' => false, ':1:2:3:4:5:6' => false, '1:2:3:4:5:6:7:' => false, ':1:2:3:4:5:6:7' => false, '::11111:0' => false, '::g' => false, '::ffff:127.00.0.1' => false, '::ffff:127.0.0.01' => false, '::ffff:256.0.0.1' => false, '::ffff:1.256.0.1' => false, '::ffff:65536.0.0.1' => false, '::ffff:256.65536.0.1' => false, '::ffff:65536.65536.0.1' => false, '::ffff:7f01:0.1' => false, 'ffff:127.0.0.1:ffff::' => false); foreach ($adds as $k => $v) { $this->assertEqual(bin2hex(php_compat_inet_pton($k)), $v, $k); if (!Piwik_Common::isWindows() && !Piwik_Common::isMacOS()) { $this->assertEqual(bin2hex(@inet_pton($k)), $v, $k); } } }
/** * Is the URL on the same host and in the same script path? * * @param string $url * @return bool True if local; false otherwise. */ public static function isLocalUrl($url) { // handle case-sensitivity differences $pathContains = Piwik_Common::isWindows() ? 'stripos' : 'strpos'; // test the scheme/protocol portion of the reconstructed "current" URL if (!strncasecmp($url, 'http://', 7) || !strncasecmp($url, 'https://', 8)) { // determine the offset to begin the comparison $offset = strpos($url, '://'); $current = strstr(self::getCurrentUrlWithoutFileName(), '://'); if ($pathContains($url, $current, $offset) === $offset) { return true; } } return false; }
protected static function executeLogImporter($logFile, $options) { $python = Piwik_Common::isWindows() ? "C:\\Python27\\python.exe" : 'python'; // create the command $cmd = $python . ' "' . PIWIK_INCLUDE_PATH . '/misc/log-analytics/import_logs.py" ' . '--url="' . self::getRootUrl() . 'tests/PHPUnit/proxy/" '; foreach ($options as $name => $value) { $cmd .= $name; if ($value !== false) { $cmd .= '="' . $value . '"'; } $cmd .= ' '; } $cmd .= '"' . $logFile . '" 2>&1'; // run the command exec($cmd, $output, $result); if ($result !== 0) { throw new Exception("log importer failed: " . implode("\n", $output)); } return $output; }