static void _iostream_done (struct _mu_stream *str) { struct _mu_iostream *sp = (struct _mu_iostream *)str; mu_stream_unref (sp->transport[_MU_STREAM_INPUT]); mu_stream_unref (sp->transport[_MU_STREAM_OUTPUT]); }
int main (int argc, char **argv) { int i; mu_stream_t in, out; mu_stream_t cvt; const char *args[5] = { "iconv" }; if (argc < 3 || argc > 4) { fprintf (stderr, "usage: %s from-code to-code [err]\n", argv[0]); return 1; } MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0)); args[1] = argv[1]; args[2] = argv[2]; i = 3; if (argc == 4) args[i++] = argv[3]; args[i] = NULL; MU_ASSERT (mu_filter_create_args (&cvt, in, args[0], i, args, MU_FILTER_DECODE, MU_FILTER_READ)); mu_stream_unref (in); MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0)); MU_ASSERT (mu_stream_copy (out, cvt, 0, NULL)); mu_stream_unref (cvt); mu_stream_flush (out); return 0; }
int mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg, mu_mime_io_buffer_t info) { int ret = 0; mu_header_t hdr; mu_stream_t istream; if (msg == NULL) return EINVAL; if (newmsg == NULL) return MU_ERR_OUT_PTR_NULL; if (info == NULL /* FIXME: not needed? */ && (ret = mu_message_get_header (msg, &hdr)) == 0) { const char *s; if (!(mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE, &s) == 0 && mu_c_strncasecmp (s, MESSAGE_RFC822_STR, sizeof (MESSAGE_RFC822_STR) - 1) == 0)) return EINVAL; } if ((ret = _attachment_setup (&info, msg, &istream)) != 0) return ret; ret = mu_stream_to_message (istream, &info->msg); mu_stream_unref (istream); if (ret == 0) *newmsg = info->msg; _attachment_free (info, ret && ret != EAGAIN); return ret; }
static PyObject * api_sieve_machine_error_text (PyObject *self, PyObject *args) { int status; PySieveMachine *py_mach; mu_stream_t estr; mu_transport_t trans[2]; PyObject *retval; mu_off_t length = 0; if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach)) return NULL; if (!py_mach->mach) PyErr_SetString (PyExc_RuntimeError, "Uninitialized Sieve machine"); mu_sieve_get_diag_stream (py_mach->mach, &estr); status = mu_stream_ioctl (estr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans); if (status == 0) { mu_stream_t str = (mu_stream_t) trans[0]; mu_stream_size (str, &length); status = mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans); mu_stream_truncate (str, 0); } if (status) PyErr_SetString (PyExc_RuntimeError, mu_strerror (status)); retval = PyString_FromStringAndSize ((char*) trans[0], length); mu_stream_unref (estr); return _ro (retval); }
static PyObject * api_stream_unref (PyObject *self, PyObject *args) { PyStream *py_stm; if (!PyArg_ParseTuple (args, "O!", &PyStreamType, &py_stm)) return NULL; mu_stream_unref (py_stm->stm); return _ro (Py_None); }
static int set_strerr_flt () { mu_stream_t flt, trans[2]; int rc; rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans); if (rc == 0) { char sessidstr[10]; char *argv[] = { "inline-comment", NULL, "-S", NULL }; snprintf (sessidstr, sizeof sessidstr, "%08lx:", mu_session_id); argv[1] = sessidstr; rc = mu_filter_create_args (&flt, trans[0], "inline-comment", 3, (const char **)argv, MU_FILTER_ENCODE, MU_STREAM_WRITE); mu_stream_unref (trans[0]); if (rc == 0) { mu_stream_set_buffer (flt, mu_buffer_line, 0); trans[0] = flt; trans[1] = NULL; rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_SET, trans); mu_stream_unref (trans[0]); if (rc) mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM", mu_stream_strerror (mu_strerr, rc)); } else mu_error (_("cannot create log filter stream: %s"), mu_strerror (rc)); } else { mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM", mu_stream_strerror (mu_strerr, rc)); } return rc; }
static void clr_strerr_flt () { mu_stream_t flt, trans[2]; int rc; rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans); if (rc == 0) { flt = trans[0]; rc = mu_stream_ioctl (flt, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans); if (rc == 0) { mu_stream_unref (trans[0]); rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_SET, trans); if (rc == 0) mu_stream_unref (flt); } } }
static PyObject * api_sieve_machine_init (PyObject *self, PyObject *args) { int status; PySieveMachine *py_mach; mu_stream_t str, estr; if (!PyArg_ParseTuple (args, "O!", &PySieveMachineType, &py_mach)) return NULL; status = mu_memory_stream_create (&str, MU_STREAM_RDWR); if (status) return _ro (PyInt_FromLong (status)); status = mu_log_stream_create (&estr, str); mu_stream_unref (str); if (status) return _ro (PyInt_FromLong (status)); status = mu_sieve_machine_init_ex (&py_mach->mach, NULL, estr); mu_stream_unref (estr); return _ro (PyInt_FromLong (status)); }
int imap4d_init_tls_server () { mu_stream_t tlsstream, stream[2]; int rc; rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_GET, stream); if (rc) { mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM", mu_stream_strerror (iostream, rc)); return 1; } rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0); if (rc) { mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), mu_stream_strerror (tlsstream, rc)); return 1; } mu_stream_unref (stream[0]); mu_stream_unref (stream[1]); stream[0] = stream[1] = tlsstream; rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, stream); if (rc) { mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM", mu_stream_strerror (iostream, rc)); imap4d_bye (ERR_STREAM_CREATE); } mu_stream_unref (stream[0]); mu_stream_unref (stream[1]); return 0; }
/* A locale-independent version of strftime */ size_t mu_strftime (char *buf, size_t size, const char *format, struct tm *tm) { int rc; mu_stream_t str; mu_stream_stat_buffer stat; if (mu_fixed_memory_stream_create (&str, buf, size, MU_STREAM_WRITE)) return 0; mu_stream_set_stat (str, MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT), stat); rc = mu_c_streamftime (str, format, tm, NULL); if (rc == 0) rc = mu_stream_write (str, "", 1, NULL); mu_stream_unref (str); return rc ? 0 : stat[MU_STREAM_STAT_OUT] - 1; }
static int _mh_prop_save (struct _mu_property *prop) { struct mu_mh_prop *mhprop = prop->_prop_init_data; mu_header_t header = prop->_prop_data; mu_stream_t stream; int rc; if (mhprop->ro) return 0; rc = mu_file_stream_create (&stream, mhprop->filename, MU_STREAM_WRITE|MU_STREAM_CREAT); if (rc) return rc; rc = _mh_prop_write_stream (header, mhprop, stream); mu_stream_unref (stream); return rc; }
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; }
static int pop_scan_message (struct _pop3_message *mpm) { int status; mu_stream_t stream; struct mu_message_scan scan; if (mpm->flags & _POP3_MSG_SCANNED) return 0; status = _pop_message_get_stream (mpm, &stream); if (status) return status; scan.flags = MU_SCAN_SEEK | MU_SCAN_SIZE; scan.message_start = 0; scan.message_size = mpm->message_size; status = mu_stream_scan_message (stream, &scan); mu_stream_unref (stream); if (status == 0) { mpm->body_start = scan.body_start; mpm->body_end = scan.body_end; mpm->header_lines = scan.header_lines; mpm->body_lines = scan.body_lines; if (!(mpm->flags & _POP3_MSG_ATTRSET)) { mpm->attr_flags = scan.attr_flags; mpm->flags |= _POP3_MSG_ATTRSET; } mpm->flags |= _POP3_MSG_SCANNED; } return status; }
static int _mh_prop_fill (struct _mu_property *prop) { struct mu_mh_prop *mhprop = prop->_prop_init_data; int rc; mu_stream_t stream; mu_header_t header; rc = mu_file_stream_create (&stream, mhprop->filename, MU_STREAM_READ); if (rc) { if ((rc = mu_header_create (&header, NULL, 0)) != 0) mu_error (_("cannot create context %s: %s"), mhprop->filename, mu_strerror (rc)); } else { rc = _mh_prop_read_stream (&header, stream); mu_stream_unref (stream); } if (rc == 0) prop->_prop_data = header; return rc; }
oo\n\ "; int main (int argc, char **argv) { int i; char *p; mu_message_t msg; mu_stream_t stream = NULL; mu_header_t hdr; mu_body_t body; mu_set_program_name (argv[0]); mu_static_memory_stream_create (&stream, text, strlen (text)); assert (mu_stream_to_message (stream, &msg) == 0); mu_stream_unref (stream); assert (mu_message_get_header (msg, &hdr) == 0); assert (mu_message_get_body (msg, &body) == 0); assert (mu_body_get_streamref (body, &stream) == 0); assert (mu_stream_seek (stream, 0, MU_SEEK_END, NULL) == 0); for (i = 1; i < argc; i++) { if (strcmp (argv[i], "-h") == 0) { mu_printf ("usage: %s [-a HDR:VAL] [-t TEXT]\n", mu_program_name); return 0; } if (strcmp (argv[i], "-a") == 0) { i++; assert (argv[i] != NULL); p = strchr (argv[i], ':'); assert (p != NULL); *p++ = 0; while (*p && mu_isspace (*p)) p++; assert (mu_header_set_value (hdr, argv[i], p, 1) == 0); } else if (strcmp (argv[i], "-l") == 0) { mu_off_t off; int whence = MU_SEEK_SET; i++; assert (argv[i] != NULL); off = strtol (argv[i], &p, 10); assert (*p == 0); if (off < 0) whence = MU_SEEK_END; assert (mu_stream_seek (stream, off, whence, NULL) == 0); } else if (strcmp (argv[i], "-t") == 0) { mu_wordsplit_t ws; i++; assert (argv[i] != NULL); if (mu_wordsplit (argv[i], &ws, MU_WRDSF_NOSPLIT | MU_WRDSF_DEFFLAGS)) { mu_error ("mu_wordsplit: %s", mu_wordsplit_strerror (&ws)); exit (1); } else assert (mu_stream_write (stream, ws.ws_wordv[0], strlen (ws.ws_wordv[0]), NULL) == 0); mu_wordsplit_free (&ws); } else mu_error ("ignoring unknown argument %s", argv[i]); } mu_stream_unref (stream); assert (mu_message_get_streamref (msg, &stream) == 0); assert (mu_stream_copy (mu_strout, stream, 0, NULL) == 0); mu_stream_unref (stream); return 0; }
static void _sieve_action_printer (void *data, mu_stream_t stream, size_t msgno, mu_message_t msg, const char *action, const char *fmt, va_list ap) { PyObject *py_args; PyObject *py_dict = PyDict_New (); PyStream *py_stm; if (!py_dict) return; py_stm = PyStream_NEW (); if (py_stm) { PyMessage *py_msg = PyMessage_NEW (); char *buf = NULL; size_t buflen = 0; if (py_msg) { PyStream *py_stm = PyStream_NEW (); if (py_stm) { py_stm->stm = stream; mu_stream_ref (stream); py_msg->msg = msg; Py_INCREF (py_msg); PyDict_SetItemString (py_dict, "msgno", PyInt_FromSize_t (msgno)); PyDict_SetItemString (py_dict, "msg", (PyObject *)py_msg); PyDict_SetItemString (py_dict, "action", PyString_FromString (action ? action : "")); if (mu_vasnprintf (&buf, &buflen, fmt, ap)) { mu_stream_unref (stream); return; } PyDict_SetItemString (py_dict, "text", PyString_FromString (buf ? buf : "")); free (buf); py_args = PyTuple_New (1); if (py_args) { struct _mu_py_sieve_logger *s = data; PyObject *py_fnc = s->py_action_printer; Py_INCREF (py_dict); PyTuple_SetItem (py_args, 0, py_dict); if (py_fnc && PyCallable_Check (py_fnc)) PyObject_CallObject (py_fnc, py_args); Py_DECREF (py_dict); Py_DECREF (py_args); } } } } }
int main (int argc, char * argv []) { mu_stream_t in, out, flt; int i; int mode = MU_FILTER_ENCODE; int flags = MU_STREAM_READ; char *fltname; mu_off_t shift = 0; int newline_option = 0; size_t bufsize = 0; if (argc == 1) usage (NULL); if (argc < 4) usage ("not enough arguments"); fltname = argv[1]; if (strcmp (argv[2], "encode") == 0) mode = MU_FILTER_ENCODE; else if (strcmp (argv[2], "decode") == 0) mode = MU_FILTER_DECODE; else usage ("2nd arg is wrong"); if (strcmp (argv[3], "read") == 0) flags = MU_STREAM_READ; else if (strcmp (argv[3], "write") == 0) flags = MU_STREAM_WRITE; else usage ("3rd arg is wrong"); for (i = 4; i < argc; i++) { if (strncmp (argv[i], "shift=", 6) == 0) shift = strtoul (argv[i] + 6, NULL, 0); else if (strncmp (argv[i], "bufsize=", 8) == 0) bufsize = strtoul (argv[i] + 8, NULL, 0); else if (strcmp (argv[i], "verbose") == 0) verbose++; else if (strcmp (argv[i], "printable") == 0) printable++; else if (strcmp (argv[i], "nl") == 0) newline_option++; else if (strcmp (argv[i], "--") == 0) { argv[i] = fltname; break; } else usage ("wrong option"); } argc -= i; argv += i; MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0)); if (bufsize) mu_stream_set_buffer (in, mu_buffer_full, bufsize); MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0)); if (flags == MU_STREAM_READ) { MU_ASSERT (mu_filter_create_args (&flt, in, fltname, argc, (const char **)argv, mode, MU_STREAM_READ|MU_STREAM_SEEK)); mu_stream_unref (in); if (bufsize) mu_stream_set_buffer (flt, mu_buffer_full, bufsize); if (shift) MU_ASSERT (mu_stream_seek (flt, shift, MU_SEEK_SET, NULL)); c_copy (out, flt); } else { MU_ASSERT (mu_filter_create_args (&flt, out, fltname, argc, (const char **)argv, mode, MU_STREAM_WRITE)); if (bufsize) mu_stream_set_buffer (flt, mu_buffer_full, bufsize); if (shift) MU_ASSERT (mu_stream_seek (in, shift, MU_SEEK_SET, NULL)); c_copy (flt, in); mu_stream_close (in); mu_stream_destroy (&in); } mu_stream_close (flt); mu_stream_destroy (&flt); if (newline_option) mu_stream_write (out, "\n", 1, NULL); mu_stream_close (out); mu_stream_destroy (&out); if (verbose) { fprintf (stderr, "\nInput stream stats:\n"); fprintf (stderr, "Bytes in: %lu\n", (unsigned long) instat[MU_STREAM_STAT_IN]); fprintf (stderr, "Bytes out: %lu\n", (unsigned long) instat[MU_STREAM_STAT_OUT]); fprintf (stderr, "Reads: %lu\n", (unsigned long) instat[MU_STREAM_STAT_READS]); fprintf (stderr, "Seeks: %lu\n", (unsigned long) instat[MU_STREAM_STAT_SEEKS]); fprintf (stderr, "\nOutput stream stats:\n"); fprintf (stderr, "Bytes in: %lu\n", (unsigned long) outstat[MU_STREAM_STAT_IN]); fprintf (stderr, "Bytes out: %lu\n", (unsigned long) outstat[MU_STREAM_STAT_OUT]); fprintf (stderr, "Writes: %lu\n", (unsigned long) outstat[MU_STREAM_STAT_WRITES]); fprintf (stderr, "Seeks: %lu\n", (unsigned long) outstat[MU_STREAM_STAT_SEEKS]); } return 0; }
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; } } } }
static int _iostream_ctl (struct _mu_stream *str, int code, int opcode, void *arg) { struct _mu_iostream *sp = (struct _mu_iostream *)str; switch (code) { case MU_IOCTL_TRANSPORT: if (!arg) return EINVAL; else { mu_transport_t *ptrans = arg; switch (opcode) { case MU_IOCTL_OP_GET: ptrans[0] = (mu_transport_t) sp->transport[_MU_STREAM_INPUT]; ptrans[1] = (mu_transport_t) sp->transport[_MU_STREAM_OUTPUT]; break; case MU_IOCTL_OP_SET: ptrans = arg; sp->transport[_MU_STREAM_INPUT] = (mu_stream_t) ptrans[0]; sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1]; break; default: return EINVAL; } } break; case MU_IOCTL_SUBSTREAM: case MU_IOCTL_TOPSTREAM: if (!arg) return EINVAL; else { mu_stream_t *pstr = arg; switch (opcode) { case MU_IOCTL_OP_GET: pstr[0] = sp->transport[0]; mu_stream_ref (pstr[0]); pstr[1] = sp->transport[1]; mu_stream_ref (pstr[1]); break; case MU_IOCTL_OP_SET: mu_stream_unref (sp->transport[0]); sp->transport[0] = pstr[0]; mu_stream_ref (sp->transport[0]); mu_stream_unref (sp->transport[1]); sp->transport[1] = pstr[1]; mu_stream_ref (sp->transport[1]); break; default: return EINVAL; } } break; case MU_IOCTL_TRANSPORT_BUFFER: if (!arg) return EINVAL; else { struct mu_buffer_query *qp = arg; if (!MU_TRANSPORT_VALID_TYPE (qp->type) || !sp->transport[qp->type]) return EINVAL; return mu_stream_ioctl (sp->transport[qp->type], code, opcode, arg); } default: return ENOSYS; } return 0; }
int mutool_filter (int argc, char **argv) { int rc, index; mu_stream_t flt, prev_stream; const char *fltname; int mode; if (argp_parse (&filter_argp, argc, argv, ARGP_IN_ORDER, &index, NULL)) return 1; argc -= index; argv += index; if (list_option) { if (argc) { mu_error (_("excess arguments")); return 1; } return list_filters (); } if (argc == 0) { mu_error (_("what filter do you want?")); return 1; } prev_stream = mu_strin; mu_stream_ref (mu_strin); do { int i; fltname = argv[0]; if (fltname[0] == '~') { mode = negate_filter_mode (filter_mode); fltname++; } else mode = filter_mode; for (i = 1; i < argc; i++) if (strcmp (argv[i], "+") == 0) break; rc = mu_filter_create_args (&flt, prev_stream, fltname, i, (const char **)argv, mode, MU_STREAM_READ); mu_stream_unref (prev_stream); if (rc) { mu_error (_("cannot open filter stream: %s"), mu_strerror (rc)); return 1; } prev_stream = flt; argc -= i; argv += i; if (argc) { argc--; argv++; } } while (argc); rc = mu_stream_copy (mu_strout, flt, 0, NULL); if (rc) { mu_error ("%s", mu_strerror (rc)); return 1; } if (newline_option) mu_stream_write (mu_strout, "\n", 1, NULL); mu_stream_destroy (&flt); mu_stream_flush (mu_strout); return 0; }
/* Generate and send the reply message */ static int vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg, char *text, char *to, char *from) { mu_mime_t mime = NULL; mu_message_t newmsg; mu_header_t newhdr; mu_address_t to_addr = NULL, from_addr = NULL; char *value; mu_mailer_t mailer; int rc; if (mu_sieve_tag_lookup (tags, "file", NULL)) { mu_stream_t instr; rc = mu_mapfile_stream_create (&instr, text, MU_STREAM_READ); if (rc) { mu_sieve_error (mach, _("%lu: cannot open message file %s: %s"), (unsigned long) mu_sieve_get_message_num (mach), text, mu_strerror (rc)); return -1; } rc = mu_stream_to_message (instr, &newmsg); mu_stream_unref (instr); if (rc) { mu_sieve_error (mach, _("%lu: cannot read message from file %s: %s"), (unsigned long) mu_sieve_get_message_num (mach), text, mu_strerror (rc)); return -1; } } else { if (build_mime (mach, tags, &mime, msg, text)) return -1; mu_mime_get_message (mime, &newmsg); mu_message_unref (newmsg); mu_message_get_header (newmsg, &newhdr); } rc = mu_address_create (&to_addr, to); if (rc) { mu_sieve_error (mach, _("%lu: cannot create recipient address <%s>: %s"), (unsigned long) mu_sieve_get_message_num (mach), from, mu_strerror (rc)); } else { mu_header_set_value (newhdr, MU_HEADER_TO, to, 0); vacation_subject (mach, tags, msg, newhdr); if (from) { if (mu_address_create (&from_addr, from)) from_addr = NULL; } else { from_addr = NULL; } if (mu_rfc2822_in_reply_to (msg, &value) == 0) { mu_header_set_value (newhdr, MU_HEADER_IN_REPLY_TO, value, 1); free (value); } if (mu_rfc2822_references (msg, &value) == 0) { mu_header_set_value (newhdr, MU_HEADER_REFERENCES, value, 1); free (value); } mailer = mu_sieve_get_mailer (mach); if (mailer) { rc = mu_mailer_send_message (mailer, newmsg, from_addr, to_addr); } else rc = MU_ERR_FAILURE; } mu_address_destroy (&to_addr); mu_address_destroy (&from_addr); mu_mime_destroy (&mime); return rc; }
/* 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; }
int main (int argc, char **argv) { int index; int rc; mu_stream_t in, tmp; mu_message_t msg; mu_header_t hdr; mu_iterator_t itr; const char *file; char *newval; mu_off_t size; mu_body_t body; mu_stream_t bstr; MU_APP_INIT_NLS (); mh_argp_init (); mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, opt_handler, NULL, &index); if (index == argc) { mu_error (_("file name not given")); exit (1); } file = argv[index]; prompter_init (); if (erase_seq) prompter_set_erase (erase_seq); if (kill_seq) prompter_set_erase (kill_seq); if ((rc = mu_stdio_stream_create (&strout, MU_STDOUT_FD, MU_STREAM_WRITE))) { mu_error (_("cannot open stdout: %s"), mu_strerror (rc)); return 1; } if ((rc = mu_file_stream_create (&in, file, MU_STREAM_RDWR))) { mu_error (_("cannot open input file `%s': %s"), file, mu_strerror (rc)); return 1; } rc = mu_stream_to_message (in, &msg); mu_stream_unref (in); if (rc) { mu_error (_("input stream %s is not a message (%s)"), file, mu_strerror (rc)); return 1; } if ((rc = mu_temp_file_stream_create (&tmp, NULL, 0))) { mu_error (_("Cannot open temporary file: %s"), mu_strerror (rc)); return 1; } /* Copy headers */ mu_message_get_header (msg, &hdr); mu_header_get_iterator (hdr, &itr); for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) { const char *name, *val; mu_iterator_current_kv (itr, (const void **)&name, (void**)&val); if (!is_empty_string (val)) { mu_stream_printf (tmp, "%s: %s\n", name, val); mu_stream_printf (strout, "%s: %s\n", name, val); } else { int cont = 0; mu_opool_t opool; const char *prompt = name; mu_opool_create (&opool, 1); do { size_t len; char *p; p = prompter_get_value (prompt); if (!p) return 1; prompt = NULL; if (cont) { mu_opool_append_char (opool, '\n'); if (!mu_isspace (p[0])) mu_opool_append_char (opool, '\t'); } len = strlen (p); if (len > 0 && p[len-1] == '\\') { len--; cont = 1; } else cont = 0; mu_opool_append (opool, p, len); free (p); } while (cont); mu_opool_append_char (opool, 0); newval = mu_opool_finish (opool, NULL); if (!is_empty_string (newval)) mu_stream_printf (tmp, "%s: %s\n", name, newval); mu_opool_destroy (&opool); } } mu_iterator_destroy (&itr); mu_stream_printf (strout, "--------\n"); mu_stream_write (tmp, "\n", 1, NULL); /* Copy body */ if (prepend_option) { mu_stream_printf (strout, "\n--------%s\n\n", _("Enter initial text")); while ((newval = prompter_get_line ())) { mu_stream_write (tmp, newval, strlen (newval), NULL); free (newval); mu_stream_write (tmp, "\n", 1, NULL); } } mu_message_get_body (msg, &body); mu_body_get_streamref (body, &bstr); if (!prepend_option && !rapid_option) { mu_stream_copy (strout, bstr, 0, NULL); mu_stream_seek (bstr, 0, MU_SEEK_SET, NULL); } mu_stream_copy (tmp, bstr, 0, NULL); mu_stream_unref (bstr); if (!prepend_option && !rapid_option) { printf ("\n--------%s\n\n", _("Enter additional text")); while ((newval = prompter_get_line ())) { mu_stream_write (tmp, newval, strlen (newval), NULL); free (newval); mu_stream_write (tmp, "\n", 1, NULL); } } /* Destroy the message */ mu_message_destroy (&msg, mu_message_get_owner (msg)); /* Rewind the streams and copy data back to in. */ mu_stream_seek (in, 0, MU_SEEK_SET, NULL); mu_stream_seek (tmp, 0, MU_SEEK_SET, NULL); mu_stream_copy (in, tmp, 0, &size); mu_stream_truncate (in, size); mu_stream_destroy (&in); mu_stream_destroy (&tmp); mu_stream_destroy (&strout); prompter_done (); 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); }
static int pop_open (mu_mailbox_t mbox, int flags) { struct _pop3_mailbox *mpd = mbox->data; int status; mu_stream_t stream; struct mu_sockaddr *sa; struct mu_sockaddr_hints hints; /* Sanity checks. */ if (mpd == NULL) return EINVAL; mbox->flags = flags; memset (&hints, 0, sizeof (hints)); hints.flags = MU_AH_DETECT_FAMILY; hints.port = mpd->pops ? MU_POPS_PORT : MU_POP_PORT; hints.protocol = IPPROTO_TCP; hints.socktype = SOCK_STREAM; status = mu_sockaddr_from_url (&sa, mbox->url, &hints); if (status) return status; status = mu_tcp_stream_create_from_sa (&stream, sa, NULL, mbox->flags); if (status) { mu_sockaddr_free (sa); return status; } #ifdef WITH_TLS if (mpd->pops) { mu_stream_t newstr; status = mu_tls_client_stream_create (&newstr, stream, stream, 0); mu_stream_unref (stream); if (status) { mu_error ("pop_open: mu_tls_client_stream_create: %s", mu_strerror (status)); return status; } stream = newstr; } #endif /* WITH_TLS */ /* FIXME: How to configure buffer size? */ mu_stream_set_buffer (stream, mu_buffer_line, 0); status = mu_pop3_create (&mpd->pop3); if (status) { mu_stream_destroy (&stream); return status; } mu_pop3_set_carrier (mpd->pop3, stream); if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_PROT)) mu_pop3_trace (mpd->pop3, MU_POP3_TRACE_SET); if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE6)) mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, MU_XSCRIPT_SECURE); if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE7)) mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, MU_XSCRIPT_PAYLOAD); do { status = mu_pop3_connect (mpd->pop3); if (status) break; status = mu_pop3_capa (mpd->pop3, 1, NULL); if (status == MU_ERR_REPLY) { mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, ("server rejected the CAPA command: %s", mu_pop3_strresp (mpd->pop3))); /* try to continue anyway */ } else if (status) return status; #ifdef WITH_TLS if (!mpd->pops && mu_url_sget_param (mbox->url, "notls", NULL) == MU_ERR_NOENT && mu_pop3_capa_test (mpd->pop3, "STLS", NULL) == 0) { status = mu_pop3_stls (mpd->pop3); if (status) break; } #endif status = mu_authority_authenticate (mbox->folder->authority); } while (0); if (status) mu_pop3_destroy (&mpd->pop3); return status; }
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; }
static void _streamref_done (struct _mu_stream *str) { struct _mu_streamref *sp = (struct _mu_streamref *)str; mu_stream_unref (sp->transport); }
int main (int argc, char **argv) { int i; char *host = NULL; char *infile = NULL; char *port = NULL; int tls = 0; int raw = 1; int flags = 0; mu_stream_t stream; mu_smtp_t smtp; mu_stream_t instr; char *from = NULL; mu_list_t rcpt_list = NULL; mu_list_t meth_list = NULL; mu_list_t skiphdr_list = NULL; struct mu_sockaddr *sa; struct mu_sockaddr_hints hints; mu_set_program_name (argv[0]); mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); if (argc < 2) usage (); memset (&hints, 0, sizeof (hints)); hints.flags = MU_AH_DETECT_FAMILY; hints.port = 25; hints.protocol = IPPROTO_TCP; hints.socktype = SOCK_STREAM; MU_ASSERT (mu_smtp_create (&smtp)); for (i = 1; i < argc; i++) { if (strncmp (argv[i], "port=", 5) == 0) port = argv[i] + 5; else if (strncmp (argv[i], "family=", 7) == 0) { hints.flags &= ~MU_AH_DETECT_FAMILY; switch (argv[i][7]) { case '4': hints.family = AF_INET; break; case '6': hints.family = AF_INET6; break; default: mu_error ("invalid family name: %s", argv[i]+7); exit (1); } } else if (strncmp (argv[i], "trace=", 6) == 0) { char *arg = argv[i] + 6; if (mu_isdigit (arg[0])) mu_smtp_trace (smtp, atoi (argv[i] + 6) ? MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR); else { mu_smtp_trace (smtp, MU_SMTP_TRACE_SET); if (strcmp (arg, "secure") == 0) mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET, MU_XSCRIPT_SECURE); else if (strcmp (arg, "payload") == 0) mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET, MU_XSCRIPT_PAYLOAD); } } else if (strncmp (argv[i], "tls=", 4) == 0) tls = atoi (argv[i] + 4); else if (strncmp (argv[i], "domain=", 7) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN, argv[i] + 7)); else if (strncmp (argv[i], "user="******"pass="******"service=", 8) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE, argv[i] + 8)); else if (strncmp (argv[i], "realm=", 6) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM, argv[i] + 6)); else if (strncmp (argv[i], "host=", 5) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST, argv[i] + 5)); else if (strncmp (argv[i], "url=", 4) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL, argv[i] + 4)); else if (strncmp (argv[i], "input=", 6) == 0) infile = argv[i] + 6; else if (strncmp (argv[i], "raw=", 4) == 0) raw = atoi (argv[i] + 4); else if (strncmp (argv[i], "rcpt=", 5) == 0) { if (!rcpt_list) MU_ASSERT (mu_list_create (&rcpt_list)); MU_ASSERT (mu_list_append (rcpt_list, argv[i] + 5)); } else if (strncmp (argv[i], "from=", 5) == 0) from = argv[i] + 5; else if (strncmp (argv[i], "auth=", 5) == 0) update_list (&meth_list, argv[i] + 5); else if (strncmp (argv[i], "skiphdr=", 8) == 0) { update_list (&skiphdr_list, argv[i] + 8); raw = 0; } else if (host) { mu_error ("server name already given: %s, new name %s?", host, argv[i]); exit (1); } else host = argv[i]; } if (!host) usage (); if (!raw) flags = MU_STREAM_SEEK; if (infile) MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags)); else MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags)); host = argv[1]; MU_ASSERT (mu_sockaddr_from_node (&sa, host, port, &hints)); MU_ASSERT (mu_tcp_stream_create_from_sa (&stream, sa, NULL, MU_STREAM_RDWR)); mu_smtp_set_carrier (smtp, stream); mu_stream_unref (stream); if (!from) { from = getenv ("USER"); if (!from) { mu_error ("cannot determine sender name"); exit (1); } } if (raw && !rcpt_list) { mu_error ("no recipients"); exit (1); } MU_ASSERT (mu_smtp_open (smtp)); MU_ASSERT (mu_smtp_ehlo (smtp)); if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0) { MU_ASSERT (mu_smtp_starttls (smtp)); MU_ASSERT (mu_smtp_ehlo (smtp)); } if (meth_list) { int status; MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list)); status = mu_smtp_auth (smtp); switch (status) { case 0: MU_ASSERT (mu_smtp_ehlo (smtp)); break; case ENOSYS: case MU_ERR_NOENT: /* Ok, skip it */ break; default: mu_error ("authentication failed: %s", mu_strerror (status)); exit (1); } } MU_ASSERT (mu_smtp_mail_basic (smtp, from, NULL)); mu_list_foreach (rcpt_list, send_rcpt_command, smtp); if (raw) { /* Raw sending mode: send from the stream directly */ MU_ASSERT (mu_smtp_send_stream (smtp, instr)); } else { /* Message (standard) sending mode: send a MU message. */ mu_message_t msg; mu_stream_t ostr, bstr; mu_header_t hdr; mu_iterator_t itr; mu_body_t body; if (skiphdr_list) mu_list_set_comparator (skiphdr_list, headercmp); MU_ASSERT (mu_stream_to_message (instr, &msg)); mu_stream_unref (instr); MU_ASSERT (mu_smtp_data (smtp, &ostr)); MU_ASSERT (mu_message_get_header (msg, &hdr)); MU_ASSERT (mu_header_get_iterator (hdr, &itr)); for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) { const char *name; void *value; mu_iterator_current_kv (itr, (void*) &name, &value); if (mu_list_locate (skiphdr_list, (void*) name, NULL) == 0) continue; mu_stream_printf (ostr, "%s: %s\n", name, (char*)value); } mu_iterator_destroy (&itr); MU_ASSERT (mu_stream_write (ostr, "\n", 1, NULL)); MU_ASSERT (mu_message_get_body (msg, &body)); MU_ASSERT (mu_body_get_streamref (body, &bstr)); MU_ASSERT (mu_stream_copy (ostr, bstr, 0, NULL)); mu_stream_destroy (&bstr); mu_stream_close (ostr); mu_stream_destroy (&ostr); } MU_ASSERT (mu_smtp_dot (smtp)); MU_ASSERT (mu_smtp_quit (smtp)); mu_smtp_destroy (&smtp); mu_stream_close (instr); mu_stream_destroy (&instr); return 0; }
int mutool_send (int argc, char **argv) { int index; char *infile; mu_stream_t instr; mu_message_t msg; size_t count; mu_url_t urlhint, url; mu_mailer_t mailer; MU_ASSERT (mu_address_create_null (&rcpt_addr)); mu_register_all_mailer_formats (); if (argp_parse (&send_argp, argc, argv, 0, &index, NULL)) return 1; argc -= index; argv += index; if (argc < 1) { mu_error (_("not enough arguments")); return 1; } infile = argv[1]; if (infile) MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|MU_STREAM_SEEK)); else MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, MU_STREAM_READ|MU_STREAM_SEEK)); MU_ASSERT (mu_stream_to_message (instr, &msg)); mu_stream_unref (instr); mu_address_get_count (rcpt_addr, &count); if (count == 0) read_recipients = 1; if (read_recipients) { int rc; mu_header_t header; const char *value; MU_ASSERT (mu_message_get_header (msg, &header)); rc = mu_header_sget_value (header, MU_HEADER_TO, &value); if (rc == 0) send_address_add (&rcpt_addr, value); else if (rc != MU_ERR_NOENT) { mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value", MU_HEADER_TO, rc); exit (1); } rc = mu_header_sget_value (header, MU_HEADER_CC, &value); if (rc == 0) send_address_add (&rcpt_addr, value); else if (rc != MU_ERR_NOENT) { mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value", MU_HEADER_CC, rc); exit (1); } rc = mu_header_sget_value (header, MU_HEADER_BCC, &value); if (rc == 0) send_address_add (&rcpt_addr, value); else if (rc != MU_ERR_NOENT) { mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value", MU_HEADER_BCC, rc); exit (1); } } mu_address_get_count (rcpt_addr, &count); if (count == 0) { mu_error (_("no recipients")); exit (1); } MU_ASSERT (mu_url_create (&urlhint, "smtp://")); MU_ASSERT (mu_url_create_hint (&url, argv[0], MU_URL_PARSE_DEFAULT, urlhint)); mu_url_invalidate (url); MU_ASSERT (mu_mailer_create_from_url (&mailer, url)); MU_ASSERT (mu_mailer_open (mailer, MU_STREAM_RDWR)); MU_ASSERT (mu_mailer_send_message (mailer, msg, from_addr, rcpt_addr)); mu_mailer_close (mailer); mu_mailer_destroy (&mailer); return 0; }