class Hermes::Cgi

Example:

class MyCgi < Cgi

def run
  if params.empty? then
    location "/sorry.rb"
  else
    document MyHtml
  end
rescue
  document MyErrorPage
end

end #execute

Constants

CGIENV

Attributes

main[RW]
param[R]
parameter[R]
parameters[R]
params[R]

Public Class Methods

new(inp = nil) click to toggle source
# File lib/hermes/cgi.rb, line 96
def initialize inp = nil
  $env ||= ENV
  @inp ||= $stdin
  @params = case request_method
    when "GET", "HEAD" then parse_query query_string
    when "POST"        then parse_posted
    else                    parse_input
  end
ensure
  @inp = nil
end

Public Instance Methods

[](key ;) click to toggle source
# File lib/hermes/cgi.rb, line 112
def [] key ; @params[ key] ; end
execute(out = nil) click to toggle source
# File lib/hermes/cgi.rb, line 86
def execute out = nil
  @main.new.execute out
end
https?() click to toggle source
# File lib/hermes/cgi.rb, line 125
def https?
  $env[ "HTTPS"].notempty?
end
inherited(cls) click to toggle source
# File lib/hermes/cgi.rb, line 83
def inherited cls
  Cgi.main = cls
end
method_missing(sym, *args) click to toggle source
Calls superclass method
# File lib/hermes/cgi.rb, line 117
def method_missing sym, *args
  if args.empty? and CGIENV.include? sym[ /\A(\w+?)_\w+\z/, 1] then
    $env[ sym.to_s.upcase]
  else
    super
  end
end
run() click to toggle source

Overwrite this.

# File lib/hermes/cgi.rb, line 92
def run
  document Html
end

Private Instance Methods

document(cls = Html, *args) click to toggle source
# File lib/hermes/cgi.rb, line 239
def document cls = Html, *args
  doc = cls.new self, *args
  ct = if doc.respond_to? :content_type then
    doc.content_type
  elsif cls.const_defined? :CONTENT_TYPE then
    doc.class::CONTENT_TYPE
  end
  done { |res|
    res.body = ""
    f = res.body.encoding
    doc.document res.body
    if ct then
      e = res.body.encoding.nil_if f
      res.headers.add :content_type, ct, charset: e
    end
    if doc.respond_to? :cookies then
      doc.cookies do |c|
        res.headers.add :set_cookie, c
      end
    end
  }
end
done(ct = nil) { |res| ... } click to toggle source
# File lib/hermes/cgi.rb, line 212
def done ct = nil
  res = Message.create
  yield res
  d = Done.new res
  raise d
end
location(dest = nil, params = nil, anchor = nil) click to toggle source
# File lib/hermes/cgi.rb, line 262
def location dest = nil, params = nil, anchor = nil
  if Hash === dest then
    dest, params, anchor = anchor, dest, params
  end
  utx = URLText.new mask_space: true
  unless dest =~ %r{\A\w+://} then
    unless dest =~ %r{\A/} then
      dest = if dest then
        d = File.dirname script_name
        dest =~ /\.\w+\z/ or dest += ".rb"
        File.join d, dest
      else
        script_name
      end
    end
    dest = %Q#{https? ? "https" : "http"}://#{http_host}#{dest}'
  end
  url = utx.mkurl dest, params, anchor
  done { |res| res.headers.add "Location", url }
end
mk_params(l) click to toggle source
# File lib/hermes/cgi.rb, line 172
def mk_params l
  URLText::Dict.create do |p|
    l.each { |s|
      s.chomp! unless s.frozen?
      k, v = s.split /=/
      if k then
        k.strip!
        p.parse k, v||true if k.notempty?
      end
    }
  end
end
parse_input() click to toggle source
# File lib/hermes/cgi.rb, line 185
    def parse_input
      if $*.any? then
        l = $*
      else
        if $stdin.tty? then
          $stderr.puts <<-EOT
Offline mode: Enter name=value pairs on standard input.
          EOT
        end
        l = []
        while (a = $stdin.gets) and a !~ /^$/ do
          l.push a
        end
      end
      ENV[ "SCRIPT_NAME"] = $0
      mk_params l
    end


    class Done < Exception
      attr_reader :result
      def initialize result
        super nil
        @result = result
      end
    end

    def done ct = nil
      res = Message.create
      yield res
      d = Done.new res
      raise d
    end

    public

    def execute out = nil
      @out ||= $stdout
      begin
        run
      rescue
        done { |res|
          res.body = "#$! (#{$!.class})#$/"
          $@.each { |a| res.body << "\t" << a << $/ }
          res.headers.add :content_type,
                            "text/plain", charset: res.body.encoding
        }
      end
    rescue Done
      @out << $!.result.to_s
    ensure
      @out = nil
    end

    def document cls = Html, *args
      doc = cls.new self, *args
      ct = if doc.respond_to? :content_type then
        doc.content_type
      elsif cls.const_defined? :CONTENT_TYPE then
        doc.class::CONTENT_TYPE
      end
      done { |res|
        res.body = ""
        f = res.body.encoding
        doc.document res.body
        if ct then
          e = res.body.encoding.nil_if f
          res.headers.add :content_type, ct, charset: e
        end
        if doc.respond_to? :cookies then
          doc.cookies do |c|
            res.headers.add :set_cookie, c
          end
        end
      }
    end

    def location dest = nil, params = nil, anchor = nil
      if Hash === dest then
        dest, params, anchor = anchor, dest, params
      end
      utx = URLText.new mask_space: true
      unless dest =~ %r{\A\w+://} then
        unless dest =~ %r{\A/} then
          dest = if dest then
            d = File.dirname script_name
            dest =~ /\.\w+\z/ or dest += ".rb"
            File.join d, dest
          else
            script_name
          end
        end
        dest = %Q#{https? ? "https" : "http"}://#{http_host}#{dest}'
      end
      url = utx.mkurl dest, params, anchor
      done { |res| res.headers.add "Location", url }
    end


    if defined? MOD_RUBY then
      # This has not been tested yet.
      def query_string
        Apache::request.args
      end
    end

  end
parse_multipart(mp) click to toggle source
# File lib/hermes/cgi.rb, line 156
def parse_multipart mp
  URLText::Dict.create do |p|
    mp.each { |part|
      cd = part.headers.content_disposition
      if cd.caption == "form-data" then
        val = if (fn = cd.filename) then
          PostedFile.new part.body, fn, part.headers.content_type
        else
          part.body
        end
        p.parse cd.name, val
      end
    }
  end
end
parse_posted() click to toggle source
# File lib/hermes/cgi.rb, line 135
def parse_posted
  data = @inp.read
  data.bytesize == content_length.to_i or
    @warn = "Content length #{content_length} is wrong (#{data.bytesize})."
  ct = ContentType.parse content_type
  case ct.fulltype
    when "application/x-www-form-urlencoded" then
      parse_query data
    when "multipart/form-data" then
      mp = Multipart.parse data, ct.hash
      parse_multipart mp
    when "text/plain" then
      # Suppose this is for testing purposes only.
      l = []
      data.each_line { |a| l.push a }
      mk_params l
    else
      parse_query data
  end
end
parse_query(data) click to toggle source
# File lib/hermes/cgi.rb, line 131
def parse_query data
  URLText.decode_hash data
end
query_string() click to toggle source

This has not been tested yet.

# File lib/hermes/cgi.rb, line 286
def query_string
  Apache::request.args
end