home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / srev13h.zip / SRERSYNC.CMD < prev    next >
OS/2 REXX Batch file  |  1999-12-13  |  7KB  |  212 lines

  1. /* 15 Nov 1999: 
  2.         sreRsync: an SRE-http pre-reply procedure that implements Rsync
  3.  
  4.    This SRE-http pre-reply procedure implements rsync differencing.
  5.    If an rsync-signature request header is present, it 
  6.    will either create an rsync difference file (to be sent to the client)
  7.    or add an  rsync-signature response header.
  8.   
  9.    a) Rsync-signature: 0 
  10.         Create an rsync-signature of the response. This can be
  11.         used (in an Rsync-signature request header) by the client 
  12.         in a future request 
  13.  
  14.    b) Rsync-signature: long_strip_of_base64_characters
  15.        Compute a difference file using the "current instance" of the 
  16.        resource (i.e.; the value of the "content" argument) and the 
  17.        "synopsis" contained in the long_string_of_base64_characters.
  18.        This difference will be returned to the client, along with a
  19.            Content-encoding: rsync-sre 
  20.        response header.
  21.  
  22. IMPORTANT NOTE:
  23.      To use sreRsync, you MUST have the RxRSYNC.DLL library installed.
  24.  
  25. For more details, please see sreRsync.doc
  26.  
  27. */
  28. sre_rsync:
  29.  
  30. /*    -------- User changeable parameters   ---------- */
  31.  
  32. /* Number of blocks to use when creating rsync-signature response header.
  33.    More blocks means longer request header, but more chances of a match 
  34.    45 yields about a 500 byte header, which is pushing acceptable
  35.    limits. Rsync_blocks must be  between 10 and 255  */
  36.  
  37. rsync_blocks=45
  38.  
  39. /*    -------- End of User changeable parameters   ---------- */
  40.  
  41. if rxfuncquery('rx_md4')=1  then do
  42.     aa=RXFuncAdd( 'RXRsyncLoad', 'RXRSYNC', 'RxRsyncLoad')
  43.     if aa=0 then do
  44.           call RxRsyncLoad
  45.     end
  46.     else do
  47.         if verbose>1 then  call pmprintf('SRE-http SRERsync procedure: ERROR -- can not find RxRSYNC.DLL')
  48.     end
  49.     if rxfuncquery('rx_md4')=1  then  return 0   /* no rsync procs available, so give up */
  50.     call pmprintf('foo')
  51. end
  52.  
  53. parse arg contents,fileflag,mimetype,clen,modstring
  54.  
  55. verbose=value('SREF_VERBOSE',,'os2environment')
  56.  
  57. /* 1) Look for a rsync-signature request header. If none, do nothing */
  58. rheader=reqfield('rsync-signature')
  59. if rheader='' then return 0
  60.  
  61. /* reqfield has problems, so re-read using entire head */
  62. 'read header var hh '
  63. do until hh =''
  64.    parse var hh aline '0d0a'x hh
  65.    aline=strip(aline)
  66.    if abbrev(translate(aline),'RSYNC-SIGNATURE:')=1 then do  
  67.        parse var aline . ':' rheader 
  68.  
  69.        DO UNTIL HH=''
  70.           PARSE VAR hh aline '0d0a'x hh
  71.           if pos(':',aline)>0 then leave
  72.           rheader=rheader||aline
  73.        end              /* do concatenate lines (goserve screwiness correction */
  74.        rheader=strip(rheader)
  75.        leave
  76.    end /* found a rsync-signature set of lines (in header) */
  77. end /* do */
  78.  
  79. /* got an rsync signature. Unpack64 it. */
  80. if rsign<>'' & rsign<>0 & rsign<>1 then
  81.    rsign=pack64(rheader)
  82.  
  83. /* create a rsync-signature? */
  84. if rsign='' | rsign=0 & rsign<>1 then do  /* rsync-signature:  with no value */
  85. say " .... rsigh "rsign
  86.    if fileflag=1 then do                /* read contents */
  87.       foo=stream(contents,'c','open read')
  88.       if abbrev(strip(translate(foo)),'READY')=0 then return 0 /* problem opening, give up */
  89.       jlen=stream(contents,'c','query size')
  90.       if jlen=0 | jlen='' then return 0
  91.       aa=charin(contents,1,jlen)
  92.       foo=stream(contents,'c','close')
  93.       contents=aa
  94.    end                          /* else, use contents as is */
  95.    bss=rsync_synopsis(rsync_blocks)     /* expose contents */
  96.    'HEADER add Rsync-signature: 'bss 
  97.    return 0
  98. end /* do */
  99.   
  100. /* else, compute rsync differnce file */
  101.  
  102. /* the signature, which is usually about 500  bytes "pre pack 64 conversion"
  103. (hence about 375 bytes post conversion) has the following structure:
  104.  blocksize:  4 bytes.  A 32 bit number: blocksize=x2d(c2x(vv))
  105.  Number_of_blocks: 1 bytes: a 8 bit number (max of 256 blocks)
  106.  block1:  8 bytes: The first four characters is a 32 bit "rolling" checksum,
  107.                    the second 4 characters are the leftmost 32 bits of
  108.                    an md4.
  109.  ...
  110.  blockn
  111. */
  112.  
  113. if fileflag=1 then 
  114.    jlen=stream(contents,'c','query size')
  115. else
  116.    jlen=length(contents)
  117.  
  118. blocksize=c2d(substr(rsign,1,4))
  119. nblocks=c2d(substr(rsign,5,1))
  120. stuff=''
  121. if verbose>2 then say 'sreRsync: Rsync-signature has 'nblocks 'blocks of size ='blocksize 
  122.  
  123. do mm=1 to nblocks
  124.    jat=((mm-1)*8)+6
  125.    foo=substr(rsign,jat,8)
  126.    stuff=stuff||left(foo,20)
  127. end
  128.  
  129. /* make a synopsis for feeding to rx_rsync_server */
  130. comment='srersync pre-reply '
  131. aa=left(comment,81)||left(blocksize,7)||left(nblocks,9)||left('md4',35)
  132. stuff=aa||stuff
  133.  
  134. tdir=value('SREF_TEMP_DATA_DIR',,'os2environment')
  135. a1=SYStempfilename(tdir||'\_RERSYNC.???')
  136.  
  137. del_contents=0
  138. if fileflag=0 then do
  139.    parse var a1 . '.' ext
  140.    a2=tdir||'\__RESYNC.'||aext
  141.    foo=charout(a2,contents,1)
  142.    if foo<>0 then return 0              /* error, give up */
  143.    foo=stream(a2,'c','close')
  144.    contents=a2
  145.    del_contents=1
  146. end
  147.  
  148. status=rx_rsync_gdiff(contents,stuff,a1,1)
  149. if abbrev(status,'OK')=0 then do
  150.   if verbose>1 then call pmprintf('sreRsync pre-reply WARNING: 'status)
  151.   return 0              /* give up */
  152. end
  153. if verbose>2 then call pmprintf('sreRsync: status= 'status)
  154. if del_contents=1 then foo=sysfiledelete(a2)
  155.  
  156. foo=stream(a1,'c','open read')
  157. if abbrev(strip(translate(foo)),'READY')=0 then do
  158.   if verbose>1 then  call pmprintf('SRE-http SRERsync pre-reply WARNING: unable to open difference file 'a1)
  159.   return 0
  160. end
  161.  
  162. issize=stream(a1,'c','query size')
  163. if (issize=0 | issize='') then do
  164.   if verbose>1 then  call pmprintf('SRE-http SRERsync pre-reply WARNING: 0 sized difference file 'a1)
  165.   return 0
  166. end
  167.  
  168. stuff=charin(a1,1,issize)
  169. issize=stream(a1,'c','CLOSE')
  170.  
  171. foo=sysfiledelete(a1)
  172.  
  173. 'HEADER add Content-encoding: rsync-sre '
  174.  
  175. return  modstring||' '||mimetype||' 1 '||'0d0a'x||stuff
  176.  
  177.  
  178. /*****************/
  179. /* create rsync synopsis */
  180. /*******************************************/
  181. rsync_synopsis:procedure EXPOSE contents 
  182. parse arg nblocks
  183.  
  184. if nblocks='' then nblocks=45
  185. if datatype(nblocks)<>'NUM' then nblocks=45
  186. if nblocks<10 | nblocks>255 then nblocks=45   /* 255 limit on # of blocks */
  187.  
  188. isize=length(contents)
  189. blocksize=trunc(0.9999 + (isize/nblocks))
  190. if blocksize<200 then do
  191.     blocksize=200
  192.     nblocks=trunc((isize/blocksize)+0.999)
  193. end /* do */
  194. ac1=d2c(blocksize)
  195. ac1=right(ac1,4,x2c('00'))
  196. ac1=ac1||d2c(nblocks)
  197. iat=1
  198. do mm=1 to nblocks
  199.   if mm=nblocks then
  200.      ablock=substr(contents,iat)
  201.   else
  202.      ablock=substr(contents,iat,blocksize)
  203.   ac0=left(x2c(rx_rsync32_md4(ablock)),8)
  204.   ac1=ac1||ac0
  205.   iat=iat+blocksize
  206. end
  207. ac1=sref_mkpack64(ac1)
  208.  
  209. return ac1
  210.  
  211.  
  212.