/src/Chapter 15/cgi.lua

http://github.com/lilijreey/lua-note · Lua · 110 lines · 81 code · 12 blank · 17 comment · 15 complexity · 418861dc2f645dd095af6ccfae428fa0 MD5 · raw file

  1. local Cgi = {}
  2. -- Return a urlencoded copy of Str. For example,
  3. -- "Here & there + 97% of other places"
  4. -- is encoded as
  5. -- "Here%20%26%20there%20%2B%2097%25%20of%20other%20places"
  6. function Cgi.Encode(Str)
  7. return string.gsub(Str, '%W', function(Str)
  8. return string.format('%%%02X', string.byte(Str)) end )
  9. end
  10. -- Returns a urldecoded copy of Str. This function reverses the effects of
  11. -- Cgi.Encode.
  12. function Cgi.Decode(Str)
  13. Str = string.gsub(Str, '%+', ' ')
  14. Str = string.gsub(Str, '%%(%x%x)', function(Str)
  15. return string.char(tonumber(Str, 16)) end )
  16. return Str
  17. end
  18. -- Returns an escaped copy of Str in which the characters &<>" are escaped for
  19. -- display in HTML documents.
  20. function Cgi.Escape(Str)
  21. Str = string.gsub(Str or "", "%&", "&amp;")
  22. Str = string.gsub(Str, '%"', "&quot;")
  23. Str = string.gsub(Str, "%<", "&lt;")
  24. return string.gsub(Str, "%>", "&gt;")
  25. end
  26. -- This function returns an associative array with the parsed contents of the
  27. -- urlencoded string Str. Multiple values with the same name are placed into an
  28. -- indexed table with the name.
  29. local function LclParse(Str)
  30. local Decode, Tbl = Cgi.Decode, {}
  31. for KeyStr, ValStr in string.gmatch(Str .. '&', '(.-)%=(.-)%&') do
  32. local Key = Decode(KeyStr)
  33. local Val = Decode(ValStr)
  34. local Sub = Tbl[Key]
  35. local SubCat = type(Sub)
  36. -- If there are multiple values with the same name, place them in an
  37. -- indexed table.
  38. if SubCat == "string" then -- replace string with table
  39. Tbl[Key] = { Sub, Val }
  40. elseif SubCat == "table" then -- insert into existing table
  41. table.insert(Sub, Val)
  42. else -- add as string field
  43. Tbl[Key] = Val
  44. end
  45. end
  46. return Tbl
  47. end
  48. -- Returns an associative array with both the GET and POST contents which
  49. -- accompany an HTTP request. Multi-part form data, usually used with uploaded
  50. -- files, is not currently supported.
  51. function Cgi.Params()
  52. local PostLen, GetStr, PostStr, KeyList, Obj
  53. KeyList = {
  54. 'PATH_INFO',
  55. 'PATH_TRANSLATED',
  56. 'REMOTE_HOST',
  57. 'REMOTE_ADDR',
  58. 'GATEWAY_INTERFACE',
  59. 'SCRIPT_NAME',
  60. 'REQUEST_METHOD',
  61. 'HTTP_ACCEPT',
  62. 'HTTP_ACCEPT_CHARSET',
  63. 'HTTP_ACCEPT_ENCODING',
  64. 'HTTP_ACCEPT_LANGUAGE',
  65. 'HTTP_FROM',
  66. 'HTTP_HOST',
  67. 'HTTP_REFERER',
  68. 'HTTP_USER_AGENT',
  69. 'QUERY_STRING',
  70. 'SERVER_SOFTWARE',
  71. 'SERVER_NAME',
  72. 'SERVER_PROTOCOL',
  73. 'SERVER_PORT',
  74. 'CONTENT_TYPE',
  75. 'CONTENT_LENGTH',
  76. 'AUTH_TYPE' }
  77. Obj = {}
  78. for J, KeyStr in ipairs(KeyList) do
  79. Obj[KeyStr] = os.getenv(KeyStr)
  80. end
  81. if not Obj.SERVER_SOFTWARE then -- Command line invocation
  82. Obj.QUERY_STRING = arg[1]
  83. PostStr = arg[2]
  84. elseif "application/x-www-form-urlencoded" == Obj.CONTENT_TYPE then
  85. -- Web server invocation with posted urlencoded content
  86. PostLen = tonumber(Obj.CONTENT_LENGTH)
  87. if PostLen and PostLen > 0 then
  88. PostStr = io.read(PostLen)
  89. end
  90. end
  91. PostStr = PostStr or ""
  92. Obj.Post = LclParse(PostStr)
  93. Obj.POST_STRING = PostStr
  94. GetStr = Obj.QUERY_STRING or ""
  95. Obj.Get = LclParse(GetStr)
  96. return Obj
  97. end
  98. return Cgi