X-Git-Url: https://code.grnet.gr/git/pithos/blobdiff_plain/4a1c29eac0deac20cf273b4e6ae375481074361b..808cea65f1f1bafa8c6bfeb713c9cc690c1b54b2:/pithos/api/functions.py diff --git a/pithos/api/functions.py b/pithos/api/functions.py index eb9efd7..a3d131b 100644 --- a/pithos/api/functions.py +++ b/pithos/api/functions.py @@ -39,16 +39,18 @@ from django.http import HttpResponse from django.template.loader import render_to_string from django.utils import simplejson as json from django.utils.http import parse_etags -from django.utils.encoding import smart_unicode, smart_str +from django.utils.encoding import smart_str from xml.dom import minidom +from pithos.lib.filter import parse_filters + from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, Forbidden, ItemNotFound, Conflict, LengthRequired, PreconditionFailed, RequestEntityTooLarge, RangeNotSatisfiable, UnprocessableEntity) from pithos.api.util import (rename_meta_key, format_header_key, printable_header_dict, get_account_headers, put_account_headers, get_container_headers, put_container_headers, get_object_headers, put_object_headers, update_manifest_meta, update_sharing_meta, update_public_meta, validate_modification_preconditions, validate_matching_preconditions, split_container_object_string, copy_or_move_object, - get_int_parameter, get_content_length, get_content_range, socket_read_iterator, + get_int_parameter, get_content_length, get_content_range, socket_read_iterator, SaveToBackendHandler, object_data_response, put_object_block, hashmap_hash, api_method, json_encode_decimal) from pithos.backends.base import NotAllowedError, QuotaError @@ -126,7 +128,7 @@ def authenticate(request): uri = uri[:uri.find('?')] response['X-Auth-Token'] = x_auth_key - response['X-Storage-Url'] = uri + (uri.endswith('/') and '' or '/') + x_auth_user + response['X-Storage-Url'] = uri + ('' if uri.endswith('/') else '/') + x_auth_user return response @api_method('GET', format_allowed=True) @@ -155,16 +157,23 @@ def account_list(request): account_meta = [] for x in accounts: + if x == request.user_uniq: + continue try: - meta = request.backend.get_account_meta(request.user_uniq, x) + meta = request.backend.get_account_meta(request.user_uniq, x, 'pithos') groups = request.backend.get_account_groups(request.user_uniq, x) except NotAllowedError: raise Forbidden('Not allowed') else: rename_meta_key(meta, 'modified', 'last_modified') rename_meta_key(meta, 'until_timestamp', 'x_account_until_timestamp') - for k, v in groups.iteritems(): - meta['X-Container-Group-' + k] = ','.join(v) + m = dict([(k[15:], v) for k, v in meta.iteritems() if k.startswith('X-Account-Meta-')]) + for k in m: + del(meta['X-Account-Meta-' + k]) + if m: + meta['X-Account-Meta'] = printable_header_dict(m) + if groups: + meta['X-Account-Group'] = printable_header_dict(dict([(k, ','.join(v)) for k, v in groups.iteritems()])) account_meta.append(printable_header_dict(meta)) if request.serialization == 'xml': data = render_to_string('accounts.xml', {'accounts': account_meta}) @@ -183,7 +192,7 @@ def account_meta(request, v_account): until = get_int_parameter(request.GET.get('until')) try: - meta = request.backend.get_account_meta(request.user_uniq, v_account, until) + meta = request.backend.get_account_meta(request.user_uniq, v_account, 'pithos', until) groups = request.backend.get_account_groups(request.user_uniq, v_account) policy = request.backend.get_account_policy(request.user_uniq, v_account) except NotAllowedError: @@ -216,8 +225,8 @@ def account_update(request, v_account): raise BadRequest('Invalid groups header') if meta or replace: try: - request.backend.update_account_meta(request.user_uniq, v_account, meta, - replace) + request.backend.update_account_meta(request.user_uniq, v_account, + 'pithos', meta, replace) except NotAllowedError: raise Forbidden('Not allowed') return HttpResponse(status=202) @@ -232,7 +241,7 @@ def container_list(request, v_account): until = get_int_parameter(request.GET.get('until')) try: - meta = request.backend.get_account_meta(request.user_uniq, v_account, until) + meta = request.backend.get_account_meta(request.user_uniq, v_account, 'pithos', until) groups = request.backend.get_account_groups(request.user_uniq, v_account) policy = request.backend.get_account_policy(request.user_uniq, v_account) except NotAllowedError: @@ -273,7 +282,7 @@ def container_list(request, v_account): for x in containers: try: meta = request.backend.get_container_meta(request.user_uniq, v_account, - x, until) + x, 'pithos', until) policy = request.backend.get_container_policy(request.user_uniq, v_account, x) except NotAllowedError: @@ -283,8 +292,13 @@ def container_list(request, v_account): else: rename_meta_key(meta, 'modified', 'last_modified') rename_meta_key(meta, 'until_timestamp', 'x_container_until_timestamp') - for k, v in policy.iteritems(): - meta['X-Container-Policy-' + k] = v + m = dict([(k[17:], v) for k, v in meta.iteritems() if k.startswith('X-Container-Meta-')]) + for k in m: + del(meta['X-Container-Meta-' + k]) + if m: + meta['X-Container-Meta'] = printable_header_dict(m) + if policy: + meta['X-Container-Policy'] = printable_header_dict(dict([(k, v) for k, v in policy.iteritems()])) container_meta.append(printable_header_dict(meta)) if request.serialization == 'xml': data = render_to_string('containers.xml', {'account': v_account, 'containers': container_meta}) @@ -305,9 +319,9 @@ def container_meta(request, v_account, v_container): until = get_int_parameter(request.GET.get('until')) try: meta = request.backend.get_container_meta(request.user_uniq, v_account, - v_container, until) + v_container, 'pithos', until) meta['object_meta'] = request.backend.list_object_meta(request.user_uniq, - v_account, v_container, until) + v_account, v_container, 'pithos', until) policy = request.backend.get_container_policy(request.user_uniq, v_account, v_container) except NotAllowedError: @@ -354,7 +368,7 @@ def container_create(request, v_account, v_container): if meta: try: request.backend.update_container_meta(request.user_uniq, v_account, - v_container, meta, replace=False) + v_container, 'pithos', meta, replace=False) except NotAllowedError: raise Forbidden('Not allowed') except NameError: @@ -387,7 +401,7 @@ def container_update(request, v_account, v_container): if meta or replace: try: request.backend.update_container_meta(request.user_uniq, v_account, - v_container, meta, replace) + v_container, 'pithos', meta, replace) except NotAllowedError: raise Forbidden('Not allowed') except NameError: @@ -442,9 +456,9 @@ def object_list(request, v_account, v_container): until = get_int_parameter(request.GET.get('until')) try: meta = request.backend.get_container_meta(request.user_uniq, v_account, - v_container, until) + v_container, 'pithos', until) meta['object_meta'] = request.backend.list_object_meta(request.user_uniq, - v_account, v_container, until) + v_account, v_container, 'pithos', until) policy = request.backend.get_container_policy(request.user_uniq, v_account, v_container) except NotAllowedError: @@ -482,9 +496,12 @@ def object_list(request, v_account, v_container): keys = request.GET.get('meta') if keys: - keys = keys.split(',') - l = [smart_str(x) for x in keys if x.strip() != ''] - keys = [format_header_key('X-Object-Meta-' + x.strip()) for x in l] + keys = [smart_str(x.strip()) for x in keys.split(',') if x.strip() != ''] + included, excluded, opers = parse_filters(keys) + keys = [] + keys += [format_header_key('X-Object-Meta-' + x) for x in included] + keys += [format_header_key('!X-Object-Meta-' + x) for x in excluded] + keys += ['%s%s%s' % (format_header_key('X-Object-Meta-' + k), o, v) for k, o, v in opers] else: keys = [] @@ -495,7 +512,7 @@ def object_list(request, v_account, v_container): try: objects = request.backend.list_objects(request.user_uniq, v_account, v_container, prefix, delimiter, marker, - limit, virtual, keys, shared, until) + limit, virtual, 'pithos', keys, shared, until) except NotAllowedError: raise Forbidden('Not allowed') except NameError: @@ -518,7 +535,7 @@ def object_list(request, v_account, v_container): else: try: meta = request.backend.get_object_meta(request.user_uniq, v_account, - v_container, x[0], x[1]) + v_container, x[0], 'pithos', x[1]) if until is None: permissions = request.backend.get_object_permissions( request.user_uniq, v_account, v_container, x[0]) @@ -538,6 +555,11 @@ def object_list(request, v_account, v_container): rename_meta_key(meta, 'modified_by', 'x_object_modified_by') rename_meta_key(meta, 'version', 'x_object_version') rename_meta_key(meta, 'version_timestamp', 'x_object_version_timestamp') + m = dict([(k[14:], v) for k, v in meta.iteritems() if k.startswith('X-Object-Meta-')]) + for k in m: + del(meta['X-Object-Meta-' + k]) + if m: + meta['X-Object-Meta'] = printable_header_dict(m) update_sharing_meta(request, permissions, v_account, v_container, x[0], meta) update_public_meta(public, meta) object_meta.append(printable_header_dict(meta)) @@ -560,7 +582,7 @@ def object_meta(request, v_account, v_container, v_object): version = request.GET.get('version') try: meta = request.backend.get_object_meta(request.user_uniq, v_account, - v_container, v_object, version) + v_container, v_object, 'pithos', version) if version is None: permissions = request.backend.get_object_permissions(request.user_uniq, v_account, v_container, v_object) @@ -629,7 +651,7 @@ def object_read(request, v_account, v_container, v_object): try: meta = request.backend.get_object_meta(request.user_uniq, v_account, - v_container, v_object, version) + v_container, v_object, 'pithos', version) if version is None: permissions = request.backend.get_object_permissions(request.user_uniq, v_account, v_container, v_object) @@ -735,19 +757,19 @@ def object_write(request, v_account, v_container, v_object): if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'): try: meta = request.backend.get_object_meta(request.user_uniq, v_account, - v_container, v_object) + v_container, v_object, 'pithos') except NotAllowedError: raise Forbidden('Not allowed') except NameError: meta = {} validate_matching_preconditions(request, meta) - copy_from = smart_unicode(request.META.get('HTTP_X_COPY_FROM'), strings_only=True) - move_from = smart_unicode(request.META.get('HTTP_X_MOVE_FROM'), strings_only=True) + copy_from = request.META.get('HTTP_X_COPY_FROM') + move_from = request.META.get('HTTP_X_MOVE_FROM') if copy_from or move_from: content_length = get_content_length(request) # Required by the API. - src_account = smart_unicode(request.META.get('HTTP_X_SOURCE_ACCOUNT'), strings_only=True) + src_account = request.META.get('HTTP_X_SOURCE_ACCOUNT') if not src_account: src_account = request.user_uniq if move_from: @@ -827,8 +849,8 @@ def object_write(request, v_account, v_container, v_object): try: version_id = request.backend.update_object_hashmap(request.user_uniq, - v_account, v_container, v_object, size, hashmap, meta, - True, permissions) + v_account, v_container, v_object, size, hashmap, + 'pithos', meta, True, permissions) except NotAllowedError: raise Forbidden('Not allowed') except IndexError, e: @@ -863,26 +885,19 @@ def object_write_form(request, v_account, v_container, v_object): # forbidden (403), # badRequest (400) + request.upload_handlers = [SaveToBackendHandler(request)] if not request.FILES.has_key('X-Object-Data'): raise BadRequest('Missing X-Object-Data field') file = request.FILES['X-Object-Data'] meta = {} meta['Content-Type'] = file.content_type - - md5 = hashlib.md5() - size = 0 - hashmap = [] - for data in file.chunks(request.backend.block_size): - size += len(data) - hashmap.append(request.backend.put_block(data)) - md5.update(data) - - meta['ETag'] = md5.hexdigest().lower() + meta['ETag'] = file.etag try: version_id = request.backend.update_object_hashmap(request.user_uniq, - v_account, v_container, v_object, size, hashmap, meta, True) + v_account, v_container, v_object, file.size, file.hashmap, + 'pithos', meta, True) except NotAllowedError: raise Forbidden('Not allowed') except NameError: @@ -903,10 +918,10 @@ def object_copy(request, v_account, v_container, v_object): # forbidden (403), # badRequest (400) - dest_account = smart_unicode(request.META.get('HTTP_DESTINATION_ACCOUNT'), strings_only=True) + dest_account = request.META.get('HTTP_DESTINATION_ACCOUNT') if not dest_account: dest_account = request.user_uniq - dest_path = smart_unicode(request.META.get('HTTP_DESTINATION'), strings_only=True) + dest_path = request.META.get('HTTP_DESTINATION') if not dest_path: raise BadRequest('Missing Destination header') try: @@ -919,7 +934,7 @@ def object_copy(request, v_account, v_container, v_object): src_version = request.META.get('HTTP_X_SOURCE_VERSION') try: meta = request.backend.get_object_meta(request.user_uniq, v_account, - v_container, v_object, src_version) + v_container, v_object, 'pithos', src_version) except NotAllowedError: raise Forbidden('Not allowed') except (NameError, IndexError): @@ -940,10 +955,10 @@ def object_move(request, v_account, v_container, v_object): # forbidden (403), # badRequest (400) - dest_account = smart_unicode(request.META.get('HTTP_DESTINATION_ACCOUNT'), strings_only=True) + dest_account = request.META.get('HTTP_DESTINATION_ACCOUNT') if not dest_account: dest_account = request.user_uniq - dest_path = smart_unicode(request.META.get('HTTP_DESTINATION'), strings_only=True) + dest_path = request.META.get('HTTP_DESTINATION') if not dest_path: raise BadRequest('Missing Destination header') try: @@ -955,7 +970,7 @@ def object_move(request, v_account, v_container, v_object): if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'): try: meta = request.backend.get_object_meta(request.user_uniq, v_account, - v_container, v_object) + v_container, v_object, 'pithos') except NotAllowedError: raise Forbidden('Not allowed') except NameError: @@ -983,7 +998,7 @@ def object_update(request, v_account, v_container, v_object): try: prev_meta = request.backend.get_object_meta(request.user_uniq, v_account, - v_container, v_object) + v_container, v_object, 'pithos') except NotAllowedError: raise Forbidden('Not allowed') except NameError: @@ -1031,7 +1046,7 @@ def object_update(request, v_account, v_container, v_object): if meta or replace: try: version_id = request.backend.update_object_meta(request.user_uniq, - v_account, v_container, v_object, meta, replace) + v_account, v_container, v_object, 'pithos', meta, replace) except NotAllowedError: raise Forbidden('Not allowed') except NameError: @@ -1064,12 +1079,10 @@ def object_update(request, v_account, v_container, v_object): elif offset > size: raise RangeNotSatisfiable('Supplied offset is beyond object limits') if src_object: - src_account = smart_unicode(request.META.get('HTTP_X_SOURCE_ACCOUNT'), strings_only=True) + src_account = request.META.get('HTTP_X_SOURCE_ACCOUNT') if not src_account: src_account = request.user_uniq src_container, src_name = split_container_object_string(src_object) - src_container = smart_unicode(src_container, strings_only=True) - src_name = smart_unicode(src_name, strings_only=True) src_version = request.META.get('HTTP_X_SOURCE_VERSION') try: src_size, src_hashmap = request.backend.get_object_hashmap(request.user_uniq, @@ -1158,8 +1171,8 @@ def object_update(request, v_account, v_container, v_object): meta.update({'ETag': hashmap_hash(request, hashmap)}) # Update ETag. try: version_id = request.backend.update_object_hashmap(request.user_uniq, - v_account, v_container, v_object, size, hashmap, meta, - replace, permissions) + v_account, v_container, v_object, size, hashmap, + 'pithos', meta, replace, permissions) except NotAllowedError: raise Forbidden('Not allowed') except NameError: