/* * find the best alternative part. * * turkeys have started emitting empty text/plain parts, * with the actual content in a text/html part, which complicates the choice. * * bigger turkeys emit a tiny base64-encoded text/plain part, * a small base64-encoded text/html part, and the real content is in * a text/calendar part. * * the magic lengths are empirically derived. * as turkeys devolve and mutate, this will only get worse. */ static Message* bestalt(Message *m, char *dir) { int len; char *subdir; Message *nm; Message *realplain, *realhtml, *realcal; realplain = realhtml = realcal = nil; for(nm = m->head; nm != nil; nm = nm->next){ subdir = estrstrdup(dir, nm->name); len = 0; free(readbody(nm->type, subdir, &len)); free(subdir); if(strcmp(nm->type, "text/plain") == 0 && len >= 8) realplain = nm; else if(strcmp(nm->type, "text/html") == 0 && len >= 600) realhtml = nm; else if(strcmp(nm->type, "text/calendar") == 0) realcal = nm; } if(realplain == nil && realhtml == nil && realcal) return realcal; /* super-turkey */ else if(realplain == nil && realhtml) return realhtml; /* regular turkey */ else return realplain; }
int quote(Message *m, CFid *fid, char *dir, char *quotetext) { char *body, *type; int i, n, nlines; char **lines; if(quotetext){ body = quotetext; n = strlen(body); type = nil; }else{ /* look for first textual component to quote */ type = readfile(dir, "type", &n); if(type == nil){ print("no type in %s\n", dir); return 0; } if(strncmp(type, "multipart/", 10)==0 || strncmp(type, "message/", 8)==0){ dir = estrstrdup(dir, "1/"); if(quote(m, fid, dir, nil)){ free(type); free(dir); return 1; } free(dir); } if(strncmp(type, "text", 4) != 0){ free(type); return 0; } body = readbody(m->type, dir, &n); if(body == nil) return 0; } nlines = 0; for(i=0; i<n; i++) if(body[i] == '\n') nlines++; nlines++; lines = emalloc(nlines*sizeof(char*)); nlines = getfields(body, lines, nlines, 0, "\n"); /* delete leading and trailing blank lines */ i = 0; while(i<nlines && lines[i][0]=='\0') i++; while(i<nlines && lines[nlines-1][0]=='\0') nlines--; while(i < nlines){ fsprint(fid, ">%s%s\n", lines[i][0]=='>'? "" : " ", lines[i]); i++; } free(lines); free(body); /* will free quotetext if non-nil */ free(type); return 1; }
void mesgload(Message *m, char *rootdir, char *file, Window *w) { char *s, *subdir, *name, *dir; Message *mp, *thisone; int n; dir = estrstrdup(rootdir, file); if(strcmp(m->type, "message/rfc822") != 0){ /* suppress headers of envelopes */ if(strlen(m->from) > 0){ Bprint(w->body, "From: %s\n", m->from); mesgline(m, "Date", m->date); mesgline(m, "To", m->to); mesgline(m, "CC", m->cc); mesgline(m, "Subject", m->subject); printheader(dir, w->body, extraheaders); }else{ printheader(dir, w->body, okheaders); printheader(dir, w->body, extraheaders); } Bprint(w->body, "\n"); } if(m->level == 1 && m->recursed == 0){ m->recursed = 1; readmbox(m, rootdir, m->name); } if(m->head == nil){ /* single part message */ if(strcmp(m->type, "text")==0 || strncmp(m->type, "text/", 5)==0){ mimedisplay(m, m->name, rootdir, w, 1); s = readbody(m->type, dir, &n); winwritebody(w, s, n); free(s); }else mimedisplay(m, m->name, rootdir, w, 0); }else{ /* multi-part message, either multipart or message/rfc822 */ thisone = nil; if(strcmp(m->type, "multipart/alternative") == 0){ thisone = bestalt(m, dir); if(thisone == nil){ thisone = m->head; /* in case we can't find a good one */ for(mp=m->head; mp!=nil; mp=mp->next) if(isprintable(mp->type)){ thisone = mp; break; } } } for(mp=m->head; mp!=nil; mp=mp->next){ if(thisone!=nil && mp!=thisone) continue; subdir = estrstrdup(dir, mp->name); name = estrstrdup(file, mp->name); /* skip first element in name because it's already in window name */ if(mp != m->head) Bprint(w->body, "\n===> %s (%s) [%s]\n", strchr(name, '/')+1, mp->type, mp->disposition); if(strcmp(mp->type, "text")==0 || strncmp(mp->type, "text/", 5)==0){ mimedisplay(mp, name, rootdir, w, 1); printheader(subdir, w->body, okheaders); printheader(subdir, w->body, extraheaders); winwritebody(w, "\n", 1); s = readbody(mp->type, subdir, &n); winwritebody(w, s, n); free(s); }else{ if(strncmp(mp->type, "multipart/", 10)==0 || strcmp(mp->type, "message/rfc822")==0){ mp->w = w; mesgload(mp, rootdir, name, w); mp->w = nil; }else mimedisplay(mp, name, rootdir, w, 0); } free(name); free(subdir); } } free(dir); }
int main (int argc, char *argv[]) { int use_stdin = 0; FILE *newsfile; FILE *newsfile_copy; char *bodyfile_name = NULL; FILE *bodyfile_r; FILE *bodyfile_w; char *mergefile_name = NULL; FILE *mergefile; #if defined(MAINLOOP) volatile int w = 1; while (w); #endif parse_commandline (argc, argv); if (printversion) { printf ("%s (" PACKAGE ") " VERSION "\n", Name); return 0; } if (!strcmp (newsfile_name, "-")) { use_stdin = 1; newsfile_name = nb_tmpnam (); newsfile_copy = open_write (newsfile_name); newsfile = stdin; mergefile = stdout; } else { newsfile_copy = NULL; newsfile = open_read (newsfile_name); mergefile_name = nb_tmpnam (); mergefile = open_write (mergefile_name); } if (filter) { expand_argv (new_argv, "-"); exec_filter (new_argv, &bodyfile_w, &bodyfile_r); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); newsfile = open_read (newsfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); check_child (); } else { bodyfile_name = nb_tmpnam (); bodyfile_w = open_write (bodyfile_name); expand_argv (new_argv, bodyfile_name); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); exec_program (new_argv); check_child (); newsfile = open_read (newsfile_name); bodyfile_r = open_read (bodyfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); } if (use_stdin) nb_unlink (newsfile_name); else nb_rename (mergefile_name, newsfile_name); if (!filter) nb_unlink (bodyfile_name); return 0; }