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))
@J;IDATx[Oy3Ԩ80唣4{q{p*E=g%1EzeO[D4c )Rq0;GAtYM*T*)72r~p=ЎmbW=t6@`VT9^ PfEYQ`nPAx dߩ^sq %|7PU@=p nБ (ˋyǛڷT8 .o+ Az_{> 꺋tZ-8EY,ӊ' eJx"PӊڎV橩@ʜJ)w> QK}q3 5dOٗ 6H`PُdX`_VTy&s_*U c(TA>`uT? fjS.ڀKqz4X W9YQǚ|?WTE*Ddpׯ7=HhYr :{+HF\Zϟ l(\/#a0)uBakJ٠X[ P'+4jԒņe<57'7 ixBmRdo2ԤU w X@QK#.Vr%LL zH4F.p$d0 +m+4y,$=' BcSZ *@ҫIK^R^[ \5DklMVX &p[ 8dDs2j/^Axzs"+W="9=7P(YV}l @OZݛ[e'sMO'\S(;*LD)|bezXh7NݨM$~duU^$Tx +aU=rDzA{/56IZuzUhF\h'p`oQj>a|#b?S XE6ߔvalt"=UjceURlA~r9o"ѳ!d,YVmO|w}ןժo{ &T{u2Hq'8:.6vӒHJᒲvN3;*o8=,c]9fB 9Hӧ`ޥ.2>hv'~e4)&JX+wi4[Pi a":jgw2܂~žMTl]Yp-`gqk7Ռ?Y vPxD-5*|ߌaJ7;ZQWW/zPt',nTK.kv#&/u PŶ岠pW2@S,RnȊ셚ʎ6\]o2``U;Ӯ![w_-1 K?y/oTH$C\\9Bk;PoJH<:)S6p2#c$dXه4#weg(T>~鴔r6D7 Ȳw;]Ssvdk*\jQ]m#&H?1,hNWfKGNrNoCC (2Ldl`'Rdko ТHG!=XW`vjc˩_йN/;fC<ҊgC_zd~i#zHk>3NYe8T,zG_):r~{s vּv eL ou~ك9\z@;KY%?>iAҢ+>~Go?n#>m$ N\3,Gq IFĂ[V;z6ZjQlݯnW65ކ7Gdx0`kE`qaf0ƒf$鱜|Rm%X ǰ<~Bq 9)1S (x c8T9 @5uOHj (Z#&@:.cp,e#b;X'L[Cnv؈<qB %%3c2c 6 [` ZD6(,Q2W49dC8P~ 0R<͢L2O\{ r_H#;hEZ%8}5T<]Zڎ ǃh$HH ^jP%_# x{,v|R,jUdGP"R"nÌ ^UA6a F`Y`0C0(_$>NQϏY-Rx诰|WFxV%szFhPlV $6kGho36kU7V,`2S)gE=a#/~nm2C =g9PT .'+bzU QO<#r_:!@T|&h4V~lG`g[(aÁ.[(4Sjm-g" ]`z ~f0YN=s&mxዎOď)WlGjF {J83H6`$SYړ`|b%V9`(i[msJ-fËo s!xɛ+3锭lܥo9c`&Uկ@m6BndFֿ#JEtT(+K-U-&S)*Wk5`%qEڋ"@8W5!DB5Jm2iR,l V7ql2ju*F5RTmn&h P_b){9fn6bXeOtV}('{ZB\ua`hgii^?ɈBf;?+:mNgVf{ԫ@--èӓL2au-GBrP\y/nt2U.xC)=.JY:5#Xaƚ6{IxGI14)޷l>˗C [2HR_Eef- V >~U##jkli'"QLb !FXP81k^*tKA 0o!@l6,7}Lٿ'pŹ>JmiYq-ɳH"ciX^1fLNj+T _VfKT0Š|`.TV0+ ²]Rȯa-%,GwRK6\d(Lʷ>Paַ]2|}Opo{e\A׆o$_w_Q+lߩj,`8Rx|ц/$u-Rι#y*PD r"x5D{_+s*YhwbQp{F1X,SEFO9 FRXF[۽݅ˌŧ?s'Ov`x- QPENl6]2L+!t,.F[&]30*O繖R,luxa2EYb˄RGl*bN?fqX rҶFe![@R? $ XEq/%&P_bU@)?Db.m|[;&5jIt.z/-x^ɔ e!1oeXxBnh'Fb[ͲЈ( HVEJ9GtI5tk,(j6O`@9ENi\5Hr@g=9 %hJnڀ+Pe,-AnDqSS>% +-t 8G">2^w*Zj` Pר4>CZ"*~~;zTuu|Q:uܩqƧP/rjU,KiRlc00iY5S O#O~x( IڋzObބ-ϊRE75lL k`:@^XI&m^lm9?i$w]ױ/=:Hj0a`q^\jjF]{۝- +,[|Vg԰W^ 9rL3\pJޚ9l@;];Gɛ:H; :᪐obiE/`QxVG]F$n_DԀ-j=ap&irR...^`҄Q[мiAaVlӾPX On(" Zەmɞ)me˟l3-V)CnP+5>/k2OsC1c]58crQ_K3Q0<x4`L5-Qhqrנ)Tir{KѪ{K۲YvsμTJ}/bۡ; jsRq bWTmg̾nԸRg `ސ,"鉘@.~ ChMPlv)>}'yuPβx7,1wv;(~ٯBΦz\ cS3+dvL_b#K .~2e:Sq>isg7l-7YxD o1eE~h.䟦fLA/4^<{P:r-FUXPƝnc ,݁7Pjy.B +Oscͨ ٌqٚX5qp~4 ֹ@xF)d8:9j@&?CFiͳ,vOTZ΢lt;^GݗEK>p8r&$H/;a"eҊE]7+&q*