]> WPIA git - gigi.git/commitdiff
Add capable templating for register page
authorFelix Dörre <felix@dogcraft.de>
Sun, 22 Jun 2014 16:48:35 +0000 (18:48 +0200)
committerFelix Dörre <felix@dogcraft.de>
Sun, 22 Jun 2014 23:20:10 +0000 (01:20 +0200)
13 files changed:
src/org/cacert/gigi/Language.java
src/org/cacert/gigi/User.java
src/org/cacert/gigi/output/DateSelector.java [new file with mode: 0644]
src/org/cacert/gigi/output/Outputable.java [new file with mode: 0644]
src/org/cacert/gigi/output/Template.java [new file with mode: 0644]
src/org/cacert/gigi/pages/LoginPage.java
src/org/cacert/gigi/pages/MainPage.java
src/org/cacert/gigi/pages/Page.java
src/org/cacert/gigi/pages/main/RegisterPage.java
src/org/cacert/gigi/pages/main/RegisterPage.templ [new file with mode: 0644]
src/org/cacert/gigi/pages/main/Signup.java [new file with mode: 0644]
src/org/cacert/gigi/pages/main/Signup.templ [new file with mode: 0644]
src/org/cacert/gigi/util/HTMLEncoder.java [new file with mode: 0644]

index 9faaaad669038005d728017ee83a95c922c8afe1..5841c3c35dc918b025df178735d3e1500706f12e 100644 (file)
@@ -4,7 +4,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.HashMap;
-
+import java.util.Locale;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -17,8 +17,16 @@ import org.xml.sax.SAXException;
 public class Language {
        private static HashMap<String, Language> langs = new HashMap<String, Language>();
        HashMap<String, String> translations = new HashMap<String, String>();
+       Locale l;
        private Language(String language) throws ParserConfigurationException,
                        IOException, SAXException {
+               if (language.contains("_")) {
+                       String[] parts = language.split("_");
+                       l = new Locale(parts[0], parts[1]);
+               } else {
+                       l = new Locale(language);
+               }
+
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();
                Document d = db.parse(new FileInputStream(new File("locale", language
@@ -36,7 +44,11 @@ public class Language {
                System.out.println(translations.size() + " strings loaded.");
        }
        public String getTranslation(String text) {
-               return translations.get(text);
+               String string = translations.get(text);
+               if (string == null || string.equals("")) {
+                       return text;
+               }
+               return string;
        }
        public static Language getInstance(String language) {
                Language l = langs.get(language);
@@ -54,5 +66,8 @@ public class Language {
                }
                return l;
        }
+       public Locale getLocale() {
+               return l;
+       }
 
 }
index 8c4b1f9dab466b7d6531e0d4d3b70cbf3becf7b0..50e13ac044e14b9e187117b44ac72a4ea533939f 100644 (file)
@@ -3,6 +3,7 @@ package org.cacert.gigi;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Date;
 
 import org.cacert.gigi.database.DatabaseConnection;
 
@@ -10,7 +11,11 @@ public class User {
 
        private int id;
        String fname;
+       String mname;
        String lname;
+       String suffix;
+       Date dob;
+       String email;
 
        public User(int id) {
                this.id = id;
@@ -28,6 +33,8 @@ public class User {
                        e.printStackTrace();
                }
        }
+       public User() {
+       }
        public int getId() {
                return id;
        }
@@ -37,5 +44,38 @@ public class User {
        public String getLname() {
                return lname;
        }
+       public String getMname() {
+               return mname;
+       }
+       public void setMname(String mname) {
+               this.mname = mname;
+       }
+       public String getSuffix() {
+               return suffix;
+       }
+       public void setSuffix(String suffix) {
+               this.suffix = suffix;
+       }
+       public Date getDob() {
+               return dob;
+       }
+       public void setDob(Date dob) {
+               this.dob = dob;
+       }
+       public String getEmail() {
+               return email;
+       }
+       public void setEmail(String email) {
+               this.email = email;
+       }
+       public void setId(int id) {
+               this.id = id;
+       }
+       public void setFname(String fname) {
+               this.fname = fname;
+       }
+       public void setLname(String lname) {
+               this.lname = lname;
+       }
 
 }
diff --git a/src/org/cacert/gigi/output/DateSelector.java b/src/org/cacert/gigi/output/DateSelector.java
new file mode 100644 (file)
index 0000000..782e612
--- /dev/null
@@ -0,0 +1,53 @@
+package org.cacert.gigi.output;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Map;
+
+import org.cacert.gigi.Language;
+
+public class DateSelector implements Outputable {
+       String[] names;
+       public DateSelector(String day, String month, String year) {
+               this.names = new String[]{day, month, year};
+       }
+       int day;
+       int month;
+       int year;
+       @Override
+       public void output(PrintWriter out, Language l, Map<String, Object> vars) {
+               out.print("<nobr><select name=\"");
+               out.print(names[0]);
+               out.println("\">");
+               for (int i = 1; i <= 31; i++) {
+                       out.print("<option");
+                       if (i == day) {
+                               out.print(" selected=\"selected\"");
+                       }
+                       out.println(">" + i + "</option>");
+               }
+               out.println("</select>");
+               SimpleDateFormat sdf = new SimpleDateFormat("MMMM", l.getLocale());
+               out.print("<select name=\"");
+               out.print(names[1]);
+               out.println("\">");
+               Calendar c = sdf.getCalendar();
+               for (int i = 1; i <= 12; i++) {
+                       c.set(Calendar.MONTH, i - 1);
+                       out.print("<option value='" + i + "'");
+                       if (i == month) {
+                               out.print(" selected=\"selected\"");
+                       }
+                       out.println(">" + sdf.format(c.getTime()) + " (" + i + ")</option>");
+               }
+               out.println("</select>");
+               out.print("<input type=\"text\" name=\"");
+               out.print(names[2]);
+               out.print("\" value=\"");
+               if (year != 0) {
+                       out.print(year);
+               }
+               out.print("\" size=\"4\" autocomplete=\"off\"></nobr>");
+       }
+}
diff --git a/src/org/cacert/gigi/output/Outputable.java b/src/org/cacert/gigi/output/Outputable.java
new file mode 100644 (file)
index 0000000..4d5978e
--- /dev/null
@@ -0,0 +1,10 @@
+package org.cacert.gigi.output;
+
+import java.io.PrintWriter;
+import java.util.Map;
+
+import org.cacert.gigi.Language;
+
+public interface Outputable {
+       public void output(PrintWriter out, Language l, Map<String, Object> vars);
+}
diff --git a/src/org/cacert/gigi/output/Template.java b/src/org/cacert/gigi/output/Template.java
new file mode 100644 (file)
index 0000000..266761a
--- /dev/null
@@ -0,0 +1,61 @@
+package org.cacert.gigi.output;
+
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.regex.Pattern;
+
+import org.cacert.gigi.Language;
+
+public class Template implements Outputable {
+       String[] contents;
+
+       public Template(Reader r) {
+               LinkedList<String> splitted = new LinkedList<String>();
+               Scanner sc = new Scanner(r);
+               Pattern p1 = Pattern.compile("([^<]|<[^?])*<\\?");
+               Pattern p2 = Pattern.compile("([^<]|<[^?])*\\?>");
+               while (true) {
+                       String s1 = sc.findWithinHorizon(p1, 0);
+                       if (s1 == null) {
+                               break;
+                       }
+                       s1 = s1.substring(0, s1.length() - 2);
+                       splitted.add(s1);
+                       String s2 = sc.findWithinHorizon(p2, 0);
+                       s2 = s2.substring(0, s2.length() - 2);
+                       splitted.add(s2);
+               }
+               sc.useDelimiter("\0");
+               if (sc.hasNext()) {
+                       splitted.add(sc.next());
+               }
+               sc.close();
+               contents = splitted.toArray(new String[splitted.size()]);
+       }
+       public void output(PrintWriter out, Language l, Map<String, Object> vars) {
+               for (int i = 0; i < contents.length; i++) {
+                       if (i % 2 == 0) {
+                               out.print(contents[i]);
+                       } else if (contents[i].startsWith("=_")) {
+                               out.print(l.getTranslation(contents[i].substring(2)));
+                       } else if (contents[i].startsWith("=$")) {
+                               Object s = vars.get(contents[i].substring(2));
+                               if (s == null) {
+                                       System.out.println("Empty variable: "
+                                                       + contents[i].substring(2));
+                               }
+                               if (s instanceof Outputable) {
+                                       ((Outputable) s).output(out, l, vars);
+                               } else {
+                                       out.print(s);
+                               }
+                       } else {
+                               System.out.println("Unknown processing instruction: "
+                                               + contents[i]);
+                       }
+               }
+       }
+}
index 905daf16aa1248252a073f602f6ad6df227018d0..fe04cd46899db939aa9e4a8b83fbeaa3c76fd091 100644 (file)
@@ -2,8 +2,8 @@ package org.cacert.gigi.pages;
 
 import java.io.IOException;
 
-import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
 
 public class LoginPage extends Page {
        public LoginPage(String title) {
@@ -11,7 +11,7 @@ public class LoginPage extends Page {
        }
 
        @Override
-       public void doGet(ServletRequest req, ServletResponse resp)
+       public void doGet(HttpServletRequest req, ServletResponse resp)
                        throws IOException {
                resp.getWriter()
                                .println(
index d1528528743f0f80cac2148572d44b329ebb206d..3da5a0bff0c8d010cc2c46283c6bc37de73f3971 100644 (file)
@@ -2,8 +2,8 @@ package org.cacert.gigi.pages;
 
 import java.io.IOException;
 
-import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
 
 public class MainPage extends Page {
        public MainPage(String title) {
@@ -11,7 +11,7 @@ public class MainPage extends Page {
        }
 
        @Override
-       public void doGet(ServletRequest req, ServletResponse resp)
+       public void doGet(HttpServletRequest req, ServletResponse resp)
                        throws IOException {
                resp.getWriter().println("Access granted.");
        }
index 7b69e56cfbd21fc6b9e88f6980b5f0363f8f800e..cfc58d7a4f4ebde46d74b61e4751d3d0dcafb56c 100644 (file)
@@ -4,6 +4,7 @@ import java.io.IOException;
 
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
 
 import org.cacert.gigi.Language;
 
@@ -14,10 +15,10 @@ public abstract class Page {
                this.title = title;
        }
 
-       public abstract void doGet(ServletRequest req, ServletResponse resp)
+       public abstract void doGet(HttpServletRequest req, ServletResponse resp)
                        throws IOException;
 
-       public void doPost(ServletRequest req, ServletResponse resp)
+       public void doPost(HttpServletRequest req, ServletResponse resp)
                        throws IOException {
                doGet(req, resp);
        }
@@ -29,9 +30,14 @@ public abstract class Page {
        public void setTitle(String title) {
                this.title = title;
        }
+       public static Language getLanguage(ServletRequest req) {
+               return Language.getInstance("de");
+       }
+
        public static String translate(ServletRequest req, String string) {
-               Language l = Language.getInstance("de");
+               Language l = getLanguage(req);
                return l.getTranslation(string);
        }
 
+
 }
index f162b9132a270cdd56b94a94db1ce225b3ac4f26..b63dbce1612fb6f4ee0de86d3f6ee95b27cd63cc 100644 (file)
@@ -1,57 +1,44 @@
 package org.cacert.gigi.pages.main;
 
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
 
-import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
-
+import javax.servlet.http.HttpServletRequest;
+import org.cacert.gigi.output.Template;
 import org.cacert.gigi.pages.Page;
 
 public class RegisterPage extends Page {
 
        public static final String PATH = "/register";
+       Template t;
 
        public RegisterPage() {
                super("Register");
+               try {
+                       t = new Template(new InputStreamReader(
+                                       Signup.class.getResourceAsStream("RegisterPage.templ"),
+                                       "UTF-8"));
+               } catch (UnsupportedEncodingException e) {
+                       e.printStackTrace();
+               }
        }
 
        @Override
-       public void doGet(ServletRequest req, ServletResponse resp)
+       public void doGet(HttpServletRequest req, ServletResponse resp)
                        throws IOException {
                PrintWriter out = resp.getWriter();
-               out.print("<p>");
-               out.print(translate(
-                               req,
-                               "By joining CAcert and becoming a member, you agree to the CAcert Community Agreement. Please take a moment now to read that and agree to it; this will be required to complete the process of joining."));
-               out.println("</p>");
-               out.print("<p>");
-               out.print(translate(
-                               req,
-                               "Warning! This site requires cookies to be enabled to ensure your privacy and security. This site uses session cookies to store temporary values to prevent people from copying and pasting the session ID to someone else exposing their account, personal details and identity theft as a result."));
-               out.println("</p>");
-               out.print("<p style=\"border:dotted 1px #900;padding:0.3em;background-color:#ffe;\"><b>");
-               out.print(translate(
-                               req,
-                               "Note: Please enter your date of birth and names as they are written in your official documents."));
-               out.println("</b><br /><br/>");
-               out.println(translate(
-                               req,
-                               "Because CAcert is a certificate authority (CA) people rely on us knowing about the identity of the users of our certificates. So even as we value privacy very much, we need to collect at least some basic information about our members. This is especially the case for everybody who wants to take part in our web of trust."));
-               out.print(translate(
-                               req,
-                               "Your private information will be used for internal procedures only and will not be shared with third parties."));
-               out.println("</p>");
-               out.print("<p style=\"border:dotted 1px #900;padding:0.3em;background-color:#ffe;\">");
-               out.println(translate(
-                               req,
-                               "A proper password wouldn't match your name or email at all, it contains at least 1 lower case letter, 1 upper case letter, a number, white space and a misc symbol. You get additional security for being over 15 characters and a second additional point for having it over 30. The system starts reducing security if you include any section of your name, or password or email address or if it matches a word from the english dictionary..."));
-               out.println("<br/><br/>");
-               out.print("<b>");
-               out.print(translate(req,
-                               "Note: White spaces at the beginning and end of a password will be removed."));
-               out.println("</b>");
-               out.println("</p>");
+               t.output(out, getLanguage(req), new HashMap<String, Object>());
+               Signup s = new Signup();
+               s.writeForm(out, req);
+       }
+       @Override
+       public void doPost(HttpServletRequest req, ServletResponse resp)
+                       throws IOException {
 
+               super.doPost(req, resp);
        }
 }
diff --git a/src/org/cacert/gigi/pages/main/RegisterPage.templ b/src/org/cacert/gigi/pages/main/RegisterPage.templ
new file mode 100644 (file)
index 0000000..4fbb41d
--- /dev/null
@@ -0,0 +1,11 @@
+<p><?=_By joining CAcert and becoming a member, you agree to the CAcert Community Agreement. Please take a moment now to read that and agree to it; this will be required to complete the process of joining.?></p>
+<p><?=_Warning! This site requires cookies to be enabled to ensure your privacy and security. This site uses session cookies to store temporary values to prevent people from copying and pasting the session ID to someone else exposing their account, personal details and identity theft as a result.?></p>
+<p style="border:dotted 1px #900;padding:0.3em;background-color:#ffe;">
+<b><?=_Note: Please enter your date of birth and names as they are written in your official documents.?></b><br /><br />
+<?=_Because CAcert is a certificate authority (CA) people rely on us knowing about the identity of the users of our certificates. So even as we value privacy very much, we need to collect at least some basic information about our members. This is especially the case for everybody who wants to take part in our web of trust.?>
+<?=_Your private information will be used for internal procedures only and will not be shared with third parties.?>
+</p>
+<p style="border:dotted 1px #900;padding:0.3em;background-color:#ffe;">
+<?=_A proper password wouldn't match your name or email at all, it contains at least 1 lower case letter, 1 upper case letter, a number, white space and a misc symbol. You get additional security for being over 15 characters and a second additional point for having it over 30. The system starts reducing security if you include any section of your name, or password or email address or if it matches a word from the english dictionary...?><br><br>
+<b><?=_Note: White spaces at the beginning and end of a password will be removed.?></b>
+</p>
diff --git a/src/org/cacert/gigi/pages/main/Signup.java b/src/org/cacert/gigi/pages/main/Signup.java
new file mode 100644 (file)
index 0000000..09f50e1
--- /dev/null
@@ -0,0 +1,61 @@
+package org.cacert.gigi.pages.main;
+
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.util.HashMap;
+
+import javax.servlet.ServletRequest;
+
+import org.cacert.gigi.User;
+import org.cacert.gigi.output.DateSelector;
+import org.cacert.gigi.output.Template;
+import org.cacert.gigi.pages.Page;
+import org.cacert.gigi.util.HTMLEncoder;
+
+public class Signup {
+       User buildup = new User();
+       String password;
+       Template t;
+       boolean general = true, country = true, regional = true, radius = true;
+       public Signup() {
+               try {
+                       t = new Template(new InputStreamReader(
+                                       Signup.class.getResourceAsStream("Signup.templ"), "UTF-8"));
+               } catch (UnsupportedEncodingException e) {
+                       e.printStackTrace();
+               }
+               buildup.setFname("");
+               buildup.setMname("");
+               buildup.setLname("");
+               buildup.setSuffix("");
+               buildup.setEmail("");
+               buildup.setDob(new Date(0));
+       }
+       DateSelector myDoB = new DateSelector("day", "month", "year");
+
+       public void writeForm(PrintWriter out, ServletRequest req) {
+               HashMap<String, Object> vars = new HashMap<String, Object>();
+               vars.put("fname", HTMLEncoder.encodeHTML(buildup.getFname()));
+               vars.put("mname", HTMLEncoder.encodeHTML(buildup.getMname()));
+               vars.put("lname", HTMLEncoder.encodeHTML(buildup.getLname()));
+               vars.put("suffix", HTMLEncoder.encodeHTML(buildup.getSuffix()));
+               vars.put("dob", myDoB);
+               vars.put("email", HTMLEncoder.encodeHTML(buildup.getEmail()));
+               vars.put("general", general ? " checked=\"checked\"" : "");
+               vars.put("country", country ? " checked=\"checked\"" : "");
+               vars.put("region", regional ? " checked=\"checked\"" : "");
+               vars.put("radius", radius ? " checked=\"checked\"" : "");
+               vars.put(
+                               "helpOnNames",
+                               String.format(
+                                               Page.translate(req, "Help on Names %sin the wiki%s"),
+                                               "<a href=\"//wiki.cacert.org/FAQ/HowToEnterNamesInJoinForm\" target=\"_blank\">",
+                                               "</a>"));
+               t.output(out, Page.getLanguage(req), vars);
+       }
+       public void update(ServletRequest r) {
+               buildup.setFname(r.getParameter("fname"));
+       }
+}
diff --git a/src/org/cacert/gigi/pages/main/Signup.templ b/src/org/cacert/gigi/pages/main/Signup.templ
new file mode 100644 (file)
index 0000000..ad0fc13
--- /dev/null
@@ -0,0 +1,83 @@
+<form method="post" action="/register" autocomplete="off">
+<table align="center" valign="middle" border="0" cellspacing="0" cellpadding="0" class="wrapper" width="400">
+  <tr>
+    <td colspan="3" class="title"><?=_My Details?></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD" width="125"><?=_First Name?>: </td>
+    <td class="DataTD" width="125"><input type="text" name="fname" size="30" value="<?=$fname?>" autocomplete="off"></td>
+    <td rowspan="4" class="DataTD" width="125"><?=$helpOnNames?></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD" valign="top"><?=_Middle Name(s)?><br>
+      (<?=_optional?>)
+    </td>
+    <td class="DataTD"><input type="text" name="mname" size="30" value="<?=$mname?>" autocomplete="off"></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD"><?=_Last Name?>: </td>
+    <td class="DataTD"><input type="text" name="lname" size="30" value="<?=$lname?>" autocomplete="off"></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD"><?=_Suffix?><br>
+      (<?=_optional?>)</td>
+    <td class="DataTD"><input type="text" name="suffix" size="30" value="<?=$suffix?>" autocomplete="off"><br><?=_Please only write Name Suffixes into this field.?></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD"><?=_Date of Birth?><br>
+           (<?=_dd/mm/yyyy?>)</td>
+    <td class="DataTD"><?=$dob?></td>
+    <td class="DataTD">&nbsp;</td>
+  </tr>
+
+  <tr>
+    <td class="DataTD"><?=_Email Address?>: </td>
+    <td class="DataTD"><input type="text" name="email" size="30" value="<?=$email?>" autocomplete="off"></td>
+    <td class="DataTD"><?=_I own or am authorised to control this email address?></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD"><?=_Pass Phrase?><font color="red">*</font>: </td>
+    <td class="DataTD"><input type="password" name="pword1" size="30" autocomplete="off"></td>
+    <td class="DataTD" rowspan="2">&nbsp;</td>
+  </tr>
+  <tr>
+    <td class="DataTD"><?=_Pass Phrase Again?><font color="red">*</font>: </td>
+    <td class="DataTD"><input type="password" name="pword2" size="30" autocomplete="off"></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD" colspan="3"><font color="red">*</font><?=_Please note, in the interests of good security, the pass phrase must be made up of an upper case letter, lower case letter, number and symbol.?></td>
+  </tr>
+  <tr>
+    <td class="DataTD" colspan="3"><?=_It's possible to get notifications of up and coming events and even just general announcements, untick any notifications you don't wish to receive. For country, regional and radius notifications to work you must choose your location once you've verified your account and logged in.?></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD" valign="top"><?=_Alert me if?>: </td>
+    <td class="DataTD" align="left">
+        <input type="checkbox" name="general" value="1" <?=$general?>><?=_General Announcements?><br>
+       <input type="checkbox" name="country" value="1" <?=$country?>><?=_Country Announcements?><br>
+       <input type="checkbox" name="regional" value="1" <?=$region?>><?=_Regional Announcements?><br>
+       <input type="checkbox" name="radius" value="1" <?=$radius?>><?=_Within 200km Announcements?></td>
+    <td class="DataTD">&nbsp;</td>
+  </tr>
+
+  <tr>
+    <td class="DataTD" colspan="3"><?=_When you click on next, we will send a confirmation email to the email address you have entered above.?></td>
+  </tr>
+  <tr>
+    <td class="DataTD" colspan="3"><input type="checkbox" name="cca_agree" value="1"><?=_I agree to the terms and conditions of the CAcert Community Agreement?>: <a href="/policy/CAcertCommunityAgreement.php">http://www.cacert.org/policy/CAcertCommunityAgreement.php</a></td>
+  </tr>
+
+  <tr>
+    <td class="DataTD" colspan="3"><input type="submit" name="process" value="<?=_Next?>"></td>
+  </tr>
+
+</table>
+</form>
diff --git a/src/org/cacert/gigi/util/HTMLEncoder.java b/src/org/cacert/gigi/util/HTMLEncoder.java
new file mode 100644 (file)
index 0000000..9303d8d
--- /dev/null
@@ -0,0 +1,12 @@
+package org.cacert.gigi.util;
+
+public class HTMLEncoder {
+       public static String encodeHTML(String s) {
+               s = s.replace("&", "&amp;");
+               s = s.replace("<", "&lt;");
+               s = s.replace(">", "&gt;");
+               s = s.replace("\"", "&quot;");
+               s = s.replace("'", "&#39;");
+               return s;
+       }
+}