Artifact 287a3edd5d3c654f833189494681d7eb38a8faf4:


0000: 3b 3b 3b 0a 3b 3b 3b 20 63 6f 6f 6b 69 65 2e 73  ;;;.;;; cookie.s
0010: 63 6d 20 2d 20 70 61 72 73 65 20 61 6e 64 20 63  cm - parse and c
0020: 6f 6e 73 74 72 75 63 74 20 68 74 74 70 20 73 74  onstruct http st
0030: 61 74 65 20 69 6e 66 6f 72 6d 61 74 69 6f 6e 0a  ate information.
0040: 3b 3b 3b 20 20 0a 3b 3b 3b 20 20 20 43 6f 70 79  ;;;  .;;;   Copy
0050: 72 69 67 68 74 20 28 63 29 20 32 30 30 30 2d 32  right (c) 2000-2
0060: 30 30 33 20 53 68 69 72 6f 20 4b 61 77 61 69 2c  003 Shiro Kawai,
0070: 20 41 6c 6c 20 72 69 67 68 74 73 20 72 65 73 65   All rights rese
0080: 72 76 65 64 2e 0a 3b 3b 3b 20 20 20 0a 3b 3b 3b  rved..;;;   .;;;
0090: 20 20 20 52 65 64 69 73 74 72 69 62 75 74 69 6f     Redistributio
00a0: 6e 20 61 6e 64 20 75 73 65 20 69 6e 20 73 6f 75  n and use in sou
00b0: 72 63 65 20 61 6e 64 20 62 69 6e 61 72 79 20 66  rce and binary f
00c0: 6f 72 6d 73 2c 20 77 69 74 68 20 6f 72 20 77 69  orms, with or wi
00d0: 74 68 6f 75 74 0a 3b 3b 3b 20 20 20 6d 6f 64 69  thout.;;;   modi
00e0: 66 69 63 61 74 69 6f 6e 2c 20 61 72 65 20 70 65  fication, are pe
00f0: 72 6d 69 74 74 65 64 20 70 72 6f 76 69 64 65 64  rmitted provided
0100: 20 74 68 61 74 20 74 68 65 20 66 6f 6c 6c 6f 77   that the follow
0110: 69 6e 67 20 63 6f 6e 64 69 74 69 6f 6e 73 0a 3b  ing conditions.;
0120: 3b 3b 20 20 20 61 72 65 20 6d 65 74 3a 0a 3b 3b  ;;   are met:.;;
0130: 3b 20 20 20 0a 3b 3b 3b 20 20 20 31 2e 20 52 65  ;   .;;;   1. Re
0140: 64 69 73 74 72 69 62 75 74 69 6f 6e 73 20 6f 66  distributions of
0150: 20 73 6f 75 72 63 65 20 63 6f 64 65 20 6d 75 73   source code mus
0160: 74 20 72 65 74 61 69 6e 20 74 68 65 20 61 62 6f  t retain the abo
0170: 76 65 20 63 6f 70 79 72 69 67 68 74 0a 3b 3b 3b  ve copyright.;;;
0180: 20 20 20 20 20 20 6e 6f 74 69 63 65 2c 20 74 68        notice, th
0190: 69 73 20 6c 69 73 74 20 6f 66 20 63 6f 6e 64 69  is list of condi
01a0: 74 69 6f 6e 73 20 61 6e 64 20 74 68 65 20 66 6f  tions and the fo
01b0: 6c 6c 6f 77 69 6e 67 20 64 69 73 63 6c 61 69 6d  llowing disclaim
01c0: 65 72 2e 0a 3b 3b 3b 20 20 0a 3b 3b 3b 20 20 20  er..;;;  .;;;   
01d0: 32 2e 20 52 65 64 69 73 74 72 69 62 75 74 69 6f  2. Redistributio
01e0: 6e 73 20 69 6e 20 62 69 6e 61 72 79 20 66 6f 72  ns in binary for
01f0: 6d 20 6d 75 73 74 20 72 65 70 72 6f 64 75 63 65  m must reproduce
0200: 20 74 68 65 20 61 62 6f 76 65 20 63 6f 70 79 72   the above copyr
0210: 69 67 68 74 0a 3b 3b 3b 20 20 20 20 20 20 6e 6f  ight.;;;      no
0220: 74 69 63 65 2c 20 74 68 69 73 20 6c 69 73 74 20  tice, this list 
0230: 6f 66 20 63 6f 6e 64 69 74 69 6f 6e 73 20 61 6e  of conditions an
0240: 64 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20  d the following 
0250: 64 69 73 63 6c 61 69 6d 65 72 20 69 6e 20 74 68  disclaimer in th
0260: 65 0a 3b 3b 3b 20 20 20 20 20 20 64 6f 63 75 6d  e.;;;      docum
0270: 65 6e 74 61 74 69 6f 6e 20 61 6e 64 2f 6f 72 20  entation and/or 
0280: 6f 74 68 65 72 20 6d 61 74 65 72 69 61 6c 73 20  other materials 
0290: 70 72 6f 76 69 64 65 64 20 77 69 74 68 20 74 68  provided with th
02a0: 65 20 64 69 73 74 72 69 62 75 74 69 6f 6e 2e 0a  e distribution..
02b0: 3b 3b 3b 20 20 0a 3b 3b 3b 20 20 20 33 2e 20 4e  ;;;  .;;;   3. N
02c0: 65 69 74 68 65 72 20 74 68 65 20 6e 61 6d 65 20  either the name 
02d0: 6f 66 20 74 68 65 20 61 75 74 68 6f 72 73 20 6e  of the authors n
02e0: 6f 72 20 74 68 65 20 6e 61 6d 65 73 20 6f 66 20  or the names of 
02f0: 69 74 73 20 63 6f 6e 74 72 69 62 75 74 6f 72 73  its contributors
0300: 0a 3b 3b 3b 20 20 20 20 20 20 6d 61 79 20 62 65  .;;;      may be
0310: 20 75 73 65 64 20 74 6f 20 65 6e 64 6f 72 73 65   used to endorse
0320: 20 6f 72 20 70 72 6f 6d 6f 74 65 20 70 72 6f 64   or promote prod
0330: 75 63 74 73 20 64 65 72 69 76 65 64 20 66 72 6f  ucts derived fro
0340: 6d 20 74 68 69 73 0a 3b 3b 3b 20 20 20 20 20 20  m this.;;;      
0350: 73 6f 66 74 77 61 72 65 20 77 69 74 68 6f 75 74  software without
0360: 20 73 70 65 63 69 66 69 63 20 70 72 69 6f 72 20   specific prior 
0370: 77 72 69 74 74 65 6e 20 70 65 72 6d 69 73 73 69  written permissi
0380: 6f 6e 2e 0a 3b 3b 3b 20 20 0a 3b 3b 3b 20 20 20  on..;;;  .;;;   
0390: 54 48 49 53 20 53 4f 46 54 57 41 52 45 20 49 53  THIS SOFTWARE IS
03a0: 20 50 52 4f 56 49 44 45 44 20 42 59 20 54 48 45   PROVIDED BY THE
03b0: 20 43 4f 50 59 52 49 47 48 54 20 48 4f 4c 44 45   COPYRIGHT HOLDE
03c0: 52 53 20 41 4e 44 20 43 4f 4e 54 52 49 42 55 54  RS AND CONTRIBUT
03d0: 4f 52 53 0a 3b 3b 3b 20 20 20 22 41 53 20 49 53  ORS.;;;   "AS IS
03e0: 22 20 41 4e 44 20 41 4e 59 20 45 58 50 52 45 53  " AND ANY EXPRES
03f0: 53 20 4f 52 20 49 4d 50 4c 49 45 44 20 57 41 52  S OR IMPLIED WAR
0400: 52 41 4e 54 49 45 53 2c 20 49 4e 43 4c 55 44 49  RANTIES, INCLUDI
0410: 4e 47 2c 20 42 55 54 20 4e 4f 54 0a 3b 3b 3b 20  NG, BUT NOT.;;; 
0420: 20 20 4c 49 4d 49 54 45 44 20 54 4f 2c 20 54 48    LIMITED TO, TH
0430: 45 20 49 4d 50 4c 49 45 44 20 57 41 52 52 41 4e  E IMPLIED WARRAN
0440: 54 49 45 53 20 4f 46 20 4d 45 52 43 48 41 4e 54  TIES OF MERCHANT
0450: 41 42 49 4c 49 54 59 20 41 4e 44 20 46 49 54 4e  ABILITY AND FITN
0460: 45 53 53 20 46 4f 52 0a 3b 3b 3b 20 20 20 41 20  ESS FOR.;;;   A 
0470: 50 41 52 54 49 43 55 4c 41 52 20 50 55 52 50 4f  PARTICULAR PURPO
0480: 53 45 20 41 52 45 20 44 49 53 43 4c 41 49 4d 45  SE ARE DISCLAIME
0490: 44 2e 20 49 4e 20 4e 4f 20 45 56 45 4e 54 20 53  D. IN NO EVENT S
04a0: 48 41 4c 4c 20 54 48 45 20 43 4f 50 59 52 49 47  HALL THE COPYRIG
04b0: 48 54 0a 3b 3b 3b 20 20 20 4f 57 4e 45 52 20 4f  HT.;;;   OWNER O
04c0: 52 20 43 4f 4e 54 52 49 42 55 54 4f 52 53 20 42  R CONTRIBUTORS B
04d0: 45 20 4c 49 41 42 4c 45 20 46 4f 52 20 41 4e 59  E LIABLE FOR ANY
04e0: 20 44 49 52 45 43 54 2c 20 49 4e 44 49 52 45 43   DIRECT, INDIREC
04f0: 54 2c 20 49 4e 43 49 44 45 4e 54 41 4c 2c 0a 3b  T, INCIDENTAL,.;
0500: 3b 3b 20 20 20 53 50 45 43 49 41 4c 2c 20 45 58  ;;   SPECIAL, EX
0510: 45 4d 50 4c 41 52 59 2c 20 4f 52 20 43 4f 4e 53  EMPLARY, OR CONS
0520: 45 51 55 45 4e 54 49 41 4c 20 44 41 4d 41 47 45  EQUENTIAL DAMAGE
0530: 53 20 28 49 4e 43 4c 55 44 49 4e 47 2c 20 42 55  S (INCLUDING, BU
0540: 54 20 4e 4f 54 20 4c 49 4d 49 54 45 44 0a 3b 3b  T NOT LIMITED.;;
0550: 3b 20 20 20 54 4f 2c 20 50 52 4f 43 55 52 45 4d  ;   TO, PROCUREM
0560: 45 4e 54 20 4f 46 20 53 55 42 53 54 49 54 55 54  ENT OF SUBSTITUT
0570: 45 20 47 4f 4f 44 53 20 4f 52 20 53 45 52 56 49  E GOODS OR SERVI
0580: 43 45 53 3b 20 4c 4f 53 53 20 4f 46 20 55 53 45  CES; LOSS OF USE
0590: 2c 20 44 41 54 41 2c 20 4f 52 0a 3b 3b 3b 20 20  , DATA, OR.;;;  
05a0: 20 50 52 4f 46 49 54 53 3b 20 4f 52 20 42 55 53   PROFITS; OR BUS
05b0: 49 4e 45 53 53 20 49 4e 54 45 52 52 55 50 54 49  INESS INTERRUPTI
05c0: 4f 4e 29 20 48 4f 57 45 56 45 52 20 43 41 55 53  ON) HOWEVER CAUS
05d0: 45 44 20 41 4e 44 20 4f 4e 20 41 4e 59 20 54 48  ED AND ON ANY TH
05e0: 45 4f 52 59 20 4f 46 0a 3b 3b 3b 20 20 20 4c 49  EORY OF.;;;   LI
05f0: 41 42 49 4c 49 54 59 2c 20 57 48 45 54 48 45 52  ABILITY, WHETHER
0600: 20 49 4e 20 43 4f 4e 54 52 41 43 54 2c 20 53 54   IN CONTRACT, ST
0610: 52 49 43 54 20 4c 49 41 42 49 4c 49 54 59 2c 20  RICT LIABILITY, 
0620: 4f 52 20 54 4f 52 54 20 28 49 4e 43 4c 55 44 49  OR TORT (INCLUDI
0630: 4e 47 0a 3b 3b 3b 20 20 20 4e 45 47 4c 49 47 45  NG.;;;   NEGLIGE
0640: 4e 43 45 20 4f 52 20 4f 54 48 45 52 57 49 53 45  NCE OR OTHERWISE
0650: 29 20 41 52 49 53 49 4e 47 20 49 4e 20 41 4e 59  ) ARISING IN ANY
0660: 20 57 41 59 20 4f 55 54 20 4f 46 20 54 48 45 20   WAY OUT OF THE 
0670: 55 53 45 20 4f 46 20 54 48 49 53 0a 3b 3b 3b 20  USE OF THIS.;;; 
0680: 20 20 53 4f 46 54 57 41 52 45 2c 20 45 56 45 4e    SOFTWARE, EVEN
0690: 20 49 46 20 41 44 56 49 53 45 44 20 4f 46 20 54   IF ADVISED OF T
06a0: 48 45 20 50 4f 53 53 49 42 49 4c 49 54 59 20 4f  HE POSSIBILITY O
06b0: 46 20 53 55 43 48 20 44 41 4d 41 47 45 2e 0a 3b  F SUCH DAMAGE..;
06c0: 3b 3b 20 20 0a 3b 3b 3b 20 20 50 6f 72 74 65 64  ;;  .;;;  Ported
06d0: 20 74 6f 20 43 68 69 63 6b 65 6e 20 62 79 20 52   to Chicken by R
06e0: 65 65 64 20 53 68 65 72 69 64 61 6e 0a 3b 3b 3b  eed Sheridan.;;;
06f0: 0a 0a 3b 3b 20 50 61 72 73 65 72 20 61 6e 64 20  ..;; Parser and 
0700: 63 6f 6e 73 74 72 75 63 74 6f 72 20 6f 66 20 68  constructor of h
0710: 74 74 70 20 22 43 6f 6f 6b 69 65 73 22 20 64 65  ttp "Cookies" de
0720: 66 69 6e 65 64 20 69 6e 0a 3b 3b 20 52 46 43 20  fined in.;; RFC 
0730: 32 39 36 35 20 48 54 54 50 20 73 74 61 74 65 20  2965 HTTP state 
0740: 6d 61 6e 61 67 65 6d 6e 65 74 20 6d 65 63 68 61  managemnet mecha
0750: 6e 69 73 6d 0a 3b 3b 20 20 20 3c 66 74 70 3a 2f  nism.;;   <ftp:/
0760: 2f 66 74 70 2e 69 73 69 2e 65 64 75 2f 69 6e 2d  /ftp.isi.edu/in-
0770: 6e 6f 74 65 73 2f 72 66 63 32 39 36 35 2e 74 78  notes/rfc2965.tx
0780: 74 3e 0a 3b 3b 20 53 65 65 20 61 6c 73 6f 0a 3b  t>.;; See also.;
0790: 3b 20 52 46 43 20 32 39 36 34 20 55 73 65 20 6f  ; RFC 2964 Use o
07a0: 66 20 48 54 54 50 20 73 74 61 74 65 20 6d 61 6e  f HTTP state man
07b0: 61 67 65 6d 65 6e 74 0a 3b 3b 20 20 20 3c 66 74  agement.;;   <ft
07c0: 70 3a 2f 2f 66 74 70 2e 69 73 69 2e 65 64 75 2f  p://ftp.isi.edu/
07d0: 69 6e 2d 6e 6f 74 65 73 2f 72 66 63 32 39 36 34  in-notes/rfc2964
07e0: 2e 74 78 74 3e 0a 3b 3b 20 54 68 65 20 70 61 72  .txt>.;; The par
07f0: 73 65 72 20 61 6c 73 6f 20 73 75 70 70 6f 72 74  ser also support
0800: 73 20 74 68 65 20 6f 6c 64 20 4e 65 74 73 63 61  s the old Netsca
0810: 70 65 20 73 70 65 63 0a 3b 3b 20 20 20 3c 68 74  pe spec.;;   <ht
0820: 74 70 3a 2f 2f 77 77 77 2e 6e 65 74 73 63 61 70  tp://www.netscap
0830: 65 2e 63 6f 6d 2f 6e 65 77 73 72 65 66 2f 73 74  e.com/newsref/st
0840: 64 2f 63 6f 6f 6b 69 65 5f 73 70 65 63 2e 68 74  d/cookie_spec.ht
0850: 6d 6c 3e 0a 0a 0a 28 72 65 71 75 69 72 65 2d 65  ml>...(require-e
0860: 78 74 65 6e 73 69 6f 6e 20 73 72 66 69 2d 31 20  xtension srfi-1 
0870: 73 72 66 69 2d 31 33 20 73 72 66 69 2d 31 34 20  srfi-13 srfi-14 
0880: 72 65 67 65 78 29 0a 28 64 65 63 6c 61 72 65 20  regex).(declare 
0890: 28 65 78 70 6f 72 74 20 70 61 72 73 65 2d 63 6f  (export parse-co
08a0: 6f 6b 69 65 2d 73 74 72 69 6e 67 20 63 6f 6e 73  okie-string cons
08b0: 74 72 75 63 74 2d 63 6f 6f 6b 69 65 2d 73 74 72  truct-cookie-str
08c0: 69 6e 67 29 29 0a 0a 23 3e 0a 23 69 6e 63 6c 75  ing))..#>.#inclu
08d0: 64 65 20 3c 74 69 6d 65 2e 68 3e 0a 3c 23 0a 0a  de <time.h>.<#..
08e0: 28 64 65 66 69 6e 65 20 66 6d 74 2d 74 69 6d 65  (define fmt-time
08f0: 0a 20 20 28 66 6f 72 65 69 67 6e 2d 6c 61 6d 62  .  (foreign-lamb
0900: 64 61 2a 20 63 2d 73 74 72 69 6e 67 20 28 28 6c  da* c-string ((l
0910: 6f 6e 67 20 73 65 63 73 5f 73 69 6e 63 65 5f 65  ong secs_since_e
0920: 70 6f 63 68 29 29 0a 20 20 20 20 22 73 74 61 74  poch)).    "stat
0930: 69 63 20 63 68 61 72 20 62 75 66 5b 32 35 36 5d  ic char buf[256]
0940: 3b 22 0a 20 20 20 20 22 74 69 6d 65 5f 74 20 74  ;".    "time_t t
0950: 20 3d 20 28 74 69 6d 65 5f 74 29 20 73 65 63 73   = (time_t) secs
0960: 5f 73 69 6e 63 65 5f 65 70 6f 63 68 3b 22 0a 20  _since_epoch;". 
0970: 20 20 20 22 73 74 72 66 74 69 6d 65 28 62 75 66     "strftime(buf
0980: 2c 20 73 69 7a 65 6f 66 28 62 75 66 29 2c 20 5c  , sizeof(buf), \
0990: 22 25 61 2c 20 25 64 2d 25 62 2d 25 59 20 25 48  "%a, %d-%b-%Y %H
09a0: 3a 25 4d 3a 25 53 20 47 4d 54 5c 22 2c 20 67 6d  :%M:%S GMT\", gm
09b0: 74 69 6d 65 28 26 74 29 29 3b 22 0a 20 20 20 20  time(&t));".    
09c0: 22 72 65 74 75 72 6e 28 62 75 66 29 3b 22 29 29  "return(buf);"))
09d0: 0a 0a 3b 3b 20 75 74 69 6c 69 74 79 20 66 6e 2e  ..;; utility fn.
09e0: 20 20 62 72 65 61 6b 73 20 20 60 60 61 74 74 72    breaks  ``attr
09f0: 3d 76 61 6c 75 65 3b 61 74 74 72 3d 76 61 6c 75  =value;attr=valu
0a00: 65 20 2e 2e 2e 20 27 27 20 69 6e 74 6f 20 61 6c  e ... '' into al
0a10: 69 73 74 2e 0a 3b 3b 20 76 65 72 73 69 6f 6e 20  ist..;; version 
0a20: 69 73 20 61 20 63 6f 6f 6b 69 65 20 76 65 72 73  is a cookie vers
0a30: 69 6f 6e 2e 20 20 69 66 20 76 65 72 73 69 6f 6e  ion.  if version
0a40: 3e 30 2c 20 77 65 20 61 6c 6c 6f 77 20 63 6f 6d  >0, we allow com
0a50: 6d 61 20 61 73 20 74 68 65 0a 3b 3b 20 64 65 6c  ma as the.;; del
0a60: 69 6d 69 74 65 72 20 61 73 20 77 65 6c 6c 20 61  imiter as well a
0a70: 73 20 73 65 6d 69 63 6f 6c 6f 6e 2e 0a 28 64 65  s semicolon..(de
0a80: 66 69 6e 65 20 28 70 61 72 73 65 2d 61 76 2d 70  fine (parse-av-p
0a90: 61 69 72 73 20 69 6e 70 75 74 20 76 65 72 73 69  airs input versi
0aa0: 6f 6e 29 0a 20 20 28 64 65 66 69 6e 65 20 61 74  on).  (define at
0ab0: 74 72 2d 72 65 67 65 78 70 0a 20 20 20 20 28 69  tr-regexp.    (i
0ac0: 66 20 28 3d 20 76 65 72 73 69 6f 6e 20 30 29 0a  f (= version 0).
0ad0: 20 20 20 20 20 20 20 20 28 72 65 67 65 78 70 20          (regexp 
0ae0: 22 5c 5c 73 2a 28 5b 5c 5c 77 24 5f 2d 5d 2b 29  "\\s*([\\w$_-]+)
0af0: 5c 5c 73 2a 28 5b 3d 5c 5c 3b 5d 5c 5c 73 2a 29  \\s*([=\\;]\\s*)
0b00: 3f 22 29 0a 20 20 20 20 20 20 20 20 28 72 65 67  ?").        (reg
0b10: 65 78 70 20 22 5c 5c 73 2a 28 5b 5c 5c 77 24 5f  exp "\\s*([\\w$_
0b20: 2d 5d 2b 29 5c 5c 73 2a 28 5b 3d 5c 5c 3b 2c 5d  -]+)\\s*([=\\;,]
0b30: 5c 5c 73 2a 29 3f 22 29 29 29 0a 20 20 28 64 65  \\s*)?"))).  (de
0b40: 66 69 6e 65 20 61 74 74 72 2d 64 65 6c 69 6d 0a  fine attr-delim.
0b50: 20 20 20 20 28 69 66 20 28 3d 20 76 65 72 73 69      (if (= versi
0b60: 6f 6e 20 30 29 20 23 5c 3b 20 28 63 68 61 72 2d  on 0) #\; (char-
0b70: 73 65 74 20 23 5c 2c 20 23 5c 5c 20 23 5c 3b 29  set #\, #\\ #\;)
0b80: 29 29 0a 20 20 0a 20 20 28 64 65 66 69 6e 65 20  )).  .  (define 
0b90: 28 72 65 61 64 2d 61 74 74 72 20 69 6e 70 75 74  (read-attr input
0ba0: 20 72 29 0a 20 20 20 20 28 63 6f 6e 64 20 28 28   r).    (cond ((
0bb0: 73 74 72 69 6e 67 2d 6e 75 6c 6c 3f 20 69 6e 70  string-null? inp
0bc0: 75 74 29 20 28 72 65 76 65 72 73 65 21 20 72 29  ut) (reverse! r)
0bd0: 29 0a 20 20 20 20 20 20 20 20 20 20 28 28 73 74  ).          ((st
0be0: 72 69 6e 67 2d 73 65 61 72 63 68 20 61 74 74 72  ring-search attr
0bf0: 2d 72 65 67 65 78 70 20 69 6e 70 75 74 29 0a 20  -regexp input). 
0c00: 20 20 20 20 20 20 20 20 20 20 3d 3e 20 28 6c 61            => (la
0c10: 6d 62 64 61 20 28 6d 29 0a 20 20 20 20 20 20 20  mbda (m).       
0c20: 20 20 20 20 20 20 20 20 20 28 69 66 20 28 61 6e           (if (an
0c30: 64 2d 6c 65 74 2a 20 28 28 64 65 6c 69 6d 69 74  d-let* ((delimit
0c40: 65 72 20 28 74 68 69 72 64 20 6d 29 29 29 20 3b  er (third m))) ;
0c50: 3b 69 73 20 61 6e 20 61 74 74 72 5f 76 61 6c 75  ;is an attr_valu
0c60: 65 20 70 61 69 0a 09 09 20 20 20 20 20 20 28 73  e pai...      (s
0c70: 74 72 69 6e 67 2d 70 72 65 66 69 78 3f 20 22 3d  tring-prefix? "=
0c80: 22 20 64 65 6c 69 6d 69 74 65 72 29 29 0a 20 20  " delimiter)).  
0c90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ca0: 20 20 28 6c 65 74 20 28 28 61 74 74 72 20 28 73    (let ((attr (s
0cb0: 65 63 6f 6e 64 20 6d 29 29 0a 20 20 20 20 20 20  econd m)).      
0cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0cd0: 20 20 20 20 28 72 65 73 74 20 28 73 74 72 69 6e      (rest (strin
0ce0: 67 2d 73 65 61 72 63 68 2d 61 66 74 65 72 20 61  g-search-after a
0cf0: 74 74 72 2d 72 65 67 65 78 70 20 69 6e 70 75 74  ttr-regexp input
0d00: 29 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ))).            
0d10: 20 20 20 20 20 20 20 20 20 20 28 69 66 20 28 73            (if (s
0d20: 74 72 69 6e 67 2d 70 72 65 66 69 78 3f 20 22 5c  tring-prefix? "\
0d30: 22 22 20 72 65 73 74 29 0a 20 20 20 20 20 20 20  "" rest).       
0d40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0d50: 20 20 20 28 72 65 61 64 2d 74 6f 6b 65 6e 2d 71     (read-token-q
0d60: 75 6f 74 65 64 20 61 74 74 72 20 28 73 74 72 69  uoted attr (stri
0d70: 6e 67 2d 64 72 6f 70 20 72 65 73 74 20 31 29 20  ng-drop rest 1) 
0d80: 72 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r).             
0d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 28 72 65               (re
0da0: 61 64 2d 74 6f 6b 65 6e 20 61 74 74 72 20 72 65  ad-token attr re
0db0: 73 74 20 72 29 29 29 0a 20 20 20 20 20 20 20 20  st r))).        
0dc0: 20 20 20 20 20 20 20 20 20 20 20 20 28 72 65 61              (rea
0dd0: 64 2d 61 74 74 72 20 28 73 74 72 69 6e 67 2d 73  d-attr (string-s
0de0: 65 61 72 63 68 2d 61 66 74 65 72 20 61 74 74 72  earch-after attr
0df0: 2d 72 65 67 65 78 70 20 69 6e 70 75 74 29 20 3b  -regexp input) ;
0e00: 3b 20 53 6b 69 70 20 61 68 65 61 64 20 69 66 20  ; Skip ahead if 
0e10: 62 72 6f 6b 65 6e 20 69 6e 70 75 74 3f 0a 20 20  broken input?.  
0e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 28 61 6c               (al
0e40: 69 73 74 2d 63 6f 6e 73 20 28 73 65 63 6f 6e 64  ist-cons (second
0e50: 20 6d 29 20 23 66 20 72 29 29 29 29 29 0a 20 20   m) #f r))))).  
0e60: 20 20 20 20 20 20 20 20 28 65 6c 73 65 0a 20 20          (else.  
0e70: 20 20 20 20 20 20 20 20 20 3b 3b 20 74 68 65 20           ;; the 
0e80: 69 6e 70 75 74 20 69 73 20 62 72 6f 6b 65 6e 3b  input is broken;
0e90: 20 66 6f 72 20 6e 6f 77 2c 20 77 65 20 69 67 6e   for now, we ign
0ea0: 6f 72 65 20 74 68 65 20 72 65 73 74 2e 0a 20 20  ore the rest..  
0eb0: 20 20 20 20 20 20 20 20 20 28 72 65 76 65 72 73           (revers
0ec0: 65 21 20 72 29 29 29 29 0a 20 20 28 64 65 66 69  e! r)))).  (defi
0ed0: 6e 65 20 28 72 65 61 64 2d 74 6f 6b 65 6e 20 61  ne (read-token a
0ee0: 74 74 72 20 69 6e 70 75 74 20 72 29 0a 20 20 20  ttr input r).   
0ef0: 20 28 63 6f 6e 64 20 28 28 73 74 72 69 6e 67 2d   (cond ((string-
0f00: 69 6e 64 65 78 20 69 6e 70 75 74 20 61 74 74 72  index input attr
0f10: 2d 64 65 6c 69 6d 29 0a 20 20 20 20 20 20 20 20  -delim).        
0f20: 20 20 20 3d 3e 20 28 6c 61 6d 62 64 61 20 28 69     => (lambda (i
0f30: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
0f40: 20 20 28 72 65 61 64 2d 61 74 74 72 20 28 73 74    (read-attr (st
0f50: 72 69 6e 67 2d 64 72 6f 70 20 69 6e 70 75 74 20  ring-drop input 
0f60: 28 2b 20 69 20 31 29 29 0a 20 20 20 20 20 20 20  (+ i 1)).       
0f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0f80: 20 20 20 20 28 61 6c 69 73 74 2d 63 6f 6e 73 20      (alist-cons 
0f90: 61 74 74 72 0a 09 09 09 09 20 20 20 20 20 20 20  attr.....       
0fa0: 28 73 74 72 69 6e 67 2d 74 72 69 6d 2d 72 69 67  (string-trim-rig
0fb0: 68 74 20 28 73 74 72 69 6e 67 2d 74 61 6b 65 20  ht (string-take 
0fc0: 69 6e 70 75 74 20 69 29 29 0a 09 09 09 09 20 20  input i)).....  
0fd0: 20 20 20 20 20 72 29 29 29 29 0a 20 20 20 20 20       r)))).     
0fe0: 20 20 20 20 20 28 65 6c 73 65 0a 20 20 20 20 20       (else.     
0ff0: 20 20 20 20 20 20 28 72 65 76 65 72 73 65 21 20        (reverse! 
1000: 28 61 6c 69 73 74 2d 63 6f 6e 73 20 61 74 74 72  (alist-cons attr
1010: 20 28 73 74 72 69 6e 67 2d 74 72 69 6d 2d 72 69   (string-trim-ri
1020: 67 68 74 20 69 6e 70 75 74 29 20 72 29 29 29 29  ght input) r))))
1030: 29 0a 20 20 28 64 65 66 69 6e 65 20 28 72 65 61  ).  (define (rea
1040: 64 2d 74 6f 6b 65 6e 2d 71 75 6f 74 65 64 20 61  d-token-quoted a
1050: 74 74 72 20 69 6e 70 75 74 20 72 29 0a 20 20 20  ttr input r).   
1060: 20 28 6c 65 74 20 6c 6f 6f 70 20 28 28 69 6e 70   (let loop ((inp
1070: 75 74 20 69 6e 70 75 74 29 0a 20 20 20 20 20 20  ut input).      
1080: 20 20 20 20 20 20 20 20 20 28 70 61 72 74 69 61           (partia
1090: 6c 20 27 28 29 29 29 0a 20 20 20 20 20 20 28 63  l '())).      (c
10a0: 6f 6e 64 20 28 28 73 74 72 69 6e 67 2d 69 6e 64  ond ((string-ind
10b0: 65 78 20 69 6e 70 75 74 20 28 63 68 61 72 2d 73  ex input (char-s
10c0: 65 74 20 23 5c 5c 20 23 5c 22 29 29 0a 20 20 20  et #\\ #\")).   
10d0: 20 20 20 20 20 20 20 20 20 20 3d 3e 20 28 6c 61            => (la
10e0: 6d 62 64 61 20 28 69 29 0a 20 20 20 20 20 20 20  mbda (i).       
10f0: 20 20 20 20 20 20 20 20 20 20 20 28 6c 65 74 20             (let 
1100: 28 28 63 20 28 73 74 72 69 6e 67 2d 72 65 66 20  ((c (string-ref 
1110: 69 6e 70 75 74 20 69 29 29 29 0a 20 20 20 20 20  input i))).     
1120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28                 (
1130: 69 66 20 28 63 68 61 72 3d 3f 20 63 20 23 5c 5c  if (char=? c #\\
1140: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
1150: 20 20 20 20 20 20 20 20 20 20 28 69 66 20 28 3c            (if (<
1160: 20 28 73 74 72 69 6e 67 2d 6c 65 6e 67 74 68 20   (string-length 
1170: 69 6e 70 75 74 29 20 28 2b 20 69 20 31 29 29 0a  input) (+ i 1)).
1180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1190: 20 20 20 20 20 20 20 20 20 20 20 20 28 65 72 72              (err
11a0: 6f 72 2d 75 6e 74 65 72 6d 69 6e 61 74 65 64 20  or-unterminated 
11b0: 61 74 74 72 29 0a 20 20 20 20 20 20 20 20 20 20  attr).          
11c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11d0: 20 20 28 6c 6f 6f 70 20 28 73 74 72 69 6e 67 2d    (loop (string-
11e0: 64 72 6f 70 20 69 6e 70 75 74 20 28 2b 20 69 20  drop input (+ i 
11f0: 32 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  2)).            
1200: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1210: 20 20 20 20 20 20 28 63 6f 6e 73 2a 20 28 73 74        (cons* (st
1220: 72 69 6e 67 20 28 73 74 72 69 6e 67 2d 72 65 66  ring (string-ref
1230: 20 69 6e 70 75 74 20 28 2b 20 69 20 31 29 29 29   input (+ i 1)))
1240: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1250: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1260: 20 20 20 20 20 20 20 20 20 20 28 73 74 72 69 6e            (strin
1270: 67 2d 74 61 6b 65 20 69 6e 70 75 74 20 69 29 0a  g-take input i).
1280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12a0: 20 20 20 20 20 20 20 20 20 70 61 72 74 69 61 6c           partial
12b0: 29 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ))).            
12c0: 20 20 20 20 20 20 20 20 20 20 20 20 28 72 65 61              (rea
12d0: 64 2d 61 74 74 72 20 28 73 74 72 69 6e 67 2d 64  d-attr (string-d
12e0: 72 6f 70 20 69 6e 70 75 74 20 28 2b 20 69 20 31  rop input (+ i 1
12f0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )).             
1300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1310: 20 20 20 20 20 20 28 61 6c 69 73 74 2d 63 6f 6e        (alist-con
1320: 73 20 61 74 74 72 0a 09 09 09 09 09 20 20 20 20  s attr......    
1330: 20 20 20 28 73 74 72 69 6e 67 2d 63 6f 6e 63 61     (string-conca
1340: 74 65 6e 61 74 65 2d 72 65 76 65 72 73 65 0a 09  tenate-reverse..
1350: 09 09 09 09 09 28 63 6f 6e 73 20 28 73 74 72 69  .....(cons (stri
1360: 6e 67 2d 74 61 6b 65 20 69 6e 70 75 74 20 69 29  ng-take input i)
1370: 0a 09 09 09 09 09 09 20 20 20 20 20 20 70 61 72  .......      par
1380: 74 69 61 6c 29 29 0a 09 09 09 09 09 20 20 20 20  tial))......    
1390: 20 20 20 72 29 29 29 29 29 29 0a 20 20 20 20 20     r)))))).     
13a0: 20 20 20 20 20 20 20 28 65 6c 73 65 20 28 65 72         (else (er
13b0: 72 6f 72 2d 75 6e 74 65 72 6d 69 6e 61 74 65 64  ror-unterminated
13c0: 20 61 74 74 72 29 29 29 29 29 0a 20 20 28 64 65   attr))))).  (de
13d0: 66 69 6e 65 20 28 65 72 72 6f 72 2d 75 6e 74 65  fine (error-unte
13e0: 72 6d 69 6e 61 74 65 64 20 61 74 74 72 29 0a 20  rminated attr). 
13f0: 20 20 20 28 65 72 72 6f 72 20 22 55 6e 74 65 72     (error "Unter
1400: 6d 69 6e 61 74 65 64 20 71 75 6f 74 65 64 20 76  minated quoted v
1410: 61 6c 75 65 20 67 69 76 65 6e 20 66 6f 72 20 61  alue given for a
1420: 74 74 72 69 62 75 74 65 22 20 61 74 74 72 29 29  ttribute" attr))
1430: 0a 0a 20 20 28 72 65 61 64 2d 61 74 74 72 20 69  ..  (read-attr i
1440: 6e 70 75 74 20 27 28 29 29 29 0a 0a 3b 3b 20 50  nput '()))..;; P
1450: 61 72 73 65 73 20 74 68 65 20 68 65 61 64 65 72  arses the header
1460: 20 76 61 6c 75 65 20 6f 66 20 22 43 6f 6f 6b 69   value of "Cooki
1470: 65 22 20 72 65 71 75 65 73 74 20 68 65 61 64 65  e" request heade
1480: 72 2e 0a 3b 3b 20 49 66 20 63 6f 6f 6b 69 65 20  r..;; If cookie 
1490: 76 65 72 73 69 6f 6e 20 69 73 20 6b 6e 6f 77 6e  version is known
14a0: 20 62 79 20 22 43 6f 6f 6b 69 65 32 22 20 72 65   by "Cookie2" re
14b0: 71 75 65 73 74 20 68 65 61 64 65 72 2c 20 69 74  quest header, it
14c0: 20 73 68 6f 75 6c 64 0a 3b 3b 20 62 65 20 70 61   should.;; be pa
14d0: 73 73 65 64 20 74 6f 20 76 65 72 73 69 6f 6e 20  ssed to version 
14e0: 28 61 73 20 69 6e 74 65 67 65 72 29 2e 20 20 4f  (as integer).  O
14f0: 74 68 65 72 77 69 73 65 2c 20 69 74 20 66 69 67  therwise, it fig
1500: 75 72 65 73 20 6f 75 74 0a 3b 3b 20 74 68 65 20  ures out.;; the 
1510: 63 6f 6f 6b 69 65 20 76 65 72 73 69 6f 6e 20 66  cookie version f
1520: 72 6f 6d 20 69 6e 70 75 74 2e 0a 3b 3b 0a 3b 3b  rom input..;;.;;
1530: 20 52 65 74 75 72 6e 73 20 74 68 65 20 66 6f 6c   Returns the fol
1540: 6c 6f 77 69 6e 67 20 66 6f 72 6d 61 74 2e 0a 3b  lowing format..;
1550: 3b 20 20 20 28 28 3c 6e 61 6d 65 3e 20 3c 76 61  ;   ((<name> <va
1560: 6c 75 65 3e 20 5b 3a 70 61 74 68 20 3c 70 61 74  lue> [:path <pat
1570: 68 3e 5d 20 5b 3a 64 6f 6d 61 69 6e 20 3c 64 6f  h>] [:domain <do
1580: 6d 61 69 6e 3e 5d 20 5b 3a 70 6f 72 74 20 3c 70  main>] [:port <p
1590: 6f 72 74 3e 5d 29 0a 3b 3b 20 20 20 20 2e 2e 2e  ort>]).;;    ...
15a0: 29 0a 0a 28 64 65 66 69 6e 65 20 28 70 61 72 73  )..(define (pars
15b0: 65 2d 63 6f 6f 6b 69 65 2d 73 74 72 69 6e 67 20  e-cookie-string 
15c0: 69 6e 70 75 74 20 23 21 6f 70 74 69 6f 6e 61 6c  input #!optional
15d0: 20 76 65 72 73 69 6f 6e 29 0a 20 20 28 6c 65 74   version).  (let
15e0: 20 28 28 76 65 72 20 28 63 6f 6e 64 20 28 28 69   ((ver (cond ((i
15f0: 6e 74 65 67 65 72 3f 20 76 65 72 73 69 6f 6e 29  nteger? version)
1600: 20 76 65 72 73 69 6f 6e 29 0a 20 20 20 20 20 20   version).      
1610: 20 20 20 20 20 20 20 20 20 20 20 20 20 28 28 73               ((s
1620: 74 72 69 6e 67 2d 73 65 61 72 63 68 20 22 5e 5c  tring-search "^\
1630: 5c 73 2a 5c 5c 24 56 65 72 73 69 6f 6e 5c 5c 73  \s*\\$Version\\s
1640: 2a 3d 5c 5c 73 2a 28 5c 5c 64 2b 29 22 20 69 6e  *=\\s*(\\d+)" in
1650: 70 75 74 29 0a 20 20 20 20 20 20 20 20 20 20 20  put).           
1660: 20 20 20 20 20 20 20 20 20 3d 3e 20 28 6c 61 6d           => (lam
1670: 62 64 61 20 28 6d 29 0a 20 20 20 20 20 20 20 20  bda (m).        
1680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1690: 20 28 73 74 72 69 6e 67 2d 3e 6e 75 6d 62 65 72   (string->number
16a0: 20 28 63 61 64 72 20 6d 29 29 29 29 0a 20 20 20   (cadr m)))).   
16b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16c0: 28 65 6c 73 65 20 30 29 29 29 29 0a 20 20 20 20  (else 0)))).    
16d0: 28 6c 65 74 20 6c 6f 6f 70 20 28 28 61 76 2d 70  (let loop ((av-p
16e0: 61 69 72 73 20 28 70 61 72 73 65 2d 61 76 2d 70  airs (parse-av-p
16f0: 61 69 72 73 20 69 6e 70 75 74 20 76 65 72 29 29  airs input ver))
1700: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1710: 28 72 20 27 28 29 29 0a 20 20 20 20 20 20 20 20  (r '()).        
1720: 20 20 20 20 20 20 20 28 63 75 72 72 65 6e 74 20         (current 
1730: 27 28 29 29 29 0a 20 20 20 20 20 20 28 63 6f 6e  '())).      (con
1740: 64 20 28 28 6e 75 6c 6c 3f 20 61 76 2d 70 61 69  d ((null? av-pai
1750: 72 73 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  rs).            
1760: 20 28 69 66 20 28 6e 75 6c 6c 3f 20 63 75 72 72   (if (null? curr
1770: 65 6e 74 29 0a 20 20 20 20 20 20 20 20 20 20 20  ent).           
1780: 20 20 20 20 20 20 28 72 65 76 65 72 73 65 20 72        (reverse r
1790: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
17a0: 20 20 20 28 72 65 76 65 72 73 65 20 28 63 6f 6e     (reverse (con
17b0: 73 20 28 72 65 76 65 72 73 65 20 63 75 72 72 65  s (reverse curre
17c0: 6e 74 29 20 72 29 29 29 29 0a 20 20 20 20 20 20  nt) r)))).      
17d0: 20 20 20 20 20 20 28 28 73 74 72 69 6e 67 2d 63        ((string-c
17e0: 69 3d 3f 20 22 24 70 61 74 68 22 20 28 63 61 61  i=? "$path" (caa
17f0: 72 20 61 76 2d 70 61 69 72 73 29 29 0a 20 20 20  r av-pairs)).   
1800: 20 20 20 20 20 20 20 20 20 20 28 6c 6f 6f 70 20            (loop 
1810: 28 63 64 72 20 61 76 2d 70 61 69 72 73 29 20 72  (cdr av-pairs) r
1820: 20 28 63 6f 6e 73 2a 20 28 63 64 61 72 20 61 76   (cons* (cdar av
1830: 2d 70 61 69 72 73 29 20 70 61 74 68 3a 20 63 75  -pairs) path: cu
1840: 72 72 65 6e 74 29 29 29 0a 20 20 20 20 20 20 20  rrent))).       
1850: 20 20 20 20 20 28 28 73 74 72 69 6e 67 2d 63 69       ((string-ci
1860: 3d 3f 20 22 24 64 6f 6d 61 69 6e 22 20 28 63 61  =? "$domain" (ca
1870: 61 72 20 61 76 2d 70 61 69 72 73 29 29 0a 20 20  ar av-pairs)).  
1880: 20 20 20 20 20 20 20 20 20 20 20 28 6c 6f 6f 70             (loop
1890: 20 28 63 64 72 20 61 76 2d 70 61 69 72 73 29 20   (cdr av-pairs) 
18a0: 72 20 28 63 6f 6e 73 2a 20 28 63 64 61 72 20 61  r (cons* (cdar a
18b0: 76 2d 70 61 69 72 73 29 20 64 6f 6d 61 69 6e 3a  v-pairs) domain:
18c0: 20 63 75 72 72 65 6e 74 29 29 29 0a 20 20 20 20   current))).    
18d0: 20 20 20 20 20 20 20 20 28 28 73 74 72 69 6e 67          ((string
18e0: 2d 63 69 3d 3f 20 22 24 70 6f 72 74 22 20 28 63  -ci=? "$port" (c
18f0: 61 61 72 20 61 76 2d 70 61 69 72 73 29 29 0a 20  aar av-pairs)). 
1900: 20 20 20 20 20 20 20 20 20 20 20 20 28 6c 6f 6f              (loo
1910: 70 20 28 63 64 72 20 61 76 2d 70 61 69 72 73 29  p (cdr av-pairs)
1920: 20 72 20 28 63 6f 6e 73 2a 20 28 63 64 61 72 20   r (cons* (cdar 
1930: 61 76 2d 70 61 69 72 73 29 20 70 6f 72 74 3a 20  av-pairs) port: 
1940: 63 75 72 72 65 6e 74 29 29 29 0a 20 20 20 20 20  current))).     
1950: 20 20 20 20 20 20 20 28 65 6c 73 65 0a 20 20 20         (else.   
1960: 20 20 20 20 20 20 20 20 20 20 28 69 66 20 28 6e            (if (n
1970: 75 6c 6c 3f 20 63 75 72 72 65 6e 74 29 0a 20 20  ull? current).  
1980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28                 (
1990: 6c 6f 6f 70 20 28 63 64 72 20 61 76 2d 70 61 69  loop (cdr av-pai
19a0: 72 73 29 20 72 20 28 6c 69 73 74 20 28 63 64 61  rs) r (list (cda
19b0: 72 20 61 76 2d 70 61 69 72 73 29 20 28 63 61 61  r av-pairs) (caa
19c0: 72 20 61 76 2d 70 61 69 72 73 29 29 29 0a 20 20  r av-pairs))).  
19d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 28                 (
19e0: 6c 6f 6f 70 20 28 63 64 72 20 61 76 2d 70 61 69  loop (cdr av-pai
19f0: 72 73 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  rs).            
1a00: 20 20 20 20 20 20 20 20 20 20 20 28 63 6f 6e 73             (cons
1a10: 20 28 72 65 76 65 72 73 65 20 63 75 72 72 65 6e   (reverse curren
1a20: 74 29 20 72 29 0a 20 20 20 20 20 20 20 20 20 20  t) r).          
1a30: 20 20 20 20 20 20 20 20 20 20 20 20 20 28 6c 69               (li
1a40: 73 74 20 28 63 64 61 72 20 61 76 2d 70 61 69 72  st (cdar av-pair
1a50: 73 29 20 28 63 61 61 72 20 61 76 2d 70 61 69 72  s) (caar av-pair
1a60: 73 29 29 29 29 29 29 29 29 29 0a 0a 3b 3b 20 43  s)))))))))..;; C
1a70: 6f 6e 73 74 72 75 63 74 20 61 20 63 6f 6f 6b 69  onstruct a cooki
1a80: 65 20 73 74 72 69 6e 67 20 73 75 69 74 61 62 6c  e string suitabl
1a90: 65 20 66 6f 72 20 53 65 74 2d 43 6f 6f 6b 69 65  e for Set-Cookie
1aa0: 20 6f 72 20 53 65 74 2d 43 6f 6f 6b 69 65 32 20   or Set-Cookie2 
1ab0: 68 65 61 64 65 72 2e 0a 3b 3b 20 73 70 65 63 73  header..;; specs
1ac0: 20 69 73 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e   is the followin
1ad0: 67 20 66 6f 72 6d 61 74 2e 0a 3b 3b 0a 3b 3b 20  g format..;;.;; 
1ae0: 20 20 28 28 3c 6e 61 6d 65 3e 20 3c 76 61 6c 75    ((<name> <valu
1af0: 65 3e 20 5b 3a 63 6f 6d 6d 65 6e 74 20 3c 63 6f  e> [:comment <co
1b00: 6d 6d 65 6e 74 3e 5d 20 5b 3a 63 6f 6d 6d 65 6e  mment>] [:commen
1b10: 74 2d 75 72 6c 20 3c 63 6f 6d 6d 65 6e 74 2d 75  t-url <comment-u
1b20: 72 6c 3e 5d 0a 3b 3b 20 20 20 20 20 20 20 20 20  rl>].;;         
1b30: 20 20 20 20 20 20 20 20 20 20 20 5b 3a 64 69 73             [:dis
1b40: 63 61 72 64 20 3c 62 6f 6f 6c 3e 5d 20 5b 3a 64  card <bool>] [:d
1b50: 6f 6d 61 69 6e 20 3c 64 6f 6d 61 69 6e 3e 5d 0a  omain <domain>].
1b60: 3b 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;;              
1b70: 20 20 20 20 20 20 5b 3a 6d 61 78 2d 61 67 65 20        [:max-age 
1b80: 3c 61 67 65 3e 5d 20 5b 3a 70 61 74 68 20 3c 76  <age>] [:path <v
1b90: 61 6c 75 65 3e 5d 20 5b 3a 70 6f 72 74 20 3c 70  alue>] [:port <p
1ba0: 6f 72 74 2d 6c 69 73 74 3e 5d 0a 3b 3b 20 20 20  ort-list>].;;   
1bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1bc0: 20 5b 3a 73 65 63 75 72 65 20 3c 62 6f 6f 6c 3e   [:secure <bool>
1bd0: 5d 20 5b 3a 76 65 72 73 69 6f 6e 20 3c 76 65 72  ] [:version <ver
1be0: 73 69 6f 6e 3e 5d 20 5b 3a 65 78 70 69 72 65 73  sion>] [:expires
1bf0: 20 3c 64 61 74 65 3e 5d 0a 3b 3b 20 20 20 20 29   <date>].;;    )
1c00: 20 2e 2e 2e 29 0a 3b 3b 0a 3b 3b 20 52 65 74 75   ...).;;.;; Retu
1c10: 72 6e 73 20 61 20 6c 69 73 74 20 6f 66 20 63 6f  rns a list of co
1c20: 6f 6b 69 65 20 73 74 72 69 6e 67 73 20 66 6f 72  okie strings for
1c30: 20 65 61 63 68 20 3c 6e 61 6d 65 3e 3d 3c 76 61   each <name>=<va
1c40: 6c 75 65 3e 20 70 61 69 72 2e 20 20 49 6e 20 74  lue> pair.  In t
1c50: 68 65 0a 3b 3b 20 60 60 6e 65 77 20 63 6f 6f 6b  he.;; ``new cook
1c60: 69 65 27 27 20 69 6d 70 6c 65 6d 65 6e 74 61 74  ie'' implementat
1c70: 69 6f 6e 2c 20 79 6f 75 20 63 61 6e 20 6a 6f 69  ion, you can joi
1c80: 6e 20 74 68 65 6d 20 62 79 20 63 6f 6d 6d 61 20  n them by comma 
1c90: 61 6e 64 20 73 65 6e 64 20 69 74 0a 3b 3b 20 61  and send it.;; a
1ca0: 74 20 6f 6e 63 65 20 77 69 74 68 20 53 65 74 2d  t once with Set-
1cb0: 63 6f 6f 6b 69 65 32 20 68 65 61 64 65 72 2e 20  cookie2 header. 
1cc0: 20 46 6f 72 20 74 68 65 20 6f 6c 64 20 6e 65 74   For the old net
1cd0: 73 63 61 70 65 20 70 72 6f 74 6f 63 6f 6c 2c 20  scape protocol, 
1ce0: 79 6f 75 0a 3b 3b 20 6d 75 73 74 20 73 65 6e 64  you.;; must send
1cf0: 20 65 61 63 68 20 6f 66 20 74 68 65 6d 20 62 79   each of them by
1d00: 20 53 65 74 2d 63 6f 6f 6b 69 65 20 68 65 61 64   Set-cookie head
1d10: 65 72 2e 0a 0a 0a 28 64 65 66 69 6e 65 20 28 63  er....(define (c
1d20: 6f 6e 73 74 72 75 63 74 2d 63 6f 6f 6b 69 65 2d  onstruct-cookie-
1d30: 73 74 72 69 6e 67 20 73 70 65 63 73 20 23 21 6f  string specs #!o
1d40: 70 74 69 6f 6e 61 6c 20 28 76 65 72 73 69 6f 6e  ptional (version
1d50: 20 31 29 29 0a 20 20 28 6d 61 70 20 28 6c 61 6d   1)).  (map (lam
1d60: 62 64 61 20 28 73 70 65 63 29 20 28 63 6f 6e 73  bda (spec) (cons
1d70: 74 72 75 63 74 2d 63 6f 6f 6b 69 65 2d 73 74 72  truct-cookie-str
1d80: 69 6e 67 2d 31 20 73 70 65 63 20 76 65 72 73 69  ing-1 spec versi
1d90: 6f 6e 29 29 0a 20 20 20 20 20 20 20 73 70 65 63  on)).       spec
1da0: 73 29 29 0a 0a 28 64 65 66 69 6e 65 20 28 63 6f  s))..(define (co
1db0: 6e 73 74 72 75 63 74 2d 63 6f 6f 6b 69 65 2d 73  nstruct-cookie-s
1dc0: 74 72 69 6e 67 2d 31 20 73 70 65 63 20 76 65 72  tring-1 spec ver
1dd0: 29 0a 20 20 28 77 68 65 6e 20 28 3c 20 28 6c 65  ).  (when (< (le
1de0: 6e 67 74 68 20 73 70 65 63 29 20 32 29 0a 20 20  ngth spec) 2).  
1df0: 20 20 28 65 72 72 6f 72 20 22 62 61 64 20 63 6f    (error "bad co
1e00: 6f 6b 69 65 20 73 70 65 63 3a 20 61 74 20 6c 65  okie spec: at le
1e10: 61 73 74 20 3c 6e 61 6d 65 3e 20 61 6e 64 20 3c  ast <name> and <
1e20: 76 61 6c 75 65 3e 20 72 65 71 75 69 72 65 64 22  value> required"
1e30: 20 73 70 65 63 29 29 0a 20 20 28 6c 65 74 20 28   spec)).  (let (
1e40: 28 6e 61 6d 65 20 28 63 61 72 20 73 70 65 63 29  (name (car spec)
1e50: 29 0a 20 20 20 20 20 20 20 20 28 76 61 6c 75 65  ).        (value
1e60: 20 28 63 61 64 72 20 73 70 65 63 29 29 29 0a 20   (cadr spec))). 
1e70: 20 20 20 28 6c 65 74 20 6c 6f 6f 70 20 28 28 61     (let loop ((a
1e80: 74 74 72 20 28 63 64 64 72 20 73 70 65 63 29 29  ttr (cddr spec))
1e90: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1ea0: 28 72 20 20 20 20 28 6c 69 73 74 20 28 69 66 20  (r    (list (if 
1eb0: 76 61 6c 75 65 0a 20 20 20 20 20 20 20 20 20 20  value.          
1ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ed0: 20 20 20 20 20 28 73 74 72 69 6e 67 2d 61 70 70       (string-app
1ee0: 65 6e 64 20 6e 61 6d 65 20 22 3d 22 0a 20 20 20  end name "=".   
1ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f10: 20 20 20 20 20 20 20 20 20 20 20 28 71 75 6f 74             (quot
1f20: 65 2d 69 66 2d 6e 65 65 64 65 64 20 76 61 6c 75  e-if-needed valu
1f30: 65 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  e)).            
1f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f50: 20 20 20 6e 61 6d 65 29 29 29 29 0a 20 20 20 20     name)))).    
1f60: 20 20 28 64 65 66 69 6e 65 20 28 6e 65 78 74 20    (define (next 
1f70: 73 29 20 28 6c 6f 6f 70 20 28 63 64 64 72 20 61  s) (loop (cddr a
1f80: 74 74 72 29 20 28 63 6f 6e 73 20 73 20 72 29 29  ttr) (cons s r))
1f90: 29 0a 20 20 20 20 20 20 28 64 65 66 69 6e 65 20  ).      (define 
1fa0: 28 69 67 6e 6f 72 65 29 20 28 6c 6f 6f 70 20 28  (ignore) (loop (
1fb0: 63 64 64 72 20 61 74 74 72 29 20 72 29 29 0a 20  cddr attr) r)). 
1fc0: 20 20 20 20 20 28 63 6f 6e 64 0a 20 20 20 20 20       (cond.     
1fd0: 20 20 28 28 6e 75 6c 6c 3f 20 61 74 74 72 29 20    ((null? attr) 
1fe0: 28 73 74 72 69 6e 67 2d 6a 6f 69 6e 20 28 72 65  (string-join (re
1ff0: 76 65 72 73 65 20 72 29 20 22 3b 22 29 29 0a 20  verse r) ";")). 
2000: 20 20 20 20 20 20 28 28 6e 75 6c 6c 3f 20 28 63        ((null? (c
2010: 64 72 20 61 74 74 72 29 29 0a 20 20 20 20 20 20  dr attr)).      
2020: 20 20 28 65 72 72 6f 72 20 28 63 6f 6e 63 20 22    (error (conc "
2030: 62 61 64 20 63 6f 6f 6b 69 65 20 73 70 65 63 3a  bad cookie spec:
2040: 20 61 74 74 72 69 62 75 74 65 20 22 20 28 63 61   attribute " (ca
2050: 72 20 61 74 74 72 29 20 22 20 72 65 71 75 69 72  r attr) " requir
2060: 65 73 20 76 61 6c 75 65 22 20 29 29 29 0a 20 20  es value" ))).  
2070: 20 20 20 20 20 28 28 65 71 76 3f 20 63 6f 6d 6d       ((eqv? comm
2080: 65 6e 74 3a 20 28 63 61 72 20 61 74 74 72 29 29  ent: (car attr))
2090: 0a 20 20 20 20 20 20 20 20 28 69 66 20 28 3e 20  .        (if (> 
20a0: 76 65 72 20 30 29 0a 09 20 20 20 20 28 6e 65 78  ver 0)..    (nex
20b0: 74 20 28 73 74 72 69 6e 67 2d 61 70 70 65 6e 64  t (string-append
20c0: 20 22 43 6f 6d 6d 65 6e 74 3d 22 20 28 71 75 6f   "Comment=" (quo
20d0: 74 65 2d 69 66 2d 6e 65 65 64 65 64 20 28 63 61  te-if-needed (ca
20e0: 64 72 20 61 74 74 72 29 29 29 29 0a 20 20 20 20  dr attr)))).    
20f0: 20 20 20 20 20 20 20 20 28 69 67 6e 6f 72 65 29          (ignore)
2100: 29 29 0a 20 20 20 20 20 20 20 28 28 65 71 76 3f  )).       ((eqv?
2110: 20 63 6f 6d 6d 65 6e 74 2d 75 72 6c 3a 20 28 63   comment-url: (c
2120: 61 72 20 61 74 74 72 29 29 0a 20 20 20 20 20 20  ar attr)).      
2130: 20 20 28 69 66 20 28 3e 20 76 65 72 20 30 29 0a    (if (> ver 0).
2140: 20 20 20 20 20 20 20 20 20 20 20 20 28 6e 65 78              (nex
2150: 74 20 28 73 74 72 69 6e 67 2d 61 70 70 65 6e 64  t (string-append
2160: 20 22 43 6f 6d 6d 65 6e 74 55 52 4c 3d 22 20 28   "CommentURL=" (
2170: 71 75 6f 74 65 2d 76 61 6c 75 65 20 28 63 61 64  quote-value (cad
2180: 72 20 61 74 74 72 29 29 29 29 0a 20 20 20 20 20  r attr)))).     
2190: 20 20 20 20 20 20 20 28 69 67 6e 6f 72 65 29 29         (ignore))
21a0: 29 0a 20 20 20 20 20 20 20 28 28 65 71 76 3f 20  ).       ((eqv? 
21b0: 64 69 73 63 61 72 64 3a 20 28 63 61 72 20 61 74  discard: (car at
21c0: 74 72 29 29 0a 20 20 20 20 20 20 20 20 28 69 66  tr)).        (if
21d0: 20 28 61 6e 64 20 28 3e 20 76 65 72 20 30 29 20   (and (> ver 0) 
21e0: 28 63 61 64 72 20 61 74 74 72 29 29 20 28 6e 65  (cadr attr)) (ne
21f0: 78 74 20 22 44 69 73 63 61 72 64 22 29 20 28 69  xt "Discard") (i
2200: 67 6e 6f 72 65 29 29 29 0a 20 20 20 20 20 20 20  gnore))).       
2210: 28 28 65 71 76 3f 20 64 6f 6d 61 69 6e 3a 20 28  ((eqv? domain: (
2220: 63 61 72 20 61 74 74 72 29 29 0a 20 20 20 20 20  car attr)).     
2230: 20 20 20 28 6e 65 78 74 20 28 73 74 72 69 6e 67     (next (string
2240: 2d 61 70 70 65 6e 64 20 22 44 6f 6d 61 69 6e 3d  -append "Domain=
2250: 22 20 28 63 61 64 72 20 61 74 74 72 29 29 29 29  " (cadr attr))))
2260: 0a 20 20 20 20 20 20 20 28 28 65 71 76 3f 20 6d  .       ((eqv? m
2270: 61 78 2d 61 67 65 3a 20 28 63 61 72 20 61 74 74  ax-age: (car att
2280: 72 29 29 0a 20 20 20 20 20 20 20 20 28 69 66 20  r)).        (if 
2290: 28 3e 20 76 65 72 20 30 29 0a 20 20 20 20 20 20  (> ver 0).      
22a0: 20 20 20 20 20 20 28 6e 65 78 74 20 28 73 70 72        (next (spr
22b0: 69 6e 74 66 20 22 4d 61 78 2d 41 67 65 3d 7e 61  intf "Max-Age=~a
22c0: 22 20 28 63 61 64 72 20 61 74 74 72 29 29 29 0a  " (cadr attr))).
22d0: 20 20 20 20 20 20 20 20 20 20 20 20 28 69 67 6e              (ign
22e0: 6f 72 65 29 29 29 0a 20 20 20 20 20 20 20 28 28  ore))).       ((
22f0: 65 71 76 3f 20 70 61 74 68 3a 20 28 63 61 72 20  eqv? path: (car 
2300: 61 74 74 72 29 29 0a 20 20 20 20 20 20 20 20 28  attr)).        (
2310: 6e 65 78 74 20 28 73 74 72 69 6e 67 2d 61 70 70  next (string-app
2320: 65 6e 64 20 22 50 61 74 68 3d 22 20 28 71 75 6f  end "Path=" (quo
2330: 74 65 2d 69 66 2d 6e 65 65 64 65 64 20 28 63 61  te-if-needed (ca
2340: 64 72 20 61 74 74 72 29 29 29 29 29 0a 20 20 20  dr attr))))).   
2350: 20 20 20 20 28 28 65 71 76 3f 20 70 6f 72 74 3a      ((eqv? port:
2360: 20 28 63 61 72 20 61 74 74 72 29 29 0a 20 20 20   (car attr)).   
2370: 20 20 20 20 20 28 69 66 20 28 3e 20 76 65 72 20       (if (> ver 
2380: 30 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 28  0).            (
2390: 6e 65 78 74 20 28 73 74 72 69 6e 67 2d 61 70 70  next (string-app
23a0: 65 6e 64 20 22 50 6f 72 74 3d 22 20 28 71 75 6f  end "Port=" (quo
23b0: 74 65 2d 76 61 6c 75 65 20 28 63 61 64 72 20 61  te-value (cadr a
23c0: 74 74 72 29 29 29 29 0a 20 20 20 20 20 20 20 20  ttr)))).        
23d0: 20 20 20 20 28 69 67 6e 6f 72 65 29 29 29 0a 20      (ignore))). 
23e0: 20 20 20 20 20 20 28 28 65 71 76 3f 20 73 65 63        ((eqv? sec
23f0: 75 72 65 3a 20 28 63 61 72 20 61 74 74 72 29 29  ure: (car attr))
2400: 0a 20 20 20 20 20 20 20 20 28 69 66 20 28 63 61  .        (if (ca
2410: 64 72 20 61 74 74 72 29 20 28 6e 65 78 74 20 22  dr attr) (next "
2420: 53 65 63 75 72 65 22 29 20 28 69 67 6e 6f 72 65  Secure") (ignore
2430: 29 29 29 0a 20 20 20 20 20 20 20 28 28 65 71 76  ))).       ((eqv
2440: 3f 20 76 65 72 73 69 6f 6e 3a 20 28 63 61 72 20  ? version: (car 
2450: 61 74 74 72 29 29 0a 20 20 20 20 20 20 20 20 28  attr)).        (
2460: 69 66 20 28 3e 20 76 65 72 20 30 29 0a 20 20 20  if (> ver 0).   
2470: 20 20 20 20 20 20 20 20 20 28 6e 65 78 74 20 28           (next (
2480: 73 70 72 69 6e 74 66 20 22 56 65 72 73 69 6f 6e  sprintf "Version
2490: 3d 7e 61 22 20 28 63 61 64 72 20 61 74 74 72 29  =~a" (cadr attr)
24a0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 28  )).            (
24b0: 69 67 6e 6f 72 65 29 29 29 0a 20 20 20 20 20 20  ignore))).      
24c0: 20 28 28 65 71 76 3f 20 65 78 70 69 72 65 73 3a   ((eqv? expires:
24d0: 20 28 63 61 72 20 61 74 74 72 29 29 0a 20 20 20   (car attr)).   
24e0: 20 20 20 20 20 28 69 66 20 28 3e 20 76 65 72 20       (if (> ver 
24f0: 30 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 28  0).            (
2500: 69 67 6e 6f 72 65 29 0a 20 20 20 20 20 20 20 20  ignore).        
2510: 20 20 20 20 28 6e 65 78 74 20 28 6d 61 6b 65 2d      (next (make-
2520: 65 78 70 69 72 65 73 2d 61 74 74 72 20 28 63 61  expires-attr (ca
2530: 64 72 20 61 74 74 72 29 29 29 29 29 0a 20 20 20  dr attr))))).   
2540: 20 20 20 20 28 65 6c 73 65 20 28 65 72 72 6f 72      (else (error
2550: 20 22 55 6e 6b 6e 6f 77 6e 20 63 6f 6f 6b 69 65   "Unknown cookie
2560: 20 61 74 74 72 69 62 75 74 65 22 20 28 63 61 72   attribute" (car
2570: 20 61 74 74 72 29 29 29 29 0a 20 20 20 20 20 20   attr)))).      
2580: 29 29 0a 20 20 29 0a 0a 0a 3b 3b 20 28 64 65 66  )).  )...;; (def
2590: 69 6e 65 20 28 71 75 6f 74 65 2d 76 61 6c 75 65  ine (quote-value
25a0: 20 76 61 6c 75 65 29 0a 3b 3b 20 20 20 28 73 74   value).;;   (st
25b0: 72 69 6e 67 2d 61 70 70 65 6e 64 20 22 5c 22 22  ring-append "\""
25c0: 20 28 72 65 67 65 78 70 2d 72 65 70 6c 61 63 65   (regexp-replace
25d0: 2d 61 6c 6c 20 23 2f 5c 22 7c 5c 5c 2f 20 76 61  -all #/\"|\\/ va
25e0: 6c 75 65 20 22 5c 5c 5c 5c 5c 5c 30 22 29 20 22  lue "\\\\\\0") "
25f0: 5c 22 22 29 29 0a 0a 28 64 65 66 69 6e 65 20 28  \""))..(define (
2600: 71 75 6f 74 65 2d 76 61 6c 75 65 20 76 61 6c 75  quote-value valu
2610: 65 29 0a 20 20 28 73 74 72 69 6e 67 2d 61 70 70  e).  (string-app
2620: 65 6e 64 20 22 5c 22 22 20 28 73 74 72 69 6e 67  end "\"" (string
2630: 2d 73 75 62 73 74 69 74 75 74 65 2a 20 76 61 6c  -substitute* val
2640: 75 65 20 27 28 28 22 5c 5c 5c 22 22 20 2e 20 22  ue '(("\\\"" . "
2650: 5c 5c 5c 22 22 29 20 28 22 5c 5c 5c 5c 22 20 2e  \\\"") ("\\\\" .
2660: 20 22 5c 5c 5c 5c 22 29 29 29 20 22 5c 22 22 29   "\\\\"))) "\"")
2670: 29 0a 0a 28 64 65 66 69 6e 65 20 71 75 6f 74 65  )..(define quote
2680: 2d 69 66 2d 6e 65 65 64 65 64 0a 20 20 28 6c 65  -if-needed.  (le
2690: 74 20 28 28 72 78 20 28 72 65 67 65 78 70 20 22  t ((rx (regexp "
26a0: 5b 5c 5c 5c 22 2c 3b 5c 5c 5c 5c 20 5c 5c 74 5c  [\\\",;\\\\ \\t\
26b0: 5c 6e 5d 22 29 29 29 0a 20 20 20 20 28 6c 61 6d  \n]"))).    (lam
26c0: 62 64 61 20 28 76 61 6c 75 65 29 0a 20 20 20 20  bda (value).    
26d0: 20 20 28 69 66 20 28 73 74 72 69 6e 67 2d 73 65    (if (string-se
26e0: 61 72 63 68 20 72 78 20 76 61 6c 75 65 29 0a 09  arch rx value)..
26f0: 20 20 28 71 75 6f 74 65 2d 76 61 6c 75 65 20 76    (quote-value v
2700: 61 6c 75 65 29 0a 09 20 20 76 61 6c 75 65 29 29  alue)..  value))
2710: 29 29 0a 0a 28 64 65 66 69 6e 65 20 28 6d 61 6b  ))..(define (mak
2720: 65 2d 65 78 70 69 72 65 73 2d 61 74 74 72 20 74  e-expires-attr t
2730: 69 6d 65 29 0a 20 20 28 73 70 72 69 6e 74 66 20  ime).  (sprintf 
2740: 22 45 78 70 69 72 65 73 3d 7e 61 22 0a 09 20 20  "Expires=~a"..  
2750: 20 28 69 66 20 28 6e 75 6d 62 65 72 3f 20 74 69   (if (number? ti
2760: 6d 65 29 0a 09 20 20 20 20 20 20 20 28 66 6d 74  me)..       (fmt
2770: 2d 74 69 6d 65 20 74 69 6d 65 29 0a 09 20 20 20  -time time)..   
2780: 20 20 20 20 74 69 6d 65 29 29 29 0a 0a 3b 3b 3b      time)))..;;;
2790: 3b 20 41 64 64 65 64 20 73 75 70 70 6f 72 74 20  ; Added support 
27a0: 66 75 6e 63 74 69 6f 6e 73 20 66 72 6f 6d 20 6d  functions from m
27b0: 79 20 75 74 69 6c 73 2c 20 73 70 6c 69 74 20 74  y utils, split t
27c0: 68 69 73 20 6f 75 74 0a 0a 28 64 65 66 69 6e 65  his out..(define
27d0: 20 28 73 74 72 69 6e 67 2d 73 65 61 72 63 68 2d   (string-search-
27e0: 61 66 74 65 72 20 72 20 73 20 23 21 6f 70 74 69  after r s #!opti
27f0: 6f 6e 61 6c 20 28 73 74 61 72 74 20 30 29 29 0a  onal (start 0)).
2800: 20 20 28 61 6e 64 2d 6c 65 74 2a 20 28 28 6d 61    (and-let* ((ma
2810: 74 63 68 2d 69 6e 64 69 63 65 73 20 28 73 74 72  tch-indices (str
2820: 69 6e 67 2d 73 65 61 72 63 68 2d 70 6f 73 69 74  ing-search-posit
2830: 69 6f 6e 73 20 72 20 73 20 73 74 61 72 74 29 29  ions r s start))
2840: 0a 09 20 20 20 20 20 28 72 69 67 68 74 2d 6d 61  ..     (right-ma
2850: 74 63 68 20 28 73 65 63 6f 6e 64 20 28 66 69 72  tch (second (fir
2860: 73 74 20 6d 61 74 63 68 2d 69 6e 64 69 63 65 73  st match-indices
2870: 29 29 29 29 0a 20 20 20 20 28 73 75 62 73 74 72  )))).    (substr
2880: 69 6e 67 20 73 20 72 69 67 68 74 2d 6d 61 74 63  ing s right-matc
2890: 68 29 29 29                                      h)))