From 5db608f43567b2fbfdfe4516e1bd289b16b2db5b Mon Sep 17 00:00:00 2001 From: jerome mouneyrac Date: Tue, 16 Feb 2010 09:04:55 +0000 Subject: [PATCH] file API MDL-20616 added support for multiple array POST parameters in the function download_file_content(). Also added unit tests. --- lib/filelib.php | 61 +++++++++++++++++++-------- lib/simpletest/testfilelib.php | 75 ++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 18 deletions(-) create mode 100644 lib/simpletest/testfilelib.php diff --git a/lib/filelib.php b/lib/filelib.php index a41c57615f3..d288a043ff2 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -797,6 +797,47 @@ function file_get_upload_error($errorcode) { return $errmessage; } +/** + * Recursive function formating an array in POST parameter + * @param array $arraydata - the array that we are going to format and add into &$data array + * @param string $currentdata - a row of the final postdata array at instant T + * when finish, it's assign to $data under this format: name[keyname][][]...[]='value' + * @param array $data - the final data array containing all POST parameters : 1 row = 1 parameter + */ +function format_array_postdata_for_curlcall($arraydata, $currentdata, &$data) { + foreach ($arraydata as $k=>$v) { + if (is_array($v)) { //the value is an array, call the function recursively + $currentdata = $currentdata.'['.urlencode($k).']'; + format_array_postdata_for_curlcall($v, $currentdata, $data); + } else { //add the POST parameter to the $data array + $data[] = $currentdata.'['.urlencode($k).']='.urlencode($v); + } + } +} + +/** + * Transform a PHP array into POST parameter + * (see the recursive function format_array_postdata_for_curlcall) + * @param array $postdata + * @return array containing all POST parameters (1 row = 1 POST parameter) + */ +function format_postdata_for_curlcall($postdata) { + $data = array(); + foreach ($postdata as $k=>$v) { + if (is_array($v)) { + $currentdata = urlencode($k); + format_array_postdata_for_curlcall($v, $currentdata, $data); + } else { + $data[] = urlencode($k).'='.urlencode($v); + } + } + $convertedpostdata = implode('&', $data); + return $convertedpostdata; +} + + + + /** * Fetches content of file from Internet (using proxy if defined). Uses cURL extension if present. * Due to security concerns only downloads from http(s) sources are supported. @@ -865,27 +906,11 @@ function download_file_content($url, $headers=null, $postdata=null, $fullrespons // use POST if requested if (is_array($postdata)) { - $data = array(); - foreach ($postdata as $k=>$v) { - if (is_array($v)) { - foreach ($v as $sk=>$sv) { - if (is_array($sv)) { - foreach ($sv as $ssk=>$ssv) { - $data[] = urlencode($k).'['.urlencode($sk).']['.urlencode($ssk).']='.urlencode($ssv); - } - } else { - $data[] = urlencode($k).'['.urlencode($sk).']='.urlencode($sv); - } - } - } else { - $data[] = urlencode($k).'='.urlencode($v); - } - } - $postdata = implode('&', $data); + $postdata = format_postdata_for_curlcall($postdata); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); } - + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connecttimeout); diff --git a/lib/simpletest/testfilelib.php b/lib/simpletest/testfilelib.php new file mode 100644 index 00000000000..8e577b38827 --- /dev/null +++ b/lib/simpletest/testfilelib.php @@ -0,0 +1,75 @@ +. + + +/** + * Unit tests for /lib/filelib.php. + * + * @package file + * @copyright 2009 Jerome Mouneyrac + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page +} +require_once($CFG->libdir . '/filelib.php'); + +class filelib_test extends UnitTestCase { + public function test_format_postdata_for_curlcall() { + + //POST params with just simple types + $postdatatoconvert =array( 'userid' => 1, 'roleid' => 22, 'name' => 'john'); + $expectedresult = "userid=1&roleid=22&name=john"; + $postdata = format_postdata_for_curlcall($postdatatoconvert); + $this->assertEqual($postdata, $expectedresult); + + //POST params with a string containing & character + $postdatatoconvert =array( 'name' => 'john&emilie', 'roleid' => 22); + $expectedresult = "name=john%26emilie&roleid=22"; //urlencode: '%26' => '&' + $postdata = format_postdata_for_curlcall($postdatatoconvert); + $this->assertEqual($postdata, $expectedresult); + + //POST params with an empty value + $postdatatoconvert =array( 'name' => null, 'roleid' => 22); + $expectedresult = "name=&roleid=22"; //urlencode: '%26' => '&' + $postdata = format_postdata_for_curlcall($postdatatoconvert); + $this->assertEqual($postdata, $expectedresult); + + //POST params with complex types + $postdatatoconvert =array( 'users' => array( + array( + 'id' => 2, + 'customfields' => array( + array + ( + 'type' => 'Color', + 'value' => 'violet' + ) + ) + ) + ) + ); + $expectedresult = "users[0][id]=2&users[0][customfields][0][type]=Color&users[0][customfields][0][value]=violet"; + $postdata = format_postdata_for_curlcall($postdatatoconvert); + $this->assertEqual($postdata, $expectedresult); + + + + + } +}