From 9a1adda5850338b90a9884746580b2aa134fc46d Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Tue, 23 Jun 2015 15:34:19 +0200 Subject: [PATCH] MDL-49497 curl: keep api private and test it using reflection. While strictly we should not be testing private APIs, in order to get this backported to stables without changing visibility we use reflection to access to such private properties and methods. Also added one exttest to verify user agent is properly sent. Finally, fix some wrong whitespace and changed the helper class name to better alternative. --- lib/filelib.php | 4 +-- lib/tests/filelib_test.php | 62 +++++++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/lib/filelib.php b/lib/filelib.php index 423e475c7cf..6375faf4ee8 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -2683,7 +2683,7 @@ class curl { public $emulateredirects = null; /** @var array cURL options */ - protected $options; + private $options; /** @var string Proxy host */ private $proxy_host = ''; @@ -2976,7 +2976,7 @@ private function formatHeader($ch, $header) { * @param array $options * @return resource The curl handle */ - protected function apply_opt($curl, $options) { + private function apply_opt($curl, $options) { // Clean up $this->cleanopt(); // set cookie diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index f74e655f391..b32c328ea31 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -883,7 +883,7 @@ public function test_get_mimetypes_array() { * Test curl agent settings. */ public function test_curl_useragent() { - $curl = new curl_extended(); + $curl = new testable_curl(); $options = $curl->get_options(); $this->assertNotEmpty($options); @@ -910,30 +910,65 @@ public function test_curl_useragent() { $curl->unset_option('CURLOPT_USERAGENT'); $curl->call_apply_opt(); $this->assertTrue(in_array('User-Agent: MoodleBot/1.0', $curl->header)); + + // Finally, test it via exttests, to ensure the agent is sent properly. + // Matching. + $testurl = $this->getExternalTestFileUrl('/test_agent.php'); + $extcurl = new curl(); + $contents = $extcurl->get($testurl, array(), array('CURLOPT_USERAGENT' => 'AnotherUserAgent/1.2')); + $response = $extcurl->getResponse(); + $this->assertSame('200 OK', reset($response)); + $this->assertSame(0, $extcurl->get_errno()); + $this->assertSame('OK', $contents); + // Not matching. + $contents = $extcurl->get($testurl, array(), array('CURLOPT_USERAGENT' => 'NonMatchingUserAgent/1.2')); + $response = $extcurl->getResponse(); + $this->assertSame('200 OK', reset($response)); + $this->assertSame(0, $extcurl->get_errno()); + $this->assertSame('', $contents); } } /** * Test-specific class to allow easier testing of curl functions. - * - * @copyright 2015 Dave Cooper + * + * @copyright 2015 Dave Cooper * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class curl_extended extends curl { +class testable_curl extends curl { /** - * Accessor for options array. + * Accessor for private options array using reflection. + * + * @return array */ public function get_options() { - return $this->options; + // Access to private property. + $rp = new ReflectionProperty('curl', 'options'); + $rp->setAccessible(true); + return $rp->getValue($this); + } + + /** + * Setter for private options array using reflection. + * + * @param array $options + */ + public function set_options($options) { + // Access to private property. + $rp = new ReflectionProperty('curl', 'options'); + $rp->setAccessible(true); + $rp->setValue($this, $options); } /** - * Setter for options array. + * Setter for individual option. * @param string $option * @param string $value */ public function set_option($option, $value) { - $this->options[$option] = $value; + $options = $this->get_options(); + $options[$option] = $value; + $this->set_options($options); } /** @@ -941,17 +976,22 @@ public function set_option($option, $value) { * @param string $option */ public function unset_option($option) { - unset($this->options[$option]); + $options = $this->get_options(); + unset($options[$option]); + $this->set_options($options); } /** - * Wrapper to access the curl::apply_opt() function + * Wrapper to access the private curl::apply_opt() method using reflection. * * @param array $options * @return resource The curl handle */ public function call_apply_opt($options = null) { + // Access to private method. + $rm = new ReflectionMethod('curl', 'apply_opt'); + $rm->setAccessible(true); $ch = curl_init(); - return $this->apply_opt($ch, $options); + return $rm->invoke($this, $ch, $options); } }