diff --git a/S3.php b/S3.php index 6f1e0499..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 @@ -1813,6 +1836,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 +1875,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 +1968,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;