Browse Source

milestone - counts are correct

flashmob 6 years ago
parent
commit
6db20b95e5
2 changed files with 172 additions and 252 deletions
  1. 77 209
      backends/s_mime.go
  2. 95 43
      backends/s_mime_test.go

+ 77 - 209
backends/s_mime.go

@@ -80,9 +80,10 @@ type parser struct {
 	isHalting                   bool
 	isHalting                   bool
 
 
 	// mime variables
 	// mime variables
-	parts   []*mimeHeader
-	msgPos  uint
-	msgLine uint
+	parts           []*mimeHeader
+	msgPos          uint
+	msgLine         uint
+	lastBoundaryPos uint
 }
 }
 
 
 type mimeHeader struct {
 type mimeHeader struct {
@@ -210,6 +211,17 @@ func (p *parser) set(input []byte) {
 
 
 }
 }
 
 
+func (p *parser) skip(nBytes int) {
+
+	for i := 0; i < nBytes; i++ {
+		p.next()
+		if p.ch == 0 {
+			return
+		}
+	}
+
+}
+
 // boundary scans until next boundary string, returns error if not found
 // boundary scans until next boundary string, returns error if not found
 // syntax specified https://tools.ietf.org/html/rfc2046 p21
 // syntax specified https://tools.ietf.org/html/rfc2046 p21
 func (p *parser) boundary(contentBoundary string) (end bool, err error) {
 func (p *parser) boundary(contentBoundary string) (end bool, err error) {
@@ -219,12 +231,8 @@ func (p *parser) boundary(contentBoundary string) (end bool, err error) {
 				p.next()
 				p.next()
 			}
 			}
 		}
 		}
-		// todo: remove this
-		//temp := p.buf[p.pos-10:p.pos+45]
-		//_ = temp
 	}()
 	}()
-	// gensen chosu
-	// shotoku chomen sho
+
 	if len(contentBoundary) < 1 {
 	if len(contentBoundary) < 1 {
 		err = errors.New("content boundary too short")
 		err = errors.New("content boundary too short")
 	}
 	}
@@ -236,13 +244,16 @@ func (p *parser) boundary(contentBoundary string) (end bool, err error) {
 			// then let next() to advance the last char.
 			// then let next() to advance the last char.
 			// in case the boundary is the tail part of buffer, calling next()
 			// in case the boundary is the tail part of buffer, calling next()
 			// will wait until we get a new buffer
 			// will wait until we get a new buffer
-			p.pos = p.pos + i + len(boundary) - 1
-			p.next()
+
+			p.skip(i)
+			p.lastBoundaryPos = p.msgPos - 1 // - uint(len(boundary))
+			p.skip(len(boundary))
 			end = p.boundaryEnd()
 			end = p.boundaryEnd()
 			p.transportPadding()
 			p.transportPadding()
-			if p.ch != '\n' {
+			if p.ch != '\n' && p.ch != 0 {
 				err = errors.New("boundary new line expected")
 				err = errors.New("boundary new line expected")
 			}
 			}
+
 			return
 			return
 
 
 		} else {
 		} else {
@@ -262,8 +273,7 @@ func (p *parser) boundary(contentBoundary string) (end bool, err error) {
 					p.boundaryMatched = 0
 					p.boundaryMatched = 0
 				}
 				}
 			}
 			}
-			p.pos = len(p.buf) - 1
-			p.next() // this will block until new bytes come in
+			p.skip(len(p.buf))
 			if p.ch == 0 {
 			if p.ch == 0 {
 				return false, io.EOF
 				return false, io.EOF
 			} else if p.boundaryMatched > 0 {
 			} else if p.boundaryMatched > 0 {
@@ -272,19 +282,21 @@ func (p *parser) boundary(contentBoundary string) (end bool, err error) {
 				if bytes.Compare(
 				if bytes.Compare(
 					p.buf[0:len(boundary)-p.boundaryMatched],
 					p.buf[0:len(boundary)-p.boundaryMatched],
 					[]byte(boundary[p.boundaryMatched:])) == 0 {
 					[]byte(boundary[p.boundaryMatched:])) == 0 {
+
 					// advance the pointer
 					// advance the pointer
-					p.pos += len(boundary) - p.boundaryMatched - 1
-					p.next()
+					p.skip(len(boundary) - p.boundaryMatched)
+
+					p.lastBoundaryPos = p.msgPos - 1 //- uint(len(boundary))
 					end = p.boundaryEnd()
 					end = p.boundaryEnd()
 					p.transportPadding()
 					p.transportPadding()
-					if p.ch != '\n' {
+					if p.ch != '\n' && p.ch != 0 {
 						err = errors.New("boundary new line expected")
 						err = errors.New("boundary new line expected")
 					}
 					}
 					return
 					return
 				}
 				}
 				p.boundaryMatched = 0
 				p.boundaryMatched = 0
 			}
 			}
-			_ = subject
+			//_ = subject
 		}
 		}
 	}
 	}
 }
 }
@@ -369,7 +381,7 @@ func (p *parser) header(mh *mimeHeader) (err error) {
 		}
 		}
 
 
 	}()
 	}()
-	mh.startingPos = p.msgPos
+
 	for {
 	for {
 
 
 		switch state {
 		switch state {
@@ -714,7 +726,6 @@ func (p *parser) body(mh *mimeHeader) (err error) {
 		} else {
 		} else {
 			fmt.Println("boundary end:", end)
 			fmt.Println("boundary end:", end)
 		}
 		}
-		mh.endingPosBody = p.msgPos
 		return
 		return
 	} else {
 	} else {
 		for {
 		for {
@@ -725,7 +736,6 @@ func (p *parser) body(mh *mimeHeader) (err error) {
 			}
 			}
 			if p.ch == '\n' && p.peek() == '\n' {
 			if p.ch == '\n' && p.peek() == '\n' {
 				p.next()
 				p.next()
-				mh.endingPosBody = p.msgPos
 				return
 				return
 			}
 			}
 
 
@@ -736,238 +746,96 @@ func (p *parser) body(mh *mimeHeader) (err error) {
 
 
 }
 }
 
 
-func (p *parser) mime(boundary string, depth string) (err error) {
-	count := 1
-	h := NewMimeHeader()
-
-	if p.ch >= 33 && p.ch <= 126 {
-		err = p.header(h)
-		if err != nil {
-			//				temp := p.buf[p.pos:p.pos+20]
-			//				_ = temp
-			return err
+func (p *parser) isMulti(part *mimeHeader) bool {
+	if part.contentType != nil {
+		if part.contentType.superType == "multipart" ||
+			part.contentType.superType == "message" {
+			return true
 		}
 		}
-	} else {
-		fmt.Println("empty header")
-	}
-
-	if p.ch == '\n' && p.peek() == '\n' {
-		p.next()
-		p.next()
-	}
-	if h.contentBoundary != "" {
-		boundary = h.contentBoundary
-
 	}
 	}
+	return false
+}
 
 
-	if end, bErr := p.boundary(boundary); bErr != nil {
-		return bErr
-	} else if end {
-		h.endingPosBody = p.msgPos
-		return
-	}
+func (p *parser) multi(part *mimeHeader, depth string) (err error) {
+	if part.contentType != nil {
+		if part.contentType.superType == "multipart" {
+			if end, bErr := p.boundary(part.contentBoundary); bErr != nil {
+				return bErr
+			} else if end {
 
 
-	if depth == "1" {
-		p.addPart(h, depth)
-	} else {
-		p.addPart(h, depth+"."+strconv.Itoa(count))
-		if h.contentType != nil &&
-			(h.contentType.superType == "message" ||
-				h.contentType.superType == "multipart") {
-			return p.mime(boundary, depth+"."+strconv.Itoa(count))
-		} else {
-			count++
+				part.endingPosBody = p.lastBoundaryPos
+				return
+			}
 		}
 		}
-	}
-
-	for {
-
-		var part mimeHeader
-
-		part = *NewMimeHeader()
-		if p.ch >= 33 && p.ch <= 126 {
-			err = p.header(&part)
+		if part.contentType.superType == "message" ||
+			part.contentType.superType == "multipart" {
+			err = p.mime(part, depth)
 			if err != nil {
 			if err != nil {
+
 				return err
 				return err
 			}
 			}
-		}
-		if p.ch == '\n' && p.peek() == '\n' {
-			p.next()
-			p.next()
-		}
 
 
-		p.addPart(&part, depth+"."+strconv.Itoa(count))
-		if part.contentType != nil &&
-			(part.contentType.superType == "message" ||
-				part.contentType.superType == "multipart") {
-			return p.mime(boundary, depth+"."+strconv.Itoa(count))
-		} else {
-			if end, bErr := p.boundary(boundary); bErr != nil {
-				return bErr
-			} else if end {
-				part.endingPosBody = p.msgPos
-				break
-			}
 		}
 		}
 
 
-		count++
-
 	}
 	}
 	return
 	return
-
 }
 }
 
 
-func (p *parser) mime2(boundary string, depth string) (err error) {
-	count := 1
-	h := NewMimeHeader()
-
-	if p.ch >= 33 && p.ch <= 126 {
-		err = p.header(h)
-		if err != nil {
-			//				temp := p.buf[p.pos:p.pos+20]
-			//				_ = temp
-			return err
-		}
-	} else {
-		fmt.Println("empty header")
-	}
-
-	if depth == "1" {
-		p.addPart(h, depth)
-	} else {
-		p.addPart(h, depth+"."+strconv.Itoa(count))
-		if h.contentType != nil &&
-			(h.contentType.superType == "message" ||
-				h.contentType.superType == "multipart") {
-			depth = depth + "." + strconv.Itoa(count)
-		}
-	}
-
-	if p.ch == '\n' && p.peek() == '\n' {
-		p.next()
-		p.next()
-	}
-	if h.contentBoundary != "" {
-		boundary = h.contentBoundary
-
-	}
-
-	if end, bErr := p.boundary(boundary); bErr != nil {
-		return bErr
-	} else if end {
-		h.endingPosBody = p.msgPos
-		return
-	}
+func (p *parser) mime(parent *mimeHeader, depth string) (err error) {
 
 
+	count := 1
 	for {
 	for {
 
 
 		var part mimeHeader
 		var part mimeHeader
 
 
 		part = *NewMimeHeader()
 		part = *NewMimeHeader()
+		part.startingPos = p.msgPos
 		if p.ch >= 33 && p.ch <= 126 {
 		if p.ch >= 33 && p.ch <= 126 {
 			err = p.header(&part)
 			err = p.header(&part)
 			if err != nil {
 			if err != nil {
 				return err
 				return err
 			}
 			}
+		} else {
+			moo := p.buf[p.pos:]
+			_ = moo
+			//break
 		}
 		}
 		if p.ch == '\n' && p.peek() == '\n' {
 		if p.ch == '\n' && p.peek() == '\n' {
 			p.next()
 			p.next()
 			p.next()
 			p.next()
 		}
 		}
-
-		p.addPart(&part, depth+"."+strconv.Itoa(count))
-		if part.contentType != nil &&
-			(part.contentType.superType == "message" ||
-				part.contentType.superType == "multipart") {
-			return p.mime(boundary, depth+"."+strconv.Itoa(count))
-		} else {
-
-			if end, bErr := p.boundary(boundary); bErr != nil {
-				return bErr
-			} else if end {
-				part.endingPosBody = p.msgPos
-				break
-			}
+		if part.contentBoundary == "" {
+			part.contentBoundary = parent.contentBoundary
 		}
 		}
-		count++
-
-	}
-	return
-
-}
-
-func (p *parser) mimeMsg(boundary string, depth string) (err error) {
-	count := 0
-	for {
-		count++
-		d := depth + "." + strconv.Itoa(count)
-		_ = d
-
-		{
-			h := NewMimeHeader()
-
-			if p.ch >= 33 && p.ch <= 126 {
-				err = p.header(h)
-				if err != nil {
-					//				temp := p.buf[p.pos:p.pos+20]
-					//				_ = temp
-					return err
-				}
-			} else {
-				fmt.Println("empty header")
-			}
-			if p.ch == '\n' && p.peek() == '\n' {
-				p.next()
-				p.next()
-			}
-
-			if h.contentBoundary != "" {
-				boundary = h.contentBoundary
-				if end, bErr := p.boundary(boundary); bErr != nil {
-					return bErr
-				} else if end {
-					return
-				}
-				err = p.mimeMsg(boundary, depth+"."+strconv.Itoa(count))
-				if err != nil {
-					return
-				}
-			} else {
-				// body-part end
-				for {
-					if end, bErr := p.boundary(boundary); bErr != nil {
-						return bErr
-					} else if end {
-						return
-					}
 
 
-				}
-
-			}
-
-			if p.ch == 0 {
-				return
-			}
+		part.startingPosBody = p.msgPos
+		partID := strconv.Itoa(count)
+		if depth != "" {
+			partID = depth + "." + strconv.Itoa(count)
+		}
+		p.addPart(&part, partID)
 
 
-			if h.contentType == nil {
-				fmt.Println("nope")
+		if p.isMulti(&part) {
+			err = p.multi(&part, partID)
+			part.endingPosBody = p.msgPos + 1 //p.lastBoundaryPos
+			if err != nil {
+				break
 			}
 			}
 
 
-			p.addPart(h, depth+"."+strconv.Itoa(count))
-			if h.contentType != nil &&
-				(h.contentType.superType == "message" ||
-					h.contentType.superType == "multipart") {
-
-				return p.mimeMsg(boundary, depth+"."+strconv.Itoa(count))
-			} else if end, bErr := p.boundary(boundary); bErr != nil {
+			return
+		} else {
+			if end, bErr := p.boundary(parent.contentBoundary); bErr != nil {
 				return bErr
 				return bErr
 			} else if end {
 			} else if end {
+				part.endingPosBody = p.lastBoundaryPos
 				return
 				return
 			}
 			}
+			part.endingPosBody = p.lastBoundaryPos
 
 
 		}
 		}
-
+		count++
 	}
 	}
+	return
 }
 }
 
 
 func (p *parser) close() error {
 func (p *parser) close() error {

+ 95 - 43
backends/s_mime_test.go

@@ -3,6 +3,7 @@ package backends
 import (
 import (
 	"bytes"
 	"bytes"
 	"fmt"
 	"fmt"
+	"strconv"
 	"testing"
 	"testing"
 )
 )
 
 
@@ -118,16 +119,15 @@ func TestBoundary(t *testing.T) {
 	part.contentBoundary = "-wololo-"
 	part.contentBoundary = "-wololo-"
 
 
 	// in the middle of the string
 	// in the middle of the string
-	p.inject([]byte("The quick brown fo-wololo-x jumped over the lazy dog"))
+	p.inject([]byte("The quick brown fo---wololo-\nx jumped over the lazy dog"))
 
 
 	_, err = p.boundary(part.contentBoundary)
 	_, err = p.boundary(part.contentBoundary)
 	if err != nil {
 	if err != nil {
 		t.Error(err)
 		t.Error(err)
 	}
 	}
 
 
-	//for c := p.next(); c != 0; c= p.next() {} // drain
-
-	p.inject([]byte("The quick brown fox jumped over the lazy dog-wololo-"))
+	// at the end (with the -- postfix)
+	p.inject([]byte("The quick brown fox jumped over the lazy dog---wololo---\n"))
 	_, err = p.boundary(part.contentBoundary)
 	_, err = p.boundary(part.contentBoundary)
 	if err != nil {
 	if err != nil {
 		t.Error(err)
 		t.Error(err)
@@ -138,8 +138,8 @@ func TestBoundary(t *testing.T) {
 
 
 	// boundary is split over multiple slices
 	// boundary is split over multiple slices
 	p.inject(
 	p.inject(
-		[]byte("The quick brown fox jumped ov-wolo"),
-		[]byte("lo-er the lazy dog"))
+		[]byte("The quick brown fox jumped ov---wolo"),
+		[]byte("lo---\ner the lazy dog"))
 	_, err = p.boundary(part.contentBoundary)
 	_, err = p.boundary(part.contentBoundary)
 	if err != nil {
 	if err != nil {
 		t.Error(err)
 		t.Error(err)
@@ -149,7 +149,7 @@ func TestBoundary(t *testing.T) {
 	// the boundary with an additional buffer in between
 	// the boundary with an additional buffer in between
 	p.inject([]byte("The quick brown fox jumped over the lazy dog"),
 	p.inject([]byte("The quick brown fox jumped over the lazy dog"),
 		[]byte("this is the middle"),
 		[]byte("this is the middle"),
-		[]byte("and thats the end-wololo-"))
+		[]byte("and thats the end---wololo---\n"))
 
 
 	_, err = p.boundary(part.contentBoundary)
 	_, err = p.boundary(part.contentBoundary)
 	if err != nil {
 	if err != nil {
@@ -203,37 +203,6 @@ func TestMimeContentQuotedParams(t *testing.T) {
 
 
 }
 }
 
 
-func msg() (err error) {
-	main := NewMimeHeader()
-	err = p.header(main)
-	if err != nil {
-		return err
-	}
-	p.addPart(main, "1")
-
-	if main.contentBoundary != "" {
-		// it's a message with mime parts
-
-		if end, bErr := p.boundary(main.contentBoundary); bErr != nil {
-			return bErr
-		} else if end {
-			return
-		}
-
-		if err = p.mimeMsg("", "1"); err != nil {
-			return err
-		}
-	} else {
-		// only contains one part (the body)
-		if err := p.body(main); err != nil {
-			return err
-		}
-	}
-	p.endBody(main)
-
-	return
-}
-
 var email = `From:  Al Gore <[email protected]>
 var email = `From:  Al Gore <[email protected]>
 To:  White House Transportation Coordinator <[email protected]>
 To:  White House Transportation Coordinator <[email protected]>
 Subject: [Fwd: Map of Argentina with Description]
 Subject: [Fwd: Map of Argentina with Description]
@@ -254,7 +223,7 @@ Content-Transfer-Encoding: 7bit
 
 
 Fred,
 Fred,
 
 
-Fire up Air Force One!  We\'re going South!
+Fire up Air Force One!  We're going South!
 
 
 Thanks,
 Thanks,
 Al
 Al
@@ -287,7 +256,7 @@ Content-Transfer-Encoding: 7bit
 
 
 Hi A1,
 Hi A1,
 
 
-I finally figured out this MIME thing.  Pretty cool.  I\'ll send you
+I finally figured out this MIME thing.  Pretty cool.  I'll send you
 some sax music in .au files next week!
 some sax music in .au files next week!
 
 
 Anyway, the attached image is really too small to get a good look at
 Anyway, the attached image is really too small to get a good look at
@@ -295,7 +264,7 @@ Argentina.  Try this for a much better map:
 
 
 http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
 http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
 
 
-Then again, shouldn\'t the CIA have something like that?
+Then again, shouldn't the CIA have something like that?
 
 
 Bill
 Bill
 --DC8------------DC8638F443D87A7F0726DEF7
 --DC8------------DC8638F443D87A7F0726DEF7
@@ -315,14 +284,97 @@ U6ZGxseyk8SasGw3J9GRzdTQky1iHNvcPNNI4TLeKdfMvy0vMqLrItvuxfDW8ubjueDtJufz
 
 
 `
 `
 
 
+var email2 = `From: [email protected]
+Content-Type: multipart/mixed;
+        boundary="----_=_NextPart_001_01CBE273.65A0E7AA"
+To: [email protected]
+
+This is a multi-part message in MIME format.
+
+------_=_NextPart_001_01CBE273.65A0E7AA
+Content-Type: multipart/alternative;
+        boundary="----_=_NextPart_002_01CBE273.65A0E7AA"
+
+
+------_=_NextPart_002_01CBE273.65A0E7AA
+Content-Type: text/plain;
+        charset="UTF-8"
+Content-Transfer-Encoding: base64
+
+[base64-content]
+------_=_NextPart_002_01CBE273.65A0E7AA
+Content-Type: text/html;
+        charset="UTF-8"
+Content-Transfer-Encoding: base64
+
+[base64-content]
+------_=_NextPart_002_01CBE273.65A0E7AA--
+------_=_NextPart_001_01CBE273.65A0E7AA
+Content-Type: message/rfc822
+Content-Transfer-Encoding: 7bit
+
+X-MimeOLE: Produced By Microsoft Exchange V6.5
+Content-class: urn:content-classes:message
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+        boundary="----_=_NextPart_003_01CBE272.13692C80"
+From: [email protected]
+To: [email protected]
+
+This is a multi-part message in MIME format.
+
+------_=_NextPart_003_01CBE272.13692C80
+Content-Type: multipart/alternative;
+        boundary="----_=_NextPart_004_01CBE272.13692C80"
+
+
+------_=_NextPart_004_01CBE272.13692C80
+Content-Type: text/plain;
+        charset="iso-8859-1"
+Content-Transfer-Encoding: quoted-printable
+
+=20
+
+Viele Gr=FC=DFe
+
+------_=_NextPart_004_01CBE272.13692C80
+Content-Type: text/html;
+        charset="iso-8859-1"
+Content-Transfer-Encoding: quoted-printable
+
+<html>...</html>
+------_=_NextPart_004_01CBE272.13692C80--
+------_=_NextPart_003_01CBE272.13692C80
+Content-Type: application/x-zip-compressed;
+        name="abc.zip"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+        filename="abc.zip"
+
+[base64-content]
+
+------_=_NextPart_003_01CBE272.13692C80--
+------_=_NextPart_001_01CBE273.65A0E7AA--`
+
 func TestNestedEmail(t *testing.T) {
 func TestNestedEmail(t *testing.T) {
+	//email = email2
 	p.inject([]byte(email))
 	p.inject([]byte(email))
 
 
-	if err := p.mime("", "1"); err != nil {
+	if err := p.mime(nil, ""); err != nil {
 		t.Error(err)
 		t.Error(err)
 	}
 	}
 	for part := range p.parts {
 	for part := range p.parts {
-		fmt.Println(p.parts[part].part, " ", p.parts[part].contentType)
+		email = replaceAtIndex(email, '#', p.parts[part].startingPos)
+		email = replaceAtIndex(email, '&', p.parts[part].startingPosBody)
+		email = replaceAtIndex(email, '*', p.parts[part].endingPosBody)
+		fmt.Println(p.parts[part].part + " " + strconv.Itoa(int(p.parts[part].startingPos)) + " " + strconv.Itoa(int(p.parts[part].startingPosBody)) + " " + strconv.Itoa(int(p.parts[part].endingPosBody)))
 	}
 	}
+	fmt.Print(email)
+	//fmt.Println(strings.Index(email, "--D7F------------D7FD5A0B8AB9C65CCDBFA872--"))
+
+	//	fmt.Println(email[p.parts[5].startingPosBody:p.parts[5].endingPosBody])
+}
 
 
+func replaceAtIndex(str string, replacement rune, index uint) string {
+	return str[:index] + string(replacement) + str[index+1:]
 }
 }