def extractValue(self, request: IRequest) -> Any: """ Extract a value from the request. In the case of key/value form posts, this attempts to reliably make the value into str. In the case of a JSON post, however, it will simply extract the value from the top-level dictionary, which means it could be any arrangement of JSON-serializiable objects. """ fieldName = self.formFieldName if fieldName is None: raise ValueError("Cannot extract unnamed form field.") contentType = request.getHeader(b"content-type") if contentType is not None and contentType.startswith( b"application/json"): # TODO: parse only once, please. parsed = request.getComponent(IParsedJSONBody) if parsed is None: request.content.seek(0) octets = request.content.read() characters = octets.decode("utf-8") parsed = json.loads(characters) request.setComponent(IParsedJSONBody, parsed) if fieldName not in parsed: return None return parsed[fieldName] allValues = request.args.get(fieldName.encode("utf-8")) if allValues: return allValues[0].decode("utf-8") else: return None
def populateRequestValues( self, injectionComponents: Componentized, instance: Any, request: IRequest, ) -> Deferred: """ Extract the values present in this request and populate a L{FieldValues} object. """ assert IFieldValues(request, None) is None validationErrors = {} prevalidationValues = {} arguments = {} checkCSRF(request) for field in self.fields: text = field.extractValue(request) prevalidationValues[field] = text try: value = field.validateValue(text) argName = field.pythonArgumentName if argName is None: raise ValidationError("Form fields must all have names.") except ValidationError as ve: validationErrors[field] = ve else: arguments[argName] = value values = FieldValues( self, arguments, prevalidationValues, validationErrors, injectionComponents, ) yield values.validate(instance, request) request.setComponent(IFieldValues, values)
def procureSession(self, request: IRequest, forceInsecure: bool = False) -> Any: alreadyProcured = request.getComponent(ISession) if alreadyProcured is not None: if not forceInsecure or not request.isSecure(): returnValue(alreadyProcured) if request.isSecure(): if forceInsecure: tokenHeader = self._insecureTokenHeader cookieName: Union[str, bytes] = self._insecureCookie sentSecurely = False else: tokenHeader = self._secureTokenHeader cookieName = self._secureCookie sentSecurely = True else: # Have we inadvertently disclosed a secure token over an insecure # transport, for example, due to a buggy client? allPossibleSentTokens: Sequence[str] = sum( [ request.requestHeaders.getRawHeaders(header, []) for header in [ self._secureTokenHeader, self._insecureTokenHeader, ] ], [], ) + [ it for it in [ request.getCookie(cookie) for cookie in [self._secureCookie, self._insecureCookie] ] if it ] # Does it seem like this check is expensive? It sure is! Don't want # to do it? Turn on your dang HTTPS! yield self._store.sentInsecurely(allPossibleSentTokens) tokenHeader = self._insecureTokenHeader cookieName = self._insecureCookie sentSecurely = False # Fun future feature: honeypot that does this over HTTPS, but sets # isSecure() to return false because it serves up a cert for the # wrong hostname or an invalid cert, to keep API clients honest # about chain validation. sentHeader = (request.getHeader(tokenHeader) or b"").decode("utf-8") sentCookie = (request.getCookie(cookieName) or b"").decode("utf-8") if sentHeader: mechanism = SessionMechanism.Header else: mechanism = SessionMechanism.Cookie if not (sentHeader or sentCookie): session = None else: try: session = yield self._store.loadSession( sentHeader or sentCookie, sentSecurely, mechanism) except NoSuchSession: if mechanism == SessionMechanism.Header: raise session = None if mechanism == SessionMechanism.Cookie and ( session is None or session.identifier != sentCookie): if session is None: if request.startedWriting: # At this point, if the mechanism is Header, we either have # a valid session or we bailed after NoSuchSession above. raise TooLateForCookies( "You tried initializing a cookie-based session too" " late in the request pipeline; the headers" " were already sent.") if request.method != b"GET": # Sessions should only ever be auto-created by GET # requests; there's no way that any meaningful data # manipulation could succeed (no CSRF token check could # ever succeed, for example). raise NoSuchSession( "Can't initialize a session on a " "{method} request.".format( method=request.method.decode("ascii"))) if not self._setCookieOnGET: # We don't have a session ID at all, and we're not allowed # by policy to set a cookie on the client. raise NoSuchSession( "Cannot auto-initialize a session for this request.") session = yield self._store.newSession(sentSecurely, mechanism) identifierInCookie = session.identifier if not isinstance(identifierInCookie, str): identifierInCookie = identifierInCookie.encode("ascii") if not isinstance(cookieName, str): cookieName = cookieName.decode("ascii") request.addCookie( cookieName, identifierInCookie, max_age=str(self._maxAge), domain=self._cookieDomain, path=self._cookiePath, secure=sentSecurely, httpOnly=True, ) if sentSecurely or not request.isSecure(): # Do not cache the insecure session on the secure request, thanks. request.setComponent(ISession, session) returnValue(session)
def provideSample(request: IRequest) -> None: """ This requirer prerequisite installs a string as the provider of ISample. """ request.setComponent(ISample, "sample component")