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; }
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; }
{ 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;
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; }
/** * 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); }
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; }
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 (); }
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); }
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; }
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 (); }