internal.lua 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. local table = table
  2. local type = type
  3. local M = {}
  4. local LIMIT = 8192
  5. local function chunksize(readbytes, body)
  6. while true do
  7. local f,e = body:find("\r\n",1,true)
  8. if f then
  9. return tonumber(body:sub(1,f-1),16), body:sub(e+1)
  10. end
  11. if #body > 128 then
  12. -- pervent the attacker send very long stream without \r\n
  13. return
  14. end
  15. body = body .. readbytes()
  16. end
  17. end
  18. local function readcrln(readbytes, body)
  19. if #body >= 2 then
  20. if body:sub(1,2) ~= "\r\n" then
  21. return
  22. end
  23. return body:sub(3)
  24. else
  25. body = body .. readbytes(2-#body)
  26. if body ~= "\r\n" then
  27. return
  28. end
  29. return ""
  30. end
  31. end
  32. function M.recvheader(readbytes, lines, header)
  33. if #header >= 2 then
  34. if header:find "^\r\n" then
  35. return header:sub(3)
  36. end
  37. end
  38. local result
  39. local e = header:find("\r\n\r\n", 1, true)
  40. if e then
  41. result = header:sub(e+4)
  42. else
  43. while true do
  44. local bytes = readbytes()
  45. header = header .. bytes
  46. if #header > LIMIT then
  47. return
  48. end
  49. e = header:find("\r\n\r\n", -#bytes-3, true)
  50. if e then
  51. result = header:sub(e+4)
  52. break
  53. end
  54. if header:find "^\r\n" then
  55. return header:sub(3)
  56. end
  57. end
  58. end
  59. for v in header:gmatch("(.-)\r\n") do
  60. if v == "" then
  61. break
  62. end
  63. table.insert(lines, v)
  64. end
  65. return result
  66. end
  67. function M.parseheader(lines, from, header)
  68. local name, value
  69. for i=from,#lines do
  70. local line = lines[i]
  71. if line:byte(1) == 9 then -- tab, append last line
  72. if name == nil then
  73. return
  74. end
  75. header[name] = header[name] .. line:sub(2)
  76. else
  77. name, value = line:match "^(.-):%s*(.*)"
  78. if name == nil or value == nil then
  79. return
  80. end
  81. name = name:lower()
  82. if header[name] then
  83. local v = header[name]
  84. if type(v) == "table" then
  85. table.insert(v, value)
  86. else
  87. header[name] = { v , value }
  88. end
  89. else
  90. header[name] = value
  91. end
  92. end
  93. end
  94. return header
  95. end
  96. function M.recvchunkedbody(readbytes, bodylimit, header, body)
  97. local result = ""
  98. local size = 0
  99. while true do
  100. local sz
  101. sz , body = chunksize(readbytes, body)
  102. if not sz then
  103. return
  104. end
  105. if sz == 0 then
  106. break
  107. end
  108. size = size + sz
  109. if bodylimit and size > bodylimit then
  110. return
  111. end
  112. if #body >= sz then
  113. result = result .. body:sub(1,sz)
  114. body = body:sub(sz+1)
  115. else
  116. result = result .. body .. readbytes(sz - #body)
  117. body = ""
  118. end
  119. body = readcrln(readbytes, body)
  120. if not body then
  121. return
  122. end
  123. end
  124. local tmpline = {}
  125. body = M.recvheader(readbytes, tmpline, body)
  126. if not body then
  127. return
  128. end
  129. header = M.parseheader(tmpline,1,header)
  130. return result, header
  131. end
  132. return M