1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: modlisp -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
6 ;;;; Purpose: Utility functions for modlisp package
7 ;;;; Programmer: Kevin M. Rosenberg
8 ;;;; Date Started: Dec 2002
11 ;;;; *************************************************************************
13 (in-package #:modlisp)
15 (defun format-string (fmt)
22 (defmacro with-ml-page ((&key (format :html) (precompute t) headers)
24 (let ((fmt (gensym "FMT-"))
25 (precomp (gensym "PRE-"))
26 (result (gensym "RES-"))
27 (outstr (gensym "STR-"))
28 (stream (gensym "STRM-"))
29 (hdr (gensym "HDR-")))
31 (,precomp ,precompute)
32 ,result ,outstr ,stream)
33 (declare (ignorable ,stream))
34 (write-header-line "Status" "200 OK")
35 (write-header-line "Content-Type" (format-string ,fmt))
36 (dolist (,hdr ,headers)
37 (write-header-line (car ,hdr) (cdr ,hdr)))
39 (write-string "end" *modlisp-socket*)
40 (write-char #\NewLine *modlisp-socket*))
42 (with-output-to-string (,stream)
43 (let ((*modlisp-socket* (if ,precomp
46 (setq ,result (progn ,@body)))))
49 (write-header-line "Content-Length"
50 (write-to-string (length ,outstr)))
51 (write-header-line "Keep-Socket" "1")
52 (write-header-line "Connection" "Keep-Alive")
53 (write-string "end" *modlisp-socket*)
54 (write-char #\NewLine *modlisp-socket*)
55 (write-string ,outstr *modlisp-socket*)
56 (finish-output *modlisp-socket*)
57 (setq *close-modlisp-socket* nil))
59 (finish-output *modlisp-socket*)
60 (setq *close-modlisp-socket* t)))
63 (defun redirect-to-location (url)
64 (write-header-line "Status" "307 Temporary Redirect")
65 (write-header-line "Location" url)
66 ;;(write-header-line "Keep-Socket" "1")
67 ;;(write-header-line "Connection" "Keep-Alive")
68 (write-string "end" *modlisp-socket*)
69 (write-char #\NewLine *modlisp-socket*)
70 (force-output *modlisp-socket*)
71 (setq *close-modlisp-socket* t))
73 (defun output-ml-page (format html)
74 (write-header-line "Status" "200 OK")
75 (write-header-line "Content-Type" (format-string format))
76 (write-header-line "Content-Length" (format nil "~d" (length html)))
77 (write-header-line "Keep-Socket" "1")
78 (write-header-line "Connection" "Keep-Alive")
79 (write-string "end" *modlisp-socket*)
80 (write-char #\NewLine *modlisp-socket*)
81 (write-string html *modlisp-socket*)
82 (force-output *modlisp-socket*)
83 (setq *close-modlisp-socket* nil))
85 (defun output-html-page (str)
86 (output-ml-page :html str))
88 (defun output-xml-page (str)
89 (output-ml-page :xml str))
91 ;; Utility functions for library users
93 (defun query-to-alist (posted-string &key (keyword t))
94 "Converts a posted string to an assoc list of keyword names and values,
95 \"a=1&bc=demo\" => ((:a . \"1\") (:bc . \"demo\"))"
98 (dolist (name=val (kmrcl:delimited-string-to-list posted-string #\&)
100 (let ((name-val-list (kmrcl:delimited-string-to-list name=val #\=)))
101 (if (= 2 (length name-val-list))
102 (destructuring-bind (name val) name-val-list
103 (push (cons (if keyword
104 (kmrcl:ensure-keyword name)
106 (kmrcl:decode-uri-query-string val))
108 (cmsg-c :debug "Invalid number of #\= in ~S" name-val-list)))))))