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 headers)
24 (defmacro write-response ((&key headers len (status "200 OK")) &body body)
25 (let ((result (gensym "RES-")))
27 (write-header-line "Status" ,status)
28 (dolist (hdr ,headers)
29 (write-header-line (car hdr) (cdr hdr)))
31 `((write-header-line "Content-Length" ,len)
32 (write-header-line "Keep-Socket" "1")
33 (write-header-line "Connection" "Keep-Alive")))
34 (write-string "end" *modlisp-socket*)
35 (write-char #\NewLine *modlisp-socket*)
36 (let ((,result (progn ,@body)))
37 (,(if len 'force-output 'finish-output) *modlisp-socket*)
38 (setq *close-modlisp-socket* ,(not len))
41 (defmacro with-ml-page ((&key (format :html) (precompute t) headers)
44 `(output-ml-page ,format (with-output-to-string (*modlisp-socket*) ,@body) :headers ,headers)
45 `(write-response (:headers (format-string ,format ,headers)) ,@body)))
47 (defun redirect-to-location (url)
48 (write-response (:status "307 Temporary Redirect" :headers `(("Location" . ,url)))))
50 (defmacro output-ml-page (format html &key headers)
51 (let ((str (gensym "STR-")))
53 (write-response (:len (format nil "~d" (length ,str))
54 :headers (format-string ,format ,headers))
55 (write-string ,str *modlisp-socket*)))))
57 (defun output-html-page (str &key headers)
58 (output-ml-page :html str :headers headers))
60 (defun output-xml-page (str &key headers)
61 (output-ml-page :xml str :headers headers))
63 ;; Utility functions for library users
65 (defun query-to-alist (posted-string &key (keyword t))
66 "Converts a posted string to an assoc list of keyword names and values,
67 \"a=1&bc=demo\" => ((:a . \"1\") (:bc . \"demo\"))"
70 (dolist (name=val (kmrcl:delimited-string-to-list posted-string #\&)
72 (let ((name-val-list (kmrcl:delimited-string-to-list name=val #\=)))
73 (if (= 2 (length name-val-list))
74 (destructuring-bind (name val) name-val-list
75 (push (cons (if keyword
76 (kmrcl:ensure-keyword name)
78 (kmrcl:decode-uri-query-string val))
80 (cmsg-c :debug "Invalid number of #\= in ~S" name-val-list)))))))