/* ** Copyright 2010-2014 Double Precision, Inc. See COPYING for ** distribution information. */ #include "rfc2045.h" #include "rfc822/rfc822.h" #include #include #include struct doconvtoutf8_info { struct rfc2045_decodemsgtoutf8_cb *callback; int err_flag; }; static void doconvtoutf8_write(const char *p, size_t n, void *void_arg) { struct doconvtoutf8_info *ptr= (struct doconvtoutf8_info *)void_arg; if (n && ptr->err_flag == 0) ptr->err_flag=(*ptr->callback->output_func) (p, n, ptr->callback->arg); } static void doconvtoutf8_write_noeol(const char *p, size_t n, void *void_arg) { while (n) { size_t i; if (*p == '\n') { doconvtoutf8_write(" ", 1, void_arg); ++p; --n; continue; } for (i=0; ierr_flag= -1; } static int doconvtoutf8_rfc822hdr(const char *header, const char *value, struct rfc2045_decodemsgtoutf8_cb *callback) { struct doconvtoutf8_info info; info.err_flag=0; info.callback=callback; if (callback->headerfilter_func && (*callback->headerfilter_func)(header, value, callback->arg) == 0) return 0; if ((callback->flags & RFC2045_DECODEMSG_NOHEADERNAME) == 0) { doconvtoutf8_write(header, strlen(header), &info); doconvtoutf8_write(": ", 2, &info); } rfc822_display_hdrvalue(header, value, "utf-8", doconvtoutf8_write_noeol, doconvtoutf8_error, &info); doconvtoutf8_write("\n", 1, &info); if (callback->headerdone_func && info.err_flag == 0) { int rc=(*callback->headerdone_func)(header, callback->arg); if (rc) info.err_flag=rc; } return info.err_flag; } static int decode_handler(const char *p, size_t n, void *voidarg) { const struct doconvtoutf8_info *ptr= (const struct doconvtoutf8_info *)voidarg; int rc=0; if (n) rc=(*ptr->callback->output_func)(p, n, ptr->callback->arg); return rc; } int rfc2045_decodemsgtoutf8(struct rfc2045src *src, struct rfc2045 *p, struct rfc2045_decodemsgtoutf8_cb *callback) { struct rfc2045headerinfo *hi; int rc; hi=rfc2045header_start(src, p); if (hi) { char *header; char *value; while (rfc2045header_get(hi, &header, &value, RFC2045H_NOLC | RFC2045H_KEEPNL) == 0 && header) { if (callback->flags & RFC2045_DECODEMSG_NOHEADERS) continue; if ((callback->flags & RFC2045_DECODEMSG_NOATTACHHEADERS) && p->parent) continue; if (doconvtoutf8_rfc822hdr(header, value, callback) < 0) return -1; } rfc2045header_end(hi); } if (p->firstpart) { for (p=p->firstpart; p; p=p->next) { if (!p->isdummy) { if ((rc=rfc2045_decodemsgtoutf8(src, p, callback)) != 0) return rc; } } } else { const char *content_type; const char *transfer_encoding; const char *charset; struct doconvtoutf8_info info; info.callback=callback; rfc2045_mimeinfo(p, &content_type, &transfer_encoding, &charset); if ((strncmp(content_type, "text/", 5) == 0 || strncmp(content_type, "message/", 8) == 0) && (callback->flags & RFC2045_DECODEMSG_NOBODY) == 0 && (rc=rfc2045_decodetextmimesection(src, p, "utf-8", NULL, decode_handler, &info)) != 0) return rc; } return 0; }