summaryrefslogtreecommitdiffstats
path: root/3rdparty/php-cloudfiles/cloudfiles_http.php
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/php-cloudfiles/cloudfiles_http.php')
-rw-r--r--3rdparty/php-cloudfiles/cloudfiles_http.php1488
1 files changed, 1488 insertions, 0 deletions
diff --git a/3rdparty/php-cloudfiles/cloudfiles_http.php b/3rdparty/php-cloudfiles/cloudfiles_http.php
new file mode 100644
index 00000000000..0e5d9717e81
--- /dev/null
+++ b/3rdparty/php-cloudfiles/cloudfiles_http.php
@@ -0,0 +1,1488 @@
+<?php
+/**
+ * This is an HTTP client class for Cloud Files. It uses PHP's cURL module
+ * to handle the actual HTTP request/response. This is NOT a generic HTTP
+ * client class and is only used to abstract out the HTTP communication for
+ * the PHP Cloud Files API.
+ *
+ * This module was designed to re-use existing HTTP(S) connections between
+ * subsequent operations. For example, performing multiple PUT operations
+ * will re-use the same connection.
+ *
+ * This modules also provides support for streaming content into and out
+ * of Cloud Files. The majority (all?) of the PHP HTTP client modules expect
+ * to read the server's response into a string variable. This will not work
+ * with large files without killing your server. Methods like,
+ * get_object_to_stream() and put_object() take an open filehandle
+ * argument for streaming data out of or into Cloud Files.
+ *
+ * Requres PHP 5.x (for Exceptions and OO syntax)
+ *
+ * See COPYING for license information.
+ *
+ * @author Eric "EJ" Johnson <ej@racklabs.com>
+ * @copyright Copyright (c) 2008, Rackspace US, Inc.
+ * @package php-cloudfiles-http
+ */
+
+/**
+ */
+require_once("cloudfiles_exceptions.php");
+
+define("PHP_CF_VERSION", "1.7.10");
+define("USER_AGENT", sprintf("PHP-CloudFiles/%s", PHP_CF_VERSION));
+define("MAX_HEADER_NAME_LEN", 128);
+define("MAX_HEADER_VALUE_LEN", 256);
+define("ACCOUNT_CONTAINER_COUNT", "X-Account-Container-Count");
+define("ACCOUNT_BYTES_USED", "X-Account-Bytes-Used");
+define("CONTAINER_OBJ_COUNT", "X-Container-Object-Count");
+define("CONTAINER_BYTES_USED", "X-Container-Bytes-Used");
+define("MANIFEST_HEADER", "X-Object-Manifest");
+define("METADATA_HEADER_PREFIX", "X-Object-Meta-");
+define("CONTENT_HEADER_PREFIX", "Content-");
+define("ACCESS_CONTROL_HEADER_PREFIX", "Access-Control-");
+define("ORIGIN_HEADER", "Origin");
+define("CDN_URI", "X-CDN-URI");
+define("CDN_SSL_URI", "X-CDN-SSL-URI");
+define("CDN_STREAMING_URI", "X-CDN-Streaming-URI");
+define("CDN_ENABLED", "X-CDN-Enabled");
+define("CDN_LOG_RETENTION", "X-Log-Retention");
+define("CDN_ACL_USER_AGENT", "X-User-Agent-ACL");
+define("CDN_ACL_REFERRER", "X-Referrer-ACL");
+define("CDN_TTL", "X-TTL");
+define("CDNM_URL", "X-CDN-Management-Url");
+define("STORAGE_URL", "X-Storage-Url");
+define("AUTH_TOKEN", "X-Auth-Token");
+define("AUTH_USER_HEADER", "X-Auth-User");
+define("AUTH_KEY_HEADER", "X-Auth-Key");
+define("AUTH_USER_HEADER_LEGACY", "X-Storage-User");
+define("AUTH_KEY_HEADER_LEGACY", "X-Storage-Pass");
+define("AUTH_TOKEN_LEGACY", "X-Storage-Token");
+define("CDN_EMAIL", "X-Purge-Email");
+define("DESTINATION", "Destination");
+define("ETAG_HEADER", "ETag");
+define("LAST_MODIFIED_HEADER", "Last-Modified");
+define("CONTENT_TYPE_HEADER", "Content-Type");
+define("CONTENT_LENGTH_HEADER", "Content-Length");
+define("USER_AGENT_HEADER", "User-Agent");
+
+/**
+ * HTTP/cURL wrapper for Cloud Files
+ *
+ * This class should not be used directly. It's only purpose is to abstract
+ * out the HTTP communication from the main API.
+ *
+ * @package php-cloudfiles-http
+ */
+class CF_Http
+{
+ private $error_str;
+ private $dbug;
+ private $cabundle_path;
+ private $api_version;
+
+ # Authentication instance variables
+ #
+ private $storage_url;
+ private $cdnm_url;
+ private $auth_token;
+
+ # Request/response variables
+ #
+ private $response_status;
+ private $response_reason;
+ private $connections;
+
+ # Variables used for content/header callbacks
+ #
+ private $_user_read_progress_callback_func;
+ private $_user_write_progress_callback_func;
+ private $_write_callback_type;
+ private $_text_list;
+ private $_account_container_count;
+ private $_account_bytes_used;
+ private $_container_object_count;
+ private $_container_bytes_used;
+ private $_obj_etag;
+ private $_obj_last_modified;
+ private $_obj_content_type;
+ private $_obj_content_length;
+ private $_obj_metadata;
+ private $_obj_headers;
+ private $_obj_manifest;
+ private $_obj_write_resource;
+ private $_obj_write_string;
+ private $_cdn_enabled;
+ private $_cdn_ssl_uri;
+ private $_cdn_streaming_uri;
+ private $_cdn_uri;
+ private $_cdn_ttl;
+ private $_cdn_log_retention;
+ private $_cdn_acl_user_agent;
+ private $_cdn_acl_referrer;
+
+ function __construct($api_version)
+ {
+ $this->dbug = False;
+ $this->cabundle_path = NULL;
+ $this->api_version = $api_version;
+ $this->error_str = NULL;
+
+ $this->storage_url = NULL;
+ $this->cdnm_url = NULL;
+ $this->auth_token = NULL;
+
+ $this->response_status = NULL;
+ $this->response_reason = NULL;
+
+ # Curl connections array - since there is no way to "re-set" the
+ # connection paramaters for a cURL handle, we keep an array of
+ # the unique use-cases and funnel all of those same type
+ # requests through the appropriate curl connection.
+ #
+ $this->connections = array(
+ "GET_CALL" => NULL, # GET objects/containers/lists
+ "PUT_OBJ" => NULL, # PUT object
+ "HEAD" => NULL, # HEAD requests
+ "PUT_CONT" => NULL, # PUT container
+ "DEL_POST" => NULL, # DELETE containers/objects, POST objects
+ "COPY" => null, # COPY objects
+ );
+
+ $this->_user_read_progress_callback_func = NULL;
+ $this->_user_write_progress_callback_func = NULL;
+ $this->_write_callback_type = NULL;
+ $this->_text_list = array();
+ $this->_return_list = NULL;
+ $this->_account_container_count = 0;
+ $this->_account_bytes_used = 0;
+ $this->_container_object_count = 0;
+ $this->_container_bytes_used = 0;
+ $this->_obj_write_resource = NULL;
+ $this->_obj_write_string = "";
+ $this->_obj_etag = NULL;
+ $this->_obj_last_modified = NULL;
+ $this->_obj_content_type = NULL;
+ $this->_obj_content_length = NULL;
+ $this->_obj_metadata = array();
+ $this->_obj_manifest = NULL;
+ $this->_obj_headers = NULL;
+ $this->_cdn_enabled = NULL;
+ $this->_cdn_ssl_uri = NULL;
+ $this->_cdn_streaming_uri = NULL;
+ $this->_cdn_uri = NULL;
+ $this->_cdn_ttl = NULL;
+ $this->_cdn_log_retention = NULL;
+ $this->_cdn_acl_user_agent = NULL;
+ $this->_cdn_acl_referrer = NULL;
+
+ # The OS list with a PHP without an updated CA File for CURL to
+ # connect to SSL Websites. It is the first 3 letters of the PHP_OS
+ # variable.
+ $OS_CAFILE_NONUPDATED=array(
+ "win","dar"
+ );
+
+ if (in_array((strtolower (substr(PHP_OS, 0,3))), $OS_CAFILE_NONUPDATED))
+ $this->ssl_use_cabundle();
+
+ }
+
+ function ssl_use_cabundle($path=NULL)
+ {
+ if ($path) {
+ $this->cabundle_path = $path;
+ } else {
+ $this->cabundle_path = dirname(__FILE__) . "/share/cacert.pem";
+ }
+ if (!file_exists($this->cabundle_path)) {
+ throw new IOException("Could not use CA bundle: "
+ . $this->cabundle_path);
+ }
+ return;
+ }
+
+ # Uses separate cURL connection to authenticate
+ #
+ function authenticate($user, $pass, $acct=NULL, $host=NULL)
+ {
+ $path = array();
+ if (isset($acct)){
+ $headers = array(
+ sprintf("%s: %s", AUTH_USER_HEADER_LEGACY, $user),
+ sprintf("%s: %s", AUTH_KEY_HEADER_LEGACY, $pass),
+ );
+ $path[] = $host;
+ $path[] = rawurlencode(sprintf("v%d",$this->api_version));
+ $path[] = rawurlencode($acct);
+ } else {
+ $headers = array(
+ sprintf("%s: %s", AUTH_USER_HEADER, $user),
+ sprintf("%s: %s", AUTH_KEY_HEADER, $pass),
+ );
+ $path[] = $host;
+ }
+ $path[] = "v1.0";
+ $url = implode("/", $path);
+
+ $curl_ch = curl_init();
+ if (!is_null($this->cabundle_path)) {
+ curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, True);
+ curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
+ }
+ curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
+ curl_setopt($curl_ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($curl_ch, CURLOPT_MAXREDIRS, 4);
+ curl_setopt($curl_ch, CURLOPT_HEADER, 0);
+ curl_setopt($curl_ch, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl_ch, CURLOPT_USERAGENT, USER_AGENT);
+ curl_setopt($curl_ch, CURLOPT_RETURNTRANSFER, TRUE);
+ curl_setopt($curl_ch, CURLOPT_HEADERFUNCTION,array(&$this,'_auth_hdr_cb'));
+ curl_setopt($curl_ch, CURLOPT_CONNECTTIMEOUT, 10);
+ curl_setopt($curl_ch, CURLOPT_URL, $url);
+ curl_exec($curl_ch);
+ curl_close($curl_ch);
+
+ return array($this->response_status, $this->response_reason,
+ $this->storage_url, $this->cdnm_url, $this->auth_token);
+ }
+
+ # (CDN) GET /v1/Account
+ #
+ function list_cdn_containers($enabled_only)
+ {
+ $conn_type = "GET_CALL";
+ $url_path = $this->_make_path("CDN");
+
+ $this->_write_callback_type = "TEXT_LIST";
+ if ($enabled_only)
+ {
+ $return_code = $this->_send_request($conn_type, $url_path .
+ '/?enabled_only=true');
+ }
+ else
+ {
+ $return_code = $this->_send_request($conn_type, $url_path);
+ }
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,array());
+ }
+ if ($return_code == 401) {
+ return array($return_code,"Unauthorized",array());
+ }
+ if ($return_code == 404) {
+ return array($return_code,"Account not found.",array());
+ }
+ if ($return_code == 204) {
+ return array($return_code,"Account has no CDN enabled Containers.",
+ array());
+ }
+ if ($return_code == 200) {
+ $this->create_array();
+ return array($return_code,$this->response_reason,$this->_text_list);
+ }
+ $this->error_str = "Unexpected HTTP response: ".$this->response_reason;
+ return array($return_code,$this->error_str,array());
+ }
+
+ # (CDN) DELETE /v1/Account/Container or /v1/Account/Container/Object
+ #
+ function purge_from_cdn($path, $email=null)
+ {
+ if(!$path)
+ throw new SyntaxException("Path not set");
+ $url_path = $this->_make_path("CDN", NULL, $path);
+ if($email)
+ {
+ $hdrs = array(CDN_EMAIL => $email);
+ $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"DELETE");
+ }
+ else
+ $return_code = $this->_send_request("DEL_POST",$url_path,null,"DELETE");
+ return $return_code;
+ }
+
+ # (CDN) POST /v1/Account/Container
+ function update_cdn_container($container_name, $ttl=86400, $cdn_log_retention=False,
+ $cdn_acl_user_agent="", $cdn_acl_referrer)
+ {
+ if ($container_name == "")
+ throw new SyntaxException("Container name not set.");
+
+ if ($container_name != "0" and !isset($container_name))
+ throw new SyntaxException("Container name not set.");
+
+ $url_path = $this->_make_path("CDN", $container_name);
+ $hdrs = array(
+ CDN_ENABLED => "True",
+ CDN_TTL => $ttl,
+ CDN_LOG_RETENTION => $cdn_log_retention ? "True" : "False",
+ CDN_ACL_USER_AGENT => $cdn_acl_user_agent,
+ CDN_ACL_REFERRER => $cdn_acl_referrer,
+ );
+ $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
+ if ($return_code == 401) {
+ $this->error_str = "Unauthorized";
+ return array($return_code, $this->error_str, NULL);
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Container not found.";
+ return array($return_code, $this->error_str, NULL);
+ }
+ if ($return_code != 202) {
+ $this->error_str="Unexpected HTTP response: ".$this->response_reason;
+ return array($return_code, $this->error_str, NULL);
+ }
+ return array($return_code, "Accepted", $this->_cdn_uri, $this->_cdn_ssl_uri);
+
+ }
+
+ # (CDN) PUT /v1/Account/Container
+ #
+ function add_cdn_container($container_name, $ttl=86400)
+ {
+ if ($container_name == "")
+ throw new SyntaxException("Container name not set.");
+
+ if ($container_name != "0" and !isset($container_name))
+ throw new SyntaxException("Container name not set.");
+
+ $url_path = $this->_make_path("CDN", $container_name);
+ $hdrs = array(
+ CDN_ENABLED => "True",
+ CDN_TTL => $ttl,
+ );
+ $return_code = $this->_send_request("PUT_CONT", $url_path, $hdrs);
+ if ($return_code == 401) {
+ $this->error_str = "Unauthorized";
+ return array($return_code,$this->response_reason,False);
+ }
+ if (!in_array($return_code, array(201,202))) {
+ $this->error_str="Unexpected HTTP response: ".$this->response_reason;
+ return array($return_code,$this->response_reason,False);
+ }
+ return array($return_code,$this->response_reason,$this->_cdn_uri,
+ $this->_cdn_ssl_uri);
+ }
+
+ # (CDN) POST /v1/Account/Container
+ #
+ function remove_cdn_container($container_name)
+ {
+ if ($container_name == "")
+ throw new SyntaxException("Container name not set.");
+
+ if ($container_name != "0" and !isset($container_name))
+ throw new SyntaxException("Container name not set.");
+
+ $url_path = $this->_make_path("CDN", $container_name);
+ $hdrs = array(CDN_ENABLED => "False");
+ $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
+ if ($return_code == 401) {
+ $this->error_str = "Unauthorized";
+ return array($return_code, $this->error_str);
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Container not found.";
+ return array($return_code, $this->error_str);
+ }
+ if ($return_code != 202) {
+ $this->error_str="Unexpected HTTP response: ".$this->response_reason;
+ return array($return_code, $this->error_str);
+ }
+ return array($return_code, "Accepted");
+ }
+
+ # (CDN) HEAD /v1/Account
+ #
+ function head_cdn_container($container_name)
+ {
+ if ($container_name == "")
+ throw new SyntaxException("Container name not set.");
+
+ if ($container_name != "0" and !isset($container_name))
+ throw new SyntaxException("Container name not set.");
+
+ $conn_type = "HEAD";
+ $url_path = $this->_make_path("CDN", $container_name);
+ $return_code = $this->_send_request($conn_type, $url_path, NULL, "GET", True);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+ }
+ if ($return_code == 401) {
+ return array($return_code,"Unauthorized",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+ }
+ if ($return_code == 404) {
+ return array($return_code,"Account not found.",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+ }
+ if ($return_code == 204) {
+ return array($return_code,$this->response_reason,
+ $this->_cdn_enabled, $this->_cdn_ssl_uri,
+ $this->_cdn_streaming_uri,
+ $this->_cdn_uri, $this->_cdn_ttl,
+ $this->_cdn_log_retention,
+ $this->_cdn_acl_user_agent,
+ $this->_cdn_acl_referrer
+ );
+ }
+ return array($return_code,$this->response_reason,
+ NULL,NULL,NULL,NULL,
+ $this->_cdn_log_retention,
+ $this->_cdn_acl_user_agent,
+ $this->_cdn_acl_referrer,
+ NULL
+ );
+ }
+
+ # GET /v1/Account
+ #
+ function list_containers($limit=0, $marker=NULL)
+ {
+ $conn_type = "GET_CALL";
+ $url_path = $this->_make_path();
+
+ $limit = intval($limit);
+ $params = array();
+ if ($limit > 0) {
+ $params[] = "limit=$limit";
+ }
+ if ($marker) {
+ $params[] = "marker=".rawurlencode($marker);
+ }
+ if (!empty($params)) {
+ $url_path .= "?" . implode("&", $params);
+ }
+
+ $this->_write_callback_type = "TEXT_LIST";
+ $return_code = $this->_send_request($conn_type, $url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,array());
+ }
+ if ($return_code == 204) {
+ return array($return_code, "Account has no containers.", array());
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Invalid account name for authentication token.";
+ return array($return_code,$this->error_str,array());
+ }
+ if ($return_code == 200) {
+ $this->create_array();
+ return array($return_code, $this->response_reason, $this->_text_list);
+ }
+ $this->error_str = "Unexpected HTTP response: ".$this->response_reason;
+ return array($return_code,$this->error_str,array());
+ }
+
+ # GET /v1/Account?format=json
+ #
+ function list_containers_info($limit=0, $marker=NULL)
+ {
+ $conn_type = "GET_CALL";
+ $url_path = $this->_make_path() . "?format=json";
+
+ $limit = intval($limit);
+ $params = array();
+ if ($limit > 0) {
+ $params[] = "limit=$limit";
+ }
+ if ($marker) {
+ $params[] = "marker=".rawurlencode($marker);
+ }
+ if (!empty($params)) {
+ $url_path .= "&" . implode("&", $params);
+ }
+
+ $this->_write_callback_type = "OBJECT_STRING";
+ $return_code = $this->_send_request($conn_type, $url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,array());
+ }
+ if ($return_code == 204) {
+ return array($return_code, "Account has no containers.", array());
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Invalid account name for authentication token.";
+ return array($return_code,$this->error_str,array());
+ }
+ if ($return_code == 200) {
+ $json_body = json_decode($this->_obj_write_string, True);
+ return array($return_code, $this->response_reason, $json_body);
+ }
+ $this->error_str = "Unexpected HTTP response: ".$this->response_reason;
+ return array($return_code,$this->error_str,array());
+ }
+
+ # HEAD /v1/Account
+ #
+ function head_account()
+ {
+ $conn_type = "HEAD";
+
+ $url_path = $this->_make_path();
+ $return_code = $this->_send_request($conn_type,$url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,0,0);
+ }
+ if ($return_code == 404) {
+ return array($return_code,"Account not found.",0,0);
+ }
+ if ($return_code == 204) {
+ return array($return_code,$this->response_reason,
+ $this->_account_container_count, $this->_account_bytes_used);
+ }
+ return array($return_code,$this->response_reason,0,0);
+ }
+
+ # PUT /v1/Account/Container
+ #
+ function create_container($container_name)
+ {
+ if ($container_name == "")
+ throw new SyntaxException("Container name not set.");
+
+ if ($container_name != "0" and !isset($container_name))
+ throw new SyntaxException("Container name not set.");
+
+ $url_path = $this->_make_path("STORAGE", $container_name);
+ $return_code = $this->_send_request("PUT_CONT",$url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return False;
+ }
+ return $return_code;
+ }
+
+ # DELETE /v1/Account/Container
+ #
+ function delete_container($container_name)
+ {
+ if ($container_name == "")
+ throw new SyntaxException("Container name not set.");
+
+ if ($container_name != "0" and !isset($container_name))
+ throw new SyntaxException("Container name not set.");
+
+ $url_path = $this->_make_path("STORAGE", $container_name);
+ $return_code = $this->_send_request("DEL_POST",$url_path,array(),"DELETE");
+
+ switch ($return_code) {
+ case 204:
+ break;
+ case 0:
+ $this->error_str .= ": Failed to obtain valid HTTP response.";;
+ break;
+ case 409:
+ $this->error_str = "Container must be empty prior to removing it.";
+ break;
+ case 404:
+ $this->error_str = "Specified container did not exist to delete.";
+ break;
+ default:
+ $this->error_str = "Unexpected HTTP return code: $return_code.";
+ }
+ return $return_code;
+ }
+
+ # GET /v1/Account/Container
+ #
+ function list_objects($cname,$limit=0,$marker=NULL,$prefix=NULL,$path=NULL)
+ {
+ if (!$cname) {
+ $this->error_str = "Container name not set.";
+ return array(0, $this->error_str, array());
+ }
+
+ $url_path = $this->_make_path("STORAGE", $cname);
+
+ $limit = intval($limit);
+ $params = array();
+ if ($limit > 0) {
+ $params[] = "limit=$limit";
+ }
+ if ($marker) {
+ $params[] = "marker=".rawurlencode($marker);
+ }
+ if ($prefix) {
+ $params[] = "prefix=".rawurlencode($prefix);
+ }
+ if ($path) {
+ $params[] = "path=".rawurlencode($path);
+ }
+ if (!empty($params)) {
+ $url_path .= "?" . implode("&", $params);
+ }
+
+ $conn_type = "GET_CALL";
+ $this->_write_callback_type = "TEXT_LIST";
+ $return_code = $this->_send_request($conn_type,$url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,array());
+ }
+ if ($return_code == 204) {
+ $this->error_str = "Container has no Objects.";
+ return array($return_code,$this->error_str,array());
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Container has no Objects.";
+ return array($return_code,$this->error_str,array());
+ }
+ if ($return_code == 200) {
+ $this->create_array();
+ return array($return_code,$this->response_reason, $this->_text_list);
+ }
+ $this->error_str = "Unexpected HTTP response code: $return_code";
+ return array(0,$this->error_str,array());
+ }
+
+ # GET /v1/Account/Container?format=json
+ #
+ function get_objects($cname,$limit=0,$marker=NULL,$prefix=NULL,$path=NULL)
+ {
+ if (!$cname) {
+ $this->error_str = "Container name not set.";
+ return array(0, $this->error_str, array());
+ }
+
+ $url_path = $this->_make_path("STORAGE", $cname);
+
+ $limit = intval($limit);
+ $params = array();
+ $params[] = "format=json";
+ if ($limit > 0) {
+ $params[] = "limit=$limit";
+ }
+ if ($marker) {
+ $params[] = "marker=".rawurlencode($marker);
+ }
+ if ($prefix) {
+ $params[] = "prefix=".rawurlencode($prefix);
+ }
+ if ($path) {
+ $params[] = "path=".rawurlencode($path);
+ }
+ if (!empty($params)) {
+ $url_path .= "?" . implode("&", $params);
+ }
+
+ $conn_type = "GET_CALL";
+ $this->_write_callback_type = "OBJECT_STRING";
+ $return_code = $this->_send_request($conn_type,$url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,array());
+ }
+ if ($return_code == 204) {
+ $this->error_str = "Container has no Objects.";
+ return array($return_code,$this->error_str,array());
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Container has no Objects.";
+ return array($return_code,$this->error_str,array());
+ }
+ if ($return_code == 200) {
+ $json_body = json_decode($this->_obj_write_string, True);
+ return array($return_code,$this->response_reason, $json_body);
+ }
+ $this->error_str = "Unexpected HTTP response code: $return_code";
+ return array(0,$this->error_str,array());
+ }
+
+
+ # HEAD /v1/Account/Container
+ #
+ function head_container($container_name)
+ {
+
+ if ($container_name == "") {
+ $this->error_str = "Container name not set.";
+ return False;
+ }
+
+ if ($container_name != "0" and !isset($container_name)) {
+ $this->error_str = "Container name not set.";
+ return False;
+ }
+
+ $conn_type = "HEAD";
+
+ $url_path = $this->_make_path("STORAGE", $container_name);
+ $return_code = $this->_send_request($conn_type,$url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,0,0);
+ }
+ if ($return_code == 404) {
+ return array($return_code,"Container not found.",0,0);
+ }
+ if ($return_code == 204 || $return_code == 200) {
+ return array($return_code,$this->response_reason,
+ $this->_container_object_count, $this->_container_bytes_used);
+ }
+ return array($return_code,$this->response_reason,0,0);
+ }
+
+ # GET /v1/Account/Container/Object
+ #
+ function get_object_to_string(&$obj, $hdrs=array())
+ {
+ if (!is_object($obj) || get_class($obj) != "CF_Object") {
+ throw new SyntaxException(
+ "Method argument is not a valid CF_Object.");
+ }
+
+ $conn_type = "GET_CALL";
+
+ $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+ $this->_write_callback_type = "OBJECT_STRING";
+ $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array($return_code0,$this->error_str,NULL);
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Object not found.";
+ return array($return_code0,$this->error_str,NULL);
+ }
+ if (($return_code < 200) || ($return_code > 299
+ && $return_code != 412 && $return_code != 304)) {
+ $this->error_str = "Unexpected HTTP return code: $return_code";
+ return array($return_code,$this->error_str,NULL);
+ }
+ return array($return_code,$this->response_reason, $this->_obj_write_string);
+ }
+
+ # GET /v1/Account/Container/Object
+ #
+ function get_object_to_stream(&$obj, &$resource=NULL, $hdrs=array())
+ {
+ if (!is_object($obj) || get_class($obj) != "CF_Object") {
+ throw new SyntaxException(
+ "Method argument is not a valid CF_Object.");
+ }
+ if (!is_resource($resource)) {
+ throw new SyntaxException(
+ "Resource argument not a valid PHP resource.");
+ }
+
+ $conn_type = "GET_CALL";
+
+ $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+ $this->_obj_write_resource = $resource;
+ $this->_write_callback_type = "OBJECT_STREAM";
+ $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array($return_code,$this->error_str);
+ }
+ if ($return_code == 404) {
+ $this->error_str = "Object not found.";
+ return array($return_code,$this->error_str);
+ }
+ if (($return_code < 200) || ($return_code > 299
+ && $return_code != 412 && $return_code != 304)) {
+ $this->error_str = "Unexpected HTTP return code: $return_code";
+ return array($return_code,$this->error_str);
+ }
+ return array($return_code,$this->response_reason);
+ }
+
+ # PUT /v1/Account/Container/Object
+ #
+ function put_object(&$obj, &$fp)
+ {
+ if (!is_object($obj) || get_class($obj) != "CF_Object") {
+ throw new SyntaxException(
+ "Method argument is not a valid CF_Object.");
+ }
+ if (!is_resource($fp)) {
+ throw new SyntaxException(
+ "File pointer argument is not a valid resource.");
+ }
+
+ $conn_type = "PUT_OBJ";
+ $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+
+ $hdrs = $this->_headers($obj);
+
+ $etag = $obj->getETag();
+ if (isset($etag)) {
+ $hdrs[] = "ETag: " . $etag;
+ }
+ if (!$obj->content_type) {
+ $hdrs[] = "Content-Type: application/octet-stream";
+ } else {
+ $hdrs[] = "Content-Type: " . $obj->content_type;
+ }
+
+ $this->_init($conn_type);
+ curl_setopt($this->connections[$conn_type],
+ CURLOPT_INFILE, $fp);
+ if (!$obj->content_length) {
+ # We don''t know the Content-Length, so assumed "chunked" PUT
+ #
+ curl_setopt($this->connections[$conn_type], CURLOPT_UPLOAD, True);
+ $hdrs[] = 'Transfer-Encoding: chunked';
+ } else {
+ # We know the Content-Length, so use regular transfer
+ #
+ curl_setopt($this->connections[$conn_type],
+ CURLOPT_INFILESIZE, $obj->content_length);
+ }
+ $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0,$this->error_str,NULL);
+ }
+ if ($return_code == 412) {
+ $this->error_str = "Missing Content-Type header";
+ return array($return_code,$this->error_str,NULL);
+ }
+ if ($return_code == 422) {
+ $this->error_str = "Derived and computed checksums do not match.";
+ return array($return_code,$this->error_str,NULL);
+ }
+ if ($return_code != 201) {
+ $this->error_str = "Unexpected HTTP return code: $return_code";
+ return array($return_code,$this->error_str,NULL);
+ }
+ return array($return_code,$this->response_reason,$this->_obj_etag);
+ }
+
+ # POST /v1/Account/Container/Object
+ #
+ function update_object(&$obj)
+ {
+ if (!is_object($obj) || get_class($obj) != "CF_Object") {
+ throw new SyntaxException(
+ "Method argument is not a valid CF_Object.");
+ }
+
+ # TODO: The is_array check isn't in sync with the error message
+ if (!$obj->manifest && !(is_array($obj->metadata) || is_array($obj->headers))) {
+ $this->error_str = "Metadata and headers arrays are empty.";
+ return 0;
+ }
+
+ $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+
+ $hdrs = $this->_headers($obj);
+ $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
+ switch ($return_code) {
+ case 202:
+ break;
+ case 0:
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ $return_code = 0;
+ break;
+ case 404:
+ $this->error_str = "Account, Container, or Object not found.";
+ break;
+ default:
+ $this->error_str = "Unexpected HTTP return code: $return_code";
+ break;
+ }
+ return $return_code;
+ }
+
+ # HEAD /v1/Account/Container/Object
+ #
+ function head_object(&$obj)
+ {
+ if (!is_object($obj) || get_class($obj) != "CF_Object") {
+ throw new SyntaxException(
+ "Method argument is not a valid CF_Object.");
+ }
+
+ $conn_type = "HEAD";
+
+ $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+ $return_code = $this->_send_request($conn_type,$url_path);
+
+ if (!$return_code) {
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ return array(0, $this->error_str." ".$this->response_reason,
+ NULL, NULL, NULL, NULL, array(), NULL, array());
+ }
+
+ if ($return_code == 404) {
+ return array($return_code, $this->response_reason,
+ NULL, NULL, NULL, NULL, array(), NULL, array());
+ }
+ if ($return_code == 204 || $return_code == 200) {
+ return array($return_code,$this->response_reason,
+ $this->_obj_etag,
+ $this->_obj_last_modified,
+ $this->_obj_content_type,
+ $this->_obj_content_length,
+ $this->_obj_metadata,
+ $this->_obj_manifest,
+ $this->_obj_headers);
+ }
+ $this->error_str = "Unexpected HTTP return code: $return_code";
+ return array($return_code, $this->error_str." ".$this->response_reason,
+ NULL, NULL, NULL, NULL, array(), NULL, array());
+ }
+
+ # COPY /v1/Account/Container/Object
+ #
+ function copy_object($src_obj_name, $dest_obj_name, $container_name_source, $container_name_target, $metadata=NULL, $headers=NULL)
+ {
+ if (!$src_obj_name) {
+ $this->error_str = "Object name not set.";
+ return 0;
+ }
+
+ if ($container_name_source == "") {
+ $this->error_str = "Container name source not set.";
+ return 0;
+ }
+
+ if ($container_name_source != "0" and !isset($container_name_source)) {
+ $this->error_str = "Container name source not set.";
+ return 0;
+ }
+
+ if ($container_name_target == "") {
+ $this->error_str = "Container name target not set.";
+ return 0;
+ }
+
+ if ($container_name_target != "0" and !isset($container_name_target)) {
+ $this->error_str = "Container name target not set.";
+ return 0;
+ }
+
+ $conn_type = "COPY";
+
+ $url_path = $this->_make_path("STORAGE", $container_name_source, rawurlencode($src_obj_name));
+ $destination = rawurlencode($container_name_target."/".$dest_obj_name);
+
+ $hdrs = self::_process_headers($metadata, $headers);
+ $hdrs[DESTINATION] = $destination;
+
+ $return_code = $this->_send_request($conn_type,$url_path,$hdrs,"COPY");
+ switch ($return_code) {
+ case 201:
+ break;
+ case 0:
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ $return_code = 0;
+ break;
+ case 404:
+ $this->error_str = "Specified container/object did not exist.";
+ break;
+ default:
+ $this->error_str = "Unexpected HTTP return code: $return_code.";
+ }
+ return $return_code;
+ }
+
+ # DELETE /v1/Account/Container/Object
+ #
+ function delete_object($container_name, $object_name)
+ {
+ if ($container_name == "") {
+ $this->error_str = "Container name not set.";
+ return 0;
+ }
+
+ if ($container_name != "0" and !isset($container_name)) {
+ $this->error_str = "Container name not set.";
+ return 0;
+ }
+
+ if (!$object_name) {
+ $this->error_str = "Object name not set.";
+ return 0;
+ }
+
+ $url_path = $this->_make_path("STORAGE", $container_name,$object_name);
+ $return_code = $this->_send_request("DEL_POST",$url_path,NULL,"DELETE");
+ switch ($return_code) {
+ case 204:
+ break;
+ case 0:
+ $this->error_str .= ": Failed to obtain valid HTTP response.";
+ $return_code = 0;
+ break;
+ case 404:
+ $this->error_str = "Specified container did not exist to delete.";
+ break;
+ default:
+ $this->error_str = "Unexpected HTTP return code: $return_code.";
+ }
+ return $return_code;
+ }
+
+ function get_error()
+ {
+ return $this->error_str;
+ }
+
+ function setDebug($bool)
+ {
+ $this->dbug = $bool;
+ foreach ($this->connections as $k => $v) {
+ if (!is_null($v)) {
+ curl_setopt($this->connections[$k], CURLOPT_VERBOSE, $this->dbug);
+ }
+ }
+ }
+
+ function getCDNMUrl()
+ {
+ return $this->cdnm_url;
+ }
+
+ function getStorageUrl()
+ {
+ return $this->storage_url;
+ }
+
+ function getAuthToken()
+ {
+ return $this->auth_token;
+ }
+
+ function setCFAuth($cfs_auth, $servicenet=False)
+ {
+ if ($servicenet) {
+ $this->storage_url = "https://snet-" . substr($cfs_auth->storage_url, 8);
+ } else {
+ $this->storage_url = $cfs_auth->storage_url;
+ }
+ $this->auth_token = $cfs_auth->auth_token;
+ $this->cdnm_url = $cfs_auth->cdnm_url;
+ }
+
+ function setReadProgressFunc($func_name)
+ {
+ $this->_user_read_progress_callback_func = $func_name;
+ }
+
+ function setWriteProgressFunc($func_name)
+ {
+ $this->_user_write_progress_callback_func = $func_name;
+ }
+
+ private function _header_cb($ch, $header)
+ {
+ $header_len = strlen($header);
+
+ if (preg_match("/^(HTTP\/1\.[01]) (\d{3}) (.*)/", $header, $matches)) {
+ $this->response_status = $matches[2];
+ $this->response_reason = $matches[3];
+ return $header_len;
+ }
+
+ if (strpos($header, ":") === False)
+ return $header_len;
+ list($name, $value) = explode(":", $header, 2);
+ $value = trim($value);
+
+ switch (strtolower($name)) {
+ case strtolower(CDN_ENABLED):
+ $this->_cdn_enabled = strtolower($value) == "true";
+ break;
+ case strtolower(CDN_URI):
+ $this->_cdn_uri = $value;
+ break;
+ case strtolower(CDN_SSL_URI):
+ $this->_cdn_ssl_uri = $value;
+ break;
+ case strtolower(CDN_STREAMING_URI):
+ $this->_cdn_streaming_uri = $value;
+ break;
+ case strtolower(CDN_TTL):
+ $this->_cdn_ttl = $value;
+ break;
+ case strtolower(MANIFEST_HEADER):
+ $this->_obj_manifest = $value;
+ break;
+ case strtolower(CDN_LOG_RETENTION):
+ $this->_cdn_log_retention = strtolower($value) == "true";
+ break;
+ case strtolower(CDN_ACL_USER_AGENT):
+ $this->_cdn_acl_user_agent = $value;
+ break;
+ case strtolower(CDN_ACL_REFERRER):
+ $this->_cdn_acl_referrer = $value;
+ break;
+ case strtolower(ACCOUNT_CONTAINER_COUNT):
+ $this->_account_container_count = (float)$value+0;
+ break;
+ case strtolower(ACCOUNT_BYTES_USED):
+ $this->_account_bytes_used = (float)$value+0;
+ break;
+ case strtolower(CONTAINER_OBJ_COUNT):
+ $this->_container_object_count = (float)$value+0;
+ break;
+ case strtolower(CONTAINER_BYTES_USED):
+ $this->_container_bytes_used = (float)$value+0;
+ break;
+ case strtolower(ETAG_HEADER):
+ $this->_obj_etag = $value;
+ break;
+ case strtolower(LAST_MODIFIED_HEADER):
+ $this->_obj_last_modified = $value;
+ break;
+ case strtolower(CONTENT_TYPE_HEADER):
+ $this->_obj_content_type = $value;
+ break;
+ case strtolower(CONTENT_LENGTH_HEADER):
+ $this->_obj_content_length = (float)$value+0;
+ break;
+ case strtolower(ORIGIN_HEADER):
+ $this->_obj_headers[ORIGIN_HEADER] = $value;
+ break;
+ default:
+ if (strncasecmp($name, METADATA_HEADER_PREFIX, strlen(METADATA_HEADER_PREFIX)) == 0) {
+ $name = substr($name, strlen(METADATA_HEADER_PREFIX));
+ $this->_obj_metadata[$name] = $value;
+ }
+ elseif ((strncasecmp($name, CONTENT_HEADER_PREFIX, strlen(CONTENT_HEADER_PREFIX)) == 0) ||
+ (strncasecmp($name, ACCESS_CONTROL_HEADER_PREFIX, strlen(ACCESS_CONTROL_HEADER_PREFIX)) == 0)) {
+ $this->_obj_headers[$name] = $value;
+ }
+ }
+ return $header_len;
+ }
+
+ private function _read_cb($ch, $fd, $length)
+ {
+ $data = fread($fd, $length);
+ $len = strlen($data);
+ if (isset($this->_user_write_progress_callback_func)) {
+ call_user_func($this->_user_write_progress_callback_func, $len);
+ }
+ return $data;
+ }
+
+ private function _write_cb($ch, $data)
+ {
+ $dlen = strlen($data);
+ switch ($this->_write_callback_type) {
+ case "TEXT_LIST":
+ $this->_return_list = $this->_return_list . $data;
+ //= explode("\n",$data); # keep tab,space
+ //his->_text_list[] = rtrim($data,"\n\r\x0B"); # keep tab,space
+ break;
+ case "OBJECT_STREAM":
+ fwrite($this->_obj_write_resource, $data, $dlen);
+ break;
+ case "OBJECT_STRING":
+ $this->_obj_write_string .= $data;
+ break;
+ }
+ if (isset($this->_user_read_progress_callback_func)) {
+ call_user_func($this->_user_read_progress_callback_func, $dlen);
+ }
+ return $dlen;
+ }
+
+ private function _auth_hdr_cb($ch, $header)
+ {
+ preg_match("/^HTTP\/1\.[01] (\d{3}) (.*)/", $header, $matches);
+ if (isset($matches[1])) {
+ $this->response_status = $matches[1];
+ }
+ if (isset($matches[2])) {
+ $this->response_reason = $matches[2];
+ }
+ if (stripos($header, STORAGE_URL) === 0) {
+ $this->storage_url = trim(substr($header, strlen(STORAGE_URL)+1));
+ }
+ if (stripos($header, CDNM_URL) === 0) {
+ $this->cdnm_url = trim(substr($header, strlen(CDNM_URL)+1));
+ }
+ if (stripos($header, AUTH_TOKEN) === 0) {
+ $this->auth_token = trim(substr($header, strlen(AUTH_TOKEN)+1));
+ }
+ if (stripos($header, AUTH_TOKEN_LEGACY) === 0) {
+ $this->auth_token = trim(substr($header,strlen(AUTH_TOKEN_LEGACY)+1));
+ }
+ return strlen($header);
+ }
+
+ private function _make_headers($hdrs=NULL)
+ {
+ $new_headers = array();
+ $has_stoken = False;
+ $has_uagent = False;
+ if (is_array($hdrs)) {
+ foreach ($hdrs as $h => $v) {
+ if (is_int($h)) {
+ list($h, $v) = explode(":", $v, 2);
+ }
+
+ if (strncasecmp($h, AUTH_TOKEN, strlen(AUTH_TOKEN)) === 0) {
+ $has_stoken = True;
+ }
+ if (strncasecmp($h, USER_AGENT_HEADER, strlen(USER_AGENT_HEADER)) === 0) {
+ $has_uagent = True;
+ }
+ $new_headers[] = $h . ": " . trim($v);
+ }
+ }
+ if (!$has_stoken) {
+ $new_headers[] = AUTH_TOKEN . ": " . $this->auth_token;
+ }
+ if (!$has_uagent) {
+ $new_headers[] = USER_AGENT_HEADER . ": " . USER_AGENT;
+ }
+ return $new_headers;
+ }
+
+ private function _init($conn_type, $force_new=False)
+ {
+ if (!array_key_exists($conn_type, $this->connections)) {
+ $this->error_str = "Invalid CURL_XXX connection type";
+ return False;
+ }
+
+ if (is_null($this->connections[$conn_type]) || $force_new) {
+ $ch = curl_init();
+ } else {
+ return;
+ }
+
+ if ($this->dbug) { curl_setopt($ch, CURLOPT_VERBOSE, 1); }
+
+ if (!is_null($this->cabundle_path)) {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
+ curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
+ }
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
+ curl_setopt($ch, CURLOPT_MAXREDIRS, 4);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$this, '_header_cb'));
+
+ if ($conn_type == "GET_CALL") {
+ curl_setopt($ch, CURLOPT_WRITEFUNCTION, array(&$this, '_write_cb'));
+ }
+
+ if ($conn_type == "PUT_OBJ") {
+ curl_setopt($ch, CURLOPT_PUT, 1);
+ curl_setopt($ch, CURLOPT_READFUNCTION, array(&$this, '_read_cb'));
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ }
+ if ($conn_type == "HEAD") {
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "HEAD");
+ curl_setopt($ch, CURLOPT_NOBODY, 1);
+ }
+ if ($conn_type == "PUT_CONT") {
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
+ curl_setopt($ch, CURLOPT_INFILESIZE, 0);
+ curl_setopt($ch, CURLOPT_NOBODY, 1);
+ }
+ if ($conn_type == "DEL_POST") {
+ curl_setopt($ch, CURLOPT_NOBODY, 1);
+ }
+ if ($conn_type == "COPY") {
+ curl_setopt($ch, CURLOPT_NOBODY, 1);
+ }
+ $this->connections[$conn_type] = $ch;
+ return;
+ }
+
+ private function _reset_callback_vars()
+ {
+ $this->_text_list = array();
+ $this->_return_list = NULL;
+ $this->_account_container_count = 0;
+ $this->_account_bytes_used = 0;
+ $this->_container_object_count = 0;
+ $this->_container_bytes_used = 0;
+ $this->_obj_etag = NULL;
+ $this->_obj_last_modified = NULL;
+ $this->_obj_content_type = NULL;
+ $this->_obj_content_length = NULL;
+ $this->_obj_metadata = array();
+ $this->_obj_manifest = NULL;
+ $this->_obj_headers = NULL;
+ $this->_obj_write_string = "";
+ $this->_cdn_streaming_uri = NULL;
+ $this->_cdn_enabled = NULL;
+ $this->_cdn_ssl_uri = NULL;
+ $this->_cdn_uri = NULL;
+ $this->_cdn_ttl = NULL;
+ $this->response_status = 0;
+ $this->response_reason = "";
+ }
+
+ private function _make_path($t="STORAGE",$c=NULL,$o=NULL)
+ {
+ $path = array();
+ switch ($t) {
+ case "STORAGE":
+ $path[] = $this->storage_url; break;
+ case "CDN":
+ $path[] = $this->cdnm_url; break;
+ }
+ if ($c == "0")
+ $path[] = rawurlencode($c);
+
+ if ($c) {
+ $path[] = rawurlencode($c);
+ }
+ if ($o) {
+ # mimic Python''s urllib.quote() feature of a "safe" '/' character
+ #
+ $path[] = str_replace("%2F","/",rawurlencode($o));
+ }
+ return implode("/",$path);
+ }
+
+ private function _headers(&$obj)
+ {
+ $hdrs = self::_process_headers($obj->metadata, $obj->headers);
+ if ($obj->manifest)
+ $hdrs[MANIFEST_HEADER] = $obj->manifest;
+
+ return $hdrs;
+ }
+
+ private function _process_headers($metadata=null, $headers=null)
+ {
+ $rules = array(
+ array(
+ 'prefix' => METADATA_HEADER_PREFIX,
+ ),
+ array(
+ 'prefix' => '',
+ 'filter' => array( # key order is important, first match decides
+ CONTENT_TYPE_HEADER => false,
+ CONTENT_LENGTH_HEADER => false,
+ CONTENT_HEADER_PREFIX => true,
+ ACCESS_CONTROL_HEADER_PREFIX => true,
+ ORIGIN_HEADER => true,
+ ),
+ ),
+ );
+
+ $hdrs = array();
+ $argc = func_num_args();
+ $argv = func_get_args();
+ for ($argi = 0; $argi < $argc; $argi++) {
+ if(!is_array($argv[$argi])) continue;
+
+ $rule = $rules[$argi];
+ foreach ($argv[$argi] as $k => $v) {
+ $k = trim($k);
+ $v = trim($v);
+ if (strpos($k, ":") !== False) throw new SyntaxException(
+ "Header names cannot contain a ':' character.");
+
+ if (array_key_exists('filter', $rule)) {
+ $result = null;
+ foreach ($rule['filter'] as $p => $f) {
+ if (strncasecmp($k, $p, strlen($p)) == 0) {
+ $result = $f;
+ break;
+ }
+ }
+ if (!$result) throw new SyntaxException(sprintf(
+ "Header name %s is not allowed", $k));
+ }
+
+ $k = $rule['prefix'] . $k;
+ if (strlen($k) > MAX_HEADER_NAME_LEN || strlen($v) > MAX_HEADER_VALUE_LEN)
+ throw new SyntaxException(sprintf(
+ "Header %s exceeds maximum length: %d/%d",
+ $k, strlen($k), strlen($v)));
+
+ $hdrs[$k] = $v;
+ }
+ }
+
+ return $hdrs;
+ }
+
+ private function _send_request($conn_type, $url_path, $hdrs=NULL, $method="GET", $force_new=False)
+ {
+ $this->_init($conn_type, $force_new);
+ $this->_reset_callback_vars();
+ $headers = $this->_make_headers($hdrs);
+
+ if (gettype($this->connections[$conn_type]) == "unknown type")
+ throw new ConnectionNotOpenException (
+ "Connection is not open."
+ );
+
+ switch ($method) {
+ case "COPY":
+ curl_setopt($this->connections[$conn_type],
+ CURLOPT_CUSTOMREQUEST, "COPY");
+ break;
+ case "DELETE":
+ curl_setopt($this->connections[$conn_type],
+ CURLOPT_CUSTOMREQUEST, "DELETE");
+ break;
+ case "POST":
+ curl_setopt($this->connections[$conn_type],
+ CURLOPT_CUSTOMREQUEST, "POST");
+ default:
+ break;
+ }
+
+ curl_setopt($this->connections[$conn_type],
+ CURLOPT_HTTPHEADER, $headers);
+
+ curl_setopt($this->connections[$conn_type],
+ CURLOPT_URL, $url_path);
+
+ if (!curl_exec($this->connections[$conn_type]) && curl_errno($this->connections[$conn_type]) !== 0) {
+ $this->error_str = "(curl error: "
+ . curl_errno($this->connections[$conn_type]) . ") ";
+ $this->error_str .= curl_error($this->connections[$conn_type]);
+ return False;
+ }
+ return curl_getinfo($this->connections[$conn_type], CURLINFO_HTTP_CODE);
+ }
+
+ function close()
+ {
+ foreach ($this->connections as $cnx) {
+ if (isset($cnx)) {
+ curl_close($cnx);
+ $this->connections[$cnx] = NULL;
+ }
+ }
+ }
+ private function create_array()
+ {
+ $this->_text_list = explode("\n",rtrim($this->_return_list,"\n\x0B"));
+ return True;
+ }
+
+}
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>