diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/LICENSE rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/LICENSE
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/LICENSE	2004-08-21 10:56:06.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/LICENSE	2004-07-26 16:14:10.000000000 +0200
@@ -0,0 +1,15 @@
+# Copyright Erik Veenstra <rubywebdialogs@erikveen.dds.nl>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public
+# License along with this program; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA.
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/README rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/README
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/README	2004-08-21 10:56:06.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/README	2004-07-26 16:16:13.000000000 +0200
@@ -0,0 +1,4 @@
+ Usage: ruby install.rb
+
+For more information, see
+http://www.erikveen.dds.nl/rubywebdialogs/ .
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/init.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/init.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/init.rb	2004-05-15 11:16:23.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/init.rb	2004-08-21 10:56:03.000000000 +0200
@@ -1,9 +1,19 @@
 require "rbconfig"
 
+def mkdirrec(dir)
+  pdir	= File.dirname(dir)
+
+  if not pdir.empty? and not File.directory?(pdir)
+    mkdirrec (pdir)
+  end
+
+  Dir.mkdir(dir)	rescue nil
+end
+
 FromDirs	= [".", "./lib", "./rubylib/lib"]
 ToDir		= Config::CONFIG["sitelibdir"] + "/ev"
 
-Dir.mkdir(ToDir)	if not File.directory?(ToDir)
+mkdirrec(ToDir)	if not File.directory?(ToDir)
 
 FromDirs.each do |fromdir|
   fromdir	= Dir.pwd	if fromdir == "."
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/install.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/install.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/install.rb	2004-05-15 11:16:23.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/install.rb	2004-08-21 10:56:03.000000000 +0200
@@ -1,9 +1,19 @@
 require "rbconfig"
 
+def mkdirrec(dir)
+  pdir	= File.dirname(dir)
+
+  if not pdir.empty? and not File.directory?(pdir)
+    mkdirrec (pdir)
+  end
+
+  Dir.mkdir(dir)	rescue nil
+end
+
 FromDirs	= [".", "./lib", "./rubylib/lib"]
 ToDir		= Config::CONFIG["sitelibdir"] + "/ev"
 
-Dir.mkdir(ToDir)	if not File.directory?(ToDir)
+mkdirrec(ToDir)	if not File.directory?(ToDir)
 
 FromDirs.each do |fromdir|
   fromdir	= Dir.pwd	if fromdir == "."
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/ftools.lib.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/ftools.lib.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/ftools.lib.rb	2004-08-21 10:56:06.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/ftools.lib.rb	2004-08-21 10:56:03.000000000 +0200
@@ -0,0 +1,161 @@
+require "ftools"
+
+class Dir
+  def self.mkdirrec(dir)
+    pdir	= File.dirname(dir)
+
+    if not pdir.empty? and not File.directory?(pdir)
+      Dir.mkdirrec(pdir)
+    end
+
+    Dir.mkdir(dir)	rescue nil
+  end
+
+  def self.copy(from, to)
+    if File.directory?(from)
+      pdir	= Dir.pwd
+      todir	= File.expand_path(to)
+
+      mkdirrec(todir)
+
+      Dir.chdir(from)
+        Dir.new(".").each do |e|
+          Dir.copy(e, todir+"/"+e)	if not [".", ".."].include?(e)
+        end
+      Dir.chdir(pdir)
+    else
+      todir	= File.dirname(File.expand_path(to))
+
+      mkdirrec(todir)
+
+      File.copy(from, to)
+    end
+  end
+
+  def self.move(from, to)
+    Dir.copy(from, to)
+    Dir.rm_rf(from)
+  end
+
+  def self.rm_rf(entry)
+    if File.ftype(entry) == "directory"
+      pdir	= Dir.pwd
+
+      Dir.chdir(entry)
+        Dir.new(".").each do |e|
+          Dir.rm_rf(e)	if not [".", ".."].include?(e)
+        end
+      Dir.chdir(pdir)
+
+      Dir.delete(entry)
+    else
+      File.delete(entry)
+    end
+  end
+
+  def self.find(entry=nil, mask=nil)
+    entry	= @dir	if entry.nil?
+
+    entry.gsub!(/[\/\\]*$/, "")	unless entry.nil?
+
+    res	= []
+
+    if File.directory?(entry)
+      pdir	= Dir.pwd
+
+      res += ["%s/" % entry]	if mask.nil? or entry =~ mask
+
+      Dir.chdir(entry)
+        Dir.new(".").each do |e|
+          res += Dir.find(e, mask).collect{|e| entry+"/"+e}	unless [".", ".."].include?(e)
+        end
+      Dir.chdir(pdir)
+    else
+      res += [entry]	if mask.nil? or entry =~ mask
+    end
+
+    res
+  end
+end
+
+class File
+  def self.rollbackup(file, mode=nil)
+    backupfile	= file + ".RB.BACKUP"
+    controlfile	= file + ".RB.CONTROL"
+
+    File.touch(file)    unless File.file?(file)
+
+	# Rollback
+
+    if File.file?(backupfile) and File.file?(controlfile)
+      $stdout.puts "Restoring #{file}..."
+
+      File.copy(backupfile, file)				# Rollback from phase 3
+    end
+
+	# Reset
+
+    File.delete(backupfile)	if File.file?(backupfile)	# Reset from phase 2 or 3
+    File.delete(controlfile)	if File.file?(controlfile)	# Reset from phase 3 or 4
+
+	# Backup
+
+    File.copy(file, backupfile)					# Enter phase 2
+    File.touch(controlfile)					# Enter phase 3
+
+	# The real thing
+
+    if block_given?
+      if mode.nil?
+        yield
+      else
+        File.open(file, mode) do |f|
+          yield(f)
+        end
+      end
+    end
+
+	# Cleanup
+
+    File.delete(backupfile)					# Enter phase 4
+    File.delete(controlfile)					# Enter phase 5
+
+	# Return, like File.open
+
+    if block_given?
+      return nil
+    else
+      return File.open(file, (mode or "r"))
+    end
+  end
+
+  def self.touch(file)
+    File.open(file, "a"){|f|}
+  end
+
+  def self.which(file)
+    res	= nil
+
+    if windows?
+      file	= file.gsub(/\.exe$/i, "") + ".exe"
+      sep		= ";"
+    else
+      sep		= ":"
+    end
+
+    catch :stop do
+      ENV["PATH"].split(/#{sep}/).reverse.each do |d|
+        if File.directory?(d)
+          Dir.new(d).each do |e|
+             if e.downcase == file.downcase
+               res	= File.expand_path(e, d)
+               throw :stop
+            end
+          end
+        end
+      end
+    end
+
+    res
+  end
+end
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/net.lib.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/net.lib.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/net.lib.rb	2004-05-15 11:16:23.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/net.lib.rb	2004-08-21 10:56:03.000000000 +0200
@@ -1,4 +1,5 @@
 require "ev/ruby"
+require "ev/ftools"
 #alias old_timeout :timeout
 require "net/http"
 #alias timeout :old_timeout
@@ -26,16 +27,68 @@
 end
 
 class TCPServer
-  def self.freeport(from, to)
+  def self.freeport(from, to, remote=false)
+    if windows?
+      TCPServer.freeport_windows(from, to, remote)
+    else
+      TCPServer.freeport_linux(from, to, remote)
+    end
+  end
+
+  def self.freeport_linux(from, to, remote)
+    ports	= (from..to).to_a
+    port	= nil
+    res		= nil
+
+    while res.nil? and not ports.empty?
+      begin
+        port	= ports[0]
+        ports.delete(port)
+
+        io	= TCPServer.new(remote ? "0.0.0.0" : "localhost", port)
+
+        res	= [port, io]
+      rescue
+      end
+    end
+
+    res	= [nil, nil]	if res.nil?
+
+    port, io	= res
+
+    return port, io
+  end
+
+  def self.freeport_windows(from, to, remote)
+    ports	= (from..to).to_a
+    port	= nil
+    res		= nil
+
+    while res.nil? and not ports.empty?
+      begin
+        port	= ports.any
+        ports.delete(port)
+
+        io	= TCPSocket.new("localhost", port)
+        io.close
+      rescue
+        res	= port
+      end
+    end
+
+    port, io	= res
+
+    return port, io
+  end
+
+  def self.freeport_windows2(from, to, remote)
     res	= nil
     port	= from
 
     while res.nil? and port <= to
       begin
-        #evtimeout(0.1) do
-          io	= TCPSocket.new("localhost", port)
-          io.close
-        #end
+        io	= TCPSocket.new("localhost", port)
+        io.close
 
         port += 1
       rescue
@@ -134,7 +187,7 @@
     vars	= nil	if @vars.empty?
     anchor	= nil	if @anchor.empty?
 
-    res	= URI::HTTP.new(@protocol, @userpass, @host, port, nil, @path, nil, vars, @anchor).to_s
+    res	= URI::HTTP.new(@protocol, @userpass, @host, port, nil, @path, nil, vars, @anchor).to_s.from_html
 
     res.gsub!(/@/, "")	if (@userpass.nil? or @userpass.empty?)
 
@@ -181,6 +234,8 @@
 
         @protocol, @code, @text	= firstline.split(/  */, 3)
 
+        @code	= @code.to_i
+
         if not rest.nil?
           rest.split(/\r*\n/).each do |line|
             key, value	= line.split(/ /, 2)
@@ -274,11 +329,11 @@
   end
 
   def self.get(uri, form={})
-    res	= Array.new
+    post	= Array.new
     form.each_pair do |var, value|
-      res << "#{var.to_html}=#{value.to_html}"
+      post << "#{var.to_html}=#{value.to_html}"
     end
-    post	= res.join("?")
+    post	= post.join("?")
 
     data	= nil
 
@@ -296,10 +351,17 @@
           end
 
           if post.empty?
-            io.write("GET #{uri.path or ´/´}#{uri.varstring.empty? ? ´´ : ´?´ + uri.varstring} HTTP/1.0\r\nHost: #{host}\r\n\r\n")
+            io.write "GET %s%s HTTP/1.0\r\n" % [(uri.path or ´/´), (uri.varstring.empty? ? ´´ : ´?´ + uri.varstring)]
+            io.write "Host: %s\r\n" % host
+            io.write "\r\n"
           else
-            io.write("POST #{uri.path or ´/´}#{uri.varstring.empty? ? ´´ : ´?´ + uri.varstring} HTTP/1.0\r\nHost: #{host}\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: #{post.length}\r\n\r\n")
-            io.write(post)
+            io.write "POST %s%s HTTP/1.0\r\n" % [(uri.path or ´/´), (uri.varstring.empty? ? ´´ : ´?´ + uri.varstring)]
+            io.write "Host: %s\r\n" % host
+            io.write "Content-Type: application/x-www-form-urlencoded\r\n"
+            io.write "Content-Length: %s\r\n" % post.length
+            io.write "Pragma: \r\n"
+            io.write "\r\n"
+            io.write post
           end
         else
           proxy	= EVURI.new($proxy)
@@ -310,10 +372,19 @@
           io	= TCPSocket.new(host, port.zero? ? 8080 : port)
 
           if post.empty?
-            io.write("GET #{uri} HTTP/1.0\r\n#{"Proxy-Authorization: Basic "+$proxy_auth+"\r\n" if not $proxy_auth.nil?}\r\n\r\n")
+            io.write "GET %s HTTP/1.0\r\n" % uri
+            io.write "Host: %s\r\n" % host
+            io.write "Proxy-Authorization: Basic %s\r\n" % $proxy_auth unless $proxy_auth.nil?
+            io.write "\r\n"
           else
-            io.write("POST #{uri} HTTP/1.0\r\n#{"Proxy-Authorization: Basic "+$proxy_auth+"\r\n" if not $proxy_auth.nil?}Content-Type: application/x-www-form-urlencoded\r\nContent-Length: #{post.length}\r\n\r\n")
-            io.write(post)
+            io.write "POST %s HTTP/1.0\r\n" % uri
+            io.write "Host: %s\r\n" % host
+            io.write "Proxy-Authorization: Basic %s\r\n" % $proxy_auth unless $proxy_auth.nil?
+            io.write "Content-Type: application/x-www-form-urlencoded\r\n"
+            io.write "Content-Length: %s\r\n" % post.length
+            io.write "Pragma: \r\n"
+            io.write "\r\n"
+            io.write post
           end
         end
 
@@ -334,6 +405,8 @@
         if header.header["transfer-encoding"] == "chunked"
           data	= Chunk.new(data).to_s	if not data.nil?
         end
+
+        data	= nil	unless header.code == 200
       end
     rescue
       data	= nil
@@ -362,7 +435,7 @@
 
     expire	= 356*24*60*60
 
-    if FileTest.file?(file) and (Time.new.to_f - File.stat(file).mtime.to_f < expire)
+    if File.file?(file) and (Time.new.to_f - File.stat(file).mtime.to_f < expire)
       @@mutex.synchronize do
         File.open(file, "rb")	{|f| data = f.read}
       end
@@ -418,6 +491,10 @@
   def to_s
     "#{@method} #{@uri} #{@protocol}\r\n"
   end
+
+  def inspect
+    "(RequestRequest: %s)" % [@method, @path, @data, @protocol].join(", ")
+  end
 end
 
 class Request < Hash
@@ -435,12 +512,14 @@
 
     @request	= RequestRequest.new(firstline.strip)
 
-    line	= @io.gets.strip
-    while not line.empty? do
+    line	= @io.gets
+    line	= line.strip	unless line.nil?
+    while not line.nil? and not line.empty?
       key, value	= line.split(" ", 2)
       self[key.sub(/:$/, "").downcase]	= value
 
-      line	= @io.gets.strip
+      line	= @io.gets
+      line	= line.strip	unless line.nil?
     end
 
     cookie	= self["cookie"]
@@ -452,12 +531,12 @@
     end
 
     if not @request.method.nil?
-      case @request.method
+      case @request.method.upcase
       when "HEAD"
       when "GET"
         @vars	= RequestGet.new(@request.data.nil? ? "" : @request.data)
       when "POST"
-        data	= @io.read(self["content-length"].to_i)
+        data	= (@io.read(self["content-length"].to_i) or "")
         @vars	= RequestPost.new((self["content-type"] == "application/x-www-form-urlencoded") ? data : "")
       else
         puts "Unknown request (´#{firstline}´)."
@@ -476,14 +555,20 @@
     end
     res
   end
+
+  def inspect
+    "(Request: %s)" % [@peeraddr, @request.inspect, @vars.inspect, @cookies.inspect, super].join(", ")
+  end
 end
 
 class Response < Hash
   attr_writer :response
+  attr_reader :cookies
 
   def initialize(io)
     @io		= io
     @response	= "HTTP/1.0 200 OK"
+    @cookies	= {}
     @data	= ""
   end
 
@@ -497,23 +582,36 @@
     self.each do |k, v|
       res << "#{k}: #{v}\r\n"
     end
+
+    @cookies.each do |k, v|
+      res << "Set-Cookie: %s=%s;\r\n" % [k, v]
+    end
+
     res
   end
 
   def << (s)
     @data << s
   end
+
+  def inspect
+    "(Response: %s)" % [@response, @data].join(", ")
+  end
 end
 
 class HTTPServer
   @@times	= {}
 
-  def self.serve(port=80, remote=false, auth=nil, realm="ev/net")
+  def self.serve(portio=80, remote=false, auth=nil, realm="ev/net")
+    port, server	= portio
+
     begin
-      server	= TCPServer.new(remote ? "0.0.0.0" : "localhost", port)
+      server	= TCPServer.new(remote ? "0.0.0.0" : "localhost", port)	if server.nil?
+
       puts "Just point your browser to http://localhost:#{port}/ ..."
     rescue
       server	= nil
+
       puts "Port #{port} is in use."
     end
 
@@ -562,7 +660,7 @@
     if auth.kind_of? String
       file	= "#{home}/#{auth}"
       auths	= {}
-      auths	= Hash.file(file)	if FileTest.file?(file)
+      auths	= Hash.file(file)	if File.file?(file)
     else
       auths	= auth
     end
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/ruby.lib.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/ruby.lib.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/ruby.lib.rb	2004-05-15 11:16:23.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/ruby.lib.rb	2004-08-21 10:56:03.000000000 +0200
@@ -1,7 +1,26 @@
 require "cgi"
 require "rbconfig"
 
-Thread.abort_on_exception	= true
+#tekens	= ´\w\~\@\#\$\%\^\&\*\-\+´
+tekens		= ´^\s\r\n\`\!\(\)\[\]\{\}\<\>\,\.\/\?\\\|\=\;\:\"´
+
+#tekens11	= ´\w´
+tekens11	= tekens + "´"
+
+tekens21	= tekens + "´"
+tekens22	= tekens
+tekens23	= tekens + "´"
+
+tekens31	= ´\w\s\r\n´
+
+RegExpStringWord	= "([#{tekens11}]+)"									; RegExpWord	= Regexp.new(RegExpStringWord)
+RegExpStringWord2	= "([#{tekens21}]([#{tekens22}]*[#{tekens23}])?)"					; RegExpWord2	= Regexp.new(RegExpStringWord2)
+RegExpStringText	= "([#{tekens31}]+)"									; RegExpText	= Regexp.new(RegExpStringText)
+RegExpStringFile	= ´(\w[\w\.\-]*)´									; RegExpFile	= Regexp.new(RegExpStringFile)
+RegExpStringEmail	= ´([\w\-\.]+@[\w\-\.]+)´								; RegExpEmail	= Regexp.new(RegExpStringEmail)
+RegExpStringURL		= ´(\w+:\/\/[\w\.\-]+(:\d*)?\/[\w\.\-\/\#\?\=\%]*)´					; RegExpURL	= Regexp.new(RegExpStringURL)
+RegExpStringPrint	= ´([\w \t\r\n\`\~\!\@\#\$\%\^\&\*\(\)\-\+\=\[\]\{\}\;\:\´\"\,\.\/\<\>\?\\\|]+)´	; RegExpPrint	= Regexp.new(RegExpStringPrint)
+RegExpStringDiff	= ´(^[\-\+]([^\-\+].*)?)´								; RegExpDiff	= Regexp.new(RegExpStringDiff)
 
 module Enumerable
   def deep_dup
@@ -13,6 +32,16 @@
   end
 end
 
+class Thread
+  def self.background(*args)
+    new(*args) do |*args|
+      Thread.pass
+
+      yield(*args)
+    end
+  end
+end
+
 class Object
   alias deep_dup :dup
   alias deep_clone :clone
@@ -20,6 +49,10 @@
   def to_fs
     to_s
   end
+
+  def ids
+    id
+  end
 end
 
 class Numeric
@@ -28,6 +61,21 @@
   end
 end
 
+class Integer
+  def oct
+    n	= self
+    res	= []
+
+    while n > 8
+      n, x	= n.divmod(8)
+      res << x
+    end
+    res << n
+
+    res.reverse.join("")
+  end
+end
+
 class String
   def chomp!(dummy=nil)
     self.gsub!(/[\r\n]*\z/, "")
@@ -65,6 +113,13 @@
     self.gsub(/[[:blank:]]+/, " ")
   end
 
+  def compressperline
+    res	= self.split(/\n/)
+    res.collect!{|line| line.compress}
+    res.delete_if{|line| line.empty?}
+    res.join("\n")
+  end
+
   def numeric?
     d, a, n	= [self].to_par
 
@@ -75,7 +130,7 @@
     res	= []
 
     IO.popen(self, "w+") do |f|
-      f.puts input	if not input.nil?
+      f.puts input	unless input.nil?
       f.close_write
 
       res	= f.readlines if output
@@ -100,8 +155,8 @@
     enddelimiters	= []
 
     delimiters.each do |k, v|
-      begindelimiters	<< k
-      enddelimiters	<< v
+      begindelimiters	<< k.downcase
+      enddelimiters	<< v.downcase
     end
 
     bd	= begindelimiters.collect	{|s| Regexp.escape(s)}
@@ -113,36 +168,45 @@
     res		= []
     type	= 0
     tmp		= ""
+    bs		= ""
     es		= ""
 
-    self.split(/(#{be}|#{ee})/).each do |s|
+    self.split(/(#{ee}|#{be})/i).each do |s|
       if type == 0
-        if begindelimiters.include?(s)
-          type	= begindelimiters.index(s)+1
+        if begindelimiters.include?(s.downcase)
+          i	= begindelimiters.index(s.downcase)
+          type	= i+1
           tmp	= s
-          es	= enddelimiters[begindelimiters.index(s)]
+          bs	= s.downcase
+          es	= enddelimiters[i]
         else
-          res << [0, s]	if not s.empty?
+          res << [0, s]	unless s.empty?
         end
       else
-        if s == es
+        if s.downcase == es
           res << [type, tmp + s]
           type	= 0
           tmp	= ""
+          bs	= ""
           es	= ""
         else
-          tmp 	= tmp + s
+          if s.downcase == bs
+            res << [0, tmp]
+            tmp	= s
+          else
+            tmp	= tmp + s
+          end
         end
       end
     end
 
-    res << [0, tmp]	if not tmp.empty?
+    res << [0, tmp]	unless tmp.empty?
 
     return res
   end
 
   def splitwords(tokens=[])
-    tokens	= [tokens]	if not tokens.kind_of?(Array)
+    tokens	= [tokens]	unless tokens.kind_of?(Array)
     res		= []
 
     self.splitblocks(["´", "´"], [´"´, ´"´]).each do |type, s|
@@ -167,10 +231,10 @@
   def uncomment
     res	= []
 
-    self.splitblocks(["´", "´"], [´"´, ´"´], ["/*", "*/"], ["<!--", "-->"], ["#", "\n"]).each do |type, s|
+    self.splitblocks(["´", "´"], [´"´, ´"´], ["#", "\n"]).each do |type, s|
       case type
       when 0, 1, 2	then	res << s
-      when 3, 4, 5
+      when 3
       end
     end
 
@@ -313,10 +377,12 @@
   end
 
   def subset(fields, values, results, exact=true, emptyline=nil, joinwith=nil)
-    fields	= [fields]	if not fields.kind_of? Array
-    values	= [values]	if not values.kind_of? Array
-    results	= [results]	if not results.kind_of? Array
-    res		= []
+    fields	= [fields]		unless fields.kind_of? Array
+    values	= [values]		unless values.kind_of? Array
+    results	= [results]		unless results.kind_of? Array
+    emptyline	= emptyline.downcase	unless emptyline.nil?
+    res		= self.dup
+    res.delete_if {true}
 
     self.each do |l|
       ok	= true
@@ -331,25 +397,33 @@
         correction	= 0
       end
 
-      0.upto(c.length-1) do |n|
-        if fields.include?(n+correction)
-          v	= values[fields.index(n+correction)]
-          if not emptyline.nil? and not v.downcase == emptyline.downcase
+      #catch :stop do
+        values2	= values.dup
+        fields.each do |f|
+          v	= values2.shift
+          v	= v.downcase	unless v.nil?
+          if emptyline.nil? or (not v == emptyline)
             if exact
-              ok	= false	unless (v.nil? or c[n].downcase == v.downcase)
+              unless (v.nil? or c[f-correction].downcase == v)
+                ok	= false
+                #throw :stop
+              end
             else
-              ok	= false	unless (v.nil? or c[n].downcase.include?(v.downcase))
+              unless (v.nil? or c[f-correction].downcase.include?(v))
+                ok	= false
+                #throw :stop
+              end
             end
           end
         end
-      end
+      #end
 
       if ok
         res2	= []
         results.each do |n|
           res2 << c[n-1]
         end
-        res2	= res2.join(joinwith)	if not joinwith.nil?
+        res2	= res2.join(joinwith)	unless joinwith.nil?
         res << res2
       end
     end
@@ -405,8 +479,10 @@
   def self.file(file)
     res	= []
 
-    File.new(file).readlines.uncomment.chomp.each do |line|
-      res << line
+    File.open(file) do |f|
+      f.readlines.uncomment.chomp.each do |line|
+        res << line
+      end
     end
 
     res
@@ -443,10 +519,22 @@
     res
   end
 
+  def any
+    if empty?
+      nil
+    else
+      self[rand(self.length)]
+    end
+  end
+
   def minmax
     min, value, max	= self
     [min, [value, max].min].max
   end
+
+  def ids
+    collect{|e| e.ids}
+  end
 end
 
 class Hash
@@ -455,21 +543,21 @@
     org	= Hash.file(file)	if (append and File.file?(file))
 
     self.sort.each do |k, v|
-     org[k]	= v
+      org[k]	= v
     end
 
     File.open(file, "w") do |f|
       org.sort.each do |k, v|
-        #f.puts "´%s´=´%s´" % [k, v]
-        f.puts "%s = %s" % [k, v]
+        f.puts "%s\t= %s" % [k, v]
       end
     end
   end
 
   def subset(fields, values, results=nil, exact=true, emptyline=nil, joinwith=nil)
-    fields	= [fields]	if not fields.kind_of? Array
-    values	= [values]	if not values.kind_of? Array
-    results	= [results]	if not results.kind_of? Array
+    fields	= [fields]		unless fields.kind_of? Array
+    values	= [values]		unless values.kind_of? Array
+    results	= [results]		unless results.kind_of? Array
+    emptyline	= emptyline.downcase	unless emptyline.nil?
     res		= self.dup
     res.delete_if {true}
 
@@ -486,18 +574,26 @@
         correction	= 0
       end
 
-      0.upto(c.length-1) do |n|
-        if fields.include?(n+correction)
-          v	= values[fields.index(n+correction)]
-          if emptyline.nil? or (not emptyline.nil? and not v.downcase == emptyline.downcase)
+      #catch :stop do
+        values2	= values.dup
+        fields.each do |f|
+          v	= values2.shift
+          v	= v.downcase	unless v.nil?
+          if emptyline.nil? or (not v == emptyline)
             if exact
-              ok	= false	unless (v.nil? or c[n].downcase == v.downcase)
+              unless (v.nil? or c[f-correction].downcase == v)
+                ok	= false
+                #throw :stop
+              end
             else
-              ok	= false	unless (v.nil? or c[n].downcase.include?(v.downcase))
+              unless (v.nil? or c[f-correction].downcase.include?(v))
+                ok	= false
+                #throw :stop
+              end
             end
           end
         end
-      end
+      #end
 
       if ok
         res2	= []
@@ -508,7 +604,7 @@
             res2 << c[n-correction]
           end
         end
-        res2	= res2.join(joinwith)	if not joinwith.nil?
+        res2	= res2.join(joinwith)	unless joinwith.nil?
         res[k]	= res2
       end
     end
@@ -523,37 +619,23 @@
   def self.file(file)
     res	= {}
 
-    File.new(file).readlines.chomp.each do |line|
-      if not line.compress.empty?
-        k, v	= line.split(/\s*=\s*/, 2)
-        res[k]	= v
-      end
-    end
-#    File.new(file).readlines.uncomment.chomp.each do |line|
-#      if not line.compress.empty?
-#        a	= line.splitwords("=")
-#
-#        if a.size == 3 and  a[1] == "="
-#	  res[a[0]]	= a[2]
-#        else
-#	  puts "Error in #{file} (not ´var=\"value\"´)."
-#        end
-#      end
-#    end
+    File.open(file) do |f|
+      #f.readlines.chomp.each do |line|
+      while line = f.gets do
+        line.chomp!
+
+        unless line.empty?
+          k, v	= line.split(/\s+=\s+/, 2)
+          res[k]	= v
+        end
+      end
+    end
 
     res
   end
-end
-
-class Dir
-  def Dir.mkdirrec(dir)
-    pdir	= File.dirname(dir)
 
-    if not pdir.empty? and not FileTest.directory?(pdir)
-      mkdirrec (pdir)
-    end
-
-    Dir.mkdir(dir)	rescue nil
+  def ids
+    collect{|k, v| [k, v].ids}
   end
 end
 
@@ -561,33 +643,33 @@
   ObjectSpace._id2ref(id)
 end
 
-def after(seconds)
+def after(seconds, *args)
   if not seconds.nil? and not seconds.zero?
-    Thread.new do
+    Thread.new(*args) do |*args|
       sleep seconds
-      yield
+      yield(*args)
     end
   end
 end
 
-def every(seconds)
+def every(seconds, *args)
   if not seconds.nil? and not seconds.zero?
-    Thread.new do
+    Thread.new(*args) do |*args|
       loop do
         sleep seconds
-        yield
+        yield(*args)
       end
     end
   end
 end
 
-def evtimeout(seconds)
+def evtimeout(seconds, *args)
   if not seconds.nil? and not seconds.zero?
     t		= Thread.current
     threads	= []
     res		= nil
 
-    threads[1] = Thread.new do
+    threads[1] = Thread.new(*args) do |*args|
       sleep seconds
       begin
         threads[2].kill
@@ -597,8 +679,8 @@
       t.wakeup
     end
 
-    threads[2] = Thread.new do
-      yield
+    threads[2] = Thread.new(*args) do |*args|
+      yield(*args)
       begin
         threads[1].kill
       rescue NameError
@@ -612,16 +694,16 @@
 
     return res
   else
-    yield
+    yield(*args)
   end
 end
 
-def evtimeoutretry(seconds)
+def evtimeoutretry(seconds, *args)
   ok	= false
 
   while not ok
-    evtimeout(seconds) do
-      yield
+    evtimeout(seconds, *args) do |*args|
+      yield(*args)
       ok	= true
     end
   end
@@ -634,7 +716,7 @@
 
 	# Seems pointless, but it´s for catching ^C under Windows...
 
-  every(1)	{}
+  every(1)	{}	if windows?
 end
 
 def linux?
@@ -664,3 +746,43 @@
 def temp
   (ENV["TEMP"] or "/tmp").gsub(/\\/, "/")
 end
+
+def stdtmp
+  $stderr = $stdout = File.new("#{temp}/ruby.#{Process.pid}.log", "a")	unless ARGV.include?("--rwd-exit")
+end
+
+def bm(label="")
+  if $bm.nil?
+    require "ev/bm"
+
+    $bm	= {}
+
+    at_exit do
+      format1	= "%10s %10s %10s %10s %10s %10s %10s"
+      format2	= "%10s %10.6f %10.6f %10.6f %10.6f %10.6f %10d"
+
+      $stderr.puts format1 % ["LABEL", "USERCPU", "SYSCPU", "CUSERCPU", "CSYSCPU", "ELAPSED", "TIMES"]
+      $bm.sort{|a, b| [a[1], a[0]] <=> [b[1], b[0]]}.each do |k, v|
+        $stderr.puts format2 % [k, *v]
+      end
+    end
+  end
+
+  label	= label.to_s
+  res	= nil
+
+  $bm[label] = [0.0]*5 + [0]	unless $bm.include?(label)
+
+  if block_given?
+    bm	= Benchmark.measure{res = yield}
+    bma	= bm.to_a	# [dummy label, user CPU time, system CPU time, childrens user CPU time, childrens system CPU time, elapsed real time]
+
+    0.upto(4) do |n|
+      $bm[label][n] += bma[n+1]
+    end
+  end
+
+  $bm[label][5] += 1
+
+  res
+end
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/rwd.lib.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/rwd.lib.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/rwd.lib.rb	2004-05-15 11:16:23.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/rwd.lib.rb	2004-08-21 10:56:03.000000000 +0200
@@ -8,7 +8,7 @@
   require "win32ole"
   require "win32/registry"
 rescue LoadError
-  $".push "win32ole.rb"
+  $".push "win32ole.so"
   $".push "win32/registry.rb"
 end
 
@@ -16,12 +16,17 @@
 $rwd_debug	= ($rwd_debug or false)
 $rwd_border	= ($rwd_border or 0)
 
+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 FileTest.file?(s))
-s	= ENV["USERPROFILE"]	; s = s + "/rwd.cfg"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil? and FileTest.file?(s))
-s	= ENV["windir"]		; s = s + "/rwd.cfg"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil? and FileTest.file?(s))
+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´"
@@ -41,9 +46,19 @@
 unless ENV.include?("RWDBROWSER")
   begin
     puts "Looking for default browser..."
-    Win32::Registry::HKEY_CLASSES_ROOT.open(´htmlfile\shell\open\command´) do |reg|
-      ENV["RWDBROWSER"]	= reg[""]
+
+    filetype	= nil
+    application	= nil
+
+    Win32::Registry::HKEY_CLASSES_ROOT.open(´.html´) do |reg|
+      filetype		= reg[""]
     end
+
+    Win32::Registry::HKEY_CLASSES_ROOT.open(filetype + ´\shell\open\command´) do |reg|
+      application	= reg[""]
+    end
+
+    ENV["RWDBROWSER"]	= application
   rescue NameError
     puts "Not found."
   end
@@ -234,7 +249,7 @@
 end
 
 class OpenTag
-  def prechildren(res, before, after, vars, switches, help, oneormorefields, firstaction, tabs, tab)
+  def prechildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab)
     bef	= before[-1]
     res.concat Format % ["Before", @subtype]	if ($rwd_debug and not bef.nil?)
     res.concat bef	if not bef.nil?
@@ -247,9 +262,13 @@
     valign	= VA
     valign	= "valign=´#{@args["valign"]}´"	if @args.include?("valign")
 
-    value	= ""
-    value	= vars[@args["name"]]		if vars.include?(@args["name"])
-    value	= @args["value"]		if @args.include?("value")
+    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")
 
     case @subtype
     when "application"
@@ -260,7 +279,7 @@
 
       res.concat(template($rwd_html1, args))
     when "p"		then res.concat "<p #{align}>"
-    when "pre"		then res.concat "<pre>"
+    when "pre"		then res.concat "<pre #{align}>"
     when "big"		then res.concat "<p #{align}><big>"
     when "small"	then res.concat "<p #{align}><small>"
     when "list"		then res.concat "<ul #{align}>"
@@ -281,22 +300,22 @@
     when "horizontal"	then res.concat "<table #{AC} border=´#{$rwd_border}´ cellspacing=´3´ cellpadding=´0´><tr #{align} #{valign}>"
     when "table"	then res.concat "<table #{AC} border=´#{$rwd_border}´ cellspacing=´3´ cellpadding=´0´>"
     when "row"		then res.concat "<tr #{align} #{valign}>"
-    when "hidden"	then res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´hidden´>"
+    when "hidden"	then res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value1}´ type=´hidden´>"
     when "text"
       maxlength	= ""
       maxlength	= "maxlength=´%s´" % @args["maxlength"]	if @args.include?("maxlength")
-      res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´text´ #{maxlength}>"
+      res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value1}´ type=´text´ #{maxlength}>"
       oneormorefields	<< "true"
     when "textarea"
-      res.concat "<p #{align}><textarea name=´#{@args["name"]}´>#{value}</textarea>"
+      res.concat "<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")
-      res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´password´ #{maxlength}>"
+      res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value1}´ type=´password´ #{maxlength}>"
       oneormorefields	<< "true"
     when "checkbox"
-      if vars[@args["name"]] == "on"
+      if varshtml[@args["name"]] == "on"
         switches[@args["name"]]	= true
         res.concat "<p #{align}><input name=´#{@args["name"]}´ checked=´on´ type=´checkbox´>"
       else
@@ -305,16 +324,16 @@
       end
       oneormorefields	<< "true"
     when "radio"
-      if vars[@args["name"]] == value
-        res.concat "<p #{align}><input name=´#{@args["name"]}´ checked=´on´ value=´#{value}´ type=´radio´>"
+      if varshtml[@args["name"]] == value1	# ??? 1 of 2?
+        res.concat "<p #{align}><input name=´#{@args["name"]}´ checked=´on´ value=´#{value1}´ type=´radio´>"
       else
-        res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´radio´>"
+        res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value1}´ type=´radio´>"
       end
       oneormorefields	<< "true"
     when "select"
       res.concat "<select #{align} name=´#{@args["name"]}´ width=´#{@args["width"]}´>"
       name	= @args["name"]
-      $select	= vars[name]
+      $select	= varshtml[name]
       oneormorefields	<< "true"
     when "option"
       if $select == @children[0].text
@@ -406,7 +425,7 @@
     after.push(aft)
   end
 
-  def postchildren(res, before, after, vars, switches, help, oneormorefields, firstaction, tabs, tab)
+  def postchildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab)
     case @subtype
     when "vertical", "window", "helpwindow", "tabs", "tab"
       res.concat Format % ["BefPost", @subtype]	if $rwd_debug
@@ -485,7 +504,7 @@
       a[k.upcase]	= v
     end
 
-    a["LOGO"]		= ""	unless ((not vars["logo"].nil?) and FileTest.file?(vars["logo"]))
+    a["LOGO"]		= ""	unless ((not vars["logo"].nil?) and File.file?(vars["logo"]))
 
     a["HELPBUTTON"]	= (not (vars["nohelpbutton"]))
     a["BACKBUTTONS"]	= (not (vars["nobackbuttons"]))
@@ -493,13 +512,15 @@
     a["CLOSEBUTTON"]	= (not (vars["noclosebutton"]))
 
     if a.include?("WIDTH")
-      a["WIDTH"]	= "width=´#{a["WIDTH"]}´"
+      a["WIDTH1"]	= "width=´#{a["WIDTH"]}´"
+      a["WIDTH2"]	= a["WIDTH"]
     else
-      a["WIDTH"]	= " "
+      a["WIDTH1"]	= " "
+      a["WIDTH2"]	= "1"
     end
 
     html.split(/\r*\n/).each do |line|
-      if line =~ /%[A-Z]+%/
+      if line =~ /%[A-Z0-9]+%/
         a.each do |k, v|
           v	= false	if (v.kind_of?(String) and v.empty?)
 
@@ -508,7 +529,7 @@
           end
         end
 
-        line	= "<!-- #{line.scan(/%[A-Z]+%/).join(" ")} -->"	if line =~ /%[A-Z]+%/
+        line	= "<!-- #{line.scan(/%[A-Z0-9]+%/).join(" ")} -->"	if line =~ /%[A-Z0-9]+%/
       end
 
       res << line
@@ -519,7 +540,7 @@
 end
 
 class Text
-  def prechildren(res, before, after, vars, switches, help, oneormorefields, firstaction, tabs, tab)
+  def prechildren(res, before, after, varshtml, varsstring, switches, help, oneormorefields, firstaction, tabs, tab)
     if not @text.scan(/[^ \t\r\n]/).empty?
       res.concat Format % ["Text", ""]	if $rwd_debug
       res.concat "#{@text}"
@@ -557,7 +578,8 @@
   end
 
   def render(vars=Hash.new, switches=Hash.new, help=false, tab="")
-    vars2		= Hash.new
+    varshtml		= Hash.new
+    varsstring		= Hash.new
     oneormorefields	= ""
     firstaction		= ""
     html		= ""
@@ -571,7 +593,8 @@
           @helprwd.gsub!(/%%#{key}%%/, value.to_s)
           @helprwd.gsub!(/%#{key}%/, value.to_s.to_html)
 
-          vars2[key]	= value.to_s.to_html
+          varshtml[key]		= value.to_s.to_html
+          varsstring[key]	= value.to_s
         end
       end
     end
@@ -592,9 +615,9 @@
     end
 
     if help
-      helpobject.parsetree("prechildren", "postchildren", html, [""], [""], vars2, switches, false, oneormorefields, firstaction, tabs, tab)
+      helpobject.parsetree("prechildren", "postchildren", html, [""], [""], varshtml, varsstring, switches, false, oneormorefields, firstaction, tabs, tab)
     else
-      windowobject.parsetree("prechildren", "postchildren", html, [""], [""], vars2, switches, (not @helprwd.empty?), oneormorefields, firstaction, tabs, tab)
+      windowobject.parsetree("prechildren", "postchildren", html, [""], [""], varshtml, varsstring, switches, (not @helprwd.empty?), oneormorefields, firstaction, tabs, tab)
     end
 
     html.gsub!(/%%*[[:alnum:]_\-]+%%*/, "")	if not $rwd_debug
@@ -616,13 +639,13 @@
 
 class RWDMessage < RWDWindow
   def initialize(msg)
-    super("<window title=´RWD Message´ nobackbuttons><vertical><p>#{msg}</p><back/></vertical></window>")
+    super("<window title=´RWD Message´ nobackbuttons noclosebutton><vertical><p>#{msg}</p><back/></vertical></window>")
   end
 end
 
 class RWDError < RWDWindow
   def initialize(msg)
-    super("<window title=´RWD Error´ nobackbuttons><vertical><p><b>Error:</b> #{msg}</p><back/></vertical></window>")
+    super("<window title=´RWD Error´ nobackbuttons noclosebutton><vertical><p><b>Error:</b> #{msg}</p><back/></vertical></window>")
   end
 end
 
@@ -654,25 +677,29 @@
     high	= low	if high.nil?
     low, high	= low.to_i, high.to_i
 
-    port	= TCPServer.freeport(low, high)	if port.nil?
-    raise "No free TCP port."			if port.nil?
+    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, auth, realm)
+    @rwd_server	= RWDServer.new(self, port, io, auth, realm)
   end
 
-  def render(res, path, post, sessionid)
+  def render(res, path, post, download, 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_msg	= nil
+    done		= false
+    help		= false
+    back		= false
+    tab			= ""
+    @rwd_msg		= nil
+    @rwd_download	= nil
 
 		# Switches are used for checkboxes.
 
@@ -694,17 +721,26 @@
 
     @rwd_action			= vars["rwd_action"]
     @rwd_action, @rwd_args	= @rwd_action.split(/\//, 2)	unless @rwd_action.nil?
+    @rwd_action, rest		= @rwd_action.split(/\?/)	unless @rwd_action.nil?
+
+    unless rest.nil?
+      rest.each do |s|
+        k, v	= s.split(/=/, 2)
+        vars[k]	= v
+      end
+    end
 
     if @rwd_action =~ /^rwd_tab_/
       @rwd_tab	= @rwd_action.sub(/^rwd_tab_/, "")
-      @rwd_history[-1][2]	= @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_window			= (@rwd_history[-1] or [nil, nil, nil])[1]
-        @rwd_tab			= (@rwd_history[-1] or [nil, nil, nil])[2]
+        @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
@@ -720,12 +756,13 @@
 		# History stuff
 
       @rwd_history	= @rwd_history[-100..-1]	if @rwd_history.length >= 100
-      @rwd_args		= []				if @rwd_args.nil?
       @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
@@ -740,17 +777,23 @@
 		# Callback.
 
       if (not back) or @rwd_call_after_back.include?(@rwd_action)
-        begin
+        unless @rwd_action =~ /^rwd_/
           puts "Method: #{@rwd_action}(#{@rwd_args.join(", ")})"	if $rwd_debug
-          method(@rwd_action).call(*@rwd_args)
-        rescue NameError
+          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", nil]]		if @rwd_action == "main"
-        @rwd_history	= [["main", "main", nil]]		if @rwd_history.empty?
-        @rwd_history.push [@rwd_action, @rwd_window, @rwd_tab]	if (@rwd_history[-1] != [@rwd_action, @rwd_window, @rwd_tab] or not @rwd_msg.nil?)
+        @rwd_history	= [["main", nil, "main", nil]]	if @rwd_action == "main"
+        @rwd_history	= [["main", nil, "main", nil]]	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_msg.nil?)
       end
     end
 
@@ -772,13 +815,20 @@
     if done
       res << RWDDone.new(@rwd_exitbrowser).render
     else
-      if not @rwd_msg.nil?
-        res << RWDMessage.new(@rwd_msg).render		if @rwd_msgtype == "message"
-        res << RWDError.new(@rwd_msg).render		if @rwd_msgtype == "error"
+      if not @rwd_download.nil?
+        puts "Download: #{@rwd_window}"		if $rwd_debug
+
+        download << @rwd_download
       else
-        puts "Window: #{@rwd_window}"			if $rwd_debug
-        puts "Tab: #{@rwd_tab}"				if $rwd_debug
-        res << RWDWindow.new(@rwd_xml, @rwd_window).render(vars, @rwd_switches, help, @rwd_tab)
+        if not @rwd_msg.nil?
+          res << RWDMessage.new(@rwd_msg).render	if @rwd_msgtype == "message"
+          res << RWDError.new(@rwd_msg).render		if @rwd_msgtype == "error"
+        else
+          puts "Window: #{@rwd_window}"		if $rwd_debug
+          puts "Tab: #{@rwd_tab}"		if $rwd_debug
+
+          res << RWDWindow.new(@rwd_xml, @rwd_window).render(vars, @rwd_switches, help, @rwd_tab)
+        end
       end
     end
 
@@ -786,7 +836,7 @@
   end
 
   def samewindow?
-    @rwd_history[-1][1] == @rwd_window
+    @rwd_history[-1][2] == @rwd_window
   end
 
   def message(msg)
@@ -799,6 +849,10 @@
     @rwd_msgtype	= "error"
   end
 
+  def download(data)
+    @rwd_download	= data
+  end
+
   def exitbrowser
     @rwd_exitbrowser	= true
   end
@@ -835,6 +889,7 @@
     @rack	= rack.to_s
     @cleanup	= SessionCleanup.new(self, 3600, 24*3600)	if cleanup
     @sessions	= {}
+
     #@store	= PStore.new("#{temp}/store.#{@rack}.#{user}")	# ???
 
     #@store.transaction do
@@ -864,6 +919,10 @@
   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
@@ -884,8 +943,8 @@
 end
 
 class RWDSession < Session
-  def render(res, path, post)
-    done	= self["object"].render(res, path, post, @sessionid)
+  def render(res, path, post, download)
+    done	= self["object"].render(res, path, post, download, @sessionid)
 
     if done
       res.gsub!(/\$RWD_SESSION\$/, "")
@@ -898,7 +957,7 @@
 end
 
 class RWDServer
-  def initialize(obj, port, auth, realm)
+  def initialize(obj, port, io, auth, realm)
     @object		= obj
     @localbrowsing	= false
     @browserstarted	= false
@@ -936,18 +995,22 @@
 	# Start server.
 
     catch :rwd_exit do
-      HTTPServer.serve(port, (not auth.nil?)) do |req, resp|
+      portio	= port
+      portio	= [port, io]	unless io.nil?
+      HTTPServer.serve(portio, (not auth.nil?)) do |req, resp|
         vars	= req.vars.dup
+        pad	= req.request.path
 
         if auth.kind_of? String
           file	= "#{home}/#{auth}"
           auths	= {}
-          auths	= Hash.file(file)	if FileTest.file?(file)
+          auths	= Hash.file(file)	if File.file?(file)
         else
           auths	= auth
         end
 
-        oldsessionid	= vars["rwd_session"]
+        #oldsessionid	= vars["rwd_session"]
+        oldsessionid	= req.cookies["sessionid"]
 
 		  # Retrieve session.
 
@@ -957,15 +1020,18 @@
 
         if session.nil?
           if auth.nil?
-            session			= RWDSession.new(MD5.new(req.peeraddr[3].to_s + @object.inspect.to_s).to_s)
+            sessionid			= MD5.new(req.peeraddr[3].to_s + @object.inspect.to_s).to_s
+            session			= RWDSession.new(sessionid)
             session["object"]		= @object
           else
-            session			= RWDSession.new(MD5.new(Time.new.to_s + req.peeraddr[3].to_s + @object.inspect.to_s).to_s)
+            sessionid			= nil
+            sessionid			= MD5.new(Time.new.to_s + req.peeraddr[3].to_s + @object.inspect.to_s).to_s	while (sessionid.nil? or @sessions.include?(sessionid))
+            session			= RWDSession.new(sessionid)
             session["object"]		= @object.clone
           end
 
           if oldsessionid.nil? or oldsessionid.empty?
-            if not auth.nil? and not auth.empty? and not session.authenticated
+            if not auth.nil? and not auth.empty? and not session.authenticated and pad != "/pixel.gif"
 
 		  # Check authentication
 
@@ -975,6 +1041,7 @@
               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
@@ -994,20 +1061,33 @@
 
         session.touch
 
-        if req.request.path == "/"
+        if pad == "/"
 
 		  # Serve methods/callbacks.
 
 		  # Build new page.
 
-          res	= ""
+          download	= ""
+          res		= ""
 
-          done	= session.render(res, req.request.path, vars)
+          done	= session.render(res, pad, vars, download)
 
           begin
-            resp["Content-Type"]	= "text/html"
+            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; filename=data"
 
-            resp << res
+              resp << download
+            end
           rescue
             puts "Sending response to browser failed."
 
@@ -1036,13 +1116,13 @@
 
 		  # Serve files.
 
-          if req.request.path == "/pixel.gif"
+          if pad == "/pixel.gif"
             resp["Cache-Control"]	= "max-age=86400"
             resp["Content-Type"]	= "image/gif"
             resp << $rwd_pixel
           else
-            if (FileTest.file?(req.request.path.sub(/^\/*/, "")))
-              resp << File.new(req.request.path.sub(/^\/*/, ""), "rb").read	rescue nil
+            if (File.file?(pad.sub(/^\/*/, "")))
+              resp << File.new(pad.sub(/^\/*/, ""), "rb").read	rescue nil
             else
               resp.response	= "HTTP/1.0 404 NOT FOUND"
             end
@@ -1199,7 +1279,7 @@
 
                 <td align=´center´>
 
-                  <table align=´center´ border=´0´ cellspacing=´0´ cellpadding=´0´ %WIDTH%>
+                  <table align=´center´ border=´0´ cellspacing=´0´ cellpadding=´0´ %WIDTH1%>
                     <tr align=´center´>
                       <td align=´center´ bgcolor=´#444488´>
 
@@ -1223,7 +1303,7 @@
                     </tr>
 
                     <tr align=´center´>
-                      <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+                      <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´%WIDTH2%´></td>
                     </tr>
 
                     <tr align=´center´>
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/sgml.lib.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/sgml.lib.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/sgml.lib.rb	2004-05-15 11:16:23.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/sgml.lib.rb	2004-08-21 10:56:03.000000000 +0200
@@ -25,11 +25,11 @@
   end
 
   def prechildren_to_s(res)
-    res << "#{@text}"
+    res << "#{CGI.unescapeHTML(@text)} "
   end
 
   def prechildren_to_sgml(res)
-    res << "#{@text}"
+    res << "#{CGI.unescapeHTML(@text)}"
   end
 end
 
@@ -73,6 +73,7 @@
   def initialize(subtype, args={})
     super(subtype)
     @args = args
+    @text = ""
   end
 end
 
@@ -97,7 +98,7 @@
       end
     end
 
-    res << "<#{a.join(" ")}>"
+    res << "<#{a.join(" ")}>" + @text
   end
 
   def postchildren_to_sgml(res)
@@ -122,84 +123,52 @@
   def buildobjects(string)
     @objects = []
 
-    string.splitblocks(["<!--", "-->"], ["<!", ">"], ["<?", "?>"], ["<", ">"]).each do |type, s|
-      case type
-      when 0	then @objects << Text.new(s)
-      when 1	then @objects << Comment.new(s)
-      when 2	then @objects << Special.new(s)
-      when 3	then @objects << Instruction.new(s)
-      when 4
-
-        tag, args, open, close	= verwerktag1(s)
-
-        @objects << OpenTag.new(tag.dup, args.dup)	if open
-        @objects << CloseTag.new(tag.dup, args.dup)	if close
-      end
-    end
-  end
-
-  def verwerktag1(string)
-    res	= nil
-
-    if @tagcache.include? string
-      res	= @tagcache[string]
-
-    else
-      res	= verwerktag2(string)
-
-      @tagcache[string] = res
-    end
-
-    return res
-  end
-
-  def verwerktag2(string)
-    a	= []
-
-    string.splitblocks(["´", "´"], [´"´, ´"´]).collect do |type, s|
-      case type
-      when 0
-        if self.class.to_s == "HTML"
-          s.splitwords(["<", ">"]).each do |w|
-            d	= w.split("=", 2)
-
-            if d.length == 1
-              a << d[0]
-            else
-              a << d[0]	if not d[0].nil? and not d[0].empty?
-              a << "="
-              a << d[1]	if not d[1].nil? and not d[1].empty?
+    verwerk3	=
+    lambda do |string|
+      a	= []
+  
+      string[1..-2].splitblocks(["´", "´"], [´"´, ´"´]).collect do |type, s|
+        case type
+        when 0
+          if self.class.to_s == "HTML"
+            s.splitwords.each do |w|
+              d	= w.split("=", 2)
+  
+              if d.length == 1
+                a << d[0]
+              else
+                a << d[0]	if not d[0].nil? and not d[0].empty?
+                a << "="
+                a << d[1]	if not d[1].nil? and not d[1].empty?
+              end
             end
+          else
+            a.concat s.splitwords(["/", "="])
           end
-        else
-          a.concat s.splitwords(["<", "/", "=", ">"])
+        when 1, 2	then a << s
         end
-      when 1, 2	then a << s
       end
-    end
-
-    a	= a[1..-2]
-    open	= false
-    close	= false
-
-    if not a.nil?
+  
+      open	= false
+      close	= false
+  
       a = a[0].splitwords("/") + a[1..-1]
-
+  
       if a[0] == "/"
         close	= true
         a.shift
       else
         open	= true
       end
-
+  
       if a[-1] == "/"
         close	= true
         a.pop
       end
-
+  
       tag	= a.shift.downcase
       args	= {}
-
+  
       while not a.length.zero?
         if a.length >= 3 and a[1] == "="
           key	= a.shift.downcase
@@ -211,9 +180,40 @@
           args[key]	= ""
         end
       end
+  
+      [tag, args, open, close]
+    end
+
+    verwerk2	=
+    lambda do |string|
+      if @tagcache.include? string
+        res	= @tagcache[string]
+      else
+        res	= verwerk3.call(string)
+
+        @tagcache[string] = res
+      end
+
+      res
+    end
+
+    verwerk1 =
+    lambda do |string|
+      tag, args, open, close	= verwerk2.call(string)
+
+      @objects << OpenTag.new(tag.dup, args.dup)	if open
+      @objects << CloseTag.new(tag.dup, args.dup)	if close
     end
 
-    return [tag, args, open, close]
+    string.splitblocks(["<!--", "-->"], ["<!", ">"], ["<?", "?>"], ["<", ">"]).each do |type, s|
+      case type
+      when 0		then @objects << Text.new(s)
+      when 1		then @objects << Comment.new(s)
+      when 2		then @objects << Special.new(s)
+      when 3		then @objects << Instruction.new(s)
+      when 4		then verwerk1.call(s)
+      end
+    end
   end
 
   def to_s
diff -ur rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/tree.lib.rb rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/tree.lib.rb
--- rubywebdialogs-0.0.9.tar.gz/rubywebdialogs/lib/tree.lib.rb	2004-05-15 11:16:23.000000000 +0200
+++ rubywebdialogs-0.0.10.tar.gz/rubywebdialogs/lib/tree.lib.rb	2004-08-21 10:56:03.000000000 +0200
@@ -157,7 +157,7 @@
 
     Dir.mkdirrec(dir)
 
-    if FileTest.file?(file)
+    if File.file?(file)
       @@mutex.synchronize do
         tree	= Marshal.restore(File.new(file, "rb"))
       end
@@ -249,68 +249,93 @@
     end
   end
 
-  def parse(types=[], subtypes=[])
+  def parse(types=[], subtypes=[], once=false)
     types	= [types]	if types.class == Class
     subtypes	= [subtypes]	if subtypes.class == String
     hidelevel	= nil
 
-    @objects.each do |obj|
-      hidelevel	= obj.level		if (@checkvisibility and hidelevel.nil? and (not obj.visible))
-      hidelevel	= nil			if (@checkvisibility and (not hidelevel.nil?) and obj.visible and obj.level <= hidelevel)
-
-      if hidelevel.nil?
-        ok = false
-        if types.empty?
-          if subtypes.empty?
-            ok = true
-          else
-            subtypes.each do |st|
-              ok = true if obj.subtype == st
-            end
-          end
+    catch :once do
+      @objects.each do |obj|
+        if (@checkvisibility and hidelevel.nil? and (not obj.visible))
+          hidelevel	= obj.level
         else
-          if subtypes.empty?
-            types.each do |t|
-              ok = true if obj.kind_of?(t)
-            end
-          else
-            types.each do |t|
-              subtypes.each do |st|
-                ok = true if obj.kind_of?(t) if obj.subtype == st
+          if (@checkvisibility and (not hidelevel.nil?) and obj.visible and obj.level <= hidelevel)
+            hidelevel	= nil
+          end
+        end
+
+        if hidelevel.nil?
+          ok = false
+          catch :stop do
+            if types.empty?
+              if subtypes.empty?
+                ok = true
+                throw :stop
+              else
+                subtypes.each do |st|
+                  if obj.subtype == st
+                    ok = true
+                    throw :stop
+                  end
+                end
+              end
+            else
+              if subtypes.empty?
+                types.each do |t|
+                  if obj.kind_of?(t)
+                    ok = true
+                    throw :stop
+                  end
+                end
+              else
+                types.each do |t|
+                  subtypes.each do |st|
+                    if obj.kind_of?(t) and obj.subtype == st
+                      ok = true
+                      throw :stop
+                    end
+                  end
+                end
               end
             end
           end
-        end
 
-        yield(obj.class.to_s, obj) if ok
+          if ok
+            yield(obj.class.to_s, obj)
+
+            throw :once	if once
+          end
+        end
       end
     end
   end
 
   def path(pad)
-    p	= self
+    p1	= self
 
     pad.split(/\//).each do |deel|
       tag, voorkomen	= deel.split(/:/)
 
-      if (not tag.nil?) and (not p.nil?)
+      if (not tag.nil?) and (not p1.nil?)
         voorkomen	= 1	if voorkomen.nil?
         voorkomen	= voorkomen.to_i
 
         teller	= 0
         p2	= nil
-        p.children.each_index do |i|
-          if p.children[i].upordown == Down
-            if p.children[i].subtype.noquotes == tag.noquotes
-              teller	+= 1
-              p2		= p.children[i]	if teller == voorkomen
+        p1.children.each_index do |i|
+          #if p1.children[i].upordown == Down
+            unless  p1.children[i].subtype.nil?
+              if p1.children[i].subtype.noquotes == tag.noquotes
+                teller += 1
+                p2	= p1.children[i]	if teller == voorkomen
+              end
             end
-          end
+          #end
         end
-        p	= p2
+        p1	= p2
       end
     end
 
-    p
+    p1
   end
 end