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 <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
* Kari Hurtta <elm@elmme-mailer.org>
*****************************************************************************/
#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 : "<not set>",
s -> filter && s -> filter -> MIME_name ?
s -> filter -> MIME_name : "<not set>"));
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 :
"<not set>"));
/* 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 :
"<no 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 : "<no 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 : "<not set>",
s -> filter && s -> filter -> MIME_name ?
s -> filter -> MIME_name : "<not set>",
s -> display_charset[0] &&
s -> display_charset[0] -> MIME_name ?
s -> display_charset[0] -> MIME_name :
"<not set>"));
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 : "<not set>",
s -> display_charset[0] &&
s -> display_charset[0] -> MIME_name ?
s -> display_charset[0] -> MIME_name :
"<not set>"));
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:
*/
syntax highlighted by Code2HTML, v. 0.9.1