diff --git a/swift/common/middleware/swift3.py b/swift/common/middleware/swift3.py
index de66a8d677..979c007538 100644
--- a/swift/common/middleware/swift3.py
+++ b/swift/common/middleware/swift3.py
@@ -18,7 +18,7 @@ import rfc822
import hmac
import base64
import errno
-import binascii
+from xml.sax.saxutils import escape as xml_escape
from webob import Request, Response
from webob.exc import HTTPNotFound
@@ -43,16 +43,20 @@ def get_err_response(code):
'NoSuchBucket':
(404, 'The specified bucket does not exist'),
'SignatureDoesNotMatch':
- (403, 'The calculated request signature does not match your provided one'),
+ (403, 'The calculated request signature does not match '\
+ 'your provided one'),
'NoSuchKey':
(404, 'The resource you requested does not exist')}
resp = Response(content_type='text/xml')
resp.status = error_table[code][0]
resp.body = error_table[code][1]
- resp.body = """\r\n\r\n %s
\r\n %s\r\n\r\n""" % (code, error_table[code][1])
+ resp.body = '\r\n\r\n ' \
+ '%s
\r\n %s\r\n\r\n' \
+ % (code, error_table[code][1])
return resp
+
class Controller(object):
def __init__(self, app):
self.app = app
@@ -61,6 +65,7 @@ class Controller(object):
def do_start_response(self, *args):
self.response_args.extend(args)
+
class ServiceController(Controller):
def __init__(self, env, app, account_name, token, **kwargs):
Controller.__init__(self, app)
@@ -85,16 +90,25 @@ class ServiceController(Controller):
resp.status = 200
# we don't keep the creation time of a backet (s3cmd doesn't
# work without that) so we use something bogus.
- resp.body = """%s""" % ("".join(['%s2009-02-03T16:45:09.000Z' % i['name'] for i in containers]))
+ resp.body = '' \
+ '' \
+ '%s' \
+ '' \
+ % ("".join(['%s' \
+ '2009-02-03T16:45:09.000Z' %
+ xml_escape(i['name']) for i in containers]))
return resp
+
class BucketController(Controller):
- def __init__(self, env, app, account_name, token, container_name, **kwargs):
+ def __init__(self, env, app, account_name, token, container_name,
+ **kwargs):
Controller.__init__(self, app)
self.container_name = unquote(container_name)
env['HTTP_X_AUTH_TOKEN'] = token
env['PATH_INFO'] = '/v1/%s/%s' % (account_name, container_name)
-
+
def GET(self, env, start_response):
env['QUERY_STRING'] = 'format=json'
body_iter = self.app(env, self.do_start_response)
@@ -113,7 +127,18 @@ class BucketController(Controller):
objects = loads(''.join(list(body_iter)))
resp = Response(content_type='text/xml')
resp.status = 200
- resp.body = """%s%s""" % (self.container_name, "".join(['%s%s%s%sSTANDARD' % (i['name'], i['last_modified'], i['hash'], i['bytes']) for i in objects]))
+ resp.body = '' \
+ '' \
+ '%s' \
+ '%s' \
+ '' % \
+ (self.container_name,
+ "".join(['%s%s'\
+ '%s%sSTANDARD'\
+ '' %
+ (xml_escape(i['name']), i['last_modified'], i['hash'],
+ i['bytes']) for i in objects]))
return resp
def PUT(self, env, start_response):
@@ -155,12 +180,15 @@ class BucketController(Controller):
resp.status = 204
return resp
+
class ObjectController(Controller):
- def __init__(self, env, app, account_name, token, container_name, object_name, **kwargs):
+ def __init__(self, env, app, account_name, token, container_name,
+ object_name, **kwargs):
Controller.__init__(self, app)
self.container_name = unquote(container_name)
env['HTTP_X_AUTH_TOKEN'] = token
- env['PATH_INFO'] = '/v1/%s/%s/%s' % (account_name, container_name, object_name)
+ env['PATH_INFO'] = '/v1/%s/%s/%s' % (account_name, container_name,
+ object_name)
def GETorHEAD(self, env, start_response):
app_iter = self.app(env, self.do_start_response)
@@ -170,9 +198,11 @@ class ObjectController(Controller):
if 200 <= status < 300:
new_hdrs = {}
for key, val in headers.iteritems():
- if key.startswith('x-object-meta-'):
+ _key = key.lower()
+ if _key.startswith('x-object-meta-'):
new_hdrs['x-amz-meta-' + key[14:]] = val
- elif key in ('Content-Length', 'Content-Type', 'Content-Encoding', 'etag', 'last-modified'):
+ elif _key in ('content-length', 'content-type',
+ 'content-encoding', 'etag', 'last-modified'):
new_hdrs[key] = val
return Response(status=status, headers=new_hdrs, app_iter=app_iter)
elif status == 401:
@@ -187,7 +217,7 @@ class ObjectController(Controller):
def GET(self, env, start_response):
return self.GETorHEAD(env, start_response)
-
+
def PUT(self, env, start_response):
body_iter = self.app(env, self.do_start_response)
status = int(self.response_args[0].split()[0])
@@ -211,7 +241,7 @@ class ObjectController(Controller):
body_iter = self.app(env, self.do_start_response)
status = int(self.response_args[0].split()[0])
headers = dict(self.response_args[1])
-
+
if status != 204:
if status == 401:
return get_err_response('AccessDenied')
@@ -225,6 +255,7 @@ class ObjectController(Controller):
resp.status = 204
return resp
+
class Swift3Middleware(object):
def __init__(self, app, conf, *args, **kwargs):
self.app = app
@@ -238,7 +269,7 @@ class Swift3Middleware(object):
elif container:
return BucketController, d
return ServiceController, d
-
+
def get_account_info(self, env, req):
if req.headers.get("content-md5"):
md5 = req.headers.get("content-md5")
@@ -258,7 +289,7 @@ class Swift3Middleware(object):
h = req.method + "\n" + md5 + "\n" + content_type + "\n" + date + "\n"
for header in req.headers:
if header.startswith("X-Amz-"):
- h += header.lower()+":"+str(req.headers[header])+"\n"
+ h += header.lower() + ":" + str(req.headers[header]) + "\n"
h += req.path
try:
account, _ = req.headers['Authorization'].split(' ')[-1].split(':')
@@ -279,18 +310,22 @@ class Swift3Middleware(object):
account_name, token = self.get_account_info(env, req)
if not account_name:
return get_err_response('InvalidArgument')(env, start_response)
-
- controller = controller(env, self.app, account_name, token, **path_parts)
+
+ controller = controller(env, self.app, account_name, token,
+ **path_parts)
if hasattr(controller, req.method):
res = getattr(controller, req.method)(env, start_response)
else:
return get_err_response('InvalidURI')(env, start_response)
-
+
return res(env, start_response)
+
def filter_factory(global_conf, **local_conf):
conf = global_conf.copy()
conf.update(local_conf)
+
def swift3_filter(app):
return Swift3Middleware(app, conf)
+
return swift3_filter