Пример #1
0
    def render(self, header = 1):
        # start out with the default renderer
        BlosxomRenderer.render(self, header)
        pyhttp = self.request.getHttp()

	useGzip = False

        if self.config.get('useGzip',False):
            if pyhttp.has_key('HTTP_ACCEPT_ENCODING'):
                # encodings = pyhttp['HTTP_ACCEPT_ENCODING'].split(",")
                # if "gzip" in encodings:
                if pyhttp['HTTP_ACCEPT_ENCODING'].find("gzip") != -1:
                    useGzip = True
                    self.addHeader("content-encoding","gzip")
       
        # if this flavour is not supposed to have XSLT translation run on it
        # then we just output the buffer as it is.  Ideally, this statement
        # should never be true anymore, but just in case, this is a failsafe
        if self.data['flavour'] not in self.config.get('xsltFlavours',[]):
            self._outputBuffer = self._compressBuffer(useGzip)
            self._out.write('\n'.join(['%s: %s' % (x, self._header[x])
                            for x in self._header.keys()]))
            self._out.write('\n\n')
            self._out.write(self._outputBuffer)
                       
            return

        # check to see if the browser is an XSLT browser
        userAgent = pyhttp['HTTP_USER_AGENT']
        flavorREs = self.config.get('xsltBrowsers',[])

        # if the browser can render XSLT natively, as indicated by the
        # xsltBrowsers config option, then we don't need to rerender it
        for x in flavorREs:
            matchobj = re.search(x,userAgent)
            if matchobj:
                self._outputBuffer = self._compressBuffer(useGzip)
                self._out.write('\n'.join(['%s: %s' % (x, self._header[x]) 
                    for x in self._header.keys()]))
                self._out.write('\n\n')
                self._out.write(self._outputBuffer)
                return
        #
        # otherwise do the XSLT transform
        #

        # find the sheet
        # eventually this will also be automated, where it digs in the XML, but
        # that is not the case now.  Instead it looks in the dict from the
        # configuration file
        xsltSheetDict = self.config.get('xsltSheets',{})
        if xsltSheetDict.has_key(self.data['flavour']):
            xsltSheet = xsltSheetDict[self.data['flavour']]
        else:
            # FIXME: some error processing would go here
            xsltSheet = "/NOFILEFOUND"
        xsltEngine = self.config.get('xsltEngine','xsltproc')
        xsltEngineParams = self.config.get('xsltEngineParams',{})

        content = None

        # try to use libxslt if it's requested
        if (self.config.get('xsltEngine','') == 'libxslt'):
            # try:
                # this is needed to render without shelling out
                import libxml2
                import libxslt

                doc = libxml2.parseDoc(self._outputBuffer)

                # this attempts to find the xml-stylesheet tag in the document
                # if it can find it, then it overwrites the original stylesheet request
                ss = None
                rootNode = doc.children
                while ss == None and rootNode != None:
                    if rootNode.name == 'xml-stylesheet':
                        matchObj = re.match('.*href="([^"]*)"',rootNode.content)
                        if matchObj:
                            ss = matchObj.groups()[0]
                            if self.config.get('serverBase',None):
                                xsltSheet  = self.config.get('serverBase','')+os.sep+ss
                    else:
                        rootNode = rootNode.get_next()

                styledoc = libxml2.parseFile(xsltSheet)
                style = libxslt.parseStylesheetDoc(styledoc)

                result = style.applyStylesheet(doc,xsltEngineParams)
                content = style.saveResultToString(result)

                # try to figure out the content type based on the XSLT method parameter
                contentMapping = self.config.get('xsltContentMapping',{})
                outputMethod = style.method()
                if contentMapping.has_key(outputMethod):
                    self.addHeader('Content-type', contentMapping[outputMethod])
                else:
                    self.addHeader('Content-type', "text/html")

                # style.freeStylesheet()
                # doc.freeDoc()
                # result.freeDoc()
            # except:
                # pass

        # if xsltproc is requested or the page hasn't been rendered yet, do this
        if (self.config.get('xsltEngine','') == 'xsltproc' or content == None):
            # store the output buffer to a temp file
            tf = tempfile.mktemp(".xml")
            f = open(tf,"w")
            f.write(self._outputBuffer)
            f.close()

            xsltEngineParamsString = " ".join(["--param %s %s" % (mem, xsltEngineParams[mem]) 
                                               for mem in xsltEngineParams])

            f = open(tempfile.mktemp(".txt"),"w")
            f.write("""%s %s %s %s""" % (xsltEngine, xsltEngineParamsString, xsltSheet, tf))
            f.close()

            childStdout, childStdin, childStderr = popen2.popen3("""%s %s %s %s""" % (xsltEngine, xsltEngineParamsString, xsltSheet, tf))
            childStdin.close()
            content = ""
            while 1:
                line = childStdout.readline()
                if not line: break
                content = content + line

            # os.unlink(tf)
            childStdout.close()
            childStderr.close()
            self.addHeader('Content-type', 'text/html')

        # in theory this should also be validated too...it's conceivable that
        # there might be different output methods than just text/html, for
        # instance, someone may do a transform to SVG for a certain flavour
	self._outputBuffer = content.decode('utf-8')
	self._outputBuffer = self._compressBuffer(useGzip)
        self._out.write('\n'.join(['%s: %s' % (x, self._header[x]) 
           for x in self._header.keys()]))
        self._out.write('\n\n')

        self._out.write(self._outputBuffer)
Пример #2
0
 def __init__(self, request, stdoutput = sys.stdout):
     BlosxomRenderer.__init__(self, request, stdoutput)
     self.request = request
     self.data = self.request.getData()
     self.config = self.request.getConfiguration()
     self._outputBuffer = ""