]> WPIA git - gigi.git/blobdiff - src/org/cacert/gigi/output/template/Form.java
fix: re-display form on error in some cases.
[gigi.git] / src / org / cacert / gigi / output / template / Form.java
index 366d31c5913684a032eaf5b379996978a48673bd..1eb0efa04e5f8ca4a87fc906bf2906f3eb7d3a4d 100644 (file)
@@ -2,15 +2,15 @@ package org.cacert.gigi.output.template;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.HashMap;
 import java.util.Map;
 
-import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
 import org.cacert.gigi.GigiApiException;
 import org.cacert.gigi.localisation.Language;
-import org.cacert.gigi.pages.Page;
+import org.cacert.gigi.pages.LoginPage;
 import org.cacert.gigi.util.RandomToken;
 
 /**
@@ -40,7 +40,7 @@ public abstract class Form implements Outputable {
      * @param hsr
      *            the request to register the form against.
      * @param action
-     *            the target path where the form should be submitted
+     *            the target path where the form should be submitted.
      */
     public Form(HttpServletRequest hsr, String action) {
         csrf = RandomToken.generateToken(32);
@@ -55,13 +55,39 @@ public abstract class Form implements Outputable {
      * @param out
      *            the stream to the user.
      * @param req
-     *            the request to take the initial data from
-     * @return true, iff the form succeeded an the user should be redirected.
+     *            the request to take the initial data from.
+     * @return true, iff the form succeeded and the user should be redirected.
      * @throws GigiApiException
      *             if internal operations went wrong.
      */
     public abstract boolean submit(PrintWriter out, HttpServletRequest req) throws GigiApiException;
 
+    /**
+     * Calls {@link #submit(PrintWriter, HttpServletRequest)} while catching and
+     * displaying errors ({@link GigiApiException}), and re-outputing the form
+     * via {@link #output(PrintWriter, Language, Map)}.
+     * 
+     * @param out
+     *            the target to write the form and errors to
+     * @param req
+     *            the request that this submit originated (for submit and for
+     *            language)
+     * @return as {@link #submit(PrintWriter, HttpServletRequest)}: true, iff
+     *         the form succeeded and the user should be redirected.
+     */
+    public boolean submitProtected(PrintWriter out, HttpServletRequest req) {
+        try {
+            boolean succeeded = submit(out, req);
+            if (succeeded) {
+                return true;
+            }
+        } catch (GigiApiException e) {
+            e.format(out, LoginPage.getLanguage(req));
+        }
+        output(out, LoginPage.getLanguage(req), new HashMap<String, Object>());
+        return false;
+    }
+
     protected String getCsrfFieldName() {
         return CSRF_FIELD;
     }
@@ -73,7 +99,6 @@ public abstract class Form implements Outputable {
         } else {
             out.println("<form method='POST' action='" + action + "'>");
         }
-        failed = false;
         outputContent(out, l, vars);
         out.print("<input type='hidden' name='" + CSRF_FIELD + "' value='");
         out.print(getCSRFToken());
@@ -84,47 +109,14 @@ public abstract class Form implements Outputable {
      * Outputs the forms contents.
      * 
      * @param out
-     *            Stream to the user
+     *            Stream to the user.
      * @param l
-     *            {@link Language} to translate text to
+     *            {@link Language} to translate text to.
      * @param vars
      *            Variables supplied from the outside.
      */
     protected abstract void outputContent(PrintWriter out, Language l, Map<String, Object> vars);
 
-    private boolean failed;
-
-    protected void outputError(PrintWriter out, ServletRequest req, String text, Object... contents) {
-        if ( !failed) {
-            failed = true;
-            out.println("<div class='formError'>");
-        }
-        out.print("<div>");
-        if (contents.length == 0) {
-            out.print(Page.translate(req, text));
-        } else {
-            out.print(String.format(Page.translate(req, text), contents));
-        }
-        out.println("</div>");
-    }
-
-    protected void outputErrorPlain(PrintWriter out, String text) {
-        if ( !failed) {
-            failed = true;
-            out.println("<div class='formError'>");
-        }
-        out.print("<div>");
-        out.print(text);
-        out.println("</div>");
-    }
-
-    public boolean isFailed(PrintWriter out) {
-        if (failed) {
-            out.println("</div>");
-        }
-        return failed;
-    }
-
     protected String getCSRFToken() {
         return csrf;
     }
@@ -135,11 +127,12 @@ public abstract class Form implements Outputable {
      * @param req
      *            the request that is directed to the form.
      * @param target
-     *            the {@link Class} of the expected form
+     *            the {@link Class} of the expected form.
      * @return the form where this request is directed to.
      * @throws CSRFException
      *             if no CSRF-token is found or the token is wrong.
      */
+    @SuppressWarnings("unchecked")
     public static <T extends Form> T getForm(HttpServletRequest req, Class<T> target) throws CSRFException {
         String csrf = req.getParameter(CSRF_FIELD);
         if (csrf == null) {
@@ -149,10 +142,17 @@ public abstract class Form implements Outputable {
         if (hs == null) {
             throw new CSRFException();
         }
-        Form f = (Form) hs.getAttribute("form/" + target.getName() + "/" + csrf);
+        Object f = hs.getAttribute("form/" + target.getName() + "/" + csrf);
         if (f == null) {
             throw new CSRFException();
         }
+        if ( !(f instanceof Form)) {
+            throw new CSRFException();
+        }
+        if ( !target.isInstance(f)) {
+            throw new CSRFException();
+        }
+        // Dynamic Cast checked by previous if statement
         return (T) f;
     }