This is metamail.c in view mode; [Download] [Up]
/* Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore) Permission to use, copy, modify, and distribute this material for any purpose and without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies, and that the name of Bellcore not be used in advertising or publicity pertaining to this material without the specific, prior written permission of an authorized representative of Bellcore. BELLCORE MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. */ /****************************************************** Metamail -- A tool to help diverse mail readers cope with diverse multimedia mail formats. Author: Nathaniel S. Borenstein, Bellcore ******************************************************* */ #import <stdio.h> #import <ctype.h> #import <libc.h> #import "config.h" #import <streams/streams.h> #import "mem_file_desc.h" #import <pwd.h> #import <sys/time.h> #import <signal.h> #include <sgtty.h> #define TMPFILE_NAME_SIZE 1000 #define MAX_FILE_NAME_SIZE 1000 #ifndef NO_RLIMITS #include <sys/resource.h> #endif #define LoStr(key) doLocalString(NULL,key,NULL) #define LINE_BUF_SIZE 2000 char fileToDelete[MAX_FILE_NAME_SIZE]; char *FindParam(); extern int NXRunAlertPanel(), doLocalString(); static char *nomem = "Out of memory!"; NXStream *InputFP = NULL; int EatLeadingNewlines = 0, PrintSomeHeaders = 1, DoInBackground = 0, Is822Format = 1, DoDebug = 0, CParamsAlloced = 0, CParamsUsed = 0, YankMode = 0, UsingStandardInput = 0; int count=1; int headpart=0; char *ContentType = NULL, *ContentEncoding = NULL, *Mimeversion = NULL, *MailerName = "unknown", *MailSubject = "Mail message", *MailFrom = "unknown sender", *MailSummary = "non-text mail message", *mailheaders = NULL, **CParams = NULL, **CParamValues = NULL, *JunkParameter = NULL; #define ENCODING_NONE 0 #define ENCODING_BASE64 1 #define ENCODING_QUOTEDPRINTABLE 2 #define ENCODING_8BIT 3 #define ENCODING_UUENCODE -1 /* non-standard */ int EncodingCode = ENCODING_NONE; char *Cleanse(s) /* no leading or trailing space, all lower case */ char *s; { char *tmp, *news; /* strip leading white space */ while (*s && isspace((unsigned char) *s)) ++s; news = s; /* put in lower case */ for (tmp=s; *tmp; ++tmp) { if (isupper((unsigned char) *tmp)) *tmp = tolower((unsigned char) *tmp); } /* strip trailing white space */ while (*--tmp && isspace((unsigned char) *tmp)) *tmp = 0; return(news); } char *UnquoteString(s) char *s; { char *ans, *t; void ExitWithError(); if (*s != '"') return(s); ans = malloc(1+strlen(s)); if (!ans) ExitWithError(nomem); ++s; t = ans; while (*s) { if (*s == '\\') { *t++ = *++s; } else if (*s == '"') { break; } else { *t++ = *s; } ++s; } *t = 0; return(ans); } char **Boundaries = NULL; int BoundaryCt = 0, BoundaryAlloc = 0; #define getc(x) NXGetc(x) #define ungetc(x,y) NXUngetc(y) #define putc(x,stream) NXPutc(stream,x) struct mem_file_desc *articles_desc = NULL; struct mem_file_desc **adpp = &articles_desc; struct mem_file_desc *get_Item(stream) NXStream *stream; { void ResetGlobals(); int HandleMessage(); int retcode=0; InputFP = stream; ResetGlobals(); retcode |= HandleMessage(NULL, 0); *adpp = NULL; return(articles_desc) ; } void ResetGlobals() { int ExitWithError(); CParamsAlloced = 0; CParamsUsed = 0; ContentType = NULL; Mimeversion = NULL; ContentEncoding = NULL; MailSubject = "Mail message"; MailFrom = "unknown sender"; MailSummary = "non-text mail message"; // mailheaders = getenv("MM_HEADERS"); mailheaders = NULL; // if (mailheaders) { // char *s; // s = malloc(15+strlen(mailheaders)); // if (!s) ExitWithError(nomem); // sprintf(s, "MM_HEADERS=%s", mailheaders); // mailheaders = s; // } CParams = NULL; CParamValues = NULL; JunkParameter = NULL; count=1; headpart=0; // articles_desc = (struct mem_file_desc *)NULL; // articles_desc=(struct mem_file_desc *)malloc(sizeof(struct mem_file_desc)); *adpp = (struct mem_file_desc *)&(articles_desc->fd_nextp); } int CheckTmp(SquirrelFile) char *SquirrelFile; { int SaveSquirrelFile(),MkTmpFileName(),WriteTmpFile(); if (SquirrelFile) { return(SaveSquirrelFile(SquirrelFile)); } else { char TmpFileName[TMPFILE_NAME_SIZE]; MkTmpFileName(TmpFileName); return(WriteTmpFile(TmpFileName)); } } int HandleMessage(SquirrelFile, nestingdepth) char *SquirrelFile; /* SquirrelFile, if non-NULL, is a place to save a recognized body instead of executing it. */ int nestingdepth; { int Read822Prefix(),PrepareMessage(),lc2strcmp(),WriteTmpFile(); int SaveSquirrelFile(),lc2strncmp(); int MkTmpFileName(),ConsumeRestOfPart(),CreateMMP(); int TranslateInputToOutput(),ExitWithError() ; int c; int r822; int len,max; char *buff, *makelower(); char *extfilename=NULL; char *accesstype=NULL; char *Extsite=NULL; char *Extname=NULL; char *UnquoteString(); NXStream *textonly; NXStream *externalB; if (Is822Format) { r822=Read822Prefix(SquirrelFile?0:1, nestingdepth); if ( r822 == -1) return(-1); } else Is822Format = 1; /* this property is not recursive for multipart or message */ PrepareMessage(); if (!lc2strcmp(Mimeversion,"1.0") && count == 1 ){ textonly = NXOpenMemory(NULL,0,NX_READWRITE); NXGetMemoryBuffer(InputFP,&buff,&len,&max); NXWrite(textonly, (const void *)buff, len); CreateMMP(textonly,"textonly.plain"); count++; return(-1); } if (!lc2strcmp(ContentType,"text") || !lc2strcmp(ContentType, "text/plain") || !lc2strcmp(ContentType,"text/richtext")) { CheckTmp(SquirrelFile); return(0); } if (!lc2strcmp(ContentType,"image") || !lc2strcmp(ContentType, "image/tiff") || !lc2strcmp(ContentType,"image/gif") || !lc2strcmp(ContentType,"image/jfif") || !lc2strcmp(ContentType,"image/jpeg") || !lc2strcmp(ContentType,"image/eps")) { Extname = FindParam("name"); if ( Extname ){ extfilename = (char *) calloc (200, sizeof(char)); sprintf(extfilename,"/%s", Extname); WriteTmpFile(extfilename); } else{ CheckTmp(SquirrelFile); } // CheckTmp(SquirrelFile); return(0); } if (!lc2strcmp(ContentType,"audio") || !lc2strcmp(ContentType, "audio/basic") || !lc2strcmp(ContentType,"audio/next")) { Extname = FindParam("name"); if ( Extname ){ extfilename = (char *) calloc (200, sizeof(char)); sprintf(extfilename,"/%s", Extname); WriteTmpFile(extfilename); } else{ CheckTmp(SquirrelFile); } // CheckTmp(SquirrelFile); return(0); } if (!lc2strcmp(ContentType,"application") || !lc2strcmp(ContentType, "application/andrew-inset") || !lc2strcmp(ContentType, "application/x-be2") || !lc2strcmp(ContentType, "application/postscript") || !lc2strcmp(ContentType,"application/ps")) { CheckTmp(SquirrelFile); return(0); } if (!lc2strcmp(ContentType,"application") || !lc2strcmp(ContentType, "application/octet-stream")) { Extname = FindParam("name"); if ( Extname ){ Extname = makelower(Extname); WriteTmpFile(Extname); } else{ externalB = NXOpenMemory(NULL,0,NX_READWRITE); CreateMMP(externalB, "/octet.vox"); } return(0); } if (!lc2strcmp(ContentType, "message") || !lc2strcmp(ContentType, "message/external-body")) { // || !lc2strcmp(ContentType, "message/rfc822")) { accesstype = FindParam("access-type"); if ( accesstype ){ accesstype = makelower(accesstype); if( !strcmp(accesstype, "local-file") ){ Extname = FindParam("name"); extfilename = (char *) calloc (200, sizeof(char)); sprintf(extfilename,"%s.local-file", Extname); }else if ( !strcmp(accesstype, "anon-ftp")){ Extname = FindParam("name"); Extsite = FindParam("site"); extfilename = (char *) calloc (200, sizeof(char)); sprintf(extfilename,"%s@%s.anon-ftp", Extname, Extsite); }else if ( !strcmp(accesstype, "x-news")){ Extname = FindParam("name"); extfilename = (char *) calloc (200, sizeof(char)); sprintf(extfilename,"%s.X-news", Extname); }else{ fprintf(stderr,"%s is not support yet.", accesstype); return(0); } externalB = NXOpenMemory(NULL,0,NX_READWRITE); CreateMMP(externalB, extfilename); }else{ externalB = NXOpenMemory(NULL,0,NX_READWRITE); CreateMMP(externalB, "/text.plain"); } // CheckTmp(SquirrelFile); return(0); // if (SquirrelFile) return(SaveSquirrelFile(SquirrelFile)); // ContentType = NULL; /* reset default */ // ContentEncoding = NULL; /* reset default */ // return(HandleMessage(NULL, nestingdepth+1)); /* simple recursion */ } if (!lc2strncmp(ContentType, "multipart", 9)) { char *boundary, *LineBuf, NewSquirrelFile[TMPFILE_NAME_SIZE]; char *subtype = NULL; int currct, result, IsAlternative, WroteSquirrelFile; if (SquirrelFile) return(SaveSquirrelFile(SquirrelFile)); boundary = FindParam("boundary"); if (!boundary) boundary =JunkParameter; /* backward compatibility hack */ if (!boundary) { ExitWithError("Bad message format -- multipart message has no boundary parameter!"); } if (boundary[0] == '"') { boundary=UnquoteString(boundary); } subtype = index(ContentType, '/'); if (subtype) { ++subtype; subtype = Cleanse(subtype); } else subtype = "mixed"; #ifndef __MSDOS__ DoInBackground = strcmp(subtype, "parallel") ? 0 : 1; #endif IsAlternative = strcmp(subtype, "alternative") ? 0 : 1; IsAlternative = 0; if (IsAlternative) { MkTmpFileName(NewSquirrelFile); WroteSquirrelFile = 0; } LineBuf = malloc(LINE_BUF_SIZE); if (!LineBuf) ExitWithError(nomem); sprintf(LineBuf, "--%s", boundary); strcpy(boundary, LineBuf); if (BoundaryCt >= BoundaryAlloc) { BoundaryAlloc += 5; if (Boundaries) { Boundaries = (char **) realloc(Boundaries, BoundaryAlloc*sizeof(char *)); } else { Boundaries = (char **) malloc(BoundaryAlloc*sizeof(char *)); } if (!Boundaries) ExitWithError(nomem); } Boundaries[BoundaryCt++] = boundary; if (DoDebug) printf("Handling multipart as built-in here. Boundary: %s\n", boundary); c = 1; while (c != -1 ) { /* find start */ // c = readline(InputFP, LineBuf, LINE_BUF_SIZE); c = NXScanf(InputFP,"%1998[^\r\n]\r\n",LineBuf); if (!strncmp(LineBuf, boundary, strlen(boundary))) break; } free(LineBuf); currct = BoundaryCt; while(currct == BoundaryCt) { if (!strcmp(subtype, "digest")) { ContentType = "message/rfc822"; } else { ContentType = NULL; /* reset default */ } ContentEncoding = NULL; /* reset default */ if (IsAlternative) { result = HandleMessage(NewSquirrelFile, nestingdepth+1); } else{ result = HandleMessage(NULL, nestingdepth+1); if (result == -1 )return(-1); } if (result) { /* Need to consume the rest of the part */ char TmpFileName[TMPFILE_NAME_SIZE]; NXStream *newfp; MkTmpFileName(TmpFileName); newfp = NXOpenMemory(NULL,0,NX_READWRITE); if (!newfp) ExitWithError("Cannot open temporary file"); ConsumeRestOfPart(newfp); CreateMMP(newfp,TmpFileName); //NXCloseMemory(newfp,NX_FREEBUFFER); } else { ++WroteSquirrelFile; } } /* Now we've seen the last encapsulation boundary, but if there is a "postfix" we must throw it away.*/ if (BoundaryCt > 0) { char TmpFileName[TMPFILE_NAME_SIZE]; NXStream *newfp; MkTmpFileName(TmpFileName); newfp = NXOpenMemory(NULL,0,NX_READWRITE); if (!newfp) ExitWithError("Cannot open temporary file"); ConsumeRestOfPart(newfp); CreateMMP(newfp,TmpFileName); //NXCloseMemory(newfp,NX_FREEBUFFER); } // if (IsAlternative) { // if (WroteSquirrelFile) { // int retcode; // char Cmd[TMPFILE_NAME_SIZE + 15]; // sprintf(Cmd, "%s %s", METAMAIL, NewSquirrelFile); // fflush(stdout); fflush(stderr); // retcode = system(Cmd); // unlink(NewSquirrelFile); // return(retcode); // } else { // printf("Cannot handle any part of multipart/alternative message\n"); // } // } return(0); } if (ContentType){ if (strlen(ContentType) >= 1){ CheckTmp(SquirrelFile); return(0); } } if (!SquirrelFile) { /* Very last resort -- unrecognized types */ char Fname[MAX_FILE_NAME_SIZE]; NXStream *fp; if (Fname[0] == 0 || Fname[0] == '\n') { char TmpFileName[TMPFILE_NAME_SIZE]; NXStream *newfp; MkTmpFileName(TmpFileName); newfp = NXOpenMemory(NULL,0,NX_READWRITE); if (!newfp) ExitWithError("Cannot open temporary file"); ConsumeRestOfPart(newfp); CreateMMP(newfp,TmpFileName); //NXCloseMemory(newfp,NX_FREEBUFFER); return(0); } else { fp = NXOpenMemory(NULL,0,NX_READWRITE); if (!fp) ExitWithError("Cannot open temporary file"); TranslateInputToOutput(InputFP, fp, EncodingCode); CreateMMP(fp,Fname); //NXCloseMemory(fp,NX_FREEBUFFER); return(0); } } return(-1); /* Unrecognized, really */ } int writeline(stream,ptr,nbytes) char *ptr; NXStream *stream; int nbytes; { int nleft, nread; char c, *Buf; nleft = nbytes; nread = 0; Buf = ptr; while( nleft > 0){ c = *Buf++; if( c != '\n' ) { NXPutc(stream,c); nread++; } else { NXPutc(stream,c); return(0); } nleft--; } return( nread ); } int readline(stream,ptr,nbytes) NXStream *stream; char *ptr; int nbytes; { int nleft, nread; char c; nleft = nbytes; nread = 0; while( nleft > 0){ c = NXGetc(stream); if( c != '\n' && c != EOF) { *ptr++ = c; nread++; } else { if ( c == EOF ) { *ptr++=c; return( -1 ); } *ptr++='\n'; *ptr++='\0'; return( nread+1 ); } nleft--; } *ptr++='\0'; return( nread ); } void usage() { int ExitWithError(); ExitWithError(NULL); } void CleanBuf(buf, si) char *buf; int si; { int i; for( i = 0; i < si ; i++) buf[i]='\0'; } int SaveSquirrelFile(SquirrelFile) char *SquirrelFile; { int TranslateInputToOutput(),CreateMMP(); NXStream *outfp; char ffff[1024]; CleanBuf(ffff, sizeof(ffff)); outfp = NXOpenMemory(NULL, 0, NX_READWRITE); if (!outfp) { fprintf(stderr, "Cannot open %s to squirrel away a portion of a multipart/alternative\n", SquirrelFile); return(-1); } // NXPrintf(outfp, "Content-type: %s", ContentType); // for (j=0; j<CParamsUsed; ++j) { // NXPrintf(outfp, " ; "); // NXPrintf(outfp, CParams[j]); // NXPrintf(outfp, " = "); // NXPrintf(outfp, CParamValues[j]); // } // NXPrintf(outfp, "\n\n"); TranslateInputToOutput(InputFP, outfp, EncodingCode); strcat(ffff,SquirrelFile); CreateMMP(outfp,ffff); // NXCloseMemory(outfp, NX_FREEBUFFER); return(0); } int CreateMMP(NXStream *stream, char *filename) { int lc2strcmp(); NXStream *basic2next(); long len; char *extention=NULL; char *key=NULL; extention = rindex(filename, '.'); if (extention) { ++extention; } else { extention = (char *) calloc (15, sizeof(char)); strcpy(extention,"NULL_Extension"); } NXSeek(stream, (long)0, NX_FROMEND); len = NXTell(stream); NXSeek(stream, (long)0, NX_FROMSTART); if (!lc2strcmp(extention,"plain") ) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"richtext")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); // (*adpp)->fd_stream = richtext2rtf(stream); (*adpp)->fd_stream = (NXStream *)stream; NXSeek((*adpp)->fd_stream, (long)0, NX_FROMEND); // len = NXTell((*adpp)->fd_stream); // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"andrew-inset") || !lc2strcmp(extention,"x-be2")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); (void)strcpy(extention,"ez"); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; NXSeek((*adpp)->fd_stream, (long)0, NX_FROMEND); // len = NXTell((*adpp)->fd_stream); // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"tiff") || !lc2strcmp(extention,"next")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"vox")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; // (void)strcpy(extention,"snd"); (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"gif")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"jfif") || !strcmp(extention,"jpeg")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); (void)strcpy(extention,"jpeg"); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!strcmp(extention,"external-body") || !strcmp(extention,"x-news") || !strcmp(extention,"anon-ftp") || !strcmp(extention,"local-file")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; NXSeek((*adpp)->fd_stream, (long)0, NX_FROMEND); // len = NXTell((*adpp)->fd_stream); // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"ps") || !lc2strcmp(extention,"postscript")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); //(void)strcpy(extention,"eps"); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = (NXStream *)stream; NXSeek((*adpp)->fd_stream, (long)0, NX_FROMEND); // len = NXTell((*adpp)->fd_stream); // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"basic") || !lc2strcmp(extention,"snd")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); (void)strcpy(extention,"snd"); (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); (*adpp)->fd_stream =(NXStream *) basic2next(stream); NXSeek((*adpp)->fd_stream, (long)0, NX_FROMEND); // len = NXTell((*adpp)->fd_stream); // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } else if (!lc2strcmp(extention,"tbl")) { if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream =(NXStream *) stream; // (*adpp)->fd_stream->buf_size = len; articles_desc=(*adpp); adpp = &(*adpp)->fd_nextp; } else{ if (( *adpp = (struct mem_file_desc *)malloc(sizeof(struct mem_file_desc ))) == NULL){ exit(-1); } (*adpp)->fd_type = FD_STREAM; key = rindex(filename, '/'); if (key) (void)strncpy((*adpp)->fd_name , ++key , NAMSIZ); else (void)strncpy((*adpp)->fd_name , filename , NAMSIZ); (*adpp)->fd_stream = stream; // (*adpp)->fd_stream->buf_size = len; adpp = &(*adpp)->fd_nextp; } if ( !strcmp(extention, "NULL_Extension")) free(extention); return(0); } int ExitWithError(txt) char *txt; { if (txt) fprintf(stderr, "metamail: %s\n", txt); NXRunAlertPanel(LoStr("MMEdit"), LoStr(txt),LoStr("OK"),NULL,NULL); exit(-1); } char * FreshHeaderCopy(s) char *s; { char *t, *newcopy; int len; while (s && *s && isspace((unsigned char) *s) && *s != '\n') ++s; t = index(s, '\n'); while (t && (*(t+1) == ' ' || *(t+1) == '\t')) { t = index(t+1, '\n'); } len = t ? (t-s+1) : (strlen(s)+1); newcopy = malloc(len+1); if (!newcopy) ExitWithError(nomem); strncpy(newcopy, s, len); newcopy[len] = 0; return(newcopy); } int Read822Prefix(PrintHeads, nestingdepth) int PrintHeads, nestingdepth; { int lc2strncmp(),StripTrailingSpace(),ParseContentParameters(); int maybephead(),phead(); int SawNewline = 0, bytes = 0, alloced = 1000, HasEncodedChars=0; int nc=0,flag=0, oldbytes; char c, c1; NXStream *fhead; char *s, *t, *tmp, *topmailhead; if (!PrintSomeHeaders) PrintHeads = 0; mailheaders = malloc(alloced+1); if (!mailheaders) ExitWithError(nomem); // strcpy(mailheaders, "MM_HEADERS=\n"); // bytes = 12; bytes = 0; yankagain: t = mailheaders + bytes; // oldbytes = bytes-1; /* a hack for YankMode */ oldbytes = bytes; /* a hack for YankMode */ while ((c = getc(InputFP)) != EOF) { if (++bytes >= alloced) { alloced += 1000; mailheaders = realloc(mailheaders, alloced); if (!mailheaders) ExitWithError(nomem); t = mailheaders + bytes - 1; } if ( c =='-' ){ c1 = getc(InputFP); if ( c1 == '-' ){ if (SawNewline){ ungetc(c1,InputFP); ungetc(c,InputFP); break; }else ungetc(c,InputFP); }else ungetc(c1,InputFP); }else if (c == '\r') { if ( nc == 0 ){ *t++=c; break; } nc++; c1 = getc(InputFP); if ( c1 == '\n' ){ flag=1; if (SawNewline){ *t++=c; *t++=c1; break; } SawNewline = 1; } ungetc(c1,InputFP); } else { if (c == '\n' && flag == 1) SawNewline = 1; else{ SawNewline = 0; flag=0; } } *t++ = c; nc=1; } *t = 0; --bytes; if (c == EOF) { if (nestingdepth) { NXRunAlertPanel(LoStr("MMEdit"), LoStr("Could not extract a MIME message from the body"),LoStr("OK"),NULL,NULL); strcpy(mailheaders,"Subject: NO MESSAGE\n"); return(-1); } else { if (YankMode) { NXRunAlertPanel(LoStr("MMEdit"), LoStr("Could not extract a MIME message from this body"),LoStr("OK"),NULL,NULL); strcpy(mailheaders,"Subject: NO MESSAGE\n"); } else { NXRunAlertPanel(LoStr("MMEdit"), LoStr("Could not find end of message headers"),LoStr("OK"),NULL,NULL); strcpy(mailheaders,"Subject: NO MESSAGE\n"); } } } //printf("<<Headers>>%s",mailheaders); if ( headpart == 0 ){ fhead = NXOpenMemory(NULL,0,NX_READWRITE); NXPrintf(fhead,"%s",mailheaders); CreateMMP(fhead, "header.tbl"); // NXCloseMemory(fhead,NX_FREEBUFFER); headpart++; } topmailhead = malloc(2*alloced); strcpy(topmailhead,"\n"); strcat(topmailhead,mailheaders); // for (s=mailheaders; *s; ++s) { for (s=topmailhead; *s; ++s) { if (*s == '\n' && (*(s+1) != ' ') && (*(s+1) != '\t')) { if (!ContentType && !lc2strncmp(s, "\ncontent-type:", 14)) { ContentType = FreshHeaderCopy(s+14); StripTrailingSpace(ContentType); ParseContentParameters(ContentType); if (PrintHeads) maybephead(s+1); } else if (!ContentEncoding && !lc2strncmp(s, "\ncontent-transfer-encoding:", 27)) { ContentEncoding = FreshHeaderCopy(s+27); if (PrintHeads) maybephead(s+1); } else if (!lc2strncmp(s, "\nmime-version:", 14)) { if (PrintHeads) maybephead(s+1); Mimeversion = FreshHeaderCopy(s+9); } else if (!lc2strncmp(s, "\nsubject:", 9)) { if (PrintHeads) maybephead(s+1); MailSubject = FreshHeaderCopy(s+9); } else if (!lc2strncmp(s, "\nfrom:", 6)) { if (PrintHeads) maybephead(s+1); MailFrom = FreshHeaderCopy(s+6); } else if (!lc2strncmp(s, "\ncontent-description:", 4)) { if(PrintHeads) maybephead(s+1); MailSubject = FreshHeaderCopy(s+21); } else { /* Print any with encoded variables */ char *dum = s; while (dum) { dum = index(dum, '?'); if (dum && *++dum == '=') break; } if (dum) { char *nl = s+1; while (nl) { nl = index(nl, '\n'); if (nl && !isspace((unsigned char) *++nl)) break; } if (nl && nl > dum) ++HasEncodedChars; } if (HasEncodedChars) { phead(s+1); } else if (PrintHeads) { maybephead(s+1); } } } } /* Ugly, but effective */ if (YankMode && !ContentType) { goto yankagain; } if (PrintHeads) printf("\n"); if (!ContentType) ContentType = "text/plain"; for (tmp=ContentType; *tmp; ++tmp) { if (isupper((unsigned char) *tmp)) *tmp = tolower((unsigned char) *tmp); } return(0); } int PrepareMessage() { int c; int StripTrailingSpace(); int lc2strcmp(), lc2strncmp(); EncodingCode = ENCODING_NONE; if (ContentEncoding) { /* strip leading white space */ while (*ContentEncoding && isspace((unsigned char) *ContentEncoding)) ++ContentEncoding; StripTrailingSpace(ContentEncoding); if (!lc2strcmp(ContentEncoding, "base64")) { EncodingCode = ENCODING_BASE64; } else if (!lc2strcmp(ContentEncoding, "quoted-printable")) { EncodingCode = ENCODING_QUOTEDPRINTABLE; } else if (!lc2strncmp (ContentEncoding, "x-uue", 5)) { fprintf (stderr, "WARNING: Using nonstandard %s encoding, trying uuencode algorithm.\n", ContentEncoding); EncodingCode = ENCODING_UUENCODE; } else { if (lc2strcmp(ContentEncoding, "none") && !lc2strcmp(ContentEncoding, "8bit") && !lc2strcmp(ContentEncoding, "7bit")) { fprintf(stderr, "Ignoring unrecognized Content-Transfer-Encoding value: %s\n", ContentEncoding); } } } if (EatLeadingNewlines) { while ((c = getc(InputFP)) != EOF) { if (c != '\n') { NXUngetc(InputFP); break; } } } return(0); } int lc2strncmp(s1, s2, len) char *s1, *s2; int len; { if (!s1 || !s2) return (-1); while (*s1 && *s2 && len > 0) { if (*s1 != *s2 && (tolower(*s1) != *s2)) return(-1); ++s1; ++s2; --len; } if (len <= 0) return(0); return((*s1 == *s2) ? 0 : -1); } int lc2strcmp(s1, s2) char *s1, *s2; { if (!s1 || !s2) return (-1); while (*s1 && *s2) { if (*s1 != *s2 && (tolower(*s1) != *s2)) return(-1); ++s1; ++s2; } return((*s1 == *s2) ? 0 : -1); } int StripTrailingSpace(s) char *s; { char *t = s+strlen(s) -1; while (isspace((unsigned char) *t)) *t-- = 0; return(0); } int maybephead(hdr) char *hdr; { static char *KeyHeads=NULL; static char **KeyHeadList; char *s; int phead(); int numkeys=0, len; if (!KeyHeads) { KeyHeads = getenv("KEYHEADS"); if (KeyHeads) { for (s=KeyHeads;*s;++s) if (isupper((unsigned char) *s)) *s=tolower((unsigned char) *s); } else { char *khtmp; /* to avoid writing into a string constant later */ khtmp = "to:cc:subject:from:content-description:date"; KeyHeads = malloc(1+strlen(khtmp)); if (!KeyHeads) ExitWithError(nomem); strcpy(KeyHeads, khtmp); } for (s=KeyHeads; *s; ++s) if (*s == ':') ++numkeys; numkeys += 2; KeyHeadList = (char **) malloc((numkeys) * sizeof(char *)); if (!KeyHeadList) ExitWithError(nomem); numkeys = 0; KeyHeadList[0] = KeyHeads; for(s=KeyHeads; *s; ++s) { if (*s == ':') { *s = '\0'; KeyHeadList[++numkeys] = s+1; } } KeyHeadList[++numkeys] = NULL; } s = index(hdr, ':'); if (s) { len = s - hdr; for (numkeys=0; KeyHeadList[numkeys]; ++numkeys) { if (!strcmp(KeyHeadList[numkeys], "*") || !lc2strncmp(hdr, KeyHeadList[numkeys], len)) { phead(hdr); break; } } } return(0); } /* This next routine prints out a mail header, and needs to deal with the new extended charset headers. */ int phead(s) char *s; { return(0); } /* This is the part that actually handles the charset issues */ int WriteTmpFile(fname) char *fname; { NXStream *fpout; int retval = 0; int TranslateInputToOutput(); fpout = NXOpenMemory(NULL,0,NX_READWRITE); if (!fpout) ExitWithError("Can't create temporary file"); TranslateInputToOutput(InputFP, fpout, EncodingCode); if (NXTell(fpout) == 0) retval = 1; CreateMMP(fpout, fname); // NXCloseMemory(fpout,NX_FREEBUFFER); return(retval); } int TranslateInputToOutput(InputFP, OutputFP, Ecode) NXStream *InputFP, *OutputFP; int Ecode; { int from64(),fromqp(),fromuue(); int ConsumeRestOfPart(); int InMultipart = BoundaryCt > 0 ? 1 : 0; switch(Ecode) { case ENCODING_BASE64: from64(InputFP, OutputFP, InMultipart ? Boundaries : NULL, &BoundaryCt); break; case ENCODING_QUOTEDPRINTABLE: fromqp(InputFP, OutputFP, InMultipart ? Boundaries : NULL, &BoundaryCt); break; case ENCODING_UUENCODE: fromuue(InputFP, OutputFP, InMultipart ? Boundaries: NULL, &BoundaryCt); break; default: ConsumeRestOfPart(OutputFP); } return(0); } int MkTmpFileName(name) char *name; { static int ctr = 0; #ifdef AMIGA strcpy(name, "T:mmXXXXXX"); mktemp(name); #else #ifndef __MSDOS__ char *subtype=NULL; if (ContentType){ subtype = index(ContentType, '/'); } if (subtype) { ++subtype; subtype = Cleanse(subtype); } else subtype = "mixed"; sprintf(name, "/tmp/mm_%d_%d_%d.%s", getuid(), getpid(), ctr++,subtype); #else strcpy(name, "TXXXXXX"); if (!mktemp(name)) name[0] = 0; else printf("temp name = \"%s\"\n", name); #endif #endif return(0); } int ConsumeRestOfPart(outfp) NXStream *outfp; { char *Buf; int PendingBoundary(); int c; if (BoundaryCt <= 0) { while ((c=getc(InputFP)) != EOF) { if (outfp) putc(c, outfp); } return(0); } Buf = malloc(LINE_BUF_SIZE); if (!Buf) ExitWithError(nomem); // while (fgets(Buf, LINE_BUF_SIZE, InputFP)) { c = 0; while ( c != -1 ) { c = readline(InputFP,Buf, LINE_BUF_SIZE); // c = NXScanf(InputFP,"%1999[^\n]\n",LineBuf); if ((BoundaryCt > 0) && (Buf[0] == '-') && (Buf[1] == '-') && PendingBoundary(Buf, Boundaries, &BoundaryCt)) { break; } // if (outfp) writeline(outfp,Buf,strlen(Buf)); if (outfp) NXPrintf(outfp,Buf); } free(Buf); return(0); } char *paramend(s) char *s; { int inquotes=0; while (*s) { if (inquotes) { if (*s == '"') { inquotes = 0; } else if (*s == '\\') { ++s; /* skip a char */ } } else if (*s == ';') { return(s); } else if (*s == '"') { inquotes = 1; } ++s; } return(NULL); } int ParseContentParameters(ct) char *ct; { char *s, *t, *eq; CParamsUsed = 0; s = index(ct, ';'); if (!s) return(0); *s++ = 0; do { t = paramend(s); if (t) *t++ = 0; eq = index(s, '='); if (!eq) { fprintf(stderr, "Ignoring unparsable content-type parameter: '%s'\n", s); JunkParameter=Cleanse(s); } else { if (CParamsUsed >= CParamsAlloced) { CParamsAlloced += 10; if (CParams) { CParams = (char **) realloc(CParams, (1+CParamsAlloced) * sizeof (char *)); CParamValues = (char **) realloc(CParamValues, (1+CParamsAlloced) * sizeof (char *)); } else { CParams = (char **) malloc((1+CParamsAlloced) * sizeof (char *)); CParamValues = (char **) malloc((1+CParamsAlloced) * sizeof (char *)); } if (!CParams || !CParamValues) ExitWithError(nomem); } *eq++ = 0; s = Cleanse(s); CParams[CParamsUsed] = s; /* strip leading white space */ while (*eq && isspace((unsigned char) *eq)) ++eq; /* strip trailing white space */ StripTrailingSpace(eq); CParamValues[CParamsUsed++] = eq; if (DoDebug) printf("NEW PARAMETER: %s VALUE: %s\n", s, eq); } s = t; } while (t); return(0); } char *FindParam(s) char *s; { int i; for (i=0; i<CParamsUsed; ++i) { if (!strcmp(s, CParams[i])) { return(CParamValues[i]); } } return(NULL); } void strcatquoting(s1, s2) char *s1; char *s2; { strcat(s1, s2); #ifdef NOTDEF while (*s1) ++s1; while (*s2) { if (*s2 == '\"' || *s2 == '\\') *s1++ = '\\'; *s1++ = *s2++; } *s1 = '\0'; #endif } void concatstream(plaintexts,addtext) NXStream *plaintexts; NXStream *addtext; { int t,len,max,size; char *buff; NXSeek(plaintexts, (long)0,NX_FROMSTART); NXSeek(plaintexts, (long)0,NX_FROMEND); (long)t = NXTell(plaintexts); NXSeek(addtext, (long)0,NX_FROMEND); (long)size = NXTell(addtext); NXSeek(addtext, (long)0,NX_FROMSTART); NXGetMemoryBuffer(addtext,&buff,&len,&max); NXWrite(plaintexts, (const void *)buff, size); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.