static char rcsid[] = "@(#)$Id: parse_util.c,v 1.29 2006/05/30 16:33:21 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.29 $ $State: Exp $ * * Author: Kari Hurtta (was hurtta+elm@ozone.FMI.FI) * Kari Hurtta *****************************************************************************/ #include "def_melib.h" #include "s_me.h" DEBUG_VAR(Debug,__FILE__,"header"); static void header_panic P_((char *,int,char *, char *)); /* Prototype */ static void header_panic(f,ln,pr,ms) char * f; int ln; char *pr; char *ms; { panic("HEADER PANIC",f,ln,pr,ms,0); } long skip_envelope(hdr, fp) struct header_rec *hdr; FILE *fp; { char buf[STRING]; int tmp; int first_line = TRUE; long result = hdr->offset; if (0 != fseek(fp,hdr->offset,SEEK_SET)) { lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedSeekEnvelope, "Failed to seek beginning of mail envelope (%ld)"), hdr->offset); DPRINT(Debug,7,(&Debug, "skip_envelope=-1 (fseek error)\n")); return -1; } DPRINT(Debug,9,(&Debug, "skip_envelope: scanning offset: %ld\n", result));; while (0 < (tmp = mail_gets(buf,sizeof(buf),fp))) { DPRINT(Debug,15,(&Debug, "skip_envelope: len=%d, got: %s\n",tmp,buf)); #ifdef MMDF if (0 == strcmp(buf,MSG_SEPARATOR)) continue; #endif if (0 == strncmp(buf,"From ",5)) { first_line = FALSE; continue; } if (!first_line && first_word_nc(buf, ">From")) continue; DPRINT(Debug,15,(&Debug, "skip_envelope: got headers: %s\n",buf)); break; } result = ftell(fp) - tmp; DPRINT(Debug,9,(&Debug, "skip_envelope: beginning of headers=%ld\n",result)); if (0 != fseek(fp,result,SEEK_SET)) { lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedSeekHeaders, "Failed to seek beginning of mail headers (%ld)"), result); DPRINT(Debug,7,(&Debug, "skip_envelope=-1 (fseek error)\n")); return -1; } DPRINT(Debug,9,(&Debug, "skip_envelope=%ld\n",result)); return result; } header_list_ptr file_read_headers(fp, flag) FILE * fp; int flag; { in_state_t state; header_list_ptr result; in_state_clear(&state,STATE_in_file); set_in_state_file(fp,&state); result = state_read_headers(&state, flag); in_state_destroy(&state); return result; } header_list_ptr state_read_headers(s, flag) in_state_t * s; int flag; { char buffer[32*1024+1]; int size; header_list_ptr result = NULL, last = NULL; DPRINT(Debug,12,(&Debug, "state_read_headers() --> START\n")); while ((size = state_read_hdr_line(s,buffer,sizeof buffer, RHL_CHECK_HEADER|flag)) > 0) { char * k; if (1 == size && 0 == strcmp(buffer,"\n")) break; k = strchr(buffer,':'); if (!k) break; *k = '\0'; k++; while (whitespace(*k)) k++; update_header_list(&result,&last,buffer,k); } DPRINT(Debug,12,(&Debug, "state_read_headers()=%p <-- END\n",result)); return result; } void state_write_raw_header(dest_file,next) out_state_t * dest_file; header_list_ptr next; { char body[ 32 * 1024 + 1]; /* Allow 32 KB headers after unfolding */ char * ptr; int first = 1; strfcpy(body,next->body, sizeof body); /* NOTE: strtok skips empty fields therefore it does NOT return ptr == body on first time when called if there was folding (ie nl) immediately after header name .... in other words if body[] starts with \n */ for (ptr = strtok(body,"\n"); ptr; ptr = strtok(NULL,"\n")) { state_add_prefix(dest_file); if (!first) { /* Do folding */ if (ptr <= body) panic("FILE PANIC",__FILE__,__LINE__, "state_write_raw_header", "ptr not advanced",0); --ptr; if (*(ptr+1) == ' ') *ptr = ' '; else *ptr = '\t'; } else { state_puts(give_header_name(next->header_name),dest_file); state_puts(": ",dest_file); first = 0; } state_puts(ptr,dest_file); /* state_nlputs or state_printf is needed for EOLN_is_CRLF conversions */ state_nlputs("\n",dest_file); } } int NULL_header_filter(hdr,flag) header_list_ptr hdr; int flag; { if (hdr -> magic != HEADER_magic) header_panic(__FILE__,__LINE__,"NULL_header_filter","Bad magic number"); flag++; /* So that flag is used */ return 1; } void state_write_header(s,next,demime,defcharset) out_state_t * s; header_list_ptr next; int demime; charset_t defcharset; { struct string *buffer = NULL; int X,L1; charset_t Y; int j; DPRINT(Debug,13,(&Debug, "state_write_header: Writing header '%s': demime=%d defcharset=%s (charset filter=%s)", give_header_name(next->header_name), demime, defcharset && defcharset -> MIME_name ? defcharset -> MIME_name : "", s -> filter && s -> filter -> MIME_name ? s -> filter -> MIME_name : "")); buffer = give_decoded_header(next,demime,defcharset); DPRINT(Debug,13,(&Debug, " (header data charset=%s)\n", buffer -> string_type -> MIME_name ? buffer -> string_type -> MIME_name : "")); /* Use current header charset as filter .... */ Y = s->filter; for (j = 0; s->display_charset[j]; j++) { DPRINT(Debug,13,(&Debug, " output charset [%d]: %s\n", j, s -> display_charset[j] -> MIME_name ? s -> display_charset[j] -> MIME_name : "")); if (match_charset_name(s->display_charset[j], buffer->string_type)) { s->filter = buffer->string_type; DPRINT(Debug,13,(&Debug, "state_write_header: Setting charset filter to %s\n", s -> filter -> MIME_name ? s -> filter -> MIME_name : "")); } } state_add_prefix(s); state_puts(give_header_name(next->header_name),s); state_puts(": ",s); L1 = string_len(buffer); for (X = 0; X < L1; ) { int len = 0; uint16 ch = 0; struct string * data; int oldX = X; while (X + len < L1) { ch = give_unicode_from_string(buffer,X+len); if (0x000C /* FF */ == ch || 0x000B /* VT */ == ch || 0x000A /* LF */ == ch) break; len++; } /* clip_from_string updates X */ data = clip_from_string(buffer,&X,len); if (oldX > 0) { /* folding ...*/ state_add_prefix(s); state_putc('\t',s); } state_printf(s,FRM("%S"),data); state_putc('\n',s); X++; free_string(&data); } if (0 == X) { /* No newline printed so print it now ... state_nlputs or state_printf is needed for EOLN_is_CRLF conversions */ state_nlputs("\n",s); } free_string(&buffer); s->filter = Y; } void state_write_headers(s,hdr,filter,flag,demime,defcharset) out_state_t * s; header_list_ptr hdr; header_filter * filter; int flag; int demime; charset_t defcharset; { header_list_ptr next = hdr; int ret; DPRINT(Debug,10,(&Debug, "state_write_headers: Writing headers: demime=%d defcharset=%s (charset filter=%s output charset=%s)\n", demime, defcharset && defcharset -> MIME_name ? defcharset -> MIME_name : "", s -> filter && s -> filter -> MIME_name ? s -> filter -> MIME_name : "", s -> display_charset[0] && s -> display_charset[0] -> MIME_name ? s -> display_charset[0] -> MIME_name : "")); for (next = hdr; next; next = next -> next_header) { if (next -> magic != HEADER_magic) header_panic(__FILE__,__LINE__,"state_write_headers", "Bad magic number"); if (! (ret = filter(next,flag))) { DPRINT(Debug,12,(&Debug, "state_write_headers: header='%s', {filter}=%d FILTERED\n", give_header_name(next->header_name), ret)); continue; } else { DPRINT(Debug,12,(&Debug, "state_write_headers: header='%s', {filter}=%d PASSED\n", give_header_name(next->header_name), ret)); } state_write_header(s,next,demime,defcharset); } } void state_write_raw_headers(s,hdr,filter,flag) out_state_t * s; header_list_ptr hdr; header_filter * filter; int flag; { header_list_ptr next = hdr; int ret; DPRINT(Debug,10,(&Debug, "state_write_raw_headers: Writing headers: (charset filter=%s output charset=%s)\n", s -> filter && s -> filter -> MIME_name ? s -> filter -> MIME_name : "", s -> display_charset[0] && s -> display_charset[0] -> MIME_name ? s -> display_charset[0] -> MIME_name : "")); for (next = hdr; next; next = next -> next_header) { if (next -> magic != HEADER_magic) header_panic(__FILE__,__LINE__,"state_write_raw_headers", "Bad magic number"); if (! (ret = filter(next,flag))) { DPRINT(Debug,12,(&Debug, "state_write_raw_headers: header='%s', {filter}=%d FILTERED\n", give_header_name(next->header_name), ret)); continue; } else { DPRINT(Debug,12,(&Debug, "state_write_raw_headers: header='%s', {filter}=%d PASSED\n", give_header_name(next->header_name), ret)); } state_write_raw_header(s,next); } } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */