static void save_snapshot_get_message_cb (EMsgComposer *composer, GAsyncResult *result, GSimpleAsyncResult *simple) { SaveContext *context; CamelMimeMessage *message; GInputStream *input_stream; CamelStream *camel_stream; GByteArray *buffer; GError *local_error = NULL; context = g_simple_async_result_get_op_res_gpointer (simple); message = e_msg_composer_get_message_draft_finish ( composer, result, &local_error); if (local_error != NULL) { g_warn_if_fail (message == NULL); g_simple_async_result_take_error (simple, local_error); g_simple_async_result_complete (simple); g_object_unref (simple); return; } g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); /* Decode the message to an in-memory buffer. We have to do this * because CamelStreams are synchronous-only, and using threads is * dangerous because CamelDataWrapper is not reentrant. */ buffer = g_byte_array_new (); camel_stream = camel_stream_mem_new (); camel_stream_mem_set_byte_array ( CAMEL_STREAM_MEM (camel_stream), buffer); camel_data_wrapper_decode_to_stream_sync ( CAMEL_DATA_WRAPPER (message), camel_stream, NULL, NULL); g_object_unref (camel_stream); g_object_unref (message); /* Load the buffer into a GMemoryInputStream. */ input_stream = g_memory_input_stream_new (); if (buffer->len > 0) g_memory_input_stream_add_data ( G_MEMORY_INPUT_STREAM (input_stream), buffer->data, (gssize) buffer->len, (GDestroyNotify) g_free); g_byte_array_free (buffer, FALSE); /* Splice the input and output streams. */ g_output_stream_splice_async ( context->output_stream, input_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, G_PRIORITY_DEFAULT, context->cancellable, (GAsyncReadyCallback) save_snapshot_splice_cb, simple); g_object_unref (input_stream); }
/** * camel_stream_mem_set_buffer: * @mem: a #CamelStreamMem object * @buffer: a memory buffer * @len: length of @buffer * * Set @buffer to be the backing data to the existing #CamelStreamMem, @mem. * * Note: @buffer will be copied into an internal #GByteArray structure * and so may have resource implications to consider. **/ void camel_stream_mem_set_buffer (CamelStreamMem *mem, const char *buffer, size_t len) { GByteArray *ba; ba = g_byte_array_new (); g_byte_array_append(ba, (const guint8 *)buffer, len); camel_stream_mem_set_byte_array(mem, ba); mem->owner = TRUE; }
void test_message_set_content_simple (CamelMimePart *part, gint how, const gchar *type, const gchar *text, gint len) { CamelStreamMem *content = NULL; CamelDataWrapper *dw; static GByteArray *ba; switch (how) { case 0: camel_mime_part_set_content (part, text, len, type); break; case 1: content = (CamelStreamMem *) camel_stream_mem_new_with_buffer (text, len); break; case 2: content = (CamelStreamMem *) camel_stream_mem_new (); camel_stream_mem_set_buffer (content, text, len); break; case 3: ba = g_byte_array_new (); g_byte_array_append (ba, (guint8 *) text, len); content = (CamelStreamMem *) camel_stream_mem_new_with_byte_array (ba); ba = NULL; break; case 4: ba = g_byte_array_new (); g_byte_array_append (ba, (guint8 *) text, len); content = (CamelStreamMem *) camel_stream_mem_new (); camel_stream_mem_set_byte_array (content, ba); g_object_weak_ref ( G_OBJECT (content), (GWeakNotify) content_weak_notify, ba); break; } if (content != 0) { dw = camel_data_wrapper_new (); camel_data_wrapper_set_mime_type (dw, type); camel_data_wrapper_construct_from_stream_sync ( dw, (CamelStream *) content, NULL, NULL); camel_medium_set_content ((CamelMedium *) part, dw); check_unref (content, 2); check_unref (dw, 2); } }
static gboolean data_wrapper_construct_from_stream_sync (CamelDataWrapper *data_wrapper, CamelStream *stream, GCancellable *cancellable, GError **error) { CamelStream *memory_stream; gssize bytes_written; camel_data_wrapper_lock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); /* Check for cancellation after locking. */ if (g_cancellable_set_error_if_cancelled (cancellable, error)) { camel_data_wrapper_unlock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return FALSE; } if (G_IS_SEEKABLE (stream)) { if (!g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, cancellable, error)) { camel_data_wrapper_unlock (data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return FALSE; } } /* Wipe any previous contents from our byte array. */ g_byte_array_set_size (data_wrapper->priv->byte_array, 0); memory_stream = camel_stream_mem_new (); /* We retain ownership of the byte array. */ camel_stream_mem_set_byte_array ( CAMEL_STREAM_MEM (memory_stream), data_wrapper->priv->byte_array); /* Transfer incoming contents to our byte array. */ bytes_written = camel_stream_write_to_stream ( stream, memory_stream, cancellable, error); g_object_unref (memory_stream); camel_data_wrapper_unlock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return (bytes_written >= 0); }
static gssize data_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper, CamelStream *stream, GCancellable *cancellable, GError **error) { CamelStream *memory_stream; gssize ret; camel_data_wrapper_lock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); /* Check for cancellation after locking. */ if (g_cancellable_set_error_if_cancelled (cancellable, error)) { camel_data_wrapper_unlock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return -1; } memory_stream = camel_stream_mem_new (); /* We retain ownership of the byte array. */ camel_stream_mem_set_byte_array ( CAMEL_STREAM_MEM (memory_stream), data_wrapper->priv->byte_array); ret = camel_stream_write_to_stream ( memory_stream, stream, cancellable, error); g_object_unref (memory_stream); camel_data_wrapper_unlock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return ret; }
static int pipe_to_sa_full (CamelMimeMessage *msg, const char *in, char **argv, int rv_err, int wait_for_termination, GByteArray *output_buffer, GError **error) { int result, status, errnosav, fds[2], out_fds[2]; CamelStream *stream; char *program; pid_t pid; if (camel_debug_start ("junk")) { int i; printf ("pipe_to_sa "); for (i = 0; argv[i]; i++) printf ("%s ", argv[i]); printf ("\n"); camel_debug_end (); } program = g_find_program_in_path (argv [0]); if (program == NULL) { d(printf ("program not found, returning %d\n", rv_err)); g_set_error (error, EM_JUNK_ERROR, rv_err, _("SpamAssassin not found, code: %d"), rv_err); return rv_err; } g_free (program); if (pipe (fds) == -1) { errnosav = errno; d(printf ("failed to create a pipe (for use with spamassassin: %s\n", strerror (errno))); g_set_error (error, EM_JUNK_ERROR, errnosav, _("Failed to create pipe: %s"), strerror (errnosav)); errno = errnosav; return rv_err; } if (output_buffer && pipe (out_fds) == -1) { errnosav = errno; d(printf ("failed to create a pipe (for use with spamassassin: %s\n", strerror (errno))); g_set_error (error, EM_JUNK_ERROR, errnosav, _("Failed to create pipe: %s"), strerror (errnosav)); close (fds [0]); close (fds [1]); errno = errnosav; return rv_err; } if (!(pid = fork ())) { /* child process */ int maxfd, fd, nullfd; nullfd = open ("/dev/null", O_WRONLY); if (dup2 (fds[0], STDIN_FILENO) == -1 || dup2 (nullfd, STDERR_FILENO) == -1 || (output_buffer == NULL && dup2 (nullfd, STDOUT_FILENO) == -1) || (output_buffer != NULL && dup2 (out_fds[1], STDOUT_FILENO) == -1)) _exit (rv_err & 0377); close (fds [0]); if (output_buffer) close (out_fds [1]); setsid (); maxfd = sysconf (_SC_OPEN_MAX); for (fd = 3; fd < maxfd; fd++) fcntl (fd, F_SETFD, FD_CLOEXEC); execvp (argv[0], argv); _exit (rv_err & 0377); } else if (pid < 0) { errnosav = errno; close (fds[0]); close (fds[1]); if (output_buffer) { close (out_fds [0]); close (out_fds [1]); } if (errnosav != 0 && errnosav != -1) g_set_error (error, EM_JUNK_ERROR, errnosav, _("Error after fork: %s"), strerror (errnosav)); errno = errnosav; return rv_err; } /* parent process */ close (fds[0]); if (output_buffer) close (out_fds [1]); if (msg) { stream = camel_stream_fs_new_with_fd (fds[1]); camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (msg), stream); camel_stream_flush (stream); camel_stream_close (stream); camel_object_unref (stream); } else if (in) { camel_write (fds[1], in, strlen (in)); close (fds[1]); } if (output_buffer) { CamelStreamMem *memstream; stream = camel_stream_fs_new_with_fd (out_fds[0]); memstream = (CamelStreamMem *) camel_stream_mem_new (); camel_stream_mem_set_byte_array (memstream, output_buffer); camel_stream_write_to_stream (stream, (CamelStream *) memstream); camel_object_unref (stream); g_byte_array_append (output_buffer, (unsigned char *)"", 1); d(printf ("child process output: %s len: %d\n", output_buffer->data, output_buffer->len)); } if (wait_for_termination) { int res; d(printf ("wait for child %d termination\n", pid)); result = waitpid (pid, &status, 0); d(printf ("child %d terminated with result %d status %d exited %d exitstatus %d\n", pid, result, status, WIFEXITED (status), WEXITSTATUS (status))); if (result == -1 && errno == EINTR) { /* child process is hanging... */ kill (pid, SIGTERM); sleep (1); result = waitpid (pid, &status, WNOHANG); if (result == 0) { /* ...still hanging, set phasers to KILL */ kill (pid, SIGKILL); sleep (1); result = waitpid (pid, &status, WNOHANG); g_set_error (error, EM_JUNK_ERROR, -2, _("SpamAssassin child process does not respond, killing...")); } else g_set_error (error, EM_JUNK_ERROR, -3, _("Wait for Spamassassin child process interrupted, terminating...")); } if (result != -1 && WIFEXITED (status)) res = WEXITSTATUS (status); else res = rv_err; if (res != 0) g_set_error (error, EM_JUNK_ERROR, res, _("Pipe to SpamAssassin failed, error code: %d"), res); return res; } else return 0; }
static void attachment_button_expand_drag_data_get_cb (EAttachmentButton *button, GdkDragContext *context, GtkSelectionData *selection, guint info, guint time) { EAttachmentView *view; EAttachment *attachment; gchar *mime_type = NULL; attachment = e_attachment_button_get_attachment (button); if (attachment != NULL) mime_type = e_attachment_dup_mime_type (attachment); if (mime_type != NULL) { gboolean processed = FALSE; GdkAtom atom; gchar *atom_name; atom = gtk_selection_data_get_target (selection); atom_name = gdk_atom_name (atom); if (g_strcmp0 (atom_name, mime_type) == 0) { CamelMimePart *mime_part; mime_part = e_attachment_ref_mime_part (attachment); if (mime_part != NULL) { CamelDataWrapper *wrapper; CamelStream *stream; GByteArray *buffer; buffer = g_byte_array_new (); stream = camel_stream_mem_new (); camel_stream_mem_set_byte_array ( CAMEL_STREAM_MEM (stream), buffer); wrapper = camel_medium_get_content ( CAMEL_MEDIUM (mime_part)); camel_data_wrapper_decode_to_stream_sync ( wrapper, stream, NULL, NULL); g_object_unref (stream); gtk_selection_data_set ( selection, atom, 8, buffer->data, buffer->len); processed = TRUE; g_byte_array_free (buffer, TRUE); g_object_unref (mime_part); } } g_free (atom_name); g_free (mime_type); if (processed) return; } view = e_attachment_button_get_view (button); e_attachment_view_drag_data_get ( view, context, selection, info, time); }
static CamelMimePart * multipart_signed_get_part (CamelMultipart *multipart, guint index) { CamelMultipartSigned *mps = (CamelMultipartSigned *) multipart; CamelDataWrapper *data_wrapper; CamelStream *stream; GByteArray *byte_array; data_wrapper = CAMEL_DATA_WRAPPER (multipart); byte_array = camel_data_wrapper_get_byte_array (data_wrapper); switch (index) { case CAMEL_MULTIPART_SIGNED_CONTENT: if (mps->content) return mps->content; if (mps->contentraw) { g_return_val_if_fail ( G_IS_SEEKABLE (mps->contentraw), NULL); stream = g_object_ref (mps->contentraw); } else if (mps->start1 == -1 && multipart_signed_parse_content (mps) == -1 && byte_array->len == 0) { g_warning ("Trying to get content on an invalid multipart/signed"); return NULL; } else if (byte_array->len == 0) { return NULL; } else if (mps->start1 == -1) { stream = camel_stream_mem_new (); camel_stream_mem_set_byte_array ( CAMEL_STREAM_MEM (stream), byte_array); } else { stream = multipart_signed_clip_stream ( mps, mps->start1, mps->end1); } g_seekable_seek ( G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL); mps->content = camel_mime_part_new (); camel_data_wrapper_construct_from_stream_sync ( CAMEL_DATA_WRAPPER (mps->content), stream, NULL, NULL); g_object_unref (stream); return mps->content; case CAMEL_MULTIPART_SIGNED_SIGNATURE: if (mps->signature) return mps->signature; if (mps->start1 == -1 && multipart_signed_parse_content (mps) == -1) { g_warning ("Trying to get signature on invalid multipart/signed"); return NULL; } else if (byte_array->len == 0) { return NULL; } stream = multipart_signed_clip_stream ( mps, mps->start2, mps->end2); g_seekable_seek ( G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL); mps->signature = camel_mime_part_new (); camel_data_wrapper_construct_from_stream_sync ( CAMEL_DATA_WRAPPER (mps->signature), stream, NULL, NULL); g_object_unref (stream); return mps->signature; default: g_warning ("trying to get object out of bounds for multipart"); } return NULL; }
static gint multipart_signed_parse_content (CamelMultipartSigned *mps) { CamelMimeParser *cmp; CamelMultipart *mp = (CamelMultipart *) mps; CamelDataWrapper *data_wrapper; GByteArray *byte_array; CamelStream *stream; const gchar *boundary; gchar *buf; gsize len; gint state; boundary = camel_multipart_get_boundary (mp); g_return_val_if_fail (boundary != NULL, -1); data_wrapper = CAMEL_DATA_WRAPPER (mps); byte_array = camel_data_wrapper_get_byte_array (data_wrapper); stream = camel_stream_mem_new (); /* Do not give the stream ownership of the byte array. */ camel_stream_mem_set_byte_array ( CAMEL_STREAM_MEM (stream), byte_array); /* This is all seriously complex. * This is so we can parse all cases properly, without altering the content. * All we are doing is finding part offsets. */ cmp = camel_mime_parser_new (); camel_mime_parser_init_with_stream (cmp, stream, NULL); camel_mime_parser_push_state (cmp, CAMEL_MIME_PARSER_STATE_MULTIPART, boundary); mps->start1 = -1; mps->end1 = -1; mps->start2 = -1; mps->end2 = -1; while ((state = camel_mime_parser_step (cmp, &buf, &len)) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) { if (mps->start1 == -1) { mps->start1 = camel_mime_parser_tell_start_headers (cmp); } else if (mps->start2 == -1) { mps->start2 = camel_mime_parser_tell_start_headers (cmp); mps->end1 = camel_mime_parser_tell_start_boundary (cmp); if (mps->end1 > mps->start1 && byte_array->data[mps->end1 - 1] == '\n') mps->end1--; if (mps->end1 > mps->start1 && byte_array->data[mps->end1 - 1] == '\r') mps->end1--; } else { g_warning ("multipart/signed has more than 2 parts, remaining parts ignored"); state = CAMEL_MIME_PARSER_STATE_MULTIPART_END; break; } if (multipart_signed_skip_content (cmp) == -1) break; } if (state == CAMEL_MIME_PARSER_STATE_MULTIPART_END) { mps->end2 = camel_mime_parser_tell_start_boundary (cmp); camel_multipart_set_preface (mp, camel_mime_parser_preface (cmp)); camel_multipart_set_postface (mp, camel_mime_parser_postface (cmp)); } g_object_unref (cmp); g_object_unref (stream); if (mps->end2 == -1 || mps->start2 == -1) { if (mps->end1 == -1) mps->start1 = -1; return -1; } return 0; }