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
MediaWiki-CVS@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to