Plugin Directory

Changeset 164970


Ignore:
Timestamp:
10/19/2009 07:49:04 PM (16 years ago)
Author:
reaperhulk
Message:

0.94 release

Location:
cdn-tools
Files:
12 added
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • cdn-tools/tags/0.94/cdn_classes/cloudfiles/cloudfiles.php

    r118371 r164970  
    3131 *   $bday = $images->create_object("first_birthday.jpg");
    3232 *
    33  *   # Upload content from a local file by streaming it
     33 *   # Upload content from a local file by streaming it.  Note that we use
     34 *   # a "float" for the file size to overcome PHP's 32-bit integer limit for
     35 *   # very large files.
    3436 *   #
    3537 *   $fname = "/home/user/photos/birthdays/birthday1.jpg";  # filename to upload
     
    328330     * Cloud Files account information
    329331     *
    330      * Return an array of two integers (or possibly floats if the value
    331      * overflows PHP's 32-bit integer); number of containers on the account
    332      * and total bytes used for the account.
     332     * Return an array of two floats (since PHP only supports 32-bit integers);
     333     * number of containers on the account and total bytes used for the account.
    333334     *
    334335     * Example:
     
    390391            throw new SyntaxException($r);
    391392        }
    392         if (strpos($container_name, "?") !== False) {
    393             $r = "Container name '".$container_name;
    394             $r .= "' cannot contain a '?' character.";
    395             throw new SyntaxException($r);
    396         }
    397         if (mb_strlen($container_name, "UTF-8") > MAX_CONTAINER_NAME_LEN) {
     393        if (strlen($container_name) > MAX_CONTAINER_NAME_LEN) {
    398394            throw new SyntaxException(sprintf(
    399                 "Container name exeeds %d characters.",
     395                "Container name exeeds %d bytes.",
    400396                MAX_CONTAINER_NAME_LEN));
    401397        }
     
    441437    function delete_container($container=NULL)
    442438    {
     439        $container_name = NULL;
     440       
    443441        if (is_object($container)) {
    444442            if (get_class($container) == "CF_Container") {
     
    541539     * @throws InvalidResponseException unexpected response
    542540     */
    543     function get_containers()
     541    function get_containers($limit=0, $marker=NULL)
    544542    {
    545543        list($status, $reason, $container_info) =
    546                 $this->cfs_http->list_containers_info();
     544                $this->cfs_http->list_containers_info($limit, $marker);
    547545        #if ($status == 401 && $this->_re_auth()) {
    548546        #    return $this->get_containers();
     
    555553        foreach ($container_info as $name => $info) {
    556554            $containers[] = new CF_Container($this->cfs_auth, $this->cfs_http,
    557                 $name, $info["count"], $info["bytes"], False);
     555                $info['name'], $info["count"], $info["bytes"], False);
    558556        }
    559557        return $containers;
     
    816814 * Objects stored in the Container are publicly available via the CDN.
    817815 *
    818  * NOTE: Due to the possible overflow of PHP's 32-bit integer, the Container's
    819  *       object_count and bytes_used instance variables may either be a
    820  *       integer or float.
    821  *
    822816 * @package php-cloudfiles
    823817 */
     
    833827    public $cdn_uri;
    834828    public $cdn_ttl;
     829    public $cdn_log_retention;
    835830
    836831    /**
     
    849844        $bytes=0, $docdn=True)
    850845    {
    851         if (mb_strlen($name, "UTF-8") > MAX_CONTAINER_NAME_LEN) {
     846        if (strlen($name) > MAX_CONTAINER_NAME_LEN) {
    852847            throw new SyntaxException("Container name exceeds "
    853848                . "maximum allowed length.");
     
    865860        $this->cdn_uri = NULL;
    866861        $this->cdn_ttl = NULL;
     862        $this->cdn_log_retention = NULL;
    867863        if ($this->cfs_http->getCDNMUrl() != NULL && $docdn) {
    868864            $this->_cdn_initialize();
     
    882878            $this->name, $this->object_count, $this->bytes_used);
    883879        if ($this->cfs_http->getCDNMUrl() != NULL) {
    884             $me .= sprintf(", cdn: %s, cdn uri: %s, cdn ttl: %.0f",
     880            $me .= sprintf(", cdn: %s, cdn uri: %s, cdn ttl: %.0f logs retention: %s",
    885881                $this->is_public() ? "Yes" : "No",
    886                 $this->cdn_uri, $this->cdn_ttl);
     882                $this->cdn_uri, $this->cdn_ttl,
     883                $this->cdn_log_retention ? "Yes" : "No"
     884                );
    887885        }
    888886        return $me;
     
    906904     * # CDN-enable the container and set it's TTL for a month
    907905     * #
    908      * $public_container->make_public(86400*30); # 30 days (86400 seconds/day)
     906     * $public_container->make_public(86400/2); # 12 hours (86400 seconds/day)
    909907     * </code>
    910908     *
     
    924922            # previously published, assume we're setting new attributes
    925923            list($status, $reason, $cdn_uri) =
    926                 $this->cfs_http->update_cdn_container($this->name,$ttl);
     924                $this->cfs_http->update_cdn_container($this->name,$ttl,$this->cdn_log_retention);
    927925            #if ($status == 401 && $this->_re_auth()) {
    928926            #    return $this->make_public($ttl);
     
    950948        $this->cdn_ttl = $ttl;
    951949        $this->cdn_uri = $cdn_uri;
     950        $this->cdn_log_retention = False;
    952951        return $this->cdn_uri;
    953952    }
    954953
     954    function log_retention($cdn_log_retention=False) {
     955        if ($this->cfs_http->getCDNMUrl() == NULL) {
     956            throw new CDNNotEnabledException(
     957                "Authentication response did not indicate CDN availability");
     958        }
     959        list($status,$reason) =
     960            $this->cfs_http->update_cdn_container($this->name,
     961                                                  $this->cdn_ttl,
     962                                                  $cdn_log_retention);
     963        if (!in_array($status, array(202,404))) {
     964            throw new InvalidResponseException(
     965                "Invalid response (".$status."): ".$this->cfs_http->get_error());
     966        }
     967        $this->cdn_log_retention = $cdn_log_retention;
     968    }
     969   
    955970    /**
    956971     * Disable the CDN sharing for this container
     
    10001015        $this->cdn_ttl = NULL;
    10011016        $this->cdn_uri = NULL;
     1017        $this->cdn_log_retention = NULL;
    10021018        return True;
    10031019    }
     
    11041120     * #
    11051121     * $first_ten = $images->list_objects(10);
    1106      * $next_ten = $images->list_objects(10,10);
     1122     *
     1123     * # Note the use of the previous result's last object name being
     1124     * # used as the 'marker' parameter to fetch the next 10 objects
     1125     * #
     1126     * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
    11071127     *
    11081128     * # Grab images starting with "birthday_party" and default limit/marker
     
    11591179     * #
    11601180     * $first_ten = $images->get_objects(10);
    1161      * $next_ten = $images->get_objects(10,10);
     1181     *
     1182     * # Note the use of the previous result's last object name being
     1183     * # used as the 'marker' parameter to fetch the next 10 objects
     1184     * #
     1185     * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
    11621186     *
    11631187     * # Grab images starting with "birthday_party" and default limit/marker
     
    11971221            $tmp = new CF_Object($this, $obj["name"], False, False);
    11981222            $tmp->content_type = $obj["content_type"];
    1199             $tmp->content_length = $obj["bytes"];
     1223            $tmp->content_length = (float) $obj["bytes"];
    12001224            $tmp->set_etag($obj["hash"]);
     1225            $tmp->last_modified = $obj["last_modified"];
    12011226            $objects[] = $tmp;
    12021227        }
     
    12721297    {
    12731298        if ($path_name[0] == '/') {
    1274             $path_name = mb_substr($path_name, 1);
     1299            $path_name = mb_substr($path_name, 0, 1);
    12751300        }
    12761301        $elements = explode('/', $path_name, -1);
     
    12951320    private function _cdn_initialize()
    12961321    {
    1297         list($status, $reason, $cdn_enabled, $cdn_uri, $cdn_ttl) =
     1322        list($status, $reason, $cdn_enabled, $cdn_uri, $cdn_ttl, $cdn_log_retention) =
    12981323            $this->cfs_http->head_cdn_container($this->name);
    12991324        #if ($status == 401 && $this->_re_auth()) {
     
    13071332        $this->cdn_uri = $cdn_uri;
    13081333        $this->cdn_ttl = $cdn_ttl;
     1334        $this->cdn_log_retention = $cdn_log_retention;
    13091335    }
    13101336
     
    13571383            throw new SyntaxException($r);
    13581384        }
    1359         if (mb_strlen($name, "UTF-8") > MAX_OBJECT_NAME_LEN) {
     1385        if (strlen($name) > MAX_OBJECT_NAME_LEN) {
    13601386            throw new SyntaxException("Object name exceeds "
    13611387                . "maximum allowed length.");
     
    13891415
    13901416    /**
     1417     * Internal check to get the proper mimetype.
     1418     *
     1419     * This function would go over the available PHP methods to get
     1420     * the MIME type.
     1421     *
     1422     * By default it will try to use the PHP fileinfo library which is
     1423     * available from PHP 5.3 or as an PECL extension
     1424     * (http://pecl.php.net/package/Fileinfo).
     1425     *
     1426     * It will get the magic file by default from the system wide file
     1427     * which is usually available in /usr/share/magic on Unix or try
     1428     * to use the file specified in the source directory of the API
     1429     * (share directory).
     1430     *
     1431     * if fileinfo is not available it will try to use the internal
     1432     * mime_content_type function.
     1433     *
     1434     * @param string $handle name of file or buffer to guess the type from
     1435     * @return boolean <kbd>True</kbd> if successful
     1436     * @throws BadContentTypeException
     1437     */
     1438    function _guess_content_type($handle) {
     1439        if ($this->content_type)
     1440            return;
     1441           
     1442        if (function_exists("finfo_open")) {
     1443            $local_magic = dirname(__FILE__) . "/share/magic";
     1444            $finfo = @finfo_open(FILEINFO_MIME, $local_magic);
     1445
     1446            if (!$finfo)
     1447                $finfo = @finfo_open(FILEINFO_MIME);
     1448               
     1449            if ($finfo) {
     1450
     1451                if (is_file((string)$handle))
     1452                    $ct = @finfo_file($finfo, $handle);
     1453                else
     1454                    $ct = @finfo_buffer($finfo, $handle);
     1455
     1456                /* PHP 5.3 fileinfo display extra information like
     1457                   charset so we remove everything after the ; since
     1458                   we are not into that stuff */
     1459                if ($ct) {
     1460                    $extra_content_type_info = strpos($ct, "; ");
     1461                    if ($extra_content_type_info)
     1462                        $ct = substr($ct, 0, $extra_content_type_info);
     1463                }
     1464
     1465                if ($ct && $ct != 'application/octet-stream')
     1466                    $this->content_type = $ct;
     1467
     1468                @finfo_close($finfo);
     1469            }
     1470        }
     1471
     1472        if (!$this->content_type && (string)is_file($handle) && function_exists("mime_content_type")) {
     1473            $this->content_type = @mime_content_type($handle);
     1474        }
     1475
     1476        if (!$this->content_type) {
     1477            throw new BadContentTypeException("Required Content-Type not set");
     1478        }
     1479        return True;
     1480    }
     1481   
     1482    /**
    13911483     * String representation of the Object's public URI
    13921484     *
     
    15861678     * @return boolean <kbd>True</kbd> when data uploaded successfully
    15871679     * @throws SyntaxException missing required parameters
     1680     * @throws BadContentTypeException if no Content-Type was/could be set
    15881681     * @throws MisMatchedChecksumException $verify is set and checksums unequal
    15891682     * @throws InvalidResponseException unexpected response
     
    16111704            # a temporary file instead.
    16121705            #
    1613             #$fp = fopen("php://temp", "rb+");
    1614             $fp = fopen("php://memory", "rb+");
    1615             fwrite($fp, $data);
     1706            $fp = fopen("php://temp", "wb+");
     1707            #$fp = fopen("php://memory", "wb+");
     1708            fwrite($fp, $data, strlen($data));
    16161709            rewind($fp);
    16171710            $close_fh = True;
    1618             $this->content_length = (float) mb_strlen($data);
     1711            $this->content_length = (float) strlen($data);
    16191712            if ($this->content_length > MAX_OBJECT_SIZE) {
    16201713                throw new SyntaxException("Data exceeds maximum object size");
    16211714            }
     1715            $ct_data = substr($data, 0, 64);
    16221716        } else {
    16231717            $this->content_length = $bytes;
    16241718            $fp = $data;
    1625         }
    1626 
    1627         /* FIXME: test if this works with string AND resource (or string only) */
    1628         if (!$this->content_type) {
    1629             if (function_exists("finfo_open")) {
    1630                 $finfo = False;
    1631                 try {
    1632                     $finfo = @finfo_open(FILEINFO_MIME);
    1633                 } catch (Exception $e) {
    1634                     try {
    1635                         $my_mime = dirname(__FILE__) . "/magic";
    1636                         $finfo = @finfo_open(FILEINFO_MIME, $my_mime);
    1637                     } catch (Exception $se) {
    1638                         $finfo = False;
    1639                     }
    1640                 }
    1641                 if (!$finfo) {
    1642                     $this->content_type = "application/octet-stream";
    1643                 } else {
    1644                     $ct = finfo_buffer($finfo, $data);
    1645                     finfo_close($finfo);
    1646                     if (!$ct) {
    1647                         $this->content_type = "application/octet-stream";
    1648                     } else {
    1649                         $this->content_type = $ct;
    1650                     }
    1651                 }
    1652             } else {
    1653                 $this->content_type = "application/octet-stream";
    1654             }
    1655         }
     1719            $ct_data = fread($data, 64);
     1720            rewind($data);
     1721        }
     1722
     1723        $this->_guess_content_type($ct_data);
    16561724
    16571725        list($status, $reason, $etag) =
     
    17051773     * @return boolean <kbd>True</kbd> if data uploaded successfully
    17061774     * @throws SyntaxException missing required parameters
     1775     * @throws BadContentTypeException if no Content-Type was/could be set
    17071776     * @throws MisMatchedChecksumException $verify is set and checksums unequal
    17081777     * @throws InvalidResponseException unexpected response
     
    17191788            throw new SyntaxException("File size exceeds maximum object size.");
    17201789        }
    1721         $auto_ct = False;
    1722         if (function_exists("finfo_open")) {
    1723             $finfo = False;
    1724             try {
    1725                 $finfo = @finfo_open(FILEINFO_MIME);
    1726             } catch (Exception $e) {
    1727                 try {
    1728                     $my_mime = dirname(__FILE__) . "/magic";
    1729                     $finfo = @finfo_open(FILEINFO_MIME, $my_mime);
    1730                 } catch (Exception $se) {
    1731                     $finfo = False;
    1732                 }
    1733             }
    1734             if ($finfo) {
    1735                 $ct = finfo_file($finfo, $filename);
    1736                 finfo_close($finfo);
    1737                 if ($ct) {
    1738                     $this->content_type = $ct;
    1739                     $auto_ct = True;
    1740                 }
    1741             }
    1742         }
    1743         if (!$auto_ct && function_exists("mime_content_type")) {
    1744             $this->content_type = @mime_content_type($filename);
    1745         } else {
    1746             $this->content_type = "application/octet-stream";
    1747         }
    1748         //ghetto png fix
    1749         $ext = strtolower(array_pop(explode('.',$filename)));
    1750         if($ext == 'png') {
    1751             $this->content_type = 'image/png';
    1752         }
    1753         //ghetto png fix
     1790
     1791        $this->_guess_content_type($filename);
     1792       
    17541793        $this->write($fp, $size, $verify);
    17551794        fclose($fp);
     
    18251864     * may either be a local filename, open resource for reading, or a string.
    18261865     *
    1827      * <b>WARNING:</b> If $data is a resource, the entire contents are read
    1828      * into a local variable (memory) before computing the checksum!  You
    1829      * should ensure that you have enough RAM to support this.
     1866     * <b>WARNING:</b> if you are uploading a big file over a stream
     1867     * it could get very slow to compute the md5 you probably want to
     1868     * set the $verify parameter to False in the write() method and
     1869     * compute yourself the md5 before if you have it.
    18301870     *
    18311871     * @param filename|obj|string $data filename, open resource, or string
     
    18351875    {
    18361876
    1837         if (is_file($data)) {
     1877        if (function_exists("hash_init") && is_resource($data)) {
     1878            $ctx = hash_init('md5');
     1879            while (!feof($data)) {
     1880                $buffer = fgets($data, 65536);
     1881                hash_update($ctx, $buffer);
     1882            }
     1883            $md5 = hash_final($ctx, false);
     1884            rewind($data);
     1885        } elseif ((string)is_file($data)) {
    18381886            $md5 = md5_file($data);
    1839         } elseif (is_resource($data)) {
    1840             # let's hope this isn't a BIG file
    1841             $contents = stream_get_contents($data); # PHP 5 and up
    1842             $md5 = md5($contents);
    1843             rewind($data);
    18441887        } else {
    18451888            $md5 = md5($data);
  • cdn-tools/tags/0.94/cdn_classes/cloudfiles/cloudfiles_exceptions.php

    r118371 r164970  
    2626class IOException extends Exception { }
    2727class CDNNotEnabledException extends Exception { }
     28class BadContentTypeException extends Exception { }
     29class InvalidUTF8Exception extends Exception { }
    2830
    2931/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  • cdn-tools/tags/0.94/cdn_classes/cloudfiles/cloudfiles_http.php

    r118371 r164970  
    3030require_once("cloudfiles_exceptions.php");
    3131
    32 define("PHP_CF_VERSION", "1.3.0");
     32define("PHP_CF_VERSION", "1.4.0");
    3333define("USER_AGENT", sprintf("PHP-CloudFiles/%s", PHP_CF_VERSION));
    3434define("ACCOUNT_CONTAINER_COUNT", "X-Account-Container-Count");
     
    3939define("CDN_URI", "X-CDN-URI");
    4040define("CDN_ENABLED", "X-CDN-Enabled");
     41define("CDN_LOG_RETENTION", "X-Log-Retention");
    4142define("CDN_TTL", "X-TTL");
    4243define("CDNM_URL", "X-CDN-Management-Url");
     
    9697    private $_cdn_uri;
    9798    private $_cdn_ttl;
     99    private $_cdn_log_retention;
    98100
    99101    function __construct($api_version)
     
    142144        $this->_cdn_uri = NULL;
    143145        $this->_cdn_ttl = NULL;
     146        $this->_cdn_log_retention = NULL;
     147
     148        # The OS list with a PHP without an updated CA File for CURL to
     149        # connect to SSL Websites. It is the first 3 letters of the PHP_OS
     150        # variable.
     151        $OS_CAFILE_NONUPDATED=array(
     152            "win",
     153        );
     154
     155        if (in_array((strtolower (substr(PHP_OS, 0,3))), $OS_CAFILE_NONUPDATED))
     156            $this->ssl_use_cabundle();
     157       
    144158    }
    145159
     
    154168            throw new IOException("Could not use CA bundle: "
    155169                . $this->cabundle_path);
    156         }
    157         return;
    158     }
    159 
    160     private function _set_connections_cainfo()
    161     {
    162         if ($this->cabundle_path) {
    163             foreach ($this->connections as $k => $v) {
    164                 if (!is_null($v)) {
    165                     curl_setopt($this->connections[$k], CURLOPT_SSL_VERIFYPEER,
    166                         True);
    167                     curl_setopt($this->connections[$k], CURLOPT_CAINFO,
    168                         $this->cabundle_path);
    169                 }
    170             }
    171170        }
    172171        return;
     
    197196
    198197        $curl_ch = curl_init();
    199         if ($this->cabundle_path) {
     198        if (!is_null($this->cabundle_path)) {
    200199            curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, True);
    201             curl_setopt($curl_ch, CURLOPT_CAINFO,
    202                 $this->cabundle_path);
     200            curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
    203201        }
    204202        curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
     
    228226
    229227        if (!$return_code) {
    230             $this->error_str = "Failed to obtain http response";
     228            $this->error_str .= ": Failed to obtain valid HTTP response.";
    231229            array(0,$this->error_str,array());
    232230        }
     
    250248    # (CDN) POST /v1/Account/Container
    251249    #
    252     function update_cdn_container($container_name, $ttl=86400)
     250    function update_cdn_container($container_name, $ttl=86400, $cdn_log_retention=False)
    253251    {
    254252        if (!$container_name) {
    255253            throw new SyntaxException("Container name not set.");
    256254        }
     255       
    257256        $url_path = $this->_make_path("CDN", $container_name);
    258257        $hdrs = array(
    259258            CDN_ENABLED => "True",
    260259            CDN_TTL => $ttl,
     260            CDN_LOG_RETENTION => $cdn_log_retention ?  "True" : "False",
    261261            );
    262262        $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
     
    338338
    339339        if (!$return_code) {
    340             $this->error_str = "Failed to obtain http response";
    341             array(0,$this->error_str,NULL,NULL,NULL);
     340            $this->error_str .= ": Failed to obtain valid HTTP response.";
     341            return array(0,$this->error_str,NULL,NULL,NULL,NULL);
    342342        }
    343343        if ($return_code == 401) {
    344             return array($return_code,"Unauthorized",NULL,NULL,NULL);
    345         }
    346         if ($return_code == 404) {
    347             return array($return_code,"Account not found.",NULL,NULL,NULL);
     344            return array($return_code,"Unauthorized",NULL,NULL,NULL,NULL);
     345        }
     346        if ($return_code == 404) {
     347            return array($return_code,"Account not found.",NULL,NULL,NULL,NULL);
    348348        }
    349349        if ($return_code == 204) {
    350350            return array($return_code,$this->response_reason,
    351                 $this->_cdn_enabled, $this->_cdn_uri, $this->_cdn_ttl);
    352         }
    353         return array($return_code,$this->response_reason,NULL,NULL,NULL);
     351                $this->_cdn_enabled, $this->_cdn_uri, $this->_cdn_ttl,
     352                $this->_cdn_log_retention
     353                );
     354        }
     355        return array($return_code,$this->response_reason,NULL,NULL,NULL,$this->_cdn_log_retention);
    354356    }
    355357
     
    377379
    378380        if (!$return_code) {
    379             $this->error_str = "Failed to obtain valid HTTP response.";
     381            $this->error_str .= ": Failed to obtain valid HTTP response.";
    380382            return array(0,$this->error_str,array());
    381383        }
     
    417419
    418420        if (!$return_code) {
    419             $this->error_str = "Failed to obtain valid HTTP response.";
     421            $this->error_str .= ": Failed to obtain valid HTTP response.";
    420422            return array(0,$this->error_str,array());
    421423        }
     
    445447
    446448        if (!$return_code) {
    447             $this->error_str = "Failed to obtain http response";
     449            $this->error_str .= ": Failed to obtain valid HTTP response.";
    448450            array(0,$this->error_str,0,0);
    449451        }
     
    470472
    471473        if (!$return_code) {
    472             $this->error_str = "Failed to obtain http response";
     474            $this->error_str .= ": Failed to obtain valid HTTP response.";
    473475            return False;
    474476        }
     
    488490
    489491        if (!$return_code) {
    490             $this->error_str = "Failed to obtain http response";
     492            $this->error_str .= ": Failed to obtain valid HTTP response.";
    491493        }
    492494        if ($return_code == 409) {
     
    536538
    537539        if (!$return_code) {
    538             $this->error_str = "Failed to obtain http response";
     540            $this->error_str .= ": Failed to obtain valid HTTP response.";
    539541            return array(0,$this->error_str,array());
    540542        }
     
    589591
    590592        if (!$return_code) {
    591             $this->error_str = "Failed to obtain http response";
     593            $this->error_str .= ": Failed to obtain valid HTTP response.";
    592594            return array(0,$this->error_str,array());
    593595        }
     
    624626
    625627        if (!$return_code) {
    626             $this->error_str = "Failed to obtain http response";
     628            $this->error_str .= ": Failed to obtain valid HTTP response.";
    627629            array(0,$this->error_str,0,0);
    628630        }
     
    653655
    654656        if (!$return_code) {
    655             $this->error_str = "Failed to obtain http response";
     657            $this->error_str .= ": Failed to obtain valid HTTP response.";
    656658            return array($return_code0,$this->error_str,NULL);
    657659        }
     
    689691
    690692        if (!$return_code) {
    691             $this->error_str = "Failed to obtain http response";
     693            $this->error_str .= ": Failed to obtain valid HTTP response.";
    692694            return array($return_code,$this->error_str);
    693695        }
     
    747749        $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
    748750        if (!$return_code) {
    749             $this->error_str = "Failed to obtain http response";
     751            $this->error_str .= ": Failed to obtain valid HTTP response.";
    750752            return array(0,$this->error_str,NULL);
    751753        }
     
    784786        $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
    785787        if (!$return_code) {
    786             $this->error_str = "Failed to obtain http response";
     788            $this->error_str .= ": Failed to obtain valid HTTP response.";
    787789            return 0;
    788790        }
     
    811813
    812814        if (!$return_code) {
    813             $this->error_str = "Failed to obtain http response";
     815            $this->error_str .= ": Failed to obtain valid HTTP response.";
    814816            return array(0, $this->error_str." ".$this->response_reason,
    815817                NULL, NULL, NULL, NULL, array());
     
    845847        $return_code = $this->_send_request("DEL_POST",$url_path,NULL,"DELETE");
    846848        if (!$return_code) {
    847             $this->error_str = "Failed to obtain http response";
     849            $this->error_str .= ": Failed to obtain valid HTTP response.";
    848850            return 0;
    849851        }
     
    932934            return strlen($header);
    933935        }
     936        if (stripos($header, CDN_LOG_RETENTION) === 0) {
     937            $this->_cdn_log_retention =
     938                trim(substr($header, strlen(CDN_LOG_RETENTION)+1)) == "True" ? True : False;
     939            return strlen($header);
     940        }
    934941        if (stripos($header, ACCOUNT_CONTAINER_COUNT) === 0) {
    935             $this->_account_container_count = trim(substr($header,
     942            $this->_account_container_count = (float) trim(substr($header,
    936943                    strlen(ACCOUNT_CONTAINER_COUNT)+1))+0;
    937944            return strlen($header);
    938945        }
    939946        if (stripos($header, ACCOUNT_BYTES_USED) === 0) {
    940             $this->_account_bytes_used = trim(substr($header,
     947            $this->_account_bytes_used = (float) trim(substr($header,
    941948                    strlen(ACCOUNT_BYTES_USED)+1))+0;
    942949            return strlen($header);
    943950        }
    944951        if (stripos($header, CONTAINER_OBJ_COUNT) === 0) {
    945             $this->_container_object_count = trim(substr($header,
     952            $this->_container_object_count = (float) trim(substr($header,
    946953                    strlen(CONTAINER_OBJ_COUNT)+1))+0;
    947954            return strlen($header);
    948955        }
    949956        if (stripos($header, CONTAINER_BYTES_USED) === 0) {
    950             $this->_container_bytes_used = trim(substr($header,
     957            $this->_container_bytes_used = (float) trim(substr($header,
    951958                    strlen(CONTAINER_BYTES_USED)+1))+0;
    952959            return strlen($header);
    953960        }
    954961        if (stripos($header, METADATA_HEADER) === 0) {
     962            # $header => X-Object-Meta-Foo: bar baz
    955963            $temp = substr($header, strlen(METADATA_HEADER));
     964            # $temp => Foo: bar baz
    956965            $parts = explode(":", $temp);
    957             $this->_obj_metadata[strtolower($parts[0])] = trim($parts[1]);
     966            # $parts[0] => Foo
     967            $val = substr(strstr($temp, ":"), 1);
     968            # $val => bar baz
     969            $this->_obj_metadata[$parts[0]] = trim($val);
    958970            return strlen($header);
    959971        }
    960         if (stripos($header, "ETag") === 0) {
    961             $parts = explode(":", $header);
    962             $this->_obj_etag = trim($parts[1]);
     972        if (stripos($header, "ETag:") === 0) {
     973            # $header => ETag: abc123def456...
     974            $val = substr(strstr($header, ":"), 1);
     975            # $val => abc123def456...
     976            $this->_obj_etag = trim($val);
    963977            return strlen($header);
    964978        }
    965         if (stripos($header, "Last-Modified") === 0) {
    966             $parts = explode(":", $header);
    967             $this->_obj_last_modified = trim($parts[1]);
     979        if (stripos($header, "Last-Modified:") === 0) {
     980            $val = substr(strstr($header, ":"), 1);
     981            $this->_obj_last_modified = trim($val);
    968982            return strlen($header);
    969983        }
    970         if (stripos($header, "Content-Type") === 0) {
    971             $parts = explode(":", $header);
    972             $this->_obj_content_type = trim($parts[1]);
     984        if (stripos($header, "Content-Type:") === 0) {
     985            $val = substr(strstr($header, ":"), 1);
     986            $this->_obj_content_type = trim($val);
    973987            return strlen($header);
    974988        }
    975         if (stripos($header, "Content-Length") === 0) {
    976             $parts = explode(":", $header);
    977             $this->_obj_content_length = trim($parts[1])+0;
     989        if (stripos($header, "Content-Length:") === 0) {
     990            $val = substr(strstr($header, ":"), 1);
     991            $this->_obj_content_length = (float) trim($val)+0;
    978992            return strlen($header);
    979993        }
     
    9931007    private function _write_cb($ch, $data)
    9941008    {
    995         $amount = strlen($data);
     1009        $dlen = strlen($data);
    9961010        switch ($this->_write_callback_type) {
    9971011        case "TEXT_LIST":
     
    9991013            break;
    10001014        case "OBJECT_STREAM":
    1001             $written = 0;
    1002             while ($written < strlen($data)) {
    1003                 $written += fwrite($this->_obj_write_resource, $data-$written);
    1004             }
    1005             if ($written > strlen($data)) {
    1006                 throw new IOException(
    1007                     "Wrote more data to client than we should have?!");
    1008             }
     1015            fwrite($this->_obj_write_resource, $data, $dlen);
    10091016            break;
    10101017        case "OBJECT_STRING":
     
    10131020        }
    10141021        if (isset($this->_user_read_progress_callback_func)) {
    1015             call_user_func($this->_user_read_progress_callback_func,strlen($data));
    1016         }
    1017         return strlen($data);
     1022            call_user_func($this->_user_read_progress_callback_func, $dlen);
     1023        }
     1024        return $dlen;
    10181025    }
    10191026
     
    10521059                    $parts = explode(":", $v);
    10531060                    $header = $parts[0];
    1054                     $value = trim($parts[1]);
     1061                    $value = trim(substr(strstr($v, ":"), 1));
    10551062                } else {
    10561063                    $header = $h;
     
    10891096        }
    10901097
    1091         $this->_set_connections_cainfo();
    1092 
    10931098        if ($this->dbug) { curl_setopt($ch, CURLOPT_VERBOSE, 1); }
     1099
     1100        if (!is_null($this->cabundle_path)) {
     1101            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
     1102            curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
     1103        }
    10941104
    10951105        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
     
    11651175        $hdrs = array();
    11661176        foreach ($obj->metadata as $k => $v) {
    1167             if (strpos($k,":") !== False || strpos($v,":") !== False) {
     1177            if (strpos($k,":") !== False) {
    11681178                throw new SyntaxException(
    1169                     "Metadata cannot contain a ':' character.");
     1179                    "Metadata keys cannot contain a ':' character.");
    11701180            }
    1171             $k = strtolower(trim($k));
     1181            $k = trim($k);
    11721182            $key = sprintf("%s%s", METADATA_HEADER, $k);
    11731183            if (!array_key_exists($key, $hdrs)) {
  • cdn-tools/tags/0.94/cdntools.php

    r161722 r164970  
    55Description: CDN Tools is a plugin designed to help you drastically speed up your blog's load time by loading content onto a distribution network.  You can use a commercial CDN or just load some of your larger JS libraries for free from Google's servers!  At this time Cloud Files is the only supported CDN.
    66Author: Paul Kehrer
    7 Version: 0.93
     7Version: 0.94
    88Author URI: http://langui.sh/
    99*/
     
    2828set_time_limit(300); //5 minutes max...
    2929
    30 define('CDNTOOLS_VERSION','0.93');
     30define('CDNTOOLS_VERSION','0.94');
    3131
    3232$dir_array = explode('/',dirname(__FILE__));
     
    121121
    122122    function bind_filters() {
     123        add_filter('init',array($this,'disable_script_concatenation'));
    123124        add_filter( 'print_scripts_array',array($this,"jquery_noconflict"),100);
    124125        add_filter('wp_handle_upload', array($this,'handle_upload_filter')); //grab data about uploads
     
    127128        add_filter('the_content', array($this,'cdn_media_url_rewrite'), 1000);  //this needs to run after any other filter
    128129        add_filter('wp_generate_attachment_metadata', array($this,'cdn_upload_resized_images'));
     130    }
     131   
     132    //wp 2.8 concatenates scripts in the admin panel and this messes up the google ajax rewriting.  hook init and disable it for now.  revisit for 2.9
     133    function disable_script_concatenation() {
     134        global $concatenate_scripts;
     135        $concatenate_scripts = false;
    129136    }
    130137   
  • cdn-tools/tags/0.94/readme.txt

    r161722 r164970  
    55Requires at least: 2.7
    66Tested up to: 2.8.4
    7 Stable tag: 0.93
     7Stable tag: 0.94
    88
    99CDN Tools is a plugin designed to help you drastically speed up your blog's load time by loading data onto a content distribution network (CDN).
     
    1111== Description ==
    1212
    13 [CDN Tools](http://swearingscience.com/cdn-tools/ "CDN Tools Home") is a WordPress plugin that allows you to load javascript and media files to an external server to drastically speed page loads.  You can sideload data to a commercial CDN or just load your larger JS libraries (prototype, jquery) for **free** from Google's servers.  CDN Tools has been designed to be as easy to use as possible, so give it a shot!  Your blog's readers will thank you.  At this time the only commercial CDN supported is Cloud Files.  Check out the plugin homepage to view a screencast.
     13[CDN Tools](http://langui.sh/cdn-tools/ "CDN Tools Home") is a WordPress plugin that allows you to load javascript and media files to an external server to drastically speed page loads.  You can sideload data to a commercial CDN or just load your larger JS libraries (prototype, jquery) for **free** from Google's servers.  CDN Tools has been designed to be as easy to use as possible, so give it a shot!  Your blog's readers will thank you.  At this time the only commercial CDN supported is Cloud Files.  Check out the plugin homepage to view a screencast.
    1414
    15 = New in 0.92/0.93 =
    16 * A partial fix for issues with customers who have full file paths stored in their postmeta table.  This is not a complete fix, but should help some (most?) users.
    17 * Major upgrade to support WP 2.8.  If you are a previous user of CDN Tools you _MUST_ unload files and then load them again.  Please let me know if you have issues because several major changes were made.  See http://langui.sh/cdn-tools for more details.
     15= New in 0.94 =
     16* Upgraded to CF API 1.4.  This should resolve some cURL issues users have experienced and removes the dependence on a png hack for RHEL4 users.
     17* Fixed major issue with Google AJAX CDN.  Previously users were unable to switch between visual and HTML mode on the edit post page.
    1818
    19 [View complete changelog](http://swearingscience.com/cdn-tools/ "CDN Tools Home").
     19[View complete changelog](http://langui.sh/cdn-tools/ "CDN Tools Home").
    2020
    2121== Installation ==
     
    3333= Could you add XXXX CDN compatibility? =
    3434
    35 I would love to, but I am not currently willing to buy accounts and pay to develop for every possible CDN out there.  If you'd like to supply me with a test account so I can support your favorite CDN I'd be happy to.  Drop me a comment on the CDN Tools home page.
     35Unfortunately I'm likely too busy to do this for your CDN, but I'd be happy to answer questions if you need some assistance in developing your own!  If you write a plugin, please let me know so I can merge it into the main distribution.
    3636
    3737= I found a bug. What do I do? =
     
    4646
    4747== Changelog ==
     48= 0.94 - 10/19/2009 =
     49* Upgraded to CF API 1.4.  This should resolve some cURL issues users have experienced and removes the dependence on a png hack for RHEL4 users.
     50* Fixed major issue with Google AJAX CDN.  Previously users were unable to switch between visual and HTML mode on the edit post page.
     51
    4852= 0.93 - 10/8/2009 =
    4953* A partial fix for issues with customers who have full file paths stored in their postmeta table.  This is not a complete fix, but should help some (most?) users.
  • cdn-tools/trunk/cdn_classes/cloudfiles/cloudfiles.php

    r118371 r164970  
    3131 *   $bday = $images->create_object("first_birthday.jpg");
    3232 *
    33  *   # Upload content from a local file by streaming it
     33 *   # Upload content from a local file by streaming it.  Note that we use
     34 *   # a "float" for the file size to overcome PHP's 32-bit integer limit for
     35 *   # very large files.
    3436 *   #
    3537 *   $fname = "/home/user/photos/birthdays/birthday1.jpg";  # filename to upload
     
    328330     * Cloud Files account information
    329331     *
    330      * Return an array of two integers (or possibly floats if the value
    331      * overflows PHP's 32-bit integer); number of containers on the account
    332      * and total bytes used for the account.
     332     * Return an array of two floats (since PHP only supports 32-bit integers);
     333     * number of containers on the account and total bytes used for the account.
    333334     *
    334335     * Example:
     
    390391            throw new SyntaxException($r);
    391392        }
    392         if (strpos($container_name, "?") !== False) {
    393             $r = "Container name '".$container_name;
    394             $r .= "' cannot contain a '?' character.";
    395             throw new SyntaxException($r);
    396         }
    397         if (mb_strlen($container_name, "UTF-8") > MAX_CONTAINER_NAME_LEN) {
     393        if (strlen($container_name) > MAX_CONTAINER_NAME_LEN) {
    398394            throw new SyntaxException(sprintf(
    399                 "Container name exeeds %d characters.",
     395                "Container name exeeds %d bytes.",
    400396                MAX_CONTAINER_NAME_LEN));
    401397        }
     
    441437    function delete_container($container=NULL)
    442438    {
     439        $container_name = NULL;
     440       
    443441        if (is_object($container)) {
    444442            if (get_class($container) == "CF_Container") {
     
    541539     * @throws InvalidResponseException unexpected response
    542540     */
    543     function get_containers()
     541    function get_containers($limit=0, $marker=NULL)
    544542    {
    545543        list($status, $reason, $container_info) =
    546                 $this->cfs_http->list_containers_info();
     544                $this->cfs_http->list_containers_info($limit, $marker);
    547545        #if ($status == 401 && $this->_re_auth()) {
    548546        #    return $this->get_containers();
     
    555553        foreach ($container_info as $name => $info) {
    556554            $containers[] = new CF_Container($this->cfs_auth, $this->cfs_http,
    557                 $name, $info["count"], $info["bytes"], False);
     555                $info['name'], $info["count"], $info["bytes"], False);
    558556        }
    559557        return $containers;
     
    816814 * Objects stored in the Container are publicly available via the CDN.
    817815 *
    818  * NOTE: Due to the possible overflow of PHP's 32-bit integer, the Container's
    819  *       object_count and bytes_used instance variables may either be a
    820  *       integer or float.
    821  *
    822816 * @package php-cloudfiles
    823817 */
     
    833827    public $cdn_uri;
    834828    public $cdn_ttl;
     829    public $cdn_log_retention;
    835830
    836831    /**
     
    849844        $bytes=0, $docdn=True)
    850845    {
    851         if (mb_strlen($name, "UTF-8") > MAX_CONTAINER_NAME_LEN) {
     846        if (strlen($name) > MAX_CONTAINER_NAME_LEN) {
    852847            throw new SyntaxException("Container name exceeds "
    853848                . "maximum allowed length.");
     
    865860        $this->cdn_uri = NULL;
    866861        $this->cdn_ttl = NULL;
     862        $this->cdn_log_retention = NULL;
    867863        if ($this->cfs_http->getCDNMUrl() != NULL && $docdn) {
    868864            $this->_cdn_initialize();
     
    882878            $this->name, $this->object_count, $this->bytes_used);
    883879        if ($this->cfs_http->getCDNMUrl() != NULL) {
    884             $me .= sprintf(", cdn: %s, cdn uri: %s, cdn ttl: %.0f",
     880            $me .= sprintf(", cdn: %s, cdn uri: %s, cdn ttl: %.0f logs retention: %s",
    885881                $this->is_public() ? "Yes" : "No",
    886                 $this->cdn_uri, $this->cdn_ttl);
     882                $this->cdn_uri, $this->cdn_ttl,
     883                $this->cdn_log_retention ? "Yes" : "No"
     884                );
    887885        }
    888886        return $me;
     
    906904     * # CDN-enable the container and set it's TTL for a month
    907905     * #
    908      * $public_container->make_public(86400*30); # 30 days (86400 seconds/day)
     906     * $public_container->make_public(86400/2); # 12 hours (86400 seconds/day)
    909907     * </code>
    910908     *
     
    924922            # previously published, assume we're setting new attributes
    925923            list($status, $reason, $cdn_uri) =
    926                 $this->cfs_http->update_cdn_container($this->name,$ttl);
     924                $this->cfs_http->update_cdn_container($this->name,$ttl,$this->cdn_log_retention);
    927925            #if ($status == 401 && $this->_re_auth()) {
    928926            #    return $this->make_public($ttl);
     
    950948        $this->cdn_ttl = $ttl;
    951949        $this->cdn_uri = $cdn_uri;
     950        $this->cdn_log_retention = False;
    952951        return $this->cdn_uri;
    953952    }
    954953
     954    function log_retention($cdn_log_retention=False) {
     955        if ($this->cfs_http->getCDNMUrl() == NULL) {
     956            throw new CDNNotEnabledException(
     957                "Authentication response did not indicate CDN availability");
     958        }
     959        list($status,$reason) =
     960            $this->cfs_http->update_cdn_container($this->name,
     961                                                  $this->cdn_ttl,
     962                                                  $cdn_log_retention);
     963        if (!in_array($status, array(202,404))) {
     964            throw new InvalidResponseException(
     965                "Invalid response (".$status."): ".$this->cfs_http->get_error());
     966        }
     967        $this->cdn_log_retention = $cdn_log_retention;
     968    }
     969   
    955970    /**
    956971     * Disable the CDN sharing for this container
     
    10001015        $this->cdn_ttl = NULL;
    10011016        $this->cdn_uri = NULL;
     1017        $this->cdn_log_retention = NULL;
    10021018        return True;
    10031019    }
     
    11041120     * #
    11051121     * $first_ten = $images->list_objects(10);
    1106      * $next_ten = $images->list_objects(10,10);
     1122     *
     1123     * # Note the use of the previous result's last object name being
     1124     * # used as the 'marker' parameter to fetch the next 10 objects
     1125     * #
     1126     * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
    11071127     *
    11081128     * # Grab images starting with "birthday_party" and default limit/marker
     
    11591179     * #
    11601180     * $first_ten = $images->get_objects(10);
    1161      * $next_ten = $images->get_objects(10,10);
     1181     *
     1182     * # Note the use of the previous result's last object name being
     1183     * # used as the 'marker' parameter to fetch the next 10 objects
     1184     * #
     1185     * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
    11621186     *
    11631187     * # Grab images starting with "birthday_party" and default limit/marker
     
    11971221            $tmp = new CF_Object($this, $obj["name"], False, False);
    11981222            $tmp->content_type = $obj["content_type"];
    1199             $tmp->content_length = $obj["bytes"];
     1223            $tmp->content_length = (float) $obj["bytes"];
    12001224            $tmp->set_etag($obj["hash"]);
     1225            $tmp->last_modified = $obj["last_modified"];
    12011226            $objects[] = $tmp;
    12021227        }
     
    12721297    {
    12731298        if ($path_name[0] == '/') {
    1274             $path_name = mb_substr($path_name, 1);
     1299            $path_name = mb_substr($path_name, 0, 1);
    12751300        }
    12761301        $elements = explode('/', $path_name, -1);
     
    12951320    private function _cdn_initialize()
    12961321    {
    1297         list($status, $reason, $cdn_enabled, $cdn_uri, $cdn_ttl) =
     1322        list($status, $reason, $cdn_enabled, $cdn_uri, $cdn_ttl, $cdn_log_retention) =
    12981323            $this->cfs_http->head_cdn_container($this->name);
    12991324        #if ($status == 401 && $this->_re_auth()) {
     
    13071332        $this->cdn_uri = $cdn_uri;
    13081333        $this->cdn_ttl = $cdn_ttl;
     1334        $this->cdn_log_retention = $cdn_log_retention;
    13091335    }
    13101336
     
    13571383            throw new SyntaxException($r);
    13581384        }
    1359         if (mb_strlen($name, "UTF-8") > MAX_OBJECT_NAME_LEN) {
     1385        if (strlen($name) > MAX_OBJECT_NAME_LEN) {
    13601386            throw new SyntaxException("Object name exceeds "
    13611387                . "maximum allowed length.");
     
    13891415
    13901416    /**
     1417     * Internal check to get the proper mimetype.
     1418     *
     1419     * This function would go over the available PHP methods to get
     1420     * the MIME type.
     1421     *
     1422     * By default it will try to use the PHP fileinfo library which is
     1423     * available from PHP 5.3 or as an PECL extension
     1424     * (http://pecl.php.net/package/Fileinfo).
     1425     *
     1426     * It will get the magic file by default from the system wide file
     1427     * which is usually available in /usr/share/magic on Unix or try
     1428     * to use the file specified in the source directory of the API
     1429     * (share directory).
     1430     *
     1431     * if fileinfo is not available it will try to use the internal
     1432     * mime_content_type function.
     1433     *
     1434     * @param string $handle name of file or buffer to guess the type from
     1435     * @return boolean <kbd>True</kbd> if successful
     1436     * @throws BadContentTypeException
     1437     */
     1438    function _guess_content_type($handle) {
     1439        if ($this->content_type)
     1440            return;
     1441           
     1442        if (function_exists("finfo_open")) {
     1443            $local_magic = dirname(__FILE__) . "/share/magic";
     1444            $finfo = @finfo_open(FILEINFO_MIME, $local_magic);
     1445
     1446            if (!$finfo)
     1447                $finfo = @finfo_open(FILEINFO_MIME);
     1448               
     1449            if ($finfo) {
     1450
     1451                if (is_file((string)$handle))
     1452                    $ct = @finfo_file($finfo, $handle);
     1453                else
     1454                    $ct = @finfo_buffer($finfo, $handle);
     1455
     1456                /* PHP 5.3 fileinfo display extra information like
     1457                   charset so we remove everything after the ; since
     1458                   we are not into that stuff */
     1459                if ($ct) {
     1460                    $extra_content_type_info = strpos($ct, "; ");
     1461                    if ($extra_content_type_info)
     1462                        $ct = substr($ct, 0, $extra_content_type_info);
     1463                }
     1464
     1465                if ($ct && $ct != 'application/octet-stream')
     1466                    $this->content_type = $ct;
     1467
     1468                @finfo_close($finfo);
     1469            }
     1470        }
     1471
     1472        if (!$this->content_type && (string)is_file($handle) && function_exists("mime_content_type")) {
     1473            $this->content_type = @mime_content_type($handle);
     1474        }
     1475
     1476        if (!$this->content_type) {
     1477            throw new BadContentTypeException("Required Content-Type not set");
     1478        }
     1479        return True;
     1480    }
     1481   
     1482    /**
    13911483     * String representation of the Object's public URI
    13921484     *
     
    15861678     * @return boolean <kbd>True</kbd> when data uploaded successfully
    15871679     * @throws SyntaxException missing required parameters
     1680     * @throws BadContentTypeException if no Content-Type was/could be set
    15881681     * @throws MisMatchedChecksumException $verify is set and checksums unequal
    15891682     * @throws InvalidResponseException unexpected response
     
    16111704            # a temporary file instead.
    16121705            #
    1613             #$fp = fopen("php://temp", "rb+");
    1614             $fp = fopen("php://memory", "rb+");
    1615             fwrite($fp, $data);
     1706            $fp = fopen("php://temp", "wb+");
     1707            #$fp = fopen("php://memory", "wb+");
     1708            fwrite($fp, $data, strlen($data));
    16161709            rewind($fp);
    16171710            $close_fh = True;
    1618             $this->content_length = (float) mb_strlen($data);
     1711            $this->content_length = (float) strlen($data);
    16191712            if ($this->content_length > MAX_OBJECT_SIZE) {
    16201713                throw new SyntaxException("Data exceeds maximum object size");
    16211714            }
     1715            $ct_data = substr($data, 0, 64);
    16221716        } else {
    16231717            $this->content_length = $bytes;
    16241718            $fp = $data;
    1625         }
    1626 
    1627         /* FIXME: test if this works with string AND resource (or string only) */
    1628         if (!$this->content_type) {
    1629             if (function_exists("finfo_open")) {
    1630                 $finfo = False;
    1631                 try {
    1632                     $finfo = @finfo_open(FILEINFO_MIME);
    1633                 } catch (Exception $e) {
    1634                     try {
    1635                         $my_mime = dirname(__FILE__) . "/magic";
    1636                         $finfo = @finfo_open(FILEINFO_MIME, $my_mime);
    1637                     } catch (Exception $se) {
    1638                         $finfo = False;
    1639                     }
    1640                 }
    1641                 if (!$finfo) {
    1642                     $this->content_type = "application/octet-stream";
    1643                 } else {
    1644                     $ct = finfo_buffer($finfo, $data);
    1645                     finfo_close($finfo);
    1646                     if (!$ct) {
    1647                         $this->content_type = "application/octet-stream";
    1648                     } else {
    1649                         $this->content_type = $ct;
    1650                     }
    1651                 }
    1652             } else {
    1653                 $this->content_type = "application/octet-stream";
    1654             }
    1655         }
     1719            $ct_data = fread($data, 64);
     1720            rewind($data);
     1721        }
     1722
     1723        $this->_guess_content_type($ct_data);
    16561724
    16571725        list($status, $reason, $etag) =
     
    17051773     * @return boolean <kbd>True</kbd> if data uploaded successfully
    17061774     * @throws SyntaxException missing required parameters
     1775     * @throws BadContentTypeException if no Content-Type was/could be set
    17071776     * @throws MisMatchedChecksumException $verify is set and checksums unequal
    17081777     * @throws InvalidResponseException unexpected response
     
    17191788            throw new SyntaxException("File size exceeds maximum object size.");
    17201789        }
    1721         $auto_ct = False;
    1722         if (function_exists("finfo_open")) {
    1723             $finfo = False;
    1724             try {
    1725                 $finfo = @finfo_open(FILEINFO_MIME);
    1726             } catch (Exception $e) {
    1727                 try {
    1728                     $my_mime = dirname(__FILE__) . "/magic";
    1729                     $finfo = @finfo_open(FILEINFO_MIME, $my_mime);
    1730                 } catch (Exception $se) {
    1731                     $finfo = False;
    1732                 }
    1733             }
    1734             if ($finfo) {
    1735                 $ct = finfo_file($finfo, $filename);
    1736                 finfo_close($finfo);
    1737                 if ($ct) {
    1738                     $this->content_type = $ct;
    1739                     $auto_ct = True;
    1740                 }
    1741             }
    1742         }
    1743         if (!$auto_ct && function_exists("mime_content_type")) {
    1744             $this->content_type = @mime_content_type($filename);
    1745         } else {
    1746             $this->content_type = "application/octet-stream";
    1747         }
    1748         //ghetto png fix
    1749         $ext = strtolower(array_pop(explode('.',$filename)));
    1750         if($ext == 'png') {
    1751             $this->content_type = 'image/png';
    1752         }
    1753         //ghetto png fix
     1790
     1791        $this->_guess_content_type($filename);
     1792       
    17541793        $this->write($fp, $size, $verify);
    17551794        fclose($fp);
     
    18251864     * may either be a local filename, open resource for reading, or a string.
    18261865     *
    1827      * <b>WARNING:</b> If $data is a resource, the entire contents are read
    1828      * into a local variable (memory) before computing the checksum!  You
    1829      * should ensure that you have enough RAM to support this.
     1866     * <b>WARNING:</b> if you are uploading a big file over a stream
     1867     * it could get very slow to compute the md5 you probably want to
     1868     * set the $verify parameter to False in the write() method and
     1869     * compute yourself the md5 before if you have it.
    18301870     *
    18311871     * @param filename|obj|string $data filename, open resource, or string
     
    18351875    {
    18361876
    1837         if (is_file($data)) {
     1877        if (function_exists("hash_init") && is_resource($data)) {
     1878            $ctx = hash_init('md5');
     1879            while (!feof($data)) {
     1880                $buffer = fgets($data, 65536);
     1881                hash_update($ctx, $buffer);
     1882            }
     1883            $md5 = hash_final($ctx, false);
     1884            rewind($data);
     1885        } elseif ((string)is_file($data)) {
    18381886            $md5 = md5_file($data);
    1839         } elseif (is_resource($data)) {
    1840             # let's hope this isn't a BIG file
    1841             $contents = stream_get_contents($data); # PHP 5 and up
    1842             $md5 = md5($contents);
    1843             rewind($data);
    18441887        } else {
    18451888            $md5 = md5($data);
  • cdn-tools/trunk/cdn_classes/cloudfiles/cloudfiles_exceptions.php

    r118371 r164970  
    2626class IOException extends Exception { }
    2727class CDNNotEnabledException extends Exception { }
     28class BadContentTypeException extends Exception { }
     29class InvalidUTF8Exception extends Exception { }
    2830
    2931/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  • cdn-tools/trunk/cdn_classes/cloudfiles/cloudfiles_http.php

    r118371 r164970  
    3030require_once("cloudfiles_exceptions.php");
    3131
    32 define("PHP_CF_VERSION", "1.3.0");
     32define("PHP_CF_VERSION", "1.4.0");
    3333define("USER_AGENT", sprintf("PHP-CloudFiles/%s", PHP_CF_VERSION));
    3434define("ACCOUNT_CONTAINER_COUNT", "X-Account-Container-Count");
     
    3939define("CDN_URI", "X-CDN-URI");
    4040define("CDN_ENABLED", "X-CDN-Enabled");
     41define("CDN_LOG_RETENTION", "X-Log-Retention");
    4142define("CDN_TTL", "X-TTL");
    4243define("CDNM_URL", "X-CDN-Management-Url");
     
    9697    private $_cdn_uri;
    9798    private $_cdn_ttl;
     99    private $_cdn_log_retention;
    98100
    99101    function __construct($api_version)
     
    142144        $this->_cdn_uri = NULL;
    143145        $this->_cdn_ttl = NULL;
     146        $this->_cdn_log_retention = NULL;
     147
     148        # The OS list with a PHP without an updated CA File for CURL to
     149        # connect to SSL Websites. It is the first 3 letters of the PHP_OS
     150        # variable.
     151        $OS_CAFILE_NONUPDATED=array(
     152            "win",
     153        );
     154
     155        if (in_array((strtolower (substr(PHP_OS, 0,3))), $OS_CAFILE_NONUPDATED))
     156            $this->ssl_use_cabundle();
     157       
    144158    }
    145159
     
    154168            throw new IOException("Could not use CA bundle: "
    155169                . $this->cabundle_path);
    156         }
    157         return;
    158     }
    159 
    160     private function _set_connections_cainfo()
    161     {
    162         if ($this->cabundle_path) {
    163             foreach ($this->connections as $k => $v) {
    164                 if (!is_null($v)) {
    165                     curl_setopt($this->connections[$k], CURLOPT_SSL_VERIFYPEER,
    166                         True);
    167                     curl_setopt($this->connections[$k], CURLOPT_CAINFO,
    168                         $this->cabundle_path);
    169                 }
    170             }
    171170        }
    172171        return;
     
    197196
    198197        $curl_ch = curl_init();
    199         if ($this->cabundle_path) {
     198        if (!is_null($this->cabundle_path)) {
    200199            curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, True);
    201             curl_setopt($curl_ch, CURLOPT_CAINFO,
    202                 $this->cabundle_path);
     200            curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
    203201        }
    204202        curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
     
    228226
    229227        if (!$return_code) {
    230             $this->error_str = "Failed to obtain http response";
     228            $this->error_str .= ": Failed to obtain valid HTTP response.";
    231229            array(0,$this->error_str,array());
    232230        }
     
    250248    # (CDN) POST /v1/Account/Container
    251249    #
    252     function update_cdn_container($container_name, $ttl=86400)
     250    function update_cdn_container($container_name, $ttl=86400, $cdn_log_retention=False)
    253251    {
    254252        if (!$container_name) {
    255253            throw new SyntaxException("Container name not set.");
    256254        }
     255       
    257256        $url_path = $this->_make_path("CDN", $container_name);
    258257        $hdrs = array(
    259258            CDN_ENABLED => "True",
    260259            CDN_TTL => $ttl,
     260            CDN_LOG_RETENTION => $cdn_log_retention ?  "True" : "False",
    261261            );
    262262        $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
     
    338338
    339339        if (!$return_code) {
    340             $this->error_str = "Failed to obtain http response";
    341             array(0,$this->error_str,NULL,NULL,NULL);
     340            $this->error_str .= ": Failed to obtain valid HTTP response.";
     341            return array(0,$this->error_str,NULL,NULL,NULL,NULL);
    342342        }
    343343        if ($return_code == 401) {
    344             return array($return_code,"Unauthorized",NULL,NULL,NULL);
    345         }
    346         if ($return_code == 404) {
    347             return array($return_code,"Account not found.",NULL,NULL,NULL);
     344            return array($return_code,"Unauthorized",NULL,NULL,NULL,NULL);
     345        }
     346        if ($return_code == 404) {
     347            return array($return_code,"Account not found.",NULL,NULL,NULL,NULL);
    348348        }
    349349        if ($return_code == 204) {
    350350            return array($return_code,$this->response_reason,
    351                 $this->_cdn_enabled, $this->_cdn_uri, $this->_cdn_ttl);
    352         }
    353         return array($return_code,$this->response_reason,NULL,NULL,NULL);
     351                $this->_cdn_enabled, $this->_cdn_uri, $this->_cdn_ttl,
     352                $this->_cdn_log_retention
     353                );
     354        }
     355        return array($return_code,$this->response_reason,NULL,NULL,NULL,$this->_cdn_log_retention);
    354356    }
    355357
     
    377379
    378380        if (!$return_code) {
    379             $this->error_str = "Failed to obtain valid HTTP response.";
     381            $this->error_str .= ": Failed to obtain valid HTTP response.";
    380382            return array(0,$this->error_str,array());
    381383        }
     
    417419
    418420        if (!$return_code) {
    419             $this->error_str = "Failed to obtain valid HTTP response.";
     421            $this->error_str .= ": Failed to obtain valid HTTP response.";
    420422            return array(0,$this->error_str,array());
    421423        }
     
    445447
    446448        if (!$return_code) {
    447             $this->error_str = "Failed to obtain http response";
     449            $this->error_str .= ": Failed to obtain valid HTTP response.";
    448450            array(0,$this->error_str,0,0);
    449451        }
     
    470472
    471473        if (!$return_code) {
    472             $this->error_str = "Failed to obtain http response";
     474            $this->error_str .= ": Failed to obtain valid HTTP response.";
    473475            return False;
    474476        }
     
    488490
    489491        if (!$return_code) {
    490             $this->error_str = "Failed to obtain http response";
     492            $this->error_str .= ": Failed to obtain valid HTTP response.";
    491493        }
    492494        if ($return_code == 409) {
     
    536538
    537539        if (!$return_code) {
    538             $this->error_str = "Failed to obtain http response";
     540            $this->error_str .= ": Failed to obtain valid HTTP response.";
    539541            return array(0,$this->error_str,array());
    540542        }
     
    589591
    590592        if (!$return_code) {
    591             $this->error_str = "Failed to obtain http response";
     593            $this->error_str .= ": Failed to obtain valid HTTP response.";
    592594            return array(0,$this->error_str,array());
    593595        }
     
    624626
    625627        if (!$return_code) {
    626             $this->error_str = "Failed to obtain http response";
     628            $this->error_str .= ": Failed to obtain valid HTTP response.";
    627629            array(0,$this->error_str,0,0);
    628630        }
     
    653655
    654656        if (!$return_code) {
    655             $this->error_str = "Failed to obtain http response";
     657            $this->error_str .= ": Failed to obtain valid HTTP response.";
    656658            return array($return_code0,$this->error_str,NULL);
    657659        }
     
    689691
    690692        if (!$return_code) {
    691             $this->error_str = "Failed to obtain http response";
     693            $this->error_str .= ": Failed to obtain valid HTTP response.";
    692694            return array($return_code,$this->error_str);
    693695        }
     
    747749        $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
    748750        if (!$return_code) {
    749             $this->error_str = "Failed to obtain http response";
     751            $this->error_str .= ": Failed to obtain valid HTTP response.";
    750752            return array(0,$this->error_str,NULL);
    751753        }
     
    784786        $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
    785787        if (!$return_code) {
    786             $this->error_str = "Failed to obtain http response";
     788            $this->error_str .= ": Failed to obtain valid HTTP response.";
    787789            return 0;
    788790        }
     
    811813
    812814        if (!$return_code) {
    813             $this->error_str = "Failed to obtain http response";
     815            $this->error_str .= ": Failed to obtain valid HTTP response.";
    814816            return array(0, $this->error_str." ".$this->response_reason,
    815817                NULL, NULL, NULL, NULL, array());
     
    845847        $return_code = $this->_send_request("DEL_POST",$url_path,NULL,"DELETE");
    846848        if (!$return_code) {
    847             $this->error_str = "Failed to obtain http response";
     849            $this->error_str .= ": Failed to obtain valid HTTP response.";
    848850            return 0;
    849851        }
     
    932934            return strlen($header);
    933935        }
     936        if (stripos($header, CDN_LOG_RETENTION) === 0) {
     937            $this->_cdn_log_retention =
     938                trim(substr($header, strlen(CDN_LOG_RETENTION)+1)) == "True" ? True : False;
     939            return strlen($header);
     940        }
    934941        if (stripos($header, ACCOUNT_CONTAINER_COUNT) === 0) {
    935             $this->_account_container_count = trim(substr($header,
     942            $this->_account_container_count = (float) trim(substr($header,
    936943                    strlen(ACCOUNT_CONTAINER_COUNT)+1))+0;
    937944            return strlen($header);
    938945        }
    939946        if (stripos($header, ACCOUNT_BYTES_USED) === 0) {
    940             $this->_account_bytes_used = trim(substr($header,
     947            $this->_account_bytes_used = (float) trim(substr($header,
    941948                    strlen(ACCOUNT_BYTES_USED)+1))+0;
    942949            return strlen($header);
    943950        }
    944951        if (stripos($header, CONTAINER_OBJ_COUNT) === 0) {
    945             $this->_container_object_count = trim(substr($header,
     952            $this->_container_object_count = (float) trim(substr($header,
    946953                    strlen(CONTAINER_OBJ_COUNT)+1))+0;
    947954            return strlen($header);
    948955        }
    949956        if (stripos($header, CONTAINER_BYTES_USED) === 0) {
    950             $this->_container_bytes_used = trim(substr($header,
     957            $this->_container_bytes_used = (float) trim(substr($header,
    951958                    strlen(CONTAINER_BYTES_USED)+1))+0;
    952959            return strlen($header);
    953960        }
    954961        if (stripos($header, METADATA_HEADER) === 0) {
     962            # $header => X-Object-Meta-Foo: bar baz
    955963            $temp = substr($header, strlen(METADATA_HEADER));
     964            # $temp => Foo: bar baz
    956965            $parts = explode(":", $temp);
    957             $this->_obj_metadata[strtolower($parts[0])] = trim($parts[1]);
     966            # $parts[0] => Foo
     967            $val = substr(strstr($temp, ":"), 1);
     968            # $val => bar baz
     969            $this->_obj_metadata[$parts[0]] = trim($val);
    958970            return strlen($header);
    959971        }
    960         if (stripos($header, "ETag") === 0) {
    961             $parts = explode(":", $header);
    962             $this->_obj_etag = trim($parts[1]);
     972        if (stripos($header, "ETag:") === 0) {
     973            # $header => ETag: abc123def456...
     974            $val = substr(strstr($header, ":"), 1);
     975            # $val => abc123def456...
     976            $this->_obj_etag = trim($val);
    963977            return strlen($header);
    964978        }
    965         if (stripos($header, "Last-Modified") === 0) {
    966             $parts = explode(":", $header);
    967             $this->_obj_last_modified = trim($parts[1]);
     979        if (stripos($header, "Last-Modified:") === 0) {
     980            $val = substr(strstr($header, ":"), 1);
     981            $this->_obj_last_modified = trim($val);
    968982            return strlen($header);
    969983        }
    970         if (stripos($header, "Content-Type") === 0) {
    971             $parts = explode(":", $header);
    972             $this->_obj_content_type = trim($parts[1]);
     984        if (stripos($header, "Content-Type:") === 0) {
     985            $val = substr(strstr($header, ":"), 1);
     986            $this->_obj_content_type = trim($val);
    973987            return strlen($header);
    974988        }
    975         if (stripos($header, "Content-Length") === 0) {
    976             $parts = explode(":", $header);
    977             $this->_obj_content_length = trim($parts[1])+0;
     989        if (stripos($header, "Content-Length:") === 0) {
     990            $val = substr(strstr($header, ":"), 1);
     991            $this->_obj_content_length = (float) trim($val)+0;
    978992            return strlen($header);
    979993        }
     
    9931007    private function _write_cb($ch, $data)
    9941008    {
    995         $amount = strlen($data);
     1009        $dlen = strlen($data);
    9961010        switch ($this->_write_callback_type) {
    9971011        case "TEXT_LIST":
     
    9991013            break;
    10001014        case "OBJECT_STREAM":
    1001             $written = 0;
    1002             while ($written < strlen($data)) {
    1003                 $written += fwrite($this->_obj_write_resource, $data-$written);
    1004             }
    1005             if ($written > strlen($data)) {
    1006                 throw new IOException(
    1007                     "Wrote more data to client than we should have?!");
    1008             }
     1015            fwrite($this->_obj_write_resource, $data, $dlen);
    10091016            break;
    10101017        case "OBJECT_STRING":
     
    10131020        }
    10141021        if (isset($this->_user_read_progress_callback_func)) {
    1015             call_user_func($this->_user_read_progress_callback_func,strlen($data));
    1016         }
    1017         return strlen($data);
     1022            call_user_func($this->_user_read_progress_callback_func, $dlen);
     1023        }
     1024        return $dlen;
    10181025    }
    10191026
     
    10521059                    $parts = explode(":", $v);
    10531060                    $header = $parts[0];
    1054                     $value = trim($parts[1]);
     1061                    $value = trim(substr(strstr($v, ":"), 1));
    10551062                } else {
    10561063                    $header = $h;
     
    10891096        }
    10901097
    1091         $this->_set_connections_cainfo();
    1092 
    10931098        if ($this->dbug) { curl_setopt($ch, CURLOPT_VERBOSE, 1); }
     1099
     1100        if (!is_null($this->cabundle_path)) {
     1101            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
     1102            curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
     1103        }
    10941104
    10951105        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
     
    11651175        $hdrs = array();
    11661176        foreach ($obj->metadata as $k => $v) {
    1167             if (strpos($k,":") !== False || strpos($v,":") !== False) {
     1177            if (strpos($k,":") !== False) {
    11681178                throw new SyntaxException(
    1169                     "Metadata cannot contain a ':' character.");
     1179                    "Metadata keys cannot contain a ':' character.");
    11701180            }
    1171             $k = strtolower(trim($k));
     1181            $k = trim($k);
    11721182            $key = sprintf("%s%s", METADATA_HEADER, $k);
    11731183            if (!array_key_exists($key, $hdrs)) {
  • cdn-tools/trunk/cdntools.php

    r161722 r164970  
    55Description: CDN Tools is a plugin designed to help you drastically speed up your blog's load time by loading content onto a distribution network.  You can use a commercial CDN or just load some of your larger JS libraries for free from Google's servers!  At this time Cloud Files is the only supported CDN.
    66Author: Paul Kehrer
    7 Version: 0.93
     7Version: 0.94
    88Author URI: http://langui.sh/
    99*/
     
    2828set_time_limit(300); //5 minutes max...
    2929
    30 define('CDNTOOLS_VERSION','0.93');
     30define('CDNTOOLS_VERSION','0.94');
    3131
    3232$dir_array = explode('/',dirname(__FILE__));
     
    121121
    122122    function bind_filters() {
     123        add_filter('init',array($this,'disable_script_concatenation'));
    123124        add_filter( 'print_scripts_array',array($this,"jquery_noconflict"),100);
    124125        add_filter('wp_handle_upload', array($this,'handle_upload_filter')); //grab data about uploads
     
    127128        add_filter('the_content', array($this,'cdn_media_url_rewrite'), 1000);  //this needs to run after any other filter
    128129        add_filter('wp_generate_attachment_metadata', array($this,'cdn_upload_resized_images'));
     130    }
     131   
     132    //wp 2.8 concatenates scripts in the admin panel and this messes up the google ajax rewriting.  hook init and disable it for now.  revisit for 2.9
     133    function disable_script_concatenation() {
     134        global $concatenate_scripts;
     135        $concatenate_scripts = false;
    129136    }
    130137   
  • cdn-tools/trunk/readme.txt

    r161722 r164970  
    55Requires at least: 2.7
    66Tested up to: 2.8.4
    7 Stable tag: 0.93
     7Stable tag: 0.94
    88
    99CDN Tools is a plugin designed to help you drastically speed up your blog's load time by loading data onto a content distribution network (CDN).
     
    1111== Description ==
    1212
    13 [CDN Tools](http://swearingscience.com/cdn-tools/ "CDN Tools Home") is a WordPress plugin that allows you to load javascript and media files to an external server to drastically speed page loads.  You can sideload data to a commercial CDN or just load your larger JS libraries (prototype, jquery) for **free** from Google's servers.  CDN Tools has been designed to be as easy to use as possible, so give it a shot!  Your blog's readers will thank you.  At this time the only commercial CDN supported is Cloud Files.  Check out the plugin homepage to view a screencast.
     13[CDN Tools](http://langui.sh/cdn-tools/ "CDN Tools Home") is a WordPress plugin that allows you to load javascript and media files to an external server to drastically speed page loads.  You can sideload data to a commercial CDN or just load your larger JS libraries (prototype, jquery) for **free** from Google's servers.  CDN Tools has been designed to be as easy to use as possible, so give it a shot!  Your blog's readers will thank you.  At this time the only commercial CDN supported is Cloud Files.  Check out the plugin homepage to view a screencast.
    1414
    15 = New in 0.92/0.93 =
    16 * A partial fix for issues with customers who have full file paths stored in their postmeta table.  This is not a complete fix, but should help some (most?) users.
    17 * Major upgrade to support WP 2.8.  If you are a previous user of CDN Tools you _MUST_ unload files and then load them again.  Please let me know if you have issues because several major changes were made.  See http://langui.sh/cdn-tools for more details.
     15= New in 0.94 =
     16* Upgraded to CF API 1.4.  This should resolve some cURL issues users have experienced and removes the dependence on a png hack for RHEL4 users.
     17* Fixed major issue with Google AJAX CDN.  Previously users were unable to switch between visual and HTML mode on the edit post page.
    1818
    19 [View complete changelog](http://swearingscience.com/cdn-tools/ "CDN Tools Home").
     19[View complete changelog](http://langui.sh/cdn-tools/ "CDN Tools Home").
    2020
    2121== Installation ==
     
    3333= Could you add XXXX CDN compatibility? =
    3434
    35 I would love to, but I am not currently willing to buy accounts and pay to develop for every possible CDN out there.  If you'd like to supply me with a test account so I can support your favorite CDN I'd be happy to.  Drop me a comment on the CDN Tools home page.
     35Unfortunately I'm likely too busy to do this for your CDN, but I'd be happy to answer questions if you need some assistance in developing your own!  If you write a plugin, please let me know so I can merge it into the main distribution.
    3636
    3737= I found a bug. What do I do? =
     
    4646
    4747== Changelog ==
     48= 0.94 - 10/19/2009 =
     49* Upgraded to CF API 1.4.  This should resolve some cURL issues users have experienced and removes the dependence on a png hack for RHEL4 users.
     50* Fixed major issue with Google AJAX CDN.  Previously users were unable to switch between visual and HTML mode on the edit post page.
     51
    4852= 0.93 - 10/8/2009 =
    4953* A partial fix for issues with customers who have full file paths stored in their postmeta table.  This is not a complete fix, but should help some (most?) users.
Note: See TracChangeset for help on using the changeset viewer.