struct rfc2045 *rfc2045_searchcontenttype(struct rfc2045 *rfc, const char *ct) { const char *content_type, *dummy; struct rfc2045 *p; rfc2045_mimeinfo(rfc, &content_type, &dummy, &dummy); if (strcmp(content_type, ct) == 0) return (rfc); for (p=rfc->firstpart; p; p=p->next) { if (p->isdummy) continue; rfc2045_mimeinfo(p, &content_type, &dummy, &dummy); if (strcmp(content_type, ct) == 0) break; if (strncmp(content_type, "multipart/", 10) == 0) return(rfc2045_searchcontenttype(p, ct)); } return (p); }
void newmsg_showfp(FILE *fp, int *attachcnt) { struct rfc2045 *p=rfc2045_fromfp(fp), *q; if (!p) enomem(); /* Here's a nice opportunity to count all attachments */ *attachcnt=0; for (q=p->firstpart; q; q=q->next) if (!q->isdummy) ++*attachcnt; if (*attachcnt) --*attachcnt; /* Not counting the 1st MIME part */ { const char *content_type; const char *content_transfer_encoding; const char *charset; rfc2045_mimeinfo(p, &content_type, &content_transfer_encoding, &charset); if (content_type && strcmp(content_type, "multipart/alternative") == 0) *attachcnt=0; } q=rfc2045_searchcontenttype(p, "text/plain"); if (q) { struct rfc2045src *src=rfc2045src_init_fd(fileno(fp)); if (src) { struct show_textarea_info info; show_textarea_init(&info, 1); rfc2045_decodetextmimesection(src, q, sqwebmail_content_charset, NULL, &show_textarea_trampoline, &info); rfc2045src_deinit(src); show_textarea(&info, "\n", 1); } } rfc2045_free(p); }
static struct rfc2045 *findtext(struct rfc2045 *rfcp) { struct rfc2045 *textp; const char *content_type; const char *content_transfer_encoding; const char *charset; rfc2045_mimeinfo(rfcp, &content_type, &content_transfer_encoding, &charset); if (strncmp(content_type, "text/", 5) == 0) textp=rfcp; else { for (textp=rfcp->firstpart; textp; textp=textp->next) { if (textp->isdummy) continue; rfc2045_mimeinfo(textp, &content_type, &content_transfer_encoding, &charset); if (strncmp(content_type, "text/", 5) == 0) break; } } return (textp); }
int rfc2045_decodetextmimesection(struct rfc2045src *src, struct rfc2045 *rfc, const char *mychset, int *conv_err, int (*handler)(const char *, size_t, void *), void *voidarg) { const char *dummy; const char *src_chset; libmail_u_convert_handle_t ci; int rc; int dummy_flag; if (!conv_err) conv_err= &dummy_flag; rfc2045_mimeinfo(rfc, &dummy, &dummy, &src_chset); *conv_err=0; if ((ci=libmail_u_convert_init(src_chset, mychset, handler, voidarg)) == NULL) { *conv_err=1; return -1; } rc=rfc2045_decodemimesection(src, rfc, &myhandler, &ci); dummy_flag=0; if (libmail_u_convert_deinit(ci, &dummy_flag)) rc= -1; if (dummy_flag) *conv_err=1; return (rc); }
int main(int argc, char **argv) { int argn; FILE *tmpfp; struct rfc2045 *rfcp; struct mimeautoreply_s replyinfo; const char *subj=0; const char *txtfile=0, *mimefile=0; const char *mimedsn=0; int nosend=0; const char *replymode="reply"; int replytoenvelope=0; int donotquote=0; const char *forwardsep="--- Forwarded message ---"; const char *replysalut="%F writes:"; struct rfc2045src *src; setlocale(LC_ALL, ""); charset=unicode_default_chset(); sender=NULL; for (argn=1; argn < argc; argn++) { char optc; char *optarg; if (argv[argn][0] != '-') break; if (strcmp(argv[argn], "--") == 0) { ++argn; break; } optc=argv[argn][1]; optarg=argv[argn]+2; if (!*optarg) optarg=NULL; switch (optc) { case 'c': if (!optarg && argn+1 < argc) optarg=argv[++argn]; if (optarg && *optarg) { char *p=libmail_u_convert_tobuf("", optarg, libmail_u_ucs4_native, NULL); if (!p) { fprintf(stderr, "Unknown charset: %s\n", charset); exit(1); } free(p); charset=optarg; } continue; case 't': if (!optarg && argn+1 < argc) optarg=argv[++argn]; txtfile=optarg; continue; case 'm': if (!optarg && argn+1 < argc) optarg=argv[++argn]; mimefile=optarg; continue; case 'r': if (!optarg && argn+1 < argc) optarg=argv[++argn]; recips=optarg; continue; case 'M': if (!optarg && argn+1 < argc) optarg=argv[++argn]; mimedsn=optarg; continue; case 'd': if (!optarg && argn+1 < argc) optarg=argv[++argn]; dbfile=optarg; continue; case 'e': replytoenvelope=1; continue; case 'T': if (!optarg && argn+1 < argc) optarg=argv[++argn]; if (optarg && *optarg) replymode=optarg; continue; case 'N': donotquote=1; continue; case 'F': if (!optarg && argn+1 < argc) optarg=argv[++argn]; if (optarg && *optarg) forwardsep=optarg; continue; case 'S': if (!optarg && argn+1 < argc) optarg=argv[++argn]; if (optarg && *optarg) replysalut=optarg; continue; case 'D': if (!optarg && argn+1 < argc) optarg=argv[++argn]; interval=optarg ? atoi(optarg):1; continue; case 'A': if (!optarg && argn+1 < argc) optarg=argv[++argn]; if (optarg) { struct header **h; for (h= &extra_headers; *h; h= &(*h)->next) ; if ((*h=malloc(sizeof(struct header))) == 0 || ((*h)->buf=strdup(optarg)) == 0) { perror("malloc"); exit(EX_TEMPFAIL); } (*h)->next=0; } continue; case 's': if (!optarg && argn+1 < argc) optarg=argv[++argn]; subj=optarg; continue; case 'f': if (optarg && *optarg) { sender=strdup(optarg); } else { sender=getenv("SENDER"); if (!sender) continue; sender=strdup(sender); } if (sender == NULL) { perror("malloc"); exit(1); } continue; case 'n': nosend=1; continue; default: usage(); } } if (!txtfile && !mimefile) usage(); if (txtfile && mimefile) usage(); tmpfp=tmpfile(); if (!tmpfp) { perror("tmpfile"); exit(1); } rfcp=savemessage(tmpfp); if (fseek(tmpfp, 0L, SEEK_SET) < 0) { perror("fseek(tempfile)"); exit(1); } read_headers(tmpfp); if (sender == NULL || *sender == 0) check_sender(); check_dsn(); check_recips(); #ifdef DbObj check_db(); #endif src=rfc2045src_init_fd(fileno(tmpfp)); memset(&replyinfo, 0, sizeof(replyinfo)); replyinfo.info.src=src; replyinfo.info.rfc2045partp=rfcp; replyinfo.info.voidarg=&replyinfo; replyinfo.info.write_func=mimeautoreply_write_func; replyinfo.info.writesig_func=mimeautoreply_writesig_func; replyinfo.info.myaddr_func=mimeautoreply_myaddr_func; replyinfo.info.replymode=replymode; replyinfo.info.replytoenvelope=replytoenvelope; replyinfo.info.donotquote=donotquote; replyinfo.info.replysalut=replysalut; replyinfo.info.forwarddescr="Forwarded message"; replyinfo.info.mailinglists=""; replyinfo.info.charset=charset; replyinfo.info.subject=subj; replyinfo.info.forwardsep=forwardsep; if (mimedsn && *mimedsn) { replyinfo.info.dsnfrom=mimedsn; replyinfo.info.replymode="replydsn"; } if (mimefile) { if ((replyinfo.contentf=fopen(mimefile, "r")) == NULL) { perror(mimefile); exit(1); } { struct rfc2045 *rfcp=rfc2045_alloc(); static const char mv[]="Mime-Version: 1.0\n"; char buf[BUFSIZ]; int l; const char *content_type; const char *content_transfer_encoding; const char *charset; rfc2045_parse(rfcp, mv, sizeof(mv)-1); while ((l=fread(buf, 1, sizeof(buf), replyinfo.contentf) ) > 0) { rfc2045_parse(rfcp, buf, l); } if (l < 0 || fseek(replyinfo.contentf, 0L, SEEK_SET) < 0) { perror(mimefile); exit(1); } rfc2045_mimeinfo(rfcp, &content_type, &content_transfer_encoding, &charset); if (strcasecmp(content_type, "text/plain")) { fprintf(stderr, "%s must specify text/plain MIME type\n", mimefile); exit(1); } { char *p=NULL; if (charset) p=libmail_u_convert_tobuf("", charset, libmail_u_ucs4_native, NULL); if (!p) { fprintf(stderr, "Unknown charset in %s\n", mimefile); exit(1); } free(p); replyinfo.info.charset=strdup(charset); } rfc2045_free(rfcp); } replyinfo.info.content_set_charset=copy_headers; replyinfo.info.content_specify=copy_body; } else if (txtfile) { if ((replyinfo.contentf=fopen(txtfile, "r")) == NULL) { perror(mimefile); exit(1); } replyinfo.info.content_specify=copy_body; } if (replyinfo.contentf) fcntl(fileno(replyinfo.contentf), F_SETFD, FD_CLOEXEC); if (nosend) replyinfo.outf=stdout; else { replyinfo.outf=tmpfile(); if (replyinfo.outf == NULL) { perror("tmpfile"); exit(1); } } { struct header *h; for (h=extra_headers; h; h=h->next) fprintf(replyinfo.outf, "%s\n", h->buf); } fprintf(replyinfo.outf, "Precedence: junk\n" "Auto-Submitted: auto-replied\n"); if (rfc2045_makereply(&replyinfo.info) < 0 || fflush(replyinfo.outf) < 0 || ferror(replyinfo.outf) || (!nosend && ( fseek(replyinfo.outf, 0L, SEEK_SET) < 0 || (close(0), dup(fileno(replyinfo.outf))) < 0) )) { perror("tempfile"); exit(1); } fclose(replyinfo.outf); fcntl(0, F_SETFD, 0); rfc2045_free(rfcp); rfc2045src_deinit(src); if (!nosend) opensendmail(argn, argc, argv); return (0); }
char *newmsg_newdraft(const char *folder, const char *pos, const char *forwardsep, const char *replysalut) { char *filename=0; char *replymode; size_t pos_n; FILE *fp; const char *mimeidptr; char *draftfilename; struct rfc2045 *rfc2045p, *rfc2045partp; int x; if (*cgi(replymode="reply") || *cgi(replymode="replyall") || *cgi(replymode="replylist") || *cgi(replymode="forward") || *cgi(replymode="forwardatt")) { pos_n=atol(pos); filename=get_msgfilename(folder, &pos_n); } if (!filename) return (0); fp=0; x=maildir_semisafeopen(filename, O_RDONLY, 0); if (x >= 0) if ((fp=fdopen(x, "r")) == 0) close(x); if (fp == 0) { free(filename); return (0); } rfc2045p=rfc2045_fromfp(fp); if (!rfc2045p) { fclose(fp); enomem(); } mimeidptr=cgi("mimeid"); rfc2045partp=0; if (*mimeidptr) { rfc2045partp=rfc2045_find(rfc2045p, mimeidptr); if (rfc2045partp) { const char *content_type, *dummy; rfc2045_mimeinfo(rfc2045partp, &content_type, &dummy, &dummy); if (!content_type || strcmp(content_type, "message/rfc822")) rfc2045partp=0; else rfc2045partp=rfc2045partp->firstpart; } } if (!rfc2045partp) rfc2045partp=rfc2045p; draftfd=maildir_createmsg(DRAFTS, 0, &draftfilename); if (draftfd < 0) { fclose(fp); rfc2045_free(rfc2045p); enomem(); } maildir_writemsgstr(draftfd, "From: "); { const char *f=pref_from; if (!f || !*f) f=login_fromhdr(); if (!f) f=""; maildir_writemsgstr(draftfd, f); maildir_writemsgstr(draftfd, "\n"); } { char *ml=getmailinglists(); struct rfc2045_mkreplyinfo ri; int rc; memset(&ri, 0, sizeof(ri)); ri.fd=fileno(fp); ri.rfc2045partp=rfc2045partp; ri.replymode=replymode; ri.replysalut=replysalut; ri.forwardsep=forwardsep; ri.myaddr_func=ismyaddr; ri.write_func=writefunc; ri.writesig_func=newmsg_writesig; ri.mailinglists=ml; ri.charset=sqwebmail_content_charset; if (strcmp(replymode, "forward") == 0 || strcmp(replymode, "forwardatt") == 0) { #if HAVE_SQWEBMAIL_UNICODE rc=rfc2045_makereply_unicode(&ri); #else rc=rfc2045_makereply(&ri); #endif } else { char *basename=maildir_basename(filename); maildir_writemsgstr(draftfd, "X-Reply-To-Folder: "); maildir_writemsgstr(draftfd, folder); maildir_writemsgstr(draftfd, "\nX-Reply-To-Msg: "); maildir_writemsgstr(draftfd, basename); free(basename); maildir_writemsgstr(draftfd, "\n"); #if HAVE_SQWEBMAIL_UNICODE rc=rfc2045_makereply_unicode(&ri); #else rc=rfc2045_makereply(&ri); #endif } free(ml); if (rc) { fclose(fp); close(draftfd); rfc2045_free(rfc2045p); enomem(); } } fclose(fp); if (maildir_closemsg(draftfd, DRAFTS, draftfilename, 1, 0)) { free(draftfilename); draftfilename=0; cgi_put("error", "quota"); } free(filename); rfc2045_free(rfc2045p); return(draftfilename); }
static void dsn(struct rfc2045 *p, int do_orig) { const char *content_type_s; const char *content_transfer_encoding_s; const char *charset_s; off_t start_pos, end_pos, start_body; off_t dummy; const char *q; char buf[BUFSIZ]; unsigned i; int ch; char *recip; char *action; char *orecip; rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s, &charset_s); if (strcasecmp(content_type_s, "multipart/report") || (q=rfc2045_getattr(p->content_type_attr, "report-type")) == 0 || strcasecmp(q, "delivery-status") || !p->firstpart || !p->firstpart->next || !p->firstpart->next->next) _exit(1); p=p->firstpart->next->next; rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s, &charset_s); rfc2045_mimepos(p, &start_pos, &end_pos, &start_body, &dummy, &dummy); if (strcasecmp(content_type_s, "message/delivery-status") || fseek(stdin, start_body, SEEK_SET) == -1) _exit(1); i=0; recip=0; orecip=0; action=0; while (start_body < end_pos) { if ((ch=getchar()) == EOF) break; ++start_body; if (i < sizeof(buf)-1) buf[i++]= ch; if (ch != '\n') continue; ch=getchar(); if (ch != EOF) ungetc(ch, stdin); if (ch != '\n' && isspace((int)(unsigned char)ch)) continue; buf[i-1]=0; if (buf[0] == 0) { if (orecip) { if (recip) free(recip); recip=orecip; orecip=0; } print_dsn_recip(recip, action); recip=0; action=0; } if (strncasecmp(buf, "Final-Recipient:", 16) == 0 && recip == 0) { recip=strdup(buf+16); if (!recip) { perror("strdup"); exit(2); } } if (strncasecmp(buf, "Original-Recipient:", 19) == 0 && orecip == 0 && do_orig) { orecip=strdup(buf+19); if (!orecip) { perror("strdup"); exit(2); } } if (strncasecmp(buf, "Action:", 7) == 0 && action == 0) { action=strdup(buf+7); if (!action) { perror("strdup"); exit(2); } } i=0; } if (orecip) { if (recip) free(recip); recip=orecip; orecip=0; } print_dsn_recip(recip, action); }
static void extract_pipe(struct rfc2045 *p, const char *filename, int argc, char **argv) { char *f=get_suitable_filename(p, "FILENAME=", 0); int pipefd[2]; pid_t pid, p2; FILE *fp; int waitstat; if (argc == 0) { fprintf(stderr, "reformime: Invalid -X option.\n"); exit(1); } if (pipe(pipefd)) { perror("pipe"); exit(1); } if ((fp=fdopen(pipefd[1], "w")) == 0) { perror("fdopen"); exit(1); } while ((pid=fork()) == -1) { sleep(2); } if (pid == 0) { const char *content_type_s; const char *content_transfer_encoding_s; const char *charset_s; if (!f) f="FILENAME=attachment.dat"; putenv(f); rfc2045_mimeinfo(p, &content_type_s, &content_transfer_encoding_s, &charset_s); f=malloc(strlen(content_type_s) +sizeof("CONTENT_TYPE=")); if (!f) { perror("malloc"); exit(1); } strcat(strcpy(f, "CONTENT_TYPE="), content_type_s); putenv(f); close(0); dup(pipefd[0]); close(pipefd[0]); close(pipefd[1]); execv(argv[0], argv); perror("exec"); _exit(1); } close(pipefd[0]); signal(SIGPIPE, SIG_IGN); do_print_section(p, fp); signal(SIGPIPE, SIG_DFL); fclose(fp); close(pipefd[1]); while ((p2=wait(&waitstat)) != pid && p2 != -1) ; free(f); }
static char *get_suitable_filename(struct rfc2045 *r, const char *pfix, int ignore_filename) { const char *disposition_s; const char *disposition_name_s; const char *disposition_filename_s; char *filename_buf; const char *content_name_s; char *p, *q; char *dyn_disp_name=0; rfc2045_dispositioninfo(r, &disposition_s, &disposition_name_s, &disposition_filename_s); content_name_s=rfc2045_contentname(r); if (!disposition_filename_s || !*disposition_filename_s) disposition_filename_s=disposition_name_s; if (!disposition_filename_s || !*disposition_filename_s) disposition_filename_s=content_name_s; filename_buf=rfc2047_decode_simple(disposition_filename_s); if (!filename_buf) { perror("rfc2047_decode_simple"); exit(1); } if (strlen(filename_buf) > 32) { p=filename_buf; q=filename_buf + strlen(filename_buf)-32; while ( (*p++ = *q++) != 0) ; } disposition_filename_s=filename_buf; if (ignore_filename) { char numbuf[NUMBUFSIZE]; static size_t counter=0; const char *p=str_size_t(++counter, numbuf); dyn_disp_name=malloc(strlen(disposition_filename_s) + strlen(p)+2); if (!dyn_disp_name) { perror("malloc"); exit(1); } disposition_filename_s=strcat(strcat(strcpy( dyn_disp_name, p), "-"), disposition_filename_s); } else if (!disposition_filename_s || !*disposition_filename_s) { dyn_disp_name=tempname("."); disposition_filename_s=dyn_disp_name+2; /* Skip over ./ */ } p=malloc((pfix ? strlen(pfix):0)+strlen(disposition_filename_s)+1); if (!p) { perror("malloc"); exit(1); } *p=0; if (pfix) strcpy(p, pfix); q=p+strlen(p); for (strcpy(q, disposition_filename_s); *q; q++) if (!isalnum(*q) && *q != '.' && *q != '-') *q='_'; if (dyn_disp_name) free(dyn_disp_name); if (!pfix) { const char *content_type_s; const char *content_transfer_encoding_s; const char *charset_s; int c; static char filenamebuf[256]; char *t; FILE *tty; if ((tty=fopen("/dev/tty", "r+")) == 0) { perror("/dev/tty"); exit(1); } rfc2045_mimeinfo(r, &content_type_s, &content_transfer_encoding_s, &charset_s); fprintf (tty, "Extract %s? ", content_type_s); fflush(tty); c=getc(tty); if (c != '\n' && c != EOF) { int cc; while ((cc=getc(tty)) != '\n' && cc != EOF) ; } if (c != 'y' && c != 'Y') { free(p); fclose(tty); free(filename_buf); return (0); } fprintf (tty, "Filename [%s]: ", p); fgets(filenamebuf, sizeof(filenamebuf)-1, tty); fclose(tty); t=strchr(filenamebuf, '\n'); if (t) *t=0; else { fprintf(stderr, "Filename too long.\n"); exit(1); } if (filenamebuf[0]) { free(p); p=strdup(filenamebuf); if (!p) { perror("malloc"); exit(1); } } } free(filename_buf); return (p); }
static void do_print_info(struct rfc2045 *s) { const char *content_type, *transfer_encoding, *charset; off_t start, end, body; const char *disposition; const char *disposition_name; const char *disposition_filename; const char *content_name; off_t nlines, nbodylines; const char *p; rfc2045_mimeinfo(s, &content_type, &transfer_encoding, &charset); rfc2045_mimepos(s, &start, &end, &body, &nlines, &nbodylines); rfc2045_dispositioninfo(s, &disposition, &disposition_name, &disposition_filename); content_name=rfc2045_contentname(s); printf("content-type: %s\n", content_type); if (content_name) { char *s=rfc2047_decode_simple(content_name); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-name: %s\n", s); free(s); } printf("content-transfer-encoding: %s\n", transfer_encoding); printf("charset: %s\n", charset); if (disposition && *disposition) printf("content-disposition: %s\n", disposition); if (disposition_name && *disposition_name) { char *s=rfc2047_decode_simple(disposition_name); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-disposition-name: %s\n", s); free(s); } if (disposition_filename && *disposition_filename) { char *s=rfc2047_decode_simple(disposition_filename); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-disposition-filename: %s\n", s); free(s); } if (*(p=rfc2045_content_id(s))) printf("content-id: <%s>\n", p); if (*(p=rfc2045_content_description(s))) { char *s=rfc2047_decode_simple(p); if (!s) { perror("rfc2047_decode_simple"); exit(1); } printf("content-description: %s\n", s); free(s); } if (*(p=rfc2045_content_language(s))) printf("content-language: %s\n", p); if (*(p=rfc2045_content_md5(s))) printf("content-md5: %s\n", p); printf("starting-pos: %lu\n", (unsigned long)start); printf("starting-pos-body: %lu\n", (unsigned long)body); printf("ending-pos: %lu\n", (unsigned long)end); printf("line-count: %lu\n", (unsigned long)nlines); printf("body-line-count: %lu\n", (unsigned long)nbodylines); }
void msgbodystructure( void (*writefunc)(const char *, size_t), int dox, FILE *fp, struct rfc2045 *mimep) { const char *content_type_s; const char *content_transfer_encoding_s; const char *charset_s; off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; const char *disposition_s; char *p, *q; rfc2045_mimeinfo(mimep, &content_type_s, &content_transfer_encoding_s, &charset_s); rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); disposition_s=mimep->content_disposition; (*writefunc)("(", 1); if (mimep->firstpart && mimep->firstpart->isdummy && mimep->firstpart->next) /* MULTIPART */ { struct rfc2045 *childp; for (childp=mimep->firstpart; (childp=childp->next) != 0; ) msgbodystructure(writefunc, dox, fp, childp); (*writefunc)(" \"", 2); p=strchr(content_type_s, '/'); if (p) msgappends(writefunc, p+1, strlen(p+1)); (*writefunc)("\"", 1); if (dox) { (*writefunc)(" ", 1); do_param_list(writefunc, mimep->content_type_attr); (*writefunc)(" ", 1); do_disposition(writefunc, disposition_s, mimep->content_disposition_attr); (*writefunc)(" ", 1); contentstr(writefunc, rfc2045_content_language(mimep)); } } else { char *mybuf; char buf[40]; const char *cp; mybuf=my_strdup(content_type_s); q=strtok(mybuf, " /"); (*writefunc)("\"", 1); if (q) msgappends(writefunc, q, strlen(q)); (*writefunc)("\" \"", 3); if (q) q=strtok(0, " /"); if (q) msgappends(writefunc, q, strlen(q)); free(mybuf); (*writefunc)("\" ", 2); do_param_list(writefunc, mimep->content_type_attr); (*writefunc)(" ", 1); cp=rfc2045_content_id(mimep); if (!cp || !*cp) contentstr(writefunc, cp); else { (*writefunc)("\"<", 2); msgappends(writefunc, cp, strlen(cp)); (*writefunc)(">\"", 2); } (*writefunc)(" ", 1); contentstr(writefunc, rfc2045_content_description(mimep)); (*writefunc)(" \"", 2); msgappends(writefunc, content_transfer_encoding_s, strlen(content_transfer_encoding_s)); (*writefunc)("\" ", 2); sprintf(buf, "%lu", (unsigned long) (end_pos-start_body+nbodylines)); /* nbodylines added for CRs */ (*writefunc)(buf, strlen(buf)); if ( (content_type_s[0] == 't' || content_type_s[0] == 'T') && (content_type_s[1] == 'e' || content_type_s[1] == 'E') && (content_type_s[2] == 'x' || content_type_s[2] == 'X') && (content_type_s[3] == 't' || content_type_s[3] == 'T') && (content_type_s[4] == '/' || content_type_s[4] == 0)) { (*writefunc)(" ", 1); sprintf(buf, "%lu", (unsigned long)nbodylines); (*writefunc)(buf, strlen(buf)); } if (mimep->firstpart && !mimep->firstpart->isdummy) /* message/rfc822 */ { (*writefunc)(" ", 1); msgenvelope(writefunc, fp, mimep->firstpart); (*writefunc)(" ", 1); msgbodystructure(writefunc, dox, fp, mimep->firstpart); (*writefunc)(" ", 1); sprintf(buf, "%lu", (unsigned long)nbodylines); (*writefunc)(buf, strlen(buf)); } if (dox) { (*writefunc)(" ", 1); contentstr(writefunc, rfc2045_content_md5(mimep)); (*writefunc)(" ", 1); do_disposition(writefunc, disposition_s, mimep->content_disposition_attr); (*writefunc)(" NIL", 4); /* TODO Content-Language: */ } } (*writefunc)(")", 1); }
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 (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; }
static void dofetchmsgbody(FILE *fp, struct fetchinfo *fi, struct imapscaninfo *i, unsigned long msgnum, struct rfc2045 *mimep) { const char *p=fi->bodysection; off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; unsigned long cnt; char buf[BUFSIZ]; char rbuf[BUFSIZ]; char *rbufptr; int rbufleft; unsigned long bufptr; unsigned long skipping; int ismsgrfc822=1; off_t start_seek_pos; struct rfc2045 *headermimep; /* ** To optimize consecutive FETCHes, we cache our virtual and physical ** position. What we do is that on the first fetch we count off the ** characters we read, and keep track of both the physical and the CRLF-based ** offset into the message. Then, on subsequent FETCHes, we attempt to ** use that information. */ off_t cnt_virtual_chars; off_t cnt_phys_chars; off_t cache_virtual_chars; off_t cache_phys_chars; headermimep=mimep; while (p && isdigit((int)(unsigned char)*p)) { unsigned long n=0; headermimep=mimep; do { n=n*10 + (*p++ - '0'); } while (isdigit((int)(unsigned char)*p)); if (mimep) { if (ismsgrfc822) { const char *ct, *dummy; if (mimep->firstpart == 0) { /* Not a multipart, n must be 1 */ if (n != 1) mimep=0; if (*p == '.') ++p; continue; } ismsgrfc822=0; rfc2045_mimeinfo(mimep, &ct, &dummy, &dummy); if (ct && strcasecmp(ct, "message/rfc822" ) == 0) ismsgrfc822=1; /* The content is another message/rfc822 */ } mimep=mimep->firstpart; while (mimep) { if (!mimep->isdummy && --n == 0) break; mimep=mimep->next; } headermimep=mimep; if (mimep && mimep->firstpart && !mimep->firstpart->isdummy) /* This is a message/rfc822 part */ { if (!*p) break; mimep=mimep->firstpart; ismsgrfc822=1; } } if (*p == '.') ++p; } if (p && strcmp(p, "MIME") == 0) mimep=headermimep; if (mimep == 0) { writes("{0}\r\n"); return; } rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); if (p && strcmp(p, "TEXT") == 0) { start_seek_pos=start_body; cnt=end_pos - start_body + nbodylines; } else if (p && strcmp(p, "HEADER") == 0) { start_seek_pos=start_pos; cnt= start_body - start_pos + (nlines - nbodylines); } else if (p && strcmp(p, "HEADER.FIELDS") == 0) { if (start_body - start_pos <= BUFSIZ) dofetchheadersbuf(fp, fi, i, msgnum, mimep, &dofetchheaderfields); else dofetchheadersfile(fp, fi, i, msgnum, mimep, &dofetchheaderfields); return; } else if (p && strcmp(p, "HEADER.FIELDS.NOT") == 0) { if (start_body - start_pos <= BUFSIZ) dofetchheadersbuf(fp, fi, i, msgnum, mimep, &dofetchheadernotfields); else dofetchheadersfile(fp, fi, i, msgnum, mimep, &dofetchheadernotfields); return; } else if (p && strcmp(p, "MIME") == 0) { if (start_body - start_pos <= BUFSIZ) dofetchheadersbuf(fp, fi, i, msgnum, mimep, &dofetchheadermime); else dofetchheadersfile(fp, fi, i, msgnum, mimep, &dofetchheadermime); return; } else if (*fi->bodysection == 0) { start_seek_pos=start_pos; cnt= end_pos - start_pos + nlines; } else /* Last possibility: entire body */ { start_seek_pos=start_body; cnt= end_pos - start_body + nbodylines; } skipping=0; if (fi->ispartial) { skipping=fi->partialstart; if (skipping > cnt) skipping=cnt; cnt -= skipping; if (fi->ispartial > 1 && cnt > fi->partialend) cnt=fi->partialend; } if (get_cached_offsets(start_seek_pos, &cnt_virtual_chars, &cnt_phys_chars) == 0 && cnt_virtual_chars <= skipping) /* Yeah - cache it, baby! */ { if (fseek(fp, start_seek_pos+cnt_phys_chars, SEEK_SET) == -1) { writes("{0}\r\n"); fetcherror("fseek", fi, i, msgnum); return; } skipping -= cnt_virtual_chars; } else { if (fseek(fp, start_seek_pos, SEEK_SET) == -1) { writes("{0}\r\n"); fetcherror("fseek", fi, i, msgnum); return; } cnt_virtual_chars=0; cnt_phys_chars=0; } cache_virtual_chars=cnt_virtual_chars; cache_phys_chars=cnt_phys_chars; writes("{"); writen(cnt); writes("}\r\n"); bufptr=0; writeflush(); rbufptr=0; rbufleft=0; while (cnt) { int c; if (!rbufleft) { rbufleft=fread(rbuf, 1, sizeof(rbuf), fp); if (rbufleft < 0) rbufleft=0; rbufptr=rbuf; } if (!rbufleft) { fetcherror("unexpected EOF", fi, i, msgnum); _exit(1); } --rbufleft; c=(int)(unsigned char)*rbufptr++; ++cnt_phys_chars; if (c == '\n') { ++cnt_virtual_chars; if (skipping) --skipping; else { if (bufptr >= sizeof(buf)) { writemem(buf, sizeof(buf)); bufptr=0; /*writeflush();*/ } buf[bufptr++]='\r'; --cnt; if (cnt == 0) break; } } ++cnt_virtual_chars; if (skipping) --skipping; else { ++body_count; if (bufptr >= sizeof(buf)) { writemem(buf, sizeof(buf)); bufptr=0; /*writeflush();*/ } buf[bufptr++]=c; --cnt; } cache_virtual_chars=cnt_virtual_chars; cache_phys_chars=cnt_phys_chars; } writemem(buf, bufptr); writeflush(); save_cached_offsets(start_seek_pos, cache_virtual_chars, cache_phys_chars); }