* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/ .
+ * along with this program. If not, see https://www.gnu.org/licenses/ .
*
* Authors: Carl Worth <cworth@cworth.org>
* Keith Packard <keithp@keithp.com>
GMimeMessage *mime_message;
/* Context provided by the caller. */
- notmuch_crypto_t *crypto;
+ _notmuch_crypto_t *crypto;
} mime_node_context_t;
static int
notmuch_status_t
mime_node_open (const void *ctx, notmuch_message_t *message,
- notmuch_crypto_t *crypto, mime_node_t **root_out)
+ _notmuch_crypto_t *crypto, mime_node_t **root_out)
{
const char *filename = notmuch_message_get_filename (message);
mime_node_context_t *mctx;
}
talloc_set_destructor (mctx, _mime_node_context_free);
+ /* Fast path */
mctx->file = fopen (filename, "r");
if (! mctx->file) {
- fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
- status = NOTMUCH_STATUS_FILE_ERROR;
- goto DONE;
- }
+ /* Slow path - for some reason the first file in the list is
+ * not available anymore. This is clearly a problem in the
+ * database, but we are not going to let this problem be a
+ * show stopper */
+ notmuch_filenames_t *filenames;
+ for (filenames = notmuch_message_get_filenames (message);
+ notmuch_filenames_valid (filenames);
+ notmuch_filenames_move_to_next (filenames))
+ {
+ filename = notmuch_filenames_get (filenames);
+ mctx->file = fopen (filename, "r");
+ if (mctx->file)
+ break;
+ }
+
+ talloc_free (filenames);
+ if (! mctx->file) {
+ /* Give up */
+ fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
+ status = NOTMUCH_STATUS_FILE_ERROR;
+ goto DONE;
+ }
+ }
mctx->stream = g_mime_stream_file_new (mctx->file);
if (!mctx->stream) {
status = NOTMUCH_STATUS_OUT_OF_MEMORY;
goto DONE;
}
- g_mime_stream_file_set_owner (GMIME_STREAM_FILE (mctx->stream), FALSE);
+ g_mime_stream_file_set_owner (GMIME_STREAM_FILE (mctx->stream), false);
mctx->parser = g_mime_parser_new_with_stream (mctx->stream);
if (!mctx->parser) {
return status;
}
-#ifdef GMIME_ATLEAST_26
-
/* Signature list destructor (GMime 2.6) */
static int
_signature_list_free (GMimeSignatureList **proxy)
/* Verify a signed mime node (GMime 2.6) */
static void
node_verify (mime_node_t *node, GMimeObject *part,
- notmuch_crypto_context_t *cryptoctx)
+ g_mime_3_unused(GMimeCryptoContext *cryptoctx))
{
GError *err = NULL;
- node->verify_attempted = TRUE;
+ node->verify_attempted = true;
node->sig_list = g_mime_multipart_signed_verify
(GMIME_MULTIPART_SIGNED (part), cryptoctx, &err);
/* Decrypt and optionally verify an encrypted mime node (GMime 2.6) */
static void
node_decrypt_and_verify (mime_node_t *node, GMimeObject *part,
- notmuch_crypto_context_t *cryptoctx)
+ g_mime_3_unused(GMimeCryptoContext *cryptoctx))
{
GError *err = NULL;
GMimeDecryptResult *decrypt_result = NULL;
GMimeMultipartEncrypted *encrypteddata = GMIME_MULTIPART_ENCRYPTED (part);
- node->decrypt_attempted = TRUE;
+ node->decrypt_attempted = true;
node->decrypted_child = g_mime_multipart_encrypted_decrypt
+#if (GMIME_MAJOR_VERSION < 3)
(encrypteddata, cryptoctx, &decrypt_result, &err);
+#else
+ (encrypteddata, GMIME_DECRYPT_NONE, NULL, &decrypt_result, &err);
+#endif
if (! node->decrypted_child) {
fprintf (stderr, "Failed to decrypt part: %s\n",
err ? err->message : "no error explanation given");
goto DONE;
}
- node->decrypt_success = TRUE;
- node->verify_attempted = TRUE;
+ node->decrypt_success = true;
+ node->verify_attempted = true;
/* This may be NULL if the part is not signed. */
node->sig_list = g_mime_decrypt_result_get_signatures (decrypt_result);
g_error_free (err);
}
-#else /* GMIME_ATLEAST_26 */
-
-/* Signature validity destructor (GMime 2.4) */
-static int
-_signature_validity_free (GMimeSignatureValidity **proxy)
-{
- g_mime_signature_validity_free (*proxy);
- return 0;
-}
-
-/* Set up signature validity destructor (GMime 2.4) */
-static void
-set_signature_validity_destructor (mime_node_t *node)
-{
- GMimeSignatureValidity **proxy = talloc (node, GMimeSignatureValidity *);
- if (proxy) {
- *proxy = node->sig_validity;
- talloc_set_destructor (proxy, _signature_validity_free);
- }
-}
-
-/* Verify a signed mime node (GMime 2.4) */
-static void
-node_verify (mime_node_t *node, GMimeObject *part,
- notmuch_crypto_context_t *cryptoctx)
-{
- GError *err = NULL;
-
- node->verify_attempted = TRUE;
- node->sig_validity = g_mime_multipart_signed_verify
- (GMIME_MULTIPART_SIGNED (part), cryptoctx, &err);
- if (node->sig_validity) {
- set_signature_validity_destructor (node);
- } else {
- fprintf (stderr, "Failed to verify signed part: %s\n",
- err ? err->message : "no error explanation given");
- }
-
- if (err)
- g_error_free (err);
-}
-
-/* Decrypt and optionally verify an encrypted mime node (GMime 2.4) */
-static void
-node_decrypt_and_verify (mime_node_t *node, GMimeObject *part,
- notmuch_crypto_context_t *cryptoctx)
-{
- GError *err = NULL;
- GMimeMultipartEncrypted *encrypteddata = GMIME_MULTIPART_ENCRYPTED (part);
-
- node->decrypt_attempted = TRUE;
- node->decrypted_child = g_mime_multipart_encrypted_decrypt
- (encrypteddata, cryptoctx, &err);
- if (! node->decrypted_child) {
- fprintf (stderr, "Failed to decrypt part: %s\n",
- err ? err->message : "no error explanation given");
- goto DONE;
- }
-
- node->decrypt_success = TRUE;
- node->verify_attempted = TRUE;
-
- /* The GMimeSignatureValidity returned here is a const, unlike the
- * one returned by g_mime_multipart_signed_verify() in
- * node_verify() above, so the destructor is not needed.
- */
- node->sig_validity = g_mime_multipart_encrypted_get_signature_validity (encrypteddata);
- if (! node->sig_validity)
- fprintf (stderr, "Failed to verify encrypted signed part: %s\n",
- err ? err->message : "no error explanation given");
-
- DONE:
- if (err)
- g_error_free (err);
-}
-
-#endif /* GMIME_ATLEAST_26 */
-
static mime_node_t *
_mime_node_create (mime_node_t *parent, GMimeObject *part)
{
mime_node_t *node = talloc_zero (parent, mime_node_t);
- notmuch_crypto_context_t *cryptoctx = NULL;
+ GMimeCryptoContext *cryptoctx = NULL;
/* Set basic node properties */
node->part = part;
return NULL;
}
+#if (GMIME_MAJOR_VERSION < 3)
if ((GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt)
|| (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify)) {
GMimeContentType *content_type = g_mime_object_get_content_type (part);
const char *protocol = g_mime_content_type_get_parameter (content_type, "protocol");
- cryptoctx = notmuch_crypto_get_context (node->ctx->crypto, protocol);
+ notmuch_status_t status;
+ status = _notmuch_crypto_get_gmime_ctx_for_protocol (node->ctx->crypto,
+ protocol, &cryptoctx);
+ if (status) /* this is a warning, not an error */
+ fprintf (stderr, "Warning: %s (%s).\n", notmuch_status_to_string (status),
+ protocol ? protocol : "NULL");
+ if (!cryptoctx)
+ return node;
}
+#endif
/* Handle PGP/MIME parts */
- if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt && cryptoctx) {
+ if (GMIME_IS_MULTIPART_ENCRYPTED (part) && node->ctx->crypto->decrypt) {
if (node->nchildren != 2) {
/* this violates RFC 3156 section 4, so we won't bother with it. */
fprintf (stderr, "Error: %d part(s) for a multipart/encrypted "
} else {
node_decrypt_and_verify (node, part, cryptoctx);
}
- } else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify && cryptoctx) {
+ } else if (GMIME_IS_MULTIPART_SIGNED (part) && node->ctx->crypto->verify) {
if (node->nchildren != 2) {
/* this violates RFC 3156 section 5, so we won't bother with it. */
fprintf (stderr, "Error: %d part(s) for a multipart/signed message "
static mime_node_t *
_mime_node_seek_dfs_walk (mime_node_t *node, int *n)
{
- mime_node_t *ret = NULL;
int i;
if (*n == 0)
return node;
*n -= 1;
- for (i = 0; i < node->nchildren && !ret; i++) {
+ for (i = 0; i < node->nchildren; i++) {
mime_node_t *child = mime_node_child (node, i);
- ret = _mime_node_seek_dfs_walk (child, n);
- if (!ret)
- talloc_free (child);
+ mime_node_t *ret = _mime_node_seek_dfs_walk (child, n);
+ if (ret)
+ return ret;
+
+ talloc_free (child);
}
- return ret;
+ return NULL;
}
mime_node_t *