~tribaal/txaws/xss-hardening

« back to all changes in this revision

Viewing changes to txaws/s3/client.py

Merged from new parent branch (due to the need for the s3 error wrapper).

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
from epsilon.extime import Time
19
19
 
20
 
from txaws.client.base import BaseClient, BaseQuery
 
20
from txaws.client.base import BaseClient, BaseQuery, error_wrapper
21
21
from txaws.s3 import model
 
22
from txaws.s3.exception import S3Error
22
23
from txaws.service import AWSServiceEndpoint, S3_ENDPOINT
23
24
from txaws.util import XML, calculate_md5
24
25
 
25
26
 
 
27
def s3_error_wrapper(error):
 
28
    error_wrapper(error, S3Error)
 
29
 
 
30
 
26
31
class URLContext(object):
27
32
    """
28
33
    The hosts and the paths that form an S3 endpoint change depending upon the
190
195
        self.endpoint.set_method(self.action)
191
196
 
192
197
    def set_content_type(self):
 
198
        """
 
199
        Set the content type based on the file extension used in the object
 
200
        name.
 
201
        """
193
202
        if self.object_name and not self.content_type:
194
203
            # XXX nothing is currently done with the encoding... we may
195
204
            # need to in the future
197
206
                self.object_name, strict=False)
198
207
 
199
208
    def get_headers(self):
 
209
        """
 
210
        Build the list of headers needed in order to perform S3 operations.
 
211
        """
200
212
        headers = {"Content-Length": len(self.data),
201
213
                   "Content-MD5": calculate_md5(self.data),
202
214
                   "Date": self.date}
214
226
        return headers
215
227
 
216
228
    def get_canonicalized_amz_headers(self, headers):
 
229
        """
 
230
        Get the headers defined by Amazon S3.
 
231
        """
217
232
        headers = [
218
233
            (name.lower(), value) for name, value in headers.iteritems()
219
234
            if name.lower().startswith("x-amz-")]
224
239
        return "".join("%s:%s\n" % (name, value) for name, value in headers)
225
240
 
226
241
    def get_canonicalized_resource(self):
 
242
        """
 
243
        Get an S3 resource path.
 
244
        """
227
245
        resource = "/"
228
246
        if self.bucket:
229
247
            resource += self.bucket
232
250
        return resource
233
251
 
234
252
    def sign(self, headers):
235
 
 
 
253
        """Sign this query using its built in credentials."""
236
254
        text = (self.action + "\n" +
237
255
                headers.get("Content-MD5", "") + "\n" +
238
256
                headers.get("Content-Type", "") + "\n" +
242
260
        return self.creds.sign(text, hash_type="sha1")
243
261
 
244
262
    def submit(self, url_context=None):
 
263
        """Submit this query.
 
264
 
 
265
        @return: A deferred from get_page
 
266
        """
245
267
        if not url_context:
246
268
            url_context = URLContext(
247
269
                self.endpoint, self.bucket, self.object_name)
248
270
        d = self.get_page(
249
271
            url_context.get_url(), method=self.action, postdata=self.data,
250
272
            headers=self.get_headers())
251
 
        # XXX - we need an error wrapper like we have for ec2... but let's
252
 
        # wait until the new error-wrapper branch has landed, and possibly
253
 
        # generalize a base class for all clients.
254
 
        #d.addErrback(s3_error_wrapper)
255
 
        return d
 
273
        return d.addErrback(s3_error_wrapper)