diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index 5e54e1bc889..aaa9b17657d 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -12,10 +12,28 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.3', '8.2', '8.1', '8.0', '7.4'] + php: ['8.4', '8.3', '8.2', '8.1', '8.0', '7.4'] DB: [ 'pdo/mysql', 'pdo/pgsql', 'pdo/sqlite', 'mysqli', 'pgsql', 'sqlite' ] compiler: [ default ] include: + - php: '8.4' + DB: 'pdo/mysql' + compiler: jit + - php: '8.4' + DB: 'pdo/pgsql' + compiler: jit + - php: '8.4' + DB: 'pdo/sqlite' + compiler: jit + - php: '8.4' + DB: 'mysqli' + compiler: jit + - php: '8.4' + DB: 'pgsql' + compiler: jit + - php: '8.4' + DB: 'sqlite' + compiler: jit - php: '8.3' DB: 'pdo/mysql' compiler: jit @@ -141,6 +159,6 @@ jobs: - name: PHPUnit Test run: | - php -d error_reporting=E_ALL -d zend.enable_gc=0 -d date.timezone=UTC -d mbstring.func_overload=7 -d mbstring.internal_encoding=UTF-8 vendor/bin/phpunit --coverage-text --configuration tests/travis/${{ matrix.DB }}.phpunit.xml + php -d error_reporting=E_ALL -d zend.enable_gc=0 -d date.timezone=UTC vendor/bin/phpunit --coverage-text --configuration tests/travis/${{ matrix.DB }}.phpunit.xml env: XDEBUG_MODE: coverage diff --git a/build-release.sh b/build-release.sh index ea549756050..47a4a5b2255 100755 --- a/build-release.sh +++ b/build-release.sh @@ -47,7 +47,7 @@ fi echo "Running tests ..." -php -d zend.enable_gc=0 -d date.timezone=UTC -d mbstring.func_overload=7 -d mbstring.internal_encoding=UTF-8 vendor/bin/phpunit --coverage-text --configuration tests/travis/sqlite.phpunit.xml +php -d zend.enable_gc=0 -d date.timezone=UTC -d mbstring.func_overload=7 vendor/bin/phpunit --coverage-text --configuration tests/travis/sqlite.phpunit.xml if [ $? -ne 0 ] then diff --git a/composer.json b/composer.json index 69686efb30f..13cb2af56f9 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "scripts": { "test:coverage": [ "@putenv XDEBUG_MODE=coverage", - "phpunit --color=always --coverage-text --configuration tests/travis/sqlite.phpunit.xml" + "phpunit --color=always --coverage-text --configuration tests/phpunit.xml" ], "post-install-cmd": [ "sed -i s/name{0}/name[0]/ vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStream.php" @@ -31,6 +31,6 @@ }, "require-dev": { "mikey179/vfsstream": "1.6.*", - "phpunit/phpunit": "4.* || 5.* || 9.*" + "phpunit/phpunit": "9.* || 10.* || 11.*" } } diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 2a61a32f7d2..98f0205b1d2 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -250,7 +250,7 @@ define('MB_ENABLED', TRUE); // mbstring.internal_encoding is deprecated starting with PHP 5.6 // and it's usage triggers E_DEPRECATED messages. - @ini_set('mbstring.internal_encoding', $charset); + // @ini_set('mbstring.internal_encoding', $charset); // This is required for mb_convert_encoding() to strip invalid characters. // That's utilized by CI_Utf8, but it's also done for consistency with iconv. mb_substitute_character('none'); @@ -267,18 +267,13 @@ define('ICONV_ENABLED', TRUE); // iconv.internal_encoding is deprecated starting with PHP 5.6 // and it's usage triggers E_DEPRECATED messages. - @ini_set('iconv.internal_encoding', $charset); + // @ini_set('iconv.internal_encoding', $charset); } else { define('ICONV_ENABLED', FALSE); } - if (is_php('5.6')) - { - ini_set('php.internal_encoding', $charset); - } - /* * ------------------------------------------------------ * Load compatibility features diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index 6b9ad4696a0..9129b7210d0 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -1152,21 +1152,19 @@ public function parseResponse($fp) // Create and Set Up XML Parser //------------------------------------- - $parser = xml_parser_create($this->xmlrpc_defencoding); - $pname = spl_object_id($parser); - $this->xh[$pname] = array( - 'isf' => 0, - 'ac' => '', - 'headers' => array(), - 'stack' => array(), - 'valuestack' => array(), - 'isf_reason' => 0 - ); - - xml_set_object($parser, $this); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE); - xml_set_element_handler($parser, 'open_tag', 'closing_tag'); - xml_set_character_data_handler($parser, 'character_data'); + $parser = xml_parser_create($this->xmlrpc_defencoding); + $this->xh = array( + 'isf' => 0, + 'ac' => '', + 'headers' => array(), + 'stack' => array(), + 'valuestack' => array(), + 'isf_reason' => 0 + ); + + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser, [$this, 'open_tag'], [$this, 'closing_tag']); + xml_set_character_data_handler($parser, [$this, 'character_data']); //xml_set_default_handler($parser, 'default_handler'); // Get headers @@ -1177,7 +1175,7 @@ public function parseResponse($fp) { break; } - $this->xh[$pname]['headers'][] = $line; + $this->xh['headers'][] = $line; } $data = implode("\r\n", $lines); @@ -1195,18 +1193,18 @@ public function parseResponse($fp) xml_parser_free($parser); // Got ourselves some badness, it seems - if ($this->xh[$pname]['isf'] > 1) + if ($this->xh['isf'] > 1) { if ($this->debug === TRUE) { - echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n"; + echo "---Invalid Return---\n".$this->xh['isf_reason']."---Invalid Return---\n\n"; } - return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']); + return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh['isf_reason']); } - elseif ( ! is_object($this->xh[$pname]['value'])) + elseif ( ! is_object($this->xh['value'])) { - return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']); + return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh['isf_reason']); } // Display XML content for debugging @@ -1214,10 +1212,10 @@ public function parseResponse($fp) { echo '
';
 
-			if (count($this->xh[$pname]['headers']) > 0)
+			if (count($this->xh['headers']) > 0)
 			{
 				echo "---HEADERS---\n";
-				foreach ($this->xh[$pname]['headers'] as $header)
+				foreach ($this->xh['headers'] as $header)
 				{
 					echo $header."\n";
 				}
@@ -1225,13 +1223,13 @@ public function parseResponse($fp)
 			}
 
 			echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
-			var_dump($this->xh[$pname]['value']);
+			var_dump($this->xh['value']);
 			echo "\n---END PARSED---
"; } // Send response - $v = $this->xh[$pname]['value']; - if ($this->xh[$pname]['isf']) + $v = $this->xh['value']; + if ($this->xh['isf']) { $errno_v = $v->me['struct']['faultCode']; $errstr_v = $v->me['struct']['faultString']; @@ -1250,7 +1248,7 @@ public function parseResponse($fp) $r = new XML_RPC_Response($v); } - $r->headers = $this->xh[$pname]['headers']; + $r->headers = $this->xh['headers']; return $r; } @@ -1281,26 +1279,24 @@ public function parseResponse($fp) */ public function open_tag($the_parser, $name) { - $the_parser = spl_object_id($the_parser); - // If invalid nesting, then return - if ($this->xh[$the_parser]['isf'] > 1) return; + if ($this->xh['isf'] > 1) return; // Evaluate and check for correct nesting of XML elements - if (count($this->xh[$the_parser]['stack']) === 0) + if (count($this->xh['stack']) === 0) { if ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL') { - $this->xh[$the_parser]['isf'] = 2; - $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing'; + $this->xh['isf'] = 2; + $this->xh['isf_reason'] = 'Top level XML-RPC element is missing'; return; } } // not top level element: see if parent is OK - elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE)) + elseif ( ! in_array($this->xh['stack'][0], $this->valid_parents[$name], TRUE)) { - $this->xh[$the_parser]['isf'] = 2; - $this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0]; + $this->xh['isf'] = 2; + $this->xh['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh['stack'][0]; return; } @@ -1310,22 +1306,22 @@ public function open_tag($the_parser, $name) case 'ARRAY': // Creates array for child elements $cur_val = array('value' => array(), 'type' => $name); - array_unshift($this->xh[$the_parser]['valuestack'], $cur_val); + array_unshift($this->xh['valuestack'], $cur_val); break; case 'METHODNAME': case 'NAME': - $this->xh[$the_parser]['ac'] = ''; + $this->xh['ac'] = ''; break; case 'FAULT': - $this->xh[$the_parser]['isf'] = 1; + $this->xh['isf'] = 1; break; case 'PARAM': - $this->xh[$the_parser]['value'] = NULL; + $this->xh['value'] = NULL; break; case 'VALUE': - $this->xh[$the_parser]['vt'] = 'value'; - $this->xh[$the_parser]['ac'] = ''; - $this->xh[$the_parser]['lv'] = 1; + $this->xh['vt'] = 'value'; + $this->xh['ac'] = ''; + $this->xh['lv'] = 1; break; case 'I4': case 'INT': @@ -1334,23 +1330,23 @@ public function open_tag($the_parser, $name) case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': - if ($this->xh[$the_parser]['vt'] !== 'value') + if ($this->xh['vt'] !== 'value') { //two data elements inside a value: an error occurred! - $this->xh[$the_parser]['isf'] = 2; - $this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a ' - .$this->xh[$the_parser]['vt'].' element inside a single value'; + $this->xh['isf'] = 2; + $this->xh['isf_reason'] = 'There is a '.$name.' element following a ' + .$this->xh['vt'].' element inside a single value'; return; } - $this->xh[$the_parser]['ac'] = ''; + $this->xh['ac'] = ''; break; case 'MEMBER': // Set name of to nothing to prevent errors later if no is found - $this->xh[$the_parser]['valuestack'][0]['name'] = ''; + $this->xh['valuestack'][0]['name'] = ''; // Set NULL value to check to see if value passed for this param/member - $this->xh[$the_parser]['value'] = NULL; + $this->xh['value'] = NULL; break; case 'DATA': case 'METHODCALL': @@ -1360,15 +1356,15 @@ public function open_tag($the_parser, $name) break; default: /// An Invalid Element is Found, so we have trouble - $this->xh[$the_parser]['isf'] = 2; - $this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name; + $this->xh['isf'] = 2; + $this->xh['isf_reason'] = 'Invalid XML-RPC element found: '.$name; break; } // Add current element name to stack, to allow validation of nesting - array_unshift($this->xh[$the_parser]['stack'], $name); + array_unshift($this->xh['stack'], $name); - $name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0; + $name === 'VALUE' OR $this->xh['lv'] = 0; } // -------------------------------------------------------------------- @@ -1382,27 +1378,25 @@ public function open_tag($the_parser, $name) */ public function closing_tag($the_parser, $name) { - $the_parser = spl_object_id($the_parser); - - if ($this->xh[$the_parser]['isf'] > 1) return; + if ($this->xh['isf'] > 1) return; // Remove current element from stack and set variable // NOTE: If the XML validates, then we do not have to worry about // the opening and closing of elements. Nesting is checked on the opening // tag so we be safe there as well. - $curr_elem = array_shift($this->xh[$the_parser]['stack']); + $curr_elem = array_shift($this->xh['stack']); switch ($name) { case 'STRUCT': case 'ARRAY': - $cur_val = array_shift($this->xh[$the_parser]['valuestack']); - $this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array(); - $this->xh[$the_parser]['vt'] = strtolower($name); + $cur_val = array_shift($this->xh['valuestack']); + $this->xh['value'] = isset($cur_val['values']) ? $cur_val['values'] : array(); + $this->xh['vt'] = strtolower($name); break; case 'NAME': - $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac']; + $this->xh['valuestack'][0]['name'] = $this->xh['ac']; break; case 'BOOLEAN': case 'I4': @@ -1411,87 +1405,87 @@ public function closing_tag($the_parser, $name) case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': - $this->xh[$the_parser]['vt'] = strtolower($name); + $this->xh['vt'] = strtolower($name); if ($name === 'STRING') { - $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; + $this->xh['value'] = $this->xh['ac']; } elseif ($name === 'DATETIME.ISO8601') { - $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime; - $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; + $this->xh['vt'] = $this->xmlrpcDateTime; + $this->xh['value'] = $this->xh['ac']; } elseif ($name === 'BASE64') { - $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']); + $this->xh['value'] = base64_decode($this->xh['ac']); } elseif ($name === 'BOOLEAN') { // Translated BOOLEAN values to TRUE AND FALSE - $this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac']; + $this->xh['value'] = (bool) $this->xh['ac']; } elseif ($name=='DOUBLE') { // we have a DOUBLE // we must check that only 0123456789-. are characters here - $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac']) - ? (float) $this->xh[$the_parser]['ac'] + $this->xh['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh['ac']) + ? (float) $this->xh['ac'] : 'ERROR_NON_NUMERIC_FOUND'; } else { // we have an I4/INT // we must check that only 0123456789- are characters here - $this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac']) - ? (int) $this->xh[$the_parser]['ac'] + $this->xh['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh['ac']) + ? (int) $this->xh['ac'] : 'ERROR_NON_NUMERIC_FOUND'; } - $this->xh[$the_parser]['ac'] = ''; - $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value + $this->xh['ac'] = ''; + $this->xh['lv'] = 3; // indicate we've found a value break; case 'VALUE': // This if() detects if no scalar was inside - if ($this->xh[$the_parser]['vt'] == 'value') + if ($this->xh['vt'] == 'value') { - $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac']; - $this->xh[$the_parser]['vt'] = $this->xmlrpcString; + $this->xh['value'] = $this->xh['ac']; + $this->xh['vt'] = $this->xmlrpcString; } // build the XML-RPC value out of the data received, and substitute it - $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']); + $temp = new XML_RPC_Values($this->xh['value'], $this->xh['vt']); - if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY') + if (count($this->xh['valuestack']) && $this->xh['valuestack'][0]['type'] === 'ARRAY') { // Array - $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp; + $this->xh['valuestack'][0]['values'][] = $temp; } else { // Struct - $this->xh[$the_parser]['value'] = $temp; + $this->xh['value'] = $temp; } break; case 'MEMBER': - $this->xh[$the_parser]['ac'] = ''; + $this->xh['ac'] = ''; // If value add to array in the stack for the last element built - if ($this->xh[$the_parser]['value']) + if ($this->xh['value']) { - $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value']; + $this->xh['valuestack'][0]['values'][$this->xh['valuestack'][0]['name']] = $this->xh['value']; } break; case 'DATA': - $this->xh[$the_parser]['ac'] = ''; + $this->xh['ac'] = ''; break; case 'PARAM': - if ($this->xh[$the_parser]['value']) + if ($this->xh['value']) { - $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value']; + $this->xh['params'][] = $this->xh['value']; } break; case 'METHODNAME': - $this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']); + $this->xh['method'] = ltrim($this->xh['ac']); break; case 'PARAMS': case 'FAULT': @@ -1516,24 +1510,22 @@ public function closing_tag($the_parser, $name) */ public function character_data($the_parser, $data) { - $the_parser = spl_object_id($the_parser); - - if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already + if ($this->xh['isf'] > 1) return; // XML Fault found already // If a value has not been found - if ($this->xh[$the_parser]['lv'] !== 3) + if ($this->xh['lv'] !== 3) { - if ($this->xh[$the_parser]['lv'] === 1) + if ($this->xh['lv'] === 1) { - $this->xh[$the_parser]['lv'] = 2; // Found a value + $this->xh['lv'] = 2; // Found a value } - if ( ! isset($this->xh[$the_parser]['ac'])) + if ( ! isset($this->xh['ac'])) { - $this->xh[$the_parser]['ac'] = ''; + $this->xh['ac'] = ''; } - $this->xh[$the_parser]['ac'] .= $data; + $this->xh['ac'] .= $data; } } diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php index eb5a24c4917..ed28721f551 100644 --- a/system/libraries/Xmlrpcs.php +++ b/system/libraries/Xmlrpcs.php @@ -232,23 +232,22 @@ public function parseRequest($data = '') // Set up XML Parser //------------------------------------- - $parser = xml_parser_create($this->xmlrpc_defencoding); - $parser_object = new XML_RPC_Message('filler'); - $pname = (string) $parser; - - $parser_object->xh[$pname] = array( - 'isf' => 0, - 'isf_reason' => '', - 'params' => array(), - 'stack' => array(), - 'valuestack' => array(), - 'method' => '' - ); + $parser = xml_parser_create($this->xmlrpc_defencoding); + $parser_object = new XML_RPC_Message('default_method', FALSE); + + $parser_object->xh = array( + 'isf' => 0, + 'isf_reason' => '', + 'params' => array(), + 'stack' => array(), + 'valuestack' => array(), + 'method' => '' + ); + + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser, [$parser_object, 'open_tag'], [$parser_object, 'closing_tag']); + xml_set_character_data_handler($parser, [$parser_object, 'character_data']); - xml_set_object($parser, $parser_object); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE); - xml_set_element_handler($parser, 'open_tag', 'closing_tag'); - xml_set_character_data_handler($parser, 'character_data'); //xml_set_default_handler($parser, 'default_handler'); //------------------------------------- @@ -265,7 +264,7 @@ public function parseRequest($data = '') xml_get_current_line_number($parser))); xml_parser_free($parser); } - elseif ($parser_object->xh[$pname]['isf']) + elseif ($parser_object->xh['isf']) { return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']); } @@ -273,17 +272,17 @@ public function parseRequest($data = '') { xml_parser_free($parser); - $m = new XML_RPC_Message($parser_object->xh[$pname]['method']); + $m = new XML_RPC_Message($parser_object->xh['method']); $plist = ''; - for ($i = 0, $c = count($parser_object->xh[$pname]['params']); $i < $c; $i++) + for ($i = 0, $c = count($parser_object->xh['params']); $i < $c; $i++) { if ($this->debug === TRUE) { - $plist .= $i.' - '.print_r(get_object_vars($parser_object->xh[$pname]['params'][$i]), TRUE).";\n"; + $plist .= $i.' - '.print_r(get_object_vars($parser_object->xh['params'][$i]), TRUE).";\n"; } - $m->addParam($parser_object->xh[$pname]['params'][$i]); + $m->addParam($parser_object->xh['params'][$i]); } if ($this->debug === TRUE) diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 10a21f3255d..e1a15456ee0 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -45,7 +45,7 @@ class_alias('org\bovigo\vfs\vfsStreamWrapper', 'vfsStreamWrapper'); if (extension_loaded('mbstring')) { defined('MB_ENABLED') OR define('MB_ENABLED', TRUE); - @ini_set('mbstring.internal_encoding', 'UTF-8'); +// @ini_set('mbstring.internal_encoding', 'UTF-8'); mb_substitute_character('none'); } else @@ -56,15 +56,13 @@ class_alias('org\bovigo\vfs\vfsStreamWrapper', 'vfsStreamWrapper'); if (extension_loaded('iconv')) { defined('ICONV_ENABLED') OR define('ICONV_ENABLED', TRUE); - @ini_set('iconv.internal_encoding', 'UTF-8'); + //@ini_set('iconv.internal_encoding', 'UTF-8'); } else { defined('ICONV_ENABLED') OR define('ICONV_ENABLED', FALSE); } -is_php('5.6') && ini_set('php.internal_encoding', 'UTF-8'); - if (is_php('7.0')) { $test_case_code = file_get_contents(PROJECT_BASE.'vendor/phpunit/phpunit/src/Framework/TestCase.php'); diff --git a/tests/codeigniter/libraries/Xmlrpc_test.php b/tests/codeigniter/libraries/Xmlrpc_test.php new file mode 100644 index 00000000000..66b1f8e11da --- /dev/null +++ b/tests/codeigniter/libraries/Xmlrpc_test.php @@ -0,0 +1,133 @@ +input = new CI_Input($security); + $utf8 = new Mock_Core_Utf8(); + $security = new Mock_Core_Security(); + $this->input = new Mock_Core_Input($security, $utf8); + + $this->input_lib_raw_stream = new ReflectionProperty($this->input, '_raw_input_stream'); + $this->input_lib_raw_stream->setAccessible(TRUE); + + $this->ci_instance_var('input', $this->input); + $this->ci_instance_var('security', $security); + } + + // -------------------------------------------------------------------- + + public function test_xmlrpc_client() + { + $xmlrpc = new Mock_Libraries_Xmlrpc(); + $xmlrpc->server('http://rpc.test/'); + $xmlrpc->method('testcontroller.test'); + + $request = array('My Blog', 'http://www.myrpc.com/test/'); + $message = 'test'.time(); + $xml_response = $this->xml_response($message); + $xmlrpc->client->mock_response = "HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\nContent-Length: ".strlen($xml_response)."\r\n\r\n$xml_response"; + + // Perform in the same request multiple calls + for ($attempt = 1; $attempt <= 2; $attempt++) + { + $xmlrpc->request($request); + + $this->assertTrue($xmlrpc->send_request()); + + $response = $xmlrpc->display_response(); + + $this->assertEquals('theuser', $response['name']); + $this->assertEquals(123435, $response['member_id']); + $this->assertEquals($message, $response['request']); + } + } + + // -------------------------------------------------------------------- + + public function test_xmlrpc_server() + { + $xmlrpcs = new Mock_Libraries_Xmlrpcs(); + + $config['functions']['Testmethod'] = array('function' => __CLASS__.'.mock_method_new_entry'); + $config['object'] = $this; + + $xmlrpcs->initialize($config); + + $_SERVER['REQUEST_METHOD'] = 'POST'; + $this->input_lib_raw_stream->setValue($this->input, $this->xml_request()); + + $xmlrpcs->serve(); + + $this->assertEquals('Test', $this->method_param); + } + + // -------------------------------------------------------------------- + + /** + * @param XML_RPC_Message $param + */ + public function mock_method_new_entry($param) + { + $this->method_param = $param->params[0]->scalarval(); + + return new XML_RPC_Response(new XML_RPC_Values(true, 'boolean')); + } + + // -------------------------------------------------------------------- + + private function xml_response($message) + { + return ' + + + + + + +name + +theuser + + + +member_id + +123435 + + + +request + +'.$message.' + + + + + +'; + } + + // -------------------------------------------------------------------- + + public function xml_request() + { + return ' + +Testmethod + + + +Test + + + +'; + } +} diff --git a/tests/mocks/autoloader.php b/tests/mocks/autoloader.php index 9360a2b34bb..3e6b0b60432 100644 --- a/tests/mocks/autoloader.php +++ b/tests/mocks/autoloader.php @@ -53,6 +53,7 @@ function autoload($class) 'Upload', 'User_agent', 'Xmlrpc', + 'Xmlrpcs', 'Zip' ); diff --git a/tests/mocks/libraries/xmlrpc.php b/tests/mocks/libraries/xmlrpc.php new file mode 100644 index 00000000000..32f5f3765d5 --- /dev/null +++ b/tests/mocks/libraries/xmlrpc.php @@ -0,0 +1,33 @@ +client = new Mock_Libraries_XML_RPC_Client('/', $url, $port, $proxy, $proxy_port); + } +} + +class Mock_Libraries_XML_RPC_Client extends XML_RPC_Client { + public $mock_response = ''; + + /** + * @param XML_RPC_Message $msg + */ + public function sendPayload($msg) + { + if (empty($msg->payload)) + { + $msg->createPayload(); + } + + $fp = fopen('php://memory', 'rw+'); + fwrite($fp, $this->mock_response); + fseek($fp, 0); + + $parsed = $msg->parseResponse($fp); + fclose($fp); + + return $parsed; + } +} + diff --git a/tests/mocks/libraries/xmlrpcs.php b/tests/mocks/libraries/xmlrpcs.php new file mode 100644 index 00000000000..35f5b13090b --- /dev/null +++ b/tests/mocks/libraries/xmlrpcs.php @@ -0,0 +1,50 @@ +parseRequest(); + + if (isset($r->method_name) && isset($this->config['functions'][$r->method_name])) { + $callback = $this->config['functions'][$r->method_name]['function']; + if (is_callable($callback)) { + call_user_func($callback, $r->parameters); + } else { + throw new Exception('Invalid callback: ' . $callback); + } + } + + $payload = 'xmlrpc_defencoding . '"?>' . "\n" . + $this->debug_msg . $r->prepare_response(); + + $this->mock_payload = "HTTP/1.1 200 OK\r\n"; + $this->mock_payload .= "Content-Type: text/xml\r\n"; + $this->mock_payload .= 'Content-Length: ' . strlen($payload) . "\r\n"; + $this->mock_payload .= "\r\n"; + $this->mock_payload .= $payload; + } + + /** + * Mock XML request (example) + */ + public function xml_request() + { + // Return a mock XML request + return ' + + Testmethod + + + + Test + + + + '; + } +} diff --git a/tests/phpunit.xml b/tests/phpunit.xml index a1626ce91ad..e44da492f38 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -1,25 +1,15 @@ - - - - - ./codeigniter/core - ./codeigniter/helpers - ./codeigniter/libraries - - - - - ../system/ - - + + + + ../system/ + + + + + ./codeigniter/core + ./codeigniter/helpers + ./codeigniter/libraries + + diff --git a/tests/travis/sqlite.phpunit.xml b/tests/travis/sqlite.phpunit.xml index 4eaafc19fdf..6d2409cfd0d 100644 --- a/tests/travis/sqlite.phpunit.xml +++ b/tests/travis/sqlite.phpunit.xml @@ -9,7 +9,7 @@ stopOnIncomplete="false" stopOnSkipped="false" beStrictAboutTestsThatDoNotTestAnything="false" - xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd" >