init.lua 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. if (not love.thread) or (not jit) then error("WEB peripherals requires love.thread and luajit") end
  2. local perpath = select(1,...) --The path to the web folder
  3. local bit = require("bit")
  4. local events = require("Engine.events")
  5. local json = require("Engine.JSON")
  6. local hasLuaSec = pcall(require,"ssl")
  7. if hasLuaSec then
  8. require("ssl"); require(perpath:gsub("/",".").."https")
  9. end
  10. local thread = love.thread.newThread(perpath.."webthread.lua")
  11. local to_channel = love.thread.newChannel()
  12. local from_channel = love.thread.newChannel()
  13. local to_counter = 0
  14. local from_counter = 0
  15. thread:start(to_channel, from_channel)
  16. local function clearFuncsFromTable(t)
  17. for k,v in pairs(t) do
  18. if type(v) == "function" then
  19. t[k] = nil
  20. elseif type(v) == "table" then
  21. clearFuncsFromTable(v)
  22. end
  23. end
  24. end
  25. return function(config) --A function that creates a new WEB peripheral.
  26. if not thread:isRunning() then error("Failed to load luajit-request: "..tostring(thread:getError())) end
  27. local timeout = config.timeout or 5
  28. local CPUKit = config.CPUKit
  29. if not CPUKit then error("WEB Peripheral can't work without the CPUKit passed") end
  30. local indirect = {} --List of functions that requires custom coroutine.resume
  31. local devkit = {}
  32. local WEB, yWEB = {}, {}
  33. function WEB.send(url,args)
  34. if type(url) ~= "string" then return error("URL must be a string, provided: "..type(url)) end
  35. local args = args or {}
  36. if type(args) ~= "table" then return error("Args Must be a table or nil, provided: "..type(args)) end
  37. clearFuncsFromTable(args) --Since JSON can't encode functions !
  38. args.timeout = timeout
  39. args = json:encode(args)
  40. to_channel:push({url,args})
  41. to_counter = to_counter + 1
  42. return to_counter --Return the request ID
  43. end
  44. function WEB.urlEncode(str)
  45. if type(str) ~= "string" then return error("STR must be a string, provided: "..type(str)) end
  46. str = str:gsub("\n", "\r\n")
  47. str = str:gsub("\r\r\n", "\r\n")
  48. str = str:gsub("([^A-Za-z0-9 %-%_%.])", function(c)
  49. local n = string.byte(c)
  50. if n < 128 then
  51. -- ASCII
  52. return string.format("%%%02X", n)
  53. else
  54. -- Non-ASCII (encode as UTF-8)
  55. return string.format("%%%02X", 192 + bit.band( bit.arshift(n,6), 31 )) ..
  56. string.format("%%%02X", 128 + bit.band( n, 63 ))
  57. end
  58. end)
  59. str = str:gsub(" ", "+")
  60. return str
  61. end
  62. local luasocket_modules = {
  63. "socket.http", "ltn12", "mime", "socket.smtp", "socket", "socket.url"
  64. }
  65. for k,v in pairs(luasocket_modules) do require(v) end
  66. for k,v in pairs(luasocket_modules) do luasocket_modules[v] = k end
  67. function WEB.luasocket(submodule)
  68. if type(submodule) ~= "string" then return error("Submodule should be a string, provided: "..submodule) end
  69. submodule = string.lower(submodule)
  70. if not luasocket_modules[submodule] then return error("Invalid submodule: "..submodule) end
  71. return require(submodule)
  72. end
  73. function WEB.hasLuaSec()
  74. return hasLuaSec and true or false
  75. end
  76. function WEB.luasec(submodule)
  77. if not hasLuaSec then return error("LuaSec is not supported at the current platform") end
  78. if type(submodule) ~= "string" then return error("Submodule should be a string, provided: "..submodule) end
  79. submodule = string.lower(submodule)
  80. if submodule ~= "ssl" and submodule ~= "https" then return error("Invalid submodule: "..submodule) end
  81. if submodule == "https" then
  82. return require(perpath:gsub("/",".").."https")
  83. end
  84. return require(submodule)
  85. end
  86. events:register("love:update",function(dt)
  87. local result = from_channel:pop()
  88. if result then
  89. from_counter = from_counter +1
  90. local data = json:decode(result)
  91. CPUKit.triggerEvent("webrequest",from_counter,unpack(data))
  92. end
  93. end)
  94. events:register("love:reboot",function()
  95. to_channel:clear()
  96. to_channel:push("shutdown")
  97. end)
  98. events:register("love:quit",function()
  99. to_channel:clear()
  100. to_channel:push("shutdown")
  101. thread:wait()
  102. end)
  103. return WEB, yWEB, devkit
  104. end