http://www.mediawiki.org/wiki/Special:Code/MediaWiki/99433
Revision: 99433
Author: reedy
Date: 2011-10-10 21:36:45 +0000 (Mon, 10 Oct 2011)
Log Message:
-----------
Noticed a couple of usages of undefined variables...
Not actually fixed, upgrade to 1.7.10
Modified Paths:
--------------
trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles.php
trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles_http.php
Modified: trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles.php
===================================================================
--- trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles.php 2011-10-10
21:33:00 UTC (rev 99432)
+++ trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles.php 2011-10-10
21:36:45 UTC (rev 99433)
@@ -208,7 +208,7 @@
if ($status == 401) {
throw new AuthenticationException("Invalid username or access
key.");
}
- if ($status != 204 && $status != 200) {
+ if ($status < 200 || $status > 299) {
throw new InvalidResponseException(
"Unexpected response (".$status."): ".$reason);
}
@@ -923,6 +923,7 @@
public $bytes_used;
public $cdn_enabled;
+ public $cdn_streaming_uri;
public $cdn_ssl_uri;
public $cdn_uri;
public $cdn_ttl;
@@ -961,6 +962,7 @@
$this->cdn_enabled = NULL;
$this->cdn_uri = NULL;
$this->cdn_ssl_uri = NULL;
+ $this->cdn_streaming_uri = NULL;
$this->cdn_ttl = NULL;
$this->cdn_log_retention = NULL;
$this->cdn_acl_user_agent = NULL;
@@ -1276,6 +1278,7 @@
$this->cdn_ttl = NULL;
$this->cdn_uri = NULL;
$this->cdn_ssl_uri = NULL;
+ $this->cdn_streaming_uri - NULL;
$this->cdn_log_retention = NULL;
$this->cdn_acl_user_agent = NULL;
$this->cdn_acl_referrer = NULL;
@@ -1493,6 +1496,235 @@
}
/**
+ * Copy a remote storage Object to a target Container
+ *
+ * Given an Object instance or name and a target Container instance or
name, copy copies the remote Object
+ * and all associated metadata.
+ *
+ * Example:
+ * <code>
+ * # ... authentication code excluded (see previous examples) ...
+ * #
+ * $conn = new CF_Authentication($auth);
+ *
+ * $images = $conn->get_container("my photos");
+ *
+ * # Copy specific object
+ * #
+ * $images->copy_object_to("disco_dancing.jpg","container_target");
+ * </code>
+ *
+ * @param obj $obj name or instance of Object to copy
+ * @param obj $container_target name or instance of target Container
+ * @param string $dest_obj_name name of target object (optional - uses
source name if omitted)
+ * @param array $metadata metadata array for new object (optional)
+ * @param array $headers header fields array for the new object (optional)
+ * @return boolean <kbd>true</kbd> if successfully copied
+ * @throws SyntaxException invalid Object/Container name
+ * @throws NoSuchObjectException remote Object does not exist
+ * @throws InvalidResponseException unexpected response
+ */
+ function
copy_object_to($obj,$container_target,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+ {
+ $obj_name = NULL;
+ if (is_object($obj)) {
+ if (get_class($obj) == "CF_Object") {
+ $obj_name = $obj->name;
+ }
+ }
+ if (is_string($obj)) {
+ $obj_name = $obj;
+ }
+ if (!$obj_name) {
+ throw new SyntaxException("Object name not set.");
+ }
+
+ if ($dest_obj_name === NULL) {
+ $dest_obj_name = $obj_name;
+ }
+
+ $container_name_target = NULL;
+ if (is_object($container_target)) {
+ if (get_class($container_target) == "CF_Container") {
+ $container_name_target = $container_target->name;
+ }
+ }
+ if (is_string($container_target)) {
+ $container_name_target = $container_target;
+ }
+ if (!$container_name_target) {
+ throw new SyntaxException("Container name target not set.");
+ }
+
+ $status =
$this->cfs_http->copy_object($obj_name,$dest_obj_name,$this->name,$container_name_target,$metadata,$headers);
+ if ($status == 404) {
+ $m = "Specified object '".$this->name."/".$obj_name;
+ $m.= "' did not exist as source to copy from or
'".$container_name_target."' did not exist as target to copy to.";
+ throw new NoSuchObjectException($m);
+ }
+ if ($status < 200 || $status > 299) {
+ throw new InvalidResponseException(
+ "Invalid response (".$status."):
".$this->cfs_http->get_error());
+ }
+ return true;
+ }
+
+ /**
+ * Copy a remote storage Object from a source Container
+ *
+ * Given an Object instance or name and a source Container instance or
name, copy copies the remote Object
+ * and all associated metadata.
+ *
+ * Example:
+ * <code>
+ * # ... authentication code excluded (see previous examples) ...
+ * #
+ * $conn = new CF_Authentication($auth);
+ *
+ * $images = $conn->get_container("my photos");
+ *
+ * # Copy specific object
+ * #
+ * $images->copy_object_from("disco_dancing.jpg","container_source");
+ * </code>
+ *
+ * @param obj $obj name or instance of Object to copy
+ * @param obj $container_source name or instance of source Container
+ * @param string $dest_obj_name name of target object (optional - uses
source name if omitted)
+ * @param array $metadata metadata array for new object (optional)
+ * @param array $headers header fields array for the new object (optional)
+ * @return boolean <kbd>true</kbd> if successfully copied
+ * @throws SyntaxException invalid Object/Container name
+ * @throws NoSuchObjectException remote Object does not exist
+ * @throws InvalidResponseException unexpected response
+ */
+ function
copy_object_from($obj,$container_source,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+ {
+ $obj_name = NULL;
+ if (is_object($obj)) {
+ if (get_class($obj) == "CF_Object") {
+ $obj_name = $obj->name;
+ }
+ }
+ if (is_string($obj)) {
+ $obj_name = $obj;
+ }
+ if (!$obj_name) {
+ throw new SyntaxException("Object name not set.");
+ }
+
+ if ($dest_obj_name === NULL) {
+ $dest_obj_name = $obj_name;
+ }
+
+ $container_name_source = NULL;
+ if (is_object($container_source)) {
+ if (get_class($container_source) == "CF_Container") {
+ $container_name_source = $container_source->name;
+ }
+ }
+ if (is_string($container_source)) {
+ $container_name_source = $container_source;
+ }
+ if (!$container_name_source) {
+ throw new SyntaxException("Container name source not set.");
+ }
+
+ $status =
$this->cfs_http->copy_object($obj_name,$dest_obj_name,$container_name_source,$this->name,$metadata,$headers);
+ if ($status == 404) {
+ $m = "Specified object '".$container_name_source."/".$obj_name;
+ $m.= "' did not exist as source to copy from or
'".$this->name."/".$obj_name."' did not exist as target to copy to.";
+ throw new NoSuchObjectException($m);
+ }
+ if ($status < 200 || $status > 299) {
+ throw new InvalidResponseException(
+ "Invalid response (".$status."):
".$this->cfs_http->get_error());
+ }
+
+ return true;
+ }
+
+ /**
+ * Move a remote storage Object to a target Container
+ *
+ * Given an Object instance or name and a target Container instance or
name, move copies the remote Object
+ * and all associated metadata and deletes the source Object afterwards
+ *
+ * Example:
+ * <code>
+ * # ... authentication code excluded (see previous examples) ...
+ * #
+ * $conn = new CF_Authentication($auth);
+ *
+ * $images = $conn->get_container("my photos");
+ *
+ * # Move specific object
+ * #
+ * $images->move_object_to("disco_dancing.jpg","container_target");
+ * </code>
+ *
+ * @param obj $obj name or instance of Object to move
+ * @param obj $container_target name or instance of target Container
+ * @param string $dest_obj_name name of target object (optional - uses
source name if omitted)
+ * @param array $metadata metadata array for new object (optional)
+ * @param array $headers header fields array for the new object (optional)
+ * @return boolean <kbd>true</kbd> if successfully moved
+ * @throws SyntaxException invalid Object/Container name
+ * @throws NoSuchObjectException remote Object does not exist
+ * @throws InvalidResponseException unexpected response
+ */
+ function
move_object_to($obj,$container_target,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+ {
+ $retVal = false;
+
+
if(self::copy_object_to($obj,$container_target,$dest_obj_name,$metadata,$headers))
{
+ $retVal = self::delete_object($obj,$this->name);
+ }
+
+ return $retVal;
+ }
+
+ /**
+ * Move a remote storage Object from a source Container
+ *
+ * Given an Object instance or name and a source Container instance or
name, move copies the remote Object
+ * and all associated metadata and deletes the source Object afterwards
+ *
+ * Example:
+ * <code>
+ * # ... authentication code excluded (see previous examples) ...
+ * #
+ * $conn = new CF_Authentication($auth);
+ *
+ * $images = $conn->get_container("my photos");
+ *
+ * # Move specific object
+ * #
+ * $images->move_object_from("disco_dancing.jpg","container_target");
+ * </code>
+ *
+ * @param obj $obj name or instance of Object to move
+ * @param obj $container_source name or instance of target Container
+ * @param string $dest_obj_name name of target object (optional - uses
source name if omitted)
+ * @param array $metadata metadata array for new object (optional)
+ * @param array $headers header fields array for the new object (optional)
+ * @return boolean <kbd>true</kbd> if successfully moved
+ * @throws SyntaxException invalid Object/Container name
+ * @throws NoSuchObjectException remote Object does not exist
+ * @throws InvalidResponseException unexpected response
+ */
+ function
move_object_from($obj,$container_source,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+ {
+ $retVal = false;
+
+
if(self::copy_object_from($obj,$container_source,$dest_obj_name,$metadata,$headers))
{
+ $retVal = self::delete_object($obj,$container_source);
+ }
+
+ return $retVal;
+ }
+
+ /**
* Delete a remote storage Object
*
* Given an Object instance or name, permanently remove the remote Object
@@ -1512,12 +1744,13 @@
* </code>
*
* @param obj $obj name or instance of Object to delete
+ * @param obj $container name or instance of Container in which the object
resides (optional)
* @return boolean <kbd>True</kbd> if successfully removed
* @throws SyntaxException invalid Object name
* @throws NoSuchObjectException remote Object does not exist
* @throws InvalidResponseException unexpected response
*/
- function delete_object($obj)
+ function delete_object($obj,$container=NULL)
{
$obj_name = NULL;
if (is_object($obj)) {
@@ -1531,12 +1764,32 @@
if (!$obj_name) {
throw new SyntaxException("Object name not set.");
}
- $status = $this->cfs_http->delete_object($this->name, $obj_name);
+
+ $container_name = NULL;
+
+ if($container === NULL) {
+ $container_name = $this->name;
+ }
+ else {
+ if (is_object($container)) {
+ if (get_class($container) == "CF_Container") {
+ $container_name = $container->name;
+ }
+ }
+ if (is_string($container)) {
+ $container_name = $container;
+ }
+ if (!$container_name) {
+ throw new SyntaxException("Container name source not set.");
+ }
+ }
+
+ $status = $this->cfs_http->delete_object($container_name, $obj_name);
#if ($status == 401 && $this->_re_auth()) {
# return $this->delete_object($obj);
#}
if ($status == 404) {
- $m = "Specified object '".$this->name."/".$obj_name;
+ $m = "Specified object '".$container_name."/".$obj_name;
$m.= "' did not exist to delete.";
throw new NoSuchObjectException($m);
}
@@ -1552,7 +1805,7 @@
*
* Given an Object whos name contains '/' path separators, this function
* will create the "directory marker" Objects of one byte with the
- * Content-Type of "application/folder".
+ * Content-Type of "application/directory".
*
* It assumes the last element of the full path is the "real" Object
* and does NOT create a remote storage Object for that last element.
@@ -1583,7 +1836,7 @@
*/
private function _cdn_initialize()
{
- list($status, $reason, $cdn_enabled, $cdn_ssl_uri, $cdn_uri, $cdn_ttl,
+ list($status, $reason, $cdn_enabled, $cdn_ssl_uri, $cdn_streaming_uri,
$cdn_uri, $cdn_ttl,
$cdn_log_retention, $cdn_acl_user_agent, $cdn_acl_referrer) =
$this->cfs_http->head_cdn_container($this->name);
#if ($status == 401 && $this->_re_auth()) {
@@ -1594,6 +1847,7 @@
"Invalid response (".$status."):
".$this->cfs_http->get_error());
}
$this->cdn_enabled = $cdn_enabled;
+ $this->cdn_streaming_uri = $cdn_streaming_uri;
$this->cdn_ssl_uri = $cdn_ssl_uri;
$this->cdn_uri = $cdn_uri;
$this->cdn_ttl = $cdn_ttl;
@@ -1634,6 +1888,7 @@
public $content_type;
public $content_length;
public $metadata;
+ public $headers;
public $manifest;
private $etag;
@@ -1663,6 +1918,7 @@
$this->content_type = NULL;
$this->content_length = 0;
$this->metadata = array();
+ $this->headers = array();
$this->manifest = NULL;
if ($dohead) {
if (!$this->_initialize() && $force_exists) {
@@ -1800,6 +2056,31 @@
}
return NULL;
}
+ /**
+ * String representation of the Object's public Streaming URI
+ *
+ * A string representing the Object's public Streaming URI assuming that
it's
+ * parent Container is CDN-enabled.
+ *
+ * Example:
+ * <code>
+ * # ... authentication/connection/container code excluded
+ * # ... see previous examples
+ *
+ * # Print out the Object's CDN Streaming URI (if it has one) in an HTML
img-tag
+ * #
+ * print "<img src='$pic->public_streaming_uri()' />\n";
+ * </code>
+ *
+ * @return string Object's public Streaming URI or NULL
+ */
+ function public_streaming_uri()
+ {
+ if ($this->container->cdn_enabled) {
+ return $this->container->cdn_streaming_uri . "/" . $this->name;
+ }
+ return NULL;
+ }
/**
* Read the remote Object's data
@@ -1923,6 +2204,12 @@
* "Version" => "1.2.2"
* );
*
+ * # Define additional headers for the object
+ * #
+ * $doc->headers = array(
+ * "Content-Disposition" => "attachment",
+ * );
+ *
* # Push the new metadata up to the storage system
* #
* $doc->sync_metadata();
@@ -1933,7 +2220,7 @@
*/
function sync_metadata()
{
- if (!empty($this->metadata) || $this->manifest) {
+ if (!empty($this->metadata) || !empty($this->headers) ||
$this->manifest) {
$status = $this->container->cfs_http->update_object($this);
#if ($status == 401 && $this->_re_auth()) {
# return $this->sync_metadata();
@@ -1976,8 +2263,8 @@
function sync_manifest()
{
return $this->sync_metadata();
- }
- /**
+ }
+ /**
* Upload Object's data to Cloud Files
*
* Write data to the remote Object. The $data argument can either be a
@@ -2074,54 +2361,6 @@
return True;
}
- /**
- * Copy one Object to another Object to Cloud Files
- *
- * Example:
- * <code>
- * # ... authentication/connection/container code excluded
- * # ... see previous examples
- *
- * $my_docs = $conn->get_container("documents");
- * $doc = $my_docs->get_object("README");
- *
- * # Copy README.txt on top of this object (which you must have
- * already written something to).
- * #
- * $doc->copy("/documents/README.txt");
- * </code>
- *
- * @param string $source Name of existing object
- * @return boolean <kbd>True</kbd> when data uploaded successfully
- * @throws SyntaxException missing required parameters
- * @throws BadContentTypeException if no Content-Type was/could be set
- * @throws MisMatchedChecksumException $verify is set and checksums unequal
- * @throws InvalidResponseException unexpected response
- */
- function copy($source)
- {
- if (!$source && !is_string($source)) {
- throw new SyntaxException("Missing data source.");
- }
- list($status, $reason, $etag) =
- $this->container->cfs_http->put_object($this, $source);
- #if ($status == 401 && $this->_re_auth()) {
- # return $this->copy($data, $source);
- #}
- if ($status == 412) {
- throw new SyntaxException("Missing Content-Type header");
- }
- if ($status == 422) {
- throw new MisMatchedChecksumException(
- "Supplied and computed checksums do not match.");
- }
- if ($status != 201) {
- throw new InvalidResponseException("Invalid response
(".$status."): "
- . $this->container->cfs_http->get_error());
- }
- return True;
- }
-
/**
* Upload Object data from local filename
*
@@ -2305,8 +2544,8 @@
private function _initialize()
{
list($status, $reason, $etag, $last_modified, $content_type,
- $content_length, $metadata) =
- $this->container->cfs_http->head_object($this);
+ $content_length, $metadata, $manifest, $headers) =
+ $this->container->cfs_http->head_object($this);
#if ($status == 401 && $this->_re_auth()) {
# return $this->_initialize();
#}
@@ -2322,7 +2561,8 @@
$this->content_type = $content_type;
$this->content_length = $content_length;
$this->metadata = $metadata;
- $this->manifest = NULL;
+ $this->headers = $headers;
+ $this->manifest = $manifest;
return True;
}
@@ -2349,4 +2589,4 @@
* c-hanging-comment-ender-p: nil
* End:
*/
-?>
+?>
\ No newline at end of file
Modified: trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles_http.php
===================================================================
--- trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles_http.php
2011-10-10 21:33:00 UTC (rev 99432)
+++ trunk/extensions/SwiftMedia/php-cloudfiles/cloudfiles_http.php
2011-10-10 21:36:45 UTC (rev 99433)
@@ -29,16 +29,22 @@
*/
require_once("cloudfiles_exceptions.php");
-define("PHP_CF_VERSION", "1.7.9");
+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("METADATA_HEADER", "X-Object-Meta-");
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");
@@ -53,6 +59,13 @@
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
*
@@ -95,11 +108,13 @@
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;
@@ -131,6 +146,7 @@
"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;
@@ -150,8 +166,10 @@
$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;
@@ -212,7 +230,6 @@
curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, True);
curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
}
- curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, False);
curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
curl_setopt($curl_ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl_ch, CURLOPT_MAXREDIRS, 4);
@@ -249,7 +266,7 @@
}
if (!$return_code) {
$this->error_str .= ": Failed to obtain valid HTTP response.";
- array(0,$this->error_str,array());
+ return array(0,$this->error_str,array());
}
if ($return_code == 401) {
return array($return_code,"Unauthorized",array());
@@ -393,17 +410,18 @@
if (!$return_code) {
$this->error_str .= ": Failed to obtain valid HTTP response.";
- return array(0,$this->error_str,NULL,NULL,NULL,NULL,NULL,NULL);
+ 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);
+ 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);
+ 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,
@@ -411,10 +429,11 @@
);
}
return array($return_code,$this->response_reason,
- NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL,
$this->_cdn_log_retention,
$this->_cdn_acl_user_agent,
- $this->_cdn_acl_referrer
+ $this->_cdn_acl_referrer,
+ NULL
);
}
@@ -511,7 +530,7 @@
if (!$return_code) {
$this->error_str .= ": Failed to obtain valid HTTP response.";
- array(0,$this->error_str,0,0);
+ return array(0,$this->error_str,0,0);
}
if ($return_code == 404) {
return array($return_code,"Account not found.",0,0);
@@ -556,16 +575,19 @@
$url_path = $this->_make_path("STORAGE", $container_name);
$return_code =
$this->_send_request("DEL_POST",$url_path,array(),"DELETE");
- if (!$return_code) {
- $this->error_str .= ": Failed to obtain valid HTTP response.";
- }
- if ($return_code == 409) {
+ 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.";
- }
- if ($return_code == 404) {
+ break;
+ case 404:
$this->error_str = "Specified container did not exist to delete.";
- }
- if ($return_code != 204) {
+ break;
+ default:
$this->error_str = "Unexpected HTTP return code: $return_code.";
}
return $return_code;
@@ -701,7 +723,7 @@
if (!$return_code) {
$this->error_str .= ": Failed to obtain valid HTTP response.";
- array(0,$this->error_str,0,0);
+ return array(0,$this->error_str,0,0);
}
if ($return_code == 404) {
return array($return_code,"Container not found.",0,0);
@@ -788,10 +810,7 @@
throw new SyntaxException(
"Method argument is not a valid CF_Object.");
}
- $source = NULL;
- if (is_string($fp)) {
- $source = $fp;
- } elseif (!is_resource($fp)) {
+ if (!is_resource($fp)) {
throw new SyntaxException(
"File pointer argument is not a valid resource.");
}
@@ -799,40 +818,32 @@
$conn_type = "PUT_OBJ";
$url_path = $this->_make_path("STORAGE",
$obj->container->name,$obj->name);
- $hdrs = $this->_metadata_headers($obj);
+ $hdrs = $this->_headers($obj);
$etag = $obj->getETag();
- if (!$source && isset($etag)) {
+ if (isset($etag)) {
$hdrs[] = "ETag: " . $etag;
}
- if ($source) {
- // If we don't include a content-type it will copy over the
existing one.
- } elseif (!$obj->content_type) {
+ if (!$obj->content_type) {
$hdrs[] = "Content-Type: application/octet-stream";
} else {
$hdrs[] = "Content-Type: " . $obj->content_type;
}
$this->_init($conn_type);
- if ($source) {
- $hdrs[] = "X-Copy-From: " . rawurlencode($source);
+ 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, 0);
- } else {
- 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);
- }
- }
+ CURLOPT_INFILESIZE, $obj->content_length);
+ }
$return_code = $this->_send_request($conn_type,$url_path,$hdrs);
if (!$return_code) {
@@ -863,25 +874,29 @@
"Method argument is not a valid CF_Object.");
}
- if (!is_array($obj->metadata) && !$obj->manifest) {
-
- $this->error_str = "Metadata array is empty.";
+ # 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->_metadata_headers($obj);
+ $hdrs = $this->_headers($obj);
$return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
- if (!$return_code) {
+ switch ($return_code) {
+ case 202:
+ break;
+ case 0:
$this->error_str .= ": Failed to obtain valid HTTP response.";
- return 0;
- }
- if ($return_code == 404) {
+ $return_code = 0;
+ break;
+ case 404:
$this->error_str = "Account, Container, or Object not found.";
- }
- if ($return_code != 202) {
+ break;
+ default:
$this->error_str = "Unexpected HTTP return code: $return_code";
+ break;
}
return $return_code;
}
@@ -903,12 +918,12 @@
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, NULL, NULL, NULL, array(), NULL, array());
}
if ($return_code == 404) {
return array($return_code, $this->response_reason,
- NULL, NULL, NULL, NULL, array());
+ NULL, NULL, NULL, NULL, array(), NULL, array());
}
if ($return_code == 204 || $return_code == 200) {
return array($return_code,$this->response_reason,
@@ -917,13 +932,68 @@
$this->_obj_content_type,
$this->_obj_content_length,
$this->_obj_metadata,
- $this->_obj_manifest);
+ $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, 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)
@@ -945,14 +1015,17 @@
$url_path = $this->_make_path("STORAGE", $container_name,$object_name);
$return_code =
$this->_send_request("DEL_POST",$url_path,NULL,"DELETE");
- if (!$return_code) {
+ switch ($return_code) {
+ case 204:
+ break;
+ case 0:
$this->error_str .= ": Failed to obtain valid HTTP response.";
- return 0;
- }
- if ($return_code == 404) {
+ $return_code = 0;
+ break;
+ case 404:
$this->error_str = "Specified container did not exist to delete.";
- }
- if ($return_code != 204) {
+ break;
+ default:
$this->error_str = "Unexpected HTTP return code: $return_code.";
}
return $return_code;
@@ -1011,112 +1084,85 @@
private function _header_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, CDN_ENABLED) === 0) {
- $val = trim(substr($header, strlen(CDN_ENABLED)+1));
- if (strtolower($val) == "true") {
- $this->_cdn_enabled = True;
- } elseif (strtolower($val) == "false") {
- $this->_cdn_enabled = False;
- } else {
- $this->_cdn_enabled = NULL;
- }
- return strlen($header);
- }
- if (stripos($header, CDN_URI) === 0) {
- $this->_cdn_uri = trim(substr($header, strlen(CDN_URI)+1));
- return strlen($header);
- }
- if (stripos($header, CDN_SSL_URI) === 0) {
- $this->_cdn_ssl_uri = trim(substr($header, strlen(CDN_SSL_URI)+1));
- return strlen($header);
- }
- if (stripos($header, CDN_TTL) === 0) {
- $this->_cdn_ttl = trim(substr($header, strlen(CDN_TTL)+1))+0;
- return strlen($header);
- }
- if (stripos($header, MANIFEST_HEADER) === 0) {
- $this->_obj_manifest = trim(substr($header,
strlen(MANIFEST_HEADER)+1));
- return strlen($header);
- }
- if (stripos($header, CDN_LOG_RETENTION) === 0) {
- $this->_cdn_log_retention =
- trim(substr($header, strlen(CDN_LOG_RETENTION)+1)) == "True" ?
True : False;
- return strlen($header);
- }
+ $header_len = strlen($header);
- if (stripos($header, CDN_ACL_USER_AGENT) === 0) {
- $this->_cdn_acl_user_agent =
- trim(substr($header, strlen(CDN_ACL_USER_AGENT)+1));
- return 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 (stripos($header, CDN_ACL_REFERRER) === 0) {
- $this->_cdn_acl_referrer =
- trim(substr($header, strlen(CDN_ACL_REFERRER)+1));
- return strlen($header);
+ 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;
+ }
}
-
- if (stripos($header, ACCOUNT_CONTAINER_COUNT) === 0) {
- $this->_account_container_count = (float) trim(substr($header,
- strlen(ACCOUNT_CONTAINER_COUNT)+1))+0;
- return strlen($header);
- }
- if (stripos($header, ACCOUNT_BYTES_USED) === 0) {
- $this->_account_bytes_used = (float) trim(substr($header,
- strlen(ACCOUNT_BYTES_USED)+1))+0;
- return strlen($header);
- }
- if (stripos($header, CONTAINER_OBJ_COUNT) === 0) {
- $this->_container_object_count = (float) trim(substr($header,
- strlen(CONTAINER_OBJ_COUNT)+1))+0;
- return strlen($header);
- }
- if (stripos($header, CONTAINER_BYTES_USED) === 0) {
- $this->_container_bytes_used = (float) trim(substr($header,
- strlen(CONTAINER_BYTES_USED)+1))+0;
- return strlen($header);
- }
- if (stripos($header, METADATA_HEADER) === 0) {
- # $header => X-Object-Meta-Foo: bar baz
- $temp = substr($header, strlen(METADATA_HEADER));
- # $temp => Foo: bar baz
- $parts = explode(":", $temp);
- # $parts[0] => Foo
- $val = substr(strstr($temp, ":"), 1);
- # $val => bar baz
- $this->_obj_metadata[$parts[0]] = trim($val);
- return strlen($header);
- }
- if (stripos($header, "ETag:") === 0) {
- # $header => ETag: abc123def456...
- $val = substr(strstr($header, ":"), 1);
- # $val => abc123def456...
- $this->_obj_etag = trim($val);
- return strlen($header);
- }
- if (stripos($header, "Last-Modified:") === 0) {
- $val = substr(strstr($header, ":"), 1);
- $this->_obj_last_modified = trim($val);
- return strlen($header);
- }
- if (stripos($header, "Content-Type:") === 0) {
- $val = substr(strstr($header, ":"), 1);
- $this->_obj_content_type = trim($val);
- return strlen($header);
- }
- if (stripos($header, "Content-Length:") === 0) {
- $val = substr(strstr($header, ":"), 1);
- $this->_obj_content_length = (float) trim($val)+0;
- return strlen($header);
- }
- return strlen($header);
+ return $header_len;
}
private function _read_cb($ch, $fd, $length)
@@ -1183,28 +1229,23 @@
if (is_array($hdrs)) {
foreach ($hdrs as $h => $v) {
if (is_int($h)) {
- $parts = explode(":", $v);
- $header = $parts[0];
- $value = trim(substr(strstr($v, ":"), 1));
- } else {
- $header = $h;
- $value = trim($v);
+ list($h, $v) = explode(":", $v, 2);
}
- if (stripos($header, AUTH_TOKEN) === 0) {
+ if (strncasecmp($h, AUTH_TOKEN, strlen(AUTH_TOKEN)) === 0) {
$has_stoken = True;
}
- if (stripos($header, "user-agent") === 0) {
+ if (strncasecmp($h, USER_AGENT_HEADER,
strlen(USER_AGENT_HEADER)) === 0) {
$has_uagent = True;
}
- $new_headers[] = $header . ": " . $value;
+ $new_headers[] = $h . ": " . trim($v);
}
}
if (!$has_stoken) {
$new_headers[] = AUTH_TOKEN . ": " . $this->auth_token;
}
if (!$has_uagent) {
- $new_headers[] = "User-Agent: " . USER_AGENT;
+ $new_headers[] = USER_AGENT_HEADER . ": " . USER_AGENT;
}
return $new_headers;
}
@@ -1228,7 +1269,7 @@
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
}
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, False);
+ 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);
@@ -1256,6 +1297,9 @@
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;
}
@@ -1274,7 +1318,9 @@
$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;
@@ -1306,30 +1352,71 @@
return implode("/",$path);
}
- private function _metadata_headers(&$obj)
+ private function _headers(&$obj)
{
- $hdrs = array();
+ $hdrs = self::_process_headers($obj->metadata, $obj->headers);
if ($obj->manifest)
$hdrs[MANIFEST_HEADER] = $obj->manifest;
- foreach ($obj->metadata as $k => $v) {
- if (strpos($k,":") !== False) {
- throw new SyntaxException(
- "Metadata keys cannot contain a ':' character.");
- }
- $k = trim($k);
- $key = sprintf("%s%s", METADATA_HEADER, $k);
- if (!array_key_exists($key, $hdrs)) {
- if (strlen($k) > 128 || strlen($v) > 256) {
- $this->error_str = "Metadata key or value exceeds ";
- $this->error_str .= "maximum length: ($k: $v)";
- return 0;
+
+ 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));
}
- $hdrs[] = sprintf("%s%s: %s", METADATA_HEADER, $k, trim($v));
+
+ $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);
@@ -1342,6 +1429,10 @@
);
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");
@@ -1394,4 +1485,4 @@
* c-hanging-comment-ender-p: nil
* End:
*/
-?>
+?>
\ No newline at end of file
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs