diff options
author | robocoder <anthon.pang@gmail.com> | 2009-12-14 00:25:01 +0300 |
---|---|---|
committer | robocoder <anthon.pang@gmail.com> | 2009-12-14 00:25:01 +0300 |
commit | 7b572d45aaad7a441f03d54c76faa7c641e55a77 (patch) | |
tree | 0cfcbdb32de3c0f4496edab071dd65a6072973c9 | |
parent | 4fdf12bf7e2fdaee05e47e7b95fd1c346bc549c3 (diff) |
refactor unserialize_array(); add Application version tests to SecurityInfo
git-svn-id: http://dev.piwik.org/svn/trunk@1682 59fd770c-687e-43c8-a1e3-f5a4ff64c105
-rw-r--r-- | core/Common.php | 24 | ||||
-rw-r--r-- | core/Cookie.php | 26 | ||||
-rw-r--r-- | core/UpdateCheck.php | 1 | ||||
-rw-r--r-- | plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php | 68 | ||||
-rw-r--r-- | plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php | 58 | ||||
-rw-r--r-- | plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php | 54 | ||||
-rw-r--r-- | tests/core/Common.test.php | 96 | ||||
-rw-r--r-- | tests/core/Cookie.test.php | 108 |
8 files changed, 302 insertions, 133 deletions
diff --git a/core/Common.php b/core/Common.php index aa65f54a4d..43668805fd 100644 --- a/core/Common.php +++ b/core/Common.php @@ -508,6 +508,30 @@ class Piwik_Common } /** + * Unserialize (serialized) array + * + * @param string + * @return array or original string if not unserializable + */ + public static function unserialize_array( $str ) + { + // we set the unserialized version only for arrays as you can have set a serialized string on purpose + if (preg_match('/^a:[0-9]+:{/', $str) + && !preg_match('/(^|;|{|})O:[0-9]+:"/', $str) + && strpos($str, "\0") === false) + { + if( ($arrayValue = @unserialize($str)) !== false + && is_array($arrayValue) ) + { + return $arrayValue; + } + } + + // return original string + return $str; + } + + /** * Returns a 32 characters long uniq ID * * @return string 32 chars diff --git a/core/Cookie.php b/core/Cookie.php index 4868d5d1f5..c688cf09eb 100644 --- a/core/Cookie.php +++ b/core/Cookie.php @@ -164,7 +164,7 @@ class Piwik_Cookie $varValue = base64_decode($varValue); // some of the values may be serialized array so we try to unserialize it - $varValue = self::unserialize_array($varValue); + $varValue = Piwik_Common::unserialize_array($varValue); } $this->set($varName, $varValue); @@ -258,28 +258,4 @@ class Piwik_Cookie { return Piwik_Common::sanitizeInputValues($value); } - - /** - * Unserialize (serialized) array - * - * @param string - * @return array or original string if not unserializable - */ - public static function unserialize_array( $str ) - { - // we set the unserialized version only for arrays as you can have set a serialized string on purpose - if (preg_match('/^a:[0-9]+:{/', $str) - && !preg_match('/(^|;|{|})O:[0-9]+:"/', $str) - && strpos($str, "\0") === false) - { - if( ($arrayValue = @unserialize($str)) !== false - && is_array($arrayValue) ) - { - return $arrayValue; - } - } - - // return original string - return $str; - } } diff --git a/core/UpdateCheck.php b/core/UpdateCheck.php index c5ebe07874..0c61300811 100644 --- a/core/UpdateCheck.php +++ b/core/UpdateCheck.php @@ -46,6 +46,7 @@ class Piwik_UpdateCheck Piwik_SetOption(self::LATEST_VERSION, $latestVersion); } catch(Exception $e) { // e.g., disable_functions = fsockopen; allow_url_open = Off + Piwik_SetOption(self::LATEST_VERSION, ''); } Piwik_SetOption(self::LAST_TIME_CHECKED, time(), $autoload = 1); } diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php b/plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php new file mode 100644 index 0000000000..7b80fd432a --- /dev/null +++ b/plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php @@ -0,0 +1,68 @@ +<?php +/** + * Test class for PHP Application + * + * @package PhpSecInfo + * @author Piwik + */ + +/** + * require the PhpSecInfo_Test_Application class + */ +require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Application.php'); + +/** + * Test class for PHP application + * + * Checks PHP version + * + * @package PhpSecInfo + * @author Piwik + */ +class PhpSecInfo_Test_Application_Php extends PhpSecInfo_Test_Application +{ + var $test_name = "PHP"; + + var $recommended_value = null; + + function _retrieveCurrentValue() { + $this->current_value = PHP_VERSION;; + + $url = 'http://php.net/releases/?serialize=1&version=5'; + $timeout = Piwik_UpdateCheck::SOCKET_TIMEOUT; + try { + $latestVersion = Piwik::sendHttpRequest($url, $timeout); + $versionInfo = Piwik_Common::unserialize_array($latestVersion); + $this->recommended_value = $versionInfo['version']; + } catch(Exception $e) { + $this->recommended_value = ''; + } + } + + function _execTest() { +var_dump($this->current_value); +var_dump($this->recommended_value); + if (version_compare($this->current_value, '5.2.1') < 0) { + return PHPSECINFO_TEST_RESULT_WARN; + } + + if (empty($this->recommended_value)) { + return PHPSECINFO_TEST_RESULT_ERROR; + } + + if ( $this->current_value === $this->recommended_value ) { + return PHPSECINFO_TEST_RESULT_OK; + } + + return PHPSECINFO_TEST_RESULT_NOTICE; + } + + function _setMessages() { + parent::_setMessages(); + + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "You are running PHP ".$this->recommended_value." (the latest version)."); + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', "You are running PHP ".$this->current_value.". The latest version of PHP is ".$this->recommended_value."."); + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', "You are running PHP ".$this->current_value." which is really old. We recommend running the latest (stable) version of PHP which includes numerous bug fixes and security fixes."); + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_ERROR, 'en', "Unable to determine the latest version of PHP available."); + } +} diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php b/plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php new file mode 100644 index 0000000000..eca0590756 --- /dev/null +++ b/plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php @@ -0,0 +1,58 @@ +<?php +/** + * Test class for Piwik Application + * + * @package PhpSecInfo + * @author Piwik + */ + +/** + * require the PhpSecInfo_Test_Application class + */ +require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Application.php'); + +/** + * Test class for Piwik application + * + * Checks Piwik version + * + * @package PhpSecInfo + * @author Piwik + */ +class PhpSecInfo_Test_Application_Piwik extends PhpSecInfo_Test_Application +{ + var $test_name = "Piwik"; + + var $recommended_value = null; + + function _retrieveCurrentValue() { + $this->current_value = Piwik_Version::VERSION; + + $this->recommended_value = Piwik_GetOption(Piwik_UpdateCheck::LATEST_VERSION); + } + + function _execTest() { + if (version_compare($this->current_value, '0.5') < 0) { + return PHPSECINFO_TEST_RESULT_WARN; + } + + if (empty($this->recommended_value)) { + return PHPSECINFO_TEST_RESULT_ERROR; + } + + if ( $this->current_value === $this->recommended_value ) { + return PHPSECINFO_TEST_RESULT_OK; + } + + return PHPSECINFO_TEST_RESULT_NOTICE; + } + + function _setMessages() { + parent::_setMessages(); + + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "You are running Piwik ".$this->recommended_value." (the latest version)."); + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', "You are running Piwik ".$this->current_value.". The latest version of Piwik is ".$this->recommended_value."."); + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', "You are running Piwik ".$this->current_value." which is no longer supported by the Piwik developers. We recommend running the latest (stable) version of Piwik which includes numerous enhancements, bug fixes, and security fixes."); + $this->setMessageForResult(PHPSECINFO_TEST_RESULT_ERROR, 'en', "Unable to determine the latest version of Piwik available."); + } +} diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php new file mode 100644 index 0000000000..f293c84746 --- /dev/null +++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php @@ -0,0 +1,54 @@ +<?php +/** + * Skeleton Test class file for Application group + * + * @package PhpSecInfo + * @author Anthon Pang + */ + +/** + * require the main PhpSecInfo class + */ +require_once(PHPSECINFO_BASE_DIR.'/Test/Test.php'); + + + +/** + * This is a skeleton class for PhpSecInfo "Application" tests + * @package PhpSecInfo + */ +class PhpSecInfo_Test_Application extends PhpSecInfo_Test +{ + + /** + * This value is used to group test results together. + * + * For example, all tests related to the mysql lib should be grouped under "mysql." + * + * @var string + */ + var $test_group = 'Application'; + + + /** + * "Application" tests should pretty much be always testable, so the default is just to return true + * + * @return boolean + */ + function isTestable() { + return Piwik::getTransportMethod() !== null; + } + + function getMoreInfoURL() { + $urls = array( + 'Piwik' => 'http://piwik.org/changelog', + 'PHP' => 'http://php.net/', + ); + + if ($tn = $this->getTestName()) { + return $urls[$tn]; + } else { + return false; + } + } +} diff --git a/tests/core/Common.test.php b/tests/core/Common.test.php index d16a38b43d..94de1e052e 100644 --- a/tests/core/Common.test.php +++ b/tests/core/Common.test.php @@ -7,6 +7,9 @@ if(!defined('PIWIK_CONFIG_TEST_INCLUDED')) require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php"; } +class Test_Piwik_Cookie_Mock_Class { +} + require_once 'Common.php'; class Test_Piwik_Common extends UnitTestCase { @@ -662,5 +665,98 @@ class Test_Piwik_Common extends UnitTestCase } } } + + public function testUnserializeArray() + { + $a = array('value1', 'value2'); + $as = serialize($a); + $expected = 'a:2:{i:0;s:6:"value1";i:1;s:6:"value2";}'; + $this->assertEqual( $as, $expected ); + + $ua = Piwik_Common::unserialize_array($as); + $this->assertTrue( is_array($ua) && count($ua) == 2 && $ua[0] === 'value1' && $ua[1] === 'value2' ); + + $a = 'O:31:"Test_Piwik_Cookie_Phantom_Class":0:{}'; + try { + unserialize($a); + $this->fail("Expected exception not raised"); + } catch(Exception $expected) { + echo "test: unserializing an object where class not (yet) defined<br>\n"; + } + + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + + $a = 'O:28:"Test_Piwik_Cookie_Mock_Class":0:{}'; + try { + unserialize($a); + echo "test: unserializing an object where class is defined<br>\n"; + } catch(Exception $unexpected) { + $this->fail("Unexpected exception raised"); + } + + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + + $a = 'a:1:{i:0;O:28:"Test_Piwik_Cookie_Mock_Class":0:{}}'; + try { + unserialize($a); + echo "test: unserializing nested object where class is defined<br>\n"; + } catch(Exception $unexpected) { + $this->fail("Unexpected exception raised"); + } + + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + + $a = 'a:2:{i:0;s:4:"test";i:1;O:28:"Test_Piwik_Cookie_Mock_Class":0:{}}'; + try { + unserialize($a); + echo "test: unserializing another nested object where class is defined<br>\n"; + } catch(Exception $unexpected) { + $this->fail("Unexpected exception raised"); + } + + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + + $a = 'O:28:"Test_Piwik_Cookie_Mock_Class":1:{s:34:"'."\0".'Test_Piwik_Cookie_Mock_Class'."\0".'name";s:4:"test";}'; + try { + unserialize($a); + echo "test: unserializing object with member where class is defined<br>\n"; + } catch(Exception $unexpected) { + $this->fail("Unexpected exception raised"); + } + + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + + $a = 'a:1:{s:4:"test";s:1:"'."\0".'";}'; + try { + unserialize($a); + echo "test: unserializing with leading null byte<br>\n"; + } catch(Exception $unexpected) { + $this->fail("Unexpected exception raised"); + } + + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + + $a = 'a:1:{s:4:"test";s:3:"'."a\0b".'";}'; + try { + unserialize($a); + echo "test: unserializing with leading intervening byte<br>\n"; + } catch(Exception $unexpected) { + $this->fail("Unexpected exception raised"); + } + + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + + // arrays and objects cannot be used as keys, i.e., generates "Warning: Illegal offset type ..." + $a = 'a:2:{i:0;a:0:{}O:28:"Test_Piwik_Cookie_Mock_Class":0:{}s:4:"test";'; + $ua = Piwik_Common::unserialize_array($a); + $this->assertEqual( $a, $ua ); + } } diff --git a/tests/core/Cookie.test.php b/tests/core/Cookie.test.php deleted file mode 100644 index a5b00608db..0000000000 --- a/tests/core/Cookie.test.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php -if(!defined("PIWIK_PATH_TEST_TO_ROOT")) { - define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../..'); -} -if(!defined('PIWIK_CONFIG_TEST_INCLUDED')) -{ - require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php"; -} - -class Test_Piwik_Cookie_Mock_Class { -} - -class Test_Piwik_Cookie extends UnitTestCase -{ - public function testUnserializeArray() - { - $a = array('value1', 'value2'); - $as = serialize($a); - $expected = 'a:2:{i:0;s:6:"value1";i:1;s:6:"value2";}'; - $this->assertEqual( $as, $expected ); - - $ua = Piwik_Cookie::unserialize_array($as); - $this->assertTrue( is_array($ua) && count($ua) == 2 && $ua[0] === 'value1' && $ua[1] === 'value2' ); - - $a = 'O:31:"Test_Piwik_Cookie_Phantom_Class":0:{}'; - try { - unserialize($a); - $this->fail("Expected exception not raised"); - } catch(Exception $expected) { - echo "test: unserializing an object where class not (yet) defined<br>\n"; - } - - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - - $a = 'O:28:"Test_Piwik_Cookie_Mock_Class":0:{}'; - try { - unserialize($a); - echo "test: unserializing an object where class is defined<br>\n"; - } catch(Exception $unexpected) { - $this->fail("Unexpected exception raised"); - } - - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - - $a = 'a:1:{i:0;O:28:"Test_Piwik_Cookie_Mock_Class":0:{}}'; - try { - unserialize($a); - echo "test: unserializing nested object where class is defined<br>\n"; - } catch(Exception $unexpected) { - $this->fail("Unexpected exception raised"); - } - - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - - $a = 'a:2:{i:0;s:4:"test";i:1;O:28:"Test_Piwik_Cookie_Mock_Class":0:{}}'; - try { - unserialize($a); - echo "test: unserializing another nested object where class is defined<br>\n"; - } catch(Exception $unexpected) { - $this->fail("Unexpected exception raised"); - } - - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - - $a = 'O:28:"Test_Piwik_Cookie_Mock_Class":1:{s:34:"'."\0".'Test_Piwik_Cookie_Mock_Class'."\0".'name";s:4:"test";}'; - try { - unserialize($a); - echo "test: unserializing object with member where class is defined<br>\n"; - } catch(Exception $unexpected) { - $this->fail("Unexpected exception raised"); - } - - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - - $a = 'a:1:{s:4:"test";s:1:"'."\0".'";}'; - try { - unserialize($a); - echo "test: unserializing with leading null byte<br>\n"; - } catch(Exception $unexpected) { - $this->fail("Unexpected exception raised"); - } - - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - - $a = 'a:1:{s:4:"test";s:3:"'."a\0b".'";}'; - try { - unserialize($a); - echo "test: unserializing with leading intervening byte<br>\n"; - } catch(Exception $unexpected) { - $this->fail("Unexpected exception raised"); - } - - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - - // arrays and objects cannot be used as keys, i.e., generates "Warning: Illegal offset type ..." - $a = 'a:2:{i:0;a:0:{}O:28:"Test_Piwik_Cookie_Mock_Class":0:{}s:4:"test";'; - $ua = Piwik_Cookie::unserialize_array($a); - $this->assertEqual( $a, $ua ); - } -} - |