コード例 #1
0
static gint
stream_fill (CamelPOP3Stream *is,
             GCancellable *cancellable,
             GError **error)
{
	gint left = 0;
	GError *local_error = NULL;

	if (is->source) {
		left = is->end - is->ptr;
		memmove (is->buf, is->ptr, left);
		is->end = is->buf + left;
		is->ptr = is->buf;
		left = camel_stream_read (
			is->source, (gchar *) is->end,
			CAMEL_POP3_STREAM_SIZE - (is->end - is->buf),
			cancellable, &local_error);
		if (local_error) {
			dd (printf ("POP3_STREAM_FILL: Failed to read bytes: %s\n", local_error->message));
			g_propagate_error (error, local_error);
		}

		if (left > 0) {
			is->end += left;
			is->end[0] = '\n';
			return is->end - is->ptr;
		} else
			return -1;
	}

	return 0;
}
コード例 #2
0
static gint
nntp_stream_fill (CamelNNTPStream *is,
                  GCancellable *cancellable,
                  GError **error)
{
	gint left = 0;

	if (is->source) {
		left = is->end - is->ptr;
		memcpy (is->buf, is->ptr, left);
		is->end = is->buf + left;
		is->ptr = is->buf;
		left = camel_stream_read (
			is->source, (gchar *) is->end,
			CAMEL_NNTP_STREAM_SIZE - (is->end - is->buf),
			cancellable, error);
		if (left > 0) {
			is->end += left;
			is->end[0] = '\n';
			return is->end - is->ptr;
		} else {
			if (left == 0) {
				errno = ECONNRESET;
				g_set_error (
					error, G_IO_ERROR,
					g_io_error_from_errno (errno),
					"%s", g_strerror (errno));
			}
			return -1;
		}
	}

	return 0;
}
コード例 #3
0
static ssize_t
scalix_fill (CamelSCALIXStream *scalix)
{
	unsigned char *inbuf, *inptr, *inend;
	ssize_t nread;
	size_t inlen;
	
	if (scalix->disconnected) {
		errno = EINVAL;
		return -1;
	}
	
	inbuf = scalix->inbuf;
	inptr = scalix->inptr;
	inend = scalix->inend;
	inlen = inend - inptr;
	
	g_assert (inptr <= inend);
	
	/* attempt to align 'inend' with realbuf + SCAN_HEAD */
	if (inptr >= inbuf) {
		inbuf -= inlen < SCALIX_READ_PRELEN ? inlen : SCALIX_READ_PRELEN;
		memmove (inbuf, inptr, inlen);
		inptr = inbuf;
		inbuf += inlen;
	} else if (inptr > scalix->realbuf) {
		size_t shift;
		
		shift = MIN (inptr - scalix->realbuf, inend - inbuf);
		memmove (inptr - shift, inptr, inlen);
		inptr -= shift;
		inbuf = inptr + inlen;
	} else {
		/* we can't shift... */
		inbuf = inend;
	}
	
	scalix->inptr = inptr;
	scalix->inend = inbuf;
	inend = scalix->realbuf + SCALIX_READ_PRELEN + SCALIX_READ_BUFLEN - 1;
	
	if ((nread = camel_stream_read (scalix->stream, inbuf, inend - inbuf)) == -1)
		return -1;
	else if (nread == 0)
		scalix->disconnected = TRUE;
	
	scalix->inend += nread;
	
	return scalix->inend - scalix->inptr;
}
コード例 #4
0
static ssize_t
imap4_fill (CamelIMAP4Stream *imap4)
{
	unsigned char *inbuf, *inptr, *inend;
	ssize_t nread;
	size_t inlen;

	if (imap4->disconnected) {
		errno = EINVAL;
		return -1;
	}

	inbuf = imap4->inbuf;
	inptr = imap4->inptr;
	inend = imap4->inend;
	inlen = inend - inptr;

	g_assert (inptr <= inend);

	/* attempt to align 'inend' with realbuf + SCAN_HEAD */
	if (inptr >= inbuf) {
		inbuf -= inlen < IMAP4_READ_PRELEN ? inlen : IMAP4_READ_PRELEN;
		memmove (inbuf, inptr, inlen);
		inptr = inbuf;
		inbuf += inlen;
	} else if (inptr > imap4->realbuf) {
		size_t shift;

		shift = MIN (inptr - imap4->realbuf, inend - inbuf);
		memmove (inptr - shift, inptr, inlen);
		inptr -= shift;
		inbuf = inptr + inlen;
	} else {
		/* we can't shift... */
		inbuf = inend;
	}

	imap4->inptr = inptr;
	imap4->inend = inbuf;
	inend = imap4->realbuf + IMAP4_READ_PRELEN + IMAP4_READ_BUFLEN - 1;

	if ((nread = camel_stream_read (imap4->stream, inbuf, inend - inbuf)) == -1)
		return -1;
	else if (nread == 0)
		imap4->disconnected = TRUE;

	imap4->inend += nread;

	return imap4->inend - imap4->inptr;
}
コード例 #5
0
static ssize_t
stream_read (CamelStream *stream, char *buffer, size_t n)
{
	CamelSCALIXStream *scalix = (CamelSCALIXStream *) stream;
	ssize_t len, nread = 0;
	
	if (scalix->mode == CAMEL_SCALIX_STREAM_MODE_LITERAL) {
		/* don't let our caller read past the end of the literal */
		n = MIN (n, scalix->literal);
	}
	
	if (scalix->inptr < scalix->inend) {
		len = MIN (n, scalix->inend - scalix->inptr);
		memcpy (buffer, scalix->inptr, len);
		scalix->inptr += len;
		nread = len;
	}
	
	if (nread < n) {
		if ((len = camel_stream_read (scalix->stream, buffer + nread, n - nread)) == 0)
			scalix->disconnected = TRUE;
		else if (len == -1)
			return -1;
		
		nread += len;
	}
	
	if (scalix->mode == CAMEL_SCALIX_STREAM_MODE_LITERAL) {
		scalix->literal -= nread;
		
		if (scalix->literal == 0) {
			scalix->mode = CAMEL_SCALIX_STREAM_MODE_TOKEN;
			scalix->eol = TRUE;
		}
	}
	
	return nread;
}
コード例 #6
0
static int
stream_fill(CamelPOP3Stream *is)
{
	int left = 0;

	if (is->source) {
		left = is->end - is->ptr;
		memcpy(is->buf, is->ptr, left);
		is->end = is->buf + left;
		is->ptr = is->buf;
		left = camel_stream_read(is->source, (char *) is->end, CAMEL_POP3_STREAM_SIZE - (is->end - is->buf));
		if (left > 0) {
			is->end += left;
			is->end[0] = '\n';
			return is->end - is->ptr;
		} else {
			dd(printf("POP3_STREAM_FILL(ERROR): '%s'\n", strerror (errno)));
			return -1;
		}
	}

	return 0;
}
static ssize_t
stream_read (CamelStream *stream, char *buffer, size_t n)
{
	CamelSeekableStream *parent;
	CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
	CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
	ssize_t v;

	if (n == 0)
		return 0;

	parent = seekable_substream->parent_stream;

	/* Go to our position in the parent stream. */
	if (!parent_reset (seekable_substream, parent)) {
		stream->eos = TRUE;
		return 0;
	}

	/* Compute how many bytes should be read. */
	if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND)
		n = MIN (seekable_stream->bound_end -  seekable_stream->position, n);

	if (n == 0) {
		stream->eos = TRUE;
		return 0;
	}

	v = camel_stream_read (CAMEL_STREAM (parent), buffer, n);

	/* ignore <0 - it's an error, let the caller deal */
	if (v > 0)
		seekable_stream->position += v;

	return v;
}
コード例 #8
0
gint
main (gint argc,
      gchar **argv)
{
	CamelStream *source;
	CamelStream *correct;
	CamelStream *stream;
	CamelMimeFilter *sh;
	gchar *work;
	gint i;
	gssize comp_progress, comp_correct_chunk, comp_filter_chunk;
	gint comp_i;
	gchar comp_correct[CHUNK_SIZE], comp_filter[CHUNK_SIZE];

	camel_test_init (argc, argv);

	for (i = 0; i < NUM_CASES; i++) {
		gint j;

		work = g_strdup_printf ("CRLF/DOT filter, test case %d", i);
		camel_test_start (work);
		g_free (work);

		for (j = CRLF_ENCODE; j < CRLF_DONE; j++) {
			CamelMimeFilterCRLFDirection direction;
			gchar *infile = NULL, *outfile = NULL;

			switch (j) {
			case CRLF_ENCODE:
				camel_test_push ("Test of the encoder");
				direction = CAMEL_MIME_FILTER_CRLF_ENCODE;
				infile = g_strdup_printf ("%s/crlf-%d.in", SOURCEDIR, i + 1);
				outfile = g_strdup_printf ("%s/crlf-%d.out", SOURCEDIR, i + 1);
				break;
			case CRLF_DECODE:
				camel_test_push ("Test of the decoder");
				direction = CAMEL_MIME_FILTER_CRLF_DECODE;
				infile = g_strdup_printf ("%s/crlf-%d.out", SOURCEDIR, i + 1);
				outfile = g_strdup_printf ("%s/crlf-%d.in", SOURCEDIR, i + 1);
				break;
			default:
				break;
			}

			camel_test_push ("Initializing objects");
			source = camel_stream_fs_new_with_name (infile, 0, O_RDONLY, NULL);
			if (!source) {
				camel_test_fail ("Failed to open input case in \"%s\"", infile);
				g_free (infile);
				continue;
			}
			g_free (infile);

			correct = camel_stream_fs_new_with_name (outfile, 0, O_RDONLY, NULL);
			if (!correct) {
				camel_test_fail ("Failed to open correct output in \"%s\"", outfile);
				g_free (outfile);
				continue;
			}
			g_free (outfile);

			stream = camel_stream_filter_new (source);
			if (!stream) {
				camel_test_fail ("Couldn't create CamelStreamFilter??");
				continue;
			}

			sh = camel_mime_filter_crlf_new (direction, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
			if (!sh) {
				camel_test_fail ("Couldn't create CamelMimeFilterCrlf??");
				continue;
			}

			camel_stream_filter_add (
				CAMEL_STREAM_FILTER (stream), sh);
			camel_test_pull ();

			camel_test_push ("Running filter and comparing to correct result");

			comp_progress = 0;

			while (1) {
				comp_correct_chunk = camel_stream_read (
					correct, comp_correct,
					CHUNK_SIZE, NULL, NULL);
				comp_filter_chunk = 0;

				if (comp_correct_chunk == 0)
					break;

				while (comp_filter_chunk < comp_correct_chunk) {
					gssize delta;

					delta = camel_stream_read (
						stream,
						comp_filter + comp_filter_chunk,
						CHUNK_SIZE - comp_filter_chunk,
						NULL, NULL);

					if (delta == 0) {
						camel_test_fail ("Chunks are different sizes: correct is %d, "
								 "filter is %d, %d bytes into stream",
								 comp_correct_chunk, comp_filter_chunk, comp_progress);
					}

					comp_filter_chunk += delta;
				}

				for (comp_i = 0; comp_i < comp_filter_chunk; comp_i++) {
					if (comp_correct[comp_i] != comp_filter[comp_i]) {
						camel_test_fail ("Difference: correct is %c, filter is %c, "
								 "%d bytes into stream",
								 comp_correct[comp_i],
								 comp_filter[comp_i],
								 comp_progress + comp_i);
					}
				}

				comp_progress += comp_filter_chunk;
			}

			camel_test_pull ();

			/* inefficient */
			camel_test_push ("Cleaning up");
			g_object_unref (stream);
			g_object_unref (correct);
			g_object_unref (source);
			g_object_unref (sh);
			camel_test_pull ();

			camel_test_pull ();
		}

		camel_test_end ();
	}

	return 0;
}
コード例 #9
0
/* Given a line that is the start of an untagged response, read and
 * return the complete response, which may include an arbitrary number
 * of literals.
 */
static char *
imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex)
{
	int fulllen, ldigits, nread, n, i, sexp = 0;
	unsigned int length;
	GPtrArray *data;
	GString *str;
	char *end, *p, *s, *d;

	p = strrchr (line, '{');
	if (!p)
		return line;

	data = g_ptr_array_new ();
	fulllen = 0;

	while (1) {
		str = g_string_new (line);
		g_free (line);
		fulllen += str->len;
		g_ptr_array_add (data, str);

		if (!(p = strrchr (str->str, '{')) || p[1] == '-')
			break;

		/* HACK ALERT: We scan the non-literal part of the string, looking for possible s expression braces.
		   This assumes we're getting s-expressions, which we should be.
		   This is so if we get a blank line after a literal, in an s-expression, we can keep going, since
		   we do no other parsing at this level.
		   TODO: handle quoted strings? */
		for (s=str->str; s<p; s++) {
			if (*s == '(')
				sexp++;
			else if (*s == ')')
				sexp--;
		}

		length = strtoul (p + 1, &end, 10);
		if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2)
			break;
		ldigits = end - (p + 1);

		/* Read the literal */
		str = g_string_sized_new (length + 2);
		str->str[0] = '\n';
		nread = 0;

		do {
			if ((n = camel_stream_read (store->istream, str->str + nread + 1, length - nread)) == -1) {
				if (errno == EINTR)
					camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
							     _("Operation cancelled"));
				else
					camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
							     g_strerror (errno));
				camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
				g_string_free (str, TRUE);
				goto lose;
			}

			nread += n;
		} while (n > 0 && nread < length);

		if (nread < length) {
			camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
					     _("Server response ended too soon."));
			camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
			g_string_free (str, TRUE);
			goto lose;
		}
		str->str[length + 1] = '\0';

		if (camel_debug("imap")) {
			printf("Literal: -->");
			fwrite(str->str+1, 1, length, stdout);
			printf("<--\n");
		}

		/* Fix up the literal, turning CRLFs into LF. Also, if
		 * we find any embedded NULs, strip them. This is
		 * dubious, but:
		 *   - The IMAP grammar says you can't have NULs here
		 *     anyway, so this will not affect our behavior
		 *     against any completely correct server.
		 *   - WU-imapd 12.264 (at least) will cheerily pass
		 *     NULs along if they are embedded in the message
		 */

		s = d = str->str + 1;
		end = str->str + 1 + length;
		while (s < end) {
			while (s < end && *s == '\0') {
				s++;
				length--;
			}
			if (*s == '\r' && *(s + 1) == '\n') {
				s++;
				length--;
			}
			*d++ = *s++;
		}
		*d = '\0';
		str->len = length + 1;

		/* p points to the "{" in the line that starts the
		 * literal. The length of the CR-less response must be
		 * less than or equal to the length of the response
		 * with CRs, therefore overwriting the old value with
		 * the new value cannot cause an overrun. However, we
		 * don't want it to be shorter either, because then the
		 * GString's length would be off...
		 */
		sprintf (p, "{%0*u}", ldigits, length);

		fulllen += str->len;
		g_ptr_array_add (data, str);

		/* Read the next line. */
		do {
			if (camel_imap_store_readline (store, &line, ex) < 0)
				goto lose;

			/* MAJOR HACK ALERT, gropuwise sometimes sends an extra blank line after literals, check that here
			   But only do it if we're inside an sexpression */
			if (line[0] == 0 && sexp > 0)
				g_warning("Server sent empty line after a literal, assuming in error");
		} while (line[0] == 0 && sexp > 0);
	}

	/* Now reassemble the data. */
	p = line = g_malloc (fulllen + 1);
	for (i = 0; i < data->len; i++) {
		str = data->pdata[i];
		memcpy (p, str->str, str->len);
		p += str->len;
		g_string_free (str, TRUE);
	}
	*p = '\0';
	g_ptr_array_free (data, TRUE);
	return line;

 lose:
	for (i = 0; i < data->len; i++)
		g_string_free (data->pdata[i], TRUE);
	g_ptr_array_free (data, TRUE);
	return NULL;
}