#!./exu

-- Title: Asearch2
-- Author: Robert Szalay
--
-- Description:
--   This is an enhanced version of asearch.
--   It has more features then RDS's asearch.
--   It SHOULD work on any platform that Euphoria
--   supports.
--   I've had it working on LINUX and WINDOWS.
--   I Developed it on the Windows platform.
--   It uses Index Sort by Pete King
--      Thanks Pete
--
-- Features:
--   * String searching
--       Strings must be enclosed in double qoutes   "insert string here"
--
--   * Ability to exclude words from the  search by prefixing a word
--       with "NOT " (thats right, "NOT ".  Case-sensitive. "not " won't 
--       do the trick)
--       so searching for "editor NOT hilight" will return all editors that do 
--       not hilight syntax.  You can exclude a single word or a string of text.
--       A search for 'tool NOT "search tool"' will return all projects that have
--       the word "tool" and not the phrase "search tool" in them.
--
--   * Ability to sort the results Ascending or Descending by the following fields:
--       Relativity  (how many times the keywords were found in each result)
--       Author (the creator of the project)
--       Name (the name of the project)
--       Size (the size of the project)
--       Date (the date the project was submited or last updated)
--       Platform (the platform the project was made for)
--       MicroMoney (the amount of MicroMoney the project has earned)
--       Stamped (if the project is stamped or not)
--
--   * Easily customizable logging. (see variable LOG_LINE in the USER
--     variables section.)
--       There are SEVERAL things you can include in your logs.
--
--   * Will work with the same form used in RDS's asearch. (the one that don't allow
--       you to sort the results)
--
--   * Looks almost the same as RDS's asearch.
--        The only difference between the two is the form and the results
--        are just a little bit different (you probably wont even notice untill I
--        tell you later on in the Notes section! (Yes, its that small of a change)).
--
--   * Strips html tags
--       It strips html tags so that you don't have to include them in your search
--       which makes finding what you want easier.  This option can be disabled but is
--       on by default.
--
--
-- Bugs:
--   None have been found yet.  (Well, there were bugs, but this is the first release.
--   I've already fixed the bugs I found :-)
--   Please e-mail me any bug reports, comments or suggestions at:
--     robsz1@netzero.net
--
-- Notes:
--   * Ok.. Ok..  The change I made to the results is...
--       results that have been updated since they were submitted are marked with
--       "updated".  Projects that have been updated in the last 6 months are 
--       also marked with "updated" except in italics.
--       The RDS version only marked projects updated in the last 6 months as updated.
--       I told you it wasn't a big change!
--
--   * Some of the results contain html tags.  Normally, this would be a problem but
--       I made it strip the html tags so we don't have that problem :-).
--
-- Suggestions:
--   I would like to hear your opinions, suggestions and comments!!
--   Send them to me!  :-)  robsz1@netzero.net
--
--   * Integrate some of guru.ex into asearch
--       Well.  That is not too likely to happen.  There are literally 1,000s of files
--       that would need to be scanned every time someone searches the archive.
--       It would cause quite a performance hit and would require more hard drive
--       space on the server.  I would say this would be on the top of the "not likely
--       to heppen" list.  Sorry.
--
--   * Implement a feature to search projects for a routine
--       This is also not likely to happen.  It could be accomplished by changing the
--       layout of the archive to include a list of routines that are in the projects.
--       It could be done and I may be willing to do this but I would need a response
--       from Robert Craig about this one.  This would mean that the archive would 
--       grow in size and that it would take a bit more to update it.  I assume that
--       Robert Craig has a tool that he is useing to update the database that would
--       need a little updateing to do this.
--
-- Future plans:
--   Well.  There aren't really any plans yet.  Here are a couple things that I have
--   thought of though.
--
--   * A hit counter.
--       The problem with this one is that it would require a bit of writing to the
--       database which may cause some slow downs in searching the archive but probably
--       not anything major.
--
--   * Implementation of the AND operator
--       This one would make some sense and would probably be quite usefull.
--       Maybe you will see it in the next version!  But first, I've got
--       to hear some opinions on this one.  If noone wants it, there isnt
--       really a point to adding this feature.
--
-- Installation:
--   I'm not much of a nix'er(or FreeBSD) so I can't really help too much on 
--   that part, but I'll try.
--
--   * Linux
--       1) Put these files into your cgi-bin directory:
--          cgi.e
--          html.e
--          mysorts.e
--          sort2.e
--          asearch2.exw
-- 
--       2) Edit the shebang line to resemble the path to exu on your 
--          system(if necessary)
--
--       3) chmod asearch.exw to 755
--
--       4) Get the latest version of archive.edb from the RDS site and put
--          it in the folder with this script.
--
--       5) Scroll down to the USER variables sections and change the variables that
--          need changing.
--
--       6) go to the script in your browser!
--
--       NOTE:  You may need to include the standard include files for the script to
--          properly work.  This depends on the configuration of your server.
--          It is quite likely that you will need to do this.
--
--   * Windows
--       1) Put these files into your cgi-bin directory:
--          cgi.e
--          html.e
--          mysorts.e
--          sort2.e
--          asearch2.exw
--
--       2) Edit the shebang line at the top of this file to resemble the path
--          to exw.exe on your system (if necessary)

--       3) Get the latest version of archive.edb from the RDS site and put
--          it in the folder with this script.
--
--       4) Scroll down to the USER variables sections and change the variables that
--          need changing.
--
--       5) That should be all you need to do.  On Apache, that is all I needed to do.
--          (I already had Apache setup and configured)
--          The other solution to this is to copy all the standard includes into
--          your cgi-bin directory with the rest of the files.
--
--       Apache Tip!: Does euphoria complain that it can't find the standard 
--       include files ?
--       Add this to your Apache configuration file:
--          PassEnv EUDIR
--
--       Does Apache require you to include a shebang line at the top of your scripts
--       to be able to execute them ?
--       Add this line to your Apache configuration file to make Apache use the registry
--       to execute the appropriate application associated with the file.
--          ScriptInterpreterSource registry
--
--   Sorry, that is all the help I have to offer for setting this up.



without warning

atom ttime, totaltime
ttime = time()
totaltime = ttime

--------------------
-- USER VARIABLES --
--------------------
constant
dbname = "ARCHIVE.EDB", -- filename of the database
baseurl = "http://67.192.61.121/", -- The site's url. (where the archive files and html are located)
LOG_SEARCHES = 1, -- Log the statistics of searches? 0 = NO anything else = Yes (numbers only!)
LOG_FNAME = "asearch.log",  -- Name of file to log to
LOG_LINE = "Search time: %ttime%\n# of results: %sr%\n\n", 
-- The layout of the logs.  Don't forget to include \n's
   -- available variables are: 
   -- %ttime% = Total time to run the script
   -- %sr% = Number of results for the search
   -- %kw% = The list of keywords
   -- %klw% = The list of killwords
   -- %ip% = The ip address of the client
   -- %hn% = The host name of the client
   -- %sd% = Details of how the user chose to sort the data
   -- %so% = Order user chose to sort the results (Ascending or Descending)
   -- %sb% = The field the user chose to sort the results by (Relativity, Author, ect...)
   -- %pl% = Platform the script is running on
   -- %ref% = the page the client came from
   -- %sp% = The path to this script (i.e. /cgi-bin/asearch2.exw)
   -- %ss% = The Software the server is running (i.e. Apache)
   -- %ua% = The User Agent(browser) the client is running (i.e. Mozilla)
   -- %qs% = the complete query string received from the client
   -- %spl% = Search platforms (the platforms the user searched)
   -- %max% = The set number of maximum results
STRIP_TAGS = 1, 
pcolors = {"#C0C0C0", "#FFCCCC", "#CCCCFF", "#BBEEBB"}, -- colors for platforms GEN DOS WIN LNX
MAX_RESULTS = 100,  -- maximum results to display per-page
MAX_TRIES = 5, -- maximum number of attempts to make to open a locked database
WAIT_TIME = 2 -- number of seconds to wait between each open attempt of a locked database




--------------------
-- MAIN variables --
--------------------
global constant 
   P_GEN = 1, 
   P_DOS = 2, 
   P_WIN = 3, 
   P_LNX = 4,
   
   
   pnames = {"GEN","DOS","WIN","LNX"},
   
   months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}, 
   current_date = date(), 
   
   A_PLATFORM = 1,   -- numeric: 0 = GEN, 1 = DOS, 2 = WIN, 3 = LNX
   A_HREF = 2,       -- string
   A_TITLE = 3,      -- string
   A_SIZE = 4,       -- number of K bytes
   A_NAME = 5,       -- string
   A_YEAR = 6,       -- year: 4 digits
   A_MONTH = 7,      -- month: 1 to 12      
   A_DAY = 8,        -- day of the month: 1 to 31
   A_MONEY = 9,      -- integer - number of pennies
   A_DESCRIPTION = 10, -- one string with \n's
   A_UPDATED = 11,     -- 0 (not updated) or 1 (updated)
   A_STAMPED = 12,    -- 0 (not stamped) or 1 (stamped)
   A_CATEGORY = 13    -- html filename without ".htm"



include file.e
include cgi.e
include database.e



global sequence keywords, qs, killwords, lkillwords, 
   data, platforms, results1, results2, sortinfo
global atom resultcount, tablesize
keywords = ""
qs = ""
killwords = ""
lkillwords = ""
data = parse_data(get_data())
platforms = repeat(0,4)
results1 = {}
results2 = {}
sortinfo = {"",""}

resultcount = 0
tablesize = 0




no_cache()
type_html()


----------------------------
--  Miscelaneous Routines --
----------------------------

global procedure sleep(atom t)
   machine_proc(64, t)
end procedure


global function lower(sequence s)
-- (quickly) convert a line to lower case 
integer c
for i = 1 to length(s) do
   c = s[i]
   if c <= 'Z' then
      if c >= 'A' then
         s[i] = c + ('a' - 'A')
      end if
   end if
end for
return s
end function


global function removeSeqItem(sequence s, atom index)
   return s[1..index-1]&s[index+1..length(s)]
end function


function recent(integer month_num, integer year_num)
-- Is the date in the past 6 months (roughly)?
integer i, j
i = year_num * 12 + month_num
j = (current_date[1] + 1900) * 12 + current_date[2]
if j - i <= 6 then
   return 1
end if
return 0
end function   

include mysorts.e



-------------------
-- Main Routines --
-------------------
procedure log_stats()
atom handle, t
sequence tmp
object junk

tmp = LOG_LINE
junk = {"","","","","","",""}
handle = open(LOG_FNAME,"a")
t = 0
if handle != -1 then
   while not lock_file(handle, LOCK_EXCLUSIVE, {}) do
      t+=1
      if t = 10 then
         close(handle)
         abort(1)
      end if
      sleep(2)
   end while
end if

for i = 1 to length(keywords) do
   junk[1] &= "\""&keywords[i]&"\", "
end for
if length(junk[1]) > 0 then
   if junk[1][length(junk[1])] = ' ' then
      junk[1] = junk[1][1..length(junk[1])-2]
   end if
end if

for i = 1 to length(killwords) do
   junk[2] &= "\""&killwords[i]&"\", "
end for
if length(junk[2]) > 0 then
   if junk[2][length(junk[2])] = ' ' then
      junk[2] = junk[2][1..length(junk[2])-2]
   end if
end if

if equal(sortinfo[1],"a") then
   junk[3] = "Ascending by "&sortinfo[2]
   junk[4] = "Ascending"
elsif equal(sortinfo[1],"d") then
   junk[3] = "Descending by "&sortinfo[2]
   junk[4] = "Descending"
else
   junk[3] = "Unknown sort method specified."
   junk[4] = "Unknown"
end if

if length(sortinfo[2]) > 0 then
   junk[5] = sortinfo[2]
else
   junk[5] = "Unknown"
end if

t = platform()
if t = 1 then
   junk[6] = "Dos"
elsif t = 2 then
   junk[6] = "Windows"
elsif t = 3 then
   junk[6] = "Linux/FreeBSD"
else
   junk[6] = "Unknown platform"
end if

for i = 1 to 4 do
   if platforms[i] then
      junk[7] &= pnames[i]&" "
   end if
end for



tmp = replace(tmp,
   {"%ttime%","%sr%","%ip%","%hn%","%kw%","%klw%","%sd%","%so%","%sb%","%pl%","%ref%", 
      "%sp%","%ss%","%ua%","%spl%","%max%","%qs%"},
   {sprintf("%.2f",totaltime),sprintf("%d",resultcount),getVar("REMOTE_ADDR"),
      getVar("REMOTE_HOST"), junk[1], junk[2], junk[3], junk[4], junk[5],junk[6],
         getVar("HTTP_REFERER"),getVar("SCRIPT_NAME"),getVar("SERVER_SOFTWARE"), 
         getVar("HTTP_USER_AGENT"),junk[7],sprintf("%d",MAX_RESULTS),
         getVar("QUERY_STRING")})

puts(handle,tmp)
unlock_file(handle,{})
close(handle)
end procedure



procedure start_table()

out("<table border=0 width=715 cellpadding=0 cellspacing=0>\n" &
   "<tr>\n"&
   "  <td width=50 nowrap></td>\n"&
   "  <td width=225 nowrap></td>\n"&
   "  <td width=40 nowrap></td>\n"&
   "  <td width=170 nowrap></td>\n"&
   "  <td width=120 nowrap></td>\n"&
   "  <td width=55 nowrap></td>\n"&
   "  <td width=55 nowrap></td>\n"&
   "</tr>\n")
end procedure


procedure make_table(sequence data)
sequence tmp tmp = ""
out(
   "<tr bgcolor="&pcolors[data[A_PLATFORM]+1]&">\n" &
   
   "  <td>\n    <font color=\"#FFFFFF\"><b>" &
      pnames[data[A_PLATFORM]+1]&"</b></font>\n  </td>\n" &
   
   "  <td>\n    <font size=2><b><a href=\""&data[A_HREF]&"\">" &
      data[A_TITLE]&"</a></b></font>\n  </td>\n" &
   
   "  <td align=right>\n    "&sprintf("%d",data[A_SIZE])&"K\n  </td>\n" &
   
   "  <td align=center>\n    <font size=2><b>"&
      data[A_NAME]&"</b></font>\n  </td>\n" &
   
   "  <td>\n    <font size=2>")
   if data[A_UPDATED] then
      if recent(data[A_MONTH], data[A_YEAR]) then
         out("<font color=\"#5500FF\"><i>updated</i></font> ")
      else
         out("<font color=\"#5500FF\">updated</font> ")
      end if
   end if
   
   out(
   sprintf("%s %d/%02d", {months[data[A_MONTH]], data[A_DAY],
	   remainder(data[A_YEAR], 100)})&"\n  </td>\n" &
   
   "  <td>\n    ")
   if data[A_MONEY] then
      out("<img src=\"/happy.gif\">" &
         "<font size=2> "&sprintf("%.2f",data[A_MONEY]/100)&
         "</font>\n  </td>\n")
   else
      out("  </td>\n")
   end if
   
   
   if data[A_STAMPED] then
      out("  <td align=\"right\">\n")
      out("<img src=\"/stamp.gif\">\n  </td>\n</tr>\n")
   else
      out("  <td>\n")
      out("  </td>\n</tr>\n")
   end if
   
   out("<tr>\n  <td colspan=7>\n    <font size=2>" &
   data[A_DESCRIPTION]&"</font>\n  </td>\n</tr>\n" &
   "<tr>\n  <td>\n     \n  </td>\n</tr>\n")

end procedure





procedure show_header()
    out("<html>\n  <head>\n")
    out("    <title>Search results for Euphoria File Archive</title>\n")
    out("  <base href=\""&baseurl&"\">\n")
    out("</head>\n")
    out("<body bgcolor=\"#FFFFFF\" link=\"#003366\"" & 
	    " vlink=\"#006699\" text=\"#333333\">\n")
    out("<basefont face=\"Arial\" size=3>\n\n")
    out("<table border=0 cellpadding=2 cellspacing=0 width=670>\n")
    out("<tr>\n  <td width=130 nowrap>\n  </td>\n")
    out("  <td width=380 nowrap>\n  </td>\n")
    out("  <td width=160>\n  </td>\n")
    out("</tr>\n\n")

    out("<tr>\n  <td colspan=3 align=center>\n")
    out("    <font face=\"verdana, arial, geneva\" size=-2 color=\"#666666\">\n")
    out("    <a href=\"index.html\">Greetings</a> |\n")
    out("    <a href=\"hotnew.htm\">What Is Euphoria?</a> |\n")
    out("    <a href=\"news.htm\">News</a> |\n")
    out("    <a href=\"listserv.htm\">The Mailing List</a> |\n")
    out("    <a href=\"v20.htm\">Download Euphoria</a> |\n")
    out("    <a href=\"contrib.htm\">Recent User Contributions</a>\n")
    out("    </font>\n  </td>\n")
    out("</tr>\n\n")
    
    out("<tr>\n  <td colspan=3 align=center>\n")
    out("    <font face=\"verdana, arial, geneva\" size=-2 color=\"#666666\">\n")
    out("    <a href=\"archive.htm\">The Archive</a> |\n")
    out("    <a href=\"othersit.htm\">Other Euphoria Web Sites</a> |\n")
    out("    <a href=\"reg.htm\">Instant Registration</a> |\n")
    out("    <a href=\"contract.htm\">RDS Application Development Division</a>\n")
    out("    </font>\n  </td>\n")
    out("</tr>\n\n")
 
    out("<tr>\n  <td colspan=3>\n    <font size=1> </font>\n  </td>\n</tr>\n\n")
  
    out("<tr>\n  <td>\n  </td>\n")
    out("  <td align=center>\n")
  
    out("    <font face=\"Arial, Helvetica\" color=\"#CC3366\" size=+2><b>\n")
    out("Search Results\n")
    out("    </b><br><font size=1 color=\"#000080\">")
    out("    <a href=/cgi-bin/asearch.txt><i>Powered by Euphoria</i></a></font></font>\n")
    out("  </td>\n")
    out("  <td>\n  </td>\n")
    out("</tr>\n\n")

    out("</table>\n\n")
end procedure


procedure show_basic_form()
   out("<form method=GET action=\"\">\n")
   out("<table border=0 cellpadding=0 cellspacing=0 width=600>\n")
   out("<tr>\n  <td width=80 nowrap>\n  </td>\n  <td width=120>\n")
   out("    <font face=\"Arial, Helvetica\" size=+1 color=\"#990033\">")
   out("Keyword(s):</font>\n  </td>\n")
   out("  <td width=300>\n")
   out("    <font face=\"Arial, Helvetica\" size=-2>\n")
   
   out("    <input type=\"CHECKBOX\" name=\"dos\"")
   if platforms[P_DOS] then
      out("CHECKED")
   end if
   out("><font color=\"#FF8080\"><b>DOS</b>  </font>\n")
   
   out("    <input type=\"CHECKBOX\" name=\"win\"")
   if platforms[P_WIN] then
      out("CHECKED")
   end if	
   out("><font color=\"#8080FF\"><b>WIN</b>  </font>\n")
    
   out("    <input type=\"CHECKBOX\" name=\"lnx\"")
   if platforms[P_LNX] then
      out("CHECKED")
   end if
   out("><font color=\"#60EE60\"><b>LNX</b>  </font>\n")
    
   out("    <input type=\"CHECKBOX\" name=\"gen\"")
   if platforms[P_GEN] then
      out("CHECKED")
   end if
   out("><font color=\"#808080\"><b>GEN</b></font>\n")
    
   out("    </font>\n")
    
   out("    <input type=\"text\" name=\"keywords\" size=38 ")
    
   out("value=\""&replace(qs,
      {"&","\"","<",">"},
      {"&",""","<",">"})&"\">\n")
   out("    <font face=\"verdana, arial, geneva\" size=3 color=\"#333333\">\n")
   out("    Sort ")
   out("    <select name=\"sortmethod\">")
   out("<option")
   if equal(sortinfo[1],"a") then
      out(" selected")
   end if
   out(" value=\"a\">Ascending</option>\n    <option")
   
   if equal(sortinfo[1],"d") then
      out(" selected")
   end if
   out(" value=\"d\">Descending</option>\n")
   out("    </select>")
   out(" by ")
   out("<select name=\"sortby\">\n")
   
   out("    <option")
      if equal(sortinfo[2],"Relativity") then
         out(" selected")
      end if
   out(">Relativity</option>\n")
   
   out("    <option")
      if equal(sortinfo[2],"Author") then
         out(" selected")
      end if
   out(">Author</option>\n")
   
   out("    <option")
      if equal(sortinfo[2],"Name") then
         out(" selected")
      end if
   out(">Name</option>\n")
   
   out("    <option")
      if equal(sortinfo[2],"Size") then
         out(" selected")
      end if
   out(">Size</option>\n")
   
   out("    <option")
      if equal(sortinfo[2],"Date") then
         out(" selected")
      end if
   out(">Date</option>\n")
   
   out("    <option")
      if equal(sortinfo[2],"Platform") then
         out(" selected")
      end if
   out(">Platform</option>\n")
   
   out("    <option")
      if equal(sortinfo[2],"MicroMoney") then
         out(" selected")
      end if
   out(">MicroMoney</option>\n")
   
   out("    <option")
      if equal(sortinfo[2],"Stamped") then
         out(" selected")
      end if
   out(">Stamped</option>\n")
   
   out("    </select>\n    <br>\n  </td>\n")
   out("  <td width=90 valign=\"bottom\">\n    <input type=\"submit\"")
   out(" value=\"Search!\">\n")
   out("  </td>\n")
   out("</tr>\n\n")
   out("</table>\n")
   out("</form>\n")

end procedure




integer dbstatus
dbstatus = 0
function open_database()
object junk
junk = db_open(dbname,DB_LOCK_SHARED)
if junk != DB_OK then
   if junk = DB_LOCK_FAIL then
      junk = 0
      while db_open(dbname,DB_LOCK_SHARED) != DB_OK do
         junk+=1
         if junk > MAX_TRIES then
            return -1
         end if
         sleep(WAIT_TIME)
      end while
   elsif junk = DB_OPEN_FAIL then
      dbstatus +=1
      if dbstatus = 1 then
         -- This part was taken from RDS's asearch.  I left it in because I figured 
         -- that it is there for a reason.
         system("/usr/local/bin/unzip -o -f -qq ../archive.zip ARCHIVE.EDB > /dev/null", 2)
         return open_database()
      else
         return -1
      end if
   else
      return -1
   end if
else
   if db_select_table("archive") != DB_OK then
      return -1
   end if
end if
return db_table_size()
end function



-- Strips html tags from the string provided
function strip_tags(sequence str)
atom f1, f2
sequence tmp
f1 = find('<',str)
while f1 do
   f2 = find('>',str[f1..length(str)])
   if f2 then
      tmp = str[1..f1-1]&str[f1+f2..length(str)]
      str = tmp
   else
      exit
   end if
   f1 = find('<',str)
end while
return str
end function



procedure standardsearch()
object junk, tmp
atom kwlen, kill_len, t
kwlen = length(keywords)
kill_len = length(killwords)
tablesize = open_database()
t = 0
if tablesize > 0 then
   for i = 1 to tablesize do
      tmp = db_record_data(i)
      if platforms[tmp[A_PLATFORM]+1] then
    	   junk = {tmp[A_TITLE]&tmp[A_NAME],tmp[A_DESCRIPTION]&
    	      tmp[A_HREF]}
    	   junk[1] = lower(strip_tags(junk[1]))
    	   junk[2] = lower(strip_tags(junk[2]))
    	   for x = 1 to kwlen do
            if match(keywords[x],junk[1]) then
               if kill_len > 0 then
                  for y = 1 to kill_len do
                     if match(killwords[y],junk[1]) then
                        exit
                     else
                        if match(killwords[y],junk[2]) then
                           exit
                        end if
                        if y = kill_len then
                           resultcount+=1
                           results1 = append(results1,tmp)
                        end if
                     end if
                  end for
               else
                  resultcount+=1
                  results1 = append(results1,tmp)
                  exit
               end if
            elsif match(keywords[x],junk[2]) then
               if kill_len > 0 then
                  for y = 1 to kill_len do
                     if match(killwords[y],junk[2]) then
                        exit
                     else
                        if match(killwords[y],junk[1]) then
                           exit
                        end if
                        if y = kill_len then
                           resultcount+=1
                           results2 = append(results2,tmp)
                        end if
                     end if
                  end for
               else
                  resultcount+=1
                  results2 = append(results2,tmp)
               end if
            end if
         end for
      end if
   end for
end if
end procedure


procedure extract_kws(sequence s)
object f1, f2, junk, tmp
f1 = match("NOT ",s)
while f1 > 0 do
   if length(s) > f1+3 then
      if s[f1+4] = '\"' then
         f2 = find('\"',s[f1+5..length(s)])
         if f2 > 0 then
            killwords = append(killwords,lower(s[f1+5..f1+3+f2]))
            tmp = s[1..f1-1]&s[f1+5+f2..length(s)]
            s=tmp
         end if
      else
         f2 = find(' ',s[f1+4..length(s)])
         if f2 > 0 then
            junk = s[f1+4..f1+f2+2]
            killwords = append(killwords,lower(junk))
            tmp = s[1..f1-1]&s[f1+length(junk)+4..length(s)]
            s=tmp
         else
            junk = s[f1+4..length(s)]
            killwords = append(killwords,lower(junk))
            s = s[1..f1-1]&s[f1+f2+4+length(junk)..length(s)]
         end if
      end if
      f1 = match("NOT ",s)
   else
      exit
   end if
end while

f1 = find('\"',s)
while f1 > 0 do
   f2 = find('\"',s[f1+1..length(s)])
   if f2 > 0 then
      keywords = append(keywords,lower(s[f1+1..f1+f2-1]))
      tmp = s[1..f1-1]&s[f1+f2+1..length(s)]
      s = tmp
   else
      exit
   end if
   f1 = find('\"',s)
end while

if length(s) > 0 then
   s = lower(s)
   s = parse(s,' ')
   keywords = keywords&s
end if


junk = keywords
keywords = {}
for i = 1 to length(junk) do
   if length(junk[i]) > 0 then
      keywords = append(keywords,junk[i])
   end if
end for
end procedure



procedure get_keywords()
object tmp
   tmp = find("keywords",data)
   if not tmp then
      return
   end if
   qs = data[tmp+1]
   extract_kws(qs)
end procedure


procedure get_platforms()
object tmp
tmp = find("dos",data)
if tmp > 0 then
   if equal(data[tmp+1],"on") then
      platforms[P_DOS] = 1
   end if
end if

tmp = find("lnx",data)
if tmp > 0 then
   if equal(data[tmp+1],"on") then
      platforms[P_LNX] = 1
   end if
end if

tmp = find("win",data)
if tmp > 0 then
   if equal(data[tmp+1],"on") then
      platforms[P_WIN] = 1
   end if
end if

tmp = find("gen",data)
if tmp > 0 then
   if equal(data[tmp+1],"on") then
      platforms[P_GEN] = 1
   end if
end if
end procedure





if length(data) > 0 then
   show_header()
   get_keywords()
   if length(keywords) < 1 then
      show_basic_form()
      out("Enter keyword(s) and click the 'Search' button to search the archive of" &
         " over 1,000 user submitted files.\n<br>\n<br>\n")
      out("</body>\n</html>")
      abort(1)
   end if
   get_platforms()
   sortinfo = get_sort_details()
   show_basic_form()
   
   standardsearch()
   if resultcount > 0 then
      
      results1 &= results2
      
      if MAX_RESULTS >= length(results1) then
         --out(sprintf("<font size=2>Matched %d of %d entries in %.2f seconds.</font>\n" &
            --"<br>\n<br>\n",
               --{length(results1),tablesize,time()-ttime}))
         out(sprintf("<font size=2>Matched %d of %d entries.</font>\n" &
            "<br>\n<br>\n",
               {length(results1),tablesize}))         
         ttime=time()
         start_table()
         if length(results1) > 1 then
            sort_results()
         end if
         for i = 1 to length(results1) do
            make_table(results1[i])
         end for
      
      else
         --out(sprintf("<font size=2>Matched %d of %d entries in %.2f seconds.  " &
            --"Displaying the best %d</font>\n<br>\n<br>\n",
            --{length(results1),tablesize,time()-ttime,MAX_RESULTS}))
         out(sprintf("<font size=2>Matched %d of %d entries.  " &
            "Displaying the best %d</font>\n<br>\n<br>\n",
            {length(results1),tablesize,MAX_RESULTS}))
         ttime=time()
         start_table()
         sort_results()
         results1=results1[1..MAX_RESULTS]
         for i = 1 to MAX_RESULTS do
            make_table(results1[i])
         end for
      end if
      
      out("</table>")
      --out("Took <b>"&sprintf("%.2f",time()-ttime)&"</b> seconds to sort and display " &
         --"results.\n<br>\n")
      ttime = time()-ttime
      totaltime = time()-totaltime
      --out("Took a total of "&sprintf("%.2f",totaltime)&" seconds.\n")
      out("<p> <br>\n")
      out("<font face=\"verdana, arial, geneva\" size=2 color=\"#333333\">")
      out("<center>End of Search Results</center></font>\n")
      out("</body>\n</html>")
      if LOG_SEARCHES then
         log_stats()
      end if
   
   else
      out("No results found.  Please redefine your search and try again.")
      out("</body>\n</html>")
   end if

else
   show_header()
   show_basic_form()
   out("Enter keyword(s) and click the 'Search' button to search the archive of" &
   " over 1,000 user submitted files.\n<br>\n<br>\n")
   out("</body>\n</html>")
end if