class Hermeneutics::Cgi

Example:

class MyCgi < Cgi

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

end Cgi.execute

Constants

CGIENV

Attributes

main[RW]

Public Class Methods

execute(out = nil) click to toggle source
# File lib/hermeneutics/cgi.rb, line 89
def execute out = nil
  (@main||self).new.execute out
end
inherited(cls) click to toggle source
# File lib/hermeneutics/cgi.rb, line 86
def inherited cls
  Cgi.main = cls
end

Public Instance Methods

data() click to toggle source
# File lib/hermeneutics/cgi.rb, line 149
def data
  case request_method
    when "GET", "HEAD" then
      Data::UrlEnc.new query_string
    when "POST"        then
      data = $stdin.read
      data.bytesize == content_length.to_i or
        warn "Content length #{content_length} is wrong (#{data.bytesize})."
      ct = ContentType.parse content_type
      data.force_encoding ct[ :charset]||Encoding::ASCII_8BIT
      case ct.fulltype
        when "application/x-www-form-urlencoded" then
          Data::UrlEnc.new data
        when "multipart/form-data" then
          Data::Multiparted.new data, ct.hash
        when "text/plain" then
          Data::Plain.new data
        when "application/json" then
          Data::Json.new data
        when "application/x-yaml", "application/yaml" then
          Data::Yaml.new data
        else
          Data::UrlEnc.new data
      end
    else
      Data::Lines.new read_interactive
  end
end
document(cls = Html, *args, &block) click to toggle source
# File lib/hermeneutics/cgi.rb, line 294
def document cls = Html, *args, &block
  done { |res|
    doc = cls.new
    doc.cgi = self
    res.body = ""
    doc.generate res.body do
      doc.document *args, &block
    end

    ct = if doc.respond_to?    :content_type then doc.content_type
    elsif   cls.const_defined? :CONTENT_TYPE then doc.class::CONTENT_TYPE
    end
    if ct then
      cs = if doc.respond_to?    :charset then doc.charset
      elsif   cls.const_defined? :CHARSET then doc.class::CHARSET
      else
        res.body.encoding||Encoding.default_external
      end
      res.headers.add :content_type, ct, charset: cs
    end
    if doc.respond_to? :cookies then
      doc.cookies do |c|
        res.headers.add :set_cookie, c
      end
    end
  }
end
execute(out = nil) click to toggle source
# File lib/hermeneutics/cgi.rb, line 272
def execute out = nil
  @out ||= $stdout
  begin
    run
  rescue
    done { |res|
      res.body = if $!.class.const_defined? :HTTP_STATUS then
        res.headers.add :status, "%03d" % $!.class::HTTP_STATUS
        $!.message + $/
      else
        # Why doesn't Ruby provide the encoding of #message?
        ($!.full_message highlight: false, order: :top).force_encoding $!.message.encoding
      end
      res.headers.add :content_type, "text/plain", charset: res.body.encoding
    }
  end
rescue Done
  @out << $!.result.to_s
ensure
  @out = nil
end
fullname(dest) click to toggle source
# File lib/hermeneutics/cgi.rb, line 334
def fullname dest
  if dest then
    if dest =~ /\.\w+\z/ then
      dest
    else
      "#{dest}.rb"
    end
  else
    script_name
  end
end
fullpath(dest) click to toggle source
# File lib/hermeneutics/cgi.rb, line 346
def fullpath dest
  dest = fullname dest
  unless File.absolute_path? dest then
    dir = File.dirname script_name rescue ""
    dest = File.join dir, dest
  end
end
https?() click to toggle source
# File lib/hermeneutics/cgi.rb, line 109
def https?
  ENV[ "HTTPS"].notempty?
end
location(dest = nil, params = nil, anchor = nil) click to toggle source
# File lib/hermeneutics/cgi.rb, line 322
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
    dest = %Q'#{https? ? "https" : "http"}://#{http_host||"localhost"}#{fullpath dest}'
  end
  url = utx.mkurl dest, params, anchor
  done { |res| res.headers.add "Location", url }
end
parameters(nl: false, sym: false, strip: false) { |k, notempty?, **kw| ... } click to toggle source
# File lib/hermeneutics/cgi.rb, line 130
def parameters nl: false, sym: false, strip: false
  if block_given? then
    data.parse do |k,v,**kw|
      k = k.to_sym if sym
      if v then
        v.strip! if strip
        v.gsub! "\r\n", "\n" if nl
      end
      yield k, v.notempty?, **kw
    end
  else
    p = {}
    parameters nl: nl, sym: sym, strip: strip do |k,v|
      p[ k] = v
    end
    p
  end
end
parameters!(nl: false, sym: false, strip: false) click to toggle source
# File lib/hermeneutics/cgi.rb, line 125
def parameters! nl: false, sym: false, strip: false
  @parameters ||= parameters nl: nl, sym: sym, strip: strip
  nil
end
query_string() click to toggle source

This has not been tested.

# File lib/hermeneutics/cgi.rb, line 360
def query_string
  Apache::request.args
end
run() click to toggle source

Overwrite this.

If you're reacting to POST uploads, please consider limiting the upload size.

Apache:   LimitRequestBody
Nginx:    client_max_body_size
Lighttpd: server.max-request-size
# File lib/hermeneutics/cgi.rb, line 121
def run
  document Html
end
warn(msg) click to toggle source
# File lib/hermeneutics/cgi.rb, line 354
def warn msg
end

Private Instance Methods

done(ct = nil) { |res| ... } click to toggle source
# File lib/hermeneutics/cgi.rb, line 263
def done ct = nil
  res = Message.create
  yield res
  d = Done.new res
  raise d
end
method_missing(sym, *args) click to toggle source
Calls superclass method
# File lib/hermeneutics/cgi.rb, line 99
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
read_interactive() click to toggle source
# File lib/hermeneutics/cgi.rb, line 237
def read_interactive
  ENV[ "SCRIPT_NAME"] ||= $0
  if $*.any? then
    $*
  else
    if $stdin.tty? then
      $stderr.puts "Offline mode: Enter name=value pairs on standard input."
      l = []
      while (a = $stdin.gets) and a !~ /^$/ do
        l.push a
      end
      l
    else
      $stdin.read.split $/
    end
  end
end