home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / srev13h.zip / doget.cmd < prev    next >
OS/2 REXX Batch file  |  2001-05-29  |  49KB  |  1,689 lines

  1. /* DOGET -- GET's a resource from an HTTP server                 
  2.    Call as: DOGET serveraddress requeststring                   
  3.    or DOGET, and program will prompt you for information                
  4.  
  5. Note: this looks better if you have ANSI.SYS installed as a device
  6. driver (i.e.; when your config.sys file contains
  7. DEVICE=x:\os2\mdos\ansi.sys, where x: is where OS/2 is installed)
  8.  
  9. */
  10.  
  11. /* ------------------------------------------------------------------- */
  12.  
  13. /*BEGINUSER*/
  14.  
  15. /*    -------- User changeable parameters   ---------- */
  16.  
  17. /* set to 1 to enable diff "diff decoding".  This REQUIRES
  18.    that gnu patch, diff, and ed be installed on you machine;
  19.    or that the SRE-http GDIFF utility be installed */
  20. allow_delta=1
  21.  
  22. /* Set to 1 to issue HEAD, instead of GET, requests */
  23. as_head=0
  24.  
  25. /* Set to 1 to pretend to be http/1.0 */
  26. as_http10=0
  27.  
  28. /* set this to the "delta cache files" directory (not strictly 
  29.   necessary, but it does help with a delta-encoding option) */
  30. deltas_dir='temp\deltas'
  31.  
  32. /* set to 1 to use GZIP to decompress, when GZIP is a Transfer Encoding 
  33.    Enabling this option REQUIRES that you have GZIP installed on
  34.    your computer */
  35. do_gzip=1
  36.  
  37.  
  38. /* the output file -- the contents of a response are written here
  39.    (a prior version of the file will be overwritten)  */
  40. outfile='doget.lst'
  41.  
  42. /* Display options:
  43.    0 = extract and display response headers, and try and do several
  44.        encodings. Write (possibly decoded) request body to outfile
  45.    1 = write everything (headers and content), without decoding, to outfile
  46.    2 = same as 1, but display response headers on screen
  47.    3 = same as 2, but also write request (line and headers) to out file  */
  48. out_literal=0
  49.  
  50.  
  51. /* Number of blocks to use when creating rsync-signature request header.
  52.    More blocks means longer request header, but more chances of a match 
  53.    45 yields about a 500 byte header, which is pushing acceptable
  54.    limits. Rsync_blocks must be  between 10 and 255  */
  55. rsync_blocks=45
  56.  
  57. /* viewer program to use (to view response). Leave blank
  58.    to supress "view response?" option  */
  59. viewer='e'
  60.  
  61. /* if viewer program is not a PM program (that is, if it's a simple
  62.   "command line" program), set this to 1 to "close session after execution "*/
  63. viewer_not_pm=0
  64.  
  65. /* Display extra status messages if verbose=1 */
  66. verbose=0 
  67.  
  68. /*    -------- End of User changeable parameters   ---------- */
  69.  
  70. /*ENDUSER*/
  71.  
  72. call load /* load functions if necessary */
  73. signal on error name err1 ; signal on syntax name err1 
  74. signal on halt name abend
  75.  
  76. call checkansi  /* ansi screen stuff */
  77.  
  78. deltas_dir=strip(deltas_dir,'t','\')
  79. httpport=80
  80. sendclose=1
  81. gosock=0
  82.  
  83. parse arg server request mode viewit rsyncarg .
  84.  
  85. parse source somewhere
  86. parse var somewhere . . somewhere . ; somewhere=strip(somewhere)
  87.  
  88. if server='?' then do
  89.   call show_intro
  90.   exit
  91. end
  92.  
  93. say "      "cy_ye" GET an http resource. "normal" (DOGET ? for the details ...)";say " "
  94.  
  95. mehost=get_hostname()
  96. crlf    ='0d0a'x                        /* constants */
  97. opts="" ;upwd=""
  98. ietags=0 ;etaglist='' ; efilelist=''
  99. out_literal=0
  100. oldverfile=''
  101. batchmode=0
  102. if mode<>'' then out_literal=mode
  103.  
  104. if request='' & pos('.',server)>0 then do   /* batch mode */
  105.    call do_batch
  106.    batch_mode=1
  107. end 
  108.  
  109.  
  110. if server="" then do 
  111.     mehost=get_hostname()
  112.     say " Please enter server address (ENTER= " mehost":"httpport')'
  113.     call charout,"    "cy_ye":"normal" "
  114.  
  115.     parse pull server
  116.     if server="" then server=mehost
  117. end  /* Do */
  118. parse var server server ':' bport
  119. if bport<>'' then httpport=bport
  120.  
  121. if request="" then  do
  122.   cmd_mode=0
  123.   say " Enter resource (on "server") to GET: "
  124.   call charout,"    "cy_ye":"normal" "
  125.   parse pull request
  126.  
  127.   getmore=yesno('Select more options ','No Few_more Many_more','N')
  128.   if getmore>0 then
  129.        call do_getmore getmore
  130.  
  131. end
  132.  
  133. else do                 /* request is on command line */
  134.   if batchmode=0 then do
  135.    cmd_mode=1
  136.    iss=stream('doget.hdr','c','query size')
  137.    if iss<>0 & iss<>'' then do
  138.          afil='doget.hdr'
  139.          goo=charin(afil,1,iss); foo=stream(afil,'c','close')
  140.          say "Note: using request headers specified in "afil
  141.          opts=opts||goo
  142.    end 
  143.   end
  144. end /* do */
  145.  
  146.  
  147. if abbrev(translate(request),'HTTP://')=0 then request='/'strip(request,'l','/')
  148.  
  149. family  ='AF_INET'
  150.  
  151. rc=1
  152. if verify(server,'1234567890.')>0 then 
  153.    rc=sockgethostbyname(server, "serv.0")  /* get dotaddress of server */
  154. else
  155.   serv.0addr=strip(server)
  156. if rc=0 then do; say 'ERROR: Unable to resolve "'server'"'; exit; end
  157. dotserver=serv.0addr                    /* .. */
  158. say 
  159. say cy_ye"Request sent to: "normal||"  "||reverse||dotserver||normal ;say " "
  160.  
  161. gosaddr.0family=family                  /* set up address */
  162. gosaddr.0port  =httpport
  163. gosaddr.0addr  =dotserver
  164.  
  165. tim1=time('r')
  166. setup1:
  167.  
  168. gosock = SockSocket(family, "SOCK_STREAM", "IPPROTO_TCP")
  169.  
  170.  
  171. gethead='GET'
  172. if as_head=1 then gethead='HEAD'
  173. httpis='HTTP/1.1'
  174. if as_http10=1 then httpis='HTTP/1.0'
  175. message=gethead' 'request' 'httpis||crlf'HOST:'server||crlf
  176.  
  177. message=message||'Referer:do_get@'||mehost||crlf
  178. if upwd<>' ' then
  179.   message=message||'Authorization: '||upwd||crlf
  180.  
  181. if opts<>"" then do
  182.    if right(opts,2)<>'0d0a'x then opts=opts||'0d0a'x
  183. end 
  184. message=message||opts
  185. if sendclose=1 then message=message||'Connection: close' crlf
  186.  
  187. if rsyncarg<>'' then do
  188.    oldverfile=rsyncarg ; enable_rsync=1
  189.    if pos('\',oldverfile)=0 then do
  190.            oldverfile=deltas_dir'\'||strip(oldverfile)
  191.    end /* do */
  192.    if stream(oldverfile,'c','query exists')='' then do
  193.       say " ... Problem: no such file (for rsync): "oldverfile
  194.       enable_rsync=0
  195.    end /* do */
  196.    else do
  197.       say " ... computing rsync synopsis for: "oldverfile
  198.    end
  199. end /* do */
  200. if enable_rsync=1  then do
  201.    aa=rsync_synopsis(oldverfile,rsync_blocks)
  202.    say " ... Rsync-signature request header is "||length(aa)||" bytes long"
  203.    message=message||'Rsync-signature: 'aa||crlf
  204. end /* do */
  205.  
  206. message=message||crlf
  207. say bold"Request message: "normal
  208. say message
  209.  
  210. rc = SockConnect(gosock,"gosaddr.0")
  211. if rc<0 then do; say 'ERROR: Unable to connect to "'server'"'; exit; end
  212. rc = SockSend(gosock, message)
  213. say bold' ...  request length = 'normal||rc " bytes "
  214. /* Now wait for the response */
  215. tim2=time('e')
  216. rs=0
  217. gots.=''
  218. gots.0=0
  219. runlen=0
  220. do forever
  221.   response=''
  222.   rc = SockRecv(gosock, "response", 1000)
  223.   if response<>'' then do
  224.      rs=rs+1
  225.      gots.rs=response   
  226.      gots.0=rs
  227.      runlen=runlen+length(response)
  228.   end 
  229.   if verbose=1 then say " ... :" runlen
  230.   if rs=1 then say " ... got first "rc " bytes of the response "
  231.   if rc<=0 then leave
  232. end 
  233.  
  234. rc = SockClose(gosock)
  235.  
  236. tim3=time('e')
  237. say  ' ... response complete. Got' runlen 'bytes.'
  238.  
  239. got=''
  240. do mm=1 to rs
  241.    got=got||gots.mm
  242. end 
  243. drop gots.
  244.  
  245. findit=crlf||crlf
  246. foo=pos(findit,got)
  247. t1=substr(got,1,foo)
  248.  
  249. /* look for 401 return code */
  250. parse var t1  line1 '0d0a'x t2
  251. parse var line1 . icode .
  252. if icode<>401  then signal writeit
  253.  
  254. goo1=yesno('  Unauthorized: retry with (new) password')
  255. if goo1<>1 then signal writeit
  256.  
  257. parse var upwd_hold gg username password
  258. upwd=make_auth(t2,username,password)
  259. if upwd<>0 then signal setup1
  260.  
  261. writeit:                        /* jump here to write stuff */
  262.  
  263. if out_literal>=2  then do
  264.    say
  265.    say cy_ye||"The response line, and response headers: "normal;say " "
  266.    say t1
  267.    if out_literal=2 then
  268.       t2=got
  269.    else
  270.       t2=message||got
  271.    signal outit
  272. end 
  273.  
  274. if out_literal=1 then do             /* save response verbatim */
  275.   t2=got
  276.   signal outit
  277. end
  278.  
  279. say
  280. say cy_ye"The response line, and response headers: "normal;say " "
  281. say t1
  282.  
  283. /* see if any transfer encodings to do */
  284. telist='';CELIST=''
  285. deltabase='';crange=''
  286. do until t1=""
  287.     parse var t1 aa '0d0a'x t1
  288.     parse  upper var aa a1a ':' a1b
  289.     if a1a='TRANSFER-ENCODING' then telist=telist' 'a1b
  290.     if a1a='CONTENT-ENCODING' then Celist=Celist' 'a1b
  291.     if a1a='DELTA-BASE' then deltabase=strip(strip(a1b),,'"')
  292.     if a1a='CONTENT-RANGE' then crange=strip(strip(a1b),,'"')
  293. end 
  294. t2=substr(got,foo+length(findit))
  295.  
  296. /* if found transfer encodings, see if you can do 'em 
  297. (you can always do chunk) */
  298. if telist<>'' & out_literal=0 then do
  299.    telist=translate(telist,' ',',')
  300.    do ww=words(telist) to 1 by -1    /* always do in reverse order of encoding */
  301.       atype=strip(word(telist,ww))
  302.       select
  303.          when abbrev(atype,'CHUNK')=1 then do
  304.            say " "
  305.            say " Chunked response -- "reverse"will unchunk "normal
  306.            t2=unchunk(t2)
  307.          end
  308.          when (atype='GZIP' | atype='COMPRESS') & do_gzip=1 then do
  309.             say " "
  310.             say " GZIP transfer-encoded response -- "reverse"will decompress "normal
  311.             t2=sref_ungzip(t2)
  312.          end /* do */
  313.          when (atype="DIFF-E" | atype="DIFFE") & allow_delta>0   then do
  314.             if  crange<>' ' then do
  315.                  say
  316.                  say "Range encountered, DIFF-e delta transfer decoding will "bold"not"normal" be attempted "
  317.                 iterate
  318.             end /* do */
  319.             ikk=wordpos(deltabase,etaglist)
  320.             if ikk=0 then
  321.                 useafile=deltas_dir'\'strip(deltabase)         /* the default */
  322.             else
  323.                 useafile=strip(word(efilelist,ikk))
  324.             say  " "
  325.             say " diff-e transfer-encoded response -- "reverse"will undiff"normal
  326.             t2=sref_undiff(useafile,t2) 
  327.          end
  328.          when (atype="GDIFF") & allow_delta>0   then do
  329.             if  crange<>' ' then do
  330.                  say
  331.                  say "Range encountered, GDIFF delta transfer decoding will "bold"not"normal" be attempted "
  332.                 iterate
  333.             end /* do */
  334.             ikk=wordpos(deltabase,etaglist)
  335.             if ikk=0 then
  336.                 useafile=deltas_dir'\'strip(deltabase)         /* the default */
  337.             else
  338.                 useafile=strip(word(efilelist,ikk))
  339.             say  " "
  340.             say " gdiff transfer-encoded response -- "reverse"will undiff"normal
  341.             t2=sref_ungdiff(useafile,t2) 
  342.          end
  343.  
  344.          otherwise nop             
  345.       end      /* select */
  346.    end          /* transfer encoding options */
  347. end             /* telist not empty */
  348.  
  349.  
  350. /* if found CONTENT encodings, see if you can do 'em  */
  351. if Celist<>'' & out_literal=0 then do
  352.    Celist=translate(Celist,' ',','||'0d0a0900'x)
  353.    do ww=words(Celist) to 1 by -1    /* always do in reverse order of encoding */
  354.       atype=strip(word(Celist,ww))
  355.       select
  356.          when (atype='GZIP' | atype='COMPRESS') & strip(do_gzip)=1 then do
  357.             say " "
  358.             say " GZIP content-encoding -- "reverse"will decompress "normal
  359.             t2=sref_ungzip(t2)
  360.          end /* do */
  361.          when (atype="DIFF-E" | atype="DIFFE") & allow_delta>0   then do
  362.             if  crange<>' ' then do
  363.                  say
  364.                  say "Range encountered, "bold"unDIFF"normal" of delta content encoding  will "bold"not"normal" be attempted "
  365.                 iterate
  366.             end /* do */
  367.             else do
  368.                ikk=wordpos(deltabase,etaglist)
  369.                if ikk=0 then
  370.                   useafile=deltas_dir'\'strip(deltabase)         /* the default */
  371.                else
  372.                   useafile=strip(word(efilelist,ikk))
  373.                say  " "
  374.                say " diff-e  content-encoding -- "reverse"will undiff"normal
  375.                t2=sref_undiff(useafile,t2) 
  376.             end
  377.          end
  378.          when atype='GDIFF'   & allow_delta>0 then do       /* gdiff */
  379.             ikk=wordpos(deltabase,etaglist)
  380.             if ikk=0 then
  381.                 useafile=deltas_dir'\'strip(deltabase)         /* the default */
  382.             else
  383.                 useafile=strip(word(efilelist,ikk))
  384.             if oldverfile<>'' then useafile=oldverfile
  385.             say  " "
  386.             say " gdiff content-encoded response -- "reverse"will undiff"normal
  387.             t2=sref_ungdiff(useafile,t2) 
  388.          end
  389.          otherwise nop             
  390.       end      /* select */
  391.    end          /* content encoding options */
  392. end             /* celist not empty */
  393.  
  394. outit:
  395. if outfile='' then do
  396.    say "Done (results NOT saved) "
  397.  
  398.    exit 0
  399. end 
  400.  
  401. tt=outfile
  402. foo=sysfiledelete(tt)
  403. eek=charout(tt,t2,1)
  404.  
  405. say " "
  406. d1=strip(tim2-tim1,'t',0) ; d2=strip(tim3-tim2,'t',0)
  407. amm=cy_ye"Elapsed time: "normal||bold||d1||normal "to establish connection. "bold||d2||normal " duration"
  408. say amm
  409.  
  410. if eek<>0 then do
  411.    say "Error: unable to write response to "outfile ": "eek
  412. end
  413. else do
  414.    if out_literal<>0 then
  415.         say "Entire response ("||length(t2)||" bytes in headers, body etc.) written to "bold||outfile||normal
  416.    else
  417.        say "A "||length(t2)||" byte response was written to "bold||outfile||normal
  418. end
  419.  
  420. d1=strip(tim2-tim1,,'0') ; d2=strip(tim3-tim2,,'0')
  421. if viewer<>'' & ( cmd_mode=0 | viewit=1) then do
  422.     aa=1
  423.     if viewit<>1 then do
  424.        aa=yesno(normal"  "bold"View the response (using "reverse||viewer||normal") ",,'N')
  425.     end
  426.    if aa=1 then do
  427.       if viewer_not_pm=1 then
  428.          arf='@START /f /c "'||strip(outfile)||' == DoGET request for '||strip(left(server' 'request,60))||'" 'viewer' 'outfile
  429.       else
  430.          arf='@START /f  "'||strip(outfile)||' == DoGET request for '||strip(left(server' 'request,60))||'" 'viewer' 'outfile
  431.        address cmd arf
  432.    end /* do */
  433. end
  434.  
  435.  
  436. exit 0
  437.  
  438. err1:
  439. say "Rexx error "rc " at line "sigl
  440. exit
  441.  
  442. abend:
  443. tim3=time('e')
  444. if gosock<>0 then do
  445.   say "Closing socket "gosock
  446.   rc=sockshutdown(gosock,2)
  447.   rc = SockClose(gosock)
  448.   dumpit=yesno('Write 'runlen' recieved bytes?')
  449.   if dumpit=1 then do
  450.      t2=''
  451.      do mm=1 to rs
  452.         t2=t2||gots.mm
  453.      end 
  454.      drop gots.
  455.      signal outit
  456.   end
  457.   exit
  458. end
  459.  
  460. /* --- Load the function library, if necessary --- */
  461. load:
  462.  
  463. if RxFuncQuery("SockLoadFuncs")=1 then do      /* already there */
  464.   call RxFuncAdd "SockLoadFuncs","rxSock","SockLoadFuncs"
  465.   call SockLoadFuncs
  466. end
  467.  
  468. /* Load up advanced REXX functions */
  469. foo=rxfuncquery('sysloadfuncs')
  470. if foo=1 then do
  471.   call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  472.   call SysLoadFuncs
  473. end
  474.  
  475. signal on error name err2 ; signal on syntax name err2
  476. enable_rsync2=1
  477. if rxfuncquery('rx_md4')=1  then do
  478.     aa=RXFuncAdd( 'RXRsyncLoad', 'RXRSYNC', 'RxRsyncLoad')
  479.     if aa=0 then call RxRsyncLoad
  480.     if rxfuncquery('rx_md4')=1  then  enable_rsync2=0
  481. end
  482. signal on syntax name err1 ; signal on error name err1 
  483. return
  484. err2:
  485. enable_rsync2=0
  486. return 
  487.  
  488. /* get the hostname (aa.bb.cc) for this machine
  489.    Developed by Timur Kazimirov  */
  490.  
  491. get_hostname:procedure
  492. if \RxFuncQuery("SockLoadFuncs")
  493.   then
  494.     nop
  495.   else
  496.     do
  497.       call RxFuncAdd "SockLoadFuncs","rxSock","SockLoadFuncs"
  498.       call SockLoadFuncs
  499.     end
  500. dot_addr = SockGetHostId()
  501. rc = SockGetHostByAddr(dot_addr, "host.")
  502. return host.name
  503.  
  504. /****************/
  505. /* figure out batch mode */
  506. do_batch:
  507.  
  508. dopause=0
  509. afil=strip(server)
  510. iss=stream(afil,'c','query size')
  511. if iss=0 | iss='' then do
  512.    say 'Sorry, could not find 'afil
  513.    exit
  514. end 
  515. goo=charin(afil,1,iss); foo=stream(afil,'c','close')
  516.  
  517. /* concatenate , lines, etc. */
  518. goo2=''
  519. do until goo=''
  520.    parse var goo aline '0d0a'x goo ; aline=strip(aline)
  521.    if aline='' then iterate
  522.    if  abbrev(aline,';')=1 then  iterate
  523.    if abbrev(aline,',')=1 then
  524.       goo2=goo2||subsrt(aline,2)
  525.    else
  526.       goo2=goo2||'0d0a'x||aline
  527. end
  528. do until goo2=''
  529.    parse var goo2 aline '0d0a'x goo2 ; aline=strip(aline)
  530.    if aline='' then iterate
  531.    if abbrev(aline,',')=1 then iterate
  532.  
  533.    parse var aline atype ':' avalue ; atype=translate(strip(atype))
  534.    atype=strip(translate(atype))
  535.    select
  536.       when atype='REQUEST' then  request=space(avalue,0)
  537.       when atype='SERVER' then server=space(avalue,0)
  538.       when atype='MODE' then out_literal=space(avalue,0)
  539.       when atype='VIEW' then viewit=space(avalue,0)
  540.       when atype='PAUSE' then dopause=space(avalue,0)
  541.       when atype='RSYNCFILE' then rsyncarg=space(avalue,0)
  542.       when atype='HEADER' then do
  543.         if opts<>'' then
  544.           opts=opts||strip(avalue)||'0d0a'x
  545.         else
  546.            opts=strip(avalue)||'0d0a'x
  547.       end /* do */
  548.       when atype='OUTFILE' then outfile=space(avalue,0)
  549.       when atype='DO_GZIP' then do_gzip=space(avalue,0)
  550.       when atype='SENDCLOSE' then sendclose=space(avalue,0)
  551.       when atype='USERNAME' then username=space(avalue,0)
  552.       when atype='PASSWORD' then password=space(avalue,0)
  553.       otherwise nop
  554.    end
  555.  end /* do */
  556.  
  557. if username<>'' then do
  558.   upwd=username':'password
  559.   if upwd<>' ' then do
  560.     upwd=space(strip(upwd))
  561.     upwd=mk_base64(translate(upwd,':',' '))
  562.     upwd='Basic 'upwd
  563.   end
  564. end
  565.  
  566. if dopause=1 then do
  567. say cy_ye"Your request: "normal
  568.    say "Server: " server
  569.    say "Request selector: " request
  570.    if upwd<>'' then say 'Authorization: 'upwd
  571.    say reverse"Custom headers:"normal
  572.    ao=opts
  573.    do until ao=''
  574.       parse var opts ali '0d0a'x ao
  575.       say "    "ali
  576.   end
  577. end 
  578. say
  579. call charout,"hit any key to continue .... "
  580. foo=sysgetkey('noecho')
  581. say 
  582. batchmode=1
  583. return 1
  584.  
  585.  
  586.  
  587.  
  588. return 1
  589.  
  590. /****************/
  591. show_intro:
  592. say clear_screen
  593. say cy_ye"DOGET"normal" will issue a GET method request to an HTTP server, and will:"
  594. say "  "bold"*"normal" display the response header "
  595. say "  "bold"*"normal" save the  response to: "outfile
  596. say bold"Features include:"
  597. say "  "bold"*"normal" You can include authorization info (username and password) --"
  598. say "    "bold"basic"normal" and "bold"digest"normal" authentication are supported"
  599. say "  "bold"*"normal" The ability to include custom request headers "
  600. say "  "bold"*"normal" http/1.1 capabilities include unchunking, GZIP decompression, and"
  601. say "    delta-encoding undifferencing"
  602. say bold"Usage:"normal
  603.  
  604. say " Command line mode: "bold"DOGET"normal" "reverse"server"normal" "reverse" request"normal" ["normal" "reverse"output_mode "normal" "reverse"viewit "normal" "reverse"rsync_base"normal" ]"
  605. say "   "cy_ye"Notes:"normal" * The contents of DOGET.HDR are used as extra request headers"
  606. say "          * The "reverse"output_mode"normal", "reverse"viewit"normal", and "reverse"rsync_base"normal" parameters are optional."
  607. say "          * "reverse"output_mode"normal" overrides the default (set in DOGET.CMD)"
  608. say "          * "reverse"viewit"normal", if 1, display results w/ viewer program (set in DOGET.CMD) "
  609. say "          * "reverse"rsync_base"normal" is a filename used to create an rsync-signature header "
  610. say "          * Example: "bold"D:>doget  www.foobar.net   /sports/index.html"normal
  611. say " Batch mode:  "bold"DOGET"normal" "reverse"filename.ext"normal
  612. say '          * FILENAME.EXT should be the name of a 'bold'DOGET'normal' batch file.'
  613. say '          * DOGET batch files contain server:, request:, and header: entries'
  614. say " Interactive mode: just enter "bold"DOGET"normal" at an OS/2 prompt, and answer away..."
  615. say
  616.  
  617.  
  618. do forever
  619.   say 
  620.   vuparams=yesno("More info",'No Parameters BatchInfo','N')
  621.   if vuparams=0 then exit
  622.   if vuparams=1 then call do_vuparams
  623.   if vuparams=2 then call do_batchdoc
  624. end
  625.  
  626. exit
  627.  
  628. /**************************/
  629. do_batchdoc:
  630.  
  631. say
  632. say "The "bold"DOGET"normal" BATCH mode files can contain the following entries:"
  633. say bold"   Request: "normal' the request "selector". '
  634. say bold'    Server: 'normal' IP name/number of the server. www.mysite.org'
  635. say bold'      Mode: 'normal' What to write (0=response content, 1=response headers & content,'
  636. say     '                       2=request, response headers & content'
  637. say bold"      View: "normal' If View: 1, then display response (using 'reverse||viewer||normal
  638. say bold"    Header: "normal' A header to add. You can have as many Header:  entries as needed.'
  639. say     '             Example: 'bold' Header: X-relevance: few 'normal
  640. say bold" RsyncFile: "normal' A file to use to construct an rsync-synopsis'
  641. /*say bold"     Delta: "normal' A file to use to construct delta encoding' */
  642. say bold"   Outfile: "normal' Name of the output file'
  643. say bold"   Do_GZIP: "normal' If 1,then attempt to unGZIP (if GZIP content/transfer encoding'
  644. say bold" SendClose: "normal' If 1, then immediately close the connection'
  645. say bold"  UserName: "normal' Your username '
  646. say bold"  PassWord: "normal' Your password '
  647. say bold"     Pause: "normal' Pause before connecting to the server '
  648.  
  649.       call charout,reverse||"hit any key to continue"||normal
  650.       getmore=sysgetkey('echo');say 
  651.  
  652. say
  653. say bold"Notes:"normal
  654. say bold"  * "normal"Entries have the format:"bold" name: value "normal
  655. say bold"  * "normal"One entry per line "
  656. say bold"  * "normal"A ! as a first character means this is a continuation line."
  657. say bold"  * "normal'For several parameters, such as Do_Gzip, default entries can be'
  658. say '    set in the user-configurable parameters section of DOGET.CMD'
  659.  
  660. say
  661. say bold" Example: "normal
  662. say '         request: samples/dir.doc'
  663. say '         server: www.mysite.org'
  664. say '         header: x-wow: abc'
  665. say '         Username: joey'
  666. say '         header: x-home: Maryland'
  667. say '         password: skeezik'
  668. say '         outfile: d:\results\ver1.lst'
  669. say '         pause: 1'
  670.  
  671.       call charout,reverse||"hit any key to continue"||normal
  672.       getmore=sysgetkey('echo');say 
  673. return 0
  674.  
  675. /**************************/
  676. do_vuparams:
  677.  
  678. foo=stream(somewhere,'c','open read')
  679. if abbrev(strip(translate(foo)),'READY')=0 then do
  680.    say "Sorry, can not read "somewhere
  681.    exit
  682. end 
  683. jsz=stream(somewhere,'c','query size')
  684. if jsz=0 | jsz='' then do
  685.    say "Sorry, can not read "somewhere
  686.    exit
  687. end 
  688. aa=charin(somewhere,1,jsz)
  689. foo=stream(somewhere,'c','close')
  690. parse var  aa . '/*BEGINUSER*/' stuff '/*ENDUSER*/' .
  691.  
  692. ii=0
  693. commenton=0
  694. do until stuff=''
  695.    c2=0
  696.    parse var stuff aline '0d0a'x stuff
  697.    if pos('/*',aline)>0 then do
  698.         parse var aline . '/*' aline ; aline='* 'aline
  699.         commenton=1
  700.    end 
  701.    if pos('*/',aline)>0 then do
  702.         parse var aline aline '*/' .
  703.         c2=1
  704.    end 
  705.    if commenton=0 then
  706.       say bold||aline||normal
  707.    else
  708.      say aline
  709.    ii=ii+1
  710.    if ii=20 then do
  711.       aa=yesno("continue ....",,'Y')
  712.       if aa=0 then return 1
  713.       ii=0
  714.    end 
  715.    if c2=1 then commenton=0
  716. end 
  717. return 1
  718.  
  719. /**************/
  720. /* ask user for a variety of other fields */
  721. do_getmore:
  722. parse arg getmore 
  723.  say 
  724.   say " Enter a (space seperated) USERNAME PASSWORD (ENTER=None, DIGEST xx xx):"
  725.    call charout,"    "cy_ye":"normal" "
  726.  
  727.   parse pull upwd
  728.   if abbrev(strip(translate(upwd)),'DIGEST')=1  then do
  729.       upwd_hold=upwd ; upwd=''
  730.   end /* do */
  731.   if upwd<>' ' then do
  732.     upwd=space(strip(upwd))
  733.     upwd=mk_base64(translate(upwd,':',' '))
  734.     upwd='Basic 'upwd
  735.   end
  736.  
  737.   say
  738.   say " Enter optional request headers (?=examples, ENTER=no more)"
  739.   aopt=0
  740.   do until aopt=""
  741.       call charout,"    "cy_ye":"normal" "
  742.  
  743.       parse pull aopt
  744.       aopt=strip(aopt)
  745.       if aopt="" then leave
  746.       if aopt="?" then do
  747.               say " "bold"Examples:"normal
  748.               say "    Connection:keep-alive"
  749.               say "    Range:bytes=0-50,200-400"
  750.               say " "
  751.               say " "bold"or"normal", to load in a file containing request headers: "
  752.               say "     FILE=filename.ext "
  753.               say
  754.               iterate
  755.       end  /* Do */
  756.       if abbrev(translate(aopt),'FILE=')=1 then do
  757.            parse var aopt . '=' afil
  758.            goo=charin(afil,1,chars(afil)); foo=stream(afil,'c','close')
  759.            opts=opts||goo
  760.       end /* do */
  761.       else do
  762.         opts=opts||aopt||crlf
  763.       end
  764.   end /* do */
  765.  
  766. if getmore<>2 then return 1
  767.  
  768.   sendclose=yesno(' Send a "Connection: Close" header ',,'Y')
  769.  
  770.   as_head=yesno(' Issue HEAD request (instead of GET) ',,'N')
  771.  
  772.  
  773.   say "Output file (ENTER="reverse||outfile||normal"):"
  774.   call charout,"    "cy_ye":"normal" "
  775.  
  776.   parse pull outfile1
  777.   if outfile1<>"" then outfile=outfile1
  778.  
  779.  
  780.  
  781.   out_literal=yesno('Write to output file','Response Hdr&Response Everything','R')
  782.   select 
  783.      when out_literal=1 then out_literal=2
  784.      when out_literal=2 then out_literal=3
  785.      otherwise nop
  786.  end
  787.  
  788.   if out_literal=0 then do
  789.      do_gzip=yesno('unGZIP, when GZIP is a Transfer or Content Encoding',,'Y') 
  790.    end
  791.  
  792.  
  793.   if allow_delta>0 then do
  794.     say ""
  795.     allow_delta=yesno(normal||"  "||bold||"Send delta-encoding info"normal,,'N')
  796.   end
  797.  
  798.   if allow_delta>0 then do              /* ask for etag file */
  799.      say "   "bold"?"normal" for examples, "bold"ENTER"normal" when done, "bold"?DIR"normal" for a directory:"
  800.      do forever
  801.        call charout,"    "cy_ye":"normal" "
  802.  
  803.        parse pull infile ; infile=strip(infile)
  804.        if infile='' then leave
  805.  
  806.        if infile="?" then do
  807.                say
  808.               say "Enter the etag, and (optionally) a cache-filename, of a "bold"cached"normal" response"
  809.               say "  "bold"Examples: "normal
  810.               say "    67_136FD_F99.2  "
  811.               say "    oba36  e:\temps\cas33.32a "
  812.               say
  813.               say "  "bold"Notes:"normal||reverse"*"normal" if no file is entered, a file (in the "bold"default cache directory"normal")"
  814.               say "          with the same name will be used (if it exists) "
  815.               call charout, "        "reverse"*"normal" the "bold"default cache directory"normal" is: "
  816.               if length(deltas_dir)>40 then do
  817.                       say; say deltas_dir
  818.               end /* do */
  819.               else do
  820.                  say deltas_dir
  821.               end /* do */
  822.               say "     "
  823.               say " "
  824.               iterate
  825.        end  /* Do */
  826.           
  827.       if abbrev(translate(infile),'?DIR')=1 then do
  828.            call get_dir
  829.            iterate
  830.       end
  831.       parse var infile anetag anfile 
  832.       if anfile='' then anfile=anetag
  833.       if pos('\',anfile)=0 then do
  834.            anfile=deltas_dir'\'||strip(anfile)
  835.       end /* do */
  836.       dogr=stream(anfile,'c','query exists')
  837.       if dogr='' then do
  838.             say "  "bold"Error"normal": no such delta file:"anfile','
  839.             iterate
  840.       end /* do */
  841.       ietags=ietags+1
  842.       etaglist=etaglist' 'anetag
  843.       efilelist=efilelist' 'dogr
  844.    end          /*keep getting files */
  845.    say "# of "bold"etag / file "normal" entries is "ietags
  846.  
  847.    if ietags>0 then do 
  848.        opts=opts||'If-none-match:"'||strip(word(etaglist,1))||'"'
  849.        do mm=2 to ietags
  850.           opts=opts||',"'||strip(word(etaglist,mm))||'"'
  851.        end /* do */
  852.        opts=opts||crlf||'TE: diff-e'||crlf
  853.    end
  854.  
  855.  end                    /* allow delta */
  856.  
  857.  
  858.  
  859.   if enable_rsync2=1 then do
  860.     enable_rsync=yesno('Include an Rsync-signature header',,'N')
  861.     if enable_rsync=1 then do
  862.        do forever
  863.          say '    Enter name of "old version" file (?DIR =display directory, .=Quit):'
  864.          call charout,bold '     ? 'normal ; pull oldverfile
  865.          if oldverfile='.' then do
  866.                 enable_rsync=0; leave
  867.          end /* do */
  868.          if oldverfile='?DIR' then do
  869.              call get_dir
  870.              iterate
  871.          end
  872.          if pos('\',oldverfile)=0 then do
  873.              oldverfile=deltas_dir'\'||strip(oldverfile)
  874.          end /* do */
  875.          
  876.          if  stream(oldverfile,'c','query exists')='' then iterate
  877.          leave
  878.        end
  879.     end
  880.   end  
  881.  
  882. return 1
  883.  
  884.  
  885. /************/
  886. get_dir:
  887.  
  888.        parse var infile . thisdir
  889.  
  890.       if thisdir="" then do
  891.            if deltas_dir='' & deltas_dir<>0 then do
  892.                thisdir=strip(directory(),'t','\')||'\*.*'
  893.            end
  894.            else do
  895.                thisdir=deltas_dir||'\*.*'
  896.            end /* do */
  897.        end
  898.        say
  899.        say reverse ' List of files in: ' normal bold thisdir normal
  900.        do while queued()>0
  901.             pull .
  902.        end /* do */
  903.        toget=thisdir
  904.  
  905.        '@DIR /b  '||toget||' | rxqueue'
  906.        foo=show_dir_queue('*')
  907.        say
  908.        infile=''
  909. return 1
  910.  
  911. /************/
  912. /* make an authorization header */
  913. make_auth:
  914.  
  915. ifoo=0
  916. parse arg r2,USERNAME0,PASSWORD0
  917. /* basic or digest? */
  918. do until r2=''
  919.    parse var r2 a1 '0d0a'x r2 ; a1=strip(a1)
  920.    parse var a1 atype ':' aheader ;atype=strip(atype)
  921.    if translate(atype)<>'WWW-AUTHENTICATE' then iterate
  922.    ifoo=1
  923.    leave
  924. end
  925.  
  926. if ifoo=0 then return 0
  927.  
  928. /*else-- parse r2 and create digest style request header */
  929.     call charout,'  'bold'Username'normal' (enter='username0'):'
  930.     parse pull username
  931.     if username='' then username=username0
  932.     
  933.     call charout,' 'bold'Password'normal' (enter='password0'):'
  934.     parse pull passwd
  935.     if passwd='' then passwd=password0
  936.  
  937.     parse var aheader atype aheader
  938.     atype=strip(translate(atype))
  939.     if atype='BASIC' then do
  940.        upwd=mk_base64(strip(username)':'strip(passwd))
  941.        upwd='Basic 'upwd
  942.        return upwd
  943.     end /* do */
  944.  
  945.     call charout," Qop response (1=yes): "
  946.      parse pull iqop
  947.     upwd=digest_mkupwd(request,username,passwd,aheader,iqop)
  948. say " Upwd after dig " upwd
  949.     if upwd=0 then return 0
  950.     return upwd   
  951.  
  952.  
  953. /************/
  954. /* create a base64 packing of a message */
  955. mk_base64:procedure
  956.  
  957. do mm=0 to 25           /* set base 64 encoding keys */
  958.    a.mm=d2c(65+mm)
  959. end /* do */
  960. do mm=26 to 51
  961.    a.mm=d2c(97+mm-26)
  962. end /* do */
  963. do mm=52 to 61
  964.    a.mm=d2c(48+mm-52)
  965. end /* do */
  966. a.62='+'
  967. a.63='/'
  968.  
  969. parse arg mess
  970. s2=x2b(c2x(mess))
  971. ith=0
  972. do forever
  973.    ith=ith+1
  974.    a1=substr(s2,1,6,0)
  975.    ms.ith=x2d(b2x(a1))
  976.    if length(s2)<7 then leave
  977.    s2=substr(s2,7)
  978. end /* do */
  979. pint=""
  980. do kk=1 to ith
  981.     oi=ms.kk ; pint=pint||a.oi
  982. end /* do */
  983. j1=length(pint)//4
  984. if j1<>0 then pint=pint||copies('=',4-j1)
  985. return pint
  986.  
  987.  
  988.  
  989. /********************************************/
  990. /*Given client digest auth, form local copy of "response";
  991.  and compare to her "response" */
  992.  
  993. digest_mkupwd:procedure
  994. parse arg auri,username,passwd,aheader,iqop
  995.  
  996.  
  997. realm='' ; nonce=''; ;qop='';opaque=''
  998. do until aheader=''
  999.    parse var aheader a1 ',' aheader
  1000.    parse var a1 a1a '=' a1b 
  1001.    a1bb=strip(strip(a1b),,'"') ; a1a=strip(upper(a1a))
  1002.    select 
  1003.       when  a1a='REALM' then realm=a1bb
  1004.       when a1a='NONCE' then nonce=a1bb
  1005.       when a1a='QOP' & iqop=1 then qop=a1bb
  1006.       when a1a='OPAQUE' then opaque=a1bb
  1007.       otherwise nop
  1008.    end
  1009. end /* do */
  1010.  
  1011. /* if username, response, uri, nonce, realm ='', then failure */
  1012. if username='' | nonce='' | realm='' then do
  1013.     say 'Insufficient information; can not create digest style Autorization request '
  1014.     return 0
  1015. end /* do */
  1016.  
  1017. if abbrev(translate(auri),'HTTP://')=0 then auri='/'strip(auri,'l','/')
  1018.  
  1019. username=strip(username); passwd=strip(passwd)
  1020.  
  1021. qop=strip(qop)
  1022. if pos('AUTH',translate(qop))>0 then do
  1023.   cnonce='testhere'
  1024.   nc=1
  1025.   qop='auth'
  1026. end /* do */
  1027. else do
  1028.   cnonce=''; nc='';qop=''
  1029. end
  1030.  
  1031. VERB='GET'
  1032.  
  1033. /* 1) form h(a1) */
  1034.   a1=username':'realm':'passwd
  1035.   ha1=lower(sref_md5x(a1))
  1036.  
  1037. /* form h(a2) */
  1038.   a2='GET:'auri
  1039.   ha2=lower(sref_md5x(a2))
  1040.  
  1041. /* if no qop */
  1042. if translate(qop)<>'AUTH' then do 
  1043.     resp1=ha1':'nonce':'ha2
  1044.     hresp=sref_md5x(resp1)
  1045. end /* do */
  1046. else do         /* AUTH */
  1047.     resp1=ha1':'nonce':'nc':'cnonce':'qop':'ha2
  1048.     hresp=sref_md5x(resp1)
  1049. end /* do */
  1050.  
  1051. rar='Digest username="'username'", realm="'realm'"'
  1052. rar=rar', uri="'auri'", nonce="'nonce'"'
  1053. if translate(qop)='AUTH' then do
  1054.    rar=rar', qop='qop', cnonce="'cnonce'", nc='nc
  1055. end /* do */
  1056. rar=rar', response="'hresp'"'
  1057.  
  1058. if opaque<>'' then rar=rar', opaque="'opaque'"'
  1059.  
  1060.  
  1061. return rar
  1062.  
  1063. /*
  1064. Authorization: Digest username="Mufasa", realm="testrealm@hopf.math.nwu.edu", ur
  1065. i="/testpage/digest/index.html", nonce="86a88f9b4d927b79d9a21c53f0757a3abd", res
  1066. ponse="d35edc9327c6149f0c3a6c5a46e84ed8"
  1067. Connection: close
  1068. */
  1069.  
  1070.  
  1071.  
  1072. /***********/
  1073. /* A fully rexx md5 digest computation procedure.
  1074.   This is NOT FAST  --  for small strings it is
  1075.   toleable (0.15 seconds on a p166 for 50 character strings),
  1076.   but for larger strings (or files) it can take many seconds --
  1077.   you should instead use a DLL product (such as MD5_OS2) */
  1078.  
  1079.  
  1080. /*  ------------------------------ */
  1081. sref_md5x:procedure
  1082. parse arg stuff
  1083.  
  1084. numeric digits 11
  1085. lenstuff=length(stuff)
  1086.  
  1087. c0=d2c(0)
  1088. c1=d2c(128)
  1089. c1a=d2c(255)
  1090. c1111=c1a||c1a||c1a||c1a
  1091. slen=length(stuff)*8
  1092. slen512=slen//512
  1093.  
  1094. /* pad message to multiple of 512 bits.  Last 2 words are 64 bit # bits in message*/
  1095. if slen512=448 then  addme=512
  1096. if slen512<448 then addme=448-slen512
  1097. if slen512>448 then addme=960-slen512
  1098. addwords=addme/8
  1099.  
  1100. apad=c1||copies(c0,addwords-1)
  1101.  
  1102. xlen=reverse(right(d2c(lenstuff*8),4,c0))||c0||c0||c0||c0  /* 2**32 max bytes in message */
  1103.  
  1104. /* NEWSTUFF is the message to be md5'ed */
  1105. newstuff=stuff||apad||xlen
  1106.  
  1107. /* starting values of registers */
  1108.  a ='67452301'x;
  1109.  b ='efcdab89'x;
  1110.  c ='98badcfe'x;
  1111.  d ='10325476'x;
  1112.  
  1113. lennews=length(newstuff)/4
  1114.  
  1115. /* loop through entire message */
  1116. do i1 = 0 to ((lennews/16)-1)
  1117.   i16=i1*64
  1118.   do j=1 to 16
  1119.      j4=((j-1)*4)+1
  1120.      jj=i16+j4
  1121.      m.j=reverse(substr(newstuff,jj,4))
  1122.   end /* do */
  1123.  
  1124. /* transform this block of 16 chars to 4 values. Save prior values first */
  1125.  aa=a;bb=b;cc=c;dd=d
  1126.  
  1127. /* do 4 rounds, 16 operations per round (rounds differ in bit'ing functions */
  1128. S11=7
  1129. S12=12
  1130. S13=17
  1131. S14=22
  1132.   a=round1( a, b, c, d,   0 , S11, 3614090360); /* 1 */
  1133.   d=round1( d, a, b, c,   1 , S12, 3905402710); /* 2 */
  1134.   c=round1( c, d, a, b,   2 , S13,  606105819); /* 3 */
  1135.   b=round1( b, c, d, a,   3 , S14, 3250441966); /* 4 */
  1136.   a=round1( a, b, c, d,   4 , S11, 4118548399); /* 5 */
  1137.   d=round1( d, a, b, c,   5 , S12, 1200080426); /* 6 */
  1138.   c=round1( c, d, a, b,   6 , S13, 2821735955); /* 7 */
  1139.   b=round1( b, c, d, a,   7 , S14, 4249261313); /* 8 */
  1140.   a=round1( a, b, c, d,   8 , S11, 1770035416); /* 9 */
  1141.   d=round1( d, a, b, c,   9 , S12, 2336552879); /* 10 */
  1142.   c=round1( c, d, a, b,  10 , S13, 4294925233); /* 11 */
  1143.   b=round1( b, c, d, a,  11 , S14, 2304563134); /* 12 */
  1144.   a=round1( a, b, c, d,  12 , S11, 1804603682); /* 13 */
  1145.   d=round1( d, a, b, c,  13 , S12, 4254626195); /* 14 */
  1146.   c=round1( c, d, a, b,  14 , S13, 2792965006); /* 15 */
  1147.   b=round1( b, c, d, a,  15 , S14, 1236535329); /* 16 */
  1148.  
  1149.   /* Round 2 */
  1150. S21=5
  1151. S22=9
  1152. S23=14
  1153. S24=20
  1154. a= round2( a, b, c, d,   1 , S21, 4129170786); /* 17 */
  1155. d= round2( d, a, b, c,   6 , S22, 3225465664); /* 18 */
  1156. c=  round2( c, d, a, b,  11 , S23,  643717713); /* 19 */
  1157. b=  round2( b, c, d, a,   0 , S24, 3921069994); /* 20 */
  1158. a=  round2( a, b, c, d,   5 , S21, 3593408605); /* 21 */
  1159. d=  round2( d, a, b, c,  10 , S22,   38016083); /* 22 */
  1160. c=  round2( c, d, a, b,  15 , S23, 3634488961); /* 23 */
  1161. b= round2( b, c, d, a,   4 , S24, 3889429448); /* 24 */
  1162. a= round2( a, b, c, d,   9 , S21,  568446438); /* 25 */
  1163. d= round2( d, a, b, c,  14 , S22, 3275163606); /* 26 */
  1164. c=  round2( c, d, a, b,   3 , S23, 4107603335); /* 27 */
  1165. b=  round2( b, c, d, a,   8 , S24, 1163531501); /* 28 */
  1166. a=  round2( a, b, c, d,  13 , S21, 2850285829); /* 29 */
  1167. d=  round2( d, a, b, c,   2 , S22, 4243563512); /* 30 */
  1168. c=  round2( c, d, a, b,   7 , S23, 1735328473); /* 31 */
  1169. b= round2( b, c, d, a,  12 , S24, 2368359562); /* 32 */
  1170.  
  1171.   /* Round 3 */
  1172. S31= 4
  1173. S32= 11
  1174. S33= 16
  1175. S34= 23
  1176. a= round3( a, b, c, d,   5 , S31, 4294588738); /* 33 */
  1177. d=  round3( d, a, b, c,   8 , S32, 2272392833); /* 34 */
  1178. c=  round3( c, d, a, b,  11 , S33, 1839030562); /* 35 */
  1179. b=  round3( b, c, d, a,  14 , S34, 4259657740); /* 36 */
  1180. a=  round3( a, b, c, d,   1 , S31, 2763975236); /* 37 */
  1181. d=  round3( d, a, b, c,   4 , S32, 1272893353); /* 38 */
  1182. c=  round3( c, d, a, b,   7 , S33, 4139469664); /* 39 */
  1183. b=  round3( b, c, d, a,  10 , S34, 3200236656); /* 40 */
  1184. a=  round3( a, b, c, d,  13 , S31,  681279174); /* 41 */
  1185. d=  round3( d, a, b, c,   0 , S32, 3936430074); /* 42 */
  1186. c=  round3( c, d, a, b,   3 , S33, 3572445317); /* 43 */
  1187. b=  round3( b, c, d, a,   6 , S34,   76029189); /* 44 */
  1188. a=  round3( a, b, c, d,   9 , S31, 3654602809); /* 45 */
  1189. d=  round3( d, a, b, c,  12 , S32, 3873151461); /* 46 */
  1190. c=  round3( c, d, a, b,  15 , S33,  530742520); /* 47 */
  1191. b=  round3( b, c, d, a,   2 , S34, 3299628645); /* 48 */
  1192.  
  1193.   /* Round 4 */
  1194. S41=6
  1195. S42=10
  1196. S43=15
  1197. s44=21
  1198. a=round4( a, b, c, d,   0 , S41, 4096336452); /* 49 */
  1199. d=round4( d, a, b, c,   7 , S42, 1126891415); /* 50 */
  1200. c=round4( c, d, a, b,  14 , S43, 2878612391); /* 51 */
  1201. b=round4( b, c, d, a,   5 , s44, 4237533241); /* 52 */
  1202. a=round4( a, b, c, d,  12 , S41, 1700485571); /* 53 */
  1203. d=round4( d, a, b, c,   3 , S42, 2399980690); /* 54 */
  1204. c=round4( c, d, a, b,  10 , S43, 4293915773); /* 55 */
  1205. b=round4( b, c, d, a,   1 , s44,  2240044497); /* 56 */
  1206. a=round4( a, b, c, d,   8 , S41, 1873313359); /* 57 */
  1207. d=round4( d, a, b, c,  15 , S42, 4264355552); /* 58 */
  1208. c=round4( c, d, a, b,   6 , S43, 2734768916); /* 59 */
  1209. b=round4( b, c, d, a,  13 , s44, 1309151649); /* 60 */
  1210. a=round4( a, b, c, d,   4 , S41, 4149444226); /* 61 */
  1211. d=round4( d, a, b, c,  11 , S42, 3174756917); /* 62 */
  1212. c=round4( c, d, a, b,   2 , S43,  718787259); /* 63 */
  1213. b=round4( b, c, d, a,   9 , s44, 3951481745); /* 64 */
  1214.  
  1215.  
  1216. a=m32add(aa,a) ; b=m32add(bb,b) ; c=m32add(cc,c) ; d=m32add(dd,d)
  1217.  
  1218. end
  1219.  
  1220. aa=c2x(reverse(a))||c2x(reverse(b))||c2x(reverse(C))||c2x(reverse(D))
  1221.  
  1222. return lower(aa)
  1223.  
  1224.  
  1225. /* round 1 to 4 functins */
  1226.  
  1227. round1:procedure expose m. c1111 c0 c1
  1228. parse arg a1,b1,c1,d1,kth,shift,sini
  1229. kth=kth+1
  1230. t1=c2d(a1)+c2d(f(b1,c1,d1))+ c2d(m.kth) + sini
  1231. t1a=right(d2c(t1),4,c0)
  1232. t2=rotleft(t1a,shift)
  1233. t3=m32add(t2,b1)
  1234. return t3
  1235.  
  1236. round2:procedure expose m. c1111 c0 c1
  1237. parse arg a1,b1,c1,d1,kth,shift,sini
  1238. kth=kth+1
  1239. t1=c2d(a1)+c2d(g(b1,c1,d1))+ c2d(m.kth) + sini
  1240. t1a=right(d2c(t1),4,c0)
  1241. t2=rotleft(t1a,shift)
  1242. t3=m32add(t2,b1)
  1243. return t3
  1244.  
  1245. round3:procedure expose m. c1111 c0 c1
  1246. parse arg a1,b1,c1,d1,kth,shift,sini
  1247. kth=kth+1
  1248. t1=c2d(a1)+c2d(h(b1,c1,d1))+ c2d(m.kth) + sini
  1249. t1a=right(d2c(t1),4,c0)
  1250. t2=rotleft(t1a,shift)
  1251. t3=m32add(t2,b1)
  1252. return t3
  1253.  
  1254. round4:procedure expose m. c1111 c0 c1
  1255. parse arg a1,b1,c1,d1,kth,shift,sini
  1256. kth=kth+1
  1257. t1=c2d(a1)+c2d(i(b1,c1,d1))+ c2d(m.kth) + sini
  1258. t1a=right(d2c(t1),4,c0)
  1259. t2=rotleft(t1a,shift)
  1260. t3=m32add(t2,b1)
  1261. return t3
  1262.  
  1263. /* add to "char" numbers, modulo 2**32, return as char */
  1264. m32add:procedure expose c0 c1 c1111
  1265. parse arg v1,v2
  1266. t1=c2d(v1)+c2d(v2)
  1267. t2=d2c(t1)
  1268. t3=right(t2,4,c0)
  1269. return t3
  1270.  
  1271. /*********** Basic functions */
  1272. /* F(x, y, z) == (((x) & (y)) | ((~x) & (z))) */
  1273. f:procedure expose c0 c1 c1111 
  1274. parse arg x,y,z
  1275. t1=bitand(x,y)
  1276. notx=bitxor(x,c1111)
  1277. t2=bitand(notx,z)
  1278. return bitor(t1,t2)
  1279.  
  1280.  
  1281. /* G(x, y, z) == (((x) & (z)) | ((y) & (~z)))*/
  1282. g:procedure expose c0 c1 c1111
  1283. parse arg x,y,z
  1284. t1=bitand(x,z)
  1285. notz=bitxor(z,c1111)
  1286. t2=bitand(y,notz)
  1287. return bitor(t1,t2)
  1288.  
  1289. /* H(x, y, z) == ((x) ^ (y) ^ (z)) */
  1290. h:procedure expose c0 c1 c1111
  1291. parse arg x,y,z
  1292. t1=bitxor(x,y)
  1293. return bitxor(t1,z)
  1294.  
  1295. /* I(x, y, z) == ((y) ^ ((x) | (~z))) */
  1296. i:procedure expose c0 c1 c1111
  1297. parse arg x,y,z
  1298. notz=bitxor(z,c1111)
  1299. t2=bitor(x,notz)
  1300. return bitxor(y,t2)
  1301.  
  1302. /* bit rotate to the left by s positions */
  1303. rotleft:procedure 
  1304. parse arg achar,s
  1305. if s=0 then return achar
  1306.  
  1307. bits=x2b(c2x(achar))
  1308. lb=length(bits)
  1309. t1=left(bits,s)
  1310. t2=bits||t1
  1311. yib=right(t2,lb)
  1312. return x2c(b2x(yib))
  1313.  
  1314.  /* function: Check if ANSI is activated                               */
  1315.  /*                                                                    */
  1316.  /* returns:  1 - ANSI support detected                                */
  1317.  /*           0 - no ANSI support available                            */
  1318.  /*          -1 - error detecting ansi                                 */
  1319.  CheckAnsi: 
  1320.    thisRC = -1
  1321.  
  1322.    trace off
  1323.                          /* install a local error handler              */
  1324.    SIGNAL ON ERROR Name InitAnsiEnd
  1325.  
  1326.    "@ANSI 2>NUL | rxqueue 2>NUL"
  1327.  
  1328.    thisRC = 0
  1329.  
  1330.    do while queued() <> 0
  1331.      queueLine = lineIN( "QUEUE:" )
  1332.      if pos( " on.", queueLine ) <> 0 | ,                       /* USA */
  1333.         pos( " (ON).", queueLine ) <> 0 then                    /* GER */
  1334.        thisRC = 1
  1335.    end /* do while queued() <> 0 */
  1336.  
  1337.  InitAnsiEnd:
  1338.  signal off error
  1339.  
  1340. if thisrc=1 then do
  1341.   aesc='1B'x
  1342.   cy_ye=aesc||'[37;46;m'
  1343.   cyanon=cy_ye
  1344.   normal=aesc||'[0;m'
  1345.   bold=aesc||'[1;m'
  1346.   re_wh=aesc||'[31;47;m'
  1347.   reverse=aesc||'[7;m'
  1348.   clear_screen=aesc||'[2J'
  1349. end
  1350. else do
  1351.   cy_ye="" ; normal="" ; bold="" ;re_wh="" ;clear_screen=''
  1352.   reverse=""
  1353. end  /* Do */
  1354.  
  1355.  
  1356.  
  1357.  RETURN 1
  1358.  
  1359.  
  1360.  
  1361.  
  1362. /*********/
  1363. /* show stuff in queue as a list */
  1364. show_dir_queue:procedure expose qlist. bold cy_ye normal reverse
  1365. parse arg lookfor
  1366.     ibs=0 ;mxlen=0
  1367.     if lookfor<>1 then
  1368.        nq=queued()
  1369.      else
  1370.         nq=qlist.0
  1371.     do ii=1 to nq
  1372.        if lookfor=1 then do
  1373.           aa=qlist.ii
  1374.           ii2=lastpos('\',aa) ; anam=substr(aa,ii2+1)
  1375.        end /* do */
  1376.        else do
  1377.           parse pull aa
  1378.           if pos(lookfor,aa)=0 & lookfor<>'*' then iterate
  1379.           parse var aa anam (lookfor) .
  1380.           if strip(anam)='.' | strip(anam)='..' then iterate
  1381.        end
  1382.        ibs=ibs+1
  1383.        blist.ibs=anam
  1384.        mxlen=max(length(anam),mxlen)
  1385.     end /* do */
  1386. arf=""
  1387. isaid=0
  1388. do il=1 to ibs
  1389.    anam=blist.il
  1390.    arf=arf||left(anam,mxlen+2)
  1391.    if length(arf)+mxlen+2>78  then do
  1392.         say arf
  1393.         isaid=(1+isaid)//22
  1394.         if isaid==0 then do
  1395.             say cy_YE " ... hit any key to continue, X to exit " NORMAL
  1396.             foo=translate(sysgetkey('noecho'))
  1397.             if foo='X' then do
  1398.                 arf='' ; leave
  1399.             end /* do */
  1400.         end
  1401.         arf=""
  1402.    end /* do */
  1403. end /* do */
  1404. if length(arf)>1 then say arf
  1405. say
  1406. return 1
  1407.  
  1408.  
  1409. /***********************************/
  1410. /* ungzip a string */
  1411. sref_ungzip:procedure 
  1412. parse arg astring
  1413. atid='DOGET'
  1414. tmpd=value('TEMP',,'os2environment')
  1415. tmpf=systempfilename(tmpd'\'||atid||'???.')
  1416. tmpfgz=tmpf||'GZ'
  1417. if stream(tmpfgz,'c','query exists')<>'' then foo=sysfiledelete(tmpfgz)
  1418. wow=charout(tmpfgz,astring,1)
  1419. wow=stream(tmpfgz,'c','close')
  1420. address cmd '@gzip  -d  ' tmpfgz 
  1421. if rc=0 then 
  1422.    awords=charin(tmpf,1,dosdir(tmpf,'s'))
  1423. else
  1424.    awords=''
  1425. foo=sysfiledelete(tmpfgz)
  1426. foo=sysfiledelete(tmpf)
  1427. return awords
  1428.  
  1429.  
  1430. /*******************************************/
  1431. rsync_synopsis:procedure 
  1432.  
  1433. parse arg afile,nblocks
  1434.  
  1435. if nblocks='' then nblocks=45
  1436. if datatype(nblocks)<>'NUM' then nblocks=45
  1437. if nblocks<10 | nblocks>255 then nblocks=45   /* 255 limit on # of blocks */
  1438.  
  1439. if afile='' then return "ERROR no old-version file specified"
  1440.  
  1441. /* read "Afile" */
  1442. aa=translate(stream(afile,'c','open read'))
  1443. if  abbrev(aa,'READY')=0 then return "ERROR could not open "afile
  1444. isize=stream(afile,'c','query size')
  1445. if isize='' | isize=0 then do
  1446.     return 'ERROR 'afile " is unaccessible"
  1447.     exit
  1448. end
  1449. astuff=charin(afile,1,isize)
  1450. aa=stream(afile,'c','close')
  1451.  
  1452.  
  1453. blocksize=trunc(0.9999 + (isize/nblocks))
  1454. if blocksize<200 then do
  1455.     blocksize=200
  1456.     nblocks=trunc((isize/blocksize)+0.999)
  1457. end /* do */
  1458. ac1=d2c(blocksize)
  1459. ac1=right(ac1,4,x2c('00'))
  1460. ac1=ac1||d2c(nblocks)
  1461. iat=1
  1462. do mm=1 to nblocks
  1463.   if mm=nblocks then
  1464.      ablock=substr(astuff,iat)
  1465.   else
  1466.      ablock=substr(astuff,iat,blocksize)
  1467.   ac0=left(x2c(rx_rsync32_md4(ablock)),8)
  1468.   ac1=ac1||ac0
  1469.   iat=iat+blocksize
  1470. end
  1471. ac1=mkpack64(ac1)
  1472.  
  1473. return ac1
  1474.  
  1475.  
  1476. /***********************************/
  1477. /* ungdiff: given a base file and gdiff-formatted difference file
  1478.    (as may be returned in a delta encoded response)output from gdiff-e (against this same
  1479.    base file) */
  1480.  
  1481. sref_ungdiff:procedure
  1482. parse arg basefile,adiff
  1483.  
  1484. atid='DOGET'
  1485. tmpd=value('TEMP',,'os2environment')
  1486. tmpf=systempfilename(tmpd'\'||atid||'???.')
  1487. tmpfdif=tmpf||'DIF'
  1488. tmpfout=tmpf||'DOU'
  1489.  
  1490. if stream(tmpfdif,'c','query exists')<>'' then foo=sysfiledelete(tmpfdif)
  1491. if stream(tmpfout,'c','query exists')<>'' then foo=sysfiledelete(tmpfout)
  1492.  
  1493. wow=charout(tmpfdif,adiff,1)
  1494. wow=stream(tmpfdif,'c','close')
  1495. goo= '@gdiff -u -q 'basefile' 'tmpfdif' 'tmpfout
  1496. address cmd goo
  1497.  
  1498. if rc=0 then do
  1499.    iii=stream(tmpfout,'c','query size')
  1500.    if iii='' | iii=0 then
  1501.         awords=""     /* error */
  1502.    else
  1503.        awords=charin(tmpfout,1,iii)
  1504. end
  1505. else do
  1506.    awords=''
  1507. end
  1508.  
  1509. foo=sysfiledelete(tmpfout)
  1510. foo=sysfiledelete(tmpfdif)
  1511.  
  1512. return awords
  1513.  
  1514. /***********************************/
  1515. /* undiff: given a basen file and output from diff-e (against this same
  1516.    base file) */
  1517.  
  1518. sref_undiff:procedure
  1519. parse arg basefile,adiff
  1520.  
  1521. atid='DOGET'
  1522. tmpd=value('TEMP',,'os2environment')
  1523. tmpf=systempfilename(tmpd'\'||atid||'???.')
  1524. tmpfdif=tmpf||'DIF'
  1525. tmpfout=tmpf||'DOU'
  1526.  
  1527. if stream(tmpfdif,'c','query exists')<>'' then foo=sysfiledelete(tmpfdif)
  1528. if stream(tmpfout,'c','query exists')<>'' then foo=sysfiledelete(tmpfout)
  1529.  
  1530. wow=charout(tmpfdif,adiff,1)
  1531. wow=stream(tmpfdif,'c','close')
  1532. goo= '@patch -s -e -o 'tmpfout' 'basefile' < 'tmpfdif
  1533. address cmd goo
  1534.  
  1535. if rc=0 then do
  1536.    iii=stream(tmpfout,'c','query size')
  1537.    if iii='' | iii=0 then
  1538.         awords=""     /* error */
  1539.    else
  1540.        awords=charin(tmpfout,1,iii)
  1541. end
  1542. else do
  1543.    awords=''
  1544. end
  1545.  
  1546.  
  1547. foo=sysfiledelete(tmpfout)
  1548. foo=sysfiledelete(tmpfdif)
  1549.  
  1550. return awords
  1551. /**********************/
  1552. mkPACK64:procedure
  1553. parse arg mess
  1554.  
  1555. biga=xrange('A','Z')||xrange('a','z')||xrange('0','9')||'+/'
  1556.  
  1557. s2=x2b(c2x(mess))
  1558.  
  1559. nith=trunc((length(s2)/6)+.9)
  1560. cont=copies(' ',nith)
  1561. oof=""
  1562. do mm=0 to 63
  1563.       oof=oof||x2c(b2x(right('00'||x2b(d2x(mm)),6)))
  1564. end /* do */
  1565. do ith=1 to nith 
  1566.   a1=substr(s2,(ith*6)-5,6,0)
  1567.   cont=overlay(x2c(b2x(a1)),cont,ith) 
  1568. end /* do */
  1569. pint=""
  1570. pint=translate(cont,biga,oof)
  1571. j1=length(pint)//4
  1572. if j1<>0 then pint=pint||copies('=',4-j1)
  1573. return pint
  1574.  
  1575.  
  1576. /* -------------------- */
  1577. /* choose between 3 alternatives (by default,a yes or no ),
  1578. return 1 if yes (or 0,1,2 for chosen altenative ) */
  1579.  
  1580. yesno:procedure expose normal reverse bold cy_ye     mm0a listfile
  1581. parse arg amessage , altans,def,arrowok
  1582. ony2:
  1583. aynn=' '
  1584. if def='' then
  1585.  defans=''
  1586. else
  1587.  defans=translate(left(strip(def),1))
  1588. if altans='' then altans='No Yes'
  1589.  
  1590. w.0=words(altans)
  1591. goo=aynn
  1592. do iw0=1 to w.0
  1593.      w.iw0=strip(word(altans,iw0))
  1594.      a.iw0=translate(left(w.iw0,1))
  1595.      aa.iw0=substr(w.iw0,2)
  1596.      aynn=aynn||bold
  1597.      if  a.iw0=defans then aynn=aynn||cy_ye
  1598.      aynn=aynn||a.iw0||normal||aa.iw0
  1599.      goo=goo||a.iw0||aa.iw0
  1600.      if iw0<w.0 then do
  1601.        aynn=aynn'  '
  1602.        goo=goo||'  '
  1603.      end
  1604. end
  1605. if arrowok=1 then aynn=aynn||' [UP]'
  1606.  
  1607. do forever
  1608.  foo1=normal||reverse||amessage||'? '||normal||aynn||': 'normal
  1609.  goo=amessage'?'||goo':'
  1610.  
  1611.  if length(goo)<73 then do
  1612.     call charout,foo1
  1613.  end
  1614.  else do
  1615.     foo1=normal||reverse||amessage||'? '||normal
  1616.     say foo1
  1617.     call charout,'     : 'aynn||': 'normal
  1618.  end
  1619.  
  1620.  anans=translate(sysgetkey('echo'))
  1621.  
  1622.  ianans=c2d(anans)
  1623.  if anans='' | ianans=13 | ianans=10 then  anans=defans
  1624.  
  1625.  if arrowok=1 & ianans=0  then do
  1626.      ians=c2d(sysgetkey('noecho'))
  1627.      if ians=72 then  do
  1628.            say ;say
  1629.            return -1  /* -1 : up key */
  1630.      end
  1631.  end /* do */
  1632.  
  1633.  do ijj=1 to w.0
  1634.     if abbrev(anans,a.ijj)=1 then do
  1635.         say
  1636.         return Ijj-1
  1637.     end
  1638.  end /* do */
  1639.  call charout,'0d'x
  1640. end
  1641.  
  1642.  
  1643. /***************/
  1644. /* return 0 for no, 1 for yes, default otherwise */
  1645. is_yes_no:procedure expose bold normal mm0a  reverse cy_ye listfile
  1646. parse arg aval,def
  1647. tdef=strip(translate(aval))
  1648. if wordpos(tdef,'Y YES 1')>0 then return 1
  1649. if wordpos(tdef,'N NO 0')>0 then return 0
  1650. return def
  1651.  
  1652.  
  1653.  
  1654. /* unchunk a chunked entity.
  1655.   a : the chunked entity entire body)
  1656.  inct: if 1, add trailers at beginning of entity (trailers crlf entity) 
  1657. */
  1658.  
  1659. unchunk:procedure
  1660. parse arg a,inct
  1661.  
  1662. stuff=''
  1663. do forever 
  1664.   parse var a a1 '0d0a'x a
  1665.   parse var a1 a2 ';' .
  1666.   da2=x2d(strip(a2))
  1667.   if da2=0 then leave
  1668.   stuff=stuff||left(a,da2)
  1669.   a=substr(a,da2+3)     /* skip crlf */
  1670. end
  1671.  
  1672. if inct<>1 then return stuff
  1673. trailers=''
  1674. do forever
  1675.    parse var a t1 '0d0a'x a
  1676.    if t1='' then leave
  1677.    trailers=trailers||t1||'0d0a'x
  1678. end /* do */
  1679. return trailers||'0d0a'x||stuff
  1680.  
  1681.  
  1682.  
  1683.  
  1684.  
  1685.  
  1686.  
  1687.  
  1688.  
  1689.