#ifndef _mime_h #define _mime_h /* This is a simple general MIME parsing/interpreting structure. Given an iostream, we can parse out the header, and recursively create the MIME entity datastructures. */ #include "md5.h" #include "list.tmpl" #include "hash.tmpl" #include "iobottle.h" /* This class encapsulates a MIME entity */ class MIME_body { public: MIME_body(IObottle *RawFile, char *endstrings[], MIME_body *lineage = NULL); ~MIME_body(); /* Decode a raw header line */ static char *DecodeLine(const char *line); /* Tell the native character set */ static void MIME_Charset(char *charset); /* Tell which MIME content-types to ignore */ static void MIME_Ignore(char *ignorelist); MIME_body *Parent(void) { return(parent); } const char *Content(void) { return(content); } bool IsHTML() { return (strstr(content, "text/html") != NULL); } const char *Encoding(void) { return(encoding); } const char *Name(void) { return(name); } int NumParts(void) { return(multipart ? 1+multipart->Size() : 1); } int AddPart(const char *file, int is_mime = 0); MIME_body *GetPart(unsigned int which) { MIME_body **retptr = NULL; /* We ARE the first part */ if ( which <= 1 ) return(this); if ( ! multipart ) return(NULL); multipart->InitIterator(); while ( --which ) { if ( ! (retptr=multipart->Iterate()) ) break; } return(retptr ? *retptr : (MIME_body *)0); } int CurrentPart(int which = -1) { if ( (which > 0) && (which <= (1+(multipart ? multipart->Size() : 0))) ) { currentpart = (which-1); } return(currentpart+1); } MIME_body *ByName(char *whatname) { MIME_body **retptr; MIME_body *okay; /* Base case -- ourselves */ if ( name && (strcmp(name, whatname) == 0) ) return(this); /* Depth first recursive search on our bodies */ if ( ! multipart ) return(NULL); multipart->InitIterator(); okay = NULL; while ( (retptr=multipart->Iterate()) ) { okay = *retptr; if ( (okay=okay->ByName(whatname)) ) break; } return(okay ? okay : (MIME_body *)0); } const char *RawPath(void) { return(rawfile->Path()); } char *File(void) { if ( decoded == NULL ) (void) Open(); ++bodyref; return(decoded); } int FreeFile(void) { MIME_body **retptr; /* Decrement reference count on file */ --bodyref; if ( bodyref > 0 ) { /* File is still in use */ return(0); } bodyref = 0; /* Unlink it */ if ( decoded ) { (void) unlink(decoded); decoded = NULL; } if ( ! multipart ) return(1); multipart->InitIterator(); while ( (retptr=multipart->Iterate()) ) { while ( (*retptr)->FreeFile() == 0 ) { /* Force the multipart body to close */; } } return(1); } int Save(char *filename, int overwrite); /* Header stuff */ char *GetHeader(char **keyholder); const char *GetField(const char *str); void NewField(const char *name, const char *value); /* Allow searching of MIME bodies */ MIME_body *Search(const char *pattern); /* Two MIME bodies are equivalent iff they have the same MD5 checksum */ int operator == (MIME_body &other) { for ( int i=0; i<16; ++i ) { if ( md5sum[i] != other.md5sum[i] ) return(0); } return(1); } int operator != (MIME_body &other) { return( ! (*this == other)); } private: static char *mime_charset; static char **mime_ignore; IObottle *rawfile; /* The raw MIME data file */ MIME_body *parent; /* The body of our parent */ Hash fieldtab; /* Header fields */ const char *version; /* MIME version header info */ const char *content; /* MIME content header info */ const char *encoding; /* MIME encoding header info */ char *name; /* Name associated with MIME body */ long hstart; /* Offset of header in file */ long bstart; /* Offset of body in file */ char **endstrings; /* MIME body boundaries */ int *endlens; /* Boundary lengths */ int numends; /* Number of boundaries */ unsigned char md5sum[16]; /* MD5 Checksum of the MIME body */ char *decoded; /* The name of the decoded file */ int bodyref; /* Reference count on decoded file */ List *multipart; List *addedparts; /* Temp files of parts added */ int currentpart; /* The "current" MIME body part */ /* Decode a message creating the 'multipart' list */ int ParseMulti(MD5_CTX *md5ctx); void GetWord(const char *src, char **dst); /* Change this MIME body into a multipart message */ int MultipartMe(char **boundaryptr); /* Decode the raw body to 'decoded' */ int Open(void); }; #endif /* _mime_h */