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))
@J4IDATxO}9K:^ԋ >g[nL Ea"j43>U5"\o /GqݢAEb;EҢYٚ#9OCpߟ9«|E Tv@c/@d`V;յYQ]u8ԪoҊys,n]Os z+",Ԅ-fUݢp'Snߒ 23leydbkۿ9O+2ʘ b9S,3%W 3Uo2JӊjՑͨI|{6t>P*Lξ/ROhqͳ}g.ˊXV"}/oДIIyr`D9U`?tW}]Y9k[1{6'PTUcj{"Eo[̓"mH(.LgL)@>.{/YfBч+ޕKY/sy?Wޣ-2IuDS:{"ڞhE.ף;=: ˬbyVa/w{ fٓl%V&Yդ.'}$`D.PSוbCkRE `N{Ń[91{-*-2"'YEM⍟VLNMImxM)Ƭ@lۘbefw<{yb+ٵ2+phT'v\_?HϪb2tzGvrB|tܾ,kbI`x7TR753bz4O M21@TLt*ԋJL *sDb|4 3ΤsB˲pؗXkś/W=d۩kބMxnV.3;9 UΛĊ`SД;iV}B&a+v'xb0_V2j2 yklUeAN㙜c_L`˘^Ҝ)Iklzٙ 6 ν{d9 6 _`E !76(6 zYY.ݠnݭ6fqx "ouvo KAi%݅ڜAu8U˻ڐoxs`9r)^ŏF.K{GKS3܉]doS4[k'UwX T<\焘ihlE=4Ѵ1&VZ0'"gygte5r5Llߥ{c :\o@JzZ{&>t}\sǠf7Ƨr[o" -rU8غ4$7?놊x*oWΖO/nuюFQ4Й:cG!Kt'o;~\C67PgL,カ,C_滽ٔ{C IĬ?_szcmB/_M)gxN5\~ߞENNGBNtq% W" L$Sk}p@Sh 1Sk?X 0 -!{hu@( ~@@6QYLml}'T :]8MmaPe"hY*\r&|O"$15].YrfcA1"ý>ad1R=~+U} /˾l~չ{3bZ? JWxًoPKmScm_ {18VZ[_p,h кF)Ї3WdOpuh],0Å,El.B.t^}a-5 :t:3ȷƯҳ 2hq}Ư:Vt埣k0{߽_nt27:lt!,|g~[9 L &b8<3&dc3aqg gE>9o<;9f2B6kQ01U=&al (kt,Jcvϙ5kİ#cAtذ]t,@j7FSBiQƨi9@GQp3lǯwFVQ@O5E6Q*5F:&cRaԊqͨtay7ţ#Q(re$1%Fi>y*KnÓʄ##f<gid|GV{kAbvr8;dcp+!S{=M[Cꈜi  P 'H``U2Izlhn1(d A doŐlۯ: ߤҖ̐Y~ٗbk76=脲TPty : +Y`]uT0d!Ep=x ŤZQGqX>\잂@dEU]pC]o_DNYm^R'Xj4+M`m܇׷MAOlD~̞[c6łMh5 Q#τ98 }T8 Q#]Űc{UwnhG>?[.͗@6F e:W,=($0=o5{D.q>7`/F{Bk_E\63߷܀[oT_Eyf9+V_:eApIP47̥/1?f{`$B$;kvzbma٪mGm{Hb a*-ly_uk틬? ,3l6i@l^)y"[`oykNW^ x+ h+_ OqŲ|2nWV#-:{L/ÝTyܟlOn<<nc0{m"oq3ccv:R Ž ~IЉc[?ٙ"?@#ȭ&v2{om/3)Z=Q){Dж:A]x2+nOwgåCma|DzM\Kt}~ JķY%.i+f0Tk,Dw/s66yO蒹U1n4EKy"i:H1h07$EY|SˏJfGCvDڼ^l>Lv4 s|'ܐN[Ԥ֌&~-mǁ Tqrtaۮ/J.T(Bh^r?|M]1Et/$GY t *Xr{k䣗xןr &YBe>BCeqXzK"AyKT% 6U{-HT4^:F .{bS1=llͶqSm;1 @Yۀi8zǣw~'4eGguA|3|C˞Dы$~_U^c\=Ql=*|J00p8iƦ$]"|`/LAc@_ ]9})`~D]l "}2]>4 tWZ-)g䊵#dDmcO1zB޵ V-n;R(3cOKV5Nꦈ cm)V"O+&O6p[)WS9̑7r$f:#~T5!l<m@lM{h{8: *N1csQ41́lY;< D8f![ת, T pz1 #pb;Dꪵ#3X r8n-8m棄UJ[5F0ЏoJctlZ1 Cu(n0p]ܐa@1&Vs}yehoC,: W9̄*=,f"F\Nu>D^$j99%h8šyld_b/_|͉>Sd3#!!X>&0p4^&5Pr=Qj&R#2[kǠá,T{ n"O< m;#S5KjŸn~6)e4'9*; VP>+F:$DPUGAk5n?/LF:[sܯbCahF֓/@ W'O7Xy H@1,p=s. "7Ƚ^/.zZ l>_*$ Rp#Qߏڻq %TJ:j%EDT] ͣn %P)5c@IM+&JKq~ &X} $kԯ|L/yBmIb*<l+O2= j\?IENDB`