/[drupal]/contributions/modules/fileapi/drivers/s3.driver
ViewVC logotype

Contents of /contributions/modules/fileapi/drivers/s3.driver

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3.4.2 - (show annotations) (download)
Thu Jan 4 11:07:59 2007 UTC (2 years, 10 months ago) by dopry
Branch: DRUPAL-5
Changes since 1.3.4.1: +19 -8 lines
fixing issues with the Content-MD5 and Content-Type headers in s3_request... like they weren't.
1 <?php
2
3 /**
4 * @file
5 * Amazon S3 storage driver for fileapi.
6 *
7 * We are treating S3 like a normal hierarchal filesystem. The bucket
8 * is predetermined by the mountpoint settings. Except for list buckets
9 * and put bucket functions.
10 *
11 * We use the keys with a delimiter of '/' to create our heirarchy.
12 *
13 * @todo examine adding caching to save some requests to S3.
14 *
15 */
16
17
18 /**
19 * driver settings form. called by fileapi.module when creating a respository using this driver.
20 * @param $settings
21 * settings array from database.
22 * @todo convert form to multistep to allow input of credentials, then bucket selection/creation.
23 * @todo add bucket access control policy settings
24 */
25
26 function fileapi_driver_s3_settings_form($settings = array()) {
27 //debug_msg($settings);
28 $form = array(
29 '#type' => 'fieldset',
30 '#title' => t('Amazon S3 storage driver settings'),
31 '#tree' => TRUE,
32 );
33
34 $form['driver'] = array(
35 '#type' => 'hidden',
36 '#value' => 's3',
37 );
38
39 $form['s3 url'] = array(
40 '#type' => 'textfield',
41 '#title' => t('Amazon S3 url'),
42 '#description' => t('The URL must not contain a trailing slash.'),
43 '#default_value' => strlen($settings['s3 url']) ? $settings['s3 url'] : 'http://s3.amazonaws.com',
44 );
45
46 $form['awsID'] = array(
47 '#type' => 'textfield',
48 '#title' => t('AWS Access Key ID'),
49 '#default_value' => $settings['awsID'],
50 );
51
52 $form['awsSecret'] = array(
53 '#type' => 'textfield',
54 '#title' => t('AWS Secret'),
55 '#default_value' => $settings['awsSecret'],
56 );
57
58 $form['bucket'] = array(
59 '#type' => 'textfield',
60 '#title' => t('S3 Bucket'),
61 '#default_value' => $settings['bucket'],
62 );
63
64 return $form;
65 }
66
67 function fileapi_driver_s3_settings_form_validate() {
68 //@todo test for trailing slash in 's3 url';
69 }
70
71 function fileapi_driver_s3_settings_form_submit() {
72 //@todo create bucket if it doesn't exist.
73 }
74
75
76 /**
77 * test if a path is a file.
78 *
79 * for S3 we are going to operate on an object if an object
80 * has the key we're requesting.
81 * see: S3 Developers Guide pg 67.
82 *
83 * @param $path
84 * path to be tested
85 *
86 */
87 function fileapi_driver_s3_is_file($settings, $path) {
88 // request meta data for an object with the key $path.
89 $result = s3_request('HEAD', $settings['bucket'] .'/'. $path, $settings);
90
91 //parse results for request...
92 }
93
94 /**
95 * test if a path is a directory.
96 * @param $path
97 * path to be tested
98 */
99 function fileapi_driver_s3_is_dir($settings, $path) {
100 }
101
102
103 /**
104 * create a directory using standard php functions
105 * @param $path
106 */
107 function fileapi_driver_s3_mkdir($settings, $path) {
108 // there are technically no directories, so we can safely do
109 // nothing here.
110 return TRUE;
111 }
112
113
114 /**
115 * remove a directory using standard php functions
116 * @param $path
117 */
118
119 function fileapi_driver_s3_rmdir($settings, $path) {
120 // there are technically no directories.
121 // so we can test is there is a file in the 'directory' and return false here.
122 }
123
124
125 /**
126 * remove a file using standard php functions
127 * @param $path
128 */
129 function fileapi_driver_s3_remove($settings, $path) {
130
131 }
132
133 /**
134 * copy a file using standard php functions
135 * @param $src
136 * @param $dst
137 */
138 function fileapi_driver_s3_copy($settings, $src, $dst) {
139
140 }
141
142 /**
143 * move a file using standard php functions
144 * @param $src
145 * @param $dst
146 */
147 function fileapi_driver_s3_move($settings, $src, $dst) {
148
149 }
150
151 /**
152 * check if a file exists using standard php functions
153 * @param $path
154 */
155 function fileapi_driver_s3_exists($settings, $path) {
156 }
157
158 /**
159 * touch a path and create a file there.
160 * @param $path
161 * path to be touched.
162 */
163 function fileapi_driver_s3_touch($settings, $path) {
164 $tmp = file_directory_tmp() .'/'. basename($path);
165 touch($tmp);
166 $headers = array();
167 $headers['Content-Type'] = 'text/plain';
168 $body = file_get_contents($tmp);
169 $result = s3_request('PUT', $path, $settings, array(), $body);
170 $xml = SimpleXMLElement($result['data']);
171 unlink($tmp);
172 }
173
174
175 /**
176 * read the contents of a directory.
177 * @param $path
178 * directory to be read.
179 * @return array
180 * action results and array of directory contents.
181 */
182 function fileapi_driver_s3_readdir($settings, $path) {
183 // $result = s3_request('GET', $settings['bucket'] .'?delimiter=/&key=$path', $settings);
184 }
185
186 /**
187 * read the contents of a file.
188 * @param $path
189 * path of file to be read.
190 *
191 * NOTE: we are not including offset and maxlen since it is only supported in php > 5.1.0
192 * and our support target is 4.3.0.
193 */
194 function fileapi_driver_s3_fileread($settings, $path) {
195 // $result = s3_request('GET', $path, $settings);
196 return $result;
197 }
198
199 function fileapi_driver_s3_filewrite($settings, $path, $data) {
200 $headers = array('Content-Type' => 'text/plain');
201 // $result = s3_request('PUT', $settings['bucket'] .'/'. $path, $settings, array(), $data);
202 return $result;
203 }
204
205 function s3_request($method, $resource, $settings, $headers=array(), $amzheaders=array(), $body=NULL) {
206
207 $url = $settings['s3 url'];
208
209 // Set date to proper format for S3.
210 $headers['Date'] = gmdate(DATE_RFC822);
211 if (!is_null($body)) {
212 $headers['Content-MD5'] = hex2b64(md5($body));
213 }
214
215 // Build S3 authorization hash.
216 $auth_string = $method ."\n";
217 // Apparently we need a trailing \n whether we have a body or not...
218 if (isset($headers['Content-MD5'])) {
219 $auth_string .= $headers['Content-MD5'];
220 }
221 $auth_string .= "\n" . $headers['Content-Type'] ."\n" . $headers['Date'] ."\n";
222 // Apparently we DONT need a trailing \n here if its not present.
223 if (count($amzheaders)) {
224 $auth_string .= implode("\n",$amzheaders) ."\n";
225 }
226 $auth_string .= '/'. $resource;
227 $signature = hex2b64(s3_hmac_sha1($settings['awsSecret'], $auth_string));
228 print "auth_string:\n$auth_string\n";
229 print "signature: $signature\n";
230
231 // Set date to proper format for S3.
232 $headers['Date'] = gmdate(DATE_RFC822);
233 $headers['Authorization'] = 'AWS '. $settings['awsID'] .':'. $signature;
234
235 $result = drupal_http_request($url .'/'. $resource, array_merge($headers, $amzheaders), $method, $body);
236 return $result;
237 // drupal_set_message('<pre>'. print_r($result, TRUE) .'</pre>');
238 // @todo error handling.
239 }
240
241
242 /**
243 * Generate an sha1 signed hash of a string.
244 * @param K
245 * key to be used for the signature.
246 * @param string
247 * string to be signed.
248 */
249 function s3_hmac_sha1($K, $string) {
250 // hash function
251 $h = 'sha1';
252 // byte length of blocks operated on by hash function.
253 $B = '64';
254 // byte length of hash function output.
255 // seems unused in the HMAC algorithm
256 $L = '20';
257 return s3_hmac($h, $B, $K, $string);
258 }
259
260 /**
261 * HMAC implementation for drupal as per
262 * http://www.ietf.org/rfc/rfc2104.txt
263 *
264 * @param $h
265 * hashing function can be any
266 * @param $B
267 * block length iterated over by hashing algorithm
268 * @param $K
269 * key to be used for signing.
270 * @param $string
271 * string to be signed.
272 */
273 function s3_hmac($h, $B, $K, $string) {
274 // Hash the key if it exceeds the blocklength.
275 if (strlen($K) > $B) {
276 // Pack that dirty string.
277 $K = pack('H*', $h($K));
278 }
279 // pad it with 0 bytes to block length
280 $K = str_pad($K, $B, chr(0x00));
281
282 // Setup inner and outer pads as per the RFC.
283 $ipad = str_repeat(chr(0x36), $B)^$K;
284 $opad = str_repeat(chr(0x5C), $B)^$K;
285
286 // Do inner concat XOR hashing. Pack that dirty string.
287 $string = pack('H*', $h($ipad.$string));
288
289 // return outer concat XOR hash
290 return $h($opad.$string);
291 }
292
293 // conversion.
294 function hex2b64($str)
295 {
296 $raw = '';
297 for ($i=0; $i < strlen($str); $i+=2)
298 {
299 $raw .= chr(hexdec(substr($str, $i, 2)));
300 }
301 return base64_encode($raw);
302 }
303

  ViewVC Help
Powered by ViewVC 1.1.2