chunk_test.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  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 n1 = `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=utf8
  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=utf8
  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/png; name="three.png"
  112. Content-Transfer-Encoding: 8bit
  113. `
  114. var email = `From: Al Gore <[email protected]>
  115. To: White House Transportation Coordinator <[email protected]>
  116. Subject: [Fwd: Map of Argentina with Description]
  117. MIME-Version: 1.0
  118. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed; s=ncr424; d=reliancegeneral.co.in;
  119. h=List-Unsubscribe:MIME-Version:From:To:Reply-To:Date:Subject:Content-Type:Content-Transfer-Encoding:Message-ID; [email protected];
  120. bh=F4UQPGEkpmh54C7v3DL8mm2db1QhZU4gRHR1jDqffG8=;
  121. b=MVltcq6/I9b218a370fuNFLNinR9zQcdBSmzttFkZ7TvV2mOsGrzrwORT8PKYq4KNJNOLBahswXf
  122. GwaMjDKT/5TXzegdX/L3f/X4bMAEO1einn+nUkVGLK4zVQus+KGqm4oP7uVXjqp70PWXScyWWkbT
  123. 1PGUwRfPd/HTJG5IUqs=
  124. Content-Type: multipart/mixed;
  125. boundary="D7F------------D7FD5A0B8AB9C65CCDBFA872"
  126. This is a multi-part message in MIME format.
  127. --D7F------------D7FD5A0B8AB9C65CCDBFA872
  128. Content-Type: text/plain; charset=us-ascii
  129. Content-Transfer-Encoding: 7bit
  130. Fred,
  131. Fire up Air Force One! We're going South!
  132. Thanks,
  133. Al
  134. --D7F------------D7FD5A0B8AB9C65CCDBFA872
  135. Content-Type: message/rfc822
  136. Content-Transfer-Encoding: 7bit
  137. Content-Disposition: inline
  138. Return-Path: <[email protected]>
  139. Received: from mailhost.whitehouse.gov ([192.168.51.200])
  140. by heartbeat.whitehouse.gov (8.8.8/8.8.8) with ESMTP id SAA22453
  141. for <[email protected]>;
  142. Mon, 13 Aug 1998 l8:14:23 +1000
  143. Received: from the_big_box.whitehouse.gov ([192.168.51.50])
  144. by mailhost.whitehouse.gov (8.8.8/8.8.7) with ESMTP id RAA20366
  145. for [email protected]; Mon, 13 Aug 1998 17:42:41 +1000
  146. Date: Mon, 13 Aug 1998 17:42:41 +1000
  147. Message-Id: <[email protected]>
  148. From: Bill Clinton <[email protected]>
  149. To: A1 (The Enforcer) Gore <[email protected]>
  150. Subject: Map of Argentina with Description
  151. MIME-Version: 1.0
  152. Content-Type: multipart/mixed;
  153. boundary="DC8------------DC8638F443D87A7F0726DEF7"
  154. This is a multi-part message in MIME format.
  155. --DC8------------DC8638F443D87A7F0726DEF7
  156. Content-Type: text/plain; charset=us-ascii
  157. Content-Transfer-Encoding: 7bit
  158. Hi A1,
  159. I finally figured out this MIME thing. Pretty cool. I'll send you
  160. some sax music in .au files next week!
  161. Anyway, the attached image is really too small to get a good look at
  162. Argentina. Try this for a much better map:
  163. http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
  164. Then again, shouldn't the CIA have something like that?
  165. Bill
  166. --DC8------------DC8638F443D87A7F0726DEF7
  167. Content-Type: image/gif; name="three.gif"
  168. Content-Transfer-Encoding: base64
  169. Content-Disposition: attachment; filename="three.gif"
  170. R0lGODlhEAAeAPAAAP///wAAACH5BAEAAAAALAAAAAAQAB4AAAIfhI+py+0Po5y0onCD3lzbD15K
  171. R4ZmiAHk6p3uC8dWAQA7
  172. --DC8------------DC8638F443D87A7F0726DEF7--
  173. --D7F------------D7FD5A0B8AB9C65CCDBFA872--
  174. `
  175. var email2 = `Delivered-To: [email protected]
  176. Received: from aaa.cn (aaa.cn [220.178.145.250])
  177. by 163.com with SMTP id [email protected];
  178. Tue, 17 Sep 2019 01:16:43 +0000
  179. 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]>
  180. To: <[email protected]>
  181. Subject: =?utf-8?Q?=E5=BA=94=E5=8A=9B=E6=AF=94b?=
  182. Date: Tue, 17 Sep 2019 09:16:29 +0800
  183. Message-ID: <[email protected]>
  184. MIME-Version: 1.0
  185. Content-Type: text/html;
  186. charset="utf-8"
  187. Content-Transfer-Encoding: 8bit
  188. X-Priority: 3 (Normal)
  189. X-MSMail-Priority: Normal
  190. X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0)
  191. Importance: Normal
  192. X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180
  193. <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>
  194. <HR>
  195. <P></P>
  196. <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>
  197. <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>`
  198. var email3 = `Delivered-To: [email protected]
  199. 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])
  200. by sharklasers.com with SMTP id [email protected];
  201. Tue, 17 Sep 2019 01:13:00 +0000
  202. Received: from mx03.listsystemsf.net [100.20.38.85] by mxs.perenter.com with SMTP; Tue, 17 Sep 2019 04:57:59 +0500
  203. Received: from mts.locks.grgtween.net ([Tue, 17 Sep 2019 04:52:27 +0500])
  204. by webmail.halftomorrow.com with LOCAL; Tue, 17 Sep 2019 04:52:27 +0500
  205. 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
  206. Received: from unknown (HELO mx03.listsystemsf.net) (Tue, 17 Sep 2019 04:41:45 +0500)
  207. by smtp-server1.cfdenselr.com with LOCAL; Tue, 17 Sep 2019 04:41:45 +0500
  208. Message-ID: <[email protected]>
  209. Date: Tue, 17 Sep 2019 04:14:56 +0500
  210. Reply-To: "Nevaeh" <[email protected]>
  211. From: "Nevaeh" <[email protected]>
  212. User-Agent: Mozilla 4.73 [de]C-CCK-MCD DT (Win98; U)
  213. X-Accept-Language: en-us
  214. MIME-Version: 1.0
  215. To: "Nevaeh" <[email protected]>
  216. Subject: czy m�glbys spotkac sie ze mna w weekend?
  217. Content-Type: text/html;
  218. charset="iso-8859-1""
  219. Content-Transfer-Encoding: base64
  220. PCFkb2N0eXBlIGh0bWw+DQo8aHRtbD4NCjxoZWFkPg0KPG1ldGEgY2hhcnNldD0idXRmLTgiPg0K
  221. PC9oZWFkPg0KPGJvZHk+DQo8dGFibGUgd2lkdGg9IjYwMCIgYm9yZGVyPSIwIiBhbGlnbj0iY2Vu
  222. dGVyIiBzdHlsZT0iZm9udC1mYW1pbHk6IEFyaWFsOyBmb250LXNpemU6IDE4cHgiPg0KPHRib2R5
  223. Pg0KPHRyPg0KPHRoIGhlaWdodD0iNjAiIHNjb3BlPSJjb2wiPk5hamdvcmV0c3plIGR6aWV3Y3p5
  224. bnkgaSBzYW1vdG5lIGtvYmlldHksIGt083JlIGNoY2Egc2Vrc3UuPG9sPjwvb2w+PC90aD4NCjwv
  225. dHI+DQo8dGQgaGVpZ2h0PSIyMjMiIGFsaWduPSJjZW50ZXIiPjxwPk5hIG5hc3plaiBzdHJvbmll
  226. IGdyb21hZHpvbmUgc2EgbWlsaW9ueSBwcm9maWxpIGtvYmlldC4gV3N6eXNjeSBjaGNhIHRlcmF6
  227. IHBpZXByenljLjwvcD4NCjxoZWFkZXI+PC9oZWFkZXI+DQo8cD5OYSBwcnp5a2xhZCBzYSBXIFRX
  228. T0lNIE1JRVNDSUUuIENoY2VzeiBpbm55Y2g/IFpuYWpkeiBuYSBuYXN6ZWogc3Ryb25pZSE8L3A+
  229. DQo8dGFibGUgY2xhc3M9Im1jbkJ1dHRvbkNvbnRlbnRDb250YWluZXIiIHN0eWxlPSJib3JkZXIt
  230. Y29sbGFwc2U6IHNlcGFyYXRlICEgaW1wb3J0YW50O2JvcmRlci1yYWRpdXM6IDNweDtiYWNrZ3Jv
  231. dW5kLWNvbG9yOiAjRTc0MTQxOyIgYm9yZGVyPSIwIiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRp
  232. bmc9IjAiPg0KIDx0Ym9keT4NCiA8dHI+DQogPHRkIGNsYXNzPSJtY25CdXR0b25Db250ZW50IiBz
  233. dHlsZT0iZm9udC1mYW1pbHk6IEFyaWFsOyBmb250LXNpemU6IDIycHg7IHBhZGRpbmc6IDE1cHgg
  234. MjVweDsiIHZhbGlnbj0ibWlkZGxlIiBhbGlnbj0iY2VudGVyIj4NCiA8YSBjbGFzcz0ibWNuQnV0
  235. dG9uICIgaHJlZj0iaHR0cDovL2JldGhhbnkuc3UiIHRhcmdldD0iX2JsYW5rIiBzdHlsZT0iZm9u
  236. dC13ZWlnaHQ6IG5vcm1hbDtsZXR0ZXItc3BhY2luZzogbm9ybWFsO2xpbmUtaGVpZ2h0OiAxMDAl
  237. O3RleHQtYWxpZ246IGNlbnRlcjt0ZXh0LWRlY29yYXRpb246IG5vbmU7Y29sb3I6ICNGRkZGRkY7
  238. Ij5odHRwOi8vYmV0aGFueS5zdTwvYT4NCiA8L3RkPg0KIDwvdHI+DQogPC90Ym9keT4NCiA8L3Rh
  239. YmxlPjx0YWJsZSB3aWR0aD0iMjglIiBib3JkZXI9IjAiPjx0Ym9keT48dHI+PHRkPjwvdGQ+PHRk
  240. PjwvdGQ+PHRkPjwvdGQ+PC90cj48L3Rib2R5PjwvdGFibGU+DQo8dGFibGUgc3R5bGU9Im1pbi13
  241. aWR0aDoxMDAlOyIgY2xhc3M9Im1jblRleHRDb250ZW50Q29udGFpbmVyIiBhbGlnbj0ibGVmdCIg
  242. Ym9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHdpZHRoPSIxMDAlIj4N
  243. Cjx0Ym9keT4NCiA8dHI+DQo8dGQgYWxpZ249ImNlbnRlciIgdmFsaWduPSJ0b3AiIGNsYXNzPSJt
  244. Y25UZXh0Q29udGVudCIgc3R5bGU9InBhZGRpbmc6IDlweCAxOHB4O2NvbG9yOiAjNkI2QjZCO2Zv
  245. bnQtZmFtaWx5OiBWZXJkYW5hLEdlbmV2YSxzYW5zLXNlcmlmO2ZvbnQtc2l6ZTogMTFweDsiPg0K
  246. VXp5aiB0ZWdvIGxpbmt1LCBqZXNsaSBwcnp5Y2lzayBuaWUgZHppYWxhPGJyPg0KPGEgaHJlZj0i
  247. aHR0cDovL2JldGhhbnkuc3UiIHRhcmdldD0iX2JsYW5rIj5odHRwOi8vYmV0aGFueS5zdTwvYT48
  248. YnI+DQpTa29waXVqIGkgd2tsZWogbGluayBkbyBwcnplZ2xhZGFya2k8L3RkPg0KPC90cj4NCjwv
  249. dGJvZHk+PC90YWJsZT48L3RkPg0KPC90cj4gDQo8L3Rib2R5Pg0KPC90YWJsZT4NCjxvbD48cD48
  250. L3A+PC9vbD4NCjx0YWJsZSB3aWR0aD0iNjAwIiBib3JkZXI9IjAiIGFsaWduPSJjZW50ZXIiPg0K
  251. IDx0Ym9keT4NCiA8dHI+DQogPHRkPjxhIGhyZWY9Imh0dHA6Ly9iZXRoYW55LnN1Ij48cCBzdHls
  252. ZT0idGV4dC1hbGlnbjogY2VudGVyIj5DYW1pbGE8L3A+DQogPG5hdj48L25hdj4NCiA8dGFibGU+
  253. DQogPHRyPg0KIDx0ZCB2YWxpZ249InRvcCIgc3R5bGU9ImJhY2tncm91bmQ6IHVybChodHRwczov
  254. L3RoZWNoaXZlLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxOS8wOS9iODE0NmEyOTI3ODY4ODkxNzk4
  255. ODY1NDhlN2QzOWEzZV93aWR0aC02MDAuanBlZz9xdWFsaXR5PTEwMCZzdHJpcD1pbmZvJnc9NjQx
  256. Jnpvb209Mikgbm8tcmVwZWF0IGNlbnRlcjtiYWNrZ3JvdW5kLXBvc2l0aW9uOiB0b3A7YmFja2dy
  257. b3VuZC1zaXplOiBjb3ZlcjsiPjwhLS1baWYgZ3RlIG1zbyA5XT4gPHY6cmVjdCB4bWxuczp2PSJ1
  258. cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbCIgZmlsbD0idHJ1ZSIgc3Ryb2tlPSJmYWxzZSIg
  259. c3R5bGU9Im1zby13aWR0aC1wZXJjZW50OjEwMDA7aGVpZ2h0OjQwMHB4OyI+IDx2OmZpbGwgdHlw
  260. ZT0idGlsZSIgc3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxOS8w
  261. OC82YWU4NzFiNTlmYjUxMDc1ZGMwMzE3ZDBiOTkzZjJhOV93aWR0aC02MDAuanBnP3F1YWxpdHk9
  262. MTAwJnN0cmlwPWluZm8mdz02NDEmem9vbT0yIiAvPiA8djp0ZXh0Ym94IGluc2V0PSIwLDAsMCww
  263. Ij4gPCFbZW5kaWZdLS0+DQogPGRpdj4NCiA8Y2VudGVyPg0KIDx0YWJsZSBjZWxsc3BhY2luZz0i
  264. MCIgY2VsbHBhZGRpbmc9IjAiIHdpZHRoPSIyODAiIGhlaWdodD0iNDAwIj4NCiA8dHI+DQogPHRk
  265. IHZhbGlnbj0ibWlkZGxlIiBzdHlsZT0idmVydGljYWwtYWxpZ246bWlkZGxlO3RleHQtYWxpZ246
  266. bGVmdDsiIGNsYXNzPSJtb2JpbGUtY2VudGVyIiBoZWlnaHQ9IjQwMCI+PGFydGljbGU+PC9hcnRp
  267. Y2xlPiA8L3RkPg0KIDwvdHI+DQogPC90YWJsZT4NCiA8L2NlbnRlcj4NCiA8L2Rpdj4NCiA8IS0t
  268. W2lmIGd0ZSBtc28gOV0+IDwvdjp0ZXh0Ym94PiA8L3Y6cmVjdD4gPCFbZW5kaWZdLS0+PC90ZD4N
  269. CiA8L3RyPg0KIDwvdGFibGU+DQogPC9hPjwvdGQ+DQogPHRkPjxhIGhyZWY9Imh0dHA6Ly9iZXRo
  270. YW55LnN1Ij48cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyIj5NaWxhPC9wPg0KIDxkaXY+PC9k
  271. aXY+DQogPHRhYmxlPg0KIDx0cj4NCiA8dGQgdmFsaWduPSJ0b3AiIHN0eWxlPSJiYWNrZ3JvdW5k
  272. OiB1cmwoaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIwMTkvMDgvODg1ZGFi
  273. OTM2MGZiYzY2NGMzYTNhNDQwOGI1NTE2ZDUtMS5qcGc/cXVhbGl0eT0xMDAmc3RyaXA9aW5mbyZ3
  274. PTY0MSZ6b29tPTIpIG5vLXJlcGVhdCBjZW50ZXI7YmFja2dyb3VuZC1wb3NpdGlvbjogdG9wO2Jh
  275. Y2tncm91bmQtc2l6ZTogY292ZXI7Ij48IS0tW2lmIGd0ZSBtc28gOV0+IDx2OnJlY3QgeG1sbnM6
  276. dj0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwiIGZpbGw9InRydWUiIHN0cm9rZT0iZmFs
  277. c2UiIHN0eWxlPSJtc28td2lkdGgtcGVyY2VudDoxMDAwO2hlaWdodDo0MDBweDsiPiA8djpmaWxs
  278. IHR5cGU9InRpbGUiIHNyYz0iaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIw
  279. MTkvMDgvMGE2Mzc2MDVkYzhkOTcyNzRhZWFkODVhOGY0YTJmYjkuanBnP3F1YWxpdHk9MTAwJnN0
  280. cmlwPWluZm8mdz02MDAiIC8+IDx2OnRleHRib3ggaW5zZXQ9IjAsMCwwLDAiPiA8IVtlbmRpZl0t
  281. LT4NCg0KIDxkaXY+DQogPGNlbnRlcj4NCiA8dGFibGUgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRk
  282. aW5nPSIwIiB3aWR0aD0iMjgwIiBoZWlnaHQ9IjQwMCI+DQogPHRyPg0KIDx0ZCB2YWxpZ249Im1p
  283. ZGRsZSIgc3R5bGU9InZlcnRpY2FsLWFsaWduOm1pZGRsZTt0ZXh0LWFsaWduOmxlZnQ7IiBjbGFz
  284. cz0ibW9iaWxlLWNlbnRlciIgaGVpZ2h0PSI0MDAiPjxocj4gPC90ZD4NCiA8L3RyPg0KIDwvdGFi
  285. bGU+DQogPC9jZW50ZXI+DQogPC9kaXY+DQogPCEtLVtpZiBndGUgbXNvIDldPiA8L3Y6dGV4dGJv
  286. eD4gPC92OnJlY3Q+IDwhW2VuZGlmXS0tPjwvdGQ+DQogPC90cj4NCiA8L3RhYmxlPg0KIDwvYT48
  287. L3RkPg0KIDwvdHI+DQogPHRyPg0KIDx0ZD48YSBocmVmPSJodHRwOi8vYmV0aGFueS5zdSI+PHAg
  288. c3R5bGU9InRleHQtYWxpZ246IGNlbnRlciI+THVuYTwvcD4NCiA8dGFibGUgd2lkdGg9Ijc0JSIg
  289. Ym9yZGVyPSIwIj48dGJvZHk+PHRyPjx0ZD48L3RkPjx0ZD48L3RkPjx0ZD48L3RkPjx0ZD48L3Rk
  290. Pjx0ZD48L3RkPjwvdHI+PC90Ym9keT48L3RhYmxlPg0KIDx0YWJsZT4NCiA8dHI+DQogPHRkIHZh
  291. bGlnbj0idG9wIiBzdHlsZT0iYmFja2dyb3VuZDogdXJsKGh0dHBzOi8vdGhlY2hpdmUuZmlsZXMu
  292. d29yZHByZXNzLmNvbS8yMDE5LzA4LzA2ZTU2YTU4ZjQ3ZDM0OGEyMjc3NmYyOTFlNjg2OWEwLTEu
  293. anBnP3F1YWxpdHk9MTAwJnN0cmlwPWluZm8mdz02NDEmem9vbT0yKSBuby1yZXBlYXQgY2VudGVy
  294. O2JhY2tncm91bmQtcG9zaXRpb246IHRvcDtiYWNrZ3JvdW5kLXNpemU6IGNvdmVyOyI+PCEtLVtp
  295. ZiBndGUgbXNvIDldPiA8djpyZWN0IHhtbG5zOnY9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206
  296. dm1sIiBmaWxsPSJ0cnVlIiBzdHJva2U9ImZhbHNlIiBzdHlsZT0ibXNvLXdpZHRoLXBlcmNlbnQ6
  297. MTAwMDtoZWlnaHQ6NDAwcHg7Ij4gPHY6ZmlsbCB0eXBlPSJ0aWxlIiBzcmM9Imh0dHBzOi8vdGhl
  298. Y2hpdmUuZmlsZXMud29yZHByZXNzLmNvbS8yMDE5LzA4LzhhYjRkYzcxMjFlYTVhMzdiMTc3NjNm
  299. ZjRhNDA1MTVlLmpwZz9xdWFsaXR5PTEwMCZzdHJpcD1pbmZvJnc9NjQxJnpvb209MiIgLz4gPHY6
  300. dGV4dGJveCBpbnNldD0iMCwwLDAsMCI+IDwhW2VuZGlmXS0tPg0KIDxkaXY+DQogPGNlbnRlcj4N
  301. CiA8dGFibGUgY2VsbHNwYWNpbmc9IjAiIGNlbGxwYWRkaW5nPSIwIiB3aWR0aD0iMjgwIiBoZWln
  302. aHQ9IjQwMCI+DQogPHRyPg0KIDx0ZCB2YWxpZ249Im1pZGRsZSIgc3R5bGU9InZlcnRpY2FsLWFs
  303. aWduOm1pZGRsZTt0ZXh0LWFsaWduOmxlZnQ7IiBjbGFzcz0ibW9iaWxlLWNlbnRlciIgaGVpZ2h0
  304. PSI0MDAiPjxicj4gPC90ZD4NCiA8L3RyPg0KIDwvdGFibGU+DQogPC9jZW50ZXI+DQogPC9kaXY+
  305. DQogPCEtLVtpZiBndGUgbXNvIDldPiA8L3Y6dGV4dGJveD4gPC92OnJlY3Q+IDwhW2VuZGlmXS0t
  306. PjwvdGQ+DQogPC90cj4NCiA8L3RhYmxlPg0KIDwvYT48L3RkPg0KIDx0ZD48YSBocmVmPSJodHRw
  307. Oi8vYmV0aGFueS5zdSI+PHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlciI+U2F2YW5uYWg8L3A+
  308. DQogPG9sPjwvb2w+DQogPHRhYmxlPg0KIDx0cj4NCiA8dGQgdmFsaWduPSJ0b3AiIHN0eWxlPSJi
  309. YWNrZ3JvdW5kOiB1cmwoaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIwMTkv
  310. MDgvYzA4MzYxNTE2MzUxNDFkNDhlY2ZmYTNkYmZkOGYxZDYuanBnP3F1YWxpdHk9MTAwJnN0cmlw
  311. PWluZm8mdz02NDEmem9vbT0yKSBuby1yZXBlYXQgY2VudGVyO2JhY2tncm91bmQtcG9zaXRpb246
  312. IHRvcDtiYWNrZ3JvdW5kLXNpemU6IGNvdmVyOyI+PCEtLVtpZiBndGUgbXNvIDldPiA8djpyZWN0
  313. IHhtbG5zOnY9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206dm1sIiBmaWxsPSJ0cnVlIiBzdHJv
  314. a2U9ImZhbHNlIiBzdHlsZT0ibXNvLXdpZHRoLXBlcmNlbnQ6MTAwMDtoZWlnaHQ6NDAwcHg7Ij4g
  315. PHY6ZmlsbCB0eXBlPSJ0aWxlIiBzcmM9Imh0dHBzOi8vdGhlY2hpdmUuZmlsZXMud29yZHByZXNz
  316. LmNvbS8yMDE5LzA4L2NhMWI4MWI5MTkyYTZkMzEyNTI1MmYwYzIwZWIxMjVjLmpwZz9xdWFsaXR5
  317. PTEwMCZzdHJpcD1pbmZvJnc9NjQxJnpvb209MiIgLz4gPHY6dGV4dGJveCBpbnNldD0iMCwwLDAs
  318. MCI+IDwhW2VuZGlmXS0tPg0KIDxkaXY+DQogPGNlbnRlcj4NCiA8dGFibGUgY2VsbHNwYWNpbmc9
  319. IjAiIGNlbGxwYWRkaW5nPSIwIiB3aWR0aD0iMjgwIiBoZWlnaHQ9IjQwMCI+DQogPHRyPg0KIDx0
  320. ZCB2YWxpZ249Im1pZGRsZSIgc3R5bGU9InZlcnRpY2FsLWFsaWduOm1pZGRsZTt0ZXh0LWFsaWdu
  321. OmxlZnQ7IiBjbGFzcz0ibW9iaWxlLWNlbnRlciIgaGVpZ2h0PSI0MDAiPjxtYWluPjwvbWFpbj4g
  322. PC90ZD4NCiA8L3RyPg0KIDwvdGFibGU+DQogPC9jZW50ZXI+DQogPC9kaXY+DQogPCEtLVtpZiBn
  323. dGUgbXNvIDldPiA8L3Y6dGV4dGJveD4gPC92OnJlY3Q+IDwhW2VuZGlmXS0tPjwvdGQ+DQogPC90
  324. cj4NCiA8L3RhYmxlPg0KIDwvYT48L3RkPg0KIDwvdHI+DQogPC90Ym9keT4NCjwvdGFibGU+DQo8
  325. dGFibGUgd2lkdGg9IjYxJSIgYm9yZGVyPSIwIj48dGJvZHk+PHRyPjx0ZD48L3RkPjx0ZD48L3Rk
  326. PjwvdHI+PC90Ym9keT48L3RhYmxlPg0KPHRhYmxlIHdpZHRoPSI2MDAiIGJvcmRlcj0iMCIgYWxp
  327. Z249ImNlbnRlciI+DQo8dGJvZHk+DQo8dHI+DQo8dGg+PHAgc3R5bGU9InRleHQtYWxpZ246IGNl
  328. bnRlciI+QnJvb2tseW48L3A+DQogPHA+PGEgaHJlZj0iaHR0cDovL2JldGhhbnkuc3UiPjxpbWcg
  329. c3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxOS8wOC9kMzc0Zjcx
  330. NDI0Nzc0MjEwNzdkOWQzZTg4ZmI1OTMxMS5qcGc/cXVhbGl0eT0xMDAmc3RyaXA9aW5mbyZ3PTY0
  331. MSZ6b29tPTIiIHdpZHRoPSIyODAiIGFsdD0ib3BlbiBwcm9maWxlIi8+PC9hPjwvcD48L3RoPg0K
  332. PHRoPjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXIiPkVtbWE8L3A+DQogPHA+PGEgaHJlZj0i
  333. aHR0cDovL2JldGhhbnkuc3UiPjxpbWcgc3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRw
  334. cmVzcy5jb20vMjAxOS8wOC9kNTk4ZjdlYTYxYWZjYTNjYjg2MjVkN2NmYTE5NzRiNC5qcGc/cXVh
  335. bGl0eT0xMDAmc3RyaXA9aW5mbyZ3PTY0MSZ6b29tPTIiIHdpZHRoPSIyODAiIGFsdD0ib3BlbiBw
  336. cm9maWxlIi8+PC9hPjwvcD48L3RoPg0KPC90cj4NCjx0cj4NCjx0ZD48dGFibGUgd2lkdGg9IjUw
  337. JSIgYm9yZGVyPSIwIj48dGJvZHk+PHRyPjx0ZD48L3RkPjx0ZD48L3RkPjwvdHI+PC90Ym9keT48
  338. L3RhYmxlPjwvdGQ+DQo8dGQ+PHVsPjxwPjwvcD48L3VsPjwvdGQ+DQo8L3RyPg0KPHRyPg0KPHRo
  339. PjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXIiPkVtbWE8L3A+DQogPHA+PGEgaHJlZj0iaHR0
  340. cDovL2JldGhhbnkuc3UiPjxpbWcgc3JjPSJodHRwczovL3RoZWNoaXZlLmZpbGVzLndvcmRwcmVz
  341. cy5jb20vMjAxOS8wOS85YzU1ZjA1MmMzZDZhODgyZGYxMTFhZDZhZmFjOWMwNF93aWR0aC02MDAu
  342. anBlZz9xdWFsaXR5PTEwMCZzdHJpcD1pbmZvJnc9NjQxJnpvb209MiIgd2lkdGg9IjI4MCIgYWx0
  343. PSJvcGVuIHByb2ZpbGUiLz48L2E+PC9wPjwvdGg+DQo8dGg+PHAgc3R5bGU9InRleHQtYWxpZ246
  344. IGNlbnRlciI+QXZhPC9wPg0KIDxwPjxhIGhyZWY9Imh0dHA6Ly9iZXRoYW55LnN1Ij48aW1nIHNy
  345. Yz0iaHR0cHM6Ly90aGVjaGl2ZS5maWxlcy53b3JkcHJlc3MuY29tLzIwMTkvMDkvMzdlMDM1ZGZj
  346. YTM2NjkyZTk3ZTA4OWFjN2ZiNWVjN2QuanBnP3F1YWxpdHk9MTAwJnN0cmlwPWluZm8mdz02NDEm
  347. em9vbT0yIiB3aWR0aD0iMjgwIiBhbHQ9Im9wZW4gcHJvZmlsZSIvPjwvYT48L3A+PC90aD4NCjwv
  348. dHI+DQo8L3Rib2R5Pg0KPC90YWJsZT4NCjxuYXY+PC9uYXY+DQo8dGFibGUgc3R5bGU9Im1heC13
  349. aWR0aDo2MDBweDsgIiBjbGFzcz0ibWNuVGV4dENvbnRlbnRDb250YWluZXIiIHdpZHRoPSIxMDAl
  350. IiBjZWxsc3BhY2luZz0iMCIgY2VsbHBhZGRpbmc9IjAiIGJvcmRlcj0iMCIgYWxpZ249ImNlbnRl
  351. ciI+DQo8dGJvZHk+PHRyPg0KPHRkIGNsYXNzPSJtY25UZXh0Q29udGVudCIgc3R5bGU9InBhZGRp
  352. bmctdG9wOjA7IHBhZGRpbmctcmlnaHQ6MThweDsgcGFkZGluZy1ib3R0b206OXB4OyBwYWRkaW5n
  353. LWxlZnQ6MThweDsiIHZhbGlnbj0idG9wIj4NCiAgIDxhIGhyZWY9Imh0dHA6Ly9iZXRoYW55LnN1
  354. L3Vuc3ViL3Vuc3ViLnBocCI+PHRhYmxlIHdpZHRoPSIwOCUiIGJvcmRlcj0iMCI+PHRib2R5Pjx0
  355. cj48dGQ+PC90ZD48dGQ+PC90ZD48L3RyPjwvdGJvZHk+PC90YWJsZT51bnN1YnNjcmliZSBmcm9t
  356. IHRoaXMgbGlzdDwvYT4uPGJyPg0KPC90ZD4NCjwvdHI+DQo8L3Rib2R5PjwvdGFibGU+DQo8L2Jv
  357. ZHk+DQo8L2h0bWw+DQo=`
  358. func TestHashBytes(t *testing.T) {
  359. var h HashKey
  360. h.Pack([]byte{222, 23, 3, 128, 1, 23, 3, 128, 1, 23, 3, 255, 1, 23, 3, 128})
  361. if h.String() != "3hcDgAEXA4ABFwP/ARcDgA" {
  362. t.Error("expecting 3hcDgAEXA4ABFwP/ARcDgA got", h.String())
  363. }
  364. }
  365. func TestTransformer(t *testing.T) {
  366. store, chunksaver, mimeanalyzer, stream := initTestStream(true)
  367. buf := make([]byte, 64)
  368. var result bytes.Buffer
  369. if _, err := io.CopyBuffer(stream, bytes.NewBuffer([]byte(email3)), buf); err != nil {
  370. t.Error(err)
  371. } else {
  372. _ = mimeanalyzer.Close()
  373. _ = chunksaver.Close()
  374. email, err := store.GetEmail(1)
  375. if err != nil {
  376. t.Error("email not found")
  377. return
  378. }
  379. // this should read all parts
  380. r, err := NewChunkedReader(store, email, 0)
  381. buf2 := make([]byte, 64)
  382. if w, err := io.CopyBuffer(&result, r, buf2); err != nil {
  383. t.Error(err)
  384. } else if w != email.size {
  385. t.Error("email.size != number of bytes copied from reader", w, email.size)
  386. }
  387. if !strings.Contains(result.String(), "</html>") {
  388. t.Error("Looks like it didn;t read the entire email, was expecting </html>")
  389. }
  390. result.Reset()
  391. }
  392. }
  393. func TestChunkSaverReader(t *testing.T) {
  394. store, chunksaver, mimeanalyzer, stream := initTestStream(false)
  395. buf := make([]byte, 64)
  396. var result bytes.Buffer
  397. if _, err := io.CopyBuffer(stream, bytes.NewBuffer([]byte(email3)), buf); err != nil {
  398. t.Error(err)
  399. } else {
  400. _ = mimeanalyzer.Close()
  401. _ = chunksaver.Close()
  402. email, err := store.GetEmail(1)
  403. if err != nil {
  404. t.Error("email not found")
  405. return
  406. }
  407. // this should read all parts
  408. r, err := NewChunkedReader(store, email, 0)
  409. buf2 := make([]byte, 64)
  410. if w, err := io.CopyBuffer(&result, r, buf2); err != nil {
  411. t.Error(err)
  412. } else if w != email.size {
  413. t.Error("email.size != number of bytes copied from reader", w, email.size)
  414. }
  415. if !strings.Contains(result.String(), "k+DQo8L2h0bWw+DQo") {
  416. t.Error("Looks like it didn;t read the entire email, was expecting k+DQo8L2h0bWw+DQo")
  417. }
  418. result.Reset()
  419. // Test the decoder, hit the decoderStateMatchNL state
  420. r, err = NewChunkedReader(store, email, 0)
  421. if err != nil {
  422. t.Error(err)
  423. }
  424. part := email.partsInfo.Parts[0]
  425. encoding := transfer.QuotedPrintable
  426. if strings.Contains(part.TransferEncoding, "base") {
  427. encoding = transfer.Base64
  428. }
  429. dr, err := transfer.NewDecoder(r, encoding, part.Charset)
  430. _ = dr
  431. if err != nil {
  432. t.Error(err)
  433. t.FailNow()
  434. }
  435. buf3 := make([]byte, 1253) // 1253 intentionally causes the decoderStateMatchNL state to hit
  436. _, err = io.CopyBuffer(&result, dr, buf3)
  437. if err != nil {
  438. t.Error()
  439. }
  440. if !strings.Contains(result.String(), "</html") {
  441. t.Error("looks like it didn't decode, expecting </html>")
  442. }
  443. result.Reset()
  444. // test the decoder, hit the decoderStateFindHeaderEnd state
  445. r, err = NewChunkedReader(store, email, 0)
  446. if err != nil {
  447. t.Error(err)
  448. }
  449. part = email.partsInfo.Parts[0]
  450. encoding = transfer.QuotedPrintable
  451. if strings.Contains(part.TransferEncoding, "base") {
  452. encoding = transfer.Base64
  453. }
  454. dr, err = transfer.NewDecoder(r, encoding, part.Charset)
  455. _ = dr
  456. if err != nil {
  457. t.Error(err)
  458. t.FailNow()
  459. }
  460. buf4 := make([]byte, 64) // state decoderStateFindHeaderEnd will hit
  461. _, err = io.CopyBuffer(&result, dr, buf4)
  462. if err != nil {
  463. t.Error()
  464. }
  465. if !strings.Contains(result.String(), "</html") {
  466. t.Error("looks like it didn't decode, expecting </html>")
  467. }
  468. }
  469. }
  470. func TestChunkSaverWrite(t *testing.T) {
  471. store, chunksaver, mimeanalyzer, stream := initTestStream(true)
  472. var out bytes.Buffer
  473. buf := make([]byte, 128)
  474. if written, err := io.CopyBuffer(stream, bytes.NewBuffer([]byte(email)), buf); err != nil {
  475. t.Error(err)
  476. } else {
  477. _ = mimeanalyzer.Close()
  478. _ = chunksaver.Close()
  479. fmt.Println("written:", written)
  480. total := 0
  481. for _, chunk := range store.chunks {
  482. total += len(chunk.data)
  483. }
  484. fmt.Println("compressed", total, "saved:", written-int64(total))
  485. email, err := store.GetEmail(1)
  486. if err != nil {
  487. t.Error("email not found")
  488. return
  489. }
  490. // this should read all parts
  491. r, err := NewChunkedReader(store, email, 0)
  492. if w, err := io.Copy(&out, r); err != nil {
  493. t.Error(err)
  494. } else if w != email.size {
  495. t.Error("email.size != number of bytes copied from reader", w, email.size)
  496. } else if !strings.Contains(out.String(), "GIF89") {
  497. t.Error("The email didn't decode properly, expecting GIF89")
  498. }
  499. out.Reset()
  500. // test the seek feature
  501. r, err = NewChunkedReader(store, email, 0)
  502. if err != nil {
  503. t.Error(err)
  504. t.FailNow()
  505. }
  506. // we start from 1 because if the start from 0, all the parts will be read
  507. for i := 1; i < len(email.partsInfo.Parts); i++ {
  508. fmt.Println("seeking to", i)
  509. err = r.SeekPart(i)
  510. if err != nil {
  511. t.Error(err)
  512. }
  513. w, err := io.Copy(&out, r)
  514. if err != nil {
  515. t.Error(err)
  516. }
  517. if w != int64(email.partsInfo.Parts[i-1].Size) {
  518. t.Error(i, "incorrect size, expecting", email.partsInfo.Parts[i-1].Size, "but read:", w)
  519. }
  520. out.Reset()
  521. }
  522. r, err = NewChunkedReader(store, email, 0)
  523. if err != nil {
  524. t.Error(err)
  525. }
  526. part := email.partsInfo.Parts[0]
  527. encoding := transfer.QuotedPrintable
  528. if strings.Contains(part.TransferEncoding, "base") {
  529. encoding = transfer.Base64
  530. }
  531. dr, err := transfer.NewDecoder(r, encoding, part.Charset)
  532. _ = dr
  533. if err != nil {
  534. t.Error(err)
  535. t.FailNow()
  536. }
  537. //var decoded bytes.Buffer
  538. //io.Copy(&decoded, dr)
  539. io.Copy(os.Stdout, dr)
  540. }
  541. }
  542. func initTestStream(transform bool) (*StoreMemory, *backends.StreamDecorator, *backends.StreamDecorator, backends.StreamProcessor) {
  543. // place the parse result in an envelope
  544. e := mail.NewEnvelope("127.0.0.1", 1, "127.0.0.1:25")
  545. to, _ := mail.NewAddress("[email protected]")
  546. e.RcptTo = append(e.RcptTo, *to)
  547. from, _ := mail.NewAddress("[email protected]")
  548. e.MailFrom = *from
  549. store := new(StoreMemory)
  550. chunkBuffer := NewChunkedBytesBufferMime()
  551. //chunkBuffer.setDatabase(store)
  552. // instantiate the chunk saver
  553. chunksaver := backends.Streamers["chunksaver"]()
  554. mimeanalyzer := backends.Streamers["mimeanalyzer"]()
  555. transformer := backends.Streamers["transformer"]()
  556. //debug := backends.Streamers["debug"]()
  557. // add the default processor as the underlying processor for chunksaver
  558. // and chain it with mimeanalyzer.
  559. // Call order: mimeanalyzer -> chunksaver -> default (terminator)
  560. // This will also set our Open, Close and Initialize functions
  561. // we also inject a Storage and a ChunkingBufferMime
  562. var stream backends.StreamProcessor
  563. if transform {
  564. stream = mimeanalyzer.Decorate(
  565. transformer.Decorate(
  566. //debug.Decorate(
  567. chunksaver.Decorate(
  568. backends.DefaultStreamProcessor{}, store, chunkBuffer)))
  569. } else {
  570. stream = mimeanalyzer.Decorate(
  571. //debug.Decorate(
  572. chunksaver.Decorate(
  573. backends.DefaultStreamProcessor{}, store, chunkBuffer)) //)
  574. }
  575. // configure the buffer cap
  576. bc := backends.BackendConfig{
  577. "stream_processors": {
  578. "chunksaver": {
  579. "chunksaver_chunk_size": 8000,
  580. "chunksaver_storage_engine": "memory",
  581. "chunksaver_compress_level": 0,
  582. },
  583. },
  584. }
  585. _ = backends.Svc.Initialize(bc)
  586. // give it the envelope with the parse results
  587. _ = chunksaver.Open(e)
  588. _ = mimeanalyzer.Open(e)
  589. if transform {
  590. _ = transformer.Open(e)
  591. }
  592. return store, chunksaver, mimeanalyzer, stream
  593. }