|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <ctype.h> ! 3: #include "mail.h" ! 4: #include "string.h" ! 5: #include "header.h" ! 6: #include "aux.h" ! 7: #include <regexp.h> ! 8: ! 9: /* imported */ ! 10: extern char *malloc(); ! 11: extern char *strcpy(); ! 12: extern char *strchr(); ! 13: extern int strncmp(); ! 14: extern void exit(); ! 15: ! 16: /* predeclared */ ! 17: extern void addheader(); ! 18: extern void addbody(); ! 19: ! 20: /* global to this file */ ! 21: static regexp *rfprog; ! 22: static regexp *fprog; ! 23: ! 24: /* imported */ ! 25: extern int extrafrom; ! 26: ! 27: /* ! 28: * Input header from standard input. Actually two extra lines are also ! 29: * read, but this is a problem. Save some header lines in the header ! 30: * array. ! 31: */ ! 32: extern ! 33: getheader(fgetsp, fp) ! 34: char *(*fgetsp)(); ! 35: FILE *fp; ! 36: { ! 37: char buf[4096]; ! 38: string *line; ! 39: string *from=NULL; ! 40: string *date=NULL; ! 41: char *cp; ! 42: header *hp; ! 43: int n; ! 44: ! 45: /* ! 46: * forget any old headers ! 47: */ ! 48: for (hp = hdrs; *(hp->name) != '\0'; hp++) ! 49: hp->line = (string *)0; ! 50: ! 51: /* ! 52: * preload the first line for the parsing below ! 53: */ ! 54: if((*fgetsp)(buf, sizeof buf, fp) == NULL) ! 55: return ferror(fp) ? -1 : 0; ! 56: ! 57: /* If the first line of an rfc822 message ! 58: * is a unix from line, use that to `seed' the From: and ! 59: * Date: fields. ! 60: */ ! 61: if(strncmp(buf, "From ", 5)==0) { ! 62: if (getunixfrom(buf, &from, &date)==0) { ! 63: for (hp = hdrs; *(hp->name) != '\0'; hp++) { ! 64: if (STRCMP("UnixFrom:", hp) == 0) { ! 65: hp->line = from; ! 66: from = (string *)0; ! 67: continue; ! 68: }; ! 69: if (STRCMP("UnixDate:", hp) == 0) { ! 70: hp->line = date; ! 71: date = (string *)0; ! 72: continue; ! 73: }; ! 74: } ! 75: return 0; ! 76: } ! 77: } ! 78: ! 79: /* Now get real 822 headers */ ! 80: while (buf[0] != '\n' && buf[0] != '\0') { ! 81: /* gather a multiple line header field */ ! 82: line = s_new(); ! 83: do { ! 84: s_append(line, buf); ! 85: if((*fgetsp)(buf, sizeof buf, fp) == NULL) { ! 86: if(ferror(fp)) ! 87: return -1; ! 88: *buf = 0; ! 89: break; ! 90: } ! 91: } while (*buf==' ' || *buf=='\t'); ! 92: ! 93: /* header lines must contain `:' with no preceding white */ ! 94: for(cp=s_to_c(line); *cp; cp++) ! 95: if(isspace(*cp) || *cp==':') ! 96: break; ! 97: if (*cp != ':') { ! 98: addbody(line); ! 99: break; ! 100: } ! 101: ! 102: /* look for `important' headers */ ! 103: for (hp = hdrs; *(hp->name) != '\0'; hp++) { ! 104: if (cistrncmp(s_to_c(line), hp->name, hp->size) == 0) { ! 105: hp->line = line; ! 106: break; ! 107: }; ! 108: } ! 109: addheader(line); ! 110: } ! 111: /* at this point, buf contains a line of the body */ ! 112: if(buf[0]) ! 113: addbody(s_copy(buf)); ! 114: return 0; ! 115: } ! 116: ! 117: /* ! 118: * Keep a (circular) list of header lines to output. ! 119: */ ! 120: typedef struct quux{ ! 121: struct quux *next; ! 122: string *line; ! 123: } hlist; ! 124: static hlist dummy = { &dummy, '\0' }; ! 125: static hlist *list = &dummy; ! 126: ! 127: /* ! 128: * Add to list of header lines. ! 129: */ ! 130: extern void ! 131: addheader(line) ! 132: string *line; ! 133: { ! 134: hlist *thing; ! 135: ! 136: thing = (hlist *)malloc(sizeof(hlist)); ! 137: if (thing == NULL) { ! 138: perror("reading header"); ! 139: exit(1); ! 140: } ! 141: thing->line = line; ! 142: thing->next = list->next; ! 143: list->next = thing; ! 144: list = thing; ! 145: } ! 146: ! 147: /* ! 148: * Print list of headers. ! 149: */ ! 150: extern int ! 151: printheaders(fputsp, fp, originalfrom) ! 152: FILE *fp; ! 153: int (*fputsp)(); ! 154: { ! 155: hlist *thing, *othing; ! 156: int printed = 0; ! 157: ! 158: for(thing = list->next->next; thing != &dummy; ){ ! 159: printed++; ! 160: if(originalfrom && strncmp(s_to_c(thing->line), "From:", 5)==0) ! 161: (*fputsp)("Original-", fp); ! 162: (*fputsp)(s_to_c(thing->line), fp); ! 163: s_free(thing->line); ! 164: othing = thing; ! 165: thing = thing->next; ! 166: free(othing); ! 167: } ! 168: list = dummy.next = &dummy; /* reinitialize for future calls */ ! 169: return(printed); ! 170: } ! 171: ! 172: /* ! 173: * Keep a (circular) list of body lines to output. ! 174: */ ! 175: static hlist bdummy = { &bdummy, '\0' }; ! 176: static hlist *blist = &bdummy; ! 177: ! 178: /* ! 179: * Add to list of body lines. ! 180: */ ! 181: extern void ! 182: addbody(line) ! 183: string *line; ! 184: { ! 185: hlist *thing; ! 186: ! 187: thing = (hlist *)malloc(sizeof(hlist)); ! 188: if (thing == NULL) { ! 189: perror("reading header"); ! 190: exit(1); ! 191: } ! 192: thing->line = line; ! 193: thing->next = blist->next; ! 194: blist->next = thing; ! 195: blist = thing; ! 196: } ! 197: ! 198: /* ! 199: * Print list of body lines ! 200: */ ! 201: extern void ! 202: printbodies(fputsp, fp) ! 203: FILE *fp; ! 204: int (*fputsp)(); ! 205: { ! 206: hlist *thing, *othing; ! 207: int line = 0; ! 208: ! 209: for(thing = blist->next->next; thing != &bdummy; ){ ! 210: /* dump extraneous new line */ ! 211: if(line++!=0 || *s_to_c(thing->line)!='\n') ! 212: (*fputsp)(s_to_c(thing->line), fp); ! 213: s_free(thing->line); ! 214: othing = thing; ! 215: thing = thing->next; ! 216: free(othing); ! 217: } ! 218: blist = bdummy.next = &bdummy; ! 219: } ! 220: ! 221: /* ! 222: * extract sender and date from a unix remote from line. return -1 ! 223: * if its the wrong format, 0 otherwise. ! 224: */ ! 225: getunixfrom(line, fpp, dpp) ! 226: char *line; ! 227: string **fpp; ! 228: string **dpp; ! 229: { ! 230: regsubexp subexp[10]; ! 231: ! 232: if (rfprog == NULL) ! 233: rfprog = regcomp(REMFROMRE); ! 234: if (regexec(rfprog, line, subexp, 10)) { ! 235: *fpp = s_new(); ! 236: append_match(subexp, *fpp, REMSYSMATCH); ! 237: s_append(*fpp, "!"); ! 238: append_match(subexp, *fpp, REMSENDERMATCH); ! 239: *dpp = s_new(); ! 240: append_match(subexp, *dpp, REMDATEMATCH); ! 241: return 0; ! 242: } ! 243: if (fprog == NULL) ! 244: fprog = regcomp(FROMRE); ! 245: if (regexec(fprog, line, subexp, 10)) { ! 246: *fpp = s_new(); ! 247: append_match(subexp, *fpp, SENDERMATCH); ! 248: *dpp = s_new(); ! 249: append_match(subexp, *dpp, DATEMATCH); ! 250: return 0; ! 251: } ! 252: return -1; ! 253: } ! 254: ! 255: /* ! 256: * The addr is either the first whitespace delimited token or ! 257: * the first thing enclosed in "<" ">". ! 258: * Sets extrafrom > 0 if a from line with other cruft in it. ! 259: */ ! 260: extern string * ! 261: getaddr(line) ! 262: char *line; ! 263: { ! 264: register char *lp; ! 265: register int comment = 0; ! 266: register int anticomment = 0; ! 267: register int inquote = 0; ! 268: static string *sender=0; ! 269: ! 270: if (!sender) ! 271: sender = s_new(); ! 272: s_restart(sender); ! 273: lp = line; ! 274: for (; *lp; lp++) { ! 275: if (comment) { ! 276: if (*lp=='(') ! 277: comment++; ! 278: if (*lp==')') ! 279: comment--; ! 280: continue; ! 281: } ! 282: if (anticomment) { ! 283: if (*lp=='>') { ! 284: if (*(lp+1)!='\n') ! 285: extrafrom++; ! 286: break; ! 287: } ! 288: } ! 289: if (inquote) { ! 290: if (*lp=='"') ! 291: inquote = 0; ! 292: s_putc(sender, *lp); ! 293: continue; ! 294: } ! 295: switch (*lp) { ! 296: case '\t': ! 297: case '\n': ! 298: break; ! 299: case ' ': ! 300: if (cistrncmp(lp, " at ", sizeof(" at ")-1)==0) { ! 301: s_putc(sender, '@'); ! 302: lp += sizeof(" at ")-2; ! 303: } ! 304: break; ! 305: case '<': ! 306: anticomment = 1; ! 307: if(*s_to_c(sender)!='\0') ! 308: extrafrom++; ! 309: s_restart(sender); ! 310: break; ! 311: case '(': ! 312: extrafrom++; ! 313: comment++; ! 314: break; ! 315: case '"': ! 316: inquote = 1; ! 317: /* fall through */ ! 318: default: ! 319: s_putc(sender, *lp); ! 320: break; ! 321: } ! 322: } ! 323: s_terminate(sender); ! 324: s_restart(sender); ! 325: return(sender); ! 326: } ! 327: ! 328: /* ! 329: * case independent string compare ! 330: */ ! 331: extern int ! 332: cistrncmp(s1, s2, n) ! 333: char *s1; ! 334: char *s2; ! 335: { ! 336: int c1, c2; ! 337: ! 338: for(; *s1 && n>0; n--, s1++, s2++){ ! 339: c1 = isupper(*s1) ? tolower(*s1) : *s1; ! 340: c2 = isupper(*s2) ? tolower(*s2) : *s2; ! 341: if (c1 != c2) ! 342: return -1; ! 343: } ! 344: return(0); ! 345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.