ev/rwd.rb in rwdmovies-0.6 vs ev/rwd.rb in rwdmovies-0.7
- old
+ new
@@ -1,1848 +1,1848 @@
-require "ev/ruby"
-require "ev/xml"
-require "ev/net"
-require "ev/browser"
-require "ev/thread"
-require "md5"
-require "rbconfig"
-
-begin
- require "win32ole"
- require "win32/registry"
-rescue LoadError
- $".push "win32ole.so"
- $".push "win32/registry.rb"
-end
-
-$rwd_exit = ARGV.include?("--rwd-exit") # Hack ???
-$rwd_debug = ($rwd_debug or $DEBUG or false)
-$rwd_border = ($rwd_border or 0)
-$rwd_dir = Dir.pwd
-$rwd_files = File.expand_path("rwd_files", Dir.pwd)
-$rwd_html = {}
-
-ARGV.delete_if do |arg|
- arg =~ /^--rwd-/
-end
-
-RWDEmptyline = "..."
-
-rcfile = nil
-s = ENV["HOME"] ; s = s + "/.rwdrc" if not s.nil? ; rcfile = s if (not s.nil? and rcfile.nil? and File.file?(s))
-s = ENV["USERPROFILE"] ; s = s + "/rwd.cfg" if not s.nil? ; rcfile = s if (not s.nil? and rcfile.nil? and File.file?(s))
-s = ENV["windir"] ; s = s + "/rwd.cfg" if not s.nil? ; rcfile = s if (not s.nil? and rcfile.nil? and File.file?(s))
-
-AL = "align='left'"
-AC = "align='center'"
-AR = "align='right'"
-VA = "valign='middle'"
-
-Format = "\n<!-- %-10s %-10s -->\t"
-
-unless rcfile.nil?
- puts "Reading #{rcfile} ..."
-
- Hash.file(rcfile).each do |k, v|
- ENV[k] = v unless ENV.include?(k)
- end
-end
-
-ENV["RWDBROWSER"] = (ENV["RWDBROWSER"] or defaultbrowser) or puts "No browser found."
-ENV["RWDPORTS"] = (ENV["RWDPORTS"] or "7701-7709")
-ENV["RWDTHEME"] = (ENV["RWDTHEME"] or "DEFAULT")
-
-trap("INT") {puts "Terminating..." ; exit}
-
-$SAFE = 2
-
-class IE
- def initialize(url)
- @ie = WIN32OLE.new("InternetExplorer.Application")
- @ev = WIN32OLE_EVENT.new(@ie, "DWebBrowserEvents2")
-
- @ie.navigate(url)
-
- @ie.menubar = false
- @ie.toolbar = false
- @ie.addressbar = false
- @ie.statusbar = false
-
- @ie.visible = true
-
- at_exit do
- @ie.visible = false
- end
-
- @ev.on_event("OnQuit") do
- Thread.main.exit
- end
-
- Thread.new do
- loop do
- WIN32OLE_EVENT.message_loop
- end
- end
- end
-end
-
-class Array
- def rwd_options(emptyline=nil)
- if emptyline.nil?
- a = self
- else
- a = [emptyline].concat(self)
- end
-
- a.numsort.collect{|s| "<option>#{s.to_html}</option>" }.join("\n")
- end
-
- def rwd_method(method)
- res = ""
-
- self.each do |s|
- s = s.join("/") if s.kind_of?(Array)
- s2 = s.dup
- s2[0..0] = s2[0..0].upcase
- res = res + "<p align='left'><a action='#{method}/#{s.to_html}'>#{s2.to_html}</a></p>"
- end
-
- return res
- end
-
- def rwd_row(key=nil, value=nil)
- res = ""
-
- res = res + "<row valign='top'>"
- res = res + "<radio name='#{key.to_html}' value='#{value.to_html}'/>" unless key.nil?
- res = res + self.collect{|s| "<p align='left'>#{s.to_html}</p>"}.join("")
- res = res + "</row>"
-
- return res
- end
-
- def rwd_headers(emptyfield=false)
- res = ""
-
- res = res + "<row>"
- res = res + "<p/>" if emptyfield
- res = res + self.collect{|s| "<p align='left'><b>#{s.to_html}</b></p>" }.join("")
- res = res + "</row>"
-
- return res
- end
-
- def rwd_form(prefix, values, twoparts=0, options={})
- res = []
-
- res << "<table>"
- self.each_index do |n|
- name = "#{prefix.to_html}#{self[n].downcase.to_html}"
-
- res << "<row>"
- res << "<p align='right'>"
- res << "#{self[n].to_html}:"
- res << "</p>"
-
- if options.keys.include?(self[n])
- res << "<select name='#{name}'>"
- res << options[self[n]].rwd_options(RWDEmptyline)
- res << "</select>"
- else
- s = ""
-
- s << "<text name='#{name}'"
- s << " value='#{values[n].to_html}'" if n < values.length
- s << "/>"
-
- res << s
- end
-
- res << "</row>"
-
- if twoparts > 0 and n == twoparts-1
- res << "<row><empty/></row>"
- end
- end
- res << "</table>"
-
- return res.join("\n")
- end
-end
-
-class Hash
- def rwd_table(field=nil, joinwith=nil, headers=nil)
- res = []
-
- res << "<table>"
- res << headers.rwd_headers((not field.nil?)) if not headers.nil?
- self.keys.numsort.each do |key|
- key2 = key
- value2 = self[key]
-
- key2 = key2.join(joinwith) if key2.kind_of?(Array)
- value2 = [value2] if value2.kind_of?(String)
-
- res << value2.rwd_row(field, key2)
- end
- res << "</table>"
-
- res.join("\n")
- end
-end
-
-class EVTable
- def rwd_table(field=nil, joinwith=@sep)
- super(field, joinwith, @headers)
- end
-
- def rwd_form(prefix="", key=nil, twoparts=false)
- values = self[key] if not key.nil?
- values = [] if values.nil?
- options = {}
-
- if File.file?(oldlocation("constraints.tsv"))
- table = File.basename(@file).gsub(/\.tsv$/, "")
-
- TSVFile.new(oldlocation("constraints.tsv")).subset(["Table", "Constraint"], [table, "key"], ["Column", "Value"]).values.each do |column, table2|
- options[column] = TSVFile.new(oldlocation("#{table2}.tsv")).keys.collect{|a| a.join("\t")}
- end
- end
-
- @headers.rwd_form(prefix, values, twoparts ? @key : 0, options)
- end
-
- def rwd_metadata
- res = []
-
- res << "<table>"
- res << "<row>"
- res << " <empty/>"
- res << " <text name='header_new' value=''/>"
- res << "</row>"
- @headers.each_index do |n|
- res << "<row>"
- res << " <text name='header_#{n}_old' value='#{@headers[n]}'/>"
- res << " <text name='header_#{n}_new' value=''/>"
- res << "</row>"
- end
- res << "</table>"
-
- return res.join("\n")
- end
-end
-
-class OpenTag
- def prechildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab, pda)
- bef = before[-1]
- res << Format % ["Before", @subtype] if ($rwd_debug and not bef.nil?)
- res << bef if not bef.nil?
-
- res << Format % ["Pre", @subtype] if $rwd_debug
-
- align = AC
- align = "align='#{@args["align"]}'" if @args.include?("align")
-
- valign = VA
- valign = "valign='#{@args["valign"]}'" if @args.include?("valign")
-
- value1 = ""
- value1 = varshtml[@args["name"]] if varshtml.include?(@args["name"])
- value1 = @args["value"] if @args.include?("value")
-
- value2 = ""
- value2 = varsstring[@args["name"]] if varsstring.include?(@args["name"])
- value2 = @args["value"] if @args.include?("value")
-
- cellspacing = 3
- cellspacing = 0 if pda
-
- case @subtype
- when "application"
- when "window", "helpwindow"
- args = @args.deep_dup
-
- args["nohelpbutton"] = (not help)
-
- template = $rwd_html_1
- template = $rwd_html_PDA_1 if pda
-
- res <<(template(template, args))
- when "p" then res << "<p #{align}>"
- when "pre" then res << "<pre #{align}>"
- when "big" then res << "<p #{align}><big>"
- when "small" then res << "<p #{align}><small>"
- when "list" then res << "<ul #{align}>"
- when "item" then res << "<li #{align}>"
- when "empty" then res << "<p><br>"
- when "image"
- width = "width='#{@args["width"]}" if @args.include?("width")
- height = "height='#{@args["height"]}'" if @args.include?("height")
-
- res << "<img src='#{@args["src"]}' alt='#{@args["alt"]}' #{width} #{height}>"
- when "progressbar"
- width = 200
-
- res << "<table>"
- res << " <tr>"
- res << " <td colspan='2'><img src='rwd_pixel.gif' height='1' width='#{width+5}'></td>"
- res << " </tr>"
- res << " <tr>"
- res << " <td bgcolor='#DDDDDD'><img src='rwd_pixel.gif' height='10' width='#{(width*@args["value"].to_f).to_i}'></td>"
- res << " <td bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='10' width='#{(width*(1.0-@args["value"].to_f)).to_i}'></td>"
- res << " </tr>"
- res << "</table>"
- when "br" then res << "<br>"
- when "hr" then res << "<hr>"
- when "b" then res << "<b>"
- when "i" then res << "<i>"
- when "a"
- if @args.include?("href")
- res << "<a href='#{@args["href"]}' target='#{@args["target"] or "_blank"}'>"
- else
- res << "<a href='javascript:document.bodyform.rwd_action.value=\"#{@args["action"]}\";document.bodyform.submit();'>"
- end
- when "vertical" then res << "<table #{AC} border='#{$rwd_border}' cellspacing='#{cellspacing}' cellpadding='0'>"
- when "horizontal" then res << "<table #{AC} border='#{$rwd_border}' cellspacing='#{cellspacing}' cellpadding='0'><tr #{align} #{valign}>"
- when "table" then res << "<table #{AC} border='#{$rwd_border}' cellspacing='#{cellspacing}' cellpadding='0'>"
- when "row" then res << "<tr #{align} #{valign}>"
- when "hidden" then res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='hidden'>"
- when "text"
- maxlength = ""
- maxlength = "maxlength='%s'" % @args["maxlength"] if @args.include?("maxlength")
- size = ""
- size = "size='%s'" % 10 if pda
- res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='text' #{maxlength} #{size}>"
- oneormorefields << "true"
- when "textarea"
- res << "<p #{align}><textarea name='#{@args["name"]}' rows='25' cols='80'>#{value2.crlf}</textarea>"
- oneormorefields << "true"
- when "password"
- maxlength = ""
- maxlength = "maxlength='%s'" % @args["maxlength"] if @args.include?("maxlength")
- size = ""
- size = "size='%s'" % 10 if pda
- res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='password' #{maxlength} #{size}>"
- oneormorefields << "true"
- when "checkbox"
- if varshtml[@args["name"]] == "on"
- switches[@args["name"]] = true
- res << "<p #{align}><input name='#{@args["name"]}' checked='on' type='checkbox'>"
- else
- switches[@args["name"]] = false
- res << "<p #{align}><input name='#{@args["name"]}' type='checkbox'>"
- end
- oneormorefields << "true"
- when "radio"
- if varshtml[@args["name"]] == value1 # ??? 1 or 2?
- res << "<p #{align}><input name='#{@args["name"]}' checked='on' value='#{value1}' type='radio'>"
- else
- res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='radio'>"
- end
- oneormorefields << "true"
- when "select"
- res << "<select #{align} name='#{@args["name"]}' width='#{@args["width"]}'>"
- name = @args["name"]
- $select = varshtml[name]
- oneormorefields << "true"
- when "option"
- if $select == @children[0].text
- res << "<option selected='true'>"
- else
- res << "<option>"
- end
- when "button"
- res << "<input type='submit' value='#{@args["caption"]}' onclick='document.bodyform.rwd_action.value=\"#{@args["action"]}\";'>"
- firstaction << @args["action"] if (firstaction.empty? and @args.include?("action"))
- oneormorefields << "true"
- when "back"
- res << "<input type='submit' value='Back' onclick='document.bodyform.rwd_action.value=\"rwd_back\";'>"
- firstaction << "rwd_back" if firstaction.empty?
- oneormorefields << "true"
- when "cancel"
- res << "<input type='submit' value='Cancel' onclick='document.bodyform.rwd_action.value=\"rwd_cancel\";'>"
- firstaction << "rwd_cancel" if firstaction.empty?
- oneormorefields << "true"
- when "help"
- res << "<input type='submit' value='Help' onclick='document.bodyform.rwd_action.value=\"rwd_help\";'>"
- firstaction << "rwd_help" if firstaction.empty?
- oneormorefields << "true"
- when "quit"
- res << "<input type='submit' value='Quit' onclick='document.bodyform.rwd_action.value=\"rwd_quit\";'>"
- firstaction << "rwd_quit" if firstaction.empty?
- oneormorefields << "true"
- when "close"
- res << "<input type='submit' value='Close' onclick='window.close();'>"
- firstaction << "rwd_quit" if firstaction.empty?
- oneormorefields << "true"
- when "main"
- res << "<input type='submit' value='Main' onclick='document.bodyform.rwd_action.value=\"rwd_main\";'>"
- firstaction << "rwd_main" if firstaction.empty?
- oneormorefields << "true"
- when "reset"
- res << "<input type='reset' value='Reset'>"
- firstaction << "rwd_quit" if firstaction.empty? # ???
- oneormorefields << "true"
- when "closewindow"
- #res << "<script type='text/javascript'>\n" # ???
- #res << "<!--\n"
- #res << " window.close();\n"
- #res << "//-->\n"
- #res << "</script>"
- when "tabs"
- res << "<table #{AC} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
- res << " <tr #{AL}>"
- res << " <td #{AL} class='tabs'>"
- res << " <table #{AL} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
- res << " <tr #{AL}>"
- #res << " <td class='notab'> </td>"
- tabs.each do |obj|
- name = obj.args["name"]
- caption = obj.args["caption"]
-
- res << "<td #{AL} class='notab'> </td>" unless obj == tabs[0]
-
- if name == tab
- res << "<td #{AC} class='activetab'><tt> #{caption} </tt></td>"
- else
- res << "<td #{AC} class='passivetab'><a href='javascript:document.bodyform.rwd_action.value=\"rwd_tab_#{name}\";document.bodyform.submit();'><tt> #{caption} </tt></a></td>"
- end
- end
- res << " <td class='notab' width='100%'> </td>"
- res << " </tr>"
- res << " </table>"
- res << " </td>"
- res << " </tr>"
- res << " <tr #{align}>"
- res << " <td #{align} class='tabblad'>"
- when "tab"
- res << "<table #{AC} border='#{$rwd_border}' cellspacing='3' cellpadding='0'>"
- when "panel"
- level = (@args["level"] or "normal")
- res << "<table #{AC} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
- res << " <tr #{align}>"
- res << " <td #{align} class='panel1'>" if level == "normal"
- res << " <td #{align} class='panel1high'>" if level == "high"
- res << " <td #{align} class='panel1low'>" if level == "low"
- res << " <table #{AC} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
- res << " <tr #{align}>"
- res << " <td #{align} class='panel2'>" if level == "normal"
- res << " <td #{align} class='panel2high'>" if level == "high"
- res << " <td #{align} class='panel2low'>" if level == "low"
- res << " <table #{AC} border='#{$rwd_border}' cellspacing='3' cellpadding='0'>"
- else
- puts "<#{@subtype}>"
- res << "<#{@subtype}>"
- end
-
- bef = nil
- aft = nil
-
- case @subtype
- when "vertical", "window", "helpwindow", "tab", "panel"
- res << Format % ["AftPre", @subtype] if $rwd_debug
- if @args.include?("spacing")
- s = "<tr><td> </td></tr>" * (@args["spacing"].to_i)
- else
- s = ""
- end
- bef = "#{s}<tr #{align} #{valign}><td #{align}>"
- aft = "</td></tr>"
- when "horizontal", "row"
- res << Format % ["AftPre", @subtype] if $rwd_debug
- bef = "<td #{align}>"
- aft = "</td>"
- end
-
- before.push(bef)
- after.push(aft)
- end
-
- def postchildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab, pda)
- case @subtype
- when "vertical", "window", "helpwindow", "tab", "panel"
- res << Format % ["BefPost", @subtype] if $rwd_debug
- if @args.include?("spacing")
- res << "<tr><td> </td></tr>" * (@args["spacing"].to_i)
- end
- when "horizontal", "row"
- res << Format % ["BefPost", @subtype] if $rwd_debug
- end
-
- res << Format % ["Post", @subtype] if $rwd_debug
-
- case @subtype
- when "application"
- when "window", "helpwindow"
- args = @args.deep_dup
-
- args["nohelpbutton"] = (not help)
-
- template = $rwd_html_2
- template = $rwd_html_PDA_2 if pda
-
- res <<(template(template, args))
- when "p" then res << "</p>"
- when "pre" then res << "</pre>"
- when "big" then res << "</big></p>"
- when "small" then res << "</small></p>"
- when "list" then res << "</ul>"
- when "item" then res << "</li>"
- when "empty" then res << "</p>"
- when "image" then res << ""
- when "progressbar" then res << ""
- when "br" then res << ""
- when "hr" then res << ""
- when "b" then res << "</b>"
- when "i" then res << "</i>"
- when "a" then res << "</a>"
- when "vertical" then res << "</table>"
- when "horizontal" then res << "</tr></table>"
- when "table" then res << "</table>"
- when "row" then res << "</tr>"
- when "hidden" then res << "</p>"
- when "text" then res << "</p>"
- when "textarea" then res << "</p>"
- when "password" then res << "</p>"
- when "checkbox" then res << "</p>"
- when "radio" then res << "</p>"
- when "select"
- res << "</select>"
- $select = nil
- when "option" then res << "</option>"
- when "button" then res << ""
- when "back" then res << ""
- when "cancel" then res << ""
- when "help" then res << ""
- when "quit" then res << ""
- when "close" then res << ""
- when "main" then res << ""
- when "reset" then res << ""
- when "closewindow" then res << ""
- when "tabs"
- res << " </td>"
- res << " </tr>"
- res << "</table>"
- when "tab"
- res << "</table>"
- when "panel"
- res << " </table>"
- res << " </td>"
- res << " </tr>"
- res << " </table>"
- res << " </td>"
- res << " </tr>"
- res << "</table>"
- else
- puts "</#{@subtype}>"
- res << "</#{@subtype}>"
- end
-
- before.pop
- after.pop
-
- aft = after[-1]
- res << Format % ["After", @subtype] if ($rwd_debug and not aft.nil?)
- res << aft if not aft.nil?
- end
-
- def template(html, vars)
- res = []
-
- a = {}
-
- vars.each do |k, v|
- a[k.upcase] = v
- end
-
- logo = nil
- logo = File.expand_path(vars["logo"], $rwd_files) if vars.include?("logo")
- logo = nil unless logo.nil? or File.file?(logo)
-
- a["LOGO"] = "" unless not logo.nil?
-
- a["HELPBUTTON"] = (not (vars["nohelpbutton"]))
- a["BACKBUTTONS"] = (not (vars["nobackbuttons"]))
- a["BACKBUTTONS"] = (not (vars["nobackbuttons"]))
- a["CLOSEBUTTON"] = (not (vars["noclosebutton"]))
-
- if a.include?("WIDTH")
- a["WIDTH1"] = "width='#{a["WIDTH"]}'"
- a["WIDTH2"] = a["WIDTH"]
- else
- a["WIDTH1"] = " "
- a["WIDTH2"] = "1"
- end
-
- html.split(/\r*\n/).each do |line|
- if line =~ /%[A-Z0-9]+%/
- a.each do |k, v|
- v = false if (v.kind_of?(String) and v.empty?)
-
- if line.include?("%#{k}%")
- line.gsub!("%#{k}%", "#{v}") if v
- end
- end
-
- line = "<!-- #{line.scan(/%[A-Z0-9]+%/).join(" ")} -->" if line =~ /%[A-Z0-9]+%/
- end
-
- res << line
- end
-
- res.join("\n")
- end
-end
-
-class Text
- def prechildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab, pda)
- if not @text.scan(/[^ \t\r\n]/).empty?
- res << Format % ["Text", ""] if $rwd_debug
- res << "#{@text}"
- end
- end
-end
-
-class RWDTree < XML
-end
-
-class RWDWindow
- @@windows = {} # Kind of caching.
- @@helpwindows = {} # Kind of caching.
-
- def initialize(rwd, window=nil)
- rwd = rwd.join("\n") if rwd.kind_of?(Array)
-
- if @@windows[rwd].nil?
- @@windows[rwd] = {}
- @@helpwindows[rwd] = {}
-
- tree = XML.new(rwd)
-
- tree.parse(OpenTag, "window") do |type, obj|
- @@windows[rwd][obj.args["name"]] = obj.to_h
- end
-
- tree.parse(OpenTag, "helpwindow") do |type, obj|
- @@helpwindows[rwd][obj.args["name"]] = obj.to_h
- end
- end
-
- @rwd = (@@windows[rwd][window] or "").dup
- @helprwd = (@@helpwindows[rwd][window] or "").dup
- end
-
- def render(pda, action=nil, vars=Hash.new, switches=Hash.new, help=false, tab="")
- varshtml = Hash.new
- varsstring = Hash.new
- oneormorefields = ""
- firstaction = ""
- html = []
-
- vars.each do |key, value|
- if not key.empty?
- if value.respond_to? "to_s"
- @rwd.gsub!(/%%#{key}%%/, value.to_s)
- @rwd.gsub!(/%#{key}%/, value.to_s.to_html)
-
- @helprwd.gsub!(/%%#{key}%%/, value.to_s)
- @helprwd.gsub!(/%#{key}%/, value.to_s.to_html)
-
- varshtml[key] = value.to_s.to_html
- varsstring[key] = value.to_s
- end
- end
- end
-
- windowobject = RWDTree.new(@rwd).children.dup.delete_if{|obj| obj.subtype != "window"}[0]
- helpobject = RWDTree.new(@helprwd).children.dup.delete_if{|obj| obj.subtype != "helpwindow"}[0]
-
- tabsobj = windowobject.children.dup.delete_if{|obj| obj.subtype != "tabs"}[0]
-
- if not tabsobj.nil?
- tabs = tabsobj.children.dup.delete_if{|obj| (not obj.kind_of?(OpenTag)) or (obj.subtype != "tab")}
-
- if tab.empty?
- tab = tabs[0].args["name"]
- end
-
- tabsobj.children.delete_if{|obj| (obj.kind_of?(OpenTag)) and (obj.subtype == "tab") and obj.args["name"] != tab}
- end
-
- if help
- helpobject.parsetree("prechildren", "postchildren", html, [""], [""], varshtml, varsstring, switches, false, oneormorefields, firstaction, tabs, tab, pda)
- else
- windowobject.parsetree("prechildren", "postchildren", html, [""], [""], varshtml, varsstring, switches, (not @helprwd.empty?), oneormorefields, firstaction, tabs, tab, pda)
- end
-
- html = html.join("") # ???
-
- html.gsub!(/%%*[[:alnum:]_\-]+%%*/, "") if not $rwd_debug
- html.gsub!(/%%/, "%")
- html.gsub!(/\n\n*/, "\n")
-
- if oneormorefields.empty?
- focus = ""
- else
- focus = "document.bodyform.elements[0].focus();"
- end
-
- firstaction = action if windowobject.args.keys.include?("refresh") unless action.nil?
-
- html.gsub!(/\$RWD_FIRSTACTION\$/ , firstaction)
- html.gsub!(/\$RWD_FOCUS\$/ , focus)
-
- html
- end
-end
-
-class RWDMessage < RWDWindow
- def initialize(msg)
- super("<window title='RWD Message' nobackbuttons noclosebutton><p>#{msg}</p><back/></window>")
- end
-end
-
-class RWDError < RWDWindow
- def initialize(msg)
- super("<window title='RWD Error' nobackbuttons noclosebutton><p><b>Error:</b> #{msg}</p><back/></window>")
- end
-end
-
-class RWDProgressBar < RWDWindow
- def initialize(refresh, progress)
- s = ""
- s << "<window title='RWD Progress' nobackbuttons noclosebutton refresh='#{refresh}'>"
- if progress.length == 1
- progress.each do |caption, value|
- s << "<p>#{caption}</p><progressbar value='#{value}'/><p>#{(100*value).to_i}%%</p>"
- end
- else
- s << "<table>"
- progress.each do |caption, value|
- s << "<row><p align='left'>#{caption}</p><progressbar value='#{value}'/><p align='right'>#{(100*value).to_i}%%</p></row>"
- end
- s << "</table>"
- end
- s << "<cancel/>"
- s << "</window>"
- super(s)
- end
-end
-
-class RWDDone < RWDWindow
- def initialize(exitbrowser)
- super("<window title='RWD Message' nobackbuttons noclosebutton><p>Done.</p><horizontal><close/>#{exitbrowser ? "" : "<button caption='Again'/>"}</horizontal>#{exitbrowser ? "<closewindow/>" : ""}</window>")
- end
-end
-
-class RWDialog
- def initialize(xml)
- @rwd_xml = xml
- @rwd_exitbrowser = false
- @rwd_history = []
- @rwd_ignore_vars = []
- @rwd_call_after_back = []
- end
-
- def self.file(rwdfile, *args)
- new(File.new(rwdfile).readlines, *args)
- end
-
- def serve(port=nil, auth=nil, realm=self.class.to_s)
- exit if $rwd_exit
-
- raise "RWD is not initialized." if @rwd_xml.nil?
-
- low, high = ENV["RWDPORTS"].split(/[^\d+]/)
- high = low if high.nil?
- low, high = low.to_i, high.to_i
-
- io = nil
-
- port, io = TCPServer.freeport(low, high, (not auth.nil?)) if port.nil?
- raise "No free TCP port." if port.nil?
-
- port = port.to_i
-
- @rwd_server = RWDServer.new(self, port, io, auth, realm)
- end
-
- def render(res, path, post, download, downloadfile, pda, sessionid)
-
- # Initialize some vars.
-
- vars = Hash.new if vars.nil?
- @rwd_switches = Hash.new if @rwd_switches.nil?
-
- done = false
- help = false
- back = false
- tab = ""
- @rwd_msgtype = nil
- @rwd_download = nil
- @rwd_download_file = nil
-
- # Switches are used for checkboxes.
-
- @rwd_switches.each do |key, value|
- vars[key] = "off"
- end
-
- @rwd_switches = Hash.new
-
- # Copy the vars from the window to vars. vars wil later on be copied to instance variables.
-
- post.sort.each do |key, value|
- puts "Post: #{key} -> #{value.from_html.inspect}" if $rwd_debug
-
- vars[key] = value.from_html
- end
-
- # Stack handling for rwd_action, rwd_window and rwd_tab.
-
- @rwd_action = vars["rwd_action"] if vars.include?("rwd_action")
- @rwd_action, @rwd_args = @rwd_action.split(/\//, 2) unless @rwd_action.nil?
- @rwd_action, rest = @rwd_action.split(/\?/) unless @rwd_action.nil?
-
- @rwd_refresh_action = (@rwd_action or @rwd_refresh_action or "main")
-
- unless rest.nil?
- rest.each do |s|
- k, v = s.split(/=/, 2)
- vars[k] = v
- end
- end
-
- if @rwd_action == "rwd_cancel"
- @rwd_progress_thread.kill unless @rwd_progress_thread.nil?
- @rwd_progress_thread = nil
- @rwd_action = "rwd_back"
- end
-
- if @rwd_action =~ /^rwd_tab_/
- @rwd_tab = @rwd_action.sub(/^rwd_tab_/, "")
- @rwd_history[-1][3] = @rwd_tab
- else
- case @rwd_action
- when "rwd_back"
- @rwd_history.pop
- @rwd_action = (@rwd_history[-1] or [nil, nil, nil])[0]
- @rwd_args = (@rwd_history[-1] or [nil, nil, nil])[1]
- @rwd_window = (@rwd_history[-1] or [nil, nil, nil])[2]
- @rwd_tab = (@rwd_history[-1] or [nil, nil, nil])[3]
- back = true
- when "rwd_help"
- help = true
- when "rwd_main"
- @rwd_action = nil
- @rwd_window = nil
- @rwd_tab = nil
- @rwd_history = []
- when "rwd_quit"
- done = true
- end
-
- # History stuff
-
- @rwd_history = @rwd_history[-100..-1] if @rwd_history.length >= 100
- @rwd_action = "main" if @rwd_action.nil?
- @rwd_action = "main" if @rwd_action.empty?
- @rwd_window = "main" if @rwd_window.nil?
- @rwd_window = "main" if @rwd_window.empty?
- @rwd_tab = "" if @rwd_tab.nil?
- @rwd_args = [] if @rwd_args.nil?
- @rwd_args = [] if @rwd_action == "main"
-
- vars["rwd_action"] = @rwd_action
- vars["rwd_window"] = @rwd_window
- vars["rwd_tab"] = @rwd_tab
-
- # Copy vars from window to instance.
-
- vars.each do |k, v|
- instance_eval "@#{k} = vars['#{k}']" if ((not k.empty?) and k.scan(/^rwd_/).empty? and not @rwd_ignore_vars.include?("@#{k}"))
- end
-
- # Callback.
-
- if (not back) or @rwd_call_after_back.include?(@rwd_action)
- unless @rwd_action =~ /^rwd_/
- puts "Method: #{@rwd_action}(#{@rwd_args.join(", ")})" if $rwd_debug
- if methods.include?(@rwd_action)
- method(@rwd_action).call(*@rwd_args)
- else
- puts "Method '%s' is not defined." % @rwd_action
- end
- end
-
- # History stuff
-
- @rwd_history = [["main", [], "main", ""]] if @rwd_action == "main"
- @rwd_history = [["main", [], "main", ""]] if @rwd_history.empty?
-
- a = [@rwd_action, @rwd_args, @rwd_window, @rwd_tab]
-
- @rwd_history.push a if (@rwd_history[-1] != a or not @rwd_msgtype.nil?)
- end
- end
-
- # Copy vars from instance to window.
-
- instance_variables.each do |k|
- k.sub!(/^@/, "")
- instance_eval "vars['#{k}'] = @#{k}.to_s" if (k.scan(/^rwd_/).empty? and not @rwd_ignore_vars.include?("@#{k}"))
- end
-
- # just ignore.
-
- vars.sort.each do |key, value|
- puts "Pre: #{key} -> #{value.inspect}" if $rwd_debug
- end
-
-
- # Answer to browser.
-
- if done
- res << RWDDone.new(@rwd_exitbrowser).render(pda)
- else
- if not @rwd_download.nil?
- puts "Download: #{@rwd_window}" if $rwd_debug
-
- download << @rwd_download
- downloadfile << @rwd_download_file
- else
- if not @rwd_msgtype.nil?
- res << RWDMessage.new(@rwd_msg).render(pda) if @rwd_msgtype == "message"
- res << RWDError.new(@rwd_msg).render(pda) if @rwd_msgtype == "error"
- else
- if not @rwd_progress_thread.nil?
- res << RWDProgressBar.new(@rwd_progress_refresh, @rwd_progress_progress).render(pda, @rwd_refresh_action)
- else
- puts "Window: #{@rwd_window}" if $rwd_debug
- puts "Tab: #{@rwd_tab}" if $rwd_debug
-
- res << RWDWindow.new(@rwd_xml, @rwd_window).render(pda, @rwd_refresh_action, vars, @rwd_switches, help, @rwd_tab)
- end
- end
- end
- end
-
- return done
- end
-
- def samewindow?
- @rwd_history[-1][2] == @rwd_window
- end
-
- def message(msg, &block)
- @rwd_msg = msg
- @rwd_msgtype = "message"
- end
-
- def error(msg, &block)
- @rwd_msg = msg
- @rwd_msgtype = "error"
- end
-
- def progressbar(refresh, *progress)
- @rwd_progress_refresh = (refresh or 1)
- @rwd_progress_progress = []
-
- while not progress.empty?
- s = (progress.shift or "")
- if s.kind_of?(Array)
- caption, value = s
- value = (value or 0.0).to_f
- else
- caption = s
- value = (progress.shift or 0.0).to_f
- end
-
- @rwd_progress_progress << [caption, value]
- end
-
- if @rwd_progress_thread.nil?
- @rwd_progress_progress.each do |a|
- a[1] = 0.0
- end
-
- @rwd_progress_thread =
- Thread.new do
- yield
- end
- Thread.pass
- end
-
- @rwd_progress_thread = nil unless @rwd_progress_thread.alive?
- end
-
- def download(data, filename="")
- @rwd_download = data
- @rwd_download_file = filename
- end
-
- def exitbrowser
- @rwd_exitbrowser = true
- end
-end
-
-class RWDLogin < RWDialog
- def initialize(realm)
- super("<window name='main' title='RWD Login for #{realm}' nobackbuttons noclosebutton><table><row><p align='right'>Username:</p><text name='rwd_a'/></row><row><p align='right'>Password:</p><password name='rwd_b'/></row></table><button caption='Login'/></window>")
- end
-end
-
-class RWDTimeOut < RWDialog
- def initialize
- super("<window name='main' title='RWD Error' nobackbuttons noclosebutton><p><b>Error:</b> Session has expired.</p><button caption='New session'/></window>")
- end
-end
-
-class SessionCleanup
- def initialize(sessions, interval, timeout)
- every(interval) do
- sessions.delete_if do |id, session|
- time = Time.now.to_i - session.lastaccess.to_i
-
- puts "Session %s deleted" % id if time > timeout
-
- time > timeout
- end
- end
- end
-end
-
-class Sessions
- def initialize(rack, cleanup)
- @rack = rack.to_s
- @cleanup = SessionCleanup.new(self, 3600, 24*3600) if cleanup
- @sessions = {}
- end
-
- def [](sessionid)
- @sessions[sessionid]
- end
-
- def []=(sessionid, value)
- @sessions[sessionid] = value
- end
-
- def delete(sessionid)
- @sessions.delete(sessionid)
- end
-
- def delete_if(&block)
- @sessions.delete_if{|k, v| block.call(k, v)}
- end
-
- def include?(sessionid)
- @sessions.include?(sessionid)
- end
-end
-
-class Session < Hash
- attr_reader :sessionid
- attr_reader :lastaccess
- attr_reader :authenticated
- attr_writer :authenticated
-
- def initialize(sessionid=nil)
- @sessionid = sessionid
- @lastaccess = Time.now
- @authenticated = false
- end
-
- def touch
- @lastaccess = Time.now
- end
-end
-
-class RWDSession < Session
- def render(res, path, post, download, downloadfile, pda)
- done = self["object"].render(res, path, post, download, downloadfile, pda, @sessionid)
-
- res.gsub!(/\$RWD_SESSION\$/, done ? "" : "#{@sessionid}")
-
- return done
- end
-end
-
-class RWDServer
- def initialize(obj, port, io, auth, realm)
- @object = obj
- @localbrowsing = false
- @browserstarted = false
- @sessions = Sessions.new(obj.class, (not auth.nil?))
-
- if auth.nil?
- @localbrowsing = true
-
- if ENV.include?("RWDBROWSER") and not ENV["RWDBROWSER"].nil? and not ENV["RWDBROWSER"].empty?
- @browserstarted = true
- @object.exitbrowser
-
- # Start browser.
-
- @browserthread =
- Thread.new do
- puts "Starting the browser..."
-
- #if ENV["RWDBROWSER"].downcase =~ /iexplore/ # ???
- #@ie = IE.new("http://localhost:#{port}/")
- #else
- browser = ENV["RWDBROWSER"].dup
- url = "http://localhost:%s/" % [port]
-
- if cygwin?
- browser.gsub!(/\\/, "/")
- browser.gsub!(/ /, "\\ ")
- end
-
- re = /[$%]1\b/
- command = "%s \"%s\"" % [browser, url]
- command = browser.gsub(re, url) if browser =~ re
-
- command.gsub!(/%port%/, port.to_s)
-
- system(command) or puts "Starting of the browser failed, or the browser terminated abnormally.\nCommand => #{command}"
- #end
-
- puts "The browser has terminated."
- end
- end
- end
-
- # Start server.
-
- portio = port
- portio = [port, io] unless io.nil?
- threadlimiter = ThreadLimiter.new(1)
-
- HTTPServer.serve(portio, (not auth.nil?)) do |req, resp|
- threadlimiter.wait do
-
- vars = req.vars.dup
- pad = (req.request.path or "/")
-
- if auth.kind_of? String
- file = "#{home}/#{auth}"
- auths = {}
- auths = Hash.file(file) if File.file?(file)
- else
- auths = auth
- end
-
- #oldsessionid = vars["rwd_session"]
- oldsessionid = req.cookies["sessionid"]
-
- # Retrieve session.
-
- session = @sessions[oldsessionid]
-
- # Eventually create new session.
-
- if session.nil?
- sessionid = MD5.new(req.peeraddr[3].to_s + @object.inspect.to_s + ("%1.6f" % Time.now.to_f)).to_s while (sessionid == nil or @sessions.include?(sessionid))
- session = RWDSession.new(sessionid)
-
- if auth.nil?
- session["object"] = @object
- else
- session["object"] = @object.clone
- end
-
- if oldsessionid.nil? or oldsessionid.empty?
- if not auth.nil? and not auth.empty? and not session.authenticated and pad != "/rwd_pixel.gif"
-
- # Check authentication
-
- us = vars["rwd_a"]
- pa = vars["rwd_b"]
-
- if us.nil? or pa.nil? or auths[us] != pa
- session = RWDSession.new
- session["object"] = RWDLogin.new(realm)
- pad = "/"
- else
- session.authenticated = true
- @sessions[session.sessionid] = session
- end
- else
- session.authenticated = true
- @sessions[session.sessionid] = session
- end
- else
- session = RWDSession.new
- session["object"] = RWDTimeOut.new
- end
-
- vars = {}
- end
-
- # Avoid timeout.
-
- session.touch
-
- if pad == "/"
-
- # Serve methods/callbacks.
-
- # Build new page.
-
- download = ""
- downloadfile = ""
- res = ""
-
- done = session.render(res, pad, vars, download, downloadfile, req.pda?)
-
- begin
- if download.empty?
- resp["Content-Type"] = "text/html"
- if done
- resp.cookies["sessionid"] = ""
- else
- resp.cookies["sessionid"] = session.sessionid
- end
-
- resp << res
- else
- resp["Content-Type"] = "application/octet-stream"
- resp["Content-Disposition"] = "attachment;"
- resp["Content-Disposition"] = "attachment; filename=%s" % downloadfile unless downloadfile.empty?
-
- resp << download
- end
- rescue
- puts "Sending response to browser failed."
-
- @sessions.delete(session.sessionid)
- end
-
- # Eventually delete this session.
-
- if done
- @sessions.delete(session.sessionid)
-
- if @localbrowsing
- resp.stop
-
- if @browserstarted and not @browserthread.nil? and @browserthread.alive?
- resp.stop do
- puts "Waiting for the browser to terminate..."
-
- @browserthread.join
- end
- end
- end
- end
-
- else
-
- # Serve files.
-
- if pad == "/rwd_pixel.gif"
- resp["Cache-Control"] = "max-age=86400"
- resp["Content-Type"] = "image/gif"
- resp << $rwd_pixel
- else
- if session.authenticated
- pwd = Dir.pwd
- file = File.expand_path(pad.gsub(/^\/*/, ""), $rwd_files)
-
- if not file.index(pwd) == 0
- resp["Content-Type"] = "text/html"
- resp.response = "HTTP/1.0 400 BAD REQUEST"
- resp << "<html><body><p><b>Bad Request.</b> (<tt>#{pad}</tt>)</p></body></html>"
- elsif File.file?(file)
- resp << File.new(file, "rb").read rescue nil
- else
- resp["Content-Type"] = "text/html"
- resp.response = "HTTP/1.0 404 NOT FOUND"
- resp << "<html><body><p><b>Not found.</b> (<tt>#{pad}</tt>)</p></body></html>"
- end
- else
- resp["Content-Type"] = "text/html"
- resp.response = "HTTP/1.0 ??? NOT AUTHORIZED"
- resp << "<html><body><p><b>Not Authorized.</b></p></body></html>"
- end
- end
-
- end
-
- end
- end
- end
-end
-
-$rwd_html["DEFAULT"] = "
-<!-- Generated by RubyWebDialog. -->
-<!-- For more information, please contact Erik Veenstra <rwd@erikveen.dds.nl>. -->
-<html>
- <head>
- <title>%TITLE%</title>
-
- <meta http-equiv='Content-Type' content='text/html; charset=%CHARSET%'>
- <meta http-equiv='Content-Style-Type' content='text/css'>
- <meta http-equiv='Refresh' content='%REFRESH%, javascript:document.bodyform.submit();'>
-
- <link rel='shortcut icon' href='%LOGO%'>
-
- <style type='text/css'>
- <!--
-
- a {
- text-decoration : none;
- }
-
- a:hover {
- background : #AAAAAA;
- }
-
- td.panel1 {
- border-color : #888888 #EEEEEE #EEEEEE #888888;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel2 {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel1high {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel2high {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : none none none none;
- }
-
- td.panel1low {
- border-color : #888888 #EEEEEE #EEEEEE #888888;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel2low {
- border-color : #888888 #EEEEEE #EEEEEE #888888;
- border-width : 1pt;
- border-style : none none none none;
- }
-
- td.tabblad {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : none solid solid solid;
- }
-
- td.passivetab {
- background-color : #BBBBBB;
- border-color : #DDDDDD #DDDDDD #EEEEEE #DDDDDD;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.activetab {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : solid solid none solid;
- }
-
- td.notab {
- border-color : #EEEEEE #EEEEEE #EEEEEE #EEEEEE;
- border-width : 1pt;
- border-style : none none solid none;
- }
-
- //-->
- </style>
-
- <script type='text/javascript'>
- <!--
- function BodyGo() {
- $RWD_FOCUS$
- }
- //-->
- </script>
- </head>
-
- <body bgcolor='white' onload='BodyGo()' link='#000000' vlink='#000000' alink='#000000'>
- <form name='bodyform' action='/' method='post'>
- <table align='center' border='0' cellspacing='0' cellpadding='0' width='100%' height='100%'>
- <tr align='center' valign='middle'>
- <td align='center'>
-
- <table align='center' border='0' cellspacing='0' cellpadding='0'>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
-
- <td align='center'>
-
- <table align='center' border='0' cellspacing='0' cellpadding='0' %WIDTH1%>
- <tr align='center'>
- <td align='center' bgcolor='#444488'>
-
- <table align='left' border='0' cellspacing='1' cellpadding='0'>
- <tr align='center'>
- <td align='border'><img src='%LOGO%' width='14' height='14'></td>
- <td align='center'><b><small><font color='#FFFFFF'> %TITLE% </font></small></b></td>
- </tr>
- </table>
-
- <table align='right' border='0' cellspacing='1' cellpadding='0'>
- <tr align='center'>
- <!-- %HELPBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_help\";document.bodyform.submit();'> ? </a></small></b></td>
- <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_main\";document.bodyform.submit();'> << </a></small></b></td>
- <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_back\";document.bodyform.submit();'> < </a></small></b></td>
- <!-- %CLOSEBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_quit\";document.bodyform.submit();'> X </a></small></b></td>
- </tr>
- </table>
-
- </td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='%WIDTH2%'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='#CCCCCC'>
- <table align='center' border='0' cellspacing='3' cellpadding='0'>
- %BODY%
- </table>
-
- <input name='rwd_action' value='$RWD_FIRSTACTION$' type='hidden'>
- <input name='rwd_session' value='$RWD_SESSION$' type='hidden'>
- </td>
- </tr>
- </table>
-
- </td>
-
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
- </tr>
-
- </table>
-
- </td>
- </tr>
- </table>
- </form>
- </body>
-</html>
-"
-
-$rwd_html["WINDOWSLOOKALIKE"] = "
-<!-- Generated by RubyWebDialog. -->
-<!-- For more information, please contact Erik Veenstra <rwd@erikveen.dds.nl>. -->
-<html>
- <head>
- <title>%TITLE%</title>
-
- <meta http-equiv='Content-Type' content='text/html; charset=%CHARSET%'>
- <meta http-equiv='Content-Style-Type' content='text/css'>
- <meta http-equiv='Refresh' content='%REFRESH%, javascript:document.bodyform.submit();'>
-
- <link rel='shortcut icon' href='%LOGO%'>
-
- <style type='text/css'>
- <!--
-
- a {
- text-decoration : none;
- }
-
- a:hover {
- background : #AAAAAA;
- }
-
- td.window {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 3pt;
- border-style : solid solid solid solid;
- }
-
- td.panel1 {
- border-color : #888888 #EEEEEE #EEEEEE #888888;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel2 {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel1high {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel2high {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : none none none none;
- }
-
- td.panel1low {
- border-color : #888888 #EEEEEE #EEEEEE #888888;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.panel2low {
- border-color : #888888 #EEEEEE #EEEEEE #888888;
- border-width : 1pt;
- border-style : none none none none;
- }
-
- td.tabblad {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : none solid solid solid;
- }
-
- td.passivetab {
- background-color : #BBBBBB;
- border-color : #DDDDDD #DDDDDD #EEEEEE #DDDDDD;
- border-width : 1pt;
- border-style : solid solid solid solid;
- }
-
- td.activetab {
- border-color : #EEEEEE #888888 #888888 #EEEEEE;
- border-width : 1pt;
- border-style : solid solid none solid;
- }
-
- td.notab {
- border-color : #EEEEEE #EEEEEE #EEEEEE #EEEEEE;
- border-width : 1pt;
- border-style : none none solid none;
- }
-
- //-->
- </style>
-
- <script type='text/javascript'>
- <!--
- function BodyGo() {
- $RWD_FOCUS$
- }
- //-->
- </script>
- </head>
-
- <body bgcolor='white' onload='BodyGo()' link='#000000' vlink='#000000' alink='#000000'>
- <form name='bodyform' action='/' method='post'>
- <table align='center' border='0' cellspacing='0' cellpadding='0' width='100%' height='100%'>
- <tr align='center' valign='middle'>
- <td align='center'>
-
- <table align='center' border='0' cellspacing='0' cellpadding='0'>
-
- <tr align='center'>
- <td align='center' class='window'>
-
- <table align='center' border='0' cellspacing='0' cellpadding='0' %WIDTH1%>
- <tr align='center'>
- <td align='center' bgcolor='#444488'>
-
- <table align='left' border='0' cellspacing='1' cellpadding='0'>
- <tr align='center'>
- <td align='border'><img src='%LOGO%' width='14' height='14'></td>
- <td align='center'><b><small><font color='#FFFFFF'> %TITLE% </font></small></b></td>
- </tr>
- </table>
-
- <table align='right' border='0' cellspacing='1' cellpadding='0'>
- <tr align='center'>
- <!-- %HELPBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_help\";document.bodyform.submit();'> ? </a></small></b></td>
- <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_main\";document.bodyform.submit();'> << </a></small></b></td>
- <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_back\";document.bodyform.submit();'> < </a></small></b></td>
- <!-- %CLOSEBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_quit\";document.bodyform.submit();'> X </a></small></b></td>
- </tr>
- </table>
-
- </td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='%WIDTH2%'></td>
- </tr>
-
- <tr align='center'>
- <td align='center' bgcolor='#CCCCCC'>
- <table align='center' border='0' cellspacing='3' cellpadding='0'>
- %BODY%
- </table>
-
- <input name='rwd_action' value='$RWD_FIRSTACTION$' type='hidden'>
- <input name='rwd_session' value='$RWD_SESSION$' type='hidden'>
- </td>
- </tr>
- </table>
-
- </td>
- </tr>
-
- </table>
-
- </td>
- </tr>
- </table>
- </form>
- </body>
-</html>
-"
-
-$rwd_html["PDA"] = "
-<!-- Generated by RubyWebDialog. -->
-<!-- For more information, please contact Erik Veenstra <rwd@erikveen.dds.nl>. -->
-<html>
- <head>
- <title>%TITLE%</title>
-
- <meta http-equiv='Content-Type' content='text/html; charset=%CHARSET%'>
- <meta http-equiv='Refresh' content='%REFRESH%, javascript:document.bodyform.submit();'>
-
- <link rel='shortcut icon' href='%LOGO%'>
-
- <script type='text/javascript'>
- <!--
- function BodyGo() {
- $RWD_FOCUS$
- }
- //-->
- </script>
- </head>
-
- <body bgcolor='white' onload='BodyGo()' link='#000000' vlink='#000000' alink='#000000'>
- <form name='bodyform' action='/' method='post'>
- <table align='center' border='0' cellspacing='0' cellpadding='0' width='100%' height='100%'>
-
- <tr align='center'>
- <td align='center' bgcolor='#444488'>
-
- <table align='left' border='0' cellspacing='1' cellpadding='0'>
- <tr align='center'>
- <td align='border'><img src='%LOGO%' width='14' height='14'></td>
- <td align='center'><b><small><font color='#FFFFFF'> %TITLE% </font></small></b></td>
- </tr>
- </table>
-
- <table align='right' border='0' cellspacing='1' cellpadding='0'>
- <tr align='center'>
- <!-- %HELPBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_help\";document.bodyform.submit();'> ? </a></small></b></td>
- <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_main\";document.bodyform.submit();'> << </a></small></b></td>
- <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_back\";document.bodyform.submit();'> < </a></small></b></td>
- <!-- %CLOSEBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_quit\";document.bodyform.submit();'> X </a></small></b></td>
- </tr>
- </table>
-
- </td>
- </tr>
-
- <!--
- <tr align='center'>
- <td align='center' bgcolor='#FFFFFF'> </td>
- </tr>
- -->
-
- <tr align='center'>
- <td align='center' bgcolor='#FFFFFF'>
-
- <table align='center' border='0' cellspacing='0' cellpadding='0'>
- %BODY%
- </table>
-
- <input name='rwd_action' value='$RWD_FIRSTACTION$' type='hidden'>
- <input name='rwd_session' value='$RWD_SESSION$' type='hidden'>
- </td>
- </tr>
-
- </table>
- </form>
- </body>
-</html>
-"
-
-$rwd_pixel = "
-R0lGODlhAQABAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoK
-CgsLCwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZ
-GRoaGhsbGxwcHB0dHR4eHh8fHyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygo
-KCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDExMTIyMjMzMzQ0NDU1NTY2Njc3
-Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkNDQ0REREVFRUZG
-RkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV
-VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2Rk
-ZGVlZWZmZmdnZ2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNz
-c3R0dHV1dXZ2dnd3d3h4eHl5eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKC
-goODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouLi4yMjI2NjY6Ojo+Pj5CQkJGR
-kZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2dnZ6enp+fn6Cg
-oKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v
-r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+
-vr+/v8DAwMHBwcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3N
-zc7Ozs/Pz9DQ0NHR0dLS0tPT09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc
-3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6uvr
-6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf39/j4+Pn5+fr6
-+vv7+/z8/P39/f7+/v///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQB
-CgD/ACwAAAAAAQABAAAIBAD/BQQAOw==
-".unpack("m").shift
-
-$rwd_html_1, $rwd_html_2 = $rwd_html[ENV["RWDTHEME"]].split(/^\s*%BODY%\s*\r*$/)
-$rwd_html_PDA_1, $rwd_html_PDA_2 = $rwd_html["PDA"].split(/^\s*%BODY%\s*\r*$/)
+require "ev/ruby"
+require "ev/xml"
+require "ev/net"
+require "ev/browser"
+require "ev/thread"
+require "md5"
+require "rbconfig"
+
+begin
+ require "win32ole"
+ require "win32/registry"
+rescue LoadError
+ $".push "win32ole.so"
+ $".push "win32/registry.rb"
+end
+
+$rwd_exit = ARGV.include?("--rwd-exit") # Hack ???
+$rwd_debug = ($rwd_debug or $DEBUG or false)
+$rwd_border = ($rwd_border or 0)
+$rwd_dir = Dir.pwd
+$rwd_files = File.expand_path("rwd_files", Dir.pwd)
+$rwd_html = {}
+
+ARGV.delete_if do |arg|
+ arg =~ /^--rwd-/
+end
+
+RWDEmptyline = "..."
+
+rcfile = nil
+s = ENV["HOME"] ; s = s + "/.rwdrc" if not s.nil? ; rcfile = s if (not s.nil? and rcfile.nil? and File.file?(s))
+s = ENV["USERPROFILE"] ; s = s + "/rwd.cfg" if not s.nil? ; rcfile = s if (not s.nil? and rcfile.nil? and File.file?(s))
+s = ENV["windir"] ; s = s + "/rwd.cfg" if not s.nil? ; rcfile = s if (not s.nil? and rcfile.nil? and File.file?(s))
+
+AL = "align='left'"
+AC = "align='center'"
+AR = "align='right'"
+VA = "valign='middle'"
+
+Format = "\n<!-- %-10s %-10s -->\t"
+
+unless rcfile.nil?
+ puts "Reading #{rcfile} ..."
+
+ Hash.file(rcfile).each do |k, v|
+ ENV[k] = v unless ENV.include?(k)
+ end
+end
+
+ENV["RWDBROWSER"] = (ENV["RWDBROWSER"] or defaultbrowser) or puts "No browser found."
+ENV["RWDPORTS"] = (ENV["RWDPORTS"] or "7701-7709")
+ENV["RWDTHEME"] = (ENV["RWDTHEME"] or "DEFAULT")
+
+trap("INT") {puts "Terminating..." ; exit}
+
+$SAFE = 2
+
+class IE
+ def initialize(url)
+ @ie = WIN32OLE.new("InternetExplorer.Application")
+ @ev = WIN32OLE_EVENT.new(@ie, "DWebBrowserEvents2")
+
+ @ie.navigate(url)
+
+ @ie.menubar = false
+ @ie.toolbar = false
+ @ie.addressbar = false
+ @ie.statusbar = false
+
+ @ie.visible = true
+
+ at_exit do
+ @ie.visible = false
+ end
+
+ @ev.on_event("OnQuit") do
+ Thread.main.exit
+ end
+
+ Thread.new do
+ loop do
+ WIN32OLE_EVENT.message_loop
+ end
+ end
+ end
+end
+
+class Array
+ def rwd_options(emptyline=nil)
+ if emptyline.nil?
+ a = self
+ else
+ a = [emptyline].concat(self)
+ end
+
+ a.numsort.collect{|s| "<option>#{s.to_html}</option>" }.join("\n")
+ end
+
+ def rwd_method(method)
+ res = ""
+
+ self.each do |s|
+ s = s.join("/") if s.kind_of?(Array)
+ s2 = s.dup
+ s2[0..0] = s2[0..0].upcase
+ res = res + "<p align='left'><a action='#{method}/#{s.to_html}'>#{s2.to_html}</a></p>"
+ end
+
+ return res
+ end
+
+ def rwd_row(key=nil, value=nil)
+ res = ""
+
+ res = res + "<row valign='top'>"
+ res = res + "<radio name='#{key.to_html}' value='#{value.to_html}'/>" unless key.nil?
+ res = res + self.collect{|s| "<p align='left'>#{s.to_html}</p>"}.join("")
+ res = res + "</row>"
+
+ return res
+ end
+
+ def rwd_headers(emptyfield=false)
+ res = ""
+
+ res = res + "<row>"
+ res = res + "<p/>" if emptyfield
+ res = res + self.collect{|s| "<p align='left'><b>#{s.to_html}</b></p>" }.join("")
+ res = res + "</row>"
+
+ return res
+ end
+
+ def rwd_form(prefix, values, twoparts=0, options={})
+ res = []
+
+ res << "<table>"
+ self.each_index do |n|
+ name = "#{prefix.to_html}#{self[n].downcase.to_html}"
+
+ res << "<row>"
+ res << "<p align='right'>"
+ res << "#{self[n].to_html}:"
+ res << "</p>"
+
+ if options.keys.include?(self[n])
+ res << "<select name='#{name}'>"
+ res << options[self[n]].rwd_options(RWDEmptyline)
+ res << "</select>"
+ else
+ s = ""
+
+ s << "<text name='#{name}'"
+ s << " value='#{values[n].to_html}'" if n < values.length
+ s << "/>"
+
+ res << s
+ end
+
+ res << "</row>"
+
+ if twoparts > 0 and n == twoparts-1
+ res << "<row><empty/></row>"
+ end
+ end
+ res << "</table>"
+
+ return res.join("\n")
+ end
+end
+
+class Hash
+ def rwd_table(field=nil, joinwith=nil, headers=nil)
+ res = []
+
+ res << "<table>"
+ res << headers.rwd_headers((not field.nil?)) if not headers.nil?
+ self.keys.numsort.each do |key|
+ key2 = key
+ value2 = self[key]
+
+ key2 = key2.join(joinwith) if key2.kind_of?(Array)
+ value2 = [value2] if value2.kind_of?(String)
+
+ res << value2.rwd_row(field, key2)
+ end
+ res << "</table>"
+
+ res.join("\n")
+ end
+end
+
+class EVTable
+ def rwd_table(field=nil, joinwith=@sep)
+ super(field, joinwith, @headers)
+ end
+
+ def rwd_form(prefix="", key=nil, twoparts=false)
+ values = self[key] if not key.nil?
+ values = [] if values.nil?
+ options = {}
+
+ if File.file?(oldlocation("constraints.tsv"))
+ table = File.basename(@file).gsub(/\.tsv$/, "")
+
+ TSVFile.new(oldlocation("constraints.tsv")).subset(["Table", "Constraint"], [table, "key"], ["Column", "Value"]).values.each do |column, table2|
+ options[column] = TSVFile.new(oldlocation("#{table2}.tsv")).keys.collect{|a| a.join("\t")}
+ end
+ end
+
+ @headers.rwd_form(prefix, values, twoparts ? @key : 0, options)
+ end
+
+ def rwd_metadata
+ res = []
+
+ res << "<table>"
+ res << "<row>"
+ res << " <empty/>"
+ res << " <text name='header_new' value=''/>"
+ res << "</row>"
+ @headers.each_index do |n|
+ res << "<row>"
+ res << " <text name='header_#{n}_old' value='#{@headers[n]}'/>"
+ res << " <text name='header_#{n}_new' value=''/>"
+ res << "</row>"
+ end
+ res << "</table>"
+
+ return res.join("\n")
+ end
+end
+
+class OpenTag
+ def prechildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab, pda)
+ bef = before[-1]
+ res << Format % ["Before", @subtype] if ($rwd_debug and not bef.nil?)
+ res << bef if not bef.nil?
+
+ res << Format % ["Pre", @subtype] if $rwd_debug
+
+ align = AC
+ align = "align='#{@args["align"]}'" if @args.include?("align")
+
+ valign = VA
+ valign = "valign='#{@args["valign"]}'" if @args.include?("valign")
+
+ value1 = ""
+ value1 = varshtml[@args["name"]] if varshtml.include?(@args["name"])
+ value1 = @args["value"] if @args.include?("value")
+
+ value2 = ""
+ value2 = varsstring[@args["name"]] if varsstring.include?(@args["name"])
+ value2 = @args["value"] if @args.include?("value")
+
+ cellspacing = 3
+ cellspacing = 0 if pda
+
+ case @subtype
+ when "application"
+ when "window", "helpwindow"
+ args = @args.deep_dup
+
+ args["nohelpbutton"] = (not help)
+
+ template = $rwd_html_1
+ template = $rwd_html_PDA_1 if pda
+
+ res <<(template(template, args))
+ when "p" then res << "<p #{align}>"
+ when "pre" then res << "<pre #{align}>"
+ when "big" then res << "<p #{align}><big>"
+ when "small" then res << "<p #{align}><small>"
+ when "list" then res << "<ul #{align}>"
+ when "item" then res << "<li #{align}>"
+ when "empty" then res << "<p><br>"
+ when "image"
+ width = "width='#{@args["width"]}" if @args.include?("width")
+ height = "height='#{@args["height"]}'" if @args.include?("height")
+
+ res << "<img src='#{@args["src"]}' alt='#{@args["alt"]}' #{width} #{height}>"
+ when "progressbar"
+ width = 200
+
+ res << "<table>"
+ res << " <tr>"
+ res << " <td colspan='2'><img src='rwd_pixel.gif' height='1' width='#{width+5}'></td>"
+ res << " </tr>"
+ res << " <tr>"
+ res << " <td bgcolor='#DDDDDD'><img src='rwd_pixel.gif' height='10' width='#{(width*@args["value"].to_f).to_i}'></td>"
+ res << " <td bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='10' width='#{(width*(1.0-@args["value"].to_f)).to_i}'></td>"
+ res << " </tr>"
+ res << "</table>"
+ when "br" then res << "<br>"
+ when "hr" then res << "<hr>"
+ when "b" then res << "<b>"
+ when "i" then res << "<i>"
+ when "a"
+ if @args.include?("href")
+ res << "<a href='#{@args["href"]}' target='#{@args["target"] or "_blank"}'>"
+ else
+ res << "<a href='javascript:document.bodyform.rwd_action.value=\"#{@args["action"]}\";document.bodyform.submit();'>"
+ end
+ when "vertical" then res << "<table #{AC} border='#{$rwd_border}' cellspacing='#{cellspacing}' cellpadding='0'>"
+ when "horizontal" then res << "<table #{AC} border='#{$rwd_border}' cellspacing='#{cellspacing}' cellpadding='0'><tr #{align} #{valign}>"
+ when "table" then res << "<table #{AC} border='#{$rwd_border}' cellspacing='#{cellspacing}' cellpadding='0'>"
+ when "row" then res << "<tr #{align} #{valign}>"
+ when "hidden" then res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='hidden'>"
+ when "text"
+ maxlength = ""
+ maxlength = "maxlength='%s'" % @args["maxlength"] if @args.include?("maxlength")
+ size = ""
+ size = "size='%s'" % 10 if pda
+ res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='text' #{maxlength} #{size}>"
+ oneormorefields << "true"
+ when "textarea"
+ res << "<p #{align}><textarea name='#{@args["name"]}' rows='25' cols='80'>#{value2.crlf}</textarea>"
+ oneormorefields << "true"
+ when "password"
+ maxlength = ""
+ maxlength = "maxlength='%s'" % @args["maxlength"] if @args.include?("maxlength")
+ size = ""
+ size = "size='%s'" % 10 if pda
+ res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='password' #{maxlength} #{size}>"
+ oneormorefields << "true"
+ when "checkbox"
+ if varshtml[@args["name"]] == "on"
+ switches[@args["name"]] = true
+ res << "<p #{align}><input name='#{@args["name"]}' checked='on' type='checkbox'>"
+ else
+ switches[@args["name"]] = false
+ res << "<p #{align}><input name='#{@args["name"]}' type='checkbox'>"
+ end
+ oneormorefields << "true"
+ when "radio"
+ if varshtml[@args["name"]] == value1 # ??? 1 or 2?
+ res << "<p #{align}><input name='#{@args["name"]}' checked='on' value='#{value1}' type='radio'>"
+ else
+ res << "<p #{align}><input name='#{@args["name"]}' value='#{value1}' type='radio'>"
+ end
+ oneormorefields << "true"
+ when "select"
+ res << "<select #{align} name='#{@args["name"]}' width='#{@args["width"]}'>"
+ name = @args["name"]
+ $select = varshtml[name]
+ oneormorefields << "true"
+ when "option"
+ if $select == @children[0].text
+ res << "<option selected='true'>"
+ else
+ res << "<option>"
+ end
+ when "button"
+ res << "<input type='submit' value='#{@args["caption"]}' onclick='document.bodyform.rwd_action.value=\"#{@args["action"]}\";'>"
+ firstaction << @args["action"] if (firstaction.empty? and @args.include?("action"))
+ oneormorefields << "true"
+ when "back"
+ res << "<input type='submit' value='Back' onclick='document.bodyform.rwd_action.value=\"rwd_back\";'>"
+ firstaction << "rwd_back" if firstaction.empty?
+ oneormorefields << "true"
+ when "cancel"
+ res << "<input type='submit' value='Cancel' onclick='document.bodyform.rwd_action.value=\"rwd_cancel\";'>"
+ firstaction << "rwd_cancel" if firstaction.empty?
+ oneormorefields << "true"
+ when "help"
+ res << "<input type='submit' value='Help' onclick='document.bodyform.rwd_action.value=\"rwd_help\";'>"
+ firstaction << "rwd_help" if firstaction.empty?
+ oneormorefields << "true"
+ when "quit"
+ res << "<input type='submit' value='Quit' onclick='document.bodyform.rwd_action.value=\"rwd_quit\";'>"
+ firstaction << "rwd_quit" if firstaction.empty?
+ oneormorefields << "true"
+ when "close"
+ res << "<input type='submit' value='Close' onclick='window.close();'>"
+ firstaction << "rwd_quit" if firstaction.empty?
+ oneormorefields << "true"
+ when "main"
+ res << "<input type='submit' value='Main' onclick='document.bodyform.rwd_action.value=\"rwd_main\";'>"
+ firstaction << "rwd_main" if firstaction.empty?
+ oneormorefields << "true"
+ when "reset"
+ res << "<input type='reset' value='Reset'>"
+ firstaction << "rwd_quit" if firstaction.empty? # ???
+ oneormorefields << "true"
+ when "closewindow"
+ #res << "<script type='text/javascript'>\n" # ???
+ #res << "<!--\n"
+ #res << " window.close();\n"
+ #res << "//-->\n"
+ #res << "</script>"
+ when "tabs"
+ res << "<table #{AC} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
+ res << " <tr #{AL}>"
+ res << " <td #{AL} class='tabs'>"
+ res << " <table #{AL} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
+ res << " <tr #{AL}>"
+ #res << " <td class='notab'> </td>"
+ tabs.each do |obj|
+ name = obj.args["name"]
+ caption = obj.args["caption"]
+
+ res << "<td #{AL} class='notab'> </td>" unless obj == tabs[0]
+
+ if name == tab
+ res << "<td #{AC} class='activetab'><tt> #{caption} </tt></td>"
+ else
+ res << "<td #{AC} class='passivetab'><a href='javascript:document.bodyform.rwd_action.value=\"rwd_tab_#{name}\";document.bodyform.submit();'><tt> #{caption} </tt></a></td>"
+ end
+ end
+ res << " <td class='notab' width='100%'> </td>"
+ res << " </tr>"
+ res << " </table>"
+ res << " </td>"
+ res << " </tr>"
+ res << " <tr #{align}>"
+ res << " <td #{align} class='tabblad'>"
+ when "tab"
+ res << "<table #{AC} border='#{$rwd_border}' cellspacing='3' cellpadding='0'>"
+ when "panel"
+ level = (@args["level"] or "normal")
+ res << "<table #{AC} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
+ res << " <tr #{align}>"
+ res << " <td #{align} class='panel1'>" if level == "normal"
+ res << " <td #{align} class='panel1high'>" if level == "high"
+ res << " <td #{align} class='panel1low'>" if level == "low"
+ res << " <table #{AC} border='#{$rwd_border}' cellspacing='0' cellpadding='0'>"
+ res << " <tr #{align}>"
+ res << " <td #{align} class='panel2'>" if level == "normal"
+ res << " <td #{align} class='panel2high'>" if level == "high"
+ res << " <td #{align} class='panel2low'>" if level == "low"
+ res << " <table #{AC} border='#{$rwd_border}' cellspacing='3' cellpadding='0'>"
+ else
+ puts "<#{@subtype}>"
+ res << "<#{@subtype}>"
+ end
+
+ bef = nil
+ aft = nil
+
+ case @subtype
+ when "vertical", "window", "helpwindow", "tab", "panel"
+ res << Format % ["AftPre", @subtype] if $rwd_debug
+ if @args.include?("spacing")
+ s = "<tr><td> </td></tr>" * (@args["spacing"].to_i)
+ else
+ s = ""
+ end
+ bef = "#{s}<tr #{align} #{valign}><td #{align}>"
+ aft = "</td></tr>"
+ when "horizontal", "row"
+ res << Format % ["AftPre", @subtype] if $rwd_debug
+ bef = "<td #{align}>"
+ aft = "</td>"
+ end
+
+ before.push(bef)
+ after.push(aft)
+ end
+
+ def postchildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab, pda)
+ case @subtype
+ when "vertical", "window", "helpwindow", "tab", "panel"
+ res << Format % ["BefPost", @subtype] if $rwd_debug
+ if @args.include?("spacing")
+ res << "<tr><td> </td></tr>" * (@args["spacing"].to_i)
+ end
+ when "horizontal", "row"
+ res << Format % ["BefPost", @subtype] if $rwd_debug
+ end
+
+ res << Format % ["Post", @subtype] if $rwd_debug
+
+ case @subtype
+ when "application"
+ when "window", "helpwindow"
+ args = @args.deep_dup
+
+ args["nohelpbutton"] = (not help)
+
+ template = $rwd_html_2
+ template = $rwd_html_PDA_2 if pda
+
+ res <<(template(template, args))
+ when "p" then res << "</p>"
+ when "pre" then res << "</pre>"
+ when "big" then res << "</big></p>"
+ when "small" then res << "</small></p>"
+ when "list" then res << "</ul>"
+ when "item" then res << "</li>"
+ when "empty" then res << "</p>"
+ when "image" then res << ""
+ when "progressbar" then res << ""
+ when "br" then res << ""
+ when "hr" then res << ""
+ when "b" then res << "</b>"
+ when "i" then res << "</i>"
+ when "a" then res << "</a>"
+ when "vertical" then res << "</table>"
+ when "horizontal" then res << "</tr></table>"
+ when "table" then res << "</table>"
+ when "row" then res << "</tr>"
+ when "hidden" then res << "</p>"
+ when "text" then res << "</p>"
+ when "textarea" then res << "</p>"
+ when "password" then res << "</p>"
+ when "checkbox" then res << "</p>"
+ when "radio" then res << "</p>"
+ when "select"
+ res << "</select>"
+ $select = nil
+ when "option" then res << "</option>"
+ when "button" then res << ""
+ when "back" then res << ""
+ when "cancel" then res << ""
+ when "help" then res << ""
+ when "quit" then res << ""
+ when "close" then res << ""
+ when "main" then res << ""
+ when "reset" then res << ""
+ when "closewindow" then res << ""
+ when "tabs"
+ res << " </td>"
+ res << " </tr>"
+ res << "</table>"
+ when "tab"
+ res << "</table>"
+ when "panel"
+ res << " </table>"
+ res << " </td>"
+ res << " </tr>"
+ res << " </table>"
+ res << " </td>"
+ res << " </tr>"
+ res << "</table>"
+ else
+ puts "</#{@subtype}>"
+ res << "</#{@subtype}>"
+ end
+
+ before.pop
+ after.pop
+
+ aft = after[-1]
+ res << Format % ["After", @subtype] if ($rwd_debug and not aft.nil?)
+ res << aft if not aft.nil?
+ end
+
+ def template(html, vars)
+ res = []
+
+ a = {}
+
+ vars.each do |k, v|
+ a[k.upcase] = v
+ end
+
+ logo = nil
+ logo = File.expand_path(vars["logo"], $rwd_files) if vars.include?("logo")
+ logo = nil unless logo.nil? or File.file?(logo)
+
+ a["LOGO"] = "" unless not logo.nil?
+
+ a["HELPBUTTON"] = (not (vars["nohelpbutton"]))
+ a["BACKBUTTONS"] = (not (vars["nobackbuttons"]))
+ a["BACKBUTTONS"] = (not (vars["nobackbuttons"]))
+ a["CLOSEBUTTON"] = (not (vars["noclosebutton"]))
+
+ if a.include?("WIDTH")
+ a["WIDTH1"] = "width='#{a["WIDTH"]}'"
+ a["WIDTH2"] = a["WIDTH"]
+ else
+ a["WIDTH1"] = " "
+ a["WIDTH2"] = "1"
+ end
+
+ html.split(/\r*\n/).each do |line|
+ if line =~ /%[A-Z0-9]+%/
+ a.each do |k, v|
+ v = false if (v.kind_of?(String) and v.empty?)
+
+ if line.include?("%#{k}%")
+ line.gsub!("%#{k}%", "#{v}") if v
+ end
+ end
+
+ line = "<!-- #{line.scan(/%[A-Z0-9]+%/).join(" ")} -->" if line =~ /%[A-Z0-9]+%/
+ end
+
+ res << line
+ end
+
+ res.join("\n")
+ end
+end
+
+class Text
+ def prechildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab, pda)
+ if not @text.scan(/[^ \t\r\n]/).empty?
+ res << Format % ["Text", ""] if $rwd_debug
+ res << "#{@text}"
+ end
+ end
+end
+
+class RWDTree < XML
+end
+
+class RWDWindow
+ @@windows = {} # Kind of caching.
+ @@helpwindows = {} # Kind of caching.
+
+ def initialize(rwd, window=nil)
+ rwd = rwd.join("\n") if rwd.kind_of?(Array)
+
+ if @@windows[rwd].nil?
+ @@windows[rwd] = {}
+ @@helpwindows[rwd] = {}
+
+ tree = XML.new(rwd)
+
+ tree.parse(OpenTag, "window") do |type, obj|
+ @@windows[rwd][obj.args["name"]] = obj.to_h
+ end
+
+ tree.parse(OpenTag, "helpwindow") do |type, obj|
+ @@helpwindows[rwd][obj.args["name"]] = obj.to_h
+ end
+ end
+
+ @rwd = (@@windows[rwd][window] or "").dup
+ @helprwd = (@@helpwindows[rwd][window] or "").dup
+ end
+
+ def render(pda, action=nil, vars=Hash.new, switches=Hash.new, help=false, tab="")
+ varshtml = Hash.new
+ varsstring = Hash.new
+ oneormorefields = ""
+ firstaction = ""
+ html = []
+
+ vars.each do |key, value|
+ if not key.empty?
+ if value.respond_to? "to_s"
+ @rwd.gsub!(/%%#{key}%%/, value.to_s)
+ @rwd.gsub!(/%#{key}%/, value.to_s.to_html)
+
+ @helprwd.gsub!(/%%#{key}%%/, value.to_s)
+ @helprwd.gsub!(/%#{key}%/, value.to_s.to_html)
+
+ varshtml[key] = value.to_s.to_html
+ varsstring[key] = value.to_s
+ end
+ end
+ end
+
+ windowobject = RWDTree.new(@rwd).children.dup.delete_if{|obj| obj.subtype != "window"}[0]
+ helpobject = RWDTree.new(@helprwd).children.dup.delete_if{|obj| obj.subtype != "helpwindow"}[0]
+
+ tabsobj = windowobject.children.dup.delete_if{|obj| obj.subtype != "tabs"}[0]
+
+ if not tabsobj.nil?
+ tabs = tabsobj.children.dup.delete_if{|obj| (not obj.kind_of?(OpenTag)) or (obj.subtype != "tab")}
+
+ if tab.empty?
+ tab = tabs[0].args["name"]
+ end
+
+ tabsobj.children.delete_if{|obj| (obj.kind_of?(OpenTag)) and (obj.subtype == "tab") and obj.args["name"] != tab}
+ end
+
+ if help
+ helpobject.parsetree("prechildren", "postchildren", html, [""], [""], varshtml, varsstring, switches, false, oneormorefields, firstaction, tabs, tab, pda)
+ else
+ windowobject.parsetree("prechildren", "postchildren", html, [""], [""], varshtml, varsstring, switches, (not @helprwd.empty?), oneormorefields, firstaction, tabs, tab, pda)
+ end
+
+ html = html.join("") # ???
+
+ html.gsub!(/%%*[[:alnum:]_\-]+%%*/, "") if not $rwd_debug
+ html.gsub!(/%%/, "%")
+ html.gsub!(/\n\n*/, "\n")
+
+ if oneormorefields.empty?
+ focus = ""
+ else
+ focus = "document.bodyform.elements[0].focus();"
+ end
+
+ firstaction = action if windowobject.args.keys.include?("refresh") unless action.nil?
+
+ html.gsub!(/\$RWD_FIRSTACTION\$/ , firstaction)
+ html.gsub!(/\$RWD_FOCUS\$/ , focus)
+
+ html
+ end
+end
+
+class RWDMessage < RWDWindow
+ def initialize(msg)
+ super("<window title='RWD Message' nobackbuttons noclosebutton><p>#{msg}</p><back/></window>")
+ end
+end
+
+class RWDError < RWDWindow
+ def initialize(msg)
+ super("<window title='RWD Error' nobackbuttons noclosebutton><p><b>Error:</b> #{msg}</p><back/></window>")
+ end
+end
+
+class RWDProgressBar < RWDWindow
+ def initialize(refresh, progress)
+ s = ""
+ s << "<window title='RWD Progress' nobackbuttons noclosebutton refresh='#{refresh}'>"
+ if progress.length == 1
+ progress.each do |caption, value|
+ s << "<p>#{caption}</p><progressbar value='#{value}'/><p>#{(100*value).to_i}%%</p>"
+ end
+ else
+ s << "<table>"
+ progress.each do |caption, value|
+ s << "<row><p align='left'>#{caption}</p><progressbar value='#{value}'/><p align='right'>#{(100*value).to_i}%%</p></row>"
+ end
+ s << "</table>"
+ end
+ s << "<cancel/>"
+ s << "</window>"
+ super(s)
+ end
+end
+
+class RWDDone < RWDWindow
+ def initialize(exitbrowser)
+ super("<window title='RWD Message' nobackbuttons noclosebutton><p>Done.</p><horizontal><close/>#{exitbrowser ? "" : "<button caption='Again'/>"}</horizontal>#{exitbrowser ? "<closewindow/>" : ""}</window>")
+ end
+end
+
+class RWDialog
+ def initialize(xml)
+ @rwd_xml = xml
+ @rwd_exitbrowser = false
+ @rwd_history = []
+ @rwd_ignore_vars = []
+ @rwd_call_after_back = []
+ end
+
+ def self.file(rwdfile, *args)
+ new(File.new(rwdfile).readlines, *args)
+ end
+
+ def serve(port=nil, auth=nil, realm=self.class.to_s)
+ exit if $rwd_exit
+
+ raise "RWD is not initialized." if @rwd_xml.nil?
+
+ low, high = ENV["RWDPORTS"].split(/[^\d+]/)
+ high = low if high.nil?
+ low, high = low.to_i, high.to_i
+
+ io = nil
+
+ port, io = TCPServer.freeport(low, high, (not auth.nil?)) if port.nil?
+ raise "No free TCP port." if port.nil?
+
+ port = port.to_i
+
+ @rwd_server = RWDServer.new(self, port, io, auth, realm)
+ end
+
+ def render(res, path, post, download, downloadfile, pda, sessionid)
+
+ # Initialize some vars.
+
+ vars = Hash.new if vars.nil?
+ @rwd_switches = Hash.new if @rwd_switches.nil?
+
+ done = false
+ help = false
+ back = false
+ tab = ""
+ @rwd_msgtype = nil
+ @rwd_download = nil
+ @rwd_download_file = nil
+
+ # Switches are used for checkboxes.
+
+ @rwd_switches.each do |key, value|
+ vars[key] = "off"
+ end
+
+ @rwd_switches = Hash.new
+
+ # Copy the vars from the window to vars. vars wil later on be copied to instance variables.
+
+ post.sort.each do |key, value|
+ puts "Post: #{key} -> #{value.from_html.inspect}" if $rwd_debug
+
+ vars[key] = value.from_html
+ end
+
+ # Stack handling for rwd_action, rwd_window and rwd_tab.
+
+ @rwd_action = vars["rwd_action"] if vars.include?("rwd_action")
+ @rwd_action, @rwd_args = @rwd_action.split(/\//, 2) unless @rwd_action.nil?
+ @rwd_action, rest = @rwd_action.split(/\?/) unless @rwd_action.nil?
+
+ @rwd_refresh_action = (@rwd_action or @rwd_refresh_action or "main")
+
+ unless rest.nil?
+ rest.each do |s|
+ k, v = s.split(/=/, 2)
+ vars[k] = v
+ end
+ end
+
+ if @rwd_action == "rwd_cancel"
+ @rwd_progress_thread.kill unless @rwd_progress_thread.nil?
+ @rwd_progress_thread = nil
+ @rwd_action = "rwd_back"
+ end
+
+ if @rwd_action =~ /^rwd_tab_/
+ @rwd_tab = @rwd_action.sub(/^rwd_tab_/, "")
+ @rwd_history[-1][3] = @rwd_tab
+ else
+ case @rwd_action
+ when "rwd_back"
+ @rwd_history.pop
+ @rwd_action = (@rwd_history[-1] or [nil, nil, nil])[0]
+ @rwd_args = (@rwd_history[-1] or [nil, nil, nil])[1]
+ @rwd_window = (@rwd_history[-1] or [nil, nil, nil])[2]
+ @rwd_tab = (@rwd_history[-1] or [nil, nil, nil])[3]
+ back = true
+ when "rwd_help"
+ help = true
+ when "rwd_main"
+ @rwd_action = nil
+ @rwd_window = nil
+ @rwd_tab = nil
+ @rwd_history = []
+ when "rwd_quit"
+ done = true
+ end
+
+ # History stuff
+
+ @rwd_history = @rwd_history[-100..-1] if @rwd_history.length >= 100
+ @rwd_action = "main" if @rwd_action.nil?
+ @rwd_action = "main" if @rwd_action.empty?
+ @rwd_window = "main" if @rwd_window.nil?
+ @rwd_window = "main" if @rwd_window.empty?
+ @rwd_tab = "" if @rwd_tab.nil?
+ @rwd_args = [] if @rwd_args.nil?
+ @rwd_args = [] if @rwd_action == "main"
+
+ vars["rwd_action"] = @rwd_action
+ vars["rwd_window"] = @rwd_window
+ vars["rwd_tab"] = @rwd_tab
+
+ # Copy vars from window to instance.
+
+ vars.each do |k, v|
+ instance_eval "@#{k} = vars['#{k}']" if ((not k.empty?) and k.scan(/^rwd_/).empty? and not @rwd_ignore_vars.include?("@#{k}"))
+ end
+
+ # Callback.
+
+ if (not back) or @rwd_call_after_back.include?(@rwd_action)
+ unless @rwd_action =~ /^rwd_/
+ puts "Method: #{@rwd_action}(#{@rwd_args.join(", ")})" if $rwd_debug
+ if methods.include?(@rwd_action)
+ method(@rwd_action).call(*@rwd_args)
+ else
+ puts "Method '%s' is not defined." % @rwd_action
+ end
+ end
+
+ # History stuff
+
+ @rwd_history = [["main", [], "main", ""]] if @rwd_action == "main"
+ @rwd_history = [["main", [], "main", ""]] if @rwd_history.empty?
+
+ a = [@rwd_action, @rwd_args, @rwd_window, @rwd_tab]
+
+ @rwd_history.push a if (@rwd_history[-1] != a or not @rwd_msgtype.nil?)
+ end
+ end
+
+ # Copy vars from instance to window.
+
+ instance_variables.each do |k|
+ k.sub!(/^@/, "")
+ instance_eval "vars['#{k}'] = @#{k}.to_s" if (k.scan(/^rwd_/).empty? and not @rwd_ignore_vars.include?("@#{k}"))
+ end
+
+ # just ignore.
+
+ vars.sort.each do |key, value|
+ puts "Pre: #{key} -> #{value.inspect}" if $rwd_debug
+ end
+
+
+ # Answer to browser.
+
+ if done
+ res << RWDDone.new(@rwd_exitbrowser).render(pda)
+ else
+ if not @rwd_download.nil?
+ puts "Download: #{@rwd_window}" if $rwd_debug
+
+ download << @rwd_download
+ downloadfile << @rwd_download_file
+ else
+ if not @rwd_msgtype.nil?
+ res << RWDMessage.new(@rwd_msg).render(pda) if @rwd_msgtype == "message"
+ res << RWDError.new(@rwd_msg).render(pda) if @rwd_msgtype == "error"
+ else
+ if not @rwd_progress_thread.nil?
+ res << RWDProgressBar.new(@rwd_progress_refresh, @rwd_progress_progress).render(pda, @rwd_refresh_action)
+ else
+ puts "Window: #{@rwd_window}" if $rwd_debug
+ puts "Tab: #{@rwd_tab}" if $rwd_debug
+
+ res << RWDWindow.new(@rwd_xml, @rwd_window).render(pda, @rwd_refresh_action, vars, @rwd_switches, help, @rwd_tab)
+ end
+ end
+ end
+ end
+
+ return done
+ end
+
+ def samewindow?
+ @rwd_history[-1][2] == @rwd_window
+ end
+
+ def message(msg, &block)
+ @rwd_msg = msg
+ @rwd_msgtype = "message"
+ end
+
+ def error(msg, &block)
+ @rwd_msg = msg
+ @rwd_msgtype = "error"
+ end
+
+ def progressbar(refresh, *progress)
+ @rwd_progress_refresh = (refresh or 1)
+ @rwd_progress_progress = []
+
+ while not progress.empty?
+ s = (progress.shift or "")
+ if s.kind_of?(Array)
+ caption, value = s
+ value = (value or 0.0).to_f
+ else
+ caption = s
+ value = (progress.shift or 0.0).to_f
+ end
+
+ @rwd_progress_progress << [caption, value]
+ end
+
+ if @rwd_progress_thread.nil?
+ @rwd_progress_progress.each do |a|
+ a[1] = 0.0
+ end
+
+ @rwd_progress_thread =
+ Thread.new do
+ yield
+ end
+ Thread.pass
+ end
+
+ @rwd_progress_thread = nil unless @rwd_progress_thread.alive?
+ end
+
+ def download(data, filename="")
+ @rwd_download = data
+ @rwd_download_file = filename
+ end
+
+ def exitbrowser
+ @rwd_exitbrowser = true
+ end
+end
+
+class RWDLogin < RWDialog
+ def initialize(realm)
+ super("<window name='main' title='RWD Login for #{realm}' nobackbuttons noclosebutton><table><row><p align='right'>Username:</p><text name='rwd_a'/></row><row><p align='right'>Password:</p><password name='rwd_b'/></row></table><button caption='Login'/></window>")
+ end
+end
+
+class RWDTimeOut < RWDialog
+ def initialize
+ super("<window name='main' title='RWD Error' nobackbuttons noclosebutton><p><b>Error:</b> Session has expired.</p><button caption='New session'/></window>")
+ end
+end
+
+class SessionCleanup
+ def initialize(sessions, interval, timeout)
+ every(interval) do
+ sessions.delete_if do |id, session|
+ time = Time.now.to_i - session.lastaccess.to_i
+
+ puts "Session %s deleted" % id if time > timeout
+
+ time > timeout
+ end
+ end
+ end
+end
+
+class Sessions
+ def initialize(rack, cleanup)
+ @rack = rack.to_s
+ @cleanup = SessionCleanup.new(self, 3600, 24*3600) if cleanup
+ @sessions = {}
+ end
+
+ def [](sessionid)
+ @sessions[sessionid]
+ end
+
+ def []=(sessionid, value)
+ @sessions[sessionid] = value
+ end
+
+ def delete(sessionid)
+ @sessions.delete(sessionid)
+ end
+
+ def delete_if(&block)
+ @sessions.delete_if{|k, v| block.call(k, v)}
+ end
+
+ def include?(sessionid)
+ @sessions.include?(sessionid)
+ end
+end
+
+class Session < Hash
+ attr_reader :sessionid
+ attr_reader :lastaccess
+ attr_reader :authenticated
+ attr_writer :authenticated
+
+ def initialize(sessionid=nil)
+ @sessionid = sessionid
+ @lastaccess = Time.now
+ @authenticated = false
+ end
+
+ def touch
+ @lastaccess = Time.now
+ end
+end
+
+class RWDSession < Session
+ def render(res, path, post, download, downloadfile, pda)
+ done = self["object"].render(res, path, post, download, downloadfile, pda, @sessionid)
+
+ res.gsub!(/\$RWD_SESSION\$/, done ? "" : "#{@sessionid}")
+
+ return done
+ end
+end
+
+class RWDServer
+ def initialize(obj, port, io, auth, realm)
+ @object = obj
+ @localbrowsing = false
+ @browserstarted = false
+ @sessions = Sessions.new(obj.class, (not auth.nil?))
+
+ if auth.nil?
+ @localbrowsing = true
+
+ if ENV.include?("RWDBROWSER") and not ENV["RWDBROWSER"].nil? and not ENV["RWDBROWSER"].empty?
+ @browserstarted = true
+ @object.exitbrowser
+
+ # Start browser.
+
+ @browserthread =
+ Thread.new do
+ puts "Starting the browser..."
+
+ #if ENV["RWDBROWSER"].downcase =~ /iexplore/ # ???
+ #@ie = IE.new("http://localhost:#{port}/")
+ #else
+ browser = ENV["RWDBROWSER"].dup
+ url = "http://localhost:%s/" % [port]
+
+ if cygwin?
+ browser.gsub!(/\\/, "/")
+ browser.gsub!(/ /, "\\ ")
+ end
+
+ re = /[$%]1\b/
+ command = "%s \"%s\"" % [browser, url]
+ command = browser.gsub(re, url) if browser =~ re
+
+ command.gsub!(/%port%/, port.to_s)
+
+ system(command) or puts "Starting of the browser failed, or the browser terminated abnormally.\nCommand => #{command}"
+ #end
+
+ puts "The browser has terminated."
+ end
+ end
+ end
+
+ # Start server.
+
+ portio = port
+ portio = [port, io] unless io.nil?
+ threadlimiter = ThreadLimiter.new(1)
+
+ HTTPServer.serve(portio, (not auth.nil?)) do |req, resp|
+ threadlimiter.wait do
+
+ vars = req.vars.dup
+ pad = (req.request.path or "/")
+
+ if auth.kind_of? String
+ file = "#{home}/#{auth}"
+ auths = {}
+ auths = Hash.file(file) if File.file?(file)
+ else
+ auths = auth
+ end
+
+ #oldsessionid = vars["rwd_session"]
+ oldsessionid = req.cookies["sessionid"]
+
+ # Retrieve session.
+
+ session = @sessions[oldsessionid]
+
+ # Eventually create new session.
+
+ if session.nil?
+ sessionid = MD5.new(req.peeraddr[3].to_s + @object.inspect.to_s + ("%1.6f" % Time.now.to_f)).to_s while (sessionid == nil or @sessions.include?(sessionid))
+ session = RWDSession.new(sessionid)
+
+ if auth.nil?
+ session["object"] = @object
+ else
+ session["object"] = @object.clone
+ end
+
+ if oldsessionid.nil? or oldsessionid.empty?
+ if not auth.nil? and not auth.empty? and not session.authenticated and pad != "/rwd_pixel.gif"
+
+ # Check authentication
+
+ us = vars["rwd_a"]
+ pa = vars["rwd_b"]
+
+ if us.nil? or pa.nil? or auths[us] != pa
+ session = RWDSession.new
+ session["object"] = RWDLogin.new(realm)
+ pad = "/"
+ else
+ session.authenticated = true
+ @sessions[session.sessionid] = session
+ end
+ else
+ session.authenticated = true
+ @sessions[session.sessionid] = session
+ end
+ else
+ session = RWDSession.new
+ session["object"] = RWDTimeOut.new
+ end
+
+ vars = {}
+ end
+
+ # Avoid timeout.
+
+ session.touch
+
+ if pad == "/"
+
+ # Serve methods/callbacks.
+
+ # Build new page.
+
+ download = ""
+ downloadfile = ""
+ res = ""
+
+ done = session.render(res, pad, vars, download, downloadfile, req.pda?)
+
+ begin
+ if download.empty?
+ resp["Content-Type"] = "text/html"
+ if done
+ resp.cookies["sessionid"] = ""
+ else
+ resp.cookies["sessionid"] = session.sessionid
+ end
+
+ resp << res
+ else
+ resp["Content-Type"] = "application/octet-stream"
+ resp["Content-Disposition"] = "attachment;"
+ resp["Content-Disposition"] = "attachment; filename=%s" % downloadfile unless downloadfile.empty?
+
+ resp << download
+ end
+ rescue
+ puts "Sending response to browser failed."
+
+ @sessions.delete(session.sessionid)
+ end
+
+ # Eventually delete this session.
+
+ if done
+ @sessions.delete(session.sessionid)
+
+ if @localbrowsing
+ resp.stop
+
+ if @browserstarted and not @browserthread.nil? and @browserthread.alive?
+ resp.stop do
+ puts "Waiting for the browser to terminate..."
+
+ @browserthread.join
+ end
+ end
+ end
+ end
+
+ else
+
+ # Serve files.
+
+ if pad == "/rwd_pixel.gif"
+ resp["Cache-Control"] = "max-age=86400"
+ resp["Content-Type"] = "image/gif"
+ resp << $rwd_pixel
+ else
+ if session.authenticated
+ pwd = Dir.pwd
+ file = File.expand_path(pad.gsub(/^\/*/, ""), $rwd_files)
+
+ if not file.index(pwd) == 0
+ resp["Content-Type"] = "text/html"
+ resp.response = "HTTP/1.0 400 BAD REQUEST"
+ resp << "<html><body><p><b>Bad Request.</b> (<tt>#{pad}</tt>)</p></body></html>"
+ elsif File.file?(file)
+ resp << File.new(file, "rb").read rescue nil
+ else
+ resp["Content-Type"] = "text/html"
+ resp.response = "HTTP/1.0 404 NOT FOUND"
+ resp << "<html><body><p><b>Not found.</b> (<tt>#{pad}</tt>)</p></body></html>"
+ end
+ else
+ resp["Content-Type"] = "text/html"
+ resp.response = "HTTP/1.0 ??? NOT AUTHORIZED"
+ resp << "<html><body><p><b>Not Authorized.</b></p></body></html>"
+ end
+ end
+
+ end
+
+ end
+ end
+ end
+end
+
+$rwd_html["DEFAULT"] = "
+<!-- Generated by RubyWebDialog. -->
+<!-- For more information, please contact Erik Veenstra <rwd@erikveen.dds.nl>. -->
+<html>
+ <head>
+ <title>%TITLE%</title>
+
+ <meta http-equiv='Content-Type' content='text/html; charset=%CHARSET%'>
+ <meta http-equiv='Content-Style-Type' content='text/css'>
+ <meta http-equiv='Refresh' content='%REFRESH%, javascript:document.bodyform.submit();'>
+
+ <link rel='shortcut icon' href='%LOGO%'>
+
+ <style type='text/css'>
+ <!--
+
+ a {
+ text-decoration : none;
+ }
+
+ a:hover {
+ background : #AAAAAA;
+ }
+
+ td.panel1 {
+ border-color : #888888 #EEEEEE #EEEEEE #888888;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel2 {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel1high {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel2high {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : none none none none;
+ }
+
+ td.panel1low {
+ border-color : #888888 #EEEEEE #EEEEEE #888888;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel2low {
+ border-color : #888888 #EEEEEE #EEEEEE #888888;
+ border-width : 1pt;
+ border-style : none none none none;
+ }
+
+ td.tabblad {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : none solid solid solid;
+ }
+
+ td.passivetab {
+ background-color : #BBBBBB;
+ border-color : #DDDDDD #DDDDDD #EEEEEE #DDDDDD;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.activetab {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : solid solid none solid;
+ }
+
+ td.notab {
+ border-color : #EEEEEE #EEEEEE #EEEEEE #EEEEEE;
+ border-width : 1pt;
+ border-style : none none solid none;
+ }
+
+ //-->
+ </style>
+
+ <script type='text/javascript'>
+ <!--
+ function BodyGo() {
+ $RWD_FOCUS$
+ }
+ //-->
+ </script>
+ </head>
+
+ <body bgcolor='white' onload='BodyGo()' link='#000000' vlink='#000000' alink='#000000'>
+ <form name='bodyform' action='/' method='post'>
+ <table align='center' border='0' cellspacing='0' cellpadding='0' width='100%' height='100%'>
+ <tr align='center' valign='middle'>
+ <td align='center'>
+
+ <table align='center' border='0' cellspacing='0' cellpadding='0'>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+
+ <td align='center'>
+
+ <table align='center' border='0' cellspacing='0' cellpadding='0' %WIDTH1%>
+ <tr align='center'>
+ <td align='center' bgcolor='#444488'>
+
+ <table align='left' border='0' cellspacing='1' cellpadding='0'>
+ <tr align='center'>
+ <td align='border'><img src='%LOGO%' width='14' height='14'></td>
+ <td align='center'><b><small><font color='#FFFFFF'> %TITLE% </font></small></b></td>
+ </tr>
+ </table>
+
+ <table align='right' border='0' cellspacing='1' cellpadding='0'>
+ <tr align='center'>
+ <!-- %HELPBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_help\";document.bodyform.submit();'> ? </a></small></b></td>
+ <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_main\";document.bodyform.submit();'> << </a></small></b></td>
+ <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_back\";document.bodyform.submit();'> < </a></small></b></td>
+ <!-- %CLOSEBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_quit\";document.bodyform.submit();'> X </a></small></b></td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='%WIDTH2%'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='#CCCCCC'>
+ <table align='center' border='0' cellspacing='3' cellpadding='0'>
+ %BODY%
+ </table>
+
+ <input name='rwd_action' value='$RWD_FIRSTACTION$' type='hidden'>
+ <input name='rwd_session' value='$RWD_SESSION$' type='hidden'>
+ </td>
+ </tr>
+ </table>
+
+ </td>
+
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='#EEEEEE'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='black'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='1'></td>
+ </tr>
+
+ </table>
+
+ </td>
+ </tr>
+ </table>
+ </form>
+ </body>
+</html>
+"
+
+$rwd_html["WINDOWSLOOKALIKE"] = "
+<!-- Generated by RubyWebDialog. -->
+<!-- For more information, please contact Erik Veenstra <rwd@erikveen.dds.nl>. -->
+<html>
+ <head>
+ <title>%TITLE%</title>
+
+ <meta http-equiv='Content-Type' content='text/html; charset=%CHARSET%'>
+ <meta http-equiv='Content-Style-Type' content='text/css'>
+ <meta http-equiv='Refresh' content='%REFRESH%, javascript:document.bodyform.submit();'>
+
+ <link rel='shortcut icon' href='%LOGO%'>
+
+ <style type='text/css'>
+ <!--
+
+ a {
+ text-decoration : none;
+ }
+
+ a:hover {
+ background : #AAAAAA;
+ }
+
+ td.window {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 3pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel1 {
+ border-color : #888888 #EEEEEE #EEEEEE #888888;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel2 {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel1high {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel2high {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : none none none none;
+ }
+
+ td.panel1low {
+ border-color : #888888 #EEEEEE #EEEEEE #888888;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.panel2low {
+ border-color : #888888 #EEEEEE #EEEEEE #888888;
+ border-width : 1pt;
+ border-style : none none none none;
+ }
+
+ td.tabblad {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : none solid solid solid;
+ }
+
+ td.passivetab {
+ background-color : #BBBBBB;
+ border-color : #DDDDDD #DDDDDD #EEEEEE #DDDDDD;
+ border-width : 1pt;
+ border-style : solid solid solid solid;
+ }
+
+ td.activetab {
+ border-color : #EEEEEE #888888 #888888 #EEEEEE;
+ border-width : 1pt;
+ border-style : solid solid none solid;
+ }
+
+ td.notab {
+ border-color : #EEEEEE #EEEEEE #EEEEEE #EEEEEE;
+ border-width : 1pt;
+ border-style : none none solid none;
+ }
+
+ //-->
+ </style>
+
+ <script type='text/javascript'>
+ <!--
+ function BodyGo() {
+ $RWD_FOCUS$
+ }
+ //-->
+ </script>
+ </head>
+
+ <body bgcolor='white' onload='BodyGo()' link='#000000' vlink='#000000' alink='#000000'>
+ <form name='bodyform' action='/' method='post'>
+ <table align='center' border='0' cellspacing='0' cellpadding='0' width='100%' height='100%'>
+ <tr align='center' valign='middle'>
+ <td align='center'>
+
+ <table align='center' border='0' cellspacing='0' cellpadding='0'>
+
+ <tr align='center'>
+ <td align='center' class='window'>
+
+ <table align='center' border='0' cellspacing='0' cellpadding='0' %WIDTH1%>
+ <tr align='center'>
+ <td align='center' bgcolor='#444488'>
+
+ <table align='left' border='0' cellspacing='1' cellpadding='0'>
+ <tr align='center'>
+ <td align='border'><img src='%LOGO%' width='14' height='14'></td>
+ <td align='center'><b><small><font color='#FFFFFF'> %TITLE% </font></small></b></td>
+ </tr>
+ </table>
+
+ <table align='right' border='0' cellspacing='1' cellpadding='0'>
+ <tr align='center'>
+ <!-- %HELPBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_help\";document.bodyform.submit();'> ? </a></small></b></td>
+ <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_main\";document.bodyform.submit();'> << </a></small></b></td>
+ <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_back\";document.bodyform.submit();'> < </a></small></b></td>
+ <!-- %CLOSEBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_quit\";document.bodyform.submit();'> X </a></small></b></td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='white'><img src='rwd_pixel.gif' height='1' width='%WIDTH2%'></td>
+ </tr>
+
+ <tr align='center'>
+ <td align='center' bgcolor='#CCCCCC'>
+ <table align='center' border='0' cellspacing='3' cellpadding='0'>
+ %BODY%
+ </table>
+
+ <input name='rwd_action' value='$RWD_FIRSTACTION$' type='hidden'>
+ <input name='rwd_session' value='$RWD_SESSION$' type='hidden'>
+ </td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+ </table>
+
+ </td>
+ </tr>
+ </table>
+ </form>
+ </body>
+</html>
+"
+
+$rwd_html["PDA"] = "
+<!-- Generated by RubyWebDialog. -->
+<!-- For more information, please contact Erik Veenstra <rwd@erikveen.dds.nl>. -->
+<html>
+ <head>
+ <title>%TITLE%</title>
+
+ <meta http-equiv='Content-Type' content='text/html; charset=%CHARSET%'>
+ <meta http-equiv='Refresh' content='%REFRESH%, javascript:document.bodyform.submit();'>
+
+ <link rel='shortcut icon' href='%LOGO%'>
+
+ <script type='text/javascript'>
+ <!--
+ function BodyGo() {
+ $RWD_FOCUS$
+ }
+ //-->
+ </script>
+ </head>
+
+ <body bgcolor='white' onload='BodyGo()' link='#000000' vlink='#000000' alink='#000000'>
+ <form name='bodyform' action='/' method='post'>
+ <table align='center' border='0' cellspacing='0' cellpadding='0' width='100%' height='100%'>
+
+ <tr align='center'>
+ <td align='center' bgcolor='#444488'>
+
+ <table align='left' border='0' cellspacing='1' cellpadding='0'>
+ <tr align='center'>
+ <td align='border'><img src='%LOGO%' width='14' height='14'></td>
+ <td align='center'><b><small><font color='#FFFFFF'> %TITLE% </font></small></b></td>
+ </tr>
+ </table>
+
+ <table align='right' border='0' cellspacing='1' cellpadding='0'>
+ <tr align='center'>
+ <!-- %HELPBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_help\";document.bodyform.submit();'> ? </a></small></b></td>
+ <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_main\";document.bodyform.submit();'> << </a></small></b></td>
+ <!-- %BACKBUTTONS% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_back\";document.bodyform.submit();'> < </a></small></b></td>
+ <!-- %CLOSEBUTTON% --><td align='center' bgcolor='#EEEEEE'><b><small><a href='javascript:document.bodyform.rwd_action.value=\"rwd_quit\";document.bodyform.submit();'> X </a></small></b></td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+ <!--
+ <tr align='center'>
+ <td align='center' bgcolor='#FFFFFF'> </td>
+ </tr>
+ -->
+
+ <tr align='center'>
+ <td align='center' bgcolor='#FFFFFF'>
+
+ <table align='center' border='0' cellspacing='0' cellpadding='0'>
+ %BODY%
+ </table>
+
+ <input name='rwd_action' value='$RWD_FIRSTACTION$' type='hidden'>
+ <input name='rwd_session' value='$RWD_SESSION$' type='hidden'>
+ </td>
+ </tr>
+
+ </table>
+ </form>
+ </body>
+</html>
+"
+
+$rwd_pixel = "
+R0lGODlhAQABAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoK
+CgsLCwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZ
+GRoaGhsbGxwcHB0dHR4eHh8fHyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygo
+KCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDExMTIyMjMzMzQ0NDU1NTY2Njc3
+Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkNDQ0REREVFRUZG
+RkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV
+VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2Rk
+ZGVlZWZmZmdnZ2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNz
+c3R0dHV1dXZ2dnd3d3h4eHl5eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKC
+goODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouLi4yMjI2NjY6Ojo+Pj5CQkJGR
+kZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2dnZ6enp+fn6Cg
+oKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v
+r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+
+vr+/v8DAwMHBwcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3N
+zc7Ozs/Pz9DQ0NHR0dLS0tPT09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc
+3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6uvr
+6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf39/j4+Pn5+fr6
++vv7+/z8/P39/f7+/v///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQB
+CgD/ACwAAAAAAQABAAAIBAD/BQQAOw==
+".unpack("m").shift
+
+$rwd_html_1, $rwd_html_2 = $rwd_html[ENV["RWDTHEME"]].split(/^\s*%BODY%\s*\r*$/)
+$rwd_html_PDA_1, $rwd_html_PDA_2 = $rwd_html["PDA"].split(/^\s*%BODY%\s*\r*$/)