1 /*
2 * $Id: util.c,v 1.4.2.10 2009/05/02 18:22:25 tomcollins Exp $
3 * Copyright (C) 1999-2004 Inter7 Internet Technologies, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <pwd.h>
27 #include <dirent.h>
28 #include <ctype.h>
29
30 #include <vpopmail.h>
31
32 #include "alias.h"
33 #include "autorespond.h"
34 #include "config.h"
35 #include "forward.h"
36 #include "mailinglist.h"
37 #include "qmailadmin.h"
38 #include "qmailadminx.h"
39 #include "printh.h"
40 #include "user.h"
41 #include "util.h"
42
43 extern FILE *lang_fs;
44 extern FILE *color_table;
45
46 #define SORT_TABLE_ENTRIES 100000
47
48 /* pointer to array of pointers */
49 unsigned char **sort_list;
50
51 unsigned char *sort_block[200]; /* memory blocks for sort data */
52 int memleft, memindex, sort_entry;
53 char *sort_ptr;
54
sort_init()55 int sort_init ()
56 {
57 sort_entry = memindex = memleft = 0;
58 sort_list = malloc(SORT_TABLE_ENTRIES * sizeof(char *));
59 if (!sort_list) { return -1; }
60 return 0;
61 }
62 /* add entry to list for sorting, copies string until it gets to char
63 'end' */
sort_add_entry(char * entry,char end)64 int sort_add_entry (char *entry, char end)
65 {
66 int len;
67
68 if (sort_entry == SORT_TABLE_ENTRIES) {
69 return -2; /* table is full */
70 }
71 if (memleft < 256)
72 {
73 /* allocate a 64K block of memory to store table entries */
74 memleft = 65536;
75 sort_ptr = sort_block[memindex++] = malloc(memleft);
76 }
77 if (!sort_ptr) { return -1; }
78 sort_list[sort_entry++] = sort_ptr;
79 len = 1; /* at least a terminator */
80 while (*entry && *entry != end) {
81 *sort_ptr++ = *entry++;
82 len++;
83 }
84 *sort_ptr++ = 0; /* NULL terminator */
85 memleft -= len;
86 return 0;
87 }
sort_get_entry(int index)88 char *sort_get_entry(int index)
89 {
90 if ((index < 0) || (index >= sort_entry)) { return NULL; }
91 return sort_list[index];
92 }
sort_cleanup()93 void sort_cleanup()
94 {
95 while (memindex) { free (sort_block[--memindex]); }
96 if (sort_list) {
97 free (sort_list);
98 sort_list = NULL;
99 }
100 }
101 /* Comparison routine used in qsort for multiple functions */
sort_compare(const void * p1,const void * p2)102 static int sort_compare (const void *p1, const void *p2)
103 {
104 return strcasecmp (*(char **)p1, *(char **)p2);
105 }
sort_dosort()106 void sort_dosort()
107 {
108 qsort (sort_list, sort_entry, sizeof(char *), sort_compare);
109 }
110
str_replace(char * s,char orig,char repl)111 void str_replace (char *s, char orig, char repl)
112 {
113 while (*s) {
114 if (*s == orig) { *s = repl; }
115 s++;
116 }
117 }
118
qmail_button(char * modu,char * command,char * user,char * dom,time_t mytime,char * png)119 void qmail_button(char *modu, char *command, char *user, char *dom, time_t mytime, char *png)
120 {
121 printf ("<td align=center>");
122 printh ("<a href=\"%s&modu=%C\">", cgiurl(command), modu);
123 printf ("<img src=\"%s/%s\" border=0></a>", IMAGEURL, png);
124 printf ("</td>\n");
125 }
126
check_local_user(user)127 int check_local_user( user )
128 char *user;
129 {
130 struct stat buf;
131 int i,j;
132
133 /* check for aliases and autoresponders */
134 if ( valias_select (user, Domain)) return(-1);
135
136 /* check for mailing list */
137 strcpy(TmpBuf, ".qmail-");
138 for(i=0,j=7;user[i]!=0;++i,++j){
139 if ( user[i] == '.' ) TmpBuf[j] = ':';
140 else TmpBuf[j] = user[i];
141 }
142 TmpBuf[j] = 0;
143 if ( stat(TmpBuf, &buf) == 0 ) return(-1);
144
145 /* check for POP/IMAP user */
146 if ( vauth_getpw(user, Domain)) return(-1);
147
148 return(0);
149 }
150
show_counts()151 void show_counts()
152 {
153 count_users();
154 count_forwards();
155 count_autoresponders();
156 count_mailinglists();
157
158 printf ("%s = %d<BR>\n", html_text[61], CurPopAccounts);
159 printf ("%s = %d<BR>\n", html_text[74], CurForwards);
160 printf ("%s = %d<BR>\n", html_text[77], CurAutoResponders);
161 printf ("%s = %d<BR>\n", html_text[80], CurMailingLists);
162 }
163
164 /* check_email_addr( char *addr )
165 *
166 * Make sure 'addr' is a valid email address. Returns 1 if it's bad,
167 * 0 if it's good.
168 */
check_email_addr(char * addr)169 int check_email_addr( char *addr )
170 {
171 char *taddr = addr;
172 char *atpos = NULL;
173 char *dotpos = NULL;
174
175 for(taddr = addr; *taddr != '\0'; ++taddr) {
176 if (*taddr == '@') {
177 if (atpos != NULL) return 1; /* double @ */
178 atpos = taddr;
179 } else if(!isalnum(*taddr) && (strchr (".-+=_&", *taddr) == NULL)) {
180 return 1;
181 }
182 }
183
184 /* if just a user name with no @domain.com then bad */
185 if (atpos == NULL) return 1;
186
187 /* Look for a sub domain */
188 dotpos = strchr (atpos, '.');
189
190 /* no '.' in the domain part */
191 if (dotpos == NULL) return 1;
192
193 /* once we know it's good, convert it to lowercase */
194 lowerit(addr);
195
196 return 0;
197 }
198
fixup_local_name(addr)199 int fixup_local_name( addr )
200 char *addr;
201 {
202 char *taddr = addr;
203
204 /* don't allow zero length user names */
205 if(strlen(taddr)<=0) return(1);
206
207 /* force it to lower case */
208 lowerit(addr);
209
210 /* check for valid email address */
211 for(taddr=addr;*taddr!=0;++taddr) {
212
213 if(!isalnum(*taddr) && !ispunct(*taddr)) return(1);
214 if(isspace(*taddr)) return(1);
215
216 if(ispunct(*taddr)&& (strchr (".-+=_&", *taddr) == NULL)){
217 return(1);
218 }
219 }
220
221 /* if we made it here, everything is okay */
222 return(0);
223 }
224
ack(msg,extra)225 void ack(msg, extra)
226 char *msg;
227 char *extra;
228 {
229 printf ("%s %s\n", get_html_text(msg), extra);
230 printf ("</BODY></HTML>\n");
231 vclose();
232 exit(0);
233 }
234
upperit(instr)235 void upperit( instr )
236 char *instr;
237 {
238 while(*instr!=0) {
239 if ( islower(*instr) ) *instr = toupper(*instr);
240 ++instr;
241 }
242 }
243
safe_getenv(char * var)244 char *safe_getenv(char *var)
245 {
246 char *s;
247
248 s = getenv(var);
249 if ( s == NULL ) return("");
250 return(s);
251 }
252
strstart(sstr,tstr)253 char *strstart(sstr, tstr)
254 char *sstr;
255 char *tstr;
256 {
257 char *ret_str;
258
259 ret_str = sstr;
260 if ( sstr == NULL || tstr == NULL ) return(NULL);
261
262 while ( *sstr != 0 && *tstr != 0 ) {
263 if ( *sstr != *tstr ) return(NULL);
264 ++sstr;
265 ++tstr;
266 }
267
268 if ( *tstr == 0 ) return(ret_str);
269 return(NULL);
270
271 }
272
open_lang(char * lang)273 int open_lang(char *lang)
274 {
275 char langfile[200];
276 static char *langpath = NULL;
277 struct stat mystat;
278
279 /* do not read lang files with path control characters */
280 if ( strchr(lang,'.')!=NULL || strchr(lang,'/')!=NULL ) return(-1);
281
282 /* convert to lower case (using lowerit() from libvpopmail) */
283 lowerit(lang);
284
285 /* close previous language if still open */
286 if (lang_fs != NULL) fclose (lang_fs);
287
288 if (langpath == NULL) {
289 langpath = getenv(QMAILADMIN_TEMPLATEDIR);
290 if (langpath == NULL ) langpath = HTMLLIBDIR;
291 }
292
293 snprintf(langfile, sizeof(langfile), "%s/lang/%s", langpath, lang);
294
295 /* do not open symbolic links */
296 if (lstat(langfile, &mystat)==-1 || S_ISLNK(mystat.st_mode)) return(-1);
297
298 if ( (lang_fs=fopen(langfile, "r"))==NULL) return(-1);
299
300 return(0);
301 }
302
get_html_text(char * index)303 char *get_html_text( char *index )
304 {
305 return html_text[atoi(index)];
306 }
307
open_colortable()308 int open_colortable()
309 {
310 char tmpbuf[200];
311 char *tmpstr;
312
313 tmpstr = getenv(QMAILADMIN_TEMPLATEDIR);
314 if (tmpstr == NULL ) tmpstr = HTMLLIBDIR;
315
316 snprintf(tmpbuf, sizeof(tmpbuf), "%s/html/colortable", tmpstr);
317 if ( (color_table=fopen(tmpbuf, "r"))==NULL) return(-1);
318 return(0);
319 }
320
get_color_text(char * index)321 char *get_color_text( char *index )
322 {
323 static char tmpbuf[400];
324 char *tmpstr;
325
326 if (color_table == NULL) return("");
327
328 rewind(color_table);
329 while(fgets(tmpbuf,sizeof(tmpbuf),color_table)!=NULL){
330 tmpstr = strtok(tmpbuf, " ");
331 if (strcmp(tmpstr, index) == 0 ) {
332 tmpstr = strtok(NULL, "\n");
333 return(tmpstr);
334 }
335 }
336 return("");
337 }
338 /* bk - use maildir++ quotas now
339 char *get_quota_used(char *dir) {
340 static char tmpbuff[40];
341 double size;
342
343 size = get_du(dir);
344 if (size > 0) {
345 size = size / 1048576;
346 }
347 sprintf(tmpbuff, "%.2lf", size);
348 return tmpbuff;
349 }
350 */
351 /* quota_to_bytes: used to convert user entered quota (given in MB)
352 back to bytes for vpasswd file
353 return value: 0 for success, 1 for failure
354 */
quota_to_bytes(char returnval[],char * quota)355 int quota_to_bytes(char returnval[], char *quota) {
356 double tmp;
357
358 if (quota == NULL) { return 1; }
359 if ((tmp = atof(quota))) {
360 tmp *= 1048576;
361 sprintf(returnval, "%.0lf", tmp);
362 return 0;
363 } else {
364 strcpy (returnval, "");
365 return 1;
366 }
367 }
368 /* quota_to_megabytes: used to convert vpasswd representation of quota
369 to number of megabytes.
370 return value: 0 for success, 1 for failure
371 */
quota_to_megabytes(char * returnval,char * quota)372 int quota_to_megabytes(char *returnval, char *quota) {
373 double tmp;
374 int i;
375
376 if (quota == NULL) { return 1; }
377 i = strlen(quota);
378 if ((quota[i-1] == 'M') || (quota[i-1] == 'm')) {
379 tmp = atol(quota); /* already in megabytes */
380 } else if ((quota[i-1] == 'K') || (quota[i-1] == 'k')) {
381 tmp = atol(quota) * 1024; /* convert kilobytes to megabytes */
382 } else if ((tmp = atol(quota))) {
383 tmp /= 1048576.0;
384 } else {
385 strcpy (returnval, "");
386 return 1;
387 }
388 sprintf(returnval, "%.2lf", tmp);
389 return 0;
390 }
391
print_user_index(char * action,int colspan,char * user,char * dom,time_t mytime)392 void print_user_index (char *action, int colspan, char *user, char *dom, time_t mytime)
393 {
394 #ifdef USER_INDEX
395 int k;
396
397 printf ("<tr bgcolor=%s>", get_color_text("000"));
398 printf ("<td colspan=%d align=\"center\">", colspan);
399 printf ("<hr>");
400 printf ("<b>%s</b> ", html_text[133]);
401 for (k = 0; k < 10; k++) {
402 printh ("<a href=\"%s&searchuser=%d\">%d</a>\n", cgiurl(action), k, k);
403 }
404 for (k = 'a'; k <= 'z'; k++) {
405 printh ("<a href=\"%s&searchuser=%c\">%c</a>\n", cgiurl(action), k, k);
406 }
407 printf ("</td>");
408 printf ("</tr>\n");
409
410 printf ("<tr bgcolor=%s>", get_color_text("000"));
411 printf ("<td colspan=%d>", colspan);
412 printf ("<table border=0 cellpadding=3 cellspacing=0 width=\"100%%\"><tr><td align=\"center\"><br>");
413 printf ("<form method=\"get\" action=\"%s/com/%s\">", CGIPATH, action);
414 printh ("<input type=\"hidden\" name=\"user\" value=\"%H\">", user);
415 printh ("<input type=\"hidden\" name=\"dom\" value=\"%H\">", dom);
416 printf ("<input type=\"hidden\" name=\"time\" value=\"%u\">", (unsigned int) mytime);
417 printh ("<input type=\"text\" name=\"searchuser\" value=\"%H\"> ", SearchUser);
418 printf ("<input type=\"submit\" value=\"%s\">", html_text[204]);
419 printf ("</form>");
420 printf ("</td></tr></table>");
421 printf ("<hr>");
422 printf ("</td></tr>\n");
423
424 #endif
425 }
426
cgiurl(char * action)427 char *cgiurl (char *action)
428 {
429 static char url[256];
430
431 snprinth (url, sizeof(url), "%s/com/%s?user=%C&dom=%C&time=%d",
432 CGIPATH, action, Username, Domain, Mytime);
433
434 return url;
435 }
436
437 /*
438 * Brian Kolaci
439 * updated function that doesn't require fts_*
440 */
441 /* bk - use maildir++ quotas now
442 off_t get_du(const char *dir_name)
443 {
444 DIR *dirp;
445 struct dirent *dp;
446 struct stat statbuf;
447 off_t file_size = 0;
448 char *tmpstr;
449
450 if (dir_name == NULL)
451 return 0;
452
453 if (chdir(dir_name) == -1)
454 return 0;
455
456 if ((dirp = opendir(".")) == NULL)
457 return 0;
458
459 while ((dp=readdir(dirp)) != NULL) {
460 if (!strcmp(dp->d_name, "..") || !strcmp(dp->d_name, "."))
461 continue;
462 if ((tmpstr=strstr(dp->d_name, ",S=")) != NULL) {
463 file_size += atol(tmpstr+3);
464 } else if (stat(dp->d_name,&statbuf)==0 && (statbuf.st_mode & S_IFDIR) ) {
465 file_size += get_du(dp->d_name);
466 }
467 }
468 closedir(dirp);
469 if (dir_name != NULL && strcmp(dir_name, ".." ) && strcmp(dir_name, "." ))
470 chdir("..");
471 return(file_size);
472 }
473 */
474