From 7c0dbbb41377498f99e7b6547315fe6e612175d8 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Mon, 6 May 2019 01:33:28 +0000
Subject: [PATCH] MIME header fields are case-insensitive. <sigh> So replace
 some strstr() calls with either (new local function) strStartWith_i() or
 strcasestr(), depending. strStartWith_i() return length of the matched word,
 so no need to sprinkle about magic numeric constants everywhere. The extra
 calls to strlen() are worth the code clarity / reliability, methinks. TODO:
 find out if there's a way to calculate the length of string-constants at
 compile-time (?).

---
 src/smblib/smbtxt.c | 46 +++++++++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/src/smblib/smbtxt.c b/src/smblib/smbtxt.c
index 1170ce84d8..a9b4f871d3 100644
--- a/src/smblib/smbtxt.c
+++ b/src/smblib/smbtxt.c
@@ -251,17 +251,26 @@ char* qp_decode(char* buf)
 	return buf;
 }
 
+static size_t strStartsWith_i(const char* buf, const char* match)
+{
+	size_t len = strlen(match);
+	if (strnicmp(buf, match, len) == 0)
+		return len;
+	return 0;
+}
+
 static enum content_transfer_encoding mime_getxferencoding(const char* beg, const char* end)
 {
 	const char* p = beg;
 
 	while(p < end) {
 		SKIP_WHITESPACE(p);
-		if(strnicmp(p, "content-transfer-encoding:", 26) != 0) {
+		size_t len = strStartsWith_i(p, "content-transfer-encoding:");
+		if(len < 1) {
 			FIND_CHAR(p, '\n');
 			continue;
 		}
-		p += 26;
+		p += len;
 		SKIP_WHITESPACE(p);
 		if(strnicmp(p, "base64", 6) == 0)
 			return CONTENT_TRANFER_ENCODING_BASE64;
@@ -283,11 +292,12 @@ static BOOL mime_getattachment(const char* beg, const char* end, char* attachmen
 
 	while(p < end) {
 		SKIP_WHITESPACE(p);
-		if(strnicmp(p, "content-disposition:", 20) != 0) {
+		size_t len = strStartsWith_i(p, "content-disposition:");
+		if(len < 1) {
 			FIND_CHAR(p, '\n');
 			continue;
 		}
-		p += 20;
+		p += len;
 		SKIP_WHITESPACE(p);
 		if(strnicmp(p, "inline", 6) == 0) {
 			FIND_CHAR(p, '\n');
@@ -338,8 +348,9 @@ void SMBCALL smb_parse_content_type(const char* content_type, char** subtype, ch
 	char* p;
 	if((p = strstr(buf, "\r\n\r\n")) != NULL)	/* Don't parse past the end of header */
 		*p = 0;
-	if((p = strstr(buf, "text/")) == buf) {
-		p += 5;
+	size_t len = strStartsWith_i(buf, "text/");
+	if(len > 0) {
+		p = buf + len;
 		if(subtype != NULL) {
 			if((*subtype = strdup(p)) != NULL) {
 				char* tp = *subtype;
@@ -350,7 +361,7 @@ void SMBCALL smb_parse_content_type(const char* content_type, char** subtype, ch
 				*tp = 0;
 			}
 		}
-		if(charset != NULL && (p = strstr(p, "charset=")) != NULL) {
+		if(charset != NULL && (p = strcasestr(p, "charset=")) != NULL) {
 			p += 8;
 			if(*p == '"')
 				p++;
@@ -365,7 +376,7 @@ void SMBCALL smb_parse_content_type(const char* content_type, char** subtype, ch
 	}
 }
 
-/* Find the specified content-type in a MIME-encoded message body, recursively */
+/* Find the specified content-type in a multi-pat MIME-encoded message body, recursively */
 static const char* mime_getcontent(const char* buf, const char* content_type, const char* content_match
 	,int depth, enum content_transfer_encoding* encoding, char** charset, char* attachment, size_t attachment_len, int index)
 {
@@ -386,15 +397,14 @@ static const char* mime_getcontent(const char* buf, const char* content_type, co
 		return NULL;
 	if(content_type == NULL)	/* Not MIME-encoded */
 		return NULL;
-	if(strstr(content_type, "multipart/alternative;") == content_type)
-		content_type += 22;
-	else if(strstr(content_type, "multipart/mixed;") == content_type)
-		content_type +=16;
-	else if(strstr(content_type, "multipart/report;") == content_type)
-		content_type +=17;
-	else
+	size_t len;
+	if(((len = strStartsWith_i(content_type, "multipart/alternative;")) < 1)
+	&& ((len = strStartsWith_i(content_type, "multipart/mixed;")) < 1)
+	&& ((len = strStartsWith_i(content_type, "multipart/report;")) < 1)
+	&& ((len = strStartsWith_i(content_type, "multipart/")) < 1))
 		return NULL;
-	p = strstr(content_type, "boundary=");
+	content_type += len;
+	p = strcasestr(content_type, "boundary=");
 	if(p == NULL)
 		return NULL;
 	p += 9;
@@ -414,8 +424,8 @@ static const char* mime_getcontent(const char* buf, const char* content_type, co
 			continue;
 		for(content_type = txt; content_type < p; content_type++) {
 			SKIP_WHITESPACE(content_type);
-			if(strnicmp(content_type, "Content-Type:", 13) == 0) {
-				content_type += 13;
+			if((len = strStartsWith_i(content_type, "Content-Type:")) > 0) {
+				content_type += len;
 				SKIP_WHITESPACE(content_type);
 				break;
 			}
-- 
GitLab