static void
filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
{
	CamelMimeFilterCharset *charset = (CamelMimeFilterCharset *)mf;
	size_t inleft, outleft, converted = 0;
	const char *inbuf;
	char *outbuf;

	if (charset->ic == (iconv_t) -1)
		goto noop;

	camel_mime_filter_set_size (mf, len * 5 + 16, FALSE);
	outbuf = mf->outbuf + converted;
	outleft = mf->outsize - converted;

	inbuf = in;
	inleft = len;

	do {
		converted = e_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft);
		if (converted == (size_t) -1) {
			if (errno == E2BIG || errno == EINVAL)
				break;

			if (errno == EILSEQ) {
				/*
				 * EILSEQ An invalid multibyte sequence has been  encountered
				 *        in the input.
				 *
				 * What we do here is eat the invalid bytes in the sequence and continue
				 */

				inbuf++;
				inleft--;
			} else {
				/* unknown error condition */
				goto noop;
			}
		}
	} while (((int) inleft) > 0);

	if (((int) inleft) > 0) {
		/* We've either got an E2BIG or EINVAL. Save the
                   remainder of the buffer as we'll process this next
                   time through */
		camel_mime_filter_backup (mf, inbuf, inleft);
	}

	*out = mf->outbuf;
	*outlen = outbuf - mf->outbuf;
	*outprespace = mf->outpre;

	return;

 noop:

	*out = in;
	*outlen = len;
	*outprespace = prespace;
}
Ejemplo n.º 2
0
static void
strip_signature (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
		 char **out, size_t *outlen, size_t *outprespace, int flush)
{
	EMStripSigFilter *stripsig = (EMStripSigFilter *) filter;
	register const char *inptr = in;
	const char *inend = in + len;
	const char *start = NULL;

	if (stripsig->midline) {
		while (inptr < inend && *inptr != '\n')
			inptr++;

		if (inptr < inend) {
			stripsig->midline = FALSE;
			inptr++;
		}
	}

	while (inptr < inend) {
		if ((inend - inptr) >= 4 && !strncmp (inptr, "-- \n", 4)) {
			start = inptr;
			inptr += 4;
		} else {
			while (inptr < inend && *inptr != '\n')
				inptr++;

			if (inptr == inend) {
				stripsig->midline = TRUE;
				break;
			}

			inptr++;
		}
	}

	if (start != NULL)
		inptr = start;

	if (!flush && inend > inptr)
		camel_mime_filter_backup (filter, inptr, inend - inptr);
	else if (!start)
		inptr = inend;

	*out = in;
	*outlen = inptr - in;
	*outprespace = prespace;
}
Ejemplo n.º 3
0
/* Yes, it is complicated ... */
static void
filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
{
	CamelMimeFilterFrom *f = (CamelMimeFilterFrom *)mf;
	register char *inptr, *inend;
	int left;
	int midline = f->midline;
	int fromcount = 0;
	struct fromnode *head = NULL, *tail = (struct fromnode *)&head, *node;
	char *outptr;

	inptr = in;
	inend = inptr+len;

	d(printf("Filtering '%.*s'\n", len, in));

	/* first, see if we need to escape any from's */
	while (inptr<inend) {
		register int c = -1;

		if (midline)
			while (inptr < inend && (c = *inptr++) != '\n')
				;

		if (c == '\n' || !midline) {
			left = inend-inptr;
			if (left > 0) {
				midline = TRUE;
				if (left < 5) {
					if (inptr[0] == 'F') {
						camel_mime_filter_backup(mf, inptr, left);
						midline = FALSE;
						inend = inptr;
						break;
					}
				} else {
					if (!strncmp(inptr, "From ", 5)) {
						fromcount++;
						/* yes, we do alloc them on the stack ... at most we're going to get
						   len / 7 of them anyway */
						node = alloca(sizeof(*node));
						node->pointer = inptr;
						node->next = NULL;
						tail->next = node;
						tail = node;
						inptr += 5;
					}
				}
			} else {
				/* \n is at end of line, check next buffer */
				midline = FALSE;
			}
		}
	}

	f->midline = midline;

	if (fromcount > 0) {
		camel_mime_filter_set_size(mf, len + fromcount, FALSE);
		node = head;
		inptr = in;
		outptr = mf->outbuf;
		while (node) {
			memcpy(outptr, inptr, node->pointer - inptr);
			outptr += node->pointer - inptr;
			*outptr++ = '>';
			inptr = node->pointer;
			node = node->next;
		}
		memcpy(outptr, inptr, inend - inptr);
		outptr += inend - inptr;
		*out = mf->outbuf;
		*outlen = outptr - mf->outbuf;
		*outprespace = mf->outbuf - mf->outreal;

		d(printf("Filtered '%.*s'\n", *outlen, *out));
	} else {
		*out = in;
		*outlen = inend - in;
		*outprespace = prespace;

		d(printf("Filtered '%.*s'\n", *outlen, *out));
	}
}
static void
filter_run(CamelMimeFilter *f, char *in, size_t inlen, size_t prespace, char **out, size_t *outlen, size_t *outprespace, int last)
{
	CamelMimeFilterPgp *pgp = (CamelMimeFilterPgp *) f;
	const char *start, *inend = in + inlen;
	register const char *inptr = in;
	register char *o;
	gboolean blank;
	size_t len;
	
	/* only need as much space as the input, we're stripping chars */
	camel_mime_filter_set_size (f, inlen, FALSE);
	
	o = f->outbuf;
	
	while (inptr < inend) {
		start = inptr;
		
		blank = TRUE;
		while (inptr < inend && *inptr != '\n') {
			if (blank && !strchr (" \t\r", *inptr))
				blank = FALSE;
			inptr++;
		}
		
		if (inptr == inend) {
			if (!last) {
				camel_mime_filter_backup (f, start, inend - start);
				inend = start;
			}
			break;
		}
		
		len = inptr - start;
		if (len > 0 && inptr[-1] == '\r')
			len--;
		
		inptr++;
		
		switch (pgp->state) {
		case PGP_PREFACE:
			/* check for the beginning of the pgp block */
			if (len == BEGIN_PGP_SIGNED_MESSAGE_LEN && !strncmp (start, BEGIN_PGP_SIGNED_MESSAGE, len)) {
				pgp->state++;
				break;
			}
			
			memcpy (o, start, inptr - start);
			o += (inptr - start);
			break;
		case PGP_HEADER:
			/* pgp headers (Hash: SHA1, etc) end with a blank (zero-length,
			   or containing only whitespace) line; see RFC2440 */
			if (blank)
				pgp->state++;
			break;
		case PGP_MESSAGE:
			/* check for beginning of the pgp signature block */
			if (len == BEGIN_PGP_SIGNATURE_LEN && !strncmp (start, BEGIN_PGP_SIGNATURE, len)) {
				pgp->state++;
				break;
			}
			
			/* do dash decoding */
			if (!strncmp (start, "- ", 2)) {
				/* Dash encoded line found, skip encoding */
				start += 2;
			}
			
			memcpy (o, start, inptr - start);
			o += (inptr - start);
			break;
		case PGP_FOOTER:
			if (len == END_PGP_SIGNATURE_LEN && !strncmp (start, END_PGP_SIGNATURE, len))
				pgp->state = PGP_PREFACE;
			break;
		}
	}
	
	*out = f->outbuf;
	*outlen = o - f->outbuf;
	*outprespace = f->outpre;
}