lib/rack-xslview.rb in rack-xslview-0.1.3 vs lib/rack-xslview.rb in rack-xslview-0.2.0
- old
+ new
@@ -1,70 +1,95 @@
-# MIT License
+# Copyright 2010 Savonix Corporation
+# Author Albert L. Lash, IV
+# License MIT
module Rack
class XSLView
+
+ class XSLViewError < StandardError ; end
+
def initialize(app, options)
- @my_path_info = String.new
@app = app
- @myhash = {}
@options = {:myxsl => nil}.merge(options)
- if @options[:myxsl] == nil
+ if @options[:myxsl].nil?
+ require 'rexml/document'
@xslt = XML::XSLT.new()
@xslt.xsl = REXML::Document.new '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"><xsl:import href="http://github.com/docunext/1bb02b59/raw/master/standard.html.xsl"/><xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" indent="yes"/></xsl:stylesheet>'
else
@xslt = @options[:myxsl]
end
end
def call(env)
- if checknoxsl(env)
- @app.call(env)
- else
- if @options[:reload] == true
- puts @options[:filepath]
- @xslt = XML::XSLT.new()
- @xslt.xsl = REXML::Document.new @options[:xslfile]
- end
- unless @options[:passenv] == nil
- @options[:passenv].each { |envkey|
- if (mp = env[envkey])
- @myhash[envkey] = "#{mp}"
- end
- }
- @xslt.parameters = @myhash
- end
- status, headers, body = @app.call(env)
+ # No matter what, @app will be called
+ status, headers, body = @app.call(env)
- # Obtain entire request body
- parts = ''
- body.each { |part| parts << part.to_s }
+ # If setup includes paths to exclude from xslt processing, check them
+ checknoxsl(env) if @options[:noxsl]
- # TODO Refactor
- if ((parts.include? "<html") || !(parts.include? "<"))
- [status, headers, body]
- else
- headers.delete('Content-Length')
- @xslt.xml = parts
- newbody = []
- newbody << @xslt.serve
- headers['Content-Length'] = newbody[0].length.to_s
- [status, headers, newbody]
- end
+ # Obtain entire request body, check to make sure it can be processed
+ myxml = getResponse(body)
+
+ # Should XSL file be reloaded?
+ if @options[:reload] == true
+ @xslt = XML::XSLT.new()
+ @xslt.xsl = REXML::Document.new @options[:xslfile]
end
+
+ # Set XML for stylesheet
+ @xslt.xml = myxml
+
+ # If setup includes env vars to pass through as params, do so
+ unless @options[:passenv].nil?
+ @myhash = {}
+ @options[:passenv].each { |envkey|
+ # Does env var exist?
+ @myhash[envkey] = "#{env[envkey]}" if env[envkey]
+ }
+ @xslt.parameters = @myhash unless @myhash.empty?
+ end
+
+ # Perform the transformation
+ newbody = Array.[](@xslt.serve)
+
+ # If we've made it this far, we can alter the headers
+ headers.delete('Content-Length')
+ headers['Content-Length'] = newbody[0].length.to_s
+ [status, headers, newbody]
+
+ rescue XSLViewError
+ # TODO Logging: "Rack XSLView not processed" if env['RACK_ENV'] == 'development'
+ [status, headers, body]
end
private
+ def checknoxsl(env)
+ @options[:noxsl].each { |path|
+ raise XSLViewError if env["PATH_INFO"].index(path)
+ }
+ end
+ def getResponse(body)
+ raise XSLViewError if body.nil?
+ newbody = ''
+ body.each { |part|
+ # Only check the first chunk to ensure 1) its not HTML and 2) its XML
+ checkForXml(part) if newbody.empty?
+ newbody << part.to_s
+ }
+ return newbody
+ end
+ def checkForXml(x)
+ # Abort processing if content cannot be processed by libxslt
+ raise XSLViewError unless x[0,1] == '<'
+ if @options[:excludehtml] == true
+ raise XSLViewError if x.include? '<html'
+ end
+ end
+
def choosesheet(env)
+ # Not used yet, this may be used to match stylesheets with paths
@options[:xslhash].each_key { |path|
if env["PATH_INFO"].index(path)
return @options[:xslhash][path]
- end
- }
- return false
- end
- def checknoxsl(env)
- @options[:noxsl].each { |path|
- if env["PATH_INFO"].index(path)
- return true
end
}
return false
end
end