1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
5 ;;;; Name: web-utils.lisp
6 ;;;; Purpose: Basic web utility functions
7 ;;;; Programmer: Kevin M. Rosenberg
8 ;;;; Date Started: Apr 2000
12 ;;;; This file, part of KMRCL, is Copyright (c) 2002 by Kevin M. Rosenberg
14 ;;;; KMRCL users are granted the rights to distribute and use this software
15 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
16 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
17 ;;;; *************************************************************************
22 ;;; HTML/XML constants
24 (defvar *standard-xml-header*
25 #.(format nil "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"yes\"?>~%"))
27 (defvar *standard-html-header* "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">")
29 (defvar *standard-xhtml-header*
30 #.(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\">"))
33 ;;; User agent functions
35 (defun user-agent-ie-p (agent)
36 "Takes a user-agent string and returns T for Internet Explorer."
37 (or (string-starts-with "Microsoft" agent)
38 (string-starts-with "Internet Explore" agent)
39 (search "Safari" agent)
40 (search "MSIE" agent)))
44 (defvar *base-url* "")
45 (defun base-url! (url)
46 (setq *base-url* url))
48 (defun make-url (page-name &key (base-dir *base-url*) (format :html) vars anchor)
49 (let ((amp (case format
57 (let ((first-var (first vars)))
59 "?" (car first-var) "=" (cdr first-var)
62 (when (and (car var) (cdr var))
64 amp (string-downcase (car var)) "=" (cdr var))))
68 (concatenate 'string "#" anchor)
71 (defun decode-uri-query-string (s)
72 "Decode a URI query string field"
73 (declare (simple-string s)
74 (optimize (speed 3) (safety 0) (space 0)))
75 (do* ((old-len (length s))
76 (new-len (- old-len (* 2 (the fixnum (count-string-char s #\%)))))
77 (new (make-string new-len))
80 ((= p-new new-len) new)
81 (declare (simple-string new)
82 (fixnum p-old p-new old-len new-len))
83 (let ((c (schar s p-old)))
88 (unless (>= old-len (+ p-old 3))
89 (error "#\% not followed by enough characters"))
90 (setf (schar new p-new)
92 (parse-integer (subseq s (1+ p-old) (+ p-old 3))
96 (setf (schar new p-new) c)
99 (defun split-uri-query-string (s)
102 (let ((pos (position #\= pair)))
104 (cons (subseq pair 0 pos)
105 (when (> (length pair) pos)
106 (decode-uri-query-string (subseq pair (1+ pos))))))))
107 (delimited-string-to-list s #\&)))