chunk_test.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. package chunk
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. "strings"
  8. "testing"
  9. "github.com/flashmob/go-guerrilla/backends"
  10. "github.com/flashmob/go-guerrilla/chunk/transfer"
  11. "github.com/flashmob/go-guerrilla/mail"
  12. )
  13. func TestChunkedBytesBuffer(t *testing.T) {
  14. var in string
  15. var buf chunkingBuffer
  16. buf.CapTo(64)
  17. // the data to write is over-aligned
  18. in = `123456789012345678901234567890123456789012345678901234567890abcde12345678901234567890123456789012345678901234567890123456789abcdef` // len == 130
  19. i, _ := buf.Write([]byte(in[:]))
  20. if i != len(in) {
  21. t.Error("did not write", len(in), "bytes")
  22. }
  23. // the data to write is aligned
  24. var buf2 chunkingBuffer
  25. buf2.CapTo(64)
  26. in = `123456789012345678901234567890123456789012345678901234567890abcde12345678901234567890123456789012345678901234567890123456789abcd` // len == 128
  27. i, _ = buf2.Write([]byte(in[:]))
  28. if i != len(in) {
  29. t.Error("did not write", len(in), "bytes")
  30. }
  31. // the data to write is under-aligned
  32. var buf3 chunkingBuffer
  33. buf3.CapTo(64)
  34. in = `123456789012345678901234567890123456789012345678901234567890abcde12345678901234567890123456789012345678901234567890123456789ab` // len == 126
  35. i, _ = buf3.Write([]byte(in[:]))
  36. if i != len(in) {
  37. t.Error("did not write", len(in), "bytes")
  38. }
  39. // the data to write is smaller than the buffer
  40. var buf4 chunkingBuffer
  41. buf4.CapTo(64)
  42. in = `1234567890` // len == 10
  43. i, _ = buf4.Write([]byte(in[:]))
  44. if i != len(in) {
  45. t.Error("did not write", len(in), "bytes")
  46. }
  47. // what if the buffer already contains stuff before Write is called
  48. // and the buffer len is smaller than the len of the slice of bytes we pass it?
  49. var buf5 chunkingBuffer
  50. buf5.CapTo(5)
  51. buf5.buf = append(buf5.buf, []byte{'a', 'b', 'c'}...)
  52. in = `1234567890` // len == 10
  53. i, _ = buf5.Write([]byte(in[:]))
  54. if i != len(in) {
  55. t.Error("did not write", len(in), "bytes")
  56. }
  57. }
  58. var email = `From: Al Gore <[email protected]>
  59. To: White House Transportation Coordinator <[email protected]>
  60. Subject: [Fwd: Map of Argentina with Description]
  61. MIME-Version: 1.0
  62. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed; s=ncr424; d=reliancegeneral.co.in;
  63. h=List-Unsubscribe:MIME-Version:From:To:Reply-To:Date:Subject:Content-Type:Content-Transfer-Encoding:Message-ID; [email protected];
  64. bh=F4UQPGEkpmh54C7v3DL8mm2db1QhZU4gRHR1jDqffG8=;
  65. b=MVltcq6/I9b218a370fuNFLNinR9zQcdBSmzttFkZ7TvV2mOsGrzrwORT8PKYq4KNJNOLBahswXf
  66. GwaMjDKT/5TXzegdX/L3f/X4bMAEO1einn+nUkVGLK4zVQus+KGqm4oP7uVXjqp70PWXScyWWkbT
  67. 1PGUwRfPd/HTJG5IUqs=
  68. Content-Type: multipart/mixed;
  69. boundary="D7F------------D7FD5A0B8AB9C65CCDBFA872"
  70. This is a multi-part message in MIME format.
  71. --D7F------------D7FD5A0B8AB9C65CCDBFA872
  72. Content-Type: text/plain; charset=us-ascii
  73. Content-Transfer-Encoding: 7bit
  74. Fred,
  75. Fire up Air Force One! We're going South!
  76. Thanks,
  77. Al
  78. --D7F------------D7FD5A0B8AB9C65CCDBFA872
  79. Content-Type: message/rfc822
  80. Content-Transfer-Encoding: 7bit
  81. Content-Disposition: inline
  82. Return-Path: <[email protected]>
  83. Received: from mailhost.whitehouse.gov ([192.168.51.200])
  84. by heartbeat.whitehouse.gov (8.8.8/8.8.8) with ESMTP id SAA22453
  85. for <[email protected]>;
  86. Mon, 13 Aug 1998 l8:14:23 +1000
  87. Received: from the_big_box.whitehouse.gov ([192.168.51.50])
  88. by mailhost.whitehouse.gov (8.8.8/8.8.7) with ESMTP id RAA20366
  89. for [email protected]; Mon, 13 Aug 1998 17:42:41 +1000
  90. Date: Mon, 13 Aug 1998 17:42:41 +1000
  91. Message-Id: <[email protected]>
  92. From: Bill Clinton <[email protected]>
  93. To: A1 (The Enforcer) Gore <[email protected]>
  94. Subject: Map of Argentina with Description
  95. MIME-Version: 1.0
  96. Content-Type: multipart/mixed;
  97. boundary="DC8------------DC8638F443D87A7F0726DEF7"
  98. This is a multi-part message in MIME format.
  99. --DC8------------DC8638F443D87A7F0726DEF7
  100. Content-Type: text/plain; charset=us-ascii
  101. Content-Transfer-Encoding: 7bit
  102. Hi A1,
  103. I finally figured out this MIME thing. Pretty cool. I'll send you
  104. some sax music in .au files next week!
  105. Anyway, the attached image is really too small to get a good look at
  106. Argentina. Try this for a much better map:
  107. http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
  108. Then again, shouldn't the CIA have something like that?
  109. Bill
  110. --DC8------------DC8638F443D87A7F0726DEF7
  111. Content-Type: image/gif; name="map_of_Argentina.gif"
  112. Content-Transfer-Encoding: base64
  113. Content-Disposition: attachment; filename="map_of_Argentina.gif"
  114. iVBORw0KGgoAAAANSUhEUgAAAG4AAAAyCAIAAAAydXkgAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA
  115. B3RJTUUH1gYEExgGfYkXIAAAAAd0RVh0QXV0aG9yAKmuzEgAAAAMdEVYdERlc2NyaXB0aW9uABMJ
  116. ISMAAAAKdEVYdENvcHlyaWdodACsD8w6AAAADnRFWHRDcmVhdGlvbiB0aW1lADX3DwkAAAAJdEVY
  117. dFNvZnR3YXJlAF1w/zoAAAALdEVYdERpc2NsYWltZXIAt8C0jwAAAAh0RVh0V2FybmluZwDAG+aH
  118. AAAAB3RFWHRTb3VyY2UA9f+D6wAAAAh0RVh0Q29tbWVudAD2zJa/AAAABnRFWHRUaXRsZQCo7tIn
  119. AAABAElEQVR4nO2ZUY6DIBCG66YH88FGvQLHEI+hHsMriPFw7AMJIYAwoO269v+eSDPDmKn5HOXx
  120. AAAAAAAAAPxblmWRZJZlSU3RCCE451Z1IUQ00c1ScM7p15zHT1J0URSpwUkpmrquh2HY60uA1+vl
  121. /b2qKkp63tUCcA8otrK8k+dKr7+I1V0tEEUppRRCZDcnzZUZHLdP6g6uFomiBACYeHUTTnF9ZwV4
  122. 3dp1HaW0V5dRUR6ZJU3e7kqLaK+9ZpymKamKOV3uTZrhigCAU1wZhV7aRE2IlKn2tq60WNeVHtz3
  123. vV7Xdc05b5pmL0ADVwLg5QOu3BNZhhxVwH1cmYoluwDqX2zbj2bPFgAAAMdJREFUNnUruBIALxmu
  124. dF1mBXhlSimtPzW6O5hfIQOJB7mcK72NSzrk2bYt+ku0IvhL8PCKwxhTi3meT9s06aBGOSjjpduF
  125. Ut1UnlnUUmG4kDtj6j5aa5c3noOfhX4ND1eXhvJMOYZFGYYxNs8zY6wsS73O3u2rUY1jjOkOBlp5
  126. uSf4NTn/fsw4Bz/oSnMMCm9laU4FuzMj5ZpN6K58JrVSfnAEW9d127ZxHInVLZM2TSOlpL/C72He
  127. j2c+wQEAAAAAAAAAfB2/3ihTGANzPd8AAAAASUVORK5CYII=
  128. --DC8------------DC8638F443D87A7F0726DEF7--
  129. --D7F------------D7FD5A0B8AB9C65CCDBFA872--
  130. `
  131. var email2 = `Delivered-To: [email protected]
  132. Received: from aaa.cn (aaa.cn [220.178.145.250])
  133. by 163.com with SMTP id [email protected];
  134. Tue, 17 Sep 2019 01:16:43 +0000
  135. From: "=?utf-8?Q?=E6=B1=9F=E5=8D=97=E6=A2=A6=E6=96=AD=E6=A8=AA=E6=B1=9F=E6=B8=9A?=" <[email protected]>
  136. To: <[email protected]>
  137. Subject: =?utf-8?Q?=E5=BA=94=E5=8A=9B=E6=AF=94b?=
  138. Date: Tue, 17 Sep 2019 09:16:29 +0800
  139. Message-ID: <[email protected]>
  140. MIME-Version: 1.0
  141. Content-Type: text/html;
  142. charset="utf-8"
  143. Content-Transfer-Encoding: 8bit
  144. X-Priority: 3 (Normal)
  145. X-MSMail-Priority: Normal
  146. X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0)
  147. Importance: Normal
  148. X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180
  149. <P><SPAN style='FONT-SIZE: large; FONT-FAMILY: "lucida Grande", Verdana, "Microsoft YaHei"; WHITE-SPACE: normal; WORD-SPACING: 0px; TEXT-TRANSFORM: none; FLOAT: none; FONT-WEIGHT: normal; COLOR: rgb(0,0,0); FONT-STYLE: normal; ORPHANS: 2; WIDOWS: 2; DISPLAY: inline !important; LETTER-SPACING: normal; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial'><FONT size=2><FONT color=black><FONT color=#008040><FONT color=#000000><FONT color=silver>Date:2019-09-17<BR>Account:[email protected]</FONT><FONT size=3> </FONT></FONT>
  150. <HR>
  151. <P></P>
  152. <P></FONT></FONT></FONT></SPAN><SPAN style='FONT-SIZE: large; FONT-FAMILY: "lucida Grande", Verdana, "Microsoft YaHei"; WHITE-SPACE: normal; WORD-SPACING: 0px; TEXT-TRANSFORM: none; FLOAT: none; FONT-WEIGHT: normal; COLOR: rgb(0,0,0); FONT-STYLE: normal; ORPHANS: 2; WIDOWS: 2; DISPLAY: inline !important; LETTER-SPACING: normal; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial'><FONT color=black size=2>丅<span style="position:absolute; bottom:-3000px"><交通指挥灯></span>載<span style="position:absolute; bottom:-3000px"><硝化作用></span>а<span style="position:absolute; bottom:-3000px"><柿子></span>ρ<span style="position:absolute; bottom:-3000px"><竞争性领域></span>ρ<span style="position:absolute; bottom:-3000px"><毛虫></span>签<span style="position:absolute; bottom:-3000px"><非持久性病毒></span>到<span style="position:absolute; bottom:-3000px"><街灯></span>領<span style="position:absolute; bottom:-3000px"><麦蜘蛛></span>1<span style="position:absolute; bottom:-3000px"><求索></span>6<span style="position:absolute; bottom:-3000px"><企业标准></span>╇<span style="position:absolute; bottom:-3000px"><气候条件></span>,<span style="position:absolute; bottom:-3000px"><农村劳动力转移></span>登<span style="position:absolute; bottom:-3000px"><穴深></span>杁<span style="position:absolute; bottom:-3000px"><预备队></span>2<span style="position:absolute; bottom:-3000px"><农机具></span>Ч<span style="position:absolute; bottom:-3000px"><营养袋育苗></span>棋<span style="position:absolute; bottom:-3000px"><生物肥料></span>牌<span style="position:absolute; bottom:-3000px"><光照强度></span>2<span style="position:absolute; bottom:-3000px"><改良系谱法></span>4<span style="position:absolute; bottom:-3000px"><加大投入></span>9<span style="position:absolute; bottom:-3000px"><茶叶产业办公室></span>8<span style="position:absolute; bottom:-3000px"><省局></span>8<span style="position:absolute; bottom:-3000px"><辐照></span>4<span style="position:absolute; bottom:-3000px"><百亩></span>.<span style="position:absolute; bottom:-3000px"><上行列车></span>c<span style="position:absolute; bottom:-3000px"><竹节></span>δ<span style="position:absolute; bottom:-3000px"><山嘴></span>м<span style="position:absolute; bottom:-3000px"><股所></span>,<span style="position:absolute; bottom:-3000px"><科学谋划></span>吋<span style="position:absolute; bottom:-3000px"><领海></span>款<span style="position:absolute; bottom:-3000px"><异常型种子></span>1<span style="position:absolute; bottom:-3000px"><董家村></span> <span style="position:absolute; bottom:-3000px"><平面球形图></span>0<span style="position:absolute; bottom:-3000px"><先来></span> <span style="position:absolute; bottom:-3000px"><藜叶斑病></span>0<span style="position:absolute; bottom:-3000px"><竞职></span>宋<span style="position:absolute; bottom:-3000px"><二棱大麦></span>2<span style="position:absolute; bottom:-3000px"><茎枯病></span> <span style="position:absolute; bottom:-3000px"><宁洱县></span>0<span style="position:absolute; bottom:-3000px"><共枕></span>鎵<span style="position:absolute; bottom:-3000px"><钙镁磷肥></span>專<span style="position:absolute; bottom:-3000px"><校正></span>員<span style="position:absolute; bottom:-3000px"><砍青></span>4<span style="position:absolute; bottom:-3000px"><独具特色></span>8<span style="position:absolute; bottom:-3000px"><装草机></span>6<span style="position:absolute; bottom:-3000px"><斑螟></span>1<span style="position:absolute; bottom:-3000px"><补偿机制></span>3<span style="position:absolute; bottom:-3000px"><创意策划></span>8<span style="position:absolute; bottom:-3000px"><投稿家></span>3<span style="position:absolute; bottom:-3000px"><茶点></span>2<span style="position:absolute; bottom:-3000px"><量天尺枯萎腐烂病></span>0<span style="position:absolute; bottom:-3000px"><河尾></span>翎<span style="position:absolute; bottom:-3000px"><台湾稻螟></span>。<span style="position:absolute; bottom:-3000px"><春城晚报></span></FONT></SPAN></P>
  153. <P><SPAN style='FONT-SIZE: large; FONT-FAMILY: "lucida Grande", Verdana, "Microsoft YaHei"; WHITE-SPACE: normal; WORD-SPACING: 0px; TEXT-TRANSFORM: none; FLOAT: none; FONT-WEIGHT: normal; COLOR: rgb(0,0,0); FONT-STYLE: normal; ORPHANS: 2; WIDOWS: 2; DISPLAY: inline !important; LETTER-SPACING: normal; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial'></SPAN><FONT color=silver size=2>Your words appear idle to me; give them proof, and I will listen.</FONT></P>`
  154. var email3 = `Delivered-To: [email protected]
  155. Received: from bb_dyn_pb-146-88-38-36.violin.co.th (bb_dyn_pb-146-88-38-36.violin.co.th [146.88.38.36])
  156. by sharklasers.com with SMTP id [email protected];
  157. Tue, 17 Sep 2019 01:13:00 +0000
  158. Received: from mx03.listsystemsf.net [100.20.38.85] by mxs.perenter.com with SMTP; Tue, 17 Sep 2019 04:57:59 +0500
  159. Received: from mts.locks.grgtween.net ([Tue, 17 Sep 2019 04:52:27 +0500])
  160. by webmail.halftomorrow.com with LOCAL; Tue, 17 Sep 2019 04:52:27 +0500
  161. Received: from mail.naihautsui.co.kr ([61.220.30.1]) by mtu67.syds.piswix.net with ASMTP; Tue, 17 Sep 2019 04:47:25 +0500
  162. Received: from unknown (HELO mx03.listsystemsf.net) (Tue, 17 Sep 2019 04:41:45 +0500)
  163. by smtp-server1.cfdenselr.com with LOCAL; Tue, 17 Sep 2019 04:41:45 +0500
  164. Message-ID: <[email protected]>
  165. Date: Tue, 17 Sep 2019 04:14:56 +0500
  166. Reply-To: "Nevaeh" <[email protected]>
  167. From: "Nevaeh" <[email protected]>
  168. User-Agent: Mozilla 4.73 [de]C-CCK-MCD DT (Win98; U)
  169. X-Accept-Language: en-us
  170. MIME-Version: 1.0
  171. To: "Nevaeh" <[email protected]>
  172. Subject: czy m�glbys spotkac sie ze mna w weekend?
  173. Content-Type: text/html;
  174. charset="iso-8859-1""
  175. Content-Transfer-Encoding: base64
  176. PCFkb2N0eXBlIGh0bWw+DQo8aHRtbD4NCjxoZWFkPg0KPG1ldGEgY2hhcnNldD0idXRmLTgiPg0K
  177. PC9oZWFkPg0KPGJvZHk+DQo8dGFibGUgd2lkdGg9IjYwMCIgYm9yZGVyPSIwIiBhbGlnbj0iY2Vu
  178. dGVyIiBzdHlsZT0iZm9udC1mYW1pbHk6IEFyaWFsOyBmb250LXNpemU6IDE4cHgiPg0KPHRib2R5
  179. Pg0KPHRyPg0KPHRoIGhlaWdodD0iNjAiIHNjb3BlPSJjb2wiPk5hamdvcmV0c3plIGR6aWV3Y3p5
  180. bnkgaSBzYW1vdG5lIGtvYmlldHksIGt083JlIGNoY2Egc2Vrc3UuPG9sPjwvb2w+PC90aD4NCjwv
  181. dHI+DQo8dGQgaGVpZ2h0PSIyMjMiIGFsaWduPSJjZW50ZXIiPjxwPk5hIG5hc3plaiBzdHJvbmll
  182. IGdyb21hZHpvbmUgc2EgbWlsaW9ueSBwcm9maWxpIGtvYmlldC4gV3N6eXNjeSBjaGNhIHRlcmF6
  183. IHBpZXByenljLjwvcD4NCjxoZWFkZXI+PC9oZWFkZXI+DQo8cD5OYSBwcnp5a2xhZCBzYSBXIFRX
  184. T0lNIE1JRVNDSUUuIENoY2VzeiBpbm55Y2g/IFpuYWpkeiBuYSBuYXN6ZWogc3Ryb25pZSE8L3A+
  185. DQo8dGFibGUgY2xhc3M9Im1jbkJ1dHRvbkNvbnRlbnRDb250YWluZXIiIHN0eWxlPSJib3JkZXIt
  186. Y29sbGFwc2U6IHNlcGFyYXRlICEgaW1wb3J0YW50O2JvcmRlci1yYWRpdXM6IDNweDtiYWNrZ3Jv
  187. dW5kLWNvbG9yOiAjRTc0MTQxOyIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRp
  188. bmc9IjAiPg0KIDx0Ym9keT4NCiA8dHI+DQogPHRkIGNsYXNzPSJtY25CdXR0b25Db250ZW50IiBz
  189. dHlsZT0iZm9udC1mYW1pbHk6IEFyaWFsOyBmb250LXNpemU6IDIycHg7IHBhZGRpbmc6IDE1cHgg
  190. MjVweDsiIHZhbGlnbj0ibWlkZGxlIiBhbGlnbj0iY2VudGVyIj4NCiA8YSBjbGFzcz0ibWNuQnV0
  191. dG9uICIgaHJlZj0iaHR0cDovL2JldGhhbnkuc3UiIHRhcmdldD0iX2JsYW5rIiBzdHlsZT0iZm9u
  192. dC13ZWlnaHQ6IG5vcm1hbDtsZXR0ZXItc3BhY2luZzogbm9ybWFsO2xpbmUtaGVpZ2h0OiAxMDAl
  193. O3RleHQtYWxpZ246IGNlbnRlcjt0ZXh0LWRlY29yYXRpb246IG5vbmU7Y29sb3I6ICNGRkZGRkY7
  194. Ij5odHRwOi8vYmV0aGFueS5zdTwvYT4NCiA8L3RkPg0KIDwvdHI+DQogPC90Ym9keT4NCiA8L3Rh
  195. YmxlPjx0YWJsZSB3aWR0aD0iMjglIiBib3JkZXI9IjAiPjx0Ym9keT48dHI+PHRkPjwvdGQ+PHRk
  196. PjwvdGQ+PHRkPjwvdGQ+PC90cj48L3Rib2R5PjwvdGFibGU+DQo8dGFibGUgc3R5bGU9Im1pbi13
  197. aWR0aDoxMDAlOyIgY2xhc3M9Im1jblRleHRDb250ZW50Q29udGFpbmVyIiBhbGlnbj0ibGVmdCIg
  198. Ym9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHdpZHRoPSIxMDAlIj4N
  199. Cjx0Ym9keT4NCiA8dHI+DQo8dGQgYWxpZ249ImNlbnRlciIgdmFsaWduPSJ0b3AiIGNsYXNzPSJt
  200. Y25UZXh0Q29udGVudCIgc3R5bGU9InBhZGRpbmc6IDlweCAxOHB4O2NvbG9yOiAjNkI2QjZCO2Zv
  201. bnQtZmFtaWx5OiBWZXJkYW5hLEdlbmV2YSxzYW5zLXNlcmlmO2ZvbnQtc2l6ZTogMTFweDsiPg0K
  202. VXp5aiB0ZWdvIGxpbmt1LCBqZXNsaSBwcnp5Y2lzayBuaWUgZHppYWxhPGJyPg0KPGEgaHJlZj0i
  203. aHR0cDovL2JldGhhbnkuc3UiIHRhcmdldD0iX2JsYW5rIj5odHRwOi8vYmV0aGFueS5zdTwvYT48
  204. YnI+DQpTa29waXVqIGkgd2tsZWogbGluayBkbyBwcnplZ2xhZGFya2k8L3RkPg0KPC90cj4NCjwv
  205. dGJvZHk+PC90YWJsZT48L3RkPg0KPC90cj4gDQo8L3Rib2R5Pg0KPC90YWJsZT4NCjxvbD48cD48
  206. L3A+PC9vbD4NCjx0YWJsZSB3aWR0aD0iNjAwIiBib3JkZXI9IjAiIGFsaWduPSJjZW50ZXIiPg0K
  207. IDx0Ym9keT4NCiA8dHI+DQogPHRkPjxhIGhyZWY9Imh0dHA6Ly9iZXRoYW55LnN1Ij48cCBzdHls
  208. ZT0idGV4dC1hbGlnbjogY2VudGVyIj5DYW1pbGE8L3A+DQogPG5hdj48L25hdj4NCiA8dGFibGU+
  209. DQogPHRyPg0KIDx0ZCB2YWxpZ249InRvcCIgc3R5bGU9ImJhY2tncm91bmQ6IHVybChodHRwczov
  210. L3RoZWNoaXZlLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxOS8wOS9iODE0NmEyOTI3ODY4ODkxNzk4
  211. ODY1NDhlN2QzOWEzZV93aWR0aC02MDAuanBlZz9xdWFsaXR5PTEwMCZzdHJpcD1pbmZvJnc9NjQx
  212. Jnpvb209Mikgbm8tcmVwZWF0IGNlbnRlcjtiYWNrZ3JvdW5kLXBvc2l0aW9uOiB0b3A7YmFja2dy
  213. b3VuZC1zaXplOiBjb3ZlcjsiPjwhLS1baWYgZ3RlIG1zbyA5XT4gPHY6cmVjdCB4bWxuczp2PSJ1
  214. cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbCIgZmlsbD0idHJ1ZSIgc3Ryb2tlPSJmYWxzZSIg
  215. c3R5bGU9Im1zby13aWR0aC1wZXJjZW50OjEwMDA7aGVpZ2h0OjQwMHB4OyI+IDx2OmZpbGwgdHlw
  216. ZT0idGlsZSIgc3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxOS8w
  217. OC82YWU4NzFiNTlmYjUxMDc1ZGMwMzE3ZDBiOTkzZjJhOV93aWR0aC02MDAuanBnP3F1YWxpdHk9
  218. MTAwJnN0cmlwPWluZm8mdz02NDEmem9vbT0yIiAvPiA8djp0ZXh0Ym94IGluc2V0PSIwLDAsMCww
  219. Ij4gPCFbZW5kaWZdLS0+DQogPGRpdj4NCiA8Y2VudGVyPg0KIDx0YWJsZSBjZWxsc3BhY2luZz0i
  220. MCIgY2VsbHBhZGRpbmc9IjAiIHdpZHRoPSIyODAiIGhlaWdodD0iNDAwIj4NCiA8dHI+DQogPHRk
  221. IHZhbGlnbj0ibWlkZGxlIiBzdHlsZT0idmVydGljYWwtYWxpZ246bWlkZGxlO3RleHQtYWxpZ246
  222. bGVmdDsiIGNsYXNzPSJtb2JpbGUtY2VudGVyIiBoZWlnaHQ9IjQwMCI+PGFydGljbGU+PC9hcnRp
  223. Y2xlPiA8L3RkPg0KIDwvdHI+DQogPC90YWJsZT4NCiA8L2NlbnRlcj4NCiA8L2Rpdj4NCiA8IS0t
  224. W2lmIGd0ZSBtc28gOV0+IDwvdjp0ZXh0Ym94PiA8L3Y6cmVjdD4gPCFbZW5kaWZdLS0+PC90ZD4N
  225. CiA8L3RyPg0KIDwvdGFibGU+DQogPC9hPjwvdGQ+DQogPHRkPjxhIGhyZWY9Imh0dHA6Ly9iZXRo
  226. YW55LnN1Ij48cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyIj5NaWxhPC9wPg0KIDxkaXY+PC9k
  227. aXY+DQogPHRhYmxlPg0KIDx0cj4NCiA8dGQgdmFsaWduPSJ0b3AiIHN0eWxlPSJiYWNrZ3JvdW5k
  228. OiB1cmwoaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIwMTkvMDgvODg1ZGFi
  229. OTM2MGZiYzY2NGMzYTNhNDQwOGI1NTE2ZDUtMS5qcGc/cXVhbGl0eT0xMDAmc3RyaXA9aW5mbyZ3
  230. PTY0MSZ6b29tPTIpIG5vLXJlcGVhdCBjZW50ZXI7YmFja2dyb3VuZC1wb3NpdGlvbjogdG9wO2Jh
  231. Y2tncm91bmQtc2l6ZTogY292ZXI7Ij48IS0tW2lmIGd0ZSBtc28gOV0+IDx2OnJlY3QgeG1sbnM6
  232. dj0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwiIGZpbGw9InRydWUiIHN0cm9rZT0iZmFs
  233. c2UiIHN0eWxlPSJtc28td2lkdGgtcGVyY2VudDoxMDAwO2hlaWdodDo0MDBweDsiPiA8djpmaWxs
  234. IHR5cGU9InRpbGUiIHNyYz0iaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIw
  235. MTkvMDgvMGE2Mzc2MDVkYzhkOTcyNzRhZWFkODVhOGY0YTJmYjkuanBnP3F1YWxpdHk9MTAwJnN0
  236. cmlwPWluZm8mdz02MDAiIC8+IDx2OnRleHRib3ggaW5zZXQ9IjAsMCwwLDAiPiA8IVtlbmRpZl0t
  237. LT4NCg0KIDxkaXY+DQogPGNlbnRlcj4NCiA8dGFibGUgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRk
  238. aW5nPSIwIiB3aWR0aD0iMjgwIiBoZWlnaHQ9IjQwMCI+DQogPHRyPg0KIDx0ZCB2YWxpZ249Im1p
  239. ZGRsZSIgc3R5bGU9InZlcnRpY2FsLWFsaWduOm1pZGRsZTt0ZXh0LWFsaWduOmxlZnQ7IiBjbGFz
  240. cz0ibW9iaWxlLWNlbnRlciIgaGVpZ2h0PSI0MDAiPjxocj4gPC90ZD4NCiA8L3RyPg0KIDwvdGFi
  241. bGU+DQogPC9jZW50ZXI+DQogPC9kaXY+DQogPCEtLVtpZiBndGUgbXNvIDldPiA8L3Y6dGV4dGJv
  242. eD4gPC92OnJlY3Q+IDwhW2VuZGlmXS0tPjwvdGQ+DQogPC90cj4NCiA8L3RhYmxlPg0KIDwvYT48
  243. L3RkPg0KIDwvdHI+DQogPHRyPg0KIDx0ZD48YSBocmVmPSJodHRwOi8vYmV0aGFueS5zdSI+PHAg
  244. c3R5bGU9InRleHQtYWxpZ246IGNlbnRlciI+THVuYTwvcD4NCiA8dGFibGUgd2lkdGg9Ijc0JSIg
  245. Ym9yZGVyPSIwIj48dGJvZHk+PHRyPjx0ZD48L3RkPjx0ZD48L3RkPjx0ZD48L3RkPjx0ZD48L3Rk
  246. Pjx0ZD48L3RkPjwvdHI+PC90Ym9keT48L3RhYmxlPg0KIDx0YWJsZT4NCiA8dHI+DQogPHRkIHZh
  247. bGlnbj0idG9wIiBzdHlsZT0iYmFja2dyb3VuZDogdXJsKGh0dHBzOi8vdGhlY2hpdmUuZmlsZXMu
  248. d29yZHByZXNzLmNvbS8yMDE5LzA4LzA2ZTU2YTU4ZjQ3ZDM0OGEyMjc3NmYyOTFlNjg2OWEwLTEu
  249. anBnP3F1YWxpdHk9MTAwJnN0cmlwPWluZm8mdz02NDEmem9vbT0yKSBuby1yZXBlYXQgY2VudGVy
  250. O2JhY2tncm91bmQtcG9zaXRpb246IHRvcDtiYWNrZ3JvdW5kLXNpemU6IGNvdmVyOyI+PCEtLVtp
  251. ZiBndGUgbXNvIDldPiA8djpyZWN0IHhtbG5zOnY9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206
  252. dm1sIiBmaWxsPSJ0cnVlIiBzdHJva2U9ImZhbHNlIiBzdHlsZT0ibXNvLXdpZHRoLXBlcmNlbnQ6
  253. MTAwMDtoZWlnaHQ6NDAwcHg7Ij4gPHY6ZmlsbCB0eXBlPSJ0aWxlIiBzcmM9Imh0dHBzOi8vdGhl
  254. Y2hpdmUuZmlsZXMud29yZHByZXNzLmNvbS8yMDE5LzA4LzhhYjRkYzcxMjFlYTVhMzdiMTc3NjNm
  255. ZjRhNDA1MTVlLmpwZz9xdWFsaXR5PTEwMCZzdHJpcD1pbmZvJnc9NjQxJnpvb209MiIgLz4gPHY6
  256. dGV4dGJveCBpbnNldD0iMCwwLDAsMCI+IDwhW2VuZGlmXS0tPg0KIDxkaXY+DQogPGNlbnRlcj4N
  257. CiA8dGFibGUgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIiB3aWR0aD0iMjgwIiBoZWln
  258. aHQ9IjQwMCI+DQogPHRyPg0KIDx0ZCB2YWxpZ249Im1pZGRsZSIgc3R5bGU9InZlcnRpY2FsLWFs
  259. aWduOm1pZGRsZTt0ZXh0LWFsaWduOmxlZnQ7IiBjbGFzcz0ibW9iaWxlLWNlbnRlciIgaGVpZ2h0
  260. PSI0MDAiPjxicj4gPC90ZD4NCiA8L3RyPg0KIDwvdGFibGU+DQogPC9jZW50ZXI+DQogPC9kaXY+
  261. DQogPCEtLVtpZiBndGUgbXNvIDldPiA8L3Y6dGV4dGJveD4gPC92OnJlY3Q+IDwhW2VuZGlmXS0t
  262. PjwvdGQ+DQogPC90cj4NCiA8L3RhYmxlPg0KIDwvYT48L3RkPg0KIDx0ZD48YSBocmVmPSJodHRw
  263. Oi8vYmV0aGFueS5zdSI+PHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlciI+U2F2YW5uYWg8L3A+
  264. DQogPG9sPjwvb2w+DQogPHRhYmxlPg0KIDx0cj4NCiA8dGQgdmFsaWduPSJ0b3AiIHN0eWxlPSJi
  265. YWNrZ3JvdW5kOiB1cmwoaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIwMTkv
  266. MDgvYzA4MzYxNTE2MzUxNDFkNDhlY2ZmYTNkYmZkOGYxZDYuanBnP3F1YWxpdHk9MTAwJnN0cmlw
  267. PWluZm8mdz02NDEmem9vbT0yKSBuby1yZXBlYXQgY2VudGVyO2JhY2tncm91bmQtcG9zaXRpb246
  268. IHRvcDtiYWNrZ3JvdW5kLXNpemU6IGNvdmVyOyI+PCEtLVtpZiBndGUgbXNvIDldPiA8djpyZWN0
  269. IHhtbG5zOnY9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206dm1sIiBmaWxsPSJ0cnVlIiBzdHJv
  270. a2U9ImZhbHNlIiBzdHlsZT0ibXNvLXdpZHRoLXBlcmNlbnQ6MTAwMDtoZWlnaHQ6NDAwcHg7Ij4g
  271. PHY6ZmlsbCB0eXBlPSJ0aWxlIiBzcmM9Imh0dHBzOi8vdGhlY2hpdmUuZmlsZXMud29yZHByZXNz
  272. LmNvbS8yMDE5LzA4L2NhMWI4MWI5MTkyYTZkMzEyNTI1MmYwYzIwZWIxMjVjLmpwZz9xdWFsaXR5
  273. PTEwMCZzdHJpcD1pbmZvJnc9NjQxJnpvb209MiIgLz4gPHY6dGV4dGJveCBpbnNldD0iMCwwLDAs
  274. MCI+IDwhW2VuZGlmXS0tPg0KIDxkaXY+DQogPGNlbnRlcj4NCiA8dGFibGUgY2VsbHNwYWNpbmc9
  275. IjAiIGNlbGxwYWRkaW5nPSIwIiB3aWR0aD0iMjgwIiBoZWlnaHQ9IjQwMCI+DQogPHRyPg0KIDx0
  276. ZCB2YWxpZ249Im1pZGRsZSIgc3R5bGU9InZlcnRpY2FsLWFsaWduOm1pZGRsZTt0ZXh0LWFsaWdu
  277. OmxlZnQ7IiBjbGFzcz0ibW9iaWxlLWNlbnRlciIgaGVpZ2h0PSI0MDAiPjxtYWluPjwvbWFpbj4g
  278. PC90ZD4NCiA8L3RyPg0KIDwvdGFibGU+DQogPC9jZW50ZXI+DQogPC9kaXY+DQogPCEtLVtpZiBn
  279. dGUgbXNvIDldPiA8L3Y6dGV4dGJveD4gPC92OnJlY3Q+IDwhW2VuZGlmXS0tPjwvdGQ+DQogPC90
  280. cj4NCiA8L3RhYmxlPg0KIDwvYT48L3RkPg0KIDwvdHI+DQogPC90Ym9keT4NCjwvdGFibGU+DQo8
  281. dGFibGUgd2lkdGg9IjYxJSIgYm9yZGVyPSIwIj48dGJvZHk+PHRyPjx0ZD48L3RkPjx0ZD48L3Rk
  282. PjwvdHI+PC90Ym9keT48L3RhYmxlPg0KPHRhYmxlIHdpZHRoPSI2MDAiIGJvcmRlcj0iMCIgYWxp
  283. Z249ImNlbnRlciI+DQo8dGJvZHk+DQo8dHI+DQo8dGg+PHAgc3R5bGU9InRleHQtYWxpZ246IGNl
  284. bnRlciI+QnJvb2tseW48L3A+DQogPHA+PGEgaHJlZj0iaHR0cDovL2JldGhhbnkuc3UiPjxpbWcg
  285. c3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxOS8wOC9kMzc0Zjcx
  286. NDI0Nzc0MjEwNzdkOWQzZTg4ZmI1OTMxMS5qcGc/cXVhbGl0eT0xMDAmc3RyaXA9aW5mbyZ3PTY0
  287. MSZ6b29tPTIiIHdpZHRoPSIyODAiIGFsdD0ib3BlbiBwcm9maWxlIi8+PC9hPjwvcD48L3RoPg0K
  288. PHRoPjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXIiPkVtbWE8L3A+DQogPHA+PGEgaHJlZj0i
  289. aHR0cDovL2JldGhhbnkuc3UiPjxpbWcgc3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRw
  290. cmVzcy5jb20vMjAxOS8wOC9kNTk4ZjdlYTYxYWZjYTNjYjg2MjVkN2NmYTE5NzRiNC5qcGc/cXVh
  291. bGl0eT0xMDAmc3RyaXA9aW5mbyZ3PTY0MSZ6b29tPTIiIHdpZHRoPSIyODAiIGFsdD0ib3BlbiBw
  292. cm9maWxlIi8+PC9hPjwvcD48L3RoPg0KPC90cj4NCjx0cj4NCjx0ZD48dGFibGUgd2lkdGg9IjUw
  293. JSIgYm9yZGVyPSIwIj48dGJvZHk+PHRyPjx0ZD48L3RkPjx0ZD48L3RkPjwvdHI+PC90Ym9keT48
  294. L3RhYmxlPjwvdGQ+DQo8dGQ+PHVsPjxwPjwvcD48L3VsPjwvdGQ+DQo8L3RyPg0KPHRyPg0KPHRo
  295. PjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXIiPkVtbWE8L3A+DQogPHA+PGEgaHJlZj0iaHR0
  296. cDovL2JldGhhbnkuc3UiPjxpbWcgc3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRwcmVz
  297. cy5jb20vMjAxOS8wOS85YzU1ZjA1MmMzZDZhODgyZGYxMTFhZDZhZmFjOWMwNF93aWR0aC02MDAu
  298. anBlZz9xdWFsaXR5PTEwMCZzdHJpcD1pbmZvJnc9NjQxJnpvb209MiIgd2lkdGg9IjI4MCIgYWx0
  299. PSJvcGVuIHByb2ZpbGUiLz48L2E+PC9wPjwvdGg+DQo8dGg+PHAgc3R5bGU9InRleHQtYWxpZ246
  300. IGNlbnRlciI+QXZhPC9wPg0KIDxwPjxhIGhyZWY9Imh0dHA6Ly9iZXRoYW55LnN1Ij48aW1nIHNy
  301. Yz0iaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIwMTkvMDkvMzdlMDM1ZGZj
  302. YTM2NjkyZTk3ZTA4OWFjN2ZiNWVjN2QuanBnP3F1YWxpdHk9MTAwJnN0cmlwPWluZm8mdz02NDEm
  303. em9vbT0yIiB3aWR0aD0iMjgwIiBhbHQ9Im9wZW4gcHJvZmlsZSIvPjwvYT48L3A+PC90aD4NCjwv
  304. dHI+DQo8L3Rib2R5Pg0KPC90YWJsZT4NCjxuYXY+PC9uYXY+DQo8dGFibGUgc3R5bGU9Im1heC13
  305. aWR0aDo2MDBweDsgIiBjbGFzcz0ibWNuVGV4dENvbnRlbnRDb250YWluZXIiIHdpZHRoPSIxMDAl
  306. IiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjAiIGJvcmRlcj0iMCIgYWxpZ249ImNlbnRl
  307. ciI+DQo8dGJvZHk+PHRyPg0KPHRkIGNsYXNzPSJtY25UZXh0Q29udGVudCIgc3R5bGU9InBhZGRp
  308. bmctdG9wOjA7IHBhZGRpbmctcmlnaHQ6MThweDsgcGFkZGluZy1ib3R0b206OXB4OyBwYWRkaW5n
  309. LWxlZnQ6MThweDsiIHZhbGlnbj0idG9wIj4NCiAgIDxhIGhyZWY9Imh0dHA6Ly9iZXRoYW55LnN1
  310. L3Vuc3ViL3Vuc3ViLnBocCI+PHRhYmxlIHdpZHRoPSIwOCUiIGJvcmRlcj0iMCI+PHRib2R5Pjx0
  311. cj48dGQ+PC90ZD48dGQ+PC90ZD48L3RyPjwvdGJvZHk+PC90YWJsZT51bnN1YnNjcmliZSBmcm9t
  312. IHRoaXMgbGlzdDwvYT4uPGJyPg0KPC90ZD4NCjwvdHI+DQo8L3Rib2R5PjwvdGFibGU+DQo8L2Jv
  313. ZHk+DQo8L2h0bWw+DQo=`
  314. func TestHashBytes(t *testing.T) {
  315. var h HashKey
  316. h.Pack([]byte{222, 23, 3, 128, 1, 23, 3, 128, 1, 23, 3, 255, 1, 23, 3, 128})
  317. if h.String() != "3hcDgAEXA4ABFwP/ARcDgA" {
  318. t.Error("expecting 3hcDgAEXA4ABFwP/ARcDgA got", h.String())
  319. }
  320. }
  321. func TestTransformer(t *testing.T) {
  322. store, chunksaver, mimeanalyzer, stream := initTestStream(true)
  323. buf := make([]byte, 64)
  324. var result bytes.Buffer
  325. if _, err := io.CopyBuffer(stream, bytes.NewBuffer([]byte(email3)), buf); err != nil {
  326. t.Error(err)
  327. } else {
  328. _ = mimeanalyzer.Close()
  329. _ = chunksaver.Close()
  330. email, err := store.GetEmail(1)
  331. if err != nil {
  332. t.Error("email not found")
  333. return
  334. }
  335. // this should read all parts
  336. r, err := NewChunkedReader(store, email, 0)
  337. buf2 := make([]byte, 64)
  338. if w, err := io.CopyBuffer(&result, r, buf2); err != nil {
  339. t.Error(err)
  340. } else if w != email.size {
  341. t.Error("email.size != number of bytes copied from reader", w, email.size)
  342. }
  343. if !strings.Contains(result.String(), "</html>") {
  344. t.Error("Looks like it didn;t read the entire email, was expecting </html>")
  345. }
  346. result.Reset()
  347. }
  348. }
  349. func TestChunkSaverReader(t *testing.T) {
  350. store, chunksaver, mimeanalyzer, stream := initTestStream(false)
  351. buf := make([]byte, 64)
  352. var result bytes.Buffer
  353. if _, err := io.CopyBuffer(stream, bytes.NewBuffer([]byte(email3)), buf); err != nil {
  354. t.Error(err)
  355. } else {
  356. _ = mimeanalyzer.Close()
  357. _ = chunksaver.Close()
  358. email, err := store.GetEmail(1)
  359. if err != nil {
  360. t.Error("email not found")
  361. return
  362. }
  363. // this should read all parts
  364. r, err := NewChunkedReader(store, email, 0)
  365. buf2 := make([]byte, 64)
  366. if w, err := io.CopyBuffer(&result, r, buf2); err != nil {
  367. t.Error(err)
  368. } else if w != email.size {
  369. t.Error("email.size != number of bytes copied from reader", w, email.size)
  370. }
  371. if !strings.Contains(result.String(), "k+DQo8L2h0bWw+DQo") {
  372. t.Error("Looks like it didn;t read the entire email, was expecting k+DQo8L2h0bWw+DQo")
  373. }
  374. result.Reset()
  375. // Test the decoder, hit the decoderStateMatchNL state
  376. r, err = NewChunkedReader(store, email, 0)
  377. if err != nil {
  378. t.Error(err)
  379. }
  380. part := email.partsInfo.Parts[0]
  381. encoding := transfer.QuotedPrintable
  382. if strings.Contains(part.TransferEncoding, "base") {
  383. encoding = transfer.Base64
  384. }
  385. dr, err := transfer.NewDecoder(r, encoding, part.Charset)
  386. _ = dr
  387. if err != nil {
  388. t.Error(err)
  389. t.FailNow()
  390. }
  391. buf3 := make([]byte, 1253) // 1253 intentionally causes the decoderStateMatchNL state to hit
  392. _, err = io.CopyBuffer(&result, dr, buf3)
  393. if err != nil {
  394. t.Error()
  395. }
  396. if !strings.Contains(result.String(), "</html") {
  397. t.Error("looks like it didn't decode, expecting </html>")
  398. }
  399. result.Reset()
  400. // test the decoder, hit the decoderStateFindHeaderEnd state
  401. r, err = NewChunkedReader(store, email, 0)
  402. if err != nil {
  403. t.Error(err)
  404. }
  405. part = email.partsInfo.Parts[0]
  406. encoding = transfer.QuotedPrintable
  407. if strings.Contains(part.TransferEncoding, "base") {
  408. encoding = transfer.Base64
  409. }
  410. dr, err = transfer.NewDecoder(r, encoding, part.Charset)
  411. _ = dr
  412. if err != nil {
  413. t.Error(err)
  414. t.FailNow()
  415. }
  416. buf4 := make([]byte, 64) // state decoderStateFindHeaderEnd will hit
  417. _, err = io.CopyBuffer(&result, dr, buf4)
  418. if err != nil {
  419. t.Error()
  420. }
  421. if !strings.Contains(result.String(), "</html") {
  422. t.Error("looks like it didn't decode, expecting </html>")
  423. }
  424. }
  425. }
  426. func TestChunkSaverWrite(t *testing.T) {
  427. store, chunksaver, mimeanalyzer, stream := initTestStream(true)
  428. var out bytes.Buffer
  429. buf := make([]byte, 128)
  430. if written, err := io.CopyBuffer(stream, bytes.NewBuffer([]byte(email3)), buf); err != nil {
  431. t.Error(err)
  432. } else {
  433. _ = mimeanalyzer.Close()
  434. _ = chunksaver.Close()
  435. fmt.Println("written:", written)
  436. total := 0
  437. for _, chunk := range store.chunks {
  438. total += len(chunk.data)
  439. }
  440. fmt.Println("compressed", total, "saved:", written-int64(total))
  441. email, err := store.GetEmail(1)
  442. if err != nil {
  443. t.Error("email not found")
  444. return
  445. }
  446. // this should read all parts
  447. r, err := NewChunkedReader(store, email, 0)
  448. if w, err := io.Copy(&out, r); err != nil {
  449. t.Error(err)
  450. } else if w != email.size {
  451. t.Error("email.size != number of bytes copied from reader", w, email.size)
  452. } else if !strings.Contains(out.String(), "</html>") {
  453. t.Error("The email didn't decode properly, expecting </html>")
  454. }
  455. out.Reset()
  456. // test the seek feature
  457. r, err = NewChunkedReader(store, email, 0)
  458. if err != nil {
  459. t.Error(err)
  460. t.FailNow()
  461. }
  462. // we start from 1 because if the start from 0, all the parts will be read
  463. for i := 1; i < len(email.partsInfo.Parts); i++ {
  464. fmt.Println("seeking to", i)
  465. err = r.SeekPart(i)
  466. if err != nil {
  467. t.Error(err)
  468. }
  469. w, err := io.Copy(&out, r)
  470. if err != nil {
  471. t.Error(err)
  472. }
  473. if w != int64(email.partsInfo.Parts[i-1].Size) {
  474. t.Error(i, "incorrect size, expecting", email.partsInfo.Parts[i-1].Size, "but read:", w)
  475. }
  476. out.Reset()
  477. }
  478. r, err = NewChunkedReader(store, email, 0)
  479. if err != nil {
  480. t.Error(err)
  481. }
  482. part := email.partsInfo.Parts[0]
  483. encoding := transfer.QuotedPrintable
  484. if strings.Contains(part.TransferEncoding, "base") {
  485. encoding = transfer.Base64
  486. }
  487. dr, err := transfer.NewDecoder(r, encoding, part.Charset)
  488. _ = dr
  489. if err != nil {
  490. t.Error(err)
  491. t.FailNow()
  492. }
  493. //var decoded bytes.Buffer
  494. //io.Copy(&decoded, dr)
  495. io.Copy(os.Stdout, dr)
  496. }
  497. }
  498. func initTestStream(transform bool) (*StoreMemory, *backends.StreamDecorator, *backends.StreamDecorator, backends.StreamProcessor) {
  499. // place the parse result in an envelope
  500. e := mail.NewEnvelope("127.0.0.1", 1)
  501. to, _ := mail.NewAddress("[email protected]")
  502. e.RcptTo = append(e.RcptTo, to)
  503. e.MailFrom, _ = mail.NewAddress("[email protected]")
  504. store := new(StoreMemory)
  505. chunkBuffer := NewChunkedBytesBufferMime()
  506. //chunkBuffer.setDatabase(store)
  507. // instantiate the chunk saver
  508. chunksaver := backends.Streamers["chunksaver"]()
  509. mimeanalyzer := backends.Streamers["mimeanalyzer"]()
  510. transformer := backends.Streamers["transformer"]()
  511. //debug := backends.Streamers["debug"]()
  512. // add the default processor as the underlying processor for chunksaver
  513. // and chain it with mimeanalyzer.
  514. // Call order: mimeanalyzer -> chunksaver -> default (terminator)
  515. // This will also set our Open, Close and Initialize functions
  516. // we also inject a Storage and a ChunkingBufferMime
  517. var stream backends.StreamProcessor
  518. if transform {
  519. stream = mimeanalyzer.Decorate(
  520. transformer.Decorate(
  521. //debug.Decorate(
  522. chunksaver.Decorate(
  523. backends.DefaultStreamProcessor{}, store, chunkBuffer))) //)
  524. } else {
  525. stream = mimeanalyzer.Decorate(
  526. //debug.Decorate(
  527. chunksaver.Decorate(
  528. backends.DefaultStreamProcessor{}, store, chunkBuffer)) //)
  529. }
  530. // configure the buffer cap
  531. bc := backends.BackendConfig{}
  532. bc["chunksaver_chunk_size"] = 8000
  533. bc["chunksaver_storage_engine"] = "memory"
  534. bc["chunksaver_compress_level"] = 0
  535. _ = backends.Svc.Initialize(bc)
  536. // give it the envelope with the parse results
  537. _ = chunksaver.Open(e)
  538. _ = mimeanalyzer.Open(e)
  539. if transform {
  540. _ = transformer.Open(e)
  541. }
  542. return store, chunksaver, mimeanalyzer, stream
  543. }