/* * $Id: template.c,v 1.7.2.13 2005/01/23 17:35:12 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 #include #include #include #include #include #include #include #include #include #include /* undef some macros that get redefined in config.h below */ #undef PACKAGE_NAME #undef PACKAGE_STRING #undef PACKAGE_TARNAME #undef PACKAGE_VERSION #include #include "alias.h" #include "autorespond.h" #include "cgi.h" #include "config.h" #include "forward.h" #include "limits.h" #include "mailinglist.h" #include "printh.h" #include "qmailadmin.h" #include "qmailadminx.h" #include "template.h" #include "user.h" #include "util.h" static char dchar[4]; void check_mailbox_flags(char newchar); void transmit_block(FILE *fs); void ignore_to_end_tag(FILE *fs); void get_calling_host(); char *get_session_val(char *session_var); /* * send an html template to the browser */ int send_template(char *actualfile) { send_template_now("header.html"); send_template_now(actualfile); send_template_now("footer.html"); return 0; } int send_template_now(char *filename) { FILE *fs; int i; int j; int inchar; char *tmpstr; struct stat mystat; char qconvert[11]; char *qnote = " MB"; struct vqpasswd *vpw; char value[MAX_BUFF]; char value2[MAX_BUFF]; if (strstr(filename, "/")!= NULL||strstr(filename,"..")!=NULL) { printf("warning: invalid file name %s\n", filename ); return(-1); } tmpstr = getenv(QMAILADMIN_TEMPLATEDIR); if (tmpstr == NULL ) tmpstr = HTMLLIBDIR; snprintf(TmpBuf2, (sizeof(TmpBuf2) - 1), "%s/html/%s", tmpstr, filename); if (lstat(TmpBuf2, &mystat) == -1) { printf("Warning: cannot lstat '%s', check permissions.
\n", TmpBuf2); return(-1); } if (S_ISLNK(mystat.st_mode)) { printf("Warning: '%s' is a symbolic link.
\n", TmpBuf2); return(-1); } /* open the template */ fs = fopen( TmpBuf2, "r" ); if (fs == NULL) { printf ("%s %s
\n", html_text[144], TmpBuf2); return 0; } /* parse the template looking for "##" pattern */ while ((inchar = fgetc(fs)) >= 0) { /* if not '#' then send it */ if (inchar != '#') { fputc(inchar, actout); /* found a '#' */ } else { /* look for a second '#' */ inchar = fgetc(fs); if (inchar < 0) { break; /* found a tag */ } else if (inchar == '#') { inchar = fgetc(fs); if (inchar < 0) break; /* switch on the tag */ switch (inchar) { /* send stock (user, dom, time) cgi parameters */ case '&': printh ("user=%C&dom=%C&time=%d&", Username, Domain, Mytime); break; case '~': printf ("%s", Lang); break; /* send the action user parameter */ case 'A': printh ("%H", ActionUser); break; /* send the Alias parameter */ case 'a': printh ("%H", Alias); break; /* show number of pop accounts */ case 'B': load_limits(); count_users(); if(MaxPopAccounts > -1) { printf("%d/%d", CurPopAccounts, MaxPopAccounts); } else { printf("%d/%s", CurPopAccounts, html_text[229]); } break; /* show the lines inside a alias table (not used, see ##d) */ case 'b': show_dotqmail_lines(Username,Domain,Mytime); break; /* send the CGIPATH parameter */ case 'C': printf ("%s", CGIPATH); break; /* show the lines inside a mailing list table */ case 'c': show_mailing_list_line2(Username,Domain,Mytime,RealDir); break; /* send the domain parameter */ case 'D': printh ("%H", Domain); break; /* show the lines inside a forward table */ case 'd': show_dotqmail_lines(Username,Domain,Mytime); break; /* this will be used to parse mod_mailinglist-idx.html */ case 'E': show_current_list_values(); break; /* show the lines inside a mailing list table */ case 'e': show_mailing_list_line(Username,Domain,Mytime,RealDir); break; /* display a file (used for mod_autorespond ONLY) */ /* this code should be moved to a function in autorespond.c */ case 'F': { FILE *fs; char *alias_line; alias_line = valias_select (ActionUser, Domain); /* should verify here that alias_line contains "/autorespond " */ if ( (alias_line = valias_select_next()) ) { strcpy (TmpBuf2, alias_line); /* See if it's a Maildir path rather than address */ i = strlen(TmpBuf2) - 1; if (TmpBuf2[i] == '/') { --i; for(; TmpBuf2[i] != '/'; --i); --i; for(;TmpBuf2[i]!='/';--i); for(++i, j=0; TmpBuf2[i] != '/'; ++j,++i) { TmpBuf3[j] = TmpBuf2[i]; } TmpBuf3[j] = '\0'; printh ("value=\"%H@%H\">\n", TmpBuf3, Domain); } else { printh ("value=\"%H\">\n", &TmpBuf2[1]); } } upperit(ActionUser); sprintf(TmpBuf, "%s/message", ActionUser); if ((fs = fopen(TmpBuf, "r")) == NULL) ack("150", TmpBuf); fgets( TmpBuf2, sizeof(TmpBuf2), fs); fgets( TmpBuf2, sizeof(TmpBuf2), fs); printf ("  \n"); printf (" \n"); printf (" \n"); printf (" %s\n", html_text[6]); /* take off newline */ i = strlen(TmpBuf2); --i; TmpBuf2[i] = 0; printh (" \n", &TmpBuf2[9]); printf ("  \n"); printf (" \n"); printf (" \n"); printf (" "); fclose(fs); } break; /* show the forwards */ case 'f': if (AdminType == DOMAIN_ADMIN) { show_forwards(Username,Domain,Mytime); } break; /* show the mailing list digest subscribers */ case 'G': if (AdminType == DOMAIN_ADMIN) { show_list_group_now(2); } break; /* show the lines inside a autorespond table */ case 'g': show_autorespond_line(Username,Domain,Mytime,RealDir); break; /* show returnhttp (from TmpCGI) */ case 'H': GetValue (TmpCGI, value, "returnhttp=", sizeof(value)); printh ("%H", value); break; /* show the counts */ case 'h': show_counts(); break; case 'I': show_dotqmail_file(ActionUser); break; /* check for user forward and forward/store vacation */ case 'i': parse_users_dotqmail( fgetc(fs) ); break; /* show mailbox flag status */ /* James Raftery 12 Dec. 2002 */ case 'J': check_mailbox_flags(fgetc(fs)); break; /* show number of mailing lists */ /* Added by 5th June 2003 */ case 'j': load_limits(); count_mailinglists(); if(MaxMailingLists > -1) { printf("%d/%d", CurMailingLists, MaxMailingLists); } else { printf("%d/%s", CurMailingLists, html_text[229]); } break; /* show number of forwards */ /* Added by 5th June 2003 */ case 'k': load_limits(); count_forwards(); if(MaxForwards > -1) { printf("%d/%d", CurForwards, MaxForwards); } else { printf("%d/%s", CurForwards, html_text[229]); } break; /* show number of autoresponders */ /* Added by 5th June 2003 */ case 'K': load_limits(); count_autoresponders(); if(MaxAutoResponders > -1) { printf("%d/%d", CurAutoResponders, MaxAutoResponders); } else { printf("%d/%s", CurAutoResponders, html_text[229]); } break; /* show the aliases stuff */ case 'l': if (AdminType == DOMAIN_ADMIN) { show_aliases(); } break; /* login username */ case 'L': if(strlen(Username)>0) { printh ("%H", Username); } else if(TmpCGI && GetValue(TmpCGI, value, "user=", sizeof(value))==0) { printh ("%H", value); } else printf("postmaster"); break; /* show the mailing list subscribers */ case 'M': if (AdminType == DOMAIN_ADMIN) { show_list_group_now(0); } break; /* show the mailing lists */ case 'm': if (AdminType == DOMAIN_ADMIN) { show_mailing_lists(Username,Domain,Mytime); } break; /* parse include files */ case 'N': i=0; TmpBuf[i]=fgetc(fs); if (TmpBuf[i] == '/') { printf ("%s", html_text[144]); } else { for(;TmpBuf[i] != '\0' && TmpBuf[i] != '#' && i < sizeof(TmpBuf)-1;) { TmpBuf[++i] = fgetc(fs); } TmpBuf[i] = '\0'; if ((strstr(TmpBuf, "../")) != NULL) { printf ("%s: %s", html_text[144], TmpBuf); } else if((strcmp(TmpBuf, filename)) != 0) { send_template_now(TmpBuf); } } break; /* show returntext (from TmpCGI) */ case 'n': GetValue (TmpCGI, value, "returntext=", sizeof(value)); printh ("%H", value); break; /* build a pulldown menu of all POP/IMAP users */ case 'O': { struct vqpasswd *pw; pw = vauth_getall(Domain,1,1); while (pw != NULL) { printh ("\n", pw->pw_name, pw->pw_name); pw = vauth_getall(Domain,0,0); } } break; /* show the mailing list moderators */ case 'o': if (AdminType == DOMAIN_ADMIN) { show_list_group_now(1); } break; /* display mailing list prefix */ case 'P': { TmpBuf3[0] = '\0'; get_mailinglist_prefix(TmpBuf3); printh ("%H", TmpBuf3); } break; /* show POP/IMAP users */ case 'p': show_user_lines(Username, Domain, Mytime, RealDir); break; /* display user's quota (mod user page) */ case 'q': vpw = vauth_getpw(ActionUser, Domain); if (strncmp(vpw->pw_shell, "NOQUOTA", 2) != 0) { quota_to_megabytes(qconvert, vpw->pw_shell); printf("%s", qconvert); } else { if(AdminType == DOMAIN_ADMIN) printf("NOQUOTA"); else printf(html_text[229]); } break; /* show returntext/returnhttp if set in CGI vars */ case 'R': GetValue (TmpCGI, value, "returntext=", sizeof(value)); GetValue (TmpCGI, value2, "returnhttp=", sizeof(value2)); if (*value != '\0') { printh ("%H", value2, value); } break; /* show the autoresponder stuff */ case 'r': if (AdminType == DOMAIN_ADMIN) { show_autoresponders(Username,Domain,Mytime); } break; /* send the status message parameter */ case 'S': printf ("%s", StatusMessage); break; /* show the catchall name */ case 's': get_catchall(); break; /* send the time parameter */ case 'T': printf ("%u", (unsigned int) Mytime); break; /* transmit block? */ case 't': transmit_block(fs); break; /* send the username parameter */ case 'U': printh ("%H", Username); break; /* show the users */ case 'u': show_users(Username,Domain,Mytime); break; /* show version number */ case 'V': printf("%s %s
", QA_PACKAGE, QA_VERSION); printf("%s %s
", PACKAGE, VERSION); break; /* display the main menu */ /* move this to a function... */ case 'v': printh ("%H

", Domain); printf ( "%s
", html_text[1]); if (AdminType==DOMAIN_ADMIN){ if (MaxPopAccounts != 0) { printh ( "", CGIPATH,Username,Mytime,Domain); printf ( "%s
", html_text[61]); } if (MaxForwards != 0 || MaxAliases != 0) { printh ( "", CGIPATH,Username,Mytime,Domain); printf ( "%s
", html_text[122]); } if (MaxAutoResponders != 0) { printh ( "", CGIPATH,Username,Mytime,Domain); printf ( "%s
", html_text[77]); } if (*EZMLMDIR != 'n' && MaxMailingLists != 0) { printh ( "", CGIPATH, Username,Mytime,Domain); printf ( "%s
", html_text[80]); } } else { /* the quota code in here is kinda screwy and could use review * then again, with recent changes, the non-admin shouldn't * even get to this page. */ long diskquota = 0; int maxmsg = 0; char path[256]; vpw = vauth_getpw(Username, Domain); printh ( "", CGIPATH,Username,Mytime,Domain,Username); printh ( "%s %H

", html_text[111], Username); if (strncmp(vpw->pw_shell, "NOQUOTA", 2) != 0) { quota_to_megabytes(qconvert, vpw->pw_shell); } else { sprintf(qconvert, html_text[229]); qnote = ""; } printf ("%s:
%s %s %s", html_text[249], html_text[253], qconvert, qnote); printf ("
%s ", html_text[254]); snprintf(path, sizeof(path), "%s/" MAILDIR, vpw->pw_dir); readuserquota(path, &diskquota, &maxmsg); printf ("%-2.2lf MB

", ((double)diskquota)/1048576.0); /* Convert to MB */ } if (AdminType == DOMAIN_ADMIN) { printf ("
"); if (MaxPopAccounts != 0) { printh ( "", CGIPATH,Username,Mytime,Domain); printf ( "%s
", html_text[125]); } if (MaxForwards != 0) { printh ( "", CGIPATH, Username,Mytime,Domain); printf ( "%s
", html_text[127]); } if (MaxAutoResponders != 0) { printh ( "", CGIPATH, Username,Mytime,Domain); printf ( "%s
", html_text[128]); } if (*EZMLMDIR != 'n' && MaxMailingLists != 0) { printh ( "", CGIPATH, Username,Mytime,Domain); printf ( "%s
", html_text[129]); } } break; /* Password */ case 'W': printh ("%H", Password); break; /* dictionary entry, followed by three more chars for the entry # */ case 'X': for(i=0;i<3;++i) dchar[i] = fgetc(fs); dchar[i] = 0; i = atoi(dchar); if ((i >= 0) && (i <= MAX_LANG_STR)) printf("%s", html_text[atoi(dchar)]); break; /* exit / logout link/text */ case 'x': printf("%H", get_session_val("returnhttp="), value); } else { printh("%s/com/logout?user=%C&dom=%C&time=%d&\">%s", CGIPATH, Username, Domain, Mytime, html_text[218]); } printf("\n"); break; /* returnhttp */ case 'y': printf("%s", get_session_val("returnhttp=")); break; /* returntext */ case 'Y': printf("%s", get_session_val("returntext=")); break; /* send the image URL directory */ case 'Z': printf ("%s", IMAGEURL); break; /* display domain on login page (last used, value of dom in URL, * or guess from hostname in URL). */ case 'z': if( strlen(Domain) > 0 ) { printh("%H", Domain); } else if(TmpCGI && GetValue(TmpCGI, value, "dom=", sizeof(value))==0) { printh("%H", value); #ifdef DOMAIN_AUTOFILL } else { get_calling_host(); #endif } break; default: break; } /* * didn't find a tag, so send out the first '#' and * the current character * */ } else { fputc('#', actout); fputc(inchar, actout); } } } fclose(fs); fflush(actout); vclose(); return 0; } /* Display status of mailbox flags */ /* James Raftery 12 Dec. 2002 / 15 Apr. 2003 */ void check_mailbox_flags(char newchar) { static struct vqpasswd *vpw = NULL; if (vpw==NULL) vpw = vauth_getpw(ActionUser, Domain); switch (newchar) { /* 1: "checked" if V_USER0 is set */ /* 2: "checked" if V_USER0 is unset */ case '1': if (vpw->pw_gid & V_USER0) printf("checked"); break; case '2': if (!(vpw->pw_gid & V_USER0)) printf("checked"); break; /* 3: "checked" if V_USER1 is set */ /* 4: "checked" if V_USER1 is unset */ case '3': if (vpw->pw_gid & V_USER1) printf("checked"); break; case '4': if (!(vpw->pw_gid & V_USER1)) printf("checked"); break; /* 5: "checked" if V_USER2 is set */ /* 6: "checked" if V_USER2 is unset */ case '5': if (vpw->pw_gid & V_USER2) printf("checked"); break; case '6': if (!(vpw->pw_gid & V_USER2)) printf("checked"); break; /* 7: "checked" if V_USER3 is set */ /* 8: "checked" if V_USER3 is unset */ case '7': if (vpw->pw_gid & V_USER3) printf("checked"); break; case '8': if (!(vpw->pw_gid & V_USER3)) printf("checked"); break; default: break; } return; } void transmit_block(FILE *fs) { /* tests to see if text between ##tX and ##tt should be transmitted */ /* where X is a letter corresponding to one of the below values */ /* jeff.hedlund@matrixsi.com */ char inchar; inchar = fgetc(fs); switch(inchar) { case 'a': /* administrative commands */ if(AdminType != DOMAIN_ADMIN) { ignore_to_end_tag(fs); } break; case 'h': #ifndef HELP ignore_to_end_tag(fs); #endif break; case 'm': #ifndef ENABLE_MYSQL ignore_to_end_tag(fs); #endif break; case 'q': #ifndef MODIFY_QUOTA ignore_to_end_tag(fs); #endif break; case 's': #ifndef MODIFY_SPAM ignore_to_end_tag(fs); #endif break; case 't': /* explicitly break if it was ##tt, that's an end tag */ break; case 'u': /* user (not administrative) */ if(AdminType != USER_ADMIN) { ignore_to_end_tag(fs); } break; } } void ignore_to_end_tag(FILE *fs) { /* simply looks for the ending tag (##tt) ignoring everything else */ /* jeff.hedlund@matrixsi.com */ int nested = 0; int inchar; inchar = fgetc(fs); while(inchar >= 0) { if(inchar=='#') { inchar = fgetc(fs); if(inchar=='#') { inchar = fgetc(fs); if(inchar=='t') { inchar = fgetc(fs); if(inchar=='t' && nested==0) return; else if(inchar!='t') nested++; else nested--; } } } inchar=fgetc(fs); } } void get_calling_host() { /* printout the virtual host that matches the HTTP_HOST */ char *srvnam; char *domptr; int count = 0; int l; FILE *fs; char dombuf[255]; sprintf(dombuf, "%s/control/virtualdomains", QMAILDIR); fs = fopen(dombuf, "r"); if( fs != NULL ) { if ((srvnam = getenv("HTTP_HOST")) != NULL) { lowerit(srvnam); while( fgets(TmpBuf, sizeof(TmpBuf), fs) != NULL && count==0 ) { /* strip off newline */ l = strlen(TmpBuf); l--; TmpBuf[l] = 0; /* virtualdomains format: "domain:domain", get to second one */ domptr = TmpBuf; for(; *domptr != 0 && *domptr !=':'; domptr++); domptr++; lowerit(domptr); if( strstr(srvnam, domptr) != NULL ) { printh("%H", domptr); count=1; } } fclose(fs); } } } char *get_session_val(char *session_var) { /* returns the value of session_var, first checking the .qw file for saved */ /* value, or the TmpCGI if it's not yet been saved */ static char value[MAX_BUFF]; char dir[MAX_BUFF]; char *retval; FILE *fs_qw; struct vqpasswd *vpw; memset(value, 0, sizeof(value)); memset(dir, 0, sizeof(dir)); retval = ""; if ( (vpw = vauth_getpw(Username, Domain)) != NULL ) { sprintf(dir, "%s/" MAILDIR "/%u.qw", vpw->pw_dir, (unsigned int) Mytime); fs_qw = fopen(dir, "r"); if ( fs_qw != NULL ) { memset(TmpBuf, 0, sizeof(TmpBuf)); if ( fgets(TmpBuf, sizeof(TmpBuf), fs_qw) != NULL ) { if(GetValue(TmpBuf, value, session_var, sizeof(value))==0) retval=value; } fclose(fs_qw); } } else if (TmpCGI) { if (GetValue(TmpCGI, value, session_var, sizeof(value))==0) retval=value; } return(retval); }