cc36444ae63d7ffcc6b88fe8988025fe846b9c1b
chinhli
  Mon Jun 4 16:25:55 2012 -0700
Validate email address format.
diff --git src/hg/hgLogin/hgLogin.c src/hg/hgLogin/hgLogin.c
index 929585f..8abfbfb 100644
--- src/hg/hgLogin/hgLogin.c
+++ src/hg/hgLogin/hgLogin.c
@@ -196,30 +196,80 @@
             break;
         case 2 :
             c = '0' + randInt(10);
             break;
         default:
             c = punc[randInt(8)];
             break;
         }
     boundary[i] = c;
     }
 boundary[i]=0;
 return cloneString(boundary);
 }
 
 /* ---- General purpose helper routines. ---- */
+
+int spc_email_isvalid(const char *address) {
+/* Code copied from the book: 
+"Secure Programming Cookbook for C and C++"
+By: John Viega; Matt Messier
+Publisher: O'Reilly Media, Inc.
+Pub. Date: July 14, 2003
+Print ISBN-13: 978-0-596-00394-4
+*/
+int  count = 0;
+const char *c, *domain;
+static char *rfc822_specials = "()<>@,;:\\\"[]";
+
+/* first we validate the name portion (name@domain) */
+for (c = address;  *c;  c++) 
+    {
+    if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) ==  '\"')) 
+        {
+        while (*++c) 
+            {
+            if (*c == '\"') break;
+            if (*c == '\\' && (*++c == ' ')) continue;
+            if (*c <= ' ' || *c >= 127) return 0;
+            }
+         if (!*c++) return 0;
+         if (*c == '@') break;
+         if (*c != '.') return 0;
+         continue;
+        }
+    if (*c == '@') break;
+    if (*c <= ' ' || *c >= 127) return 0;
+    if (strchr(rfc822_specials, *c)) return 0;
+    }
+if (c == address || *(c - 1) == '.') return 0;
+
+/* next we validate the domain portion (name@domain) */
+if (!*(domain = ++c)) return 0;
+do {
+    if (*c == '.') 
+        {
+        if (c == domain || *(c - 1) == '.') return 0;
+        count++;
+        }
+    if (*c <= ' ' || *c >= 127) return 0;
+    if (strchr(rfc822_specials, *c)) return 0;
+} while (*++c);
+
+return (count >= 1);
+}
+
 void backToHgSession(int nSec)
 /* delay for N/10 micro seconds then go back to hgSession page */
 {
 char *hgLoginHost = wikiLinkHost();
 int delay=nSec*100;
 hPrintf("<script  language=\"JavaScript\">\n"
     "<!-- \n"
     "window.setTimeout(afterDelay, %d);\n"
     "function afterDelay() {\n"
     "window.location =\"http://%s/cgi-bin/hgSession?hgS_doMainPage=1\";\n}"
     "\n//-->\n</script>", delay, hgLoginHost);
 }
 
 void backToDoLoginPage(int nSec)
 /* delay for N micro seconds then go back to Login page */
@@ -840,30 +890,38 @@
     errMsg = cloneString("A user with this name already exists.");
     signupPage(conn);
     freez(&user);
     return;
     }
 
 char *email = cartUsualString(cart, "hgLogin_email", "");
 if (!email || sameString(email,""))
     {
     freez(&errMsg);
     errMsg = cloneString("Email cannot be blank.");
     signupPage(conn);
     return;
     }
 
+if (spc_email_isvalid(email) == 0)
+    {
+    freez(&errMsg);
+    errMsg = cloneString("Invalid email address format.");
+    signupPage(conn);
+    return;
+    }
+
 char *email2 = cartUsualString(cart, "hgLogin_email2", "");
 if (!email2 || sameString(email2,"")) 
     {
     freez(&errMsg);
     errMsg = cloneString("Email cannot be blank.");
     signupPage(conn);
     return;
     }
 
 if (email && email2 && !sameString(email, email2))
     {
     freez(&errMsg);
     errMsg = cloneString("Email addresses do not match.");
     signupPage(conn);
     return;