int mu_message_save_attachment (mu_message_t msg, const char *filename, mu_mime_io_buffer_t info) { mu_stream_t istream; int ret; mu_header_t hdr; const char *fname = NULL; char *partname = NULL; if (msg == NULL) return EINVAL; if ((ret = _attachment_setup (&info, msg, &istream)) != 0) return ret; if (ret == 0 && (ret = mu_message_get_header (msg, &hdr)) == 0) { if (filename == NULL) { ret = mu_message_aget_decoded_attachment_name (msg, info->charset, &partname, NULL); if (partname) fname = partname; } else fname = filename; if (fname && (ret = mu_file_stream_create (&info->fstream, fname, MU_STREAM_WRITE | MU_STREAM_CREAT)) == 0) { const char *content_encoding; if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING, &content_encoding)) content_encoding = "7bit"; ret = mu_filter_create (&info->stream, istream, content_encoding, MU_FILTER_DECODE, MU_STREAM_READ); } } if (info->stream && istream) ret = mu_stream_copy (info->fstream, info->stream, 0, NULL); if (ret != EAGAIN && info) { mu_stream_close (info->fstream); mu_stream_destroy (&info->stream); mu_stream_destroy (&info->fstream); } mu_stream_destroy (&istream); _attachment_free (info, ret); /* FIXME: or 0? */ /* Free fname if we allocated it. */ if (partname) free (partname); return ret; }
static int chk_ssha (const char *db_pass, const char *pass) { int rc; unsigned char sha1digest[20]; unsigned char *d1; struct mu_sha1_ctx sha1context; mu_stream_t str = NULL, flt = NULL; size_t size; size = strlen (db_pass); mu_static_memory_stream_create (&str, db_pass, size); mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE, MU_STREAM_READ); mu_stream_unref (str); d1 = malloc (size); if (!d1) { mu_stream_destroy (&flt); return ENOMEM; } mu_stream_read (flt, (char*) d1, size, &size); mu_stream_destroy (&flt); if (size <= 16) { mu_error ("malformed SSHA1 password: %s", db_pass); return MU_ERR_FAILURE; } mu_sha1_init_ctx (&sha1context); mu_sha1_process_bytes (pass, strlen (pass), &sha1context); mu_sha1_process_bytes (d1 + 20, size - 20, &sha1context); mu_sha1_finish_ctx (&sha1context, sha1digest); rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 ? 0 : MU_ERR_AUTH_FAILURE; free (d1); return rc; }
static int chk_sha (const char *db_pass, const char *pass) { unsigned char sha1digest[20]; unsigned char d1[20]; mu_stream_t str = NULL, flt = NULL; struct mu_sha1_ctx sha1context; mu_sha1_init_ctx (&sha1context); mu_sha1_process_bytes (pass, strlen (pass), &sha1context); mu_sha1_finish_ctx (&sha1context, sha1digest); mu_static_memory_stream_create (&str, db_pass, strlen (db_pass)); mu_filter_create (&flt, str, "base64", MU_FILTER_DECODE, MU_STREAM_READ); mu_stream_unref (str); mu_stream_read (flt, (char*) d1, sizeof d1, NULL); mu_stream_destroy (&flt); return memcmp (sha1digest, d1, sizeof sha1digest) == 0 ? 0 : MU_ERR_AUTH_FAILURE; }
int mu_smtp_send_stream (mu_smtp_t smtp, mu_stream_t stream) { int status; mu_stream_t input; if (!smtp) return EINVAL; if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR)) return MU_ERR_FAILURE; if (smtp->state != MU_SMTP_MORE) return MU_ERR_SEQ; status = mu_filter_create (&input, stream, "CRLFDOT", MU_FILTER_ENCODE, MU_STREAM_READ); if (status) return status; status = _smtp_data_send (smtp, input); mu_stream_destroy (&input); return status; }
/* Build a mime response message from original message MSG. TEXT is the message text. */ static int build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime, mu_message_t msg, const char *text) { mu_mime_t mime = NULL; mu_message_t newmsg; mu_stream_t stream, input; mu_header_t hdr; mu_body_t body; const char *header = "Content-Type: text/plain;charset=" MU_SIEVE_CHARSET "\n" "Content-Transfer-Encoding: 8bit\n\n"; int rc; mu_mime_create (&mime, NULL, 0); mu_message_create (&newmsg, NULL); mu_message_get_body (newmsg, &body); if ((rc = mu_static_memory_stream_create (&input, text, strlen (text)))) { mu_sieve_error (mach, _("cannot create temporary stream: %s"), mu_strerror (rc)); mu_mime_destroy (&mime); mu_message_destroy (&newmsg, NULL); return 1; } if (mu_sieve_tag_lookup (tags, "mime", NULL)) { mu_stream_t fstr; rc = mu_filter_create (&fstr, input, "base64", MU_FILTER_ENCODE, MU_STREAM_READ); mu_stream_unref (input); if (rc == 0) { header = "Content-Type: text/plain;charset=" MU_SIEVE_CHARSET "\n" "Content-Transfer-Encoding: base64\n\n"; input = fstr; } } rc = mu_body_get_streamref (body, &stream); if (rc) { mu_sieve_error (mach, _("cannot get input body stream: %s"), mu_strerror (rc)); mu_mime_destroy (&mime); mu_message_destroy (&newmsg, NULL); mu_stream_destroy (&input); return 1; } rc = mu_stream_copy (stream, input, 0, NULL); if (rc) { mu_sieve_error (mach, _("stream copy failed: %s"), mu_strerror (rc)); mu_mime_destroy (&mime); mu_message_destroy (&newmsg, NULL); mu_stream_destroy (&input); mu_stream_destroy (&stream); return 1; } mu_stream_destroy (&input); mu_header_create (&hdr, header, strlen (header)); mu_message_set_header (newmsg, hdr, NULL); mu_mime_add_part (mime, newmsg); mu_message_unref (newmsg); *pmime = mime; return 0; }
static int _pop_message_get_stream (struct _pop3_message *mpm, mu_stream_t *pstr) { int status; struct _pop3_mailbox *mpd = mpm->mpd; if (!(mpm->flags & _POP3_MSG_CACHED)) { mu_stream_t stream; mu_off_t size; status = mu_pop3_retr (mpd->pop3, mpm->num, &stream); if (status) return status; do { mu_stream_t flt; if (!mpd->cache) { status = mu_temp_file_stream_create (&mpd->cache, NULL, 0); if (status) /* FIXME: Try to recover first */ break; mu_stream_set_buffer (mpd->cache, mu_buffer_full, 8192); } status = mu_stream_size (mpd->cache, &mpm->offset); if (status) break; status = mu_filter_create (&flt, stream, "CRLF", MU_FILTER_DECODE, MU_STREAM_READ); if (status) break; status = mu_stream_copy (mpd->cache, flt, 0, &size); mu_stream_destroy (&flt); } while (0); if (status) { pop_stream_drain (stream); mu_stream_unref (stream); return status; } mu_stream_unref (stream); mpm->message_size = size; /* FIXME: Possible overflow. */ mpm->flags |= _POP3_MSG_CACHED | _POP3_MSG_SIZE; } return mu_streamref_create_abridged (pstr, mpd->cache, mpm->offset, mpm->offset + mpm->message_size - 1); }
int mu_message_create_attachment (const char *content_type, const char *encoding, const char *filename, mu_message_t *newmsg) { mu_header_t hdr; mu_body_t body; mu_stream_t fstream = NULL, tstream = NULL; char *header = NULL, *name = NULL, *fname = NULL; int ret; if (newmsg == NULL) return MU_ERR_OUT_PTR_NULL; if (filename == NULL) return EINVAL; if ((ret = mu_message_create (newmsg, NULL)) == 0) { if (content_type == NULL) content_type = "text/plain"; if (encoding == NULL) encoding = "7bit"; if ((fname = strdup (filename)) != NULL) { name = strrchr (fname, '/'); if (name) name++; else name = fname; ret = mu_asprintf (&header, "Content-Type: %s; name=%s\n" "Content-Transfer-Encoding: %s\n" "Content-Disposition: attachment; filename=%s\n\n", content_type, name, encoding, name); if (ret == 0) { if ((ret = mu_header_create (&hdr, header, strlen (header))) == 0) { mu_stream_t bstr; mu_message_get_body (*newmsg, &body); mu_body_get_streamref (body, &bstr); if ((ret = mu_file_stream_create (&fstream, filename, MU_STREAM_READ)) == 0) { if ((ret = mu_filter_create (&tstream, fstream, encoding, MU_FILTER_ENCODE, MU_STREAM_READ)) == 0) { mu_stream_copy (bstr, tstream, 0, NULL); mu_stream_unref (tstream); mu_message_set_header (*newmsg, hdr, NULL); } } mu_stream_unref (bstr); free (header); } } } } if (ret) { if (*newmsg) mu_message_destroy (newmsg, NULL); if (hdr) mu_header_destroy (&hdr); if (fstream) mu_stream_destroy (&fstream); if (fname) free (fname); } return ret; }
void message_display_parts (mu_message_t msg, int indent) { int ret, j; size_t nparts; mu_message_t part; mu_header_t hdr; mu_stream_t str; mu_body_t body; int ismulti; size_t nbytes; /* How many parts does the message has? */ if ((ret = mu_message_get_num_parts (msg, &nparts)) != 0) { fprintf (stderr, "mu_message_get_num_parts - %s\n", mu_strerror (ret)); exit (2); } /* Iterate through all the parts. Treat type "message/rfc822" differently, since it is a message of its own that can have other subparts(recursive). */ for (j = 1; j <= nparts; j++) { int status; const char *hvalue; char *type = NULL; const char *encoding = ""; MU_ASSERT (mu_message_get_part (msg, j, &part)); MU_ASSERT (mu_message_get_header (part, &hdr)); status = mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE, &hvalue); if (status == MU_ERR_NOENT) /* nothing */; else if (status != 0) mu_error ("Cannot get header value: %s", mu_strerror (status)); else { status = mu_mimehdr_aget_disp (hvalue, &type); if (status) mu_error ("Cannot extract content type field: %s", mu_strerror (status)); } printf ("%*.*sType of part %d = %s\n", indent, indent, "", j, type ? type : ""); print_message_part_sizes (part, indent); if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING, &encoding)) encoding = ""; ismulti = 0; if ((type && mu_c_strcasecmp (type, "message/rfc822") == 0) || (mu_message_is_multipart (part, &ismulti) == 0 && ismulti)) { if (!ismulti) MU_ASSERT (mu_message_unencapsulate (part, &part, NULL)); MU_ASSERT (mu_message_get_header (part, &hdr)); if (mu_header_sget_value (hdr, MU_HEADER_FROM, &from)) from = ""; if (mu_header_sget_value (hdr, MU_HEADER_SUBJECT, &subject)) subject = ""; printf ("%*.*sEncapsulated message : %s\t%s\n", indent, indent, "", from, subject); printf ("%*.*sBegin\n", indent, indent, ""); message_display_parts (part, indent + indent_level); mu_message_destroy (&part, NULL); } else if (!type || (mu_c_strcasecmp (type, "text/plain") == 0) || (mu_c_strcasecmp (type, "text/html")) == 0) { printf ("%*.*sText Message\n", indent, indent, ""); printf ("%*.*sBegin\n", indent, indent, ""); mu_message_get_body (part, &body); mu_body_get_streamref (body, &str); /* Make sure the original body stream is not closed when str gets destroyed */ mu_filter_create (&str, str, encoding, MU_FILTER_DECODE, MU_STREAM_READ); while (mu_stream_readline (str, buf, sizeof (buf), &nbytes) == 0 && nbytes) { printf ("%*.*s%s", indent, indent, "", buf); } mu_stream_destroy (&str); } else { /* Save the attachements. */ char *fname = NULL; mu_message_aget_decoded_attachment_name (part, charset, &fname, NULL); if (fname == NULL) fname = mu_tempname (NULL); printf ("%*.*sAttachment - saving [%s]\n", indent, indent, "", fname); printf ("%*.*sBegin\n", indent, indent, ""); if (charset) { mu_mime_io_buffer_t info; mu_mime_io_buffer_create (&info); mu_mime_io_buffer_set_charset (info, charset); MU_ASSERT (mu_message_save_attachment (part, NULL, info)); mu_mime_io_buffer_destroy (&info); } else MU_ASSERT (mu_message_save_attachment (part, fname, NULL)); if (print_attachments) print_file (fname, indent); free (fname); } printf ("\n%*.*sEnd\n", indent, indent, ""); free (type); } }
void io_setio (int ifd, int ofd, int tls) { mu_stream_t str, istream, ostream; if (ifd == -1) imap4d_bye (ERR_NO_IFILE); if (ofd == -1) imap4d_bye (ERR_NO_OFILE); if (mu_stdio_stream_create (&istream, ifd, MU_STREAM_READ)) imap4d_bye (ERR_STREAM_CREATE); mu_stream_set_buffer (istream, mu_buffer_line, 0); if (mu_stdio_stream_create (&ostream, ofd, MU_STREAM_WRITE)) imap4d_bye (ERR_STREAM_CREATE); mu_stream_set_buffer (ostream, mu_buffer_line, 0); /* Combine the two streams into an I/O one. */ #ifdef WITH_TLS if (tls) { int rc = mu_tls_server_stream_create (&str, istream, ostream, 0); if (rc) { mu_stream_unref (istream); mu_stream_unref (ostream); mu_error (_("failed to create TLS stream: %s"), mu_strerror (rc)); imap4d_bye (ERR_STREAM_CREATE); } } else #endif if (mu_iostream_create (&str, istream, ostream)) imap4d_bye (ERR_STREAM_CREATE); /* Convert all writes to CRLF form. There is no need to convert reads, as the code ignores extra \r anyway. */ if (mu_filter_create (&iostream, str, "CRLF", MU_FILTER_ENCODE, MU_STREAM_WRITE | MU_STREAM_RDTHRU)) imap4d_bye (ERR_STREAM_CREATE); /* Change buffering scheme: filter streams are fully buffered by default. */ mu_stream_set_buffer (iostream, mu_buffer_line, 0); if (imap4d_transcript) { int rc; mu_stream_t dstr, xstr; rc = mu_dbgstream_create (&dstr, MU_DIAG_DEBUG); if (rc) mu_error (_("cannot create debug stream; transcript disabled: %s"), mu_strerror (rc)); else { rc = mu_xscript_stream_create (&xstr, iostream, dstr, NULL); mu_stream_unref (dstr); if (rc) mu_error (_("cannot create transcript stream: %s"), mu_strerror (rc)); else { mu_stream_unref (iostream); iostream = xstr; } } } }