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'>&nbsp;</td>" - tabs.each do |obj| - name = obj.args["name"] - caption = obj.args["caption"] - - res << "<td #{AL} class='notab'>&nbsp;</td>" unless obj == tabs[0] - - if name == tab - res << "<td #{AC} class='activetab'><tt>&nbsp;#{caption}&nbsp;</tt></td>" - else - res << "<td #{AC} class='passivetab'><a href='javascript:document.bodyform.rwd_action.value=\"rwd_tab_#{name}\";document.bodyform.submit();'><tt>&nbsp;#{caption}&nbsp;</tt></a></td>" - end - end - res << " <td class='notab' width='100%'>&nbsp;</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 << "&lt;#{@subtype}&gt;" - 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>&nbsp;</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>&nbsp;</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 << "&lt;/#{@subtype}&gt;" - 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'>&nbsp;%TITLE%&nbsp;</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();'>&nbsp;?&nbsp;</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();'>&nbsp;&lt;&lt;&nbsp;</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();'>&nbsp;&lt;&nbsp;</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();'>&nbsp;X&nbsp;</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'>&nbsp;%TITLE%&nbsp;</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();'>&nbsp;?&nbsp;</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();'>&nbsp;&lt;&lt;&nbsp;</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();'>&nbsp;&lt;&nbsp;</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();'>&nbsp;X&nbsp;</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'>&nbsp;%TITLE%&nbsp;</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();'>&nbsp;?&nbsp;</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();'>&nbsp;&lt;&lt;&nbsp;</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();'>&nbsp;&lt;&nbsp;</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();'>&nbsp;X&nbsp;</a></small></b></td> - </tr> - </table> - - </td> - </tr> - - <!-- - <tr align='center'> - <td align='center' bgcolor='#FFFFFF'>&nbsp;</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'>&nbsp;</td>" + tabs.each do |obj| + name = obj.args["name"] + caption = obj.args["caption"] + + res << "<td #{AL} class='notab'>&nbsp;</td>" unless obj == tabs[0] + + if name == tab + res << "<td #{AC} class='activetab'><tt>&nbsp;#{caption}&nbsp;</tt></td>" + else + res << "<td #{AC} class='passivetab'><a href='javascript:document.bodyform.rwd_action.value=\"rwd_tab_#{name}\";document.bodyform.submit();'><tt>&nbsp;#{caption}&nbsp;</tt></a></td>" + end + end + res << " <td class='notab' width='100%'>&nbsp;</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 << "&lt;#{@subtype}&gt;" + 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>&nbsp;</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>&nbsp;</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 << "&lt;/#{@subtype}&gt;" + 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'>&nbsp;%TITLE%&nbsp;</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();'>&nbsp;?&nbsp;</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();'>&nbsp;&lt;&lt;&nbsp;</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();'>&nbsp;&lt;&nbsp;</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();'>&nbsp;X&nbsp;</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'>&nbsp;%TITLE%&nbsp;</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();'>&nbsp;?&nbsp;</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();'>&nbsp;&lt;&lt;&nbsp;</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();'>&nbsp;&lt;&nbsp;</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();'>&nbsp;X&nbsp;</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'>&nbsp;%TITLE%&nbsp;</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();'>&nbsp;?&nbsp;</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();'>&nbsp;&lt;&lt;&nbsp;</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();'>&nbsp;&lt;&nbsp;</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();'>&nbsp;X&nbsp;</a></small></b></td> + </tr> + </table> + + </td> + </tr> + + <!-- + <tr align='center'> + <td align='center' bgcolor='#FFFFFF'>&nbsp;</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*$/)