/* * Copyright (c) 2003, 2004 The University of Wroclaw. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the University may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ namespace Sioux { using Nemerle.Collections; using Nemerle.Xml; using System.Net.Sockets; using System.Xml; /** * The exception thrown in case of an irrecoverable error. */ public class DieException : System.Exception { public this () {} } /** * Describes a Nemerle web application. */ public class Application { /* -- CONSTRUCTORS ----------------------------------------------------- */ /** * Creates a new instance of a Nemerle web application. */ public this () { PageName = ""; FormTemplate = None (); } /* -- PUBLIC METHODS --------------------------------------------------- */ /** * Handles an HTTP request */ public virtual HandleRequest (request : Request, response : Response) : void { this.request = request; this.response = response; match (request.RequestInfo) { | RequestInfo.DynamicGet (url, _) | RequestInfo.Post (url, _ , _) => PageName = url | _ => ReportInternalError ("invalid request type in HandleRequest") }; put_get_and_post_vars_into_hashtables (); // TODO this.response.AddCookie(Cookie("SIOUXSESSIONID",this.request.GetSession().SessionID)); try { run (); maybe_send_response (); } catch { | _ is DieException => () | exn => try { ReportInternalError ("got a fatal exception " + exn.ToString () + "\n\n" + exn.StackTrace) } catch { | _ is DieException => () } } } /** * Reports an internal error and dies */ public virtual ReportInternalError (msg : string) : void { response.WriteLine ("HTTP/1.0 500 Server Error"); response.WriteLine ("Content-type: text/plain"); response.WriteLine (); response.WriteLine (msg); throw DieException () } /* -- PROTECTED METHODS ------------------------------------------------ */ /** * Handles a GET request */ protected virtual DoGet() : void { // do nothing } /** * Handles a POST request */ protected virtual DoPost() : void { // do nothing } /* -- PRIVATE METHODS -------------------------------------------------- */ /** * Performs the server-side computations associated with this action. */ protected run () : void { if(request_type_is_get) DoGet(); else DoPost(); } /** * Writes the contents of the form template, if any present */ protected maybe_send_response () : void { match (FormTemplate) { | Some (template) => encode_urls(this.request.GetSession().SessionID); response.WriteXhtml (template.GetDocument ()) | _ => () } } /** * We don't really care about the ordering of the GET and POST * variables, so put them into hashtables for convenience. */ protected put_get_and_post_vars_into_hashtables () : void { def move_to_hashtable (hashtable : Hashtable [string, string], parms : list [string * string]) : void { match (parms) { | [] => () | (parameter, value) :: rest => System.Console.WriteLine ("VAR: '{0}' = '{1}'", parameter, value); hashtable.Set (parameter, value); move_to_hashtable (hashtable, rest) } }; def move_files_to_hashtable (hashtable : Hashtable [string, string * string * int], files : list [string * string * string * int]) : void { match (files) { | [] => () | (name, real_name, temp_name, size) :: rest => System.Console.WriteLine ("FILE: " + name + ", " + real_name + ", " + temp_name + ", " + size.ToString()); hashtable.Set (name, (real_name,temp_name,size)); move_files_to_hashtable (hashtable, rest) } }; match (request.RequestInfo ) { | RequestInfo.DynamicGet (_, parms) => GetVars = Hashtable (List.Length (parms)); PostVars = null; PostedFiles = null; request_type_is_get = true; move_to_hashtable (GetVars, parms) | RequestInfo.Post (_, parms , files) => PostVars = Hashtable (List.Length (parms)); PostedFiles = Hashtable (List.Length (files)); GetVars = null; request_type_is_get = false; move_to_hashtable (PostVars, parms); move_files_to_hashtable (PostedFiles, files) | _ => ReportInternalError ("invalid request type") } } /** * Modifies url adding session id to it */ protected encode_urls (session_id : string) : void { def walk (n : XmlNode,session_id) { when (n.NodeType == XmlNodeType.Element) { def element = (n :> XmlElement); def attributes = element.Attributes; foreach(attribute :> XmlAttribute in attributes) { def delimiter = array[';']; def split = attribute.Value.Split(delimiter); when(split.Length == 2 && split[1]=="EncodeUrl()") attribute.Value = split[0] + ";" + session_id } } def walk_children (cur : XmlNode,session_id) { if (cur == null) () else { walk (cur,session_id); walk_children (cur.NextSibling,session_id); } } walk_children (n.FirstChild,session_id) } when(Option.IsSome(FormTemplate)) { def document = Option.UnSome(FormTemplate).GetDocument(); walk (document,session_id); } } /* -- PROTECTED FIELDS ------------------------------------------------- */ protected mutable GetVars : Hashtable [string, string]; protected mutable PostVars : Hashtable [string, string]; protected mutable PostedFiles : Hashtable [string, string * string * int]; protected mutable request_type_is_get : bool; protected mutable PageName : string; protected mutable FormTemplate : option [XmlTemplate]; protected mutable request : Request; protected mutable response : Response; } }