Exemplo n.º 1
0
int rfc2045_decodemimesection(struct rfc2045src *src, struct rfc2045 *rfc,
			      int (*handler)(const char *, size_t, void *),
			      void *voidarg)
{
	off_t	start_pos, end_pos, start_body;
	char	buf[BUFSIZ];
	ssize_t	cnt;
	off_t	dummy;
	int	rc;

	rfc2045_mimepos(rfc, &start_pos, &end_pos, &start_body,
		&dummy, &dummy);
	if (SRC_SEEK(src, start_body) == (off_t)-1) return (-1);

        rfc2045_cdecode_start(rfc, handler, voidarg);

        while (start_body < end_pos)
        {
                cnt=sizeof(buf);
                if (cnt > end_pos-start_body)
                        cnt=end_pos-start_body;
                cnt=SRC_READ(src, buf, cnt);
                if (cnt <= 0)   break;
                if ((rc=rfc2045_cdecode(rfc, buf, cnt)) != 0)
			return (rc);
		start_body += cnt;
        }
        return (rfc2045_cdecode_end(rfc));
}
Exemplo n.º 2
0
static void do_print_section(struct rfc2045 *s, FILE *fp)
{
off_t start, end, body;
off_t nlines;
off_t nbodylines;

	rfc2045_mimepos(s, &start, &end, &body, &nlines, &nbodylines);

	if (fseek(stdin, body, SEEK_SET) == -1)
	{
		perror("fseek");
		exit(1);
	}

	rfc2045_cdecode_start(s, &decode_to_file, fp);
	while (body < end)
	{
	char	buf[BUFSIZ];
	size_t	n=sizeof(buf);

		if ((off_t)n > end-body)	n=end-body;
		n=fread(buf, 1, n, stdin);
		if (n == 0)
		{
			perror("fread");
			exit(1);
		}
		rfc2045_cdecode(s, buf, n);
		body += n;
	}
	rfc2045_cdecode_end(s);
}
Exemplo n.º 3
0
static void rfc822text(FILE *fp, struct fetchinfo *fi,
	struct imapscaninfo *info, unsigned long msgnum,
	struct rfc2045 *rfcp)
{
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;
unsigned long i;
int	c;
char	buf[BUFSIZ];
unsigned long l;

	writes("RFC822.TEXT {");

	rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body,
		&nlines, &nbodylines);

	if (fseek(fp, start_body, SEEK_SET) == -1)
	{
		fetcherror("fseek", fi, info, msgnum);
		writes("0}\r\n");
		return;
	}

	i=end_pos - start_body + nbodylines;

	writen(i);
	writes("}\r\n");

	l=0;
	while (i)
	{
		c=getc(fp);
		if (c == EOF)
		{
			fetcherror("unexpected EOF", fi, info, msgnum);
			_exit(1);
		}
		--i;
		if (l >= sizeof(BUFSIZ))
		{
			writemem(buf, l);
			l=0;
		}
		if (c == '\n' && i)
		{
			--i;
			buf[l++]='\r';
			if (l >= sizeof(BUFSIZ))
			{
				writemem(buf, l);
				l=0;
			}
		}
		buf[l++]=c;
		++body_count;
	}
	writemem(buf, l);
}
Exemplo n.º 4
0
static void rfc822size(FILE *fp, struct fetchinfo *fi,
	struct imapscaninfo *i, unsigned long msgnum,
	struct rfc2045 *mimep)
{
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;

	writes("RFC822.SIZE ");

	rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
		&nlines, &nbodylines);

	writen(end_pos - start_pos + nlines);
}
Exemplo n.º 5
0
static int search_spell(const char *filename, unsigned parnum, unsigned pos)
{
struct	rfc2045	*rfcp, *textp;
struct	buf newtext, current_line;
off_t start_pos, end_pos, start_body;
int	made_replacements, has_misspelling;
char *new_line;
unsigned paragraph;
const char	*ignoreword="";
const char	*replacefrom="";
const char	*replaceto="";
int	checked=0;
off_t	dummy;
FILE	*fp=0;
int	x;

	x=maildir_safeopen(filename, O_RDONLY, 0);
	if (x >= 0)
		if ((fp=fdopen(x, "r")) == 0)
			close(x);

	if (!fp)	return (0);
	rfcp=rfc2045_fromfp(fp);
	if (!rfcp)	enomem();

	textp=findtext(rfcp);

	if (!textp)
	{
		rfc2045_free(rfcp);
		fclose(fp);
		return (0);
	}

	buf_init(&newtext);
	buf_init(&current_line);

        rfc2045_mimepos(textp, &start_pos, &end_pos, &start_body,
		&dummy, &dummy);
        if (fseek(fp, start_body, SEEK_SET) == -1)
                enomem();

	made_replacements=0;
	has_misspelling=0;
	paragraph=0;
        for ( ; start_body < end_pos; start_body++)
	{
	int	c=getc(fp);

		if (c < 0)	enomem();
		if (c != '\n')
		{
			buf_append(&current_line, c);
			continue;
		}
		buf_append(&current_line, '\0');
		if (parnum)
		{
			--parnum;
			buf_cat(&newtext, current_line.ptr);
			buf_cat(&newtext, "\n");
			current_line.cnt=0;
			++paragraph;
			continue;
		}

		if (!checked)
		{
		int	l;

			checked=1;
			if ((l=strlen(cgi("word"))) > 0)
			{

/* Ok, what should we do? */

			const char *newword=cgi("REPLACE");

				if (!*newword || strcmp(newword, "#other") == 0)
					newword=cgi("OTHER");
				/*
				** Perhaps they entered the word without
				** checking this checkmark.
				*/
				else if (*newword == '#')
					newword="";

				if (*newword && pos + l <= strlen(current_line.ptr))
				{
				struct buf tempbuf;

					buf_init(&tempbuf);
					buf_cpyn(&tempbuf, current_line.ptr,
						pos);
					buf_cat(&tempbuf, newword);
					buf_cat(&tempbuf,
						current_line.ptr+pos+l);
					pos += strlen(newword);
					if (*cgi("REPLACEALL"))
					{
						replacefrom=cgi("word");
						replaceto=newword;
					}
					buf_append(&tempbuf, '\0');
					buf_cpy(&current_line, tempbuf.ptr);
					buf_append(&current_line, '\0');
					buf_free(&tempbuf);
					made_replacements=1;
				}
				else
				{
					pos += l;
					if (strcmp(cgi("REPLACE"),
						"#ignoreall") == 0)
						ignoreword=cgi("word");
				}

				if (strcmp(cgi("REPLACE"),
						"#insert") == 0)
				{
					spelladd(cgi("word"));
				}
			}
		}


		if (*current_line.ptr == '>')
		{
			buf_cat(&newtext, current_line.ptr);
			buf_cat(&newtext, "\n");
			pos=0;
			current_line.cnt=0;
			++paragraph;
			continue;
		}
		if (!has_misspelling)
		{
			new_line=spell_check(current_line.ptr, paragraph, pos,
				ignoreword, replacefrom, replaceto,
				&has_misspelling);
			if (new_line)
			{
				buf_cat(&newtext, new_line);
				free(new_line);
				made_replacements=1;
			}
			else	buf_cat(&newtext, current_line.ptr);
		}
		else	buf_cat(&newtext, current_line.ptr);
		buf_cat(&newtext, "\n");
		pos=0;
		current_line.cnt=0;
		++paragraph;
	}
	if (current_line.cnt)
		buf_cat(&newtext, "\n");
	rfc2045_free(rfcp);
	fclose(fp);
	if (made_replacements)
	{
	char	*p=newmsg_createdraft_do(filename, newtext.ptr,
					 NEWMSG_SQISPELL);

		if (p)	free(p);

		if (*cgi("error"))
		{
			has_misspelling=0;	/* Abort spell checking */
		}
	}

	buf_free(&newtext);
	buf_free(&current_line);

	if (*ignoreword)
	{
	static char *p=0;

		if (p)	free(p);
		p=malloc(strlen(cgi("globignore")) + 2 + strlen(ignoreword));

		if (!p)	enomem();

		strcpy(p, cgi("globignore"));
		if (*p)	strcat(p, ":");
		strcat(p, ignoreword);
		cgi_put("globignore", p);
	}

	if (*replacefrom)
	{
	static char *p=0;

		if (p)	free(p);
		p=malloc(strlen(cgi("globreplace"))+3
			+strlen(replacefrom)+strlen(replaceto));

		if (!p)	enomem();
		strcpy(p, cgi("globreplace"));
		if (*p)	strcat(p, ":");
		strcat(strcat(strcat(p, replacefrom), ":"), replaceto);
		cgi_put("globreplace", p);
		free(p);
	}
	if (has_misspelling)	return (1);
	return (0);
}
Exemplo n.º 6
0
void msgenvelope(void (*writefunc)(const char *, size_t),
		FILE *fp, struct rfc2045 *mimep)
{
char	*date=0, *subject=0;
char	*from=0, *sender=0, *replyto=0, *to=0, *cc=0, *bcc=0;
char	*inreplyto=0, *msgid=0;

off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;

char	*p, *q, *r;

	rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
		&nlines, &nbodylines);

	if (fseek(fp, start_pos, SEEK_SET) < 0)
	{
		perror("fseek");
		exit(0);
	}

	while ((p=read_header(fp, &start_pos, &start_body)) != 0)
	{
	char	**hdrp=0;
	size_t	oldl, newl;
	size_t	c;

		if ((q=strchr(p, ':')) != 0)
			*q++=0;
		for (r=p; *r; r++)
			*r=tolower((int)(unsigned char)*r);
		if (strcmp(p, "date") == 0)	hdrp= &date;
		if (strcmp(p, "subject") == 0)	hdrp= &subject;
		if (strcmp(p, "from") == 0)	hdrp= &from;
		if (strcmp(p, "sender") == 0)	hdrp= &sender;
		if (strcmp(p, "reply-to") == 0)	hdrp= &replyto;
		if (strcmp(p, "to") == 0)	hdrp= &to;
		if (strcmp(p, "cc") == 0)	hdrp= &cc;
		if (strcmp(p, "bcc") == 0)	hdrp= &bcc;
		if (strcmp(p, "in-reply-to") == 0) hdrp= &inreplyto;
		if (strcmp(p, "message-id") == 0) hdrp= &msgid;
		if (!hdrp)	continue;
		if (!q)	q="";
		oldl= *hdrp ? strlen(*hdrp):0;
		newl= strlen(q);
		c=oldl+newl+1;
		if (c > 8192)	c=8192;
		r= (char *)(*hdrp ? realloc(*hdrp, c+1):malloc(c+1));
		if (!r)
		{
			perror("malloc");
			exit(1);
		}
		if (oldl && oldl < c)
			r[oldl++]=',';
		newl=c-oldl;
		if (newl)	memcpy(r+oldl, q, newl);
		r[oldl+newl]=0;
		*hdrp= r;
	}

#if 1
	if (!replyto)
		replyto=strdup(from ? from:"");
	if (!sender)
		sender=strdup(from ? from:"");

	if (!replyto || !sender)
	{
		perror("malloc");
		exit(1);
	}
#endif

	(*writefunc)("(", 1);
	doenvs(writefunc, date);
	(*writefunc)(" ", 1);
	doenvs(writefunc, subject);
	(*writefunc)(" ", 1);
	doenva(writefunc, from);
	(*writefunc)(" ", 1);
	doenva(writefunc, sender);
	(*writefunc)(" ", 1);
	doenva(writefunc, replyto);
	(*writefunc)(" ", 1);
	doenva(writefunc, to);
	(*writefunc)(" ", 1);
	doenva(writefunc, cc);
	(*writefunc)(" ", 1);
	doenva(writefunc, bcc);
	(*writefunc)(" ", 1);
	doenvs(writefunc, inreplyto);
	(*writefunc)(" ", 1);
	doenvs(writefunc, msgid);
	(*writefunc)(")", 1);
}
Exemplo n.º 7
0
static void dsn(struct rfc2045 *p, int do_orig)
{
const char *content_type_s;
const char *content_transfer_encoding_s;
const char *charset_s;
off_t start_pos, end_pos, start_body;
off_t dummy;
const char *q;
char	buf[BUFSIZ];
unsigned i;
int	ch;
char *recip;
char *action;
char *orecip;

	rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s,
		&charset_s);
	if (strcasecmp(content_type_s, "multipart/report") ||
		(q=rfc2045_getattr(p->content_type_attr, "report-type")) == 0 ||
		strcasecmp(q, "delivery-status") ||
		!p->firstpart || !p->firstpart->next ||
		!p->firstpart->next->next)
		_exit(1);
	p=p->firstpart->next->next;
	rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s,
		&charset_s);
	rfc2045_mimepos(p, &start_pos, &end_pos, &start_body, &dummy, &dummy);
	if (strcasecmp(content_type_s, "message/delivery-status") ||
		fseek(stdin, start_body, SEEK_SET) == -1)
		_exit(1);

	i=0;
	recip=0;
	orecip=0;
	action=0;
	while (start_body < end_pos)
	{
		if ((ch=getchar()) == EOF)	break;
		++start_body;
		if (i < sizeof(buf)-1)
			buf[i++]= ch;
		if (ch != '\n')	continue;
		ch=getchar();
		if (ch != EOF)	ungetc(ch, stdin);
		if (ch != '\n' && isspace((int)(unsigned char)ch))
			continue;
		buf[i-1]=0;
		if (buf[0] == 0)
		{
			if (orecip)
			{
				if (recip)	free(recip);
				recip=orecip;
				orecip=0;
			}
			print_dsn_recip(recip, action);
			recip=0;
			action=0;
		}
		if (strncasecmp(buf, "Final-Recipient:", 16) == 0 &&
			recip == 0)
		{
			recip=strdup(buf+16);
			if (!recip)
			{
				perror("strdup");
				exit(2);
			}
		}
		if (strncasecmp(buf, "Original-Recipient:", 19) == 0 &&
			orecip == 0 && do_orig)
		{
			orecip=strdup(buf+19);
			if (!orecip)
			{
				perror("strdup");
				exit(2);
			}
		}
		if (strncasecmp(buf, "Action:", 7) == 0 && action == 0)
		{
			action=strdup(buf+7);
			if (!action)
			{
				perror("strdup");
				exit(2);
			}
		}
		i=0;
	}
	if (orecip)
	{
		if (recip)	free(recip);
		recip=orecip;
		orecip=0;
	}
	print_dsn_recip(recip, action);
}
Exemplo n.º 8
0
static void do_print_info(struct rfc2045 *s)
{
const char *content_type, *transfer_encoding, *charset;
off_t start, end, body;
const char *disposition;
const char *disposition_name;
const char *disposition_filename;
const char *content_name;
off_t nlines, nbodylines;
const char *p;

	rfc2045_mimeinfo(s, &content_type, &transfer_encoding, &charset);
	rfc2045_mimepos(s, &start, &end, &body, &nlines, &nbodylines);
	rfc2045_dispositioninfo(s, &disposition, &disposition_name,
		&disposition_filename);
	content_name=rfc2045_contentname(s);
	printf("content-type: %s\n", content_type);
	if (content_name)
	{
	char *s=rfc2047_decode_simple(content_name);

		if (!s)
		{
			perror("rfc2047_decode_simple");
			exit(1);
		}
		printf("content-name: %s\n", s);
		free(s);
	}

	printf("content-transfer-encoding: %s\n", transfer_encoding);
	printf("charset: %s\n", charset);
	if (disposition && *disposition)
		printf("content-disposition: %s\n", disposition);
	if (disposition_name && *disposition_name)
	{
	char *s=rfc2047_decode_simple(disposition_name);

		if (!s)
		{
			perror("rfc2047_decode_simple");
			exit(1);
		}
		printf("content-disposition-name: %s\n", s);
		free(s);
	}

	if (disposition_filename && *disposition_filename)
	{
	char *s=rfc2047_decode_simple(disposition_filename);

		if (!s)
		{
			perror("rfc2047_decode_simple");
			exit(1);
		}
		printf("content-disposition-filename: %s\n", s);
		free(s);
	}

	if (*(p=rfc2045_content_id(s)))
		printf("content-id: <%s>\n", p);
	if (*(p=rfc2045_content_description(s)))
	{
	char *s=rfc2047_decode_simple(p);

		if (!s)
		{
			perror("rfc2047_decode_simple");
			exit(1);
		}
		printf("content-description: %s\n", s);
		free(s);
	}
	if (*(p=rfc2045_content_language(s)))
		printf("content-language: %s\n", p);
	if (*(p=rfc2045_content_md5(s)))
		printf("content-md5: %s\n", p);

	printf("starting-pos: %lu\n", (unsigned long)start);
	printf("starting-pos-body: %lu\n", (unsigned long)body);
	printf("ending-pos: %lu\n", (unsigned long)end);
	printf("line-count: %lu\n", (unsigned long)nlines);
	printf("body-line-count: %lu\n", (unsigned long)nbodylines);
}
Exemplo n.º 9
0
void msgbodystructure( void (*writefunc)(const char *, size_t), int dox,
	FILE *fp, struct rfc2045 *mimep)
{
const char *content_type_s;
const char *content_transfer_encoding_s;
const char *charset_s;
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;
const char *disposition_s;

char	*p, *q;

	rfc2045_mimeinfo(mimep, &content_type_s, &content_transfer_encoding_s,
		&charset_s);
	rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
		&nlines, &nbodylines);

	disposition_s=mimep->content_disposition;

	(*writefunc)("(", 1);

	if (mimep->firstpart && mimep->firstpart->isdummy &&
		mimep->firstpart->next)
		/* MULTIPART */
	{
	struct rfc2045	*childp;

		for (childp=mimep->firstpart; (childp=childp->next) != 0; )
			msgbodystructure(writefunc, dox, fp, childp);

		(*writefunc)(" \"", 2);
		p=strchr(content_type_s, '/');
		if (p)
			msgappends(writefunc, p+1, strlen(p+1));
		(*writefunc)("\"", 1);

		if (dox)
		{
			(*writefunc)(" ", 1);
			do_param_list(writefunc, mimep->content_type_attr);

			(*writefunc)(" ", 1);
			do_disposition(writefunc, disposition_s,
				mimep->content_disposition_attr);

			(*writefunc)(" ", 1);
			contentstr(writefunc, rfc2045_content_language(mimep));
		}
	}
	else
	{
	char	*mybuf;
	char	buf[40];
	const	char *cp;

		mybuf=my_strdup(content_type_s);
		q=strtok(mybuf, " /");
		(*writefunc)("\"", 1);
		if (q)
			msgappends(writefunc, q, strlen(q));
		(*writefunc)("\" \"", 3);
		if (q)	q=strtok(0, " /");
		if (q)
			msgappends(writefunc, q, strlen(q));
		free(mybuf);
		(*writefunc)("\" ", 2);

		do_param_list(writefunc, mimep->content_type_attr);

		(*writefunc)(" ", 1);
		cp=rfc2045_content_id(mimep);
		if (!cp || !*cp)
			contentstr(writefunc, cp);
		else
		{
			(*writefunc)("\"<", 2);
			msgappends(writefunc, cp, strlen(cp));
			(*writefunc)(">\"", 2);
		}
		(*writefunc)(" ", 1);
		contentstr(writefunc, rfc2045_content_description(mimep));

		(*writefunc)(" \"", 2);
		msgappends(writefunc, content_transfer_encoding_s,
			strlen(content_transfer_encoding_s));
		(*writefunc)("\" ", 2);

		sprintf(buf, "%lu", (unsigned long)
			(end_pos-start_body+nbodylines));
			/* nbodylines added for CRs */
		(*writefunc)(buf, strlen(buf));

		if (
		(content_type_s[0] == 't' || content_type_s[0] == 'T') &&
		(content_type_s[1] == 'e' || content_type_s[1] == 'E') &&
		(content_type_s[2] == 'x' || content_type_s[2] == 'X') &&
		(content_type_s[3] == 't' || content_type_s[3] == 'T') &&
			(content_type_s[4] == '/' ||
			 content_type_s[4] == 0))
		{
			(*writefunc)(" ", 1);
			sprintf(buf, "%lu", (unsigned long)nbodylines);
			(*writefunc)(buf, strlen(buf));
		}

		if (mimep->firstpart && !mimep->firstpart->isdummy)
			/* message/rfc822 */
		{
			(*writefunc)(" ", 1);
			msgenvelope(writefunc, fp, mimep->firstpart);
			(*writefunc)(" ", 1);
			msgbodystructure(writefunc, dox, fp, mimep->firstpart);
			(*writefunc)(" ", 1);
			sprintf(buf, "%lu", (unsigned long)nbodylines);
			(*writefunc)(buf, strlen(buf));
		}

		if (dox)
		{
			(*writefunc)(" ", 1);
			contentstr(writefunc, rfc2045_content_md5(mimep));

			(*writefunc)(" ", 1);
			do_disposition(writefunc, disposition_s,
				mimep->content_disposition_attr);

			(*writefunc)(" NIL", 4);
				/* TODO Content-Language: */
		}
	}
	(*writefunc)(")", 1);
}
Exemplo n.º 10
0
static void dofetchheadersbuf(FILE *fp, struct fetchinfo *fi,
	struct imapscaninfo *info, unsigned long msgnum,
	struct rfc2045 *mimep,
	int (*headerfunc)(struct fetchinfo *fi, const char *))
{
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;
size_t i,j,k,l;
char	buf[BUFSIZ+2];
int	goodheader;
unsigned long skipping;
unsigned long cnt;
char	*p;
int	ii;

	rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
		&nlines, &nbodylines);
	if (fseek(fp, start_pos, SEEK_SET) == -1)
	{
		writes("{0}\r\n");
		fetcherror("fseek", fi, info, msgnum);
		return;
	}

	ii=fread(buf, 1, start_body - start_pos, fp);
	if (ii < 0 || (i=ii) != start_body - start_pos)
	{
		fetcherror("unexpected EOF", fi, info, msgnum);
		exit(1);
	}
	goodheader= (*headerfunc)(fi, "");

	l=0;
	for (j=0; j<i; )
	{
		if (buf[j] != '\n' && buf[j] != '\r' &&
			!isspace((int)(unsigned char)buf[j]))
		{
			goodheader= (*headerfunc)(fi, "");

			for (k=j; k<i; k++)
			{
				if (buf[k] == '\n' || buf[k] == ':')
					break;
			}

			if (k < i && buf[k] == ':')
			{
				buf[k]=0;
				goodheader=(*headerfunc)(fi, buf+j);
				buf[k]=':';
			}
		}
		else if (buf[j] == '\n')
			goodheader=0;

		for (k=j; k<i; k++)
			if (buf[k] == '\n')
			{
				++k;
				break;
			}

		if (goodheader)
		{
			while (j<k)
				buf[l++]=buf[j++];
		}
		j=k;
	}

	buf[l++]='\n';	/* Always append a blank line */

	cnt=l;
	for (i=0; i<l; i++)
		if (buf[i] == '\n')	++cnt;

	skipping=0;
	if (fi->ispartial)
	{
		skipping=fi->partialstart;
		if (skipping > cnt)	skipping=cnt;
		cnt -= skipping;
		if (fi->ispartial > 1 && cnt > fi->partialend)
			cnt=fi->partialend;
	}

	writes("{");
	writen(cnt);
	writes("}\r\n");
	p=buf;
	while (skipping)
	{
		if (*p == '\n')
		{
			--skipping;
			if (skipping == 0)
			{
				if (cnt)
				{
					writes("\n");
					--cnt;
				}
				break;
			}
		}
		--skipping;
		++p;
	}

	while (cnt)
	{
		if (*p == '\n')
		{
			writes("\r");
			if (--cnt == 0)	break;
			writes("\n");
			--cnt;
			++p;
			continue;
		}
		for (i=0; i<cnt; i++)
			if (p[i] == '\n')
				break;
		writemem(p, i);
		p += i;
		cnt -= i;
		header_count += i;
	}
}
Exemplo n.º 11
0
static void dofetchmsgbody(FILE *fp, struct fetchinfo *fi,
	struct imapscaninfo *i, unsigned long msgnum,
	struct rfc2045 *mimep)
{
const char *p=fi->bodysection;
off_t start_pos, end_pos, start_body;
off_t nlines, nbodylines;
unsigned long cnt;
char	buf[BUFSIZ];
char	rbuf[BUFSIZ];
char	*rbufptr;
int	rbufleft;
unsigned long bufptr;
unsigned long skipping;
int	ismsgrfc822=1;

off_t start_seek_pos;
 struct rfc2045 *headermimep;

/*
** To optimize consecutive FETCHes, we cache our virtual and physical
** position.  What we do is that on the first fetch we count off the
** characters we read, and keep track of both the physical and the CRLF-based
** offset into the message.  Then, on subsequent FETCHes, we attempt to
** use that information.
*/

off_t cnt_virtual_chars;
off_t cnt_phys_chars;

off_t cache_virtual_chars;
off_t cache_phys_chars;

	headermimep=mimep;
 
	while (p && isdigit((int)(unsigned char)*p))
	{
	unsigned long n=0;

		headermimep=mimep;

		do
		{
			n=n*10 + (*p++ - '0');
		} while (isdigit((int)(unsigned char)*p));

		if (mimep)
		{
			if (ismsgrfc822)
			{
				const char *ct, *dummy;

				if (mimep->firstpart == 0)
				{
					/* Not a multipart, n must be 1 */
					if (n != 1)
						mimep=0;
					if (*p == '.')
						++p;
					continue;
				}
				ismsgrfc822=0;

				rfc2045_mimeinfo(mimep, &ct,
						 &dummy,
						 &dummy);

				if (ct && strcasecmp(ct, "message/rfc822"
						     ) == 0)
					ismsgrfc822=1;
				/* The content is another message/rfc822 */
			}

			mimep=mimep->firstpart;
			while (mimep)
			{
				if (!mimep->isdummy && --n == 0)
					break;
				mimep=mimep->next;
			}
			headermimep=mimep;

			if (mimep && mimep->firstpart &&
				!mimep->firstpart->isdummy)
				/* This is a message/rfc822 part */
			{
				if (!*p)
					break;

				mimep=mimep->firstpart;
				ismsgrfc822=1;
			}
		}
		if (*p == '.')
			++p;
	}

	if (p && strcmp(p, "MIME") == 0)
		mimep=headermimep;

	if (mimep == 0)
	{
		writes("{0}\r\n");
		return;
	}

	rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
		&nlines, &nbodylines);


	if (p && strcmp(p, "TEXT") == 0)
	{
		start_seek_pos=start_body;
		cnt=end_pos - start_body + nbodylines;
	}
	else if (p && strcmp(p, "HEADER") == 0)
	{
		start_seek_pos=start_pos;
		cnt= start_body - start_pos + (nlines - nbodylines);
	}
	else if (p && strcmp(p, "HEADER.FIELDS") == 0)
	{
		if (start_body - start_pos <= BUFSIZ)
			dofetchheadersbuf(fp, fi, i, msgnum, mimep,
				&dofetchheaderfields);
		else
			dofetchheadersfile(fp, fi, i, msgnum, mimep,
				&dofetchheaderfields);
		return;
	}
	else if (p && strcmp(p, "HEADER.FIELDS.NOT") == 0)
	{
		if (start_body - start_pos <= BUFSIZ)
			dofetchheadersbuf(fp, fi, i, msgnum, mimep,
				&dofetchheadernotfields);
		else
			dofetchheadersfile(fp, fi, i, msgnum, mimep,
				&dofetchheadernotfields);
		return;
	}
	else if (p && strcmp(p, "MIME") == 0)
	{
		if (start_body - start_pos <= BUFSIZ)
			dofetchheadersbuf(fp, fi, i, msgnum, mimep,
				&dofetchheadermime);
		else
			dofetchheadersfile(fp, fi, i, msgnum, mimep,
				&dofetchheadermime);
		return;
	}
	else if (*fi->bodysection == 0)
	{
		start_seek_pos=start_pos;

		cnt= end_pos - start_pos + nlines;
	}
	else	/* Last possibility: entire body */
	{
		start_seek_pos=start_body;

		cnt= end_pos - start_body + nbodylines;
	}

	skipping=0;
	if (fi->ispartial)
	{
		skipping=fi->partialstart;
		if (skipping > cnt)	skipping=cnt;
		cnt -= skipping;
		if (fi->ispartial > 1 && cnt > fi->partialend)
			cnt=fi->partialend;
	}

	if (get_cached_offsets(start_seek_pos, &cnt_virtual_chars,
			       &cnt_phys_chars) == 0 &&
	    cnt_virtual_chars <= skipping)	/* Yeah - cache it, baby! */
	{
		if (fseek(fp, start_seek_pos+cnt_phys_chars, SEEK_SET) == -1)
		{
			writes("{0}\r\n");
			fetcherror("fseek", fi, i, msgnum);
			return;
		}
		skipping -= cnt_virtual_chars;
	}
	else
	{
		if (fseek(fp, start_seek_pos, SEEK_SET) == -1)
		{
			writes("{0}\r\n");
			fetcherror("fseek", fi, i, msgnum);
			return;
		}

		cnt_virtual_chars=0;
		cnt_phys_chars=0;
	}

	cache_virtual_chars=cnt_virtual_chars;
	cache_phys_chars=cnt_phys_chars;

	writes("{");
	writen(cnt);
	writes("}\r\n");
	bufptr=0;
	writeflush();

	rbufptr=0;
	rbufleft=0;

	while (cnt)
	{
	int	c;

		if (!rbufleft)
		{
			rbufleft=fread(rbuf, 1, sizeof(rbuf), fp);
			if (rbufleft < 0)	rbufleft=0;
			rbufptr=rbuf;
		}

		if (!rbufleft)
		{
			fetcherror("unexpected EOF", fi, i, msgnum);
			_exit(1);
		}

		--rbufleft;
		c=(int)(unsigned char)*rbufptr++;
		++cnt_phys_chars;

		if (c == '\n')
		{
			++cnt_virtual_chars;

			if (skipping)
				--skipping;
			else
			{
				if (bufptr >= sizeof(buf))
				{
					writemem(buf, sizeof(buf));
					bufptr=0;
					/*writeflush();*/
				}
				buf[bufptr++]='\r';
				--cnt;

				if (cnt == 0)
					break;
			}
		}

		++cnt_virtual_chars;
		if (skipping)
			--skipping;
		else
		{
			++body_count;

			if (bufptr >= sizeof(buf))
			{
				writemem(buf, sizeof(buf));
				bufptr=0;
				/*writeflush();*/
			}
			buf[bufptr++]=c;
			--cnt;
		}
		cache_virtual_chars=cnt_virtual_chars;
		cache_phys_chars=cnt_phys_chars;
	}
	writemem(buf, bufptr);
	writeflush();
	save_cached_offsets(start_seek_pos, cache_virtual_chars,
			    cache_phys_chars);
}
Exemplo n.º 12
0
static void dofetchheadersfile(FILE *fp, struct fetchinfo *fi,
	struct imapscaninfo *info, unsigned long msgnum,
	struct rfc2045 *mimep,
	int (*headerfunc)(struct fetchinfo *fi, const char *))
{
off_t start_pos, end_pos, start_body, left;
off_t nlines, nbodylines;
size_t i;
int	c, pass;
char	buf1[256];
int	goodheader;
struct	fetchheaderinfo finfo;

	finfo.cnt=0;
	for (pass=0; pass<2; pass++)
	{
	void (*func)(struct fetchheaderinfo *, const char *, size_t)=
			pass ? printheader:countheader;

		rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
			&nlines, &nbodylines);
		if (fseek(fp, start_pos, SEEK_SET) == -1)
		{
			writes("{0}\r\n");
			fetcherror("fseek", fi, info, msgnum);
			return;
		}
		if (pass)
		{
			finfo.skipping=0;
			if (fi->ispartial)
			{
				finfo.skipping=fi->partialstart;
				if (finfo.skipping > finfo.cnt)
					finfo.skipping=finfo.cnt;
				finfo.cnt -= finfo.skipping;
				if (fi->ispartial > 1 &&
					finfo.cnt > fi->partialend)
					finfo.cnt=fi->partialend;
			}

			writes("{");
			writen(finfo.cnt+2);	/* BUG */
			writes("}\r\n");
		}
		left=start_body - start_pos;

		goodheader= (*headerfunc)(fi, "");
		while (left)
		{
			for (i=0; i<sizeof(buf1)-1 && i<left; i++)
			{
				c=getc(fp);
				if (c == EOF)
				{
					fetcherror("unexpected EOF", fi, info, msgnum);
					_exit(1);
				}

				if (c == '\n' || c == ':')
				{
					ungetc(c, fp);
					break;
				}
				buf1[i]=c;
			}
			buf1[i]=0;
			left -= i;

			if (buf1[0] != '\n' && buf1[0] != '\r' &&
				!isspace((int)(unsigned char)buf1[0]))
				goodheader= (*headerfunc)(fi, buf1);
			else if (buf1[0] == '\n')
				goodheader=0;

			if (!goodheader)
			{
				while (left)
				{
					c=getc(fp);
					--left;
					if (c == EOF)
					{
						fetcherror("unexpected EOF", fi, info, msgnum);
						_exit(1);
					}
					if (c == '\n')	break;
				}
				continue;
			}

			(*func)(&finfo, buf1, i);

			i=0;
			while (left)
			{
				c=getc(fp);
				if (c == EOF)
				{
					fetcherror("unexpected EOF", fi, info, msgnum);
					_exit(1);
				}
				--left;
				if (i >= sizeof(buf1))
				{
					(*func)(&finfo, buf1, i);
					i=0;
				}
				if (c == '\n')
				{
					(*func)(&finfo, buf1, i);
					buf1[0]='\r';
					i=1;
				}
				buf1[i++]=c;
				if (c == '\n')	break;
			}
			(*func)(&finfo, buf1, i);
			if (pass && finfo.cnt == 0)	break;
		}
	}
	writes("\r\n");	/* BUG */
}