diff --git a/docs/NEWS b/docs/NEWS index d34595b3..80a31274 100644 --- a/docs/NEWS +++ b/docs/NEWS @@ -14,6 +14,10 @@ Version 2.1-beta1 (June 8th, 2016) disabled to prevent Server Side Request Forgery (SSRF). Thanks to Xu Yue for pointing this out! + * Added new API wrapper serendipity_request_url() to request URLs. + Currently uses HTTP_Request2, might change to curl or others in + the future, but irrelevant to plugins using this function. + * Removed outdated themes blue, carl_contest, kubrick and wp. They live on Spartacus now. diff --git a/include/functions.inc.php b/include/functions.inc.php index 6619ac69..7b0d8ad7 100644 --- a/include/functions.inc.php +++ b/include/functions.inc.php @@ -1120,6 +1120,114 @@ function serendipity_request_end() { return true; } +/* Request the contents of an URL, API wrapper + * @param $uri string The URL to fetch + * @param $method string HTTP method (GET/POST/PUT/OPTIONS...) + * @param $contenttype string optional HTTP content type + * @param $contenttype mixed optional extra data (i.e. POST body), can be an array + * @param $extra_options array Extra options for HTTP_Request $options array (can override defaults) + * @param $addData string possible extra event addData declaration for 'backend_http_request' hook + * @param $auth array Array with 'user' and 'pass' for HTTP Auth + * @return $content string The URL contents + */ + +function serendipity_request_url($uri, $method = 'GET', $contenttype = null, $data = null, $extra_options = null, $addData = null, $auth = null) { + global $serendipity; + + require_once S9Y_PEAR_PATH . 'HTTP/Request2.php'; + $options = array('follow_redirects' => true, 'max_redirects' => 5); + + if (is_array($extra_options)) { + foreach($extra_options AS $okey => $oval) { + $options[$okey] = $oval; + } + } + serendipity_plugin_api::hook_event('backend_http_request', $options, $addData); + serendipity_request_start(); + if (version_compare(PHP_VERSION, '5.6.0', '<')) { + // On earlier PHP versions, the certificate validation fails. We deactivate it on them to restore the functionality we had with HTTP/Request1 + $options['ssl_verify_peer'] = false; + } + + switch(strtoupper($method)) { + case 'GET': + $http_method = HTTP_Request2::METHOD_GET; + break; + + case 'PUT': + $http_method = HTTP_Request2::METHOD_PUT; + break; + + case 'OPTIONS': + $http_method = HTTP_Request2::METHOD_OPTIONS; + break; + + case 'HEAD': + $http_method = HTTP_Request2::METHOD_HEAD; + break; + + case 'DELETE': + $http_method = HTTP_Request2::METHOD_DELETE; + break; + + case 'TRACE': + $http_method = HTTP_Request2::METHOD_TRACE; + break; + + case 'CONNECT': + $http_method = HTTP_Request2::METHOD_CONNECT; + break; + + default: + case 'POST': + $http_method = HTTP_Request2::METHOD_POST; + break; + + } + + $req = new HTTP_Request2($uri, $http_method, $options); + if (isset($contenttype) && $contenttype !== null) { + $req->setHeader('Content-Type', $contenttype); + } + + if (is_array($auth)) { + $req->setAuth($auth['user'], $auth['pass']); + } + + if ($data != null) { + if (is_array($data)) { + $req->addPostParameter($data); + } else { + $req->setBody($data); + } + } + + try { + $res = $req->send(); + } catch (HTTP_Request2_Exception $e) { + serendipity_request_end(); + return false; + } + + + $fContent = $res->getBody(); + $serendipity['last_http_request'] = array( + 'responseCode' => $res->getStatus(), + 'effectiveUrl' => $res->getEffectiveUrl(), + 'reasonPhrase' => $res->getReasonPhrase(), + 'isRedirect' => $res->isRedirect(), + 'cookies' => $res->getCookies(), + 'version' => $res->getVersion(), + 'header' => $res->getHeader(), + + 'object' => $res // forward compatibility for possible other checks + ); + + serendipity_request_end(); + return $fContent; +} + + if (!function_exists('microtime_float')) { /** * Get current timestamp as microseconds