def escapedData(data, inAttribute, inXML): """ Escape a string for inclusion in a document. @type data: C{str} @param data: The string to escape. @type inAttribute: C{bool} @param inAttribute: A flag which, if set, indicates that the string should be quoted for use as the value of an XML tag value. @type inXML: C{bool} @param inXML: A flag which, if set, indicates that the string should be quoted for use as an XML text node or as the value of an XML tag value. @rtype: C{str} @return: The quoted form of C{data}. """ if inXML or inAttribute: data = toBytes(data).replace(b'&', b'&' ).replace(b'<', b'<' ).replace(b'>', b'>') if inAttribute: data = toBytes(data).replace(b'"', b'"') return toBytes(data)
def fromString(klass, st): scheme, netloc, path, query, fragment = urllib.parse.urlsplit(st) u = klass( scheme, netloc, toBytes(''.join([urllib.parse.unquote(unicode(seg)) for seg in unicode(path).split('/')[1:]])), unquerify(toBytes(query)), urllib.parse.unquote(unicode(fragment))) return u
def fromContext(klass, context): '''Create a URL object that represents the current URL in the traversal process.''' request = inevow.IRequest(context) request.prepath=[toBytes(i) for i in request.prepath] uri = toBytes(request.prePathURL()) if b'?' in toBytes(request.uri): uri += b'?' + toBytes(request.uri).split(b'?')[-1] return klass.fromString(unicode(uri))
def _cbFinishRender(self, html, ctx): """ Callback for the page rendering process having completed. @param html: Either the content of the response body (L{bytes}) or a marker that an exception occurred and has already been handled or an object adaptable to L{IResource} to use to render the response. """ if self._lostConnection: # No response can be sent at this point. pass elif isinstance(html, str): self.write(toBytes(html)) self.finishRequest( True ) elif isinstance(html, bytes): self.write(html) self.finishRequest( True ) elif html is errorMarker: ## Error webpage has already been rendered and finish called pass else: res = inevow.IResource(html) pageContext = context.PageContext(tag=res, parent=ctx) return self.gotPageContext(pageContext) return html
def _cbFinishRender(self, html, ctx): """ Callback for the page rendering process having completed. @param html: Either the content of the response body (L{bytes}) or a marker that an exception occurred and has already been handled or an object adaptable to L{IResource} to use to render the response. """ if self._lostConnection: # No response can be sent at this point. pass elif isinstance(html, str): self.write(toBytes(html)) self.finishRequest(True) elif isinstance(html, bytes): self.write(html) self.finishRequest(True) elif html is errorMarker: ## Error webpage has already been rendered and finish called pass else: res = inevow.IResource(html) pageContext = context.PageContext(tag=res, parent=ctx) return self.gotPageContext(pageContext) return html
def URLOverlaySerializer(original, context): if context.precompile: yield original else: url = original.urlaccessor(context) for (cmd, args, kw) in original.dolater: url = getattr(url, cmd)(*args, **kw) req = context.locate(inevow.IRequest) for key in original._keep: for value in req.args.get(key, []): url = url.add(key, value) yield toBytes(b''.join(serialize(url, context)))
def serialize(obj=_undefined, **kw): """ JSON-encode an object. @param obj: None, True, False, an int, long, float, unicode string, list, tuple, or dictionary the JSON-encoded form of which will be returned. """ if obj is _undefined: obj = kw L = [] _serialize(obj, L.append, {}) return b''.join([toBytes(i) for i in L])
def URLSerializer(original, context): """ Serialize the given L{URL}. Unicode path, query and fragment components are handled according to the IRI standard (RFC 3987). """ def _maybeEncode(s): if isinstance(s, str): s = s.encode('utf-8') return s urlContext = WovenContext(parent=context, precompile=context.precompile, inURL=True) if original.scheme: # TODO: handle Unicode (see #2409) yield b"%s://%s" % (toBytes(original.scheme), toBytes(original.netloc)) for pathsegment in original._qpathlist: yield b'/' yield serialize(_maybeEncode(pathsegment), urlContext) query = original._querylist if query: yield b'?' first = True for key, value in query: if not first: # xhtml can't handle unescaped '&' if context.isAttrib is True: yield b'&' else: yield b'&' else: first = False yield serialize(_maybeEncode(key), urlContext) if value is not None: yield b'=' yield serialize(_maybeEncode(value), urlContext) if original.fragment: yield b"#" yield serialize(_maybeEncode(original.fragment), urlContext)
def iterflatten(stan, ctx, writer, shouldYieldItem=None): """This is the main meat of the nevow renderer. End-user programmers should instead use either flatten or precompile. """ # 'rest' is a list of generators. # initialize as one-element list of a one-element generator of rest = [ iter([partialflatten(ctx, stan)]) ] straccum = [] while rest: gen = rest.pop() for item in gen: if isinstance(item, bytes): straccum.append(item) elif isinstance(item, str): straccum.append(item.encode('utf8')) elif isinstance(item, (list, types.GeneratorType)): # stop iterating this generator and put it back on the stack # and start iterating the new item instead. rest.append(gen) rest.append(iter(item)) break else: if straccum: writer(util.toBytes(tags.raw(b''.join(straccum)))) straccum=[] if shouldYieldItem is not None and shouldYieldItem(item): replacement = [] yield item, replacement.append rest.append(gen) rest.append(iter([replacement])) break else: if ctx.precompile: ## We're precompiling and this is an item which can't be calculated until render time ## add it to the list in 'precompile' writer(item) else: rest.append(gen) rest.append(iter([partialflatten(ctx, item)])) break if straccum: writer(tags.raw(b''.join([i for i in straccum])))
def iterflatten(stan, ctx, writer, shouldYieldItem=None): """This is the main meat of the nevow renderer. End-user programmers should instead use either flatten or precompile. """ # 'rest' is a list of generators. # initialize as one-element list of a one-element generator of rest = [iter([partialflatten(ctx, stan)])] straccum = [] while rest: gen = rest.pop() for item in gen: if isinstance(item, bytes): straccum.append(item) elif isinstance(item, str): straccum.append(item.encode('utf8')) elif isinstance(item, (list, types.GeneratorType)): # stop iterating this generator and put it back on the stack # and start iterating the new item instead. rest.append(gen) rest.append(iter(item)) break else: if straccum: writer(util.toBytes(tags.raw(b''.join(straccum)))) straccum = [] if shouldYieldItem is not None and shouldYieldItem(item): replacement = [] yield item, replacement.append rest.append(gen) rest.append(iter([replacement])) break else: if ctx.precompile: ## We're precompiling and this is an item which can't be calculated until render time ## add it to the list in 'precompile' writer(item) else: rest.append(gen) rest.append(iter([partialflatten(ctx, item)])) break if straccum: writer(tags.raw(b''.join([i for i in straccum])))
def StringSerializer(original, context): # Quote the string as necessary. URLs need special quoting - only # alphanumeric and a few punctation characters are valid. # Otherwise we use normal XML escaping rules but also replacing " # in an attribute because Nevow always uses "..." for values. original = toBytes(original) if context.inURL: # The magic string "-_.!*'()" also appears in url.py. Thinking about # changing this? Change that, too. return urllib.parse.quote(original, safe="-_.!*'()") ## quote it if context.inJS: original = _jsSingleQuoteQuote(original) if not context.inJSSingleQuoteString: original = b"'%s'" % (original,) if context.isAttrib: return original.replace(b"&", b"&").replace(b"<", b"<").replace(b">", b">").replace(b'"', b""") elif context.inJS: return original else: return original.replace(b"&", b"&").replace(b"<", b"<").replace(b">", b">")
def _sessionCookie(): return md5(toBytes("%s_%s" % (str(random.random()), str(time.time())))).hexdigest()
def _sessionCookie(): return md5(toBytes("%s_%s" % (str(random.random()) , str(time.time())))).hexdigest()
def cbFlattened(result): synchronous.append(None) return (result, (toBytes(s) for s in results))
def _flatten(request, root, slotData, renderFactory, inAttribute, inXML): """ Make C{root} slightly more flat by yielding all or part of it as strings or generators. @param request: A request object which will be passed to L{IRenderable.render}. @param root: An object to be made flatter. This may be of type C{unicode}, C{str}, L{raw}, L{Proto}, L{xml}, L{slot}, L{_PrecompiledSlot}, L{Tag}, L{URL}, L{tuple}, L{list}, L{GeneratorType}, L{Entity}, L{Deferred}, or it may be an object which is adaptable to L{IRenderable}. Deprecated backwards-compatibility support is also present for objects adaptable to L{IRenderer} or for which a flattener has been registered via L{registerFlattener}. @param slotData: A C{list} of C{dict} mapping C{str} slot names to data with which those slots will be replaced. @param inAttribute: A flag which, if set, indicates that C{str} and C{unicode} instances encountered must be quoted as for XML tag attribute values. @param inXML: A flag which, if set, indicates that C{str} and C{unicode} instances encountered must be quoted as for XML text node data. @return: An iterator which yields C{str}, L{Deferred}, and more iterators of the same type. """ if isinstance(root, str): root = root.encode('utf-8') elif isinstance(root, WovenContext): # WovenContext is supported via the getFlattener case, but that is a # very slow case. Checking here is an optimization. It also lets us # avoid the deprecation warning which would be emitted whenever a # precompiled document was flattened, since those contain WovenContexts # for tags with render directives. -exarkun inAttribute = root.isAttrib inXML = True root = root.tag if isinstance(root, raw): root = toBytes(root) if inAttribute: root = root.replace(b'"', b'"') yield root elif isinstance(root, Proto): root = toBytes(root) if root: if root in allowSingleton: yield b'<' + root + b' />' else: yield b'<' + root + b'></' + root + '>' elif isinstance(root, bytes): yield escapedData(root, inAttribute, inXML) elif isinstance(root, slot): slotValue = _getSlotValue(root.name, slotData) yield _flatten(request, slotValue, slotData, renderFactory, inAttribute, inXML) elif isinstance(root, _PrecompiledSlot): slotValue = _getSlotValue(root.name, slotData) yield _flatten(request, slotValue, slotData, renderFactory, root.isAttrib, inXML) elif isinstance(root, Tag): if root.pattern is Unset or root.pattern is None: slotData.append(root.slotData) if root.render is Unset: if not root.tagName: for element in _flatten(request, root.children, slotData, renderFactory, False, True): yield element else: yield b'<' if isinstance(root.tagName, str): tagName = root.tagName.encode('ascii') else: tagName = toBytes(root.tagName) yield tagName for k, v in sorted(root.attributes.items()): if isinstance(k, str): k = k.encode('ascii') yield b" " + k + b"=\"" for element in _flatten(request, v, slotData, renderFactory, True, True): yield element yield b"\"" if root.children or tagName not in allowSingleton: yield b'>' for element in _flatten(request, root.children, slotData, renderFactory, False, True): yield element yield b'</' + tagName + b'>' else: yield b' />' else: if isinstance(root.render, directive): rendererName = root.render.name else: rendererName = root.render root = root.clone(False) del root._specials['render'] result = renderFactory.renderer(rendererName)(request, root) yield _flatten(request, result, slotData, renderFactory, None, inXML) slotData.pop() elif isinstance(root, URL): yield escapedData(str(root), inAttribute, inXML) elif isinstance(root, (tuple, list, GeneratorType)): for element in root: yield _flatten(request, element, slotData, renderFactory, inAttribute, inXML) elif isinstance(root, Entity): yield '&#' yield root.num yield ';' elif isinstance(root, xml): if isinstance(root.content, str): yield root.content.encode('utf-8') else: yield root.content elif isinstance(root, Deferred): yield root.addCallback( lambda result: (result, _flatten(request, result, slotData, renderFactory, inAttribute, inXML))) else: renderable = IRenderable(root, None) if renderable is not None: # [] for the slotData parameter of this call to _flatten means # slots returned by this renderable's render method won't be filled # with data which has so far accumulated in the slotData stack. # This seems like a reasonable thing to me, since a renderable is a # piece of Python code. It should be isolated from this other # stuff, which is primarily data. -exarkun yield _flatten(request, renderable.render(request), [], renderable, inAttribute, inXML) else: renderer = IRenderer(root, None) if renderer is not None: ctx = _ctxForRequest(request, slotData, None, inAttribute) results = [] synchronous = [] flattened = flattenFactory(renderer, ctx, results.append, lambda ign: None) def cbFlattened(result): synchronous.append(None) return (result, (toBytes(s) for s in results)) flattened.addCallback(cbFlattened) if synchronous: yield b''.join(map(toBytes, results)) else: yield flattened else: flattener = getFlattener(root) if flattener is not None: ctx = _ctxForRequest(request, slotData, renderFactory, inAttribute) yield _flatten(request, flattener(root, ctx), slotData, renderFactory, False, False) else: raise UnsupportedType(root)