getConnection(); $conn->createRequest('GET', $url); $data = $conn->getReturnData(); $conn->closeRequest(); $this->_initial_request = TRUE; return $data; } //------------------------------------------------- // Put info to the server. //------------------------------------------------- function putInfo($url, $xml) { //------------------------------------------------- // Make sure we're doing things the REST way. //------------------------------------------------- if(!$this->_initial_request) { trigger_error("[ERROR] This is a REST application, not RPC."); } //------------------------------------------------- // Use a socket connection for this for the sake of // simplicity. //------------------------------------------------- $conn = &new Socket_Connection; $conn->createRequest('PUT', $url); $conn->setPutData($xml); $data = $conn->getReturnData(); $conn->closeRequest(); return $data; } } //------------------------------------------------- // Deal with RPC (remote procedure call) // requests. //------------------------------------------------- class RPC_Request extends RemoteXMLRequest { //------------------------------------------------- // Put info to the server. //------------------------------------------------- function putInfo($url, $xml) { //------------------------------------------------- // Use a socket connection for this for the sake of // simplicity. //------------------------------------------------- $conn = &new Socket_Connection; $conn->createRequest('PUT', $url); $conn->setPutData($xml); $data = $conn->getReturnData(); $conn->closeRequest(); $this->_initial_put = TRUE; return $data; } //------------------------------------------------- // Get the information after out inital PUT //------------------------------------------------- function getInfo($url) { //------------------------------------------------- // Make sure we're doing things the RPC way. //------------------------------------------------- if(!$this->_initial_put) { trigger_error("[ERROR] This is a REST application, not RPC.", E_USER_ERROR); } //------------------------------------------------- // Get out socket/cURL connection and make the request. //------------------------------------------------- $conn = &$this->getConnection(); $conn->createRequest('GET', $url); $data = $conn->getReturnData(); $conn->closeRequest(); return $data; } } //------------------------------------------------- // Interface for cURL and socket connections. //------------------------------------------------- class RemoteXMLConnection { var $_conn; var $_conn_closed = FALSE; //------------------------------------------------- // Some nice variables //------------------------------------------------- var $_scheme; var $_server; var $_path; var $_port = 80; var $_timeout = 5; var $_put = FALSE; var $_head = FALSE; function createRequest($type = 'GET', $server = '', $path = '/', $port = 80) { assert(FALSE); } function closeRequest() { assert(FALSE); } function getReturnData() { assert(FALSE); } function setFile($file_name) { assert(FALSE); } function errorNo() { assert(FALSE); } function showAnyErrors() { assert(FALSE); } function setXMLData(&$data) { if(!is_a($data, 'RemoteXMLDocument')) { trigger_error("[ERROR] The data must be an instance of the RemoteXMLDocument object."); } } function _parseUrl($url) { //------------------------------------------------- // Parse the passed in URL. //------------------------------------------------- $url = parse_url($url); $this->_scheme = strtoupper($url['scheme']); $this->_server = $url['host']; $this->_path = isset($url['path']) ? $url['path'] : '/'; $this->_port = isset($url['port']) ? $url['port'] : 80; $this->_timeout = isset($url['fragment']) ? $url['fragment'] : 5; } } //------------------------------------------------- // A cURL layer for doing what we need to do :D //------------------------------------------------- class cURL_Connection extends RemoteXMLConnection { var $_called_exec = FALSE; //------------------------------------------------- // Create a request. //------------------------------------------------- function createRequest($method = 'GET', $url) { //------------------------------------------------- // Parse the url to get the connection data. //------------------------------------------------- $this->_parseUrl($url); //------------------------------------------------- // Check to see if the cURL extension is even enabled. //------------------------------------------------- if(function_exists('curl_init')) { //------------------------------------------------- // Start connecting and do stuff. //------------------------------------------------- $this->_conn = &curl_init(); $this->showAnyErrors(); curl_setopt($this->_conn, CURLOPT_URL, $this->_server . $this->_path); curl_setopt($this->_conn, CURLOPT_HTTP_VERSION, 1.0); curl_setopt($this->_conn, CURLOPT_USERAGENT, REMOTE_XML_USERAGENT); $this->showAnyErrors(); //------------------------------------------------- // Figure out what connection method we are using. //------------------------------------------------- $return_headers = FALSE; if($method == 'GET') { $method = CURLOPT_HTTPGET; } else if($method == 'POST') { $method = CURLOPT_POST; } else if($method == 'HEAD') { $method = 'GET'; $return_headers = TRUE; } else { $method = CURLOPT_PUT; $this->_put = TRUE; } curl_setopt($this->_conn, $method, 1); //------------------------------------------------- // Should we display the headers? //------------------------------------------------- curl_setopt($this->_conn, CURLOPT_HEADER, $return_headers); //------------------------------------------------- // If the request fails (error code > 400), fail silently. //------------------------------------------------- curl_setopt($this->_conn, CURLOPT_FAILONERROR, 1); //------------------------------------------------- // Follow header(Location: )'s, but only a max of 5 // of them. //------------------------------------------------- curl_setopt($this->_conn, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($this->_conn, CURLOPT_MAXREDIRS, 5); //------------------------------------------------- // Make sure to close the request. //------------------------------------------------- register_shutdown_function(array(&$this, 'closeRequest')); } else { trigger_error("[ERROR] The cURL extension cannot be found."); } } //------------------------------------------------- // Get the return data from the execution. //------------------------------------------------- function getReturnData() { curl_setopt($this->_conn, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec($this->_conn); $this->_called_exec = TRUE; return $data; } //------------------------------------------------- // Close the connection //------------------------------------------------- function closeRequest() { if(!$this->_conn_closed) { if(!$this->_called_exec) { curl_exec($this->_conn); } curl_close($this->_conn); } } //------------------------------------------------- // If we're using HTTP PUT, we need to 'put' a file to // their server, so, open up a file pointer to the local // file that we want to put and send it to their server. //------------------------------------------------- function setFile($file_name) { if($this->_put) { //------------------------------------------------- // Do some nice error checking.. //------------------------------------------------- if(!file_exists($file_name)) { trigger_error("[ERROR] File [$file_name] does not exist."); } if(!is_readable($file_name)) { trigger_error("[ERROR] File [$file_name] cannot be read."); } //------------------------------------------------- // Get and put the file. //------------------------------------------------- $file_fp = fopen($file_name, "r"); $file_size = filesize($file_name); curl_setopt($this->_conn, CURLOPT_INFILE, $file_fp); curl_setopt($this->_conn, CURLOPT_INFILESIZE, $file_size); $this->showAnyErrors(); } } //-------------------------------------------- // Send XML data through the curl session. //-------------------------------------------- function setPutData($xml) { if($this->_put) { // TODO:{[Should I make this create a file only to pass it to cURL only to delete it after?[setPutData[cURL_Connection} } } //------------------------------------------------- // Return the last error code of the curl operation. //------------------------------------------------- function errorNo() { return curl_errno($this->_conn); } //------------------------------------------------- // If there are any errors, show them. //------------------------------------------------- function showAnyErrors() { if($this->errorNo() > 0) { trigger_error(curl_error($this->_conn), E_USER_ERROR); } } } //------------------------------------------------- // Do everything that the above cURL stuff does, but // manually with the socket. //------------------------------------------------- class Socket_Connection extends RemoteXMLConnection { //------------------------------------------------- // Open a socket to the url on the specified port. //------------------------------------------------- function createRequest($method = 'GET', $url) { //------------------------------------------------- // Parse the url to get the connection data. //------------------------------------------------- $this->_parseUrl(); //------------------------------------------------- // Connect... //------------------------------------------------- $scheme = $this->_scheme == 'HTTPS' ? 'ssl' : $this->_scheme; $this->_conn = fsockopen($scheme .'://'. $this->_server, $this->_port, $error_number, $error_string, $this->_timeout); //------------------------------------------------- // Error check. //------------------------------------------------- if(!$this->_conn) { trigger_error("[ERROR] Could not open the socket.", E_USER_ERROR); } $data = stream_get_meta_data($this->_conn); if($data['timed_out']) { trigger_error("[ERROR] Socket times out.", E_USER_ERROR); } //------------------------------------------------- // Make sure it times out. //------------------------------------------------- stream_set_timeout($this->_conn, $this->_timeout); stream_set_blocking($this->_conn, FALSE); //------------------------------------------------- // Figure out what connection method we are using. //------------------------------------------------- if($method == 'PUT') { $this->_put = TRUE; } else if($method == 'HEAD') { $this->_head = TRUE; } //------------------------------------------------- // Set the headers. //------------------------------------------------- if($this->_scheme == 'HTTPS') { $this->_scheme = 'HTTP'; } if($this->_scheme != 'UDP') { $this->_socketCommand("{$method} {$this->_path} {$this->_scheme}"); } $this->_socketCommand("Host: {$this->_server}"); $this->_socketCommand("User-Agent: ". REMOTE_XML_USERAGENT); $this->_socketCommand("X-Requested-With: ". REMOTE_XML_USERAGENT); $this->_socketCommand("Connection: Close"); $this->_socketCommand(""); //------------------------------------------------- // Make sure to close the request. //------------------------------------------------- register_shutdown_function(array(&$this, 'closeRequest')); } //------------------------------------------------- // Close the socket. //------------------------------------------------- function closeRequest() { if(!$this->_conn_closed) { fclose($this->_conn); $this->_conn_closed = TRUE; } } //------------------------------------------------- // Get the data that the socket returned. //------------------------------------------------- function getReturnData() { $data = ""; $first_line = TRUE; $getting_headers = TRUE; //------------------------------------------------- // Loop through the data returned. //------------------------------------------------- while(!feof($this->_conn)) { $line = fgets($this->_conn, 4096); //------------------------------------------------- // This is the first line, check for the 200 code // (everything's a-okay) //------------------------------------------------- if($first_line) { if(strlen($line) != 0) { //------------------------------------------------- // Did something go wrong? //------------------------------------------------- if(strstr($line, " 200 ") === FALSE) { trigger_error("[ERROR] An error occured. HTTP status code was not 200."); } $first_line = FALSE; //------------------------------------------------- // If we only want to get the headers, make them part // of the data. //------------------------------------------------- if($this->_head) { $data .= $line; } } } //------------------------------------------------- // If we're not getting headers anymore, add this line to the data. //------------------------------------------------- if(!$getting_headers && !$this->_head) { $data .= $line; } //------------------------------------------------- // If we're still getting headers and this line is equal // to CR\LF, tell the script to start recording data for // the next loop. //------------------------------------------------- if($getting_headers && $line == "\r\n") { $getting_headers = FALSE; //------------------------------------------------- // So, we only want to return the headers. //------------------------------------------------- if($this->_head) { break; } } } return $data; } //-------------------------------------------- // Send data through the socket. //-------------------------------------------- function setPutData($xml) { if($this->_put) { fputs($this->_conn, $xml, strlen($xml)); } } //-------------------------------------------- // Send a command to the socket. //-------------------------------------------- function _socketCommand($command) { $command = $command ."\r\n"; fputs($this->_conn, $command, strlen($command)); } } ?>