;;;; Programmer: Kevin M. Rosenberg
;;;; Date Started: Apr 2000
;;;;
-;;;; $Id: web-utils.lisp,v 1.12 2003/06/12 11:10:38 kevin Exp $
-;;;;
;;;; This file, part of KMRCL, is Copyright (c) 2002 by Kevin M. Rosenberg
;;;;
;;;; KMRCL users are granted the rights to distribute and use this software
;;; HTML/XML constants
-(defvar *standard-xml-header*
+(defvar *standard-xml-header*
#.(format nil "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>~%"))
(defvar *standard-html-header* "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">")
(defvar *standard-xhtml-header*
- #.(format nil "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>~%<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3c.org/TR/xhtml11/DTD/xhtml11\">"))
+ #.(format nil "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>~%<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">"))
;;; User agent functions
"Takes a user-agent string and returns T for Internet Explorer."
(or (string-starts-with "Microsoft" agent)
(string-starts-with "Internet Explore" agent)
+ (search "Safari" agent)
(search "MSIE" agent)))
;;; URL Functions
(defun base-url! (url)
(setq *base-url* url))
-(defun make-url (page-name &key (base-dir *base-url*) (format :html) (vars nil))
+(defun make-url (page-name &key (base-dir *base-url*) (format :html) vars anchor)
(let ((amp (case format
- (:html
- "&")
- ((:xml :ie-xml)
- "&"))))
- (concatenate 'string
+ (:html
+ "&")
+ ((:xml :ie-xml)
+ "&"))))
+ (concatenate 'string
base-dir page-name
(if vars
- (let ((first-var (first vars)))
- (concatenate 'string
- "?" (car first-var) "=" (cadr first-var)
- (mapcar-append-string
- #'(lambda (var)
- (when (and (car var) (cadr var))
- (concatenate 'string
- amp (car var) "=" (cadr var))))
- (rest vars))))
- ""))))
-
-(defun make-url-new (page-name &key (base-dir *base-url*) (format :html)
- (vars nil))
- (let ((amp (ecase format
- (:html "&")
- ((:xml :ie-xml) "&"))))
- (concatenate 'string
- base-dir page-name
- (if vars
- (let ((first-var (first vars)))
- (concatenate 'string
- "?" (car first-var) "=" (cadr first-var)
- (mapcar-append-string
- #'(lambda (var)
- (when (and (car var) (cadr var))
- (concatenate 'string
- amp (car var) "=" (cadr var))))
- (rest vars))))
- ""))))
+ (let ((first-var (first vars)))
+ (concatenate 'string
+ "?" (car first-var) "=" (cdr first-var)
+ (mapcar-append-string
+ #'(lambda (var)
+ (when (and (car var) (cdr var))
+ (concatenate 'string
+ amp (string-downcase (car var)) "=" (cdr var))))
+ (rest vars))))
+ "")
+ (if anchor
+ (concatenate 'string "#" anchor)
+ ""))))
(defun decode-uri-query-string (s)
"Decode a URI query string field"
(declare (simple-string s)
- (optimize (speed 3) (safety 0) (space 0)))
+ (optimize (speed 3) (safety 0) (space 0)))
(do* ((old-len (length s))
- (new-len (- old-len (* 2 (count-string-char s #\%))))
- (new (make-string new-len))
- (p-old 0)
- (p-new 0 (1+ p-new)))
+ (new-len (- old-len (* 2 (the fixnum (count-string-char s #\%)))))
+ (new (make-string new-len))
+ (p-old 0)
+ (p-new 0 (1+ p-new)))
((= p-new new-len) new)
(declare (simple-string new)
- (fixnum p-old p-new old-len new-len))
- (let ((c (schar s p-old)))
- (when (char= c #\+)
- (setq c #\space))
- (case c
- (#\%
- (unless (>= old-len (+ p-old 3))
- (error "#\% not followed by enough characters"))
- (setf (schar new p-new)
- (code-char
- (parse-integer (subseq s (1+ p-old) (+ p-old 3))
- :radix 16)))
- (incf p-old 3))
- (t
- (setf (schar new p-new) c)
- (incf p-old))))))
+ (fixnum p-old p-new old-len new-len))
+ (let ((c (schar s p-old)))
+ (when (char= c #\+)
+ (setq c #\space))
+ (case c
+ (#\%
+ (unless (>= old-len (+ p-old 3))
+ (error "#\% not followed by enough characters"))
+ (setf (schar new p-new)
+ (code-char
+ (parse-integer (subseq s (1+ p-old) (+ p-old 3))
+ :radix 16)))
+ (incf p-old 3))
+ (t
+ (setf (schar new p-new) c)
+ (incf p-old))))))
+
+(defun split-uri-query-string (s)
+ (mapcar
+ (lambda (pair)
+ (let ((pos (position #\= pair)))
+ (when pos
+ (cons (subseq pair 0 pos)
+ (when (> (length pair) pos)
+ (decode-uri-query-string (subseq pair (1+ pos))))))))
+ (delimited-string-to-list s #\&)))