static ssize_t mime_part_write_to_stream (GMimeObject *object, GMimeStream *stream) { GMimePart *mime_part = (GMimePart *) object; ssize_t nwritten, total = 0; /* write the content headers */ if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1) return -1; total += nwritten; /* terminate the headers */ if (g_mime_stream_write (stream, "\n", 1) == -1) return -1; total++; if ((nwritten = write_content (mime_part, stream)) == -1) return -1; total += nwritten; return total; }
/** * g_mime_stream_writev: * @stream: a #GMimeStream * @vector: a #GMimeStreamIOVector * @count: number of vector elements * * Writes at most @count blocks described by @vector to @stream. * * Returns: the number of bytes written or %-1 on fail. **/ ssize_t g_mime_stream_writev (GMimeStream *stream, GMimeStreamIOVector *vector, size_t count) { ssize_t total = 0; size_t i; g_return_val_if_fail (GMIME_IS_STREAM (stream), -1); for (i = 0; i < count; i++) { char *buffer = vector[i].data; size_t nwritten = 0; ssize_t n; while (nwritten < vector[i].len) { if ((n = g_mime_stream_write (stream, buffer + nwritten, vector[i].len - nwritten)) < 0) return -1; nwritten += n; } total += nwritten; } return total; }
/** * g_mime_stream_write_to_stream: * @src: source stream * @dest: destination stream * * Attempts to write the source stream to the destination stream. * * Returns: the number of bytes written or %-1 on fail. **/ ssize_t g_mime_stream_write_to_stream (GMimeStream *src, GMimeStream *dest) { ssize_t nread, nwritten, total = 0; char buf[4096]; g_return_val_if_fail (GMIME_IS_STREAM (src), -1); g_return_val_if_fail (GMIME_IS_STREAM (dest), -1); while (!g_mime_stream_eos (src)) { if ((nread = g_mime_stream_read (src, buf, sizeof (buf))) < 0) return -1; if (nread > 0) { nwritten = 0; while (nwritten < nread) { ssize_t len; if ((len = g_mime_stream_write (dest, buf + nwritten, nread - nwritten)) < 0) return -1; nwritten += len; } total += nwritten; } } return total; }
static ssize_t write_content_type (GMimeStream *stream, const char *name, const char *value) { GMimeContentType *content_type; ssize_t nwritten; GString *out; char *val; out = g_string_new (""); g_string_printf (out, "%s: ", name); content_type = g_mime_content_type_new_from_string (value); val = g_mime_content_type_to_string (content_type); g_string_append (out, val); g_free (val); g_mime_param_write_to_string (content_type->params, TRUE, out); g_object_unref (content_type); nwritten = g_mime_stream_write (stream, out->str, out->len); g_string_free (out, TRUE); return nwritten; }
static void test_html (const char *datadir, const char *input, const char *output, guint32 citation) { guint32 flags = GMIME_FILTER_HTML_CONVERT_NL | GMIME_FILTER_HTML_CONVERT_SPACES | GMIME_FILTER_HTML_CONVERT_URLS | GMIME_FILTER_HTML_CONVERT_ADDRESSES; const char *what = "GMimeFilterHtml", *mode; GByteArray *expected, *actual; GMimeStream *stream; GMimeFilter *filter; char *path; switch (citation) { case GMIME_FILTER_HTML_BLOCKQUOTE_CITATION: mode = "blockquote"; break; case GMIME_FILTER_HTML_MARK_CITATION: mode = "mark"; break; case GMIME_FILTER_HTML_CITE: mode = "cite"; break; default: mode = "none"; break; } testsuite_check ("%s (%s %s)", what, input, mode); actual = g_byte_array_new (); stream = g_mime_stream_mem_new_with_byte_array (actual); g_mime_stream_mem_set_owner ((GMimeStreamMem *) stream, FALSE); filter = g_mime_filter_html_new (flags | citation, 0x008888); path = g_build_filename (datadir, input, NULL); pump_data_through_filter (filter, path, stream, TRUE, TRUE); g_mime_filter_reset (filter); g_object_unref (stream); g_object_unref (filter); g_free (path); path = g_build_filename (datadir, output, NULL); expected = read_all_bytes (path, TRUE); g_free (path); if (actual->len != expected->len) { testsuite_check_failed ("%s failed: stream lengths do not match: expected=%u; actual=%u", what, expected->len, actual->len); stream = g_mime_stream_fs_open (output, O_WRONLY | O_CREAT, 0644, NULL); g_mime_stream_write (stream, (const char *) actual->data, actual->len); g_mime_stream_flush (stream); g_object_unref (stream); goto error; } if (memcmp (actual->data, expected->data, actual->len) != 0) { testsuite_check_failed ("%s failed: stream contents do not match", what); goto error; } testsuite_check_passed (); error: g_byte_array_free (expected, TRUE); g_byte_array_free (actual, TRUE); }
static void print_depth (GMimeStream *stream, int depth) { int i; for (i = 0; i < depth; i++) g_mime_stream_write (stream, INDENT, strlen (INDENT)); }
/** * g_mime_stream_write_string: * @stream: a #GMimeStream * @str: string to write * * Writes @string to @stream. * * Returns: the number of bytes written or %-1 on fail. **/ ssize_t g_mime_stream_write_string (GMimeStream *stream, const char *str) { g_return_val_if_fail (GMIME_IS_STREAM (stream), -1); g_return_val_if_fail (str != NULL, -1); return g_mime_stream_write (stream, str, strlen (str)); }
static void test_gzip (const char *datadir, const char *filename) { char *name = g_strdup_printf ("%s.gz", filename); char *path = g_build_filename (datadir, filename, NULL); const char *what = "GMimeFilterGzip::zip"; GByteArray *actual, *expected; GMimeStream *stream; GMimeFilter *filter; testsuite_check ("%s", what); actual = g_byte_array_new (); stream = g_mime_stream_mem_new_with_byte_array (actual); g_mime_stream_mem_set_owner ((GMimeStreamMem *) stream, FALSE); filter = g_mime_filter_gzip_new (GMIME_FILTER_GZIP_MODE_ZIP, 9); g_mime_filter_gzip_set_filename ((GMimeFilterGZip *) filter, filename); g_mime_filter_gzip_set_comment ((GMimeFilterGZip *) filter, "This is a comment."); pump_data_through_filter (filter, path, stream, TRUE, TRUE); g_mime_filter_reset (filter); g_object_unref (stream); g_object_unref (filter); g_free (path); path = g_build_filename (datadir, name, NULL); expected = read_all_bytes (path, FALSE); g_free (name); g_free (path); if (actual->len != 1233 && (actual->len != expected->len || memcmp (actual->data, expected->data, actual->len) != 0)) { if (actual->len != expected->len) testsuite_check_failed ("%s failed: streams are not the same length: %u", what, actual->len); else testsuite_check_failed ("%s failed: streams do not match", what); name = g_strdup_printf ("%s.1.gz", filename); path = g_build_filename (datadir, name, NULL); g_free (name); stream = g_mime_stream_fs_open (path, O_WRONLY | O_CREAT | O_TRUNC, 0644, NULL); g_free (path); g_mime_stream_write (stream, (const char *) actual->data, actual->len); g_mime_stream_flush (stream); g_object_unref (stream); } else { testsuite_check_passed (); } g_byte_array_free (expected, TRUE); g_byte_array_free (actual, TRUE); }
static GMimeStream * random_whole_stream (const char *datadir, char **filename) { size_t nwritten, buflen, total = 0, size, i; GMimeStream *stream; char buf[4096]; ssize_t n; int fd; /* read between 4k and 14k bytes */ size = 4096 + (size_t) (10240.0 * (rand () / (RAND_MAX + 1.0))); v(fprintf (stdout, "Generating %zu bytes of random data... ", size)); v(fflush (stdout)); g_mkdir_with_parents (datadir, 0755); g_snprintf (buf, sizeof (buf), "%s%cstream.%u", datadir, G_DIR_SEPARATOR, getpid ()); if ((fd = open (buf, O_CREAT | O_TRUNC | O_RDWR, 0666)) == -1) { fprintf (stderr, "Error: Cannot create `%s': %s\n", buf, g_strerror (errno)); exit (EXIT_FAILURE); } *filename = g_strdup (buf); stream = g_mime_stream_fs_new (fd); while (total < size) { buflen = size - total > sizeof (buf) ? sizeof (buf) : size - total; for (i = 0; i < buflen; i++) buf[i] = (char) (255 * (rand () / (RAND_MAX + 1.0))); nwritten = 0; do { if ((n = g_mime_stream_write (stream, buf + nwritten, buflen - nwritten)) <= 0) break; nwritten += n; total += n; } while (nwritten < buflen); if (nwritten < buflen) break; } g_mime_stream_flush (stream); g_mime_stream_reset (stream); v(fputs ("done\n", stdout)); return stream; }
static ssize_t write_disposition (GMimeStream *stream, const char *name, const char *value) { GMimeContentDisposition *disposition; ssize_t nwritten; GString *out; out = g_string_new (""); g_string_printf (out, "%s: ", name); disposition = g_mime_content_disposition_new_from_string (value); g_string_append (out, disposition->disposition); g_mime_param_write_to_string (disposition->params, TRUE, out); g_object_unref (disposition); nwritten = g_mime_stream_write (stream, out->str, out->len); g_string_free (out, TRUE); return nwritten; }
/** * g_mime_stream_printf: * @stream: a #GMimeStream * @fmt: format * @Varargs: arguments * * Write formatted output to a stream. * * Returns: the number of bytes written or %-1 on fail. **/ ssize_t g_mime_stream_printf (GMimeStream *stream, const char *fmt, ...) { va_list args; char *string; ssize_t ret; g_return_val_if_fail (GMIME_IS_STREAM (stream), -1); g_return_val_if_fail (fmt != NULL, -1); va_start (args, fmt); string = g_strdup_vprintf (fmt, args); va_end (args); if (!string) return -1; ret = g_mime_stream_write (stream, string, strlen (string)); g_free (string); return ret; }
static void read_msg (SpruceFolder *folder, GPtrArray *uids, int cursor) { GMimeMessage *message; GMimeStream *stream; GError *err = NULL; if (!(message = spruce_folder_get_message (folder, uids->pdata[cursor], &err))) { fprintf (stderr, "can't get message: %s\n", err ? err->message : "(null)"); g_error_free (err); return; } stream = g_mime_stream_fs_new (dup (fileno (stdout))); g_mime_object_write_to_stream ((GMimeObject *) message, stream); g_mime_stream_write (stream, "\n", 1); g_mime_stream_flush (stream); g_object_unref (message); g_object_unref (stream); mark_msgs (folder, uids, NULL, cursor, SPRUCE_MESSAGE_SEEN, SPRUCE_MESSAGE_SEEN); }
static void lsv_escape_change_state(GSimpleAction * action, GVariant * state, gpointer user_data) { LibBalsaSourceViewerInfo *lsvi = g_object_get_data(G_OBJECT(user_data), "lsvi"); LibBalsaMessage *msg = lsvi->msg; GMimeStream *msg_stream; GMimeStream *mem_stream; char *raw_message; if (!msg->mailbox) { libbalsa_information(LIBBALSA_INFORMATION_WARNING, _("Mailbox closed")); return; } msg_stream = libbalsa_mailbox_get_message_stream(msg->mailbox, msg->msgno, TRUE); if (msg_stream == NULL) return; mem_stream = g_mime_stream_mem_new(); libbalsa_mailbox_lock_store(msg->mailbox); g_mime_stream_write_to_stream(msg_stream, mem_stream); libbalsa_mailbox_unlock_store(msg->mailbox); g_mime_stream_write(mem_stream, "", 1); /* close string */ raw_message = (char *) GMIME_STREAM_MEM(mem_stream)->buffer->data; *(lsvi->escape_specials) = g_variant_get_boolean(state); lsv_show_message(raw_message, lsvi, *(lsvi->escape_specials)); g_object_unref(msg_stream); g_object_unref(mem_stream); g_simple_action_set_state(action, state); }
static size_t gen_random_stream (GMimeStream *stream) { size_t nwritten, buflen, total = 0, size, i; char buf[4096]; ssize_t n; /* read between 4k and 14k bytes */ size = 4096 + (size_t) (10240.0 * (rand () / (RAND_MAX + 1.0))); v(fprintf (stdout, "Generating %" G_GSIZE_FORMAT " bytes of random data... ", size)); v(fflush (stdout)); while (total < size) { buflen = size - total > sizeof (buf) ? sizeof (buf) : size - total; for (i = 0; i < buflen; i++) buf[i] = (char) (255 * (rand () / (RAND_MAX + 1.0))); nwritten = 0; do { if ((n = g_mime_stream_write (stream, buf + nwritten, buflen - nwritten)) <= 0) break; nwritten += n; total += n; } while (nwritten < buflen); if (nwritten < buflen) break; } g_mime_stream_flush (stream); g_mime_stream_reset (stream); v(fputs ("done\n", stdout)); return size; }
static ssize_t message_part_write_to_stream (GMimeObject *object, GMimeFormatOptions *options, gboolean content_only, GMimeStream *stream) { GMimeMessagePart *part = (GMimeMessagePart *) object; GMimeMessage *message = part->message; ssize_t nwritten, total = 0; const char *newline, *eoln; gboolean match; size_t len; newline = g_mime_format_options_get_newline (options); if (!content_only) { /* write the content headers */ if ((nwritten = g_mime_header_list_write_to_stream (object->headers, options, stream)) == -1) return -1; total += nwritten; /* terminate the headers */ if ((nwritten = g_mime_stream_write_string (stream, newline)) == -1) return -1; total += nwritten; } /* write the message */ if (message) { if (message->marker && (len = strlen (message->marker)) > 0) { if (*(eoln = message->marker + (len - 1)) == '\n') { if (eoln > message->marker && eoln[-1] == '\r') eoln--; /* check if newline sequences match... */ if (!(match = !strcmp (eoln, newline))) { /* they don't match... trim off the eoln sequence */ len = (size_t) (eoln - message->marker); } } else { match = FALSE; } if ((nwritten = g_mime_stream_write (stream, message->marker, len)) == -1) return -1; total += nwritten; if (!match) { if ((nwritten = g_mime_stream_write_string (stream, newline)) == -1) return -1; total += nwritten; } } if ((nwritten = g_mime_object_write_to_stream ((GMimeObject *) message, options, stream)) == -1) return -1; total += nwritten; } return total; }
static void test_parser (GMimeParser *parser, GMimeStream *mbox, GMimeStream *summary) { gint64 message_begin, message_end, headers_begin, headers_end; GMimeFormatOptions *format = g_mime_format_options_get_default (); InternetAddressList *list; GMimeMessage *message; char *marker, *buf; const char *subject; GMimeObject *body; GDateTime *date; int nmsg = 0; while (!g_mime_parser_eos (parser)) { message_begin = g_mime_parser_tell (parser); if (!(message = g_mime_parser_construct_message (parser, NULL))) throw (exception_new ("failed to parse message #%d", nmsg)); message_end = g_mime_parser_tell (parser); headers_begin = g_mime_parser_get_headers_begin (parser); headers_end = g_mime_parser_get_headers_end (parser); g_mime_stream_printf (summary, "message offsets: %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT "\n", message_begin, message_end); g_mime_stream_printf (summary, "header offsets: %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT "\n", headers_begin, headers_end); marker = g_mime_parser_get_mbox_marker (parser); g_mime_stream_printf (summary, "%s\n", marker); if ((list = g_mime_message_get_from (message)) != NULL && internet_address_list_length (list) > 0) { buf = internet_address_list_to_string (list, format, FALSE); g_mime_stream_printf (summary, "From: %s\n", buf); g_free (buf); } if ((list = g_mime_message_get_addresses (message, GMIME_ADDRESS_TYPE_TO)) != NULL && internet_address_list_length (list) > 0) { buf = internet_address_list_to_string (list, format, FALSE); g_mime_stream_printf (summary, "To: %s\n", buf); g_free (buf); } if (!(subject = g_mime_message_get_subject (message))) subject = ""; g_mime_stream_printf (summary, "Subject: %s\n", subject); if (!(date = g_mime_message_get_date (message))) { date = g_date_time_new_from_unix_utc (0); } else { g_date_time_ref (date); } buf = g_mime_utils_header_format_date (date); g_mime_stream_printf (summary, "Date: %s\n", buf); g_date_time_unref (date); g_free (buf); body = g_mime_message_get_mime_part (message); print_mime_struct (summary, body, 0); g_mime_stream_write (summary, "\n", 1); if (mbox) { if (nmsg > 0) g_mime_stream_write (mbox, "\n", 1); g_mime_stream_printf (mbox, "%s\n", marker); g_mime_object_write_to_stream ((GMimeObject *) message, format, mbox); } g_object_unref (message); g_free (marker); nmsg++; } }
static ssize_t write_content (GMimePart *part, GMimeStream *stream) { ssize_t nwritten, total = 0; if (!part->content) return 0; /* Evil Genius's "slight" optimization: Since GMimeDataWrapper::write_to_stream() * decodes its content stream to the raw format, we can cheat by requesting its * content stream and not doing any encoding on the data if the source and * destination encodings are identical. */ if (part->encoding != g_mime_data_wrapper_get_encoding (part->content)) { GMimeStream *filtered_stream; const char *filename; GMimeFilter *filter; switch (part->encoding) { case GMIME_CONTENT_ENCODING_UUENCODE: filename = g_mime_part_get_filename (part); nwritten = g_mime_stream_printf (stream, "begin 0644 %s\n", filename ? filename : "unknown"); if (nwritten == -1) return -1; total += nwritten; /* fall thru... */ case GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE: case GMIME_CONTENT_ENCODING_BASE64: filtered_stream = g_mime_stream_filter_new (stream); filter = g_mime_filter_basic_new (part->encoding, TRUE); g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter); g_object_unref (filter); break; default: filtered_stream = stream; g_object_ref (stream); break; } nwritten = g_mime_data_wrapper_write_to_stream (part->content, filtered_stream); g_mime_stream_flush (filtered_stream); g_object_unref (filtered_stream); if (nwritten == -1) return -1; total += nwritten; if (part->encoding == GMIME_CONTENT_ENCODING_UUENCODE) { /* FIXME: get rid of this special-case x-uuencode crap */ nwritten = g_mime_stream_write (stream, "end\n", 4); if (nwritten == -1) return -1; total += nwritten; } } else { GMimeStream *content_stream; content_stream = g_mime_data_wrapper_get_stream (part->content); g_mime_stream_reset (content_stream); nwritten = g_mime_stream_write_to_stream (content_stream, stream); g_mime_stream_reset (content_stream); if (nwritten == -1) return -1; total += nwritten; } return total; }
static ssize_t pkcs7_stream_write (void *stream, const void *buffer, size_t size) { return g_mime_stream_write ((GMimeStream *) stream, (const char *) buffer, size); }
static ssize_t multipart_write_to_stream (GMimeObject *object, GMimeStream *stream) { GMimeMultipart *multipart = (GMimeMultipart *) object; ssize_t nwritten, total = 0; const char *boundary; GMimeObject *part; guint i; /* make sure a boundary is set unless we are writing out a raw * header (in which case it should already be set... or if * not, then it's a broken multipart and so we don't want to * alter it or we'll completely break the output) */ boundary = g_mime_object_get_content_type_parameter (object, "boundary"); if (!boundary && !g_mime_header_list_get_stream (object->headers)) { g_mime_multipart_set_boundary (multipart, NULL); boundary = g_mime_object_get_content_type_parameter (object, "boundary"); } /* write the content headers */ if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1) return -1; total += nwritten; /* write the preface */ if (multipart->preface) { /* terminate the headers */ if (g_mime_stream_write (stream, "\n", 1) == -1) return -1; total++; if ((nwritten = g_mime_stream_write_string (stream, multipart->preface)) == -1) return -1; total += nwritten; } for (i = 0; i < multipart->children->len; i++) { part = multipart->children->pdata[i]; /* write the boundary */ if ((nwritten = g_mime_stream_printf (stream, "\n--%s\n", boundary)) == -1) return -1; total += nwritten; /* write this part out */ if ((nwritten = g_mime_object_write_to_stream (part, stream)) == -1) return -1; total += nwritten; } /* write the end-boundary (but only if a boundary is set) */ if (boundary) { if ((nwritten = g_mime_stream_printf (stream, "\n--%s--\n", boundary)) == -1) return -1; total += nwritten; } /* write the postface */ if (multipart->postface) { if ((nwritten = g_mime_stream_write_string (stream, multipart->postface)) == -1) return -1; total += nwritten; } return total; }
/* * callback to write data to a stream */ static ssize_t g_mime_gpgme_stream_wr(GMimeStream * stream, void *buffer, size_t size) { return g_mime_stream_write(stream, buffer, size); }