@@ -0,0 +1,153 @@
7+Vars = List (String, String);
9+data CGIInfo = CGISt Vars -- GET
16+get_GET : CGIInfo -> Vars;
17+get_GET (CGISt g _ _ _ _ _) = g;
19+get_POST : CGIInfo -> Vars;
20+get_POST (CGISt _ p _ _ _ _) = p;
22+get_Cookies : CGIInfo -> Vars;
23+get_Cookies (CGISt _ _ c _ _ _) = c;
25+get_UAgent : CGIInfo -> String;
26+get_UAgent (CGISt _ _ _ a _ _) = a;
28+get_Headers : CGIInfo -> String;
29+get_Headers (CGISt _ _ _ _ h _) = h;
31+get_Output : CGIInfo -> String;
32+get_Output (CGISt _ _ _ _ _ o) = o;
34+add_Headers : String -> CGIInfo -> CGIInfo;
35+add_Headers str (CGISt g p c a h o) = CGISt g p c a (h ++ str) o;
37+add_Output : String -> CGIInfo -> CGIInfo;
38+add_Output str (CGISt g p c a h o) = CGISt g p c a h (o ++ str);
41+data CGI : Set -> Set where
42+ MkCGI : (CGIInfo -> IO (a, CGIInfo)) -> CGI a;
44+getAction : CGI a -> CGIInfo -> IO (a, CGIInfo);
45+getAction (MkCGI act) = act;
47+instance Monad CGI where {
48+ (>>=) (MkCGI f) k = MkCGI (\s => do { v <- f s;
49+ getAction (k (fst v)) (snd v); });
51+ return v = MkCGI (\s => return (v, s));
54+setInfo : CGIInfo -> CGI ();
55+setInfo i = MkCGI (\s => return ((), i));
57+getInfo : CGI CGIInfo;
58+getInfo = MkCGI (\s => return (s, s));
61+lift : IO a -> CGI a ;
62+lift op = MkCGI (\st => do { x <- op;
66+output : String -> CGI ();
67+output s = do { i <- getInfo;
68+ setInfo (add_Output s i); };
72+queryVars = do { i <- getInfo;
73+ return (get_GET i); };
77+postVars = do { i <- getInfo;
78+ return (get_POST i); };
81+cookieVars : CGI Vars;
82+cookieVars = do { i <- getInfo;
83+ return (get_Cookies i); };
86+queryVar : String -> CGI (Maybe String);
87+queryVar x = do { vs <- queryVars;
88+ return (lookup x vs); };
90+getOutput : CGI String;
91+getOutput = do { i <- getInfo;
92+ return (get_Output i); };
94+getHeaders : CGI String;
95+getHeaders = do { i <- getInfo;
96+ return (get_Headers i); };
99+flushHeaders : CGI ();
100+flushHeaders = do { o <- getHeaders;
106+flush = do { o <- getOutput;
110+getVars : List Char -> String -> List (String, String);
111+getVars seps query = mapMaybe readVar (split (\x => elem x seps) query)
113+ readVar : String -> Maybe (String, String);
114+ readVar xs with split (\x => x == '=') xs {
115+ | [k, v] = Just (trim k, trim v);
120+getContent : Int -> IO String;
121+getContent x = getC x "" where {
122+ getC : Int -> String -> IO String;
123+ getC 0 acc = return $ rev acc;
124+ getC n acc = do { x <- getChar;
125+ getC (n-1) (strCons x acc); };
129+runCGI : CGI a -> IO a;
131+ clen_in <- getEnv "CONTENT_LENGTH";
132+ let clen = prim__strToInt clen_in;
133+ content <- getContent clen;
134+ query <- getEnv "QUERY_STRING";
135+ cookie <- getEnv "HTTP_COOKIE";
136+ agent <- getEnv "HTTP_USER_AGENT";
138+ let get_vars = getVars ['&',';'] query;
139+ let post_vars = getVars ['&'] content;
140+ let cookies = getVars [';'] cookie;
142+ p <- getAction prog (CGISt get_vars post_vars cookies agent
143+ "Content-type: text/html\n"
145+ putStrLn (get_Headers (snd p));
146+ putStr (get_Output (snd p));