diff options
Diffstat (limited to 'google_appengine/lib/django/django/http/__init__.py')
-rwxr-xr-x | google_appengine/lib/django/django/http/__init__.py | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/google_appengine/lib/django/django/http/__init__.py b/google_appengine/lib/django/django/http/__init__.py new file mode 100755 index 0000000..0ae90c4 --- /dev/null +++ b/google_appengine/lib/django/django/http/__init__.py @@ -0,0 +1,304 @@ +import os +from Cookie import SimpleCookie +from pprint import pformat +from urllib import urlencode, quote +from django.utils.datastructures import MultiValueDict + +RESERVED_CHARS="!*'();:@&=+$,/?%#[]" + +try: + # The mod_python version is more efficient, so try importing it first. + from mod_python.util import parse_qsl +except ImportError: + from cgi import parse_qsl + +class Http404(Exception): + pass + +class HttpRequest(object): + "A basic HTTP request" + def __init__(self): + self.GET, self.POST, self.COOKIES, self.META, self.FILES = {}, {}, {}, {}, {} + self.path = '' + self.method = None + + def __repr__(self): + return '<HttpRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \ + (pformat(self.GET), pformat(self.POST), pformat(self.COOKIES), + pformat(self.META)) + + def __getitem__(self, key): + for d in (self.POST, self.GET): + if d.has_key(key): + return d[key] + raise KeyError, "%s not found in either POST or GET" % key + + def has_key(self, key): + return self.GET.has_key(key) or self.POST.has_key(key) + + def get_full_path(self): + return '' + + def is_secure(self): + return os.environ.get("HTTPS") == "on" + +def parse_file_upload(header_dict, post_data): + "Returns a tuple of (POST MultiValueDict, FILES MultiValueDict)" + import email, email.Message + from cgi import parse_header + raw_message = '\r\n'.join(['%s:%s' % pair for pair in header_dict.items()]) + raw_message += '\r\n\r\n' + post_data + msg = email.message_from_string(raw_message) + POST = MultiValueDict() + FILES = MultiValueDict() + for submessage in msg.get_payload(): + if submessage and isinstance(submessage, email.Message.Message): + name_dict = parse_header(submessage['Content-Disposition'])[1] + # name_dict is something like {'name': 'file', 'filename': 'test.txt'} for file uploads + # or {'name': 'blah'} for POST fields + # We assume all uploaded files have a 'filename' set. + if name_dict.has_key('filename'): + assert type([]) != type(submessage.get_payload()), "Nested MIME messages are not supported" + if not name_dict['filename'].strip(): + continue + # IE submits the full path, so trim everything but the basename. + # (We can't use os.path.basename because it expects Linux paths.) + filename = name_dict['filename'][name_dict['filename'].rfind("\\")+1:] + FILES.appendlist(name_dict['name'], { + 'filename': filename, + 'content-type': (submessage.has_key('Content-Type') and submessage['Content-Type'] or None), + 'content': submessage.get_payload(), + }) + else: + POST.appendlist(name_dict['name'], submessage.get_payload()) + return POST, FILES + +class QueryDict(MultiValueDict): + """A specialized MultiValueDict that takes a query string when initialized. + This is immutable unless you create a copy of it.""" + def __init__(self, query_string, mutable=False): + MultiValueDict.__init__(self) + self._mutable = True + for key, value in parse_qsl((query_string or ''), True): # keep_blank_values=True + self.appendlist(key, value) + self._mutable = mutable + + def _assert_mutable(self): + if not self._mutable: + raise AttributeError, "This QueryDict instance is immutable" + + def __setitem__(self, key, value): + self._assert_mutable() + MultiValueDict.__setitem__(self, key, value) + + def __copy__(self): + result = self.__class__('', mutable=True) + for key, value in dict.items(self): + dict.__setitem__(result, key, value) + return result + + def __deepcopy__(self, memo={}): + import copy + result = self.__class__('', mutable=True) + memo[id(self)] = result + for key, value in dict.items(self): + dict.__setitem__(result, copy.deepcopy(key, memo), copy.deepcopy(value, memo)) + return result + + def setlist(self, key, list_): + self._assert_mutable() + MultiValueDict.setlist(self, key, list_) + + def appendlist(self, key, value): + self._assert_mutable() + MultiValueDict.appendlist(self, key, value) + + def update(self, other_dict): + self._assert_mutable() + MultiValueDict.update(self, other_dict) + + def pop(self, key): + self._assert_mutable() + return MultiValueDict.pop(self, key) + + def popitem(self): + self._assert_mutable() + return MultiValueDict.popitem(self) + + def clear(self): + self._assert_mutable() + MultiValueDict.clear(self) + + def setdefault(self, *args): + self._assert_mutable() + return MultiValueDict.setdefault(self, *args) + + def copy(self): + "Returns a mutable copy of this object." + return self.__deepcopy__() + + def urlencode(self): + output = [] + for k, list_ in self.lists(): + output.extend([urlencode({k: v}) for v in list_]) + return '&'.join(output) + +def parse_cookie(cookie): + if cookie == '': + return {} + c = SimpleCookie() + c.load(cookie) + cookiedict = {} + for key in c.keys(): + cookiedict[key] = c.get(key).value + return cookiedict + +class HttpResponse(object): + "A basic HTTP response, with content and dictionary-accessed headers" + def __init__(self, content='', mimetype=None): + from django.conf import settings + self._charset = settings.DEFAULT_CHARSET + if not mimetype: + mimetype = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE, settings.DEFAULT_CHARSET) + if not isinstance(content, basestring) and hasattr(content, '__iter__'): + self._container = content + self._is_string = False + else: + self._container = [content] + self._is_string = True + self.headers = {'Content-Type': mimetype} + self.cookies = SimpleCookie() + self.status_code = 200 + + def __str__(self): + "Full HTTP message, including headers" + return '\n'.join(['%s: %s' % (key, value) + for key, value in self.headers.items()]) \ + + '\n\n' + self.content + + def __setitem__(self, header, value): + self.headers[header] = value + + def __delitem__(self, header): + try: + del self.headers[header] + except KeyError: + pass + + def __getitem__(self, header): + return self.headers[header] + + def has_header(self, header): + "Case-insensitive check for a header" + header = header.lower() + for key in self.headers.keys(): + if key.lower() == header: + return True + return False + + def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None): + self.cookies[key] = value + for var in ('max_age', 'path', 'domain', 'secure', 'expires'): + val = locals()[var] + if val is not None: + self.cookies[key][var.replace('_', '-')] = val + + def delete_cookie(self, key, path='/', domain=None): + self.cookies[key] = '' + if path is not None: + self.cookies[key]['path'] = path + if domain is not None: + self.cookies[key]['domain'] = domain + self.cookies[key]['expires'] = 0 + self.cookies[key]['max-age'] = 0 + + def _get_content(self): + content = ''.join(self._container) + if isinstance(content, unicode): + content = content.encode(self._charset) + return content + + def _set_content(self, value): + self._container = [value] + self._is_string = True + + content = property(_get_content, _set_content) + + def __iter__(self): + self._iterator = self._container.__iter__() + return self + + def next(self): + chunk = self._iterator.next() + if isinstance(chunk, unicode): + chunk = chunk.encode(self._charset) + return chunk + + def close(self): + if hasattr(self._container, 'close'): + self._container.close() + + # The remaining methods partially implement the file-like object interface. + # See http://docs.python.org/lib/bltin-file-objects.html + def write(self, content): + if not self._is_string: + raise Exception, "This %s instance is not writable" % self.__class__ + self._container.append(content) + + def flush(self): + pass + + def tell(self): + if not self._is_string: + raise Exception, "This %s instance cannot tell its position" % self.__class__ + return sum([len(chunk) for chunk in self._container]) + +class HttpResponseRedirect(HttpResponse): + def __init__(self, redirect_to): + HttpResponse.__init__(self) + self['Location'] = quote(redirect_to, safe=RESERVED_CHARS) + self.status_code = 302 + +class HttpResponsePermanentRedirect(HttpResponse): + def __init__(self, redirect_to): + HttpResponse.__init__(self) + self['Location'] = quote(redirect_to, safe=RESERVED_CHARS) + self.status_code = 301 + +class HttpResponseNotModified(HttpResponse): + def __init__(self): + HttpResponse.__init__(self) + self.status_code = 304 + +class HttpResponseNotFound(HttpResponse): + def __init__(self, *args, **kwargs): + HttpResponse.__init__(self, *args, **kwargs) + self.status_code = 404 + +class HttpResponseForbidden(HttpResponse): + def __init__(self, *args, **kwargs): + HttpResponse.__init__(self, *args, **kwargs) + self.status_code = 403 + +class HttpResponseNotAllowed(HttpResponse): + def __init__(self, permitted_methods): + HttpResponse.__init__(self) + self['Allow'] = ', '.join(permitted_methods) + self.status_code = 405 + +class HttpResponseGone(HttpResponse): + def __init__(self, *args, **kwargs): + HttpResponse.__init__(self, *args, **kwargs) + self.status_code = 410 + +class HttpResponseServerError(HttpResponse): + def __init__(self, *args, **kwargs): + HttpResponse.__init__(self, *args, **kwargs) + self.status_code = 500 + +def get_host(request): + "Gets the HTTP host from the environment or request headers." + host = request.META.get('HTTP_X_FORWARDED_HOST', '') + if not host: + host = request.META.get('HTTP_HOST', '') + return host |