static gint multipart_signed_construct_from_parser (CamelMultipart *multipart, CamelMimeParser *mp) { gint err; CamelContentType *content_type; CamelMultipartSigned *mps = (CamelMultipartSigned *) multipart; CamelDataWrapper *data_wrapper; GByteArray *byte_array; gchar *buf; gsize len; /* we *must not* be in multipart state, otherwise the mime parser will * parse the headers which is a no no @#$@# stupid multipart/signed spec */ g_assert (camel_mime_parser_state (mp) == CAMEL_MIME_PARSER_STATE_HEADER); /* All we do is copy it to a memstream */ content_type = camel_mime_parser_content_type (mp); camel_multipart_set_boundary (multipart, camel_content_type_param (content_type, "boundary")); data_wrapper = CAMEL_DATA_WRAPPER (multipart); byte_array = camel_data_wrapper_get_byte_array (data_wrapper); /* Wipe any previous contents from the byte array. */ g_byte_array_set_size (byte_array, 0); while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END) g_byte_array_append (byte_array, (guint8 *) buf, len); mps->start1 = -1; if (mps->content) { g_object_unref (mps->content); mps->content = NULL; } if (mps->contentraw) { g_object_unref (mps->contentraw); mps->contentraw = NULL; } if (mps->signature) { g_object_unref (mps->signature); mps->signature = NULL; } err = camel_mime_parser_errno (mp); if (err != 0) { errno = err; return -1; } else return 0; }
static gint multipart_construct_from_parser (CamelMultipart *multipart, CamelMimeParser *mp) { gint err; CamelContentType *content_type; CamelMimePart *bodypart; gchar *buf; gsize len; g_assert (camel_mime_parser_state (mp) == CAMEL_MIME_PARSER_STATE_MULTIPART); /* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */ d(printf("Creating multi-part\n")); content_type = camel_mime_parser_content_type (mp); camel_multipart_set_boundary (multipart, camel_content_type_param(content_type, "boundary")); while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) { camel_mime_parser_unstep (mp); bodypart = camel_mime_part_new (); camel_mime_part_construct_from_parser_sync ( bodypart, mp, NULL, NULL); camel_multipart_add_part (multipart, bodypart); g_object_unref (bodypart); } /* these are only return valid data in the MULTIPART_END state */ camel_multipart_set_preface (multipart, camel_mime_parser_preface (mp)); camel_multipart_set_postface (multipart, camel_mime_parser_postface (mp)); err = camel_mime_parser_errno (mp); if (err != 0) { errno = err; return -1; } else return 0; }
CamelMimeMessage * scalix_appointment_to_mime_message (ScalixObject * object) { CamelMimeMessage *message; CamelMultipart *multipart; CamelMimePart *part; CamelMedium *medium; CamelStream *stream; CamelDataWrapper *wrapper; ECalComponentDateTime dtstart, dtend; ECalComponent *comp; ECalComponentText text; icalcomponent_kind kind; icalcomponent *icalcomp, *toplevel_comp; icaltimezone *zone = NULL; GSList *attachment_list = NULL; GSList *attachment_list_new = NULL; GSList *siter = NULL; GList *part_list = NULL; GList *iter = NULL; char *msgid; char *str, *meeting_status; const char *ouid = NULL; char *file_contents = NULL; char *full_path, *filename, *mime_filename; char *cid; int size; g_object_get (SCALIX_APPOINTMENT (object), "timezone", &zone, NULL); comp = E_CAL_COMPONENT (scalix_object_clone (object)); message = camel_mime_message_new (); medium = CAMEL_MEDIUM (message); camel_medium_add_header (medium, "X-Scalix-Class", "IPM.Appointment"); /* Preserve msg id if there is already one */ if (scalix_appointment_get (SCALIX_APPOINTMENT (comp), X_SCALIX_MSG_ID, &msgid)) { scalix_appointment_unset (SCALIX_APPOINTMENT (comp), X_SCALIX_MSG_ID); } else { msgid = camel_header_msgid_generate (); } camel_mime_message_set_message_id (message, msgid); /* subject */ e_cal_component_get_summary (comp, &text); if (text.value != NULL) { camel_mime_message_set_subject (message, text.value); } /* start day */ e_cal_component_get_dtstart (comp, &dtstart); if (!icaltime_get_timezone (*dtstart.value)) icaltime_set_timezone (dtstart.value, icaltimezone_get_builtin_timezone_from_tzid (dtstart.tzid)); /* end day */ e_cal_component_get_dtend (comp, &dtend); if (!icaltime_get_timezone (*dtend.value)) icaltime_set_timezone (dtend.value, icaltimezone_get_builtin_timezone_from_tzid (dtend.tzid)); /* set From: and Sender: */ if (e_cal_component_has_organizer (comp)) { ECalComponentOrganizer organizer; e_cal_component_get_organizer (comp, &organizer); if (!strncasecmp (organizer.value, "MAILTO:", 7)) { camel_medium_add_header (medium, "Sender", organizer.value + 7); camel_medium_add_header (medium, "From", organizer.value + 7); } } /* set the appropriate recipient headers from the recipient table */ if (e_cal_component_has_attendees (comp) && e_cal_component_has_organizer (comp)) { GSList *iter, *attendees = NULL; CamelInternetAddress *recipients_to = NULL; CamelInternetAddress *recipients_cc = NULL; meeting_status = "1"; e_cal_component_get_attendee_list (comp, &attendees); for (iter = attendees; iter; iter = iter->next) { ECalComponentAttendee *attendee = iter->data; const char *mail = NULL; /* attendee entries must start with MAILTO: */ if (strncasecmp (attendee->value, "MAILTO:", 7)) { continue; } mail = attendee->value + 7; if (attendee->role == ICAL_ROLE_REQPARTICIPANT) { if (recipients_to == NULL) { recipients_to = camel_internet_address_new (); } camel_internet_address_add (recipients_to, attendee->cn, mail); } else if (attendee->role == ICAL_ROLE_OPTPARTICIPANT) { if (recipients_cc == NULL) { recipients_cc = camel_internet_address_new (); } camel_internet_address_add (recipients_cc, attendee->cn, mail); } else { continue; } } if (recipients_to != NULL) { camel_mime_message_set_recipients (message, "To", recipients_to); camel_object_unref (recipients_to); } if (recipients_cc != NULL) { camel_mime_message_set_recipients (message, "Cc", recipients_cc); camel_object_unref (recipients_cc); } } else { meeting_status = "0"; } /* Clear properties */ scalix_appointment_unset (SCALIX_APPOINTMENT (comp), X_SCALIX_IMAP_UID); /* Render the text/calendar */ e_cal_component_commit_sequence (comp); icalcomp = e_cal_component_get_icalcomponent (comp); kind = icalcomponent_isa (icalcomp); if (kind != ICAL_VCALENDAR_COMPONENT) { /* If its not a VCALENDAR, make it one to simplify below */ toplevel_comp = e_cal_util_new_top_level (); icalcomponent_add_component (toplevel_comp, icalcomp); icalcomp = toplevel_comp; } /* set METHOD to PUSBLISH */ icalcomponent_set_method (icalcomp, ICAL_METHOD_PUBLISH); /* Add the VTIMEZONE components for start- and/or end-times */ if (zone) { icalcomponent_add_component (icalcomp, icaltimezone_get_component (zone)); } else if (dtstart.tzid) { icalcomponent_add_component (icalcomp, icaltimezone_get_component (icaltimezone_get_builtin_timezone_from_tzid (dtstart.tzid))); } if (dtstart.tzid && dtend.tzid && strcmp (dtstart.tzid, dtend.tzid) != 0) { icalcomponent_add_component (icalcomp, icaltimezone_get_component (icaltimezone_get_builtin_timezone_from_tzid (dtend.tzid))); } /* FIXME: do we leek icalcomponents here? */ if (e_cal_component_has_attachments (comp)) { multipart = camel_multipart_new (); camel_multipart_set_boundary (multipart, NULL); e_cal_component_get_uid (comp, &ouid); e_cal_component_get_attachment_list (comp, &attachment_list); for (siter = attachment_list; siter; siter = siter->next) { if (siter->data == NULL) continue; if (strstr (siter->data, "file://") != siter->data) continue; full_path = ((char *) siter->data) + strlen ("file://"); filename = g_strrstr (full_path, "/") + 1; mime_filename = filename + strlen (ouid) + 1; size = 0; file_contents = get_file_contents (full_path, &size); if (file_contents == NULL) continue; stream = camel_stream_mem_new_with_buffer (file_contents, size); wrapper = camel_data_wrapper_new (); camel_data_wrapper_construct_from_stream (wrapper, stream); camel_object_unref (stream); part = camel_mime_part_new (); camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper); camel_mime_part_set_filename (part, mime_filename); camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64); cid = camel_header_msgid_generate (); camel_mime_part_set_content_id (part, cid); camel_mime_part_set_description (part, mime_filename); camel_mime_part_set_disposition (part, "attachment"); part_list = g_list_append (part_list, part); attachment_list_new = g_slist_append (attachment_list_new, g_strdup_printf ("CID:%s", cid)); g_free (cid); } e_cal_component_set_attachment_list (comp, attachment_list_new); str = icalcomponent_as_ical_string (icalcomp); part = camel_mime_part_new (); camel_mime_part_set_content (part, str, strlen (str), "text/calendar; method=PUBLISH; charset=UTF-8"); part_list = g_list_prepend (part_list, part); for (iter = part_list; iter; iter = iter->next) { part = (CamelMimePart *) iter->data; camel_multipart_add_part (multipart, part); camel_object_unref (part); } camel_medium_set_content_object (CAMEL_MEDIUM (message), CAMEL_DATA_WRAPPER (multipart)); camel_object_unref (multipart); g_slist_free (attachment_list); g_slist_free (attachment_list_new); g_list_free (part_list); } else { str = icalcomponent_as_ical_string (icalcomp); camel_mime_part_set_content (CAMEL_MIME_PART (message), str, strlen (str), "text/calendar; method=PUBLISH; charset=UTF-8"); } scalix_appointment_set (SCALIX_APPOINTMENT (object), X_SCALIX_MSG_ID, msgid); return message; }
static int sm_sign(CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) { int res = -1; NSSCMSMessage *cmsg; CamelStream *ostream, *istream; SECOidTag sechash; NSSCMSEncoderContext *enc; CamelDataWrapper *dw; CamelContentType *ct; switch (hash) { case CAMEL_CIPHER_HASH_SHA1: case CAMEL_CIPHER_HASH_DEFAULT: default: sechash = SEC_OID_SHA1; break; case CAMEL_CIPHER_HASH_MD5: sechash = SEC_OID_MD5; break; } cmsg = sm_signing_cmsmessage((CamelSMIMEContext *)context, userid, sechash, ((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN, ex); if (cmsg == NULL) return -1; ostream = camel_stream_mem_new(); /* FIXME: stream this, we stream output at least */ istream = camel_stream_mem_new(); if (camel_cipher_canonical_to_stream(ipart, CAMEL_MIME_FILTER_CANON_STRIP |CAMEL_MIME_FILTER_CANON_CRLF |CAMEL_MIME_FILTER_CANON_FROM, istream) == -1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not generate signing data: %s"), g_strerror(errno)); goto fail; } enc = NSS_CMSEncoder_Start(cmsg, sm_write_stream, ostream, /* DER output callback */ NULL, NULL, /* destination storage */ NULL, NULL, /* password callback */ NULL, NULL, /* decrypt key callback */ NULL, NULL ); /* detached digests */ if (!enc) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create encoder context")); goto fail; } if (NSS_CMSEncoder_Update(enc, (char *) ((CamelStreamMem *)istream)->buffer->data, ((CamelStreamMem *)istream)->buffer->len) != SECSuccess) { NSS_CMSEncoder_Cancel(enc); camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to CMS encoder")); goto fail; } if (NSS_CMSEncoder_Finish(enc) != SECSuccess) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to encode data")); goto fail; } res = 0; dw = camel_data_wrapper_new(); camel_stream_reset(ostream); camel_data_wrapper_construct_from_stream(dw, ostream); dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY; if (((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN) { CamelMultipartSigned *mps; CamelMimePart *sigpart; sigpart = camel_mime_part_new(); ct = camel_content_type_new("application", "x-pkcs7-signature"); camel_content_type_set_param(ct, "name", "smime.p7s"); camel_data_wrapper_set_mime_type_field(dw, ct); camel_content_type_unref(ct); camel_medium_set_content_object((CamelMedium *)sigpart, dw); camel_mime_part_set_filename(sigpart, "smime.p7s"); camel_mime_part_set_disposition(sigpart, "attachment"); camel_mime_part_set_encoding(sigpart, CAMEL_TRANSFER_ENCODING_BASE64); mps = camel_multipart_signed_new(); ct = camel_content_type_new("multipart", "signed"); camel_content_type_set_param(ct, "micalg", camel_cipher_hash_to_id(context, hash)); camel_content_type_set_param(ct, "protocol", context->sign_protocol); camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mps, ct); camel_content_type_unref(ct); camel_multipart_set_boundary((CamelMultipart *)mps, NULL); mps->signature = sigpart; mps->contentraw = istream; camel_stream_reset(istream); camel_object_ref(istream); camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps); } else { ct = camel_content_type_new("application", "x-pkcs7-mime"); camel_content_type_set_param(ct, "name", "smime.p7m"); camel_content_type_set_param(ct, "smime-type", "signed-data"); camel_data_wrapper_set_mime_type_field(dw, ct); camel_content_type_unref(ct); camel_medium_set_content_object((CamelMedium *)opart, dw); camel_mime_part_set_filename(opart, "smime.p7m"); camel_mime_part_set_description(opart, "S/MIME Signed Message"); camel_mime_part_set_disposition(opart, "attachment"); camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64); } camel_object_unref(dw); fail: camel_object_unref(ostream); camel_object_unref(istream); return res; }
static void mail_attachment_handler_x_uid_list (EAttachmentView *view, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, EAttachmentHandler *handler) { static GdkAtom atom = GDK_NONE; EMailAttachmentHandlerPrivate *priv; CamelDataWrapper *wrapper; CamelMimeMessage *message; CamelMultipart *multipart; CamelMimePart *mime_part; CamelFolder *folder = NULL; EAttachment *attachment; EAttachmentStore *store; EMailSession *session; GPtrArray *uids; const gchar *data; const gchar *cp, *end; gchar *description; gpointer parent; gint length; guint ii; GError *local_error = NULL; if (G_UNLIKELY (atom == GDK_NONE)) atom = gdk_atom_intern_static_string ("x-uid-list"); if (gtk_selection_data_get_target (selection_data) != atom) return; store = e_attachment_view_get_store (view); priv = E_MAIL_ATTACHMENT_HANDLER_GET_PRIVATE (handler); parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); parent = gtk_widget_is_toplevel (parent) ? parent : NULL; uids = g_ptr_array_new (); data = (const gchar *) gtk_selection_data_get_data (selection_data); length = gtk_selection_data_get_length (selection_data); /* The UID list is delimited by NUL characters. * Brilliant. So we can't use g_strsplit(). */ cp = data; end = data + length; while (cp < end) { const gchar *start = cp; while (cp < end && *cp != '\0') cp++; /* Skip the first string. */ if (start > data) g_ptr_array_add (uids, g_strndup (start, cp - start)); cp++; } if (uids->len == 0) goto exit; session = e_mail_backend_get_session (priv->backend); /* The first string is the folder URI. */ /* FIXME Not passing a GCancellable here. */ folder = e_mail_session_uri_to_folder_sync ( session, data, 0, NULL, &local_error); if (folder == NULL) goto exit; /* Handle one message. */ if (uids->len == 1) { const gchar *message_uid; message_uid = g_ptr_array_index (uids, 0); /* FIXME Not passing a GCancellable here. */ message = camel_folder_get_message_sync ( folder, message_uid, NULL, &local_error); if (message == NULL) goto exit; attachment = e_attachment_new_for_message (message); e_attachment_store_add_attachment (store, attachment); e_attachment_load_async ( attachment, (GAsyncReadyCallback) call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL); g_object_unref (attachment); g_object_unref (message); goto exit; } /* Build a multipart/digest message out of the UIDs. */ multipart = camel_multipart_new (); wrapper = CAMEL_DATA_WRAPPER (multipart); camel_data_wrapper_set_mime_type (wrapper, "multipart/digest"); camel_multipart_set_boundary (multipart, NULL); for (ii = 0; ii < uids->len; ii++) { /* FIXME Not passing a GCancellable here. */ message = camel_folder_get_message_sync ( folder, uids->pdata[ii], NULL, &local_error); if (message == NULL) { g_object_unref (multipart); goto exit; } mime_part = camel_mime_part_new (); wrapper = CAMEL_DATA_WRAPPER (message); camel_mime_part_set_disposition (mime_part, "inline"); camel_medium_set_content ( CAMEL_MEDIUM (mime_part), wrapper); camel_mime_part_set_content_type (mime_part, "message/rfc822"); camel_multipart_add_part (multipart, mime_part); g_object_unref (mime_part); g_object_unref (message); } mime_part = camel_mime_part_new (); wrapper = CAMEL_DATA_WRAPPER (multipart); camel_medium_set_content (CAMEL_MEDIUM (mime_part), wrapper); description = g_strdup_printf ( ngettext ( "%d attached message", "%d attached messages", uids->len), uids->len); camel_mime_part_set_description (mime_part, description); g_free (description); attachment = e_attachment_new (); e_attachment_set_mime_part (attachment, mime_part); e_attachment_store_add_attachment (store, attachment); e_attachment_load_async ( attachment, (GAsyncReadyCallback) call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL); g_object_unref (attachment); g_object_unref (mime_part); g_object_unref (multipart); exit: if (local_error != NULL) { const gchar *folder_name = data; if (folder != NULL) folder_name = camel_folder_get_display_name (folder); e_alert_run_dialog_for_args ( parent, "mail-composer:attach-nomessages", folder_name, local_error->message, NULL); g_clear_error (&local_error); } if (folder != NULL) g_object_unref (folder); g_ptr_array_free (uids, TRUE); g_signal_stop_emission_by_name (view, "drag-data-received"); }
void org_gnome_format_tnef(void *ep, EMFormatHookTarget *t) { char *tmpdir = NULL, *name = NULL; CamelStream *out; struct dirent *d; DIR *dir; CamelMultipart *mp; CamelMimePart *mainpart; CamelDataWrapper *content; int len; TNEFStruct *tnef; tnef = (TNEFStruct *) g_malloc(sizeof(TNEFStruct)); tmpdir = e_mkdtemp("tnef-attachment-XXXXXX"); if (tmpdir == NULL) return; filepath = tmpdir; name = g_build_filename(tmpdir, ".evo-attachment.tnef", NULL); out = camel_stream_fs_new_with_name(name, O_RDWR|O_CREAT, 0666); if (out == NULL) goto fail; content = camel_medium_get_content_object((CamelMedium *)t->part); if (content == NULL) goto fail; if (camel_data_wrapper_decode_to_stream(content, out) == -1 || camel_stream_close(out) == -1) { camel_object_unref(out); goto fail; } camel_object_unref(out); /* Extracting the winmail.dat */ TNEFInitialize(tnef); tnef->Debug = verbose; if (TNEFParseFile(name, tnef) == -1) { printf("ERROR processing file\n"); } processTnef(tnef); TNEFFree(tnef); /* Extraction done */ dir = opendir(tmpdir); if (dir == NULL) goto fail; mainpart = camel_mime_part_new(); mp = camel_multipart_new(); camel_data_wrapper_set_mime_type((CamelDataWrapper *)mp, "multipart/mixed"); camel_multipart_set_boundary(mp, NULL); camel_medium_set_content_object((CamelMedium *)mainpart, (CamelDataWrapper *)mp); while ((d = readdir(dir))) { CamelMimePart *part; CamelDataWrapper *content; CamelStream *stream; char *path; const char *type; if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..") || !strcmp(d->d_name, ".evo-attachment.tnef")) continue; path = g_build_filename(tmpdir, d->d_name, NULL); stream = camel_stream_fs_new_with_name(path, O_RDONLY, 0); content = camel_data_wrapper_new(); camel_data_wrapper_construct_from_stream(content, stream); camel_object_unref(stream); part = camel_mime_part_new(); camel_mime_part_set_encoding(part, CAMEL_TRANSFER_ENCODING_BINARY); camel_medium_set_content_object((CamelMedium *)part, content); camel_object_unref(content); type = em_utils_snoop_type(part); if (type) camel_data_wrapper_set_mime_type((CamelDataWrapper *)part, type); camel_mime_part_set_filename(part, d->d_name); g_free(path); camel_multipart_add_part(mp, part); } closedir(dir); len = t->format->part_id->len; g_string_append_printf(t->format->part_id, ".tnef"); if (camel_multipart_get_number(mp) > 0) em_format_part_as(t->format, t->stream, mainpart, "multipart/mixed"); else if (t->item->handler.old) t->item->handler.old->handler(t->format, t->stream, t->part, t->item->handler.old); g_string_truncate(t->format->part_id, len); camel_object_unref(mainpart); goto ok; fail: if (t->item->handler.old) t->item->handler.old->handler(t->format, t->stream, t->part, t->item->handler.old); ok: g_free(name); g_free(tmpdir); }