src/hg/instinct/webUserAdmin/webUserAdmin.c 1.13
1.13 2010/02/08 21:42:17 sbenz
Made checking for admin email more verbose
Index: src/hg/instinct/webUserAdmin/webUserAdmin.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/webUserAdmin/webUserAdmin.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -b -B -U 1000000 -r1.12 -r1.13
--- src/hg/instinct/webUserAdmin/webUserAdmin.c 13 Jan 2010 01:16:16 -0000 1.12
+++ src/hg/instinct/webUserAdmin/webUserAdmin.c 8 Feb 2010 21:42:17 -0000 1.13
@@ -1,1197 +1,1206 @@
/* webUserAdmin - Administer web user account - signup, lost password, etc. */
#include "common.h"
#include "hash.h"
#include "obscure.h"
#include "hgConfig.h"
#include "cheapcgi.h"
#include "memalloc.h"
#include "jksql.h"
#include "htmshell.h"
#include "cart.h"
#include "hPrint.h"
#include "hdb.h"
#include "hui.h"
#include "web.h"
#include "ra.h"
#include "hgColors.h"
#include <crypt.h>
#include "net.h"
#include "webUserAdmin.h"
#include "webUsers.h"
#include "versionInfo.h"
static char const rcsid[] = "$Id$";
char *excludeVars[] = { "submit", "Submit", "debug", "fixMembers", "update", "webUser_password", NULL };
/* The excludeVars are not saved to the cart. (We also exclude
* any variables that start "near.do.") */
/* ---- Global variables. ---- */
struct cart *cart; /* This holds cgi and other variables between clicks. */
char *database; /* Name of genome database - hg15, mm3, or the like. */
struct hash *oldCart; /* Old cart hash. */
char *errMsg; /* Error message to show user when form data rejected */
char *myHostName; /* The host name of this server */
char *siteName; /* The official name of this site */
char *adminEmail; /* admin's email address */
/* -------- password functions ---- */
void encryptPWD(char *password, char *salt, char *buf, int bufsize)
/* encrypt a password */
{
/* encrypt user's password. */
safef(buf,bufsize,crypt(password, salt));
}
void encryptNewPwd(char *password, char *buf, int bufsize)
/* encrypt a new password */
{
unsigned long seed[2];
char salt[] = "$1$........";
const char *const seedchars =
"./0123456789ABCDEFGHIJKLMNOPQRST"
"UVWXYZabcdefghijklmnopqrstuvwxyz";
int i;
/* Generate a (not very) random seed. */
seed[0] = time(NULL);
seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
/* Turn it into printable characters from `seedchars'. */
for (i = 0; i < 8; i++)
salt[3+i] = seedchars[(seed[i/5] >> (i%5)*6) & 0x3f];
encryptPWD(password, salt, buf, bufsize);
}
bool checkPwd(char *password, char *encPassword)
/* check an encrypted password */
{
+if(!password || !encPassword)
+ return FALSE;
char encPwd[35] = "";
encryptPWD(password, encPassword, encPwd, sizeof(encPwd));
if (sameString(encPassword,encPwd))
{
return TRUE;
}
else
{
return FALSE;
}
}
boolean checkPwdCharClasses(char *password)
/* check that password uses at least 2 character classes */
{
/* [A-Z] [a-z] [0-9] [!@#$%^&*()] */
int classes[4]={0,0,0,0};
char c;
while ((c=*password++))
{
if (c >= 'A' && c <= 'Z') classes[0] = 1;
if (c >= 'a' && c <= 'z') classes[1] = 1;
if (c >= '0' && c <= '9') classes[2] = 1;
if (strchr("!@#$%^&*()",c)) classes[3] = 1;
}
return ((classes[0]+classes[1]+classes[2]+classes[3])>=2);
}
unsigned int randInt(unsigned int n)
/* little randome number helper returns 0 to n-1 */
{
return (unsigned int) n * (rand() / (RAND_MAX + 1.0));
}
char *generateRandomPasswordExtended()
/* Smiliar to generateRandomPassword(), but with finer timer resolution seed */
/* Generate valid random password for users who have lost their old one.
* Free the returned value.*/
{
char boundary[256];
char punc[] = "!@#$%^&*()";
char str[200];
struct timeval tim;
/* choose a new string for the boundary */
/* Set initial seed */
int i = 0;
int r = 0;
char c = ' ';
boundary[0]=0;
/* seed it with microsecond to get fine resolution */
gettimeofday(&tim, NULL);
srand((unsigned)tim.tv_usec);
for(i=0;i<8;++i)
{
r = randInt(4);
switch (r)
{
case 0 :
c = 'A' + randInt(26);
break;
case 1 :
c = 'a' + randInt(26);
break;
case 2 :
c = '0' + randInt(10);
break;
default:
c = punc[randInt(10)];
break;
}
boundary[i] = c;
}
boundary[i]=0;
return cloneString(boundary);
}
char *generateRandomPassword()
/* Generate valid random password for users who have lost their old one.
* Free the returned value.*/
{
char boundary[256];
char punc[] = "!@#$%^&*()";
/* choose a new string for the boundary */
/* Set initial seed */
int i = 0;
int r = 0;
char c = ' ';
boundary[0]=0;
srand( (unsigned)time( NULL ) );
for(i=0;i<8;++i)
{
r = randInt(4);
switch (r)
{
case 0 :
c = 'A' + randInt(26);
break;
case 1 :
c = 'a' + randInt(26);
break;
case 2 :
c = '0' + randInt(10);
break;
default:
c = punc[randInt(10)];
break;
}
boundary[i] = c;
}
boundary[i]=0;
return cloneString(boundary);
}
/* --- update passwords file ----- */
void updatePasswordsFile(struct sqlConnection *conn)
/* update the passwords file containing email:encryptedPassword */
{
struct sqlResult *sr;
char **row;
FILE *out = mustOpen("../conf/passwords", "w");
sr = sqlGetResult(conn,
"select email,password from webUsers where activated='Y'"
" and (expireDate='' or (current_date() < expireDate))");
while ((row = sqlNextRow(sr)) != NULL)
{
fprintf(out,"%s:%s\n",row[0],row[1]);
}
sqlFreeResult(&sr);
carefulClose(&out);
}
/* ---------- reverse DNS function --------- */
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
char *reverseDns(char *ip)
/* do reverse dns lookup on ip using getnamebyaddr,
* and then return a string to be freed that is the host */
{
struct hostent *hp;
struct sockaddr_in sock;
if (inet_aton(ip,&sock.sin_addr) == 0) return NULL;
hp = gethostbyaddr(&sock.sin_addr,sizeof(sock.sin_addr),AF_INET);
if (!hp) return NULL;
return cloneString(hp->h_name);
}
/* -------- functions ---- */
void debugShowAllMembers(struct sqlConnection *conn)
/* display all webUsers */
{
struct sqlResult *sr;
char **row;
hPrintf("<h1>Members</h1>");
hPrintf("<table>");
hPrintf("<th>email</th><th>password</th>");
sr = sqlGetResult(conn, "select * from webUsers");
while ((row = sqlNextRow(sr)) != NULL)
{
hPrintf("<tr><td>%s</td><td>%s</td></tr>",row[0],row[1]);
}
sqlFreeResult(&sr);
hPrintf("</table>");
}
void lostPasswordPage(struct sqlConnection *conn)
/* draw the lost password page */
{
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<font color=red>%s</font>"
"<h3>Send Me A New Password</h3>"
"<form method=post action=\"webUserAdmin\" name=lostPasswordForm >"
"<table>"
"<tr><td>E-mail</td><td><input type=text name=webUser_email size=20> "
"(your e-mail is also your user-id)</td></tr>"
"<tr><td> </td><td><input type=submit name=webUserAdmin.do.lostPassword value=submit>"
" <input type=submit name=webUserAdmin.do.signupPage value=cancel></td></tr>"
"</table>"
"<br>"
,siteName
, errMsg ? errMsg : ""
);
cartSaveSession(cart);
hPrintf("</FORM>");
}
void lostPassword(struct sqlConnection *conn)
/* process the lost password form */
{
char query[256];
char cmd[256];
char *email = cartUsualString(cart, "webUser_email", "");
if (!email || sameString(email,""))
{
freez(&errMsg);
errMsg = cloneString("Email cannot be blank.");
lostPasswordPage(conn);
return;
}
safef(query,sizeof(query), "select password from webUsers where email='%s'", email);
char *password = sqlQuickString(conn, query);
if (!password)
{
freez(&errMsg);
errMsg = cloneString("Email not found.");
lostPasswordPage(conn);
return;
}
freez(&password);
password = generateRandomPassword();
char encPwd[35] = "";
encryptNewPwd(password, encPwd, sizeof(encPwd));
safef(query,sizeof(query), "update webUsers set password='%s' where email='%s'", sqlEscapeString(encPwd), sqlEscapeString(email));
sqlUpdate(conn, query);
updatePasswordsFile(conn);
safef(cmd,sizeof(cmd),
"echo 'Your new password is: %s' | mail -s \"Lost password\" %s"
, password, email);
int result = system(cmd);
if (result == -1)
{
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<h3>Error emailing password to: %s</h3>"
"Click <a href=webUserAdmin?webUserAdmin.do.signupPage=1>here</a> to return.<br>"
, siteName
, email
);
}
else
{
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<h3>Password has been emailed to: %s</h3>"
"Click <a href=webUserAdmin?webUserAdmin.do.signupPage=1>here</a> to return.<br>"
, siteName
, email
);
}
freez(&password);
}
void changePasswordPage(struct sqlConnection *conn)
/* change password page */
{
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<font color=red>%s</font>"
"<h3>Change Password</h3>"
"<form method=post action=\"webUserAdmin\" name=changePasswordForm >"
"<table>"
"<tr><td>E-mail</td><td><input type=text name=webUser_email size=20 value=\"%s\"> "
"(your e-mail is also your user-id)</td></tr>"
"<tr><td>Current Password</td><td><input type=password name=webUser_password value=\"\" size=10></td></tr>\n"
"<tr><td>New Password</td><td><input type=password name=webUser_newPassword value=\"\" size=10></td></tr>\n"
"<tr><td>Re-enter new Password</td><td><input type=password name=webUser_newPassword2 value=\"\" size=10></td></tr>\n"
"<tr><td> </td><td><input type=submit name=webUserAdmin.do.changePassword value=submit>"
" <input type=submit name=webUserAdmin.do.signupPage value=cancel></td></tr>"
"</table>"
"<br>"
, siteName
, errMsg ? errMsg : ""
, cartUsualString(cart, "webUser_email", "")
);
cartSaveSession(cart);
hPrintf("</FORM>");
}
void registerBatchWebUsersPage(struct sqlConnection *conn)
/* activate a user page */
{
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<font color=red>%s</font>"
"<h3>Register a batch of user emails</h3>"
"<form method=post action=\"webUserAdmin\" name=registerBatchWebUsersForm >"
"<table>"
"<tr><td>E-mail list of the users to be registered: </td><td><input type=text name=webUser_emailsList size=20 value=\"%s\"> "
"</td></tr>"
"<tr><td>Admin Password</td><td><input type=password name=webUser_adminPassword value=\"\" size=10></td></tr>\n"
"<tr><td> </td><td><input type=submit name=webUserAdmin.do.registerBatchWebUsers value=register>"
" <input type=submit name=webUserAdmin.do.signupPage value=cancel></td></tr>"
"</table>"
"<br>"
, siteName
, errMsg ? errMsg : ""
, cartUsualString(cart, "webUser_emailsList", "")
);
cartSaveSession(cart);
hPrintf("</FORM>");
}
void registerBatchWebUsers(struct sqlConnection *conn)
/* process activate web user form */
{
char query[256];
char *emailsListFileName = cartUsualString(cart, "webUser_emailsList", "");
char *adminPasswordEntered = cartUsualString(cart, "webUser_adminPassword", "");
char cmd[1024];
if (!emailsListFileName || sameString(emailsListFileName, ""))
{
freez(&errMsg);
errMsg = cloneString("E-mail list file name cannot be blank.");
registerBatchWebUsersPage(conn);
return;
}
if (!adminPasswordEntered || sameString(adminPasswordEntered,""))
{
freez(&errMsg);
errMsg = cloneString("Admin password cannot be blank.");
registerBatchWebUsersPage(conn);
return;
}
safef(query,sizeof(query), "select password from webUsers where email='%s'", adminEmail);
char *adminPassword = sqlQuickString(conn, query);
if (!checkPwd(adminPasswordEntered, adminPassword))
{
freez(&errMsg);
errMsg = cloneString("Wrong admin password.");
registerBatchWebUsersPage(conn);
return;
}
else
{
freez(&errMsg);
struct lineFile *lf = lineFileOpen(emailsListFileName, TRUE);
if (lf != NULL)
{
char *line;
int lineSize;
while (lineFileNext(lf, &line, &lineSize))
{
char *password = generateRandomPasswordExtended();
char encPwd[35] = "";
char *webUserEmail;
webUserEmail = line;
safef(query,sizeof(query), "insert into webUsers set email='%s'", webUserEmail);
sqlGetResult(conn, query);
encryptNewPwd(password, encPwd, sizeof(encPwd));
safef(query,sizeof(query),
"update webUsers set password='%s', name='%s', activated='Y' where email='%s'",
sqlEscapeString(encPwd), password, sqlEscapeString(webUserEmail));
// !!! remove inserting password later by replacing the above 2 lines:
//"update webUsers set password='%s', activated='Y' where email='%s'",
//sqlEscapeString(encPwd), sqlEscapeString(webUserEmail));
safef(cmd,sizeof(cmd),
"cat batchLet1.txt |sed -e 's/xx_password/%s/'|sed -e 's/xx_email/%s/g'|sed -e 's/xx_host/%s/'|sed -e 's/xx_adminEmail/%s/'|mail -s \"User account created for you at %s site, %s.\" %s",
password, webUserEmail, myHostName, adminEmail, siteName, myHostName, webUserEmail);
int result = system(cmd);
if (result == -1)
{
errMsg = cloneString("Emailing failed during batch registration.");
registerBatchWebUsersPage(conn);
return;
}
sqlUpdate(conn, query);
updatePasswordsFile(conn);
}
errMsg = cloneString("The batch of emails registered.");
registerBatchWebUsersPage(conn);
return;
}
else
{
errMsg = cloneString("E-mails list file, %s, could not be opened.");
registerBatchWebUsersPage(conn);
return;
}
}
return;
}
void activateWebUserPage(struct sqlConnection *conn)
/* activate a user page */
{
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<font color=red>%s</font>"
"<h3>Activate a web user</h3>"
"<form method=post action=\"webUserAdmin\" name=activateWebUserForm >"
"<table>"
"<tr><td>E-mail of the user to be activated: </td><td><input type=text name=webUser_email size=20 value=\"%s\"> "
"</td></tr>"
"<tr><td>Admin Password</td><td><input type=password name=webUser_adminPassword value=\"\" size=10></td></tr>\n"
"<tr><td> </td><td><input type=submit name=webUserAdmin.do.activateWebUser value=activate>"
" <input type=submit name=webUserAdmin.do.signupPage value=cancel></td></tr>"
"</table>"
"<br>"
, siteName
, errMsg ? errMsg : ""
, cartUsualString(cart, "webUser_email", "")
);
cartSaveSession(cart);
hPrintf("</FORM>");
}
void activateWebUser(struct sqlConnection *conn)
/* process activate web user form */
{
char query[256];
char *email = cartUsualString(cart, "webUser_email", "");
char *adminPasswordEntered = cartUsualString(cart, "webUser_adminPassword", "");
if (!email || sameString(email,""))
{
freez(&errMsg);
errMsg = cloneString("Email cannot be blank.");
activateWebUserPage(conn);
return;
}
if (!adminPasswordEntered || sameString(adminPasswordEntered,""))
{
freez(&errMsg);
errMsg = cloneString("Admin password cannot be blank.");
activateWebUserPage(conn);
return;
}
safef(query,sizeof(query), "select password from webUsers where email='%s'", adminEmail);
char *adminPassword = sqlQuickString(conn, query);
-if (!checkPwd(adminPasswordEntered, adminPassword))
+if(!adminPassword)
+ {
+ freez(&errMsg);
+ errMsg = cloneString("Unable to find admin email in database.");
+ activateWebUserPage(conn);
+ return;
+ }
+else if (!checkPwd(adminPasswordEntered, adminPassword))
{
freez(&errMsg);
errMsg = cloneString("Wrong admin password.");
activateWebUserPage(conn);
return;
}
else
{
freez(&errMsg);
safef(query,sizeof(query), "update webUsers set activated='Y' where email='%s'", email);
sqlUpdate(conn, query);
updatePasswordsFile(conn);
cartRemove(cart, "webUser_adminPassword");
char cmd[1024];
safef(cmd,sizeof(cmd),
"echo \"Hi,\n\n Your request for a user account at %s, %s, has been approved.\n\nWeb User Administrator\nUCSC Cancer Genomics Browser Team.\" | mail -s \"Your user account is approved at %s, %s.\" %s"
, siteName, myHostName, siteName, myHostName, email);
int result = system(cmd);
if (result == -1)
{
hPrintf("<br>Note: sending approved email notice to the user %s failed\n", email);
hPrintf("Click <a href=webUserAdmin?webUserAdmin.do.signupPage=1>here</a> to return.<br>\n");
return;
}
errMsg = cloneString("The web user was activated successfully.");
activateWebUserPage(conn);
return;
}
safef(query,sizeof(query), "select password from webUsers where email='%s'", adminEmail);
char *password = sqlQuickString(conn, query);
if (!password)
{
freez(&errMsg);
errMsg = cloneString("Admin email not found.");
activateWebUserPage(conn);
return;
}
}
void changePassword(struct sqlConnection *conn)
/* process the change password form */
{
char query[256];
char *email = cartUsualString(cart, "webUser_email", "");
char *currentPassword = cartUsualString(cart, "webUser_password", "");
char *newPassword = cartUsualString(cart, "webUser_newPassword", "");
char *newPassword2 = cartUsualString(cart, "webUser_newPassword2", "");
if (!email || sameString(email,""))
{
freez(&errMsg);
errMsg = cloneString("Email cannot be blank.");
changePasswordPage(conn);
return;
}
if (!currentPassword || sameString(currentPassword,""))
{
freez(&errMsg);
errMsg = cloneString("Current password cannot be blank.");
changePasswordPage(conn);
return;
}
if (!newPassword || sameString(newPassword,""))
{
freez(&errMsg);
errMsg = cloneString("New password cannot be blank.");
changePasswordPage(conn);
return;
}
if (!sameWord(newPassword, newPassword2))
{
freez(&errMsg);
errMsg = cloneString("The new password you entered and the one you re-entered must be the same. Please try again.");
changePasswordPage(conn);
return;
}
safef(query,sizeof(query), "select password from webUsers where email='%s'", email);
char *password = sqlQuickString(conn, query);
if (!password)
{
freez(&errMsg);
errMsg = cloneString("Email not found.");
changePasswordPage(conn);
return;
}
if (!checkPwd(currentPassword, password))
{
freez(&errMsg);
errMsg = cloneString("Invalid current password.");
changePasswordPage(conn);
return;
}
freez(&password);
if (!newPassword || sameString(newPassword,"") || (strlen(newPassword)<8))
{
freez(&errMsg);
errMsg = cloneString("New password must be at least 8 characters long.");
changePasswordPage(conn);
return;
}
if (!checkPwdCharClasses(newPassword))
{
freez(&errMsg);
errMsg = cloneString(
"Password must contain characters from 2 of the following 4 classes: "
"[A-Z] [a-z] [0-9] [!@#$%^&*()].");
changePasswordPage(conn);
return;
}
char encPwd[35] = "";
encryptNewPwd(newPassword, encPwd, sizeof(encPwd));
safef(query,sizeof(query), "update webUsers set password='%s' where email='%s'", sqlEscapeString(encPwd), sqlEscapeString(email));
sqlUpdate(conn, query);
hPrintf
(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<h3>Password has been changed.</h3>"
"Click <a href=webUserAdmin?webUserAdmin.do.signupPage=1>here</a> to return.<br>"
, siteName
, email
);
updatePasswordsFile(conn);
cartRemove(cart, "webUser_password");
cartRemove(cart, "webUser_password2");
cartRemove(cart, "webUser_newPassword");
cartRemove(cart, "webUser_newPassword2");
}
void updatePasswordUserInfoPage(struct sqlConnection *conn)
/* change password and update user info page */
{
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<font color=red>%s</font>"
"<h3>Change Password and Update User Info</h3>"
"<form method=post action=\"webUserAdmin\" name=updatePasswordUserInfoForm >"
"<table>"
"<tr><td>E-mail</td><td>%s</td></tr>"
//"<tr><td>E-mail</td><td><input type=text name=webUser_email size=20 value=\"%s\"> "
// "(your e-mail is also your user-id)</td></tr>"
"<tr><td>Initial temporary password</td><td><input type=password name=webUser_password value=\"\" size=10></td></tr>\n"
"<tr><td>New Password</td><td><input type=password name=webUser_newPassword value=\"\" size=10></td></tr>\n"
"<tr><td>Name</td><td><input type=text name=webUser_name size=20></td></tr>\n"
"<tr><td>Phone</td><td><input type=text name=webUser_phone size=20></td></tr>\n"
"<tr><td>Institution</td><td><input type=text name=webUser_institution size=40></td></tr>\n"
"<tr><td> </td><td><input type=submit name=webUserAdmin.do.updatePasswordUserInfo value=submit>"
" <input type=submit name=webUserAdmin.do.signupPage value=cancel></td></tr>"
"</table>"
"<br>"
, siteName
, errMsg ? errMsg : ""
, cartUsualString(cart, "webUser_email", "")
);
cartSaveSession(cart);
hPrintf("</FORM>");
}
void updatePasswordUserInfo(struct sqlConnection *conn)
/* process the change password form */
{
char query[256];
char *email = cartUsualString(cart, "webUser_email", "");
char *currentPassword = cartUsualString(cart, "webUser_password", "");
char *newPassword = cartUsualString(cart, "webUser_newPassword", "");
if (!email || sameString(email,""))
{
freez(&errMsg);
errMsg = cloneString("Email cannot be blank.");
updatePasswordUserInfoPage(conn);
return;
}
if (!currentPassword || sameString(currentPassword,""))
{
freez(&errMsg);
errMsg = cloneString("Current password cannot be blank.");
updatePasswordUserInfoPage(conn);
return;
}
if (!newPassword || sameString(newPassword,""))
{
freez(&errMsg);
errMsg = cloneString("New password cannot be blank.");
updatePasswordUserInfoPage(conn);
return;
}
safef(query,sizeof(query), "select password from webUsers where email='%s'", email);
char *password = sqlQuickString(conn, query);
if (!password)
{
freez(&errMsg);
errMsg = cloneString("Email not found.");
updatePasswordUserInfoPage(conn);
return;
}
if (!checkPwd(currentPassword, password))
{
freez(&errMsg);
errMsg = cloneString("Invalid current password.");
updatePasswordUserInfoPage(conn);
return;
}
freez(&password);
if (!newPassword || sameString(newPassword,"") || (strlen(newPassword)<8))
{
freez(&errMsg);
errMsg = cloneString("New password must be at least 8 characters long.");
updatePasswordUserInfoPage(conn);
return;
}
if (!checkPwdCharClasses(newPassword))
{
freez(&errMsg);
errMsg = cloneString(
"Password must contain characters from 2 of the following 4 classes: "
"[A-Z] [a-z] [0-9] [!@#$%^&*()].");
updatePasswordUserInfoPage(conn);
return;
}
char encPwd[35] = "";
encryptNewPwd(newPassword, encPwd, sizeof(encPwd));
safef(query,sizeof(query), "update webUsers set password='%s' where email='%s'", sqlEscapeString(encPwd), sqlEscapeString(email));
sqlUpdate(conn, query);
/* update user info */
char *name = cartUsualString(cart, "webUser_name", "");
char *phone = cartUsualString(cart, "webUser_phone", "");
char *institution = cartUsualString(cart, "webUser_institution", "");
safef(query,sizeof(query), "update webUsers set name='%s', phone='%s', institution='%s' where email='%s'", sqlEscapeString(name), sqlEscapeString(phone), sqlEscapeString(institution), sqlEscapeString(email));
sqlUpdate(conn, query);
updatePasswordsFile(conn);
hPrintf
(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<h3>Password and user info have been updated.</h3>"
"Click <a href=webUserAdmin?webUserAdmin.do.signupPage=1>here</a> to return.<br>"
, siteName
, email
);
cartRemove(cart, "webUser_password");
cartRemove(cart, "webUser_password2");
cartRemove(cart, "webUser_newPassword");
cartRemove(cart, "webUser_newPassword2");
}
void signupPage(struct sqlConnection *conn)
/* draw the signup page */
{
hPrintf("<h2>%s</h2>\n", siteName);
hPrintf("<p align=\"left\">" "</p>"
"If you are already a member, click <a href=http://%s/>here</a> to access %s at %s.<br>\n",
myHostName, siteName, myHostName);
hPrintf("To view your existing account, click <a href=");
hPrintf("\"webUserAdmin?webUserAdmin.do.displayAccountPage=1\">here</a>.<br>\n");
hPrintf("To change your password, click <a href=");
hPrintf("\"webUserAdmin?webUserAdmin.do.changePasswordPage=1\">here</a>.<br>\n");
hPrintf("To change your password and contact info, click <a href=");
hPrintf("\"webUserAdmin?webUserAdmin.do.updatePasswordUserInfoPage=1\">here</a>.<br>\n");
hPrintf("Lost your password? Click <a href=");
hPrintf("\"webUserAdmin?webUserAdmin.do.lostPasswordPage=1\">here</a>.<br>\n");
/* The following options are shown only for admin */
if (sameWord(cartUsualString(cart, "adminId", ""), adminEmail))
{
hPrintf("<BR>To activate a web user? Click <a href=");
hPrintf("\"webUserAdmin?webUserAdmin.do.activateWebUserPage=1\">here</a>.<br>\n");
hPrintf("To register a batch of web users? Click <a href=");
hPrintf("\"webUserAdmin?webUserAdmin.do.registerBatchWebUsersPage=1\">here</a>.<br>\n");
}
hPrintf("<font color=red>%s</font>", errMsg ? errMsg : "");
hPrintf("<h3>Sign Up</h3>\n"
"<form method=post action=\"webUserAdmin\" name=mainForm >\n"
"NOTE: Your e-mail is also your user login ID.\n");
hPrintf("<br>Password must be at least 8 characters long and it must contain characters");
hPrintf("<br>from 2 of the following 4 classes: [A-Z] [a-z] [0-9] [!@#$%^&*()].<br><br>");
hPrintf("<table>\n"
"<tr><td>E-mail</td><td><input type=text name=webUser_email value=\"%s\"size=20>\n"
"<tr><td>Password</td><td><input type=password name=webUser_password value=\"%s\" size=10></td></tr>\n"
"<tr><td>Re-enter password</td><td><input type=password name=webUser_password2 value=\"%s\" size=10></td></tr>\n"
"<tr><td>Name</td><td><input type=text name=webUser_name value=\"%s\" size=20></td></tr>\n"
"<tr><td>Phone</td><td><input type=text name=webUser_phone value=\"%s\" size=20></td></tr>\n"
"<tr><td>Institution</td><td><input type=text name=webUser_institution value=\"%s\" size=40></td></tr>\n"
"<tr><td> </td><td><input type=submit name=webUserAdmin.do.signup value=submit></td></tr>\n"
"</table>\n"
"<br>\n"
"Questions or problems? Please email <a href=\"mailto:%s\">%s</a>.<br>\n"
, cartUsualString(cart, "webUser_email", "")
, cartUsualString(cart, "webUser_password", "")
, cartUsualString(cart, "webUser_password2", "")
, cartUsualString(cart, "webUser_name", "")
, cartUsualString(cart, "webUser_phone", "")
, cartUsualString(cart, "webUser_institution", "")
//, sameString("commercial",cartUsualString(cart, "webUser_type", "")) ? " checked" : ""
//, sameString("academic",cartUsualString(cart, "webUser_type", "")) ? " checked" : ""
, adminEmail
, adminEmail
);
cartSaveSession(cart);
hPrintf("</FORM>");
}
void signup(struct sqlConnection *conn)
/* process the signup form */
{
char query[256];
char *email = cartUsualString(cart, "webUser_email", "");
if (!email || sameString(email,""))
{
freez(&errMsg);
errMsg = cloneString("Email cannot be blank.");
signupPage(conn);
return;
}
safef(query,sizeof(query), "select password from webUsers where email='%s'", email);
char *password = sqlQuickString(conn, query);
if (password)
{
freez(&errMsg);
errMsg = cloneString("A user with this email address already exists.");
signupPage(conn);
freez(&password);
return;
}
password = cartUsualString(cart, "webUser_password", "");
if (!password || sameString(password,"") || (strlen(password)<8))
{
freez(&errMsg);
errMsg = cloneString("Password must be at least 8 characters long.");
signupPage(conn);
return;
}
char *password2 = cartUsualString(cart, "webUser_password2", "");
if (!sameWord(password, password2))
{
freez(&errMsg);
errMsg = cloneString("The password you entered and the one you re-entered must be the same. Please try again.");
signupPage(conn);
return;
}
if (!checkPwdCharClasses(password))
{
freez(&errMsg);
errMsg = cloneString("Password must contain characters from 2 of the following 4 classes: [A-Z] [a-z] [0-9] [!@#$%^&*()].");
signupPage(conn);
return;
}
char *name = cartUsualString(cart, "webUser_name", "");
if (!name || sameString(name,""))
{
freez(&errMsg);
errMsg = cloneString("Name cannot be blank.");
signupPage(conn);
return;
}
char *phone = cartUsualString(cart, "webUser_phone", "");
if (!phone || sameString(phone,""))
{
freez(&errMsg);
errMsg = cloneString("Phone cannot be blank.");
signupPage(conn);
return;
}
char *institution = cartUsualString(cart, "webUser_institution", "");
if (!institution || sameString(institution,""))
{
freez(&errMsg);
errMsg = cloneString("Institution cannot be blank.");
signupPage(conn);
return;
}
/*
char *type = cartUsualString(cart, "webUser_type", "");
if (!type || sameString(type,""))
{
freez(&errMsg);
errMsg = cloneString("Type cannot be blank.");
signupPage(conn);
return;
}
*/
char encPwd[35] = "";
encryptNewPwd(password, encPwd, sizeof(encPwd));
safef(query,sizeof(query), "insert into webUsers set "
"email='%s',password='%s',activated='%s',name='%s',phone='%s',institution='%s'",
sqlEscapeString(email), sqlEscapeString(encPwd), "N", sqlEscapeString(name), sqlEscapeString(phone), sqlEscapeString(institution));
sqlUpdate(conn, query);
hPrintf(
"<h2>%s</h2>\n"
"<p align=\"left\">\n"
"</p>\n"
"<h3>Thank you for signing up. Your request will be reviewed shortly."
"<br>Upon its approval, you will be notified by an email."
"</h3>\n"
, siteName
);
char cmd[256];
safef(cmd,sizeof(cmd),
"echo \"%s just signed up.\nPlease authorize this person as appropriate. \" | mail -s \"Someone just signed up at %s.\" %s"
, email, myHostName, adminEmail);
int result = system(cmd);
if (result == -1)
{
hPrintf("<br>Note: sending email notice to the reviwer for %s failed\n", email);
}
hPrintf(
"Click <a href=webUserAdmin?webUserAdmin.do.signupPage=1>here</a> to return.<br>\n"
);
}
/* ----- account login/display functions ---- */
void displayAccountPage(struct sqlConnection *conn)
/* draw the account login page */
{
char *email = cartUsualString(cart, "webUser_email", "");
/* for password security, use cgi hash instead of cart */
char *password = cgiUsualString("webUser_password", "");
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<font color=red>%s</font>"
"<h3>Account Login</h3>"
"<form method=post action=\"webUserAdmin\" name=accountLoginForm >"
"<table>"
"<tr><td>E-mail</td><td><input type=text name=webUser_email value=\"%s\" size=20> "
"<tr><td>Password</td><td><input type=password name=webUser_password value=\"%s\" size=10></td></tr>\n"
"(your e-mail is also your user-id)</td></tr>"
"<tr><td> </td><td><input type=submit name=webUserAdmin.do.displayAccount value=submit>"
" <input type=submit name=webUserAdmin.do.signupPage value=cancel></td></tr>"
"</table>"
"<br>"
, siteName
, errMsg ? errMsg : ""
, email
, password
);
cartSaveSession(cart);
hPrintf("</FORM>");
}
void displayAccount(struct sqlConnection *conn)
/* display user account info */
{
struct sqlResult *sr;
char **row;
char query[256];
char *email = cartUsualString(cart, "webUser_email", "");
if (sameString(email,""))
{
freez(&errMsg);
errMsg = cloneString("Email cannot be blank.");
displayAccountPage(conn);
return;
}
/* for password security, use cgi hash instead of cart */
char *password = cgiUsualString("webUser_password", "");
if (sameString(password,""))
{
freez(&errMsg);
errMsg = cloneString("Password cannot be blank.");
displayAccountPage(conn);
return;
}
safef(query,sizeof(query),"select * from webUsers where email='%s'", email);
sr = sqlGetResult(conn, query);
if ((row = sqlNextRow(sr)) == NULL)
{
freez(&errMsg);
char temp[256];
safef(temp,sizeof(temp),"Email %s not found.",email);
errMsg = cloneString(temp);
displayAccountPage(conn);
return;
}
struct webUsers *m = webUsersLoad(row);
sqlFreeResult(&sr);
if (checkPwd(password,m->password))
{
hPrintf("<h1>Account Information</h1>\n",m->email);
hPrintf("<table>\n");
hPrintf("<tr><td align=right>user login ID:</td><td>%s</td><tr>\n",m->email);
hPrintf("<tr><td align=right>name:</td><td>%s</td><tr>\n",m->name);
hPrintf("<tr><td align=right>phone:</td><td>%s</td><tr>\n",m->phone);
hPrintf("<tr><td align=right>institution:</td><td>%s</td><tr>\n",m->institution);
hPrintf("<tr><td align=right>activated:</td><td>%s</td><tr>\n",m->activated);
hPrintf("</table>\n");
hPrintf("<br>\n");
hPrintf("Return to <a href=\"webUserAdmin\">signup</A>.<br>\n");
hPrintf("Go to <a href=\"/\">%s</A>.<br>\n", siteName);
}
else
{
hPrintf("<h1>Invalid User/Password</h1>\n",m->email);
hPrintf("Return to <a href=\"webUserAdmin\">signup</A>.<br>\n");
}
webUsersFree(&m);
}
/*
void upgradeMembersTable(struct sqlConnection* conn)
/ * one-time upgrade of webUsers table to store encrypted passwords * /
{
char query[256];
safef(query,sizeof(query),"select email from webUsers");
struct slName *email=NULL,*list = sqlQuickList(conn,query);
for(email=list;email;email=email->next)
{
uglyf("email=%s<br>\n",email->name);
safef(query,sizeof(query),"select password from webUsers where email='%s'", email->name);
char *password = sqlQuickString(conn,query);
uglyf("password=%s<br>\n",password);
if (password)
{
if (!startsWith("$1$",password)) / * upgrade has not already been done * /
{
uglyf("does not start with $1$<br>\n");
char encPwd[35] = "";
encryptNewPwd(password, encPwd, sizeof(encPwd));
safef(query,sizeof(query),"update webUsers set password = '%s' where email='%s'",
sqlEscapeString(encPwd), sqlEscapeString(email->name));
uglyf("query: %s<br>\n",query);
sqlUpdate(conn,query);
}
freez(&password);
}
uglyf("<br>\n");
}
slFreeList(&list);
}
*/
void doMiddle(struct cart *theCart)
/* Write the middle parts of the HTML page.
* This routine sets up some globals and then
* dispatches to the appropriate page-maker. */
{
struct sqlConnection *conn = hAllocConnProfile("localDb", "membership");
if(!siteName || !adminEmail)
errAbort("Missing required hg.conf variables.\n"
"Please set the following:\n"
"hostname, siteName, adminEmail");
cart = theCart;
if (cartVarExists(cart, "debug"))
debugShowAllMembers(conn);
else if (cartVarExists(cart, "update"))
{
updatePasswordsFile(conn);
hPrintf(
"<h2>%s</h2>"
"<p align=\"left\">"
"</p>"
"<h3>Successfully updated the authentication file.</h3>"
"Click <a href=webUserAdmin?webUserAdmin.do.signupPage=1>here</a> to return.<br>"
, siteName
);
}
else if (cartVarExists(cart, "webUserAdmin.do.lostPasswordPage"))
lostPasswordPage(conn);
else if (cartVarExists(cart, "webUserAdmin.do.lostPassword"))
lostPassword(conn);
else if (cartVarExists(cart, "webUserAdmin.do.changePasswordPage"))
changePasswordPage(conn);
else if (cartVarExists(cart, "webUserAdmin.do.updatePasswordUserInfoPage"))
updatePasswordUserInfoPage(conn);
else if (cartVarExists(cart, "webUserAdmin.do.updatePasswordUserInfo"))
updatePasswordUserInfo(conn);
else if (cartVarExists(cart, "webUserAdmin.do.activateWebUserPage"))
activateWebUserPage(conn);
else if (cartVarExists(cart, "webUserAdmin.do.activateWebUser"))
activateWebUser(conn);
else if (cartVarExists(cart, "webUserAdmin.do.registerBatchWebUsersPage"))
registerBatchWebUsersPage(conn);
else if (cartVarExists(cart, "webUserAdmin.do.registerBatchWebUsers"))
registerBatchWebUsers(conn);
else if (cartVarExists(cart, "webUserAdmin.do.changePassword"))
changePassword(conn);
else if (cartVarExists(cart, "webUserAdmin.do.displayAccountPage"))
displayAccountPage(conn);
else if (cartVarExists(cart, "webUserAdmin.do.displayAccount"))
displayAccount(conn);
else if (cartVarExists(cart, "webUserAdmin.do.signup"))
signup(conn);
else
signupPage(conn);
hFreeConn(&conn);
cartRemovePrefix(cart, "webUserAdmin.do.");
}
void usage()
/* Explain usage and exit. */
{
errAbort(
"webUserAdmin - administer web user account functions - a cgi script\n"
"usage:\n"
" webUserAdmin\n"
);
}
int main(int argc, char *argv[])
/* Process command line. */
{
pushCarefulMemHandler(100000000);
cgiSpoof(&argc, argv);
htmlSetStyle(htmlStyleUndecoratedLink);
htmlSetBgColor(HG_CL_OUTSIDE);
oldCart = hashNew(10);
siteName = cfgOption("siteName");
adminEmail = cfgOption("adminEmail");
myHostName = getenv("HTTP_HOST");
cartHtmlShell(siteName, doMiddle, hUserCookie(), excludeVars, oldCart);
return 0;
}