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; }
static gssize multipart_signed_write_to_stream_sync (CamelDataWrapper *data_wrapper, CamelStream *stream, GCancellable *cancellable, GError **error) { CamelMultipartSigned *mps = (CamelMultipartSigned *) data_wrapper; CamelMultipart *mp = (CamelMultipart *) mps; GByteArray *byte_array; const gchar *boundary; gssize total = 0; gssize count; gchar *content; byte_array = camel_data_wrapper_get_byte_array (data_wrapper); /* we have 3 basic cases: * 1. constructed, we write out the data wrapper stream we got * 2. signed content, we create and write out a new stream * 3. invalid */ /* 1 */ /* FIXME: locking? */ if (byte_array->len > 0) { return camel_stream_write ( stream, (gchar *) byte_array->data, byte_array->len, cancellable, error); } /* 3 */ if (mps->contentraw == NULL) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("No content available")); return -1; } /* 3 */ if (mps->signature == NULL) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("No signature available")); return -1; } /* 2 */ boundary = camel_multipart_get_boundary (mp); if (mp->preface) { count = camel_stream_write_string ( stream, mp->preface, cancellable, error); if (count == -1) return -1; total += count; } /* first boundary */ content = g_strdup_printf ("\n--%s\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; /* output content part */ /* XXX Both CamelGpgContext and CamelSMIMEContext set this * to a memory stream, so assume it's always seekable. */ g_seekable_seek ( G_SEEKABLE (mps->contentraw), 0, G_SEEK_SET, NULL, NULL); count = camel_stream_write_to_stream ( mps->contentraw, stream, cancellable, error); if (count == -1) return -1; total += count; /* boundary */ content = g_strdup_printf ("\n--%s\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; /* signature */ count = camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (mps->signature), stream, cancellable, error); if (count == -1) return -1; total += count; /* write the terminating boudary delimiter */ content = g_strdup_printf ("\n--%s--\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; /* and finally the postface */ if (mp->postface) { count = camel_stream_write_string ( stream, mp->postface, cancellable, error); if (count == -1) return -1; total += count; } return total; }
/* this is MIME specific, doesn't belong here really */ static gssize multipart_write_to_stream_sync (CamelDataWrapper *data_wrapper, CamelStream *stream, GCancellable *cancellable, GError **error) { CamelMultipart *multipart = CAMEL_MULTIPART (data_wrapper); const gchar *boundary; GList *node; gchar *content; gssize total = 0; gssize count; /* get the bundary text */ boundary = camel_multipart_get_boundary (multipart); /* we cannot write a multipart without a boundary string */ g_return_val_if_fail (boundary, -1); /* * write the preface text (usually something like * "This is a mime message, if you see this, then * your mail client probably doesn't support ...." */ if (multipart->preface) { count = camel_stream_write_string ( stream, multipart->preface, cancellable, error); if (count == -1) return -1; total += count; } /* * Now, write all the parts, separated by the boundary * delimiter */ node = multipart->parts; while (node) { content = g_strdup_printf ("\n--%s\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; count = camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (node->data), stream, cancellable, error); if (count == -1) return -1; total += count; node = node->next; } /* write the terminating boudary delimiter */ content = g_strdup_printf ("\n--%s--\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; /* and finally the postface */ if (multipart->postface) { count = camel_stream_write_string ( stream, multipart->postface, cancellable, error); if (count == -1) return -1; total += count; } return total; }