PNG  IHDR!@ PLTE>O`jqv 7'tEXtPage
cookie.scm - metalympiada
git clone git://metalympiada.org/
Log | Files | README | LICENSE

cookie.scm (3693B)


   1 ;;; guile-webutils -- Web application utilities for Guile
   2 ;;; Copyright © 2016  Christopher Allan Webber <cwebber@dustycloud.org>
   3 (define-module (cookie)
   4   #:export (set-cookie delete-cookie))
   5 (use-modules (srfi srfi-1)
   6              (srfi srfi-19)
   7              (srfi srfi-26)
   8              (ice-9 control)
   9              (ice-9 match)
  10              (web http))
  11 
  12 (define cookie-val-char-set
  13   (char-set-difference (char-set-delete char-set:ascii #\, #\;)
  14                        char-set:iso-control))
  15 
  16 (define cookie-name-char-set
  17   (char-set-delete cookie-val-char-set #\=))
  18 
  19 (define (parse-cookie cookie-text)
  20   (let ((parts (string-split cookie-text #\;)))
  21     (define (split-cookie-pair cookie-pair)
  22       (let* ((trimmed (string-trim cookie-pair))
  23              (delim (string-index trimmed #\=))
  24              (attrib (if delim
  25                          (substring trimmed 0 delim)
  26                          trimmed))
  27              (val (if delim
  28                       (substring trimmed (+ delim 1))
  29                       #t)))
  30         (cons attrib val)))
  31     (map split-cookie-pair parts)))
  32 
  33 (define (date->http-date-string date)
  34   (call-with-output-string (cut (@@ (web http) write-date) date <>)))
  35 
  36 (define (write-cookie cookie-alist port)
  37   (let ((cookie-str
  38          (string-join 
  39           (map (match-lambda
  40                  ((name . (? string? val))
  41                   (string-append name "=" val))
  42                  ((name . (? date? val))
  43                   (string-append name "=" (date->http-date-string val)))
  44                  ((name . #t)
  45                   name))
  46                cookie-alist)
  47           "; ")))
  48     (display cookie-str port)))
  49 
  50 (define (valid-cookie-name? str)
  51   (and (string? str)
  52        (string-every cookie-name-char-set str)))
  53 
  54 (define (valid-cookie-val? str)
  55   (or (eq? str #t)
  56       (and (string? str)
  57            (string-every cookie-val-char-set str))
  58       (date? str)))
  59 
  60 (define (validate-cookie cookie-alist)
  61   (match cookie-alist
  62     ((((? valid-cookie-name? name) . (or #t (? valid-cookie-val? _))) ...)
  63      #t)
  64     (_ #f)))
  65 
  66 (declare-header! "Cookie"
  67                  parse-cookie validate-cookie write-cookie)
  68 
  69 (define (parse-set-cookie str)
  70   (match (parse-cookie str)
  71     (((name . val) attrs ...)
  72      (list name val attrs))))
  73 
  74 (define (validate-set-cookie obj)
  75   (match obj
  76     ((name val (attrs ...))
  77      (validate-cookie
  78       (cons (cons name val)
  79             attrs)))
  80     (_ #f)))
  81 
  82 (define (write-set-cookie obj port)
  83   (match obj
  84     ((name val (attrs ...))
  85      (write-cookie
  86       (cons (cons name val)
  87             attrs)
  88       port))))
  89 
  90 (declare-header! "Set-Cookie"
  91                  parse-set-cookie validate-set-cookie write-set-cookie
  92                  #:multiple? #t)
  93 
  94 (define* (set-cookie name #:optional (val "")
  95                      #:key expires max-age domain
  96                      path secure http-only
  97                      (extensions '())) 
  98   (define (maybe-append name val)
  99     (lambda (prev)
 100       (if val
 101           (cons (cons name val)
 102                 prev)
 103           prev)))
 104   (define basic-prop-alist
 105     ((compose
 106       (maybe-append "Expires" expires)
 107       (maybe-append "Max-Age" max-age)
 108       (maybe-append "Domain" domain)
 109       (maybe-append "Path" path)
 110       (maybe-append "Secure" secure)
 111       (maybe-append "HttpOnly" http-only))
 112      '()))
 113   (define prop-alist
 114     (append basic-prop-alist
 115             extensions))
 116   (cons 'set-cookie (list name val prop-alist)))
 117 
 118 (define %the-epoch
 119   (time-monotonic->date (make-time 'time-monotonic 0 0) 0))
 120 
 121 (define (delete-cookie name)
 122   (set-cookie name
 123               #:expires %the-epoch
 124               #:path "/"
 125               #:secure #t
 126               #:http-only #t))
@JIDATx[]u$wf+c.%v X(gve&t4i<mU 옛Yy;syhfrHMIHF,q ɹ=g'-wFܝ3;߹璐?/^D2;0g`V;Et0+; YlȊšk0 6-Ċ̡z#]&0% NXRef#V WX?-YV}5Y;Eׅg0X 2^_}Z Y(:7YڧnJg}E)/h"ۧ H"jTo}CKi㙵?6aXL,ZroÝ aN쫾ɐG:rVdZQ /'5̉>²Ȗ/+f-C 6_w)({Ӫ59w"Uفp޻SrA @>9{wB4\YW1F+ B% ꫌_~եriVd촹zMv;(EDH<+g푙/1$%<[al*rm.1|q]|~N^ﹾyRkQ;DWجi9Tlgyj!UcFidC@iI> E$eQt(. 'KxB#=Zj-=Q: HUwW{d|3l M,E$:MY,-OnÙb(:Ѹ3mr͌zߐmy-&\&O ߱>{'gcؘ gM`{ق"Ғ3L.zqgBR#Iݻ2dL h1g39cqju`?/YQ` E[x3L KF3XtPϐ /N.CdX3[0{Ef;OHEǢt:)@9VvbEol`Ob;ƍaa-*, 7IXqmJ,ݭ8p.]'$D;@A eW YhV=|[0P#R%z3aT*~ݭ$6M_N|8`2tǿ1Lt. Kvs;9{*d7^ށ漕6.J%<}OzEB`#Eydm"wS{yXsT^ [)oEH{i`¯=OBV`;aFDd=|ZV,Y&.  .{M;w󏦄Dz\>ɫ@,l^.gBbmd߬l&[JxbQ],ZP[R'`^Pjo bZxv3X5 !K gIΓ9{,؍B\St  HwrJ+CJ2Ba6 _{dV%-A#N 6$7˯$T*FS ߁?.B4:`)5NM ܃ p[@x\zF JP'V-{$-!\ѹ\]]'# MKF V?k3Ae.% [ &oVqVCl,o'_8mb3G %?8/ 8QT=m>0bUwxZ\T>Nm/m^\u[7o{@-܃rvv{\ن~YyM6U0XnMR7y@X+l89Kcb1w0d'81.;d51q8 8 9438_V|} PZ0/Z,V&Hx֓(<=Rbyst}RAzJX#?`CaF5 S7$ȌrK: '[#ԇm(͎xjF2RGDgwXfVMKҸ<@2 `Xr!;&Qo Z)FU>&whU^`g_G<뺗Jc$^@C}x\E3Z'׬tʯ!6D6>7;}lN9ZrL4e24@c(w'g [Gߋd4 ym޿խ~'%P#{0ܹy3A]/^wrLo:nzM5X?fiiЏ ѭ?kWAX}֟nd*0@Uie["熸k>//(@b>'<:J~HJ5A&|EQ,xlxQ9_$}RRava$:J}uw, KH6W5FAM`6$8Ս߽|ǎ d.h{TlKR7$y`t.!r@,TBi6 (=v!c23'58yWw6͎JT=/e{e1vOPluY:$c- FasuZu"esL%[KM6G"GlY[qIp GMX kn͉d,KTBWQoQc $wD曹U"V}>Sr3imu"\쏞c}q*C5Ue)d!֘U7 D&t(oJv^u~03ڬ!=w7XG Fz+Hk} -hK;jN6AYw*-ܴ$P^DjgZD-LDC@pGnE+R2jG~xIwʩp5E՝旱r i"8Nrߑ_$ Qs?Zy o2ipì8[]7M#PMV[3 w&Zt1[Ӻ]ȏ٭A5Cb5y4mV{a:I *uхȏ*a_rY pqHJ.\zՑ"ӳdS3DnHVs,p'n+(" \1m+xu!&ĴX/ Fŷƫ 5jg&mNKf!)AT0,F.yW-}I=wckrU^,ͯLȔR'l\m`.Drr8Lo]7$[re~Ni7넍iˮzJ r׽ooƯs ka/rEp6$M9{ֲl-s>O6۹"GXm7 ʡ Øj38Uw~a6I hs3We+I-$ꈊSAOhj%JA[Uqaɹ9zk_-h%}A]0el*鈾VŊOδ2Ў %h8:ʮqg3IZ BtR) Ap=AwY| a5Φ43g@*5 pq"*b>JOBi[RxE*2(i"#b*d kc[=P]$QC!AK77E7h]P5tpKi!ƭoI!t*ng-2 31IM= :;nMU×juR*UWA _:vPԨ}c:] I^]IbҢȠqC ixƴ_-õ*eݵI8_`7xf;3|q@ hF((U}g:حyw|f`z *Aɫ O-r \}NjZ@!?ZqXًCEK Pum<_JK/& A:=ojJ"m`iz:7@$6Z?HH~&ޒ+~ lPEl2< Dh]鬀Ba>] EJffԫnp;$r 7]N։w({j/v䤻>x1@"9\CVD6 :WXhWk *-Ǧã۸k3@k<`$3$b =!kd#W͞SNB/?XdTg ^C6 sSPY*%S6pY0s;ͻ "4." STsq ^ `[!@ ɷXeC##YS_Cq nf6AW*mV t~6i"4S4\b3) dа h VbLy-)\aFxw%6 G`pV 8\Uuuŵp6a 0ebg2M.@,8Q+?`PggVa#,\,E_ P4@GStPF#u x1S)@k.mGJxht%R>v׻B4!\rm" 63}^A>C4"'a|bD'$_^L\ˏŗm^B-%/Q&[> +p.(P@ ?TJ(ju]ACIENDB`