/core/model/modx/rest/modrestcurlclient.class.php
PHP | 279 lines | 145 code | 25 blank | 109 comment | 30 complexity | ce66a42a8051c3d672b220a3e2b3504b MD5 | raw file
- <?php
- /**
- * @package modx
- * @subpackage rest
- */
- require_once dirname(__FILE__) . '/modrestclient.class.php';
- /**
- * Handles REST requests through a cURL-based client
- * @package modx
- * @subpackage rest
- */
- class modRestCurlClient extends modRestClient {
- /**
- * @param modX $modx A reference to the modX object
- * @param array $config An array of configuration options
- */
- function __construct(modX &$modx,array $config = array()) {
- parent::__construct($modx, $config);
- $this->config = array_merge(array(
- ),$this->config);
- }
- /**
- * Extends modRestClient::request to provide cURL specific request handling
- *
- * @param string $host The host of the REST server.
- * @param string $path The path to request to on the REST server.
- * @param string $method The HTTP method to use for the request. May be GET,
- * PUT or POST.
- * @param array $params An array of parameters to send with the request.
- * @param array $options An array of options to pass to the request.
- * @return modRestResponse The response object.
- */
- public function request($host,$path,$method = 'GET',array $params = array(),array $options = array()) {
- /* start our cURL connection */
- $ch = curl_init();
- /* setup request */
- $this->setUrl($ch,$host,$path,$method,$params,$options);
- $this->setAuth($ch,$options);
- $this->setProxy($ch,$options);
- $this->setOptions($ch,$options);
- /* execute request */
- $result = trim(curl_exec($ch));
-
- /* make sure to close connection */
- curl_close($ch);
- return $result;
- }
- /**
- * Configure and set the URL to use, along with any request parameters.
- *
- * @param resource $ch The cURL connection resource
- * @param string $host The host to send the request to
- * @param string $path The path of the request
- * @param string $method The method of the request (GET/POST)
- * @param array $params An array of request parameters to attach to the URL
- * @param array $options An array of options when setting the URL
- * @return boolean Whether or not the URL was set
- * @see modRestClient::request for parameter documentation.
- */
- public function setUrl($ch,$host,$path,$method = 'GET',array $params = array(),array $options = array()) {
- $q = http_build_query($params);
- switch ($method) {
- case 'GET':
- $path .= '?'.$q;
- break;
- case 'POST':
- curl_setopt($ch,CURLOPT_POST,1);
- $contentType = $this->modx->getOption('contentType',$options,'xml');
- switch ($contentType) {
- case 'json':
- $json = $this->modx->toJSON($params);
- curl_setopt($ch,CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
- curl_setopt($ch,CURLOPT_POSTFIELDS,$json);
- break;
- case 'xml':
- curl_setopt($ch,CURLOPT_HTTPHEADER, array('Content-Type: application/xml'));
- $xml = modRestArrayToXML::toXML($params,!empty($options['rootNode']) ? $options['rootNode'] : 'request');
- curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
- break;
- default:
- curl_setopt($ch,CURLOPT_POSTFIELDS,$params);
- break;
- }
- break;
- }
- /* prevent invalid xhtml ampersands in request path */
- $url = str_replace('&', '&', $host.$path);
- return curl_setopt($ch, CURLOPT_URL,$url);
- }
- /**
- * Set up cURL-specific options
- *
- * @param resource $ch The cURL connection resource
- * @param array $options An array of options
- */
- public function setOptions($ch,array $options = array()) {
- /* always return us the result */
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- /* we dont want header gruft */
- curl_setopt($ch, CURLOPT_HEADER, 0);
- /* default timeout to 30 seconds */
- curl_setopt($ch, CURLOPT_TIMEOUT,$this->config[modRestClient::OPT_TIMEOUT]);
- /* disable verifypeer since it's not helpful on most environments */
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
- /* send a useragent to allow proper responses */
- curl_setopt($ch, CURLOPT_USERAGENT,$this->config[modRestCurlClient::OPT_USERAGENT]);
- /* can only use follow location if safe_mode and open_basedir are off */
- $safeMode = ini_get('safe_mode');
- $openBasedir = ini_get('open_basedir');
- if (empty($safeMode) && empty($openBasedir)) {
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
- }
- }
- /**
- * Set up authentication configuration , if specified, to be used with REST request.
- *
- * @param resource $ch The cURL connection resource.
- * @param array $options An array of options
- * @return boolean True if authentication was used.
- */
- public function setAuth($ch,array $options = array()) {
- $auth = false;
- if (!empty($options[modRestClient::OPT_USERPWD])) {
- $options[modRestClient::OPT_AUTHTYPE] = $this->modx->getOption(modRestClient::OPT_AUTHTYPE,$options,'BASIC');
- switch ($options[modRestClient::OPT_AUTHTYPE]) {
- case 'ANY': curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); break;
- case 'ANYSAFE': curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); break;
- case 'DIGEST': curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); break;
- case 'GSSNEGOTIATE': curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE); break;
- case 'NTLM': curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM); break;
- default: case 'BASIC': curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); break;
- }
- $auth = curl_setopt($ch, CURLOPT_USERPWD, !empty($options[modRestClient::OPT_USERPWD]) ? $options[modRestClient::OPT_USERPWD] : 'username:password');
- }
- return $auth;
- }
- /**
- * Set up proxy configuration , if specified, to be used with REST request.
- *
- * @param resource $ch The cURL connection resource.
- * @param array $options An array of options
- * @return boolean True if the proxy was setup.
- */
- public function setProxy($ch,array $options = array()) {
- $proxyEnabled = false;
- /* if proxy is set, attempt to use it */
- $proxyHost = $this->modx->getOption('proxy_host',null,'');
- if (!empty($proxyHost)) {
- $proxyEnabled = curl_setopt($ch, CURLOPT_PROXY,$proxyHost);
- $proxyPort = $this->modx->getOption('proxy_port',null,'');
- if (!empty($proxyPort)) {
- curl_setopt($ch, CURLOPT_PROXYPORT,$proxyPort);
- }
- $proxyUserpwd = $this->modx->getOption('proxy_username',null,'');
- if (!empty($proxyUserpwd)) {
- $proxyAuthType = $this->modx->getOption('proxy_auth_type',null,'BASIC');
- $proxyAuthType = $proxyAuthType == 'NTLM' ? CURLAUTH_NTLM : CURLAUTH_BASIC;
- curl_setopt($ch, CURLOPT_PROXYAUTH,$proxyAuthType);
- $proxyPassword = $this->modx->getOption('proxy_password',null,'');
- if (!empty($proxyPassword)) $proxyUserpwd .= ':'.$proxyPassword;
- curl_setopt($ch, CURLOPT_PROXYUSERPWD,$proxyUserpwd);
- }
- }
- return $proxyEnabled;
- }
- }
- if (!class_exists('modRestArrayToXML')) {
- /**
- * Utility class for array-to-XML transformations.
- *
- * @package modx
- * @subpackage rest
- */
- class modRestArrayToXML {
- /**
- * The main function for converting to an XML document.
- * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document.
- *
- * @param array $data
- * @param string $rootNodeName - what you want the root node to be - defaultsto data.
- * @param SimpleXMLElement $xml - should only be used recursively
- * @return string XML
- */
- public static function toXML( $data, $rootNodeName = 'ResultSet', &$xml=null ) {
- // turn off compatibility mode as simple xml throws a wobbly if you don't.
- if ( ini_get('zend.ze1_compatibility_mode') == 1 ) ini_set ( 'zend.ze1_compatibility_mode', 0 );
- if ( is_null( $xml ) ) $xml = simplexml_load_string('<?xml version="1.0" encoding="UTF-8" standalone="yes"?><'.$rootNodeName.'></'.$rootNodeName.'>');
- // loop through the data passed in.
- foreach( $data as $key => $value ) {
- // no numeric keys in our xml please!
- if ( is_numeric( $key ) ) {
- $numeric = 1;
- $key = $rootNodeName;
- }
- // delete any char not allowed in XML element names
- $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);
- // if there is another array found recrusively call this function
- if ( is_array( $value ) ) {
- $node = modRestArrayToXML::isAssoc( $value ) || $numeric ? $xml->addChild( $key ) : $xml;
- // recrusive call.
- if ( $numeric ) $key = 'anon';
- modRestArrayToXML::toXml( $value, $key, $node );
- } else {
- // add single node.
- $value = htmlentities( $value );
- $xml->addChild( $key, $value );
- }
- }
- // pass back as XML
- //return $xml->asXML();
- // if you want the XML to be formatted, use the below instead to return the XML
- $doc = new DOMDocument('1.0');
- $doc->preserveWhiteSpace = false;
- $doc->loadXML( $xml->asXML() );
- $doc->formatOutput = true;
- return $doc->saveXML();
- }
- /**
- * Convert an XML document to a multi dimensional array
- * Pass in an XML document (or SimpleXMLElement object) and this recrusively loops through and builds a representative array
- *
- * @param string $xml - XML document - can optionally be a SimpleXMLElement object
- * @return array ARRAY
- */
- public static function toArray( $xml ) {
- if ( is_string( $xml ) ) $xml = new SimpleXMLElement( $xml );
- $children = $xml->children();
- if ( !$children ) return (string) $xml;
- $arr = array();
- foreach ( $children as $key => $node ) {
- $node = modRestArrayToXML::toArray( $node );
- // support for 'anon' non-associative arrays
- if ( $key == 'anon' ) $key = count( $arr );
- // if the node is already set, put it into an array
- if ( isset( $arr[$key] ) ) {
- if ( !is_array( $arr[$key] ) || $arr[$key][0] == null ) $arr[$key] = array( $arr[$key] );
- $arr[$key][] = $node;
- } else {
- $arr[$key] = $node;
- }
- }
- return $arr;
- }
- /**
- * Determine if a variable is an associative array
- *
- * @static
- * @param mixed $array The variable to check
- * @return boolean True if is an array
- */
- public static function isAssoc( $array ) {
- return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
- }
- }
- }