static void show_reply_headers (GMimeMessage *message) { GMimeStream *stream_stdout = NULL; stream_stdout = g_mime_stream_file_new (stdout); if (stream_stdout) { g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); /* Output RFC 2822 formatted (and RFC 2047 encoded) headers. */ g_mime_object_write_to_stream (GMIME_OBJECT(message), stream_stdout); g_object_unref(stream_stdout); } }
static void mime_foreach_callback (GMimeObject * parent, GMimeObject * part, gpointer user_data) { GMimeContentType *type; if (GMIME_IS_MESSAGE_PART (part)) { /* message/rfc822 or message/news */ GMimeMessage *message; /* g_mime_message_foreach_part() won't descend into child message parts, so if we want to count any subparts of this child message, we'll have to call g_mime_message_foreach_part() again here. */ rspamd_printf ("got message part %p: parent: %p\n", part, parent); message = g_mime_message_part_get_message ((GMimeMessagePart *) part); g_mime_message_foreach (message, mime_foreach_callback, part); } else if (GMIME_IS_MULTIPART (part)) { type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT ( part)); rspamd_printf ("got multipart part %p, boundary: %s: parent: %p, type: %s/%s\n", part, g_mime_multipart_get_boundary (GMIME_MULTIPART(part)), parent, g_mime_content_type_get_media_type (type), g_mime_content_type_get_media_subtype (type)); } else { type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT ( part)); rspamd_printf ("got normal part %p, parent: %p, type: %s/%s\n", part, parent, g_mime_content_type_get_media_type (type), g_mime_content_type_get_media_subtype (type)); } }
static void fold_to(GSList** stack, guint level) { guint min_level = level ? level : 1; while ( g_slist_length(*stack) > min_level ) { /* pop and add to top */ GSList* top = *stack; GMimeObject* part = GMIME_OBJECT(top->data); if ( GMIME_IS_MESSAGE(part) ) { GMimeMessagePart* mgp = g_mime_message_part_new_with_message( "rfc822", GMIME_MESSAGE(part)); part = GMIME_OBJECT(mgp); } *stack = g_slist_remove_link(*stack, top); add_part(stack, part); g_slist_free(top); } }
static void show_message_part (mime_node_t *node, show_message_state_t *state, const notmuch_show_format_t *format, int first) { /* Formatters expect the envelope for embedded message parts */ GMimeObject *part = node->envelope_part ? GMIME_OBJECT (node->envelope_part) : node->part; int i; if (!first) fputs (format->part_sep, stdout); /* Format this part */ if (format->part_start) format->part_start (part, &(state->part_count)); if (node->decrypt_attempted && format->part_encstatus) format->part_encstatus (node->decrypt_success); if (node->verify_attempted && format->part_sigstatus) #ifdef GMIME_ATLEAST_26 format->part_sigstatus (node->sig_list); #else format->part_sigstatus (node->sig_validity); #endif format->part_content (part); if (node->envelope_part) { fputs (format->header_start, stdout); if (format->header_message_part) format->header_message_part (GMIME_MESSAGE (node->part)); fputs (format->header_end, stdout); fputs (format->body_start, stdout); } /* Recurse over the children */ state->part_count += 1; for (i = 0; i < node->nchildren; i++) show_message_part (mime_node_child (node, i), state, format, i == 0); /* Finish this part */ if (node->envelope_part) fputs (format->body_end, stdout); if (format->part_end) format->part_end (part); }
/* Write a MIME text part out to the given stream. * * If (flags & NOTMUCH_SHOW_TEXT_PART_REPLY), this prepends "> " to * each output line. * * Both line-ending conversion (CRLF->LF) and charset conversion ( -> * UTF-8) will be performed, so it is inappropriate to call this * function with a non-text part. Doing so will trigger an internal * error. */ void show_text_part_content (GMimeObject *part, GMimeStream *stream_out, notmuch_show_text_part_flags flags) { GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part)); GMimeStream *stream_filter = NULL; GMimeDataWrapper *wrapper; const char *charset; if (! g_mime_content_type_is_type (content_type, "text", "*")) INTERNAL_ERROR ("Illegal request to format non-text part (%s) as text.", g_mime_content_type_to_string (content_type)); if (stream_out == NULL) return; stream_filter = g_mime_stream_filter_new (stream_out); g_mime_stream_filter_add(GMIME_STREAM_FILTER (stream_filter), g_mime_filter_crlf_new (FALSE, FALSE)); charset = g_mime_object_get_content_type_parameter (part, "charset"); if (charset) { GMimeFilter *charset_filter; charset_filter = g_mime_filter_charset_new (charset, "UTF-8"); /* This result can be NULL for things like "unknown-8bit". * Don't set a NULL filter as that makes GMime print * annoying assertion-failure messages on stderr. */ if (charset_filter) { g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter), charset_filter); g_object_unref (charset_filter); } } if (flags & NOTMUCH_SHOW_TEXT_PART_REPLY) { GMimeFilter *reply_filter; reply_filter = g_mime_filter_reply_new (TRUE); if (reply_filter) { g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter), reply_filter); g_object_unref (reply_filter); } } wrapper = g_mime_part_get_content_object (GMIME_PART (part)); if (wrapper && stream_filter) g_mime_data_wrapper_write_to_stream (wrapper, stream_filter); if (stream_filter) g_object_unref(stream_filter); }
/** * g_mime_part_new: * * Creates a new MIME Part object with a default content-type of * text/plain. * * Returns: an empty MIME Part object with a default content-type of * text/plain. **/ GMimePart * g_mime_part_new (void) { GMimeContentType *content_type; GMimePart *mime_part; mime_part = g_object_newv (GMIME_TYPE_PART, 0, NULL); content_type = g_mime_content_type_new ("text", "plain"); g_mime_object_set_content_type (GMIME_OBJECT (mime_part), content_type); g_object_unref (content_type); return mime_part; }
/** * g_mime_multipart_new_with_subtype: * @subtype: content-type subtype * * Creates a new MIME multipart object with a content-type of * multipart/@subtype. * * Returns: an empty MIME multipart object with a content-type of * multipart/@subtype. **/ GMimeMultipart * g_mime_multipart_new_with_subtype (const char *subtype) { GMimeContentType *content_type; GMimeMultipart *multipart; multipart = g_object_newv (GMIME_TYPE_MULTIPART, 0, NULL); content_type = g_mime_content_type_new ("multipart", subtype ? subtype : "mixed"); g_mime_object_set_content_type (GMIME_OBJECT (multipart), content_type); g_object_unref (content_type); return multipart; }
/** * g_mime_part_new_with_type: * @type: content-type string * @subtype: content-subtype string * * Creates a new MIME Part with a sepcified type. * * Returns: an empty MIME Part object with the specified content-type. **/ GMimePart * g_mime_part_new_with_type (const char *type, const char *subtype) { GMimeContentType *content_type; GMimePart *mime_part; mime_part = g_object_newv (GMIME_TYPE_PART, 0, NULL); content_type = g_mime_content_type_new (type, subtype); g_mime_object_set_content_type (GMIME_OBJECT (mime_part), content_type); g_object_unref (content_type); return mime_part; }
static void reply_part_content (GMimeObject *part) { GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part)); GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part); if (g_mime_content_type_is_type (content_type, "text", "*") && !g_mime_content_type_is_type (content_type, "text", "html")) { GMimeStream *stream_stdout = NULL, *stream_filter = NULL; GMimeDataWrapper *wrapper; const char *charset; charset = g_mime_object_get_content_type_parameter (part, "charset"); stream_stdout = g_mime_stream_file_new (stdout); if (stream_stdout) { g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); stream_filter = g_mime_stream_filter_new(stream_stdout); if (charset) { g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter), g_mime_filter_charset_new(charset, "UTF-8")); } } g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter), g_mime_filter_reply_new(TRUE)); wrapper = g_mime_part_get_content_object (GMIME_PART (part)); if (wrapper && stream_filter) g_mime_data_wrapper_write_to_stream (wrapper, stream_filter); if (stream_filter) g_object_unref(stream_filter); if (stream_stdout) g_object_unref(stream_stdout); } else { if (disposition && strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0) { const char *filename = g_mime_part_get_filename (GMIME_PART (part)); printf ("Attachment: %s (%s)\n", filename, g_mime_content_type_to_string (content_type)); } else { printf ("Non-text part: %s\n", g_mime_content_type_to_string (content_type)); } } }
static void add_part(GSList** stack, GMimeObject* p) { GMimeObject* top_part = GMIME_OBJECT((*stack)->data); if ( GMIME_IS_MESSAGE(top_part) ) { GMimeMessage* m = GMIME_MESSAGE(top_part); GMimeObject* msg_part = g_mime_message_get_mime_part(m); GMimeObject* add_part = p; if ( msg_part ) { add_part = add_part_to_existing(msg_part, p); } g_mime_message_set_mime_part(m, add_part); } else { (*stack)->data = add_part_to_existing(top_part, p); } }
static GMimeObject* add_part_to_existing(GMimeObject* mp, GMimeObject* p) { GMimeObject* rv = mp; /* there was a previous part, switch to multipart or just add if we already switched */ /* g_debug("mp=%p (%s), p=%p (%s)", mp, G_OBJECT_TYPE_NAME(mp), p, G_OBJECT_TYPE_NAME(p)); */ if ( GMIME_IS_MULTIPART(mp) ) { g_mime_multipart_add(GMIME_MULTIPART(mp), p); } else { GMimeMultipart* mlp = g_mime_multipart_new(); g_mime_multipart_add(mlp, mp); g_mime_multipart_add(mlp, p); rv = GMIME_OBJECT(mlp); } return rv; }
static void show_reply_headers (GMimeMessage *message) { GMimeStream *stream_stdout = NULL, *stream_filter = NULL; stream_stdout = g_mime_stream_file_new (stdout); if (stream_stdout) { g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); stream_filter = g_mime_stream_filter_new(stream_stdout); if (stream_filter) { g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter), g_mime_filter_headers_new()); g_mime_object_write_to_stream(GMIME_OBJECT(message), stream_filter); g_object_unref(stream_filter); } g_object_unref(stream_stdout); } }
static void format_part_content_json (GMimeObject *part) { GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part)); GMimeStream *stream_memory = g_mime_stream_mem_new (); const char *cid = g_mime_object_get_content_id (part); void *ctx = talloc_new (NULL); GByteArray *part_content; printf (", \"content-type\": %s", json_quote_str (ctx, g_mime_content_type_to_string (content_type))); if (cid != NULL) printf(", \"content-id\": %s", json_quote_str (ctx, cid)); if (GMIME_IS_PART (part)) { const char *filename = g_mime_part_get_filename (GMIME_PART (part)); if (filename) printf (", \"filename\": %s", json_quote_str (ctx, filename)); } if (g_mime_content_type_is_type (content_type, "text", "*") && !g_mime_content_type_is_type (content_type, "text", "html")) { show_text_part_content (part, stream_memory); part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory)); printf (", \"content\": %s", json_quote_chararray (ctx, (char *) part_content->data, part_content->len)); } else if (g_mime_content_type_is_type (content_type, "multipart", "*")) { printf (", \"content\": ["); } else if (g_mime_content_type_is_type (content_type, "message", "rfc822")) { printf (", \"content\": [{"); } talloc_free (ctx); if (stream_memory) g_object_unref (stream_memory); }
parsed_article *parse_file(const char *file_name) { static parsed_article pa; GMimeStream *stream; GMimeMessage *msg = NULL; int offset; int file; printf("%s\n", file_name); if ((file = open(file_name, O_RDONLY|O_STREAMING)) == -1) { fprintf(stderr, "Can't open %s\n", file_name); return NULL; } stream = g_mime_stream_fs_new(file); msg = g_mime_parser_construct_message(stream); g_mime_stream_unref(stream); if (msg != 0) { hstrcpy(pa.from, g_mime_message_get_header(msg, "From")); hstrcpy(pa.subject, g_mime_message_get_subject(msg)); hstrcpy(pa.message_id, g_mime_message_get_message_id(msg)); hstrcpy(pa.references, g_mime_message_get_header(msg, "references")); hstrcpy(pa.xref, g_mime_message_get_header(msg, "xref")); hstrcpy(pa.original_message_id, g_mime_message_get_header(msg, "original-message-id")); g_mime_message_get_date(msg, &pa.date, &offset); if (pa.xref != NULL && strstr(pa.xref, "gmane.spam.detected") != NULL) pa.spamp = 1; else pa.spamp = 0; g_mime_message_foreach_part(msg, count_part, (gpointer) &pa); g_mime_object_unref(GMIME_OBJECT(msg)); } close(file); return &pa; }
static void format_part_content_text (GMimeObject *part) { const char *cid = g_mime_object_get_content_id (part); GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part)); if (GMIME_IS_PART (part)) { const char *filename = g_mime_part_get_filename (GMIME_PART (part)); if (filename) printf (", Filename: %s", filename); } if (cid) printf (", Content-id: %s", cid); printf (", Content-type: %s\n", g_mime_content_type_to_string (content_type)); if (g_mime_content_type_is_type (content_type, "text", "*") && !g_mime_content_type_is_type (content_type, "text", "html")) { GMimeStream *stream_stdout = g_mime_stream_file_new (stdout); g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); show_text_part_content (part, stream_stdout); g_object_unref(stream_stdout); } else if (g_mime_content_type_is_type (content_type, "multipart", "*") || g_mime_content_type_is_type (content_type, "message", "rfc822")) { /* Do nothing for multipart since its content will be printed * when recursing. */ } else { printf ("Non-text part: %s\n", g_mime_content_type_to_string (content_type)); } }
static void multipart_set_boundary (GMimeMultipart *multipart, const char *boundary) { char bbuf[35]; if (!boundary) { /* Generate a fairly random boundary string. */ unsigned char digest[16], *p; guint32 save = 0; int state = 0; read_random_pool (digest, 16); strcpy (bbuf, "=-"); p = (unsigned char *) bbuf + 2; p += g_mime_encoding_base64_encode_step (digest, 16, p, &state, &save); *p = '\0'; boundary = bbuf; } g_mime_object_set_content_type_parameter (GMIME_OBJECT (multipart), "boundary", boundary); }
static void write_part(GMimeObject *part) { GList *l; const GMimeContentType *ct; ct = g_mime_object_get_content_type(GMIME_OBJECT(part)); if (GMIME_IS_MULTIPART(part)) { if (g_mime_content_type_is_type(ct, "multipart", "alternative")) { choose_alternative(part); level += g_list_length(GMIME_MULTIPART(part)->subparts); } else { l = GMIME_MULTIPART(part)->subparts; while (l != NULL) { write_part(l->data); l = l->next; level++; } } } else if (GMIME_IS_MESSAGE_PART(part)) { } else if (GMIME_IS_PART(part)) { display_part(part, ct); } }
static GMimeMessage * create_reply_message(void *ctx, notmuch_config_t *config, notmuch_message_t *message, notmuch_bool_t reply_all) { const char *subject, *from_addr = NULL; const char *in_reply_to, *orig_references, *references; /* The 1 means we want headers in a "pretty" order. */ GMimeMessage *reply = g_mime_message_new (1); if (reply == NULL) { fprintf (stderr, "Out of memory\n"); return NULL; } subject = notmuch_message_get_header (message, "subject"); if (subject) { if (strncasecmp (subject, "Re:", 3)) subject = talloc_asprintf (ctx, "Re: %s", subject); g_mime_message_set_subject (reply, subject); } from_addr = add_recipients_from_message (reply, config, message, reply_all); /* * Sadly, there is no standard way to find out to which email * address a mail was delivered - what is in the headers depends * on the MTAs used along the way. * * If none of the user's email addresses are in the To: or Cc: * headers, we try a number of heuristics which hopefully will * answer this question. * * First, check for Envelope-To:, X-Original-To:, and * Delivered-To: headers. */ if (from_addr == NULL) from_addr = get_from_in_to_headers (config, message); /* * Check for a (for <*****@*****.**>) clause in Received: headers, * and the domain part of known email addresses in the 'by' part * of Received: headers */ if (from_addr == NULL) from_addr = guess_from_in_received_headers (config, message); /* Default to user's primary address. */ if (from_addr == NULL) from_addr = notmuch_config_get_user_primary_email (config); from_addr = talloc_asprintf (ctx, "%s <%s>", notmuch_config_get_user_name (config), from_addr); g_mime_object_set_header (GMIME_OBJECT (reply), "From", from_addr); in_reply_to = talloc_asprintf (ctx, "<%s>", notmuch_message_get_message_id (message)); g_mime_object_set_header (GMIME_OBJECT (reply), "In-Reply-To", in_reply_to); orig_references = notmuch_message_get_header (message, "references"); if (!orig_references) /* Treat errors like missing References headers. */ orig_references = ""; references = talloc_asprintf (ctx, "%s%s%s", *orig_references ? orig_references : "", *orig_references ? " " : "", in_reply_to); g_mime_object_set_header (GMIME_OBJECT (reply), "References", references); return reply; }
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; }
/* This format is currently tuned for a git send-email --notmuch hook */ static int notmuch_reply_format_headers_only(void *ctx, notmuch_config_t *config, notmuch_query_t *query, unused (notmuch_show_params_t *params), notmuch_bool_t reply_all, unused (sprinter_t *sp)) { GMimeMessage *reply; notmuch_messages_t *messages; notmuch_message_t *message; const char *in_reply_to, *orig_references, *references; char *reply_headers; notmuch_status_t status; status = notmuch_query_search_messages_st (query, &messages); if (print_status_query ("notmuch reply", query, status)) return 1; for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); /* The 0 means we do not want headers in a "pretty" order. */ reply = g_mime_message_new (0); if (reply == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } in_reply_to = talloc_asprintf (ctx, "<%s>", notmuch_message_get_message_id (message)); g_mime_object_set_header (GMIME_OBJECT (reply), "In-Reply-To", in_reply_to); orig_references = notmuch_message_get_header (message, "references"); /* We print In-Reply-To followed by References because git format-patch treats them * specially. Git does not interpret the other headers specially */ references = talloc_asprintf (ctx, "%s%s%s", orig_references ? orig_references : "", orig_references ? " " : "", in_reply_to); g_mime_object_set_header (GMIME_OBJECT (reply), "References", references); (void)add_recipients_from_message (reply, config, message, reply_all); reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply)); printf ("%s", reply_headers); free (reply_headers); g_object_unref (G_OBJECT (reply)); reply = NULL; notmuch_message_destroy (message); } return 0; }
gboolean g_mime_gpgme_mpe_encrypt(GMimeMultipartEncrypted * mpe, GMimeObject * content, GPtrArray * recipients, gboolean trust_all, GtkWindow * parent, GError ** err) { GMimeStream *filtered_stream; GMimeStream *ciphertext; GMimeStream *stream; GMimePart *version_part; GMimePart *encrypted_part; GMimeDataWrapper *wrapper; GMimeFilter *crlf_filter; g_return_val_if_fail(GMIME_IS_MULTIPART_ENCRYPTED(mpe), FALSE); g_return_val_if_fail(GMIME_IS_OBJECT(content), FALSE); /* get the cleartext */ stream = g_mime_stream_mem_new(); filtered_stream = g_mime_stream_filter_new(stream); crlf_filter = g_mime_filter_crlf_new(TRUE, FALSE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream), crlf_filter); g_object_unref(crlf_filter); g_mime_object_write_to_stream(content, filtered_stream); g_mime_stream_flush(filtered_stream); g_object_unref(filtered_stream); /* reset the content stream */ g_mime_stream_reset(stream); /* encrypt the content stream */ ciphertext = g_mime_stream_mem_new(); if (!libbalsa_gpgme_encrypt (recipients, NULL, stream, ciphertext, GPGME_PROTOCOL_OpenPGP, FALSE, trust_all, parent, err)) { g_object_unref(ciphertext); g_object_unref(stream); return FALSE; } g_object_unref(stream); g_mime_stream_reset(ciphertext); /* construct the version part */ version_part = g_mime_part_new_with_type("application", "pgp-encrypted"); g_mime_part_set_content_encoding(version_part, GMIME_CONTENT_ENCODING_7BIT); stream = g_mime_stream_mem_new_with_buffer("Version: 1\n", strlen("Version: 1\n")); wrapper = g_mime_data_wrapper_new_with_stream(stream, GMIME_CONTENT_ENCODING_7BIT); g_mime_part_set_content_object(version_part, wrapper); g_object_unref(wrapper); g_object_unref(stream); /* construct the encrypted mime part */ encrypted_part = g_mime_part_new_with_type("application", "octet-stream"); g_mime_part_set_content_encoding(encrypted_part, GMIME_CONTENT_ENCODING_7BIT); wrapper = g_mime_data_wrapper_new_with_stream(ciphertext, GMIME_CONTENT_ENCODING_7BIT); g_mime_part_set_content_object(encrypted_part, wrapper); g_object_unref(ciphertext); g_object_unref(wrapper); /* save the version and encrypted parts */ /* FIXME: make sure there aren't any other parts?? */ g_mime_multipart_add(GMIME_MULTIPART(mpe), GMIME_OBJECT(version_part)); g_mime_multipart_add(GMIME_MULTIPART(mpe), GMIME_OBJECT(encrypted_part)); g_object_unref(encrypted_part); g_object_unref(version_part); /* set the content-type params for this multipart/encrypted part */ g_mime_object_set_content_type_parameter(GMIME_OBJECT(mpe), "protocol", "application/pgp-encrypted"); g_mime_multipart_set_boundary(GMIME_MULTIPART(mpe), NULL); return TRUE; }
static notmuch_status_t format_part_text (const void *ctx, mime_node_t *node, int indent, const notmuch_show_params_t *params) { /* The disposition and content-type metadata are associated with * the envelope for message parts */ GMimeObject *meta = node->envelope_part ? GMIME_OBJECT (node->envelope_part) : node->part; GMimeContentType *content_type = g_mime_object_get_content_type (meta); const notmuch_bool_t leaf = GMIME_IS_PART (node->part); const char *part_type; int i; if (node->envelope_file) { notmuch_message_t *message = node->envelope_file; part_type = "message"; printf ("\f%s{ id:%s depth:%d match:%d excluded:%d filename:%s\n", part_type, notmuch_message_get_message_id (message), indent, notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH) ? 1 : 0, notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_EXCLUDED) ? 1 : 0, notmuch_message_get_filename (message)); } else { GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (meta); const char *cid = g_mime_object_get_content_id (meta); const char *filename = leaf ? g_mime_part_get_filename (GMIME_PART (node->part)) : NULL; if (disposition && strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0) part_type = "attachment"; else part_type = "part"; printf ("\f%s{ ID: %d", part_type, node->part_num); if (filename) printf (", Filename: %s", filename); if (cid) printf (", Content-id: %s", cid); printf (", Content-type: %s\n", g_mime_content_type_to_string (content_type)); } if (GMIME_IS_MESSAGE (node->part)) { GMimeMessage *message = GMIME_MESSAGE (node->part); InternetAddressList *recipients; const char *recipients_string; printf ("\fheader{\n"); if (node->envelope_file) printf ("%s\n", _get_one_line_summary (ctx, node->envelope_file)); printf ("Subject: %s\n", g_mime_message_get_subject (message)); printf ("From: %s\n", g_mime_message_get_sender (message)); recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO); recipients_string = internet_address_list_to_string (recipients, 0); if (recipients_string) printf ("To: %s\n", recipients_string); recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_CC); recipients_string = internet_address_list_to_string (recipients, 0); if (recipients_string) printf ("Cc: %s\n", recipients_string); printf ("Date: %s\n", g_mime_message_get_date_as_string (message)); printf ("\fheader}\n"); printf ("\fbody{\n"); } if (leaf) { if (g_mime_content_type_is_type (content_type, "text", "*") && !g_mime_content_type_is_type (content_type, "text", "html")) { GMimeStream *stream_stdout = g_mime_stream_file_new (stdout); g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); show_text_part_content (node->part, stream_stdout, 0); g_object_unref(stream_stdout); } else { printf ("Non-text part: %s\n", g_mime_content_type_to_string (content_type)); } } for (i = 0; i < node->nchildren; i++) format_part_text (ctx, mime_node_child (node, i), indent, params); if (GMIME_IS_MESSAGE (node->part)) printf ("\fbody}\n"); printf ("\f%s}\n", part_type); return NOTMUCH_STATUS_SUCCESS; }
void format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) { /* Any changes to the JSON format should be reflected in the file * devel/schemata. */ if (node->envelope_file) { printf ("{"); format_message_json (ctx, node->envelope_file); printf ("\"headers\": "); format_headers_json (ctx, GMIME_MESSAGE (node->part), FALSE); printf (", \"body\": ["); format_part_json (ctx, mime_node_child (node, 0), first); printf ("]}"); return; } void *local = talloc_new (ctx); /* The disposition and content-type metadata are associated with * the envelope for message parts */ GMimeObject *meta = node->envelope_part ? GMIME_OBJECT (node->envelope_part) : node->part; GMimeContentType *content_type = g_mime_object_get_content_type (meta); const char *cid = g_mime_object_get_content_id (meta); const char *filename = GMIME_IS_PART (node->part) ? g_mime_part_get_filename (GMIME_PART (node->part)) : NULL; const char *terminator = ""; int i; if (!first) printf (", "); printf ("{\"id\": %d", node->part_num); if (node->decrypt_attempted) printf (", \"encstatus\": [{\"status\": \"%s\"}]", node->decrypt_success ? "good" : "bad"); if (node->verify_attempted) { printf (", \"sigstatus\": "); format_part_sigstatus_json (node); } printf (", \"content-type\": %s", json_quote_str (local, g_mime_content_type_to_string (content_type))); if (cid) printf (", \"content-id\": %s", json_quote_str (local, cid)); if (filename) printf (", \"filename\": %s", json_quote_str (local, filename)); if (GMIME_IS_PART (node->part)) { /* For non-HTML text parts, we include the content in the * JSON. Since JSON must be Unicode, we handle charset * decoding here and do not report a charset to the caller. * For text/html parts, we do not include the content. If a * caller is interested in text/html parts, it should retrieve * them separately and they will not be decoded. Since this * makes charset decoding the responsibility on the caller, we * report the charset for text/html parts. */ if (g_mime_content_type_is_type (content_type, "text", "html")) { const char *content_charset = g_mime_object_get_content_type_parameter (meta, "charset"); if (content_charset != NULL) printf (", \"content-charset\": %s", json_quote_str (local, content_charset)); } else if (g_mime_content_type_is_type (content_type, "text", "*")) { GMimeStream *stream_memory = g_mime_stream_mem_new (); GByteArray *part_content; show_text_part_content (node->part, stream_memory, 0); part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory)); printf (", \"content\": %s", json_quote_chararray (local, (char *) part_content->data, part_content->len)); g_object_unref (stream_memory); } } else if (GMIME_IS_MULTIPART (node->part)) { printf (", \"content\": ["); terminator = "]"; } else if (GMIME_IS_MESSAGE (node->part)) { printf (", \"content\": [{"); printf ("\"headers\": "); format_headers_json (local, GMIME_MESSAGE (node->part), FALSE); printf (", \"body\": ["); terminator = "]}]"; } talloc_free (local); for (i = 0; i < node->nchildren; i++) format_part_json (ctx, mime_node_child (node, i), i == 0); printf ("%s}", terminator); }
gboolean g_mime_gpgme_mps_sign(GMimeMultipartSigned * mps, GMimeObject * content, const gchar * userid, gpgme_protocol_t protocol, GtkWindow * parent, GError ** err) { GMimeStream *stream; GMimeStream *filtered; GMimeStream *sigstream; GMimeFilter *filter; GMimeContentType *content_type; GMimeDataWrapper *wrapper; GMimeParser *parser; GMimePart *signature; gchar *micalg; const gchar *proto_type; const gchar *sig_subtype; gpgme_hash_algo_t hash_algo; g_return_val_if_fail(GMIME_IS_MULTIPART_SIGNED(mps), FALSE); g_return_val_if_fail(GMIME_IS_OBJECT(content), FALSE); /* Prepare all the parts for signing... */ sign_prepare(content); /* get the cleartext */ stream = g_mime_stream_mem_new(); filtered = g_mime_stream_filter_new(stream); /* Note: see rfc3156, section 3 - second note */ filter = g_mime_filter_from_new(GMIME_FILTER_FROM_MODE_ARMOR); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter); g_object_unref(filter); /* Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156) */ filter = g_mime_filter_strip_new(); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter); g_object_unref(filter); g_mime_object_write_to_stream(content, filtered); g_mime_stream_flush(filtered); g_object_unref(filtered); g_mime_stream_reset(stream); /* Note: see rfc2015 or rfc3156, section 5.1 */ filtered = g_mime_stream_filter_new(stream); filter = g_mime_filter_crlf_new(TRUE, FALSE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter); g_object_unref(filter); /* construct the signature stream */ sigstream = g_mime_stream_mem_new(); /* sign the content stream */ hash_algo = libbalsa_gpgme_sign(userid, filtered, sigstream, protocol, FALSE, parent, err); g_object_unref(filtered); if (hash_algo == GPGME_MD_NONE) { g_object_unref(sigstream); g_object_unref(stream); return FALSE; } g_mime_stream_reset(sigstream); g_mime_stream_reset(stream); /* set the multipart/signed protocol and micalg */ content_type = g_mime_object_get_content_type(GMIME_OBJECT(mps)); if (protocol == GPGME_PROTOCOL_OpenPGP) { micalg = g_strdup_printf("PGP-%s", gpgme_hash_algo_name(hash_algo)); proto_type = "application/pgp-signature"; sig_subtype = "pgp-signature"; } else { micalg = g_strdup(gpgme_hash_algo_name(hash_algo)); proto_type = "application/pkcs7-signature"; sig_subtype = "pkcs7-signature"; } g_mime_content_type_set_parameter(content_type, "micalg", micalg); g_free(micalg); g_mime_content_type_set_parameter(content_type, "protocol", proto_type); g_mime_multipart_set_boundary(GMIME_MULTIPART(mps), NULL); /* construct the content part */ parser = g_mime_parser_new_with_stream(stream); content = g_mime_parser_construct_part(parser); g_object_unref(stream); g_object_unref(parser); /* construct the signature part */ signature = g_mime_part_new_with_type("application", sig_subtype); wrapper = g_mime_data_wrapper_new(); g_mime_data_wrapper_set_stream(wrapper, sigstream); g_mime_part_set_content_object(signature, wrapper); g_object_unref(sigstream); g_object_unref(wrapper); /* FIXME: temporary hack, this info should probably be set in * the CipherContext class - maybe ::sign can take/output a * GMimePart instead. */ if (protocol == GPGME_PROTOCOL_CMS) { g_mime_part_set_content_encoding(signature, GMIME_CONTENT_ENCODING_BASE64); g_mime_part_set_filename(signature, "smime.p7m"); } /* save the content and signature parts */ /* FIXME: make sure there aren't any other parts?? */ g_mime_multipart_add(GMIME_MULTIPART(mps), content); g_mime_multipart_add(GMIME_MULTIPART(mps), (GMimeObject *) signature); g_object_unref(signature); g_object_unref(content); return TRUE; }
GMimeObject * g_mime_gpgme_mpe_decrypt(GMimeMultipartEncrypted * mpe, GMimeGpgmeSigstat ** signature, GtkWindow * parent, GError ** err) { GMimeObject *decrypted, *version, *encrypted; GMimeStream *stream, *ciphertext; GMimeStream *filtered_stream; GMimeContentType *mime_type; GMimeGpgmeSigstat *sigstat; GMimeDataWrapper *wrapper; GMimeFilter *crlf_filter; GMimeParser *parser; const char *protocol; char *content_type; g_return_val_if_fail(GMIME_IS_MULTIPART_ENCRYPTED(mpe), NULL); if (signature && *signature) { g_object_unref(G_OBJECT(*signature)); *signature = NULL; } protocol = g_mime_object_get_content_type_parameter(GMIME_OBJECT(mpe), "protocol"); /* make sure the protocol is present and matches the cipher encrypt protocol */ if (!protocol || g_ascii_strcasecmp("application/pgp-encrypted", protocol) != 0) { g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR, _ ("Cannot decrypt multipart/encrypted part: unsupported encryption protocol “%s”."), protocol ? protocol : _("(none)")); return NULL; } version = g_mime_multipart_get_part(GMIME_MULTIPART(mpe), GMIME_MULTIPART_ENCRYPTED_VERSION); /* make sure the protocol matches the version part's content-type */ content_type = g_mime_content_type_to_string(version->content_type); if (g_ascii_strcasecmp(content_type, protocol) != 0) { g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR, "%s", _ ("Cannot decrypt multipart/encrypted part: content-type does not match protocol.")); g_free(content_type); return NULL; } g_free(content_type); /* get the encrypted part and check that it is of type application/octet-stream */ encrypted = g_mime_multipart_get_part(GMIME_MULTIPART(mpe), GMIME_MULTIPART_ENCRYPTED_CONTENT); mime_type = g_mime_object_get_content_type(encrypted); if (!g_mime_content_type_is_type (mime_type, "application", "octet-stream")) { g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR, "%s", _ ("Cannot decrypt multipart/encrypted part: unexpected content type")); return NULL; } /* get the ciphertext stream */ wrapper = g_mime_part_get_content_object(GMIME_PART(encrypted)); ciphertext = g_mime_data_wrapper_get_decoded_stream(wrapper); g_mime_stream_reset(ciphertext); stream = g_mime_stream_mem_new(); filtered_stream = g_mime_stream_filter_new(stream); crlf_filter = g_mime_filter_crlf_new(FALSE, FALSE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream), crlf_filter); g_object_unref(crlf_filter); /* get the cleartext */ sigstat = libbalsa_gpgme_decrypt(ciphertext, filtered_stream, GPGME_PROTOCOL_OpenPGP, parent, err); if (!sigstat) { g_object_unref(filtered_stream); g_object_unref(ciphertext); g_object_unref(stream); return NULL; } g_mime_stream_flush(filtered_stream); g_object_unref(filtered_stream); g_object_unref(ciphertext); g_mime_stream_reset(stream); parser = g_mime_parser_new(); g_mime_parser_init_with_stream(parser, stream); g_object_unref(stream); decrypted = g_mime_parser_construct_part(parser); g_object_unref(parser); if (!decrypted) { g_set_error(err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s", _ ("Cannot decrypt multipart/encrypted part: failed to parse decrypted content")); g_object_unref(G_OBJECT(sigstat)); return NULL; } /* cache the decrypted part */ if (signature) { if (sigstat->status != GPG_ERR_NOT_SIGNED) *signature = sigstat; else g_object_unref(G_OBJECT(sigstat)); } return decrypted; }
END_TEST START_TEST(test_imap_get_partspec) { DbmailMessage *message; GMimeObject *object; char *result, *expect; /* text/plain */ message = dbmail_message_new(); message = dbmail_message_init_with_string(message, g_string_new(rfc822)); object = imap_get_partspec(GMIME_OBJECT(message->content),"HEADER"); result = imap_get_logical_part(object,"HEADER"); expect = g_strdup("From nobody Wed Sep 14 16:47:48 2005\r\n" "Content-Type: text/plain; charset=\"us-ascii\"\r\n" "MIME-Version: 1.0\r\n" "Content-Transfer-Encoding: 7bit\r\n" "Message-Id: <1199706209l.3020l.1l@(none)>\r\n" "To: [email protected]\r\n" "From: [email protected]\r\n" "Subject: dbmail test message\r\n" ""); fail_unless(MATCH(expect,result),"imap_get_partsec failed \n[%s] !=\n[%s]\n", expect, result); g_free(expect); g_free(result); object = imap_get_partspec(GMIME_OBJECT(message->content),"TEXT"); result = imap_get_logical_part(object,"TEXT"); expect = g_strdup("\r\n" " this is a test message\r\n" "\r\n"); fail_unless(MATCH(expect,result),"imap_get_partsec failed \n[%s] !=\n[%s]\n", expect, result); g_free(expect); g_free(result); dbmail_message_free(message); /* multipart */ message = dbmail_message_new(); message = dbmail_message_init_with_string(message, g_string_new(multipart_message)); object = imap_get_partspec(GMIME_OBJECT(message->content),"1"); result = imap_get_logical_part(object,NULL); expect = g_strdup("Content-type: text/html\r\n" "Content-disposition: inline\r\n\r\n" "Test message one\r\n" " and more.\r\n"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); object = imap_get_partspec(GMIME_OBJECT(message->content),"1.TEXT"); result = imap_get_logical_part(object,"TEXT"); expect = g_strdup("Test message one\r\n" " and more.\r\n"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); object = imap_get_partspec(GMIME_OBJECT(message->content),"1.HEADER"); result = imap_get_logical_part(object,"HEADER"); expect = g_strdup("Content-type: text/html\r\n" "Content-disposition: inline\r\n"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); object = imap_get_partspec(GMIME_OBJECT(message->content),"2.MIME"); result = imap_get_logical_part(object,"MIME"); expect = g_strdup("Content-type: text/plain; charset=us-ascii; name=testfile\r\n" "Content-transfer-encoding: base64\r\n"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); dbmail_message_free(message); /* multipart mixed */ message = dbmail_message_new(); message = dbmail_message_init_with_string(message, g_string_new(multipart_mixed)); object = imap_get_partspec(GMIME_OBJECT(message->content),"2.HEADER"); result = imap_get_logical_part(object,"HEADER"); fail_unless(strncmp(result,"From: \"try\" <*****@*****.**>",29)==0,"imap_get_partspec failed"); g_free(result); object = imap_get_partspec(GMIME_OBJECT(message->content),"2.1.1"); result = imap_get_logical_part(object,NULL); expect = g_strdup("Content-Type: text/plain;\r\n" " charset=\"us-ascii\"\r\n" "Content-Transfer-Encoding: 7bit\r\n\r\n" "Body of doc2\r\n\r\n"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); dbmail_message_free(message); }
static int notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params) { GMimeMessage *reply; notmuch_messages_t *messages; notmuch_message_t *message; const char *subject, *from_addr = NULL; const char *in_reply_to, *orig_references, *references; const notmuch_show_format_t *format = &format_reply; for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); /* The 1 means we want headers in a "pretty" order. */ reply = g_mime_message_new (1); if (reply == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } subject = notmuch_message_get_header (message, "subject"); if (subject) { if (strncasecmp (subject, "Re:", 3)) subject = talloc_asprintf (ctx, "Re: %s", subject); g_mime_message_set_subject (reply, subject); } from_addr = add_recipients_from_message (reply, config, message); if (from_addr == NULL) from_addr = guess_from_received_header (config, message); if (from_addr == NULL) from_addr = notmuch_config_get_user_primary_email (config); from_addr = talloc_asprintf (ctx, "%s <%s>", notmuch_config_get_user_name (config), from_addr); g_mime_object_set_header (GMIME_OBJECT (reply), "From", from_addr); in_reply_to = talloc_asprintf (ctx, "<%s>", notmuch_message_get_message_id (message)); g_mime_object_set_header (GMIME_OBJECT (reply), "In-Reply-To", in_reply_to); orig_references = notmuch_message_get_header (message, "references"); references = talloc_asprintf (ctx, "%s%s%s", orig_references ? orig_references : "", orig_references ? " " : "", in_reply_to); g_mime_object_set_header (GMIME_OBJECT (reply), "References", references); show_reply_headers (reply); g_object_unref (G_OBJECT (reply)); reply = NULL; printf ("On %s, %s wrote:\n", notmuch_message_get_header (message, "date"), notmuch_message_get_header (message, "from")); show_message_body (notmuch_message_get_filename (message), format, params); notmuch_message_destroy (message); } return 0; }
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; }
END_TEST START_TEST(test_imap_get_partspec) { DbmailMessage *message; GMimeObject *object; char *result, *expect; /* text/plain */ message = dbmail_message_new(NULL); message = dbmail_message_init_with_string(message, rfc822); object = imap_get_partspec(GMIME_OBJECT(message->content),"HEADER"); result = g_mime_object_to_string(object); fail_unless(MATCH(rfc822,result), "imap_get_partsec failed \n[%s] !=\n[%s]\n", rfc822, result); g_free(result); result = imap_get_logical_part(object,"HEADER"); expect = g_strdup("From nobody Wed Sep 14 16:47:48 2005\r\n" "Content-Type: text/plain; charset=\"us-ascii\"\r\n" "MIME-Version: 1.0\r\n" "Content-Transfer-Encoding: 7bit\r\n" "Message-Id: <1199706209l.3020l.1l@(none)>\r\n" "To: [email protected]\r\n" "From: [email protected]\r\n" "Subject: dbmail test message\r\n" "\r\n"); fail_unless(MATCH(expect,result),"imap_get_partsec failed \n[%s] !=\n[%s]\n", expect, result); g_free(expect); g_free(result); object = imap_get_partspec(GMIME_OBJECT(message->content),"TEXT"); result = imap_get_logical_part(object,"TEXT"); expect = g_strdup("\r\n" " this is a test message\r\n" "\r\n"); fail_unless(MATCH(expect,result),"imap_get_partsec failed \n[%s] !=\n[%s]\n", expect, result); g_free(expect); g_free(result); dbmail_message_free(message); /* multipart */ message = dbmail_message_new(NULL); message = dbmail_message_init_with_string(message, multipart_message); /* test a simple mime part */ object = imap_get_partspec(GMIME_OBJECT(message->content),"1"); result = imap_get_logical_part(object,"MIME"); expect = g_strdup("Content-type: text/html\r\n" "Content-disposition: inline\r\n\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); result = imap_get_logical_part(object,NULL); expect = g_strdup("Test message one\r\n and more.\r\n"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); /* object isn't a message/rfc822 so these are * acually invalid. Let's try anyway */ result = imap_get_logical_part(object,"HEADER"); expect = g_strdup("Content-type: text/html\r\n" "Content-disposition: inline\r\n\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); result = imap_get_logical_part(object,"TEXT"); expect = g_strdup("Test message one\r\n and more.\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); /* moving on */ object = imap_get_partspec(GMIME_OBJECT(message->content),"2"); result = imap_get_logical_part(object,"MIME"); expect = g_strdup( "Content-type: text/plain; charset=us-ascii; name=testfile\r\n" "Content-transfer-encoding: base64\r\n" "\r\n" ); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); dbmail_message_free(message); /* multipart mixed */ message = dbmail_message_new(NULL); message = dbmail_message_init_with_string(message, multipart_mixed); object = imap_get_partspec(GMIME_OBJECT(message->content),"2"); result = imap_get_logical_part(object,"HEADER"); expect = g_strdup("From: \"try\" <*****@*****.**>"); fail_unless((strncmp(expect,result,29)==0), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(expect); g_free(result); object = imap_get_partspec(GMIME_OBJECT(message->content),"2.1.1"); result = imap_get_logical_part(object,NULL); expect = g_strdup("Body of doc2\r\n\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); result = imap_get_logical_part(object,"MIME"); expect = g_strdup("Content-Type: text/plain;\r\n" " charset=\"us-ascii\"\r\n" "Content-Transfer-Encoding: 7bit\r\n\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); dbmail_message_free(message); /* multipart signed */ message = dbmail_message_new(NULL); message = dbmail_message_init_with_string(message, multipart_signed); object = imap_get_partspec(GMIME_OBJECT(message->content),"1.1"); result = imap_get_logical_part(object,NULL); expect = g_strdup("quo-pri text"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); object = imap_get_partspec(GMIME_OBJECT(message->content),"1.3"); result = g_mime_object_to_string(object); expect = g_strdup("Content-Type: message/rfc822;\n" "Content-Transfer-Encoding: 7bit\n" "Content-Disposition: attachment;\n" " filename=\"msg1.eml\"\n" "\n" "Date: Mon, 19 Aug 2013 14:54:05 +0200\n" "To: a@b\n" "From: d@b\n" "Reply-To: e@b\n" "Subject: msg1\n" "MIME-Version: 1.0\n" "Content-Type: multipart/alternative;\n" " boundary=b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845\n" "\n" "\n" "--b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845\n" "Content-Type: text/plain; charset=\"ISO-8859-1\"\n" "Content-Transfer-Encoding: quoted-printable\n" "\n" "quo-pri text\n" "--b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845\n" "Content-Type: text/html; charset=\"ISO-8859-1\"\n" "Content-Transfer-Encoding: quoted-printable\n" "\n" "html text\n" "\n" "--b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845--\n" "\n" "\n" "\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); result = imap_get_logical_part(object,"MIME"); expect = g_strdup("Content-Type: message/rfc822;\r\n" "Content-Transfer-Encoding: 7bit\r\n" "Content-Disposition: attachment;\r\n" " filename=\"msg1.eml\"\r\n" "\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); result = imap_get_logical_part(object,NULL); expect = g_strdup("Date: Mon, 19 Aug 2013 14:54:05 +0200\r\n" "To: a@b\r\n" "From: d@b\r\n" "Reply-To: e@b\r\n" "Subject: msg1\r\n" "MIME-Version: 1.0\r\n" "Content-Type: multipart/alternative;\r\n" " boundary=b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845\r\n" "\r\n" "\r\n" "--b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845\r\n" "Content-Type: text/plain; charset=\"ISO-8859-1\"\r\n" "Content-Transfer-Encoding: quoted-printable\r\n" "\r\n" "quo-pri text\r\n" "--b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845\r\n" "Content-Type: text/html; charset=\"ISO-8859-1\"\r\n" "Content-Transfer-Encoding: quoted-printable\r\n" "\r\n" "html text\r\n" "\r\n" "--b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845--\r\n" "\r\n" "\r\n" "\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); result = imap_get_logical_part(object,"MIME"); expect = g_strdup("Content-Type: message/rfc822;\r\n" "Content-Transfer-Encoding: 7bit\r\n" "Content-Disposition: attachment;\r\n" " filename=\"msg1.eml\"\r\n" "\r\n"); fail_unless(MATCH(expect,result), "imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); result = imap_get_logical_part(object,"HEADER"); expect = g_strdup("Date: Mon, 19 Aug 2013 14:54:05 +0200\r\n" "To: a@b\r\n" "From: d@b\r\n" "Reply-To: e@b\r\n" "Subject: msg1\r\n" "MIME-Version: 1.0\r\n" "Content-Type: multipart/alternative;\r\n" "\tboundary=b1_7ad0d7cccab59d27194f9ad69c14606001f05f531376916845\r\n" "\r\n"); fail_unless(MATCH(expect,result),"imap_get_partspec failed:\n[%s] != \n[%s]\n", expect, result); g_free(result); g_free(expect); dbmail_message_free(message); }
void format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node, notmuch_bool_t first, notmuch_bool_t output_body, notmuch_bool_t include_html) { /* Any changes to the JSON or S-Expression format should be * reflected in the file devel/schemata. */ if (node->envelope_file) { sp->begin_map (sp); format_message_sprinter (sp, node->envelope_file); sp->map_key (sp, "headers"); format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE); if (output_body) { sp->map_key (sp, "body"); sp->begin_list (sp); format_part_sprinter (ctx, sp, mime_node_child (node, 0), first, TRUE, include_html); sp->end (sp); } sp->end (sp); return; } /* The disposition and content-type metadata are associated with * the envelope for message parts */ GMimeObject *meta = node->envelope_part ? GMIME_OBJECT (node->envelope_part) : node->part; GMimeContentType *content_type = g_mime_object_get_content_type (meta); const char *cid = g_mime_object_get_content_id (meta); const char *filename = GMIME_IS_PART (node->part) ? g_mime_part_get_filename (GMIME_PART (node->part)) : NULL; int nclose = 0; int i; sp->begin_map (sp); sp->map_key (sp, "id"); sp->integer (sp, node->part_num); if (node->decrypt_attempted) { sp->map_key (sp, "encstatus"); sp->begin_list (sp); sp->begin_map (sp); sp->map_key (sp, "status"); sp->string (sp, node->decrypt_success ? "good" : "bad"); sp->end (sp); sp->end (sp); } if (node->verify_attempted) { sp->map_key (sp, "sigstatus"); format_part_sigstatus_sprinter (sp, node); } sp->map_key (sp, "content-type"); sp->string (sp, g_mime_content_type_to_string (content_type)); if (cid) { sp->map_key (sp, "content-id"); sp->string (sp, cid); } if (filename) { sp->map_key (sp, "filename"); sp->string (sp, filename); } if (GMIME_IS_PART (node->part)) { /* For non-HTML text parts, we include the content in the * JSON. Since JSON must be Unicode, we handle charset * decoding here and do not report a charset to the caller. * For text/html parts, we do not include the content unless * the --include-html option has been passed. If a html part * is not included, it can be requested directly. This makes * charset decoding the responsibility on the caller so we * report the charset for text/html parts. */ if (g_mime_content_type_is_type (content_type, "text", "*") && (include_html || ! g_mime_content_type_is_type (content_type, "text", "html"))) { GMimeStream *stream_memory = g_mime_stream_mem_new (); GByteArray *part_content; show_text_part_content (node->part, stream_memory, 0); part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory)); sp->map_key (sp, "content"); sp->string_len (sp, (char *) part_content->data, part_content->len); g_object_unref (stream_memory); } else { format_omitted_part_meta_sprinter (sp, meta, GMIME_PART (node->part)); } } else if (GMIME_IS_MULTIPART (node->part)) { sp->map_key (sp, "content"); sp->begin_list (sp); nclose = 1; } else if (GMIME_IS_MESSAGE (node->part)) { sp->map_key (sp, "content"); sp->begin_list (sp); sp->begin_map (sp); sp->map_key (sp, "headers"); format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE); sp->map_key (sp, "body"); sp->begin_list (sp); nclose = 3; } for (i = 0; i < node->nchildren; i++) format_part_sprinter (ctx, sp, mime_node_child (node, i), i == 0, TRUE, include_html); /* Close content structures */ for (i = 0; i < nclose; i++) sp->end (sp); /* Close part map */ sp->end (sp); }