#lang scheme/base
(require scheme/match
web-server/http
xml/xml
"base.ss"
"cookie.ss")
(define idcheck-cookie-domain (make-parameter #f))
(define (get-idcheck-cookie-domain)
(let ([cookie-domain (idcheck-cookie-domain)])
(if cookie-domain
cookie-domain
(raise-exn:idcheck
#<<ENDSTR
The idcheck-cookie-domain parameter has not been set.
Initialize the parameter with a call to parameterize as follows:
(parameterize ([idcheck-cookie-domain ".untyped.com"])
)
ENDSTR
))))
(define (preregistration-key? key)
(and (regexp-match #px"R[0-9]{31}" key) #t))
(define (registered-key? key)
(and (regexp-match #px"[0-9]{32}" key) #t))
(define (headers-cookies headers)
(let ([cookies (assoc-value/default 'cookie headers #"")])
(if (bytes? cookies)
(bytes->string/utf-8 cookies)
cookies)))
(define (headers-keys headers)
(let* ([cookies (headers-cookies headers)]
[prereg-key (get-cookie/single "idcheck.request" cookies)]
[reg-key (get-cookie/single "idcheck" cookies)])
(values prereg-key reg-key)))
(define (headers-registered-key headers)
(let-values ([(prereg-key reg-key) (headers-keys headers)])
reg-key))
(define (headers-preregistered-key headers)
(let-values ([(prereg-key reg-key) (headers-keys headers)])
prereg-key))
(define (unregistered? headers)
(let-values (((prereg reg) (headers-keys headers)))
(and (or (not prereg) (preregistration-key? prereg))
(not reg))))
(define (unvalidated? headers)
(let-values (((prereg reg) (headers-keys headers)))
(and prereg (registered-key? prereg) (not reg))))
(define (validated? headers)
(let-values (((prereg reg) (headers-keys headers)))
reg))
(define status-regexp
(regexp "^HTTP/([0-9]+)\\.([0-9]+) +([1-5][0-9][0-9]) +(.*)"))
(define (successful? status)
(let ((code (status-code status)))
(and (>= code 200) (<= code 299))))
(define-struct status (major-version minor-version code reason) #:transparent #:mutable)
(define (parse-status string)
(match (regexp-match status-regexp string)
[(list whole major minor status reason)
(make-status
(string->number major)
(string->number minor)
(string->number status)
reason)]
[_ (raise-exn:idcheck
(format "Invalid status line: ~a" string))]))
(define (my-redirect-to url headers)
(make-response/full
302
"Moved temporarily"
(current-seconds)
#"text/html"
(cons (make-header #"Location" (string->bytes/utf-8 url))
(map (lambda (kvp)
(make-header (string->bytes/utf-8 (symbol->string (car kvp)))
(string->bytes/utf-8 (cdr kvp))))
headers))
(list (xexpr->string
`(html (head (meta ((http-equiv "refresh") (url ,url)))
(title "Redirect to " ,url))
(body (p "Redirecting to " (a ([href ,url]) ,url))))))))
(define idcheck-cookie-name "idcheck.request")
(define private-cookie-name "idcheck")
(define (set-idcheck-cookie value)
(cookie:add-path
(cookie:add-expires
(cookie:add-domain
(set-cookie idcheck-cookie-name value)
(get-idcheck-cookie-domain))
(+ (current-seconds) 480))
"/"))
(define (clear-idcheck-cookie)
(cookie:add-path
(cookie:add-expires
(cookie:add-domain
(set-cookie idcheck-cookie-name "null")
(get-idcheck-cookie-domain))
0)
"/"))
(define (set-private-cookie value)
(cookie:add-path
(set-cookie private-cookie-name value)
"/"))
(define (clear-private-cookie)
(cookie:add-path
(cookie:add-expires
(set-cookie private-cookie-name "null")
0)
"/"))
(provide idcheck-cookie-domain
preregistration-key?
registered-key?
unregistered?
unvalidated?
validated?
successful?
headers-cookies
headers-registered-key
headers-preregistered-key
my-redirect-to
parse-status
(struct-out status)
set-idcheck-cookie
clear-idcheck-cookie
set-private-cookie
clear-private-cookie)