home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / goswish5.zip / GOSWISH.CMD < prev    next >
OS/2 REXX Batch file  |  1999-06-08  |  127KB  |  4,131 lines

  1. /* 8 June 1999: The GoSWISH front end to the SWISH search engine, ver 1.48
  2.  
  3.   GOSWISH can be called in a number of different manners:
  4.  
  5.         a) As a cgi-bin script, or sre-http addon, to create a
  6.            swish index
  7.         b) Called as a Detached program, in order to create a
  8.            description cache
  9.         c) As a cgi-bin script (or sre-http addon) to search a swish index 
  10.            (and possibly a description   cache)
  11.         d) As a cgi-bin script (or sre-http addon) to display list of current
  12.           "search forms" (stored in goswish.ind)
  13.     
  14.  Regardless of how you use it .... you'll need to set a few parameters below
  15.  (the same settings are use in all modes). 
  16.  
  17. */
  18.  
  19.  
  20. /********************* BEGIN USER CONFIGURABLE PARAMETERS ***************/
  21. /* If you do not set these parameters (i.e.; set them =""); then
  22.    defaults will be used.  These defaults will make some sense if
  23.    you run this as an sre-http addon, but will probably be 
  24.    barely tolerable if you run this as a cgi-bin script.
  25. */
  26.  
  27. /* SWISH_DIR should be the fully qualified name of the directory
  28.    used for storing SWISH Index Files. It should also contain SWISH.EXE
  29.    (or, SWISH should be in your PATH).
  30.    If called as an SRE-http addon, the default is the SRE-http DATA directory.
  31.    If called as CGI-BIN, the default is the current directory (which is probably
  32.    inappropriate).
  33. */
  34. SWISH_DIR='swish_directory'
  35.  
  36.  
  37. /* WEB_ROOT_DIR is the root of your web directories. 
  38.    If called as an SRE-http addon, the default is the GoServe data directory.
  39.    If called as CGI-BIN, the default is the current directory (which is probably
  40.    inappropriate). 
  41. */
  42. WEB_ROOT_DIR='web_root_directory' 
  43.  
  44.  
  45. /* SRE-http option (only used if GOSWISH is run under the SRE-http server):
  46.      NEED_PRIVS is a set of "privileges" that permit creation of a swish
  47.      index.  That is, to create a swish index, the client must have ONE 
  48.      of these privileges (not all of, but at least one of). 
  49.      If she doesn't have one of these
  50.      privileges, an authorization request will be returned.
  51.      If this is called as a cgi-bin script, NEED_PRIVS is ignored.
  52.      If need_privs contains an *, then need_privs is ignored (open access)
  53. */
  54. need_privs='*'
  55.  
  56. /* Swish version:
  57.    Identifies the version of swish you are using
  58.         11 == version 1.1
  59.         12 == version 1.2
  60.         13 == version 1.3
  61.       13_DLL = use rxSWISH DLL
  62. */
  63. swish_version='13'
  64.  
  65. /* how to display links to "other matches" (i.e. 1-20, 20-40, etc.)
  66.      If all_sets=0, then just show link to prior and next set. 
  67.      If all_sets=1, then show numbers (1 2 3 ... ) linking to
  68.      1st, 2nd, etc. sets.
  69.   This is only used when the START=0 1 option is used when first invoking
  70.   the GoSWISH search mode */
  71. all_sets=1
  72.  
  73.  
  74. /* Add a modifier to process execution commands. This can be used
  75.    with SPE, and other programs, to lower the priority of the submission
  76.    Set to 0, or '', if you don't want to do this "priority modification"
  77.    For example, the freeware SPE package can use used to execute programs
  78.    using a given priority; with a syntax of SPE i-20 file.cmd opt1 opt2.
  79.    In this example, EXEC_MODIFIER would be 'SPE i-20 ', and you should
  80.    have a copy of SPE.EXE in your PATH.
  81. */
  82. exec_modifier=' ' 
  83.  
  84. /* Add hit number to matches (i.e.; 1).... 20) )
  85.    Set to 1 to enable, 0 to disable */
  86. Add_Hit_Num=1
  87.    
  88.  
  89. /* Suppress writing the "Tips" section in the "search form"
  90.    NO_TIPS=1 : suppress
  91.    NO_TIPS=0 : do NOT suppress 
  92. */
  93. no_tips=0
  94.  
  95. /* ovewrite=1 means "overwrite files",0 means "use new name"
  96.   This can be overridden by an OVERWRITE=1 or OVERWRITE=2 (2=no) request option */
  97. overwrite=1
  98.  
  99.  
  100. /* DEF_HTMLS is used to identify extensions used for HTML documents.
  101.    This is ONLY used when summaries are being created "on the fly". At 
  102.    other times, parameters in the configuration file are used */
  103. def_Htmls="SHT SHTML HTM HTML HTM-SSI HTML-SSI"
  104.  
  105.  
  106. /* CGI_STRING is the "prefix" for cgi-bin scripts. If blank, then
  107.    /cgi-bin/ is used. This is used in "description regeneration" lists */
  108. cgi_string=''
  109.  
  110. /********************** END of  USER CONFIGURABLE PARAMETERS ****************/
  111.  
  112. goswish:
  113. parse arg  ddir, tempfile, reqstrg,list,verb ,uri,user, ,
  114.           basedir ,workdir,privset,enmadd,transaction,verbose, ,
  115.          servername,host_nickname,homedir,xx,semqueue,prog_file
  116.  
  117. signal on error name foo10 ; signal on syntax name foo10
  118.  
  119. call load_dll           /* load some dlls */
  120.  
  121. crlf='0d0a'x
  122.  
  123. if abbrev(strip(ddir),'*DESCRIBE')=1 then do 
  124.     verb='DESCRIBE'
  125.     parse var ddir . daswishdir dawwwdir daswifile ','dafdescribe','darepwith','datype','dasummfile
  126. end /* do */
  127.  
  128. if WEB_ROOT_DIR=0 then WEB_ROOT_DIR=""                    /* double check directories */
  129. if SWISH_DIR=0 then SWISH_DIR=""
  130. privset=translate(privset)
  131.  
  132. if exec_modifiler=0 then exec_modifier=''
  133.  
  134. use_swish_dll=0
  135. if translate(swish_version)="13_DLL" then do
  136.   swish_version=13
  137.   use_swish_dll=1
  138. end
  139.  
  140. /* 
  141. Check for CGI-BIN call */
  142. is_cgi=0
  143. if verb="" then do    /* is it cgi-bin? */
  144.    method = value("REQUEST_METHOD",,'os2environment')
  145.    if method="" then do
  146.      say "This script is not meant to be run in standalone mode "
  147.      exit
  148.    end  /* Do */
  149.    else do
  150.       is_cgi=1
  151.       if method='GET' then do
  152.           list=value("QUERY_STRING",,'os2environment')
  153.       end
  154.       else do
  155.          tlen = value("CONTENT_LENGTH",,'os2environment')
  156.          list=charin(,,tlen)
  157.       end /* do */
  158.       servername=value("SERVER_NAME",,'os2environment')
  159.    end
  160.    if WEB_ROOT_DIR='' then WEB_ROOT_DIR=directory()
  161.    if SWISH_DIR='' then SWISH_DIR=directory()
  162.    prog_file=''
  163. end
  164.  
  165. list0=list              /* used by search_it et al */
  166.  
  167. /* clear up directory names */
  168.  
  169. SWISH_DIR=strip(translate(SWISH_DIR,'\','/'),'t','\')
  170. okk=dir_exists(SWISH_DIR)
  171. if okk=0 then do
  172.     foo=is_error(' Sorry, bad index directory: 'SWISH_DIR)
  173.     exit
  174. end /* do */
  175. WEB_ROOT_DIR=strip(WEB_ROOT_DIR,'t','\')
  176. okk=dir_exists(WEB_ROOT_DIR)
  177. if okk=0 then do
  178.     foo=is_error(' Sorry, bad www directory: 'WEB_ROOT_DIR)
  179.     exit
  180. end /* do */
  181.  
  182. /* set defaults */
  183.  
  184. deflist='sel swifile repwith  indexname  indexadmin indexdescription indexpointer ',
  185.         'extlist extlist_nofollow ignorelimit ignorewords file mode summaryfile ',
  186.         ' makesummary filename  describefile htmls dostem propnames metanames ',
  187.         'fr_directory fr_title  fr_filename fr_pathname  watch searchdoc dctfile ' ,
  188.         'FORM_TITLE RESULTS_TITLE  indexcomments showprop swishversion overwrite '
  189.  
  190. deflist=translate(deflist)
  191.  
  192. vs.!verbose=3
  193. vs.!wwwdir=WEB_ROOT_DIR         /* NOTE: wwwdir request option no longer supported */
  194. vs.!FORM_TITLE=''
  195. vs.!RESULTS_TITLE=''
  196. vs.!sel='/'
  197. vs.!showprop=''
  198. vs.!indexcomments=0
  199. vs.!overwrite=overwrite
  200. vs.!searchdoc=''
  201. vs.!dctfile=''
  202. vs.!summaryfile=''
  203. vs.!dostem=0
  204. vs.!propnames=0
  205. vs.!metanames=0
  206. vs.!repwith=0
  207. vs.!watch=1
  208. vs.!indexname=0 
  209. vs.!indexdescription=0
  210. vs.!indexadmin='Created by 'user
  211. vs.!indexpointer=servername
  212. vs.!makesummary=0
  213. vs.!swishversion=swish_version
  214. vs.!swifile=''
  215. vs.!extlist='.htm .txt .gif .xbm .jpg .doc .sht .html .shtml '
  216. vs.!extlist_nofollow=' .gif .xbm .jpg '
  217. vs.!ignorelimit='50 100'
  218. vs.!ignorewords='SwishDefault'
  219.  
  220. vs.!fr_pathname='contains admin testing demo trash construction PRIVATE private confidential '
  221. vs.!fr_filename='contains # % ~ .bak .orig .old old. '
  222. vs.!fr_title='contains construction example pointers '
  223. vs.!fr_directory='contains .htaccess'
  224.  
  225. vs.!htmls=" HTM HTML SHTML SHT "
  226. vs.!describefile='DESCRIBE.TXT'
  227.  
  228.  
  229. /* parse options, and load them into the "VS." stem variable */
  230. do until list=""
  231.    parse var list aw '&' list
  232.    parse var aw a1 '=' a2
  233.    a1=translate(strip(a1))
  234.    if wordpos(a1,deflist)=0 then iterate  /* not a valid option */
  235.    aa='!'||a1
  236.    a2=strip(decodekeyval(translate(a2,' ','+'||'00090a0d'x)))
  237.    if a2="" | a2=0 then iterate                /* blank,  don't change */
  238.    vs.aa=a2
  239. end /* do */
  240.  
  241. if vs.!summaryfile<>"" then vs.!dctfile=vs.!summaryfile
  242.  
  243. swish_version=vs.!swishversion          /* might be user specified */
  244. if wordpos(swish_version,'11 12 13 13_DLL')=0 then do
  245.    if is_cgi=1 then say "ERROR: not a known swish version " swish_version
  246.    exit
  247. end /* do */
  248. if translate(swish_version)="13_DLL" then do
  249.   swish_version=13
  250.   use_swish_dll=1
  251. end
  252.  
  253.  
  254. /* clean up the options */
  255. vs.!repwith=translate(vs.!repwith,' ',',"'||"'"||'00090d0a'x)
  256.  
  257. select
  258.    when  swish_version=11 then do             /* suppress 1.2+ options? */
  259.        vs.!dostem=0
  260.        vs.!indexcomments=1
  261.        vs.!propnames=0
  262.        vs.!metanames=0
  263.        vs.!showprop=0
  264.    end
  265.    when  swish_version=12 then do             /* suppress 1.3 options? */
  266.        vs.!dostem=0
  267.        vs.!propnames=0
  268.        vs.!showprop=0
  269.    end
  270.    otherwise do
  271.      if wordpos(translate(vs.!dostem),'1 YES Y')>0 then vs.!dostem=1
  272.      if wordpos(translate(vs.!dostem),'0 NO N')>0 then vs.!dostem=0
  273.    end
  274. end
  275.  
  276. /*** Check for SEARCH mode or LIST INDICES MODE DREGEN 2DREGEN REGEN REGEN2 */
  277.  
  278. if abbrev(translate(vs.!mode),'S')=1 then do   /* SEARCH MODE */
  279.   foo=search_it(list0)
  280.   return 0
  281. end /* do */
  282.  
  283. if abbrev(translate(Vs.!mode),'L')=1  then do  /* LIST INDICES MODE */
  284.   foo=show_forms(list0)
  285.   return 0
  286. end /* do */
  287.  
  288. if abbrev(translate(Vs.!mode),'REGEN')=1  then do  /* choose index to regenerate */
  289.   foo=choose_confile(list0)
  290.   return 0
  291. end /* do */
  292.  
  293. /* choose descriptive summaries to regenerate */
  294. /************ n.a. 
  295. if abbrev(translate(Vs.!mode),'DREGEN')=1  then do 
  296.   foo=choose_dctfile(list0)
  297.   return 0
  298. end   ***********/
  299.  
  300.  
  301. /* regen descriptive summaries */ 
  302. /**************  N.a.
  303. if abbrev(translate(Vs.!mode),'2DREGEN')=1  then do 
  304.  
  305.   dafile='<html><head><title>Regenerating descriptive summaries</title>'crlf
  306.   dafile=dafile||'<body><h2>Regenerating descriptive summaries</h2>'crlf
  307.   dafile=dafile||'Regenerating descriptive summaries for  'vs.!swifile ' <p>'
  308.   dafile=dafile||'<em>with search document of: </em> <a href="'vs.!searchdoc'">'vs.!searchdoc'</a><p>'
  309.  
  310.   if is_cgi=0 then do
  311.     fii=value('SREF_PREFIX',,'os2environment')
  312.     if fii='' then do            
  313.        if fex>0 then  foo=sref_expire_response(fex,0,,'Y')
  314.       'SEND TYPE  text/html '
  315.       'var name dafile'
  316.     end
  317.     else do
  318.        fii=sref_multi_send(dafile,'text/html','1S')  
  319.     end 
  320.   end
  321.   else do
  322.      say 'Content-Type: text/html'
  323.      say ""
  324.      say dafile           
  325.   end
  326.   vs.!watch=0
  327.   vs.!makesummary=2
  328.   signal jump3
  329. end  *******************************  */
  330.  
  331. if abbrev(translate(Vs.!mode),'2REGEN')=1  then do  /* provides a conf file to reuse */
  332.  
  333.   isconf=use_conffile(list0)
  334.   if isconf=0 then return 0  /* no such configuration file */ 
  335.   parse var isconf conffile (crlf)   .
  336.   dafile='<html><head><title>Regenerating a Swish Index</title>'crlf
  337.   dafile=dafile||'<body><h2>Regenerating a Swish Index</h2>'crlf
  338.   dafile=dafile||'Using 'conffile ' to regenerate a swish index <p>'crlf
  339.   dafile=dafile||'<em>with search document of: </em> <a href="'vs.!searchdoc'">'vs.!searchdoc'</a><br>'crlf
  340.   dafile=dafile||' Note that <tt>descriptive summaries</tt> will <b>not</b> be regenerated<p>'crlf
  341.   if is_cgi=0 then do
  342.     fii=value('SREF_PREFIX',,'os2environment')
  343.     if fii='' then do             /* 1.2 */
  344.        if fex>0 then  foo=sref_expire_response(fex,0,,'Y')
  345.       'SEND TYPE  text/html '
  346.       'var name dafile'
  347.     end
  348.     else do
  349.        fii=sref_multi_send(dafile,'text/html','1S')  /* sre ver 1.3 */
  350.     end /* do */
  351.   end
  352.   else do
  353.      say 'Content-Type: text/html'
  354.      say ""
  355.      say dafile           /* cgi-bin output */
  356.   end
  357.  
  358.   vs.!watch=0
  359.   signal jump2
  360.  
  361. end /* do */
  362.  
  363.   
  364.  
  365.  
  366. /***** IF here--- we are making an index, or making a description */
  367. /* is this an "addon" call, other then for "making descriptions ? */
  368. if is_cgi=0 & verb<>'DESCRIBE' then do    /* yes, let's check SRE-http privileges */
  369.   isp=0
  370.   if wordpos('*',need_privs)>0 then do
  371.      isp=1
  372.   end /* do */
  373.   else do
  374.     do mm=1 to words(need_privs)
  375.         aww=strip(translate(word(need_privs,mm)))
  376.         if wordpos(aww,privset)>0  then do
  377.             isp=mm ; leave
  378.         end /* do */
  379.     end /* do */
  380.   end
  381.   if isp=0 then do
  382.       'header add WWW-Authenticate: Basic Realm=<!SWISH_INDEX>'  /* challenge */
  383.        return sref_response('unauth', "You do not have SWISH Index creation rights ",tempfile,servername)
  384.   end  /* Do */
  385.   if  method="GET" then    parse var uri . '?' list   
  386.   if WEB_ROOT_DIR='' then WEB_ROOT_DIR=ddir
  387.   if SWISH_DIR='' then SWISH_DIR=get_value('workdata_dir')
  388. end
  389.  
  390. /* if here, either not an sre-http addon call, or sre-http privileges are fine. */
  391.  
  392. /*  If it's not a "Make description call", then determine the "index file" */
  393. if verb<>"DESCRIBE" then do             /* creating an index */
  394.    vs.!swifile=mk_filename(vs.!swifile,SWISH_DIR,'INDEX','SWI',vs.!Overwrite)
  395.    foo=sysfiledelete(vs.!swifile)
  396. end
  397.  
  398. vs.!wwwdir=strip(translate(vs.!wwwdir,'\','/'),'t','\')  /* fix up the WEB_ROOT_DIR */
  399. if dir_exists(vs.!wwwdir)=0 then do
  400.     foo=is_error(' Sorry, no such Web_Root directory: 'vs.!wwwdir)
  401.     exit
  402. end
  403.  
  404. /*** Let's clean up some more parameters, now that we now we might need 'em */
  405.  
  406. /* What type of "summary" should be made? (if any)*/
  407. vv=translate(vs.!makesummary)
  408. select
  409.    when wordpos(vv,'N NO 0')>0 then
  410.     vs.!makesummary=0
  411.    when wordpos(vv,'Y YES 1')>0 then
  412.      vs.!makesummary=1
  413.    when wordpos(vv,'C CREATE 2')>0 then
  414.      vs.!makesummary=2
  415.   otherwise
  416.      vs.!makesummary=0
  417. end
  418. if vs.!makesummary>0 then do
  419.    parse var vs.!swifile taa '.' .   
  420.    vs.!dctfile=taa||'.dct'
  421. end /* do */
  422. tt=""
  423. do until vs.!htmls=""           /* list of HTML extentions */
  424.    parse var vs.!htmls a1 vs.!htmls ;a1=strip(a1)
  425.    tt=tt||' '||strip(a1,'l','.')
  426. end /* do */
  427. vs.!htmls=strip(tt)
  428.  
  429. tt=""                           /* list of "text" extensions */
  430. vs.!extlist=translate(vs.!extlist,' ','00090a0d'x||',')
  431. do until vs.!extlist=""
  432.    parse var vs.!extlist a1 vs.!extlist ;a1=strip(a1)
  433.    tt=tt||' .'||strip(a1,'l','.')
  434. end /* do */
  435. vs.!extlist=strip(tt)
  436.  
  437.  
  438. tt=""                           /* list of "non text, but index anyways, extensions */
  439. do until vs.!extlist_nofollow=""
  440.    parse var vs.!extlist_nofollow a1 vs.!extlist_nofollow ;a1=strip(a1)
  441.    tt=tt||' .'||strip(a1,'l','.')
  442. end /* do */
  443. vs.!extlist_nofollow=strip(tt)
  444.  
  445.  
  446. /* used in sre-http addon mode (to enable real time reporting of status */
  447. if wordpos(translate(vs.!watch),'1 YES Y')>0 then vs.!watch=1
  448. if wordpos(translate(vs.!watch),') NO N')>0 then vs.!watch=0
  449. if is_cgi=1 then vs.!watch=0    /* cgi-bin monitoring of output is too hard */
  450.  
  451. vs.!sel=space(translate(vs.!sel,' ','00090d0a'x))
  452. vs.!selorig=vs.!sel
  453.  
  454. vsel=vs.!sel                    /* fix up each of possibly several "directories to index */
  455. vs.!sel='' 
  456. do forever                      /* fix up \'s */
  457.    if vsel='' then leave
  458.    parse var vsel a1 vsel ; a1=strip(a1)
  459.    a1=translate(a1,'\','/')
  460.    a1=strip(a1,,'\')
  461.    if pos(':',a1)>0 then 
  462.        vs.!sel=vs.!sel' 'a1
  463.    else
  464.        vs.!sel=vs.!sel'  \'||a1
  465. end /* do */
  466.  
  467. if datatype(vs.!verbose)<>'NUM' then vs.!verbose=3
  468. if vs.!verbose>3 | vs.!verbose<0 then vs.!verbose=3
  469.  
  470.  
  471. /***  Make a summary; from an invocation of GOSWISH (as a 2nd, detached process) */
  472. if verb="DESCRIBE" then   do    /* make a summary mode ? */
  473.    vs.!swifile=daswifile ; SWF=VS.!SWIFILE
  474.    vs.!dctfile=dasummfile
  475.    vs.!makesummary=datype
  476.    vs.!watch=0 ; vs.!mode='SUMMARY'
  477.    vs.!repwith=darepwith
  478.    vs.!describefile=dafdescribe
  479.    web_root_dir=dawwwdir
  480.    vs.!wwwdir=dawwwdir
  481.    swish_dir=daswishdir
  482.    do forever           /* wait until vs.!swifile is avaiable */   
  483.        if stream(swf,'c','query exists')<>"" then leave
  484.        call syssleep 2
  485.    end /* do */
  486.    call syssleep 1
  487.    fpp=make_dctfile()
  488.    exit
  489. end                     /* When done making summary, EXIT */
  490.  
  491. /**** If here, we are making a swish index   -------------------- */
  492.  
  493. /* the search-form document to create (and a link to it */
  494. usedoc0=translate(strip(vs.!searchdoc),' ','+')
  495. parse var usedoc0 usedoc doob
  496. aform=mk_filename(usedoc,vs.!wwwdir,'SEARCH','HTM',vs.!overwrite)
  497. foo=sysfiledelete(aform)
  498. if words(usedoc0)=1 then
  499.       doob=translate(substr(aform,length(vs.!wwwdir)+1),'/','\')
  500. doob=translate(substr(aform,length(vs.!wwwdir)+1),'/','\')
  501. if pos('.',doob)=0 then doob=doob'.'   /* avoid "implicit directory types of problems*/
  502.  
  503. yeek=filespec('D',aform)||filespec('P',aform)
  504. if dir_exists(yeek)=0 then do
  505.      foo=is_error(' Sorry, bad search-document name: 'aform)
  506.      exit
  507. end /* do */
  508. fff=sysfiledelete(aforM)
  509.  
  510. if vs.!indexdescription=0 | vs.!indexdescription=' ' then 
  511.    vs.!indexdescription=vs.!selorig' on ' servername
  512. if vs.!indexname=0 | vs.!indexname=' ' then 
  513.   vs.!indexname='Index of 'vs.!selorig
  514.  
  515. /* write the response to client */
  516.  
  517. dafile='<html><head><title>Swish Configuration File</title>'crlf
  518. dafile=dafile||' <SCRIPT language="Javascript">'crlf
  519. dafile=dafile||'<!-- 'crlf
  520. dafile=dafile||'var iloaded=0 'crlf
  521.  
  522. dafile=dafile||'function chekit(aname) { 'crlf
  523. dafile=dafile||'  if (iloaded==1) {return true}'crlf
  524. dafile=dafile||'  return window.confirm("GoSWISH is still uploading contents...\n' , 
  525.                '  Are you sure you want to load: \n " +  aname  )'crlf
  526. dafile=dafile||'}'crlf
  527. dafile=dafile||'// -->'crlf
  528. dafile=dafile||'</script>'crlf
  529.  
  530. dafile=dafile'</head>'crlf
  531. dafile=dafile'<body onLoad="iloaded=1">'crlf
  532. dafile=dafile||'<a name="TOP"><h2 align="CENTER">Creating a Swish Index </h2></a>'crlf
  533.  
  534. swiver=1.3
  535. if swish_version=11 then swiver=1.1
  536. if swish_version=12 then swiver=1.2
  537.  
  538. dafile=dafile||'<table><tr><td colspan=2> Using SWISH version: <b>'swiver'</b></td>'crlf
  539. dafile=dafile||'<tr><td valign="TOP" nowrap>Creating an <b>index</b> of files in: </td>'crlf
  540. dafile=dafile||'<td valign="TOP">'vs.!selorig'</td>'crlf
  541. dafile=dafile||'<tr><td valign="TOP">SWISH <b>Index</b> file: </td><td align="top">'vs.!swifile'</td>'crlf
  542. dafile=dafile||'<tr><td valign="TOP"> <tt>Search form</tt>: </td> 'crlf
  543. bobo='"'doob'"'
  544. bobo0="'"doob"'"
  545. if doob<>'' then
  546.   dafile=dafile||'<td valign="TOP"> <a onClick="return chekit('||bobo0||') " href='||bobo||'>'aform||'</a>'crlf
  547. else
  548.   dafile=dafile||' <td valign="TOP">  'aform||crlf
  549. dafile=dafile||'<em>(wait until this page is completely downloaded, and then you can try this link!)</em></td>' 
  550.  
  551.  
  552. if abbrev(translate(vs.!swifile),translate(swish_dir))=1 then 
  553.     eekz=substr(vs.!swifile,length(swish_dir)+2)
  554. else
  555.    eekz=vs.!swifile
  556.  
  557. eekz2=vs.!dctfile
  558.  
  559. if eekz2<>'' then do
  560.   if abbrev(translate(eekz2),translate(swish_dir))=1 then 
  561.     eekz2=substr(eekz2,length(swish_dir)+2)
  562. end
  563. xx=write_form(aform,eekz,eekz2,doob)  /* write stuff to search-form document */
  564.  
  565. dafile=dafile||'<tr><td colspan=2>You can use this <tt>Search form</tt> to search the <TT>'vs.!swifile'</TT> SWISH index'
  566. if vs.!makesummary>0 then do
  567.   dafile=dafile||', or the <TT>'vs.!dctfile '</TT> descriptions file'crlf
  568. end
  569. else do
  570.   dafile=dafile||'.'crlf
  571. end
  572. dafile=dafile||'</td></table>'crlf
  573. if vs.!watch=0  then dafile=dafile||'<p> <b>You may need to wait for a few minutes </b> (until SWISH completes 'vs.!swifile')'crlf
  574.  
  575. parse var vs.!swifile a1 '.' .
  576. cnffile=mk_filename(a1'.CON',swish_dir,'INDEX','.con',vs.!Overwrite)
  577. foo=sysfiledelete(cnffile)
  578.  
  579. dafile=dafile||'<hr><h3> The configuration file </h3> 'crlf
  580. dafile=dafile||' The following configuration file ('cnffile ') is  used to generate the <b>' vs.!swifile '</b> <em> SWISH index</em><br>'
  581.  
  582. if is_cgi=0 then do
  583.   fii=value('SREF_PREFIX',,'os2environment')
  584.   if fii='' then do             /* 1.2 */
  585.      if fex>0 then  foo=sref_expire_response(fex,0,,'Y')
  586.      'SEND TYPE  text/html '
  587.      'var name dafile'
  588.   end
  589.   else do
  590.        fii=sref_multi_send(dafile,'text/html','1S')  /* sre ver 1.3 */
  591.   end /* do */
  592. end
  593. else do
  594.    say 'Content-Type: text/html'
  595.    say ""
  596.    say dafile           /* cgi-bin output */
  597. end
  598. isconf=''
  599.  
  600. jump2:          /* jump here if regenerateing index */
  601. dafile=write_conf(isconf)      /* create the swish configuration file, and run swish */
  602. if dafile=0 & vs.!watch=1 then signal onerr2
  603.  
  604.  
  605. if vs.!watch=0 then do
  606.   dafile='<br><em> Construction of 'vs.!swifile' may take a few minutes.</em><br>'
  607.  call write_her(dafile)
  608. end /* do */
  609.  
  610. jump3:  /* jump here on regenerate summaries, when supported */
  611.  
  612. /* make a summary (here, with echoing; or via a detach */
  613. if vs.!makesummary>0 then do
  614.  
  615.    if vs.!watch=1 then do
  616.  
  617.      call write_her('<hr><pre>')
  618.      aa=time('r')
  619.      swf=vs.!swifile
  620.      do forever           /* wait until vs.!swifile is avaiable */   
  621.        if stream(swf,'c','query exists')="" then do
  622.           if is_cgi=0 then do
  623.              if vs.!watch=1 then call write_her('Waiting for 'swf' '||time('e'))
  624.               if result<0  then return 0
  625.           end /* do */
  626.           call syssleep 1
  627.           iterate
  628.        end /* do */
  629.        else do
  630.          if vs.!watch=1 then call write_her('</pre><h3>Creating Descriptions </h3>')
  631.          leave
  632.        end
  633.      end /* do */
  634.  
  635.      fpp=make_dctfile()     /* make_dctfile does the summary creation */
  636.    end                  /* watch mode */
  637.    else do              /* non-watch -- detach GoSWISH in DESCRIBE mode*/
  638.       if prog_file<>" " then
  639.           xxx=prog_file
  640.       else
  641.           xxx=SWISH_DIR'\goswish'
  642.       tmp1=translate(vs.!repwith,'\','/')
  643.       arglist='*DESCRIBE ' ,
  644.                 swish_dir' 'web_root_dir' 'vs.!swifile','vs.!describefile','tmp1',' ,
  645.                 vs.!makesummary',' , 
  646.                 vs.!dctfile
  647.       if is_cgi=0 then do
  648.          gloob=exec_modifier||xxx
  649.  
  650.          address cmd 'detach  'gloob' 'arglist
  651.       end
  652.       else do
  653.          crob=left(vs.!selorig,min(35,length(vs.!selorig)))
  654.  
  655.          bubba='"Descriptions of 'crob'" /C /MIN  'exec_modifier||xxx ' 'arglist ' > nul '
  656.          address cmd '@start 'bubba
  657.       end /* do */
  658.  
  659.    end /* do */
  660. end
  661.  
  662. call write_her('<hr><a href="#top">Top of document</a>')
  663.  
  664. onerr2:  nop                     /* jump here on error (i.e.; no such dir */
  665. dafile='</pre></body></html>'
  666. call write_her(dafile)
  667.  
  668. if is_cgi=0 then  do
  669.   if fii='' then   /* sre 1.2 */
  670.    'SEND COMPLETE '
  671.   else
  672.      foo=sref_multi_send(' ',,'1E')  /* sre 1.3 */
  673. end
  674.  
  675. /* write info to the "index "*/
  676. tbo=date('n')' 'time('n')
  677. if vs.!makesummary>0 then tbo=tbo' (w/summaries) '
  678. aline=doob','aform','vs.!swifile' 'cnffile' 'vs.!dctfile' 'vs.!describefile','tbo','vs.!indexname
  679. goindx=SWISH_DIR'\goswish.ind'
  680. if stream(goindx,'c','query exists')<>"" then do
  681.     oo=translate(stream(goindx,'c','open'))
  682.     if abbrev(oo,'READY')=0 then return 0        /* can't open, give up */
  683.     aa=charin(goindx,1,chars(goindx))
  684.     aa=strip(aa,'t','1a'x)
  685. end
  686. else do
  687.     aa=''
  688. end /* do */
  689. aa=aline||'0d0a'x||aa
  690. aa2=charout(goindx,aa,1)
  691. foo=stream(goindx,'c','close')
  692. return 0
  693.  
  694. /***********************/
  695. /* write the configuration file, with parameters */
  696. write_conf:procedure expose vs. SWISH_DIR WEB_ROOT_DIR servername is_cgi realsel realdir ,
  697.                 enmadd ddir transaction homedir host_nickname cnffile swish_version ,
  698.                 exec_modifier use_swish_dll
  699. crlf='0d0a'x
  700.  
  701. parse arg gotconf
  702.  
  703. use_swish_dll=0         /* for now, suppress use of dll on writes */
  704.  
  705.  
  706. if gotconf<>"" then do  /* user supplied configuration file */
  707.    parse arg cnffile (crlf) gotconf
  708.    aboo='<pre>'gotconf'</pre>'
  709.    call write_her(aboo)
  710.    signal makeindx
  711. end /* do */
  712.  
  713. /* else, write conf file from form input */
  714.  
  715. if is_cgi=0 then do             /* use a virtual dir */
  716.     vsel=vs.!sel ; realdir='' ; realsel=''
  717.     do forever
  718.        if vsel='' then leave
  719.        parse var vsel eek1 vsel ; eek1=strip(eek1)
  720.        if pos(':',eek1)=0 then do
  721.            eek1=translate(eek1,'/','\')||'/'
  722.            realdir9=sref_do_virtual(ddir,eek1,enmadd,0,trans,homedir,host_nickname)
  723.        end /* do */
  724.        else do
  725.            realdir9=eek1
  726.        end
  727.        realdir=realdir' 'strip(realdir9,'t','\')
  728.        if eek1='//' | eek1='/' then 
  729.           realsel=realsel' /'
  730.       else
  731.          realsel=realsel' 'strip(eek1,'t','/')
  732.    end
  733. end
  734. else do
  735.     vsel=vs.!sel ; realdir='' ; realsel=''
  736.     do forever
  737.        if vsel='' then leave
  738.        parse var vsel eek1 vsel ; eek1=strip(eek1)
  739.        if pos(':',eek1)=0 then do
  740.            eek1=translate(eek1,'/','\')
  741.            realdir9=strip(strip(vs.!wwwdir,'t','\')||eek1,'t','\')
  742.            realdir9=translate(realdir9,'\','/')
  743.        end /* do */
  744.        else do
  745.            realdir9=eek1
  746.        end
  747.        realdir=realdir' 'strip(realdir9,'t','\')
  748.        if eek1='//' | eek1='/' then 
  749.           realsel=realsel' /'
  750.       else
  751.          realsel=realsel' 'strip(eek1,'t','/')
  752.  
  753.    end
  754. end
  755. crlf='0d0a'x
  756.  
  757. do ii=1 to 50
  758.    conf.ii=' '
  759. end
  760.  
  761. conf.0=50
  762. swiver=1.3
  763. if swish_version=11 then swiver=1.1
  764. if swish_version=12 then swiver=1.2
  765. if swish_version=13 then swiver=1.3
  766. conf.1='#Auto-generated SWISH (ver 'swiver') configuration file '||date('n')' 'time('n')
  767. conf.3=' '
  768. conf.4='# space delimited list of files/directories to index '
  769.  
  770. conf.5='IndexDir '
  771. rrr=fixslash(realdir,swish_version)
  772. do ik=1 to words(rrr)
  773.    rrr1=strip(word(rrr,ik))
  774.    if pos('*',rrr1)=0 then  do
  775.       conf.5=conf.5' 'rrr1
  776.    end
  777.    else do
  778.      oo=sysfiletree(rrr1,'tff','FO')
  779.      if tff.0>1 & length(conf.5)>30 then conf.5=conf.5||crlf||'IndexDir ' 
  780.      do ik2=1 to tff.0
  781.          rrr3=fixslash(tff.ik2,swish_version)
  782.          conf.5=conf.5' 'rrr3
  783.          if (ik2//5)=4 then conf.5=conf.5||crlf||'IndexDir ' 
  784.      end /* do */
  785.    end   
  786. end /* do */
  787.  
  788.  
  789. /* quick check on # of files to be indexed */
  790. do mm=1 to words(realdir)
  791.    dadd=strip(word(realdir,mm))
  792.    if pos('*',dadd)=0 then do
  793.      if dir_exists(dadd)=0 then do                /* no such dir! */
  794.         call write_her('<B> Error. No such directory: 'dadd)
  795.         return 0  
  796.      end /* do */
  797.      dadd2=strip(dadd,'t','\')||'\*.*'
  798.      oo=sysfiletree(dadd2,'tff','FSO')
  799.      oo2=sysfiletree(dadd2,'tff2','DSO')
  800.      conf.5=conf.5||crlf||'# 'dadd' contains 'tff2.0' subdirectories and 'tff.0' files'
  801.    end
  802.    else do
  803.      oo=sysfiletree(dadd,'tff','FO')
  804.      conf.5=conf.5||crlf||'# 'dadd' matches 'tff.0' files'
  805.    end /* do */
  806. end /* do */
  807.  
  808.  
  809. conf.6=' '
  810. conf.7='# the generated index file '
  811. conf.8='IndexFile '||fixslash(vs.!swifile,swish_version)
  812. conf.9=' '
  813. conf.10='#some identification info '
  814.  
  815. conf.11='IndexName 'vs.!indexname
  816. conf.12='IndexDescription 'vs.!indexdescription
  817.  
  818. conf.13='IndexPointer 'vs.!indexpointer
  819. conf.14='IndexAdmin 'VS.!indexadmin
  820. conf.15=' '
  821. conf.16='# Only files with these suffixes will be indexed.'
  822. if pos('*',vs.!extlist)=0 then
  823.     conf.17='IndexOnly 'vs.!extlist
  824. conf.18='# but do not look at contents of these files '
  825. if pos('*',vs.!extlist_nofollow)=0 then
  826.    conf.19='NoContents 'vs.!extlist_nofollow 
  827.  
  828. conf.21='# this converts fully qualified file references into urls '
  829. /* do the replace rules */
  830. conf.22=''
  831.  
  832. if vs.!repwith=0 | vs.!repwith=' ' then do   /* defaults */
  833.   repwithb=''; vs.!repwith=''
  834.   do mm=1 to words(realsel)
  835.      aw=strip(word(realsel,mm))
  836.      if pos(':',aw)>0 then iterate  /* no auto reprules for fully qualified dirs */
  837.      if aw='/' then aw=''   /* if "search web_root was chowdn */
  838.      if pos('*',aw)>0 then do
  839.         jm=max(lastpos('\',aw),lastpos('/',aw))
  840.         if jm>0 then aw=left(aw,jm-1)
  841.      end 
  842.      repwithb='http://'||servername||aw
  843.      rdir=strip(word(realdir,mm))
  844.      if pos('*',rdir)>0 then do
  845.         jm=max(lastpos('\',rdir),lastpos('/',rdir))
  846.         if jm>0 then rdir=left(rdir,jm-1)
  847.      end /* do */
  848.      repwitha=fixslash(rdir,swish_version)
  849.      if conf.22<>'' then conf.22=conf.22||'0d0a'x
  850.      conf.22=conf.22|| ,
  851.          'ReplaceRules replace "'repwitha'"  "'||repwithb||'" '
  852. /* vs.!repwith is used in make_dctfile */
  853.      vs.!repwith=vs.!repwith' 'repwitha' 'repwithb
  854.   end
  855. end 
  856. else do         /* do user specified */
  857.   tmp=vs.!repwith
  858.   if translate(Tmp)='NONE' | translate(tmp)='NO' then do
  859.        conf.22='# no replace rules were specified '
  860.   end /* do */
  861.   else do
  862.     repwitha='' ; repwithb=''
  863.     do forever
  864.       parse var tmp a1 a2 tmp 
  865.       if a2='' then leave 
  866.       a1=fixslash(strip(a1),swish_version) ; a2=strip(a2)
  867.       if conf.22<>'' then conf.22=conf.22||'0d0a'x
  868.       conf.22=conf.22|| ,
  869.          'ReplaceRules replace "'a1'"  "'||a2||'" '
  870.     end
  871.   end           /* reprules <> NONE */
  872. end
  873.  
  874. conf.24='# these are used to not search files and directories '
  875. if vs.!fr_pathname<>0 & vs.!fr_pathname<>' ' then conf.25='FileRules pathname 'vs.!fr_pathname
  876. if vs.!fr_filename<>0 & vs.!fr_filename<>" " then conf.26='FileRules filename 'vs.!fr_filename
  877. if vs.!fr_title<>0 & vs.!fr_title<>' 'then conf.27='FileRules title 'vs.!fr_title
  878. if vs.!fr_directory<>0 & vs.!fr_directory<>' 'then conf.28='FileRules directory 'vs.!fr_directory
  879. conf.30='# ignore certain common words '
  880. conf.31='IgnoreLimit ' vs.!ignorelimit
  881. conf.32='IgnoreWords ' vs.!ignorewords
  882.  
  883. conf.34='# the following are SWISH 1.3 options '
  884. conf.35='#  UseStemming yes to apply word stemming algorithm during indexing, no otherwise'
  885.  
  886. if swish_version=13  then do
  887.   conf.36='UseStemming no'
  888.   if vs.!dostem=1 then  conf.36='UseStemming yes'
  889. end
  890. else do
  891.    conf.36='# UseStemming not supported under SWISH 1.2 or less '
  892. end /* do */
  893.  
  894. conf.37='# IndexComments 1 to NOT examine html comments, 0 otherwise '
  895. if swish_version<>11 then do
  896.   conf.38="IndexComments 0"
  897.   if vs.!indexcomments=1 then conf.38="IndexComments 1"
  898. end
  899. else do
  900.    conf.38="# IndexComments not supported under SWISH 1.1 "
  901. end /* do */
  902.  
  903.  
  904. conf.40='# List of meta tags names that can be retrieved with the -p option.'
  905. if swish_version=11 | swish_version=12 then do
  906.    conf.41='# PropertyaNames not supported under SWISH 1.2 or less '
  907. end /* do */
  908. else do
  909.   if vs.!propnames=0 | vs.!propnames='' then
  910.       conf.41='#PropertyNames description author datamodified'
  911.   else
  912.       conf.41='PropertyNames 'vs.!propnames
  913. end
  914.  
  915.  
  916. conf.42='# List of metanames for use with -w mname=awords option.'
  917. if swish_version=11  then do
  918.    conf.43='# MetaNames not supported under SWISH 1.1 '
  919. end /* do */
  920. else do
  921.   if vs.!metanames=0 | vs.!metanames='' then
  922.       conf.43='MetaNames '
  923.   else
  924.       conf.43='MetaNames 'vs.!metanames
  925. end
  926.  
  927.  
  928.  
  929. conf.46='# verbosity, and an os/2 necessary switch '
  930. conf.47=' IndexReport ' vs.!verbose
  931. conf.48=' followSymLinks no '
  932.  
  933.  
  934. aboo=""
  935. do mm=1 to conf.0
  936.  call lineout cnffile,strip(conf.mm)
  937.   aboo=aboo||conf.mm||'0d0a'x
  938. end /* do */
  939. call lineout cnffile
  940.  
  941. aboo='<pre>'aboo'</pre>'
  942. call write_her(aboo)
  943.  
  944. makeindx:  /* jump here if user supplied configuration file */
  945. /* which swish? */
  946. select
  947. /*   when use_Swish_dll=1 then nop   -- doesn't work yet */
  948.    when swish_version=11 then   xxx=SWISH_DIR'\swish'
  949.    otherwise   xxx=SWISH_DIR'\swish-e'
  950. end
  951.  
  952. if use_swish_dll=0 then do
  953.   if exec_modifier<>'' & exec_modifier<>0 then
  954.      xxx2=exec_modifier' 'xxx
  955.   else
  956.     xxx2=xxx
  957. end
  958.  
  959. /* cgi bin? */
  960. if is_cgi=1 & use_swish_dll=0 then do
  961.    if stream(xxx'.exe','c','query exists')="" then do
  962.       say "<b> ERROR: Could not find " xxx'.exe </b>'
  963.       return 0
  964.    end
  965.    address cmd '@START "Swish Index for 'VS.!selorig '" /N /MIN 'xxx2 ' -c  'cnffile ' > nul'  
  966.    call write_her('<p><em>Hint: you can monitor the status of SWISH by viewing the <tt>ctrl-esc</tt> process list </em>')
  967.    return 1
  968. end
  969.  
  970.  
  971. /* sre-http.. */
  972. /* monitor output via RXQUEUE */
  973. useq=''
  974. if vs.!watch<>0 & use_swish_dll=0 then do
  975.   oldq=rxqueue('g')
  976.   useq=rxqueue('c','SWISHQ')
  977.   foo=rxqueue('s',useq)
  978.   do queued(); pull .; end                   /* flush */
  979. end
  980.  
  981. if use_swish_dll=0 then do
  982.   fdr=directory(swish_dir)
  983.  
  984.   if vs.!watch=1 then do
  985.     if swish_version=11 then
  986.        address cmd 'detach ' exec_modifier||'swish -c 'cnffile ' | rxqueue  "'useq'"'
  987.     else
  988.       address cmd 'detach ' exec_modifier||'swish-e -c 'cnffile ' | rxqueue  "'useq'"'
  989.   end
  990.   else do
  991.     if swish_version=11 then
  992.        address cmd 'detach ' exec_modifier||' swish -c 'cnffile 
  993.     else
  994.       address cmd 'detach  ' exec_modifier||'swish-e -c 'cnffile 
  995.   end /* do */
  996. end
  997. else do         /* use dll mode */
  998.    rc=rxswEmulate('-c 'cnffile)
  999. end /* do */
  1000.  
  1001.  
  1002. aa=directory(fdr)
  1003. if vs.!watch=0 then return 0
  1004. /* monitor output of swish */
  1005.  
  1006. aboo='<hr><h3> SWISH Results </h3><pre>'||crlf
  1007. call write_her(aboo)
  1008. if result<0 then do
  1009.       'string 'crlf||'</pre> .. broken connection, but SWISH is still running)<p> '
  1010.       return 0
  1011. end
  1012.  
  1013. oo=time('r')
  1014. ipo=0
  1015. do forever
  1016.   ipo2=0 ;bbb=""
  1017.   if queued()>0 then do
  1018.      parse pull aline
  1019.      if TRANSLATE(strip(aline))='INDEXING DONE!' then leave
  1020.      ipo2=ipo2+1 ;ipo=0
  1021.      bbb=bbb||aline||crlf
  1022.      if ipo2>10 then do
  1023.          call write_her(bbb)
  1024.          bbb=""
  1025.         foo=time('r')
  1026.      end
  1027.   end
  1028.   if length(bbb)>0 then do
  1029.         call write_her(bbb)
  1030.         foo=time('r')
  1031.   end
  1032.   if time('e')>15 then do
  1033.       'string 'crlf||'</pre> ... (monitoring now ending, but SWISH is still running)<p> '
  1034.       return 0
  1035.   end /* do */
  1036. end
  1037.  
  1038. foo=rxqueue('d',useq)
  1039. foo=rxqueue('s',oldq)
  1040.  
  1041. call write_her('</pre>')
  1042.  
  1043. return 1
  1044.  
  1045. /**************************/
  1046. /* convert \ to / ? */
  1047. fixslash:procedure
  1048. parse arg amess,swver
  1049. if swver=11 then return amess
  1050. return translate(amess,'/','\')
  1051.  
  1052.  
  1053. /**************************/
  1054. /* create file name, numbered from 1...
  1055.  call as:
  1056.      afile=mk_filename(usefile,defdir,defname,detext,overwrite)
  1057.  
  1058. usefile= suggested filename; lots of possibilities 
  1059. defdir = default directory to write to
  1060. defname = default name to use (no path, no extension)
  1061. defext = default extentsion
  1062. overwrite = overwrite file, otherwise modify name 
  1063. ****/
  1064.  
  1065. mk_filename:procedure
  1066. parse arg aname,defdir,defname,defext,overwrite
  1067.  
  1068. defext=strip(strip(defext),,'.'); defname=strip(defname)
  1069. parse var defname defname '.' .
  1070.  
  1071. aname=strip(aname)
  1072. aname=translate(aname,'\','/')
  1073.  
  1074. defdir=strip(translate(defdir,'\','/'),'t','\')
  1075.  
  1076. /* case 1: drive provided; so this is fully qualifed path (or more) */
  1077. if pos(':',aname)>0 then do
  1078.      if right(aname,1)='\'  then do      /* D:\foo\bar\ : a subdir-- use defaults */
  1079.         aname=aname||defname'.'defext
  1080.      end 
  1081.      if pos('.',aname)=0 then do                /* D:\FOO\BAR :  a subdir */
  1082.         aname=aname'\'defname'.'defext
  1083.      end
  1084. end 
  1085. if aname='' then do                     /* use a defaultt */
  1086.     aname=defdir'\'||defname'.'defext
  1087. end
  1088. if pos(':',aname)=0 then do             /* relative dir */
  1089.     aname=defdir||'\'||strip(aname,'l','\')
  1090.     if right(aname,1)='\'  then do      /* D:\foo\bar\ : a subdir-- use defaults */
  1091.         aname=aname||defname'.'defext
  1092.      end /* do */
  1093.      if pos('.',aname)=0 then do                /* FOO\BAR :  a name */
  1094.         aname=aname'.'defext
  1095.      end
  1096. end 
  1097.  
  1098. if overwrite=1 then return aname
  1099.  
  1100. if stream(aname,'c','query exists')="" then return aname  /* doesn't exist, so use */
  1101.  
  1102. /* does exist, and not overwrite -- look for different name */
  1103. PARSE var aname aname '.' aext0
  1104. do mm=1 to 999
  1105.     f1=aname||mm||'.'aext0
  1106.     if stream(f1,'c','query exists')="" then do
  1107.        return f1
  1108.     end /* do */
  1109. end /* do */
  1110. return f1       /* use name999.ext in a pinch */
  1111.  
  1112.  
  1113. /************************************************/
  1114. /* procedure from TEST-CGI.CMD by  Frankie Fan <kfan@netcom.com>  7/11/94 */
  1115. DecodeKeyVal: procedure
  1116.   parse arg Code
  1117.   Text=''
  1118.   Code=translate(Code, ' ', '+')
  1119.   rest='%'
  1120.   do while (rest\='')
  1121.      Parse var Code T '%' rest
  1122.      Text=Text || T
  1123.      if (rest\='' ) then
  1124.       do
  1125.         ch = left( rest,2)
  1126.         if verify(ch,'01234567890ABCDEF')=0 then
  1127.            c=X2C(ch)
  1128.         else
  1129.            c=ch
  1130.         Text=Text || c
  1131.         Code=substr( rest, 3)
  1132.       end
  1133.   end
  1134.   return Text
  1135.  
  1136.  
  1137. /*********/
  1138. /* return error message */
  1139. is_error:procedure expose is_cgi
  1140. parse arg amess
  1141. if  is_cgi=0 then do
  1142.      'string ' amess
  1143. end
  1144. else do
  1145.    say 'Content-type: text/plain'
  1146.    say
  1147.    say amess
  1148. end
  1149. return 1
  1150.  
  1151.  
  1152. /***********/
  1153. /* generate form that calls the "search in a swish index" document */
  1154. write_form:procedure expose vs. is_cgi  swish_version add_hit_num no_tips
  1155. parse arg tofile,swifile,sumfile,doob
  1156. crlf='0d0a'x
  1157. do mmm=1 to 65
  1158.    frm.mmm=''
  1159. end /* do */
  1160.  
  1161. frm.1='<!doctype html public "-//IETF//DTD HTML 2.0//EN">'
  1162. frm.2='<html><head><title>Search an index  </title></head><body>'
  1163.  
  1164. frm.3= '<a name="top"> '
  1165. if vs.!FORM_TITLE='' then do
  1166.    frm.3=frm.3||'<h2 align="CENTER">Search an index of: 'vs.!selorig'</h2></a>'
  1167. end
  1168. else do
  1169.    form_title=translate(form_title,'`','"')
  1170.    frm.3=frm.3||vs.!form_title
  1171. end
  1172. frm.3=frm.3||' </a>'
  1173.  
  1174. if is_cgi=1 then
  1175.    frm.5='<FORM ACTION="/cgi-bin/goswish.cmd" METHOD="POST">'
  1176. else 
  1177.   frm.5='<FORM ACTION="/goswish" METHOD="POST">'
  1178.  
  1179. frm.6='<INPUT TYPE="hidden" NAME="index"  VALUE="'swifile'">'crlf
  1180. if sumfile<>'' then
  1181.    frm.7='<INPUT TYPE="hidden" NAME="dct_file"  VALUE="'sumfile'">'
  1182. frm.8=' '
  1183.  
  1184. if no_tips=0 then
  1185.   frm.9='<a href="#tips"><em>(tips)</em></a>  'crlf
  1186.  
  1187. frm.10='Enter search string: <INPUT TYPE="text" NAME="keyword"  VALUE="help"  SIZE=40 >'
  1188.  
  1189. if vs.!makesummary>0 then do
  1190.      frm.11='    <nobr><input type="checkbox" name="summary" value="1">Display summaries </nobr>'
  1191. end
  1192.  
  1193. /* choose to display property names */
  1194. if vs.!propnames<>0 & vs.!propnames<>''  then do
  1195.   ise=words(vs.!propnames)
  1196.   if vs.!makesummary>0 then ise=ise+1
  1197.   rr='<select name="showprop" size='||strip(ise)' multiple>'||'0d0a'x
  1198.   if vs.!makesummary>0 then do
  1199.         rr=rr||'<Option value="_summary_1">Summary.'||'0d0a'x
  1200.     frm.11='      <nobr>Display: '
  1201.   end /* do */
  1202.   do np=1 to words(vs.!propnames)
  1203.      apr=strip(word(vs.!Propnames,np))
  1204.      rr=rr||'<option value="'apr'">'apr||'0d0a'x
  1205.   end
  1206.   rr=rr||'</select></nobr>'
  1207.   frm.12=frm.12||'0d0a'x||rr
  1208. end
  1209.  
  1210. frm.13='<br>'crlf
  1211. frm.14='<br><INPUT TYPE="submit" VALUE="Start the search"> <INPUT TYPE="reset" VALUE="reset values">'
  1212. frm.15='<h3> Options: </h3>'
  1213. frm.16='<table border=1><tr><td><INPUT TYPE=RADIO NAME="cond" VALUE="OR">Match any word ||'
  1214. frm.17='<INPUT TYPE=RADIO NAME="cond" checked VALUE="AND">Match all words<br>'
  1215. frm.18=''
  1216. frm.19='<INPUT TYPE=RADIO NAME="cond" VALUE="NOT">Match first word, but not others<br>'
  1217. frm.20='<INPUT TYPE=RADIO NAME="option1" VALUE="-m 10">Best 10 matches ||'
  1218. frm.21='<INPUT TYPE=RADIO NAME="option1" checked VALUE="-m 20">Best 20 matches <br>'
  1219. frm.22='<INPUT TYPE=RADIO NAME="option1" VALUE="-m 40">Best 40 matches || '
  1220. frm.23='<INPUT TYPE=RADIO NAME="option1" VALUE="-m 150">Best 150 matches <br>'
  1221. frm.23=frm.23||'0d0a'x||'<INPUT TYPE=RADIO NAME="option1" VALUE="-m 100000">All matches <br>'
  1222.  
  1223. i6=6
  1224. if vs.!makesummary=0 then i6=4
  1225. frm.24='</td><td><SELECT NAME="option2" SIZE='i6'> '
  1226. frm.25='<OPTION SELECTED value="" >Search all documents'
  1227. frm.26='<OPTION value="-t+HB">Search HTML documents: text'
  1228. frm.27='<OPTION value="-t+ehtc">Search HTML documents: "descriptive" elements'
  1229. frm.28='<OPTION value="-t+t">Search HTML documents: <TITLE> only'
  1230. if vs.!makesummary>0 then do
  1231.   frm.29='<option value="summary"> Search "summaries" only'
  1232.   frm.30='<OPTION value="path">Search path and file names only'
  1233.   frm.31='<OPTION value="file">Search file names only'
  1234.  
  1235. /*  frm.33='<input type="checkbox" name="summary" value="1">Display summaries '*/
  1236.   frm.33=''
  1237. end
  1238. frm.32='</SELECT></td></table><p>'
  1239. /* Too slow, so don't make it automatically available.
  1240.  if is_cgi=0 then frm.34='<br> <input type="checkbox" name="exists" value=1">   Check that document exists <br>'
  1241. */
  1242.  
  1243. if vs.!results_title='' then do
  1244.    frm.35='<input type="hidden" name="H2" value="Search of 'vs.!selorig'">'
  1245. end
  1246. else do
  1247.    vs.!results_title=translate(vs.!results_title,'`','"')
  1248.    frm.35='<input type="hidden" name="HEADER" value="'vs.!results_title'">'
  1249. end
  1250.  
  1251. frm.36='<input type="hidden" name="MODE" value="S"> '
  1252. Frm.36=frm.36||' <input type="Hidden" name="START" value="1+0">'
  1253.  
  1254. frm.37='<p><INPUT TYPE="hidden" NAME="ADD_HIT" value="'add_hit_num'">' 
  1255.  
  1256. frm.38='<input type="hidden" name="search_link" value="'doob'">'
  1257.  
  1258. frm.39='</FORM>'
  1259.  
  1260.  
  1261. if no_tips=0 then do
  1262.  frm.40='</ul><a name="tips"><hr></a><h4>Useful tips</h4>' 
  1263.  frm.41='<blockquote>Using this form, you can search: <tt>'vs.!indexdescription'</tt></blockquote>'
  1264.  frm.42='<menu><li> You can enter multiple words. '
  1265.  frm.43='<li> You can use <b>AND, NOT, OR,</strong> and <b>( )</b> to further modify search logic'
  1266.  frm.44='<li> Search is case insensitive.'
  1267.  if vs.!dostem=1 then do
  1268.    frm.44=frm.44'<li>Search uses <em>stemming rules</em> to remove "s", "ed", and other common stems.'
  1269.  end /* do */
  1270.  if vs.!indexcomments=1 then do
  1271.    frm.44=frm.44'<br>Search ignores HTML <!-- comments -->. '
  1272.  end 
  1273.  frm.45='<li> You can use * to match the </em>beginning of words <em> (for example, SHIP* will match <tt>SHIP</tt> and <tt>ShipMate</tt>)</em>'
  1274.  if vs.!makesummary>0 then do
  1275.     frm.45=frm.45||'<br> For searches of filenames and summaries, do NOT use * (a substring match is used for all searches)'
  1276.  end
  1277.  frm.46='<li><em>descriptive HTML elements</em> include Emphasis (I, EM, B and STRONG), Titles, H1 .. H7 headers, and comments.'
  1278.  
  1279.  if vs.!makesummary>0 then do
  1280.    frm.48='<li> If selected, short (3-5 line) <strong>summaries </strong>will be displayed (when available) for each matching file'
  1281.  end
  1282.  if vs.!propnames<>0 & vs.!propnames<>''  then do
  1283.   frm.50='<li> You can also display the contents of the following <META> tags: ' ,
  1284.          '<b> ' vs.!propnames '</b>'
  1285.  end
  1286.  
  1287.  if vs.!metanames<>0 & vs.!metanames<>''  then do
  1288.     frm.52='<li> You can also search for words in the folllowing <META> fields: <b>' vs.!metanames '</b>'
  1289.     frm.53='<br>     Example: <tt> MymetaName1 = (a1 or a4) not (a3 and a7) </tt><br>'
  1290.     frm.54='This query will retrieve all the files in which the "MymetaName1" is associated either with "a1" or "a4" and that do '
  1291.     frm.55='not contain the words "a3" and "a7", where "a3" and "a7" are not associated to any meta name.'
  1292.  end
  1293.  
  1294.  frm.61='</menu>'
  1295.  frm.62='<hr><a href="#top">Top of document</a>'
  1296. end
  1297.  
  1298.  
  1299. frm.63='</body></html>'
  1300.  
  1301. do mm=1 to 65
  1302.    call lineout tofile,frm.mm
  1303. end
  1304. call lineout tofile
  1305.  
  1306. return 1
  1307.  
  1308. foo10:
  1309. say " GOSWISH: error at " sigl rc 
  1310. exit 0
  1311.  
  1312.  
  1313. /* See if directory exists , 0=no 1=yes*/
  1314. dir_exists:procedure
  1315. parse upper arg lookfor
  1316. lookfor=strip(lookfor,'t','\')
  1317.  
  1318. adrive=filespec('d',lookfor)       /* does drive exist? */
  1319. if adrive<>"" then do
  1320.   oo2=sysdrivemap(,'used')
  1321.   if pos(translate(adrive),translate(oo2))=0 then return 0   /* no such drive */
  1322. end
  1323. eek=lastpos('\',lookfor)
  1324. if eek>0 then do
  1325.   lookfor1=substr(lookfor,eek+1)
  1326.   foo=delstr(lookfor,eek)
  1327. end
  1328. else do
  1329.    return 1       /* it's a root dir */
  1330. end /* do */
  1331. foo=foo'\*.*'
  1332. aa=sysfiletree(foo,'eek','DO')
  1333. do mm=1 to eek.0
  1334.    if translate(filespec('n',eek.mm))=lookfor1 then do 
  1335.        return 1
  1336.    end /* do */
  1337. end /* do */
  1338. return 0
  1339.  
  1340. /* ----------- */
  1341. /* get environment value, possibly host specific */
  1342. /* ------------ */
  1343. get_value: procedure expose enmadd host_nickname
  1344. parse arg vname,hname0
  1345. if hname0=0 then
  1346.         hname=' '
  1347. else
  1348.     hname=strip(host_nickname)
  1349.  
  1350. vname=strip(vname) ;
  1351. if hname<>' ' then do
  1352.    aval=value(enmadd||vname||'.'||hname,,'os2environment')
  1353.    if aval<>' ' Then
  1354.         return aval
  1355. end
  1356. aval=value(enmadd||vname,,'os2environment')
  1357. return aval
  1358.  
  1359.  
  1360.  
  1361. /********/
  1362. /* say or send , or not, adesc */
  1363. write_her:procedure expose vs. is_cgi fii  swish_version
  1364. parse arg axx
  1365.  
  1366. if translate(fii)='FII' then fii=value('SREF_PREFIX',,'os2environment')
  1367.  
  1368. if is_cgi=1 then do
  1369.   say axx
  1370. end
  1371. else do
  1372.   if fii='' then do
  1373.     'VAR 'Axx
  1374.   end
  1375.   else do
  1376.     foo=sref_multi_send(axx)
  1377.     if foo<0 then exit -1
  1378.   end
  1379. end
  1380. return 1
  1381.  
  1382. /***********************************************************/
  1383. /* create a "dct file"  */
  1384. make_dctfile:procedure expose vs.  swish_version servername realsel realdir
  1385.  
  1386. /* parameters */
  1387. htmls=vs.!htmls
  1388. nocontents=vs.!extlist_Nofollow
  1389. outname=vs.!dctfile
  1390. fdescribe=vs.!describefile
  1391. daindx=vs.!swifile
  1392. defdir=vs.!wwwdir
  1393. crlf='0d0a'x
  1394.  
  1395.  
  1396. /* These are used as default "summaries" */
  1397. gmess.1=' File not available'
  1398. gmess.2=' Summary not available'
  1399. gmess.3=' Summary  not available'
  1400. gmess.4=' No summary available'
  1401.  
  1402. /* This is the character used to signal "continuation of a description"
  1403. I.e. (assuming continuation_flag='|'
  1404. FOOBAR.TXT   This is the description of foobar.txt
  1405.  |           And this is the second line.
  1406. Note that the | should be the first non space character */
  1407. continuation_flag='|'
  1408.  
  1409. /* and this is a comment flag */
  1410. comment_flag='; '
  1411.  
  1412. if vs.!repwith=0 | vs.!repwith='' then do  
  1413.   nreps=0
  1414.   reprules.0=0
  1415. end /* do */
  1416. else do
  1417.    reps=vs.!repwith ; nbb=0
  1418.    do forever
  1419.       if reps='' then leave
  1420.       nbb=nbb+1
  1421.       parse var reps afile asel reps
  1422.       reprules.nbb.!old=fixslash(strip(translate(afile)),swish_version)
  1423.       reprules.nbb.!new=fixslash(strip(translate(asel)),1.3)
  1424.    end
  1425.    reprules.0=nbb
  1426. end /* do */
  1427.  
  1428. call get_swifile        /* read filenames from .swi file */
  1429. call get_filelist_info  /* assign "file types" based on file extension */
  1430.  
  1431. if vs.!watch=1 then call write_her(" Creating descriptions for " filelist.0 " files <ol> ")
  1432. latestd.=''
  1433. latestd.!dir=' '
  1434. do m=1 to filelist.0
  1435.    bigd.m=translate(filelist.m.!original,'/','\')
  1436.    bigd.m.!title=filelist.m.!title
  1437.    bigd.m.!size=filelist.m.!size
  1438.    bigd.m.!ASUMMARY=strip(make_summary(filelist.m,filelist.m.!type,vs.!makesummary))
  1439.    bigd.m.!sumtype=yaman          /* yaman is exposed: 0-none, 1=from contents, 2=from dir-spec file */
  1440.    if vs.!watch=1 then do
  1441.      if yaman>0 then 
  1442.          call write_her(' <li> 'bigd.m', 'bigd.m.!title)
  1443.      else
  1444.          call write_her(' <li> 'bigd.m', No Description is Available')
  1445.    end
  1446. end /* do */
  1447.  
  1448. bigd.0=filelist.0
  1449.  
  1450. div=' &^%^& '
  1451. div2=' #$*~~#$* '
  1452. allf=""
  1453. do ii=1 to bigd.0
  1454.    aa=bigd.ii.!sumtype||div||bigd.ii||div||bigd.ii.!title||div||bigd.ii.!size|| , 
  1455.         div||bigd.ii.!ASUMMARY
  1456.    allf=allf||aa
  1457.    if ii<>bigd.0 then allf=allf||div2
  1458. end /* do */
  1459. outname=strip(outname)
  1460. sike=charout(outname,allf,1)
  1461. sike=stream(outname,'c','close')
  1462.  
  1463.  
  1464. outname=strip(outname)
  1465. div=' &^%^& '
  1466. div2=' #$*~~#$* '
  1467. allf="" 
  1468. foo=stream(outname,'c','open write')
  1469. if translate(foo)<>'READY:' then do
  1470.      say "ERROR: could not open " outname
  1471.      exit
  1472. end /* do */
  1473. do ii=1 to bigd.0
  1474.      aa=bigd.ii.!sumtype||div||bigd.ii||div||bigd.ii.!title||div||bigd.ii.!size|| , 
  1475.         div||bigd.ii.!asummary
  1476.     allf=allf||aa
  1477.     if ii<>bigd.0 then allf=allf||div2
  1478.     if length(allf)>10000 then do 
  1479.        aba=charout(outname,allf)
  1480.        allf=''
  1481.     end 
  1482. end /* do */
  1483. if length(allf)>0 then aba=charout(outname,allf)
  1484. sike=stream(outname,'c','close')
  1485.  
  1486. if vs.!watch=1 then call write_her("</ol>Description-cache  (DCT) index file ("outname") has been created.")
  1487. return 1
  1488.  
  1489.  
  1490. /*********************************************************/
  1491. /* read swish file, create a file list (uses reprules found in con file */
  1492. get_swifile:
  1493.  
  1494. call syssleep 2         /* make sure things are properly closed */
  1495.  
  1496. nfiles=get_swish_filelist(daindx)
  1497. if nfiles<1 then do
  1498.    foo=is_error("Error: not a swish index file: "nfiles)
  1499.    return 0
  1500. end
  1501.  
  1502. /* convert url style names back to original files */
  1503. do nf=1 to nfiles
  1504.    afil=filelist.nf.!original
  1505.    do il=1 to reprules.0        /* convert to fully qualified names */
  1506.        if abbrev(afil,reprules.il.!new)=1 then do
  1507.              aa=reprules.il.!old
  1508.              bb=substr(afil,1+length(reprules.il.!new))
  1509.              aa=aa||bb
  1510.              leave
  1511.        end  /* Do */
  1512.    end /* do */
  1513.    filelist.nf=aa
  1514. end /* do */
  1515. return nfiles
  1516.  
  1517.  
  1518. /****************************/
  1519. /* given a filefilst, get descriptions */
  1520. get_filelist_info:
  1521. /* determine type of file: 2=text, 1=html, 0=non-text */
  1522. htmls=translate(translate(htmls),' ','.')
  1523. nocontents=translate(translate(nocontents),' ','.')
  1524. do mm=1 to filelist.0
  1525.    aff=filelist.mm
  1526.    filelist.mm.!type=2               /* assume it's text */
  1527.    foo=lastpos('.',aff)
  1528.    if foo=0 then iterate
  1529.  
  1530.    anext=strip(translate(substr(aff,foo+1)))
  1531.    if wordpos(anext,htmls)>0 then do
  1532.         filelist.mm.!type=1
  1533.         iterate
  1534.    end
  1535.    if wordpos(anext,nocontents)>0 then filelist.mm.!type=0
  1536.  
  1537. end /* do */
  1538.  
  1539. return 0
  1540.  
  1541.  
  1542.  
  1543. /***************/
  1544. /* ------------------------------------- */
  1545. /* create summary info: from explicit description in fdescribe (DESCRIBE.TXT)
  1546.    or by parsing contents of file
  1547. afilename: fully qualified filename to investigate
  1548. atype: 1- html, 2-non-html text, 0-non text (of file)
  1549. asummary: 1- pre-existent only (in describe.txt), 
  1550.           2-create if necessary
  1551.  
  1552. returns a text or html summary, or a numeric code:
  1553. 1= File not available
  1554. 2= Summary not available
  1555. 3= Explicit summary not available
  1556. 4= Error in routine -- no summary available
  1557.  
  1558. yaman is also returned:
  1559.  0-no description, 1=created, 2=explicit (from describe.txt, or <META> ) 
  1560.  
  1561. */
  1562.  
  1563. make_summary:procedure  expose yaman atitle asize fdescribe latestd. comment_flag continuation_flag  swish_version
  1564.  
  1565. parse arg afilename,atype,asummary
  1566.  
  1567. gmess.1=' File not available'
  1568. gmess.2=' Summary not available'
  1569. gmess.3=' Summary  not available'
  1570. gmess.4=' No summary available'
  1571.  
  1572.  
  1573. yaman=0
  1574. eek=stream(afilename,'c','query exists')   /* check for existence*/
  1575.  
  1576. if eek="" then return gmess.4            /* error */
  1577.  
  1578. /* check in directory-specific description file (I.E.; describe.txt) */
  1579. if fdescribe<>" " then do
  1580.  checkd=filespec('d',afilename)||filespec('p',afilename)
  1581.  checkd=translate(checkd,'\','/')
  1582.  checkd=strip(checkd,'t,','\')||'\'
  1583.  if checkd<> latestd.!dir then do 
  1584.     call make_desc(checkd)      /* saves latestd.filename=a summary */
  1585.     latestd.!dir=checkd
  1586.  end
  1587.  
  1588.  fnm=strip(translate(filespec('n',afilename)))   /* check the descriptions, and return match if found */
  1589.  if latestd.fnm<>'' then do              /* got a match, use it */
  1590.      yaman=2
  1591.      return latestd.fnm
  1592.  end /* do */
  1593. end             /* check description file */
  1594.  
  1595.  
  1596. /* no directory-specific summary -- perhaps create summary from file contents ? */
  1597. select
  1598.   when atype=0 | asummary<2 then    /* not text, or not "create description */
  1599.       return gmess.2
  1600.  
  1601.   when atype=2 then do   /* non-html text, create mode */
  1602.        alen=min(chars(afilename),300)
  1603.        stuff=charin(afilename,1,alen)
  1604.        fpp=stream(afilename,'c','close')
  1605.        yaman=1
  1606.        wow=replacestrg(wow,'&','&','ALL')
  1607.        wow=replacestrg(stuff,'<','<','ALL')
  1608.        wow=replacestrg(wow,'>','>','ALL')
  1609.        wow=replacestrg(wow,'"','"','ALL')
  1610.        return wow
  1611.   end
  1612.  
  1613.   when atype=1 then do                  /* html text, create mode */
  1614.      alen=min(chars(afilename),10000)
  1615.      stuff=charin(afilename,1,alen)
  1616.      fpp=stream(afilename,'c','close')
  1617.      stuff=space(translate(stuff,' ','00090a0d1a1b'x))
  1618.      wow=look_header(afilename)
  1619.      if wow<>0 then do
  1620.          yaman=2
  1621.         return wow
  1622.      end  /* Do */
  1623.  
  1624.     if wow=0 & asummary<>2 then 
  1625.        return gmess.4
  1626.  
  1627.     WOW=LOOK_HTAG()                     /* use <Hn> for summary */
  1628.     if wow<>0 then do 
  1629.        yaman=1
  1630.        return wow
  1631.     end  /* Do */
  1632.     return gmess.3
  1633.   end
  1634.  
  1635.   otherwise do
  1636.      say " ERROR: should not be here in make summary "
  1637.      return gmess.4
  1638.   end
  1639. end
  1640.  
  1641.  
  1642. /******************/
  1643. /* read a description file with possible continuation lines */
  1644. make_desc:procedure expose comment_Flag continuation_flag latestd.  fdescribe  
  1645. parse arg checkd
  1646.  
  1647. latestd.=''
  1648. foo2=checkd||fdescribe
  1649. if stream(foo2,'c','query exists')="" then do /*no such file */
  1650.   checkd.0=0
  1651.   return 0
  1652. end /* do */
  1653.  
  1654. aname='';build1=''
  1655. do forever
  1656.     if lines(foo2)=0 then leave
  1657.     if abbrev(strip(alin),comment_flag) then iterate  /* comments */
  1658.     alin=strip(linein(foo2))
  1659.     if abbrev(alin,continuation_flag)=1 then do  /* continuations */
  1660.          build1=build1||substr(alin,length(continuation_flag)+1)
  1661.          iterate
  1662.     end                         /* else, got a file name. So write prior entry */
  1663.     if aname<>'' then do
  1664.       fnm=strip(translate(filespec('n',aname)))   /* check the descriptions, and return match if found */
  1665.       latestd.fnm=build1
  1666.     end
  1667.     parse var alin aname build1
  1668. end /* do */
  1669. if aname<>'' then do
  1670.       fnm=strip(translate(filespec('n',aname)))   /* check the descriptions, and return match if found */
  1671.       latestd.fnm=build1
  1672. end
  1673.  
  1674. xx=stream(foo2,'c','close')
  1675. return igoo
  1676.  
  1677.  
  1678.  
  1679. /* ----------------------------------------------------------------------- */
  1680. /* Look for "desc" field in header     */
  1681. /* ----------------------------------------------------------------------- */
  1682.  
  1683. look_header: procedure expose stuff url_title  swish_version
  1684. parse arg afile
  1685. dowrite=0
  1686. do until stuff=""
  1687.  
  1688.     parse var stuff  p1 '<' tag '>' stuff
  1689.     if  translate(word(tag,1))="HEAD" then do   /* now in head !*/
  1690.             dowrite=1
  1691.             iterate
  1692.     end
  1693.     if dowrite=0 then iterate    /* wait till we get into head .. */
  1694.  
  1695.     if  translate(word(tag,1))="/HEAD" then  /* out of head, all done ! */
  1696.         leave
  1697.  
  1698. /* IT IS A TITLE TAG?  */
  1699.      if translate(word(tag,1))="TITLE" then do
  1700.         parse var stuff url_title '<' footag '>' stuff
  1701.      end
  1702.  
  1703. /* is it a  META HTTP-EQUIV or a META NAME ? */
  1704.     if translate(word(tag,1))="META" then do
  1705.         parse var tag ameta atype '=' rest
  1706.         tatype=translate(atype)
  1707.         if tatype="HTTP-EQUIV" | tatype="NAME" then do
  1708.            parse var rest aval1 rest
  1709.            REST=STRIP(REST)
  1710.  
  1711.            aval1=strip(aval1) ;
  1712.            aval1=strip(aval1,,'"')
  1713.            if abbrev(translate(aval1),'DESC')<>1 then iterate
  1714.  
  1715.            aval2=" "
  1716.            foo1=ABBREV(translate(rest),'CONTENT')
  1717.            if foo1>0 then do
  1718.                 PARSE VAR REST FOO '=' AVAL2
  1719.                 aval2=strip(aval2)
  1720.                 aval2=strip(aval2,'b','"')
  1721.                 WOW=LEFT(AVAL2,500)
  1722.                 return WOW
  1723.            end
  1724.         end             /* name or http-equiv */
  1725.     end         /* meta */
  1726. end             /* stuff */
  1727.  
  1728.  
  1729. return 0
  1730.  
  1731.  
  1732. /* ----------------------------------------------------------------------- */
  1733. /* Extract <hn> fields     */
  1734. /* ----------------------------------------------------------------------- */
  1735.  
  1736. look_htag: procedure expose stuff filename  swish_version
  1737.  
  1738. stuff0=left(stuff,1000)
  1739.  
  1740. amessage=""
  1741. dowrite=0
  1742. do until stuff=""
  1743.     parse var stuff  p1 '<' tag '>' stuff
  1744.     ttag=translate(word(tag,1))
  1745.     if wordpos(ttag,' H1 H2 H3 H4 TITLE')>0 THEN DO   /* grab stuff */
  1746.         parse var stuff  amess '<' tag2 '>' stuff
  1747.         amessage=amessage||amess||'<b> | </b>'
  1748.     end
  1749. end
  1750.  
  1751. if amessage="" then do  /* getting desperate -- grab any old words! */
  1752.    do until stuff0=""
  1753.       parse var stuff0 p1 '<' tag '>' stuff0
  1754.       amessage=amessage||' '||p1
  1755.    end
  1756. end
  1757.  
  1758. if amessage="" then
  1759.    return 0
  1760. amessage=left(amessage,300)  /* keep it short */
  1761. return amessage
  1762.  
  1763.  
  1764.  
  1765.  
  1766. /* ------------- */
  1767. /* ----------------------------------------------------------------------- */
  1768. /* REPLACESTRG: In string astring, find first occurence substring target and
  1769. .   replace it with substring putme
  1770. .      if no target, return unchanged astring
  1771. .      if no putme, then remove target
  1772. .      if type=backward, then find/change LAST occurence
  1773. .      if type=all, find/change all occurences
  1774. .      if exactmatch=yes, then do not capitalize during search (exact match only */
  1775. /* ----------------------------------------------------------------------- */
  1776.  
  1777. replacestrg:procedure
  1778.  
  1779. exactmatch=0
  1780. backward=0 ; doall=0
  1781.  
  1782. parse arg astring ,  target   , putme , type , exactmatch
  1783.  
  1784. type = translate(type)
  1785. if type="BACKWARD" then backward="YES"
  1786. if type="ALL" then doall="YES"
  1787.  
  1788. iat=1
  1789. joelen=length(target)
  1790. joelen2=length(putme)
  1791.  
  1792. doagain:                /* here if doall=yes */
  1793.  if exactmatch="YES" then do
  1794.     if   backward="YES" then
  1795.         joe= lastpos(target,astring)
  1796.     else
  1797.         joe= pos(target,astring,iat)
  1798.  end
  1799.  else do
  1800.    if   backward="YES" then
  1801.         joe= lastpos(translate(target),translate(astring))
  1802.     else
  1803.         joe= pos(translate(target),translate(astring),iat)
  1804.  end
  1805.  if joe=0 then
  1806.          return astring
  1807.  
  1808.  astring=delstr(astring,joe,joelen)
  1809.  if putme<>' ' then
  1810.     astring=insert(putme,astring,joe-1)
  1811.  
  1812.  if doall="YES" then do
  1813.      iat=joe+joelen2
  1814.      signal doagain
  1815.  end
  1816. /* else, all done */
  1817.  return astring
  1818.  
  1819.  
  1820.  
  1821. /*********************************************/
  1822. /* SHOW list of SEARCH FORMS   */
  1823. /*********************************************/
  1824. show_Forms:procedure expose SWISH_DIR vs. is_cgi  swish_version
  1825. parse arg list
  1826.  
  1827. crlf='0d0a'x
  1828.  
  1829. if is_cgi=1 then do
  1830.    call dumpit('content-type: text/html')
  1831.    call dumpit("")
  1832. end /* do */
  1833.  
  1834. dafile='<html><head><title>List of SWISH search forms</title></head></body>'crlf
  1835. dafile=dafile||'<a name="TOP"><h2>List of SWISH search forms </h2></a>'crlf
  1836.  
  1837. goindx=stream(SWISH_DIR'\goswish.ind','c','query exists')
  1838. if goindx<>"" then 
  1839.    yow=charin(goindx,1,chars(goindx))
  1840. else
  1841.   yow=""
  1842.  
  1843. nin=0
  1844. do until yow=""
  1845.    parse var yow aline (crlf) yow ; aline=strip(aline)
  1846.    if aline="" then iterate
  1847.    if abbrev(aline,';')=1 then iterate
  1848.    parse var aline theurl','thefile','hoog','thetime','thedesc
  1849.    parse upper var hoog theswi theconf thedct thedescribe 
  1850.  
  1851.    if thefile='' | theswi='' | theurl='' then iterate
  1852.    if stream(thefile,'c','query exists')='' then iterate  /* relevant files still exist? */
  1853.    if stream(theswi,'c','query exists')='' then iterate
  1854.  
  1855.    nin=nin+1
  1856.    outs.nin='<a href="'theurl'">'thedesc'</a> <em>( 'thetime ')</em>'
  1857. end
  1858. if nin=0 then do                /* no legit entries */
  1859.   dafile=dafile||' <b>Sorry.</b> Currently, no search forms are available.</BODY> </HTML> '
  1860.   if is_cgi=0 then do
  1861.       call write_her(dafile)
  1862.   end
  1863.   else do
  1864.      say dafile ; dafile=''
  1865.   end
  1866.   return 0
  1867. end
  1868.  
  1869. /* got some still alive forms --  present them in a list */
  1870. dafile=dafile||'<b> The following search indices are current available:</b><br><ul>'
  1871. if is_cgi=1 then do
  1872.    call dumpit(dafile); dafile=''
  1873. end /* do */
  1874. do mm=1 to nin
  1875.     if is_cgi=0 then do
  1876.        dafile=dafile||crlf||'<li>'outs.mm
  1877.     end
  1878.     else do
  1879.        call dumpit(crlf||'<li>'outs.mm) ; dafile=''
  1880.    end
  1881. end
  1882.  
  1883. if is_cgi=0 then do
  1884.        dafile=dafile||crlf||'</ul></body></html>'
  1885. end
  1886. else do
  1887.        call dumpit(crlf||'</ul></body></html>') ; dafile=''
  1888. end
  1889.  
  1890. if is_cgi=0 then do
  1891.    gaz=value('SREF_PREFIX',,'os2environment')
  1892.    if gaz='' then
  1893.      'VAR type text/html name dafile '
  1894.    else
  1895.      foo=sref_gos('VAR type text/html name dafile ',dafile)
  1896. end
  1897. else do
  1898.   call dumpit(dafile)
  1899. end
  1900.  
  1901. return 1
  1902.  
  1903.  
  1904.  
  1905. /*********************************************/
  1906. /* regenerate using given configureation file */
  1907. use_conffile:procedure expose SWISH_DIR vs. is_cgi  swish_version
  1908.  
  1909. crlf='0d0a'x
  1910.  
  1911. if is_cgi=1 then do
  1912.    call dumpit('content-type: text/html')
  1913.    call dumpit("")
  1914. end /* do */
  1915.  
  1916. dafile='<html><head><title>Can not Regenerate a SWISH index</title></head></body>'crlf
  1917. dafile=dafile||'<a name="TOP"><h2>Can not Regenerate a SWISH index </h2></a>'crlf
  1918.  
  1919. aconf=stream(vs.!file,'c','query exists')
  1920. if aconf='' then do
  1921.   dafile=dafile||' No such configuration file: 'vs.!file'</body></html>'
  1922.   signal nocando
  1923. end
  1924.  
  1925. isize=stream(aconf,'c','query size')
  1926. foo=stream(aconf,'c','open read')
  1927. if abbrev(translate(foo),'READY')=0 then do
  1928.   dafile=dafile||' Unable to open configuration file: 'aconf'</body></html>'
  1929.   signal nocando
  1930. end
  1931. getit=charin(aconf,1,isize)
  1932. foo=stream(aconf,'c','close')
  1933. return aconf||crlf||getit
  1934.  
  1935.  
  1936. nocando:        /* error */
  1937.   if is_cgi=0 then do
  1938.      gaz=value('SREF_PREFIX',,'os2environment')
  1939.      if gaz='' then
  1940.        'VAR type text/html name dafile '
  1941.      else
  1942.        foo=sref_gos('VAR type text/html name dafile ',dafile)
  1943.   end
  1944.   else do
  1945.     call dumpit(dafile)
  1946.   end
  1947.   return 0
  1948.  
  1949. /*********************************************/
  1950. /* choose a .CON file, for regenerating an index */
  1951. choose_confile:procedure expose SWISH_DIR vs. is_cgi  swish_version cgi_string
  1952. parse arg list
  1953.  
  1954. crlf='0d0a'x
  1955. if cgi_string='' then cgi_string='/cgi-bin/'
  1956.  
  1957.  
  1958. if is_cgi=1 then do
  1959.    call dumpit('content-type: text/html')
  1960.    call dumpit("")
  1961. end /* do */
  1962.  
  1963.  
  1964. dafile='<html><head><title>Regenerate a SWISH index</title></head></body>'crlf
  1965. dafile=dafile||'<a name="TOP"><h2>Regenerate a SWISH index </h2></a>'crlf
  1966.  
  1967. goindx=stream(SWISH_DIR'\goswish.ind','c','query exists')
  1968. if goindx<>"" then 
  1969.    yow=charin(goindx,1,chars(goindx))
  1970. else
  1971.   yow=""
  1972.  
  1973. nin=0
  1974. do until yow=""
  1975.    parse var yow aline (crlf) yow ; aline=strip(aline)
  1976.    if aline="" then iterate
  1977.    if abbrev(aline,';')=1 then iterate  
  1978.  
  1979.    parse var aline theurl','thefile','hoog','thetime','thedesc
  1980.    parse upper var hoog theswi theconf thedct thedescribe 
  1981.  
  1982.    if theconf='' then iterate
  1983.    if stream(thefile,'c','query exists')='' then iterate  /* relevant files still exist? */
  1984.    if stream(theconf,'c','query exists')='' then iterate
  1985.  
  1986.    nin=nin+1
  1987.    if is_cgi=1 then
  1988.      outs.nin='<a href="'cgi_string'GOSWISH.CMD?MODE=2REGEN&file='theconf'&swifile='theswi'&searchdoc='theurl
  1989.    else
  1990.      outs.nin='<a href="GOSWISH?MODE=2REGEN&file='theconf'&swifile='theswi'&searchdoc='theurl
  1991.    outs.nin=outs.nin||'">'thedesc'</a> '
  1992.    outs.nin=outs.nin': <a href="'theurl'">search form</a>'
  1993.    outs.nin=outs.nin|| ' <em>('thetime')</em>'
  1994. end
  1995. if nin=0 then do                /* no legit entries */
  1996.   dafile=dafile||' <b>Sorry.</b> Currently, no configuration files are available.</BODY> </HTML> '
  1997.   if is_cgi=0 then do
  1998.       call write_her(dafile)
  1999.   end
  2000.   else do
  2001.      say dafile ; dafile=''
  2002.   end
  2003.   return 0
  2004. end
  2005.  
  2006. /* got some still alive forms --  present them in a list */
  2007. dafile=dafile||'<b> The following configuration files are current available:</b><br><ul>'
  2008. if is_cgi=1 then do
  2009.    call dumpit(dafile); dafile=''
  2010. end /* do */
  2011. do mm=1 to nin
  2012.     if is_cgi=0 then do
  2013.        dafile=dafile||crlf||'<li>'outs.mm
  2014.     end
  2015.     else do
  2016.        call dumpit(crlf||'<li>'outs.mm) ; dafile=''
  2017.    end
  2018. end
  2019.  
  2020. if is_cgi=0 then do
  2021.        dafile=dafile||crlf||'</ul></body></html>'
  2022. end
  2023. else do
  2024.        call dumpit(crlf||'</ul></body></html>') ; dafile=''
  2025. end
  2026.  
  2027. if is_cgi=0 then do
  2028.    gaz=value('SREF_PREFIX',,'os2environment')
  2029.    if gaz='' then
  2030.      'VAR type text/html name dafile '
  2031.    else
  2032.      foo=sref_gos('VAR type text/html name dafile ',dafile)
  2033. end
  2034. else do
  2035.   call dumpit(dafile)
  2036. end
  2037.  
  2038. return 1
  2039.  
  2040.  
  2041. /*********************************************/
  2042. /* NOT FULLY SUPPORTED */
  2043. /* choose a descriptive summaries file, for regenerating an index */
  2044. choose_dctfile:procedure expose SWISH_DIR vs. is_cgi  swish_version
  2045. parse arg list
  2046.  
  2047. crlf='0d0a'x
  2048.  
  2049. if is_cgi=1 then do
  2050.    call dumpit('content-type: text/html')
  2051.    call dumpit("")
  2052. end /* do */
  2053.  
  2054.  
  2055. dafile='<html><head><title>Regenerate a SWISH index</title></head></body>'crlf
  2056. dafile=dafile||'<a name="TOP"><h2>Regenerate a SWISH index </h2></a>'crlf
  2057.  
  2058. goindx=stream(SWISH_DIR'\goswish.ind','c','query exists')
  2059. if goindx<>"" then 
  2060.    yow=charin(goindx,1,chars(goindx))
  2061. else
  2062.   yow=""
  2063.  
  2064. nin=0
  2065. do until yow=""
  2066.    parse var yow aline (crlf) yow ; aline=strip(aline)
  2067.    if aline="" then iterate
  2068.    if abbrev(aline,';')=1 then iterate
  2069.    parse var aline theurl','thefile','hoog','thetime','thedesc
  2070.    parse upper var hoog theswi theconf thedct thedescribe 
  2071.    if theconf='' | thefile='' | thedct='' then iterate
  2072.    if stream(thefile,'c','query exists')='' then iterate  /* relevant files still exist? */
  2073.    if stream(theconf,'c','query exists')='' then iterate
  2074.  
  2075.    nin=nin+1
  2076.    outs.nin='<a href="GOSWISH?MODE=2DREGEN&file='theconf'&swifile='theswi'&searchdoc='theurl
  2077.    outs.nin=outs.nin||'&dctfile='thedct'&describefile='thedescribe
  2078.    outs.nin=outs.nin||'">'thedesc'</a> '
  2079.    outs.nin=outs.nin': <a href="'theurl'">search form</a>'
  2080.    outs.nin=outs.nin|| ' <em>('thetime')</em>'
  2081. end
  2082. if nin=0 then do                /* no legit entries */
  2083.   dafile=dafile||' <b>Sorry.</b> Currently, no configuration files are available.</BODY> </HTML> '
  2084.   if is_cgi=0 then do
  2085.       call write_her(dafile)
  2086.   end
  2087.   else do
  2088.      say dafile ; dafile=''
  2089.   end
  2090.   return 0
  2091. end
  2092.  
  2093. /* got some still alive forms --  present them in a list */
  2094. dafile=dafile||'<b> The following configuration files are current available:</b><br><ul>'
  2095. if is_cgi=1 then do
  2096.    call dumpit(dafile); dafile=''
  2097. end /* do */
  2098. do mm=1 to nin
  2099.     if is_cgi=0 then do
  2100.        dafile=dafile||crlf||'<li>'outs.mm
  2101.     end
  2102.     else do
  2103.        call dumpit(crlf||'<li>'outs.mm) ; dafile=''
  2104.    end
  2105. end
  2106.  
  2107. if is_cgi=0 then do
  2108.        dafile=dafile||crlf||'</ul></body></html>'
  2109. end
  2110. else do
  2111.        call dumpit(crlf||'</ul></body></html>') ; dafile=''
  2112. end
  2113.  
  2114. if is_cgi=0 then do
  2115.    gaz=value('SREF_PREFIX',,'os2environment')
  2116.    if gaz='' then
  2117.      'VAR type text/html name dafile '
  2118.    else
  2119.      foo=sref_gos('VAR type text/html name dafile ',dafile)
  2120. end
  2121. else do
  2122.   call dumpit(dafile)
  2123. end
  2124.  
  2125. return 1
  2126.  
  2127.  
  2128.  
  2129. /******************************************************************/
  2130. /* THIS IS THE SEARCH COMPONENT OF GOSWISH */
  2131. /******************************************************************/
  2132. SEARCH_IT:procedure expose SWISH_DIR  swish_version  is_cgi servername tempfile ,
  2133.                            all_sets verb uri reqstrg def_htmls use_swish_dll
  2134. parse arg list
  2135. signal on error name errarf ; signal on syntax name errarf ;
  2136.  
  2137. if is_cgi=1 then do
  2138.   method = value("REQUEST_METHOD",,'os2environment')
  2139.   verb=method
  2140.   servername=value("SERVER_NAME",,'os2environment')
  2141. end
  2142. else do
  2143.    bigstuff=''
  2144.   
  2145. end /* do */
  2146.  
  2147. crlf='0d0a'x
  2148.  
  2149. /* A temporary file to capture output from SWISH */
  2150. turkey=SWISH_DIR'\ST$?????.OUT'
  2151. TEMPOUT = systempfileName(turkey)
  2152.  
  2153. searchwhat='documents'
  2154.  
  2155. if is_cgi=1 then do
  2156.   call dumpit "Content-type: text/html"
  2157.   call dumpit ' '
  2158. end
  2159.  
  2160. if tempout = "0" | tempout="" then do
  2161.      tt='<!doctype html public "-//IETF//DTD HTML 2.0//EN">' crlf ,
  2162.        "<html><head><title>Index search results </title></head>" crlf ,
  2163.        "<body> <STRONG> ERROR: Could not access working directory </STRONG>" crlf ,
  2164.       " </BODY> </HTML> "
  2165.      call dumpit tt
  2166.      signal donesearch
  2167. end
  2168.  
  2169.  
  2170. keywords='help'
  2171. index_file="INDEX.SWI"
  2172. dct_file=' '
  2173.  
  2174.  
  2175. plist=''
  2176. ndofiles=20
  2177. didnew=0
  2178. swopts=' '
  2179. header_file=' '
  2180. footer_file=' '
  2181. search_link=''
  2182. isfilesearch=0          /* 0=ignore, 1= path&filename search, 2=description search, 3= filename search */
  2183. aheader="Search the site-index "
  2184. ncmt=0 ; door=0
  2185. summary=0
  2186. nfound=0
  2187. NUMBEROFHITS=0
  2188. exists=0
  2189. add_hit_num=0
  2190. start=0
  2191. max_find=-1      /* if max_find is set to 0 below, then we get "all" the matches */
  2192. incache=0
  2193. dctindx.=0
  2194. dcache.=0 ; dcachel.=0
  2195. cache_type=0            /* 0=none, 1=regular, 2=structured */
  2196.  
  2197. /* newlist is needed to make "pointers to next set of matches */
  2198. if is_cgi=0 then do
  2199.    if verb='GET' then 
  2200.       parse var uri newlist '?' list
  2201.    else
  2202.      newlist=reqstrg
  2203. end
  2204. else do
  2205.    newlist=value('SCRIPT_NAME',,'os2environment')
  2206. end /* do */
  2207. newlist=newlist||'?'            /* links have to be "GETS" */
  2208.  
  2209.  
  2210. /* Rescan options list... */
  2211. do until list="" 
  2212.   parse var list v1 '&' list ; oldv1=v1
  2213.   parse var v1 avar '=' aval ; avar=translate(avar) ;
  2214.   aval=decodekeyval(translate(aval,' ','+'))
  2215.  
  2216.   aval=strip(aval,,'"')
  2217.  
  2218.   if abbrev(avar,"KEYWORD")=1 then  do
  2219.       keywords=decodekeyval(translate(aval,' ','+'))
  2220.   end
  2221.   if avar='H1' | avar='HEADER' | avar='H2'   then do
  2222.       aheader=decodekeyval(translate(aval,' ','+'||'000d0a09'x))
  2223.       if avar='H1' then aheader='<h1>'aheader'</h1>'
  2224.       if avar='H2' then aheader='<h2>'aheader'</h2>'
  2225.   end
  2226.   if abbrev(avar,'HEADER_FILE')=1 then do
  2227.       header_file=decodekeyval(translate(aval,' ','+'))
  2228.       header_file=strip(translate(header_file,'\','/'),'t','\')
  2229.   end
  2230.  
  2231.   if abbrev(avar,'FOOTER_FILE')=1 then do
  2232.       footer_file=decodekeyval(translate(aval,' ','+'))
  2233.       footer_file=strip(translate(footer_file,'\','/'),'t','\')
  2234.   end
  2235.  
  2236.   if abbrev(avar,"SEARCH_LINK")=1 then do
  2237.      search_link=decodekeyval(aval)
  2238.   end /* do */
  2239.  
  2240.   if abbrev(avar,'START')=1 then do
  2241.        tt=translate(decodekeyval(translate(aval,' ','+')))
  2242.        parse var tt tt1 tt2
  2243.        if datatype(tt1)='NUM' then start=tt1
  2244.        if start<0 then start=0
  2245.        found_matches=tt2
  2246.        if datatype(tt2)='NUM' then max_find=tt2
  2247.        if datatype(max_find)<>'NUM' then max_find=-1  /* -1 is a "suppresion" */
  2248.        oldv1=''         /* suppress it in "next match" links -- appropriate start will be added below*/
  2249.   end /* do */
  2250.  
  2251.   if abbrev(avar,'SHOWPROP')=1 then do
  2252.       taval=translate(aval)
  2253.       if abbrev(taval,'_SUMMARY_')=1 then do  /* a SUMMARY synonym */
  2254.         parse var taval '_SUMMARY_' tt . ; tt=strip(tt)
  2255.         if tt="NO" then      summary=0
  2256.         if tt="YES" | tt=1 then    summary=1
  2257.         if tt="CREATE"| tt=2 then  summary=2
  2258.       end /* do */              /* and SUMMA will pick this up below */
  2259.       else do
  2260.          plist=plist' 'taval
  2261.       end /* do */
  2262.   end /* do */
  2263.  
  2264.  
  2265.   if abbrev(avar,'INDEX')=1 then do
  2266.      indxfile=''
  2267.      tmp=aval
  2268.      do forever
  2269.        if tmp='' then leave
  2270.        parse var tmp a1 tmp ; a1=strip(a1) ; a1=translate(a1,'\','/')
  2271.        if pos(':',a1)=0  then do
  2272.           a1=SWISH_DIR||'\'||strip(a1,'l','\')
  2273.        end
  2274.       if stream(a1,'c','query exists')="" then do
  2275.          aa=" <p><b>Sorry</b>, the requested search index does not exist (" a1 ") "
  2276.          call dumpit(aa)
  2277.          rmessage=' Error: No SWISH index file: 'a1
  2278.          signal sendher
  2279.       end
  2280.       indxfile=indxfile' 'a1
  2281.      end                /* forever */
  2282.   end
  2283.  
  2284.  
  2285. /* text_dct_File is the old name for DCT_FILE */
  2286.   if abbrev(avar,'TEXT_DESCRIP_FILE')=1 | abbrev(avar,'DCT_F')=1 then do
  2287.      dct_File=''
  2288.      tmp=aval
  2289.      do forever
  2290.        if tmp='' then leave
  2291.        parse var tmp a1 tmp ; a1=strip(a1) ; a1=translate(a1,'\','/')
  2292.        if pos(':',a1)=0  then do
  2293.           a1=SWISH_DIR||'\'||strip(a1,'l','\')
  2294.        end
  2295.        if stream(a1,'c','query exists')="" then do
  2296.          aa=" <p><b>Warning:</b>, a requested DCT file does not exist (" a1 ")<p> "
  2297.          call dumpit(aa)
  2298.          iterate
  2299.        end
  2300.        dct_File=dct_File' 'a1
  2301.      end                /* forever */
  2302.   end
  2303.  
  2304.   if abbrev(avar,'COMMENT')=1 then do
  2305.       ncmt=ncmt+1
  2306.       comments.ncmt=translate(aval, ' ','+'||'00090d0a'x) 
  2307.   end
  2308.   if abbrev(avar,'COND')=1 then do
  2309.         select
  2310.          when abbrev(translate(aval),'Y')=1 then
  2311.                door=' or '
  2312.          when abbrev(translate(aval),'O')=1 then
  2313.                door=' or '
  2314.           when abbrev(translate(aval),'N')=1 then
  2315.                 door=' not '
  2316.           otherwise
  2317.                 door=0
  2318.         end
  2319.   end
  2320.  
  2321.   if abbrev(avar,"ADD_HIT")=1 then do
  2322.       if wordpos(translate(aval),'1 Y YES')>0 then add_hit_num=1
  2323.       if wordpos(translate(aval),'0 N NO')>0 then add_hit_num=0
  2324.   end /* do */
  2325.  
  2326.   if abbrev(avar,'SUMMA')=1 then do
  2327.         tt=translate(aval)
  2328.         summary=tt
  2329.         if tt="NO" then   summary=0
  2330.         if tt="YES"  then  summary=1
  2331.         if tt="CREATE" then summary=2
  2332.   end
  2333.  
  2334.   if abbrev(avar,'EXIST')=1 then do
  2335.         tt=translate(aval)
  2336.         if wordpos(translate(tt),'YES Y 1')>0 then
  2337.            exists=1
  2338.         else
  2339.            exists=0
  2340.   end
  2341.  
  2342.   if abbrev(avar,'OPTION')=1 then do    /* one of several possible options */
  2343.       aval=strip(translate(aval,' ','+'))
  2344.       select
  2345.          when abbrev(translate(aval),'PATH')=1 then
  2346.             isfilesearch=1      /* filename */
  2347.          when abbrev(translate(aval),'SUMMARY')=1 then
  2348.             isfilesearch=2      /* summary */
  2349.          when abbrev(translate(aval),'FILE')=1 then
  2350.             isfilesearch=3      /* summary */
  2351.  
  2352.          otherwise do
  2353.            select
  2354.               when abbrev(AVAL,'-m')=1 then do
  2355.                  parse var aval '-m' ndofiles
  2356.                  if datatype(ndofiles)<>'NUM' then ndofiles=20 /* if bad syntax, use default */
  2357.                  aval='-m '||strip(ndofiles)
  2358.               end
  2359.               when aval='-t HB' then  searchwhat='Contents of HTML documents'
  2360.               when aval='-t t'  then  searchwhat='TITLEs of HTML documents'
  2361.               when aval='-t ehtc' then searchwhat='<em>descriptive elements</em> in HTML documents'
  2362.               otherwise nop
  2363.             end
  2364.             swopts=swopts||" "||aval            /*SWOPTS "accumulates" OPTIONx options */
  2365.          end            /* select aval */
  2366.       end /* do */
  2367.   end
  2368.  
  2369.   if oldv1<>'' then newlist=newlist||oldv1||'&'
  2370.  
  2371. end             /* Options parsing */
  2372. newlist=strip(newlist,'t','&')          /* preparatory for adding "next links */
  2373.  
  2374. /* -------- We now have all the options ... */
  2375.  
  2376.  
  2377. /***  load the  one (or more) old-style  "dct" files */
  2378. if  dct_file<>' ' & (summary>0 | isfilesearch>0) then do
  2379.    div=' &^%^& ' 
  2380.    div2=' #$*~~#$* '
  2381.    ndcts=words(dct_File)
  2382.    tmpfs=dct_File
  2383.    ii=0 
  2384.    do forever
  2385.      if tmpfs='' then leave
  2386.      parse var tmpfs adfil tmpfs ; adfil=strip(adfil)
  2387.      if stream(adfil,'c','query exists')='' then do
  2388.          call dumpit('<p><B>Warning: </b> No such DCT file='adfil)
  2389.          iterate
  2390.      end
  2391.      bobo=stream(adfil,'c','open read')
  2392.      goofy=charin(adfil,1,10)
  2393.      if abbrev(goofy,'#GOSWISH')=1 then do
  2394.          if ndcts>1 then do
  2395.            call dumpit('<p><B>Warning: </b> can not combine structured DCT file= 'adfil)
  2396.            iterate
  2397.          end
  2398.          istat=load_desc_cache(adfil)
  2399.          if istat<0 then do
  2400.             call dumpit,' Error using description cache file: 'istat
  2401.             signal donesearch
  2402.          end
  2403.          incache=DCTINDX.0 
  2404.          cache_type=2 ; scachename=adfil
  2405.      end                /*  structured dct */
  2406.      else do            /* regular dct */
  2407.          llena=stream(adfil,'c','query size')
  2408.          goofy=charin(adfil,1,llena)
  2409.          bobo=stream(adfil,'c','open read')
  2410.          i1=1 ; lengoofy=length(goofy) ;isleave=0
  2411.          do  forever
  2412.             i2=pos(div2,goofy,i1)
  2413.             if i2=0 then do
  2414.                isleave=1
  2415.                i2=lengoofy
  2416.             end /* do */
  2417.             aa=substr(goofy,i1,i2-i1)
  2418.             i1=i2+length(div2)
  2419.             ii=ii+1 ; dcache.0=ii
  2420.             parse var aa dcache.ii.!sumtype (div) dcache.ii (div) dcache.ii.!title (div) ,
  2421.                     dcache.ii.!size (div) dcache.ii.!ASUMMARY
  2422.             if (isleave=1) then leave
  2423.          end                    /* do forever; read lines from a dct ifle */
  2424.          cache_type=1
  2425.      end                   /* is a regular dct */
  2426.  
  2427.   end                   /* do forever: reading multiple dct files*/
  2428. end                  /* dctfile <>' '*/
  2429.  
  2430.  
  2431. if cache_type=2 & isfilesearch>0 then do  /* copy structured dct to non structured */
  2432.   bodyat=dctindx.!offset+1
  2433.   fsize=stream(scachename,'c','query size')
  2434.   goofy=charin(scachename,bodyat,1+fsize-(bodyat+8))
  2435.   div5='05'x
  2436.   ii=0
  2437.  
  2438.   i1=1 ;ii=0 ;leaveit=0
  2439.   do  forever
  2440.       ii=ii+1  
  2441.       do rr=1 to 6  
  2442.         i2=pos(div5,goofy,i1)
  2443.         if i2=0 then do 
  2444.              leaveit=1
  2445.              leave
  2446.         end /* do */
  2447.         abb.rr=substr(goofy,i1,i2-i1)
  2448.         i1=i2+1
  2449.       end /* do */
  2450.       if leaveit=1 then leave
  2451.       dcache.ii.!sumtype=abb.2 ; dcache.ii=abb.3
  2452.       dcache.ii.!title=abb.4  ; dcache.ii.!size=abb.5
  2453.       dcache.ii.!asummary=abb.6
  2454.       dcachel.II=dcache.II
  2455.   end
  2456.  
  2457.  
  2458.   DCACHE.0=DCTINDX.0 ; DCACHEL=0=DCACHE.0
  2459.   drop goofy
  2460. end /* do */
  2461.  
  2462. if cache_type=1 then do
  2463.     do mm=1 to dcache.0          /* copy urls to  a url array */
  2464.         dcachel.mm=dcache.mm
  2465.     end /* do */
  2466.     dcachel.0=dcache.0
  2467.     incache=dcache.0
  2468. end /* do */
  2469.  
  2470.  
  2471. /* Double check the number to find; and if not specified, use the default */
  2472. parse var swopts p1 '-m' TOFIND p2    /* How many matches to find? */
  2473. IF TOFIND="" then TOFIND=ndofiles  
  2474. mmx=tofind       
  2475. if start>0 then do              /* If START option given, then adjust the -m option */
  2476.    MMX=TOFIND+START-1           /* since we might need all of them? */
  2477.    if max_find=0 then  mmx=1000      /* max_find=0 means "this is the first of 1+0 call */
  2478. end /* do */
  2479. swopts=p1||' -m '||mmx||' '||p2   /* reconstitute the swish options list */
  2480.  
  2481. START=MAX(START,1)              /* DON'T NEED "START=0" FLAG ANYMORE */
  2482.  
  2483. /* if filesearch and no description file, it's an error */
  2484. if isfilesearch>0 & dcache.0=0 then do
  2485.   tt='<!doctype html public "-//IETF//DTD HTML 2.0//EN">' crlf ,
  2486.      "<html><head><title>Index search results </title></head>" crlf ,
  2487.     " <STRONG>Sorry</strong> FileSearch requires a description file.  </BODY> </HTML> " crlf 
  2488.   call dumpit tt
  2489.   signal donesearch
  2490. end  /* Do */
  2491.  
  2492.  
  2493. /* write the top part of the response */
  2494. aa=""
  2495. aa=aa|| '<!doctype html public "-//IETF//DTD HTML 2.0//EN">'
  2496. aa=aa|| "<html><head><title>Index search results </title>"
  2497. aa=aa||"</head>"
  2498. call dumpit(aa)
  2499.  
  2500. /* write the header -- use HEADER, H1, H2, and COMMENTS */
  2501. aa=""
  2502. if header_file<>' ' then do
  2503.    tff=swish_dir'\'header_file
  2504.    wow=afileread(tff)
  2505.    if wow=0 & is_cgi=0 then call pmprintf("GoSWISH warning: no header file="tff)
  2506.    do ww=1 to wow
  2507.       aa=aa||crlf||ffread.ww
  2508.    end /* do */
  2509. end  /* Do */
  2510. if aa="" then do 
  2511.    aa='<body> '||aheader||'<p>'||crlf  /* Aheader set by HEADER, H1, and H2 options */
  2512. end
  2513. call dumpit(aa)
  2514.  
  2515. aa=""                   /* write out "comments" */
  2516. do mm=1 to ncmt
  2517.    aa=aa||' <em> ' comments.mm ' </em> <br>'crlf
  2518. end
  2519. call dumpit(aa)
  2520.  
  2521. /* fix up keyword list (words to search for) */
  2522. twords=translate(keywords) ; srchwords=""
  2523. /* remove silly srchwords */
  2524. do mm=1 to words(twords)
  2525.    aword=word(twords,mm)
  2526.    igu=wordpos(translate(aword),'AND OR NOT')
  2527.    if igu>0  then aword=strip(word('and or not',igu))
  2528.    srchwords=srchwords||" "||aword
  2529. end
  2530.  
  2531. /* add implicit NOT or OR conditions? */
  2532. if door<>0 & words(keywords)>1 then do   /* insert not / or  into keyword list */
  2533.    tmp=word(keywords,1) ; wasand=0
  2534.    do mmm=2 to words(keywords)
  2535.       aww=word(keywords,mmm) ; taw=strip(translate(aww))
  2536.       if wasand=1 then do
  2537.         tmp=tmp||' '||aww
  2538.         wasand=0
  2539.         iterate
  2540.       end
  2541.       if translate(taw)="OR"| translate(taw)="AND" | translate(taw)="NOT"then do
  2542.         tmp=tmp||' '||aww
  2543.         wasand=1
  2544.         iterate
  2545.       end
  2546.       tmp=tmp||door||aww
  2547.     end
  2548.     keywords=tmp
  2549. end
  2550.  
  2551. /**** NOW we are ready to ask SWISH to do the search! Note the 1.1 and 1.3 modes */
  2552. /*    Or, search in the "description" file */
  2553.  
  2554.  
  2555. if isfilesearch=0 then do
  2556.  
  2557. /* read the type of the indexfile(s) */
  2558.    itype=check_indxfile_type(indxfile)  /* returns 11, 12, 13, or error message */
  2559.    if wordpos(itype,'11 12 13')=0 then do
  2560.         call dumpit(itype'<p>')
  2561.         signal donesearch
  2562.    end /* do */
  2563.    
  2564.    swish_version=itype          /* this is the type to use (effects which swish to use*/
  2565.  
  2566.    izs=stream(indxfile,'c','query size')
  2567.    if iz2s=0 | iz2='' then do
  2568.        call dumpit(' Error. No such SWISH index file: 'indxfile)
  2569.        call donesearch
  2570.   end /* do */
  2571.    if swish_version=11 then do
  2572.         t1='swish -f '||INDXfile ||' -w '||keywords||' '||swopts||' > '||tempout
  2573.    end
  2574.    else do           
  2575.        if plist<>'' then plist=' -p '||plist||' ' 
  2576.        t1='swish-e -f '||INDXfile ||' -w '||keywords||' '||swopts||plist||' > '||tempout
  2577.    end
  2578.  
  2579.    if use_swish_dll=1  then do                        /* dll mode */
  2580.       oof='-f '||INDXfile ||' -w '||keywords||' '||swopts||plist 
  2581.  
  2582. /*      oof='-f '||INDXfile ||' -w '||strip(keywords)||' -t ehtc' 
  2583. aa=directory('e:\goserve\swish\godata') 
  2584. oof="-f index12.swi -w help " */
  2585.  
  2586.       rc=rxswEmulate(oof,"1","FILELINES")
  2587.       if rc<>0 then do then
  2588.          call dumpit("GoSwish error (rxswEmulate): "rc)
  2589.          signal donesearch
  2590.       end /* do */
  2591.       gotem=filelines.0
  2592.  
  2593.    end /* do */
  2594.  
  2595.    else do                      /* exe mode */
  2596.       if is_cgi=1 then t1='@'t1
  2597.       foodir=directory(SWISH_DIR)
  2598.       signal on error name askerr2 ; signal on syntax name askerr2 
  2599.       didt1=0
  2600.       address cmd
  2601.           t1
  2602.         address
  2603.        foodir=directory(foodir)
  2604.        didt1=1
  2605.        gotem=afileread(tempout) /* get results from the temporary file SWISH wrote to */
  2606.        do iij=1 to gotem
  2607.           filelines.iij=ffread.iij
  2608.        end /* do */
  2609.        filelines.0=gotem
  2610.        goo=sysfiledelete(tempout)
  2611.    end
  2612.    signal on error name errarf ; signal on syntax name errarf ;  /* reset error loction */
  2613.  
  2614. end
  2615.  
  2616. else do                /* don't use swish inde -- instead, search the description file.... */
  2617.   gotem=do_fsearch(isfilesearch,keywords,start,ndofiles)  /* one of the cache search variants */
  2618. end
  2619.  
  2620. askerr2:                         /* jump here if error */
  2621. if didt1=0 then do      
  2622.    foodir=directory(foodir)
  2623.    gotem=afileread(tempout)
  2624.    call dumpit('<b> SWISH search error, unable to complete request.</b> <pre>')
  2625.    do iij=1 to gotem
  2626.       filelines.iij=ffread.iij
  2627.       call dumpit(filelines.iij)
  2628.    end /* do */
  2629.    call dumpit('</pre>')
  2630.    filelines.0=gotem
  2631.    goo=sysfiledelete(tempout)
  2632.    signal donesearch
  2633. end
  2634.  
  2635. if gotem=0 then do              /* nothing returned */
  2636.     aa=" <p><STRONG> No matches found </STRONG> </BODY> </HTML> "
  2637.     call dumpit aa
  2638.     signal donesearch
  2639. end
  2640.  
  2641. /** Got some results, let's display them */
  2642. igot=0
  2643. aa='  <b>Searching 'searchwhat' for: </b></tt>'keywords'</tt> <dl>'
  2644. call dumpit(aa)
  2645. swiver=0
  2646. propnames.0=0                   /* what property names are returned? */
  2647. do mm=1 to gotem
  2648.    RLINE = filelines.mm
  2649.    IF RLINE = '' THEN leave
  2650.    IF RLINE = '.' THEN leave
  2651.  
  2652. /* examine  comment lines -- should all be at beginning of file  */
  2653. /* We need to extract "number of hits", DOC PROPERTY, and COUNTS */
  2654.    IF abbrev(RLINE,'#') = 1  THEN do
  2655.       parse var rline '#' a1 ':' a2 ; a1=translate(space(a1,0))
  2656.        select
  2657.          when a1='NUMBEROFHITS' then DO 
  2658.              IF MAX_FIND=0 THEN max_find=strip(a2)
  2659.              NUMBEROFHITS=STRIP(A2)
  2660.          end /* do */
  2661.          when abbrev(a1,'DOCPROPERTY')=1 then do
  2662.              parse var a1 'DOCPROPERTY' np 
  2663.              propnames.np=strip(a2) ; propnames.0=np
  2664.          end /* do */
  2665.          when a1="SWISHFORMAT1.1" then swiver=11
  2666.          when a1="SWISHFORMAT1.2" then swiver=12
  2667.          when a1="SWISHFORMAT1.3" then swiver=13
  2668.          when a1="GOSWISHSEARCH"  then swiver=10  /* goswish search of filenames/summaries */
  2669.          otherwise nop
  2670.       end  
  2671.       iterate
  2672.    end /* do */
  2673.  
  2674. /* Split the line into fields. */
  2675. /* if here,  might be a result, might be an error */
  2676.  
  2677.     PARSE VAR RLINE R_SCORE R_FILE R_stuff
  2678.  
  2679.     if translate(r_file)='WORDS:' then iterate /* a 1.1 format comment */
  2680. /* check for some kind of error */
  2681.     trs=strip(translate(r_score))
  2682.     if abbrev(trs,'SWISH:')+abbrev(trs,'ERR:')+abbrev(trs,'USAGE:')>0 then do
  2683.         parse var rline . ':' anerr
  2684.         if strip(translate(anerr))="NO RESULTS" then do
  2685.            call dumpit('<p><em>NO matches. </em><BR> ')
  2686.         end
  2687.         else do
  2688.            call dumpit('<b>A SWISH error occurred:'anerr' </b><p>')
  2689.         end
  2690.         signal donesearch 
  2691.       end /* do */
  2692.  
  2693. /* if here, it's a real entry */
  2694.     igot=igot+1
  2695.  
  2696.     if igot=1 then do           /* on first entry, there might be things to do*/
  2697.        if swiver=0 then do      /* not a swish return */
  2698.            call dumpit('<b>Error. Not a recognized SWISH format ')
  2699.            signal donesearch 
  2700.        end /* do */
  2701.        if swiver=11 then do             /* best guess as to # of good entries */
  2702.             numberofhits=filelines.0-mm
  2703.             IF MAX_FIND=0 THEN max_find=max(numberofhits,max_find)
  2704.        end /* do */
  2705.     end /* do */
  2706.     if igot<start then iterate    /* skip if a START is binding */
  2707.  
  2708. /* read fields (possibly propnames, if swish 1.3) */
  2709.     PARSE VAR R_STUFF '"' R_TITLE '"'  R_POSITION R_STUFF
  2710.     gotprop=0
  2711.     DO IPQ=1 TO PROPNAMES.0
  2712.        PARSE VAR R_STUFF '"' APROP.IPq '"' R_STUFF
  2713.        if aprop.ipq<>'' then gotprop=1
  2714.     end /* do */
  2715.  
  2716.  
  2717. /* Spit out this reference as a HTML link. */
  2718.   r_file=translate(r_file,'/','\')
  2719.   r_title=strip(strip(r_title),,'"')
  2720.   if r_title="" then do 
  2721.       tmp2=translate(r_file,' ','\/'); r_title=word(tmp2,words(tmp2))
  2722.   end /* do */
  2723.  
  2724.   if add_hit_num=1 then
  2725.      aa2='<dt> <em>'igot') </em>   <A href=' r_file '>' r_title '</a>'crlf
  2726.    else
  2727.      aa2='<dt> <A href=' r_file '>' r_title '</a>'crlf
  2728.  
  2729. /**** MAKE A SUMMARY (either on the fly, or from a DESCRIPTION CACHE file .... */
  2730.  
  2731.   aa='  <em> Score= ' r_score ' </em> 'crlf
  2732.   aa=aa||' <code> , ' r_position 'bytes </code> <br>'crlf
  2733.   if summary>0 | exists>0 then do
  2734.      oof=''
  2735.      if add_hit_num=1 then oof='<em>'igot') </em>   '
  2736.      foo=make_summary2(aa,r_title,r_file,summary,srchwords,exists,gotprop,oof,incache,cache_type)
  2737.   end
  2738.   else do
  2739.      call dumpit(aa2||aa)
  2740.      if gotproP>0 then call dumpit('<ul>')
  2741.   end /* do */
  2742.  
  2743.   if gotprop>0 then do          /* display "properties" */
  2744.      do ihh=1 to propnames.0
  2745.       if  aprop.ihh='' then iterate
  2746.       aa='<li><b>'propnames.ihh':</b> 'aprop.ihh
  2747.       call dumpit(aa)
  2748.     end /* do */
  2749.   end
  2750.   if gotprop>0 then call dumpit('</ul>')
  2751.  
  2752.   nfound=nfound+1
  2753.   IF IGOT>=(START+TOFIND-1) then leave
  2754.  
  2755. end
  2756. if igot>start then call dumpit('</dl>')
  2757.  
  2758. /* write a summarization line */
  2759. makelink=0
  2760. select 
  2761.   when NUMBEROFHITS=0 then
  2762.      call dumpit('<p><em>No matches... </em><BR> ')
  2763.   when nfound=0 then            /* > 0 HITS, BUT ALL LESS THEN START # */
  2764.      call dumpit('<p> <em> Number of matches less then requested starting match (at # 'start') </em><BR>')
  2765.   when nfound<tofind & start<2  then
  2766.         call dumpit("<p> <em> Total of " igot " matches </em><BR>")
  2767.   otherwise do
  2768.     if max_find>0 then do
  2769.         call dumpit("<p> <em> Displaying " (1+igot-start) "  of " MAX_FIND" total matches (starting from match # "start ") </em><BR>")
  2770.         makelink=1
  2771.     end
  2772.     else do
  2773.         call dumpit("<p> <em> Displaying " (1+igot-start) " matches (starting from match # "start ") </em><BR>")
  2774.     end
  2775.   end
  2776. end
  2777.  
  2778. if makelink=1 then do
  2779.   if max_find>0  then do           /* set up links to next/prior matches */
  2780.      call dumpit('<br>')
  2781.      if all_sets<>1 then
  2782.         call show_prior_next
  2783.      else
  2784.         call show_all_sets
  2785.   end /* do */
  2786.  
  2787.   if search_link<>'' then do
  2788.      aa='   ||   <a href="'search_link'">New search?</a><br>'||crlf
  2789.      call dumpit(aa)
  2790.      didnew=1
  2791.   end /* do */
  2792. end
  2793.  
  2794.  
  2795. call dumpit('<p>')
  2796.  
  2797. donesearch:                     /* skip here on error */
  2798. if didnew=0 & search_link<>'' then do
  2799.    aa='   <a href="'search_link'">New search?</a><br>'||crlf
  2800.    call dumpit(aa)
  2801. end /* do */
  2802.  
  2803. /*write a footer file */
  2804. if footer_file<>' ' then do       
  2805.    aa=""
  2806.   if footer_file<>' ' then do
  2807.      tff=swish_dir'\'footer_file
  2808.      wow=afileread(tff)
  2809.      if wow=0 & is_cgi=0 then call pmprintf("GoSWISH warning: no footer file="tff)
  2810.      do ww=1 to wow
  2811.         aa=aa||crlf||ffread.ww
  2812.      end /* do */
  2813.      call dumpit(aa)
  2814.    end  /* Do */
  2815. end  /* Do */
  2816.  
  2817. sendher: nop
  2818. aa='</body></html> '
  2819. call dumpit aa
  2820.  
  2821. if is_cgi=0 then do
  2822.    gaz=value('SREF_PREFIX',,'os2environment')
  2823.    if gaz='' then
  2824.      'VAR type text/html name bigstuff'
  2825.    else
  2826.      foo=sref_gos('VAR type text/html name bigstuff ',bigstuff)
  2827. end
  2828. return 0
  2829.  
  2830.  
  2831.  
  2832. /**************************/
  2833. /* links to sets of matches */
  2834. show_all_sets:
  2835. call dumpit('<br><tt>Other matches:</em> ')
  2836. glen=0
  2837. do mj1=1 to max_find by tofind
  2838.   newlist1=newlist||'&START='||mj1||'+'||max_find
  2839.   call dumpit('<a href="'||newlist1||'">' mj1'</a>    ')
  2840.   glen=glen+1
  2841. end /* do */
  2842.  
  2843. return 1
  2844.  
  2845. /**************************/
  2846. /* links to prior & next matches */
  2847. show_prior_next:
  2848.  
  2849.    if igot>tofind then do       /* setup link for prior TOFIND */
  2850.         j1=MAX(1,start-tofind)
  2851.         newlist1=newlist||'&START='||j1||'+'||max_find
  2852.         call dumpit('<a href="'||newlist1||'">Prior' tofind ' matches </a> ')
  2853.    end
  2854.    if igot<max_find then do   /* set up link for next TOFIND */
  2855.         j1=start+nfound
  2856.         newlist1=newlist||'&START='||j1||'+'||max_find
  2857.         eef=' '
  2858.         if igot>tofind then eef=' || '
  2859.         call dumpit(eef' <a href="'||newlist1||'"> Next' tofind ' matches </a> ')
  2860.    end /* do */
  2861. return 1
  2862.  
  2863. /*******************/
  2864.  
  2865.  
  2866.  
  2867. /**************** say ***/
  2868. /* say to stdout */
  2869. dumpit:procedure expose is_cgi bigstuff
  2870. parse arg aa
  2871.  
  2872. if is_cgi=0 then do
  2873.    bigstuff=bigstuff||aa||'0d0a'x
  2874.    return 0
  2875. end /* do */
  2876. aa=aa||'0d0a'x
  2877. say aa
  2878. return 0
  2879.  
  2880.  
  2881. /*****************************/
  2882. /* check swish indices of a list of indices.
  2883. Returns 11 if (all) are 1.1
  2884.         12 if (all) are 1.2
  2885.         13 if all are 1.3
  2886.         Error message if a problem (missing file, mixed types, non-swish index */
  2887. check_indxfile_type:procedure
  2888.  
  2889. parse arg fils
  2890. is11=0 ; is13=0 ; is12=0
  2891. do forever
  2892.    if fils='' then leave
  2893.    parse var fils afil fils
  2894.    afil=translate(strip(afil),'\','/')
  2895.    if stream(afil,'c','query exists')='' then return 'No such file: 'afil
  2896.    aa=charin(afil,1,80) ;saa=stream(afil,'c','close')
  2897.    a1=translate(space(aa,0))
  2898.    select
  2899.      when  abbrev(a1,'#SWISHFORMAT1.1')=1 then is11=1
  2900.      when  abbrev(a1,'#SWISHFORMAT1.2')=1 then is12=1
  2901.      when  abbrev(a1,'#SWISHFORMAT1.3')=1 then is13=1
  2902.      otherwise return 'Error. Not a SWISH index file: 'afil
  2903.    end
  2904.    if (is11+is13+is12)>1 then return 'Error: can not examine a mixture of SWISH index types'
  2905. end
  2906. iu=(is11*11)+(is13*13)+(is12*12)
  2907. if iu=0 then return 'Error. Could not determin SWISH index type'
  2908. return iu
  2909.  
  2910.  
  2911.  
  2912.  
  2913. /************/
  2914. /* read file into ffread stem var */
  2915. afileread:procedure expose ffread.
  2916. parse arg hfile
  2917. crlf='0d0a'x
  2918. if stream(hfile,'c','query exists')="" then return 0
  2919. tmp=strip(charin(hfile,1,chars(hfile)),'t','1a'x)
  2920. tt=stream(hfile,'c','close')
  2921. itmp=0
  2922. do until tmp=""
  2923.    itmp=itmp+1
  2924.    parse var tmp ffread.itmp (crlf) tmp
  2925. end /* do */
  2926. ffread.0=itmp
  2927. return itmp 
  2928.  
  2929.  
  2930.  
  2931. /***********************************/
  2932. /* search files names, etc instead of keyword index 
  2933. dcache.  contains cache index 
  2934. dcachel. just the urls (for searching in)
  2935. filelines. return these to be displayed
  2936. isfilesearch: 0= normal keywords, 1=search pathnames, 2=search summarys, 3=search filenames
  2937. keywords: keywords to search for (and highlight)
  2938. ndofiles: max matches to display
  2939. ktall: count all matches (only return ndofiles 
  2940. */
  2941. do_fsearch:procedure expose dcache. dcachel. filelines.  swish_version is_cgi bigstuff
  2942.  
  2943.   parse arg  isfilesearch,keywords,start,ndofiles
  2944.  keywords='OR '||translate(strip(keywords))
  2945. /* seperate out OR AND and NOT keywords. Default is AND (first
  2946. one is OR) */
  2947. alist.1=' ' ; alist.2=' ' ; alist.3=' ';ismod=1
  2948. do mm=1 to words(keywords)
  2949.    aw=translate(strip(word(keywords,mm)))
  2950.    oop= wordpos(aw,'OR AND NOT')
  2951.    if oop=0 then do
  2952.         alist.ismod=alist.ismod||' '||aw
  2953.         ismod=2                 /* reset to AND */
  2954.    end
  2955.    else do
  2956.         ismod=oop
  2957.    end  /* Do */
  2958. end /* do */
  2959.  
  2960. oof=keywords
  2961. if strip(translate(word(keywords,1)))="OR" then oof=subword(keywords,2)
  2962.  
  2963. select
  2964.   when isfilesearch=3 then
  2965.      bb='<p><strong> Searching file names for: </strong><code> 'oof||'</code>'||'0d0a'x
  2966.   when isfilesearch=1 then
  2967.      bb='<p><strong> Searching path & file names for: </strong><code> 'oof||'</code>'||'0d0a'x
  2968.   otherwise  
  2969.      bb='<p><strong> Searching <em>summaries </em> for: </strong><code> 'oof||'</code>'||'0d0a'x
  2970. end
  2971.  
  2972. call dumpit(bb)
  2973.  
  2974. ors=alist.1 ; ors.0=0
  2975. if ors<>' ' then ors.0=words(ors)
  2976. ands=alist.2 ; ands.0=0
  2977. if ands<>' ' then ands.0=words(ands)
  2978. nots=alist.3 ; nots.0=0
  2979. if nots<>' ' then nots.0=words(nots)
  2980.  
  2981. /* check each line for ors, ands, and nots */
  2982. do mm=1 to dcache.0
  2983.    isok.mm=0            /* assume faiulre */
  2984.  
  2985.    select
  2986.       when isfilesearch=3 then do
  2987.         aurl=strip(translate(dcachel.mm))
  2988.         booi=lastpos('/',translate(aurl,'/','\'))
  2989.         if booi>0 then aurl=substr(aurl,booi+1)
  2990.      end /* do */
  2991.      when isfilesearch=1 then do
  2992.           aurl=strip(translate(dcachel.mm))
  2993.      end
  2994.      otherwise do
  2995.         aurl=strip(translate(dcache.mm.!ASUMMARY))
  2996.      end
  2997.   end
  2998.  
  2999. /* if it's a not, failure */
  3000.    do mm2=1 to nots.0
  3001.       if pos(strip(word(nots,mm2)),aurl)>0 then iterate mm
  3002.    end
  3003. /* all and's have to be there */
  3004.     do mm2=1 to ands.0
  3005.         if pos(strip(word(ands,mm2)),aurl)=0 then iterate mm
  3006.     end /* do */
  3007. /*any of the ors */
  3008.    isok.mm=1           
  3009.    if ors.0=0  then iterate   /* >0 ors, 1 must be fulfilled */
  3010.    do mm2=1 to ors.0
  3011.       jj=strip(word(ors,mm2)) 
  3012.       if  pos(jj,aurl)>0 then iterate mm /* success*/
  3013.    end /* do */
  3014.    isok.mm=0             /* did not match an ors */
  3015. end /* do */
  3016.  
  3017. /* if isok=1, then this is a match. Return the first ndo matches in
  3018. the filelines. stem variable. Filelines. should contain:
  3019.  score url title position:
  3020. score=100 (that is, no score)
  3021. url=dcache.n
  3022. title=dcache.n.!title
  3023. bytes=title.n.!size
  3024. */
  3025. filelines.1='# GoSWISH Search'
  3026. imatch=0
  3027. do mm=1 to dcache.0
  3028.    if isok.mm=1 then imatch=imatch+1
  3029. end
  3030. filelines.2='# Number of hits: 'imatch
  3031. noks=2
  3032. do mm=1 to dcache.0
  3033.    if isok.mm=1 then do
  3034.        noks=noks+1
  3035.        atitle=dcache.mm.!title ; if atitle="" then atitle=dcache.mm
  3036.        filelines.noks='100 ' dcache.mm ' ' atitle ' ' dcache.mm.!size
  3037.        if noks0=(2+start+ndofiles) then leave
  3038.    end  /* Do */
  3039. end /* do */
  3040. filelines.0=noks
  3041. return noks
  3042.  
  3043.  
  3044. /* ---------------------------------------------------------------------- */
  3045. /* extract summary info from cache-descripton file (or create it on the
  3046.    fly 
  3047. Asummary:  1=use preexsiting only, 2=create if necessary
  3048. acheck:1=check on existence of file or url
  3049. cache_type : 0=none, 1=old style, 2= new (big) style
  3050. */
  3051.  
  3052. make_summary2:procedure expose tempfile ddir enmadd transaction  dcache. dcachel. ,
  3053.           swish_version is_cgi bigstuff  dctindx. def_htmls
  3054.  
  3055.  
  3056. parse arg aa,a_title,aurl,asummary, srchwords,acheck,addli,addhit,incache,cache_type
  3057.  
  3058. crlf='0a0d'x
  3059. if addli>0 then do
  3060.    atag='<li>'
  3061. end
  3062. else do
  3063.   atag='<dd>'
  3064. end
  3065.  
  3066.  
  3067. aayes='<dt>'addhit' <A href=' aurl '>' a_title '</a>'crlf
  3068. aano='<dt>'addhit' <u>' a_title '</u>'crlf
  3069.  
  3070. ishttp=abbrev(strip(translate(aurl)),"HTTP://") /* file, or url? */
  3071.  
  3072. /* if acheck=1, then check on existence of file, or of url */
  3073. if acheck=1 then do
  3074.   if ishttp=0 then do
  3075.     afilenam=aurl
  3076.     if afilenam<>"" then afilenam=stream(afilenam,'c','query exists')
  3077.     if afilename="" then
  3078.        call dumpit(aano||aa)
  3079.     else
  3080.        call dumpit(aayes||aa)
  3081.     
  3082.   end
  3083.   else do               /* use HEAD request for url */
  3084.      stuff=a_head_url(aurl)
  3085.      if stuff=0 then
  3086.        call dumpit(aano||aa)
  3087.      else
  3088.        call dumpit(aayes||aa)
  3089.   end /* do */
  3090. end
  3091. else do         /* no check, assume it exists */
  3092.        call dumpit(aayes||aa)
  3093. end
  3094.  
  3095. if asummary<1   then return 0   /* no summary desired,  so return */
  3096.  
  3097. if addli>0 then    call dumpit('<ul>')
  3098.  
  3099. if asummary=1 & (cache_type=0 | incache=0 ) then do   /* no create, no cache ..*/
  3100.     call dumpit(' 'atag' <code> Summary not available </code> ')
  3101.     return 0
  3102. end
  3103.  
  3104.  
  3105. /******* try and find, or create, a summary */
  3106.  
  3107. /* note: .!sumtype values:  0-none, 1=created, 2=explicit */
  3108. aurl=translate(aurl)
  3109.  
  3110. if cache_type>0  then do           /* cache exists:ALWAYS Use it! */
  3111.    gotit=0
  3112.    if cache_type=1 then do              /* scan regular index  */
  3113.      do mm=1 to dcachel.0
  3114.        if dcachel.mm=aurl then do
  3115.            gotit=mm ; leave
  3116.        end /* do */
  3117.      end /* do */
  3118.    end
  3119.    else do                      /* extract from  the structured index */
  3120.      gotit=1
  3121.      arecord=read_desc_record(aurl)
  3122.      if arecord<>'' then do
  3123.         div='05'x
  3124.         parse var arecord sumtype  (div) . (div) . (div) dathing
  3125.         if sumtype=0 then do                            /* signal "no sumary */
  3126.            call dumpit(atag' <code> '|| dathing|| ' </code> ')
  3127.            return 0
  3128.         end
  3129.      end
  3130.      else do                    /* signal "no match */
  3131.          gotit=0
  3132.      end /* do */
  3133.    end /* do */
  3134.  
  3135.    if gotit=0 then do    /* shouldn't happen (all files should have some entry */
  3136.        call dumpit(' 'atag' <code> Summary is not available </code> ')
  3137.        return 0
  3138.     end
  3139.  
  3140. /* if here, got some kind of match */
  3141.    if  cache_type=1 then  do
  3142.       dathing=strip(dcache.GOTIT.!ASUMMARY) /* if cache_type=2, already know it*/
  3143.       if dcache.gotit.!sumtype=0 then do        /* no match signal */
  3144.          call dumpit(atag' <code> '|| dathing|| ' </code> ')
  3145.          return 0
  3146.        end  /* Do */
  3147.    end
  3148.  
  3149.    wow=space(translate(dathing,' ','00090a0d1a1b'x))    /* cleanup selection */
  3150.    srchwords2=what_words(srchwords)
  3151.     do jmm=1 to words(srchwords2)
  3152.          aword=strip(word(srchwords2,jmm))
  3153.          if wordpos(translate(aword),'OR NOT AND ( )')=0 then
  3154.             wow=make_block(aword,wow,'<u>','</u>')   /* highlight matches */
  3155.      end
  3156.      if  dcache.gotit.!sumtype=1 then     /* "created" is a "rougher" match */
  3157.           aa=atag'  <code> ' wow ' </code>'
  3158.      else
  3159.           aa=atag'   ' wow
  3160.      call dumpit(aa)
  3161.      return 0
  3162. end               /* search in description-cache file */
  3163.  
  3164.  
  3165. /* if here == no cache, but create */
  3166.  
  3167. /***** generate on the fly ***/
  3168.  
  3169. anext=''
  3170. goo=lastpos('.',aurl)
  3171. if goo>0 then
  3172.   anext=substr(aurl,goo+1)
  3173. ishtml=0
  3174. if wordpos(translate(strip(anext)),translate(def_htmls))>0 then ishtml=1
  3175. /* strip out http://a.b.c/ */
  3176.  
  3177. if ishttp=0 then do
  3178.  
  3179.   if afilenam="" then do
  3180.      call dumpit(atag' <code> No summary available </code> ')
  3181.      return 0
  3182.   end
  3183.  
  3184.   eek=sysfiletree(afilenam,'aflist','F')   /* check for existence*/
  3185.   if eek<>0 | aflist.0=0 then do            /* error */
  3186.       call dumpit(atag' <code> Summary not available </code> ')
  3187.       return 0
  3188.   end
  3189.  
  3190. end
  3191.  
  3192. /* text/plain summary ... */
  3193. if ISHTML=0 then do
  3194.    if ishttp=1 then do
  3195.         stuff=get_url(aurl,500)
  3196.         if length(stuff)>500 then stuff=left(stuff,500)
  3197.         else
  3198.         if stuff=0 then do
  3199.            call dumpit(atag' <code> Summary not available </code> ')
  3200.            return 0
  3201.         end
  3202.     end
  3203.     else do
  3204.        filename=aflist.1
  3205.        filename=strip(word(aflist.1,words(aflist.1)))
  3206.        alen=min(chars(filename),500)
  3207.        stuff=charin(filename,1,alen)
  3208.     end
  3209.  
  3210.     wow=space(translate(stuff,' ','00090a0d1a1b'x))
  3211.     wow=replacestrg(wow,'&','&','ALL')
  3212.     wow=replacestrg(wow,'<','<','ALL')
  3213.     wow=replacestrg(wow,'>','>','ALL')
  3214.     wow=replacestrg(wow,'"','"','ALL')
  3215.     srchwords2=what_words(srchwords)
  3216.     do jmm=1 to words(srchwords2)
  3217.          aword=strip(word(srchwords2,jmm))
  3218.          if wordpos(translate(aword),'OR NOT AND ( )')=0 then
  3219.             wow=make_block(aword,wow,'<u>','</u>')   /* highlight matches */
  3220.      end
  3221.     call dumpit(atag'   '|| wow)
  3222.     return 0
  3223. end
  3224.  
  3225. /* if not html (and not text/plain), return no summary*/
  3226. if ISHTML=0  then do
  3227.      call dumpit(atag' <code> Summary not available </code> ')
  3228.    return 0
  3229. end
  3230.  
  3231.  
  3232. /* if here--  html*/
  3233. /* and the url points to a legit file; read it in (up to 10000 characters */
  3234.  
  3235. if ishttp=1 then do
  3236.         stuff=get_url(aurl,10000)
  3237.         if stuff=0 then do
  3238.            call dumpit(atag' <code> Summary not available </code> ')
  3239.            return 0
  3240.         end
  3241. end
  3242. else do
  3243.    filename=aflist.1
  3244.    filename=strip(word(aflist.1,words(aflist.1)))
  3245.    alen=min(chars(filename),10000)
  3246.    stuff=charin(filename,1,alen)
  3247. end
  3248.  
  3249. stuff=space(translate(stuff,' ','00090a0d1a1b'x))
  3250. url_title=0
  3251.  
  3252. wow=look_header(filename)
  3253.  
  3254. if wow<>0 then do
  3255.    srchwords2=what_words(srchwords)
  3256.    do jmm=1 to words(srchwords2)
  3257.       aword=strip(word(srchwords2,jmm))
  3258.       if wordpos(translate(aword),'OR NOT AND ( )')=0 then
  3259.           wow=make_block(aword,wow,'<u>','</u>')   /* highlight matches */
  3260.   end
  3261.   call dumpit(atag' '|| wow)
  3262.   return 0
  3263. end
  3264.  
  3265. WOW=LOOK_HTAG()
  3266. if wow<>0 then do
  3267.   do jmm=1 to words(srchwords)
  3268.       aword=strip(strip(word(srchwords,jmm)),'t','*')
  3269.       if wordpos(translate(aword),'OR NOT AND ( )')=0 then
  3270.          wow=make_block(aword,wow,'<u>','</u>')   /* highlight matches */
  3271.   end
  3272.   call dumpit(atag' <code>'||  wow ||' </code>')
  3273.   return 0
  3274. end
  3275.  
  3276. if url_title<>0 then
  3277.    aa=atag' <code> ' url_title ' </code> '
  3278. else
  3279.    aa=atag' <code> Summary not available </code> '
  3280. call dumpit(aa)
  3281. return 0
  3282.  
  3283.  
  3284.  
  3285. /* do a head request */
  3286. a_head_url:procedure
  3287. parse arg aurl
  3288. crlf='0d0a'x
  3289.  
  3290. got=""
  3291. aurl=fix_url(aurl)
  3292. if abbrev(translate(aurl),'HTTP://')=1 then do
  3293.    aurl=substr(aurl,8)
  3294. end
  3295. parse var aurl server '/' request
  3296.  
  3297. family  ='AF_INET'
  3298. httpport=80
  3299.  
  3300. rc=sockgethostbyname(server, "serv.0")  /* get dotaddress of server */
  3301. if rc=0 then do;  return 0; end
  3302.  
  3303. dotserver=serv.0addr                    /* .. */
  3304.  
  3305. gosaddr.0family=family                  /* set up address */
  3306. gosaddr.0port  =httpport
  3307. gosaddr.0addr  =dotserver
  3308.  
  3309. gosock = SockSocket(family, "SOCK_STREAM", "IPPROTO_TCP")
  3310.  
  3311. request=strip(request,'l','/')
  3312. message='HEAD /'request' HTTP/1.0'crlf'HOST:'server||crlf
  3313.  
  3314. message=message||crlf
  3315. got=''
  3316. rc = SockConnect(gosock,"gosaddr.0")
  3317. if rc<0 then do;  return 0 ; end
  3318. rc = SockSend(gosock, message)
  3319. /* Now wait for the response */
  3320. do r=1 by 1
  3321.   rc = SockRecv(gosock, "response", 1000)
  3322.   got=got||response
  3323.   if rc<=0 then leave
  3324.   end r
  3325. rc = SockClose(gosock)
  3326.  
  3327. parse var  got aa (crlf) .
  3328. parse var aa a1 a2 a3
  3329. if a2>=300 then return 0
  3330. return 1
  3331.  
  3332.  
  3333. /*--------------------------- */
  3334. /* exract search words */
  3335. what_words:procedure
  3336. parse arg wlist
  3337.  
  3338. wlist=strip(translate(wlist,' ','()*'))
  3339. if pos('=',wlist)=0 then return strip(space(wlist))
  3340.  
  3341. /*else, remove "meta names" */
  3342. bm=''
  3343. do forever
  3344.   if wlist='' then return strip(space(bm))
  3345.   parse var wlist a1 '=' wlist
  3346.   if words(a1)>1 then do
  3347.      a1=delword(a1,words(a1))
  3348.      bm=bm' 'a1
  3349.   end
  3350. end
  3351.  
  3352.  
  3353. /* ----------------------------------------------------------------------- */
  3354. /* MAKE BLOCK: Replace all occurences of NEEDLE in HAYSTACK
  3355. .        with delim1 needle delim2.
  3356. .        If delim1 and delim2 not give, then { AND } are used.
  3357. .   Example: make_block(boys,' there are wild boys out there','<b>',' </b>')
  3358. .      returns 'there are wild <b>boys </b> out  there'
  3359. .      (note that spaces are all retained)
  3360. */
  3361. /* ----------------------------------------------------------------------- */
  3362.  
  3363. make_block:procedure
  3364.  
  3365. parse arg needle, haystack, delim1 , delim2, check_case
  3366.  
  3367. if delim1="" then delim1='{'
  3368. if delim2="" then delim1='}'
  3369.  
  3370. build=""
  3371. do forever
  3372.   if check_case<>1 then
  3373.      mm=pos(translate(needle),translate(haystack))
  3374.   else
  3375.      mm=pos(needle,haystack)
  3376.  
  3377.   if mm=0 then do
  3378.     build=build||haystack
  3379.     return build
  3380.   end
  3381.  
  3382.   t1=substr(haystack,1,mm-1)
  3383.   t2=substr(haystack,mm,length(needle))
  3384.   haystack=substr(haystack,mm+length(needle))
  3385.   build=build||t1||delim1||t2||delim2
  3386.  
  3387.  
  3388. end
  3389.  
  3390.  
  3391. /* ---------------------------------------------*/
  3392. /* get a url from some site, return first
  3393. maxchar characters (if maxchar missing, get 10million (the whole thing?) */
  3394. /* ---------------------------------------------*/
  3395. get_url:procedure
  3396. parse arg aurl,maxchar
  3397.  
  3398. if maxchar="" then maxchar=10000000
  3399.  
  3400. got=""
  3401. aurl=fix_url(aurl)
  3402. if abbrev(translate(aurl),'HTTP://')=1 then do
  3403.    aurl=substr(aurl,8)
  3404. end
  3405. parse var aurl server '/' request
  3406.  
  3407.  
  3408. /* now get the url.  This is based on GoServe's MOVEAUD command. It
  3409. requires the RxSock.DLL be in your LIBPATH. */
  3410.  
  3411.     crlf    ='0d0a'x                        /* constants */
  3412.     family  ='AF_INET'
  3413.     httpport=80
  3414.  
  3415.     rc=sockgethostbyname(server, "serv.0")  /* get dotaddress of server */
  3416.     if rc=0 then do
  3417.         return 0
  3418.     end
  3419.     dotserver=serv.0addr                    /* .. */
  3420.     gosaddr.0family=family                  /* set up address */
  3421.     gosaddr.0port  =httpport
  3422.     gosaddr.0addr  =dotserver
  3423.  
  3424.     gosock = SockSocket(family, "SOCK_STREAM", "IPPROTO_TCP")
  3425.  
  3426.     /* Set up request [HTTP 0.9 style, for all servers] */
  3427.     message="GET /"request''crlf
  3428.  
  3429.     got=''
  3430.     rc = SockConnect(gosock,"gosaddr.0")
  3431.     if rc<0 then do
  3432.         return 0
  3433.     end
  3434.     rc = SockSend(gosock, message)
  3435.  
  3436.  
  3437.  /* Now wait for the response */
  3438.  
  3439.    do r=1 by 1
  3440.      rc = SockRecv(gosock, "response", 1000)
  3441.      got=got||response
  3442.      if rc<=0 then leave
  3443.      tmplen=length(got)
  3444.      if tmplen> maxchar then leave
  3445.   end r
  3446.  
  3447.   rc = SockClose(gosock)
  3448.  
  3449. return got
  3450.  
  3451.  
  3452.  
  3453. /* ----------------------------------------------------------------------- */
  3454. /* FIX_URL: Make a fully specified http://url out of message            */
  3455. /* mayl not work if subdirectories have periods */
  3456. /* ----------------------------------------------------------------------- */
  3457. fix_url:procedure
  3458. parse arg message,servername,serverport
  3459.  
  3460. /* use defaults if not provided */
  3461. if servername="" then  servername=get_hostname()
  3462. if serverport="" then  serverport=80
  3463.  
  3464.  
  3465.  message=strip(translate(message,'/','\'))
  3466.  
  3467.  if abbrev(translate(message),"HTTP://")=1 then
  3468.              return message              /* assume the rest is legit */
  3469.  
  3470. /* if not a fully qualified http url (i.e. http://xxx.yyy/zzz) then
  3471.    make it so
  3472.  
  3473. Rule: (assuming  no http:// in message)
  3474.   Strip leading any leading /
  3475.   Look for a /  If no slash found, 
  3476.         look for periods.  If > 1 found, it's a "default" for a ip address
  3477.         if <2 found, it's a local file
  3478.   Check stuff before first /.
  3479.          If it has any periods, its an ip address (stuff after is the url)
  3480.          If no periods, it's a local url (stuff before is first subdirectory)
  3481. */
  3482.  
  3483. message=strip(message,'l','/')
  3484.  
  3485.  
  3486. islash=pos('/',message)
  3487. if islash=0 then do
  3488.     foo=translate(message,' ','.')
  3489.     if words(foo)>2 then do
  3490.           anip=message
  3491.           aport=80
  3492.           afile=""
  3493.     end
  3494.     else do
  3495.           anip=servername
  3496.           aport=serverport
  3497.           afile=message
  3498.     end
  3499. end                                     /* no slashes found */
  3500.  
  3501. else do
  3502.    parse var message p1 '/' p2     /* slash found,extract what's before it */
  3503.    foo=translate(p1,' ','.')
  3504.    if words(foo)>1 then do    /* >0 periods signifies this is an ip address */
  3505.           anip=p1
  3506.           aport=80
  3507.           afile=p2
  3508.     end
  3509.     else do
  3510.           anip=servername
  3511.           aport=serverport
  3512.           afile=message
  3513.     end
  3514. end
  3515.  
  3516. isit="http://"||anip
  3517. if aport<>80 then
  3518.     isit=isit||':'||aport
  3519. isit=isit||'/'||afile
  3520.  
  3521.  return isit
  3522.  
  3523.  
  3524.  
  3525.  
  3526. /* get the hostname (aa.bb.cc) for this machine */                     
  3527. get_hostname: procedure                                                
  3528.     do queued(); pull .; end                   /* flush */             
  3529.     address cmd '@hostname | rxqueue'                                  
  3530.                                                                        
  3531.     parse pull hostname                                                
  3532.     return hostname                                                    
  3533.                                                                        
  3534.  
  3535. errarf:
  3536. say " ERROR at line " sigl' 'rc
  3537. return 0
  3538.  
  3539.  
  3540. /***********************/
  3541. /* read entry names (files, or replacerule'd files, from a 1.3 swish index.  
  3542. Call as
  3543.  nfiles=get_swish_filelist(swish_index_file)
  3544. where
  3545.  nfiles: # of files or an error code
  3546. and
  3547.  filelist. is an "expose" stem containing these entries (in "reverse" order),
  3548.  with tails
  3549.    n.!original -- the entry name in the index
  3550.    n.!title    -- it's title
  3551.    n.!size     -- it's size
  3552. and with 
  3553.   filelist.0=nfiles (assuming no error, else filelist.0=0)
  3554.  
  3555. The error codes are:
  3556.  -1  -- could not file swish_index_file
  3557.  -2  -- is not a swish_index_file (first line does not look like "# SWISH format 1.3" 
  3558.  -3  -- could not find file count in swish_index_file
  3559.  -4  -- could not open swish_index_file
  3560.  -5  -- not a proper 1.3 or 1.2 index file (did not end in a '0a'x)
  3561.  -6  -- file does not contain nfile entries 
  3562.  -7  -- file contains nfiles-1 entries, but could not find nfile'th entry
  3563.  -8  -- it's a swish index, but not a 1.1, 1.2 or a 1.3 swish index
  3564.  -9  -- same as -8
  3565. */
  3566.  
  3567. get_swish_filelist:procedure expose filelist.
  3568. parse arg filename
  3569. cr='0a'x
  3570. filelist.0=0
  3571. filelen=stream(filename,'c','query size')
  3572. if filelen=0 | filelen='' then return -1
  3573. aa=stream(filename,'c','open read')
  3574. if translate(aa)<>'READY:' then return '-4 '
  3575.  
  3576. chunk=charin(filename,1,min(filelen,1000))
  3577.  
  3578. parse var chunk  aline (cr) chunk
  3579.  
  3580. parse upper var aline a1 a2 a3 verswi dpg 
  3581. verswi=strip(verswi)
  3582. if strip(a2)<>'SWISH' | strip(a3)<>'FORMAT' then return -2  /* not a swish file,give up*/
  3583. nfiles=0
  3584. do mm=1 to 100       /* read lines until you find # Counts: 6193 words, 100 files */
  3585.    parse var chunk aline (cr) chunk
  3586.    parse upper var aline . a1 . ',' a2 .
  3587.    if a1="COUNTS:" then do
  3588.         nfiles=a2
  3589.         leave
  3590.    end /* do */
  3591. end /* do */
  3592. if nfiles=0 then return -3  
  3593.  
  3594. if verswi=1.1 then signal is11
  3595. if verswi=1.2 then signal is12
  3596.  
  3597.  
  3598. if wordpos(verswi,'1.2 1.3')=0 then return -9
  3599.  
  3600. /* try this sized chunk, up it if not big enough */
  3601. perfile=220  
  3602.  
  3603.  
  3604. tryagain:               /* jump here to try again */
  3605. nget=perfile*nfiles
  3606.  
  3607. ifrom=max(1,1+filelen-nget)             /* get chunk starting here */
  3608. chunk=charin(filename,ifrom,nget)
  3609. if right(chunk,1)<>'0a'x then return  -5  /* 1.3 always ends in '0a'x */
  3610. nget2=length(chunk)
  3611.  
  3612. ii=lastpos('0a'x,chunk,nget2-1)    /* get beyoud property names */
  3613. ii2=lastpos('0a'x,chunk,ii-1)     /* and some other number stuff */
  3614.  
  3615. /* now scan back in chunk, parsing on '0000'x (which seems to signal "end of entry" */
  3616. do jj=1 to nfiles-1
  3617.    ii2=lastpos('0000'x,chunk,ii2-1)
  3618.    if ii2=0 then do                     /* perhaps didn't get enough info ? */
  3619.         if ifrom=1 then return -6      /* can't get more? give up */
  3620.         perfile=perfile*2               /* so get a bigger chunk this time */
  3621.         leave
  3622.    end /* do */
  3623.    kj=pos('0a'x,chunk,ii2+1)
  3624.    baa=substr(chunk,ii2,kj-ii2)
  3625.    baa=strip(translate(baa,' ','00090d0a'x))
  3626.    parse var baa aa  '"' atitle '"' asize .
  3627.    filelist.jj.!original=translate(strip(aa))
  3628.    filelist.jj.!title=atitle
  3629.    filelist.jj.!size=asize
  3630. end /* do */
  3631. if ii2=0 then signal tryagain   /* rexx can be buggy when signaling from a do loop */
  3632.  
  3633. /* last one is tricky -- can't search for 0000 */
  3634. do forever                      /* exit via a return or a signal */
  3635.    ii2=lastpos('0a'x,chunk,ii2-2)
  3636.    if ii2=0 then do                     /* perhaps didn't get enough info ? */
  3637.         if ifrom=1 then return -7      /* can't get more? give up */
  3638.         perfile=perfile*2               /* so get a bigger chunk this time */
  3639.         leave
  3640.    end /* do */
  3641.    isa=c2d(substr(chunk,ii2+1,1))
  3642.    if isa>31 then do 
  3643.        kj=pos('0a'x,chunk,ii2+1)
  3644.        baa=substr(chunk,ii2,kj-ii2)
  3645.        baa=strip(translate(baa,' ','00090d0a'x))
  3646.        parse var baa aa  '"' atitle '"' asize .
  3647.        filelist.nfiles.!original=translate(strip(aa))
  3648.        filelist.nfiles.!title=atitle
  3649.        filelist.nfiles.!size=asize
  3650.        filelist.0=nfiles
  3651.        return nfiles
  3652.    end
  3653. end /* do */
  3654. signal tryagain                 /* only way to get here is by ii2=0 */
  3655.  
  3656.  
  3657. /* ----------------------- */
  3658. is11:           /* jump here if 1.1 format */
  3659. /* count lines in the file */
  3660. call linein filename,1,0
  3661. ndo=0
  3662. do until lines(filename)=0
  3663.    foo=linein(filename)
  3664.    ndo=ndo+1
  3665. end /* do */
  3666. /* now get the lines ndo-nfiles to ndo-1 */
  3667. call linein filename,1,0
  3668. i1=1
  3669. do ij=1 to ndo-(i1+nfiles)
  3670.    foo=linein(filename)
  3671. end /* do */
  3672.  
  3673. do nf=1 to nfiles         /* extract the filenames */
  3674.    baa=linein(filename)
  3675.    baa=strip(translate(baa,' ','00090d0a'x))
  3676.    parse var baa aa  '"' atitle '"' asize .
  3677.    afil=translate(strip(word(aa,1)))
  3678.    filelist.nf.!original=afil
  3679.    filelist.nf.!title=atitle
  3680.    filelist.nf.!size=asize
  3681. end /* do */
  3682. filelist.0=nfiles
  3683. return nfiles
  3684.  
  3685.  
  3686. /* ----------------------- */
  3687. is12:           /* jump here if 1.2 format */
  3688. /* count lines in the file */
  3689. call linein filename,1,0
  3690. ndo=0
  3691. do until lines(filename)=0
  3692.    foo=linein(filename)
  3693.    ndo=ndo+1
  3694. end /* do */
  3695. /* now get the lines ndo-nfiles to ndo-1 */
  3696. call linein filename,1,0
  3697. i1=1
  3698. do ij=1 to (ndo-1)-(i1+nfiles)
  3699.    foo=linein(filename)
  3700. end /* do */
  3701.  
  3702. do nf=1 to nfiles         /* extract the filenames */
  3703.    baa=linein(filename)
  3704.    baa=strip(translate(baa,' ','00090d0a'x))
  3705.    parse var baa aa  '"' atitle '"' asize .
  3706.    afil=translate(strip(word(aa,1)))
  3707.    filelist.nf.!original=afil
  3708.    filelist.nf.!title=atitle
  3709.    filelist.nf.!size=asize
  3710. end /* do */
  3711. filelist.0=nfiles
  3712. return nfiles
  3713.  
  3714.  
  3715.  
  3716. /***************************************************/
  3717. /* build a "description-cache index"
  3718. Call as:
  3719.   status=build_desc_cache(outname,swifile)
  3720. where
  3721.   outname: .dct file to create
  3722.   swifile : index file built from
  3723. and
  3724.   status = 1 : success, 0=failure
  3725.  
  3726. And where the DESC. variable is used (via an expose)
  3727. DESC. should be structured as:
  3728.   desc.0  : # of records
  3729.   desc.i   : the identifier (as stored in the swish index file)
  3730.   desc.i.!sumtype :  0= none, 
  3731.                  1= generated
  3732.                  2= derived from directory-specific description file
  3733.   desc.i.!title  : the title (as stored in the swish index file)
  3734.   desc.i.!size   : the size (as stored in the swish index file)
  3735.   desc.i.!summary : the summary. Might be "No Summary Available "
  3736. */
  3737. build_desc_cache:procedure expose desc.
  3738. parse arg outname,amessage
  3739.  
  3740. /* 
  3741. The structure is:
  3742.   idstring : identifies the file type, starts with a #GOSWISH and ends with a crlf
  3743.                  Example: #GOSWISH 1.4  This is descriptive summaries for foo.swi 
  3744.              The idstring must be less then 500 characters.
  3745.  parameters: A space delimited list of parameters:
  3746.               NRECS:   # of records,
  3747.               IDBYTES:  # of bytes used to score record id digests,
  3748.               OFFBYTES:  # of bytes used to store offset in body-of-records, and
  3749.               BODYAT:  # offset to first byte of body-of-records
  3750.    indx: list of record-id digests and offsets.
  3751.  body-of-records:  the various records; with fields seperated by '05'x character
  3752.  Terminator: a string consisting of crlf"END."  (useful for checking integrity)
  3753. */
  3754.  
  3755. idstring="#GOSWISH 1.4 : "||strip(amessage)||'0d0a'x
  3756.  
  3757.  
  3758. /* create a list of digests of each entry name */
  3759. do mm=1 to desc.0
  3760.    md5s.mm=rexx_md0(desc.mm)
  3761. end /* do */
  3762. /* check for 4 char, 8 char and 16 char uniqueness. If all
  3763. these fail, all 32 characters (16 bytes) */
  3764. iuse=2
  3765. do iss=2 to 8 by 2
  3766.   iuse=iss*2           /*4,6,8,..,16 */
  3767.   drop tlist.
  3768.   drop idlist.
  3769.   tlist.=0
  3770.   iok=1                 /* assume okay */
  3771.   do mm=1 to desc.0
  3772.     a1=left(md5s.mm,iuse)    /* left most iuse characters of md5 digest*/
  3773.     if tlist.a1=1 then do        /* is this "id" already used? */
  3774.        say ' repeated 'iuse ' character id ='a1
  3775.        iok=0                    /* yep, leave and try larger set of character */
  3776.        leave
  3777.     end /* do */
  3778.     tlist.a1=1                   /* mark this id as used */
  3779.     idlist.mm=a1                /* save for later use */
  3780.   end /* do */
  3781.   if iok=1 then leave           /* this size works */
  3782. end /* do */
  3783. if iok=0 then 
  3784.   idbytes=16
  3785. else
  3786.   idbytes=iuse/2           /* # hex chars /2 = # of bytes */
  3787.  
  3788.  
  3789. /* Build the string of contents. An entry at a time.
  3790.    Each entry has fields seperated by '05'x.
  3791.    Each entry starts with a 2 byte size code (hence max entry size is 60k), where
  3792.    the size includes seperators but NOT the two byte size code
  3793.    Iats.ii points to the start of the entry (to first byte of the 2 byte size code)
  3794. */
  3795. div='05'x
  3796. body_of_records=''
  3797. do ii=1 to desc.0  
  3798.    blk0=desc.ii.!sumtype||div||desc.ii||div||desc.ii.!title||div||desc.ii.!size
  3799.    c2=translate(desc.ii.!summary,' ','0001020304050607'x)  /* convert some stuff to ' '*/
  3800.    blk0=blk0||div||c2||div
  3801.    il=length(blk0)
  3802.    if il>99999 then  do
  3803.       blk0=left(blk0,99999)  /* should never happen, but ... */
  3804.       il=99999
  3805.    end
  3806.    ilc=left(il,5,' ')
  3807.    blk0=ilc||div||blk0
  3808.    iats.ii=length(body_of_records)+1
  3809.    body_of_records=body_of_records||blk0   
  3810. end
  3811.  
  3812.  
  3813. /* Create offset to the entries contained in body_of_records (use iats.)
  3814.   But first-- how many bytes needed for this offset value? */
  3815.  
  3816. select
  3817.    when length(body_of_records)<64000 then offbytes=2
  3818.    when length(body_of_records)<16000000 then offbytes=3
  3819.    otherwise offbytes=4
  3820. end
  3821.  
  3822. parameters=desc.0' 'idbytes' 'offbytes' '
  3823.  
  3824.  
  3825. /* build the index to bigblock: desc.0 items with each item consisting of
  3826.    an id (with a length of idbytes bytes) and an offset (with a length of offbytes bytes)
  3827. */
  3828.  
  3829. indx=''
  3830. jpt=offbytes*2
  3831. do mm=1 to desc.0
  3832.    ida=x2c(idlist.mm)
  3833.    apt= right(d2x(iats.mm),jpt,0)  
  3834.    apt=x2c(apt)
  3835.    indx=indx||ida||apt    
  3836. end /* do */
  3837. indx=indx||'ENDINDEX'||'0d0a'x
  3838. /* we now have id string,  index, and body of entries.
  3839.    Compute total length of idstring + parameters + index + 10 -- add this value
  3840.    to parameters (in a 8 character integer + crlf) */
  3841.  
  3842. isize=length(idstring)+length(parameters)+10+length(indx)+1
  3843. parameters=parameters||right(isize,8,' ')||'0d0a'x
  3844.  
  3845. /*
  3846.    Put 'em together and write'em out */
  3847. bigblock=idstring||parameters||indx||body_of_records||'0d0a'x||'END.'
  3848.  
  3849. ff=sysfiledelete(outname)
  3850. sike=charout(outname,bigblock,1)
  3851. if sike<>0 then return 0
  3852. sike=stream(outname,'c','close')
  3853. return 1
  3854.  
  3855.  
  3856. /****************************************/
  3857. /* return a record, given a string (as pulled from swish index) 
  3858.   Requires dctindx. file (as reated by load_desc_cache) to be expose
  3859.  
  3860. Call as:
  3861.    arecord=read_desc_record(lookfor)
  3862. where
  3863.   lookfor : string to look for (should be one of the identifiers in the swish index file)
  3864. and
  3865.   arecord  :the record corresponding to lookfor, or a blank if no such record
  3866.  
  3867. Arecord can be parsed using
  3868. div='05'x
  3869. parse var arecord summary_type  (div) title (div) size (div) description
  3870. where summary_type: 0= none, 
  3871.                     1= generated,
  3872.                     2= derived from directory-specific description file
  3873.                     3= hand entered (i.e.; edit mode 
  3874. */
  3875.  
  3876. read_desc_record:procedure expose dctindx.
  3877.  
  3878. parse arg lookfor
  3879. div='05'x
  3880.  
  3881. md5=rexx_md0(strip(lookfor))
  3882. rr=left(x2c(md5),dctindx.!keylen)
  3883.  
  3884. thisoff=dctindx.rr
  3885. if thisoff=0 then return ""
  3886.  
  3887. off2=thisoff+dctindx.!offset
  3888. reclen=strip(charin(dctindx.!file,off2,5))
  3889.  
  3890. arec=charin(dctindx.!file,off2,reclen+6)
  3891.  
  3892. parse var arec dlen (div) summary_type (div) thename (div) thetitle (div) ,
  3893.                      thesize (div) thesummary (div) .
  3894.  
  3895. return  summary_type||div||thetitle||div||thesize||div||thesummary
  3896.  
  3897.  
  3898. /****************************************/
  3899. /* load the index, and other info, from a decription-cache file 
  3900.  
  3901. Call as:
  3902.    status=load_desc_cache(dctfile)
  3903. where
  3904.   dctfile : the name of the description cache file
  3905. and
  3906.   status is 1 for okay, or a negative valued error code
  3907.   error codes are:
  3908.      -1 = "Not a GoSWISH descriptive-summaries cache file"
  3909.      -2 = "File corrupted (problem with terminiator) "
  3910.      -3  = Corrupted GoSWISH description-cache file (improper termination of index): "
  3911. And where
  3912.   dctindx.  is set (it's exposed). Note that dctindx. will be intialized.
  3913. DCTINDX. is structured as:
  3914.   DCTINDX.0 = # records
  3915.   DCTINDX.!KEYLEN  : size (in bytes) of the "tails"
  3916.   DCTINDX.!OFFSET : start (in dctfile) of first record
  3917.   DCTINDX.!FILE   : name of file this is derived from
  3918.   DCTINDX.!MESSAGE : message stored with file
  3919.   DCTINDX.atail=offset   
  3920. where atail is the DCTINDX.!KEYLEN length (in bytes) x2c  hash of what you want to lookup
  3921.       offset is the offset (after DCTINDX.!OFFSET, of the start of this record.
  3922.  
  3923. ******/
  3924. load_desc_cache:procedure expose dctindx.
  3925. parse arg dctfile
  3926.  
  3927. drop dctindx.
  3928. dctindx.=0
  3929.  
  3930. fsize=stream(dctfile,'c','query size')
  3931. abegin=charin(dctfile,1,min(600,fsize))
  3932. parse var abegin agoswish iver ':' amess '0d0a'x abegin
  3933. if strip(translate(agoswish))<>'#GOSWISH' then   return -1
  3934.  
  3935. aend=charin(dctfile,fsize-3,4)
  3936. if aend<>'END.' then  return -2
  3937.  
  3938.  
  3939. parse var abegin nrecs idbytes offbytes bodyat '0d0a'x .
  3940.  
  3941. dctindx.!message=amess
  3942. dctindx.0=nrecs
  3943. dctindx.!keylen=idbytes
  3944. dctindx.!offset=bodyat-1
  3945. dctindx.!file=dctfile
  3946. /* get the index */
  3947. iget=((idbytes+offbytes)*nrecs)
  3948. goof=charin(dctfile,1,iget+600)
  3949. parse var goof . '0d0a'x . '0d0a'x goof
  3950. goof=left(goof,iget+8)
  3951. if right(goof,8)<>'ENDINDEX' then return -3
  3952.  
  3953. do ii=1 to nrecs
  3954.    igg=((ii-1)*(idbytes+offbytes))+1
  3955.    atail=substr(goof,igg,idbytes)
  3956.    dctindx.atail=c2d(substr(goof,igg+idbytes,offbytes) )
  3957. end /* do */
  3958.  
  3959. return 1
  3960.  
  3961. /***************************************************/
  3962. /* a hash, based on md5 */
  3963. rexx_md0:procedure        
  3964. parse arg stuff
  3965.  
  3966. numeric digits 11
  3967. lenstuff=length(stuff)
  3968.  
  3969. c0=d2c(0)
  3970. c1=d2c(128)
  3971. c1a=d2c(255)
  3972. c1111=c1a||c1a||c1a||c1a
  3973. slen=length(stuff)*8
  3974. slen512=slen//512
  3975.  
  3976. /* pad message to multiple of 512 bits.  Last 2 words are 64 bit # bits in message*/
  3977. if slen512=448 then  addme=512
  3978. if slen512<448 then addme=448-slen512
  3979. if slen512>448 then addme=960-slen512
  3980. addwords=addme/8
  3981.  
  3982. apad=c1||copies(c0,addwords-1)
  3983.  
  3984. xlen=reverse(right(d2c(lenstuff*8),4,c0))||c0||c0||c0||c0  /* 2**32 max bytes in message */
  3985.  
  3986. /* NEWSTUFF is the message to be md5'ed */
  3987. newstuff=stuff||apad||xlen
  3988.  
  3989. /* starting values of registers */
  3990.  a ='67452301'x;
  3991.  b ='efcdab89'x;
  3992.  c ='98badcfe'x;
  3993.  d ='10325476'x;
  3994.  
  3995. lennews=length(newstuff)/4
  3996.  
  3997. /* loop through entire message */
  3998. do i1 = 0 to ((lennews/16)-1)
  3999.   i16=i1*64
  4000.   do j=1 to 16
  4001.      j4=((j-1)*4)+1
  4002.      jj=i16+j4
  4003.      m.j=reverse(substr(newstuff,jj,4))
  4004.   end /* do */
  4005.  
  4006. /* transform this block of 16 chars to 4 values. Save prior values first */
  4007.  aa=a;bb=b;cc=c;dd=d
  4008.  
  4009. /* do 4 rounds, 16 operations per round (rounds differ in bit'ing functions */
  4010. S11=7
  4011. S12=12
  4012. S13=17
  4013. S14=22
  4014.   a=round1( a, b, c, d,   0 , S11, 3614090360); /* 1 */
  4015.   d=round1( d, a, b, c,   1 , S12, 3905402710); /* 2 */
  4016.   c=round1( c, d, a, b,   2 , S13,  606105819); /* 3 */
  4017.   b=round1( b, c, d, a,   3 , S14, 3250441966); /* 4 */
  4018.   a=round1( a, b, c, d,   4 , S11, 4118548399); /* 5 */
  4019.   d=round1( d, a, b, c,   5 , S12, 1200080426); /* 6 */
  4020.   c=round1( c, d, a, b,   6 , S13, 2821735955); /* 7 */
  4021.   b=round1( b, c, d, a,   7 , S14, 4249261313); /* 8 */
  4022.   a=round1( a, b, c, d,   8 , S11, 1770035416); /* 9 */
  4023.   d=round1( d, a, b, c,   9 , S12, 2336552879); /* 10 */
  4024.  
  4025. c=round1( c, d, a, b,  10 , S13, 4294925233); /* 11 */
  4026.   b=round1( b, c, d, a,  11 , S14, 2304563134); /* 12 */
  4027.   a=round1( a, b, c, d,  12 , S11, 1804603682); /* 13 */
  4028.   d=round1( d, a, b, c,  13 , S12, 4254626195); /* 14 */
  4029.   c=round1( c, d, a, b,  14 , S13, 2792965006); /* 15 */
  4030.   b=round1( b, c, d, a,  15 , S14, 1236535329); /* 16 */
  4031.   
  4032. a=m32add(aa,a) ; b=m32add(bb,b) ; c=m32add(cc,c) ; d=m32add(dd,d)
  4033.  
  4034. end
  4035.  
  4036. aa=c2x(reverse(a))||c2x(reverse(b))||c2x(reverse(C))||c2x(reverse(D))
  4037. return aa
  4038.  
  4039. /* round 1 to 4 functins */
  4040.  
  4041. round1:procedure expose m. c1111 c0 c1
  4042. parse arg a1,b1,c1,d1,kth,shift,sini
  4043. kth=kth+1
  4044. t1=c2d(a1)+c2d(f(b1,c1,d1))+ c2d(m.kth) + sini
  4045. t1a=right(d2c(t1),4,c0)
  4046. t2=rotleft(t1a,shift)
  4047. t3=m32add(t2,b1)
  4048. return t3
  4049.  
  4050.  
  4051. /* add to "char" numbers, modulo 2**32, return as char */
  4052. m32add:procedure expose c0 c1 c1111
  4053. parse arg v1,v2
  4054. t1=c2d(v1)+c2d(v2)
  4055. t2=d2c(t1)
  4056. t3=right(t2,4,c0)
  4057. return t3
  4058.  
  4059.  
  4060.  
  4061. /*********** Basic functions */
  4062. /* F(x, y, z) == (((x) & (y)) | ((~x) & (z))) */
  4063. f:procedure expose c0 c1 c1111 
  4064. parse arg x,y,z
  4065. t1=bitand(x,y)
  4066. notx=bitxor(x,c1111)
  4067. t2=bitand(notx,z)
  4068. return bitor(t1,t2)
  4069.  
  4070.  
  4071. /* G(x, y, z) == (((x) & (z)) | ((y) & (~z)))*/
  4072. g:procedure expose c0 c1 c1111
  4073. parse arg x,y,z
  4074. t1=bitand(x,z)
  4075. notz=bitxor(z,c1111)
  4076. t2=bitand(y,notz)
  4077. return bitor(t1,t2)
  4078.  
  4079. /* H(x, y, z) == ((x) ^ (y) ^ (z)) */
  4080. h:procedure expose c0 c1 c1111
  4081. parse arg x,y,z
  4082. t1=bitxor(x,y)
  4083. return bitxor(t1,z)
  4084.  
  4085. /* I(x, y, z) == ((y) ^ ((x) | (~z))) */
  4086. i:procedure expose c0 c1 c1111
  4087. parse arg x,y,z
  4088. notz=bitxor(z,c1111)
  4089. t2=bitor(x,notz)
  4090. return bitxor(y,t2)
  4091.  
  4092. /* bit rotate to the left by s positions */
  4093. rotleft:procedure 
  4094. parse arg achar,s
  4095. if s=0 then return achar
  4096.  
  4097. bits=x2b(c2x(achar))
  4098. lb=length(bits)
  4099. t1=left(bits,s)
  4100. t2=bits||t1
  4101. yib=right(t2,lb)
  4102. return x2c(b2x(yib))
  4103.  
  4104.  
  4105. /*****************/
  4106. /* load various dlls */
  4107. load_dll:procedure
  4108. /*---   Load REXX libraries ----- */
  4109. /* Load up advanced REXX functions */
  4110. foo=rxfuncquery('sysloadfuncs')
  4111. if foo=1 then do
  4112.   call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  4113.   call SysLoadFuncs
  4114. end
  4115. if \RxFuncQuery("SockLoadFuncs") then nop
  4116. else do
  4117.        call RxFuncAdd "SockLoadFuncs","rxSock","SockLoadFuncs"
  4118.        call SockLoadFuncs
  4119. end
  4120.  
  4121. if rxfuncquery('rxswLoadFuncs')=1 then do
  4122.    call RxFuncAdd 'rxswLoadFuncs', 'RXSWISH', 'rxswLoadFuncs'
  4123.    call rxswLoadFuncs
  4124. end /* if */
  4125. if rxfuncquery('rxswLoadFuncs')=1 then do
  4126.   say "GoSWISH: could not find RXSWISH.DLL "
  4127. end
  4128.  
  4129. return 0
  4130.  
  4131.