mimetest.lua 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. local socket = require("socket")
  2. local ltn12 = require("ltn12")
  3. local mime = require("mime")
  4. local unpack = unpack or table.unpack
  5. dofile("testsupport.lua")
  6. local qptest = "qptest.bin"
  7. local eqptest = "qptest.bin2"
  8. local dqptest = "qptest.bin3"
  9. local b64test = "b64test.bin"
  10. local eb64test = "b64test.bin2"
  11. local db64test = "b64test.bin3"
  12. -- from Machado de Assis, "A Mão e a Rosa"
  13. local mao = [[
  14. Cursavam estes dois moços a academia de S. Paulo, estando
  15. Luís Alves no quarto ano e Estêvão no terceiro.
  16. Conheceram-se na academia, e ficaram amigos íntimos, tanto
  17. quanto podiam sê-lo dois espíritos diferentes, ou talvez por
  18. isso mesmo que o eram. Estêvão, dotado de extrema
  19. sensibilidade, e não menor fraqueza de ânimo, afetuoso e
  20. bom, não daquela bondade varonil, que é apanágio de uma alma
  21. forte, mas dessa outra bondade mole e de cera, que vai à
  22. mercê de todas as circunstâncias, tinha, além de tudo isso,
  23. o infortúnio de trazer ainda sobre o nariz os óculos
  24. cor-de-rosa de suas virginais ilusões. Luís Alves via bem
  25. com os olhos da cara. Não era mau rapaz, mas tinha o seu
  26. grão de egoísmo, e se não era incapaz de afeições, sabia
  27. regê-las, moderá-las, e sobretudo guiá-las ao seu próprio
  28. interesse. Entre estes dois homens travara-se amizade
  29. íntima, nascida para um na simpatia, para outro no costume.
  30. Eram eles os naturais confidentes um do outro, com a
  31. diferença que Luís Alves dava menos do que recebia, e, ainda
  32. assim, nem tudo o que dava exprimia grande confiança.
  33. ]]
  34. local function random(handle, io_err)
  35. if handle then
  36. return function()
  37. if not handle then error("source is empty!", 2) end
  38. local len = math.random(0, 1024)
  39. local chunk = handle:read(len)
  40. if not chunk then
  41. handle:close()
  42. handle = nil
  43. end
  44. return chunk
  45. end
  46. else return ltn12.source.empty(io_err or "unable to open file") end
  47. end
  48. local function named(f)
  49. return f
  50. end
  51. local what = nil
  52. local function transform(input, output, filter)
  53. local source = random(io.open(input, "rb"))
  54. local sink = ltn12.sink.file(io.open(output, "wb"))
  55. if what then
  56. sink = ltn12.sink.chain(filter, sink)
  57. else
  58. source = ltn12.source.chain(source, filter)
  59. end
  60. --what = not what
  61. ltn12.pump.all(source, sink)
  62. end
  63. local function encode_qptest(mode)
  64. local encode = mime.encode("quoted-printable", mode)
  65. local split = mime.wrap("quoted-printable")
  66. local chain = ltn12.filter.chain(encode, split)
  67. transform(qptest, eqptest, chain)
  68. end
  69. local function compare_qptest()
  70. io.write("testing qp encoding and wrap: ")
  71. compare(qptest, dqptest)
  72. end
  73. local function decode_qptest()
  74. local decode = mime.decode("quoted-printable")
  75. transform(eqptest, dqptest, decode)
  76. end
  77. local function create_qptest()
  78. local f, err = io.open(qptest, "wb")
  79. if not f then fail(err) end
  80. -- try all characters
  81. for i = 0, 255 do
  82. f:write(string.char(i))
  83. end
  84. -- try all characters and different line sizes
  85. for i = 0, 255 do
  86. for j = 0, i do
  87. f:write(string.char(i))
  88. end
  89. f:write("\r\n")
  90. end
  91. -- test latin text
  92. f:write(mao)
  93. -- force soft line breaks and treatment of space/tab in end of line
  94. local tab
  95. f:write(string.gsub(mao, "(%s)", function(c)
  96. if tab then
  97. tab = nil
  98. return "\t"
  99. else
  100. tab = 1
  101. return " "
  102. end
  103. end))
  104. -- test crazy end of line conventions
  105. local eol = { "\r\n", "\r", "\n", "\n\r" }
  106. local which = 0
  107. f:write(string.gsub(mao, "(\n)", function(c)
  108. which = which + 1
  109. if which > 4 then which = 1 end
  110. return eol[which]
  111. end))
  112. for i = 1, 4 do
  113. for j = 1, 4 do
  114. f:write(eol[i])
  115. f:write(eol[j])
  116. end
  117. end
  118. -- try long spaced and tabbed lines
  119. f:write("\r\n")
  120. for i = 0, 255 do
  121. f:write(string.char(9))
  122. end
  123. f:write("\r\n")
  124. for i = 0, 255 do
  125. f:write(' ')
  126. end
  127. f:write("\r\n")
  128. for i = 0, 255 do
  129. f:write(string.char(9),' ')
  130. end
  131. f:write("\r\n")
  132. for i = 0, 255 do
  133. f:write(' ',string.char(32))
  134. end
  135. f:write("\r\n")
  136. f:close()
  137. end
  138. local function cleanup_qptest()
  139. os.remove(qptest)
  140. os.remove(eqptest)
  141. os.remove(dqptest)
  142. end
  143. -- create test file
  144. local function create_b64test()
  145. local f = assert(io.open(b64test, "wb"))
  146. local t = {}
  147. for j = 1, 100 do
  148. for i = 1, 100 do
  149. t[i] = math.random(0, 255)
  150. end
  151. f:write(string.char(unpack(t)))
  152. end
  153. f:close()
  154. end
  155. local function encode_b64test()
  156. local e1 = mime.encode("base64")
  157. local e2 = mime.encode("base64")
  158. local e3 = mime.encode("base64")
  159. local e4 = mime.encode("base64")
  160. local sp4 = mime.wrap()
  161. local sp3 = mime.wrap(59)
  162. local sp2 = mime.wrap("base64", 30)
  163. local sp1 = mime.wrap(27)
  164. local chain = ltn12.filter.chain(e1, sp1, e2, sp2, e3, sp3, e4, sp4)
  165. transform(b64test, eb64test, chain)
  166. end
  167. local function decode_b64test()
  168. local d1 = named(mime.decode("base64"), "d1")
  169. local d2 = named(mime.decode("base64"), "d2")
  170. local d3 = named(mime.decode("base64"), "d3")
  171. local d4 = named(mime.decode("base64"), "d4")
  172. local chain = named(ltn12.filter.chain(d1, d2, d3, d4), "chain")
  173. transform(eb64test, db64test, chain)
  174. end
  175. local function cleanup_b64test()
  176. os.remove(b64test)
  177. os.remove(eb64test)
  178. os.remove(db64test)
  179. end
  180. local function compare_b64test()
  181. io.write("testing b64 chained encode: ")
  182. compare(b64test, db64test)
  183. end
  184. local function identity_test()
  185. io.write("testing identity: ")
  186. local chain = named(ltn12.filter.chain(
  187. named(mime.encode("quoted-printable"), "1 eq"),
  188. named(mime.encode("base64"), "2 eb"),
  189. named(mime.decode("base64"), "3 db"),
  190. named(mime.decode("quoted-printable"), "4 dq")
  191. ), "chain")
  192. transform(b64test, eb64test, chain)
  193. compare(b64test, eb64test)
  194. os.remove(eb64test)
  195. end
  196. local function padcheck(original, encoded)
  197. local e = (mime.b64(original))
  198. local d = (mime.unb64(encoded))
  199. if e ~= encoded then fail("encoding failed") end
  200. if d ~= original then fail("decoding failed") end
  201. end
  202. local function chunkcheck(original, encoded)
  203. local len = string.len(original)
  204. for i = 0, len do
  205. local a = string.sub(original, 1, i)
  206. local b = string.sub(original, i+1)
  207. local e, r = mime.b64(a, b)
  208. local f = (mime.b64(r))
  209. if (e .. (f or "") ~= encoded) then fail(e .. (f or "")) end
  210. end
  211. end
  212. local function padding_b64test()
  213. io.write("testing b64 padding: ")
  214. padcheck("a", "YQ==")
  215. padcheck("ab", "YWI=")
  216. padcheck("abc", "YWJj")
  217. padcheck("abcd", "YWJjZA==")
  218. padcheck("abcde", "YWJjZGU=")
  219. padcheck("abcdef", "YWJjZGVm")
  220. padcheck("abcdefg", "YWJjZGVmZw==")
  221. padcheck("abcdefgh", "YWJjZGVmZ2g=")
  222. padcheck("abcdefghi", "YWJjZGVmZ2hp")
  223. padcheck("abcdefghij", "YWJjZGVmZ2hpag==")
  224. chunkcheck("abcdefgh", "YWJjZGVmZ2g=")
  225. chunkcheck("abcdefghi", "YWJjZGVmZ2hp")
  226. chunkcheck("abcdefghij", "YWJjZGVmZ2hpag==")
  227. print("ok")
  228. end
  229. local function test_b64lowlevel()
  230. io.write("testing b64 low-level: ")
  231. local a, b
  232. a, b = mime.b64("", "")
  233. assert(a == "" and b == "")
  234. a, b = mime.b64(nil, "blablabla")
  235. assert(a == nil and b == nil)
  236. a, b = mime.b64("", nil)
  237. assert(a == nil and b == nil)
  238. a, b = mime.unb64("", "")
  239. assert(a == "" and b == "")
  240. a, b = mime.unb64(nil, "blablabla")
  241. assert(a == nil and b == nil)
  242. a, b = mime.unb64("", nil)
  243. assert(a == nil and b == nil)
  244. local binary=string.char(0x00,0x44,0x1D,0x14,0x0F,0xF4,0xDA,0x11,0xA9,0x78,0x00,0x14,0x38,0x50,0x60,0xCE)
  245. local encoded = mime.b64(binary)
  246. local decoded=mime.unb64(encoded)
  247. assert(binary == decoded)
  248. print("ok")
  249. end
  250. local t = socket.gettime()
  251. create_b64test()
  252. identity_test()
  253. encode_b64test()
  254. decode_b64test()
  255. compare_b64test()
  256. cleanup_b64test()
  257. padding_b64test()
  258. test_b64lowlevel()
  259. create_qptest()
  260. encode_qptest()
  261. decode_qptest()
  262. compare_qptest()
  263. encode_qptest("binary")
  264. decode_qptest()
  265. compare_qptest()
  266. cleanup_qptest()
  267. print(string.format("done in %.2fs", socket.gettime() - t))