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[ouQ(/-)`QP6HU<J#Rs @p%~PVtygQo ";U 0`TE"hS{+۔ܞ{g'rv S5=?s/ U:)w x1p<# PgE߀c:q@xNT9](>XDz!-V:qd3JcXQq' LnAתTZVĊ^O xi6U ?`LhE/V,0)KMͲI2f) Kg̊5JT&T<'r~Ǔ)rb"+ƣ;`2/= 63]+MJ $Vs*Ug+j| &]YCM òe]xqJzXЊP,N@ ,~@+?88LRp $/Z\RugɫUeIWȱeR5E'GvC o"k@o> `.yE&@U9xHa>9:@D _nQGrhVL@!fGX*^*`ʑ%/R7r_#SVqdZ*P/҂[+ eJlL |Y|~~v֐@iΑW|?RTUGbUJ(uM_; bɔ,[`ç3Ix*OHpvxYa{`|/0 KêQ#QKF_k)kOPa2yqKs7ZRu:+u’TJIlT=֔1Ҷ `|J4-5%dvGKS8E1B}.6G m{")kFc7SbD \χ)fhUO;Z1ӄ}c տ`,k I(3ԾBݺ |3[׷@Ֆ#kSNJY#`,9V8f& 0`͢v3^w r Z>@%QVȞ ۹{/6_ʯO+tNފ3lq;b#bw^jv0c^TBkr'GGcFp|g>3M gnnGf:4vo\MGc\qF AGL>'GRB (!Us4퍚% 5md m rWDa곗AY>Csh:j;eH7GʌZ}A$S#xrChQ[=>3G|A iW<[~> #2-"]hQQ\yFaJ0Ѣ++(3<vB]){}v@ aDi@z.@r7rδAN cj(UZ73 &-C7?"8I.lXM)>LNUZ1*ey١_鱚fKpYL3`8ou`P0Ārҥܿ;I4tވ@SS~]} ?\̽VbMco{Pbʟ)Z h|$`E$nH^7|t^dmi1YMTl̇Ԩ`;&>ܽh.GaPlT=? }5B6i1*%}Og^ v!&pVd-\?G#UjoeO<*ʽ̄x'iVJ{"9Y m}HȩDkeXҞKW8DqJ\֑F;J2ՠl'q)qYWZ"_Y\0pfⓇz婘RZG\ylȅasU I1YM5,fC-ea^CiẔG-D5 B+zonu 3)b@.o@OLY TN籵VL#6!VRqe*66wq?H\4>-qD̆4Q]&'f}A4x|ٹgߊ>`Uv2M"~ziz/^h \+ b#}LSZo+QrRHb${_Ÿ%//$bv4?X s-aq/Zn%FkCN=f.y,KarTu[1Y $\BrYݎmb$Vw֝2y(`(đ56'-Gر,]>+6YcmZNCU1F4b7ـ) Ɏ5. S#yq۽ِi~:%sP4tYW%3v@LG6??X^~4MvːPe^xHR »I$xmp,U< l#]3}$;ϝil}nC%Nŝunom.3RBTU.[f7y \1RL(eL.%l83;^~w%/<*z=>@d$?O{~̽նW ȉ<CJ[X܍|vΙJ!msT@ 4Ӌ%j/8x4g^7ou;/$ZGfJ.nt+@+V.\z ~mWqHPk*Dv^ =@mIp̒;u->=MGAh8@]osRҥz5̘8ϼ~?eg8/mXlLAvðOa <,Z7Z &q7LEP*lQ5g e@Tb F w{ BJ-#*C'ӛ jZ g u1`~y^YJܐ3jB/h=Xeu]Lö`S[* gdgXE:לۘNDw]!:Ѝ|{ϰ7Q!CI`DXq1OzzXem/b` 0f(tVF\'XoRbR^QhqRpćnM47IdTYJ 4+Ho=X0 y -&F 7{%Ӊ4ӓ$J_) cɦ,\GG>9*?D4oa$ߗr4 V3;;4aLl(WKhL`GR_X<>k n*DW"|5C:Q% 4AN` 0b/tlLFFzJwHp3p1dQBؠ,۞3GuD70  ZTTJgR>Wnw[W)ois>K QG*eJE3U-·HL&a>(r=o}>LUB5e)g8S[D17t1VՋO&c@e*Vܩ}WW)ֹudA L;`~u+?+Fdɔk'nȓzwZNq?D7~br4wc͝DcuYx*6 @)*HY>@^Ϻq2-!mҧ ivF%YbT=> 9x[؋3yTH& Yj}T `%wG/jQZդgeLF(jGfXSeדsFA$APMޯ@N~`ϰoc. #a5E8_q!L|IO<, .=2l'Xjyx_%=E es-ZޞmPFƼO%2Gd҂/أ ^\CF7Lק`xlĝU\3аlϾdx/:@RZopOm#̚>٪-/LN[blF(eD^@ԿgۈE/ZYI54,)5d_T\ Yn7 XYf]Pq &4Dl|v /1+dUL?=sj>VBsKDNu]N@69 Vjὴdw2),+D|%,lݻ5?` 0Z$y)dzk^9õrF'[;@Vij [hAhEO΃L4nbDnȵuifv6T?p@d, o\LׄQu+dKAfYEχ,ߛ'1Y,r-xԦsdcoF??މI%kԙ!B++kF2#~'ܸ1=~,0*^YS>ʒxS7PM,?fKSAq&OcYuN4>ztL>^C&}7;QIENDB`