/* ** ** Copyright (C) 1993 Swedish University Network (SUNET) ** ** ** This program is developed by UDAC, Uppsala University by commission ** of the Swedish University Network (SUNET). ** ** 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 FITTNESS 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., 675 Mass Ave, Cambridge, MA 02139, USA. ** ** ** Martin.Wendel@its.uu.se ** Torbjorn.Wictorin@its.uu.se ** ** ITS ** P.O. Box 887 ** S-751 08 Uppsala ** Sweden ** */ #include "emil.h" /* * */ /* * void * encode_header() * */ void encode_header(struct message *m) { switch(target->iformat) { case MIME: encode_mime(m); break; case MAILTOOL: encode_mailtool(m); break; default: encode_rfc822(m); break; } } /* * void * decode_header() * * Parses the header of current message. */ void decode_header(struct message *m) { struct data *d; d = m->sd; if (m->h == NULL) { logger(LOG_DEBUG, "decode_header: empty header"); return; } /** ** m->level 0 specifics **/ if (m->level == 0) { if (matchheader(m, "Content-Conversion", "Prohibited", 0)) { #ifdef DEBUG if (edebug) fprintf(stderr, "Content conversion prohibited.\n"); #endif det_sket_sig = TRUE; return; } } if (decode_mime(m) != OK) { if (decode_mailtool(m) != OK) { decode_rfc822(m); } } } /* * char * * fixstring(STRING, BEFORE, AFTER, PROCESS) * * Process STRING according to PROCESS (UNQUOTE, UNSPACE) and return * the merged BEFORE, STRING and AFTER. */ char * fixstring(char *string, char *before, char *after, short process) { char *tmp1, *tmp2; int slen, blen, alen; if (string == NULL) return(NULL); if (*string != '\0' && (process & UNSPACE)) { tmp1 = string; while(*tmp1 == ' ' || *tmp1 == '\t') tmp1++; if (*tmp1 != '\0') { tmp2 = tmp1 + strlen(tmp1) - 1; while (*tmp2 == ' ' || *tmp2 == '\t') tmp2--; tmp2++; *tmp2 = '\0'; } string = tmp1; } if (*string != '\0' && (process & UNQUOTE) ) { tmp1 = string; if (*tmp1 == '"') { tmp1++; tmp2 = string + strlen(string) - 1; if (*tmp2 == '"') { *tmp2 = '\0'; string = tmp1; } } } if (*string != '\0') slen = strlen(string); else slen = 0; if (before != NULL && *before != '\0') blen = strlen(before); else blen = 0; if (after != NULL && *after != '\0') alen = strlen(after); else alen = 0; tmp1 = (char *)Yalloc(blen + slen + alen + 1); if (blen) strcpy(tmp1, before); if (slen) strcat(tmp1, string); if (alen) strcat(tmp1, after); return(tmp1); } /* * bool * matchheader(HFIELD, HVAL) * * If header HFIELD is available, matches HVAL against the value * of the header. Returns TRUE on success and FALSE on failure. */ int matchheader(struct message *m, char *hfield, char *hval, int format) { struct header *hdr; if (hfield == NULL || hval == NULL) return(FALSE); for (hdr = m->h; hdr != NULL; hdr = hdr->next) { if (hdr->type != UNIXFROM && hdr->field->end != 0 && (cmatch(hdr->field->contents, hfield) == TRUE)) { if (matchhvalue(hdr, hval)) /* if (hdr->value->end != 0 && (cmatch(hdr->value->contents, hval) == TRUE)) */ { #ifdef DEBUG if (edebug) fprintf(stderr, "* matchhvalue success\n"); #endif hdr->format = format; return(TRUE); } else { #ifdef DEBUG if (edebug) fprintf(stderr, "* matchhvalue failed\n"); #endif return(FALSE); } } } return(FALSE); } int matchhvalue(struct header *hdr, char *line) { static struct header *th = NULL; if (th == NULL) { th = (struct header *)Yalloc(sizeof(struct header)); th->field = (struct data *)Yalloc(sizeof(struct data)); th->value = (struct data *)Yalloc(sizeof(struct data)); } else { th->field->end = 0; th->value->end = 0; th->value->offset = 0; th->hvalue = NULL; } append_data(th->field, hdr->field->contents, strlen(hdr->field->contents), 256); append_data(th->value, line, strlen(line), 256); #ifdef DEBUG if (edebug) fprintf(stderr, "* matchhvalue: %s: matching %s with %s\n", hdr->field->contents, hdr->value->contents, line); #endif if (parse_rfc1522(th) != OK) return(0); if (parse_rfc1522(hdr) != OK) return(0); return(compare_header(hdr->hvalue, th->hvalue)); } int compare_header(struct hprs *dirty, struct hprs *clean) { if (clean == NULL && dirty == NULL) return(0); if (clean == NULL || clean->type != DELIMITER) { while(dirty != NULL && dirty->type == DELIMITER) dirty = dirty->sibling; if (dirty == NULL) { if (clean == NULL) return(0); else { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: dirty unexpected end\n"); #endif return(0); } } } while(dirty->type == COMMENT) dirty = dirty->sibling; #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: trying match between %d and %d\n", dirty->type, clean->type); #endif switch (clean->type) { case UNKNOWN: if (dirty->type != UNKNOWN) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: clean type is UNKNOWN\n"); #endif return(0); } break; case COMMENT: break; case HQSTRING: if (dirty->type != HQSTRING) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: expecting COMMENT got %d\n", dirty->type); #endif return(0); } break; case DLITERAL: if (dirty->type != DLITERAL) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: expecting DLITERAL got %d\n", dirty->type); #endif return(0); } break; case RADDR: if (dirty->type != RADDR) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: expecting RADDR got %d\n", dirty->type); #endif return(0); } break; case RFC1522: if (dirty->type != RFC1522) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: expecting RFC1522 got %d\n", dirty->type); #endif return(0); } break; case ATOM: if (dirty->type != ATOM) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: expecting ATOM got %d\n", dirty->type); #endif return(0); } /* MW 960517 if (dmatch(clean->sd, dirty->sd) == 0) return(0); */ if (dmatch(clean->sd, dirty->sd) != 0) return(1); break; case DELIMITER: if (dirty->type != DELIMITER) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: expecting DELIMITER got %d\n", dirty->type); #endif return(0); } break; case TEXT: if (dirty->type != TEXT) { #ifdef DEBUG if (edebug) fprintf(stderr, "* compare_header: expecting TEXT got %d\n", dirty->type); #endif return(0); } clean = clean->child; dirty = dirty->child; return(compare_header(dirty, clean)); break; default: break; } /* clean = clean->sibling; */ dirty = dirty->sibling; return(compare_header(dirty, clean)); } int dmatch(struct data *a, struct data *b) { int alen, blen; alen = a->bodyend - a->bodystart; blen = b->bodyend - b->bodystart; if (alen == 0 || alen != blen) { #ifdef DEBUG if (edebug) { fprintf(stderr, "* dmatch: lengths differ: %d %d\n", alen, blen); fprintf(stderr, "* dmatch: tried to compare %s and %s\n", a->contents, b->contents); } #endif return(0); } if (strncasecmp(a->contents + a->bodystart, b->contents + b->bodystart, alen) != 0) { #ifdef DEBUG if (edebug) fprintf(stderr, "* dmatch: %s and %s does not match\n", a->contents + a->bodystart, b->contents + b->bodystart); #endif return(0); } #ifdef DEBUG if (edebug) fprintf(stderr, "* dmatch: %s and %s does match\n", a->contents + a->bodystart, b->contents + b->bodystart); #endif return(1); } /* * char * * gethval(HFIELD) * * If header HFIELD is available, returns the corresponding value * as a string. Returns NULL on failure. */ char * gethval(struct message *m, char *hfield, int format) { struct header *hdr; if (hfield == NULL) return(NULL); for (hdr = m->h; hdr != NULL; hdr = hdr->next) { if (hdr->type != UNIXFROM && hdr->field->end != 0 && cmatch(hdr->field->contents, hfield) == TRUE) { if (format) hdr->format = format; return(hdr->value->contents); } } return(NULL); } /* * int * string2dec(STRING) * * If STRING is not NULL and not of m->length zero and consists of 0-9, * returns the translation to an integer. Returns 0 on failure. */ int string2dec(char *string) { if (string == NULL) return(0); return((int)atol(string)); } /* * char * * stringpart(STRING, DEL, PARTNO) * * Delimits STRING by DEL and returns part number PARTNO, where * parts start with zero for the first part and so on. Returns * NULL on failure. */ char * stringpart(char *string, char *del, int partno) { char *str, *start; int slen; int i = 0; if (string == NULL || del == NULL) return(string); slen = strlen(string); str = (char *)NEWSTR(string); start = str; /* Loop on string */ while (1) { /* Delimit string */ while (*str != '\0' && index(del, *str) == NULL) { str++; slen--; } *str = '\0'; if (i == partno) return(start); else { if (!slen) break; str++; slen--; start = str; } i++; } return(NULL); } /* * bool * matchpart(STRING1, STRING2, DEL, PARTNO) * * Delimits STRING2 by DEL and and matches part number PARTNO with * STRING1. Returns TRUE on success and FALSE on failure. */ int matchpart(char *string1, char *string2, char *del, int partno) { char *str, *start; int i = 0; if (string1 == NULL || string2 == NULL || del == NULL) return(FALSE); str = NEWSTR(string1); start = str; for (; str != '\0' && i <= partno; str++) { if (index(del, *str) != NULL) { *str = '\0'; if (i == partno && cmatch(start, string2) == TRUE) { return(TRUE); } else { str++; start = str; } i++; } } return(FALSE); } /* * char * * getpartrest(STRING, MATCH, DEL) * * Delimits STRING by DEL and tries MATCH on every part returns the * unmatched part of the part matched. */ char * getpartrest(char *string, char *matchstr, char *del) { char *str, *start; int mlen, slen; #ifdef DEBUG if (edebug) fprintf(stderr, "\ngetpartrest: string: %s matchstr: %s, del: %s\n", string, matchstr, del); #endif if (string == NULL || matchstr == NULL || del == NULL) return(NULL); if ((mlen = strlen(matchstr)) == 0 || (slen = strlen(string)) == 0) return(NULL); str = (char *)NEWSTR(string); start = str; while (1) { /* Delimit string */ if (!slen) return(NULL); while (*str != '\0' && *del != *str) { str++; slen--; if (!slen) break; } *str = '\0'; while (isspace(*start)) start++; if (strncasecmp(matchstr, start, mlen) == 0) return(start + mlen); else { if (!slen) break; str++; slen--; start = str; } } return(NULL); } /* * int * match(string1, string2) * * Case sensitive match */ int match(char *string1, char *string2) { if (string1 == NULL || string2 == NULL) return(FALSE); if (strcmp(string1, string2) == 0) return(TRUE); else return(FALSE); } /* * int * cmatch(string1, string2) * * Case insensitive match */ int cmatch(char *string1, char *string2) { if (string1 == NULL || string2 == NULL) return(FALSE); if (strcasecmp(string1, string2) == 0) return(TRUE); else return(FALSE); }