/*
* $Id: user.c,v 1.11.2.13 2006/02/09 05:09:53 tomcollins Exp $
* Copyright (C) 1999-2004 Inter7 Internet Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pwd.h>
#include <dirent.h>
#include <errno.h>
#include <vpopmail_config.h>
#include "vpopmail.h"
/* undef some macros that get redefined in config.h below */
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#include "alias.h"
#include "cgi.h"
#include "config.h"
#include "limits.h"
#include "printh.h"
#include "qmailadmin.h"
#include "qmailadminx.h"
#include "show.h"
#include "template.h"
#include "user.h"
#include "util.h"
#include "vauth.h"
#define HOOKS 1
#ifdef HOOKS
/* note that as of December 2003, only the first three hooks are
implemented */
#define HOOK_ADDUSER "adduser"
#define HOOK_DELUSER "deluser"
#define HOOK_MODUSER "moduser"
#define HOOK_ADDMAILLIST "addmaillist"
#define HOOK_DELMAILLIST "delmaillist"
#define HOOK_MODMAILLIST "modmaillist"
#define HOOK_LISTADDUSER "addlistuser"
#define HOOK_LISTDELUSER "dellistuser"
#endif
void show_users(char *Username, char *Domain, time_t Mytime)
{
if (MaxPopAccounts == 0) return;
send_template("show_users.html");
}
int show_user_lines(char *user, char *dom, time_t mytime, char *dir)
{
int i,j,k,startnumber,moreusers = 1;
FILE *fs;
struct vqpasswd *pw;
int totalpages;
int bounced;
int colspan = 7;
int allowdelete;
char qconvert[11];
if (MaxPopAccounts == 0) return 0;
/* Get the default catchall box name */
if ((fs=fopen(".qmail-default","r")) == NULL) {
/* report error opening .qmail-default and exit */
printf ("<tr><td colspan=\"%i\">%s .qmail-default</tr></td>",
colspan, html_text[144]);
vclose();
exit(0);
}
fgets(TmpBuf, sizeof(TmpBuf), fs);
fclose(fs);
if (*SearchUser) {
pw = vauth_getall(dom,1,1);
for (k=0; pw!=NULL; k++) {
if ((!SearchUser[1] && *pw->pw_name >= *SearchUser) ||
((!strcmp(SearchUser, pw->pw_name)))) {
break;
}
pw = vauth_getall(dom,0,0);
}
if (k == 0) strcpy (Pagenumber, "1");
else sprintf(Pagenumber, "%d", (k/MAXUSERSPERPAGE)+1);
}
/* Determine number of pages */
pw = vauth_getall(dom,1,1);
for (k=0; pw!=NULL; k++) pw = vauth_getall(dom, 0, 0);
if (k == 0) totalpages = 1;
else totalpages = ((k/MAXUSERSPERPAGE)+1);
/* End determine number of pages */
if (atoi(Pagenumber)==0) *Pagenumber='1';
if ( strstr(TmpBuf, " bounce-no-mailbox\n") != NULL ) {
bounced = 1;
} else if ( strstr(TmpBuf, "@") != NULL ) {
bounced = 0;
/* check for local user to forward to */
if (strstr(TmpBuf, dom) != NULL) {
i = strlen(TmpBuf); --i; TmpBuf[i] = 0; /* take off newline */
for(;TmpBuf[i]!=' ';--i);
for(j=0,++i;TmpBuf[i]!=0 && TmpBuf[i]!='@';++j,++i)
TmpBuf3[j] = TmpBuf[i];
TmpBuf3[j]=0;
}
} else {
/* Maildir type catchall */
bounced = 0;
i = strlen(TmpBuf); --i; TmpBuf[i] = 0; /* take off newline */
for(;TmpBuf[i]!='/';--i);
for(j=0,++i;TmpBuf[i]!=0;++j,++i) TmpBuf3[j] = TmpBuf[i];
TmpBuf3[j]=0;
}
startnumber = MAXUSERSPERPAGE * (atoi(Pagenumber) - 1);
/*
* check to see if there are any users to list,
* otherwise repeat previous page
*
*/
pw = vauth_getall(dom,1,1);
if ( AdminType==DOMAIN_ADMIN ||
(AdminType==USER_ADMIN && strcmp(pw->pw_name,Username)==0)){
for (k = 0; k < startnumber; ++k) {
pw = vauth_getall(dom,0,0);
}
}
if (pw == NULL) {
printf ("<tr><td colspan=\"%i\" bgcolor=%s>%s</td></tr>\n",
colspan, get_color_text("000"), html_text[131]);
moreusers = 0;
} else {
char path[256];
while ((pw != NULL) && ((k < MAXUSERSPERPAGE + startnumber) ||
(AdminType!=DOMAIN_ADMIN || AdminType!=DOMAIN_ADMIN ||
(AdminType==USER_ADMIN && strcmp(pw->pw_name,Username)==0)))) {
if (AdminType==DOMAIN_ADMIN ||
(AdminType==USER_ADMIN && strcmp(pw->pw_name,Username)==0)) {
long diskquota = 0;
int maxmsg = 0;
/* display account name and user name */
printf ("<tr bgcolor=%s>", get_color_text("000"));
printh ("<td align=\"left\">%H</td>", pw->pw_name);
printh ("<td align=\"left\">%H</td>", pw->pw_gecos);
/* display user's quota */
snprintf(path, sizeof(path), "%s/" MAILDIR, pw->pw_dir);
readuserquota(path, &diskquota, &maxmsg);
printf ("<td align=\"right\">%-2.2lf / </td>", ((double)diskquota)/1048576.0); /* Convert to MB */
if (strncmp(pw->pw_shell, "NOQUOTA", 2) != 0) {
if(quota_to_megabytes(qconvert, pw->pw_shell)) {
printf ("<td align=\"left\">(BAD)</td>");
}
else { printf ("<td align=\"left\">%s</td>", qconvert); }
}
else { printf ("<td align=\"left\">%s</td>", html_text[229]); }
/* display button to modify user */
printf ("<td align=\"center\">");
printh ("<a href=\"%s/com/moduser?user=%C&dom=%C&time=%d&moduser=%C\">",
CGIPATH,user,dom,mytime,pw->pw_name);
printf ("<img src=\"%s/modify.png\" border=\"0\"></a>", IMAGEURL);
printf ("</td>");
/* if the user has admin privileges and pw->pw_name is not
* the user or postmaster, allow deleting
*/
if (AdminType==DOMAIN_ADMIN &&
strcmp(pw->pw_name, Username) != 0 &&
strcmp(pw->pw_name, "postmaster") != 0) {
allowdelete = 1;
/* else, don't allow deleting */
} else {
allowdelete = 0;
}
/* display trashcan for delete, or nothing if delete not allowed */
printf ("<td align=\"center\">");
if (allowdelete) {
printh ("<a href=\"%s/com/deluser?user=%C&dom=%C&time=%d&deluser=%C\">",
CGIPATH,user,dom,mytime,pw->pw_name);
printf ("<img src=\"%s/trash.png\" border=\"0\"></a>", IMAGEURL);
} else {
/* printf ("<img src=\"%s/disabled.png\" border=\"0\">", IMAGEURL); */
}
printf ("</td>");
/* display button in the 'set catchall' column */
printf ("<td align=\"center\">");
if (bounced==0 && strncmp(pw->pw_name,TmpBuf3,sizeof(TmpBuf3)) == 0) {
printf ("<img src=\"%s/radio-on.png\" border=\"0\"></a>",
IMAGEURL);
} else if (AdminType==DOMAIN_ADMIN) {
printh ("<a href=\"%s/com/setdefault?user=%C&dom=%C&time=%d&deluser=%C&page=%s\">",
CGIPATH,user,dom,mytime,pw->pw_name,Pagenumber);
printf ("<img src=\"%s/radio-off.png\" border=\"0\"></a>",
IMAGEURL);
} else {
printf ("<img src=\"%s/disabled.png\" border=\"0\">",
IMAGEURL);
}
printf ("</td>");
printf ("</tr>\n");
}
pw = vauth_getall(dom,0,0);
++k;
}
}
if (AdminType == DOMAIN_ADMIN) {
print_user_index ("showusers", colspan, user, dom, mytime);
printf ("<tr bgcolor=%s>", get_color_text("000"));
printf ("<td colspan=\"%i\" align=\"right\">", colspan);
#ifdef USER_INDEX
printf ("<font size=\"2\"><b>");
printf ("[ ");
/* only display "previous page" if pagenumber > 1 */
if (atoi(Pagenumber) > 1) {
printh ("<a href=\"%s/com/showusers?user=%C&dom=%C&time=%d&page=%d\">%s</a>",
CGIPATH,user,dom,mytime,
atoi(Pagenumber)-1 ? atoi(Pagenumber)-1 : atoi(Pagenumber),
html_text[135]);
printf (" | ");
}
if (moreusers && atoi(Pagenumber) < totalpages) {
printh ("<a href=\"%s/com/showusers?user=%C&dom=%C&time=%d&page=%d\">%s</a>",
CGIPATH,user,dom,mytime,atoi(Pagenumber)+1,
html_text[137]);
printf (" | ");
}
/* printf (" | ");*/
#endif
printh ("<a href=\"%s/com/deleteall?user=%C&dom=%C&time=%d\">%s</a>",
CGIPATH,user,dom,mytime,html_text[235]);
printf (" | ");
printh ("<a href=\"%s/com/bounceall?user=%C&dom=%C&time=%d\">%s</a>",
CGIPATH,user,dom,mytime,html_text[134]);
printf (" | ");
printh ("<a href=\"%s/com/setremotecatchall?user=%C&dom=%C&time=%d\">%s</a>",
CGIPATH,user,dom,mytime,html_text[206]);
printf (" ]");
printf ("</b></font>");
printf ("</td></tr>\n");
}
return 0;
}
void adduser()
{
count_users();
load_limits();
if ( AdminType!=DOMAIN_ADMIN ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
vclose();
exit(0);
}
if ( MaxPopAccounts != -1 && CurPopAccounts >= MaxPopAccounts ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s %d\n", html_text[199],
MaxPopAccounts);
show_menu(Username, Domain, Mytime);
vclose();
exit(0);
}
send_template( "add_user.html" );
}
void moduser()
{
if (!( AdminType==DOMAIN_ADMIN ||
(AdminType==USER_ADMIN && strcmp(ActionUser,Username)==0))){
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
vclose();
exit(0);
}
send_template( "mod_user.html" );
}
void addusernow()
{
int cnt=0, num;
char *c_num;
char **mailingListNames;
char *tmp;
char *email;
char **arguments;
#ifdef MODIFY_QUOTA
char qconvert[11];
#endif
int pid;
int error;
struct vqpasswd *mypw;
#ifdef MODIFY_SPAM
char spamvalue[50];
static char NewBuf[156];
FILE *fs;
#endif
c_num = malloc(MAX_BUFF);
email = malloc(128);
tmp = malloc(MAX_BUFF);
arguments = (char **)malloc(MAX_BUFF);
count_users();
load_limits();
if ( AdminType!=DOMAIN_ADMIN ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
vclose();
exit(0);
}
if ( MaxPopAccounts != -1 && CurPopAccounts >= MaxPopAccounts ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s %d\n", html_text[199],
MaxPopAccounts);
show_menu(Username, Domain, Mytime);
vclose();
exit(0);
}
GetValue(TmpCGI,Newu, "newu=", sizeof(Newu));
if ( fixup_local_name(Newu) ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s %s\n", html_text[148], Newu);
adduser();
vclose();
exit(0);
}
if ( check_local_user(Newu) ) {
snprinth (StatusMessage, sizeof(StatusMessage), "%s %H\n", html_text[175], Newu);
adduser();
vclose();
exit(0);
}
// Coded added by jhopper
#ifdef MODIFY_QUOTA
GetValue(TmpCGI, Quota, "quota=", sizeof(Quota));
#endif
GetValue(TmpCGI,Password1, "password1=", sizeof(Password1));
GetValue(TmpCGI,Password2, "password2=", sizeof(Password2));
if ( strcmp( Password1, Password2 ) != 0 ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[200]);
adduser();
vclose();
exit(0);
}
#ifndef ENABLE_LEARN_PASSWORDS
if ( strlen(Password1) <= 0 ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[234]);
adduser();
vclose();
exit(0);
}
#endif
snprintf (email, 128, "%s@%s", Newu, Domain);
GetValue(TmpCGI,Gecos, "gecos=", sizeof(Gecos));
if ( strlen( Gecos ) == 0 ) {
strcpy(Gecos, Newu);
}
GetValue(TmpCGI, c_num, "number_of_mailinglist=", MAX_BUFF);
num = atoi(c_num);
if(!(mailingListNames = malloc(sizeof(char *) * num))) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[201]);
vclose();
exit(0);
} else {
for(cnt = 0; cnt < num; cnt++) {
if(!(mailingListNames[cnt] = malloc(MAX_BUFF))) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[201]);
vclose();
exit(0);
}
}
for(cnt = 0; cnt < num; cnt++) {
sprintf(tmp, "subscribe%d=", cnt);
error = GetValue(TmpCGI, mailingListNames[cnt], tmp, MAX_BUFF);
if( error != -1 ) {
pid=fork();
if (pid==0) {
sprintf(TmpBuf1, "%s/ezmlm-sub", EZMLMDIR);
sprintf(TmpBuf2, "%s/%s", RealDir, mailingListNames[cnt]);
execl(TmpBuf1, "ezmlm-sub", TmpBuf2, email, NULL);
exit(127);
} else {
wait(&pid);
}
}
}
}
/* add the user then get the vpopmail password structure */
if ( vadduser( Newu, Domain, Password1, Gecos, USE_POP ) == 0 &&
#ifdef MYSQL_REPLICATION
!sleep(2) &&
#endif
(mypw = vauth_getpw( Newu, Domain )) != NULL ) {
/* vadduser() in vpopmail 5.3.29 and later sets the default
* quota, so we only need to change it if the user enters
* something in the Quota field.
*/
#ifdef MODIFY_QUOTA
if (strcmp (Quota, "NOQUOTA") == 0) {
vsetuserquota (Newu, Domain, "NOQUOTA");
} else if ( Quota[0] != 0 ) {
if(quota_to_bytes(qconvert, Quota)) {
snprintf (StatusMessage, sizeof(StatusMessage), html_text[314]);
} else {
vsetuserquota (Newu, Domain, qconvert);
}
}
#endif
#ifdef MODIFY_SPAM
GetValue(TmpCGI, spamvalue, "spamcheck=", sizeof(spamvalue));
if(strcmp(spamvalue, "on") == 0) {
snprintf(NewBuf, sizeof(NewBuf), "%s/.qmail", mypw->pw_dir);
fs = fopen(NewBuf, "w+");
fprintf(fs, "%s\n", SPAM_COMMAND);
fclose(fs);
}
#endif
/* report success */
snprinth (StatusMessage, sizeof(StatusMessage), "%s %H@%H (%H) %s",
html_text[2], Newu, Domain, Gecos,
html_text[119]);
} else {
/* otherwise, report error */
snprinth (StatusMessage, sizeof(StatusMessage), "<font color=\"red\">%s %H@%H (%H) %s</font>",
html_text[2], Newu, Domain, Gecos, html_text[120]);
}
call_hooks(HOOK_ADDUSER, Newu, Domain, Password1, Gecos);
/* After we add the user, show the user page
* people like to visually verify the results
*/
show_users(Username, Domain, Mytime);
}
int call_hooks(char *hook_type, char *p1, char *p2, char *p3, char *p4)
{
FILE *fs = NULL;
int pid;
char *hooks_path;
char *cmd = NULL;
char *tmpstr;
int error;
hooks_path = malloc(MAX_BUFF);
/* first look in directory for domain */
sprintf(hooks_path, "%s/.qmailadmin-hooks", RealDir);
if((fs = fopen(hooks_path, "r")) == NULL) {
/* then try ~vpopmail/etc */
sprintf(hooks_path, "%s/etc/.qmailadmin-hooks", VPOPMAILDIR);
if((fs = fopen(hooks_path, "r")) == NULL) {
return (0);
}
}
while(fgets(TmpBuf, sizeof(TmpBuf), fs) != NULL) {
if ( (*TmpBuf == '#') || (*TmpBuf == '\0')) continue;
tmpstr = strtok(TmpBuf, " :\t\n");
if (tmpstr == NULL) continue;
if ( strcmp(tmpstr, hook_type) == 0) {
tmpstr = strtok(NULL, " :\t\n");
if ((tmpstr == NULL) || (*tmpstr == '\0')) continue;
cmd = strdup(tmpstr);
break;
}
}
fclose(fs);
if (cmd == NULL) return 0; /* don't have a hook for this type */
pid = fork();
if (pid == 0) {
/* Second param to execl should actually be just the program name,
without the path information. Add a pointer to point into cmd
at the start of the program name only. BUG 2003-12 */
error = execl(cmd, cmd, p1, p2, p3, p4, NULL);
printf ("Error %d %s \"%s\", %s, %s, %s, %s, %s\n",
errno, html_text[202], cmd, hook_type, p1, p2, p3, p4);
/* if (error == -1) return (-1); */
exit(127);
} else {
wait(&pid);
}
return (0);
}
void deluser()
{
send_template( "del_user_confirm.html" );
}
void delusergo()
{
static char forward[200] = "";
static char forwardto[200] = "";
if ( AdminType!=DOMAIN_ADMIN ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
vclose();
exit(0);
}
vdeluser( ActionUser, Domain );
snprinth (StatusMessage, sizeof(StatusMessage), "%H %s", ActionUser, html_text[141]);
/* Start create forward when delete -
* Code added by Eugene Teo 6 June 2000
* Modified by Jeff Hedlund (jeff.hedlund@matrixsi.com) 4 June 2003
*/
GetValue(TmpCGI,forward, "forward=", sizeof(forward));
if (strcmp(forward, "on") == 0) {
GetValue(TmpCGI, forwardto, "forwardto=", sizeof(forwardto));
if(adddotqmail_shared(ActionUser, forwardto, -1)!=0) {
snprintf (StatusMessage, sizeof(StatusMessage), html_text[315], forwardto);
}
}
call_hooks(HOOK_DELUSER, ActionUser, Domain, forwardto, "");
show_users(Username, Domain, Mytime);
}
void count_users()
{
struct vqpasswd *pw;
CurPopAccounts = 0;
pw = vauth_getall(Domain,1,0);
while(pw!=NULL){
++CurPopAccounts;
pw = vauth_getall(Domain,0,0);
}
}
void setremotecatchall()
{
send_template("setremotecatchall.html");
}
void set_qmaildefault(char *opt)
{
FILE *fs;
if ( (fs = fopen(".qmail-default", "w")) == NULL ) {
printf ("%s %s<br>\n", html_text[144], ".qmail-default");
} else {
fprintf(fs,"| %s/bin/vdelivermail '' %s\n", VPOPMAILDIR, opt);
fclose(fs);
}
show_users(Username, Domain, Mytime);
vclose();
exit(0);
}
void setremotecatchallnow()
{
char *fwdaddr;
GetValue(TmpCGI,Newu, "newu=", sizeof(Newu));
if (check_email_addr(Newu) ) {
snprinth (StatusMessage, sizeof(StatusMessage), "%s %H\n", html_text[148], Newu);
setremotecatchall();
exit(0);
}
if (*Newu == '@') {
/* forward all mail to external domain */
fwdaddr = malloc (strlen(Newu) + 4 + 1);
if (fwdaddr != NULL) {
sprintf (fwdaddr, "$EXT%s", Newu);
set_qmaildefault (fwdaddr);
free (fwdaddr);
}
} else {
set_qmaildefault (Newu);
}
}
void bounceall()
{
set_qmaildefault ("bounce-no-mailbox");
}
void deleteall()
{
set_qmaildefault ("delete");
}
int get_catchall()
{
int i,j;
FILE *fs;
/* Get the default catchall box name */
if ((fs=fopen(".qmail-default","r")) == NULL) {
printf ("<tr><td colspan=\"5\">%s %s</td><tr>\n",
html_text[144], ".qmail-default");
vclose();
exit(0);
}
fgets( TmpBuf, sizeof(TmpBuf), fs);
fclose(fs);
if (strstr(TmpBuf, " bounce-no-mailbox\n") != NULL) {
printf ("<b>%s</b>", html_text[130]);
} else if (strstr(TmpBuf, " delete\n") != NULL) {
printf ("<b>%s</b>", html_text[236]);
} else if ( strstr(TmpBuf, "@") != NULL ) {
i=strlen(TmpBuf);
for(;TmpBuf[i-1]!=' ';--i);
if (strncmp (&TmpBuf[i], "$EXT@", 5) == 0) {
/* forward to an entire domain */
printh ("<b>%s <I>user</I>%H</b>", html_text[62], &TmpBuf[i+4]);
} else {
printh ("<b>%s %H</b>", html_text[62], &TmpBuf[i]);
}
} else {
i = strlen(TmpBuf) - 1;
for(;TmpBuf[i]!='/';--i);
for(++i,j=0;TmpBuf[i]!=0;++j,++i) TmpBuf2[j] = TmpBuf[i];
TmpBuf2[j--] = '\0';
/* take off newline */
i = strlen(TmpBuf2); --i; TmpBuf2[i] = 0;/* take off newline */
printh ("<b>%s %H</b>", html_text[62], TmpBuf2);
}
return 0;
}
int makevacation (FILE *d, char *dir)
{
char subject[80];
FILE *f;
char fn[156];
GetValue(TmpCGI, subject, "vsubject=", sizeof(subject));
/* if no subject, error */
if ( (subject == NULL) || (*subject == '\0') ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[216]);
return 1;
}
/* make the vacation directory */
snprintf (fn, sizeof(fn), "%s/vacation", dir);
mkdir (fn, 0750);
fprintf (d, "| %s/autorespond 86400 3 %s/vacation/message %s/vacation\n",
AUTORESPOND_PATH, dir, dir );
/* set up the message file */
snprintf(fn, sizeof(fn), "%s/vacation/message", dir);
GetValue(TmpCGI, Message, "vmessage=", sizeof(Message));
if ( (f = fopen(fn, "w")) == NULL ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s %s\n", html_text[150], fn);
return 1;
}
fprintf(f, "From: %s@%s\n", ActionUser, Domain);
fprintf(f, "Subject: %s\n\n%s", subject, Message);
fclose(f);
return 0;
}
void modusergo()
{
char *tmpstr;
int ret_code;
struct vqpasswd *vpw=NULL;
static char box[500];
char cforward[50];
static char NewBuf[156];
char dotqmailfn[156];
#ifdef MODIFY_QUOTA
char *quotaptr;
char qconvert[11];
#endif
int count;
FILE *fs;
int spam_check = 0;
int vacation = 0;
int saveacopy = 0;
int emptydotqmail;
char *olddotqmail = NULL;
char *dotqmailline;
struct stat sb;
int err;
const char *flagfields[] = { "zeroflag=", "oneflag=", "twoflag=", "threeflag=" };
const gid_t gidflags[] = { V_USER0, V_USER1, V_USER2, V_USER3 };
gid_t orig_gid;
int i;
if (!( AdminType==DOMAIN_ADMIN ||
(AdminType==USER_ADMIN && strcmp(ActionUser,Username)==0))){
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
vclose();
exit(0);
}
if (strlen(Password1)>0 && strlen(Password2)>0 ) {
if ( strcmp( Password1, Password2 ) != 0 ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[200]);
moduser();
vclose();
exit(0);
}
ret_code = vpasswd( ActionUser, Domain, Password1, USE_POP);
if ( ret_code != VA_SUCCESS ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s (%s)", html_text[140],
verror(ret_code));
} else {
/* snprinth (StatusMessage, sizeof(StatusMessage), "%s %H@%H.", html_text[139],
ActionUser, Domain ); */
strcpy (StatusMessage, html_text[139]);
}
}
#ifdef MODIFY_QUOTA
/* strings used: 307 = "Invalid Quota", 308 = "Quota set to unlimited",
* 309 = "Quota set to %s bytes"
*/
if (AdminType == DOMAIN_ADMIN) {
GetValue(TmpCGI, Quota, "quota=", sizeof(Quota));
vpw = vauth_getpw(ActionUser, Domain);
if ((strlen(Quota) == 0) || (strcmp (vpw->pw_shell, Quota) == 0)) {
/* Blank or no change, do nothing */
} else if (strncmp(Quota, "NOQUOTA", 2)==0) {
if (vsetuserquota( ActionUser, Domain, Quota )) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[307]); /* invalid quota */
} else {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[308]);
}
} else if (atoi(Quota)) {
quotaptr = Quota;
if (quota_to_bytes(qconvert, quotaptr)) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[307]);
} else if(strcmp(qconvert, vpw->pw_shell)==0) {
/* unchanged, do nothing */
} else if(vsetuserquota( ActionUser, Domain, qconvert )) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[307]);
} else {
snprintf (StatusMessage, sizeof(StatusMessage), html_text[309], qconvert);
}
} else {
snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[307]);
}
}
#endif
GetValue(TmpCGI,Gecos, "gecos=", sizeof(Gecos));
vpw = vauth_getpw (ActionUser, Domain);
/* check for the V_USERx flags and set accordingly */
/* new code by Tom Collins <tom@tomlogic.com>, Dec 2004 */
/* replaces code by James Raftery <james@now.ie>, 12 Dec. 2002 */
orig_gid = vpw->pw_gid;
for (i = 0; i < 4; i++) {
GetValue (TmpCGI, box, (char *) flagfields[i], sizeof (box));
if (strcmp (box, "on") == 0)
vpw->pw_gid |= gidflags[i];
else if (strcmp (box, "off") == 0)
vpw->pw_gid &= ~gidflags[i];
}
/* we're trying to cut down on unnecessary updates to the password entry
* we accomplish this by only updating if the pw_gid or gecos changed
*/
if ((*Gecos != '\0') && (strcmp (Gecos, vpw->pw_gecos) != 0)) {
vpw->pw_gecos = Gecos;
vauth_setpw(vpw, Domain);
} else if (vpw->pw_gid != orig_gid) vauth_setpw (vpw, Domain);
/* get value of the spam filter box */
GetValue(TmpCGI, box, "spamcheck=", sizeof(box));
if ( strcmp(box, "on") == 0 ) spam_check = 1;
/* get the value of the vacation checkbox */
GetValue(TmpCGI, box, "vacation=", sizeof(box));
if ( strcmp(box, "on") == 0 ) vacation = 1;
/* if they want to save a copy */
GetValue(TmpCGI, box, "fsaved=", sizeof(box));
if ( strcmp(box,"on") == 0 ) saveacopy = 1;
/* get the value of the cforward radio button */
GetValue(TmpCGI, cforward, "cforward=", sizeof(cforward));
if ( strcmp(cforward, "vacation") == 0 ) vacation = 1;
/* open old .qmail file if it exists and load it into memory */
snprintf (dotqmailfn, sizeof(dotqmailfn), "%s/.qmail", vpw->pw_dir);
err = stat (dotqmailfn, &sb);
if (err == 0) {
olddotqmail = malloc (sb.st_size);
if (olddotqmail != NULL) {
fs = fopen (dotqmailfn, "r");
if (fs != NULL) {
fread (olddotqmail, sb.st_size, 1, fs);
fclose (fs);
}
}
}
fs = fopen (dotqmailfn, "w");
/* Scan through old .qmail and write out any unrecognized program delivery
* lines to the new .qmail file.
*/
emptydotqmail = 1;
if (olddotqmail != NULL) {
dotqmailline = strtok (olddotqmail, "\n");
while (dotqmailline) {
if ( (*dotqmailline == '|') &&
(strstr (dotqmailline, "/true delete") == NULL) &&
(strstr (dotqmailline, "/autorespond ") == NULL) &&
(strstr (dotqmailline, SPAM_COMMAND) == NULL) ) {
fprintf (fs, "%s\n", dotqmailline);
emptydotqmail = 0;
}
dotqmailline = strtok (NULL, "\n");
}
free (olddotqmail);
}
/* Decide on what to write to the new .qmail file after any old program
* delivery lines are written.
*/
err = 0;
/* note that we consider a .qmail file with just Maildir delivery to be empty
* since it can be removed.
*/
/* if they want to forward */
if (strcmp (cforward, "forward") == 0 ) {
/* get the value of the foward */
GetValue(TmpCGI, box, "nforward=", sizeof(box));
/* If nothing was entered, error */
if ( box[0] == 0 ) {
snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[215]);
err = 1;
} else {
tmpstr = strtok(box," ,;\n");
/* tmpstr points to first non-token */
count=0;
while( tmpstr != NULL && count < MAX_FORWARD_PER_USER) {
if ((*tmpstr != '|') && (*tmpstr != '/')) {
fprintf(fs, "&%s\n", tmpstr);
emptydotqmail = 0;
++count;
}
tmpstr = strtok(NULL," ,;\n");
}
}
}
if ( (strcmp (cforward, "forward") != 0) || saveacopy ) {
if (strcmp (cforward, "blackhole") == 0) {
fprintf (fs, "# delete\n");
emptydotqmail = 0;
} else if (spam_check == 1) {
fprintf (fs, "%s\n", SPAM_COMMAND);
emptydotqmail = 0;
} else {
fprintf (fs, "%s/" MAILDIR "/\n", vpw->pw_dir);
/* this isn't enough to consider the .qmail file non-empty */
}
}
if (vacation) {
err = makevacation (fs, vpw->pw_dir);
emptydotqmail = 0;
} else {
/* delete old vacation directory */
snprintf (NewBuf, sizeof(NewBuf), "%s/vacation", vpw->pw_dir);
vdelfiles (NewBuf);
}
fclose (fs);
if (emptydotqmail) unlink (dotqmailfn);
if (err) {
moduser();
vclose();
exit(0);
}
call_hooks(HOOK_MODUSER, ActionUser, Domain, Password1, Gecos);
moduser();
}
/* display ##i0 - ##i9 macros */
void parse_users_dotqmail (char newchar)
{
static struct vqpasswd *vpw = NULL;
static FILE *fs1=NULL; /* for the .qmail file */
static FILE *fs2=NULL; /* for the vacation message file */
int i, j;
char fn[500];
char linebuf[256];
int inheader;
static unsigned int dotqmail_flags = 0;
#define DOTQMAIL_STANDARD (1<<0)
#define DOTQMAIL_FORWARD (1<<1)
#define DOTQMAIL_SAVECOPY (1<<3)
#define DOTQMAIL_VACATION (1<<4)
#define DOTQMAIL_BLACKHOLE (1<<8)
#define DOTQMAIL_SPAMCHECK (1<<9)
#define DOTQMAIL_OTHERPGM (1<<14)
if (vpw == NULL) vpw = vauth_getpw(ActionUser, Domain);
if (vpw == NULL) return;
if (fs1 == NULL) {
snprintf (fn, sizeof(fn), "%s/.qmail", vpw->pw_dir);
fs1 = fopen (fn, "r");
if (fs1 == NULL) {
/* no .qmail file, standard delivery */
dotqmail_flags = DOTQMAIL_STANDARD;
} else {
while (fgets (linebuf, sizeof(linebuf), fs1) != NULL) {
i = strlen (linebuf);
/* strip trailing newline if any */
if (i && (linebuf[i-1] == '\n')) linebuf[i-1] = '\0';
switch (*linebuf) {
case '\0': /* blank line, ignore */
break;
case '.':
case '/': /* maildir delivery */
/* see if it's the user's maildir */
if (1)
dotqmail_flags |= DOTQMAIL_SAVECOPY;
break;
case '|': /* program delivery */
/* in older versions of QmailAdmin, we used "|/bin/true delete"
* for blackhole accounts. Since the path to true may vary,
* just check for the end of the string
*/
if (strstr (linebuf, "/true delete") != NULL)
dotqmail_flags |= DOTQMAIL_BLACKHOLE;
else if (strstr (linebuf, "/autorespond ") != NULL) {
dotqmail_flags |= DOTQMAIL_VACATION;
snprintf (fn, sizeof(fn), "%s/vacation/message", vpw->pw_dir);
fs2 = fopen (fn, "r");
}
else if (strstr (linebuf, SPAM_COMMAND) != NULL )
dotqmail_flags |= DOTQMAIL_SPAMCHECK;
else /* unrecognized program delivery, set a flag so we don't blackhole */
dotqmail_flags |= DOTQMAIL_OTHERPGM;
break;
case '#': /* comment */
/* ignore unless it's our 'blackhole' comment */
if (strcmp (linebuf, "# delete") == 0)
dotqmail_flags |= DOTQMAIL_BLACKHOLE;
break;
default: /* email address delivery */
dotqmail_flags |= DOTQMAIL_FORWARD;
}
}
/* if other flags were set, in addition to blackhole, clear blackhole flag */
if ( dotqmail_flags & (DOTQMAIL_FORWARD | DOTQMAIL_SAVECOPY) )
dotqmail_flags &= ~DOTQMAIL_BLACKHOLE;
/* if no flags were set (.qmail file without delivery), it's a blackhole */
if (dotqmail_flags == 0)
dotqmail_flags = DOTQMAIL_BLACKHOLE;
/* clear OTHERPGM flag, as it tells us nothing at this point */
dotqmail_flags &= ~DOTQMAIL_OTHERPGM;
/* if forward and save-a-copy are set, it will actually set the spam flag */
if ((dotqmail_flags & DOTQMAIL_FORWARD) && (dotqmail_flags & DOTQMAIL_SPAMCHECK))
dotqmail_flags |= DOTQMAIL_SAVECOPY;
/* if forward is not set, clear save-a-copy */
if (! (dotqmail_flags & DOTQMAIL_FORWARD))
dotqmail_flags &= ~DOTQMAIL_SAVECOPY;
}
/* if deleted and forward aren't set, */
/* default to standard delivery */
if (! (dotqmail_flags & (DOTQMAIL_BLACKHOLE | DOTQMAIL_FORWARD)) )
dotqmail_flags |= DOTQMAIL_STANDARD;
}
switch (newchar) {
case '0': /* standard delivery checkbox */
case '1': /* forward delivery checkbox */
case '3': /* save-a-copy checkbox */
case '4': /* vacation checkbox */
case '8': /* blackhole checkbox */
case '9': /* spam check checkbox */
if (dotqmail_flags & (1 << (newchar - '0'))) printf ("checked ");
break;
case '2': /* forwarding addresses */
if (fs1 != NULL) {
rewind (fs1);
j = 0;
while (fgets (linebuf, sizeof(linebuf), fs1) != NULL) {
i = strlen (linebuf);
/* strip trailing newline if any */
if (i && (linebuf[i-1] == '\n')) linebuf[i-1] = '\0';
switch (*linebuf) {
case '\0': /* blank line */
case '/': /* maildir delivery */
case '|': /* program delivery */
case '#': /* comment */
/* ignore */
break;
default: /* email address delivery */
/* print address, skipping over '&' if necessary */
if (j++) printf (", ");
printh ("%H", &linebuf[(*linebuf == '&' ? 1 : 0)], "\n");
}
}
}
break;
case '5': /* vacation subject */
if (fs2 != NULL) {
rewind (fs2);
/* scan headers for Subject */
while (fgets (linebuf, sizeof(linebuf), fs2) != NULL) {
if (*linebuf == '\n') break;
if (strncasecmp (linebuf, "Subject: ", 9) == 0)
printh ("%H", &linebuf[9]);
}
}
break;
case '6': /* vacation message */
if (fs2 != NULL) {
rewind (fs2);
/* read from file, skipping headers (look for first blank line) */
inheader = 1;
while (fgets (linebuf, sizeof(linebuf), fs2) != NULL) {
if (!inheader) printh ("%H", linebuf);
if (*linebuf == '\n') inheader = 0;
}
}
break;
case '7': /* gecos (real name) */
printh ("%H", vpw->pw_gecos);
break;
}
}
syntax highlighted by Code2HTML, v. 0.9.1