########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/Xslt/Http.py,v 1.27 2005/04/06 23:05:46 jkloth Exp $
"""
XSLT and XPath extensions for use to access the 4SS API

Copyright 2004 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

from Ns import HTTP_NS

from Ft.Server import RESERVED_NAMESPACE
from Ft.Server.Common.Util import RepoPathToUri
from Ft.Xml.Lib.XmlString import IsQName
from Ft.Xml.XPath import Conversions
from Ft.Xml.Xslt import XsltElement, ContentInfo, AttributeInfo

def LocalUri(context, uri):
    """
    Given an ftss URI, returns a URI reference. The reference will be
    relative to the HTTP handler's document root.
    """
    uri = Conversions.StringValue(uri)
    handler = context.processor.extensionParams[(RESERVED_NAMESPACE, 'handler')]
    docRoot = RepoPathToUri(handler.documentRoot)
    if docRoot and uri[:len(docRoot)] == docRoot:
        uri = uri[len(docRoot):]
    return uri


def LocalPath(context, path):
    """
    Given a repo path, returns a repo path that is relative to the
    HTTP handler's document root, if possible. Otherwise, returns
    the given path unchanged.
    """
    path = Conversions.StringValue(path)
    handler = context.processor.extensionParams[(RESERVED_NAMESPACE, 'handler')]
    docRoot = handler.documentRoot
    if docRoot and path[:len(docRoot)] == docRoot:
        path = path[len(docRoot):]
    return path


def GetQueryArguments(context):
    """
    fhttp:get-query-args() returns a node-set consisting of
    one 'requestParameters' element, containing one child
    element for each item in the HTTP request parameters,
    a.k.a. the query arguments (typically HTML form data).

    The HTTP server will have already decoded the parameters
    and made them available to the XSLT processor; this
    function merely provides access to that data as a
    node-set. The parameter name becomes the element name,
    and the value is the element's content. If there are
    multiple parameters with the same name, they'll manifest
    as separate elements.
    """
    queryArgs = context.processor.extensionParams[(RESERVED_NAMESPACE, 'queryArgs')]
    proc = context.processor
    proc.pushResultTree(context.currentInstruction.baseUri)
    try:
        proc.writers[-1].startElement(u'requestParameters')
        for name, values in queryArgs.items():
            #print "(%s,%s)"%(name,repr(values))
            # colons and characters not allowed in
            # XSLT parameter names become hyphens.
            if name.find(u':') != -1:
                name = name.replace(u':', u'-')
            if not IsQName(name):
                newname = u''
                for c in name:
                    if not IsQName(c):
                        c = u'-'
                    newname += c
                name = newname
                del newname
            for value in values:
                proc.writers[-1].startElement(name)
                proc.writers[-1].text(value)
                proc.writers[-1].endElement(name)
        proc.writers[-1].endElement(u'requestParameters')
    finally:
        rtf = proc.popResult()
    return rtf.childNodes


class ResponseUriElement(XsltElement):

    content = ContentInfo.Empty
    legalAttrs = {
        'uri' : AttributeInfo.UriReferenceAvt(
            required=1, description=('The URI to use for the response'
                                     ' redirect.')),
        }

    def instantiate(self, context, processor):
        context.setProcessState(self)
        uri = self._uri.evaluate(context)
        context.processor.extensionParams[(RESERVED_NAMESPACE, 'response-uri')] = uri
        return


class RequestHeadersElement(XsltElement):

    content = ContentInfo.Empty
    legalAttrs = {}

    def instantiate(self, context, processor):
        handler = context.processor.extensionParams.get((RESERVED_NAMESPACE,
                                                         'handler'))
        for k, v in handler.headers_in.items():
            processor.writers[-1].startElement(u'Header')
            processor.writers[-1].startElement(u'Name')
            processor.writers[-1].text(unicode(k))
            processor.writers[-1].endElement(u'Name')
            if not isinstance(v, list):
                v = [v]
            for actual in v:
                processor.writers[-1].startElement(u'Value')
                processor.writers[-1].text(unicode(actual))
                processor.writers[-1].endElement(u'Value')
            processor.writers[-1].endElement(u'Header')
        return


ExtElements = {
    (HTTP_NS, 'response-uri'): ResponseUriElement,
    (HTTP_NS, 'request-headers') : RequestHeadersElement,
    }

ExtFunctions = {
    (HTTP_NS, 'local-uri'): LocalUri,
    (HTTP_NS, 'local-path'): LocalPath,
    (HTTP_NS, 'get-query-args'): GetQueryArguments,
    }
