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[Oly$(,GM޲m8ZCv}ztBJyB7B5{㄄ԭʉt̍OM՛9ʆmhď f ۾bN "lP<ėaaNP%EP|;ϡ22? dyQc>9Ū/%nU d_[Atl|3W7=zK\BNe׊X<9[ Ȁ _Ђqݠ02Zk^{lʶ׭q+eĵ{@){mQlWWJk߸YU(5׾YZYjP`:P*ˏ OŬ]L K) (qFl:fo)ϯ Ê60:6@veůϊp2|(1⏶[{@<9*0 w'Nj[QfGoW7n}@XQM̊7!ʼny@ΕIdOqȳR&u.c8LhElA+lvƔcp :>_RC'p;N"\ao7@ )0tKSd{g\) dSe beFс?&{NGZO"xOm3:d@^A0?OZ'^QhFmL-Iv(JT$ \[!.-ʮL^w fK"P40%)\p幽v~V`L[=4c1|,@ 4`mw8{,h&ہDꍷ!0̃+--n3GE2qe7ɾ7-Z&B2҇ޑK iR̵ݻ*۩13 8 mlH 9~Ev2wXM34ŢڑV YcoX+vk]Ɩe ߳g7V0Dڃ(q$%@:zmVh~1 "|w"1xV'lY3|`'e.譵! f1xjyҭ1Ha҇x3B{sۘS`Hy@>ކ0A(؋qCnHrV; x'\ƒwN.>B;A&\Z4-hC|A'X-70l>(ctg+YH:H6(-^,3%#V JiJW|Y}0N3us"p j7 i8U{upx5Arkf R UWdpxl*>R]s{j,\ L$Ew,6,&ӥ- (.3Ůɜ|[ ~ͭoro.\n37"x CYa kl4\ѽ,KҙA 9 ܹN: 1$\l'k| Zc2U-3ńQ%ZiÙN"cA{DJ}6< 4fb*Y;@x4`gY yo;Gz7'uL) duDz:3B}WS6WmdGq f} OG3P*1۬8 % ,= %ذ2%G[.Ƅ6ێ}ڵ.)NtQ̖h Y?/Js&GuW -Cl9(B'1Du\P?S XT|Zʳ1oUKD `Ds 2?bBDj(4ZF~%ջop&DŽP7+]QU*J =ڙRA-sCMཏqR;Mw܋HQ{6\ NLc}jt0.һ# Y] :lz'iK{|.*b4+M{Ȇ2Fzλ& eŅ"v}3bJL.ȫ|~ג`&ԒbQ$D'h,5aE LrI[v kpwxHo>FdYT ̗LgVW" @0paeELI&LIńxPT*J:*ză̆]PESXॳ 'F2RCv0έ߭&/} ,ͰЋ)G+ V0ejRʩ%@uz< 1E "sCW @蓽ٌ(WXIbK--k \/L.:bNEׄ^edӷ9*ݐŢ)߀B2ghT0?D+4M- n:]PBڭV g$ߕJ,85vA p]P?-\4.g14sm}͆"CMpj Li*9@U=7;kϳ.) YxB+W]} ߧlPQs8֨HɾxzM ՗':'ZE5og־5&㕬\͐3jZQu",/tr'HH2d1`C^jX&s6/e2a8oCJ94  EmaVe†R?zA.XK b˹ܙ4!!}{}0R2M@AqG4S1&P ݁RuL*L9'k),].X 1mҖ%beZ6Fc=\KL3e<͝tьJQ>3Z(B-%)"aLYE2O1f hz1f5T.wЪ--9ޚ& ;f,$wDvdk{EW. kEyxiU$GY8kHm@9C- ۷\0!6Tw4"fySX;Q˨S1}eC.0K+<Hɬ^TK[>}i!7Lǒб:߮NoS̞/rǝ鈕un%Y}O ֫G@ug\1!)od+)[_VsEbr7#t︜bn=|yVf^SA"ڔXMW'@lݷ]2K) uACL NB}.}&ݩ/,=MumjPwXژ\ﯸTWmY+ .u2++j2w@e0ѝ|A!Pr \h\o{UP{4xmhh IPӹB ٙ+YC$r!;XSxn#*2>L3 U.1eHE Q~N0U9T=B,(C7F/!}hJGfD\b h C@d/`0hxO6' {|e*9#Oȴ\| ;Po S?ɕZ-ڂQrU^j%z5ln MACKG(@ݻzXk]1AWi/X~Hf;`lBl@E&~ d;#xR-cZuzI^@CCl F Z[vheamj ah5QNzhZ% k(T`,;(Ы5iu{F