static void gmime_callback(SIPE_UNUSED_PARAMETER GMimeObject *parent, GMimeObject *part, gpointer user_data) { GMimeDataWrapper *data = g_mime_part_get_content_object((GMimePart *)part); if (data) { GMimeStream *stream = g_mime_data_wrapper_get_stream(data); if (stream) { ssize_t length = g_mime_stream_length(stream); if (length != -1) { gchar *content = g_malloc(length + 1); if (g_mime_stream_read(stream, content, length) == length) { struct gmime_callback_data *cd = user_data; GSList *fields = gmime_fields_to_nameval(part); (*(cd->callback))(cd->user_data, fields, content, length); sipe_utils_nameval_free(fields); } g_free(content); } } } }
static void test_cat_seek (GMimeStream *whole, struct _StreamPart *parts, int bounded) { struct _StreamPart *part = parts; GMimeStream *stream, *cat; gint64 offset, len; Exception *ex; int fd; if (whole->bound_end != -1) { len = whole->bound_end - whole->bound_start; } else if ((len = g_mime_stream_length (whole)) == -1) { ex = exception_new ("unable to get original stream length"); throw (ex); } cat = g_mime_stream_cat_new (); while (part != NULL) { d(fprintf (stderr, "adding %s start=%lld, end=%lld...\n", part->filename, part->pstart, part->pend)); if ((fd = open (part->filename, O_RDONLY, 0)) == -1) { ex = exception_new ("could not open `%s': %s", part->filename, g_strerror (errno)); g_object_unref (cat); throw (ex); } stream = g_mime_stream_fs_new_with_bounds (fd, part->pstart, bounded ? part->pend : -1); g_mime_stream_cat_add_source ((GMimeStreamCat *) cat, stream); g_object_unref (stream); part = part->next; } /* calculate a random seek offset to compare at */ offset = (gint64) (len * (rand () / (RAND_MAX + 1.0))); if (g_mime_stream_seek (whole, offset, GMIME_STREAM_SEEK_SET) == -1) { ex = exception_new ("could not seek to %lld in original stream: %s", offset, g_strerror (errno)); throw (ex); } if (g_mime_stream_seek (cat, offset, GMIME_STREAM_SEEK_SET) == -1) { ex = exception_new ("could not seek to %lld: %s", offset, g_strerror (errno)); throw (ex); } if (check_streams_match (whole, cat, "stream.part*", TRUE) == -1) { ex = exception_new ("streams did not match"); g_object_unref (cat); throw (ex); } }
static void test_stream_mem (const char *filename) { /* Note: this also tests g_mime_stream_write_to_stream */ GMimeStream *stream, *fstream; int fd; if ((fd = open (filename, O_RDONLY, 0)) == -1) { v(fprintf (stderr, "failed to open %s: %s\n", filename, g_strerror (errno))); return; } testsuite_start ("GMimeStreamMem"); fstream = g_mime_stream_fs_new (fd); stream = g_mime_stream_mem_new (); testsuite_check ("GMimeStreamMem::read()"); try { if (g_mime_stream_write_to_stream (fstream, stream) == -1) throw (exception_new ("g_mime_stream_write_to_stream() failed")); if (g_mime_stream_length (stream) != g_mime_stream_length (fstream)) throw (exception_new ("stream lengths didn't match")); test_stream_read (stream, filename); testsuite_check_passed (); } catch (ex) { testsuite_check_failed ("GMimeStreamMem::read() failed: %s", ex->message); } finally; g_object_unref (fstream); g_object_unref (stream); testsuite_end (); }
gint64 mux_message_part_get_size (MuxMessagePart *self) { GMimeStream *mstream; g_return_val_if_fail (MUX_IS_MESSAGE_PART(self), FALSE); if (!GMIME_IS_PART(self->mime_object)) return 0; mstream = get_mime_stream (self->mime_object, NULL); if (!mstream) return -1; return g_mime_stream_length (mstream); }
/* note: this will return -1 in case of error or if the size is * unknown */ static ssize_t get_part_size (GMimePart *part) { GMimeDataWrapper *wrapper; GMimeStream *stream; wrapper = g_mime_part_get_content_object (part); if (!GMIME_IS_DATA_WRAPPER(wrapper)) return -1; stream = g_mime_data_wrapper_get_stream (wrapper); if (!stream) return -1; /* no stream -> size is 0 */ else return g_mime_stream_length (stream); /* NOTE: stream/wrapper are owned by gmime, no unreffing */ }
static void format_omitted_part_meta_sprinter (sprinter_t *sp, GMimeObject *meta, GMimePart *part) { const char *content_charset = g_mime_object_get_content_type_parameter (meta, "charset"); const char *cte = g_mime_object_get_header (meta, "content-transfer-encoding"); GMimeDataWrapper *wrapper = g_mime_part_get_content_object (part); GMimeStream *stream = g_mime_data_wrapper_get_stream (wrapper); ssize_t content_length = g_mime_stream_length (stream); if (content_charset != NULL) { sp->map_key (sp, "content-charset"); sp->string (sp, content_charset); } if (cte != NULL) { sp->map_key (sp, "content-transfer-encoding"); sp->string (sp, cte); } if (content_length >= 0) { sp->map_key (sp, "content-length"); sp->integer (sp, content_length); } }
static gboolean streams_match (GMimeStream **streams, const char *filename) { char buf[4096], dbuf[4096], errstr[1024]; gint64 len, totalsize, totalread = 0; size_t nread, size; ssize_t n; v(fprintf (stdout, "Matching original stream (%" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT ") with %s (%" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ")... ", streams[0]->position, streams[0]->bound_end, filename, streams[1]->position, streams[1]->bound_end)); if (streams[0]->bound_end != -1) { totalsize = streams[0]->bound_end - streams[0]->position; } else if ((len = g_mime_stream_length (streams[0])) == -1) { sprintf (errstr, "Error: Unable to get length of original stream: %s\n", g_strerror (errno)); goto fail; } else if (len < (streams[0]->position - streams[0]->bound_start)) { sprintf (errstr, "Error: Overflow on original stream?\n"); goto fail; } else { totalsize = len - (streams[0]->position - streams[0]->bound_start); } while (totalread < totalsize) { if ((n = g_mime_stream_read (streams[0], buf, sizeof (buf))) <= 0) break; size = n; nread = 0; totalread += n; d(fprintf (stderr, "read %" G_GSIZE_FORMAT " bytes from stream[0]\n", size)); do { if ((n = g_mime_stream_read (streams[1], dbuf + nread, size - nread)) <= 0) { d(fprintf (stderr, "stream[1] read() returned %" G_GSSIZE_FORMAT ", EOF\n", n)); break; } d(fprintf (stderr, "read %" G_GSSIZE_FORMAT " bytes from stream[1]\n", n)); nread += n; } while (nread < size); if (nread < size) { sprintf (errstr, "Error: `%s' appears to be truncated, short %" G_GSIZE_FORMAT "+ bytes\n", filename, size - nread); goto fail; } if (memcmp (buf, dbuf, size) != 0) { sprintf (errstr, "Error: `%s': content does not match\n", filename); goto fail; } else { d(fprintf (stderr, "%" G_GSIZE_FORMAT " bytes identical\n", size)); } } if (totalread < totalsize) { sprintf (errstr, "Error: expected more data from stream[0]\n"); goto fail; } if ((n = g_mime_stream_read (streams[1], buf, sizeof (buf))) > 0) { sprintf (errstr, "Error: `%s' appears to contain extra content\n", filename); goto fail; } v(fputs ("passed\n", stdout)); return TRUE; fail: v(fputs ("failed\n", stdout)); v(fputs (errstr, stderr)); return FALSE; }
int main (int argc, char **argv) { const char *datadir = "data/cat"; struct _StreamPart *list, *tail, *n; gboolean failed = FALSE; gint64 wholelen, left; GMimeStream *whole; guint32 part = 0; gint64 start = 0; char *filename; struct stat st; gint64 len; int fd, i; srand (time (NULL)); g_mime_init (0); testsuite_init (argc, argv); for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { datadir = argv[i]; break; } } if (i < argc) { if (stat (datadir, &st) == -1) { if (errno == ENOENT) { g_mkdir_with_parents (datadir, 0755); if (stat (datadir, &st) == -1) return EXIT_FAILURE; } else return EXIT_FAILURE; } if (S_ISREG (st.st_mode)) { /* test a particular input file */ if ((fd = open (argv[i], O_RDONLY, 0)) == -1) return EXIT_FAILURE; filename = g_strdup (argv[i]); whole = g_mime_stream_fs_new (fd); } else if (S_ISDIR (st.st_mode)) { /* use path as test suite data dir */ whole = random_whole_stream (argv[i], &filename); } else { return EXIT_FAILURE; } } else { whole = random_whole_stream (datadir, &filename); } if ((wholelen = g_mime_stream_length (whole)) == -1) { fprintf (stderr, "Error: length of test stream unknown\n"); g_object_unref (whole); return EXIT_FAILURE; } else if (wholelen == 64) { fprintf (stderr, "Error: length of test stream is unsuitable for testing\n"); g_object_unref (whole); return EXIT_FAILURE; } list = NULL; tail = (struct _StreamPart *) &list; left = wholelen; while (left > 0) { len = 1 + (gint64) (left * (rand () / (RAND_MAX + 1.0))); n = g_new (struct _StreamPart, 1); sprintf (n->filename, "%s.%u", filename, part++); n->pstart = (gint64) 0; /* FIXME: we could make this a random offset */ n->pend = n->pstart + len; n->wend = start + len; n->wstart = start; tail->next = n; tail = n; start += len; left -= len; } tail->next = NULL; testsuite_start ("GMimeStreamCat"); for (i = 0; i < G_N_ELEMENTS (checks) && !failed; i++) { testsuite_check (checks[i].what); try { checks[i].check (whole, list, checks[i].bounded); testsuite_check_passed (); } catch (ex) { testsuite_check_failed ("%s failed: %s", checks[i].what, ex->message); failed = TRUE; } finally; } testsuite_end (); while (list != NULL) { n = list->next; if (!failed) unlink (list->filename); g_free (list); list = n; } g_object_unref (whole); if (!failed) unlink (filename); g_free (filename); g_mime_shutdown (); return testsuite_exit (); }
static void test_cat_substream (GMimeStream *whole, struct _StreamPart *parts, int bounded) { GMimeStream *stream, *cat, *sub1, *sub2; struct _StreamPart *part = parts; gint64 start, end, len; Exception *ex; int fd; if (whole->bound_end != -1) { len = whole->bound_end - whole->bound_start; } else if ((len = g_mime_stream_length (whole)) == -1) { ex = exception_new ("unable to get original stream length"); throw (ex); } cat = g_mime_stream_cat_new (); while (part != NULL) { d(fprintf (stderr, "adding %s start=%lld, end=%lld...\n", part->filename, part->pstart, part->pend)); if ((fd = open (part->filename, O_RDONLY, 0)) == -1) { ex = exception_new ("could not open `%s': %s", part->filename, g_strerror (errno)); g_object_unref (cat); throw (ex); } stream = g_mime_stream_fs_new_with_bounds (fd, part->pstart, bounded ? part->pend : -1); g_mime_stream_cat_add_source ((GMimeStreamCat *) cat, stream); g_object_unref (stream); part = part->next; } /* calculate a random start/end offsets */ start = (gint64) (len * (rand () / (RAND_MAX + 1.0))); if (rand () % 2) end = start + (gint64) ((len - start) * (rand () / (RAND_MAX + 1.0))); else end = -1; if (!(sub1 = g_mime_stream_substream (whole, start, end))) { ex = exception_new ("could not substream the original stream: %s", g_strerror (errno)); g_object_unref (cat); throw (ex); } if (!(sub2 = g_mime_stream_substream (cat, start, end))) { ex = exception_new ("%s", g_strerror (errno)); g_object_unref (sub1); g_object_unref (cat); throw (ex); } g_object_unref (cat); if (check_streams_match (sub1, sub2, "stream.part*", TRUE) == -1) { ex = exception_new ("streams did not match"); g_object_unref (sub1); g_object_unref (sub2); throw (ex); } g_object_unref (sub1); g_object_unref (sub2); }
static int check_streams_match (GMimeStream *orig, GMimeStream *dup, const char *filename, int check_overflow) { char buf[4096], dbuf[4096], errstr[1024]; gint64 len, totalsize, totalread = 0; size_t nread, size; ssize_t n; v(fprintf (stdout, "Matching original stream (%" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT ") with %s (%" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ")... ", orig->position, orig->bound_end, filename, dup->position, dup->bound_end)); if (orig->bound_end != -1) { totalsize = orig->bound_end - orig->position; } else if ((len = g_mime_stream_length (orig)) == -1) { sprintf (errstr, "Error: Unable to get length of original stream\n"); goto fail; } else if (len < (orig->position - orig->bound_start)) { sprintf (errstr, "Error: Overflow on original stream?\n"); goto fail; } else { totalsize = len - (orig->position - orig->bound_start); } while (totalread < totalsize) { if ((n = g_mime_stream_read (orig, buf, sizeof (buf))) <= 0) break; size = n; nread = 0; totalread += n; d(fprintf (stderr, "read %zu bytes from original stream\n", size)); do { if ((n = g_mime_stream_read (dup, dbuf + nread, size - nread)) <= 0) { d(fprintf (stderr, "dup read() returned %zd, EOF\n", n)); break; } d(fprintf (stderr, "read %zd bytes from dup stream\n", n)); nread += n; } while (nread < size); if (nread < size) { sprintf (errstr, "Error: `%s' appears to be truncated, short %zu+ bytes\n", filename, size - nread); goto fail; } if (memcmp (buf, dbuf, size) != 0) { sprintf (errstr, "Error: `%s': content does not match\n", filename); goto fail; } else { d(fprintf (stderr, "%zu bytes identical\n", size)); } } if (totalread < totalsize) { sprintf (errstr, "Error: expected more data from original stream\n"); goto fail; } if (check_overflow && (n = g_mime_stream_read (dup, buf, sizeof (buf))) > 0) { sprintf (errstr, "Error: `%s' appears to contain extra content\n", filename); goto fail; } v(fputs ("passed\n", stdout)); return 0; fail: v(fputs ("failed\n", stdout)); v(fputs (errstr, stderr)); return -1; }
static gboolean streams_match (GMimeStream *istream, GMimeStream *ostream) { char buf[4096], dbuf[4096], errstr[1024], *bufptr, *bufend, *dbufptr; gint64 len, totalsize, totalread = 0; size_t nread, size; gint64 offset = 0; ssize_t n; v(fprintf (stdout, "Checking if streams match... ")); if (istream->bound_end != -1) { totalsize = istream->bound_end - istream->position; } else if ((len = g_mime_stream_length (istream)) == -1) { sprintf (errstr, "Error: Unable to get length of original stream\n"); goto fail; } else if (len < (istream->position - istream->bound_start)) { sprintf (errstr, "Error: Overflow on original stream?\n"); goto fail; } else { totalsize = len - (istream->position - istream->bound_start); } while (totalread < totalsize) { if ((n = g_mime_stream_read (istream, buf, sizeof (buf))) <= 0) break; size = n; nread = 0; totalread += n; d(fprintf (stderr, "read %zu bytes from istream\n", size)); do { if ((n = g_mime_stream_read (ostream, dbuf + nread, size - nread)) <= 0) { fprintf (stderr, "ostream's read(%p, dbuf + %zu, %zu) returned %zd, EOF\n", ostream, nread, size - nread, n); break; } d(fprintf (stderr, "read %zd bytes from ostream\n", n)); nread += n; } while (nread < size); if (nread < size) { sprintf (errstr, "Error: ostream appears to be truncated, short %zu+ bytes\n", size - nread); goto fail; } bufend = buf + size; dbufptr = dbuf; bufptr = buf; while (bufptr < bufend) { if (*bufptr != *dbufptr) break; dbufptr++; bufptr++; } if (bufptr < bufend) { sprintf (errstr, "Error: content does not match at offset %" G_GINT64_FORMAT "\n", offset + (bufptr - buf)); /*fprintf (stderr, "-->'%.*s'<--\nvs\n-->'%.*s'<--\n", bufend - bufptr, bufptr, bufend - bufptr, dbufptr);*/ goto fail; } else { d(fprintf (stderr, "%zu bytes identical\n", size)); } offset += size; } if (totalread < totalsize) { strcpy (errstr, "Error: expected more data from istream\n"); goto fail; } if ((n = g_mime_stream_read (ostream, buf, sizeof (buf))) > 0) { strcpy (errstr, "Error: ostream appears to contain extra content\n"); goto fail; } v(fputs ("passed\n", stdout)); return TRUE; fail: v(fputs ("failed\n", stdout)); v(fputs (errstr, stderr)); return FALSE; }