diff --git a/src/smblib/smblib.h b/src/smblib/smblib.h index 5669890e9e9a3f75b29b12ca4c868f69bebe6a59..2e1e94d025bc4721fd4692ae1328bb66a01f04ae 100644 --- a/src/smblib/smblib.h +++ b/src/smblib/smblib.h @@ -99,13 +99,16 @@ #define SMB_ALL_REFS 0 /* Free all references to data */ -#define GETMSGTXT_TAILS (1<<0) /* Get message tail(s) */ -#define GETMSGTXT_NO_BODY (1<<1) /* Don't retrieve message body */ -#define GETMSGTXT_NO_HFIELDS (1<<2) /* Don't include text header fields */ + /* smb_getmsgtxt() mode flags */ +#define GETMSGTXT_TAILS (1<<0) /* Incude message tail(s) */ +#define GETMSGTXT_NO_BODY (1<<1) /* Exclude message body */ +#define GETMSGTXT_NO_HFIELDS (1<<2) /* Exclude text header fields */ #define GETMSGTXT_PLAIN (1<<3) /* Get plaintext portion only of MIME-encoded body (all, otherwise) */ + /* common smb_getmsgtxt() mode values */ #define GETMSGTXT_BODY_ONLY GETMSGTXT_NO_HFIELDS #define GETMSGTXT_TAIL_ONLY (GETMSGTXT_TAILS|GETMSGTXT_NO_BODY|GETMSGTXT_NO_HFIELDS) #define GETMSGTXT_ALL GETMSGTXT_TAILS +#define GETMSGTXT_NO_TAILS 0 /* Exclude message tails(s) */ #define SMB_IS_OPEN(smb) ((smb)->shd_fp!=NULL) @@ -266,9 +269,11 @@ SMBEXPORT enum smb_net_type SMBCALL smb_get_net_type_by_addr(const char* addr); SMBEXPORT void SMBCALL smb_dump_msghdr(FILE* fp, smbmsg_t* msg); /* smbtxt.c */ -SMBEXPORT char* SMBCALL smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, ulong mode); -SMBEXPORT char* SMBCALL smb_getplaintext(smbmsg_t* msg, char* buf); -SMBEXPORT uint8_t* SMBCALL smb_getattachment(smbmsg_t* msg, char* buf, char* filename, size_t filename_len, uint32_t* filelen, int index); +SMBEXPORT char* SMBCALL smb_getmsgtxt(smb_t*, smbmsg_t*, ulong mode); +SMBEXPORT char* SMBCALL smb_getplaintext(smbmsg_t*, char* body); +SMBEXPORT char* SMBCALL smb_getcontenttype(smbmsg_t*); +SMBEXPORT uint8_t* SMBCALL smb_getattachment(smbmsg_t*, char* body, char* filename, size_t filename_len, uint32_t* filelen, int index); +SMBEXPORT ulong SMBCALL smb_countattachments(smb_t*, smbmsg_t*, const char* body); /* smbfile.c */ SMBEXPORT int SMBCALL smb_feof(FILE* fp); diff --git a/src/smblib/smbtxt.c b/src/smblib/smbtxt.c index 2580e1ecbd339ca48aca3acbd5aca2f57f993a5c..07c0985d0bde7fad7ae1ed612fc052719e98b0f1 100644 --- a/src/smblib/smbtxt.c +++ b/src/smblib/smbtxt.c @@ -338,8 +338,8 @@ static char* mime_getcontent(char* buf, const char* content_type, const char* co int found = 0; if(content_match != NULL) { - match_len = sprintf(match1, "Content-Type: %s;", content_match); - sprintf(match2, "Content-Type: %s\r", content_match); + match_len = sprintf(match1, "%s;", content_match); + sprintf(match2, "%s\r", content_match); } if(depth > 2) @@ -372,8 +372,11 @@ static char* mime_getcontent(char* buf, const char* content_type, const char* co continue; for(content_type = txt; content_type < p; content_type++) { SKIP_WHITESPACE(content_type); - if(strnicmp(content_type, "Content-Type:", 13) == 0) + if(strnicmp(content_type, "Content-Type:", 13) == 0) { + content_type += 13; + SKIP_WHITESPACE(content_type); break; + } FIND_CHAR(content_type, '\r'); } if(content_type >= p) @@ -400,23 +403,31 @@ static char* mime_getcontent(char* buf, const char* content_type, const char* co return NULL; } +/* Returns the MIME content-type or NULL if not a MIME-encoded message */ +char* SMBCALL smb_getcontenttype(smbmsg_t* msg) +{ + int i; + + for(i = 0; i < msg->total_hfields; i++) { + if(msg->hfield[i].type == RFC822HEADER) { + if(strnicmp((char*)msg->hfield_dat[i], "Content-Type:", 13) == 0) { + char* result = msg->hfield_dat[i] + 13; + SKIP_WHITESPACE(result); + return result; + } + } + } + return NULL; /* not MIME */ +} + /* Get just the plain-text portion of a MIME-encoded message body */ /* Returns NULL if there is no MIME-encoded plain-text portion of the message */ char* SMBCALL smb_getplaintext(smbmsg_t* msg, char* buf) { - int i; char* txt; - char* content_type = NULL; + char* content_type = smb_getcontenttype(msg); enum content_transfer_encoding xfer_encoding = CONTENT_TRANFER_ENCODING_NONE; - for(i=0;i<msg->total_hfields;i++) { - if(msg->hfield[i].type==RFC822HEADER) { - if(strnicmp((char*)msg->hfield_dat[i],"Content-Type:",13)==0) { - content_type=msg->hfield_dat[i]; - break; - } - } - } if(content_type == NULL) /* not MIME */ return NULL; txt = mime_getcontent(buf, content_type, "text/plain", 0, &xfer_encoding @@ -442,21 +453,13 @@ char* SMBCALL smb_getplaintext(smbmsg_t* msg, char* buf) } /* Get just an attachment (just one) from MIME-encoded message body */ +/* This function is destructive (over-writes 'buf' with decoded attachment)! */ uint8_t* SMBCALL smb_getattachment(smbmsg_t* msg, char* buf, char* filename, size_t filename_len, uint32_t* filelen, int index) { - int i; char* txt; - char* content_type = NULL; + char* content_type = smb_getcontenttype(msg); enum content_transfer_encoding xfer_encoding = CONTENT_TRANFER_ENCODING_NONE; - for(i=0;i<msg->total_hfields;i++) { - if(msg->hfield[i].type==RFC822HEADER) { - if(strnicmp((char*)msg->hfield_dat[i],"Content-Type:",13)==0) { - content_type=msg->hfield_dat[i]; - break; - } - } - } if(content_type == NULL) /* not MIME */ return NULL; txt = mime_getcontent(buf, content_type, /* match-type: */NULL, 0, &xfer_encoding @@ -466,9 +469,43 @@ uint8_t* SMBCALL smb_getattachment(smbmsg_t* msg, char* buf, char* filename, siz int result = b64_decode(buf, strlen(buf), buf, strlen(buf)); if(result < 1) return NULL; - *filelen = result; + if(filelen != NULL) + *filelen = result; return (uint8_t*)buf; } return NULL; /* No attachment */ } + +/* Return number of file attachments contained in MIME-encoded message body */ +/* 'body' may be NULL if the body text is not already read/available */ +ulong SMBCALL smb_countattachments(smb_t* smb, smbmsg_t* msg, const char* body) +{ + char* content_type = smb_getcontenttype(msg); + + if(content_type == NULL) /* not MIME */ + return 0; + + ulong count = 0; + char* buf; + + if(body == NULL) + buf = smb_getmsgtxt(smb, msg, GETMSGTXT_ALL); + else + buf = strdup(body); + + if(buf == NULL) + return 0; + + char* tmp; + while((tmp = strdup(buf)) != NULL) { + uint8_t* attachment = smb_getattachment(msg, tmp, NULL, 0, NULL, count); + free(tmp); + if(attachment == NULL) + break; + count++; + } + + free(buf); + return count; +}