From 59f59a15efe901fa521fb3c094eeadbece09de76 Mon Sep 17 00:00:00 2001 From: nvcnvn Date: Thu, 5 Feb 2015 22:22:06 +0700 Subject: [PATCH 1/3] fix panic error when extracting boundary without surrounding quotes --- message.go | 43 +++++++++++++++++++++++++++++++++++-------- message_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 message_test.go diff --git a/message.go b/message.go index d7b5a81..9217b93 100644 --- a/message.go +++ b/message.go @@ -4,7 +4,6 @@ import ( "crypto/rand" "encoding/base64" "log" - "regexp" "strings" "time" ) @@ -116,14 +115,11 @@ func (content *Content) ParseMIMEBody() *MIMEBody { if hdr, ok := content.Headers["Content-Type"]; ok { if len(hdr) > 0 { - re := regexp.MustCompile("boundary=\"([^\"]+)\"") - match := re.FindStringSubmatch(hdr[0]) - if len(match) < 2 { - log.Printf("Boundary not found: %s", hdr[0]) + boundary := extractBoundary(hdr[0]) + var p []string + if len(boundary) > 0 { + p = strings.Split(content.Body, "--"+boundary) } - log.Printf("Got boundary: %s", match[1]) - - p := strings.Split(content.Body, "--"+match[1]) for _, s := range p { if len(s) > 0 { @@ -204,3 +200,34 @@ func ContentFromString(data string) *Content { Body: x[0], } } + +// extractBoundary extract boundary string in contentType. +// It returns empty string if no valid boundary found +func extractBoundary(contentType string) string { + var boundary string + // first searching for the 'boundary=' token + boundaryIdx := strings.Index(contentType, "boundary=") + if boundaryIdx > -1 && len(contentType) > boundaryIdx+9 { + // then id check if what is the next char after '=' + firstCharIdx := boundaryIdx + 9 + if contentType[firstCharIdx] == '"' { + // ok, searching for the close quote + closeQuoteIdx := strings.Index(contentType[firstCharIdx+1:], "\"") + if closeQuoteIdx > -1 { + boundary = contentType[firstCharIdx+1 : firstCharIdx+closeQuoteIdx+1] + } + } else { + // that mean the boundary not quoted, check for ';' or 'space' + // or any kind of newline + terminateIdx := strings.IndexAny(contentType[firstCharIdx:], "; \r\n") + if terminateIdx > -1 { + boundary = contentType[firstCharIdx : firstCharIdx+terminateIdx] + } else { + // the boundary is the last param of contentType + boundary = contentType[firstCharIdx:] + } + } + } + + return boundary +} diff --git a/message_test.go b/message_test.go new file mode 100644 index 0000000..32794a7 --- /dev/null +++ b/message_test.go @@ -0,0 +1,27 @@ +package data + +import ( + "testing" +) + +func TestExtractBoundary(t *testing.T) { + contents := []struct { + content string + expect string + }{ + { + `multipart/alternative; boundary="_----------=_MCPart_498914860"`, + `_----------=_MCPart_498914860`, + }, + { + `multipart/alternative; boundary=047d7bd74a2049b624050d805118`, + `047d7bd74a2049b624050d805118`, + }, + } + + for _, c := range contents { + if b := extractBoundary(c.content); b != c.expect { + t.Fatal("extractBoundary expect", c.expect, "but get", b) + } + } +} From 70e57e825d83dadcfcc5f56a1c063b43fb2c9153 Mon Sep 17 00:00:00 2001 From: nvcnvn Date: Thu, 5 Feb 2015 22:32:02 +0700 Subject: [PATCH 2/3] add back original log printing line --- message.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/message.go b/message.go index 9217b93..c0bcd05 100644 --- a/message.go +++ b/message.go @@ -119,6 +119,9 @@ func (content *Content) ParseMIMEBody() *MIMEBody { var p []string if len(boundary) > 0 { p = strings.Split(content.Body, "--"+boundary) + log.Printf("Got boundary: %s", boundary) + } else { + log.Printf("Boundary not found: %s", hdr[0]) } for _, s := range p { From 6a26f27d84d1ebaa102040aa4e7cd90b029313b4 Mon Sep 17 00:00:00 2001 From: nvcnvn Date: Thu, 5 Feb 2015 23:44:56 +0700 Subject: [PATCH 3/3] use mime package to extract boundary --- message.go | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/message.go b/message.go index c0bcd05..3f28a81 100644 --- a/message.go +++ b/message.go @@ -4,6 +4,7 @@ import ( "crypto/rand" "encoding/base64" "log" + "mime" "strings" "time" ) @@ -207,30 +208,9 @@ func ContentFromString(data string) *Content { // extractBoundary extract boundary string in contentType. // It returns empty string if no valid boundary found func extractBoundary(contentType string) string { - var boundary string - // first searching for the 'boundary=' token - boundaryIdx := strings.Index(contentType, "boundary=") - if boundaryIdx > -1 && len(contentType) > boundaryIdx+9 { - // then id check if what is the next char after '=' - firstCharIdx := boundaryIdx + 9 - if contentType[firstCharIdx] == '"' { - // ok, searching for the close quote - closeQuoteIdx := strings.Index(contentType[firstCharIdx+1:], "\"") - if closeQuoteIdx > -1 { - boundary = contentType[firstCharIdx+1 : firstCharIdx+closeQuoteIdx+1] - } - } else { - // that mean the boundary not quoted, check for ';' or 'space' - // or any kind of newline - terminateIdx := strings.IndexAny(contentType[firstCharIdx:], "; \r\n") - if terminateIdx > -1 { - boundary = contentType[firstCharIdx : firstCharIdx+terminateIdx] - } else { - // the boundary is the last param of contentType - boundary = contentType[firstCharIdx:] - } - } + _, params, err := mime.ParseMediaType(contentType) + if err == nil { + return params["boundary"] } - - return boundary + return "" }