diff --git a/Makefile b/Makefile index 9299dfd..11f07b8 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,9 @@ LIBS= # DEBUGGING Related Flags OBJ=ripmime -RIPOLE_OBJS= ripOLE/ole.o ripOLE/olestream-unwrap.o ripOLE/bytedecoders.o ripOLE/bt-int.o +RIPOLE_OBJS= ripOLE/ole.o ripOLE/olestream-unwrap.o ripOLE/bytedecoders.o ripOLE/bt-int.o #RIPOLE_OBJS= -OFILES= strstack.o mime.o ffget.o MIME_headers.o tnef/tnef.o rawget.o pldstr.o logger.o libmime-decoders.o boundary-stack.o uuencode.o filename-filters.o $(RIPOLE_OBJS) - +OFILES= strstack.o mime.o ffget.o mime_headers.o tnef/tnef.o rawget.o pldstr.o logger.o libmime-decoders.o boundary-stack.o uuencode.o filename-filters.o mime_element.o $(RIPOLE_OBJS) default: tnef/tnef.o ripmime ripOLE/ole.o diff --git a/README.md b/README.md index 68ffb52..15e3c46 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ### Features -- Extracts all attachments even from multiple MUA personalities +- Extracts all attachments even from multiple MUA personalities ### TODO diff --git a/boundary-stack.c b/boundary-stack.c index 4f6b5c5..8866214 100644 --- a/boundary-stack.c +++ b/boundary-stack.c @@ -49,16 +49,16 @@ static struct BS_globals glb; Function Name : BS_init Returns Type : int ----Parameter List - 1. void , + 1. void , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_init( void ) { @@ -82,14 +82,14 @@ int BS_init( void ) ----Parameter List 1. int limit , how many boundary strings to hold ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_set_hold_limit( int limit ) { @@ -102,16 +102,16 @@ int BS_set_hold_limit( int limit ) Function Name : BS_set_verbose Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_set_verbose( int level ) { @@ -124,16 +124,16 @@ int BS_set_verbose( int level ) Function Name : BS_set_debug Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_set_debug( int level ) { @@ -146,16 +146,16 @@ int BS_set_debug( int level ) Function Name : BS_set_boundary_detect_limit Returns Type : int ----Parameter List - 1. int limit , + 1. int limit , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_set_boundary_detect_limit( int limit ) { @@ -172,16 +172,16 @@ int BS_set_boundary_detect_limit( int limit ) Function Name : BS_clear Returns Type : int ----Parameter List - 1. void , + 1. void , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_clear( void ) { @@ -209,16 +209,16 @@ int BS_clear( void ) Function Name : BS_non_hyphen_length Returns Type : int ----Parameter List - 1. char *boundary , + 1. char *boundary , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_non_hyphen_length( char *boundary ) { @@ -234,28 +234,28 @@ int BS_non_hyphen_length( char *boundary ) Function Name : BS_push Returns Type : int ----Parameter List - 1. char *boundary , + 1. char *boundary , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_push( char *boundary ) { struct BS_node *node; - if ((glb.hold_limit > 0)&&(glb.count >= glb.hold_limit)) + if ((glb.hold_limit > 0)&&(glb.count >= glb.hold_limit)) { DBS LOGGER_log("%s:%d:BS_push:DEBUG: Number of boundaries to hold is at limit (limit=%d)",FL,glb.hold_limit); return 0; } - + node = malloc(sizeof(struct BS_node)); DBS LOGGER_log("%s:%d:BS_push:DEBUG: head = %p, nn = %p boundary = '%s'",FL, glb.boundarystack, node, boundary); @@ -289,16 +289,16 @@ int BS_push( char *boundary ) Function Name : *BS_pop Returns Type : char ----Parameter List - 1. void , + 1. void , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ char *BS_pop( void ) { @@ -321,16 +321,16 @@ char *BS_pop( void ) Function Name : *BS_top Returns Type : char ----Parameter List - 1. void , + 1. void , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ char *BS_top( void ) { @@ -346,16 +346,16 @@ char *BS_top( void ) Function Name : BS_count Returns Type : int ----Parameter List - 1. void , + 1. void , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_count( void ) { @@ -367,16 +367,16 @@ int BS_count( void ) Function Name : BS_is_long_enough Returns Type : int ----Parameter List - 1. int blen , + 1. int blen , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_is_long_enough( int blen ) { @@ -390,17 +390,17 @@ int BS_is_long_enough( int blen ) Function Name : BS_boundary_detect Returns Type : int ----Parameter List - 1. char *needle, - 2. char *haystack , + 1. char *needle, + 2. char *haystack , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_boundary_detect( char *haystack, char *needle, int needle_length ) { @@ -434,8 +434,8 @@ int BS_boundary_detect( char *haystack, char *needle, int needle_length ) if (strncmp( needle, haystack_start, needle_length )==0) { DBS LOGGER_log("%s:%d:BS_boundary_detect:DEBUG: Hit on compare",FL); - result = 0; - break; + result = 0; + break; } haystack_start++; } @@ -454,13 +454,13 @@ int BS_boundary_detect( char *haystack, char *needle, int needle_length ) 2. int len , the length of the boundary ------------------ Exit Codes : 1 == boundary found, 0 == no boundary found - Side Effects : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int BS_cmp( char *boundary, int len ) { @@ -504,7 +504,7 @@ int BS_cmp( char *boundary, int len ) { // if (node->boundary_length <= len) if (node->boundary_nhl == nhl) - { + { DBS LOGGER_log("%s:%d:BS_cmp:DEBUG: Comparing '%s' to '%s'", FL, boundary, node->boundary); // * 20040903-08H57:PLD: Set boundary length comparison from > 0 to >= 0 if ((node->boundary != NULL)&&(node->boundary_length >= 0)) diff --git a/ffget.c b/ffget.c index cdd0360..8c9c9b2 100644 --- a/ffget.c +++ b/ffget.c @@ -58,10 +58,10 @@ int FFGET_set_watch_SDL( int level ) Function Name : FFGET_set_allow_nul Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: This tells the FFGET_raw() if it needs to remove \0's or not @@ -270,13 +270,13 @@ int FFGET_feof( FFGET_FILE *f ) Function Name : FFGET_seek Returns Type : int ----Parameter List - 1. FFGET_FILE *f, - 2. size_t offset , + 1. FFGET_FILE *f, + 2. size_t offset , ------------------ - Exit Codes : + Exit Codes : -1 = error, check logs for reason of failure. - Side Effects : + Side Effects : -------------------------------------------------------------------- Comments: Seeks to 'offset' bytes from the first byte of the file. @@ -309,10 +309,10 @@ int FFGET_seek( FFGET_FILE *f, long offset, int whence ) Function Name : FFGET_tell Returns Type : size_t ----Parameter List - 1. FFGET_FILE *f , + 1. FFGET_FILE *f , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: Returns the position in the file that the current "file cursor" diff --git a/ffget.h b/ffget.h index bb251d7..4cf878d 100644 --- a/ffget.h +++ b/ffget.h @@ -13,21 +13,21 @@ #define FFGET_DNORMAL ((FFGET_debug >= FFGET_DEBUG_NORMAL )) #define FFGET_DPEDANTIC ((FFGET_debug >= FFGET_DEBUG_PEDANTIC)) -#define FFGET_MAX_LINE_LEN 1024 -#define FFGET_BUFFER_MAX 8192 +#define FFGET_MAX_LINE_LEN 1024 * sizeof(char) +#define FFGET_BUFFER_MAX 8192 * sizeof(char) #define FFGET_BUFFER_PADDING 1 #define FFGET_DEBUG_NORMAL 1 #define FFGET_DEBUG_PEDANTIC 10 -#define FFGET_LINEBREAK_NONE 0 -#define FFGET_LINEBREAK_LF 1 -#define FFGET_LINEBREAK_CR 2 +#define FFGET_LINEBREAK_NONE 0 +#define FFGET_LINEBREAK_LF 1 +#define FFGET_LINEBREAK_CR 2 struct _FFGET_FILE { FILE *f; - char buffer[FFGET_BUFFER_MAX+4]; + char buffer[FFGET_BUFFER_MAX + 4 * sizeof(char)]; char *startpoint; char *endpoint; char *buffer_end; diff --git a/libmime-decoders.c b/libmime-decoders.c index 8b51f4e..87b7d2a 100644 --- a/libmime-decoders.c +++ b/libmime-decoders.c @@ -29,7 +29,7 @@ /* our base 64 decoder table */ static unsigned char b64[256]={ - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,\ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,\ diff --git a/logger.c b/logger.c index d0cc5dc..ed049a6 100644 --- a/logger.c +++ b/logger.c @@ -196,7 +196,7 @@ int LOGGER_clean_output( char *string, char **buffer ) int maxsize = slen *2; // First up, allocate maxsize bytes for a temporary new string. - newstr = malloc(slen *2 +1); + newstr = malloc(slen *2 +1); if ( newstr == NULL ) { // FIXME - Report an error here ... to -somewhere- diff --git a/mime.c b/mime.c index 8ea9233..46eafab 100644 --- a/mime.c +++ b/mime.c @@ -34,8 +34,6 @@ #include #include #include -#include -#include #include #include #include @@ -49,6 +47,9 @@ #include "pldstr.h" #include "boundary-stack.h" #include "ffget.h" +#include "strstack.h" +#include "mime_element.h" +#include "mime_headers.h" #include "mime.h" #include "tnef/tnef_api.h" #include "ripOLE/ole.h" @@ -56,31 +57,34 @@ #include "uuencode.h" #include "filename-filters.h" #include "logger.h" -#include "strstack.h" -#include "MIME_headers.h" -int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hinfo, int current_recursion_level, struct SS_object *ss ); -int MIME_unpack_single( char *unpackdir, char *mpname, int current_recursion_level, struct SS_object *ss ); -int MIME_unpack_single_fp( char *unpackdir, FILE *fi, int current_recursion_level, struct SS_object *ss ); -int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_level, struct SS_object *ss ); -int MIME_handle_multipart( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ); -int MIME_handle_rfc822( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ); +int MIME_unpack_stage2( FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo, int current_recursion_level, struct SS_object *ss ); +int MIME_unpack_single_diskfile( RIPMIME_output *unpack_metadata, char *mpname, int current_recursion_level, struct SS_object *ss ); +int MIME_unpack_single_file( RIPMIME_output *unpack_metadata, FILE *fi, int current_recursion_level, struct SS_object *ss ); +int MIME_unpack_mailbox( RIPMIME_output *unpack_metadata, char *mpname, int current_recursion_level, struct SS_object *ss ); +int MIME_handle_multipart( MIME_element* parent_mime, FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ); +int MIME_handle_rfc822( MIME_element* parent_mime, FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ); + +MIME_element* MIME_decode_std_raw( MIME_element* parent, FFGET_FILE *f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo); +MIME_element* MIME_decode_std_text( MIME_element* parent, FFGET_FILE *f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ); +MIME_element* MIME_decode_std_64( MIME_element* parent, FFGET_FILE *f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ); + // Predefined filenames #define MIME_BLANKZONE_FILENAME_DEFAULT "_blankzone_" #define MIME_HEADERS_FILENAME "_headers_" #ifndef FL -#define FL __FILE__, __LINE__ +#define FL __FILE__,__LINE__ #endif -#define _ENC_UNKNOWN 0 -#define _ENC_BASE64 1 -#define _ENC_PLAINTEXT 2 -#define _ENC_QUOTED 3 -#define _ENC_EMBEDDED 4 -#define _ENC_NOFILE -1 +#define _ENC_UNKNOWN 0 +#define _ENC_BASE64 1 +#define _ENC_PLAINTEXT 2 +#define _ENC_QUOTED 3 +#define _ENC_EMBEDDED 4 +#define _ENC_NOFILE -1 #define _MIME_CHARS_PER_LINE 32 #define _MIME_MAX_CHARS_PER_LINE 76 #define _RECURSION_LEVEL_DEFAULT 20 @@ -95,8 +99,6 @@ int MIME_handle_rfc822( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info #define _MIME_WRITE_BUFFER_SIZE (8 *1024) #define _MIME_WRITE_BUFFER_LIMIT (_MIME_WRITE_BUFFER_SIZE -4) - - // Debug precodes #define MIME_DPEDANTIC ((glb.debug >= _MIME_DEBUG_PEDANTIC)) #define MIME_DNORMAL ((glb.debug >= _MIME_DEBUG_NORMAL )) @@ -104,18 +106,16 @@ int MIME_handle_rfc822( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info #define MIME_VERBOSE_12 ((glb.verbosity_12x_style > 0 )) #define DMIME if (glb.debug >= _MIME_DEBUG_NORMAL) -#define FL __FILE__,__LINE__ - /* our base 64 decoder table */ -static unsigned char b64[256]={ - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ +static unsigned char b64[256] = { + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,\ - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,\ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,\ 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\ - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,\ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,\ 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,\ - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128,\ + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128,\ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,\ @@ -126,11 +126,7 @@ static unsigned char b64[256]={ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 \ }; - - - struct MIME_globals { - int header_defect_count; int filecount; char blankfileprefix[_MIME_STRLEN_MAX]; @@ -144,11 +140,9 @@ struct MIME_globals { int quiet; int syslogging; int stderrlogging; - int unique_names; - int rename_method; char headersname[_MIME_STRLEN_MAX]; char tempdirectory[_MIME_STRLEN_MAX]; - int save_headers; + int dump_headers; int attachment_count; int current_line; int no_nameless; @@ -169,7 +163,7 @@ struct MIME_globals { int blankzone_saved; int blankzone_save_option; - char blankzone_filename[_MIMEH_STRLEN_MAX +1]; + char blankzone_filename[_MIMEH_STRLEN_MAX + 1]; int (*filename_decoded_reporter)(char *, char *); // Pointer to the reporting function for filenames as they are decoded @@ -184,12 +178,6 @@ struct MIME_globals { static struct MIME_globals glb; -//char OK[]="OKAY"; -static char scratch[1024]; - -/* File pointer for the headers output */ -FILE *headers; - /*-----------------------------------------------------------------\ Function Name : MIME_version Returns Type : int @@ -243,7 +231,6 @@ the different types of content-types. int MIME_set_name_by_type( int level ) { glb.name_by_type = level; - return glb.name_by_type; } @@ -265,6 +252,7 @@ int MIME_set_debug( int level ) MDECODE_set_debug(level); UUENCODE_set_debug(level); FNFILTER_set_debug(level); + MIMEELEMENT_set_debug(level); return glb.debug; } @@ -312,28 +300,6 @@ int MIME_set_recursion_level( int level ) return glb.max_recursion_level; } -/*-----------------------------------------------------------------\ - Function Name : MIME_set_decode_tnef - Returns Type : int - ----Parameter List - 1. int level , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int MIME_set_decode_tnef( int level ) -{ - glb.decode_tnef = level; - TNEF_set_decode( level ); - - return level; -} /*-----------------------------------------------------------------\ Function Name : MIME_set_decode_ole Returns Type : int @@ -675,7 +641,7 @@ int MIME_set_filename_report_fn( int (*ptr_to_fn)(char *, char *) ) int MIME_set_dumpheaders( int level ) { - glb.save_headers = level; + glb.dump_headers = level; return 0; } @@ -772,7 +738,7 @@ int MIME_set_blankzone_save_option( int option ) break; default: - LOGGER_log("%s:%d:MIME_set_blankzone_save_option:WARNING: Unknown option for saving method (%d). Setting to '%s'",FL, option, MIME_BLANKZONE_FILENAME_DEFAULT ); + LOGGER_log("%s:%d:%s:WARNING: Unknown option for saving method (%d). Setting to '%s'",FL,__func__, option, MIME_BLANKZONE_FILENAME_DEFAULT ); glb.blankzone_save_option = MIME_BLANKZONE_SAVE_FILENAME; snprintf( glb.blankzone_filename, _MIME_STRLEN_MAX, "%s", MIME_BLANKZONE_FILENAME_DEFAULT ); } @@ -834,19 +800,6 @@ int MIME_set_no_nameless( int level ) return 0; } -/*------------------------------------------------------------------------ -Procedure: MIME_set_uniquenames ID:1 -Purpose: -Input: -Output: -Errors: -------------------------------------------------------------------------*/ -int MIME_set_uniquenames( int level ) -{ - glb.unique_names = level; - return 0; -} - /*------------------------------------------------------------------------ Procedure: MIME_set_noparanoid ID:1 Purpose: If set, will prevent MIME from clobbering what it considers @@ -878,28 +831,6 @@ int MIME_set_mailboxformat( int level ) return 0; } -/*------------------------------------------------------------------------ -Procedure: MIME_set_renamemethod ID:1 -Purpose: -Input: -Output: -Errors: -------------------------------------------------------------------------*/ -int MIME_set_renamemethod( int method ) -{ - if (( method >= _MIME_RENAME_METHOD_INFIX ) && ( method <= _MIME_RENAME_METHOD_RANDPOSTFIX )) - { - glb.rename_method = method; - } - else - { - LOGGER_log("%s:%d:MIME_set_renamemethod:ERROR: selected method not within %d > x > %d range", FL, _MIME_RENAME_METHOD_INFIX, _MIME_RENAME_METHOD_POSTFIX ); - return -1; - } - - return 0; -} - /*-----------------------------------------------------------------\ Function Name : MIME_get_header_defect_count Returns Type : int @@ -932,199 +863,109 @@ int MIME_get_attachment_count( void ) return glb.attachment_count; } -int get_random_value(void) { - int randval; - FILE *fp; - fp = fopen("/dev/urandom", "r"); - fread(&randval, sizeof(randval), 1, fp); - fclose(fp); - if (randval < 0) { randval = randval *( -1); }; - return randval; -} - /*------------------------------------------------------------------------ -Procedure: MIME_test_uniquename ID:1 -Purpose: Checks to see that the filename specified is unique. If it's not -unique, it will modify the filename -Input: char *path: Path in which to look for similar filenames -char *fname: Current filename -int method: Method of altering the filename (infix, postfix, prefix, randinfix, randpostfix, randprefix) -Output: +Procedure: MIME_is_RFC +Purpose: Determines if the file handed to it is a MIME type email file. + +Input: FILE object to analyze +Output: 0 if not RFC, + 1 if the file represents RFC content, + -1 oherwise Errors: ------------------------------------------------------------------------*/ -int MIME_test_uniquename( char *path, char *fname, int method ) +int MIME_is_file_RFC822( FILE *f ) { - struct stat buf; - - char newname[_MIME_STRLEN_MAX +1]; - char scr[_MIME_STRLEN_MAX +1]; /** Scratch var **/ - char *frontname, *extention; - - int cleared = 0; - int count = 1; - - int randval = get_random_value(); - - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_test_uniquename:DEBUG: Start (%s)",FL,fname); - - frontname = extention = NULL; // shuts the compiler up + char conditions[16][16] = { + "Received: ", + "From: ", + "Subject: ", + "Date: ", + "Content-", + "content-", + "from: ", + "subject: ", + "date: ", + "boundary=", + "Boundary=", + "MIME-Version" }; + int result = 0; + int flag_mime_version = 0; + int hitcount = 0; + int linecount = 100; // We should only need to read the first 10 lines of any file. + char *line; - if (method == _MIME_RENAME_METHOD_INFIX) + line = malloc(sizeof(char) *1025); + if (!line) { - PLD_strncpy(scr,fname, _MIMEH_STRLEN_MAX); - frontname = scr; - extention = strrchr(scr,'.'); - - if (extention) - { - *extention = '\0'; - extention++; - } - else - { - method = _MIME_RENAME_METHOD_POSTFIX; - } + LOGGER_log("%s:%d:%s:ERROR: cannot allocate memory for read buffer", FL,__func__); + return -1; } - if (method == _MIME_RENAME_METHOD_RANDINFIX) + fseek(f, 0, SEEK_SET); + + while (((!flag_mime_version)||(hitcount < 2))&&(fgets(line,1024,f))&&(linecount--)) { - PLD_strncpy(scr,fname, _MIMEH_STRLEN_MAX); - frontname = scr; - extention = strrchr(scr,'.'); + /** test every line for possible headers, until we get a blank line **/ - if (extention) - { - *extention = '\0'; - extention++; - } - else - { - method = _MIME_RENAME_METHOD_RANDPOSTFIX; - } - } + if ((glb.header_longsearch == 0)&&(*line == '\n' || *line == '\r')) break; - snprintf(newname,_MIME_STRLEN_MAX,"%s/%s",path,fname); - while (!cleared) - { - if ((stat(newname, &buf) == -1)) - { - cleared++; - } - else + for (result = 0; result < 12; result++) { - if (method == _MIME_RENAME_METHOD_PREFIX) + /** Test for every possible MIME header prefix, ie, From: Subject: etc **/ + if (MIME_DPEDANTIC) LOGGER_log("%s:%d:%s:DEBUG: Testing for '%s' in '%s'", FL,__func__, line, conditions[result]); + if (strncasecmp(line,conditions[result],strlen(conditions[result]))==0) { - snprintf(newname,_MIME_STRLEN_MAX,"%s/%d_%s",path,count,fname); - } - else - if (method == _MIME_RENAME_METHOD_INFIX) + /** If we get a match, then increment the hit counter **/ + hitcount++; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Hit on %s",FL,__func__,conditions[result]); + if (result == 11) { - snprintf(newname,_MIME_STRLEN_MAX,"%s/%s_%d.%s",path,frontname,count,extention); + flag_mime_version = 1; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Find 'MIME Version' field",FL,__func__); } - else - if (method == _MIME_RENAME_METHOD_POSTFIX) - { - snprintf(newname,_MIME_STRLEN_MAX,"%s/%s_%d",path,fname,count); - } - else - /* Handle randome methots*/ - if (method == _MIME_RENAME_METHOD_RANDPREFIX) - { - snprintf(newname,_MIME_STRLEN_MAX,"%s/%d_%d_%s",path,count,randval,fname); - } - else - if (method == _MIME_RENAME_METHOD_RANDINFIX) - { - snprintf(newname,_MIME_STRLEN_MAX,"%s/%s_%d_%d.%s",path,frontname,count,randval,extention); - } - else - if (method == _MIME_RENAME_METHOD_RANDPOSTFIX) - { - snprintf(newname,_MIME_STRLEN_MAX,"%s/%s_%d_%d",path,fname,count,randval); - } - count++; + } } } - if (count > 1) - { - frontname = strrchr(newname,'/'); - if (frontname) frontname++; - else frontname = newname; - PLD_strncpy(fname, frontname, _MIMEH_FILENAMELEN_MAX); //FIXME - this assumes that the buffer space is at least MIME_STRLEN_MAX sized. - } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_test_uniquename:DEBUG: Done (%s)",FL,fname); - return 0; + if (hitcount >= 2 && flag_mime_version) + result = 1; + else + result = 0; + if (line) + free(line); + if (MIME_DNORMAL) + LOGGER_log("%s:%d:%s:DEBUG: Hit count = %d, result = %d",FL,__func__,hitcount,result); + return result; } /*------------------------------------------------------------------------ -Procedure: MIME_is_file_mime ID:1 +Procedure: MIME_is_diskfile_RFC822 Purpose: Determines if the file handed to it is a MIME type email file. Input: file name to analyze Output: Returns 0 for NO, 1 for YES, -1 for "Things di Errors: ------------------------------------------------------------------------*/ -int MIME_is_file_RFC822( char *fname ) +int MIME_is_diskfile_RFC822( char *fname ) { - char conditions[16][16] = { - "Received: ", "From: ", "Subject: ", "Date: ", "Content-", "content-", "from: ", "subject: ", "date: ", "boundary=", "Boundary=", "MIME-Version" }; int result = 0; - int flag_mime_version = 0; - int hitcount = 0; - int linecount = 100; // We should only need to read the first 10 lines of any file. - char *line; FILE *f; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_is_file_RFC822:DEBUG: Testing %s for RFC822 headers",FL,fname); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Testing %s for RFC822 headers",FL,__func__,fname); f = fopen(fname,"r"); if (!f) { if (glb.quiet == 0) { - LOGGER_log("%s:%d:MIME_is_file_mime:ERROR: cannot open file '%s' for reading (%s)", FL, fname,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: cannot open file '%s' for reading (%s)", FL,__func__, fname,strerror(errno)); } return 0; } - line = malloc(sizeof(char) *1025); - if (!line) - { - LOGGER_log("%s:%d:MIME_is_file_mime:ERROR: cannot allocate memory for read buffer", FL); - return 0; - } - - while (((!flag_mime_version)||(hitcount < 2))&&(fgets(line,1024,f))&&(linecount--)) - { - /** test every line for possible headers, until we get a blank line **/ - - if ((glb.header_longsearch == 0)&&(*line == '\n' || *line == '\r')) break; - - for (result = 0; result < 12; result++) - { - /** Test for every possible MIME header prefix, ie, From: Subject: etc **/ - if (MIME_DPEDANTIC) LOGGER_log("%s:%d:MIME_is_file_mime:DEBUG: Testing for '%s' in '%s'", FL, line, conditions[result]); - if (strncasecmp(line,conditions[result],strlen(conditions[result]))==0) - { - /** If we get a match, then increment the hit counter **/ - hitcount++; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_is_file_RFC822:DEBUG: Hit on %s",FL,conditions[result]); - if (result == 11) - { - flag_mime_version = 1; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_is_file_RFC822:DEBUG: Find 'MIME Version' field",FL); - } - } - } - } - + result = MIME_is_file_RFC822(f); fclose(f); - if (hitcount >= 2 && flag_mime_version) result = 1; - else result = 0; - if (line) free(line); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_is_file_RFC822:DEBUG: Hit count = %d, result = %d",FL,hitcount,result); - return result; + return result == 1; } /*------------------------------------------------------------------------ @@ -1162,21 +1003,16 @@ Purpose: Decodes TNEF encoded attachments Output: Errors: ------------------------------------------------------------------------*/ -int MIME_decode_TNEF( char *unpackdir, struct MIMEH_header_info *hinfo, int keep ) +int MIME_decode_TNEF( RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ) { - int result=0; - char fullpath[1024]; - - snprintf(fullpath,sizeof(fullpath),"%s/%s",unpackdir,hinfo->filename); - TNEF_set_path(unpackdir); - result = TNEF_main( fullpath ); + int result = TNEF_main( hinfo->filename, unpack_metadata->dir ); if (result >= 0) { // result = remove( fullpath ); if (result == -1) { - if (MIME_VERBOSE) LOGGER_log("%s:%d:MIME_decode_TNEF: Removing %s failed (%s)",FL,fullpath,strerror(errno)); + if (MIME_VERBOSE) LOGGER_log("%s:%d:%s: Removing %s/%s failed (%s)",FL,__func__,hinfo->filename, unpack_metadata->dir,strerror(errno)); } } return result; @@ -1190,12 +1026,11 @@ int MIME_report_filename_decoded_RIPOLE(char *filename) } /*-----------------------------------------------------------------\ - Function Name : MIME_decode_OLE + Function Name : MIME_decode_OLE_diskfile Returns Type : int ----Parameter List - 1. char *unpackdir, + 1. RIPMIME_output *unpack_metadata, 2. struct MIMEH_header_info *hinfo, - 3. int keep , ------------------ Exit Codes : Side Effects : @@ -1206,13 +1041,15 @@ int MIME_report_filename_decoded_RIPOLE(char *filename) Changes: \------------------------------------------------------------------*/ -int MIME_decode_OLE( char *unpackdir, struct MIMEH_header_info *hinfo, int keep ) +int MIME_decode_OLE_diskfile( RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ) { struct OLE_object ole; - char fullpath[1024]; int result; + char *fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(hinfo->filename) + sizeof(char) * 2; - snprintf(fullpath,sizeof(fullpath),"%s/%s",unpackdir,hinfo->filename); + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,hinfo->filename); OLE_init(&ole); OLE_set_quiet(&ole,glb.quiet); @@ -1221,33 +1058,58 @@ int MIME_decode_OLE( char *unpackdir, struct MIMEH_header_info *hinfo, int keep OLE_set_save_unknown_streams(&ole,0); OLE_set_filename_report_fn(&ole, MIME_report_filename_decoded_RIPOLE ); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_OLE:DEBUG: Starting OLE Decode",FL); - result = OLE_decode_file(&ole, fullpath, unpackdir ); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_OLE:DEBUG: Decode done, cleaning up.",FL); - OLE_decode_file_done(&ole); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Starting OLE Decode",FL,__func__); + result = OLE_decode_diskfile(&ole, fn, unpack_metadata ); + free(fn); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decode done, cleaning up.",FL,__func__); + OLE_decode_done(&ole); + if (ole.f) + fclose(ole.f); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_OLE:DEBUG: Decode returned with code = %d",FL,result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decode returned with code = %d",FL,__func__,result); + return result; +} + +int MIME_decode_OLE_file( RIPMIME_output *unpack_metadata, FILE *f ) +{ + struct OLE_object ole; + int result; + + OLE_init(&ole); + OLE_set_quiet(&ole,glb.quiet); + OLE_set_verbose(&ole,glb.verbosity); + OLE_set_debug(&ole,glb.debug); + OLE_set_save_unknown_streams(&ole,0); + OLE_set_filename_report_fn(&ole, MIME_report_filename_decoded_RIPOLE ); + + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Starting OLE Decode",FL,__func__); + result = OLE_decode_file(&ole, f, unpack_metadata ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decode done, cleaning up.",FL,__func__); + OLE_decode_done(&ole); + if (ole.f) + fseek(ole.f, 0, SEEK_SET); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decode returned with code = %d",FL,__func__,result); return result; } #endif + /*------------------------------------------------------------------------ -Procedure: MIME_decode_raw ID:1 +Procedure: MIME_decode_std_raw ID:1 Purpose: Decodes a binary type attachment, ie, no encoding, just raw data. Input: Output: Errors: ------------------------------------------------------------------------*/ -int MIME_decode_raw( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hinfo, int keep ) +MIME_element* MIME_decode_std_raw(MIME_element* parent, FFGET_FILE *f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo) { int result = 0; - char fullpath[1024]; int bufsize=1024; - char *buffer = malloc((bufsize +1)*sizeof(char)); + char *buffer = malloc((bufsize + 1)*sizeof(char)); size_t readcount; int file_has_uuencode = 0; int decode_entire_file = 0; - int fo; + MIME_element* cur_mime = NULL; /* Decoding / reading a binary attachment is a real interesting situation, as we * still use the fgets() call, but we do so repeatedly until it returns a line with a @@ -1256,74 +1118,64 @@ int MIME_decode_raw( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *h * --binary flag */ - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Start\n",FL); - - snprintf(fullpath,sizeof(fullpath),"%s/%s",unpackdir,hinfo->filename); - fo = open(fullpath, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Start\n",FL,__func__); - if (fo == -1) - { - LOGGER_log("%s:%d:MIME_decode_raw:ERROR: cannot open file %s for writing. (%s)\n\n",FL,fullpath,strerror(errno)); - return -1; - } + cur_mime = MIME_element_add (NULL, unpack_metadata, hinfo->filename, hinfo->content_type_string, hinfo->content_transfer_encoding_string, hinfo->name, hinfo->current_recursion_level, glb.attachment_count, glb.filecount, __func__); while ((readcount=FFGET_raw(f, (unsigned char *) buffer,bufsize)) > 0) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: BUFFER[%p]= '%s'\n",FL,buffer, buffer); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: BUFFER[%p]= '%s'\n",FL,__func__,buffer, buffer); if ((!file_has_uuencode)&&(UUENCODE_is_uuencode_header( buffer ))) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: UUENCODED is YES (buffer=[%p]\n",FL,buffer); - - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: File contains UUENCODED data(%s)\n",FL,buffer); - + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: File contains UUENCODED data(%s)\n",FL,__func__,buffer); file_has_uuencode = 1; } if (BS_cmp(buffer, readcount)) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Boundary located - breaking out.\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Boundary located - breaking out.\n",FL,__func__); break; } else { - size_t bc; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: writing: %s\n",FL, buffer); - bc = write( fo, buffer, readcount); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: writing: %s\n",FL,__func__, buffer); + fwrite( buffer, readcount, 1, cur_mime->f); } } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Completed reading RAW data\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Completed reading RAW data\n",FL,__func__); free(buffer); - close(fo); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Closed file and free'd buffer\n",FL); + // If there was UUEncoded portions [potentially] in the email, the // try to extract them using the MIME_decode_uu() if (file_has_uuencode) { - char full_decode_path[512]; - snprintf(full_decode_path,sizeof(full_decode_path),"%s/%s",unpackdir,hinfo->filename); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Decoding UUencoded data\n",FL); + FFGET_FILE * ffg = NULL; + + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding UUencoded data\n",FL,__func__); if ( hinfo->content_transfer_encoding == _CTRANS_ENCODING_UUENCODE ) decode_entire_file = 0; - //result = UUENCODE_decode_uu(NULL, unpackdir, hinfo->filename, hinfo->uudec_name, sizeof(hinfo->uudec_name), decode_entire_file, keep ); - result = UUENCODE_decode_uu(NULL, unpackdir, full_decode_path, hinfo->uudec_name, sizeof(hinfo->uudec_name), decode_entire_file, keep ); + ffg = UUENCODE_make_sourcestream(cur_mime->f); /* fseek to begin is here */ + result = UUENCODE_decode_uu(ffg , hinfo->uudec_name, decode_entire_file, unpack_metadata, hinfo ); if (result == -1) { switch (uuencode_error) { case UUENCODE_STATUS_SHORT_FILE: case UUENCODE_STATUS_CANNOT_OPEN_FILE: case UUENCODE_STATUS_CANNOT_FIND_FILENAME: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Nullifying uuencode_error result %d",FL, uuencode_error); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Nullifying uuencode_error result %d",FL,__func__, uuencode_error); result = 0; break; case UUENCODE_STATUS_CANNOT_ALLOCATE_MEMORY: - LOGGER_log("%s:%d:MIME_decode_raw:ERROR: Failure to allocate memory for UUdecode process",FL); - return -1; + LOGGER_log("%s:%d:%s:ERROR: Failure to allocate memory for UUdecode process",FL,__func__); + cur_mime->decode_result_code = -1; + return cur_mime; break; default: - LOGGER_log("%s:%d:MIME_decode_raw:ERROR: Unknown return code from UUDecode process [%d]",FL,uuencode_error); - return -1; + LOGGER_log("%s:%d:%s:ERROR: Unknown return code from UUDecode process [%d]",FL,__func__,uuencode_error); + cur_mime->decode_result_code = -1; + return cur_mime; } } if (result == UUENCODE_STATUS_SHORT_FILE) result = 0; @@ -1332,72 +1184,65 @@ int MIME_decode_raw( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *h { if (strcasecmp(hinfo->uudec_name,"winmail.dat")==0) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Decoding TNEF format\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding TNEF format\n",FL,__func__); snprintf(hinfo->filename, 128, "%s", hinfo->uudec_name); - MIME_decode_TNEF( unpackdir, hinfo, keep); + MIME_decode_TNEF( unpack_metadata, hinfo); } - else LOGGER_log("%s:%d:MIME_decode_raw:WARNING: hinfo has been clobbered.\n",FL); + else LOGGER_log("%s:%d:%s:WARNING: hinfo has been clobbered.\n",FL,__func__); } } + MIME_element_deactivate(cur_mime, unpack_metadata); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Closed file and free'd buffer\n",FL,__func__); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: End[result = %d]\n",FL,result); - return result; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: End[result = %d]\n",FL,__func__,result); + cur_mime->decode_result_code = result; + return cur_mime; } /*------------------------------------------------------------------------ -Procedure: MIME_decode_text ID:1 +Procedure: MIME_decode_std_text ID:1 Purpose: Decodes an input stream into a text file. Input: unpackdir : directory where to place new text file hinfo : struct containing information from the last parsed headers -keep : if set, retain the file Output: Errors: ------------------------------------------------------------------------*/ -int MIME_decode_text( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hinfo, int keep ) +MIME_element* MIME_decode_std_text( MIME_element* parent, FFGET_FILE *f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ) { - - FILE *of; // output file int linecount = 0; // The number of lines int file_has_uuencode = 0; // Flag to indicate this text has UUENCODE in it - char fullfilename[1024]=""; // Filename of the output file char line[1024]; // The input lines from the file we're decoding char *get_result = &line[0]; int lastlinewasboundary = 0; int result = 0; int decodesize=0; + MIME_element* cur_mime = NULL; - snprintf(fullfilename,sizeof(fullfilename),"%s/%s",unpackdir,hinfo->filename); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: Decoding TEXT [encoding=%d] to %s\n",FL, hinfo->content_transfer_encoding, fullfilename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding TEXT [encoding=%d] to %s\n",FL,__func__, hinfo->content_transfer_encoding, hinfo->filename); + cur_mime = MIME_element_add (NULL, unpack_metadata, hinfo->filename, hinfo->content_type_string, hinfo->content_transfer_encoding_string, hinfo->name, hinfo->current_recursion_level, glb.attachment_count, glb.filecount, __func__); if (!f) { /** If we cannot open the file for reading, leave an error and return -1 **/ - LOGGER_log("%s:%d:MIME_decode_text:ERROR: print-quotable input stream broken.",FL); - return _EXITERR_MIMEREAD_CANNOT_OPEN_INPUT; + LOGGER_log("%s:%d:%s:ERROR: print-quotable input stream broken.",FL,__func__); + cur_mime->decode_result_code = _EXITERR_MIMEREAD_CANNOT_OPEN_INPUT; + return cur_mime; } if (f) { - /** If we were able to open the input file, try opening the output file and process the data **/ - of = fopen(fullfilename,"w"); - if (!of) - { - /** If we were unable to open the output file, report the error and return -1 **/ - LOGGER_log("%s:%d:MIME_decode_text:ERROR: cannot open %s for writing",FL,fullfilename); - return _EXITERR_MIMEREAD_CANNOT_WRITE_OUTPUT; - } - while ((get_result = FFGET_fgets(line,1023,f))&&(of)) + while ((get_result = FFGET_fgets(line,1023,f))&&(cur_mime->f)) { int line_len = strlen(line); linecount++; - // if (MIME_DPEDANTIC) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: line=%s",FL,line); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: line[len=%d]=%s",FL,line_len,line); + // if (MIME_DPEDANTIC) LOGGER_log("%s:%d:%s:DEBUG: line=%s",FL,__func__,line); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: line[len=%d]=%s",FL,__func__,line_len,line); //20041217-1529:PLD: if (line[0] == '-') { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: Testing boundary",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: Testing boundary",FL,__func__); if ((BS_count() > 0)&&(BS_cmp(line,line_len))) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: Hit a boundary on the line",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: Hit a boundary on the line",FL,__func__); lastlinewasboundary = 1; result = 0; break; @@ -1408,37 +1253,33 @@ int MIME_decode_text( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info * { if (hinfo->content_transfer_encoding == _CTRANS_ENCODING_QP) { - size_t bc; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: Hit a boundary on the line",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: Hit a boundary on the line",FL,__func__); decodesize = MDECODE_decode_qp_text(line); - bc = fwrite(line, 1, decodesize, of); + fwrite(line, 1, decodesize, cur_mime->f); } else { - fprintf(of,"%s",line); + fprintf(cur_mime->f,"%s",line); } if ((!file_has_uuencode)&&( UUENCODE_is_uuencode_header( line ))) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: UUENCODED data located in file.\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: UUENCODED data located in file.\n",FL,__func__); file_has_uuencode = 1; } } // linecount++; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: End processing line.",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_DNORMAL:DEBUG: End processing line.",FL,__func__); } // while - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: Done writing output file '%s'...now attempting to close.",FL, fullfilename); - // if the file is still safely open - if (of) - { - fclose(of); - } // if file still safely open + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Done writing output file '%s'...now attempting to close.",FL,__func__, cur_mime->fullpath); + + MIME_element_deactivate(cur_mime, unpack_metadata); if (linecount == 0) { - result = MIME_STATUS_ZERO_FILE; - return result; + cur_mime->decode_result_code = MIME_STATUS_ZERO_FILE; + return cur_mime; } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: Closed.",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Closed.",FL,__func__); } // if main input file stream was open // If our input from the file was invalid due to EOF or other @@ -1446,7 +1287,7 @@ int MIME_decode_text( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info * // occured. // if (!get_result) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: FFGET module ran out of file data while attempting to decode",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: FFGET module ran out of file data while attempting to decode",FL,__func__); // result = -1; result = MIME_ERROR_FFGET_EMPTY; // 20040305-1323:PLD } @@ -1456,14 +1297,20 @@ int MIME_decode_text( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info * // if (file_has_uuencode) { - char ffname[256]; - snprintf(ffname,256,"%s/%s", unpackdir, hinfo->filename); + FILE *fuue = NULL; + FFGET_FILE * ffg = NULL; + char *fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(hinfo->filename) + sizeof(char) * 2; + + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,hinfo->filename); + // PLD-20040627-1212 // Make sure uudec_name is blank too // hinfo->uudec_name[0] = '\0'; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: Decoding UUencoded data in file '%s'\n",FL,hinfo->filename); - //result = UUENCODE_decode_uu( NULL, unpackdir, hinfo->filename, hinfo->uudec_name, sizeof(hinfo->uudec_name), 1, keep ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding UUencoded data in file '%s'\n",FL,__func__,hinfo->filename); + //result = UUENCODE_decode_uu( NULL, info->filename, hinfo->uudec_name, 1 ); // Attempt to decode the UUENCODED data in the file, // NOTE - hinfo->uudec_name is a blank buffer which will be filled by the UUENCODE_decode_uu // function once it has located a filename in the UUENCODED data. A bit of a problem here @@ -1472,43 +1319,50 @@ int MIME_decode_text( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info * // NOTE - this function returns the NUMBER of attachments it decoded in the return value! Don't // propergate this value unintentionally to parent functions (ie, if you were thinking it was // an error-status return value + fuue = UUENCODE_make_file_obj (fn); + free(fn); + ffg = UUENCODE_make_sourcestream(fuue); - result = UUENCODE_decode_uu( NULL, unpackdir, ffname, hinfo->uudec_name, sizeof(hinfo->uudec_name), 1, keep ); + result = UUENCODE_decode_uu( ffg, hinfo->uudec_name, 1, unpack_metadata, hinfo ); + fclose(fuue); if (result == -1) { switch (uuencode_error) { case UUENCODE_STATUS_SHORT_FILE: case UUENCODE_STATUS_CANNOT_OPEN_FILE: case UUENCODE_STATUS_CANNOT_FIND_FILENAME: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_raw:DEBUG: Nullifying uuencode_error result %d",FL, uuencode_error); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Nullifying uuencode_error result %d",FL,__func__, uuencode_error); result = 0; break; case UUENCODE_STATUS_CANNOT_ALLOCATE_MEMORY: - LOGGER_log("%s:%d:MIME_decode_raw:ERROR: Failure to allocate memory for UUdecode process",FL); - return -1; + LOGGER_log("%s:%d:%s:ERROR: Failure to allocate memory for UUdecode process",FL,__func__); + cur_mime->decode_result_code = -1; + return cur_mime; break; default: - LOGGER_log("%s:%d:MIME_decode_raw:ERROR: Unknown return code from UUDecode process [%d]",FL,uuencode_error); - return -1; + LOGGER_log("%s:%d:%s:ERROR: Unknown return code from UUDecode process [%d]",FL,__func__,uuencode_error); + cur_mime->decode_result_code = -1; + return cur_mime; } } if ( result > 0 ) { glb.attachment_count += result; result = 0; } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: hinfo = %p\n",FL,hinfo); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: Done. [ UUName = '%s' ]\n",FL,hinfo->uudec_name); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: hinfo = %p\n",FL,__func__,hinfo); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Done. [ UUName = '%s' ]\n",FL,__func__,hinfo->uudec_name); if (strncasecmp(hinfo->uudec_name,"winmail.dat",11)==0) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: Decoding TNEF format\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding TNEF format\n",FL,__func__); snprintf(hinfo->filename, 128, "%s", hinfo->uudec_name); - MIME_decode_TNEF( unpackdir, hinfo, keep ); + MIME_decode_TNEF( unpack_metadata, hinfo ); } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: Completed decoding UUencoded data.\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Completed decoding UUencoded data.\n",FL,__func__); } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_text:DEBUG: result=%d ----------------Done\n",FL,result); - return result; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: result=%d ----------------Done\n",FL,__func__,result); + cur_mime->decode_result_code = result; + return cur_mime; } /*------------------------------------------------------------------------ -Procedure: MIME_decode_64 ID:1 +Procedure: MIME_decode_std_64 ID:1 Purpose: This routine is very very very important, it's the key to ensuring we get our attachments out of the email file without trauma! NOTE - this has been -slightly altered- in order to make provision @@ -1518,12 +1372,12 @@ now have to detect the start character of the "boundary" marker I may consider testing the 1st n' chars of the boundary marker just incase it's not always a hypen '-'. Input: FGET_FILE *f: stream we're reading from -char *unpackdir: directory we have to write the file to +RIPMIME_output *unpack_metadata: directory we have to write the file to struct MIMEH_header_info *hinfo: Auxillairy information such as the destination filename Output: Errors: ------------------------------------------------------------------------*/ -int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hinfo ) +MIME_element* MIME_decode_std_64( MIME_element* parent, FFGET_FILE *f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ) { int i; int cr_total = 0; @@ -1538,7 +1392,6 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi long int bytecount=0; /* The total file decoded size */ char output[3]; /* The 4->3 byte output array */ char input[4]; /* The 4->3 byte input array */ - char fullMIME_filename[_MIME_STRLEN_MAX]=""; /* Full Filename of output file */ // Write Buffer routine @@ -1546,21 +1399,15 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi unsigned char *wbpos; int wbcount = 0; int loop; + MIME_element* cur_mime = NULL; - int of; /* output file pointer */ - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: attempting to decode '%s'", FL, hinfo->filename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: attempting to decode '%s'", FL,__func__, hinfo->filename); - /* generate the MIME_filename, and open it up... */ - if (glb.unique_names) MIME_test_uniquename( unpackdir, hinfo->filename, glb.rename_method ); - snprintf(fullMIME_filename,_MIME_STRLEN_MAX,"%s/%s",unpackdir,hinfo->filename); - //of = fopen(fullMIME_filename,"wb"); - of = open(fullMIME_filename, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); - /* if we were unable to open the output file, then we better log an error and drop out */ - if (of < 0) + cur_mime = MIME_element_add (NULL, unpack_metadata, hinfo->filename, hinfo->content_type_string, hinfo->content_transfer_encoding_string, hinfo->name, hinfo->current_recursion_level, glb.attachment_count, glb.filecount, __func__); + if (cur_mime->f == NULL) { - LOGGER_log("%s:%d:MIME_decode_64:ERROR: Cannot open output file %s for BASE64 decoding. (%s)",FL,fullMIME_filename, strerror(errno)); - // exit(_EXITERR_BASE64_OUTPUT_NOT_OPEN); - return -1; + cur_mime->decode_result_code = -1; + return cur_mime; } // Allocate the write buffer. By using the write buffer we gain an additional 10% in performance @@ -1568,8 +1415,9 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi writebuffer = malloc( _MIME_WRITE_BUFFER_SIZE *sizeof(unsigned char)); if (!writebuffer) { - LOGGER_log("%s:%d:MIME_decode_64:ERROR: cannot allocate %dbytes of memory for the write buffer",FL, _MIME_WRITE_BUFFER_SIZE); - return -1; + LOGGER_log("%s:%d:%s:ERROR: cannot allocate %dbytes of memory for the write buffer",FL,__func__, _MIME_WRITE_BUFFER_SIZE); + cur_mime->decode_result_code = -1; + return cur_mime; } else { wbpos = writebuffer; @@ -1578,7 +1426,7 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi /* Set our ignore_crcount flag */ if (BS_count() > 0) { - //LOGGER_log("%s:%d:MIME_decode_64:DEBUG: Ignore CR set to 1",FL); + //LOGGER_log("%s:%d:%s:DEBUG: Ignore CR set to 1",FL,__func__); ignore_crcount = 1; } /* collect prefixing trash (if any, such as spaces, CR's etc)*/ @@ -1590,7 +1438,6 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi /* do an endless loop, as we're -breaking- out later */ while (1) { - int lastchar_was_linebreak=0; /* Initialise the decode buffer */ input[0] = input[1] = input[2] = input[3] = 0; // was '0' - Stepan Kasal patch /* snatch 4 characters from the input */ @@ -1607,7 +1454,7 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi //----------INLINE Version of FFGET_getchar() // do { - if ((c == '\n')||(c == '\r')) lastchar_was_linebreak = 1; else lastchar_was_linebreak = 0; + // lastchar_was_linebreak = ((c == '\n')||(c == '\r')); if (f->ungetcset) { f->ungetcset = 0; @@ -1634,11 +1481,11 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi // //-------END OF INLINE--------------------------------------------- if ((ignore_crcount == 1)&&(c == '-')) - //&&(lastchar_was_linebreak == 1)) + //&&(lastchar_was_linebreak)) { int hit = 0; char *p; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: leader '-' found at %50s",FL,(f->startpoint -1)); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: leader '-' found at %50s",FL,__func__,(f->startpoint -1)); p = strchr((f->startpoint -1), '\n'); if (p == NULL) { /* The boundary test was failing because sometimes the full line @@ -1647,16 +1494,16 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi */ char scratch[1024]; FFGET_fgets(scratch,sizeof(scratch), f); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: Scratch = '%s'", FL, scratch); - hit = BS_cmp(scratch,strlen(scratch) +1); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: Boundary hit = %d", FL, hit); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Scratch = '%s'", FL,__func__, scratch); + hit = BS_cmp(scratch,strlen(scratch) + 1); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Boundary hit = %d", FL,__func__, hit); } else { *p = '\0'; - hit = BS_cmp((f->startpoint -1),strlen(f->startpoint) +1); + hit = BS_cmp((f->startpoint -1),strlen(f->startpoint) + 1); *p = '\n'; } if (hit > 0) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: Boundary detected and breaking out ",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Boundary detected and breaking out ",FL,__func__); // FFGET_fgets(scratch,sizeof(scratch),f); // eom_reached = 1; boundary_crash = 1; @@ -1691,7 +1538,7 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi // CR's ). if (cr_count > 2) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: EOF Reached due to two consecutive CR's on line %d\n",FL,cr_total); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: EOF Reached due to two consecutive CR's on line %d\n",FL,__func__,cr_total); eom_reached++; break; } @@ -1707,18 +1554,19 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi /* if we get an EOF char, then we know something went wrong */ if ( c == EOF ) { - size_t bc; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: input stream broken for base64 decoding for file %s. %ld bytes of data in buffer to be written out\n",FL,hinfo->filename,wbcount); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: input stream broken for base64 decoding for file %s. %ld bytes of data in buffer to be written out\n",FL,__func__,hinfo->filename,wbcount); status = MIME_ERROR_B64_INPUT_STREAM_EOF; - //fwrite(writebuffer, 1, wbcount, of); - bc = write( of, writebuffer, wbcount); - close(of); - if (writebuffer) free(writebuffer); - return status; + fwrite(writebuffer, 1, wbcount, cur_mime->f); + MIME_element_deactivate(cur_mime, unpack_metadata); + if (writebuffer) + free(writebuffer); + cur_mime->decode_result_code = status; + return cur_mime; break; } /* if c was the EOF */ else if (c == '=') { + char line_buf[1025]; // Once we've found a stop char, we can actually just "pad" in the rest // of the stop chars because we know we're at the end. Some MTA's dont // put in enough stopchars... at least it seems X-MIMEOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 @@ -1737,8 +1585,8 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi // are now only retrieving data byte at a time. // So, now we -absorb- till the end of the line using FFGET_fgets() stopcount = 4 -i; - FFGET_fgets(scratch,sizeof(scratch),f); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: Stop char detected pos=%d...StopCount = %d\n",FL,i,stopcount); + FFGET_fgets(line_buf,1024,f); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Stop char detected pos=%d...StopCount = %d\n",FL,__func__,i,stopcount); i = 4; break; // out of FOR. } @@ -1778,9 +1626,7 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi // interrupt costs. if ( wbcount > _MIME_WRITE_BUFFER_LIMIT ) { - size_t bc; - bc = write ( of, writebuffer, wbcount ); - // fwrite(writebuffer, 1, wbcount, of); + fwrite(writebuffer, 1, wbcount, cur_mime->f); wbpos = writebuffer; wbcount = 0; } @@ -1794,7 +1640,7 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi // tally up our total byte conversion count bytecount+=(3 -stopcount); } - else if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: could not attain 4 bytes input\n",FL); + else if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: could not attain 4 bytes input\n",FL,__func__); // if we wrote less than 3 chars, it means we were at the end of the encoded file thus we exit if ((eom_reached)||(stopcount > 0)||(boundary_crash)||(i!=4)) @@ -1803,40 +1649,40 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi // we'll end up with truncated files. if (wbcount > 0) { - size_t bc; - //fwrite(writebuffer, 1, wbcount, of); - bc = write( of, writebuffer, wbcount); + fwrite(writebuffer, 1, wbcount, cur_mime->f); } /* close the output file, we're done writing to it */ - close(of); + MIME_element_deactivate(cur_mime, unpack_metadata); /* if we didn't really write anything, then trash the file */ if (bytecount == 0) { - // unlink(fullMIME_filename); + // unlink(fullpath); status = MIME_BASE64_STATUS_ZERO_FILE; } if (boundary_crash) { // Absorb to end of line - // status = MIME_BASE64_STATUS_HIT_BOUNDARY; // was _BOUNDARY_CRASH } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_64:DEBUG: File size = %ld bytes, Exit Status = %d, Boundary Crash = %d\n",FL, bytecount, status, boundary_crash); - if (writebuffer) free(writebuffer); - return status; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: File size = %ld bytes, Exit Status = %d, Boundary Crash = %d\n",FL,__func__, bytecount, status, boundary_crash); + if (writebuffer) + free(writebuffer); + cur_mime->decode_result_code = status; + return cur_mime; } // if End-of-MIME or Stopchars appeared } // while - if (writebuffer) free(writebuffer); - return status; + if (writebuffer) + free(writebuffer); + cur_mime->decode_result_code = status; + return cur_mime; } - /*-----------------------------------------------------------------\ - Function Name : MIME_decode_64_cleanup + Function Name : MIME_decode_std_64_cleanup Returns Type : int ----Parameter List 1. FFGET_FILE *f, - 2. char *unpackdir, + 2. RIPMIME_output *unpack_metadata, 3. struct MIMEH_header_info *hinfo, ------------------ Exit Codes : @@ -1848,7 +1694,7 @@ int MIME_decode_64( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hi Changes: \------------------------------------------------------------------*/ -int MIME_decode_64_cleanup( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hinfo) +int MIME_decode_std_64_cleanup( FFGET_FILE *f) { int result = 0; char buffer[128]; @@ -1867,13 +1713,13 @@ Purpose: Decodes a text sequence as detected in the processing of the MIME This is a specialised call, not really a normal part of MIME decoding, but is required in order to deal with decyphering MS Outlook visable defects. Input: char *filename: Name of the encoded file we need to decode -char *unpackdir: Directory we need to unpack the file to +RIPMIME_output *unpack_metadata: Directory we need to unpack the file to struct MIMEH_header_info *hinfo: Header information already gleaned from the headers int current_recursion_level: How many nest levels we are deep Output: Errors: ------------------------------------------------------------------------*/ -int MIME_doubleCR_decode( char *filename, char *unpackdir, struct MIMEH_header_info *hinfo, int current_recursion_level ) +int MIME_doubleCR_decode( char *filename, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo, int current_recursion_level ) { int result = 0; struct MIMEH_header_info h; @@ -1885,21 +1731,27 @@ int MIME_doubleCR_decode( char *filename, char *unpackdir, struct MIMEH_header_i p = filename; // * Initialise the header fields h.uudec_name[0] = '\0'; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_doubleCR_decode:DEBUG: filename=%s, path=%s, recursion=%d", FL, filename, unpackdir, current_recursion_level ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: filename=%s, path=%s, recursion=%d", FL,__func__, filename, unpack_metadata->dir, current_recursion_level ); memcpy(&h, hinfo, sizeof(h)); // Works for ripMIME snprintf(h.filename, sizeof(h.filename), "%s/%s", unpackdir, p); snprintf(h.filename, sizeof(h.filename), "%s", p); /// Works for Xamime - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_doubleCR_decode:DEBUG: header.filename = %s", FL, h.filename ); - if (MIME_is_file_RFC822(filename)) + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: header.filename = %s", FL,__func__, h.filename ); + if (MIME_is_diskfile_RFC822(filename)) { if (MIME_VERBOSE) LOGGER_log("Attempting to decode Double-CR delimeted MIME attachment '%s'\n",filename); - result = MIME_unpack( unpackdir, filename, current_recursion_level ); // 20040305-1303:PLD - Capture the result of the unpack and propagate up + result = MIME_unpack( unpack_metadata, filename, current_recursion_level ); // 20040305-1303:PLD - Capture the result of the unpack and propagate up } - else if (UUENCODE_is_file_uuencoded(h.filename)) + else if (UUENCODE_is_diskfile_uuencoded(h.filename)) { + FILE *fuue = NULL; + FFGET_FILE * ffg = NULL; + if (MIME_VERBOSE) LOGGER_log("Attempting to decode UUENCODED attachment from Double-CR delimeted attachment '%s'\n",filename); + fuue = UUENCODE_make_file_obj (filename); + ffg = UUENCODE_make_sourcestream(fuue); UUENCODE_set_doubleCR_mode(1); - result = UUENCODE_decode_uu(NULL, unpackdir, filename, h.uudec_name, _MIMEH_FILENAMELEN_MAX , 1, 1 ); + result = UUENCODE_decode_uu(ffg, h.uudec_name, 1, unpack_metadata, hinfo ); + fclose(fuue); UUENCODE_set_doubleCR_mode(0); glb.attachment_count += result; result = 0; @@ -1926,61 +1778,61 @@ size_t MIME_read_raw( char *src_mpname, char *dest_mpname, size_t rw_buffer_size size_t readcount, writecount; size_t fsize=-1; char *rw_buffer; - int fin; - int fout; + FILE* input_f = NULL; + FILE* result_f = NULL; rw_buffer = NULL; if (*src_mpname == '\0') { - fin = STDIN_FILENO; + input_f = STDIN_FILENO; } else { - fin = open(src_mpname, O_RDONLY); - if (fin == -1) { - LOGGER_log("%s:%d:MIME_read_raw:ERROR: Cannot open '%s' for reading (%s)", FL, src_mpname, strerror(errno)); + input_f = fopen(src_mpname, "r"); + if (input_f == NULL) { + LOGGER_log("%s:%d:%s:ERROR: Cannot open '%s' for reading (%s)", FL,__func__, src_mpname, strerror(errno)); return -1; } } - rw_buffer = malloc( (rw_buffer_size +1) *sizeof(char) ); + rw_buffer = malloc( (rw_buffer_size + 1) *sizeof(char) ); if ( !rw_buffer ) { - LOGGER_log("%s:%d:MIME_read:ERROR: could not allocate %d of memory for file read buffer\n",FL, rw_buffer_size ); + LOGGER_log("%s:%d:%s:ERROR: could not allocate %d of memory for file read buffer\n",FL,__func__, rw_buffer_size ); return -1; } /* open up our input file */ - fout = open(dest_mpname,O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); - if (fout == -1) { - LOGGER_log("%s:%d:MIME_read_raw:ERROR: Cannot open '%s' for writing. (%s)",FL, dest_mpname, strerror(errno)); + result_f = fopen(dest_mpname, "w"); + if (result_f == NULL) { + LOGGER_log("%s:%d:%s:ERROR: Cannot open '%s' for writing. (%s)",FL,__func__, dest_mpname, strerror(errno)); return -1; } fsize=0; /* while there is more data, consume it */ do { - readcount = read( fin, rw_buffer, rw_buffer_size ); + readcount = fread( rw_buffer, rw_buffer_size, 1, input_f ); if (readcount > 0) { - writecount = write( fout, rw_buffer, readcount ); + writecount = fwrite(rw_buffer, readcount, 1, result_f ); if (writecount == -1) { - LOGGER_log("%s:%d:MIME_read_raw:ERROR: While attempting to write data to '%s' (%s)", FL, dest_mpname, strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: While attempting to write data to '%s' (%s)", FL,__func__, dest_mpname, strerror(errno)); return -1; } if ( readcount != writecount ) { - LOGGER_log("%s:%d:MIME_read_raw:ERROR: Attempted to write %d bytes, but only managed %d to file '%s'",FL, readcount, writecount, dest_mpname ); + LOGGER_log("%s:%d:%s:ERROR: Attempted to write %d bytes, but only managed %d to file '%s'",FL,__func__, readcount, writecount, dest_mpname ); } fsize += writecount; } } while (readcount > 0); if ((*src_mpname != '\0')&&(readcount >= 0)) { - close(fin); + fclose(input_f); } if (readcount == -1) { - LOGGER_log("%s:%d:MIME_read_raw:ERROR: read() '%s'",FL, strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: read() '%s'",FL,__func__, strerror(errno)); return -1; } - close(fout); + fclose(result_f); if ( rw_buffer != NULL ) free( rw_buffer ); return (size_t)(fsize); } @@ -2008,7 +1860,7 @@ int MIME_read( char *mpname ) buffer = malloc( MIME_MIME_READ_BUFFER_SIZE *sizeof(char) ); if ( !buffer ) { - LOGGER_log("%s:%d:MIME_read:ERROR: could not allocate 4K of memory for file read buffer\n",FL ); + LOGGER_log("%s:%d:%s:ERROR: could not allocate 4K of memory for file read buffer\n",FL,__func__ ); return -1; } /* open up our input file */ @@ -2016,7 +1868,7 @@ int MIME_read( char *mpname ) /* check that out file opened up okay */ if (!fout) { - LOGGER_log("%s:%d:MIME_read:ERROR: Cannot open file %s for writing... check permissions perhaps?",FL,mpname); + LOGGER_log("%s:%d:%s:ERROR: Cannot open file %s for writing... check permissions perhaps?",FL,__func__,mpname); //exit(_EXITERR_MIMEREAD_CANNOT_OPEN_OUTPUT); return -1; } @@ -2035,7 +1887,7 @@ int MIME_read( char *mpname ) if ( readcount != writecount ) { - LOGGER_log("%s:%d:MIME_read:ERROR: Attempted to write %d bytes, but only managed %d to file '%s'",FL, readcount, writecount, mpname ); + LOGGER_log("%s:%d:%s:ERROR: Attempted to write %d bytes, but only managed %d to file '%s'",FL,__func__, readcount, writecount, mpname ); } } else { @@ -2052,9 +1904,6 @@ int MIME_read( char *mpname ) return (int)(fsize /1024); } - - - /*------------------------------------------------------------------------ Procedure: MIME_init ID:1 Purpose: Initialise various required parameters to ensure a clean starting of @@ -2063,17 +1912,15 @@ MIME decoding. Output: Errors: ------------------------------------------------------------------------*/ -int MIME_init( void ) +void MIME_init( void ) { - BS_init(); // Boundary-stack initialisations MIMEH_init(); // Initialise MIME header routines. UUENCODE_init(); // uuen:coding decoding initialisations FNFILTER_init(); // Filename filtering - MDECODE_init(); // ISO filename decoding initialisation + MDECODE_init(); // ISO filename decoding initialisation TNEF_init(); // TNEF decoder - glb.header_defect_count = 0; glb.filecount = 0; glb.attachment_count = 0; @@ -2084,12 +1931,10 @@ int MIME_init( void ) glb.quiet = 0; glb.syslogging = 0; glb.stderrlogging = 1; - glb.unique_names = 0; - glb.save_headers = 0; + glb.dump_headers = 0; glb.no_nameless = 0; glb.mailbox_format = 0; glb.name_by_type = 0; - glb.rename_method = _MIME_RENAME_METHOD_INFIX; glb.header_longsearch = 0; glb.max_recursion_level = _RECURSION_LEVEL_DEFAULT; @@ -2112,11 +1957,9 @@ int MIME_init( void ) glb.subject[0]='\0'; - return 0; + all_MIME_elements_init(); } - - /*-----------------------------------------------------------------\ Function Name : MIME_generate_multiple_hardlink_filenames Returns Type : int @@ -2135,19 +1978,24 @@ hardlinks to replicate this in our output. Changes: \------------------------------------------------------------------*/ -int MIME_generate_multiple_hardlink_filenames(struct MIMEH_header_info *hinfo, char *unpackdir) +void MIME_generate_multiple_hardlink_filenames(struct MIMEH_header_info *hinfo, RIPMIME_output *unpack_metadata) { char *name; - char oldname[1024]; + char *oldfn; + int fn_l = strlen(unpack_metadata->dir) + strlen(hinfo->filename) + sizeof(char) * 2; - if (glb.multiple_filenames == 0) return 0; + if (glb.multiple_filenames == 0) + return; - //LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:DEBUG: Generating hardlinks for %s",FL, hinfo->filename); - snprintf(oldname,sizeof(oldname),"%s/%s",unpackdir, hinfo->filename); + //LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:DEBUG: Generating hardlinks for %s",FL,__func__, hinfo->filename); + oldfn = malloc(fn_l); + snprintf(oldfn,fn_l,"%s/%s",unpack_metadata->dir,hinfo->filename); - if (SS_count(&(hinfo->ss_names)) > 1){ - do { + if (SS_count(&(hinfo->ss_names)) > 1) + { + do + { name = SS_pop(&(hinfo->ss_names)); if (name != NULL) { @@ -2159,14 +2007,14 @@ int MIME_generate_multiple_hardlink_filenames(struct MIMEH_header_info *hinfo, c np = strrchr(name, '/'); if (np) np++; else np = name; - snprintf(newname,sizeof(newname),"%s/%s",unpackdir, np); - //LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:DEBUG: Linking %s->%s",FL,newname, oldname); - rv = link(oldname, newname); + snprintf(newname,sizeof(newname),"%s/%s",unpack_metadata->dir, np); + //LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:DEBUG: Linking %s->%s",FL,__func__,newname, oldfn); + rv = link(oldfn, newname); if (rv == -1) { if (errno != EEXIST) { - LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:WARNING: While trying to create '%s' link to '%s' (%s)",FL, newname, oldname,strerror(errno)); + LOGGER_log("%s:%d:%s:WARNING: While trying to create '%s' link to '%s' (%s)",FL,__func__, newname, oldfn,strerror(errno)); } } else { @@ -2176,27 +2024,26 @@ int MIME_generate_multiple_hardlink_filenames(struct MIMEH_header_info *hinfo, c } } } - } while(name != NULL); } if (SS_count(&(hinfo->ss_filenames)) > 1) { - do { - + do + { name = SS_pop(&(hinfo->ss_filenames)); if (name != NULL) { char newname[1024]; int rv; - snprintf(newname,sizeof(newname),"%s/%s",unpackdir, name); - //LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:DEBUG: Linking %s->%s",FL,newname, oldname); - rv = link(oldname, newname); + snprintf(newname,sizeof(newname),"%s/%s",unpack_metadata->dir, name); + //LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:DEBUG: Linking %s->%s",FL,__func__,newname, oldfn); + rv = link(oldfn, newname); if (rv == -1) { if (errno != EEXIST) { - LOGGER_log("%s:%d:MIME_generate_multiple_hardlink_filenames:WARNING: While trying to create '%s' link to '%s' (%s)",FL, newname, oldname,strerror(errno)); + LOGGER_log("%s:%d:%s:WARNING: While trying to create '%s' link to '%s' (%s)",FL,__func__, newname, oldfn,strerror(errno)); } } else { @@ -2206,35 +2053,44 @@ int MIME_generate_multiple_hardlink_filenames(struct MIMEH_header_info *hinfo, c } } } - } while(name != NULL); } + free(oldfn); +} - return 0; - +MIME_element * resencapsulate(MIME_element *decoded_mime, int decode_result, struct MIMEH_header_info *hinfo) +{ + if (decoded_mime == NULL) + { + decoded_mime = malloc(sizeof(MIME_element)); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoded MIME NULL!! filename = '%s'",FL,__func__,hinfo->filename); + } + decoded_mime->decode_result_code = decode_result; + return decoded_mime; } /*------------------------------------------------------------------------ -Procedure: MIME_decode_encoding ID:1 +Procedure: MIME_process_content_transfer_encoding ID:1 Purpose: Based on the contents of hinfo, this function will call the -required function needed to decode the contents of the file -which is contained within the MIME structure + required function needed to decode the contents of the file + which is contained within the MIME structure Input: Output: Errors: ------------------------------------------------------------------------*/ -int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hinfo, struct SS_object *ss ) +MIME_element* MIME_process_content_transfer_encoding( MIME_element* parent_mime, FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo, struct SS_object *ss ) { int keep = 1; - int result = -1; + int decode_result = -1; + MIME_element* decoded_mime = NULL; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Start:DEBUG: (%s)\n",FL, hinfo->filename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Start:DEBUG: (%s)\n",FL,__func__, hinfo->filename); // If we have a valid filename, then put it through the process of // cleaning and filtering if (isprint((int)hinfo->filename[0])) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Filename is valid, cleaning\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Filename is valid, cleaning\n",FL,__func__); FNFILTER_filter(hinfo->filename, _MIMEH_FILENAMELEN_MAX); /* check out thefilename for ISO filenames */ } @@ -2265,7 +2121,7 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in // then we'll simply use the blankfileprefix. snprintf( hinfo->filename, _MIMEH_FILENAMELEN_MAX, "%s%d", glb.blankfileprefix, glb.filecount ); } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Filename is empty, setting to default...(%s)\n",FL, hinfo->filename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Filename is empty, setting to default...(%s)\n",FL,__func__, hinfo->filename); if (glb.no_nameless) keep = 0; glb.filecount++; } @@ -2279,9 +2135,9 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in // If we are required to have "unique" filenames for everything, rather than // allowing ripMIME to overwrite stuff, then we put the filename through // its tests here - if ((glb.unique_names)&&(keep)) + if ((unpack_metadata->unique_names)&&(keep)) { - MIME_test_uniquename( unpackdir, hinfo->filename, glb.rename_method ); + MIME_test_uniquename( unpack_metadata, hinfo->filename ); } // If the calling program requested verbosity, then indicate that we're decoding // the file here @@ -2310,7 +2166,7 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in // The format of the evaluation is: // // (logic-test?true-expression:false-expression) - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: About to execute callback [0x%p]",FL,glb.filename_decoded_reporter); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: About to execute callback [0x%p]",FL,__func__,glb.filename_decoded_reporter); if (glb.filename_decoded_reporter != NULL) { glb.filename_decoded_reporter( hinfo->filename, (MIMEH_get_verbosity_contenttype()?hinfo->content_type_string:NULL)); @@ -2318,13 +2174,16 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in } // If we were using the new filename telling format } // If we were telling the filename (verbosity) - if (1) + { char *fp; /** Find the start of the filename. **/ fp = strrchr(hinfo->filename, '/'); - if (fp) fp++; else fp = hinfo->filename; - //LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Pushing filename %s to the stack",FL,fp); + if (fp) + fp++; + else + fp = hinfo->filename; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Pushing filename %s to the stack",FL,__func__,fp); // 20040305-1419:PLD // Store the filename we're going to use to save the file to in the filename stack SS_push(ss, fp, strlen(fp)); @@ -2332,68 +2191,77 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in // Select the decoding method based on the content transfer encoding // method which we read from the headers - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: ENCODING = %d\n",FL, hinfo->content_transfer_encoding); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: ENCODING = %d\n",FL,__func__, hinfo->content_transfer_encoding); switch (hinfo->content_transfer_encoding) { case _CTRANS_ENCODING_B64: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding BASE64 format\n",FL); - result = MIME_decode_64(f, unpackdir, hinfo); - switch (result) { + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding BASE64 format\n",FL,__func__); + decoded_mime = MIME_decode_std_64(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; + switch (decode_result) { case MIME_ERROR_B64_INPUT_STREAM_EOF: break; case MIME_BASE64_STATUS_HIT_BOUNDARY: - result = 0; + decode_result = 0; break; case 0: - result = MIME_decode_64_cleanup(f, unpackdir, hinfo); + decode_result = MIME_decode_std_64_cleanup(input_f); break; default: break; } break; case _CTRANS_ENCODING_7BIT: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding 7BIT format\n",FL); - result = MIME_decode_text(f, unpackdir, hinfo, keep); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding 7BIT format\n",FL,__func__); + + decoded_mime = MIME_decode_std_text(parent_mime, input_f, unpack_metadata, hinfo);decode_result = decoded_mime->decode_result_code; break; case _CTRANS_ENCODING_8BIT: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding 8BIT format\n",FL); - result = MIME_decode_text(f, unpackdir, hinfo, keep); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding 8BIT format\n",FL,__func__); + decoded_mime = MIME_decode_std_text(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; break; case _CTRANS_ENCODING_BINARY: case _CTRANS_ENCODING_RAW: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding RAW format\n",FL); - result = MIME_decode_raw(f, unpackdir, hinfo, keep); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding RAW format\n",FL,__func__); + decoded_mime = MIME_decode_std_raw(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; break; case _CTRANS_ENCODING_QP: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding Quoted-Printable format\n",FL); - result = MIME_decode_text(f, unpackdir, hinfo, keep); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding Quoted-Printable format\n",FL,__func__); + decoded_mime = MIME_decode_std_text(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; break; case _CTRANS_ENCODING_UUENCODE: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding UUENCODED format\n",FL); + int fcount; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding UUENCODED format\n",FL,__func__); // Added as a test - remove if we can get this to work in a better way snprintf(hinfo->uudec_name,sizeof(hinfo->uudec_name),"%s",hinfo->filename); - result = UUENCODE_decode_uu(f, unpackdir, hinfo->filename, hinfo->uudec_name, sizeof(hinfo->uudec_name), 0, keep ); - glb.attachment_count += result; + fcount = UUENCODE_decode_uu(input_f, hinfo->uudec_name, 0, unpack_metadata, hinfo ); + glb.attachment_count += fcount; // Because this is a file-count, it's not really an 'error result' as such, so, set the // return code back to 0! - result = 0; + decode_result = 0; break; case _CTRANS_ENCODING_UNKNOWN: switch (hinfo->content_disposition) { case _CDISPOSITION_FORMDATA: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding UNKNOWN format of FORMDATA disposition\n",FL); - result = MIME_decode_raw(f, unpackdir, hinfo, keep); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding UNKNOWN format of FORMDATA disposition\n",FL,__func__); + decoded_mime = MIME_decode_std_raw(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; break; default: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding UNKNOWN format\n",FL); - result = MIME_decode_text(f, unpackdir, hinfo, keep); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding UNKNOWN format\n",FL,__func__); + decoded_mime = MIME_decode_std_text(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: UNKNOWN Decode completed, result = %d\n",FL,result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: UNKNOWN Decode completed, result = %d\n",FL,__func__,decode_result); break; case _CTRANS_ENCODING_UNSPECIFIED: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding UNSPECIFIED format\n",FL); - result = MIME_decode_text(f, unpackdir, hinfo, keep); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding result for UNSPECIFIED format = %d\n",FL, result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding UNSPECIFIED format\n",FL,__func__); + decoded_mime = MIME_decode_std_text(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding result for UNSPECIFIED format = %d\n",FL,__func__, decode_result); // 20040114-1236:PLD: Added nested mail checking // // Sometimes mailpacks have false headers at the start, resulting @@ -2405,40 +2273,42 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in // because dud headers will always result in a UNSPECIFIED encoding // // Original sample mailpack was sent by Farit - thanks. - if (1) + char *fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(hinfo->filename) + sizeof(char) * 2; + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,hinfo->filename); + LOGGER_log("%s:%d:%s:DEBUG:REMOVEME: Testing for RFC822 headers in file %s",FL,__func__,fn); + if (MIME_is_diskfile_RFC822(fn) > 0 ) { - snprintf(hinfo->scratch,sizeof(hinfo->scratch),"%s/%s",unpackdir,hinfo->filename); - LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG:REMOVEME: Testing for RFC822 headers in file %s",FL,hinfo->scratch); - if (MIME_is_file_RFC822(hinfo->scratch) > 0 ) - { - // 20040305-1304:PLD: unpack the file, propagate result upwards - result = MIME_unpack_single( unpackdir, hinfo->scratch, (hinfo->current_recursion_level+1),ss ); - } + // 20040305-1304:PLD: unpack the file, propagate result upwards + decode_result = MIME_unpack_single_diskfile( unpack_metadata, fn, (hinfo->current_recursion_level+ 1),ss ); } + free(fn); break; default: - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding format is not defined (%d)\n",FL, hinfo->content_transfer_encoding); - result = MIME_decode_raw(f, unpackdir, hinfo, keep); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding format is not defined (%d)\n",FL,__func__, hinfo->content_transfer_encoding); + decoded_mime = MIME_decode_std_raw(parent_mime, input_f, unpack_metadata, hinfo); + decode_result = decoded_mime->decode_result_code; break; } // Analyze our results - switch (result) { + switch (decode_result) { case 0: break; case MIME_STATUS_ZERO_FILE: - return MIME_STATUS_ZERO_FILE; + return resencapsulate(decoded_mime, MIME_STATUS_ZERO_FILE, hinfo); break; case MIME_ERROR_FFGET_EMPTY: - return result; + return resencapsulate(decoded_mime, decode_result, hinfo); break; case MIME_ERROR_RECURSION_LIMIT_REACHED: - return result; + return resencapsulate(decoded_mime, decode_result, hinfo); break; - default: - return result; + default: + return resencapsulate(decoded_mime, decode_result, hinfo); } - if ((result != -1)&&(result != MIME_STATUS_ZERO_FILE)) + if ((decode_result != -1)&&(decode_result != MIME_STATUS_ZERO_FILE)) { #ifdef RIPOLE // If we have OLE decoding active and compiled in, then @@ -2448,7 +2318,7 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in // performance of the ripMIME decoding engine if (glb.decode_ole > 0) { - MIME_decode_OLE( unpackdir, hinfo, 0 ); + MIME_decode_OLE_diskfile( unpack_metadata, hinfo ); } #endif @@ -2460,9 +2330,9 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in // side-effects if (hinfo->content_type == _CTYPE_TNEF) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Decoding TNEF format\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding TNEF format\n",FL,__func__); glb.attachment_count++; - MIME_decode_TNEF( unpackdir, hinfo, 0 ); + MIME_decode_TNEF( unpack_metadata, hinfo ); } // Decode TNEF // Look for Microsoft MHT files... and try decode them. @@ -2474,49 +2344,58 @@ int MIME_decode_encoding( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_in { if (glb.decode_mht != 0) { + char *fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(hinfo->filename) + sizeof(char) * 2; + // Patched 26-01-03: supplied by Chris Hine - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Microsoft MHT format email filename='%s'\n",FL, hinfo->filename); - snprintf(hinfo->scratch,sizeof(hinfo->scratch),"%s/%s",unpackdir,hinfo->filename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Microsoft MHT format email filename='%s'\n",FL,__func__, hinfo->filename); + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,hinfo->filename); // 20040305-1304:PLD: unpack the file, propagate result upwards - result = MIME_unpack_single( unpackdir, hinfo->scratch, (hinfo->current_recursion_level+1),ss ); + decode_result = MIME_unpack_single_diskfile( unpack_metadata, fn, (hinfo->current_recursion_level+ 1),ss ); + free(fn); } } // Decode MHT files - } // If result != -1 + } // If decode_result != -1 // End. - MIME_generate_multiple_hardlink_filenames(hinfo,unpackdir); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_decode_encoding:DEBUG: Done for filename = '%s'",FL,hinfo->filename); - return result; + MIME_generate_multiple_hardlink_filenames(hinfo,unpack_metadata); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Done for filename = '%s'",FL,__func__,hinfo->filename); + return resencapsulate(decoded_mime, decode_result, hinfo); } /*------------------------------------------------------------------------ Procedure: MIME_postdecode_cleanup ID:1 Purpose: Performs any cleanup operations required after the immediate completion of the mailpack decoding. -Input: char *unpackdir - directory where the mailpack was unpacked to +Input: RIPMIME_output *unpack_metadata - directory where the mailpack was unpacked to Output: none Errors: ------------------------------------------------------------------------*/ -int MIME_postdecode_cleanup( char *unpackdir, struct SS_object *ss ) +int MIME_postdecode_cleanup( RIPMIME_output *unpack_metadata, struct SS_object *ss ) { - char fullpath[256]; - int result; - result = 0; + int result = 0; do { char *filename; - if (MIME_DNORMAL) LOGGER_log("%s:%d: Popping file...",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s Popping file...",FL,__func__); filename = SS_pop(ss); if (filename == NULL) break; - if (MIME_DNORMAL) LOGGER_log("%s:%d: Popped file '%s'",FL, filename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s Popped file '%s'",FL,__func__, filename); if ( strncmp( glb.blankfileprefix, filename, strlen( glb.blankfileprefix ) ) == 0 ) { - snprintf( fullpath, sizeof(fullpath), "%s/%s", unpackdir, filename ); - result = unlink( fullpath ); + char *fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(filename) + sizeof(char) * 2; + + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,filename); + + result = unlink( fn ); if (MIME_VERBOSE) { - if (result == -1) LOGGER_log("Error removing '%s'; %s", fullpath, strerror(errno)); - else LOGGER_log("Removed %s [status = %d]\n", fullpath, result ); + if (result == -1) LOGGER_log("Error removing '%s'; %s", fn, strerror(errno)); + else LOGGER_log("Removed %s [status = %d]\n", fn, result ); } + free(fn); } } while (1); return 0; @@ -2526,8 +2405,8 @@ int MIME_postdecode_cleanup( char *unpackdir, struct SS_object *ss ) Function Name : MIME_handle_multipart Returns Type : int ----Parameter List - 1. FFGET_FILE *f, - 2. char *unpackdir, + 1. FFGET_FILE *input_f, + 2. RIPMIME_output *unpack_metadata, 3. struct MIMEH_header_info *hinfo, 4. int current_recursion_level, 5. struct SS_object *ss , @@ -2541,10 +2420,12 @@ int MIME_postdecode_cleanup( char *unpackdir, struct SS_object *ss ) Changes: \------------------------------------------------------------------*/ -int MIME_handle_multipart( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ) +int MIME_handle_multipart( MIME_element* parent_mime, FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ) { + MIME_element* decoded_mime = NULL; + int result = 0; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_multipart:DEBUG: Decoding multipart/embedded \n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding multipart/embedded \n",FL,__func__); // If there is no filename, then we have a "standard" // embedded message, which can be just read off as a // continuous stream (simply with new boundaries @@ -2559,29 +2440,33 @@ int MIME_handle_multipart( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_i // layer of headers and get into the core of the message. This is why we // call unpack_stage2() because this function just reads the next set of // headers and decodes. - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_multipart:DEBUG: Non base64 encoding AND no filename, embedded message\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Non base64 encoding AND no filename, embedded message\n",FL,__func__); h->boundary_located = 0; - result = MIME_unpack_stage2(f, unpackdir, h, current_recursion_level , ss); + result = MIME_unpack_stage2(input_f, unpack_metadata, h, current_recursion_level , ss); p = BS_top(); if (p) PLD_strncpy(h->boundary, p,sizeof(h->boundary)); } else { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_multipart:DEBUG: Embedded message has a filename, decoding to file %s",FL,h->filename); - result = MIME_decode_encoding( f, unpackdir, h, ss ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Embedded message has a filename, decoding to file %s",FL,__func__,h->filename); + decoded_mime = MIME_process_content_transfer_encoding( parent_mime, input_f, unpack_metadata, h, ss ); + result = decoded_mime->decode_result_code; if (result == 0) { - // Because we're calling MIME_unpack_single again [ie, recursively calling it + char *fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(h->filename) + sizeof(char) * 2; + + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,h->filename); + // Because we're calling MIME_unpack_single_diskfile again [ie, recursively calling it // we need to now adjust the input-filename so that it correctly is prefixed // with the directory we unpacked to. - snprintf(scratch,sizeof(scratch),"%s/%s",unpackdir, h->filename); - snprintf(h->filename,sizeof(h->filename),"%s",scratch); - - //result = MIME_unpack_single( unpackdir, h->filename, current_recursion_level +1, ss); - result = MIME_unpack_single( unpackdir, h->filename, current_recursion_level, ss ); + //result = MIME_unpack_single_diskfile( unpackdir, fn, current_recursion_level + 1, ss); + result = MIME_unpack_single_diskfile( unpack_metadata, fn, current_recursion_level, ss ); + free(fn); } } // else-if transfer-encoding != B64 && filename was empty - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_multipart:DEBUG: done handling '%s' result = %d",FL,h->filename, result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: done handling '%s' result = %d",FL,__func__,h->filename, result); return result; } @@ -2589,11 +2474,11 @@ int MIME_handle_multipart( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_i Function Name : MIME_handle_rfc822 Returns Type : int ----Parameter List - 1. FFGET_FILE *f, Input stream - 2. char *unpackdir, Directory to write files to + 1. FFGET_FILE *input_f, Input stream + 2. RIPMIME_output *unpack_metadata, Directory to write files to 3. struct MIMEH_header_info *hinfo, Header information structure - 4. int current_recursion_level, Current recursion level - 5. struct SS_object *ss , String stack containing already decoded file names + 4. int current_recursion_level, Current recursion level + 5. struct SS_object *ss , String stack containing already decoded file names ------------------ Exit Codes : Side Effects : @@ -2604,16 +2489,18 @@ int MIME_handle_multipart( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_i Changes: \------------------------------------------------------------------*/ -int MIME_handle_rfc822( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ) +int MIME_handle_rfc822( MIME_element* parent_mime, FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ) { - /** Decode a RFC822 encoded stream of data from *f **/ + MIME_element* decoded_mime = NULL; + + /** Decode a RFC822 encoded stream of data from *input_f **/ int result = 0; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: Decoding RFC822 message\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding RFC822 message\n",FL,__func__); /** If there is no filename, then we have a "standard" ** embedded message, which can be just read off as a ** continuous stream (simply with new boundaries **/ - DMIME LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: Filename='%s', encoding = %d",FL, h->filename, h->content_transfer_encoding); + DMIME LOGGER_log("%s:%d:%s:DEBUG: Filename='%s', encoding = %d",FL,__func__, h->filename, h->content_transfer_encoding); // if ((0)&&( h->content_transfer_encoding != _CTRANS_ENCODING_B64)&&( h->filename[0] == '0' )) 20041217-1635:PLD: if (( h->content_transfer_encoding != _CTRANS_ENCODING_B64)&&( h->filename[0] == '\0' )) @@ -2627,31 +2514,35 @@ int MIME_handle_rfc822( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // layer of headers and get into the core of the message. This is why we // call unpack_stage2() because this function just reads the next set of // headers and decodes. - DMIME LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: Non base64 encoding AND no filename, embedded message\n",FL); + DMIME LOGGER_log("%s:%d:%s:DEBUG: Non base64 encoding AND no filename, embedded message\n",FL,__func__); h->boundary_located = 0; - result = MIME_unpack_stage2(f, unpackdir, h, current_recursion_level , ss); + result = MIME_unpack_stage2(input_f, unpack_metadata, h, current_recursion_level , ss); p = BS_top(); if (p) PLD_strncpy(h->boundary, p,sizeof(h->boundary)); } else { /** ...else... if the section has a filename or B64 type encoding, we need to put it through extra decoding **/ - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: Embedded message has a filename, decoding to file %s",FL,h->filename); - result = MIME_decode_encoding( f, unpackdir, h, ss ); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: Result of extracting %s is %d",FL,h->filename, result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Embedded message has a filename, decoding to file %s",FL,__func__,h->filename); + decoded_mime = MIME_process_content_transfer_encoding( parent_mime, input_f, unpack_metadata, h, ss ); + result = decoded_mime->decode_result_code; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Result of extracting %s is %d",FL,__func__,h->filename, result); if (result == 0) { - /** Because we're calling MIME_unpack_single again [ie, recursively calling it + char * fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(h->filename) + sizeof(char) * 2; + + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,h->filename); + + /** Because we're calling MIME_unpack_single_diskfile again [ie, recursively calling it we need to now adjust the input-filename so that it correctly is prefixed with the directory we unpacked to. **/ + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Now attempting to extract contents of '%s'",FL,__func__,h->filename); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: Now attempting to extract contents of '%s'",FL,h->filename); - snprintf(scratch,sizeof(scratch),"%s/%s",unpackdir, h->filename); - snprintf(h->filename,sizeof(h->filename),"%s",scratch); - - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: Now attempting to extract contents of '%s'",FL,scratch); - result = MIME_unpack_single( unpackdir, scratch, current_recursion_level, ss ); + result = MIME_unpack_single_diskfile( unpack_metadata, fn, current_recursion_level, ss ); + free(fn); result = 0; } } /** else-if transfer-encoding != B64 && filename was empty **/ - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_rfc822:DEBUG: done handling '%s' result = %d",FL,h->filename, result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: done handling '%s' result = %d",FL,__func__,h->filename, result); return result; } @@ -2659,8 +2550,8 @@ int MIME_handle_rfc822( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info Function Name : MIME_handle_plain Returns Type : int ----Parameter List - 1. FFGET_FILE *f, - 2. char *unpackdir, + 1. FFGET_FILE *input_f, + 2. RIPMIME_output *unpack_metadata, 3. struct MIMEH_header_info *h, 4. int current_recursion_level, 5. struct SS_object *ss , @@ -2674,23 +2565,30 @@ int MIME_handle_rfc822( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info Changes: \------------------------------------------------------------------*/ -int MIME_handle_plain( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ) +int MIME_handle_plain( MIME_element* parent_mime, FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *h, int current_recursion_level, struct SS_object *ss ) { - /** Handle a plain text encoded data stream from *f **/ + MIME_element* decoded_mime = NULL; + + /** Handle a plain text encoded data stream from *input_f **/ int result = 0; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_handle_plain:DEBUG: Handling plain email",FL); - result = MIME_decode_encoding( f, unpackdir, h, ss ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Handling plain email",FL,__func__); + decoded_mime = MIME_process_content_transfer_encoding( parent_mime, input_f, unpack_metadata, h, ss ); + result = decoded_mime->decode_result_code; if ((result == MIME_ERROR_FFGET_EMPTY)||(result == 0)) { /** Test for RFC822 content... if so, go decode it **/ - snprintf(h->scratch,sizeof(h->scratch),"%s/%s",unpackdir,h->filename); - if (MIME_is_file_RFC822(h->scratch)==1) + char *fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(h->filename) + sizeof(char) * 2; + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,h->filename); + if (MIME_is_diskfile_RFC822(fn)==1) { - /** If the file is RFC822, then decode it using MIME_unpack_single() **/ + /** If the file is RFC822, then decode it using MIME_unpack_single_diskfile() **/ if (glb.header_longsearch != 0) MIMEH_set_header_longsearch(glb.header_longsearch); - result = MIME_unpack_single( unpackdir, h->scratch, current_recursion_level, ss ); + result = MIME_unpack_single_diskfile( unpack_metadata, fn, current_recursion_level, ss ); if (glb.header_longsearch != 0) MIMEH_set_header_longsearch(0); } + free(fn); } return result; } @@ -2703,33 +2601,35 @@ as required by the MIME structure of the file. Output: Errors: ------------------------------------------------------------------------*/ -int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info *hinfo, int current_recursion_level, struct SS_object *ss ) +int MIME_unpack_stage2( FFGET_FILE *input_f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo, int current_recursion_level, struct SS_object *ss ) { int result = 0; struct MIMEH_header_info *h; + MIME_element* parent_mime = NULL; + MIME_element* decoded_mime = NULL; char *p; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Start, recursion %d\n",FL, current_recursion_level); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Start, recursion %d\n",FL,__func__, current_recursion_level); if (current_recursion_level > glb.max_recursion_level) { /** Test for recursion limits **/ - if (MIME_VERBOSE) LOGGER_log("%s:%d:MIME_unpack_stage2:WARNING: Current recursion level of %d is greater than permitted %d"\ - ,FL, current_recursion_level, glb.max_recursion_level); + if (MIME_VERBOSE) LOGGER_log("%s:%d:%s:WARNING: Current recursion level of %d is greater than permitted %d"\ + ,FL,__func__, current_recursion_level, glb.max_recursion_level); return MIME_ERROR_RECURSION_LIMIT_REACHED; // 20040306-1301:PLD } h = hinfo; // Get our headers and determin what we have... // - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Parsing headers (initial)\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Parsing headers (initial)\n",FL,__func__); // Parse the headers, extracting what information we need /** 20041216-1102:PLD: Keep attempting to read headers until we get a sane set **/ do { /** Read next set of headers, repeat until a sane set of headers are found **/ - result = MIMEH_parse_headers(f,h); - DMIME LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Parsing of headers done, sanity = %d, result = %d",FL,h->sanity, result); + result = MIMEH_parse_headers(NULL, NULL, input_f,h,unpack_metadata, 0, 0); + DMIME LOGGER_log("%s:%d:%s:DEBUG: Parsing of headers done, sanity = %d, result = %d",FL,__func__,h->sanity, result); } while ((h->sanity == 0)&&(result != -1)); - DMIME LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Repeat loop of header-reading done, sanity = %d, result = %d",FL,h->sanity, result); + DMIME LOGGER_log("%s:%d:%s:DEBUG: Repeat loop of header-reading done, sanity = %d, result = %d",FL,__func__,h->sanity, result); glb.header_defect_count += MIMEH_get_defect_count(h); // Test the result output switch (result) { @@ -2741,12 +2641,12 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // this will give us the 'main' subject of the entire email and prevent // and subsequent subjects from clobbering it. //if (glb.subject[0] == '\0') snprintf(glb.subject, _MIME_STRLEN_MAX, "%s", h->subject ); - if ((strlen(glb.subject) < 1)&&(h->subject != NULL)&&(strlen(h->subject) > 0)) + if ((strlen(glb.subject) < 1) && (strlen(h->subject) > 0)) { snprintf(glb.subject, sizeof(glb.subject), "%s", h->subject ); } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Headers parsed, Result = %d, Boundary located = %d\n"\ - ,FL,result, hinfo->boundary_located); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Headers parsed, Result = %d, Boundary located = %d\n"\ + ,FL,__func__,result, hinfo->boundary_located); // Test to see if we encountered any DoubleCR situations while we // were processing the headers. If we did encounter a doubleCR @@ -2754,7 +2654,7 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // flag. if (MIMEH_get_doubleCR() != 0) { - MIME_doubleCR_decode( MIMEH_get_doubleCR_name(), unpackdir, h, current_recursion_level); + MIME_doubleCR_decode( MIMEH_get_doubleCR_name(), unpack_metadata, h, current_recursion_level); MIMEH_set_doubleCR( 0 ); FFGET_SDL_MODE = 0; } @@ -2767,7 +2667,7 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info char *lbc; char *fbc; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Boundary located, pushing to stack (%s)\n",FL,h->boundary); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Boundary located, pushing to stack (%s)\n",FL,__func__,h->boundary); BS_push(h->boundary); // Get the first and last character positions of the boundary @@ -2778,23 +2678,23 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // Circumvent attempts to trick the boundary // Even though we may end up pushing 3 boundaries to the stack // they will be popped off if they're not needed. - if (*fbc == '"') { BS_push((fbc +1)); MIMEH_set_defect( hinfo, MIMEH_DEFECT_UNBALANCED_BOUNDARY_QUOTE); } + if (*fbc == '"') { BS_push((fbc + 1)); MIMEH_set_defect( hinfo, MIMEH_DEFECT_UNBALANCED_BOUNDARY_QUOTE); } if (*lbc == '"') { *lbc = '\0'; BS_push(h->boundary); *lbc = '"'; MIMEH_set_defect( hinfo, MIMEH_DEFECT_UNBALANCED_BOUNDARY_QUOTE); } h->boundary_located = 0; } else { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding in BOUNDARY-LESS mode\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding in BOUNDARY-LESS mode\n",FL,__func__); if (h->content_type == _CTYPE_RFC822) { // Pass off to the RFC822 handler - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding with RFC822 decoder\n",FL); - result = MIME_handle_rfc822(f,unpackdir,h,current_recursion_level,ss); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding with RFC822 decoder\n",FL,__func__); + result = MIME_handle_rfc822( parent_mime, input_f,unpack_metadata,h,current_recursion_level,ss); } else if (MIMEH_is_contenttype(_CTYPE_MULTIPART, h->content_type)) { // Pass off to the multipart handler - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding with Multipart decoder\n",FL); - result = MIME_handle_multipart(f,unpackdir,h,current_recursion_level,ss); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding with Multipart decoder\n",FL,__func__); + result = MIME_handle_multipart( parent_mime, input_f,unpack_metadata,h,current_recursion_level,ss); } else { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding boundaryless file (%s)...\n",FL,h->filename); - result = MIME_handle_plain( f, unpackdir,h,current_recursion_level,ss); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding boundaryless file (%s)...\n",FL,__func__,h->filename); + result = MIME_handle_plain( parent_mime, input_f, unpack_metadata,h,current_recursion_level,ss); } // else-if content was RFC822 or multi-part return result; } // End of the boundary-LESS mode ( processing the mail which has no boundaries in the primary headers ) @@ -2802,13 +2702,14 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info if ((BS_top()!=NULL)&&(result == 0)) { // Commence decoding WITH boundary awareness. - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding with boundaries (filename = %s)\n",FL,h->filename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding with boundaries (filename = %s)\n",FL,__func__,h->filename); // Decode the data in the current MIME segment // based on the header information retrieved from // the start of this function. - result = MIME_decode_encoding(f, unpackdir, h, ss); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Done decoding, result = %d",FL,result); + decoded_mime = MIME_process_content_transfer_encoding( parent_mime, input_f, unpack_metadata, h, ss); + result = decoded_mime->decode_result_code; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Done decoding, result = %d",FL,__func__,result); if (result == 0) { if (BS_top()!=NULL) @@ -2824,13 +2725,13 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info h->content_transfer_encoding = -1; h->content_disposition = -1; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding headers...\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding headers...\n",FL,__func__); do { - result = MIMEH_parse_headers(f,h); + result = MIMEH_parse_headers(NULL, NULL, input_f, h, unpack_metadata, 0, 0); } while ((h->sanity == 0)&&(result != -1)); glb.header_defect_count += MIMEH_get_defect_count(h); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Mime header parsing result = %d\n",FL, result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Mime header parsing result = %d\n",FL,__func__, result); // 20040305-1331:PLD if (result == -1) { @@ -2840,7 +2741,7 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info if (h->boundary_located) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Pushing boundary %s\n",FL, h->boundary); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Pushing boundary %s\n",FL,__func__, h->boundary); BS_push(h->boundary); h->boundary_located = 0; } @@ -2859,7 +2760,7 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info || (MIMEH_is_contenttype(_CTYPE_MULTIPART, h->content_type))\ ) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Multipart/RFC822 mail headers found\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Multipart/RFC822 mail headers found\n",FL,__func__); /* If there is no filename, then we have a "standard" * embedded message, which can be just read off as a * continuous stream (simply with new boundaries */ @@ -2871,11 +2772,11 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // the file into ripMIME. Certainly, this is not // the most efficent way of dealing with nested emails // however, it is a rather robust/reliable way. - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Chose Content-type == RFC822 clause",FL); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Calling MIME_decode_encoding()",FL); - result = MIME_handle_rfc822(f,unpackdir,h,current_recursion_level,ss); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Chose Content-type == RFC822 clause",FL,__func__); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Calling MIME_process_content_transfer_encoding()",FL,__func__); + result = MIME_handle_rfc822(parent_mime, input_f,unpack_metadata,h,current_recursion_level,ss); // First up - extract the RFC822 body out of the parent mailpack - // XX result = MIME_decode_encoding( f, unpackdir, h, ss ); + // XX result = MIME_process_content_transfer_encoding( input_f, unpackdir, h, ss ); // Now decode the RFC822 body. /** @@ -2884,10 +2785,10 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info { snprintf(scratch,sizeof(scratch),"%s/%s",unpackdir, h->filename); snprintf(h->filename,sizeof(h->filename),"%s",scratch); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Now calling MIME_unpack_single() on the file '%s' for our RFC822 decode operation.",FL, scratch); - //result = MIME_unpack_single( unpackdir, h->filename, current_recursion_level +1, ss); - result = MIME_unpack( unpackdir, h->filename, current_recursion_level +1 ); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Unpack result = %d", FL, result); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Now calling MIME_unpack_single_diskfile() on the file '%s' for our RFC822 decode operation.",FL,__func__, scratch); + //result = MIME_unpack_single_diskfile( unpackdir, h->filename, current_recursion_level + 1, ss); + result = MIME_unpack( unpackdir, h->filename, current_recursion_level + 1 ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Unpack result = %d", FL,__func__, result); result = 0; } else return result; // 20040305-1312:PLD */ @@ -2898,9 +2799,9 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // To be honest, i've forgotten what this section of test is supposed to pick out // in terms of files - certainly it does pick out some, but I'm not sure what format // they are. Shame on me for not remembering, in future I must comment more. - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: NON-BASE64 DECODE\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: NON-BASE64 DECODE\n",FL,__func__); h->boundary_located = 0; - result = MIME_unpack_stage2(f, unpackdir, h, current_recursion_level , ss); + result = MIME_unpack_stage2(input_f, unpack_metadata, h, current_recursion_level , ss); // When we've exited from decoding the sub-mailpack, we need to restore the original // boundary @@ -2916,25 +2817,28 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // and embedded format, it does not have the normal headers->[headers->data] // layout of other nested emails - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Handle Appledouble explicitly",FL); - result = MIME_unpack_stage2(f, unpackdir, h, current_recursion_level , ss); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Handle Appledouble explicitly",FL,__func__); + result = MIME_unpack_stage2(input_f, unpack_metadata, h, current_recursion_level , ss); } else { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: RFC822 Message to be decoded...\n",FL); - result = MIME_decode_encoding( f, unpackdir, h, ss ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: RFC822 Message to be decoded...\n",FL,__func__); + decoded_mime = MIME_process_content_transfer_encoding( parent_mime, input_f, unpack_metadata, h, ss ); + result = decoded_mime->decode_result_code; if (result != 0) return result; // 20040305-1313:PLD else { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Now running ripMIME over decoded RFC822 message...\n",FL); + char * fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(h->filename) + sizeof(char) * 2; + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Now running ripMIME over decoded RFC822 message...\n",FL,__func__); - // Because we're calling MIME_unpack_single again [ie, recursively calling it + // Because we're calling MIME_unpack_single_diskfile again [ie, recursively calling it // we need to now adjust the input-filename so that it correctly is prefixed // with the directory we unpacked to. - - snprintf(scratch,sizeof(scratch),"%s/%s",unpackdir, h->filename); - snprintf(h->filename,sizeof(h->filename),"%s",scratch); - //result = MIME_unpack_single( unpackdir, h->filename, current_recursion_level +1, ss); - result = MIME_unpack_single( unpackdir, h->filename, current_recursion_level,ss ); + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,h->filename); + //result = MIME_unpack_single_diskfile( unpackdir, fn, current_recursion_level + 1, ss); + result = MIME_unpack_single_diskfile( unpack_metadata, fn, current_recursion_level,ss ); + free(fn); } } // else-if transfer-encoding wasn't B64 and filename was blank @@ -2942,10 +2846,11 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info // If the attachment included in this MIME segment is NOT a // multipart or RFC822 embedded email, we can then simply use // the normal decoding function to interpret its data. - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding a normal attachment \n",FL); - result = MIME_decode_encoding( f, unpackdir, h, ss ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding a normal attachment \n",FL,__func__); + decoded_mime = MIME_process_content_transfer_encoding( parent_mime, input_f, unpack_metadata, h, ss ); + result = decoded_mime->decode_result_code; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Decoding a normal attachment '%s' done. \n",FL, h->filename); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding a normal attachment '%s' done. \n",FL,__func__, h->filename); // See if we have an attachment output which is actually another // email. // @@ -2957,14 +2862,14 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info { char *mime_fname; - mime_fname = PLD_dprintf("%s/%s", unpackdir, h->filename); + mime_fname = PLD_dprintf("%s/%s", unpack_metadata->dir, h->filename); if(mime_fname != NULL) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Testing '%s' for email type",FL,mime_fname); - if (MIME_is_file_RFC822(mime_fname)) + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Testing '%s' for email type",FL,__func__,mime_fname); + if (MIME_is_diskfile_RFC822(mime_fname)) { - //MIME_unpack_single( unpackdir, mime_fname, (hinfo->current_recursion_level+1), ss); - MIME_unpack_single( unpackdir, mime_fname, current_recursion_level+1,ss); + //MIME_unpack_single_diskfile( unpackdir, mime_fname, (hinfo->current_recursion_level+ 1), ss); + MIME_unpack_single_diskfile( unpack_metadata, mime_fname, current_recursion_level+ 1,ss); } free(mime_fname); } @@ -2983,7 +2888,7 @@ int MIME_unpack_stage2( FFGET_FILE *f, char *unpackdir, struct MIMEH_header_info } // if MIME_BS_top() } // if result == 0 } // if (result) - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_stage2:DEBUG: Exiting with result=%d recursion=%d\n",FL,result, current_recursion_level); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Exiting with result=%d recursion=%d\n",FL,__func__,result, current_recursion_level); return result; } @@ -2994,9 +2899,9 @@ Purpose: Decodes mailbox formatted email files Output: Errors: ------------------------------------------------------------------------*/ -int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_level, struct SS_object *ss ) +int MIME_unpack_mailbox( RIPMIME_output *unpack_metadata, char *mpname, int current_recursion_level, struct SS_object *ss ) { - FFGET_FILE f; + FFGET_FILE input_f; FILE *fi; FILE *fo; char fname[1024]; @@ -3006,17 +2911,16 @@ int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_le int result; int input_is_stdin=0; - snprintf(fname,sizeof(fname),"%s/tmp.email000.mailpack",unpackdir); + snprintf(fname,sizeof(fname),"%s/tmp.email000.mailpack",unpack_metadata->dir); if ((mpname[0] == '-')&&(mpname[1] == '\0')) { fi = stdin; input_is_stdin=1; } else { - // fi = fopen(mpname,"r"); - if (strcmp(mpname,"-")==0) fi = stdin; else fi = fopen(mpname,"r"); // 20040208-1715:PLD + fi = (strcmp(mpname,"-")==0) ? stdin : fopen(mpname,"r"); if (!fi) { - LOGGER_log("%s:%d:MIME_unpack_mailbox:ERROR: Cannot open '%s' for reading (%s)",FL, mpname,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: Cannot open '%s' for reading (%s)",FL,__func__, mpname,strerror(errno)); return -1; } } @@ -3024,12 +2928,12 @@ int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_le fo = fopen(fname,"w"); if (!fo) { - LOGGER_log("%s:%d:MIME_unpack_mailbox:ERROR: Cannot open '%s' for writing (%s)",FL, fname,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: Cannot open '%s' for writing (%s)",FL,__func__, fname,strerror(errno)); return -1; } - FFGET_setstream(&f, fi); - while (FFGET_fgets(line,sizeof(line),&f)) + FFGET_setstream(&input_f, fi); + while (FFGET_fgets(line,sizeof(line),&input_f)) { // If we have the construct of "\n\rFrom ", then we // can be -pretty- sure that a new email is about @@ -3040,17 +2944,17 @@ int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_le // Close the mailpack fclose(fo); // Now, decode the mailpack - //MIME_unpack_single(unpackdir, fname, current_recursion_level, ss); + //MIME_unpack_single_diskfile(unpackdir, fname, current_recursion_level, ss); // 20040317-2358:PLD - MIME_unpack_single(unpackdir, fname, current_recursion_level ,ss ); + MIME_unpack_single_diskfile(unpack_metadata, fname, current_recursion_level ,ss ); // Remove the now unpacked mailpack result = remove(fname); if (result == -1) { - LOGGER_log("%s:%d:MIME_unpack_mailbox:ERROR: removing temporary mailpack '%s' (%s)",FL, fname,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: removing temporary mailpack '%s' (%s)",FL,__func__, fname,strerror(errno)); } // Create a new mailpack filename, and keep on going... - snprintf(fname,sizeof(fname),"%s/tmp.email%03d.mailpack",unpackdir,++mcount); + snprintf(fname,sizeof(fname),"%s/tmp.email%03d.mailpack",unpack_metadata->dir,++mcount); fo = fopen(fname,"w"); } else @@ -3085,23 +2989,23 @@ int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_le fclose(fo); // Now, decode the mailpack - //MIME_unpack_single(unpackdir, fname, current_recursion_level, ss); + //MIME_unpack_single_diskfile(unpackdir, fname, current_recursion_level, ss); // 20040317-2358:PLD - MIME_unpack_single(unpackdir, fname, current_recursion_level , ss ); + MIME_unpack_single_diskfile(unpack_metadata, fname, current_recursion_level , ss ); // Remove the now unpacked mailpack result = remove(fname); if (result == -1) { - LOGGER_log("%s:%d:MIME_unpack_mailbox:ERROR: removing temporary mailpack '%s' (%s)",FL, fname,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: removing temporary mailpack '%s' (%s)",FL,__func__, fname,strerror(errno)); } return 0; } /*-----------------------------------------------------------------\ - Function Name : MIME_unpack_single + Function Name : MIME_unpack_single_diskfile Returns Type : int ----Parameter List - 1. char *unpackdir, + 1. RIPMIME_output *unpack_metadata, 2. char *mpname, 3. int current_recursion_level , ------------------ @@ -3114,22 +3018,22 @@ int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_le Changes: \------------------------------------------------------------------*/ -int MIME_unpack_single( char *unpackdir, char *mpname, int current_recursion_level, struct SS_object *ss ) +int MIME_unpack_single_diskfile( RIPMIME_output *unpack_metadata, char *mpname, int current_recursion_level, struct SS_object *ss ) { FILE *fi; /* Pointer for the MIME file we're going to be going through */ int result = 0; if (current_recursion_level > glb.max_recursion_level) { - LOGGER_log("%s:%d:MIME_unpack_single:WARNING: Current recursion level of %d is greater than permitted %d",FL, current_recursion_level, glb.max_recursion_level); + LOGGER_log("%s:%d:%s:WARNING: Current recursion level of %d is greater than permitted %d",FL,__func__, current_recursion_level, glb.max_recursion_level); return MIME_ERROR_RECURSION_LIMIT_REACHED; } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single:DEBUG: dir=%s packname=%s level=%d (max = %d)\n",FL, unpackdir, mpname, current_recursion_level, glb.max_recursion_level); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: dir=%s packname=%s level=%d (max = %d)\n",FL,__func__, unpack_metadata->dir, mpname, current_recursion_level, glb.max_recursion_level); /* if we're reading in from STDIN */ if( mpname[0] == '-' && mpname[1] == '\0' ) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single:DEBUG: STDIN opened...\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: STDIN opened...\n",FL,__func__); fi = stdin; } else @@ -3137,37 +3041,37 @@ int MIME_unpack_single( char *unpackdir, char *mpname, int current_recursion_lev fi = fopen(mpname,"r"); if (!fi) { - LOGGER_log("%s:%d:MIME_unpack_single:ERROR: Cannot open file '%s' for reading.\n",FL, mpname); + LOGGER_log("%s:%d:%s:ERROR: Cannot open file '%s' for reading.\n",FL,__func__, mpname); return -1; } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single:DEBUG: Input file (%s) opened...\n",FL, mpname); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Input file (%s) opened...\n",FL,__func__, mpname); } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single:DEBUG: Checking input streams...\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Checking input streams...\n",FL,__func__); /* check to see if we had problems opening the file */ if (fi == NULL) { - LOGGER_log("%s:%d:MIME_unpack_single:ERROR: Could not open mailpack file '%s' (%s)",FL, mpname, strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: Could not open mailpack file '%s' (%s)",FL,__func__, mpname, strerror(errno)); return -1; } // 20040317-2359:PLD - result = MIME_unpack_single_fp(unpackdir,fi,current_recursion_level , ss); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single:DEBUG: result = %d, recursion = %d, filename = '%s'", FL, result, current_recursion_level, mpname ); + result = MIME_unpack_single_file(unpack_metadata,fi,current_recursion_level , ss); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: result = %d, recursion = %d, filename = '%s'", FL,__func__, result, current_recursion_level, mpname ); if ((current_recursion_level > 1)&&(result == 241)) result = 0; fclose(fi); return result; } /*------------------------------------------------------------------------ -Procedure: MIME_unpack_single ID:1 +Procedure: MIME_unpack_single_diskfile ID:1 Purpose: Decodes a single mailpack file (as apposed to mailbox format) into its possible attachments and text bodies -Input: char *unpackdir: Directory to unpack the attachments to +Input: RIPMIME_output *unpack_metadata: Directory to unpack the attachments to char *mpname: Name of the mailpack we have to decode int current_recusion_level: Level of recursion we're currently at. Output: Errors: ------------------------------------------------------------------------*/ -int MIME_unpack_single_fp( char *unpackdir, FILE *fi, int current_recursion_level, struct SS_object *ss ) +int MIME_unpack_single_file( RIPMIME_output *unpack_metadata, FILE *fi, int current_recursion_level, struct SS_object *ss ) { struct MIMEH_header_info h; int result = 0; @@ -3175,39 +3079,47 @@ int MIME_unpack_single_fp( char *unpackdir, FILE *fi, int current_recursion_leve FFGET_FILE f; FILE *hf = NULL; + h.header_file = NULL; // Because this MIME module gets used in both CLI and daemon modes // we should check to see that we can report to stderr // - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: dir=%s level=%d (max = %d)\n",FL, unpackdir, current_recursion_level, glb.max_recursion_level); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: dir=%s level=%d (max = %d)\n",FL,__func__, unpack_metadata->dir, current_recursion_level, glb.max_recursion_level); if (current_recursion_level > glb.max_recursion_level) { - LOGGER_log("%s:%d:MIME_unpack_single_fp:WARNING: Current recursion level of %d is greater than permitted %d",FL, current_recursion_level, glb.max_recursion_level); + LOGGER_log("%s:%d:%s:WARNING: Current recursion level of %d is greater than permitted %d",FL,__func__, current_recursion_level, glb.max_recursion_level); // return -1; return MIME_ERROR_RECURSION_LIMIT_REACHED; // 20040305-1302:PLD //return 0; // 20040208-1723:PLD } - else h.current_recursion_level = current_recursion_level; + else + h.current_recursion_level = current_recursion_level; glb.current_line = 0; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: recursion level checked...%d\n",FL, current_recursion_level); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: DumpHeaders = %d\n",FL, glb.save_headers); - if ((!hf)&&(glb.save_headers)&&(MIMEH_get_headers_save()==0)) + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: recursion level checked...%d\n",FL,__func__, current_recursion_level); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: DumpHeaders = %d\n",FL,__func__, glb.dump_headers); + if ((!hf)&&(glb.dump_headers)) { + char * fn; + int fn_l = strlen(unpack_metadata->dir) + strlen(glb.headersname) + sizeof(char) * 2; + + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",unpack_metadata->dir,glb.headersname); + // Prepend the unpackdir path to the headers file name - snprintf(scratch,sizeof(scratch),"%s/%s",unpackdir, glb.headersname); - hf = fopen(scratch,"w"); + hf = fopen(fn,"w"); if (!hf) { - glb.save_headers = 0; - LOGGER_log("%s:%d:MIME_unpack_single_fp:ERROR: Cannot open '%s' for writing (%s)",FL, glb.headersname,strerror(errno)); + glb.dump_headers = 0; + LOGGER_log("%s:%d:%s:ERROR: Cannot open '%s' for writing (%s)", FL,__func__, fn, strerror(errno)); } else { headers_save_set_here = 1; - MIMEH_set_headers_save(hf); + h.header_file = hf; } + free(fn); } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: Setting up streams to decode\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Setting up streams to decode\n",FL,__func__); FFGET_setstream(&f, fi); /** Initialize the header record **/ h.boundary[0] = '\0'; @@ -3229,16 +3141,16 @@ int MIME_unpack_single_fp( char *unpackdir, FILE *fi, int current_recursion_leve } } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: preparing to decode, calling stage2...\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: preparing to decode, calling stage2...\n",FL,__func__); // 20040318-0001:PLD - result = MIME_unpack_stage2(&f, unpackdir, &h, current_recursion_level +1, ss); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: done decoding ( in stage2 ) result=%d, to %s\n",FL, result, unpackdir); + result = MIME_unpack_stage2(&f, unpack_metadata, &h, current_recursion_level + 1, ss); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: done decoding ( in stage2 ) result=%d, to %s\n",FL,__func__, result, unpack_metadata->dir); // fclose(fi); 20040208-1726:PLD if ( headers_save_set_here > 0 ) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: Closing header file.\n",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Closing header file.\n",FL,__func__); fflush(stdout); - MIMEH_set_headers_nosave(); + h.header_file = NULL; fclose(hf); } @@ -3246,7 +3158,7 @@ int MIME_unpack_single_fp( char *unpackdir, FILE *fi, int current_recursion_leve /** Flush out the string stacks **/ SS_done(&(h.ss_filenames)); SS_done(&(h.ss_names)); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack_single_fp:DEBUG: Done. Result=%d Recursion=%d\n",FL, result, current_recursion_level); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Done. Result=%d Recursion=%d\n",FL,__func__, result, current_recursion_level); return result; // return status; // 20040305-1318:PLD } @@ -3259,35 +3171,34 @@ which one to execute based on the mailbox setting Output: Errors: ------------------------------------------------------------------------*/ -int MIME_unpack( char *unpackdir, char *mpname, int current_recursion_level ) +int MIME_unpack( RIPMIME_output *unpack_metadata, char *mpname, int current_recursion_level ) { int result = 0; struct SS_object ss; // Stores the filenames that are created in the unpack operation if (current_recursion_level > glb.max_recursion_level) return MIME_ERROR_RECURSION_LIMIT_REACHED; - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack: Unpacking %s to %s, recursion level is %d",FL,mpname,unpackdir,current_recursion_level); - MIMEH_set_outputdir(unpackdir); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s: Unpacking %s to %s, recursion level is %d",FL,__func__,mpname,unpack_metadata->dir,current_recursion_level); if (MIME_DNORMAL) SS_set_debug(&ss,1); SS_init(&ss); if (glb.mailbox_format > 0) { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack: Unpacking using mailbox format",FL); - result = MIME_unpack_mailbox( unpackdir, mpname, (current_recursion_level), &ss ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s: Unpacking using mailbox format",FL,__func__); + result = MIME_unpack_mailbox( unpack_metadata, mpname, (current_recursion_level), &ss ); } else { - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack: Unpacking standard mailpack",FL,mpname,unpackdir,current_recursion_level); - result = MIME_unpack_single( unpackdir, mpname, (current_recursion_level +1), &ss ); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s: Unpacking standard mailpack",FL,__func__,mpname,unpack_metadata->dir,current_recursion_level); + result = MIME_unpack_single_diskfile( unpack_metadata, mpname, (current_recursion_level + 1), &ss ); } if (glb.no_nameless) { - MIME_postdecode_cleanup( unpackdir, &ss ); + MIME_postdecode_cleanup( unpack_metadata, &ss ); } if (MIME_DNORMAL) { - LOGGER_log("%s:%d:MIME_unpack: Files unpacked from '%s' (recursion=%d);",FL,mpname,current_recursion_level); + LOGGER_log("%s:%d:%s: Files unpacked from '%s' (recursion=%d);",FL,__func__,mpname,current_recursion_level); SS_dump(&ss); } @@ -3312,24 +3223,32 @@ int MIME_unpack( char *unpackdir, char *mpname, int current_recursion_level ) if (current_recursion_level == 0) { - //LOGGER_log("%s:%d:MIME_unpack:DEBUG: Clearing boundary stack",FL); + //LOGGER_log("%s:%d:%s:DEBUG: Clearing boundary stack",FL,__func__); BS_clear(); } - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack: Unpacking of %s is done.",FL,mpname); - if (MIME_DNORMAL) LOGGER_log("%s:%d:MIME_unpack: -----------------------------------",FL); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s: Unpacking of %s is done.",FL,__func__,mpname); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s: -----------------------------------",FL,__func__); return result; } /*-------------------------------------------------------------------- * MIME_close * - * Closes the files used in MIME_unpack, such as headers etc */ -int MIME_close( void ) + * Closes the files used in MIME_unpack, such as headers etc + * Writes memory FILE object content to disk if there is in-memory mode + */ +void MIME_close(RIPMIME_output *unpack_metadata) { - if (headers) - { - fclose(headers); + + if (unpack_metadata->unpack_mode == RIPMIME_UNPACK_MODE_IN_MEMORY) + write_all_to_FS_files(unpack_metadata); + + if (MIME_DNORMAL) { + LOGGER_log("%s:%d:%s: start.",FL,__func__); + printArray(all_MIME_elements.mime_arr); } - return 0; + + freeArray(all_MIME_elements.mime_arr, unpack_metadata); } -/*----------END OF MIME.c------------*/ + +/* EOF */ diff --git a/mime.h b/mime.h index a3e8e85..65da91e 100644 --- a/mime.h +++ b/mime.h @@ -6,28 +6,20 @@ #define LIBMIME_VERSION "200811050000" /* Exit Error codes */ -#define _EXITERR_UNDEFINED_BOUNDARY 100 -#define _EXITERR_PRINT_QUOTABLE_INPUT_NOT_OPEN 200 -#define _EXITERR_PRINT_QUOTABLE_OUTPUT_NOT_OPEN 201 -#define _EXITERR_BASE64_OUTPUT_NOT_OPEN 210 -#define _EXITERR_BASE64_UNABLE_TO_OUTPUT 211 -#define _EXITERR_MIMEREAD_CANNOT_OPEN_OUTPUT 220 -#define _EXITERR_MIMEREAD_CANNOT_WRITE_OUTPUT 221 -#define _EXITERR_MIMEREAD_CANNOT_OPEN_INPUT 222 -#define _EXITERR_MIMEUNPACK_CANNOT_OPEN_INPUT_FILE 230 -#define _EXITERR_MIMEUNPACK_CANNOT_OPEN_HEADERS_FILE 231 - -#define MIME_ERROR_RECURSION_LIMIT_REACHED 240 -#define MIME_ERROR_FFGET_EMPTY 241 -#define MIME_ERROR_B64_INPUT_STREAM_EOF 242 - -#define _MIME_RENAME_METHOD_INFIX 1 -#define _MIME_RENAME_METHOD_PREFIX 2 -#define _MIME_RENAME_METHOD_POSTFIX 3 -#define _MIME_RENAME_METHOD_RANDINFIX 4 -#define _MIME_RENAME_METHOD_RANDPREFIX 5 -#define _MIME_RENAME_METHOD_RANDPOSTFIX 6 - +#define _EXITERR_UNDEFINED_BOUNDARY 100 +#define _EXITERR_PRINT_QUOTABLE_INPUT_NOT_OPEN 200 +#define _EXITERR_PRINT_QUOTABLE_OUTPUT_NOT_OPEN 201 +#define _EXITERR_BASE64_OUTPUT_NOT_OPEN 210 +#define _EXITERR_BASE64_UNABLE_TO_OUTPUT 211 +#define _EXITERR_MIMEREAD_CANNOT_OPEN_OUTPUT 220 +#define _EXITERR_MIMEREAD_CANNOT_WRITE_OUTPUT 221 +#define _EXITERR_MIMEREAD_CANNOT_OPEN_INPUT 222 +#define _EXITERR_MIMEUNPACK_CANNOT_OPEN_INPUT_FILE 230 +#define _EXITERR_MIMEUNPACK_CANNOT_OPEN_HEADERS_FILE 231 + +#define MIME_ERROR_RECURSION_LIMIT_REACHED 240 +#define MIME_ERROR_FFGET_EMPTY 241 +#define MIME_ERROR_B64_INPUT_STREAM_EOF 242 #define _MIME_STRLEN_MAX 1023 @@ -59,10 +51,7 @@ int MIME_version( void ); size_t MIME_read_raw( char *src_mpname, char *dest_mpname, size_t rw_buffer_size ); int MIME_read( char *mpname ); /* returns filesize in KB */ -int MIME_unpack( char *unpackdir, char *mpname, int current_recusion_level ); -//int MIME_unpack_single( char *unpackdir, char *mpname, int current_recusion_level ); -//int MIME_unpack_single_fp( char *unpackdir, FILE *fi, int current_recusion_level ); -//int MIME_unpack_mailbox( char *unpackdir, char *mpname, int current_recursion_level ); +int MIME_unpack( RIPMIME_output *unpack_metadata, char *mpname, int current_recusion_level ); int MIME_insert_Xheader( char *fname, char *xheader ); int MIME_set_blankfileprefix( char *prefix ); int MIME_set_recursion_level(int level); @@ -108,15 +97,11 @@ int MIME_get_header_defect_count( void ); int MIME_is_file_mime( char *fname ); int MIME_is_file_uuenc( char *fname ); - char *MIME_get_blankfileprefix( void ); char *MIME_get_headersname( void ); char *MIME_get_subject( void ); -int MIME_init( void ); -int MIME_close( void ); +void MIME_init( void ); +void MIME_close( RIPMIME_output *unpack_metadata ); int MIME_set_tmpdir( char *tmpdir ); -//int MIME_postdecode_cleanup( char *unpackdir, struct SS_object *ss ); - -//int MIME_decode_TNEF( FILE *f, char *unpackdir, struct _header_info *hinfo, int keep ); #endif diff --git a/mime_element.c b/mime_element.c new file mode 100644 index 0000000..659368c --- /dev/null +++ b/mime_element.c @@ -0,0 +1,428 @@ + +#include +#include +#include +#include +#include + +#include "mime_element.h" +#include "logger.h" +#include "pldstr.h" + +#ifndef FL +#define FL __FILE__, __LINE__ +#endif + +#define _FS_PATH_MAX 1023 +#define _FS_FILE_MAX 254 + +/* Dynamic array support*/ +#define INITIAL_SIZE 8 + +// function prototypes +// array container functions +void arrayInit(dynamic_array** arr_ptr); + +// Basic Operation functions +void insertItem(dynamic_array* container, MIME_element* item); +void updateItem(dynamic_array* container, int i, MIME_element* item); +MIME_element* getItem(dynamic_array* container, int i); +void deleteItem(dynamic_array* container, int i); + +struct MIME_globals { + int debug; +}; + +static struct MIME_globals glb; + +#define MIME_DNORMAL (glb.debug) + +int MIMEELEMENT_set_debug( int level ) +{ + glb.debug = level; + return glb.debug; +} + + +void all_MIME_elements_init (void) +{ + all_MIME_elements.mime_count = 0; + arrayInit(&(all_MIME_elements.mime_arr)); +} + +all_MIME_elements_s all_MIME_elements; + +static char * dup_ini(char* s) +{ + return (s != NULL) ? strdup(s) : "\0"; +} + +MIME_element* MIME_element_add(struct MIME_element* parent, RIPMIME_output *unpack_metadata, + char* filename, char* content_type_string, char* content_transfer_encoding, char* name, + int current_recursion_level, int attachment_count, int filecount, const char* func) +{ + MIME_element *cur = malloc(sizeof(MIME_element)); + int fullpath_len = 0; + + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:start\n",FL,__func__); + + fullpath_len = strlen(unpack_metadata->dir) + strlen(filename) + 3 * sizeof(char); + insertItem(all_MIME_elements.mime_arr, cur); + cur->parent = parent; + cur->decode_result_code = -1; + cur->id = all_MIME_elements.mime_count++; + cur->directory = unpack_metadata->dir; + cur->filename = dup_ini(filename); + cur->content_type_string = dup_ini(content_type_string); + cur->content_transfer_encoding = dup_ini(content_transfer_encoding); + cur->name = dup_ini(name); + + cur->fullpath = (char*)malloc(fullpath_len); + snprintf(cur->fullpath,fullpath_len,"%s/%s",unpack_metadata->dir,filename); + if (unpack_metadata->unpack_mode == RIPMIME_UNPACK_MODE_TO_DIRECTORY) + cur->f = fopen(cur->fullpath,"wb"); + else + cur->f = open_memstream (&cur->mem_filearea, &cur->mem_filearea_l); + + if (cur->f == NULL) { + LOGGER_log("%s:%d:%s:ERROR: cannot open %s for writing",FL,func,cur->fullpath); + return cur; + } + + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Decoding [encoding=%d] to %s\n",FL,__func__, content_transfer_encoding, cur->fullpath); + + if (unpack_metadata != NULL && unpack_metadata->unpack_mode == RIPMIME_UNPACK_MODE_LIST_MIME && cur->f != NULL) { + fprintf (stdout, "%d|%d|%d|%d|%s|%s\n", all_MIME_elements.mime_count, attachment_count, filecount, current_recursion_level, cur->content_type_string, cur->filename); + } + return cur; +} + +MIME_element* MIME_element_add_root(RIPMIME_output *unpack_metadata, + char* filename) +{ + MIME_element *cur = malloc(sizeof(MIME_element)); + int fullpath_len = 0; + + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:start\n",FL,__func__); + + fullpath_len = strlen(unpack_metadata->dir) + strlen(filename) + 3 * sizeof(char); + insertItem(all_MIME_elements.mime_arr, cur); + cur->parent = NULL; + cur->decode_result_code = 0; + cur->id = 0; + cur->directory = unpack_metadata->dir; + cur->filename = dup_ini(filename); + cur->content_type_string = NULL; + cur->content_transfer_encoding = NULL; + cur->name = NULL; + + cur->fullpath = (char*)malloc(fullpath_len); + snprintf(cur->fullpath,fullpath_len,"%s/%s",unpack_metadata->dir,filename); + cur->f = fopen(cur->fullpath,"r"); + if (cur->f == NULL) { + LOGGER_log("%s:%d:%s:ERROR: cannot open %s for reading",FL,"main",cur->fullpath); + return cur; + } + return cur; +} + +static void dup_free(char *s) +{ + if ((s != NULL) && s[0]) + free(s); +} + +void MIME_element_free (MIME_element* cur) +{ + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:start\n",FL,__func__); + + if (cur == NULL) { + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:NULL, nothing to free\n",FL,__func__); + return; + } + + if (cur->f != NULL) { + fclose(cur->f); + } + dup_free(cur->fullpath); + dup_free(cur->filename); + dup_free(cur->content_type_string); + dup_free(cur->content_transfer_encoding); + dup_free(cur->name); + + free(cur); + cur = NULL; +} + +void MIME_element_deactivate(MIME_element* cur, RIPMIME_output *unpack_metadata) +{ + if (unpack_metadata->unpack_mode == RIPMIME_UNPACK_MODE_TO_DIRECTORY) + MIME_element_free(cur); +} + +static inline int get_random_value(void) { + int randval; + FILE *fp; + size_t res = 0; + + fp = fopen("/dev/urandom", "r"); + res = fread(&randval, sizeof(randval), 1, fp); + if (res == 0) { + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s: /dev/urandom Read error\n",FL,__func__); + exit(1); + } + fclose(fp); + if (randval < 0) + { randval = randval *( -1); }; + return randval; +} + +/*------------------------------------------------------------------------ +Procedure: MIME_test_uniquename ID:1 +Purpose: Checks to see that the filename specified is unique. If it's not +unique, it will modify the filename +char *fname: filename +Output: +Errors: +------------------------------------------------------------------------*/ +int MIME_test_uniquename( RIPMIME_output *unpack_metadata, char *fname ) +{ + struct stat buf; + + char newname[ _FS_PATH_MAX + 1]; + char scr[ _FS_PATH_MAX + 1]; /** Scratch var **/ + char *frontname, *extention; + int cleared = 0; + int count = 1; + + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Start (%s)",FL,__func__,fname); + + frontname = extention = NULL; // shuts the compiler up + + if (unpack_metadata->rename_method == _MIME_RENAME_METHOD_INFIX) + { + PLD_strncpy(scr,fname, _FS_PATH_MAX); + frontname = scr; + extention = strrchr(scr,'.'); + + if (extention) + { + *extention = '\0'; + extention++; + } + else + { + unpack_metadata->rename_method = _MIME_RENAME_METHOD_POSTFIX; + } + } + + if (unpack_metadata->rename_method == _MIME_RENAME_METHOD_RANDINFIX) + { + PLD_strncpy(scr,fname, _FS_PATH_MAX); + frontname = scr; + extention = strrchr(scr,'.'); + + if (extention) + { + *extention = '\0'; + extention++; + } + else + { + unpack_metadata->rename_method = _MIME_RENAME_METHOD_RANDPOSTFIX; + } + } + + snprintf(newname, _FS_PATH_MAX,"%s/%s",unpack_metadata->dir,fname); + while (!cleared) + { + if ((stat(newname, &buf) == -1)) + { + cleared++; + } + else + { + int randval = get_random_value(); + + switch (unpack_metadata->rename_method) { + case _MIME_RENAME_METHOD_PREFIX: + snprintf(newname, _FS_PATH_MAX,"%s/%d_%s",unpack_metadata->dir,count,fname); + break; + case _MIME_RENAME_METHOD_INFIX: + snprintf(newname, _FS_PATH_MAX,"%s/%s_%d.%s",unpack_metadata->dir,frontname,count,extention); + break; + case _MIME_RENAME_METHOD_POSTFIX: + snprintf(newname, _FS_PATH_MAX,"%s/%s_%d",unpack_metadata->dir,fname,count); + break; + case _MIME_RENAME_METHOD_RANDPREFIX: + snprintf(newname, _FS_PATH_MAX,"%s/%d_%d_%s",unpack_metadata->dir,count,randval,fname); + break; + case _MIME_RENAME_METHOD_RANDINFIX: + snprintf(newname, _FS_PATH_MAX,"%s/%s_%d_%d.%s",unpack_metadata->dir,frontname,count,randval,extention); + break; + case _MIME_RENAME_METHOD_RANDPOSTFIX: + snprintf(newname, _FS_PATH_MAX,"%s/%s_%d_%d",unpack_metadata->dir,fname,count,randval); + } + count++; + } + } + if (count > 1) + { + frontname = strrchr(newname,'/'); + if (frontname) frontname++; + else frontname = newname; + + PLD_strncpy(fname, frontname, _FS_PATH_MAX); //FIXME - this assumes that the buffer space is at least MIME_STRLEN_MAX sized. + } + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Done (%s)",FL,__func__,fname); + return 0; +} + +static void copyFILEcontent(FILE* src, FILE* dst) +{ + int c; /* Not CHAR! for EOF */ + + fseek(src, 0, SEEK_SET); + // Read contents from file + while (EOF != (c = fgetc(src))) + { + fputc(c, dst); + } +} + +void write_FS_file(RIPMIME_output *unpack_metadata, MIME_element* cur) +{ + char * wr_filename = NULL; + FILE* wf = NULL; + int fn_l = 0; + + MIME_test_uniquename(unpack_metadata, cur->filename); + fn_l = strlen(unpack_metadata->dir) + strlen(cur->filename) + sizeof(char) * 2; + wr_filename = malloc(fn_l); + snprintf(wr_filename,fn_l,"%s/%s",unpack_metadata->dir,cur->filename); + if (cur->f == NULL) { + LOGGER_log("%s:%d:%s:ERROR: Cannot copy data from mime_element memory file, programming error (for %s)", FL,__func__, wr_filename, strerror(errno)); + free(wr_filename); + return; + } + // Prepend the unpackdir path to the headers file name + wf = fopen(wr_filename,"w"); + if (wf == NULL) + { + LOGGER_log("%s:%d:%s:ERROR: Cannot open '%s' for writing (%s)", FL,__func__, wr_filename, strerror(errno)); + free(wr_filename); + return; + } + copyFILEcontent(cur->f, wf); + if (MIME_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Memory FILE have cpoied to %s",FL,__func__,wr_filename); + + free(wr_filename); + fclose(wf); +} + +void write_all_to_FS_files(RIPMIME_output *unpack_metadata) +{ + int i; + for (i = 0; i < all_MIME_elements.mime_count; i++) + { + MIME_element* m = getItem(all_MIME_elements.mime_arr, i); + write_FS_file(unpack_metadata, m); + } +} + +//------Dynamic array function definitions------ +// Array initialization +void arrayInit(dynamic_array** arr_ptr) +{ + dynamic_array *container; + container = (dynamic_array*)malloc(sizeof(dynamic_array)); + if(!container) { + LOGGER_log("%s:%d:%s:ERROR: Memory allocation failed", FL,__func__); + exit(0); + } + + container->size = 0; + container->capacity = INITIAL_SIZE; + container->array = (MIME_element **)malloc(INITIAL_SIZE * sizeof(MIME_element*)); + if (!container->array){ + LOGGER_log("%s:%d:%s:ERROR: Memory allocation failed", FL,__func__); + exit(0); + } + + *arr_ptr = container; +} + +// Insertion Operation +void insertItem(dynamic_array* container, MIME_element* item) +{ + if (container->size == container->capacity) { + MIME_element **temp = container->array; + container->capacity <<= 1; + container->array = realloc(container->array, container->capacity * sizeof(MIME_element*)); + if(!container->array) { + LOGGER_log("%s:%d:%s:ERROR: Out of memory reallocation", FL,__func__); + container->array = temp; + return; + } + } + container->array[container->size++] = item; +} + +// Retrieve Item at Particular Index +MIME_element* getItem(dynamic_array* container, int index) +{ + if(index >= container->size) { + LOGGER_log("%s:%d:%s:ERROR: Index %d is out of bounds", FL,__func__, index); + return NULL; + } + return container->array[index]; +} + +// Update Operation +void updateItem(dynamic_array* container, int index, MIME_element* item) +{ + if (index >= container->size) { + LOGGER_log("%s:%d:%s:ERROR: Index %d is out of bounds", FL,__func__, index); + return; + } + container->array[index] = item; +} + +// Delete Item from Particular Index +void deleteItem(dynamic_array* container, int index) +{ + if(index >= container->size) { + LOGGER_log("%s:%d:%s:ERROR: Index %d is out of bounds", FL,__func__, index); + return; + } + + for (int i = index; i < container->size; i++) { + container->array[i] = container->array[i + 1]; + } + container->size--; +} + +// Array Traversal +void printArray(dynamic_array* container) +{ + printf("Array elements: "); + for (int i = 0; i < container->size; i++) { + printf("%p ", container->array[i]); + } + printf("\nSize: "); + printf("%lu", container->size); + printf("\nCapacity: "); + printf("%lu\n", container->capacity); +} + +// Freeing the memory allocated to the array +void freeArray(dynamic_array* container, RIPMIME_output *unpack_metadata) +{ + if (unpack_metadata->unpack_mode != RIPMIME_UNPACK_MODE_TO_DIRECTORY) + for (int i = 0; i < container->size; i++) { + MIME_element_free(container->array[i]); + } + free(container->array); + free(container); +} +/*---------- EOF -----------*/ diff --git a/mime_element.h b/mime_element.h new file mode 100644 index 0000000..1030142 --- /dev/null +++ b/mime_element.h @@ -0,0 +1,78 @@ + +#ifndef MIME_ELEMENT +#define MIME_ELEMENT +/* mime_element.h */ + +/* unpack modes */ +#define RIPMIME_UNPACK_MODE_TO_DIRECTORY 0 +#define RIPMIME_UNPACK_MODE_IN_MEMORY 1 +#define RIPMIME_UNPACK_MODE_LIST_MIME 2 + +#define _MIME_RENAME_METHOD_INFIX 1 +#define _MIME_RENAME_METHOD_PREFIX 2 +#define _MIME_RENAME_METHOD_POSTFIX 3 +#define _MIME_RENAME_METHOD_RANDINFIX 4 +#define _MIME_RENAME_METHOD_RANDPREFIX 5 +#define _MIME_RENAME_METHOD_RANDPOSTFIX 6 + +struct mime_output +{ + char *dir; + int unpack_mode; + // int fragment_number; will be used later + int rename_method; + int unique_names; // flague +}; +typedef struct mime_output RIPMIME_output; + +typedef struct { + struct MIME_element* parent; + int id; + char* directory; + char* filename; + char* fullpath; + FILE* f; + char* content_type_string; + char* content_transfer_encoding; + char* name; + char* mem_filearea; + size_t mem_filearea_l; + int decode_result_code; +} MIME_element; + +typedef struct { + size_t size; + size_t capacity; + MIME_element** array; +} dynamic_array; + +typedef struct { + int mime_count; + dynamic_array* mime_arr; +} all_MIME_elements_s; + +extern all_MIME_elements_s all_MIME_elements; + +int MIMEELEMENT_set_debug( int level ); + +void all_MIME_elements_init (void); +MIME_element* MIME_element_add ( + struct MIME_element* parent, + RIPMIME_output *unpack_metadata, + char* filename, + char* content_type_string, + char* content_transfer_encoding, + char* name, + int current_recursion_level, + int attachment_count, + int filecount, + const char* func); +// void MIME_element_free (MIME_element* cur); +void MIME_element_deactivate (MIME_element* cur, RIPMIME_output *unpack_metadata); +void printArray(dynamic_array* container); +void freeArray(dynamic_array* container, RIPMIME_output *unpack_metadata); +void write_all_to_FS_files(RIPMIME_output *unpack_metadata); + +int MIME_test_uniquename( RIPMIME_output *unpack_metadata, char *fname ); + +#endif diff --git a/MIME_headers.c b/mime_headers.c similarity index 76% rename from MIME_headers.c rename to mime_headers.c index 57812d3..6003647 100644 --- a/MIME_headers.c +++ b/mime_headers.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "ffget.h" @@ -35,7 +34,8 @@ #include "strstack.h" #include "boundary-stack.h" #include "filename-filters.h" -#include "MIME_headers.h" +#include "mime_element.h" +#include "mime_headers.h" #ifndef FL #define FL __FILE__, __LINE__ @@ -45,24 +45,31 @@ #define MIMEH_DPEDANTIC ((glb.debug >= _MIMEH_DEBUG_PEDANTIC)) #define MIMEH_DNORMAL ((glb.debug >= _MIMEH_DEBUG_NORMAL )) -#define DMIMEH if ((glb.debug >= _MIMEH_DEBUG_NORMAL)) +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) char *MIMEH_defect_description_array[_MIMEH_DEFECT_ARRAY_SIZE]; -struct MIMEH_globals { +int MIMEH_read_headers( FILE* header_file, FILE* original_header_file, struct MIMEH_header_info *hinfo, FFGET_FILE *f, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ); +int MIMEH_headers_get(FILE* header_file, FILE* original_header_file, struct MIMEH_header_info *hinfo, FFGET_FILE *f, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ); +int MIMEH_read_primary_headers( FILE* header_file, FILE* original_header_file, char *fname, struct MIMEH_header_info *hinfo, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ); +struct MIMEH_globals { int doubleCR; int doubleCR_save; - char doubleCRname[_MIMEH_STRLEN_MAX +1]; + char doubleCRname[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; - char appledouble_filename[_MIMEH_STRLEN_MAX +1]; + char appledouble_filename[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; - char subject[_MIMEH_STRLEN_MAX +1]; + char subject[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; - char *headerline; - char *headerline_original; // Holds the original header-form without decoding. - int save_headers; - int save_headers_original; int test_mailbox; int debug; int webform; @@ -73,11 +80,6 @@ struct MIMEH_globals { int header_longsearch; // keep searching until valid headers are found - this is used to filter out qmail bounced emails - breaks RFC's but people are wanting it :-( int longsearch_limit; // how many segments do we attempt to look ahead... - - char output_dir[_MIMEH_STRLEN_MAX +1]; - FILE *header_file; - FILE *original_header_file; - int original_header_save_to_file; }; static struct MIMEH_globals glb; @@ -118,17 +120,9 @@ int MIMEH_version(void) Changes: \------------------------------------------------------------------*/ -int MIMEH_init( void ) +void MIMEH_init( void ) { glb.doubleCR = 0; - glb.headerline = NULL; - glb.headerline_original = NULL; - glb.header_file = NULL; - glb.original_header_file = NULL; - glb.original_header_save_to_file = 0; - - glb.save_headers = 0; - glb.save_headers_original = 0; glb.test_mailbox = 0; glb.debug = 0; glb.webform = 0; @@ -137,13 +131,10 @@ int MIMEH_init( void ) glb.header_fix = 1; glb.verbose = 0; glb.verbose_contenttype = 0; - glb.output_dir[0]='\0'; glb.doubleCRname[0]='\0'; glb.appledouble_filename[0]='\0'; glb.header_longsearch=0; glb.longsearch_limit=1; - - return 0; } /*-----------------------------------------------------------------\ @@ -289,26 +280,6 @@ int MIMEH_set_debug( int level ) return glb.debug; } -/*-----------------------------------------------------------------\ - Function Name : MIMEH_set_outputdir - Returns Type : int - ----Parameter List - 1. char *dir , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: -\------------------------------------------------------------------*/ -int MIMEH_set_outputdir( char *dir ) -{ - if (dir) snprintf(glb.output_dir,_MIMEH_STRLEN_MAX,"%s",dir); - return 0; -} - /*-----------------------------------------------------------------\ Function Name : MIMEH_set_webform Returns Type : int @@ -413,150 +384,6 @@ int MIMEH_get_verbosity_contenttype( void ) return glb.verbose_contenttype; } -/*------------------------------------------------------------------------ -Procedure: MIMEH_set_headers_save ID:1 -Purpose: Sets MIMEH's headers save file (where MIMEH will save the -headers it reads in from the mailpack) -Input: -Output: -Errors: -------------------------------------------------------------------------*/ -int MIMEH_set_headers_save( FILE *f ) -{ - glb.header_file = f; - glb.save_headers = 1; - return 0; -} - -/*-----------------------------------------------------------------\ - Function Name : MIMEH_set_headers_original_save_to_file - Returns Type : int - ----Parameter List - 1. FILE *f , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int MIMEH_set_headers_original_save_to_file( FILE *f ) -{ - if (f == NULL) glb.original_header_save_to_file = 0; - else glb.original_header_save_to_file = 1; - glb.original_header_file = f; - - return glb.original_header_save_to_file; -} - -/*-----------------------------------------------------------------\ - Function Name : MIMEH_set_headers_nosave - Returns Type : int - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int MIMEH_set_headers_nosave( void ) -{ - glb.header_file = NULL; - glb.save_headers = 0; - return 0; -} - -/*-----------------------------------------------------------------\ - Function Name : MIMEH_get_headers_save - Returns Type : int - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int MIMEH_get_headers_save( void ) -{ - return glb.save_headers; -} - - -/*-----------------------------------------------------------------\ - Function Name : MIMEH_set_headers_save_original - Returns Type : int - ----Parameter List - 1. int level , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int MIMEH_set_headers_save_original( int level ) -{ - glb.save_headers_original = level; - return glb.save_headers_original; -} - - -/*-----------------------------------------------------------------\ - Function Name : MIMEH_get_headers_ptr - Returns Type : int - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -char *MIMEH_get_headers_ptr( void ) -{ - return glb.headerline; -} - -/*-----------------------------------------------------------------\ - Function Name : *MIMEH_get_headers_original_ptr - Returns Type : char - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -char *MIMEH_get_headers_original_ptr( void ) -{ - return glb.headerline_original; -} - /*-----------------------------------------------------------------\ Function Name : MIMEH_set_header_longsearch Returns Type : int @@ -604,7 +431,7 @@ int MIMEH_set_defect( struct MIMEH_header_info *hinfo, int defect ) { hinfo->defects[defect]++; hinfo->header_defect_count++; - DMIMEH LOGGER_log("%s:%d:MIMEH_set_defect:DEBUG: Setting defect index '%d' to '%d'",FL, defect, hinfo->defects[defect]); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Setting defect index '%d' to '%d'",FL, __func__, defect, hinfo->defects[defect]); } return 0; } @@ -691,11 +518,11 @@ int MIMEH_are_headers_RFC822( char *headers ) if (headers == NULL) { - DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG: Headers are NULL"); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Headers are NULL"); return 0; } - DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG:----\n%s\n----",FL,headers); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG:----\n%s\n----",FL, __func__, headers); lc_headers = strdup(headers); if (lc_headers == NULL) return 0; @@ -703,13 +530,13 @@ int MIMEH_are_headers_RFC822( char *headers ) //PLD_strlower((unsigned char *)lc_headers); PLD_strlower(lc_headers); - DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG:----(lowercase)----\n%s\n----",FL,lc_headers); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG:----(lowercase)----\n%s\n----",FL, __func__, lc_headers); for (condition_item=0; condition_item < 6; condition_item++) { char *p; - DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG: Condition test item[%d] = '%s'",FL,condition_item,conditions[condition_item]); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Condition test item[%d] = '%s'",FL, __func__, condition_item,conditions[condition_item]); p = strstr(lc_headers, conditions[condition_item]); if (p != NULL) { @@ -742,43 +569,30 @@ int MIMEH_are_headers_RFC822( char *headers ) Changes: \------------------------------------------------------------------*/ -int MIMEH_save_doubleCR( FFGET_FILE *f ) +int MIMEH_save_doubleCR( FFGET_FILE *f, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ) { - //char c; int c; - FILE *fo; - struct stat st; + MIME_element* cur_mime = NULL; - // Determine a file name we can use. - do { - glb.doubleCR_count++; - snprintf(glb.doubleCRname,_MIMEH_STRLEN_MAX,"%s/doubleCR.%d",glb.output_dir,glb.doubleCR_count); - } - while (stat(glb.doubleCRname, &st) == 0); + glb.doubleCR_count++; + snprintf(glb.doubleCRname,_MIMEH_STRLEN_MAX,"%s/%s_doubleCR.%d_", unpack_metadata->dir, hinfo->filename, glb.doubleCR_count); + cur_mime = MIME_element_add (NULL, unpack_metadata, glb.doubleCRname, "doubleCR", NULL, "doubleCR", hinfo->current_recursion_level + 1, 0, 0, __func__); - fo = fopen(glb.doubleCRname,"w"); - if (!fo) - { - LOGGER_log("%s:%d:MIMEH_save_doubleCR:ERROR: unable to open '%s' to write (%s)", FL,glb.doubleCRname,strerror(errno)); - return -1; - } - - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_save_doubleCR:DEBUG: Saving DoubleCR header: %s\n", FL,glb.doubleCRname); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Saving DoubleCR header: %s\n", FL, __func__, glb.doubleCRname); while (1) { c = FFGET_fgetc(f); - fprintf(fo,"%c",c); + fprintf(cur_mime->f,"%c",c); if ((c == EOF)||(c == '\n')) { break; } } - fclose(fo); + MIME_element_deactivate(cur_mime, unpack_metadata); return 0; } - /*-----------------------------------------------------------------\ Function Name : * Returns Type : char @@ -856,7 +670,7 @@ int MIMEH_strip_comments( char *input ) { int stop_searching = 0; - DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: Located open ( at %s",FL,p); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Located open ( at %s",FL, __func__, p); // If we did locate an opening parenthesis, look for the closing one // NOTE - we cannot have a breaking \n or \r inbetween // q = strpbrk(p, ")\n\r"); @@ -880,7 +694,7 @@ int MIMEH_strip_comments( char *input ) break; case ')': - DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: Located closing ) at %s",FL,q); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Located closing ) at %s",FL, __func__, q); if (in_quote == 0) stop_searching = 1; break; } @@ -901,7 +715,7 @@ int MIMEH_strip_comments( char *input ) // Move q to the first char after the closing parenthesis q++; - DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: located closing ) at %s ",FL, q); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: located closing ) at %s ",FL, __func__, q); // While there's more chars in string, copy them to where // the opening parenthesis is while (*q != '\0') @@ -910,7 +724,7 @@ int MIMEH_strip_comments( char *input ) p++; q++; } // While q != '\0' - DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: char copy done",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: char copy done",FL, __func__); // Terminate the string *p = '\0'; @@ -920,7 +734,7 @@ int MIMEH_strip_comments( char *input ) } // if p == NULL } while ((p != NULL)&&(p_org != NULL)); // do-while more comments to remove - DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: Final string = '%s'",FL,input); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Final string = '%s'",FL, __func__, input); return 0; } @@ -992,7 +806,7 @@ int MIMEH_fix_header_mistakes( char *data ) int result = 0; char *p; - DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Checking and fixing headers in '%s'",FL,data); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Checking and fixing headers in '%s'",FL, __func__, data); if (glb.header_fix == 0) return result; @@ -1006,7 +820,7 @@ int MIMEH_fix_header_mistakes( char *data ) q = p+1; - DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Located ';' at offset %d '%20s",FL, p -data, p); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Located ';' at offset %d '%20s",FL, __func__, p -data, p); if ((*q == '\n')||(*q == '\r')) { nonblank_detected = 0; @@ -1033,7 +847,7 @@ int MIMEH_fix_header_mistakes( char *data ) } /** ELSE - if *q wasn't a line break char **/ if (nonblank_detected == 1) { - DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Line was normal/safe, continue...",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Line was normal/safe, continue...",FL, __func__); p++; continue; } /** if nonblank_detected == 1 **/ @@ -1041,11 +855,11 @@ int MIMEH_fix_header_mistakes( char *data ) ** line, then we need to pull up the next line **/ if (*q != '\0') { if(!MIMEH_check_ct(q)){ - DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Line needs fixing",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Line needs fixing",FL, __func__); *q = ' '; q++; if ((*q == '\n')||(*q == '\r')) *q = ' '; - DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Line fixed",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Line fixed",FL, __func__); p = q; }else{ p++; @@ -1053,7 +867,7 @@ int MIMEH_fix_header_mistakes( char *data ) } /** If q wasn't the end of data **/ } /** while looking for more ';' chars **/ - DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Done",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Done",FL, __func__); return result; } @@ -1065,19 +879,17 @@ Purpose: Reads from the stream F until it detects a From line, or a blank Output: Errors: ------------------------------------------------------------------------*/ -int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) +int MIMEH_read_headers( FILE* header_file, FILE* original_header_file, struct MIMEH_header_info *hinfo, FFGET_FILE *f, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ) { char buffer[_MIMEH_STRLEN_MAX+1]; int totalsize=0; int linesize=0; int totalsize_original=0; int result = 0; - int firstline = 1; int search_count=0; char *tmp; char *tmp_original; char *fget_result = NULL; - char *headerline_end; char *p; char *linestart; char *lineend; @@ -1093,16 +905,17 @@ int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) to be overly intelligent about interpreting data. **/ - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: File position = %ld [0x%0X]" + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: File position = %ld [0x%0X]" ,FL + ,__func__ ,FFGET_ftell(f) ,FFGET_ftell(f) ); do { + char *headerline_original = NULL; // Holds the original header-form without decoding. search_count++; - glb.headerline = NULL; - glb.headerline_original = NULL; + hinfo->headerline_buffer = NULL; tmp_original = NULL; while ((fget_result=FFGET_fgets(buffer,_MIMEH_STRLEN_MAX, f))) @@ -1115,73 +928,73 @@ int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) else if (strstr(linestart,"\r\r")) hinfo->crcr_count++; else if (strchr(linestart,'\n')) hinfo->lf_count++; - if (MIMEH_DNORMAL)LOGGER_log("%s:%d:MIMEH_read_headers: [CRLF=%d, CRCR=%d, LF=%d] Data In=[sz=%d:tb=%d:mem=%p]'%s'",FL, hinfo->crlf_count, hinfo->crcr_count, hinfo->lf_count, linesize, f->trueblank, glb.headerline, buffer); + if (MIMEH_DNORMAL)LOGGER_log("%s:%d:%s: [CRLF=%d, CRCR=%d, LF=%d] Data In=[sz=%d:tb=%d:mem=%p]'%s'",FL, __func__, hinfo->crlf_count, hinfo->crcr_count, hinfo->lf_count, linesize, f->trueblank, hinfo->headerline_buffer, buffer); // If we are being told to copy the input data to an output file // then do so here (this is for the originals) - if ((glb.original_header_save_to_file > 0)&&(glb.original_header_file != NULL)) + if (hinfo->original_header_file != NULL) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: saving to file...",FL); - fprintf(glb.original_header_file,"%s",linestart); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: saving to file...",FL, __func__); + fprintf(hinfo->original_header_file,"%s",linestart); } // if we are being told to keep a copy of the original data // as it comes in from ffget, then do the storage here - if (glb.save_headers_original > 0) + if (save_headers_original) { - if (MIMEH_DNORMAL) LOGGER_log("MIMEH_read_headers:DEBUG:Data-In:[%d:%d] '%s'", strlen(linestart), linesize, linestart); - tmp_original = realloc(glb.headerline_original, totalsize_original+linesize+1); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG:Data-In:[%d:%d] '%s'", FL, __func__, strlen(linestart), linesize, linestart); + tmp_original = realloc(headerline_original, totalsize_original+linesize+1); if (tmp_original == NULL) { - LOGGER_log("%s:%d:MIMEH_read_headers:ERROR: Cannot allocate %d bytes to contain new headers_original ", FL,totalsize_original +linesize +1); - if (glb.headerline_original != NULL) free(glb.headerline_original); - glb.headerline_original = NULL; + LOGGER_log("%s:%d:%s:ERROR: Cannot allocate %d bytes to contain new headers_original ", FL, __func__, totalsize_original +linesize + 1); + if (headerline_original != NULL) free(headerline_original); + headerline_original = NULL; return -1; } - if (glb.headerline_original == NULL) + if (headerline_original == NULL) { - glb.headerline_original = tmp_original; - totalsize_original = linesize +1; - PLD_strncpy( glb.headerline_original, linestart, (linesize+1)); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: '%s'", FL, glb.headerline_original); + headerline_original = tmp_original; + totalsize_original = linesize + 1; + PLD_strncpy( headerline_original, linestart, (linesize+1)); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: '%s'", FL, __func__, headerline_original); } else { - glb.headerline_original = tmp_original; - PLD_strncpy( (glb.headerline_original +totalsize_original -1), linestart, (linesize +1)); + headerline_original = tmp_original; + PLD_strncpy( (headerline_original +totalsize_original -1), linestart, (linesize + 1)); totalsize_original += linesize; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: HO = '%s'", FL, glb.headerline_original); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: HO = '%s'", FL, __func__, headerline_original); } //LOGGER_log("DEBUG:linesize=%d data='%s'",linesize, linestart); } /** Normal processing of the headers now starts. **/ - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: realloc'ing dataspace",FL); - tmp = realloc(glb.headerline, totalsize+linesize+1); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: realloc'ing dataspace",FL, __func__); + tmp = realloc(hinfo->headerline_buffer, totalsize+linesize+1); if (tmp == NULL) { - LOGGER_log("%s:%d:MIMEH_read_headers:ERROR: Cannot allocate %d bytes to contain new headers ", FL,totalsize +linesize +1); - if (glb.headerline != NULL) free(glb.headerline); - glb.headerline = NULL; + LOGGER_log("%s:%d:%s:ERROR: Cannot allocate %d bytes to contain new headers ", FL, __func__, totalsize +linesize + 1); + if (hinfo->headerline_buffer != NULL) + free(hinfo->headerline_buffer); + hinfo->headerline_buffer = NULL; return -1; } - if (glb.headerline == NULL) + if (hinfo->headerline_buffer == NULL) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Initial appending of head to dataspace headerline = NULL realloc block = %p linestart = %p linesize = %d",FL, tmp, linestart, linesize); - glb.headerline = tmp; + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Initial appending of head to dataspace headerline = NULL realloc block = %p linestart = %p linesize = %d",FL, __func__, tmp, linestart, linesize); + hinfo->headerline_buffer = tmp; totalsize = linesize; - PLD_strncpy(glb.headerline, linestart, (linesize +1)); - headerline_end = glb.headerline +totalsize; + PLD_strncpy(hinfo->headerline_buffer, linestart, (linesize + 1)); } // If the global headerline is currently NULL else { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Appending of new data to existing header existing-headerline = %p new realloc block = %p linestart = %p linesize = %d",FL, glb.headerline, tmp, linestart, linesize); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Appending of new data to existing header existing-headerline = %p new realloc block = %p linestart = %p linesize = %d",FL, __func__, hinfo->headerline_buffer, tmp, linestart, linesize); // Perform header unfolding by removing any CRLF's // of the last line if the first characters of the // newline are blank/space - glb.headerline = tmp; + hinfo->headerline_buffer = tmp; if ((linestart < lineend)&&((*linestart == '\t')||(*linestart == ' '))) { @@ -1197,40 +1010,40 @@ int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) // 'p' holds the location at the -end- of the current headers where // we are going to append the newly read line - p = glb.headerline +totalsize -1; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: unwrapping headers headers=%p, p = %p",FL,glb.headerline, p); - while ((p >= glb.headerline)&&(( *p == '\n' )||( *p == '\r' ))) + p = hinfo->headerline_buffer + totalsize -1; + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: unwrapping headers headers=%p, p = %p",FL, __func__, hinfo->headerline_buffer, p); + while ((p >= hinfo->headerline_buffer)&&(( *p == '\n' )||( *p == '\r' ))) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Removing trailing space p=[%p]%c",FL, p, *p); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Removing trailing space p=[%p]%c",FL, __func__, p, *p); *p = '\0'; p--; totalsize--; } - p = glb.headerline +totalsize -1; + p = hinfo->headerline_buffer + totalsize -1; } - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Memcopying line, source = %p, dest = %p, size = %d", FL, linestart, glb.headerline +totalsize, linesize); - memcpy((glb.headerline +totalsize), linestart, (linesize)); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Memcopying line, source = %p, dest = %p, size = %d", FL, __func__, linestart, hinfo->headerline_buffer + totalsize, linesize); + memcpy((hinfo->headerline_buffer + totalsize), linestart, (linesize)); totalsize += linesize; - *(glb.headerline +totalsize) = '\0'; + *(hinfo->headerline_buffer + totalsize) = '\0'; - } // If the glb.headerline already is allocated and we're appending to it. + } // If the hinfo->headerline_buffer already is allocated and we're appending to it. if (f->trueblank) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Trueblank line detected in header reading",FL); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Headers /before/ decoding\n-------\n%s\n-------------------",FL, glb.headerline); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Trueblank line detected in header reading",FL, __func__); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Headers /before/ decoding\n-------\n%s\n-------------------",FL, __func__, hinfo->headerline_buffer); - MIMEH_fix_header_mistakes( glb.headerline ); - MDECODE_decode_ISO( glb.headerline, totalsize ); + MIMEH_fix_header_mistakes( hinfo->headerline_buffer ); + MDECODE_decode_ISO( hinfo->headerline_buffer, totalsize ); - if ((glb.save_headers)&&(glb.headerline)) + if ((save_headers)&&(hinfo->headerline_buffer)) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Saving header line.",FL); - fprintf(glb.header_file,"%s",glb.headerline); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Saving header line.",FL, __func__); + fprintf(hinfo->header_file,"%s",hinfo->headerline_buffer); } - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Final Headers\n------------------\n%s---------------", FL,glb.headerline); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Final Headers\n------------------\n%s---------------", FL, __func__, hinfo->headerline_buffer); //result = 1; //result = 0; break; @@ -1243,17 +1056,14 @@ int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) { if (glb.doubleCR_save != 0) { - MIMEH_save_doubleCR(f); + MIMEH_save_doubleCR(f, unpack_metadata, hinfo); glb.doubleCR = 1; } FFGET_doubleCR = 0; FFGET_SDL_MODE = 0; } // FFGET_doubleCR test - - firstline = 0; } // While reading more headers from the source file. - // If FFGET ran out of data whilst processing the headers, then acknowledge this // by returning a -1. // @@ -1262,17 +1072,17 @@ int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) if (!fget_result) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:ERROR: FFGET module ran out of input while reading headers",FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:ERROR: FFGET module ran out of input while reading headers",FL, __func__); /** If we're meant to be saving the headers, we better do that now, even though we couldn't ** read everything we wanted to **/ - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: save_headers=%d totalsize=%d headerline=%s", FL, glb.save_headers, totalsize, glb.headerline); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: save_headers=%d totalsize=%d headerline=%s", FL, __func__, save_headers, totalsize, hinfo->headerline_buffer); - if ((glb.save_headers)&&(glb.headerline)) + if ((save_headers)&&(hinfo->headerline_buffer)) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Saving header line.",FL); - MIMEH_fix_header_mistakes( glb.headerline ); - MDECODE_decode_ISO( glb.headerline, totalsize ); - fprintf(glb.header_file,"%s",glb.headerline); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Saving header line.",FL, __func__); + MIMEH_fix_header_mistakes( hinfo->headerline_buffer ); + MDECODE_decode_ISO( hinfo->headerline_buffer, totalsize ); + fprintf(hinfo->header_file,"%s",hinfo->headerline_buffer); } result = -1; @@ -1280,23 +1090,30 @@ int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) if (glb.header_longsearch > 0) { /** Test the headers for RFC compliance... **/ - is_RFC822_headers = MIMEH_are_headers_RFC822(glb.headerline); + is_RFC822_headers = MIMEH_are_headers_RFC822(hinfo->headerline_buffer); if (is_RFC822_headers == 0) { /** If not RFC822 headers, then clean up everything we allocated in here **/ - DMIMEH LOGGER_log("%s:%d:MIME_read_headers:DEBUG: No RFC822 headers detected, cleanup.", FL); - MIMEH_headers_cleanup(); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: No RFC822 headers detected, cleanup.", FL, __func__); + if (headerline_original != NULL) + { + free(headerline_original); + headerline_original = NULL; + } + if (hinfo->headerline_buffer != NULL) + { + free(hinfo->headerline_buffer); + hinfo->headerline_buffer = NULL; + } } } } } while ((is_RFC822_headers==0)&&(glb.header_longsearch>0)&&(result==0)&&(search_count 0) { *s = *(s+1); @@ -1811,7 +1623,7 @@ int MIMEH_parse_header_parameter( struct MIMEH_header_info *hinfo, char *data, // Now that our string is all cleaned up, save it to our output value snprintf( output_value, output_value_size, "%s", string ); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Final value = '%s'",FL, output_value); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Final value = '%s'",FL, __func__, output_value); } // If the first non-whitespace char wasn't a '=' } // If the first char after the search-string wasn't a '*' @@ -1822,18 +1634,11 @@ int MIMEH_parse_header_parameter( struct MIMEH_header_info *hinfo, char *data, if (hl != NULL) free(hl); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: [return=%d] Done seeking for '%s' data_end_point=%p (from %p)",FL, return_value, searchstr, *data_end_point, data); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: [return=%d] Done seeking for '%s' data_end_point=%p (from %p)",FL, __func__, return_value, searchstr, *data_end_point, data); return return_value; - } - - - - - - /*-----------------------------------------------------------------\ Function Name : MIMEH_is_valid_header_prefix Returns Type : int @@ -1885,8 +1690,6 @@ int MIMEH_is_valid_header_prefix( char *data, char *prefix_name ) return 1; } - - /*-----------------------------------------------------------------\ Function Name : MIMEH_parse_contenttype_linear Returns Type : int @@ -1929,10 +1732,7 @@ int MIMEH_parse_contenttype_linear_EXPERIMENT( char *header_name, char *header_v // if (strncasecmp(chv, "boundary" } - - return 0; - } /*-----------------------------------------------------------------\ @@ -1954,21 +1754,18 @@ int MIMEH_parse_contenttype_linear_EXPERIMENT( char *header_name, char *header_v \------------------------------------------------------------------*/ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH_header_info *hinfo ) { - int return_value; char *p, *q; char *hv = strdup( header_value ); - // CONTENT TYPE ------------------------------- - // CONTENT TYPE ------------------------------- // CONTENT TYPE ------------------------------- - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Start",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Start",FL, __func__); p = strstr(header_name,"content-type"); if (p != NULL) { - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype: Content-type string found in header-name",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s: Content-type string found in header-name",FL, __func__); /** 20041216-1106:PLD: Increase our sanity **/ hinfo->sanity++; @@ -1999,11 +1796,12 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH hinfo->content_type = _CTYPE_APPLICATION_APPLEFILE; if ( hinfo->filename[0] == '\0' ) { - if (strlen(glb.appledouble_filename)>0) + int l = strlen(glb.appledouble_filename); + if (l>0) { - snprintf(hinfo->filename, sizeof(hinfo->filename), "%s.applemeta", glb.appledouble_filename ); + snprintf(hinfo->filename, _MIMEH_FILENAMELEN_MAX, "%s.applemeta", glb.appledouble_filename ); } else { - snprintf(hinfo->filename, sizeof(hinfo->filename), "applefile"); + snprintf(hinfo->filename, _MIMEH_FILENAMELEN_MAX, "applefile"); } } } @@ -2019,12 +1817,11 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH ** with that char normally, we'll convert it to something ** else **/ - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Located x-mac attachment",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Located x-mac attachment",FL, __func__); hinfo->x_mac = 1; FNFILTER_set_mac(hinfo->x_mac); } - // Copy the string to our content-type string storage field p = header_value; if (p != NULL) @@ -2083,11 +1880,8 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH if (*param == '\0') break; /** - ** Look for name or filename specifications in the headers - ** Look for name or filename specifications in the headers ** Look for name or filename specifications in the headers **/ - return_value = MIMEH_parse_header_parameter( hinfo, param, "name", hinfo->name, sizeof(hinfo->name), &data_end_point); /** Update param to point where data_end_point is ** this is so when we come around here again due @@ -2102,16 +1896,16 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH // Move the parameter search point up to where we stopped // processing the data in the MIMEH_parse_header_parameter() call - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Pushing new filename to stack '%s'",FL, hinfo->name); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Pushing new filename to stack '%s'",FL, __func__, hinfo->name); /** Step 1: Check to see if this filename already ** exists in the stack. We do this so that we don't ** duplicate entries and also to prevent false ** bad-header reports. **/ if (SS_cmp(&(hinfo->ss_names), hinfo->name, strlen(hinfo->name))==NULL) { - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Filtering '%s'",FL, hinfo->name); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Filtering '%s'",FL, __func__, hinfo->name); FNFILTER_filter(hinfo->name, _MIMEH_FILENAMELEN_MAX); - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Pushing '%s'",FL, hinfo->name); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Pushing '%s'",FL, __func__, hinfo->name); SS_push(&(hinfo->ss_names),hinfo->name,strlen(hinfo->name)); if (SS_count(&(hinfo->ss_names)) > 1) { @@ -2125,19 +1919,14 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH } /* If a filename was located in the headers */ - - - /** - ** Look for the MIME Boundary specification in the headers - ** Look for the MIME Boundary specification in the headers ** Look for the MIME Boundary specification in the headers **/ return_value = MIMEH_parse_header_parameter(hinfo, param, "boundary", hinfo->boundary, sizeof(hinfo->boundary), &data_end_point); - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Param<=>data_end gap = %d", FL,data_end_point -param); - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Param<=>data_end gap = %d", FL, __func__, data_end_point -param); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: param start pos = '%s'",FL, __func__, param); if (data_end_point > param) param = data_end_point; - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: param start pos = '%s'",FL, __func__, param); if ( return_value == 0 ) { // Move the parameter search point up to where we stopped @@ -2145,9 +1934,9 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH //hinfo->boundary_located = 1; hinfo->boundary_located++; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Pushed boundary to stack (%s)",FL, hinfo->boundary); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Pushed boundary to stack (%s)",FL, __func__, hinfo->boundary); BS_push(hinfo->boundary); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Setting hinfo->boundary_located to %d",FL, hinfo->boundary_located ); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Setting hinfo->boundary_located to %d",FL, __func__, hinfo->boundary_located ); if (hinfo->boundary_located > 1) { @@ -2162,9 +1951,9 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH //param = PLD_strtok( &tx, NULL, ";\n\r" ); // * PLD:20040831-22H15: Added 'if (param != NULL)' prefix to debugging lines // * In response to bug #32, submitted by ICL ZA - if (param != NULL) DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param); + if (param != NULL) if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: param start pos = '%s'",FL, __func__, param); param = strpbrk( param, ";\n\r " ); - if (param != NULL) DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param); + if (param != NULL) if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: param start pos = '%s'",FL, __func__, param); } // While } @@ -2172,21 +1961,11 @@ int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH if (hv != NULL) free(hv); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: end.",FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: end.",FL, __func__); return 0; - } - - - - - - - - - /*-----------------------------------------------------------------\ Function Name : MIMEH_parse_contentlocation Returns Type : int @@ -2209,9 +1988,6 @@ int MIMEH_parse_contentlocation( char *header_name, char *header_value, struct M char *p, *q; // CONTENT LOCATION ------------------------------- - // CONTENT LOCATION ------------------------------- - // CONTENT LOCATION ------------------------------- - PLD_strlower( header_name ); p = strstr(header_name,"content-location"); if (p) @@ -2219,7 +1995,7 @@ int MIMEH_parse_contentlocation( char *header_name, char *header_value, struct M /** 20041216-1108:PLD: Increase our sanity **/ hinfo->sanity++; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_contentlocation:DEBUG: Content Location line found - '%s'\n", FL, header_value); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Content Location line found - '%s'\n", FL, __func__, header_value); p = q = header_value; @@ -2231,32 +2007,16 @@ int MIMEH_parse_contentlocation( char *header_name, char *header_value, struct M if (p) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_contentlocation:DEBUG: filename = %s\n", FL, p); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: filename = %s\n", FL, __func__, p); snprintf(hinfo->name, sizeof(hinfo->name),"%s",p); snprintf(hinfo->filename, sizeof(hinfo->filename),"%s",p); FNFILTER_filter(hinfo->filename, _MIMEH_FILENAMELEN_MAX); SS_push(&(hinfo->ss_filenames), hinfo->filename, strlen(hinfo->filename)); - } } - return 0; - } - - - - - - - - - - - - - /*-----------------------------------------------------------------\ Function Name : MIMEH_parse_contenttransferencoding Returns Type : int @@ -2280,10 +2040,6 @@ int MIMEH_parse_contenttransferencoding( char *header_name, char *header_value, char c = '\n'; // CONTENT TRANSFER ENCODING --------------------- - // CONTENT TRANSFER ENCODING --------------------- - // CONTENT TRANSFER ENCODING --------------------- - - p = strstr(header_name,"content-transfer-encoding"); if (p) { @@ -2304,27 +2060,27 @@ int MIMEH_parse_contenttransferencoding( char *header_name, char *header_value, if (strstr(p,"base64")) { hinfo->content_transfer_encoding = _CTRANS_ENCODING_B64; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to BASE64", FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s: Encoding set to BASE64", FL, __func__); } else if (strstr(p,"7bit")) { hinfo->content_transfer_encoding = _CTRANS_ENCODING_7BIT; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to 7-BIT ", FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s: Encoding set to 7-BIT ", FL, __func__); } else if (strstr(p,"8bit")) { hinfo->content_transfer_encoding = _CTRANS_ENCODING_8BIT; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to 8-BIT", FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s: Encoding set to 8-BIT", FL, __func__); } else if (strstr(p,"quoted-printable")) { hinfo->content_transfer_encoding = _CTRANS_ENCODING_QP; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to Quoted-Printable", FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s: Encoding set to Quoted-Printable", FL, __func__); } else if (strstr(p,"binary")) { hinfo->content_transfer_encoding = _CTRANS_ENCODING_BINARY; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to Binary", FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s: Encoding set to Binary", FL, __func__); } else if ( (strstr(p,"uu")) @@ -2333,7 +2089,7 @@ int MIMEH_parse_contenttransferencoding( char *header_name, char *header_value, ) { hinfo->content_transfer_encoding = _CTRANS_ENCODING_UUENCODE; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to UUENCODE", FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s: Encoding set to UUENCODE", FL, __func__); } else hinfo->content_transfer_encoding = _CTRANS_ENCODING_RAW; @@ -2363,9 +2119,7 @@ int MIMEH_parse_contenttransferencoding( char *header_name, char *header_value, // which use the data. if (q != NULL) *q = c; } - return 0; - } /*-----------------------------------------------------------------\ @@ -2391,10 +2145,7 @@ int MIMEH_parse_contentdisposition( char *header_name, char *header_value, struc char *hv = strdup(header_value); // CONTENT DISPOSITION ------------------------------ - // CONTENT DISPOSITION ------------------------------ - // CONTENT DISPOSITION ------------------------------ - - //LOGGER_log("%s:%d:DEBUG: Headers='%s'",FL,header_value); + //LOGGER_log("%s:%d:DEBUG: Headers='%s'",FL, __func__, header_value); p = strstr(header_name,"content-disposition"); if (p != NULL) { @@ -2444,7 +2195,7 @@ int MIMEH_parse_contentdisposition( char *header_name, char *header_value, struc *q = '\0'; } - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contentdisposition:DEBUG: Disposition string = '%s'",FL, hv); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Disposition string = '%s'",FL, __func__, hv); // Commence to decode the disposition string into its components. p = strpbrk( hv, ";\t\n\r " ); @@ -2462,7 +2213,7 @@ int MIMEH_parse_contentdisposition( char *header_name, char *header_value, struc int parse_result; char *data_end_point; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contentdisposition:DEBUG: Parsing '%s'",FL,param); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Parsing '%s'",FL, __func__, param); // Seek out possible 'filename' parameters @@ -2492,7 +2243,7 @@ int MIMEH_parse_contentdisposition( char *header_name, char *header_value, struc if ( hinfo->content_type == _CTYPE_MULTIPART_APPLEDOUBLE ) { snprintf( glb.appledouble_filename, sizeof(glb.appledouble_filename), "%s", hinfo->filename ); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contentdisposition:DEBUG: Setting appledouble filename to: '%s'",FL,glb.appledouble_filename); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Setting appledouble filename to: '%s'",FL, __func__, glb.appledouble_filename); } } // If the header-value contained ;'s ( indicating parameters ) @@ -2504,9 +2255,6 @@ int MIMEH_parse_contentdisposition( char *header_name, char *header_value, struc return 0; } - - - /*-----------------------------------------------------------------\ Function Name : MIMEH_parse_subject Returns Type : int @@ -2529,7 +2277,7 @@ int MIMEH_parse_generic( char *header_name, char *header_value, struct MIMEH_hea int compare_result = 0; int tlen; - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_generic:DEBUG: Searching for %s in %s",FL,tokenstr,header_name); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Searching for %s in %s",FL, __func__, tokenstr,header_name); /** Sanity check the parameters **/ if (hinfo == NULL) return -1; if (tokenstr == NULL) return -1; @@ -2548,14 +2296,12 @@ int MIMEH_parse_generic( char *header_name, char *header_value, struct MIMEH_hea case ' ': case '\t': case '\0': - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_generic:DEBUG: Located! Sanity up +1",FL); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Located! Sanity up + 1",FL, __func__); snprintf( buffer, bsize, "%s", header_value ); hinfo->sanity++; break; } - } - return 0; } @@ -2585,9 +2331,6 @@ int MIMEH_parse_subject( char *header_name, char *header_value, struct MIMEH_hea return result; } - - - /*-----------------------------------------------------------------\ Function Name : MIMEH_parse_date Returns Type : int @@ -2610,8 +2353,6 @@ int MIMEH_parse_date( char *header_name, char *header_value, struct MIMEH_header return MIMEH_parse_generic( header_name, header_value, hinfo, "date", hinfo->date, sizeof(hinfo->date) ); } - - /*-----------------------------------------------------------------\ Function Name : MIMEH_parse_from Returns Type : int @@ -2720,7 +2461,7 @@ int MIMEH_parse_charset( char *header_name, char *header_value, struct MIMEH_hea int result = 0; result = MIMEH_parse_generic( header_name, header_value, hinfo, "charset", hinfo->charset, sizeof(hinfo->charset) ); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_charset:DEBUG: Charset value = '%s'", FL, hinfo->charset); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Charset value = '%s'", FL, __func__, hinfo->charset); return result; } @@ -2741,41 +2482,39 @@ int MIMEH_parse_charset( char *header_name, char *header_value, struct MIMEH_hea Changes: \------------------------------------------------------------------*/ -int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ) +void MIMEH_headers_process( struct MIMEH_header_info *hinfo ) { /** scan through our headers string looking for information that is ** valid **/ - char *safeh, *h, *safehl; + char *safehl; char *current_header_position; int headerlength; - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Start [hinfo=%p]\n",FL, hinfo); - - safeh = h = headers; + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Start [hinfo=%p]\n",FL, __func__, hinfo); /** Duplicate the headers for processing - this way we don't 'taint' the ** original headers during our searching / altering. **/ - headerlength = strlen(h); + headerlength = strlen(hinfo->headerline_buffer); safehl = malloc(sizeof(char) *(headerlength+1)); - PLD_strncpy(safehl, h, headerlength+1); + PLD_strncpy(safehl, hinfo->headerline_buffer, headerlength+1); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_headers:DEBUG: Header length = %d\n", FL,headerlength); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Header length = %d\n", FL, __func__, headerlength); - MIMEH_strip_comments(h); + MIMEH_strip_comments(hinfo->headerline_buffer); - current_header_position = h; + current_header_position = hinfo->headerline_buffer; // Searching through the headers, we seek out header 'name:value;value;value' sets, // Each set is then cleaned up, seperated and parsed. - while ((current_header_position != NULL)&&( current_header_position <= (h +headerlength) )) + while ((current_header_position != NULL)&&( current_header_position <= (hinfo->headerline_buffer +headerlength) )) { char *header_name, *header_value; char *header_name_end_position; char *header_value_end_position; - DMIMEH LOGGER_log("%s:%d:MIMEH_headers_process:DEBUG: Processing '%s'",FL,current_header_position); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Processing '%s'",FL, __func__, current_header_position); /** Tokenise for the header 'name', ie, content-type, subject etc **/ header_name = current_header_position; @@ -2791,11 +2530,11 @@ int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ) // NOTE: this may activate on the true-blank lines, hence why we // dump the source string, just for confirmation - DMIMEH LOGGER_log("%s:%d:MIMEH_headers_process:DEBUG: Could not locate ':' separator, using whitespace (source='%s')",FL,header_name); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Could not locate ':' separator, using whitespace (source='%s')",FL, __func__, header_name); header_name_end_position = strpbrk( header_name, "\t " ); if (header_name_end_position == NULL) { - DMIMEH LOGGER_log("%s:%d:MIMEH_headers_process:DEBUG: Cannot find a header name:value pair in '%s'",FL, header_name); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Cannot find a header name:value pair in '%s'",FL, __func__, header_name); } } @@ -2834,7 +2573,7 @@ int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ) // we will 'ignore' them rather than throwing up our arms. This // ensures that we are not made to break over spurilous data. - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: This line contains no header:value pair (%s)", FL, current_header_position); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: This line contains no header:value pair (%s)", FL, __func__, current_header_position); continue; } else { @@ -2843,7 +2582,7 @@ int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ) // parse the data through our various parsing // functions. - header_value = header_name_end_position +1; + header_value = header_name_end_position + 1; header_value_end_position = strpbrk( header_value, "\n\r" ); if ( header_value_end_position != NULL ) { @@ -2851,8 +2590,8 @@ int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ) *header_value_end_position = '\0'; if (MIMEH_DNORMAL) { - LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Header Name ='%s'", FL, header_name ); - LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Header Value='%s'", FL, header_value ); + LOGGER_log("%s:%d:%s:DEBUG: Header Name ='%s'", FL, __func__, header_name ); + LOGGER_log("%s:%d:%s:DEBUG: Header Value='%s'", FL, __func__, header_value ); } // To make parsing simpler, convert our @@ -2876,28 +2615,26 @@ int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ) MIMEH_parse_received( header_name, header_value, hinfo ); MIMEH_parse_charset( header_name, header_value, hinfo ); - if (hinfo->filename[0] == '\0') { MIMEH_parse_contentlocation( header_name, header_value, hinfo ); } } else { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headerss:DEBUG: Header value end position is NULL",FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%ss:DEBUG: Header value end position is NULL",FL, __func__); } } - - - } // while // Final analysis on our headers: if ( hinfo->content_type == _CTYPE_MULTIPART_APPLEDOUBLE ) { - char tmp[128]; - snprintf( tmp, sizeof(tmp), "mac-%s", hinfo->filename ); - snprintf( hinfo->filename, sizeof(hinfo->filename), "%s", tmp ); - snprintf( hinfo->name, sizeof(hinfo->name), "%s", tmp ); + int len = strlen(hinfo->filename); + char * tmp = malloc(len + 4); + snprintf( tmp, min(_MIMEH_FILENAMELEN_MAX, len + 4), "mac-%s", hinfo->filename ); + strncat(hinfo->filename, tmp, min(_MIMEH_FILENAMELEN_MAX, len)); + strncat(hinfo->name, tmp, min(_MIMEH_STRLEN_MAX, len)); + free(tmp); } // PLD:20031205 @@ -2912,24 +2649,21 @@ int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ) || (strlen(hinfo->content_transfer_encoding_string) < 1) ) { - //LOGGER_log("%s:%d:DEBUG: Encoding pair was octet but no encoding, filename=%s\n",FL,hinfo->filename); + //LOGGER_log("%s:%d:DEBUG: Encoding pair was octet but no encoding, filename=%s\n",FL, __func__, hinfo->filename); hinfo->content_transfer_encoding = _CTRANS_ENCODING_RAW; } } - if (safehl) { free(safehl); } - else LOGGER_log("%s:%d:MIME_parse_headers:WARNING: Unable to free HEADERS allocated memory\n", FL); + else LOGGER_log("%s:%d:%s:WARNING: Unable to free HEADERS allocated memory\n", FL, __func__); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: END [hinfo=%p]\n", FL, hinfo); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: END [hinfo=%p]\n", FL, __func__, hinfo); - return 0; } - /*-----------------------------------------------------------------\ Date Code: : 20081124-184934 Function Name : MIMEH_headers_clearcount @@ -2952,7 +2686,6 @@ int MIMEH_headers_clearcount( struct MIMEH_header_info *hinfo ) { hinfo->lf_count = 0; hinfo->crcr_count = 0; return 0; - } /*-----------------------------------------------------------------\ @@ -2971,7 +2704,7 @@ int MIMEH_headers_clearcount( struct MIMEH_header_info *hinfo ) { Changes: \------------------------------------------------------------------*/ -int MIMEH_headers_get( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) +int MIMEH_headers_get(FILE* header_file, FILE* original_header_file, struct MIMEH_header_info *hinfo, FFGET_FILE *f, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ) { int result = 0; @@ -2992,29 +2725,27 @@ int MIMEH_headers_get( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) hinfo->lf_count=0; if (f->linebreak == (FFGET_LINEBREAK_CR|FFGET_LINEBREAK_LF)) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_headers_get:DEBUG: Setting to CRLF based on ffget value of %d", FL, f->linebreak); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Setting to CRLF based on ffget value of %d", FL, __func__, f->linebreak); snprintf(hinfo->delimeter,sizeof(hinfo->delimeter),"\r\n"); hinfo->crlf_count = 1; } else if (f->linebreak == FFGET_LINEBREAK_LF) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_headers_get:DEBUG: Setting to LF based on ffget value of %d", FL, f->linebreak); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Setting to LF based on ffget value of %d", FL, __func__, f->linebreak); snprintf(hinfo->delimeter,sizeof(hinfo->delimeter),"\n"); hinfo->lf_count = 1; } else { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_headers_get:DEBUG: ffget value of %d offered us no guide for the delimeter", FL, f->linebreak); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: ffget value of %d offered us no guide for the delimeter", FL, __func__, f->linebreak); } - - // Initialise header defects array. hinfo->header_defect_count = 0; memset(hinfo->defects, 0, sizeof(int) *_MIMEH_DEFECT_ARRAY_SIZE); snprintf( hinfo->content_type_string, _MIMEH_CONTENT_TYPE_MAX , "text/plain" ); - // Read from the file, the headers we need FFGET_set_watch_SDL(1); - result = MIMEH_read_headers(hinfo, f); + + result = MIMEH_read_headers(header_file, original_header_file, hinfo, f, unpack_metadata, save_headers_original, save_headers); FFGET_set_watch_SDL(0); if (hinfo->lf_count > hinfo->crlf_count) { @@ -3025,55 +2756,20 @@ int MIMEH_headers_get( struct MIMEH_header_info *hinfo, FFGET_FILE *f ) // flag this, free up the headers, and return. if (result == -1) { - if (glb.headerline) free(glb.headerline); return result; } // If we came back with an OKAY result, but there's nothing in the // headers, then flag off an error - if (glb.headerline == NULL) + if (hinfo->headerline_buffer == NULL) { - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_headers:DEBUG: null headerline\n", FL); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: null headerline\n", FL, __func__); return 1; } return result; } -/*-----------------------------------------------------------------\ - Function Name : MIMEH_headers_cleanup - Returns Type : int - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int MIMEH_headers_cleanup( void ) -{ - if (glb.headerline != NULL) - { - free(glb.headerline); - glb.headerline = NULL; - } - - if (glb.headerline_original != NULL) - { - free(glb.headerline_original); - glb.headerline_original = NULL; - } - - return 0; -} - - - /*-----------------------------------------------------------------\ Function Name : MIMEH_parse_headers Returns Type : int @@ -3090,22 +2786,20 @@ int MIMEH_headers_cleanup( void ) Changes: \------------------------------------------------------------------*/ -int MIMEH_parse_headers( FFGET_FILE *f, struct MIMEH_header_info *hinfo ) +int MIMEH_parse_headers( FILE* header_file, FILE* original_header_file, FFGET_FILE *f, struct MIMEH_header_info *hinfo, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ) { int result = 0; - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Start [F=%p, hinfo=%p]\n", FL, f, hinfo); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Start [F=%p, hinfo=%p]\n", FL, __func__, f, hinfo); /** 20041216-1100:PLD: Set the header sanity to zero **/ if ( result == 0 ) hinfo->sanity = 0; /** Proceed to read, process and finish headers **/ - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Getting headers",FL); - if ( result == 0 ) result = MIMEH_headers_get( hinfo, f ); - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Processing headers",FL); - if ( result == 0 ) result = MIMEH_headers_process( hinfo, glb.headerline ); - DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: cleanup of headers",FL); - if ( result == 0 ) result = MIMEH_headers_cleanup(); - if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: END [F=%p, hinfo=%p, sanity=%d]\n", FL, f, hinfo, hinfo->sanity); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Getting headers",FL, __func__); + if ( result == 0 ) result = MIMEH_headers_get( header_file, original_header_file, hinfo, f, unpack_metadata, save_headers_original, save_headers); + if(MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Processing headers",FL, __func__); + MIMEH_headers_process( hinfo ); + if (MIMEH_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: END [F=%p, hinfo=%p, sanity=%d]\n", FL, __func__, f, hinfo, hinfo->sanity); return result; } @@ -3126,7 +2820,7 @@ Displays a list of the located defects Changes: \------------------------------------------------------------------*/ -int MIMEH_dump_defects( struct MIMEH_header_info *hinfo ) +void MIMEH_dump_defects( struct MIMEH_header_info *hinfo ) { int i; @@ -3149,8 +2843,6 @@ int MIMEH_dump_defects( struct MIMEH_header_info *hinfo ) } } - - return 0; } /*-----------------------------------------------------------------\ @@ -3170,7 +2862,6 @@ int MIMEH_dump_defects( struct MIMEH_header_info *hinfo ) \------------------------------------------------------------------*/ int MIMEH_get_defect_count( struct MIMEH_header_info *hinfo ) { - return hinfo->header_defect_count; } @@ -3192,19 +2883,19 @@ int MIMEH_get_defect_count( struct MIMEH_header_info *hinfo ) Changes: \------------------------------------------------------------------*/ -int MIMEH_read_primary_headers( char *fname, struct MIMEH_header_info *hinfo ) +int MIMEH_read_primary_headers( FILE* header_file, FILE* original_header_file, char *fname, struct MIMEH_header_info *hinfo, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ) { FFGET_FILE F; FILE *f; f = fopen(fname,"r"); if (!f) { - LOGGER_log("%s:%d:MIMEH_read_primary_headers:ERROR: Cannot open mailpack '%s' (%s)", FL, fname, strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: Cannot open mailpack '%s' (%s)", FL, __func__, fname, strerror(errno)); return 0; } FFGET_setstream(&F,f); - MIMEH_parse_headers(&F, hinfo); + MIMEH_parse_headers(header_file, original_header_file, &F, hinfo, unpack_metadata, save_headers_original, save_headers); fclose(f); return 0; diff --git a/MIME_headers.h b/mime_headers.h similarity index 52% rename from MIME_headers.h rename to mime_headers.h index 1ca00c8..435365b 100644 --- a/MIME_headers.h +++ b/mime_headers.h @@ -5,80 +5,82 @@ #define _CTYPE_RANGE 99 -#define _CTYPE_UNSPECIFIED -1 -#define _CTYPE_MESSAGE_START 1 -#define _CTYPE_MESSAGE 1 -#define _CTYPE_MESSAGE_END 100 - -#define _CTYPE_MULTIPART_START 100 -#define _CTYPE_MULTIPART 100 -#define _CTYPE_MULTIPART_MIXED 101 -#define _CTYPE_MULTIPART_APPLEDOUBLE 102 -#define _CTYPE_MULTIPART_RELATED 103 -#define _CTYPE_MULTIPART_ALTERNATIVE 104 -#define _CTYPE_MULTIPART_REPORT 105 -#define _CTYPE_MULTIPART_SIGNED 106 -#define _CTYPE_MULTIPART_END 199 - -#define _CTYPE_TEXT_START 200 -#define _CTYPE_TEXT 200 -#define _CTYPE_TEXT_PLAIN 201 -#define _CTYPE_TEXT_UNKNOWN 202 -#define _CTYPE_TEXT_HTML 203 -#define _CTYPE_TEXT_CALENDAR 204 -#define _CTYPE_TEXT_END 299 - -#define _CTYPE_IMAGE_START 300 -#define _CTYPE_IMAGE 300 -#define _CTYPE_IMAGE_GIF 301 -#define _CTYPE_IMAGE_JPEG 302 -#define _CTYPE_IMAGE_PNG 303 -#define _CTYPE_IMAGE_END 399 - -#define _CTYPE_AUDIO_START 400 -#define _CTYPE_AUDIO 400 -#define _CTYPE_AUDIO_END 499 - -#define _CTYPE_OCTECT 800 -#define _CTYPE_RFC822 500 -#define _CTYPE_TNEF 600 -#define _CTYPE_APPLICATION 700 -#define _CTYPE_APPLICATION_APPLEFILE 701 -#define _CTYPE_UNKNOWN 0 - -#define _CTRANS_ENCODING_UNSPECIFIED -1 -#define _CTRANS_ENCODING_B64 100 -#define _CTRANS_ENCODING_7BIT 101 -#define _CTRANS_ENCODING_8BIT 102 -#define _CTRANS_ENCODING_QP 103 -#define _CTRANS_ENCODING_RAW 104 -#define _CTRANS_ENCODING_BINARY 105 -#define _CTRANS_ENCODING_UUENCODE 106 -#define _CTRANS_ENCODING_UNKNOWN 0 - -#define _CDISPOSITION_UNSPECIFIED -1 -#define _CDISPOSITION_INLINE 100 -#define _CDISPOSITION_ATTACHMENT 200 -#define _CDISPOSITION_FORMDATA 300 -#define _CDISPOSITION_UNKNOWN 0 - -#define _MIMEH_FOUND_FROM 100 +#define _CTYPE_UNSPECIFIED -1 +#define _CTYPE_MESSAGE_START 1 +#define _CTYPE_MESSAGE 1 +#define _CTYPE_MESSAGE_END 100 + +#define _CTYPE_MULTIPART_START 100 +#define _CTYPE_MULTIPART 100 +#define _CTYPE_MULTIPART_MIXED 101 +#define _CTYPE_MULTIPART_APPLEDOUBLE 102 +#define _CTYPE_MULTIPART_RELATED 103 +#define _CTYPE_MULTIPART_ALTERNATIVE 104 +#define _CTYPE_MULTIPART_REPORT 105 +#define _CTYPE_MULTIPART_SIGNED 106 +#define _CTYPE_MULTIPART_END 199 + +#define _CTYPE_TEXT_START 200 +#define _CTYPE_TEXT 200 +#define _CTYPE_TEXT_PLAIN 201 +#define _CTYPE_TEXT_UNKNOWN 202 +#define _CTYPE_TEXT_HTML 203 +#define _CTYPE_TEXT_CALENDAR 204 +#define _CTYPE_TEXT_END 299 + +#define _CTYPE_IMAGE_START 300 +#define _CTYPE_IMAGE 300 +#define _CTYPE_IMAGE_GIF 301 +#define _CTYPE_IMAGE_JPEG 302 +#define _CTYPE_IMAGE_PNG 303 +#define _CTYPE_IMAGE_END 399 + +#define _CTYPE_AUDIO_START 400 +#define _CTYPE_AUDIO 400 +#define _CTYPE_AUDIO_END 499 + +#define _CTYPE_OCTECT 800 +#define _CTYPE_RFC822 500 +#define _CTYPE_TNEF 600 +#define _CTYPE_APPLICATION 700 +#define _CTYPE_APPLICATION_APPLEFILE 701 +#define _CTYPE_UNKNOWN 0 + +#define _CTRANS_ENCODING_UNSPECIFIED -1 +#define _CTRANS_ENCODING_B64 100 +#define _CTRANS_ENCODING_7BIT 101 +#define _CTRANS_ENCODING_8BIT 102 +#define _CTRANS_ENCODING_QP 103 +#define _CTRANS_ENCODING_RAW 104 +#define _CTRANS_ENCODING_BINARY 105 +#define _CTRANS_ENCODING_UUENCODE 106 +#define _CTRANS_ENCODING_UNKNOWN 0 + +#define _CDISPOSITION_UNSPECIFIED -1 +#define _CDISPOSITION_INLINE 100 +#define _CDISPOSITION_ATTACHMENT 200 +#define _CDISPOSITION_FORMDATA 300 +#define _CDISPOSITION_UNKNOWN 0 + +#define _MIMEH_FOUND_FROM 100 #ifndef PATH_MAX -#define PATH_MAX 4096 +#define PATH_MAX 4096 * sizeof(char) #endif -#define _MIMEH_STRLEN_MAX 10230 +#define _MIMEH_STRLEN_MAX 10230 * sizeof(char) #define _MIMEH_FILENAMELEN_MAX PATH_MAX -#define _MIMEH_CONTENT_TYPE_MAX 1280 -#define _MIMEH_SUBJECTLEN_MAX 1280 -#define _MIMEH_CONTENT_DESCRIPTION_MAX 1280 -#define _MIMEH_CONTENT_TRANSFER_ENCODING_MAX 2560 -#define _MIMEH_CONTENT_DISPOSITION_MAX 2560 +#define _MIMEH_CONTENT_TYPE_MAX 1280 * sizeof(char) +#define _MIMEH_SUBJECTLEN_MAX 1280 * sizeof(char) +#define _MIMEH_CONTENT_DESCRIPTION_MAX 1280 * sizeof(char) +#define _MIMEH_CONTENT_TRANSFER_ENCODING_MAX 2560 * sizeof(char) +#define _MIMEH_CONTENT_DISPOSITION_MAX 2560 * sizeof(char) +#define _MIMEH_CHARSET_MAX 128 * sizeof(char) + #define _MIMEH_DEBUG_NORMAL 1 #define _MIMEH_DEBUG_PEDANTIC 10 #define _MIMEH_DEFECT_ARRAY_SIZE 100 -#define _MIMEH_CHARSET_MAX 128 + // Errors to throw back #define MIMEH_ERROR_DISK_FULL 128 @@ -95,25 +97,25 @@ #define MIMEH_DEFECT_MULTIPLE_NAMES 9 #define MIMEH_DEFECT_MULTIPLE_FILENAMES 10 - struct MIMEH_header_info { - char scratch[_MIMEH_STRLEN_MAX +1]; + FILE *header_file; + FILE *original_header_file; int content_type; - char content_type_string[ _MIMEH_CONTENT_TYPE_MAX +1 ]; - char content_description_string[ _MIMEH_CONTENT_DESCRIPTION_MAX +1 ]; - char boundary[_MIMEH_STRLEN_MAX +1]; + char content_type_string[ _MIMEH_CONTENT_TYPE_MAX + 1 * sizeof(char) ]; + char content_description_string[ _MIMEH_CONTENT_DESCRIPTION_MAX + 1 * sizeof(char) ]; + char boundary[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; int boundary_located; - char subject[_MIMEH_SUBJECTLEN_MAX +1]; - char filename[_MIMEH_FILENAMELEN_MAX +1]; - char name[_MIMEH_STRLEN_MAX +1]; + char subject[_MIMEH_SUBJECTLEN_MAX + 1 * sizeof(char)]; + char filename[_MIMEH_FILENAMELEN_MAX + 1 * sizeof(char)]; + char name[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; /** 20041217-1601:PLD: New header fields to keep **/ - char from[_MIMEH_STRLEN_MAX +1]; - char date[_MIMEH_STRLEN_MAX +1]; - char to[_MIMEH_STRLEN_MAX +1]; - char messageid[_MIMEH_STRLEN_MAX +1]; - char received[_MIMEH_STRLEN_MAX +1]; + char from[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; + char date[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; + char to[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; + char messageid[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; + char received[_MIMEH_STRLEN_MAX + 1 * sizeof(char)]; /** end of new fields **/ // Store multiple filenames @@ -122,14 +124,14 @@ struct MIMEH_header_info struct SS_object ss_names; int content_transfer_encoding; - char content_transfer_encoding_string[ _MIMEH_CONTENT_TRANSFER_ENCODING_MAX +1 ]; + char content_transfer_encoding_string[ _MIMEH_CONTENT_TRANSFER_ENCODING_MAX + 1 * sizeof(char) ]; int content_disposition; - char content_disposition_string[ _MIMEH_CONTENT_DISPOSITION_MAX +1 ]; + char content_disposition_string[ _MIMEH_CONTENT_DISPOSITION_MAX + 1 * sizeof(char) ]; //int charset; - char charset[ _MIMEH_CHARSET_MAX +1 ]; + char charset[ _MIMEH_CHARSET_MAX + 1 * sizeof(char) ]; int format; int file_has_uuencode; - char uudec_name[_MIMEH_FILENAMELEN_MAX +1]; // UUDecode name. This is a post-decode information field. + char uudec_name[_MIMEH_FILENAMELEN_MAX + 1 * sizeof(char)]; // UUDecode name. This is a post-decode information field. int current_recursion_level; // Malformed email reporting @@ -150,29 +152,24 @@ struct MIMEH_header_info int crcr_count; // 200811151149:PLD: Tally's the number of CRLF lines int lf_count; // 200811151149:PLD: Tally's the number of LF only lines + char *headerline_buffer; }; - #ifdef RIPMIME_V2XX struct MIMEH_header_node { struct MIMEH_header_info *header_list; struct MIMEH_header_node *next; }; - struct MIMEH_email_info { char mailpack_name[1024]; struct MIMEH_header_node *headers; }; #endif - - - - int MIMEH_version(void); -int MIMEH_init( void ); +void MIMEH_init( void ); int MIMEH_set_debug( int level ); int MIMEH_set_verbosity( int level ); int MIMEH_set_verbosity_contenttype( int level ); @@ -202,12 +199,12 @@ char *MIMEH_get_doubleCR_name( void ); int MIMEH_set_header_longsearch( int level ); int MIMEH_headers_clearcount( struct MIMEH_header_info *hinfo ); -int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f ); -int MIMEH_headers_get( struct MIMEH_header_info *hinfo, FFGET_FILE *f ); -int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers ); + +void MIMEH_headers_process( struct MIMEH_header_info *hinfo ); int MIMEH_headers_cleanup(); -int MIMEH_parse_headers( FFGET_FILE *f, struct MIMEH_header_info *hinfo ); + +int MIMEH_parse_headers( FILE* header_file, FILE* original_header_file, FFGET_FILE *f, struct MIMEH_header_info *hinfo, RIPMIME_output *unpack_metadata, int save_headers_original, int save_headers ); int MIMEH_display_info( struct MIMEH_header_info *hinfo ); @@ -215,11 +212,11 @@ int MIMEH_set_webform( int level ); int MIMEH_set_outputdir( char *dir ); int MIMEH_set_defect( struct MIMEH_header_info *hinfo, int defect ); -int MIMEH_dump_defects( struct MIMEH_header_info *hinfo ); +void MIMEH_dump_defects( struct MIMEH_header_info *hinfo ); int MIMEH_get_defect_count( struct MIMEH_header_info *hinfo ); int MIMEH_set_report_MIME( int level ); -int MIMEH_read_primary_headers( char *fname, struct MIMEH_header_info *hinfo ); + #endif diff --git a/ripOLE/Makefile b/ripOLE/Makefile index 6276e04..ff13ef0 100644 --- a/ripOLE/Makefile +++ b/ripOLE/Makefile @@ -1,8 +1,7 @@ -OBJS= ole.o olestream-unwrap.o bytedecoders.o logger.o pldstr.o bt-int.o +OBJS= ole.o olestream-unwrap.o bytedecoders.o logger.o pldstr.o bt-int.o mime_element.o CFLAGS=-Wall -g -O2 -I. - .c.o: $(CC) $(CFLAGS) $(DEFINES) -c $*.c diff --git a/ripOLE/logger.h b/ripOLE/logger.h index 703ce6f..94e3fe4 100644 --- a/ripOLE/logger.h +++ b/ripOLE/logger.h @@ -13,7 +13,7 @@ #define _LOGGER_NULL 5 #ifndef FL -#define FL __FILE__,__LINE__ +#define FL __FILE__,__LINE__,__func__ #endif int LOGGER_log( char *format, ...); diff --git a/ripOLE/mime_element.c b/ripOLE/mime_element.c new file mode 120000 index 0000000..058ccc0 --- /dev/null +++ b/ripOLE/mime_element.c @@ -0,0 +1 @@ +../mime_element.c \ No newline at end of file diff --git a/ripOLE/mime_element.h b/ripOLE/mime_element.h new file mode 120000 index 0000000..e1310b6 --- /dev/null +++ b/ripOLE/mime_element.h @@ -0,0 +1 @@ +../mime_element.h \ No newline at end of file diff --git a/ripOLE/ole.c b/ripOLE/ole.c index 05ede33..4b5613a 100644 --- a/ripOLE/ole.c +++ b/ripOLE/ole.c @@ -10,31 +10,32 @@ #include "pldstr.h" #include "bt-int.h" #include "bytedecoders.h" +#include "mime_element.h" #include "olestream-unwrap.h" #include "ole.h" /** Sector ID values (predefined) **/ -#define OLE_SECTORID_FREE -1 /** Unallocated sector **/ -#define OLE_SECTORID_ENDOFCHAIN -2 /** Sector marks the end of the a sector-ID chain **/ -#define OLE_SECTORID_SAT -3 /** Sector used by sector allocation Table **/ -#define OLE_SECTORID_MSAT -4 /** Sector used by master sector allocation Table **/ +#define OLE_SECTORID_FREE -1 /** Unallocated sector **/ +#define OLE_SECTORID_ENDOFCHAIN -2 /** Sector marks the end of the a sector-ID chain **/ +#define OLE_SECTORID_SAT -3 /** Sector used by sector allocation Table **/ +#define OLE_SECTORID_MSAT -4 /** Sector used by master sector allocation Table **/ // Main header accessors -#define header_id(x) ((x) +0) -#define header_clid(x) ((x) +0x08) -#define header_minor_version(x) ((x) +0x18) -#define header_dll_version(x) ((x) +0x1a) -#define header_byte_order(x) ((x) +0x1c) -#define header_sector_shift(x) ((x) +0x1e) -#define header_mini_sector_shift(x) ((x) +0x20) -#define header_fat_sector_count(x) ((x) +0x2c) +#define header_id(x) ((x) +0) +#define header_clid(x) ((x) +0x08) +#define header_minor_version(x) ((x) +0x18) +#define header_dll_version(x) ((x) +0x1a) +#define header_byte_order(x) ((x) +0x1c) +#define header_sector_shift(x) ((x) +0x1e) +#define header_mini_sector_shift(x) ((x) +0x20) +#define header_fat_sector_count(x) ((x) +0x2c) #define header_directory_stream_start_sector(x) ((x) +0x30) -#define header_mini_cutoff_size(x) ((x) +0x38) -#define header_mini_fat_start(x) ((x) +0x3c) -#define header_mini_fat_sector_count(x) ((x) +0x40) -#define header_dif_start_sector(x) ((x) +0x44) -#define header_dif_sector_count(x) ((x) +0x48) -#define header_fat_sectors(x) ((x) +0x4c) +#define header_mini_cutoff_size(x) ((x) +0x38) +#define header_mini_fat_start(x) ((x) +0x3c) +#define header_mini_fat_sector_count(x) ((x) +0x40) +#define header_dif_start_sector(x) ((x) +0x44) +#define header_dif_sector_count(x) ((x) +0x48) +#define header_fat_sectors(x) ((x) +0x4c) //Property Storage accessor macros #define pps_rawname(x) ((x) +0) @@ -42,35 +43,34 @@ #define pps_type(x) ((x) +0x42) #define pps_previouspps(x) ((x) +0x44) #define pps_nextpps(x) ((x) +0x48) -#define pps_directorypps(x) ((x) +0x4c) -#define pps_time1seconds(x) ((x) +0x64) +#define pps_directorypps(x) ((x) +0x4c) +#define pps_time1seconds(x) ((x) +0x64) #define pps_time1days(x) ((x) +0x68) -#define pps_time2seconds(x) ((x) +0x6c) +#define pps_time2seconds(x) ((x) +0x6c) #define pps_time2days(x) ((x) +0x70) #define pps_propertystart(x) ((x) +0x74) #define pps_sizeofproperty(x) ((x) +0x78) // Type lenghts #define LEN_BYTE 1 -#define LEN_USHORT 2 +#define LEN_USHORT 2 #define LEN_ULONG 4 // Directory types -#define STGTY_INVALID 0 -#define STGTY_STORAGE 1 -#define STGTY_STREAM 2 -#define STGTY_LOCKBYTES 3 -#define STGTY_PROPERTY 4 -#define STGTY_ROOT 5 +#define STGTY_INVALID 0 +#define STGTY_STORAGE 1 +#define STGTY_STREAM 2 +#define STGTY_LOCKBYTES 3 +#define STGTY_PROPERTY 4 +#define STGTY_ROOT 5 // Directory tag colours -#define DE_RED 0 -#define DE_BLACK 1 +#define DE_RED 0 +#define DE_BLACK 1 #define DOLE if (OLE_DNORMAL(ole->debug)) #define VOLE if (ole->verbose) - unsigned char OLE_id_v2[]={ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }; unsigned char OLE_id_v1[]={ 0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0xe0 }; @@ -96,7 +96,6 @@ int OLE_version( void ) return 0; } - /*-----------------------------------------------------------------\ Function Name : OLE_init Returns Type : int @@ -241,7 +240,7 @@ int OLE_set_quiet( struct OLE_object *ole, int level ) int OLE_set_debug( struct OLE_object *ole, int level ) { ole->debug = level; - if (ole->debug > 0) LOGGER_log("%s:%d:OLE_set_debug: Debug level set to %d",FL, ole->debug); + if (ole->debug > 0) LOGGER_log("%s:%d:%s: Debug level set to %d",FL,__func__, ole->debug); return OLE_OK; } @@ -323,7 +322,7 @@ int OLE_get_block( struct OLE_object *ole, int block_index, unsigned char *block { if (block_buffer == NULL) { - LOGGER_log("%s:%d:OLE_get_block:ERROR: Block buffer is NULL",FL); + LOGGER_log("%s:%d:%s:ERROR: Block buffer is NULL",FL,__func__); return -1; } @@ -337,52 +336,52 @@ int OLE_get_block( struct OLE_object *ole, int block_index, unsigned char *block bb = malloc(sizeof(unsigned char) *ole->header.sector_size); if (bb == NULL) { - LOGGER_log("%s:%d:OLE_get_block:ERROR: Cannot allocate %d bytes for OLE block",FL, ole->header.sector_size); + LOGGER_log("%s:%d:%s:ERROR: Cannot allocate %d bytes for OLE block",FL,__func__, ole->header.sector_size); return -1; } - DOLE LOGGER_log("%s:%d:OLE_get_block:DEBUG: BlockIndex=%d, Buffer=0x%x",FL, block_index, block_buffer); + DOLE LOGGER_log("%s:%d:%s:DEBUG: BlockIndex=%d, Buffer=0x%x",FL,__func__, block_index, block_buffer); //20051211-2343:PLD: offset = (block_index +1) << ole->header.sector_shift; offset = OLE_sectorpos(ole, block_index); - DOLE LOGGER_log("%s:%d:OLE_get_block:DEBUG: Read offset in file = 0x%x size to read= 0x%x",FL,offset,ole->header.sector_size); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Read offset in file = 0x%x size to read= 0x%x",FL,__func__,offset,ole->header.sector_size); fseek_result = fseek(ole->f, offset, SEEK_SET); if (fseek_result != 0) { if (bb != NULL) { free(bb); bb = NULL; } - LOGGER_log("%s:%d:OLE_get_block:ERROR: Seek failure (block=%d:%d)",FL, block_index,offset, strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: Seek failure (block=%d:%d)",FL,__func__, block_index,offset, strerror(errno)); return OLEER_GET_BLOCK_SEEK; } //read_count = fread(block_buffer, sizeof(unsigned char), ole->header.sector_size, ole->f); read_count = fread(bb, sizeof(unsigned char), ole->header.sector_size, ole->f); - DOLE LOGGER_log("%s:%d:OLE_get_block:DEBUG: Read %d byte of data",FL,read_count); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Read %d byte of data",FL,__func__,read_count); if (read_count != (int)ole->header.sector_size) { if (bb != NULL){ free(bb); bb = NULL; } - VOLE LOGGER_log("%s:%d:Mismatch in bytes read. Requested %d, got %d\n", FL, ole->header.sector_size, read_count); + VOLE LOGGER_log("%s:%d:Mismatch in bytes read. Requested %d, got %d\n", FL,__func__, ole->header.sector_size, read_count); return OLEER_GET_BLOCK_READ; } - DOLE LOGGER_log("%s:%d:OLE_get_block:DEBUG: Copying over memory read from file",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Copying over memory read from file",FL,__func__); memcpy(block_buffer, bb, ole->header.sector_size); - DOLE LOGGER_log("%s:%d:OLE_get_block:DEBUG: memory block copied to block_buffer",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: memory block copied to block_buffer",FL,__func__); /* We're now done with BB, dispose of it */ if (bb) { free(bb); bb = NULL; } - DOLE LOGGER_log("%s:%d:OLE_get_block:DEBUG: Disposed of temporary bb block",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Disposed of temporary bb block",FL,__func__); } else { - LOGGER_log("%s:%d:OLE_get_block:ERROR: OLE file is closed\n",FL); + LOGGER_log("%s:%d:%s:ERROR: OLE file is closed\n",FL,__func__); return -1; } - DOLE LOGGER_log("%s:%d:OLE_get_block:DEBUG: Done",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Done",FL,__func__); return OLE_OK; } @@ -827,7 +826,7 @@ int OLE_convert_directory( struct OLE_object *ole, unsigned char *buf, struct OL /** Size of this stream **/ DOLE LOGGER_log("%s:%d:OLE_directory_entry:DEBUG: stream size = 0x%x %x %x %x" - ,FL + ,FL,__func__ ,*(buf +0x78) ,*(buf +0x79) ,*(buf +0x7A) @@ -904,8 +903,8 @@ int OLE_load_FAT( struct OLE_object *ole ) unsigned int FAT_size; FAT_size = ole->header.fat_sector_count << ole->header.sector_shift; - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG:Allocating for %d sectors (%d bytes) \n" - ,FL,ole->header.fat_sector_count, FAT_size); + DOLE LOGGER_log("%s:%d:%s:DEBUG:Allocating for %d sectors (%d bytes) \n" + ,FL,__func__,ole->header.fat_sector_count, FAT_size); ole->FAT = malloc( FAT_size *sizeof(unsigned char)); ole->FAT_limit = ole->FAT +FAT_size; @@ -918,7 +917,7 @@ int OLE_load_FAT( struct OLE_object *ole ) if (sector_count > OLE_HEADER_FAT_SECTOR_COUNT_LIMIT) { sector_count = OLE_HEADER_FAT_SECTOR_COUNT_LIMIT; - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: sector count greater than limit; set to %d",FL, sector_count); + DOLE LOGGER_log("%s:%d:%s:DEBUG: sector count greater than limit; set to %d",FL,__func__, sector_count); } // Load in all our primary-FAT sectors from the OLE file @@ -926,7 +925,7 @@ int OLE_load_FAT( struct OLE_object *ole ) { int getblock_result = 0; - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: Loading sector %d",FL, i); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading sector %d",FL,__func__, i); getblock_result = OLE_get_block(ole, ole->header.FAT[i], fat_position); if (getblock_result != 0) { @@ -945,7 +944,7 @@ int OLE_load_FAT( struct OLE_object *ole ) fat_position += ole->header.sector_size; if (fat_position > ole->FAT_limit) { - LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: FAT boundary limit exceeded %p > %p", FL, fat_position, ole->FAT_limit); + LOGGER_log("%s:%d:%s:DEBUG: FAT boundary limit exceeded %p > %p", FL,__func__, fat_position, ole->FAT_limit); return -1; } } @@ -962,13 +961,13 @@ int OLE_load_FAT( struct OLE_object *ole ) unsigned char *fat_block_end; unsigned int current_sector = ole->header.dif_start_sector; - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: Allocating %d bytes to fat_block\n",FL, ole->header.sector_size); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Allocating %d bytes to fat_block\n",FL,__func__, ole->header.sector_size); fat_block = malloc( ole->header.sector_size ); if (fat_block == NULL) { - LOGGER_log("%s:%d:OLE_load_FAT:ERROR: Unable to allocate %d bytes\n", FL, ole->header.sector_size); + LOGGER_log("%s:%d:%s:ERROR: Unable to allocate %d bytes\n", FL,__func__, ole->header.sector_size); return -1; // exit(1); } @@ -986,7 +985,7 @@ int OLE_load_FAT( struct OLE_object *ole ) // contain the actual FAT data we're after (this is the double // dereference bit that twists your brain ) - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: Loading DIF sectors (count = %d)",FL,ole->header.dif_sector_count); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading DIF sectors (count = %d)",FL,__func__,ole->header.dif_sector_count); for (i = 0; i < ole->header.dif_sector_count; i++) { @@ -995,7 +994,7 @@ int OLE_load_FAT( struct OLE_object *ole ) int tick = 0; int getblock_result; - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: Reading DIF/XBAT index-data[%d] from sector 0x%x",FL,i,current_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Reading DIF/XBAT index-data[%d] from sector 0x%x",FL,__func__,i,current_sector); getblock_result = OLE_get_block(ole, current_sector, fat_block); if (getblock_result != OLE_OK) { @@ -1013,23 +1012,23 @@ int OLE_load_FAT( struct OLE_object *ole ) do { import_sector = get_int32( (char *) DIF ); - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: import sector = 0x%x",FL,import_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: import sector = 0x%x",FL,__func__,import_sector); if (import_sector >= 0) { if (fat_position +ole->header.sector_size <= ole->FAT_limit) { - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: Reading DIF/XBAT-data[%d] from sector 0x%x",FL,tick,import_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Reading DIF/XBAT-data[%d] from sector 0x%x",FL,__func__,tick,import_sector); getblock_result = OLE_get_block(ole, import_sector, fat_position); if (getblock_result != OLE_OK) { - LOGGER_log("%s:%d:OLE_load_FAT:ERROR: Not able to load block, import sector = 0x%x, fat position = 0x%x",FL, import_sector, fat_position); + LOGGER_log("%s:%d:%s:ERROR: Not able to load block, import sector = 0x%x, fat position = 0x%x",FL,__func__, import_sector, fat_position); if (fat_block) free(fat_block); return getblock_result; } fat_position += ole->header.sector_size; - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: FAT position = 0x%x (start = 0x%x, end = 0x%x)" - ,FL + DOLE LOGGER_log("%s:%d:%s:DEBUG: FAT position = 0x%x (start = 0x%x, end = 0x%x)" + ,FL,__func__ ,fat_position ,fat_block ,ole->FAT_limit @@ -1038,22 +1037,22 @@ int OLE_load_FAT( struct OLE_object *ole ) //if (fat_position +ole->header.sector_size > ole->FAT_limit) if (fat_position > ole->FAT_limit) { - DOLE LOGGER_log("%s:%d:OLE_load_FAT:ERROR: FAT memory boundary limit exceeded %p >= %p",FL,fat_position,ole->FAT_limit); + DOLE LOGGER_log("%s:%d:%s:ERROR: FAT memory boundary limit exceeded %p >= %p",FL,__func__,fat_position,ole->FAT_limit); if (fat_block) free(fat_block); return OLEER_MEMORY_OVERFLOW; } tick++; DIF += LEN_ULONG; } else { - LOGGER_log("%s:%d:OLE_load_FAT:ERROR: FAT memory boundary limit exceeded %p >= %p",FL,fat_position,ole->FAT_limit); + LOGGER_log("%s:%d:%s:ERROR: FAT memory boundary limit exceeded %p >= %p",FL,__func__,fat_position,ole->FAT_limit); if (fat_block) free(fat_block); return OLEER_MEMORY_OVERFLOW; } } else { - VOLE LOGGER_log("%s:%d:OLE_load_FAT:ERROR: sector request was negative (%d)",FL, import_sector); + VOLE LOGGER_log("%s:%d:%s:ERROR: sector request was negative (%d)",FL,__func__, import_sector); } - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: DIF = 0x%x",FL,DIF); + DOLE LOGGER_log("%s:%d:%s:DEBUG: DIF = 0x%x",FL,__func__,DIF); } while ((import_sector >= 0)&&(DIF < fat_block_end)); // Get the next sector of DIF/XBAT data ... @@ -1066,7 +1065,7 @@ int OLE_load_FAT( struct OLE_object *ole ) if ( i < ole->header.dif_sector_count -1 ) { current_sector = get_uint32((char *) fat_block_end ); - DOLE LOGGER_log("%s:%d:OLE_load_FAT:DEBUG: Next DIF/XBAT index sector located at 0x%x",FL,current_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Next DIF/XBAT index sector located at 0x%x",FL,__func__,current_sector); if (current_sector < 0) break; } } // For every DIF/XBAT sector we're supposed to read @@ -1079,8 +1078,6 @@ int OLE_load_FAT( struct OLE_object *ole ) return OLE_OK; } - - /*-----------------------------------------------------------------\ Function Name : OLE_follow_chain Returns Type : int @@ -1109,7 +1106,7 @@ int OLE_follow_chain( struct OLE_object *ole, int FAT_sector_start ) if (FAT_sector_start < 0) return 0; - DOLE LOGGER_log("%s:%d:OLE_follow_chain:DEBUG: Starting chain follow at sector %d",FL, FAT_sector_start ); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Starting chain follow at sector %d",FL,__func__, FAT_sector_start ); do { unsigned int next_sector; @@ -1117,7 +1114,7 @@ int OLE_follow_chain( struct OLE_object *ole, int FAT_sector_start ) next_sector_location = ole->FAT +(LEN_ULONG *current_sector); if (next_sector_location > (ole->FAT_limit -4)) { - DOLE LOGGER_log("%s:%d:OLE_follow_chain:DEBUG: ERROR: Next sector was outside of the limits of this file (%ld > %ld)",FL, next_sector_location, ole->FAT_limit); + DOLE LOGGER_log("%s:%d:%s:DEBUG: ERROR: Next sector was outside of the limits of this file (%ld > %ld)",FL,__func__, next_sector_location, ole->FAT_limit); break; } @@ -1126,13 +1123,13 @@ int OLE_follow_chain( struct OLE_object *ole, int FAT_sector_start ) if (BTI_add(&n, next_sector) != 0) { - DOLE LOGGER_log("%s:%d:OLE_follow_chain:DEBUG: Sector collision, terminating chain traversal",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Sector collision, terminating chain traversal",FL,__func__); chain_length=-1; break; } - DOLE LOGGER_log("%s:%d:OLE_follow_chain:DEBUG: 0x%0X:%d)->(0x%0X:%d)\n",FL, current_sector, current_sector, next_sector, next_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: 0x%0X:%d)->(0x%0X:%d)\n",FL,__func__, current_sector, current_sector, next_sector, next_sector); // 20040729-10H37 Added this to prevent endless loop which sometimes occurs at sector 0 @@ -1186,22 +1183,22 @@ int OLE_follow_minichain( struct OLE_object *ole, int miniFAT_sector_start ) int chain_length=0; int break_out = 0; - DOLE LOGGER_log("%s:%d:OLE_follow_minichain:DEBUG: Starting at sector %d",FL, miniFAT_sector_start); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Starting at sector %d",FL,__func__, miniFAT_sector_start); if (miniFAT_sector_start < 0) return 0; do { unsigned int next_sector; - DOLE LOGGER_log("%s:%d:OLE_follow_minichain:DEBUG: Requesting 4-byte value at '%d'",FL, ole->miniFAT +(LEN_ULONG *current_sector)); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Requesting 4-byte value at '%d'",FL,__func__, ole->miniFAT +(LEN_ULONG *current_sector)); if (ole->miniFAT +(LEN_ULONG *current_sector) > ole->miniFAT_limit) { - DOLE LOGGER_log("%s:%d:OLE_follow_minichain:DEBUG: Requested location is out of bounds\n",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Requested location is out of bounds\n",FL,__func__); return 0; } next_sector = get_uint32((char*) ole->miniFAT +(LEN_ULONG *current_sector)); - DOLE LOGGER_log("%s:%d:OLE_follow_minichain:DEBUG: Current Msector(0x%0X:%d)->next(0x%0X:%d)\n", FL, current_sector, current_sector, next_sector, next_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Current Msector(0x%0X:%d)->next(0x%0X:%d)\n", FL,__func__, current_sector, current_sector, next_sector, next_sector); /** Check for conditions that indicate we should stop traversing this chain **/ @@ -1223,10 +1220,10 @@ int OLE_follow_minichain( struct OLE_object *ole, int miniFAT_sector_start ) break_out=0; }; - DOLE LOGGER_log("%s:%d:OLE_follow_minichain:DEBUG: current sector = %d",FL,current_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: current sector = %d",FL,__func__,current_sector); } while ((break_out==0)&&(current_sector <= ole->last_sector )); - DOLE LOGGER_log("%s:%d:OLE_follow_minichain:DEBUG: Done. Chainlength=%d",FL, chain_length); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Done. Chainlength=%d",FL,__func__, chain_length); return chain_length; } @@ -1258,13 +1255,13 @@ unsigned char *OLE_load_minichain( struct OLE_object *ole, int miniFAT_sector_st unsigned char *buffer; unsigned char *bp; - DOLE LOGGER_log("%s:%d:OLE_load_minichain:DEBUG: Loading minichain starting at %d",FL, miniFAT_sector_start); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading minichain starting at %d",FL,__func__, miniFAT_sector_start); // Added this sanity checking 2003 Aug 28 if (miniFAT_sector_start < 0) return NULL; chain_length = OLE_follow_minichain( ole, miniFAT_sector_start ); - DOLE LOGGER_log("%s:%d:OLE_load_minichain:DEBUG: Found %d mini-sectors to load (%d bytes)\n",FL, chain_length, chain_length *ole->header.mini_sector_size); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Found %d mini-sectors to load (%d bytes)\n",FL,__func__, chain_length, chain_length *ole->header.mini_sector_size); // 20040911-21H59 // If our chain is 0 length, then there's nothing to return @@ -1276,7 +1273,7 @@ unsigned char *OLE_load_minichain( struct OLE_object *ole, int miniFAT_sector_st do { unsigned int next_sector; - DOLE LOGGER_log("%s:%d:OLE_load_minichain:DEBUG: Loading sector %d",FL, current_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading sector %d",FL,__func__, current_sector); OLE_get_miniblock( ole, current_sector, bp ); bp += ole->header.mini_sector_size; @@ -1284,10 +1281,10 @@ unsigned char *OLE_load_minichain( struct OLE_object *ole, int miniFAT_sector_st current_sector = next_sector; } while ((current_sector != OLE_SECTORID_ENDOFCHAIN)&&(current_sector >= 0)&&(current_sector <= ole->last_sector)); } else { - LOGGER_log("%s:%d:OLE_get_miniblock:ERROR: Failed to allocate enough memory for miniChain",FL); + LOGGER_log("%s:%d:OLE_get_miniblock:ERROR: Failed to allocate enough memory for miniChain",FL,__func__); } - DOLE LOGGER_log("%s:%d:OLE_load_minichain:DEBUG: Done. buffer=%p",FL, buffer); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Done. buffer=%p",FL,__func__, buffer); return buffer; } @@ -1324,10 +1321,10 @@ unsigned char *OLE_load_chain( struct OLE_object *ole, int FAT_sector_start ) if (FAT_sector_start < 0) return NULL; - DOLE LOGGER_log("%s:%d:OLE_load_chain:DEBUG: Loading chain, starting at sector %d",FL,FAT_sector_start); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading chain, starting at sector %d",FL,__func__,FAT_sector_start); chain_length = OLE_follow_chain( ole, FAT_sector_start ); - DOLE LOGGER_log("%s:%d:OLE_load_chain:DEBUG: %d sectors need to be loaded",FL,chain_length); + DOLE LOGGER_log("%s:%d:%s:DEBUG: %d sectors need to be loaded",FL,__func__,chain_length); if (chain_length > 0) { @@ -1337,7 +1334,7 @@ unsigned char *OLE_load_chain( struct OLE_object *ole, int FAT_sector_start ) bp = buffer = malloc( offset *sizeof(unsigned char)); if (buffer == NULL) { - LOGGER_log("%s:%d:OLE_load_chain:ERROR: Cannot allocate %d bytes for OLE chain",FL,offset); + LOGGER_log("%s:%d:%s:ERROR: Cannot allocate %d bytes for OLE chain",FL,__func__,offset); return NULL; } @@ -1350,7 +1347,7 @@ unsigned char *OLE_load_chain( struct OLE_object *ole, int FAT_sector_start ) do { int next_sector; - DOLE LOGGER_log("%s:%d:OLE_load_chain:DEBUG: Loading sector[%d] %d",FL, tick, current_sector ); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading sector[%d] %d",FL,__func__, tick, current_sector ); ole->error = OLE_get_block( ole, current_sector, bp ); if (ole->error != OLE_OK) @@ -1362,7 +1359,7 @@ unsigned char *OLE_load_chain( struct OLE_object *ole, int FAT_sector_start ) bp += ole->header.sector_size; if (bp > bp_limit) { if (buffer != NULL) { free(buffer); bp = buffer = NULL; } - VOLE LOGGER_log("%s:%d:OLE_load_chain:ERROR: Load-chain went over memory boundary",FL); + VOLE LOGGER_log("%s:%d:%s:ERROR: Load-chain went over memory boundary",FL,__func__); return NULL; }; @@ -1372,11 +1369,39 @@ unsigned char *OLE_load_chain( struct OLE_object *ole, int FAT_sector_start ) } while ((current_sector >= 0)&&(current_sector <= ole->last_sector)); } } - DOLE LOGGER_log("%s:%d:OLE_load_chain:DEBUG: Done loading chain",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Done loading chain",FL,__func__); return buffer; } +/*-----------------------------------------------------------------\ + Function Name : OLE_input_file_data_ini + Returns Type : int + ----Parameter List + 1. struct OLE_object *ole, + ------------------ + Exit Codes : + Side Effects : + -------------------------------------------------------------------- +Comments: + +-------------------------------------------------------------------- +Changes: +\------------------------------------------------------------------*/ +int OLE_input_file_data_ini( struct OLE_object *ole ) +{ + fseek(ole->f, 0L, SEEK_END); + ole->file_size = ftell(ole->f); + fseek(ole->f, 0L, SEEK_SET); + if (ole->file_size < OLE_HEADER_BLOCK_SIZE) { + fclose(ole->f); + ole->f = NULL; + return OLEER_NOT_OLE_FILE; + } + ole->last_sector = -1; + return OLE_OK; +} + /*-----------------------------------------------------------------\ Function Name : OLE_open_file Returns Type : int @@ -1395,43 +1420,23 @@ unsigned char *OLE_load_chain( struct OLE_object *ole, int FAT_sector_start ) can use this in the sanity checking to see if the requested sectors are outside of the possible valid filesize range. - +20220425-mkgrgis: rewrite file size to seek, exclude FS operations \------------------------------------------------------------------*/ int OLE_open_file( struct OLE_object *ole, char *fullpath ) { - struct stat st; - int stat_result; - FILE *f; - - stat_result = stat(fullpath, &st); - if (stat_result != 0) { - DOLE LOGGER_log("%s:%d:OLE_open_file:ERROR: Cannot locate file '%s' for opening (%s)",FL, fullpath, strerror(errno)); - return OLEER_BAD_INPUT_FILE; - } - - DOLE LOGGER_log("%s:%d:OLE_open_file:DEBUG: File size of %s = %ld",FL, fullpath, st.st_size); - if ((stat_result == 0) && (st.st_size < 512)) return OLEER_NOT_OLE_FILE; - - ole->file_size = st.st_size; - - f = fopen(fullpath,"r"); - if (f == NULL) + ole->f = fopen(fullpath,"r"); + if (ole->f == NULL) { - ole->f = NULL; if (ole->quiet == 0) { - LOGGER_log("%s:%d:OLE_open_file:ERROR:Cannot open %s for reading (%s)\n",FL,fullpath, strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR:Cannot open %s for reading (%s)\n",FL,__func__,fullpath, strerror(errno)); } return -1; - } else { - ole->f = f; - ole->file_size = st.st_size; - ole->last_sector = -1; } - return OLE_OK; + else + return OLE_OK; } - /*-----------------------------------------------------------------\ Function Name : OLE_open_directory Returns Type : int @@ -1448,14 +1453,14 @@ int OLE_open_file( struct OLE_object *ole, char *fullpath ) Changes: \------------------------------------------------------------------*/ -int OLE_open_directory( struct OLE_object *ole, char *directory ) +int OLE_open_directory( struct OLE_object *ole, RIPMIME_output *unpack_metadata ) { int result=0; - result = mkdir( directory, S_IRWXU ); + result = mkdir( unpack_metadata->dir, S_IRWXU ); if ((result != 0)&&(errno != EEXIST)) { - LOGGER_log("%s:%d:OLE_open_directory:ERROR: %s",FL,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: %s",FL,__func__,strerror(errno)); } else result = OLE_OK; return result; @@ -1505,49 +1510,26 @@ int OLE_set_filename_report_fn( struct OLE_object *ole, int (*ptr_to_fn)(char *) Changes: \------------------------------------------------------------------*/ -int OLE_store_stream( struct OLE_object *ole, char *stream_name, char *directory, char *stream, size_t stream_size ) +int OLE_store_stream( struct OLE_object *ole, char *stream_name, RIPMIME_output *unpack_metadata, char *stream, size_t stream_size ) { - char *full_path = NULL; + MIME_element* cur_mime = MIME_element_add (NULL, unpack_metadata, stream_name, "OLE", "OLE", "OLE", 0, 1, 0, __func__); - full_path = PLD_dprintf("%s/%s", directory, stream_name); - if (full_path == NULL) + size_t written_bytes = fwrite( stream, 1, stream_size, cur_mime->f ); + if (written_bytes != stream_size) { - LOGGER_log("%s:%d:OLE_store_stream:ERROR: Cannot compose full filename string from '%s' and '%s'", FL, directory, stream_name); - return -1; - } else { - FILE *f; - - f = fopen(full_path,"w"); - if (f == NULL) - { - LOGGER_log("%s:%d:OLE_store_stream:ERROR: Cannot open %s for writing (%s)",FL, full_path, strerror(errno)); - if (full_path) free(full_path); - return -1; - } else { - size_t written_bytes; - - written_bytes = fwrite( stream, 1, stream_size, f ); - if (written_bytes != stream_size) - { - LOGGER_log("%s:%d:OLE_store_stream:WARNING: Only wrote %d of %d bytes to file %s",FL,written_bytes,stream_size,full_path); - } - fclose(f); - - if ((OLE_VNORMAL(ole->verbose))&&(ole->filename_report_fn != NULL)) - { - ole->filename_report_fn( stream_name ); - } - } // if file is valid - } // if full_path is valid - - if (full_path) free(full_path); + LOGGER_log("%s:%d:%s:WARNING: Only wrote %d of %d bytes to file %s",FL,__func__,written_bytes,stream_size,cur_mime->fullpath); + } + MIME_element_deactivate (cur_mime, unpack_metadata); + if ((OLE_VNORMAL(ole->verbose))&&(ole->filename_report_fn != NULL)) + { + ole->filename_report_fn( stream_name ); + } return OLE_OK; } - /*-----------------------------------------------------------------\ - Function Name : OLE_decode_file_done + Function Name : OLE_decode_done Returns Type : int ----Parameter List 1. struct OLE_object *ole , @@ -1561,16 +1543,15 @@ int OLE_store_stream( struct OLE_object *ole, char *stream_name, char *directory Changes: \------------------------------------------------------------------*/ -int OLE_decode_file_done( struct OLE_object *ole ) +void OLE_decode_done( struct OLE_object *ole ) { - if (ole->f) fclose(ole->f); /** Why weren't these active? (they were commented out ) **/ + DOLE LOGGER_log("%s:%d:%s:DEBUG: OLE FAT",FL,__func__); if (ole->FAT) free(ole->FAT); if (ole->miniFAT) free(ole->miniFAT); + DOLE LOGGER_log("%s:%d:%s:DEBUG: OLE streams",FL,__func__); if (ole->ministream) free(ole->ministream); if (ole->properties) free(ole->properties); - - return 0; } @@ -1592,57 +1573,12 @@ int OLE_decode_file_done( struct OLE_object *ole ) \------------------------------------------------------------------*/ int OLE_terminate_and_return( struct OLE_object *ole, int result ) { - OLE_decode_file_done(ole); + OLE_decode_done(ole); + DOLE LOGGER_log("%s:%d:%s:DEBUG: ole->f close",FL,__func__); + if (ole->f) fclose(ole->f); return result; } - -#ifdef RIPOLE_WALK_TREE -int OLE_walk_tree( struct OLE_object *ole, char *fname, char *decode_path, int depth ) -{ - - /** Sanity check **/ - - if (depth > 100) return 0; - if (ole->total_file_count > 10000) return 0; - if (element_type < 0) return 0; - - switch (element_type) { - - case STGTY_ROOT: - /** ROOT DIRECTORY ENTRY **/ - /** ROOT DIRECTORY ENTRY **/ - /** ROOT DIRECTORY ENTRY **/ - DOLE LOGGER_log("%s:%d:OLE_walk_tree:DEBUG: Loading ministream/SmallBlockArray",FL); - ole->ministream = OLE_load_chain( ole, adir->start_sector ); - if (ole->ministream == NULL) return OLEER_MINISTREAM_READ_FAIL; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: ministream done",FL); - } - - - - - - - -} else if (adir->element_type == STGTY_STORAGE) { - /** STORAGE ELEMENT **/ - /** STORAGE ELEMENT **/ - /** STORAGE ELEMENT **/ - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Item is directory, start child is at index %d\n",FL,i); - ole->ministream = OLE_load_chain( ole, adir->start_sector ); - if (ole->ministream == NULL) return OLEER_MINISTREAM_READ_FAIL; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: DIRECTORY ministream done",FL); - - -} -#endif - - - - - - /*-----------------------------------------------------------------\ Date Code: : 20081101-020137 Function Name : OLE_decode_stream @@ -1661,7 +1597,7 @@ Side Effects : Changes: \------------------------------------------------------------------*/ -int OLE_decode_stream( struct OLE_object *ole, struct OLE_directory_entry *adir, char *decode_path ) +int OLE_decode_stream( struct OLE_object *ole, struct OLE_directory_entry *adir, RIPMIME_output *unpack_metadata ) { unsigned char *stream_data; struct OLEUNWRAP_object oleuw; @@ -1672,52 +1608,49 @@ int OLE_decode_stream( struct OLE_object *ole, struct OLE_directory_entry *adir memset(element_name, '\0', 64); OLE_dbstosbs( adir->element_name, adir->element_name_byte_count, element_name, 64 ); - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Decoding stream '%s'",FL, element_name); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Decoding stream '%s'",FL,__func__, element_name); - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Initializing stream unwrapper",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Initializing stream unwrapper",FL,__func__); OLEUNWRAP_init(&oleuw); OLEUNWRAP_set_debug(&oleuw,ole->debug); OLEUNWRAP_set_verbose(&oleuw,ole->verbose); OLEUNWRAP_set_filename_report_fn(&oleuw, ole->filename_report_fn); OLEUNWRAP_set_save_unknown_streams(&oleuw, ole->save_unknown_streams); - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Unwrap engine set.",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Unwrap engine set.",FL,__func__); if (adir->stream_size >= ole->header.mini_cutoff_size) { /** Standard size sector stored stream **/ /** Standard size sector stored stream **/ /** Standard size sector stored stream **/ - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Loading normal sized chain starting at sector %d",FL, adir->start_sector); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading normal sized chain starting at sector %d",FL,__func__, adir->start_sector); stream_data = OLE_load_chain( ole, (int)adir->start_sector ); if (stream_data == NULL) { - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Terminating from stream data being NULL ",FL); - //OLE_decode_file_done(ole); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Terminating from stream data being NULL ",FL,__func__); + //OLE_decode_done(ole); return OLEER_MINISTREAM_STREAM_READ_FAIL; } - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Normal decode START. element name ='%s' stream size = '%ld'",FL, element_name, adir->stream_size); - decode_result = OLEUNWRAP_decodestream( &oleuw, element_name, (char *)stream_data, adir->stream_size, decode_path ); - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Normal decode done.",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Normal decode START. element name ='%s' stream size = '%ld'",FL,__func__, element_name, adir->stream_size); + decode_result = OLEUNWRAP_decodestream( &oleuw, element_name, (char *)stream_data, adir->stream_size, unpack_metadata ); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Normal decode done.",FL,__func__); } else { - - /** Minichain/Minisector stored stream **/ /** Minichain/Minisector stored stream **/ - /** Minichain/Minisector stored stream **/ - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Minichain loader, starting at sector %d" - ,FL + DOLE LOGGER_log("%s:%d:%s:DEBUG: Minichain loader, starting at sector %d" + ,FL,__func__ ,adir->start_sector ); stream_data = OLE_load_minichain( ole, adir->start_sector ); if (stream_data == NULL) { - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Ministream was non-existant, terminating",FL); - //OLE_decode_file_done(ole); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Ministream was non-existant, terminating",FL,__func__); + //OLE_decode_done(ole); return OLEER_NORMALSTREAM_STREAM_READ_FAIL; } - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Mini decode START.",FL); - decode_result = OLEUNWRAP_decodestream( &oleuw, element_name, (char *)stream_data, adir->stream_size, decode_path ); - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Mini decode done.",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Mini decode START.",FL,__func__); + decode_result = OLEUNWRAP_decodestream( &oleuw, element_name, (char *)stream_data, adir->stream_size, unpack_metadata ); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Mini decode done.",FL,__func__); } if ((stream_data != NULL)&&(decode_result == OLEUW_STREAM_NOT_DECODED)&&(ole->save_unknown_streams)) @@ -1727,8 +1660,8 @@ int OLE_decode_stream( struct OLE_object *ole, struct OLE_directory_entry *adir lfname = PLD_dprintf("ole-stream.%d",adir->start_sector); if (lfname != NULL) { - DOLE LOGGER_log("%s:%d:OLE_decode_stream:DEBUG: Saving stream to %s",FL,lfname); - OLE_store_stream( ole, lfname, decode_path, (char *) stream_data, adir->stream_size ); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Saving stream to %s",FL,__func__,lfname); + OLE_store_stream( ole, lfname, unpack_metadata, (char *) stream_data, adir->stream_size ); free(lfname); } } // If we needed to save an unknown stream @@ -1740,53 +1673,26 @@ int OLE_decode_stream( struct OLE_object *ole, struct OLE_directory_entry *adir return result; } -/*-----------------------------------------------------------------\ - Function Name : OLE_decode_file - Returns Type : int - ----Parameter List - 1. char *fname, - 2. char *decode_path , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int OLE_decode_file( struct OLE_object *ole, char *fname, char *decode_path ) +int OLE_decode( struct OLE_object *ole, RIPMIME_output *unpack_metadata ) { unsigned char *current_property, *property_limit; int result = 0; int i; - // Reject any bad paramters. - if (ole == NULL) return OLEER_DECODE_NULL_OBJECT; - if (fname == NULL) return OLEER_DECODE_NULL_FILENAME; - if (decode_path == NULL) return OLEER_DECODE_NULL_PATH; - - // We need to gain access to the OLE2 data file, without - // this pretty much everything is pointless. - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: opening %s", FL, fname ); - result = OLE_open_file( ole, fname ); - if (result != 0) return result; - // Try create the output directory which we're using // to write the decoded files out to. - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: opening output directory %s", FL, decode_path); - result = OLE_open_directory( ole, decode_path ); + DOLE LOGGER_log("%s:%d:%s:DEBUG: opening output directory %s", FL,__func__, unpack_metadata->dir); + result = OLE_open_directory( ole, unpack_metadata); if (result != 0) return result; // In order to successfully decode an OLE2 stream, we have to read // and understand the first 512 bytes of the file, this is the // OLE2 header. - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Getting main header", FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Getting main header", FL,__func__); result = OLE_get_header( ole ); if (result != 0) return result; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Converting main header", FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Converting main header", FL,__func__); result = OLE_convert_header( ole ); if (result != 0) return result; @@ -1795,15 +1701,15 @@ int OLE_decode_file( struct OLE_object *ole, char *fname, char *decode_path ) DOLE OLE_print_header( ole ); - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Loading FAT", FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading FAT", FL,__func__); result = OLE_load_FAT( ole ); if (result != 0) return result; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Loading miniFAT chain", FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading miniFAT chain", FL,__func__); ole->miniFAT = OLE_load_chain( ole, ole->header.mini_fat_start ); if (ole->miniFAT == NULL) return OLEER_MINIFAT_READ_FAIL; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Loading Directory stream chain", FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading Directory stream chain", FL,__func__); ole->properties = OLE_load_chain( ole, ole->header.directory_stream_start_sector ); if (ole->properties == NULL) return OLEER_PROPERTIES_READ_FAIL; @@ -1823,65 +1729,43 @@ int OLE_decode_file( struct OLE_object *ole, char *fname, char *decode_path ) property_value = get_uint8((char *)current_property); if (property_value < 1) break; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG:--------- DIRECTORY INDEX: %d",FL,i); + DOLE LOGGER_log("%s:%d:%s:DEBUG:--------- DIRECTORY INDEX: %d",FL,__func__,i); OLE_convert_directory( ole, current_property, adir ); DOLE { - LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Printing directory details...",FL); + LOGGER_log("%s:%d:%s:DEBUG: Printing directory details...",FL,__func__); OLE_print_directory( ole, adir); - LOGGER_log("%s:%d:OLE_decode_file:DEBUG: End of directory details",FL); + LOGGER_log("%s:%d:%s:DEBUG: End of directory details",FL,__func__); } if (adir->element_colour > 1) break; if ((adir->element_type == STGTY_INVALID)||(adir->element_type > STGTY_ROOT)) { - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: breaking out due to element type %d",FL, adir->element_type); + DOLE LOGGER_log("%s:%d:%s:DEBUG: breaking out due to element type %d",FL,__func__, adir->element_type); break; - } else if (adir->element_type == STGTY_ROOT){ /** ROOT DIRECTORY ENTRY **/ - /** ROOT DIRECTORY ENTRY **/ - /** ROOT DIRECTORY ENTRY **/ - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Loading ministream/SmallBlockArray",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Loading ministream/SmallBlockArray",FL,__func__); ole->ministream = OLE_load_chain( ole, adir->start_sector ); if (ole->ministream == NULL) return OLEER_MINISTREAM_READ_FAIL; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: ministream done",FL); - - - - - - - + DOLE LOGGER_log("%s:%d:%s:DEBUG: ministream done",FL,__func__); } else if (adir->element_type == STGTY_STORAGE) { /** STORAGE ELEMENT **/ - /** STORAGE ELEMENT **/ - /** STORAGE ELEMENT **/ - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Item is directory, start child is at index %d\n",FL,i); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Item is directory, start child is at index %d\n",FL,__func__,i); ole->ministream = OLE_load_chain( ole, adir->start_sector ); if (ole->ministream == NULL) return OLEER_MINISTREAM_READ_FAIL; - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: DIRECTORY ministream done",FL); - - - - + DOLE LOGGER_log("%s:%d:%s:DEBUG: DIRECTORY ministream done",FL,__func__); } else if (adir->element_type == STGTY_STREAM) { /** STREAM ELEMENT **/ - /** STREAM ELEMENT **/ - /** STREAM ELEMENT **/ - OLE_decode_stream( ole, adir, decode_path ); - - - + OLE_decode_stream( ole, adir, unpack_metadata ); } else { /** If the element isn't of the above types then it's possibly ** an empty element or just one used for the MSAT/SAT ** either way we just step over it and carry on **/ - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Element type %d does not need to be handled",FL,adir->element_type); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Element type %d does not need to be handled",FL,__func__,adir->element_type); } - // Jump to the next property record, which // is always 128 bytes ahead. current_property += 128; @@ -1889,16 +1773,62 @@ int OLE_decode_file( struct OLE_object *ole, char *fname, char *decode_path ) } // While there are still more directory entries to read in. - DOLE LOGGER_log("%s:%d:OLE_decode_file:DEBUG: Finished",FL); + DOLE LOGGER_log("%s:%d:%s:DEBUG: Finished",FL,__func__); - /* - //if (ole->f) fclose(ole->f); - fclose(ole->f); - if (ole->FAT) free(ole->FAT); - if (ole->miniFAT) free(ole->miniFAT); - if (ole->ministream) free(ole->ministream); - if (ole->properties) free(ole->properties); + /* OLE_decode_done(ole); */ - return OLE_OK; } + +/*-----------------------------------------------------------------\ + Function Name : OLE_decode_diskfile + Returns Type : int + ----Parameter List + 1. char *fname, + 2. char *decode_path , + ------------------ + Exit Codes : + Side Effects : + -------------------------------------------------------------------- +Comments: + +-------------------------------------------------------------------- +Changes: + +\------------------------------------------------------------------*/ +int OLE_decode_diskfile( struct OLE_object *ole, char *fname, RIPMIME_output *unpack_metadata ) +{ + int result = 0; + + // Reject any bad paramters. + if (ole == NULL) return OLEER_DECODE_NULL_OBJECT; + if (fname == NULL) return OLEER_DECODE_NULL_FILENAME; + if (unpack_metadata == NULL || unpack_metadata->dir == NULL) return OLEER_DECODE_NULL_PATH; + + // We need to gain access to the OLE2 data file, without + // this pretty much everything is pointless. + DOLE LOGGER_log("%s:%d:%s:DEBUG: opening %s", FL,__func__, fname ); + result = OLE_open_file( ole, fname ); + if (result != 0) return result; + + result = OLE_input_file_data_ini(ole); + if (result != 0) return result; + return OLE_decode( ole, unpack_metadata ); +} + +int OLE_decode_file( struct OLE_object *ole, FILE *f, RIPMIME_output *unpack_metadata ) +{ + int result = 0; + + DOLE LOGGER_log("%s:%d:%s:DEBUG: opening %s", FL,__func__); + // Reject any bad paramters. + if (ole == NULL) return OLEER_DECODE_NULL_OBJECT; + if (f == NULL) return OLEER_DECODE_NULL_FILENAME; + if (unpack_metadata == NULL || unpack_metadata->dir == NULL) return OLEER_DECODE_NULL_PATH; + + ole->f = f; + + result = OLE_input_file_data_ini(ole); + if (result != 0) return result; + return OLE_decode( ole, unpack_metadata ); +} diff --git a/ripOLE/ole.h b/ripOLE/ole.h index f4d1cca..3f44e88 100644 --- a/ripOLE/ole.h +++ b/ripOLE/ole.h @@ -10,26 +10,26 @@ #define OLEER_NOT_OLE_FILE 102 #define OLEER_INSANE_OLE_FILE 103 -#define OLEER_DECODE_NULL_OBJECT 10 +#define OLEER_DECODE_NULL_OBJECT 10 #define OLEER_DECODE_NULL_FILENAME 11 #define OLEER_DECODE_NULL_PATH 12 #define OLEER_MINIFAT_READ_FAIL 30 #define OLEER_PROPERTIES_READ_FAIL 31 #define OLEER_MINISTREAM_READ_FAIL 32 -#define OLEER_MINISTREAM_STREAM_READ_FAIL 33 -#define OLEER_NORMALSTREAM_STREAM_READ_FAIL 34 +#define OLEER_MINISTREAM_STREAM_READ_FAIL 33 +#define OLEER_NORMALSTREAM_STREAM_READ_FAIL 34 -#define OLEER_GET_BLOCK_SEEK 41 -#define OLEER_GET_BLOCK_READ 42 +#define OLEER_GET_BLOCK_SEEK 41 +#define OLEER_GET_BLOCK_READ 42 -#define OLEER_MEMORY_OVERFLOW 50 +#define OLEER_MEMORY_OVERFLOW 50 -#define OLE_VERBOSE_NORMAL 1 -#define OLE_VERBOSE_FATREAD 2 -#define OLE_VERBOSE_DIRREAD 4 -#define OLE_VERBOSE_STREAMREAD 8 -#define OLE_VERBOSE_STREAMDECODE 16 +#define OLE_VERBOSE_NORMAL 1 +#define OLE_VERBOSE_FATREAD 2 +#define OLE_VERBOSE_DIRREAD 4 +#define OLE_VERBOSE_STREAMREAD 8 +#define OLE_VERBOSE_STREAMDECODE 16 #define OLE_VNORMAL(x) ((x) && OLE_VERBOSE_NORMAL == OLE_VERBOSE_NORMAL ) @@ -39,7 +39,6 @@ #define OLE_DNORMAL(x) ((x) && OLE_DEBUG_NORMAL == OLE_DEBUG_NORMAL) #define OLE_DPEDANTIC(x) ((x) && OLE_DEBUG_PEDANTIC == OLE_DEBUG_PEDANTIC) - #define OLE_HEADER_FAT_SECTOR_COUNT_LIMIT 109 struct OLE_header { unsigned int minor_version; @@ -59,9 +58,9 @@ struct OLE_header { unsigned int FAT[OLE_HEADER_FAT_SECTOR_COUNT_LIMIT]; }; -#define OLE_DIRECTORY_ELEMENT_NAME_SIZE 64 -#define OLE_DIRECTORY_CLASS_SIZE 16 -#define OLE_DIRECTORY_TIMESTAMPS_SIZE 16 +#define OLE_DIRECTORY_ELEMENT_NAME_SIZE 64 +#define OLE_DIRECTORY_CLASS_SIZE 16 +#define OLE_DIRECTORY_TIMESTAMPS_SIZE 16 struct OLE_directory_entry { char element_name[OLE_DIRECTORY_ELEMENT_NAME_SIZE]; int element_name_byte_count; @@ -80,11 +79,9 @@ struct OLE_directory_entry { unsigned int stream_size; }; - #define OLE_HEADER_BLOCK_SIZE 512 struct OLE_object { - int error; size_t file_size; int last_sector; @@ -116,11 +113,8 @@ struct OLE_object { int decode_normal_streams; int (*filename_report_fn)(char *); - }; - - // Prototypes int OLE_version( void ); @@ -147,9 +141,9 @@ int OLE_follow_minichain( struct OLE_object *ole, int miniFAT_sector_start ); unsigned char *OLE_load_minichain( struct OLE_object *ole, int miniFAT_sector_start ); unsigned char *OLE_load_chain( struct OLE_object *ole, int FAT_sector_start ); int OLE_open_file( struct OLE_object *ole, char *fullpath ); -int OLE_decode_file( struct OLE_object *ole, char *fname, char *decode_path ); -int OLE_decode_file_done( struct OLE_object *ole ); - +int OLE_decode_diskfile( struct OLE_object *ole, char *fname, RIPMIME_output *unpack_metadata ); +int OLE_decode_file( struct OLE_object *ole, FILE *f, RIPMIME_output *unpack_metadata ); +void OLE_decode_done( struct OLE_object *ole ); // Our callbacks. int OLE_set_filename_report_fn( struct OLE_object *ole, int (*ptr_to_fn)(char *) ); diff --git a/ripOLE/olestream-unwrap.c b/ripOLE/olestream-unwrap.c index 0b43663..5b5b2b7 100644 --- a/ripOLE/olestream-unwrap.c +++ b/ripOLE/olestream-unwrap.c @@ -8,6 +8,7 @@ #include "pldstr.h" #include "bytedecoders.h" +#include "mime_element.h" #include "olestream-unwrap.h" #define DUW if (oleuw->debug) @@ -145,48 +146,29 @@ int OLEUNWRAP_set_save_unknown_streams( struct OLEUNWRAP_object *oleuw, int leve Changes: \------------------------------------------------------------------*/ -int OLEUNWRAP_save_stream( struct OLEUNWRAP_object *oleuw, char *fname, char *decode_path, char *stream, size_t bytes ) +int OLEUNWRAP_save_stream( struct OLEUNWRAP_object *oleuw, char *fname, RIPMIME_output *unpack_metadata, char *stream, size_t bytes ) { - char *full_name; - FILE *f; int result = 0; + MIME_element* cur_mime = NULL; + size_t write_count; - DUW LOGGER_log("%s:%d:OLEUNWRAP_save_stream:DEBUG: fname=%s, decodepath=%s, size=%ld" - ,FL + DUW LOGGER_log("%s:%d:%s:DEBUG: fname=%s, decodepath=%s, size=%ld" + ,FL,__func__ ,fname - ,decode_path + ,unpack_metadata->dir ,bytes ); - full_name = PLD_dprintf("%s/%s", decode_path, fname ); - if (full_name == NULL) - { - LOGGER_log("%s:%d:OLEUNWRAP_save_stream:ERROR: Unable to create filename string from '%s' and '%s'",FL,fname,decode_path); - return -1; - } + cur_mime = MIME_element_add (NULL, unpack_metadata, fname, "OLE", "OLE", "OLE", 0, 1, 0, __func__); - f = fopen(full_name,"w"); - if (f != NULL) + write_count = fwrite( stream, 1, bytes, cur_mime->f ); + if (write_count != bytes) { - size_t write_count; - - write_count = fwrite( stream, 1, bytes, f ); - if (write_count != bytes) - { - LOGGER_log("%s:%d:OLEUNWRAP_save_stream:WARNING: Only wrote %d of %d bytes to file %s\n",FL, write_count, bytes, full_name ); - } - - fclose(f); - - - } else { - LOGGER_log("%s:%d:OLEUNWRAP_save_stream:ERROR: Unable to open %s for writing (%s)\n",FL,full_name, strerror(errno)); - result = -1; + LOGGER_log("%s:%d:%s:WARNING: Only wrote %d of %d bytes to file %s\n",FL,__func__, write_count, bytes, cur_mime->fullpath ); } - if (full_name) free(full_name); - - DUW LOGGER_log("%s:%d:OLEUNWRAP_save_stream:DEBUG: Done saving '%s'",FL, fname); + MIME_element_deactivate (cur_mime, unpack_metadata); + DUW LOGGER_log("%s:%d:%s:DEBUG: Done saving '%s'",FL,__func__, fname); return result; } @@ -268,7 +250,7 @@ int OLEUNWRAP_seach_for_file_sig( struct OLEUNWRAP_object *oleuw, char *block, s p = tsp->sequence; /** set p to point to the start of the image signature sequence **/ cmpresult = memcmp(bp, p, 3); if (cmpresult == 0) { - DUW LOGGER_log("%s:%d:OLEUNWRAP_seach_for_file_sig:DEBUG: Hit at offset %d for signature %d",FL,(bp-block),(tsp -sigs)); + DUW LOGGER_log("%s:%d:%s:DEBUG: Hit at offset %d for signature %d",FL,__func__,(bp-block),(tsp -sigs)); hit = 1; break; } /** If we had a match in the signatures **/ @@ -290,8 +272,6 @@ int OLEUNWRAP_seach_for_file_sig( struct OLEUNWRAP_object *oleuw, char *block, s return result; } - - /** Look for PNG signature **/ /*-----------------------------------------------------------------\ Function Name : OLEUNWRAP_decode_attachment @@ -308,7 +288,7 @@ int OLEUNWRAP_seach_for_file_sig( struct OLEUNWRAP_object *oleuw, char *block, s Changes: \------------------------------------------------------------------*/ -int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, size_t stream_size, char *decode_path ) +int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, size_t stream_size, RIPMIME_output *unpack_metadata ) { struct OLE10_header oh; char *sp = stream; @@ -319,7 +299,7 @@ int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, s oh.attach_size_1 = (size_t)get_int32( sp ); sp += 4; - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: attachsize = %d [ 0x%x ], stream length = %d [ 0x%x] \n", FL, oh.attach_size_1, oh.attach_size_1, stream_size, stream_size ); + DUW LOGGER_log("%s:%d:%s:DEBUG: attachsize = %d [ 0x%x ], stream length = %d [ 0x%x] \n", FL,__func__, oh.attach_size_1, oh.attach_size_1, stream_size, stream_size ); oh.attach_start_offset = (stream_size -oh.attach_size_1); data_start_point = stream +oh.attach_start_offset; @@ -336,31 +316,31 @@ int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, s // check next 4 bytes. cbheader = get_uint16( sp ); - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: cbHeader = %d [ 0x%x ]", FL, cbheader, cbheader); + DUW LOGGER_log("%s:%d:%s:DEBUG: cbHeader = %d [ 0x%x ]", FL,__func__, cbheader, cbheader); mfpmm = get_uint16( sp +2 ); - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: mfp.mm = %d [ 0x%x ]", FL, mfpmm, mfpmm); + DUW LOGGER_log("%s:%d:%s:DEBUG: mfp.mm = %d [ 0x%x ]", FL,__func__, mfpmm, mfpmm); mfpxext = get_uint16( sp +4 ); - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: mfp.xext = %d [ 0x%x ]", FL, mfpxext, mfpxext); + DUW LOGGER_log("%s:%d:%s:DEBUG: mfp.xext = %d [ 0x%x ]", FL,__func__, mfpxext, mfpxext); mfpyext = get_uint16( sp +8 ); - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: mfp.yext = %d [ 0x%x ]", FL, mfpyext, mfpyext); + DUW LOGGER_log("%s:%d:%s:DEBUG: mfp.yext = %d [ 0x%x ]", FL,__func__, mfpyext, mfpyext); mfphmf = get_uint16( sp +10 ); - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: mfp.hmf = %d [ 0x%x ]", FL, mfphmf, mfphmf); + DUW LOGGER_log("%s:%d:%s:DEBUG: mfp.hmf = %d [ 0x%x ]", FL,__func__, mfphmf, mfphmf); // If we only had the stream byte-lenght in our header // then we know we don't have a complex header. DUW { switch (mfpmm) { case 100: - LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Image is Escher format",FL); + LOGGER_log("%s:%d:%s:DEBUG: Image is Escher format",FL,__func__); break; case 99: - LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Image is Bitmapped",FL); + LOGGER_log("%s:%d:%s:DEBUG: Image is Bitmapped",FL,__func__); break; case 98: - LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Image is TIFF",FL); + LOGGER_log("%s:%d:%s:DEBUG: Image is TIFF",FL,__func__); break; default: - LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Unknown image type for code '%d'",FL, mfpmm); + LOGGER_log("%s:%d:%s:DEBUG: Unknown image type for code '%d'",FL,__func__, mfpmm); } } @@ -371,25 +351,25 @@ int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, s int imageoffset = 0; int search_size = 500; - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: searcing for image signatures",FL); + DUW LOGGER_log("%s:%d:%s:DEBUG: searcing for image signatures",FL,__func__); if (stream_size < (search_size +68)) search_size = (stream_size -69); /** just make sure we don't over-search the stream **/ imageoffset = OLEUNWRAP_seach_for_file_sig(oleuw, data_start_point, search_size); if (imageoffset >= 0) { - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Image data found at offset %d",FL,imageoffset); + DUW LOGGER_log("%s:%d:%s:DEBUG: Image data found at offset %d",FL,__func__,imageoffset); data_start_point += imageoffset; } else { - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Could not detect image signature, dumping whole stream",FL); + DUW LOGGER_log("%s:%d:%s:DEBUG: Could not detect image signature, dumping whole stream",FL,__func__); } } oh.attach_name = PLD_dprintf("image-%ld",oh.attach_size_1); oh.attach_size = oh.attach_size_1; oh.fname_1 = oh.fname_2 = NULL; - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Setting attachment name to '%s', size = %d",FL,oh.attach_name, oh.attach_size); + DUW LOGGER_log("%s:%d:%s:DEBUG: Setting attachment name to '%s', size = %d",FL,__func__,oh.attach_name, oh.attach_size); } else { - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Decoding file information header",FL); + DUW LOGGER_log("%s:%d:%s:DEBUG: Decoding file information header",FL,__func__); // Unknown memory segment memcpy( oh.data, sp, 2 ); sp += 2; @@ -418,7 +398,7 @@ int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, s data_start_point = sp; } - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Attachment %s:%s:%s size = %d\n",FL, oh.attach_name, oh.fname_1, oh.fname_2, oh.attach_size ); + DUW LOGGER_log("%s:%d:%s:DEBUG: Attachment %s:%s:%s size = %d\n",FL,__func__, oh.attach_name, oh.fname_1, oh.fname_2, oh.attach_size ); /** 20050119:2053:PLD - Added to sanitize 8-bit filenames **/ @@ -427,12 +407,12 @@ int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, s OLEUNWRAP_sanitize_filename(oh.fname_1); OLEUNWRAP_sanitize_filename(oh.fname_2); - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Sanitized attachment filenames",FL); + DUW LOGGER_log("%s:%d:%s:DEBUG: Sanitized attachment filenames",FL,__func__); - result = OLEUNWRAP_save_stream( oleuw, oh.attach_name, decode_path, data_start_point, oh.attach_size ); + result = OLEUNWRAP_save_stream( oleuw, oh.attach_name, unpack_metadata, data_start_point, oh.attach_size ); if (result == OLEUW_OK) { - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Calling reporter for the filename",FL); + DUW LOGGER_log("%s:%d:%s:DEBUG: Calling reporter for the filename",FL,__func__); if ((oleuw->verbose > 0)&&(oleuw->filename_report_fn != NULL)) { oleuw->filename_report_fn(oh.attach_name); @@ -440,13 +420,13 @@ int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, s // Do call back to reporting function } - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Cleaning up",FL); + DUW LOGGER_log("%s:%d:%s:DEBUG: Cleaning up",FL,__func__); // Clean up our previously allocated data if (oh.fname_1 != NULL) free(oh.fname_1); if (oh.attach_name != NULL) free(oh.attach_name); if (oh.fname_2 != NULL) free(oh.fname_2); - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: done.",FL); + DUW LOGGER_log("%s:%d:%s:DEBUG: done.",FL,__func__); return OLEUW_OK; } @@ -466,23 +446,23 @@ int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, s Changes: \------------------------------------------------------------------*/ -int OLEUNWRAP_decodestream( struct OLEUNWRAP_object *oleuw, char *element_string, char *stream, size_t stream_size, char *decode_path ) +int OLEUNWRAP_decodestream( struct OLEUNWRAP_object *oleuw, char *element_string, char *stream, size_t stream_size, RIPMIME_output *unpack_metadata ) { int result = OLEUW_OK; if (strstr(element_string, OLEUW_ELEMENT_10NATIVE_STRING) != NULL) { - DUW LOGGER_log("%s:%d:OLEUNWRAP_decodestream:DEBUG: Debugging element '%s'",FL, element_string); - OLEUNWRAP_decode_attachment( oleuw, stream, stream_size, decode_path ); + DUW LOGGER_log("%s:%d:%s:DEBUG: Debugging element '%s'",FL,__func__, element_string); + OLEUNWRAP_decode_attachment( oleuw, stream, stream_size, unpack_metadata ); } else if (strstr(element_string, OLEUW_ELEMENT_DATA) != NULL) { - DUW LOGGER_log("%s:%d:OLEUNWRAP_decodestream:DEBUG: Debugging element '%s'",FL, element_string); - OLEUNWRAP_decode_attachment( oleuw, stream, stream_size, decode_path ); + DUW LOGGER_log("%s:%d:%s:DEBUG: Debugging element '%s'",FL,__func__, element_string); + OLEUNWRAP_decode_attachment( oleuw, stream, stream_size, unpack_metadata ); } else { - DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Unable to decode stream with element string '%s'\n", FL, element_string); + DUW LOGGER_log("%s:%d:%s:DEBUG: Unable to decode stream with element string '%s'\n", FL,__func__, element_string); result = OLEUW_STREAM_NOT_DECODED; } diff --git a/ripOLE/olestream-unwrap.h b/ripOLE/olestream-unwrap.h index 82f6e90..df2c7df 100644 --- a/ripOLE/olestream-unwrap.h +++ b/ripOLE/olestream-unwrap.h @@ -19,9 +19,9 @@ int OLEUNWRAP_set_debug( struct OLEUNWRAP_object *oleuw, int level ); int OLEUNWRAP_set_verbose( struct OLEUNWRAP_object *oleuw, int level ); int OLEUNWRAP_set_save_unknown_streams( struct OLEUNWRAP_object *oleuw, int level ); -int OLEUNWRAP_save_stream( struct OLEUNWRAP_object *oleuw, char *fname, char *decode_path, char *stream, size_t bytes ); -int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, size_t stream_size, char *decode_path ); -int OLEUNWRAP_decodestream( struct OLEUNWRAP_object *oleuw, char *element_string, char *stream, size_t stream_size, char *decode_path ); +int OLEUNWRAP_save_stream( struct OLEUNWRAP_object *oleuw, char *fname, RIPMIME_output *unpack_metadata, char *stream, size_t bytes ); +int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, size_t stream_size, RIPMIME_output *unpack_metadata ); +int OLEUNWRAP_decodestream( struct OLEUNWRAP_object *oleuw, char *element_string, char *stream, size_t stream_size, RIPMIME_output *unpack_metadata ); int OLEUNWRAP_set_filename_report_fn( struct OLEUNWRAP_object *oleuw, int (*ptr_to_fn)(char *) ); diff --git a/ripOLE/pldstr.c b/ripOLE/pldstr.c deleted file mode 100644 index ca29de3..0000000 --- a/ripOLE/pldstr.c +++ /dev/null @@ -1,770 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include - -#include "logger.h" -#include "pldstr.h" - - -/*-----------------------------------------------------------------\ - Function Name : *PLD_strstr - Returns Type : char - ----Parameter List - 1. char *haystack, - 2. char *needle, - 3. int insensitive, - ------------------ - Exit Codes : - Side Effects : --------------------------------------------------------------------- - Comments: - --------------------------------------------------------------------- - Changes: - -\------------------------------------------------------------------*/ -char *PLD_strstr(char *haystack, char *needle, int insensitive) -{ - char *hs, *ne; - char *result; - -// LOGGER_log("%s:%d:\nHS=%s\nNE=%s\nIS=%d\n",FL, haystack, needle, insensitive ); - - if (insensitive > 0) - { - hs = strdup(haystack); - PLD_strlower(hs); - ne = strdup(needle); - PLD_strlower(ne); - } else { - hs = haystack; - ne = needle; - } - - result = strstr(hs, ne); -// if (result) LOGGER_log("%s:%d:HIT: %s",FL, result); -// else LOGGER_log("%s:%d:MISS (looking for %s|%s)",FL, needle,ne); - - if ((result != NULL)&&(insensitive > 0)) - { - result = result -hs +haystack; -// free(hs); -// free(ne); - -// LOGGER_log("%s:%d:HIT - %s",FL, result ); - } - if (insensitive) { - free(hs); - free(ne); - } - - return result; -} - -/*------------------------------------------------------------------------ -Procedure: PLD_strncpy ID:1 -Purpose: Copy characters from 'src' to 'dst', writing not more than 'len' -characters to the destination, including the terminating \0. -Thus, for any effective copying, len must be > 1. -Input: char *dst: Destination string -char *src: Source string -size_t len: length of string -Output: Returns a pointer to the destination string. -Errors: -------------------------------------------------------------------------*/ -char *PLD_strncpy (char *dst, const char *src, size_t len) -{ - - // Thanks go to 'defrost' of #c for providing the replacement - // code which you now see here. It covers the errors better - // than my own previous code. - - // If we have no buffer space, then it's futile attempting - // to copy anything, just return NULL - if (len==0) return NULL; - - // Providing our destination pointer isn't NULL, we can - // commence copying data across - - if (dst) - { - char *dp = dst; - - // If our source string exists, start moving it to the - // destination string character at a time. - if (src) - { - char *sp = (char *)src; - while ((--len)&&(*sp)) { *dp=*sp; dp++; sp++; } - } - - *dp='\0'; - } - - return dst; -} - - - -/*------------------------------------------------------------------------ -Procedure: PLD_strncat ID:1 -Purpose: Buffer size limited string concat function for two strings. -Input: char *dst: Destination string -char *src: Source string -size_t len: Destination string buffer size - total string size cannot exceed this -Output: -Errors: If the length of both strings in total is greater than the available buffer space -in *dst, we copy the maximum possible amount of chars from *src such that -buffer does not overflow. A suffixed '\0' will always be appended. -------------------------------------------------------------------------*/ -char *PLD_strncat( char *dst, const char *src, size_t len ) -{ - char *dp = dst; - const char *sp = src; - size_t cc; - - if (len == 0) return dst; - - len--; - - // Locate the end of the current string. - cc = 0; - while ((*dp)&&(cc < len)) { dp++; cc++; } - - // If we have no more buffer space, then return the destination - - if (cc >= len) return dst; - - // While we have more source, and there's more char space left in the buffer - - while ((*sp)&&(cc < len)) - { - cc++; - *dp = *sp; - dp++; - sp++; - } - - // Terminate dst, as a gaurantee of string ending. - - *dp = '\0'; - - return dst; -} - - -/*------------------------------------------------------------------------ -Procedure: PLD_strncate ID:1 -Purpose: Catencates a source string to the destination string starting from a given -endpoint. This allows for faster catencation of strings by avoiding the -computation required to locate the endpoint of the destination string. -Input: char *dst: Destination string -char *src: Source string -size_t len: Destination buffer size -char *endpoint: Endpoint of destination string, location from where new -string will be appended -Output: -Errors: -------------------------------------------------------------------------*/ -char *PLD_strncate( char *dst, const char *src, size_t len, char *endpoint ) -{ - char *dp = dst; - const char *sp = src; - size_t cc = 0; - - if (len == 0) return dst; - - len--; - - // If endpoint does not relate correctly, then force manual detection - // of the endpoint. - - if ((!endpoint)||(endpoint == dst)||((endpoint -dst +1)>(int)len)) - { - // Locate the end of the current string. - cc = 0; - while ((*dp != '\0')&&(cc < len)) { dp++; cc++; } - } - else { - cc = endpoint -dst +1; - dp = endpoint; - } - - // If we have no more buffer space, then return the destination - - if (cc >= len) return dst; - - // While we have more source, and there's more char space left in the buffer - - while ((*sp)&&(cc < len)) - { - cc++; - *dp = *sp; - dp++; - sp++; - } - - // Terminate dst, as a gaurantee of string ending. - - *dp = '\0'; - - return dst; -} - - - - - -/*------------------------------------------------------------------------ -Procedure: XAM_strncasecmp ID:1 -Purpose: Portable version of strncasecmp(), this may be removed in later -versions as the strncase* type functions are more widely -implemented -Input: -Output: -Errors: -------------------------------------------------------------------------*/ -int PLD_strncasecmp( char *s1, char *s2, int n ) -{ - char *ds1 = s1, *ds2 = s2; - char c1, c2; - int result = 0; - - while(n > 0) - { - c1 = tolower(*ds1); - c2 = tolower(*ds2); - - if (c1 == c2) - { - n--; - ds1++; - ds2++; - } - else - { - result = c2 - c1; - n = 0; - } - - } - - return result; - -} - - - - - -/*------------------------------------------------------------------------ -Procedure: XAM_strtok ID:1 -Purpose: A thread safe version of strtok() -Input: -Output: -Errors: -------------------------------------------------------------------------*/ -char *PLD_strtok( struct PLD_strtok *st, char *line, char *delimeters ) -{ - char *stop; - char *dc; - char *result = NULL; - - if ( line ) - { - st->start = line; - } - - //Strip off any leading delimeters - - dc = delimeters; - while ((st->start)&&(*dc != '\0')) - { - if (*dc == *(st->start)) - { - st->start++; - dc = delimeters; - } - else dc++; - } - - // Where we are left, is the start of our token. - - result = st->start; - - if ((st->start)&&(*(st->start) != '\0')) - { - stop = strpbrk( st->start, delimeters ); /* locate our next delimeter */ - - // If we found a delimeter, then that is good. We must now break the string here - // and don't forget to store the character which we stopped on. Very useful bit - // of information for programs which process expressions. - - if (stop) - { - - // Store our delimeter. - - st->delimeter = *stop; - - // Terminate our token. - - *stop = '\0'; - - - // Because we're emulating strtok() behaviour here, we have to - // absorb all the concurrent delimeters, that is, unless we - // reach the end of the string, we cannot return a string with - // no chars. - - stop++; - dc = delimeters; - while (*dc != '\0') - { - if (*dc == *stop) - { - stop++; - dc = delimeters; - } - else dc++; - } // While - - if (*stop == '\0') st->start = NULL; - else st->start = stop; - - } - else { - st->start = NULL; - st->delimeter = '\0'; - } - } - else { - st->start = NULL; - result = NULL; - } - - - return result; -} - - - -/*------------------------------------------------------------------------ -Procedure: PLD_strlower ID:1 -Purpose: Converts a string to lowercase -Input: char *convertme : string to convert -Output: -Errors: -Comments: Really need to validate against high-ASCII chars. - Tested against strings like; - Logo de la République française - Македонски - -------------------------------------------------------------------------*/ -int PLD_strlower( char *convertme ) -{ - - char *c = convertme; - - while ( *c != '\0') {*c = (unsigned char)tolower((int)*c); c++;} - - return 0; -} - - -/*-----------------------------------------------------------------\ - Function Name : *PLD_strreplace - Returns Type : char - ----Parameter List - 1. char *source, Original buffer, \0 terminated - 2. char *searchfor, String sequence to search for - 3. char *replacewith, String sequence to replace 'searchfor' with - 4. int replacenumber , How many times to replace 'searchfor', 0 == unlimited - ------------------ - Exit Codes : Returns a pointer to the new buffer space. The original - buffer will still remain intact - ensure that the calling - program free()'s the original buffer if it's no longer - needed - Side Effects : - -------------------------------------------------------------------- -Comments: -Start out with static text matching - upgrade to regex later. - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -char *PLD_strreplace_general( struct PLD_strreplace *replace_details ) -{ - char *new_buffer=NULL; - char *source_end; - char *segment_start, *segment_end, *segment_p; - char *new_p; - char *preexist_location=NULL; - char *postexist_location=NULL; - int replace_count=0; - int size_required; - int size_difference; - int source_length; - int searchfor_length; - int replacewith_length; - int segment_ok; - - if (replace_details->source == NULL) return NULL; - - source_length = strlen( replace_details->source ); - source_end = replace_details->source +source_length; - searchfor_length = strlen(replace_details->searchfor); - replacewith_length = strlen(replace_details->replacewith); - size_difference = replacewith_length -searchfor_length; - size_required = source_length; - replace_count = replace_details->replacenumber; - - if ((replace_details->preexist != NULL)&&(strlen(replace_details->preexist) < 1)) replace_details->preexist = NULL; - if ((replace_details->postexist != NULL)&&(strlen(replace_details->postexist) < 1)) replace_details->postexist = NULL; - - // If we have a 'pre-exist' request, then we need to check this out first - // because if the pre-exist string cannot be found, then there's very - // little point us continuing on in our search ( because without the - // preexist string existing, we are thus not qualified to replace anything ) - if (replace_details->preexist != NULL) - { - preexist_location = PLD_strstr(replace_details->source, replace_details->preexist, replace_details->insensitive); - if (preexist_location == NULL) - { - return replace_details->source; - } - } - - // Determine if initial POSTexist tests will pass, if we don't pick up - // anything here, then there's no point in continuing either - if (replace_details->postexist != NULL) - { - char *p = replace_details->source; - postexist_location = NULL; - do { - p = PLD_strstr(p, replace_details->postexist, replace_details->insensitive); - if (p != NULL) - { - postexist_location = p; - p = p +strlen(replace_details->postexist); - } - } while (p != NULL); - - if (postexist_location == NULL) - { - return replace_details->source; - } - } - - - // Step 1 - determine the MAXIMUM number of times we might have to replace this string ( or the limit - // set by replacenumber - // - // Note - we only need this number if the string we're going to be inserting into the - // source is larger than the one we're replacing - this is so that we can ensure that - // we have sufficient memory available in the buffer. - if (size_difference > 0) - { - if (replace_count == 0) - { - char *p, *q; - - p = replace_details->source; - q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive); - while (q != NULL) - { - replace_count++; - //size_required += size_difference; - p = q +searchfor_length; - q = PLD_strstr(p, replace_details->searchfor, replace_details->insensitive); - } - - } - size_required = source_length +(size_difference *replace_count) +1; - } else size_required = source_length +1; - - - // Allocate the memory required to hold the new string [at least], check to see that - // all went well, if not, then return an error - new_buffer = malloc( sizeof(char) *size_required); - if (new_buffer == NULL) - { - LOGGER_log("%s:%d:PLD_strreplace:ERROR: Cannot allocate %d bytes of memory to perform replacement operation", FL, size_required); - return replace_details->source; - } - - // Our segment must always start at the beginning of the source, - // on the other hand, the segment_end can be anything from the - // next byte to NULL ( which is specially treated to mean to - // the end of the source ) - segment_start = replace_details->source; - - - // Locate the first segment - segment_ok = 0; - segment_end = PLD_strstr(replace_details->source, replace_details->searchfor, replace_details->insensitive); - - // Determine if the first segment is valid in the presence of the - // pre-exist and post-exist requirements - while ((segment_end != NULL)&&(segment_ok == 0)\ - &&((replace_details->preexist != NULL)||(replace_details->postexist != NULL))) - { - int pre_ok = 0; - int post_ok = 0; - - // The PREexist test assumes a couple of factors - please ensure these are - // relevant if you change any code prior to this point. - // - // 1. preexist_location has already been computed and is not NULL - // - // 2. By relative position, the first preexist_location will be a valid location - // on which to validate for ALL replacements beyond that point, thus, we - // never actually have to recompute preexist_location again. - // - // 3. Conversely, the last computed postexist_location is valid for all - // matches before it - // - if (preexist_location == NULL) pre_ok = 1; - else if (preexist_location < segment_end){ pre_ok = 1;} - - if (postexist_location == NULL) post_ok = 1; - else if (postexist_location > segment_end){ post_ok = 1;} - - if ((pre_ok == 0)||(post_ok == 0)) { segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); } - else segment_ok = 1; - } - - segment_p = segment_start; - new_p = new_buffer; - while (segment_start != NULL) - { - int replacewith_count; - char *replacewith_p; - - if (segment_end == NULL) segment_end = source_end; - - replace_count--; - - // Perform the segment copy - segment_p = segment_start; - while ((segment_p < segment_end)&&(size_required > 0)) - { - *new_p = *segment_p; - new_p++; - segment_p++; - size_required--; - } - - // Perform the string replacement - if (segment_end < source_end) - { - replacewith_count = replacewith_length; - replacewith_p = replace_details->replacewith; - while ((replacewith_count--)&&(size_required > 0)) - { - *new_p = *replacewith_p; - new_p++; - replacewith_p++; - size_required--; - } - } - - if (size_required < 1 ) - { - LOGGER_log("%s:%d:PLD_strreplace_general: Allocated memory ran out while replacing '%s' with '%s'",FL, replace_details->searchfor, replace_details->replacewith); - *new_p='\0'; - break; - } - - // Find the next segment - segment_start = segment_end +searchfor_length; - - // If we've reached the end of the number of replacements we're supposed - // to do, then we prepare the termination of the while loop by setting - // our segment end to the end of the source. - // - // NOTE: Remember that the replace_count is pre-decremented at the start - // of the while loop, so, if the caller requested '0' replacements - // this will now be -1, thus, it won't get terminated from this == 0 - // match. Just thought you'd like to be reminded of that incase you - // were wondering "Huh? this would terminate an unlimited replacement" - if (replace_count == 0) - { - segment_end = NULL; - } else { - // If our new segment to copy starts after the - // end of the source, then we actually have - // nothing else to copy, thus, we prepare the - // segment_start varible to cause the while loop - // to terminate. - // - // Otherwise, we try and locate the next segment - // ending point, and set the starting point to - // be on the 'other side' of the 'searchfor' string - // which we found in the last search. - // - if (segment_start > source_end) - { - segment_start = NULL; - } else { - - // Try find the next segment - segment_ok = 0; - segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); - - // If we have a pre/post-exist requirement, then enter into this - // series of tests. NOTE - at least one of the pre or post tests - // must fire to give an meaningful result - else we'll end up with - // a loop which simply goes to the end of the searchspace buffer - while ((segment_end != NULL)&&(segment_ok == 0)\ - &&((replace_details->preexist != NULL)||(replace_details->postexist != NULL))) - { - int pre_ok = 0; - int post_ok = 0; - - // The PREexist test assumes a couple of factors - please ensure these are - // relevant if you change any code prior to this point. - // - // 1. preexist_location has already been computed and is not NULL - // - // 2. By relative position, the first preexist_location will be a valid location - // on which to validate for ALL replacements beyond that point, thus, we - // never actually have to recompute preexist_location again. - // - // 3. Conversely, the last computed postexist_location is valid for all - // matches before it - // - if (preexist_location == NULL) pre_ok = 1; - else if (preexist_location < segment_end){ pre_ok = 1;} - - if (postexist_location == NULL) post_ok = 1; - else if (postexist_location > segment_end){ post_ok = 1;} - - if ((pre_ok == 0)||(post_ok == 0)) { segment_end = PLD_strstr(segment_end +searchfor_length, replace_details->searchfor, replace_details->insensitive); } - else segment_ok = 1; - } - - } // If-else segment_start > source_end - - } - - } - - *new_p = '\0'; - -// if (replace_details->source != NULL) free (replace_details->source); -// replace_details->source = new_buffer; - return new_buffer; -} - -/*-----------------------------------------------------------------\ - Function Name : *PLD_strreplace - Returns Type : char - ----Parameter List - 1. char **source, - 2. char *searchfor, - 3. char *replacewith, - 4. int replacenumber , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -char *PLD_strreplace( char **source, char *searchfor, char *replacewith, int replacenumber ) -{ - struct PLD_strreplace replace_details; - char *tmp_source; - - replace_details.source = *source; - replace_details.searchfor = searchfor; - replace_details.replacewith = replacewith; - replace_details.replacenumber = replacenumber; - replace_details.preexist = NULL; - replace_details.postexist = NULL; - replace_details.insensitive = 0; - - tmp_source = PLD_strreplace_general( &replace_details ); - - if (tmp_source != *source) *source = tmp_source; - - return *source; -} - - -/*-----------------------------------------------------------------\ - Function Name : *PLD_dprintf - Returns Type : char - ----Parameter List - 1. const char *format, - 2. ..., - ------------------ - Exit Codes : - Side Effects : --------------------------------------------------------------------- - Comments: - This is a dynamic string allocation function, not as fast as some - other methods, but it works across the board with both glibc 2.0 - and 2.1 series. - --------------------------------------------------------------------- - Changes: - -\------------------------------------------------------------------*/ -char *PLD_dprintf(const char *format, ...) -{ - int n, size = 1024; // Assume we don't need more than 1K to start with - char *p; - va_list ap; - - // Attempt to allocate and then check - p = malloc(size *sizeof(char)); - if (p == NULL) return NULL; - - while (1) - { - // Attempt to print out string out into the allocated space - va_start(ap, format); - n = vsnprintf (p, size, format, ap); - va_end(ap); - - // If things went well, then return the new string - if ((n > -1) && (n < size)) return p; - - // If things didn't go well, then we have to allocate more space - // based on which glibc we're using ( fortunately, the return codes - // tell us which glibc is being used! *phew* - // - // If n > -1, then we're being told precisely how much space we need - // else (older glibc) we have to just guess again ... - - if (n > -1) size = n+1; // Allocate precisely what is needed - else size *= 2; // Double the amount allocated, note, we could just increase by 1K, but if we have a long string, we'd end up using a lot of realloc's - - // We could just realloc 'blind', but that'd be wrong and potentially cause a DoS, so - // instead, we'll be good and first attempt to realloc to a temp variable then, if all - // is well, we go ahead and update - if (1) - { - char *tmp_p; - - tmp_p = realloc(p, size); - if (tmp_p == NULL){ if (p != NULL) free(p); return NULL; } - else p = tmp_p; - } - } - -} - - -//-----------------END. diff --git a/ripOLE/pldstr.c b/ripOLE/pldstr.c new file mode 120000 index 0000000..4ffd4b6 --- /dev/null +++ b/ripOLE/pldstr.c @@ -0,0 +1 @@ +../pldstr.c \ No newline at end of file diff --git a/ripOLE/pldstr.h b/ripOLE/pldstr.h deleted file mode 100644 index 338a314..0000000 --- a/ripOLE/pldstr.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __PLDSTR__ -#define __PLDSTR__ - -#ifndef FL -#define FL __FILE__,__LINE__ -#endif - -struct PLD_strtok -{ - char *start; - char delimeter; -}; - -struct PLD_strreplace -{ - char *source; - char *searchfor; - char *replacewith; - - char *preexist; - char *postexist; - - int replacenumber; - - int insensitive; -}; - -char *PLD_strstr(char *haystack, char *needle, int insensitive); -char *PLD_strncpy( char *dst, const char *src, size_t len ); -char *PLD_strncat( char *dst, const char *src, size_t len ); -char *PLD_strncate( char *dst, const char *src, size_t len, char *endpoint ); -char *PLD_strtok( struct PLD_strtok *st, char *line, char *delimeters ); -int PLD_strncasecmp( char *s1, char *s2, int n ); -int PLD_strlower( char *convertme ); - -char *PLD_strreplace_general( struct PLD_strreplace *replace_details ); -char *PLD_strreplace( char **source, char *searchfor, char *replacewith, int replacenumber ); -char *PLD_dprintf(const char *fmt, ...); - -#endif diff --git a/ripOLE/pldstr.h b/ripOLE/pldstr.h new file mode 120000 index 0000000..da26a11 --- /dev/null +++ b/ripOLE/pldstr.h @@ -0,0 +1 @@ +../pldstr.h \ No newline at end of file diff --git a/ripOLE/ripole.c b/ripOLE/ripole.c index 387d382..6395ef8 100644 --- a/ripOLE/ripole.c +++ b/ripOLE/ripole.c @@ -8,6 +8,7 @@ #include "logger.h" #include "pldstr.h" +#include "mime_element.h" #include "ole.h" struct ripOLE_object { @@ -309,6 +310,7 @@ int main( int argc, char **argv ) { struct ripOLE_object role; struct OLE_object *ole = NULL; + RIPMIME_output o; int result = 0; if (argc == 1) { fprintf (stdout, "%s\n", help); exit(1); } @@ -320,7 +322,6 @@ int main( int argc, char **argv ) return 1; } - LOGGER_set_output_mode(_LOGGER_STDOUT); OLE_init(ole); @@ -335,8 +336,10 @@ int main( int argc, char **argv ) OLE_set_filename_report_fn(ole, ROLE_report_filename_decoded ); - result = OLE_decode_file( ole, role.inputfile, role.outputdir ); - OLE_decode_file_done(ole); + o.dir = role.outputdir; + o.unpack_mode = RIPMIME_UNPACK_MODE_TO_DIRECTORY; + result = OLE_decode_diskfile( ole, role.inputfile, &o ); + OLE_decode_done(ole); if ((result != 0)) { if (role.verbose) { diff --git a/ripmime-api.c b/ripmime-api.c index d036616..3caf7e7 100644 --- a/ripmime-api.c +++ b/ripmime-api.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -44,7 +43,7 @@ char version[] = "v1.4.0.1 - 30/08/2004 (C) PLDaniels http://www.pldaniels.com/r Changes: \------------------------------------------------------------------*/ -int RIPMIME_init (struct RIPMIME_object *rm) +void RIPMIME_init (struct RIPMIME_object *rm) { rm->outputdir = defaultdir; rm->mailpack = NULL; @@ -55,9 +54,6 @@ int RIPMIME_init (struct RIPMIME_object *rm) MIME_set_paranoid(0); MIME_set_renamemethod(_MIME_RENAME_METHOD_INFIX); MIME_set_verbosity(0); - - - return 0; } @@ -138,7 +134,6 @@ int RIPMIME_decode( struct RIPMIME_object *rm, char *mailpack, char *outputdir ) MIME_close (); return 0; - } /*-END-----------------------------------------------------------*/ diff --git a/ripmime.c b/ripmime.c index 8241ffe..c295e99 100644 --- a/ripmime.c +++ b/ripmime.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -24,9 +23,10 @@ #include "buildcodes.h" #include "logger.h" #include "ffget.h" +#include "mime_element.h" #include "mime.h" #include "strstack.h" -#include "MIME_headers.h" +#include "mime_headers.h" #define RIPMIME_ERROR_CANT_CREATE_OUTPUT_DIR 1 #define RIPMIME_ERROR_CANT_OPEN_INPUT_FILE 2 @@ -36,8 +36,8 @@ struct RIPMIME_globals { - char *inputfile; - char *dir; + char *input_path; + RIPMIME_output *output; int use_return_codes; int timeout; int quiet; @@ -55,7 +55,7 @@ char help[] = "ripMIME -i -d " "[-p prefix] [-e [header file]] [-vVh] [--version]" "[--no_nameless] [--unique_names [--prefix|--postfix|--infix|--randprefix|--randpostfix|--randinfix]]" "[--paranoid] [--mailbox] [--formdata] [--debug]" - "[--no-tnef] [--no-quotedprintable] [--no-uudecode]\n" + "[--no-quotedprintable] [--no-uudecode]\n" "Options available :\n" "-i : Input MIME encoded file (use '-' to input from STDIN)\n" "\tIf is a directory, it will be recursed\n" @@ -64,6 +64,8 @@ char help[] = "ripMIME -i -d " "-e [headers file name] : Dump headers from mailpack (default '_headers_')\n" "-v : Turn on verbosity\n" "-q : Run quietly, do no report non-fatal errors\n" + "-l : list included mime fragments metadata to STDOUT delimited by '|' sign. Contains :\n" + " internal id, attachment count, file count, recursion level, mime content type, file name\n" "\n" "--verbose-contenttype : Turn on verbosity of file content type\n" "--verbose-oldstyle : Uses the v1.2.x style or filename reporting\n" @@ -89,7 +91,6 @@ char help[] = "ripMIME -i -d " "--mailbox : Process mailbox file\n" "--formdata : Process as form data (from HTML form etc). Inhibits conversion of NUL/zero-bytes to spaces\n" "\n" - "--no-tnef : Turn off TNEF/winmail.dat decoding\n" "--no-ole : Turn off OLE decoding\n" "--no-uudecode : Turns off the facility of detecting UUencoded attachments in emails\n" "--no-quotedprintable : Turns off the facility of decoding QuotedPrintable data\n" @@ -182,14 +183,14 @@ int RIPMIME_parse_parameters (struct RIPMIME_globals *glb, int argc, char **argv case 'i': if (argv[i][2] != '\0') { - glb->inputfile = &argv[i][2]; + glb->input_path = &argv[i][2]; } else { i++; if (i < argc) { - glb->inputfile = argv[i]; + glb->input_path = argv[i]; } else { @@ -201,14 +202,14 @@ int RIPMIME_parse_parameters (struct RIPMIME_globals *glb, int argc, char **argv case 'd': if (argv[i][2] != '\0') { - glb->dir = &(argv[i][2]); + glb->output->dir = &(argv[i][2]); } else { i++; if (i < argc) { - glb->dir = argv[i]; + glb->output->dir = argv[i]; } else { @@ -263,6 +264,10 @@ int RIPMIME_parse_parameters (struct RIPMIME_globals *glb, int argc, char **argv break; // blankzone storage option #endif + case 'l': + glb->output->unpack_mode = RIPMIME_UNPACK_MODE_LIST_MIME; + break; + case 'v': MIME_set_verbosity (1); glb->verbose = 1; @@ -317,40 +322,40 @@ int RIPMIME_parse_parameters (struct RIPMIME_globals *glb, int argc, char **argv } else if (strncmp (&(argv[i][2]), "prefix", 6) == 0) { - MIME_set_renamemethod (_MIME_RENAME_METHOD_PREFIX); + glb->output->rename_method = _MIME_RENAME_METHOD_PREFIX; } else if (strncmp (&(argv[i][2]), "postfix", 7) == 0) { - MIME_set_renamemethod (_MIME_RENAME_METHOD_POSTFIX); + glb->output->rename_method = _MIME_RENAME_METHOD_POSTFIX; } else if (strncmp (&(argv[i][2]), "infix", 5) == 0) { - MIME_set_renamemethod (_MIME_RENAME_METHOD_INFIX); + glb->output->rename_method = _MIME_RENAME_METHOD_INFIX; } /* New methods of generating file name: add counter and random number*/ else if (strncmp (&(argv[i][2]), "randprefix", 10) == 0) { - MIME_set_renamemethod (_MIME_RENAME_METHOD_RANDPREFIX); + glb->output->rename_method = _MIME_RENAME_METHOD_RANDPREFIX; } else if (strncmp (&(argv[i][2]), "randpostfix", 11) == 0) { - MIME_set_renamemethod (_MIME_RENAME_METHOD_RANDPOSTFIX); + glb->output->rename_method = _MIME_RENAME_METHOD_RANDPOSTFIX; } else if (strncmp (&(argv[i][2]), "randinfix", 9) == 0) { - MIME_set_renamemethod (_MIME_RENAME_METHOD_RANDINFIX); + glb->output->rename_method = _MIME_RENAME_METHOD_RANDINFIX; } else if (strncmp (&(argv[i][2]), "overwrite", 9) == 0) { - MIME_set_uniquenames (0); + glb->output->unique_names = 0; } else if (strncmp (&(argv[i][2]), "unique_names", 12) == 0) { - MIME_set_uniquenames (1); + glb->output->unique_names = 1; } else if (strncmp (&(argv[i][2]), "unique-names", 12) == 0) { - MIME_set_uniquenames (1); + glb->output->unique_names = 1; } else if (strncmp(&(argv[i][2]), "name-by-type", 12) == 0) { @@ -404,10 +409,6 @@ int RIPMIME_parse_parameters (struct RIPMIME_globals *glb, int argc, char **argv { MIME_set_decode_uudecode(0); } - else if (strncmp (&(argv[i][2]), "no-tnef", 7) == 0) - { - MIME_set_decode_tnef (0); - } else if (strncmp (&(argv[i][2]), "no-ole", 6) == 0) { MIME_set_decode_ole(0); @@ -510,7 +511,6 @@ int RIPMIME_parse_parameters (struct RIPMIME_globals *glb, int argc, char **argv } - /*-----------------------------------------------------------------\ Function Name : RIPMIME_init Returns Type : int @@ -526,16 +526,19 @@ Side Effects : Changes: \------------------------------------------------------------------*/ -int RIPMIME_init (struct RIPMIME_globals *glb) +int RIPMIME_init (struct RIPMIME_globals *glb, RIPMIME_output *o) { - glb->dir = defaultdir; - glb->inputfile = NULL; + glb->output = o; + glb->output->dir = defaultdir; + glb->output->unpack_mode = RIPMIME_UNPACK_MODE_TO_DIRECTORY; + glb->output->rename_method = _MIME_RENAME_METHOD_INFIX; + glb->output->unique_names = 1; + glb->input_path = NULL; glb->use_return_codes = 0; glb->timeout = 0; glb->quiet = 0; glb->verbose_defects = 0; glb->verbose = 0; - return 0; } @@ -556,7 +559,7 @@ Side Effects : \------------------------------------------------------------------*/ void RIPMIME_signal_alarm( int sig ) { - if (ripmime_globals->quiet == 0) LOGGER_log("%s:%d:RIPMIME_signal_alarm: ripMIME took too long to complete. Mailpack is \"%s\", output dir is \"%s\"",FL, ripmime_globals->inputfile, ripmime_globals->dir ); + if (ripmime_globals->quiet == 0) LOGGER_log("%s:%d:RIPMIME_signal_alarm: ripMIME took too long to complete. Mailpack is \"%s\", output dir is \"%s\"",FL, ripmime_globals->input_path, ripmime_globals->output->dir ); exit(RIPMIME_ERROR_TIMEOUT); } @@ -587,12 +590,11 @@ int RIPMIME_unpack_single( struct RIPMIME_globals *glb, char *fname ) alarm(glb->timeout); } - MIMEH_set_outputdir (glb->dir); - result = MIME_unpack (glb->dir, fname, 0); + result = MIME_unpack (glb->output, fname, 0); // do any last minute things - MIME_close (); + MIME_close (glb->output); return result; } @@ -621,8 +623,8 @@ int RIPMIME_unpack( struct RIPMIME_globals *glb ) /** If we're not inputting from STDIN, check to see if the ** input is a directory **/ - if (strcmp(glb->inputfile,"-")!=0) { - stat_result = stat(glb->inputfile, &st); + if (strcmp(glb->input_path,"-")!=0) { + stat_result = stat(glb->input_path, &st); if (stat_result != 0) return -1; if (S_ISDIR(st.st_mode)) input_is_directory = 1; @@ -634,7 +636,7 @@ int RIPMIME_unpack( struct RIPMIME_globals *glb ) struct dirent *dir_entry; fprintf(stderr,"input file is a directory, recursing\n"); - dir = opendir(glb->inputfile); + dir = opendir(glb->input_path); if (dir == NULL) return -1; do { @@ -648,7 +650,7 @@ int RIPMIME_unpack( struct RIPMIME_globals *glb ) if (strcmp(dir_entry->d_name, ".")==0) continue; if (strcmp(dir_entry->d_name, "..")==0) continue; - snprintf(fullfilename,sizeof(fullfilename),"%s/%s", glb->inputfile, dir_entry->d_name); + snprintf(fullfilename,sizeof(fullfilename),"%s/%s", glb->input_path, dir_entry->d_name); stat_result = stat( fullfilename, &st ); if (stat_result != 0) continue; if (S_ISREG(st.st_mode)) { @@ -662,7 +664,7 @@ int RIPMIME_unpack( struct RIPMIME_globals *glb ) } else { /** If the supplied file was actually a normal file, then decode normally **/ - result = RIPMIME_unpack_single( glb, glb->inputfile ); + result = RIPMIME_unpack_single( glb, glb->input_path ); } return result; } @@ -686,6 +688,7 @@ Side Effects : int main (int argc, char **argv) { struct RIPMIME_globals glb; + RIPMIME_output mime_output; int result = 0; /* if the user has just typed in "ripmime" and nothing else, then we had better give them @@ -711,42 +714,37 @@ int main (int argc, char **argv) // Perform system initialisations MIME_init (); - RIPMIME_init (&glb); + RIPMIME_init (&glb, &mime_output); // Setup our default behaviours */ - MIME_set_uniquenames (1); MIME_set_paranoid (0); MIME_set_header_longsearch(1); // 20040310-0117:PLD - Added by default as it seems stable, use --disable-qmail-bounce to turn off - MIME_set_renamemethod (_MIME_RENAME_METHOD_INFIX); - RIPMIME_parse_parameters (&glb, argc, argv); - // if our input filename wasn't specified, then we better let the user know! - if (!glb.inputfile) + if (!glb.input_path) { - LOGGER_log("Error: No input file was specified\n"); + LOGGER_log("Error: No input path or file was specified\n"); return RIPMIME_ERROR_NO_INPUT_FILE; } // Fire up the randomizer - srand (time (NULL)); // clean up the output directory name if required (remove any trailing /'s, as suggested by James Cownie 03/02/2001 - if (glb.dir[strlen (glb.dir) - 1] == '/') + if (glb.output->dir[strlen (glb.output->dir) - 1] == '/') { - glb.dir[strlen (glb.dir) - 1] = '\0'; + glb.output->dir[strlen (glb.output->dir) - 1] = '\0'; } // Create the output directory required as specified by the -d parameter - if (glb.dir != defaultdir) + if (glb.output->dir != defaultdir) { - result = mkdir (glb.dir, S_IRWXU); + result = mkdir (glb.output->dir, S_IRWXU); // if we had a problem creating a directory, and it wasn't just // due to the directory already existing, then we have a bit of @@ -756,7 +754,7 @@ int main (int argc, char **argv) if ((result == -1) && (errno != EEXIST)) { LOGGER_log("ripMIME: Cannot create directory '%s' (%s)\n", - glb.dir, strerror (errno)); + glb.output->dir, strerror (errno)); return RIPMIME_ERROR_CANT_CREATE_OUTPUT_DIR; } diff --git a/strstack.c b/strstack.c index 65c4635..629877f 100644 --- a/strstack.c +++ b/strstack.c @@ -1,3 +1,5 @@ +/* STRING STACK IMPLEMEMNTATION */ + #include #include #include @@ -18,17 +20,17 @@ /*-----------------------------------------------------------------\ Function Name : SS_init Returns Type : int - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : + ----Parameter List + 1. void , + ------------------ + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int SS_init( struct SS_object *ss ) { @@ -43,17 +45,17 @@ int SS_init( struct SS_object *ss ) /*-----------------------------------------------------------------\ Function Name : SS_set_verbose Returns Type : int - ----Parameter List - 1. int level , - ------------------ - Exit Codes : - Side Effects : + ----Parameter List + 1. int level , + ------------------ + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int SS_set_verbose( struct SS_object *ss, int level ) { @@ -66,16 +68,16 @@ int SS_set_verbose( struct SS_object *ss, int level ) Function Name : SS_set_debug Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int SS_set_debug( struct SS_object *ss, int level ) { @@ -88,16 +90,16 @@ int SS_set_debug( struct SS_object *ss, int level ) Function Name : SS_done Returns Type : int ----Parameter List - 1. void , + 1. void , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int SS_done( struct SS_object *ss ) { @@ -125,16 +127,16 @@ int SS_done( struct SS_object *ss ) Function Name : SS_dump Returns Type : int ----Parameter List - 1. struct SS_object *ss , + 1. struct SS_object *ss , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int SS_dump( struct SS_object *ss ) { @@ -153,23 +155,21 @@ int SS_dump( struct SS_object *ss ) Function Name : SS_push Returns Type : int ----Parameter List - 1. char *string , + 1. char *string , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int SS_push( struct SS_object *ss, char *data, size_t data_length ) { - struct SS_node *node = malloc(sizeof(struct SS_node)); - if (node) { DSS LOGGER_log("%s:%d:SS_push: Pushing %s to %p, stack count = %d",FL,data, ss->stringstack, ss->count); @@ -191,21 +191,20 @@ int SS_push( struct SS_object *ss, char *data, size_t data_length ) /*-----------------------------------------------------------------\ Function Name : *SS_pop Returns Type : char - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : + ----Parameter List + 1. void , + ------------------ + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ char *SS_pop( struct SS_object *ss ) { - struct SS_node *node = ss->stringstack; if ((ss->stringstack)&&(ss->count > 0)) @@ -223,21 +222,20 @@ char *SS_pop( struct SS_object *ss ) /*-----------------------------------------------------------------\ Function Name : *SS_top Returns Type : char - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : + ----Parameter List + 1. void , + ------------------ + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ char *SS_top( struct SS_object *ss ) { - if (ss->stringstack) { return ss->stringstack->data; @@ -248,17 +246,17 @@ char *SS_top( struct SS_object *ss ) /*-----------------------------------------------------------------\ Function Name : SS_count Returns Type : int - ----Parameter List - 1. void , - ------------------ - Exit Codes : - Side Effects : + ----Parameter List + 1. void , + ------------------ + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ int SS_count( struct SS_object *ss ) { @@ -269,17 +267,17 @@ int SS_count( struct SS_object *ss ) Function Name : *SS_cmp Returns Type : char ----Parameter List - 1. struct SS_object *ss, - 2. char *find_me , + 1. struct SS_object *ss, + 2. char *find_me , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: - + -------------------------------------------------------------------- Changes: - + \------------------------------------------------------------------*/ char *SS_cmp( struct SS_object *ss, char *find_me, size_t find_me_len ) { diff --git a/tnef/tnef.c b/tnef/tnef.c index 06e1ade..0b73612 100644 --- a/tnef/tnef.c +++ b/tnef/tnef.c @@ -29,13 +29,15 @@ * 1.3 Version (7/22/97) * Ok, take out the DTR over the stream, now uses read_16. * + * 1.5 Version (4/24/24) + * Rewritten from file utility to part of ripMIME + * * NOTE: THIS SOFTWARE IS FOR YOUR PERSONAL GRATIFICATION ONLY. I DON'T * IMPLY IN ANY LEGAL SENSE THAT THIS SOFTWARE DOES ANYTHING OR THAT IT WILL * BE USEFULL IN ANY WAY. But, you can send me fixes to it, I don't mind. ***************************************************************************/ #include -#include #include #include #include @@ -51,7 +53,7 @@ #define VERSION "pldtnef/0.0.2" #ifndef FL -#define FL __FILE__,__LINE__ +#define FL __FILE__, __LINE__ #endif #define TNEF_VERBOSE ((TNEF_glb.verbose > 0)) @@ -60,34 +62,22 @@ /** 20041207-1246:PLD: Added RT32 macro to allow for large numbers of read-tests **/ #define RT32( num_addr, offset ) if (read_32(num_addr, offset)==-1) return -1 -#define TNEF_PATH_SIZE 1024 - struct TNEF_globals { int file_num; int verbose; int verbosity_contenttype; int debug; - char path[ TNEF_PATH_SIZE +1]; int TNEF_Verbose; - int savedata; uint8 *tnef_home; uint8 *tnef_limit; int (*filename_decoded_report)(char *, char *); // Pointer to our filename reporting function - }; static struct TNEF_globals TNEF_glb; -// The variables below have been pushed into the TNEF globals -//int Verbose = FALSE; -//int SaveData = FALSE; -//uint8 *tnef_home; -//uint8 *tnef_limit; - - /*-----------------------------------------------------------------\ Function Name : TNEF_init Returns Type : int @@ -103,59 +93,16 @@ static struct TNEF_globals TNEF_glb; Changes: \------------------------------------------------------------------*/ -int TNEF_init( void ) +void TNEF_init( void ) { TNEF_glb.file_num = 0; TNEF_glb.verbose = 0; TNEF_glb.verbosity_contenttype = 0; TNEF_glb.debug = 0; - TNEF_glb.savedata = 1; TNEF_glb.TNEF_Verbose = 0; TNEF_glb.filename_decoded_report = NULL; - TNEF_glb.path[0] = '\0'; - - return 0; -} - - -/*-----------------------------------------------------------------\ - Function Name : TNEF_set_decode - Returns Type : int - ----Parameter List - 1. int level , - ------------------ - Exit Codes : - Side Effects : - -------------------------------------------------------------------- -Comments: - --------------------------------------------------------------------- -Changes: - -\------------------------------------------------------------------*/ -int TNEF_set_decode( int level ) -{ - TNEF_glb.savedata = level; - - return TNEF_glb.savedata; } - -/*------------------------------------------------------------------------ -Procedure: TNEF_set_path ID:1 -Purpose: -Input: -Output: -Errors: -------------------------------------------------------------------------*/ -int TNEF_set_path( char *path ) -{ - snprintf( TNEF_glb.path, TNEF_PATH_SIZE , "%s", path); - - return 0; -} - - /*------------------------------------------------------------------------ Procedure: TNEF_set_verbosity ID:1 Purpose: @@ -169,7 +116,6 @@ int TNEF_set_verbosity( int level ) return TNEF_glb.verbose; } - /*-----------------------------------------------------------------\ Function Name : TNEF_set_verbosity_contenttype Returns Type : int @@ -210,12 +156,9 @@ int TNEF_set_verbosity_contenttype( int level ) int TNEF_set_filename_report_fn( int (*ptr_to_fn)(char *, char *) ) { TNEF_glb.filename_decoded_report = ptr_to_fn; - return 0; } - - /*------------------------------------------------------------------------ Procedure: TNEF_set_debug ID:1 Purpose: @@ -230,10 +173,6 @@ int TNEF_set_debug( int level ) return TNEF_glb.debug; } - - - - /* Some systems don't like to read unaligned data */ /*------------------------------------------------------------------------ Procedure: read_32 ID:1 @@ -248,7 +187,7 @@ int read_32( uint32 *value, uint8 *tsp) if ((tsp +4) > TNEF_glb.tnef_limit) { - if ((TNEF_VERBOSE)||(TNEF_DEBUG)) LOGGER_log("%s:%d:TNEF_read_32:ERROR: Attempting to read beyond end of memory block",FL); + if ((TNEF_VERBOSE)||(TNEF_DEBUG)) LOGGER_log("%s:%d:%s:ERROR: Attempting to read beyond end of memory block",FL,__func__); return -1; } @@ -278,7 +217,7 @@ int read_16( uint16 *value, uint8 *tsp) //PLD-20070707-17H20, how do we even compare tsp to a negative!? ||(tsp == -1) ) { - if ((TNEF_VERBOSE)||(TNEF_DEBUG)) LOGGER_log("%s:%d:TNEF_read_16:ERROR: Attempting to read past end\n",FL); + if ((TNEF_VERBOSE)||(TNEF_DEBUG)) LOGGER_log("%s:%d:%s:ERROR: Attempting to read past end\n",FL,__func__); return -1; } @@ -292,8 +231,6 @@ int read_16( uint16 *value, uint8 *tsp) return 0; } - - /*------------------------------------------------------------------------ Procedure: make_string ID:1 Purpose: @@ -306,19 +243,9 @@ char *make_string(uint8 *tsp, int size) static char s[256] = ""; snprintf(s,sizeof(s),"%s",tsp); - - /** 20041106-0929:PLD: Remove this ugly old code and use snprintf() instead - int len = (size>sizeof(s)-1) ? sizeof(s)-1 : size; - - strncpy(s,tsp, len); - s[len] = '\0'; - **/ - return s; } - - /*------------------------------------------------------------------------ Procedure: save_attach_data ID:1 Purpose: @@ -326,28 +253,28 @@ Procedure: save_attach_data ID:1 Output: Errors: ------------------------------------------------------------------------*/ -int save_attach_data(char *title, uint8 *tsp, uint32 size) +int save_attach_data(char *title, uint8 *tsp, uint32 size, char * file_dir) { FILE *out; - char filename[1024]; - size_t bc; - - snprintf(filename, sizeof(filename),"%s/%s", TNEF_glb.path, title ); + char * fn; + int fn_l = strlen(file_dir) + strlen(title) + sizeof(char) * 2; - out = fopen(filename, "w"); + fn = malloc(fn_l); + snprintf(fn,fn_l,"%s/%s",file_dir,title); + out = fopen(fn, "w"); if (!out) { - LOGGER_log("%s:%d:TNEF_save_attach_data:ERROR: Failed opening file %s for writing (%s)\n", FL, filename, strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: Failed opening file %s for writing (%s)\n", FL,__func__, fn, strerror(errno)); + free(fn); return -1; } - bc = fwrite(tsp, sizeof(uint8), size, out); + free(fn); + fwrite(tsp, sizeof(uint8), size, out); fclose(out); return 0; } - - /*------------------------------------------------------------------------ Procedure: handle_props ID:1 Purpose: @@ -355,7 +282,7 @@ Procedure: handle_props ID:1 Output: Errors: ------------------------------------------------------------------------*/ -int handle_props(uint8 *tsp) +int handle_props(uint8 *tsp, char * file_dir) { int bytes = 0; uint32 num_props = 0; @@ -385,7 +312,7 @@ int handle_props(uint8 *tsp) { sprintf (filename, "XAM_%d.rtf", TNEF_glb.file_num); TNEF_glb.file_num++; - save_attach_data(filename, tsp+bytes, num); + save_attach_data(filename, tsp+bytes, num, file_dir); } /* num + PAD */ bytes += num + ((num % 4) ? (4 - num%4) : 0); @@ -429,13 +356,9 @@ int handle_props(uint8 *tsp) } x++; } - return 0; } - - - /*------------------------------------------------------------------------ Procedure: default_handler ID:1 Purpose: @@ -469,12 +392,8 @@ int default_handler(uint32 attribute, uint8 *tsp, uint32 size) break; } return 0; - } - - - /*------------------------------------------------------------------------ Procedure: read_attribute ID:1 Purpose: @@ -482,13 +401,12 @@ Procedure: read_attribute ID:1 Output: Errors: ------------------------------------------------------------------------*/ -int read_attribute(uint8 *tsp) +int read_attribute(uint8 *tsp, char *file_dir) { int bytes = 0, header = 0; int rv = 0; uint32 attribute; - uint8 component = 0; uint32 size = 0; uint16 checksum = 0; static char attach_title[256] = { @@ -497,20 +415,18 @@ int read_attribute(uint8 *tsp) //static uint32 attach_loc = 0; // 2003-02-22-1231-PLD static uint8 *attach_loc = 0; - component = *tsp; - bytes += sizeof(uint8); // Read the attributes of this component - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_read_attribute:DEBUG: Reading Attribute...\n",FL); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Reading Attribute...\n",FL,__func__); rv = read_32(&attribute, tsp+bytes); if (rv == -1) return -1; bytes += sizeof(attribute); // Read the size of the information we have to read - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_read_attribute: Reading Size...\n",FL); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s: Reading Size...\n",FL,__func__); rv = read_32(&size, tsp+bytes); if (rv == -1) return -1; bytes += sizeof(size); @@ -538,12 +454,12 @@ int read_attribute(uint8 *tsp) // --END of ammendment. - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_read_attribute:DEBUG: Reading Checksum...(offset %d, bytes=%d)\n", FL, tsp -TNEF_glb.tnef_home, bytes); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Reading Checksum...(offset %d, bytes=%d)\n", FL,__func__, tsp -TNEF_glb.tnef_home, bytes); if (read_16(&checksum, tsp+bytes) == -1) return -1; bytes += sizeof(checksum); - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_read_attribute:DEBUG: Decoding attribute %d\n", FL, attribute); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Decoding attribute %d\n", FL,__func__, attribute); switch (attribute) { case attNull: @@ -577,8 +493,8 @@ int read_attribute(uint8 *tsp) attach_size=size; // attach_loc =(int)tsp+header; // 2003-02-22-1232-PLD attach_loc =(uint8 *)tsp+header; - if (TNEF_glb.savedata && strlen(attach_title)>0 && attach_size > 0) { - if (!save_attach_data(attach_title, (uint8 *)attach_loc,attach_size)) + if (strlen(attach_title)>0 && attach_size > 0) { + if (!save_attach_data(attach_title, (uint8 *)attach_loc,attach_size,file_dir)) { if (TNEF_VERBOSE) { if (TNEF_glb.filename_decoded_report == NULL) @@ -592,14 +508,14 @@ int read_attribute(uint8 *tsp) } else { - LOGGER_log("%s:%d:TNEF_read_attribute:ERROR: While saving attachment '%s'\n", FL, attach_title); + LOGGER_log("%s:%d:%s:ERROR: While saving attachment '%s'\n", FL,__func__, attach_title); } } break; case attAttachTitle: strncpy(attach_title, make_string(tsp+header,size),255); - if (TNEF_glb.savedata && strlen(attach_title)>0 && attach_size > 0) { - if (!save_attach_data(attach_title, (uint8 *)attach_loc,attach_size)) + if (strlen(attach_title)>0 && attach_size > 0) { + if (!save_attach_data(attach_title, (uint8 *)attach_loc,attach_size, file_dir)) { if (TNEF_VERBOSE) { if (TNEF_glb.filename_decoded_report == NULL) @@ -613,7 +529,7 @@ int read_attribute(uint8 *tsp) } else { - LOGGER_log("%s:%d:TNEF_read_attribute:ERROR: While saving attachment '%s'\n", FL, attach_title); + LOGGER_log("%s:%d:%s:ERROR: While saving attachment '%s'\n", FL,__func__, attach_title); } } break; @@ -636,7 +552,7 @@ int read_attribute(uint8 *tsp) default_handler(attribute, tsp+header, size); break; case attMAPIProps: - if (handle_props(tsp+header)==-1) return -1; + if (handle_props(tsp+header, file_dir)==-1) return -1; break; case attRecipTable: default_handler(attribute, tsp+header, size); @@ -683,9 +599,6 @@ int read_attribute(uint8 *tsp) } - - - /*------------------------------------------------------------------------ Procedure: decode_tnef ID:1 Purpose: @@ -693,7 +606,7 @@ Procedure: decode_tnef ID:1 Output: Errors: ------------------------------------------------------------------------*/ -int TNEF_decode_tnef(uint8 *tnef_stream, int size) +int TNEF_decode_tnef(uint8 *tnef_stream, int size, char* file_dir) { int ra_response; @@ -701,7 +614,7 @@ int TNEF_decode_tnef(uint8 *tnef_stream, int size) uint16 tnef_attachkey; uint8 *tsp; - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_decode_tnef:DEBUG: Start. Size = %d\n", FL,size); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Start. Size = %d\n", FL,__func__,size); // TSP == TNEF Stream Pointer (well memory block actually!) // @@ -712,9 +625,9 @@ int TNEF_decode_tnef(uint8 *tnef_stream, int size) ra_response = read_32(&tnefs, tsp); if ((ra_response != -1)&&(TNEF_SIGNATURE == tnefs)) { - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_decode_tnef:DEBUG: TNEF signature is good\n",FL); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: TNEF signature is good\n",FL,__func__); } else { - if (TNEF_VERBOSE) LOGGER_log("%s:%d:TNEF_decode_tnef:WARNING: Bad TNEF signature, expecting %lx got %lx\n",FL,TNEF_SIGNATURE,tnefs); + if (TNEF_VERBOSE) LOGGER_log("%s:%d:%s:WARNING: Bad TNEF signature, expecting %lx got %lx\n",FL,__func__,TNEF_SIGNATURE,tnefs); } // Move tsp pointer along @@ -723,7 +636,7 @@ int TNEF_decode_tnef(uint8 *tnef_stream, int size) /** Read the TNEF Attach key **/ if (read_16(&tnef_attachkey, tsp) == -1) return -1; - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_decode_tnef:DEBUG: TNEF Attach Key: %x\n",FL,tnef_attachkey); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: TNEF Attach Key: %x\n",FL,__func__,tnef_attachkey); // Move tsp pointer along // @@ -733,11 +646,11 @@ int TNEF_decode_tnef(uint8 *tnef_stream, int size) // go through entire memory block and extract // all the required attributes and files // - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_decode_tnef:DEBUG: TNEF - Commence reading attributes\n",FL); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: TNEF - Commence reading attributes\n",FL,__func__); while ((tsp - tnef_stream) < size) { - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_decode_tnef:DEBUG: Offset = %d\n", FL,tsp -TNEF_glb.tnef_home); - ra_response = read_attribute(tsp); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Offset = %d\n", FL,__func__,tsp -TNEF_glb.tnef_home); + ra_response = read_attribute(tsp, file_dir); if ( ra_response > 0 ) { tsp += ra_response; @@ -746,115 +659,90 @@ int TNEF_decode_tnef(uint8 *tnef_stream, int size) // Must find out /WHY/ this happens, and, how to rectify the issue. tsp++; - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_decode_tnef:WARNING: TNEF - Attempting to read attribute at %d resulted in a sub-zero response, ending decoding to be safe\n",FL,tsp); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:WARNING: TNEF - Attempting to read attribute at %d resulted in a sub-zero response, ending decoding to be safe\n",FL,__func__,tsp); break; } } - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_decode_tnef:DEBUG: Done.\n",FL); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Done.\n",FL,__func__); return 0; } - - - - - -/*------------------------------------------------------------------------ -Procedure: TNEF_main ID:1 -Purpose: Decodes a given TNEF encoded file -Input: -Output: -Errors: -------------------------------------------------------------------------*/ -int TNEF_main( char *filename ) +int TNEF_file_processing( FILE *fp, char *file_dir ) { - FILE *fp; - struct stat sb; uint8 *tnef_stream; int size, nread; - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_main:DEBUG: Start, decoding %s\n",FL, filename); - - if (TNEF_glb.savedata == 0 ) - { - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_name:DEBUG: decode_tnef is set to 0, not decoding file.",FL); - return 0; - } - - - // Test to see if the file actually exists - // - if (stat(filename,&sb) == -1) - { - LOGGER_log("%s:%d:TNEF_main:ERROR: while attempting to get details on file %s (%s)\n", FL, filename,strerror(errno)); - return -1; - } - // Get the filesize - // - size = sb.st_size; + fseek(fp, 0L, SEEK_END); + size = ftell(fp); + fseek(fp, 0L, SEEK_SET); // Allocate enough memory to read in the ENTIRE file // FIXME - This could be a real consumer if multiple // instances of TNEF decoding is going on - // TNEF_glb.tnef_home = tnef_stream = (uint8 *)malloc(size); TNEF_glb.tnef_limit = TNEF_glb.tnef_home +size; // If we were unable to allocate enough memory, then we // should report this - // if (tnef_stream == NULL) { - LOGGER_log("%s:%d:TNEF_main:ERROR: When allocating %d bytes for loading file (%s)\n", FL, size,strerror(errno)); - if (TNEF_glb.tnef_home) free(TNEF_glb.tnef_home); - return -1; - } - - // Attempt to open up the TNEF encoded file... if it fails - // then report the failed condition to syslog - // - if ((fp = fopen(filename,"r")) == NULL) - { - LOGGER_log("%s:%d:TNEF_main:ERROR: opening file %s for reading (%s)\n", FL, filename,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: When allocating %d bytes for loading file (%s)\n", FL,__func__, size,strerror(errno)); if (TNEF_glb.tnef_home) free(TNEF_glb.tnef_home); return -1; } // Attempt to read in the entire file - // nread = fread(tnef_stream, sizeof(uint8), size, fp); - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_main:DEBUG: Read %d bytes\n", FL, nread); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Read %d bytes\n", FL,__func__, nread); // If we did not read in all the bytes, then let syslogs know! - // if (nread < size) { - LOGGER_log("%s:%d:TNEF_main:ERROR: while reading stream from file %s (%s)\n", FL, filename,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: while reading stream from TNEF file (%s)\n", FL,__func__, strerror(errno)); if (TNEF_glb.tnef_home) free(TNEF_glb.tnef_home); return -1; } - // Close the file - // - fclose(fp); - // Proceed to decode the file - // - TNEF_decode_tnef(tnef_stream,size); + TNEF_decode_tnef(tnef_stream,size, file_dir); if (TNEF_glb.tnef_home) free(TNEF_glb.tnef_home); - - if (TNEF_DEBUG) LOGGER_log("%s:%d:TNEF_main:DEBUG: finished decoding.\n",FL); + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: finished decoding.\n",FL,__func__); return 0; } +/*------------------------------------------------------------------------ +Procedure: TNEF_main ID:1 +Purpose: Decodes a given TNEF encoded file +Input: +Output: +Errors: +------------------------------------------------------------------------*/ +int TNEF_main( char *filename, char *file_dir ) +{ + FILE *fp; -//--------------------------END. + if (TNEF_DEBUG) LOGGER_log("%s:%d:%s:DEBUG: Start, decoding %s\n",FL,__func__, filename); + // Attempt to open up the TNEF encoded file... if it fails + // then report the failed condition to syslog + if ((fp = fopen(filename,"r")) == NULL) + { + LOGGER_log("%s:%d:%s:ERROR: opening file %s for reading (%s)\n", FL,__func__, filename,strerror(errno)); + if (TNEF_glb.tnef_home) free(TNEF_glb.tnef_home); + return -1; + } + TNEF_file_processing(fp, file_dir); + + // Close the file + fclose(fp); + return 0; +} +//--------------------------END. diff --git a/tnef/tnef_api.h b/tnef/tnef_api.h index 9dd3b24..3ecefbe 100644 --- a/tnef/tnef_api.h +++ b/tnef/tnef_api.h @@ -3,12 +3,11 @@ #ifndef __TNEF_API__ #define __TNEF_API__ -int TNEF_init( void ); -int TNEF_main( char *filename ); +void TNEF_init( void ); +int TNEF_main( char *filename, char* file_dir ); int TNEF_set_filename_report_fn( int (*ptr_to_fn)(char *, char *)); int TNEF_set_verbosity( int level ); int TNEF_set_verbosity_contenttype( int level ); int TNEF_set_debug( int level ); -int TNEF_set_path( char *path ); int TNEF_set_decode( int level ); #endif diff --git a/uuencode.c b/uuencode.c index 2209b2a..87949db 100644 --- a/uuencode.c +++ b/uuencode.c @@ -19,11 +19,12 @@ The biggest issue is that the interfaces to the decoding functions are too speci #include "pldstr.h" #include "ffget.h" #include "filename-filters.h" +#include "strstack.h" +#include "mime_element.h" +#include "mime_headers.h" #include "uuencode.h" - - #ifndef FL #define FL __FILE__,__LINE__ #endif @@ -41,23 +42,22 @@ The biggest issue is that the interfaces to the decoding functions are too speci #define UUENCODE_WRITE_BUFFER_SIZE 4096 #define UUENCODE_WRITE_BUFFER_LIMIT 4000 - -static unsigned char uudec[256]={ - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\ +static unsigned char uudec[256] = { + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 \ }; @@ -68,6 +68,7 @@ struct UUENCODE_globals { int decode; int doubleCR_mode; int (*filename_decoded_report)(char *, char *); // Pointer to our filename reporting function + FFGET_FILE ffinf; }; static struct UUENCODE_globals glb; @@ -79,10 +80,10 @@ int uuencode_error; // this contains the error code for parents to check if th Function Name : UUENCODE_init Returns Type : int ----Parameter List - 1. void , + 1. void , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: @@ -106,10 +107,10 @@ int UUENCODE_init( void ) Function Name : UUENCODE_set_debug Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: @@ -127,10 +128,10 @@ int UUENCODE_set_debug( int level ) Function Name : UUENCODE_set_verbosity Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: @@ -148,10 +149,10 @@ int UUENCODE_set_verbosity( int level ) Function Name : UUENCODE_set_verbosity_contenttype Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: @@ -169,10 +170,10 @@ int UUENCODE_set_verbosity_contenttype( int level ) Function Name : UUENCODE_set_decode Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: @@ -190,10 +191,10 @@ int UUENCODE_set_decode( int level ) Function Name : UUENCODE_set_doubleCR_mode Returns Type : int ----Parameter List - 1. int level , + 1. int level , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: @@ -211,11 +212,11 @@ int UUENCODE_set_doubleCR_mode( int level ) Function Name : UUENCODE_set_filename_report_fn Returns Type : int ----Parameter List - 1. int (*ptr_to_fn)(char *, - 2. char *) , + 1. int (*ptr_to_fn)(char *, + 2. char *) , ------------------ - Exit Codes : - Side Effects : + Exit Codes : + Side Effects : -------------------------------------------------------------------- Comments: @@ -258,7 +259,7 @@ int UUENCODE_is_uuencode_header( char *line ) // colon after the BEGIN // // 2003-08-12:PLD:Added *(bp+6) test as recommended by Bernard Fischer to ensure there's more - // data after the begin + // data after the begin if ((bp)&&(strncasecmp(bp,"begin",5)==0)&&(*(bp+5)!=':')&&(isspace((int)*(bp+5)))&&(*(bp+6))) { @@ -269,7 +270,7 @@ int UUENCODE_is_uuencode_header( char *line ) if (fp) { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_is_uuencode_header:DEBUG: PERMISSIONS = %s\n", FL, fp); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: PERMISSIONS = %s\n", FL,__func__, fp); if ((atoi(fp) == 0)||(atoi(fp) > 777)) // Maximum is 777, because R+W+X = 7 { @@ -279,18 +280,32 @@ int UUENCODE_is_uuencode_header( char *line ) } else { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_is_uuencode_header:WARNING: Cannot read permissions for UUENCODED data file (%s)\n", FL, line); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:WARNING: Cannot read permissions for UUENCODED data file (%s)\n", FL,__func__, line); } } - return result; } +int UUENCODE_is_file_uuencoded( FILE *f ) +{ + int result = 0; + int linecount = 0; + int limit=20; + char line[ UUENCODE_STRLEN_MAX ]; - - - + while ((linecount < limit)&&(fgets(line, sizeof(line), f))) + { + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Testing line '%s'\n", FL,__func__, line); + if (UUENCODE_is_uuencode_header( line )) + { + result = 1; + break; + } + linecount++; + } + return result; +} /*------------------------------------------------------------------------ Procedure: UUENCODE_is_file_uuenc ID:1 @@ -304,53 +319,60 @@ Output: 0 = not uuencoded 1 = _probably_ uuencoded. Errors: ------------------------------------------------------------------------*/ -int UUENCODE_is_file_uuencoded( char *fname ) +int UUENCODE_is_diskfile_uuencoded( char *fname ) { int result = 0; - int linecount = 0; - int limit=20; - char line[ UUENCODE_STRLEN_MAX ]; FILE *f; f = fopen(fname,"r"); if (!f) { - LOGGER_log("%s:%d:UUENCODE_is_file_uuencoded:ERROR: cannot open file '%s' for reading (%s)", FL, fname,strerror(errno)); + LOGGER_log("%s:%d:%s:ERROR: cannot open file '%s' for reading (%s)", FL,__func__, fname,strerror(errno)); uuencode_error = UUENCODE_STATUS_CANNOT_OPEN_FILE; return -1; } - while ((linecount < limit)&&(fgets(line, sizeof(line), f))) - { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_is_file_uuencoded:DEBUG: Testing line '%s'\n", FL, line); - if (UUENCODE_is_uuencode_header( line )) - { - result = 1; - break; - } - linecount++; - } - + result = UUENCODE_is_file_uuencoded(f); fclose(f); - return result; } +FILE * UUENCODE_make_file_obj (char *input_filename) +{ + FILE *inf = fopen(input_filename,"r"); + if (!inf) + { + LOGGER_log("%s:%d:%s:ERROR: Cannot open file '%s' for reading (%s)", FL,__func__, input_filename, strerror(errno)); + uuencode_error = UUENCODE_STATUS_CANNOT_OPEN_FILE; + return NULL; + } + return inf; +} + +FFGET_FILE * UUENCODE_make_sourcestream( FILE *f) +{ + if (f == NULL) + return NULL; + fseek(f, 0, SEEK_SET); + FFGET_setstream(&(glb.ffinf), f); + FFGET_set_watch_SDL( glb.doubleCR_mode ); + + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Creation done. [FFGET-FILE=%p, FILE=%p]\n", FL,__func__, &(glb.ffinf), f); + return &(glb.ffinf); +} /*-----------------------------------------------------------------\ Function Name : UUENCODE_decode_uu Returns Type : int ----Parameter List - 1. FFGET_FILE *f, Source Data Stream - 2. char *unpackdir, Directory to prefix to our write output - 3. char *input_filename, The fully pathed input filename, containing UU data - 4. char *out_filename, Pointer to a buffer where we will write the filename of the UU data - 5. int out_filename_size, out_filename buffers size - 6. int decode_whole_file, 0 == only first segment, >0 == all - 7. int keep , Keep the files we create, don't delete + 1. FFGET_FILE *f, Source Data Stream + 2. char *out_filename, Pointer to a buffer where we will write the filename of the UU data + 3. int decode_whole_file, 0 == only first segment, >0 == all + 4. unpack file metadata + 5. related MIME headers ------------------ Exit Codes : Returns the number of attachments decoded in the data - Side Effects : + Side Effects : -------------------------------------------------------------------- Comments: @@ -358,13 +380,12 @@ int UUENCODE_is_file_uuencoded( char *fname ) Changes: \------------------------------------------------------------------*/ -int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, char *out_filename, int out_filename_size, int decode_whole_file, int keep ) +int UUENCODE_decode_uu( FFGET_FILE *f, char *out_filename, int decode_whole_file, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ) { int filename_found = 0; char buf[ UUENCODE_STRLEN_MAX ]; - char *bp = buf, *fn, *fp; + char *bp = buf, *fn = NULL, *fp = NULL; int n, i, expected; - char fullpath[ UUENCODE_STRLEN_MAX ]=""; struct PLD_strtok tx; unsigned char *writebuffer = NULL; unsigned char *wbpos; @@ -372,60 +393,18 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch int loop = 0; int buflen = 0; int filecount = 0; - FFGET_FILE ffinf; // Local static FFGET struct used if *f is NULL - FFGET_FILE *finf; // Points to either *f or &ffinf - FILE *outf; - int outfo =0; // set if outfile was opened. - FILE *inf = NULL; - int output_filename_supplied = 0; - int start_found = 0; - if ((out_filename != NULL)) - { - if ((out_filename[0] != '\0')) - { - output_filename_supplied = 1; - } - } + int output_filename_supplied = (out_filename != NULL) && (out_filename[0] != '\0'); + int start_found = 0; bp = buf; - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Starting.(input=%s,output=%s)\n", FL, input_filename,out_filename ); - - - // If no FFGET_FILE param is passed to us directly, then we must create out own. - - if (!f) - { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: NULL FFGET source stream given to us, create our own.\n",FL); - - // Setup the full source-data file path. - snprintf(fullpath, sizeof(fullpath),"%s", input_filename ); - - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Full INPUT file path set as '%s'\n", FL, fullpath); - - inf = fopen(fullpath,"r"); - if (!inf) - { - LOGGER_log("%s:%d:UUENCODE_decode_uu:ERROR: Cannot open file '%s' for reading (%s)", FL, fullpath, strerror(errno)); - uuencode_error = UUENCODE_STATUS_CANNOT_OPEN_FILE; - return -1; - } - - FFGET_setstream(&ffinf, inf); - FFGET_set_watch_SDL( glb.doubleCR_mode ); - finf = &ffinf; - - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Creation done. [FFGET-FILE=%p, FILE=%p]\n", FL, finf, inf); - } else { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: File handle already exists to read from, using",FL); - finf = f; - } + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Starting.(input=%s,output=%s)\n", FL,__func__, hinfo->filename,out_filename ); writebuffer = malloc( UUENCODE_WRITE_BUFFER_SIZE *sizeof(unsigned char)); if (!writebuffer) { - LOGGER_log("%s:%d:UUENCODE_decode_uu:ERROR: cannot allocate 100K of memory for the write buffer",FL); + LOGGER_log("%s:%d:%s:ERROR: cannot allocate 100K of memory for the write buffer",FL,__func__); uuencode_error = UUENCODE_STATUS_CANNOT_ALLOCATE_MEMORY; return -1; } @@ -434,45 +413,35 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch wbcount = 0; } + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Beginning.(%s)\n",FL,__func__,hinfo->filename); - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Beginning.(%s)\n",FL,fullpath); - - - while (!FFGET_feof(finf)) + while (!FFGET_feof(f)) { filename_found = 0; - - // First lets locate the BEGIN line of this UUDECODE file - - // if (output_filename_supplied == 0) - - if (1) /** 20041105-23H00:PLD: Stepan Kasal - UUbegin patch **/ { - - while (FFGET_fgets(buf, sizeof(buf), finf)) + while (FFGET_fgets(buf, sizeof(buf), f)) { + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: BUFFER: \n%s\n", FL,__func__, buf); - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: BUFFER: \n%s\n", FL, buf); - - // Check for the presence of 'BEGIN', but make sure it's not followed by a + // Check for the presence of 'BEGIN', but make sure it's not followed by a // colon ( which indicates a VCARD instead of UUENCODE if ((strncasecmp(buf,"begin",5)==0)&&(buf[5] !=':')&&(isspace((int)buf[5]))) { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Located BEGIN\n",FL); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Located BEGIN\n",FL,__func__); // Okay, so the line contains begin at the start, now, lets get the decode details fp = fn = NULL; bp = PLD_strtok(&tx, buf, " \n\r\t"); // Get the begin - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: BEGIN = '%s'\n", FL, bp); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: BEGIN = '%s'\n", FL,__func__, bp); if (bp) fp = PLD_strtok(&tx, NULL, " \n\r\t"); // Get the file-permissions - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Permissions/Name = '%s'\n", FL, fp); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Permissions/Name = '%s'\n", FL,__func__, fp); if (fp) fn = PLD_strtok(&tx, NULL, "\n\r"); // Get the file-name - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Name = '%s'\n", FL, fn); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Name = '%s'\n", FL,__func__, fn); if (!fn) { @@ -482,19 +451,17 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch if ((!bp)&&(!f)) { - LOGGER_log("%s:%d:UUENCODE_decode_uu:WARNING: unable to obtain filename from UUencoded text file header", FL); + LOGGER_log("%s:%d:%s:WARNING: unable to obtain filename from UUencoded text file header", FL,__func__); if (writebuffer) free(writebuffer); - fclose(inf); uuencode_error = UUENCODE_STATUS_CANNOT_FIND_FILENAME; return -1; } - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Full path = (%s)\n",FL,bp); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Full path = (%s)\n",FL,__func__,bp); filename_found = 1; break; } // If line starts with BEGIN - } // While more lines in the INPUT file. } @@ -505,58 +472,44 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch { filename_found = 1; bp = out_filename; - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Output filename set to '%s'",FL, bp); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Output filename set to '%s'",FL,__func__, bp); } - - - // If we have a filename, and we have our bp as NON-null, then we shall commence // to decode the UUencoded data from the stream. if ((filename_found != 0)&&(bp)) { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Located filename (%s), now decoding.\n", FL, bp); + MIME_element* cur_mime = NULL; + + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Located filename (%s), now decoding.\n", FL,__func__, bp); // Clean up the file name - FNFILTER_filter( bp, out_filename_size ); + FNFILTER_filter( bp, 255 ); /* the longest for most of filesystems */ // If our filename wasn't supplied via the params, then copy it over here - if (output_filename_supplied == 0) snprintf( out_filename, out_filename_size, "%s", bp ); - + if (output_filename_supplied == 0) + out_filename = strdup(bp); - // Create the new output full path + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Filename = (%s)\n", FL,__func__, fn); - snprintf(fullpath, sizeof(fullpath), "%s/%s", unpackdir, bp ); - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Filename = (%s)\n", FL, fullpath); - - outf = fopen(fullpath, "wb"); - if (!outf) - { - LOGGER_log("%s:%d:UUENCODE_decode_uu:ERROR: Cannot open file '%s' (%s)", FL, fullpath,strerror(errno)); - if (writebuffer) free(writebuffer); - uuencode_error = UUENCODE_STATUS_CANNOT_OPEN_FILE; - return -1; - } - else outfo = 1; + cur_mime = MIME_element_add (NULL, unpack_metadata, fn, hinfo->content_type_string, hinfo->content_transfer_encoding_string, hinfo->name, hinfo->current_recursion_level, 1, filecount, __func__); // Allocate the write buffer. By using the write buffer we gain an additional 10% in performance // due to the lack of function call (fwrite) overheads // Okay, now we have the UUDECODE data to decode... - wbcount = 0; wbpos = writebuffer; - while (outf) + while (cur_mime->f) { - // for each input line - FFGET_fgets(buf, sizeof(buf), finf); - if (UUENCODE_DPEDANTIC) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Read line:\n%s",FL,buf); - if (FFGET_feof(finf) != 0) + FFGET_fgets(buf, sizeof(buf), f); + if (UUENCODE_DPEDANTIC) LOGGER_log("%s:%d:%s:DEBUG: Read line:\n%s",FL,__func__,buf); + if (FFGET_feof(f) != 0) { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:WARNING: Short file (%s)\n",FL, fullpath); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:WARNING: Short file (%s)\n",FL,__func__, hinfo->filename); if (writebuffer != NULL) free(writebuffer); uuencode_error = UUENCODE_STATUS_SHORT_FILE; return -1; @@ -566,20 +519,18 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch if (strncasecmp(buf,"end",3)==0) { - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: End of UUencoding detected\n",FL); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: End of UUencoding detected\n",FL,__func__); break; } if ( !strpbrk(buf,"\r\n") ) { - LOGGER_log("%s:%d:UUENCODE_decode_uu:WARNING: Excessive length line\n",FL); + LOGGER_log("%s:%d:%s:WARNING: Excessive length line\n",FL,__func__); } // The first char of the line indicates how many bytes are to be expected - n = uudec[(int)*buf]; - // If the line is a -blank- then break out. if ((start_found == 0)&&((*buf == '\n')||(*buf == '\r'))) continue; @@ -601,7 +552,7 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch // In order to reduce function call overheads, we've bought the UUDecoding // bit shifting routines into the UUDecode main decoding routines. This should // save us about 250,000 function calls per Mb. - // UUENCODE_outdec(bp, outf, n); + // UUENCODE_outdec(bp, cur_mime->f, n); char c[3]; int m = n; @@ -615,9 +566,9 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch if ( wbcount >= UUENCODE_WRITE_BUFFER_LIMIT ) { size_t bc; - bc = fwrite(writebuffer, 1, wbcount, outf); + bc = fwrite(writebuffer, 1, wbcount, cur_mime->f); if (bc != wbcount) { - LOGGER_log("%s:%d:ERROR: Attempted to write %ld bytes, only wrote %ld\n", FL, wbcount, bc); + LOGGER_log("%s:%d:ERROR: Attempted to write %ld bytes, only wrote %ld\n", FL,__func__, wbcount, bc); } wbpos = writebuffer; wbcount = 0; @@ -642,18 +593,16 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch } // While (1) - if ((outfo)&&(wbcount > 0)) + if ((cur_mime->f != NULL)&&(wbcount > 0)) { - size_t bc; - bc = fwrite(writebuffer, 1, wbcount, outf); + size_t bc = fwrite(writebuffer, 1, wbcount, cur_mime->f); + if (bc != wbcount) { - LOGGER_log("%s:%d:ERROR: Attempted to write %ld bytes, only wrote %ld\n", FL, wbcount, bc); + LOGGER_log("%s:%d:ERROR: Attempted to write %ld bytes, only wrote %ld\n", FL,__func__, wbcount, bc); } - } - - if (outfo) fclose(outf); + MIME_element_deactivate(cur_mime, unpack_metadata); // Call our reporting function, else, if no function is defined, use the default // standard call @@ -661,47 +610,33 @@ int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, ch { if (glb.filename_decoded_report == NULL) { - LOGGER_log("Decoded: %s\n", fullpath); + LOGGER_log("Decoded: %s\n", hinfo->filename); } else { - glb.filename_decoded_report( fullpath, (glb.verbosity_contenttype>0?"uuencoded":NULL) ); + glb.filename_decoded_report( hinfo->filename, (glb.verbosity_contenttype>0?"uuencoded":NULL) ); } } filecount++; - } // If valid filename was found for UUdecode else { out_filename[0] = '\0'; - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: No FILENAME was found in data...\n",FL); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: No FILENAME was found in data...\n",FL,__func__); } - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Segment completed\n",FL); + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Segment completed\n",FL,__func__); // If this file was a result of the x-uuencode content encoding, then we need to exit out // as we're reading in the -stream-, and we dont want to carry on reading because we'll // end up just absorbing email data which we weren't supposed to. - if ((f)&&( !decode_whole_file )) break; - - } // While !feof(inf) - - if (writebuffer) free(writebuffer); - if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:UUENCODE_decode_uu:DEBUG: Completed\n",FL); - - if (inf) fclose(inf); - + if (UUENCODE_DNORMAL) LOGGER_log("%s:%d:%s:DEBUG: Completed\n",FL,__func__); return filecount; } - - - - - diff --git a/uuencode.h b/uuencode.h index 07c4f16..cedbca6 100644 --- a/uuencode.h +++ b/uuencode.h @@ -1,8 +1,9 @@ -#define UUENCODE_STATUS_SHORT_FILE 100 -#define UUENCODE_STATUS_CANNOT_OPEN_FILE 101 -#define UUENCODE_STATUS_CANNOT_ALLOCATE_MEMORY 102 -#define UUENCODE_STATUS_CANNOT_FIND_FILENAME 103 -#define UUENCODE_STATUS_OK 0 + +#define UUENCODE_STATUS_SHORT_FILE 100 +#define UUENCODE_STATUS_CANNOT_OPEN_FILE 101 +#define UUENCODE_STATUS_CANNOT_ALLOCATE_MEMORY 102 +#define UUENCODE_STATUS_CANNOT_FIND_FILENAME 103 +#define UUENCODE_STATUS_OK 0 extern int uuencode_error; @@ -18,7 +19,9 @@ int UUENCODE_set_doubleCR_mode( int level ); int UUENCODE_set_filename_report_fn( int (*ptr_to_fn)(char *, char *) ); int UUENCODE_is_uuencode_header( char *line ); -int UUENCODE_is_file_uuencoded( char *fname ); +int UUENCODE_is_diskfile_uuencoded( char *fname ); -int UUENCODE_decode_uu( FFGET_FILE *f, char *unpackdir, char *input_filename, char *out_filename, int out_filename_size, int decode_whole_file, int keep ); +int UUENCODE_decode_uu( FFGET_FILE *f, char *out_filename, int decode_whole_file, RIPMIME_output *unpack_metadata, struct MIMEH_header_info *hinfo ); +FILE * UUENCODE_make_file_obj (char *input_filename); +FFGET_FILE * UUENCODE_make_sourcestream( FILE *f);