From 7ef51be754c1feb64104b8c529da2374aee805c4 Mon Sep 17 00:00:00 2001 From: Nathan Phillip Brink Date: Fri, 23 Dec 2011 04:16:51 +0000 Subject: [PATCH 1/2] Let libcurl parse the Last-Modified header, avoiding one call to strtotime(). --- S3.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/S3.php b/S3.php index 6f1e0499..42d79502 100644 --- a/S3.php +++ b/S3.php @@ -1813,6 +1813,7 @@ public function getResponse() } curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_FILETIME, true); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, false); curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback')); @@ -1851,7 +1852,12 @@ public function getResponse() // Execute, grab errors if (curl_exec($curl)) + { $this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $last_modified = curl_getinfo($curl, CURLINFO_FILETIME); + if ($last_modified > -1) + $this->response->headers['time'] = $last_modified; + } else $this->response->error = array( 'code' => curl_errno($curl), @@ -1939,9 +1945,7 @@ private function __responseHeaderCallback(&$curl, &$data) $data = trim($data); if (strpos($data, ': ') === false) return $strlen; list($header, $value) = explode(': ', $data, 2); - if ($header == 'Last-Modified') - $this->response->headers['time'] = strtotime($value); - elseif ($header == 'Content-Length') + if ($header == 'Content-Length') $this->response->headers['size'] = (int)$value; elseif ($header == 'Content-Type') $this->response->headers['type'] = $value; From 23b807f826789ade43aaeedd0ba25c65685b07cf Mon Sep 17 00:00:00 2001 From: Nathan Phillip Brink Date: Fri, 23 Dec 2011 04:20:04 +0000 Subject: [PATCH 2/2] Avoid PHP's notices about setting the timezone which are irrelevant when parsing UTC dates. This is done by avoiding calls to strtotime(). Instead, a DateTimeZone object with UTC set as its timezone is created. When this object is passed to DateTime's constructor, PHP is pacified by being given the timezone context even though it isn't consulted. --- S3.php | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/S3.php b/S3.php index 42d79502..3ee2cf0d 100644 --- a/S3.php +++ b/S3.php @@ -64,6 +64,8 @@ class S3 private static $__signingKeyPairId = null; // AWS Key Pair ID private static $__signingKeyResource = false; // Key resource, freeSigningKey() must be called to clear it from memory + // Used by self::__utcstrtotime() + private static $__timezone = null; /** * Constructor - if you're not using the class statically @@ -79,6 +81,10 @@ public function __construct($accessKey = null, $secretKey = null, $useSSL = fals self::setAuth($accessKey, $secretKey); self::$useSSL = $useSSL; self::$endpoint = $endpoint; + + /* Create the dummy UTC timezone object used by self::__utcstrtotime() */ + if (self::$__timezone === null) + self::$__timezone = new DateTimeZone('UTC'); } @@ -253,7 +259,7 @@ public static function listBuckets($detailed = false) $results['buckets'] = array(); foreach ($rest->body->Buckets->Bucket as $b) $results['buckets'][] = array( - 'name' => (string)$b->Name, 'time' => strtotime((string)$b->CreationDate) + 'name' => (string)$b->Name, 'time' => self::__utcstrtotime((string)$b->CreationDate) ); } else foreach ($rest->body->Buckets->Bucket as $b) $results[] = (string)$b->Name; @@ -301,7 +307,7 @@ public static function getBucket($bucket, $prefix = null, $marker = null, $maxKe { $results[(string)$c->Key] = array( 'name' => (string)$c->Key, - 'time' => strtotime((string)$c->LastModified), + 'time' => self::__utcstrtotime((string)$c->LastModified), 'size' => (int)$c->Size, 'hash' => substr((string)$c->ETag, 1, -1) ); @@ -334,7 +340,7 @@ public static function getBucket($bucket, $prefix = null, $marker = null, $maxKe { $results[(string)$c->Key] = array( 'name' => (string)$c->Key, - 'time' => strtotime((string)$c->LastModified), + 'time' => self::__utcstrtotime((string)$c->LastModified), 'size' => (int)$c->Size, 'hash' => substr((string)$c->ETag, 1, -1) ); @@ -667,7 +673,7 @@ public static function copyObject($srcBucket, $srcUri, $bucket, $uri, $acl = sel return false; } return isset($rest->body->LastModified, $rest->body->ETag) ? array( - 'time' => strtotime((string)$rest->body->LastModified), + 'time' => self::__utcstrtotime((string)$rest->body->LastModified), 'hash' => substr((string)$rest->body->ETag, 1, -1) ) : false; } @@ -1470,7 +1476,7 @@ private static function __parseCloudFrontDistributionConfig(&$node) { $dist['id'] = (string)$node->Id; $dist['status'] = (string)$node->Status; - $dist['time'] = strtotime((string)$node->LastModifiedTime); + $dist['time'] = self::__utcstrtotime((string)$node->LastModifiedTime); $dist['domain'] = (string)$node->DomainName; } @@ -1624,6 +1630,23 @@ private static function __getHash($string) (str_repeat(chr(0x36), 64))) . $string))))); } + + /** + * Convert a UTC time string to a timestamp + * + * This function avoids PHP's silly irrelevant notices about + * setting the timezone. + * + * @internal Used wherever we are forced to parse time. + * @param string $time The UTC time to parse. + * @return int The unix timestamp for $time. + */ + private static function __utcstrtotime($time) + { + $t = new DateTime($time, self::$__timezone); + return $t->getTimestamp(); + } + } final class S3Request