Here they are (if you're interested)B!
Note that I haven't yet tested them against regenerating an mbox. For the moment, my tests are done on a one message at the time context, using an online mailing list.
-Jose
-
#include "hypermail.h"
#include <ctype.h>
#include <errno.h>
--- 25,30 ----
-
/* ! * Prefix to prepend to all saved attachments' filenames */
/*
/* ! * Suffix to prepend to all saved attachments' filenames when the ! * headers don't propose a filename */
/* * Prefix to prepend to all saved attachments' directory names (before ***************
*/
#define DIR_PREFIXER "att-"
+
/* * Used to replace invalid characters in supplied attachment filenames */ *************** *** 93,113 **** return (inlist(set_inline_types, type));}
! int preferedcontent(char *type)
{
! /* We let plain text remain PREFERED at all times */ ! if(!strcasecmp("text/plain", type)) ! return 1; ! /* ! ** Parsing for embedded html needs more work before we ! ** can actually do this... ! */ ! if(set_prefered_types) { ! return (inlist(set_prefered_types, type));
}
! return 0;
}
int textcontent(char *type)
--- 93,133 ----
return (inlist(set_inline_types, type)); }
! int preferedcontent(int *current_weight, char *type) {
! int weight; ! int status; ! ! status = 0; ! /* We let plain text remain PREFERED at all times */ ! if(!strcasecmp("text/plain", type)) { ! if (*current_weight != 0) { ! /* to avoid having two text/plain alternatives */ ! *current_weight = 0; ! status = 1; ! } ! } ! /* find the weight of the type arg. If the weight is ! inferior to the current_weight, we make it the ! prefered content */ ! else if (set_prefered_types) { ! weight = inlist_pos (set_prefered_types, type); ! if (weight != -1) { ! /* +1 so that weight 0 is reserved for text/plain */ ! weight++; ! if (*current_weight == -1) { ! *current_weight = weight; ! status = 1; ! } ! else if (*current_weight > weight) { ! *current_weight = weight; ! status = 1; ! } ! }
}
! return status;
}
int textcontent(char *type)
! void emptydir(char *firstdir, char *directory)
{
struct stat fileinfo;
! char *realdir = maprintf("%s%c%s", firstdir, PATH_SEPARATOR, directory);
if(!lstat(realdir, &fileinfo)) {
if(S_ISDIR(fileinfo.st_mode)) {
--- 897,907 ----
}
! void emptydir(char *directory)
{
struct stat fileinfo;
! char *realdir = directory;
if(!lstat(realdir, &fileinfo)) {
if(S_ISDIR(fileinfo.st_mode)) {
/*
--- 924,929 ----
/* -- variables for the multipart/alternative parser -- */
struct body *origbp=NULL; /* store the original bp */ struct body *origlp=NULL; /* ... and the original lp */ char alternativeparser=FALSE; /* set when inside alternative parser mode *//* -- end of alternative parser variables -- */
struct body *bp;
--- 951,980 ----
char *emailp =NULL;
char line[MAXLINE],
fromdate[DATESTRLEN]="";
! char *cp;
! char *dp = NULL;
int num, isinheader, hassubject, hasdate; struct emailinfo *emp;
! char *att_dir=NULL; /* directory name to store attachments in */ ! ! typedef enum { ! NO_FILE, ! MAKE_FILE, ! MADE_FILE ! } FileStatus; /* for attachments */ /* -- variables for the multipart/alternative parser -- */ struct body *origbp=NULL; /* store the original bp */ struct body *origlp=NULL; /* ... and the original lp */ char alternativeparser=FALSE; /* set when inside alternative parser mode */ + int alternative_weight=-1; /* the current weight of the prefered alternative content */ + struct body *alternative_lp; /* the previous alternative lp */ + struct body *alternative_bp; /* the previous alternative bp */ + FileStatus alternative_lastfile_created = NO_FILE; /* previous alternative attachments, for non-inline MIME types */ + char alternative_file[129]; /* file name where we store the non-inline alternatives */ + char alternative_lastfile[129]; /* last file name where we store the non-inline alternatives */+ int att_counter = 0; /* used to generate a unique name for attachments */ +
/* -- end of alternative parser variables -- */
struct body *bp;
char *binname=NULL; /* file name to store binary attachments in */
int binfile=-1;
-
char *charset=NULL; /* this is the LOCAL charset used in the mail */
char *boundary;
char type[129]; /* for Content-Type type */
char charbuffer[129]; /* for Content-Type charset */
! enum { ! NO_FILE, ! MAKE_FILE, ! MADE_FILE ! } file_created = NO_FILE; /* for attachments */
char attachname[129]; /* for attachment file names */
EncodeType decode=ENCODE_NORMAL;
ContentType content=CONTENT_TEXT;
--- 1002,1018 ----
char *binname=NULL; /* file name to store binary attachments in */
int binfile=-1;
char *charset=NULL; /* this is the LOCAL charset used in the mail */
char *boundary;
char type[129]; /* for Content-Type type */
char charbuffer[129]; /* for Content-Type charset */
! FileStatus file_created = NO_FILE; /* for attachments */
char attachname[129]; /* for attachment file names */
+ char inline_force = FALSE; /* show a attachment in-line, regardles of + the content_disposition */ + char *description = NULL; /* user-supplied description for an attachment */
EncodeType decode=ENCODE_NORMAL;
ContentType content=CONTENT_TEXT;
/*
--- 1087,1097 ----
/*
else if (!strncasecmp( head->line, "Content-Type:", 13)) { char *ptr=head->line+13; --- 1178,1205 ---- safe_filename(attachname); } else { ! attachname[0]='\0'; /* just clear it */ } file_created = MAKE_FILE; /* please make one */ } ! else if (!strncasecmp(ptr, "inline;", 7) ! && (content != CONTENT_IGNORE) ! && (!strncasecmp (type, "image/", 5))) { ! inline_force = TRUE; ! /* make sure it is binary */ ! content = CONTENT_BINARY; ! /* see if there's a file name to use: */ ! fname = strstr(ptr, "filename="); ! if (fname) { ! sscanf(fname+10, "%128[^\"]", attachname); ! safe_filename(attachname); ! } ! else { ! attachname[0]='\0'; /* just clear it */ ! } ! file_created = MAKE_FILE; /* please make one */ ! } ! } else if (!strncasecmp( head->line, "Content-Type:", 13)) { char *ptr=head->line+13;
! if(alternativeparser) { ! /* We are parsing alternatives... */ ! if(preferedcontent(type) ) { ! /* ... this is a prefered type, we want to store this [instead of the earlier one]. */
#if 0
! struct body *next; ! printf("%s is more fun than the previous one\n", ! type); ! #endif ! #if 0 ! /* ! ** Not sure why this free section is here. ! ** It is causing purify to barf with massive numbers of ! ** "FMR: Free memory reads". When I commented it out it ! ** cleared up the problem with no associated memory leaked ! ** or difference in output. It's history for now. ! */ ! while(bp) { ! next=bp->next; ! if (bp->line) free(bp->line); ! if (bp) free(bp); ! bp=next; ! }
#endif
! headp = NULL; } else { /* ...and this type is not a prefered one. Thus, we * shall ignore it completely! */ content = CONTENT_IGNORE; } ! } ! if(ignorecontent(type)) { ! /* don't save this */ ! content = CONTENT_IGNORE; ! } ! else if (textcontent(type) || ! (inlinehtml && !strcasecmp(type, "text/html"))) { ! /* text content or text/html follows. ! */ ! ! if (!strcasecmp(type, "text/html")) ! content = CONTENT_HTML; ! else ! content = CONTENT_TEXT; ! continue; ! } else if (!strncasecmp(type, "message/rfc822", 14)) { /* ** Here comes an attached mail! This can be ugly, --- 1232,1305 ---- charset = strsav(charbuffer); } ! if (alternativeparser) { ! struct body *next, *temp_bp; ! ! /* We are parsing alternatives... */ ! if(preferedcontent(&alternative_weight, type) ) { ! /* ... this is a prefered type, we want to store this [instead of the earlier one]. */
#if 0
! printf("%s is more fun than the previous one\n", ! type);
#endif
! /* erase the previous alternative info */ ! temp_bp = alternative_bp; /* remember the value of bp for GC */ ! alternative_bp = alternative_lp = NULL; ! alternative_lastfile_created = NO_FILE; ! content = CONTENT_UNKNOWN; ! if (alternative_lastfile[0] != '\0') { ! /* remove the previous attachment */ ! unlink (alternative_lastfile); ! alternative_lastfile[0] = '\0'; ! } } else { /* ...and this type is not a prefered one. Thus, we * shall ignore it completely! */ content = CONTENT_IGNORE; + /* erase the current alternative info */ + temp_bp = bp; /* remember the value of bp for GC */ + lp = alternative_lp; + bp = alternative_bp; + strcpy (alternative_file, alternative_lastfile); + file_created = alternative_lastfile_created; + alternative_bp = alternative_lp = NULL; + alternative_lastfile_created = NO_FILE; + alternative_lastfile[0] = '\0'; + /* we haven't yet created any attachment file, so there's no need + to erase it yet */ } ! /* free any previous alternative */ ! while (temp_bp) { ! next = temp_bp->next; ! if (temp_bp->line) free (temp_bp->line); ! free (temp_bp); ! temp_bp = next; ! } ! /* _at_@ not sure if I should add a diff flag to do this break */ ! if (content == CONTENT_IGNORE) ! /* end the header parsing... we already know what we want */ ! break; ! } ! ! if (content == CONTENT_IGNORE) ! continue; ! else if (ignorecontent(type)) ! /* don't save this */ ! content = CONTENT_IGNORE; ! else if (textcontent(type) ! || (inlinehtml && !strcasecmp(type, "text/html"))) { ! /* text content or text/html follows and we should display it ! */ ! ! if (!strcasecmp(type, "text/html")) ! content = CONTENT_HTML; ! else ! content = CONTENT_TEXT; ! continue; ! } else if (!strncasecmp(type, "message/rfc822", 14)) { /* ** Here comes an attached mail! This can be ugly,
file_created = MAKE_FILE; /* please make one */ --- 1340,1346 ---- safe_filename(attachname); } else { ! attachname[0]='\0'; /* just clear it */ } file_created = MAKE_FILE; /* please make one */
alternativeparser = TRUE;
-
/* restart on a new list: */ lp=bp=NULL; } headp = lp; /* start at this point next time */ } else { ! bp = addbody(bp, &lp, line, BODY_HEADER|bodyflags); } } else { --- 1492,1509 ---- origlp=lp; alternativeparser = TRUE; /* restart on a new list: */ lp=bp=NULL; + /* clean the alternative status variables */ + alternative_weight = -1; + alternative_lp = alternative_bp = NULL; + alternative_lastfile_created = NO_FILE; + alternative_file[0] = alternative_lastfile[0] = '\0'; } headp = lp; /* start at this point next time */ } else { ! bp = addbody(bp, &lp, line, BODY_HEADER|bodyflags); } } else {
num++;
- - /* create a directory name to store all attachments in */ - if(newdir) - free(newdir); - newdir = maprintf("%s%04d", DIR_PREFIXER, num); - - /* If this is a repeated run on the same archive we already have - * HTML'ized, we risk extracting the same attachments several times - * and therefore we need to remove all the attachments currently - * present before we go ahead! (Daniel -- August 6, 1999) */ - - emptydir(dir, newdir); } if(hasdate)
/* by default we have none! */ hassubject = 0;
isinheader = 0; /* no header, the ending boundary can't have any describing --- 1628,1642 ---- !strncmp(line, "--", 2) && !strncmp(line+2, boundp->line, strlen(boundp->line))) { /* right at this point, we have another part coming up */! #endif
#if 0
printf("hit %s\n", line);
#endif
if (!strncmp(line+2+strlen(boundp->line), "--", 2)) { + /* _at_@@ don't know why we had this line here. Doesn't hurt to take + it out, though */ + #if 0 bp = addbody(bp,&lp,"\n",BODY_HTMLIZED|bodyflags);
isinheader = 0; /* no header, the ending boundary can't have any describing
file_created = MADE_FILE; /* we have, or at least we tried */ ! /* If we found a name then lets check it out to see if we can use ! * it. */ ! ! if (fname[0]) { ! /* Check if we can use this attached name * for storing: */ ! ! if(strlen(fname) + ! strlen(dir) + ! strlen(newdir) + ! strlen(FILE_PREFIXER) <= 500) { ! /* yes, we have room in our array */ ! struct stat fileinfo; ! char alter[2]=""; ! int counter='a'; ! ! mkdir(newdir, set_dirmode); ! ! fprintf(stderr, "\nCreated dir %s\n", newdir); ! ! nameisuniq=TRUE; ! do { ! sprintf(checkpath, "%s%c%s%c" FILE_PREFIXER "%s%s", ! dir, PATH_SEPARATOR, ! newdir, PATH_SEPARATOR, ! alter, fname); ! /* loop while the file exist and try a few ! alternative file names before giving up */ ! if(counter>='z') { ! nameisuniq=FALSE; /* we didn't find a unique file name */ ! break; ! } ! sprintf(alter, "%c", counter++); ! } while(0 == lstat(checkpath, &fileinfo)); ! } ! } /* Saving of the attachments is being done inline as they are * encountered. The directories must exist first... */ ! ! if(!nameisuniq) { ! /* first make the path to create this in */ ! sprintf(checkpath, "%s%c%s", ! dir, PATH_SEPARATOR, ! newdir); ! /* get a random name */ ! binname = tmpname(checkpath, FILE_PREFIXER "bin"); ! } ! else ! binname = checkpath; ! if (binname) { ! binfile=open(binname, O_WRONLY|O_CREAT, ! set_filemode); if(-1 != binfile) { chmod(binname, set_filemode); if(set_showprogress) - print_progress(num,lang[MSG_CREATED_ATTACHMENT_FILE],binname); ! } ! ! file=strrchr(binname, PATH_SEPARATOR); ! if (file) ! file++; /* pass the separator */ ! else ! file=binname; ! } ! ! if( inlinecontent(type) ) { ! /* if we know our browsers can show this type of context ! as-is, we make a <IMG> tag instead of <A HREF>! */ ! ! snprintf(buffer, sizeof(buffer), ! "%s<IMG SRC=\"%s/%s\" ALT=\"%s\">\n", ! (set_showhr ? "<HR>\n" : ""), ! newdir, ! file, ! fname ? fname : "picture"); ! } ! else { ! snprintf(buffer, sizeof(buffer), ! "%s<UL>\n<LI>%s %s: <A HREF=\"%s/%s\">%s</A>\n</UL>\n", ! (set_showhr ? "<HR>\n" : ""), ! type, ! lang[MSG_ATTACHMENT], ! newdir, ! file ? file : "<void>", ! fname[0] ? fname : "stored"); ! ! } ! /* Print attachment comment before attachment */ ! bp = addbody(bp, &lp, buffer, BODY_HTMLIZED|bodyflags); ! snprintf(buffer, sizeof(buffer), ! "<!-- attachment=\"%.80s\" -->\n", ! file); ! bp = addbody(bp, &lp, buffer, BODY_HTMLIZED|bodyflags); ! if (binname && (binfile!=-1)) ! content = CONTENT_BINARY; ! else ! content = CONTENT_UNKNOWN; ! ! if (!nameisuniq && binname) ! free(binname); ! } ! }
#endif
if (-1 != binfile) { if (datalen < 0)
} else if (content == CONTENT_BINARY) {
#ifndef REMOVED_990310
/* If there is no file created, we create and init one */ if(file_created == MAKE_FILE) { ! char *fname; ! char *binname; ! char *file = NULL; ! char buffer[512]; file_created = MADE_FILE; /* we have, or at least we tried */ ! /* create the attachment directory if it doesn't exist */ ! if (att_dir == NULL) { ! /* first check the DIR_PREFIXER */ ! att_dir = maprintf ("%s%c" DIR_PREFIXER "%.4d", dir, ! PATH_SEPARATOR, num); ! check1dir (att_dir); ! /* If this is a repeated run on the same archive we already ! * have HTML'ized, we risk extracting the same attachments ! * several times and therefore we need to remove all the ! * attachments currently present before we go ahead! ! *(Daniel -- August 6, 1999) */ ! /* jk: removed it for a while, as it's not so necessary ! once we can generate the same file names */ ! #if 0 ! emptydir(att_dir); ! #endif ! } ! ! /* If the attachment has a name, we keep it and add the ! current value of the counter, to guarantee that we ! have a unique name. Otherwise, we use a fixed name + ! the counter. We go thru all this trouble so that we ! can easily regenerate the same archive, without breaking ! any links */ ! ! if (att_counter > 99) ! binname = NULL; ! else { ! if (attachname[0]) ! fname = attachname; ! else ! fname = FILE_SUFFIXER; ! ! binname = maprintf ("%s%c%.2d-%s", ! att_dir, PATH_SEPARATOR, att_counter, ! fname); ! att_counter++; ! } /* Saving of the attachments is being done inline as they are * encountered. The directories must exist first... */ ! if (binname) { ! binfile = open(binname, O_WRONLY|O_CREAT, ! set_filemode); if(-1 != binfile) { chmod(binname, set_filemode); if(set_showprogress) print_progress(num,lang[MSG_CREATED_ATTACHMENT_FILE],binname); ! ! if (alternativeparser) ! /* save the last name, in case we need to supress it */ ! strncpy (alternative_file, binname, sizeof (alternative_file) -1); ! } else { ! if (alternativeparser) ! /* save the last name, in case we need to supress it */ ! alternative_file[0] = '\0'; ! } ! ! /* point to the filename and skip the separator */ ! file = &binname[strlen (dir) + 1]; ! ! /* protection against having a filename bigger than buffer */ ! if (strlen (file) <= 500) { ! char *desc; ! ! if (description && description[0] != '\0') ! desc = description; ! else if (inline_force || inlinecontent(type)) ! desc = attachname[0] ? attachname : "picture"; ! else ! desc = attachname[0] ? attachname : "stored"; ! ! if (description) ! description = NULL; ! ! if( inline_force || inlinecontent(type) ) { ! /* if we know our browsers can show this type of context ! as-is, we make a <IMG> tag instead of <A HREF>! */ ! ! snprintf(buffer, sizeof(buffer), ! "%s<IMG SRC=\"%s\" ALT=\"%s\">\n", ! (set_showhr ? "<HR>\n" : ""), file, ! desc); ! } ! else { ! snprintf(buffer, sizeof(buffer), ! "%s<UL>\n<LI>%s %s: <A HREF=\"%s\">%s</A>\n</UL>\n", ! (set_showhr ? "<HR>\n" : ""), type, ! lang[MSG_ATTACHMENT], ! file ? file : "<void>", ! desc); ! } ! ! /* Print attachment comment before attachment */ ! bp = addbody(bp, &lp, buffer, BODY_HTMLIZED|bodyflags); ! snprintf(buffer, sizeof(buffer), ! "<!-- attachment=\"%.80s\" -->\n", ! file); ! bp = addbody(bp, &lp, buffer, BODY_HTMLIZED|bodyflags); ! } ! } ! inline_force = FALSE; ! attachname[0] = '\0'; ! ! if (binname && (binfile!=-1)) ! content = CONTENT_BINARY; ! else ! content = CONTENT_UNKNOWN; ! ! if (binname) ! free (binname); ! } ! }
#endif
if (-1 != binfile) { if (datalen < 0)
if (!isinheader || readone) {
if (!hassubject) subject = NOSUBJECT; --- 1939,1946 ---- } }
+
if (!isinheader || readone) {
if (!hassubject) subject = NOSUBJECT;
+ /* _at_@@ if we didn't add the mail, we should consider erasing the attdir + if it's there */ + if(hasdate) free(date); if(hassubject)
+ /* reset the status counters */ + /* _at_@ verify we're doing it everywhere */ + bodyflags=0; /* reset state flags */ + + /* go back to default mode: */ + content = CONTENT_TEXT; + decode = ENCODE_NORMAL; + Mime_B = FALSE; + headp = NULL; + multilinenoend = FALSE; + if (att_dir) { + free (att_dir); + att_dir = NULL; + } + att_counter = 0; + description = NULL; + + /* by default we have none! */ + hassubject = 0; + hasdate = 0; }
if (set_showprogress && !readone) Received on Sat 14 Aug 1999 07:06:20 PM GMT
This archive was generated by hypermail 2.2.0 : Thu 22 Feb 2007 07:33:51 PM GMT GMT