コード例 #1
0
ファイル: mu-msg-part.c プロジェクト: otfrom/mu
gboolean
write_part_to_fd (GMimePart *part, int fd, GError **err)
{
	GMimeStream *stream;
	GMimeDataWrapper *wrapper;
	gboolean rv;

	stream = g_mime_stream_fs_new (fd);
	if (!GMIME_IS_STREAM(stream)) {
		g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME,
			     "failed to create stream");
		return FALSE;
	}
	g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), FALSE);

	wrapper = g_mime_part_get_content_object (part);
	if (!GMIME_IS_DATA_WRAPPER(wrapper)) {
		g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME,
			     "failed to create wrapper");
		g_object_unref (stream);
		return FALSE;
	}
	g_object_ref (part); /* FIXME: otherwise, the unrefs below
			      * give errors...*/

	if (g_mime_data_wrapper_write_to_stream (wrapper, stream) == -1) {
		rv = FALSE;
		g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME,
			     "failed to write to stream");
	} else
		rv = TRUE;

	g_object_unref (wrapper);
	g_object_unref (stream);

	return rv;
}
コード例 #2
0
ファイル: test-streams.c プロジェクト: CMogilko/gmime
static int
gen_test_data (const char *datadir, char **stream_name)
{
	GMimeStream *istream, *ostream, *stream;
	char input[256], output[256], *name, *p;
	gint64 start, end, len, size;
	int fd, i;
	
	srand (time (NULL));
	
	name = g_stpcpy (input, datadir);
	*name++ = G_DIR_SEPARATOR;
	name = g_stpcpy (name, "input");
	
	p = g_stpcpy (output, datadir);
	*p++ = G_DIR_SEPARATOR;
	p = g_stpcpy (p, "output");
	
	g_mkdir_with_parents (input, 0755);
	g_mkdir_with_parents (output, 0755);
	
	*name++ = G_DIR_SEPARATOR;
	strcpy (name, "streamXXXXXX");
	
	if ((fd = g_mkstemp (input)) == -1)
		return -1;
	
	*stream_name = g_strdup (name);
	
	*p++ = G_DIR_SEPARATOR;
	p = g_stpcpy (p, name);
	*p++ = '_';
	
	istream = g_mime_stream_fs_new (fd);
	size = gen_random_stream (istream);
	
	for (i = 0; i < 64; i++) {
	retry:
		start = (gint64) (size * (rand () / (RAND_MAX + 1.0)));
		len = (gint64) (size * (rand () / (RAND_MAX + 1.0)));
		if (start + len > size) {
			len = size - start;
			end = -1;
		} else {
			end = start + len;
		}
		
		sprintf (p, "%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT, start, end);
		
		if ((fd = open (output, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0666)) == -1)
			goto retry;
		
		ostream = g_mime_stream_fs_new (fd);
		stream = g_mime_stream_substream (istream, start, end);
		g_mime_stream_write_to_stream (stream, ostream);
		g_mime_stream_flush (ostream);
		g_object_unref (ostream);
		g_object_unref (stream);
	}
	
	return 0;
}
コード例 #3
0
ファイル: recmail.c プロジェクト: ac000/recmail
{
	GMimeStream *stream;
	GMimeDataWrapper *content;
	char file[NAME_MAX + 1];
	int fd;
	static int npart = 0;
	FILE *fp;

	fp = fopen("00INDEX", "a");
	snprintf(file, sizeof(file), "part-%03d.obj", npart++);
	fprintf(fp, "%s\t%s\n", file, (char *)g_mime_part_get_filename(
				(GMimePart *)part));
	fclose(fp);

	fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
	stream = g_mime_stream_fs_new(fd);
	content = g_mime_part_get_content_object((GMimePart *)part);
	g_mime_data_wrapper_write_to_stream(content, stream);
	g_mime_stream_flush(stream);
	close(fd);

	g_object_unref(content);
	g_object_unref(stream);
}

/*
 * Process a mail message, passed on by sendmail
 */
static void process_message(void)
{
	GMimeStream *stream;
コード例 #4
0
ファイル: smtp_utils.c プロジェクト: eneq123/rspamd
gboolean
write_smtp_reply (struct smtp_session *session)
{
	gchar logbuf[1024], *new_subject;
	const gchar *old_subject;
	struct smtp_metric_callback_data cd;
	GMimeStream *stream;
	gint old_fd, sublen;

	/* Check metrics */
	cd.session = session;
	cd.action = METRIC_ACTION_NOACTION;
	cd.res = NULL;
	cd.log_buf = logbuf;
	cd.log_offset = rspamd_snprintf (logbuf,
			sizeof (logbuf),
			"id: <%s>, qid: <%s>, ",
			session->task->message_id,
			session->task->queue_id);
	cd.log_size = sizeof (logbuf);
	if (session->task->user) {
		cd.log_offset += rspamd_snprintf (logbuf + cd.log_offset,
				sizeof (logbuf) - cd.log_offset,
				"user: %s, ",
				session->task->user);
	}

	g_hash_table_foreach (session->task->results, smtp_metric_callback, &cd);

	msg_info ("%s", logbuf);

	if (cd.action <= METRIC_ACTION_REJECT) {
		if (!rspamd_dispatcher_write (session->dispatcher,
			session->ctx->reject_message, 0, FALSE, TRUE)) {
			return FALSE;
		}
		if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) -
			1, FALSE, TRUE)) {
			return FALSE;
		}
		destroy_session (session->s);
		return FALSE;
	}
	else if (cd.action <= METRIC_ACTION_ADD_HEADER || cd.action <=
		METRIC_ACTION_REWRITE_SUBJECT) {
		old_fd = session->temp_fd;
		if (!make_smtp_tempfile (session)) {
			session->error = SMTP_ERROR_FILE;
			session->state = SMTP_STATE_CRITICAL_ERROR;
			rspamd_dispatcher_restore (session->dispatcher);
			if (!rspamd_dispatcher_write (session->dispatcher, session->error,
				0, FALSE, TRUE)) {
				goto err;
			}
			destroy_session (session->s);
			return FALSE;
		}

		if (cd.action <= METRIC_ACTION_REWRITE_SUBJECT) {
			/* XXX: add this action */
			old_subject = g_mime_message_get_subject (session->task->message);
			if (old_subject != NULL) {
				sublen = strlen (old_subject) + sizeof (SPAM_SUBJECT);
				new_subject = rspamd_mempool_alloc (session->pool, sublen);
				rspamd_snprintf (new_subject,
					sublen,
					"%s%s",
					SPAM_SUBJECT,
					old_subject);
			}
			else {
				new_subject = SPAM_SUBJECT;
			}
			g_mime_message_set_subject (session->task->message, new_subject);
		}
		else if (cd.action <= METRIC_ACTION_ADD_HEADER) {
#ifndef GMIME24
			g_mime_message_add_header (session->task->message, "X-Spam",
				"true");
#else
			g_mime_object_append_header (GMIME_OBJECT (
					session->task->message), "X-Spam", "true");
#endif
		}
		stream = g_mime_stream_fs_new (session->temp_fd);
		g_mime_stream_fs_set_owner (GMIME_STREAM_FS (stream), FALSE);
		close (old_fd);

		if (g_mime_object_write_to_stream (GMIME_OBJECT (session->task->message),
			stream) == -1) {
			msg_err ("cannot write MIME object to stream: %s",
				strerror (errno));
			session->error = SMTP_ERROR_FILE;
			session->state = SMTP_STATE_CRITICAL_ERROR;
			rspamd_dispatcher_restore (session->dispatcher);
			if (!rspamd_dispatcher_write (session->dispatcher, session->error,
				0, FALSE, TRUE)) {
				goto err;
			}
			destroy_session (session->s);
			return FALSE;
		}
		g_object_unref (stream);
	}
	/* XXX: Add other actions */
	return smtp_send_upstream_message (session);
err:
	session->error = SMTP_ERROR_FILE;
	session->state = SMTP_STATE_CRITICAL_ERROR;
	if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE,
		TRUE)) {
		return FALSE;
	}
	destroy_session (session->s);
	return FALSE;
}
コード例 #5
0
ファイル: dump-parts.c プロジェクト: kryptBlue/lumail
/**
 * Output a list of the parts included in the current message.
 */
void dump_mail( char *filename )
{
    std::string result;

    GMimeMessage *m_message;
    GMimeParser *parser;
    GMimeStream *stream;
    int fd;

    std::cout << "File: " << filename << std::endl;

    if ((fd = open( filename, O_RDONLY, 0)) == -1)
    {
        std::cout << "Opening failed ..." << std::endl;
        return;
    }

    stream = g_mime_stream_fs_new (fd);

    parser = g_mime_parser_new_with_stream (stream);
    g_object_unref (stream);

    m_message = g_mime_parser_construct_message (parser);
    g_object_unref (parser);

    /**
     * Create an iterator
     */
    GMimePartIter *iter =  g_mime_part_iter_new ((GMimeObject *) m_message);
    int count = 1;

    /**
     * Iterate over the message.
     */
    do
    {
        GMimeObject *part  = g_mime_part_iter_get_current (iter);

        if ( ( GMIME_IS_OBJECT( part ) ) &&
             ( GMIME_IS_PART(part) ) )
        {
            /**
             * Get the content-type
             */
            GMimeContentType *content_type = g_mime_object_get_content_type (part);
            const char *filename = g_mime_object_get_content_disposition_parameter(part, "filename");
            gchar *type = g_mime_content_type_to_string ( content_type );
            std::cout << count << " " << type << std::endl;
            if ( filename )
                std::cout << "\t[This is an attachment with file-name " << filename << "]" << std::endl;
        }


        /**
         * Highlight inline parts - which are not attachments.
         */
        GMimeContentDisposition *disp = g_mime_object_get_content_disposition(part);
        if ( disp != NULL )
        {
            const char *str = g_mime_content_disposition_get_disposition (disp);
            std::cout << "\tNOTE: Content-Disposition: " << str << std::endl;

        }

       count += 1;
    }
    while (g_mime_part_iter_next (iter));

    g_mime_part_iter_free (iter);
    g_object_unref(m_message);
}
コード例 #6
0
ファイル: tokenizer.c プロジェクト: larsmagne/wesearch
document* parse_file(const char *file_name) {
  int tallied_length = 0;
  GMimeStream *stream;
  GMimeMessage *msg = 0;
  // struct stat stat_buf;
  const char *author, *subject, *xref, *xref_end;
  time_t date;
  int offset;
  int num_words = 0;
  int file;
  InternetAddress *iaddr;
  InternetAddressList *iaddr_list;
  char *address;

#if DEBUG
  printf("%s\n", file_name);
#endif

  /*
  if ((file = stat(file_name, &stat_buf)) == -1) {
    perror("tokenizer");
    return NULL;
  }
  */

  // |O_STREAMING
  if ((file = open(file_name, O_RDONLY|O_STREAMING)) == -1) {
    perror("tokenizer");
    return NULL;
  }

#ifdef POSIX_FADV_NOREUSE
  no_reuse(file);
#endif

  stream = g_mime_stream_fs_new(file);
  msg = g_mime_parser_construct_message(stream);
  g_mime_stream_unref(stream);

  if (msg != 0) {
    table = g_hash_table_new(g_str_hash, g_str_equal);
    bufp = buffer;
    dword_table[0].word = NULL;
    bzero(saved_body, MAX_SAVED_BODY_LENGTH);
    saved_body_length = 0;
    author = g_mime_message_get_sender(msg);
    subject = g_mime_message_get_subject(msg);
    xref = g_mime_message_get_header(msg, "Xref");
    g_mime_message_get_date(msg, &date, &offset);
    if (author != NULL && subject != NULL && xref != NULL) {
      tallied_length = tally_string(author, tallied_length);
      strncpy(doc.author, author, MAX_HEADER_LENGTH-1);

      /* Get the address from the From header. */
      if ((iaddr_list = internet_address_parse_string(author)) != NULL) {
	iaddr = iaddr_list->address;
	internet_address_set_name(iaddr, NULL);
	address = internet_address_to_string(iaddr, FALSE);
	strncpy(doc.address, address, MAX_HEADER_LENGTH-1);
	downcase_string(doc.address);
	free(address);
	internet_address_list_destroy(iaddr_list);
      } else {
	*doc.address = 0;
      }

      tallied_length = tally_string(subject, tallied_length);
      strncpy(doc.subject, subject, MAX_HEADER_LENGTH-1);

      doc.time = date;

      if ((xref = strchr(xref, ' ')) != NULL) {
	xref++;
	xref_end = strchr(xref, ':');
	*doc.group = 0;
	strncat(doc.group, xref, min(xref_end-xref, MAX_HEADER_LENGTH-1));
	xref_end++;
	sscanf(xref_end, "%d", &doc.article);
      }

      g_mime_message_foreach_part(msg, partFound, (gpointer) &tallied_length);

      strncpy(doc.body, saved_body, MAX_SAVED_BODY_LENGTH);

      g_hash_table_foreach(table, add_word_to_table, (gpointer) &num_words);
      dword_table[num_words].word = NULL;
      g_hash_table_destroy(table);
      g_mime_object_unref(GMIME_OBJECT(msg));
    } else {
      close(file);
      return NULL;
    }
  }
  close(file);
  doc.words = dword_table;
  doc.num_words = num_words;

  return &doc;
}
コード例 #7
0
ファイル: test-cat.c プロジェクト: CMogilko/gmime
int main (int argc, char **argv)
{
	const char *datadir = "data/cat";
	struct _StreamPart *list, *tail, *n;
	gboolean failed = FALSE;
	gint64 wholelen, left;
	GMimeStream *whole;
	guint32 part = 0;
	gint64 start = 0;
	char *filename;
	struct stat st;
	gint64 len;
	int fd, i;
	
	srand (time (NULL));
	
	g_mime_init (0);
	
	testsuite_init (argc, argv);
	
	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-') {
			datadir = argv[i];
			break;
		}
	}
	
	if (i < argc) {
		if (stat (datadir, &st) == -1) {
			if (errno == ENOENT) {
				g_mkdir_with_parents (datadir, 0755);
				if (stat (datadir, &st) == -1)
					return EXIT_FAILURE;
			} else
				return EXIT_FAILURE;
		}
		
		if (S_ISREG (st.st_mode)) {
			/* test a particular input file */
			if ((fd = open (argv[i], O_RDONLY, 0)) == -1)
				return EXIT_FAILURE;
			
			filename = g_strdup (argv[i]);
			whole = g_mime_stream_fs_new (fd);
		} else if (S_ISDIR (st.st_mode)) {
			/* use path as test suite data dir */
			whole = random_whole_stream (argv[i], &filename);
		} else {
			return EXIT_FAILURE;
		}
	} else {
		whole = random_whole_stream (datadir, &filename);
	}
	
	if ((wholelen = g_mime_stream_length (whole)) == -1) {
		fprintf (stderr, "Error: length of test stream unknown\n");
		g_object_unref (whole);
		return EXIT_FAILURE;
	} else if (wholelen == 64) {
		fprintf (stderr, "Error: length of test stream is unsuitable for testing\n");
		g_object_unref (whole);
		return EXIT_FAILURE;
	}
	
	list = NULL;
	tail = (struct _StreamPart *) &list;
	
	left = wholelen;
	while (left > 0) {
		len = 1 + (gint64) (left * (rand () / (RAND_MAX + 1.0)));
		n = g_new (struct _StreamPart, 1);
		sprintf (n->filename, "%s.%u", filename, part++);
		n->pstart = (gint64) 0; /* FIXME: we could make this a random offset */
		n->pend = n->pstart + len;
		n->wend = start + len;
		n->wstart = start;
		tail->next = n;
		tail = n;
		
		start += len;
		left -= len;
	}
	
	tail->next = NULL;
	
	testsuite_start ("GMimeStreamCat");
	
	for (i = 0; i < G_N_ELEMENTS (checks) && !failed; i++) {
		testsuite_check (checks[i].what);
		try {
			checks[i].check (whole, list, checks[i].bounded);
			testsuite_check_passed ();
		} catch (ex) {
			testsuite_check_failed ("%s failed: %s", checks[i].what,
						ex->message);
			failed = TRUE;
		} finally;
	}
	
	testsuite_end ();
	
	while (list != NULL) {
		n = list->next;
		if (!failed)
			unlink (list->filename);
		g_free (list);
		list = n;
	}
	
	g_object_unref (whole);
	
	if (!failed)
		unlink (filename);
	
	g_free (filename);
	
	g_mime_shutdown ();
	
	return testsuite_exit ();
}
コード例 #8
0
ファイル: test-pgp.c プロジェクト: GNOME/gmime
static void
test_export (GMimeCryptoContext *ctx, const char *path)
{
	GMimeStream *istream, *ostream;
	register const char *inptr;
	const char *inbuf, *outbuf;
	size_t inlen, outlen;
	Exception *ex = NULL;
	const char *keys[2];
	GError *err = NULL;
	int fd;
	
	if ((fd = open (path, O_RDONLY, 0)) == -1)
		throw (exception_new ("open() failed: %s", g_strerror (errno)));
	
	ostream = g_mime_stream_fs_new (fd);
	istream = g_mime_stream_mem_new ();
	g_mime_stream_write_to_stream (ostream, istream);
	g_mime_stream_reset (istream);
	g_object_unref (ostream);
	
	keys[0] = "*****@*****.**";
	keys[1] = NULL;
	
	ostream = g_mime_stream_mem_new ();
	
	g_mime_crypto_context_export_keys (ctx, keys, ostream, &err);
	
	if (err != NULL) {
		ex = exception_new ("%s", err->message);
		g_object_unref (istream);
		g_object_unref (ostream);
		g_error_free (err);
		throw (ex);
	}
	
	inbuf = (const char *) GMIME_STREAM_MEM (istream)->buffer->data;
	inlen = GMIME_STREAM_MEM (istream)->buffer->len;
	if ((inptr = strstr (inbuf, "\n\n"))) {
		/* skip past the headers which may have different version numbers */
		inptr += 2;
		inlen -= (inptr - inbuf);
		inbuf = inptr;
	}
	
	outbuf = (const char *) GMIME_STREAM_MEM (ostream)->buffer->data;
	outlen = GMIME_STREAM_MEM (ostream)->buffer->len;
	if ((inptr = strstr (outbuf, "\n\n"))) {
		/* skip past the headers which may have different version numbers */
		inptr += 2;
		outlen -= (inptr - outbuf);
		outbuf = inptr;
	}
	
	if (outlen != inlen || memcmp (outbuf, inbuf, inlen) != 0)
		ex = exception_new ("exported key does not match original key");
	
	g_object_unref (istream);
	g_object_unref (ostream);
	
	if (ex != NULL)
		throw (ex);
}
コード例 #9
0
ファイル: uuencode.c プロジェクト: CMogilko/gmime
static int
uuencode (const char *progname, int argc, char **argv)
{
	GMimeStream *istream, *ostream, *fstream;
	GMimeContentEncoding encoding;
	const char *filename, *name;
	GMimeFilter *filter;
	gboolean base64;
	struct stat st;
	int fd, opt;
	
	base64 = FALSE;
	encoding = GMIME_CONTENT_ENCODING_UUENCODE;
	while ((opt = getopt_long (argc, argv, "hvm", longopts, NULL)) != -1) {
		switch (opt) {
		case 'h':
			usage (progname);
			return 0;
		case 'v':
			version (progname);
			return 0;
		case 'm':
			base64 = TRUE;
			encoding = GMIME_CONTENT_ENCODING_BASE64;
			break;
		default:
			printf ("Try `%s --help' for more information.\n", progname);
			return -1;
		}
	}
	
	if (optind >= argc) {
		printf ("Try `%s --help' for more information.\n", progname);
		return -1;
	}
	
	if (optind + 1 < argc)
		filename = argv[optind++];
	else
		filename = NULL;
	
	name = argv[optind];
	
	/* open our input file... */
	if ((fd = filename ? open (filename, O_RDONLY, 0) : dup (0)) == -1) {
		fprintf (stderr, "%s: %s: %s\n", progname,
			 filename ? filename : "stdin",
			 g_strerror (errno));
		return -1;
	}
	
	/* stat() our input file for file mode permissions */
	if (fstat (fd, &st) == -1) {
		fprintf (stderr, "%s: %s: %s\n", progname,
			 filename ? filename : "stdin",
			 g_strerror (errno));
		close (fd);
		return -1;
	}
	
	printf ("begin%s %.3o %s\n", base64 ? "-base64" : "", st.st_mode & 0777, name);
	fflush (stdout);
	
	istream = g_mime_stream_fs_new (fd);
	
	/* open our output stream */
	ostream = g_mime_stream_fs_new (1);
	g_mime_stream_fs_set_owner ((GMimeStreamFs *) ostream, FALSE);
	
	fstream = g_mime_stream_filter_new (ostream);
	
	/* attach an encode filter */
	filter = g_mime_filter_basic_new (encoding, TRUE);
	g_mime_stream_filter_add ((GMimeStreamFilter *) fstream, filter);
	g_object_unref (filter);
	
	if (g_mime_stream_write_to_stream (istream, fstream) == -1) {
		fprintf (stderr, "%s: %s\n", progname, g_strerror (errno));
		g_object_unref (fstream);
		g_object_unref (istream);
		g_object_unref (ostream);
		return -1;
	}
	
	g_mime_stream_flush (fstream);
	g_object_unref (fstream);
	g_object_unref (istream);
	
	if (g_mime_stream_write_string (ostream, base64 ? "====\n" : "end\n") == -1) {
		fprintf (stderr, "%s: %s\n", progname, g_strerror (errno));
		g_object_unref (ostream);
		return -1;
	}
	
	g_object_unref (ostream);
	
	return 0;
}
コード例 #10
0
ファイル: test-mbox.c プロジェクト: GNOME/gmime
int main (int argc, char **argv)
{
	const char *datadir = "data/mbox";
	char input[256], output[256], *tmp, *p, *q;
	GMimeStream *istream, *ostream, *mstream, *pstream;
	GMimeParser *parser;
	const char *dent;
	const char *path;
	struct stat st;
	GDir *dir;
	int i;
#ifdef ENABLE_MBOX_MATCH
	int fd;

	if (mkdir ("./tmp", 0755) == -1 && errno != EEXIST)
		return 0;
#endif
	
	g_mime_init ();
	
	testsuite_init (argc, argv);
	
	path = datadir;
	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-') {
			path = argv[i];
			break;
		}
	}
	
	testsuite_start ("Mbox parser");
	
	if (stat (path, &st) == -1)
		goto exit;
	
	if (S_ISDIR (st.st_mode)) {
		/* automated testsuite */
		p = g_stpcpy (input, path);
		*p++ = G_DIR_SEPARATOR;
		p = g_stpcpy (p, "input");
		
		if (!(dir = g_dir_open (input, 0, NULL)))
			goto exit;
		
		*p++ = G_DIR_SEPARATOR;
		*p = '\0';
		
		q = g_stpcpy (output, path);
		*q++ = G_DIR_SEPARATOR;
		q = g_stpcpy (q, "output");
		*q++ = G_DIR_SEPARATOR;
		*q = '\0';
		
		while ((dent = g_dir_read_name (dir))) {
			if (!g_str_has_suffix (dent, ".mbox"))
				continue;
			
			strcpy (p, dent);
			strcpy (q, dent);
			
			tmp = NULL;
			parser = NULL;
			istream = NULL;
			ostream = NULL;
			mstream = NULL;
			pstream = NULL;
			
			testsuite_check ("%s", dent);
			try {
				if (!(istream = g_mime_stream_fs_open (input, O_RDONLY, 0, NULL))) {
					throw (exception_new ("could not open `%s': %s",
							      input, g_strerror (errno)));
				}
				
				if (!(ostream = g_mime_stream_fs_open (output, O_RDONLY, 0, NULL))) {
					throw (exception_new ("could not open `%s': %s",
							      output, g_strerror (errno)));
				}
				
#ifdef ENABLE_MBOX_MATCH
				tmp = g_strdup_printf ("./tmp/%s", dent);
				if ((fd = open (tmp, O_CREAT | O_RDWR | O_TRUNC, 0644)) == -1) {
					throw (exception_new ("could not open `%s': %s",
							      tmp, g_strerror (errno)));
				}
				
				mstream = g_mime_stream_fs_new (fd);
#endif
				
				parser = g_mime_parser_new_with_stream (istream);
				g_mime_parser_set_persist_stream (parser, TRUE);
				g_mime_parser_set_format (parser, GMIME_FORMAT_MBOX);
				
				if (!g_mime_parser_get_persist_stream (parser))
					throw (exception_new ("persist stream check failed"));
				
				if (g_mime_parser_get_format (parser) != GMIME_FORMAT_MBOX)
					throw (exception_new ("format check failed"));
				
				if (strstr (dent, "content-length") != NULL) {
					g_mime_parser_set_respect_content_length (parser, TRUE);
					
					if (!g_mime_parser_get_respect_content_length (parser))
						throw (exception_new ("respect content-length check failed"));
				} else {
					g_mime_parser_set_respect_content_length (parser, FALSE);
					
					if (g_mime_parser_get_respect_content_length (parser))
						throw (exception_new ("respect content-length check failed"));
				}
				
				g_mime_parser_set_header_regex (parser, "^X-Evolution", xevcb, NULL);
				
				pstream = g_mime_stream_mem_new ();
				test_parser (parser, mstream, pstream);
				
#ifdef ENABLE_MBOX_MATCH
				g_mime_stream_flush (mstream);
				g_mime_stream_reset (istream);
				g_mime_stream_reset (mstream);
				if (!streams_match (istream, mstream))
					throw (exception_new ("mboxes do not match for `%s'", dent));
#endif
				
				g_mime_stream_reset (ostream);
				g_mime_stream_reset (pstream);
				if (!streams_match (ostream, pstream))
					throw (exception_new ("summaries do not match for `%s'", dent));
				
				testsuite_check_passed ();
				
#ifdef ENABLE_MBOX_MATCH
				unlink (tmp);
#endif
			} catch (ex) {
				if (parser != NULL)
					testsuite_check_failed ("%s: %s", dent, ex->message);
				else
					testsuite_check_warn ("%s: %s", dent, ex->message);
			} finally;
			
			if (mstream != NULL)
				g_object_unref (mstream);
			
			if (pstream != NULL)
				g_object_unref (pstream);
			
			if (istream != NULL)
				g_object_unref (istream);
			
			if (ostream != NULL)
				g_object_unref (ostream);
			
			if (parser != NULL)
				g_object_unref (parser);
			
			g_free (tmp);
		}
		
		g_dir_close (dir);
	} else if (S_ISREG (st.st_mode)) {
		/* manually run test on a single file */
		if (!(istream = g_mime_stream_fs_open (path, O_RDONLY, 0, NULL)))
			goto exit;
		
		parser = g_mime_parser_new_with_stream (istream);
		g_mime_parser_set_format (parser, GMIME_FORMAT_MBOX);
		
#ifdef ENABLE_MBOX_MATCH
		tmp = g_strdup ("./tmp/mbox-test.XXXXXX");
		if ((fd = g_mkstemp (tmp)) == -1) {
			g_object_unref (istream);
			g_object_unref (parser);
			g_free (tmp);
			goto exit;
		}
		
		mstream = g_mime_stream_fs_new (fd);
#else
		mstream = NULL;
#endif
		
		ostream = g_mime_stream_file_new (stdout);
		g_mime_stream_file_set_owner ((GMimeStreamFile *) ostream, FALSE);
		
		testsuite_check ("user-input mbox: `%s'", path);
		try {
			test_parser (parser, mstream, ostream);
			
#ifdef ENABLE_MBOX_MATCH
			g_mime_stream_reset (istream);
			g_mime_stream_reset (mstream);
			if (!streams_match (istream, mstream))
				throw (exception_new ("`%s' does not match `%s'", tmp, path));
			
			unlink (tmp);
#endif
			
			testsuite_check_passed ();
		} catch (ex) {
			testsuite_check_failed ("user-input mbox `%s': %s", path, ex->message);
		} finally;
		
		g_object_unref (istream);
		g_object_unref (ostream);
		g_object_unref (parser);
		
#ifdef ENABLE_MBOX_MATCH
		g_object_unref (mstream);
		g_free (tmp);
#endif
	} else {
		goto exit;
	}
	
 exit:
	
#ifdef ENABLE_MBOX_MATCH
	//if ((dir = g_dir_open ("./tmp", 0, NULL))) {
	//	p = g_stpcpy (input, "./tmp");
	//	*p++ = G_DIR_SEPARATOR;
	//	
	//	while ((dent = g_dir_read_name (dir))) {
	//		strcpy (p, dent);
	//		unlink (input);
	//	}
	//	
	//	g_dir_close (dir);
	//}
	
	//rmdir ("./tmp");
#endif
	
	testsuite_end ();
	
	g_mime_shutdown ();
	
	return testsuite_exit ();
}