/* * 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.Fit { using Nemerle.Collections; using Nemerle.Xml; using Nemerle.IO; using System.Xml; using System.Xml.Xsl; /** * The FIT web application */ public class Fit : Application { /** * Applies an XSL transform to an XML document */ private apply_xsl_transform (xsl : XslTransform, doc : XmlDocument) : XmlDocument { def reader = xsl.Transform (doc, null, (null : XmlResolver)); def result = XmlDocument (); result.XmlResolver = null; result.Load (reader); result } /** * */ public ServePage (page_handler : option [XmlTemplate -> XmlTemplate], xml_file_name : option [string], xsl_file_name : option [string]) : void { def page_document = XmlDocument (); // load the page XML document, if any match (xml_file_name) { | Some (xml_file_name) => def reader = XmlTextReader (xml_file_name); reader.XmlResolver = null; page_document.Load (reader) | _ => () }; // create the XmlTemplate and apply the page handler, if any def page_template = XmlTemplate (page_document); def page_template = match (page_handler) { | Some (page_handler) => page_handler (page_template) | _ => page_template }; def page_document = page_template.GetDocument (); // load and apply the custom transform, if any def page_document = match (xsl_file_name) { | Some (xsl_file_name) => def xsl = XslTransform (); xsl.Load (xsl_file_name, null); apply_xsl_transform (xsl, page_document); | _ => page_document }; // apply the final transform def final_document = apply_xsl_transform (fit_xsl, page_document); FormTemplate = Some (XmlTemplate (final_document)) } public static get_val (h : Hashtable [string, string], key : string) : string { if (h == null) "" else match (h.Get (key)) { | Some (res) => res | None => "" } } /* -- PAGE HANDLERS ---------------------------------------------------- */ submission_form (t : XmlTemplate) : XmlTemplate { def t = Submission ().get_submission_form (t); t.SetText ("removal", ""); t } submission (t : XmlTemplate) : XmlTemplate { def subm = Submission (); subm.read_post (PostVars, true); subm.get_submission_confirm (t, admin_mode, false) } submission_edit (t : XmlTemplate) : XmlTemplate { def subm = Submission (); subm.read_post (PostVars, false); subm.get_submission_confirm (t, admin_mode, true) } edit (t : XmlTemplate) : XmlTemplate { def res = lock (submissions) submissions.Get (get_val (GetVars, "id")); match (res) { | Some (subm) => def template = subm.get_submission_form (t); if (admin_mode) template.SetText ("submission/action", secret_password + "/submission-edit.xml") else template.SetText ("submission/action", "/submission-edit.xml"); unless (admin_mode) template.SetText ("removal", ""); template | None => def template = XmlTemplate ("fit/error.xml"); template.SetText ("msg", "ZgÅ‚oszenie nie istnieje."); template } } submission_edit_form (t : XmlTemplate) : XmlTemplate { def res = lock (submissions) submissions.Get (get_val (GetVars, "id")); match (res) { | Some (subm) => def template = subm.get_submission_form (t); if (admin_mode) template.SetText ("submission/action", secret_password + "/submission-edit.xml") else template.SetText ("submission/action", "/submission-edit.xml"); template | None => def template = XmlTemplate ("fit/error.xml"); template.SetText ("msg", "ZgÅ‚oszenie nie istnieje."); template } } list_data () : void { FormTemplate = Some (XmlTemplate (list_xml)); } remind () : void { def email = get_val (PostVars, "email"); def maybe_add (id, subm : Submission, acc) { if (subm.val ("email") == email) sprintf ("%s\n%s %s: http://lilith.ii.uni.wroc.pl:8000/edit.xml?id=%s", acc, subm.val ("first_name"), subm.val ("last_name"), id) else acc }; def str = submissions.Fold ("", maybe_add); if (str == "") { def template = XmlTemplate ("fit/error.xml"); template.SetText ("msg", sprintf ("Brak adresu '%s' w bazie.", email)); ServePage (Some (fun (_) { template }), None (), None ()) } else { def m = System.Web.Mail.MailMessage (); m.BodyEncoding = System.Text.Encoding.GetEncoding ("iso-8859-2"); m.Subject = "Przypomnienie linku edycji zgÅ‚oszenia na FIT"; m.To = email; m.From = "FIT XVIII "; m.Body = str + "\n\n"; System.Web.Mail.SmtpMail.Send (m); def template = XmlTemplate ("fit/message.xml"); template.SetText ("msg", "Przypomnienie wysÅ‚ano."); ServePage (Some (fun (_) { template }), None (), None ()) } } kill_submission () : void { if (get_val (PostVars, "kill_it") == "") { def template = XmlTemplate ("fit/error.xml"); template.SetText ("msg", "Aby usunÄ�‡ zgÅ‚oszenie zaznacz checkbox."); ServePage (Some (fun (_) { template }), None (), None ()) } else { def id = get_val (PostVars, "id2"); match (submissions.Get (id)) { | Some (subm) => submissions.Remove (id); subm.send_kill_email (admin_mode); serialize (); def template = XmlTemplate ("fit/message.xml"); template.SetText ("msg", "ZgÅ‚oszenie usuniÄ™to."); ServePage (Some (fun (_) { template }), None (), None ()) | None => def template = XmlTemplate ("fit/error.xml"); template.SetText ("msg", "Nie ma takiego zgÅ‚oszenia."); ServePage (Some (fun (_) { template }), None (), None ()) } } } static cycle_backup () : void { for (mutable i = 49; i >= 0; i = i - 1) { try { System.IO.File.Delete (sprintf ("fit/data/data.xml.%d", i + 1)) } catch { _ is System.Exception => () }; try { System.IO.File.Move (sprintf ("fit/data/data.xml.%d", i), sprintf ("fit/data/data.xml.%d", i + 1)) } catch { _ is System.Exception => () }; }; try { System.IO.File.Move ("fit/data/data.xml", "fit/data/data.xml.0"); } catch { _ is System.Exception => () }; } static serialize () : void { def doc = XmlDocument (); def n = doc.CreateElement ("submissions"); ignore (doc.AppendChild (n)); def add (subm : Submission) { ignore (n.AppendChild (subm.serialize (doc))) }; def compare (s1 : Submission, s2 : Submission) { System.DateTime.Compare (System.DateTime.Parse (s1.val ("time_started")), System.DateTime.Parse (s2.val ("time_started"))) }; lock (submissions) { cycle_backup (); def subm = submissions.Fold ([], fun (_, subm, acc) { subm :: acc }); List.Iter (List.Sort (subm, compare), add); doc.Save ("fit/data/data.xml"); n.SetAttribute ("secret", secret_password); def reader = list_xsl.Transform (n, null, (null : XmlResolver)); def doc' = XmlDocument (); doc'.XmlResolver = null; doc'.Load (reader); list_xml = doc'; } } static unserialize () : void { def doc = XmlDocument (); doc.Load ("fit/data/data.xml"); def add (n : XmlNode) { when (n != null) { when (n.NodeType == XmlNodeType.Element) { def subm = Submission (); subm.unserialize (n); subm.store (); }; add (n.NextSibling) } }; add (doc.DocumentElement.FirstChild); } mutable admin_mode : bool; override protected DoGet () : void { when (PageName.StartsWith (secret_password)) { PageName = PageName.Substring (secret_password.Length); admin_mode = true }; def serve_static (xml_file_name : string) : void { ServePage (None (), Some (xml_file_name), None ()) }; match (PageName) { | "/submission.xml" => ServePage (Some (submission), Some ("fit/submission.xml"), None ()); serialize () | "/submission-edit.xml" => ServePage (Some (submission_edit), Some ("fit/submission.xml"), None ()); serialize () | "/submission-form.xml" => ServePage (Some (submission_form), Some ("fit/submission-form.xml"), None ()) | "/edit.xml" => ServePage (Some (edit), Some ("fit/submission-form.xml"), None ()) | "/list.xml" when admin_mode => list_data () | "/remind.xml" => remind () | "/kill_submission.xml" => kill_submission () | "/register.xml" => serve_static ("fit/register.xml") | _ => serve_static ("fit/index.xml") } } override protected DoPost() : void { DoGet() } static this () { fit_xsl = XslTransform (); fit_xsl.Load ("fit/fit.xsl", null); list_xsl = XslTransform (); list_xsl.Load ("fit/display-table.xsl", null); def f = System.IO.File.OpenText ("fit/password"); secret_password = f.ReadLine (); f.Close (); submissions = Hashtable (1000); try { unserialize () } catch { | _ is System.IO.FileNotFoundException => () }; serialize (); } /* -- INTERNAL FIELDS -------------------------------------------------- */ internal static submissions : Hashtable [string, Submission]; internal static secret_password : string; /* -- PRIVATE FIELDS --------------------------------------------------- */ private static mutable fit_xsl : XslTransform; private static mutable list_xsl : XslTransform; private static mutable list_xml : XmlDocument; } }