Simple status box for the sidebar.
[elgg_plugins.git] / amazons3 / s3.class.php
blob95d50be87ba8b0ef772bfe8ec0ca5c39cfed948f
1 <?php
2 /**
3 * Amazon S3 REST API Implementation
5 * This a generic PHP class that can hook-in to Amazon's S3 Simple Storage Service
6 *
7 * Contributions and/or donations are welcome.
9 * Author: Geoffrey P. Gaudreault
10 * http://www.neurofuzzy.net
12 * This code is free, provided AS-IS with no warranty expressed or implied. Use at your own risk.
13 * If you find errors or bugs in this code, please contact me at interested@zanpo.com
14 * If you enhance this code in any way, please send me an update. Thank you!
16 * Version: 0.31a
17 * Last Updated: 9/09/2006
19 * NOTE: ENTER YOUR API ID AND SECRET KEY BELOW!!!
21 */
23 class s3 {
25 // The API access point URL
26 var $S3_URL = "http://s3.amazonaws.com/";
28 // list of valid actions (validation not implemented yet)
29 var $verbs = array("GET"=>1, "DELETE"=>1, "PUT"=>1);
31 // set to true to echo debug info
32 var $_debug = false;
34 // -----------------------------------------
35 // -----------------------------------------
36 // your API key ID
37 var $keyId = "";
38 // your API Secret Key
39 var $secretKey = "";
40 // -----------------------------------------
41 // -----------------------------------------
43 // default action
44 var $_verb = "GET";
46 // default ACL
47 var $_acl = "private";
49 // default content type
50 var $_contentType = "application/octet-stream";
52 // default response content type
53 var $_responseContentType = "text/xml";
55 // bucket object name prefix
56 var $prefix = "";
58 // bucket list marker (useful for pagination)
59 var $marker = "";
61 // number of keys to retrieve in a list
62 var $max_keys = "";
64 // list delimiter
65 var $delimiter = "";
67 // your default bucket name
68 var $bucketname = "slideroll_photos";
70 // your current object name
71 var $objectname = "temp";
75 * Constructor: Amazon S3 REST API implementation
77 function s3($options = NULL) {
79 define('DATE_RFC822', 'D, d M Y H:i:s T');
80 $this->httpDate = gmdate(DATE_RFC822);
82 $available_options = array("acl", "contentType");
84 if (is_array($options)) {
86 foreach ($options as $key => $value) {
88 $this->debug_text("Option: $key");
90 if (in_array($key, $available_options) ) {
92 $this->debug_text("Valid Config options: $key");
93 $property = '_'.$key;
94 $this->$property = $value;
95 $this->debug_text("Setting $property to $value");
97 } else {
99 $this->debug_text("ERROR: Config option: $key is not a valid option");
107 // REQUIRES PEAR PACKAGE
108 // get with "pear install Crypt_HMAC"
109 require_once 'Crypt/HMAC.php';
111 $this->hasher =& new Crypt_HMAC($this->secretKey, "sha1");
113 // REQUIRES PEAR PACKAGE
114 // get with "pear install --onlyreqdeps HTTP_Request"
116 // NOTE FROM AMAZON:
118 // Note that version HTTP_Request 1.3.0 has a BUG in it! Change line
119 // 765 from:
120 // (HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_postData) && empty($this->_postFiles))) {
121 // to:
122 // (HTTP_REQUEST_METHOD_POST == $this->_method && empty($this->_postData) && empty($this->_postFiles))) {
124 // Without this change PUTs with non-empty content-type will fail!
126 require_once 'HTTP/Request.php';
132 * Method: setBucketName
133 * Sets the name of the default bucket
135 function setBucketName ($bucket) {
136 $this->bucketname = $bucket;
141 * Method: getBucketName
142 * Gets the name of the default bucket
144 function getBucketName () {
145 return $this->bucketname;
150 * Method: setBucketName
151 * Sets the name of the default bucket
153 function setObjectName ($object) {
154 $this->objectname = $object;
159 * Method: getObjectName
160 * Gets the name of the current object
162 function getObjectName () {
163 return $this->objectname;
168 * Method: setContentType
169 * Sets the content type of the object
171 function setContentType ($ct) {
172 $this->_contentType = $ct;
177 * Method: getContentType
178 * Gets the content type of the object
180 function getContentType () {
181 return $this->_contentType;
186 * Method: getResponseContentType
187 * Gets the content type of the response
189 function getResponseContentType () {
190 return $this->_responseContentType;
195 * Method: setAcl
196 * sets the acces control policy for the current object
198 function setAcl ($acl) {
199 $this->_acl = $acl;
204 * Method: getAcl
205 * gets the acces control policy for the current object
207 function getAcl () {
208 return $this->_acl;
213 * Method: sendRequest
214 * Sends the request to S3
216 * Parameters:
217 * resource - the name of the resource to act upon
218 * verb - the action to apply to the resource (GET, PUT, DELETE, HEAD)
219 * objectdata - the source data (body) of the resource (only applies to objects)
220 * acl - the access control policy for the resource
221 * contentType - the contentType of the resource (only applies to objects)
222 * metadata - any metadata you want to save in the header of the object
224 function sendRequest ($resource, $verb = NULL, $objectdata = NULL, $acl = NULL, $contentType = NULL, $metadata = NULL) {
226 if ($verb == NULL) {
227 $verb = $this->verb;
230 if ($acl == NULL) {
231 $aclstring = "";
232 } else {
233 $aclstring = "x-amz-acl:$acl\n";
236 $contenttypestring = "";
238 if ($contentType != NULL && ($verb == "PUT") && ($objectdata != NULL) && ($objectdata != "")) {
239 $contenttypestring = "$contentType";
242 // update date / time on each request
243 $this->httpDate = gmdate(DATE_RFC822);
244 // $this->httpDate = str_replace("0000","000",str_replace("+",".",gmdate(DATE_ISO8601))) . "Z";
246 $httpDate = $this->httpDate;
248 $paramstring = "";
249 $delim = "?";
251 if (strlen($this->prefix)) {
253 $paramstring .= $delim."prefix=".urlencode($this->prefix);
254 $delim = "&";
258 if (strlen($this->marker)) {
260 $paramstring .= $delim."marker=".urlencode($this->marker);
261 $delim = "&";
265 if (strlen($this->max_keys)) {
267 $paramstring .= $delim."max-keys=".$this->max_keys;
268 $delim = "&";
272 if (strlen($this->delimiter)) {
274 $paramstring .= $delim."delimiter=".urlencode($this->delimiter);
275 $delim = "&";
279 $this->debug_text("HTTP Request sent to: " . $this->S3_URL . $resource . $paramstring);
281 $req =& new HTTP_Request($this->S3_URL . $resource . $paramstring);
282 $req->setMethod($verb);
284 if (($objectdata != NULL) && ($objectdata != "")) {
286 $contentMd5 = $this->hex2b64(md5($objectdata));
287 $req->addHeader("CONTENT-MD5", $contentMd5);
288 $this->debug_text("MD5 HASH OF DATA: " . $contentMd5);
290 $contentmd5string = $contentMd5;
292 } else {
294 $contentmd5string = "";
298 if (strlen($contenttypestring)) {
299 $this->debug_text("Setting content type to $contentType");
300 $req->addHeader("CONTENT-TYPE", $contentType);
303 $req->addHeader("DATE", $httpDate);
305 if (strlen($aclstring)) {
306 $this->debug_text("Setting acl string to $acl");
307 $req->addHeader("x-amz-acl", $acl);
310 $metadatastring = "";
312 if (is_array($metadata)) {
314 ksort($metadata);
316 $this->debug_text("Metadata found.");
318 foreach ($metadata as $key => $value) {
320 $metadatastring .= "x-amz-meta-".$key.":".trim($value)."\n";
322 $req->addHeader("x-amz-meta-".$key, trim($value));
324 $this->debug_text("Setting x-amz-meta-$key to '$value'");
330 if (($objectdata != NULL) && ($objectdata != "")) {
332 $req->setBody($objectdata);
336 $stringToSign = "$verb\n$contentmd5string\n$contenttypestring\n$httpDate\n$aclstring$metadatastring/$resource";
337 // $stringToSign = "$verb\n$contentmd5string\n$httpDate\n$aclstring$metadatastring/$resource";
338 $this->debug_text("Signing String: $stringToSign");
339 $signature = $this->hex2b64($this->hasher->hash($stringToSign));
340 $this->debug_text("Signed string: $signature");
341 $req->addHeader("Authorization", "AWS " . $this->keyId . ":" . $signature);
343 $req->sendRequest();
345 $this->_responseContentType = $req->getResponseHeader("content-type");
347 if (strlen($req->getResponseBody())) {
349 $this->debug_text($req->getResponseBody());
350 return $req->getResponseBody();
352 } else {
354 $this->debug_text($req->getResponseHeader());
355 return $req->getResponseHeader();
363 * Method: getBuckets
364 * Returns a list of all buckets
366 function getBuckets () {
367 return $this->sendRequest("","GET");
372 * Method: getBucket
373 * Gets a list of all objects in the default bucket
375 function getBucket ($bucketname = NULL) {
377 if ($bucketname == NULL) {
379 return $this->sendRequest($this->bucketname,"GET");
381 } else {
383 return $this->sendRequest($bucketname,"GET");
391 * Method: getObjects
392 * Gets a list of all objects in the specified bucket
394 * Parameters:
395 * prefix - (optional) Limits the response to keys which begin with the indicated prefix. You can use prefixes to separate a bucket into different sets of keys in a way similar to how a file system uses folders.
396 * marker - (optional) Indicates where in the bucket to begin listing. The list will only include keys that occur lexicographically after marker. This is convenient for pagination: To get the next page of results use the last key of the current page as the marker.
397 * max-keys - (optional) The maximum number of keys you'd like to see in the response body. The server may return fewer than this many keys, but will not return more.
399 function getObjects ($bucketname, $prefix = NULL, $marker = NULL, $max_keys = NULL, $delimiter = NULL) {
401 if ($prefix != NULL) {
403 $this->prefix = $prefix;
405 } else {
407 $this->prefix = "";
411 if ($marker != NULL) {
413 $this->marker = $marker;
415 } else {
417 $this->marker = "";
421 if ($max_keys != NULL) {
423 $this->max_keys = $max_keys;
425 } else {
427 $this->max_keys = "";
431 if ($delimiter != NULL) {
433 $this->delimiter = $delimiter;
435 } else {
437 $this->delimiter = "";
441 if ($bucketname != NULL) {
443 return $this->sendRequest($bucketname,"GET");
445 } else {
447 return false;
455 * Method: getObjectInfo
456 * Get header information about the object. The HEAD operation is used to retrieve information about a specific object,
457 * without actually fetching the object itself
459 * Parameters:
460 * objectname - The name of the object to get information about
461 * bucketname - (optional) the name of the bucket containing the object. If none is supplied, the default bucket is used
463 function getObjectInfo ($objectname, $bucketname = NULL) {
464 if ($bucketname == NULL) {
465 $bucketname = $this->bucketname;
467 return $this->sendRequest($bucketname."/".$objectname,"HEAD");
472 * Method: getObject
473 * Gets an object from S3
475 * Parameters:
476 * objectname - the name of the object to get
477 * bucketname - (optional) the name of the bucket containing the object. If none is supplied, the default bucket is used
479 function getObject ($objectname, $bucketname = NULL) {
480 if ($bucketname == NULL) {
481 $bucketname = $this->bucketname;
483 return $this->sendRequest($bucketname."/".$objectname,"GET");
488 * Method: putBucket
489 * Creates a new bucket in S3
491 * Parameters:
492 * bucketname - the name of the bucket. It must be unique. No other S3 users may have this bucket name
494 function putBucket ($bucketname) {
495 return $this->sendRequest($bucketname,"PUT");
500 * Method: putObject
501 * Puts an object into S3
503 * Parameters:
504 * objectname - the name of the object to put
505 * objectdata - the source data (body) of the resource (only applies to objects)
506 * bucketname - (optional) the name of the bucket containing the object. If none is supplied, the default bucket is used
507 * acl - the access control policy for the resource
508 * contentType - the contentType of the resource (only applies to objects)
509 * metadata - any metadata you want to save in the header of the object
511 function putObject ($objectname, $objectdata, $bucketname = NULL, $acl = NULL, $contentType = NULL, $metadata = NULL) {
513 if ($bucketname == NULL) {
514 $bucketname = $this->bucketname;
517 if ($acl == NULL || $acl == "") {
518 $acl = $this->_acl;
521 if ($contentType == NULL || $contentType == "") {
522 $contentType = $this->_contentType;
525 if ($objectdata != NULL) {
526 return $this->sendRequest($bucketname."/".$objectname, "PUT", $objectdata, $acl, $contentType, $metadata);
527 } else {
528 return false;
535 * Method: deleteBucket
536 * Deletes bucket in S3. The bucket name will fall into the public domain.
538 function deleteBucket ($bucketname) {
539 return $this->sendRequest($bucketname, "DELETE");
544 * Method: deleteObject
545 * Deletes an object from S3
547 * Parameters:
548 * objectname - the name of the object to delete
549 * bucketname - (optional) the name of the bucket containing the object. If none is supplied, the default bucket is used
551 function deleteObject ($objectname, $bucketname = NULL) {
553 if ($bucketname == NULL) {
555 $bucketname = $this->bucketname;
559 return $this->sendRequest($bucketname."/".$objectname, "DELETE");
565 * Method: hex2b64
566 * Utility function for constructing signatures
568 function hex2b64($str) {
570 $raw = '';
571 for ($i=0; $i < strlen($str); $i+=2) {
572 $raw .= chr(hexdec(substr($str, $i, 2)));
574 return base64_encode($raw);
580 * Method: debug_text
581 * Echoes debug information to the browser. Set this->debug to false for production use
583 function debug_text($text) {
585 if ($this->_debug) {
586 echo("<br>\n");
587 print_r($text);
588 echo("<br><br>\n\n");
591 return true;