lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi all,

attachment is post data(to upload file), when I use below code to parse only success on plain text file, failed with any binary file.
My quest is  lpeg only support plain text? and if support binary even partly, how to update my lpeg code to parse attachment if support binary.

thank you for you option or help.

```lua
local lpeg = require'lpeg'

local P,R,S,V = lpeg.P,lpeg.R,lpeg.S,lpeg.V
local    C,     Cb,     Cf,    Cg,      Ct,     Cmt =
    lpeg.C,lpeg.Cb,lpeg.Cf,lpeg.Cg,lpeg.Ct,lpeg.Cmt
local alpha  = R('az')+R('AZ')

local line       = P"--"
local crlf       = P"\r"^-1 * P"\n"
local name_value = Cg(C(alpha^1) * '=' * P'"'^-1 * C( (1-P'"'-crlf)^0 ) * P'"'^-1) - crlf
local name_      = alpha^1 * (P'-'^0    * alpha)^1
local subtype    = alpha^1 * (S('/-')^0 * alpha)^1

local header     = Ct(C(name_) * ': ' * C(subtype) * Cf(Ct"" * (S(',;') * ' ' * name_value)^0,rawset) )

local headers    = Ct( header * (crlf*header)^0 )

local build = function(boundary)
  local _, _, bound = string.find(boundary,'boundary=(.+)')
  if (bound) then
    boundary = P(bound)
  else
    boundary = P(boundary)
  end

  local node        = Ct(line*boundary*crlf*headers*crlf*crlf*C( P(1)^0- crlf*line*boundary ))
  local nodes       = Ct(node * (crlf*node)^0 * crlf * line*boundary*line)
  return nodes
end

local basic_parse = function(multipart, boundary)
  local nodes = build(boundary)
  p(nodes)
  p(multipart)
  p(#multipart)
  return lpeg.match(nodes,multipart)
end


local echo = function(s) print(s) end

local parse
parse=function(body, boundary)
 -- local io = require'enhance.io'
 -- io.savedata('toparse.bin',body)
  local basic = basic_parse(body,boundary)
  if not basic then
    print(boundary)
    print(body)
    print(#body)
    assert(nil,'fail to parse')
  end
  local ret = {}
  for i=1,#basic do
    local part = basic[i]
    local headers,value = part[1],part[2]
    if(string.lower(headers[1][1])=='content-disposition'
      and headers[1][2]=='form-data') then
      --form-data
      if (headers[1][3].filename) then
          --handle fileupload
          local file = {filename=headers[1][3].filename}
          file[1] = value
          for j=2,#headers do
            file[headers[j][1]] = headers[j][2]
          end
          ret[headers[1][3].name] = file
      else
        if #headers==1 then
          --simple key-value pair
          ret[headers[1][3].name] = value
        else
          local t = {}
          ret[headers[1][3].name] = t
          if(string.lower(headers[2][1])=='content-type'
            and string.match(headers[2][2],'^multipart')) then
            --multipart sub
            ret[headers[1][3].name] = assert(parse(value,headers[2][3].boundary))
          else
            ret[headers[1][3].name] = value
          end
        end
      end
    else
    end
  end
  return ret
end
--]]

return parse
```

Attachment: toparse.bin
Description: Binary data