Revision 9fefc052

b/pithos/api/util.py
37 37
from wsgiref.handlers import format_date_time
38 38
from binascii import hexlify, unhexlify
39 39
from datetime import datetime, tzinfo, timedelta
40
from urllib import quote, unquote
40 41

  
41 42
from django.conf import settings
42 43
from django.http import HttpResponse
......
758 759
        h = [subhash(h[x] + h[x + 1]) for x in range(0, len(h), 2)]
759 760
    return hexlify(h[0])
760 761

  
762
def update_request_headers(request):
763
    # Handle URL-encoded keys and values.
764
    meta = request.META
765
    for k, v in meta.copy().iteritems():
766
        if ((k.startswith('HTTP_X_ACCOUNT_META_') or k.startswith('HTTP_X_ACCOUNT_GROUP_') or
767
             k.startswith('HTTP_X_CONTAINER_META_') or k.startswith('HTTP_X_OBJECT_META_') or
768
             k in ('HTTP_X_OBJECT_MANIFEST', 'HTTP_X_OBJECT_SHARING',
769
                   'HTTP_X_COPY_FROM', 'HTTP_X_MOVE_FROM',
770
                   'HTTP_X_SOURCE_ACCOUNT', 'HTTP_X_SOURCE_OBJECT',
771
                   'HTTP_DESTINATION_ACCOUNT', 'HTTP_DESTINATION')) and
772
            ('%' in k or '%' in v)):
773
            del(meta[k])
774
            meta[unquote(k)] = unquote(v)
775

  
761 776
def update_response_headers(request, response):
762 777
    if request.serialization == 'xml':
763 778
        response['Content-Type'] = 'application/xml; charset=UTF-8'
......
766 781
    elif not response['Content-Type']:
767 782
        response['Content-Type'] = 'text/plain; charset=UTF-8'
768 783
    
769
    if not response.has_header('Content-Length') and not (response.has_header('Content-Type') and response['Content-Type'].startswith('multipart/byteranges')):
784
    if (not response.has_header('Content-Length') and
785
        not (response.has_header('Content-Type') and
786
             response['Content-Type'].startswith('multipart/byteranges'))):
770 787
        response['Content-Length'] = len(response.content)
771 788
    
789
    # URL-encode unicode in headers.
790
    meta = response.items()
791
    for k, v in meta:
792
        if (k.startswith('X-Account-Meta-') or k.startswith('X-Account-Group-') or
793
            k.startswith('X-Container-Meta-') or k.startswith('X-Object-Meta-') or
794
            k in ('X-Container-Object-Meta', 'X-Object-Manifest', 'X-Object-Sharing', 'X-Object-Shared-By')):
795
            del(response[k])
796
            response[quote(k)] = quote(v)
797
    
772 798
    if settings.TEST:
773 799
        response['Date'] = format_date_time(time())
774 800

  
......
824 850
                if len(args) > 2 and len(args[2]) > 1024:
825 851
                    raise BadRequest('Object name too large.')
826 852
                
853
                # Format and check headers.
854
                update_request_headers(request)
855
                meta = dict([(k, v) for k, v in request.META.iteritems() if k.startswith('HTTP_')])
856
                if len(meta) > 90:
857
                    raise BadRequest('Too many headers.')
858
                for k, v in meta.iteritems():
859
                    if len(k) > 128:
860
                        raise BadRequest('Header name too large.')
861
                    if len(v) > 256:
862
                        raise BadRequest('Header value too large.')
863
                
827 864
                # Fill in custom request variables.
828 865
                request.serialization = request_serialization(request, format_allowed)
829 866
                request.backend = connect_backend()
b/pithos/middleware/__init__.py
1 1
from log import LoggingConfigMiddleware
2
from header import URLEncodedHeadersMiddleware
3 2
from auth import AuthMiddleware
/dev/null
1
# Copyright 2011 GRNET S.A. All rights reserved.
2
# 
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
# 
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
# 
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
# 
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
# 
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

  
34
from urllib import unquote
35

  
36

  
37
class URLEncodedHeadersMiddleware(object):
38
    def process_request(self, request):
39
        meta = request.META
40
        for k, v in meta.copy().iteritems():
41
            if k.startswith('HTTP_') and ('%' in k or '%' in v):
42
                del(meta[k])
43
                meta[unquote(k)] = unquote(v)
b/pithos/settings.d/00-apps.conf
6 6

  
7 7
MIDDLEWARE_CLASSES = (
8 8
    'django.middleware.common.CommonMiddleware',
9
    'pithos.middleware.URLEncodedHeadersMiddleware',
10 9
    'pithos.middleware.LoggingConfigMiddleware',
11 10
    'pithos.middleware.AuthMiddleware'
12 11
)

Also available in: Unified diff