/*! * jQuery JavaScript Library v1.4.2 * http://jquery.com/ * * Copyright 2010, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2010, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Sat Feb 13 22:33:48 2010 -0500 */ (function( window, undefined ) { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // Use the correct document accordingly with window argument (sandbox) document = window.document, // A central reference to the root jQuery(document) rootjQuery, // A simple way to check for HTML strings or ID strings // (both of which we optimize for) quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/, // Is it a simple selector isSimple = /^.[^:#\[\.,]*$/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, // Used for trimming whitespace rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, // Keep a UserAgent string for use with jQuery.browser userAgent = navigator.userAgent, // For matching the engine and version of the browser browserMatch, // Has the ready events already been bound? readyBound = false, // The functions to execute on DOM ready readyList = [], // The ready event handler DOMContentLoaded, // Save a reference to some core methods toString = Object.prototype.toString, hasOwnProperty = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, indexOf = Array.prototype.indexOf; jQuery.fn = jQuery.prototype = { init: function( selector, context ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context ) { this.context = document; this[0] = document.body; this.selector = "body"; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? match = quickExpr.exec( selector ); // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { doc = (context ? context.ownerDocument || context : document); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = buildFragment( [ match[1] ], [ doc ] ); selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; } return jQuery.merge( this, selector ); // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); if ( elem ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $("TAG") } else if ( !context && /^\w+$/.test( selector ) ) { this.selector = selector; this.context = document; selector = document.getElementsByTagName( selector ); return jQuery.merge( this, selector ); // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return jQuery( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used jquery: "1.4.2", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set size: function() { return this.length; }, toArray: function() { return slice.call( this, 0 ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set var ret = jQuery(); if ( jQuery.isArray( elems ) ) { push.apply( ret, elems ); } else { jQuery.merge( ret, elems ); } // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; if ( name === "find" ) { ret.selector = this.selector + (this.selector ? " " : "") + selector; } else if ( name ) { ret.selector = this.selector + "." + name + "(" + selector + ")"; } // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // If the DOM is already ready if ( jQuery.isReady ) { // Execute the function immediately fn.call( document, jQuery ); // Otherwise, remember the function for later } else if ( readyList ) { // Add the function to the wait list readyList.push( fn ); } return this; }, eq: function( i ) { return i === -1 ? this.slice( i ) : this.slice( i, +i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || jQuery(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { // copy reference to target object var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging object literal values or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src : jQuery.isArray(copy) ? [] : {}; // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ noConflict: function( deep ) { window.$ = _$; if ( deep ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // Handle when the DOM is ready ready: function() { // Make sure that the DOM is not already loaded if ( !jQuery.isReady ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready, 13 ); } // Remember that the DOM is ready jQuery.isReady = true; // If there are functions bound, to execute if ( readyList ) { // Execute all of them var fn, i = 0; while ( (fn = readyList[ i++ ]) ) { fn.call( document, jQuery ); } // Reset the list of functions readyList = null; } // Trigger any bound ready events if ( jQuery.fn.triggerHandler ) { jQuery( document ).triggerHandler( "ready" ); } } }, bindReady: function() { if ( readyBound ) { return; } readyBound = true; // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { return jQuery.ready(); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent("onreadystatechange", DOMContentLoaded); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return toString.call(obj) === "[object Function]"; }, isArray: function( obj ) { return toString.call(obj) === "[object Array]"; }, isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { return false; } // Not own constructor property must be Object if ( obj.constructor && !hasOwnProperty.call(obj, "constructor") && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwnProperty.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, error: function( msg ) { throw msg; }, parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data ); // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { // Try to use the native JSON parser first return window.JSON && window.JSON.parse ? window.JSON.parse( data ) : (new Function("return " + data))(); } else { jQuery.error( "Invalid JSON: " + data ); } }, noop: function() {}, // Evalulates a script in a global context globalEval: function( data ) { if ( data && rnotwhite.test(data) ) { // Inspired by code by Andrea Giammarchi // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html var head = document.getElementsByTagName("head")[0] || document.documentElement, script = document.createElement("script"); script.type = "text/javascript"; if ( jQuery.support.scriptEval ) { script.appendChild( document.createTextNode( data ) ); } else { script.text = data; } // Use insertBefore instead of appendChild to circumvent an IE6 bug. // This arises when a base node is used (#2709). head.insertBefore( script, head.firstChild ); head.removeChild( script ); } }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback
""" The :mod:`request` module provides a :class:`Request` class used to wrap the standard `request` object received in all the views. The wrapped request then offers a richer API, in particular : - content automatically parsed according to `Content-Type` header, and available as :meth:`.DATA<Request.DATA>` - full support of PUT method, including support for file uploads - form overloading of HTTP method, content type and content """ from StringIO import StringIO from django.http.multipartparser import parse_header from rest_framework import exceptions from rest_framework.settings import api_settings def is_form_media_type(media_type): """ Return True if the media type is a valid form media type. """ base_media_type, params = parse_header(media_type) return (base_media_type == 'application/x-www-form-urlencoded' or base_media_type == 'multipart/form-data') class Empty(object): """ Placeholder for unset attributes. Cannot use `None`, as that may be a valid value. """ pass def _hasattr(obj, name): return not getattr(obj, name) is Empty def clone_request(request, method): """ Internal helper method to clone a request, replacing with a different HTTP method. Used for checking permissions against other methods. """ ret = Request(request._request, request.parsers, request.authenticators, request.parser_context) ret._data = request._data ret._files = request._files ret._content_type = request._content_type ret._stream = request._stream ret._method = method if hasattr(request, '_user'): ret._user = request._user if hasattr(request, '_auth'): ret._auth = request._auth return ret class Request(object): """ Wrapper allowing to enhance a standard `HttpRequest` instance. Kwargs: - request(HttpRequest). The original request instance. - parsers_classes(list/tuple). The parsers to use for parsing the request content. - authentication_classes(list/tuple). The authentications used to try authenticating the request's user. """ _METHOD_PARAM = api_settings.FORM_METHOD_OVERRIDE _CONTENT_PARAM = api_settings.FORM_CONTENT_OVERRIDE _CONTENTTYPE_PARAM = api_settings.FORM_CONTENTTYPE_OVERRIDE def __init__(self, request, parsers=None, authenticators=None, negotiator=None, parser_context=None): self._request = request self.parsers = parsers or () self.authenticators = authenticators or () self.negotiator = negotiator or self._default_negotiator() self.parser_context = parser_context self._data = Empty self._files = Empty self._method = Empty self._content_type = Empty self._stream = Empty if self.parser_context is None: self.parser_context = {} self.parser_context['request'] = self def _default_negotiator(self): return api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS() @property def method(self): """ Returns the HTTP method. This allows the `method` to be overridden by using a hidden `form` field on a form POST request. """ if not _hasattr(self, '_method'): self._load_method_and_content_type() return self._method @property def content_type(self): """ Returns the content type header. This should be used instead of `request.META.get('HTTP_CONTENT_TYPE')`, as it allows the content type to be overridden by using a hidden form field on a form POST request. """ if not _hasattr(self, '_content_type'): self._load_method_and_content_type() return self._content_type @property def stream(self): """ Returns an object that may be used to stream the request content. """ if not _hasattr(self, '_stream'): self._load_stream() return self._stream @property def QUERY_PARAMS(self): """ More semantically correct name for request.GET. """ return self._request.GET @property def DATA(self): """ Parses the request body and returns the data. Similar to usual behaviour of `request.POST`, except that it handles arbitrary parsers, and also works on methods other than POST (eg PUT). """ if not _hasattr(self, '_data'): self._load_data_and_files() return self._data @property def FILES(self): """ Parses the request body and returns any files uploaded in the request. Similar to usual behaviour of `request.FILES`, except that it handles arbitrary parsers, and also works on methods other than POST (eg PUT). """ if not _hasattr(self, '_files'): self._load_data_and_files() return self._files @property def user(self): """ Returns the user associated with the current request, as authenticated by the authentication classes provided to the request. """ if not hasattr(self, '_user'): self._user, self._auth = self._authenticate() return self._user @user.setter def user(self, value): """ Sets the user on the current request. This is necessary to maintain compatilbility with django.contrib.auth where the user proprety is set in the login and logout functions. """ self._user = value @property def auth(self): """ Returns any non-user authentication information associated with the request, such as an authentication token. """ if not hasattr(self, '_auth'): self._user, self._auth = self._authenticate() return self._auth @auth.setter def auth(self, value): """ Sets any non-user authentication information associated with the request, such as an authentication token. """ self._auth = value def _load_data_and_files(self): """ Parses the request content into self.DATA and self.FILES. """ if not _hasattr(self, '_content_type'): self._load_method_and_content_type() if not _hasattr(self, '_data'): self._data, self._files = self._parse() def _load_method_and_content_type(self): """ Sets the method and content_type, and then check if they've been overridden. """ self._content_type = self.META.get('HTTP_CONTENT_TYPE', self.META.get('CONTENT_TYPE', '')) self._perform_form_overloading() # if the HTTP method was not overloaded, we take the raw HTTP method if not _hasattr(self, '_method'): self._method = self._request.method def _load_stream(self): """ Return the content body of the request, as a stream. """ try: content_length = int(self.META.get('CONTENT_LENGTH', self.META.get('HTTP_CONTENT_LENGTH'))) except (ValueError, TypeError): content_length = 0 if content_length == 0: self._stream = None elif hasattr(self._request, 'read'): self._stream = self._request else: self._stream = StringIO(self.raw_post_data) def _perform_form_overloading(self): """ If this is a form POST request, then we need to check if the method and content/content_type have been overridden by setting them in hidden form fields or not. """ USE_FORM_OVERLOADING = ( self._METHOD_PARAM or (self._CONTENT_PARAM and self._CONTENTTYPE_PARAM) ) # We only need to use form overloading on form POST requests. if (not USE_FORM_OVERLOADING or self._request.method != 'POST' or not is_form_media_type(self._content_type)): return # At this point we're committed to parsing the request as form data. self._data = self._request.POST self._files = self._request.FILES # Method overloading - change the method and remove the param from the content. if (self._METHOD_PARAM and self._METHOD_PARAM in self._data): self._method = self._data[self._METHOD_PARAM].upper() # Content overloading - modify the content type, and force re-parse. if (self._CONTENT_PARAM and self._CONTENTTYPE_PARAM and self._CONTENT_PARAM in self._data and self._CONTENTTYPE_PARAM in self._data): self._content_type = self._data[self._CONTENTTYPE_PARAM] self._stream = StringIO(self._data[self._CONTENT_PARAM]) self._data, self._files = (Empty, Empty) def _parse(self): """ Parse the request content, returning a two-tuple of (data, files) May raise an `UnsupportedMediaType`, or `ParseError` exception. """ stream = self.stream media_type = self.content_type if stream is None or media_type is None: return (None, None) parser = self.negotiator.select_parser(self, self.parsers) if not parser: raise exceptions.UnsupportedMediaType(media_type) parsed = parser.parse(stream, media_type, self.parser_context) # Parser classes may return the raw data, or a # DataAndFiles object. Unpack the result as required. try: return (parsed.data, parsed.files) except AttributeError: return (parsed, None) def _authenticate(self): """ Attempt to authenticate the request using each authentication instance in turn. Returns a two-tuple of (user, authtoken). """ for authenticator in self.authenticators: user_auth_tuple = authenticator.authenticate(self) if not user_auth_tuple is None: return user_auth_tuple return self._not_authenticated() def _not_authenticated(self): """ Return a two-tuple of (user, authtoken), representing an unauthenticated request. By default this will be (AnonymousUser, None). """ if api_settings.UNAUTHENTICATED_USER: user = api_settings.UNAUTHENTICATED_USER() else: user = None if api_settings.UNAUTHENTICATED_TOKEN: auth = api_settings.UNAUTHENTICATED_TOKEN() else: auth = None return (user, auth) def __getattr__(self, attr): """ Proxy other attributes to the underlying HttpRequest object. """ return getattr(self._request, attr)