diff --git a/collects/net/base64-sig.ss b/collects/net/base64-sig.ss index 242f953fca..a56c2888fc 100644 --- a/collects/net/base64-sig.ss +++ b/collects/net/base64-sig.ss @@ -4,4 +4,3 @@ base64-decode-stream base64-encode base64-decode) - diff --git a/collects/net/base64-unit.ss b/collects/net/base64-unit.ss index 730b9a0648..e84e0010f9 100644 --- a/collects/net/base64-unit.ss +++ b/collects/net/base64-unit.ss @@ -4,137 +4,131 @@ (import) (export base64^) - (define base64-digit (make-vector 256)) - (let loop ([n 0]) - (unless (= n 256) - (cond - [(<= (char->integer #\A) n (char->integer #\Z)) - (vector-set! base64-digit n (- n (char->integer #\A)))] - [(<= (char->integer #\a) n (char->integer #\z)) - (vector-set! base64-digit n (+ 26 (- n (char->integer #\a))))] - [(<= (char->integer #\0) n (char->integer #\9)) - (vector-set! base64-digit n (+ 52 (- n (char->integer #\0))))] - [(= (char->integer #\+) n) - (vector-set! base64-digit n 62)] - [(= (char->integer #\/) n) - (vector-set! base64-digit n 63)] - [else - (vector-set! base64-digit n #f)]) - (loop (add1 n)))) + (define base64-digit (make-vector 256)) + (let loop ([n 0]) + (unless (= n 256) + (cond [(<= (char->integer #\A) n (char->integer #\Z)) + (vector-set! base64-digit n (- n (char->integer #\A)))] + [(<= (char->integer #\a) n (char->integer #\z)) + (vector-set! base64-digit n (+ 26 (- n (char->integer #\a))))] + [(<= (char->integer #\0) n (char->integer #\9)) + (vector-set! base64-digit n (+ 52 (- n (char->integer #\0))))] + [(= (char->integer #\+) n) + (vector-set! base64-digit n 62)] + [(= (char->integer #\/) n) + (vector-set! base64-digit n 63)] + [else + (vector-set! base64-digit n #f)]) + (loop (add1 n)))) - (define digit-base64 (make-vector 64)) - (define (each-char s e pos) - (let loop ([i (char->integer s)][pos pos]) - (unless (> i (char->integer e)) - (vector-set! digit-base64 pos i) - (loop (add1 i) (add1 pos))))) - (each-char #\A #\Z 0) - (each-char #\a #\z 26) - (each-char #\0 #\9 52) - (each-char #\+ #\+ 62) - (each-char #\/ #\/ 63) - - (define (base64-filename-safe) - (vector-set! base64-digit (char->integer #\-) 62) - (vector-set! base64-digit (char->integer #\_) 63) - (each-char #\- #\- 62) - (each-char #\_ #\_ 63)) + (define digit-base64 (make-vector 64)) + (define (each-char s e pos) + (let loop ([i (char->integer s)][pos pos]) + (unless (> i (char->integer e)) + (vector-set! digit-base64 pos i) + (loop (add1 i) (add1 pos))))) + (each-char #\A #\Z 0) + (each-char #\a #\z 26) + (each-char #\0 #\9 52) + (each-char #\+ #\+ 62) + (each-char #\/ #\/ 63) - (define (base64-decode-stream in out) - (let loop ([waiting 0][waiting-bits 0]) - (if (>= waiting-bits 8) - (begin - (write-byte (arithmetic-shift waiting (- 8 waiting-bits)) - out) - (let ([waiting-bits (- waiting-bits 8)]) - (loop (bitwise-and waiting (sub1 (arithmetic-shift 1 waiting-bits))) - waiting-bits))) - (let* ([c0 (read-byte in)] - [c (if (eof-object? c0) (char->integer #\=) c0)] - [v (vector-ref base64-digit c)]) - (cond - [v (loop (+ (arithmetic-shift waiting 6) v) - (+ waiting-bits 6))] - [(eq? c (char->integer #\=)) (void)] ; done - [else (loop waiting waiting-bits)]))))) + (define (base64-filename-safe) + (vector-set! base64-digit (char->integer #\-) 62) + (vector-set! base64-digit (char->integer #\_) 63) + (each-char #\- #\- 62) + (each-char #\_ #\_ 63)) + (define (base64-decode-stream in out) + (let loop ([waiting 0][waiting-bits 0]) + (if (>= waiting-bits 8) + (begin + (write-byte (arithmetic-shift waiting (- 8 waiting-bits)) out) + (let ([waiting-bits (- waiting-bits 8)]) + (loop (bitwise-and waiting (sub1 (arithmetic-shift 1 waiting-bits))) + waiting-bits))) + (let* ([c0 (read-byte in)] + [c (if (eof-object? c0) (char->integer #\=) c0)] + [v (vector-ref base64-digit c)]) + (cond [v (loop (+ (arithmetic-shift waiting 6) v) + (+ waiting-bits 6))] + [(eq? c (char->integer #\=)) (void)] ; done + [else (loop waiting waiting-bits)]))))) - (define base64-encode-stream - (case-lambda - [(in out) (base64-encode-stream in out #"\n")] - [(in out linesep) - ;; Process input 3 characters at a time, because 18 bits - ;; is divisible by both 6 and 8, and 72 (the line length) - ;; is divisible by 3. - (let ([three (make-bytes 3)] - [outc (lambda (n) - (write-byte (vector-ref digit-base64 n) out))] - [done (lambda (fill) - (let loop ([fill fill]) - (unless (zero? fill) - (write-byte (char->integer #\=) out) - (loop (sub1 fill)))) - (display linesep out))]) - (let loop ([pos 0]) - (if (= pos 72) - ; Insert newline - (begin - (display linesep out) - (loop 0)) - ;; Next group of 3 - (let ([n (read-bytes-avail! three in)]) - (cond - [(eof-object? n) - (unless (= pos 0) - (done 0))] - [(= n 3) - ;; Easy case: - (let ([a (bytes-ref three 0)] - [b (bytes-ref three 1)] - [c (bytes-ref three 2)]) - (outc (arithmetic-shift a -2)) - (outc (+ (bitwise-and #x3f (arithmetic-shift a 4)) - (arithmetic-shift b -4))) - (outc (+ (bitwise-and #x3f (arithmetic-shift b 2)) - (arithmetic-shift c -6))) - (outc (bitwise-and #x3f c)) - (loop (+ pos 4)))] - [else - ;; Hard case: n is 1 or 2 - (let ([a (bytes-ref three 0)]) - (outc (arithmetic-shift a -2)) - (let* ([next (if (= n 2) - (bytes-ref three 1) - (read-byte in))] - [b (if (eof-object? next) - 0 - next)]) - (outc (+ (bitwise-and #x3f (arithmetic-shift a 4)) - (arithmetic-shift b -4))) - (if (eof-object? next) - (done 2) - ;; More to go - (let* ([next (read-byte in)] - [c (if (eof-object? next) - 0 - next)]) - (outc (+ (bitwise-and #x3f (arithmetic-shift b 2)) - (arithmetic-shift c -6))) - (if (eof-object? next) - (done 1) - ;; Finish c, loop - (begin - (outc (bitwise-and #x3f c)) - (loop (+ pos 4))))))))])))))])) + (define base64-encode-stream + (case-lambda + [(in out) (base64-encode-stream in out #"\n")] + [(in out linesep) + ;; Process input 3 characters at a time, because 18 bits + ;; is divisible by both 6 and 8, and 72 (the line length) + ;; is divisible by 3. + (let ([three (make-bytes 3)] + [outc (lambda (n) + (write-byte (vector-ref digit-base64 n) out))] + [done (lambda (fill) + (let loop ([fill fill]) + (unless (zero? fill) + (write-byte (char->integer #\=) out) + (loop (sub1 fill)))) + (display linesep out))]) + (let loop ([pos 0]) + (if (= pos 72) + ;; Insert newline + (begin + (display linesep out) + (loop 0)) + ;; Next group of 3 + (let ([n (read-bytes-avail! three in)]) + (cond + [(eof-object? n) + (unless (= pos 0) (done 0))] + [(= n 3) + ;; Easy case: + (let ([a (bytes-ref three 0)] + [b (bytes-ref three 1)] + [c (bytes-ref three 2)]) + (outc (arithmetic-shift a -2)) + (outc (+ (bitwise-and #x3f (arithmetic-shift a 4)) + (arithmetic-shift b -4))) + (outc (+ (bitwise-and #x3f (arithmetic-shift b 2)) + (arithmetic-shift c -6))) + (outc (bitwise-and #x3f c)) + (loop (+ pos 4)))] + [else + ;; Hard case: n is 1 or 2 + (let ([a (bytes-ref three 0)]) + (outc (arithmetic-shift a -2)) + (let* ([next (if (= n 2) + (bytes-ref three 1) + (read-byte in))] + [b (if (eof-object? next) + 0 + next)]) + (outc (+ (bitwise-and #x3f (arithmetic-shift a 4)) + (arithmetic-shift b -4))) + (if (eof-object? next) + (done 2) + ;; More to go + (let* ([next (read-byte in)] + [c (if (eof-object? next) + 0 + next)]) + (outc (+ (bitwise-and #x3f (arithmetic-shift b 2)) + (arithmetic-shift c -6))) + (if (eof-object? next) + (done 1) + ;; Finish c, loop + (begin + (outc (bitwise-and #x3f c)) + (loop (+ pos 4))))))))])))))])) - (define (base64-decode src) - (let ([s (open-output-bytes)]) - (base64-decode-stream (open-input-bytes src) s) - (get-output-bytes s))) + (define (base64-decode src) + (let ([s (open-output-bytes)]) + (base64-decode-stream (open-input-bytes src) s) + (get-output-bytes s))) - (define (base64-encode src) - (let ([s (open-output-bytes)]) - (base64-encode-stream (open-input-bytes src) s - (bytes 13 10)) - (get-output-bytes s)))) + (define (base64-encode src) + (let ([s (open-output-bytes)]) + (base64-encode-stream (open-input-bytes src) s (bytes 13 10)) + (get-output-bytes s)))) diff --git a/collects/net/cgi-sig.ss b/collects/net/cgi-sig.ss index 61c95284c0..9f979dd467 100644 --- a/collects/net/cgi-sig.ss +++ b/collects/net/cgi-sig.ss @@ -3,7 +3,7 @@ (struct cgi-error ()) (struct incomplete-%-suffix (chars)) (struct invalid-%-suffix (char)) - + ;; -- cgi methods -- get-bindings get-bindings/post @@ -15,9 +15,8 @@ extract-bindings extract-binding/single get-cgi-method - + ;; -- general HTML utilities -- string->html generate-link-text ) - diff --git a/collects/net/cgi-unit.ss b/collects/net/cgi-unit.ss index 58c7600248..f754d216b3 100644 --- a/collects/net/cgi-unit.ss +++ b/collects/net/cgi-unit.ss @@ -5,238 +5,235 @@ (import) (export cgi^) - ;; type bindings = list ((symbol . string)) + ;; type bindings = list ((symbol . string)) - ;; -------------------------------------------------------------------- + ;; -------------------------------------------------------------------- - ;; Exceptions: + ;; Exceptions: - (define-struct cgi-error ()) + (define-struct cgi-error ()) - ;; chars : list (char) - ;; -- gives the suffix which is invalid, not including the `%' + ;; chars : list (char) + ;; -- gives the suffix which is invalid, not including the `%' - (define-struct (incomplete-%-suffix cgi-error) (chars)) + (define-struct (incomplete-%-suffix cgi-error) (chars)) - ;; char : char - ;; -- an invalid character in a hex string + ;; char : char + ;; -- an invalid character in a hex string - (define-struct (invalid-%-suffix cgi-error) (char)) + (define-struct (invalid-%-suffix cgi-error) (char)) - ;; -------------------------------------------------------------------- + ;; -------------------------------------------------------------------- - ;; query-chars->string : list (char) -> string + ;; query-chars->string : list (char) -> string - ;; -- The input is the characters post-processed as per Web specs, which - ;; is as follows: - ;; spaces are turned into "+"es and lots of things are turned into %XX, - ;; where XX are hex digits, eg, %E7 for ~. The output is a regular - ;; Scheme string with all the characters converted back. + ;; -- The input is the characters post-processed as per Web specs, which + ;; is as follows: + ;; spaces are turned into "+"es and lots of things are turned into %XX, where + ;; XX are hex digits, eg, %E7 for ~. The output is a regular Scheme string + ;; with all the characters converted back. - (define (query-chars->string chars) - (list->string - (let loop ([chars chars]) - (if (null? chars) null - (let ([first (car chars)] - [rest (cdr chars)]) - (let-values ([(this rest) - (cond - [(char=? first #\+) - (values #\space rest)] - [(char=? first #\%) - (if (and (pair? rest) - (pair? (cdr rest))) - (values - (integer->char - (or (string->number - (string - (car rest) (cadr rest)) - 16) - (raise (make-invalid-%-suffix - (if (string->number - (string (car rest)) - 16) - (cadr rest) - (car rest)))))) - (cddr rest)) - (raise - (make-incomplete-%-suffix rest)))] - [else - (values first rest)])]) - (cons this (loop rest)))))))) + (define (query-chars->string chars) + (list->string + (let loop ([chars chars]) + (if (null? chars) null + (let ([first (car chars)] + [rest (cdr chars)]) + (let-values ([(this rest) + (cond + [(char=? first #\+) + (values #\space rest)] + [(char=? first #\%) + (if (and (pair? rest) (pair? (cdr rest))) + (values + (integer->char + (or (string->number + (string (car rest) (cadr rest)) + 16) + (raise (make-invalid-%-suffix + (if (string->number + (string (car rest)) + 16) + (cadr rest) + (car rest)))))) + (cddr rest)) + (raise (make-incomplete-%-suffix rest)))] + [else + (values first rest)])]) + (cons this (loop rest)))))))) - ;; string->html : string -> string - ;; -- the input is raw text, the output is HTML appropriately quoted + ;; string->html : string -> string + ;; -- the input is raw text, the output is HTML appropriately quoted - (define (string->html s) - (apply string-append (map (lambda (c) - (case c - [(#\<) "<"] - [(#\>) ">"] - [(#\&) "&"] - [else (string c)])) - (string->list s)))) + (define (string->html s) + (apply string-append + (map (lambda (c) + (case c + [(#\<) "<"] + [(#\>) ">"] + [(#\&) "&"] + [else (string c)])) + (string->list s)))) - (define default-text-color "#000000") - (define default-bg-color "#ffffff") - (define default-link-color "#cc2200") - (define default-vlink-color "#882200") - (define default-alink-color "#444444") + (define default-text-color "#000000") + (define default-bg-color "#ffffff") + (define default-link-color "#cc2200") + (define default-vlink-color "#882200") + (define default-alink-color "#444444") - ;; generate-html-output : - ;; html-string x list (html-string) x ... -> () + ;; generate-html-output : + ;; html-string x list (html-string) x ... -> () - (define generate-html-output - (opt-lambda (title body-lines - [text-color default-text-color] - [bg-color default-bg-color] - [link-color default-link-color] - [vlink-color default-vlink-color] - [alink-color default-alink-color]) - (let ([sa string-append]) - (for-each - (lambda (l) (display l) (newline)) - `("Content-type: text/html" - "" - "" - "" - "
" - ,(sa ""
+ ,@(map (lambda (bind)
+ (string-append (symbol->string (car bind))
+ " --> "
+ (cdr bind)
+ "
"))
+ bindings)
+ "
"))
- ;; bindings-as-html : bindings -> list (html-string)
- ;; -- formats name-value bindings as HTML appropriate for displaying
- (define (bindings-as-html bindings)
- `(""
- ,@(map (lambda (bind)
- (string-append (symbol->string (car bind))
- " --> "
- (cdr bind)
- "
"))
- bindings)
- "
"))
+ ;; extract-bindings : (string + symbol) x bindings -> list (string)
+ ;; -- Extracts the bindings associated with a given name. The semantics of
+ ;; forms states that a CHECKBOX may use the same NAME field multiple times.
+ ;; Hence, a list of strings is returned. Note that the result may be the
+ ;; empty list.
+ (define (extract-bindings field-name bindings)
+ (let ([field-name (if (symbol? field-name)
+ field-name (string->symbol field-name))])
+ (let loop ([found null] [bindings bindings])
+ (if (null? bindings)
+ found
+ (if (equal? field-name (caar bindings))
+ (loop (cons (cdar bindings) found) (cdr bindings))
+ (loop found (cdr bindings)))))))
- ;; extract-bindings : (string + symbol) x bindings -> list (string)
- ;; -- Extracts the bindings associated with a given name. The semantics
- ;; of forms states that a CHECKBOX may use the same NAME field multiple
- ;; times. Hence, a list of strings is returned. Note that the result
- ;; may be the empty list.
- (define (extract-bindings field-name bindings)
- (let ([field-name (if (symbol? field-name)
- field-name (string->symbol field-name))])
- (let loop ([found null] [bindings bindings])
- (if (null? bindings)
- found
- (if (equal? field-name (caar bindings))
- (loop (cons (cdar bindings) found) (cdr bindings))
- (loop found (cdr bindings)))))))
+ ;; extract-binding/single : (string + symbol) x bindings -> string
+ ;; -- used in cases where only one binding is supposed to occur
+ (define (extract-binding/single field-name bindings)
+ (let* ([field-name (if (symbol? field-name)
+ field-name (string->symbol field-name))]
+ [result (extract-bindings field-name bindings)])
+ (cond
+ [(null? result)
+ (generate-error-output
+ (cons (format "No binding for field `~a':