/[drupal]/contributions/modules/aws/aws.module
ViewVC logotype

Contents of /contributions/modules/aws/aws.module

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


Revision 1.6 - (show annotations) (download) (as text)
Fri Feb 29 07:14:09 2008 UTC (20 months, 4 weeks ago) by dragonwize
Branch: MAIN
CVS Tags: DRUPAL-6--1-0, HEAD
Branch point for: DRUPAL-6--1
Changes since 1.5: +147 -146 lines
File MIME type: text/x-php
minor format changes
1 <?php
2 // $Id: aws.module,v 1.5 2008/02/10 04:52:18 dragonwize Exp $
3 /**
4 * @file
5 * An base module for for common functions that are used by
6 * the sub-modules enabling specific Amazon Web Services API for
7 * other Drupal modules.
8 */
9
10 /**
11 * Implementation of hook_perm()
12 * @return array An array of valid permissions for the aws module
13 */
14 function aws_perm() {
15 return array('administer aws');
16 }
17
18 /**
19 * Implementation hook_menu()
20 * @return array A menu api array for the module
21 */
22 function aws_menu($may_cache) {
23 $items = array();
24 if (!$may_cache) {
25 $items[] = array(
26 'path' => 'admin/settings/aws',
27 'title' => t('Amazon Web Services'),
28 'description' => t('Amazon Web Services Settings'),
29 'callback' => 'drupal_get_form',
30 'callback arguments' => 'aws_admin_settings',
31 'access' => user_access('administer aws')
32 );
33 $items[] = array(
34 'path' => 'admin/settings/aws/api',
35 'title' => t('AWS'),
36 'description' => t('Amazon Web Services Settings'),
37 'type' => MENU_DEFAULT_LOCAL_TASK,
38 'access' => user_access('administer aws')
39 );
40 }
41 return $items;
42 }
43
44 /**
45 * Implementation admin_settings()
46 * @return array A form api array of the admin setting
47 */
48 function aws_admin_settings() {
49 $form['aws_accessKey'] = array(
50 '#type' => 'textfield',
51 '#title' => t('AWS Access Key'),
52 '#default_value' => variable_get('aws_accessKey', ''),
53 '#size' => 21,
54 '#maxlength' => 20,
55 '#description' => t('Amazon web services access key ID.')
56 );
57
58 $form['aws_secretKey'] = array(
59 '#type' => 'textfield',
60 '#title' => t('AWS Secret Key'),
61 '#default_value' => variable_get('aws_secretKey', ''),
62 '#size' => 41,
63 '#maxlength' => 40,
64 '#description' => t('Amazon web services secret access key.')
65 );
66
67 // Define a validation function.
68 $form['#validate'] = array(
69 'aws_admin_settings_validate' => array()
70 );
71
72 return system_settings_form($form);
73 }
74
75 /**
76 * validate aws admin settings form
77 * @param string $form_id
78 * @param array $form_values
79 */
80 function aws_admin_settings_validate($form_id, $form_values) {
81 if (strlen($form_values['aws_accessKey']) !== 20) {
82 form_set_error('aws_accessKey', t('AWS access key ID must be 20 characters long.'));
83 }
84 if (strlen($form_values['aws_secretKey']) !== 40) {
85 form_set_error('aws_accessKey', t('AWS secret access key must be 40 characters long.'));
86 }
87 }
88
89
90 /* ******************** AWS Common Functions **********************************/
91
92 /* ******************** AWS REST API Functions ********************************/
93
94 /**
95 * AWS REST request controller.
96 * @public
97 * @param array $request see README
98 * @param array $headers see README
99 * @param array $data see README
100 * @param int $retry number of retries if redirected
101 * @return object std class see README
102 */
103 function aws_restRequest($request = array(), $headers = array(), $data = null, $retry = 3) {
104 $headers = aws_buildRestHeader($request, $headers, $data);
105 return rest_client_request($request, $headers, $data, $retry);
106 }
107
108 /**
109 * Builds the needed headers for AWS over REST, including signing the header.
110 * @private
111 * @param array $request see README
112 * @param array $headers see README
113 * @param array $data see README
114 * @return array of headers to be used in the HTTP request
115 */
116 function aws_buildRestHeader($request, $headers, $data) {
117 // TODO: run check for all aws specific required headers and provide error feedback
118
119 // get AWS access key
120 $accessKey = variable_get('aws_accessKey', '');
121
122 // set request defaults
123 $request['host'] = $headers['host'];
124 $request['method'] = $request['method'] ? $request['method'] : 'GET';
125 $request['resource'] = $request['resource'] ? $request['resource'] : '/';
126 $request['port'] = $request['port'] ? $request['port'] : '80';
127 $request['httpversion'] = $request['httpversion'] ? $request['httpversion'] : '1.0';
128
129 // set defaults
130 $headers['content-md5'] = $data ? base64_encode(rest_client_binaryMd5($data)) : '';
131 // not using DATE_RFC822 constant to be PHP4 compat, DATE_RFC822 > PHP 5.1.1
132 $headers['date'] = gmdate('D, d M Y H:i:s T');
133
134 if ($data && ! $headers['content-type']) {
135 $headers['content-type'] = ($data['type'] === 'string') ? 'text/plain' : 'binary/octet-stream';
136 }
137
138 // set authorization with header signature
139 $headers['authorization'] = 'AWS ' . $accessKey . ':' . aws_headerSign($request, $headers);
140
141 return $headers;
142 }
143
144 /**
145 * Creates the header signature
146 * @private
147 * @param array $request see README
148 * @param array $headers see README
149 * @return string header signature
150 */
151 function aws_headerSign($request, $headers) {
152 $strToSign = strtoupper($request['method']) . "\n" . $headers['content-md5'] .
153 "\n" . $headers['content-type'] . "\n" . $headers['date'];
154
155 // Format and sort x-amz headers
156 $h = array();
157 foreach($headers as $key => $val) {
158 $key = trim(strtolower($key));
159 $val = trim($val);
160 if(substr($key, 0, 5) === 'x-amz') {
161 if(isset($h[$key])) {
162 $h[$key] .= ",$val";
163 } else {
164 $h[$key] = "$key:$val";
165 }
166 }
167 }
168 if ($h !== array()) {
169 ksort($h);
170 $h = implode("\n", $h);
171 $h = "\n$h";
172 } else {
173 $h = '';
174 }
175
176 // get AWS secret access key
177 $secretKey = variable_get('aws_secretKey', '');
178
179 // Build and sign the string
180 $strToSign .= $h . "\n" . $request['cresource'];
181 return aws_hmac($strToSign, $secretKey);
182 }
183
184
185
186
187 /* ******************** AWS Query API Functions *******************************/
188
189 /**
190 * AWS Query request controller.
191 * @public
192 * @param string $host request host
193 * @param array $query key => value pair array holding query parameters and values
194 * @param bool $ssl true to use https
195 * @param int $retry number of retries if redirected
196 * @return object std class see README
197 */
198 function aws_queryRequest($host, $request = array(), $ssl = false, $headers = array(), $retry = 3) {
199 $query = aws_buildQueryString($request);
200 $scheme = $ssl ? 'https' : 'http';
201 $url = $scheme . '://' . $host . '/?' . $query;
202 return drupal_http_request($url, $headers, 'GET', null, $retry);
203 }
204
205 /**
206 * Builds the querystring for AWS over QUERY, including signing the header.
207 * @private
208 * @param array $query key => value pair array holding query parameters and values
209 * @param array $headers see README
210 * @param array $data see README
211 * @return the query string to be used in the HTTP request
212 */
213 function aws_buildQueryString($query) {
214 // required querystring values
215 $query['AWSAccessKeyId'] = variable_get('aws_accessKey', '');
216 $query['SignatureVersion'] = 1;
217
218 // Use an expiry if we've set one.
219 // Amazon defaults to 15 minutes when a timestamp is used instead
220 if ( ! $query['Expires']) {
221 $query['Timestamp'] = gmdate('Y-m-d\TH:i:s') . 'Z';
222 }
223
224 // set authorization with header signature
225 $query['Signature'] = aws_querySign($query);
226
227 // return the encoded querystring
228 return drupal_query_string_encode($query);
229 }
230
231 /**
232 * Creates the querystring signature
233 * @private
234 * @param array $request see README
235 * @return string signature
236 */
237 function aws_querySign($query) {
238 // Amazon need items sorted case-insensitively
239 uksort($query, 'strnatcasecmp');
240
241 // get AWS secret access key
242 $secretKey = variable_get('aws_secretKey', '');
243
244 // Build and sign the string
245 foreach ($query as $key => $value) {
246 $strToSign .= $key . $value;
247 }
248
249 return aws_hmac($strToSign, $secretKey);
250 }
251
252 /**
253 * Converts an array to array with numbered labels ('item.1' => 'data', 'item.2' => 'data')
254 * @private
255 * @param string $label Label name to prepend .<itemcount>
256 * @param array $items Array of items
257 * @return array formatted array
258 */
259 function aws_numberKeys($label, $items = array()) {
260 $result = array();
261 $itemcount = 1;
262 foreach ($items as $item) {
263 $result[$label . '.' . ++$itemcount] = $item;
264 }
265 return $result;
266 }
267
268
269
270
271 /* *********************** Utility functions *****************************/
272
273 /**
274 * Creates a HMAC code
275 * @public
276 * @param string $data data to be encoded
277 * @param sting $key key to use for encryption
278 * @return string binary version of a sha1 hash
279 */
280 function aws_hmac($data, $key) {
281 if (strlen($key) < 64) {
282 $key = str_pad($key, 64, chr(0));
283 }
284 $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
285 $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5c), 64));
286
287 $hmac = aws_binarySha1($opad . aws_binarySha1($ipad . $data));
288
289 return base64_encode($hmac);
290 }
291
292 /**
293 * Creates a binary sha1 hash
294 * @public
295 * @param string $data
296 * @return string binary version of a sha1 hash
297 */
298 function aws_binarySha1($data) {
299 if (version_compare(PHP_VERSION, '5.0.0', '>=')) {
300 return sha1($data, true);
301 } else {
302 return pack('H40', sha1($data));
303 }
304 }
305
306 ?>
307

  ViewVC Help
Powered by ViewVC 1.1.2