mirror of
https://github.com/kepler155c/opus
synced 2025-10-18 17:27:39 +00:00
rttp initial version -- insecure
This commit is contained in:
57
sys/apis/fs/redfs.lua
Normal file
57
sys/apis/fs/redfs.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
--[[
|
||||
Mount a readonly file system from another computer across rednet. The
|
||||
target computer must be running OpusOS or redserver.
|
||||
|
||||
Syntax:
|
||||
rn://<id>/directory/subdir
|
||||
|
||||
Examples:
|
||||
rn://12/usr/etc
|
||||
rn://8/usr
|
||||
]]--
|
||||
|
||||
local rttp = require('rttp')
|
||||
|
||||
local fs = _G.fs
|
||||
|
||||
local redfs = { }
|
||||
|
||||
local function getListing(uri)
|
||||
local success, response = rttp.get(uri .. '?recursive=true')
|
||||
|
||||
if not success then
|
||||
error(response)
|
||||
end
|
||||
|
||||
if response.statusCode ~= 200 then
|
||||
error('Received response ' .. response.statusCode)
|
||||
end
|
||||
|
||||
local list = { }
|
||||
for _,v in pairs(response.data) do
|
||||
if not v.isDir then
|
||||
list[v.path] = {
|
||||
url = uri .. '/' .. v.path,
|
||||
size = v.size,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
function redfs.mount(dir, uri)
|
||||
if not uri then
|
||||
error('redfs syntax: uri')
|
||||
end
|
||||
|
||||
local list = getListing(uri)
|
||||
for path, entry in pairs(list) do
|
||||
if not fs.exists(fs.combine(dir, path)) then
|
||||
local node = fs.mount(fs.combine(dir, path), 'urlfs', entry.url)
|
||||
node.size = entry.size
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return redfs
|
@@ -1,3 +1,4 @@
|
||||
local rttp = require('rttp')
|
||||
local Util = require('util')
|
||||
|
||||
local fs = _G.fs
|
||||
@@ -50,7 +51,12 @@ function urlfs.open(node, fn, fl)
|
||||
|
||||
local c = node.cache
|
||||
if not c then
|
||||
c = Util.httpGet(node.url)
|
||||
if node.url:match('^([%w][%w%+%-%.]*)%:') == 'rn' then
|
||||
local s, response = rttp.get(node.url)
|
||||
c = s and response.statusCode == 200 and response.data
|
||||
else
|
||||
c = Util.httpGet(node.url)
|
||||
end
|
||||
if c then
|
||||
node.cache = c
|
||||
node.size = #c
|
||||
|
95
sys/apis/rttp.lua
Normal file
95
sys/apis/rttp.lua
Normal file
@@ -0,0 +1,95 @@
|
||||
local device = _G.device
|
||||
local os = _G.os
|
||||
|
||||
local rttp = { }
|
||||
local computerId = os.getComputerID()
|
||||
|
||||
local function parse(url, default)
|
||||
-- initialize default parameters
|
||||
local parsed = {}
|
||||
local authority
|
||||
|
||||
for i,v in pairs(default or parsed) do parsed[i] = v end
|
||||
-- remove whitespace
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
-- Decode unreserved characters
|
||||
url = string.gsub(url, "%%(%x%x)", function(hex)
|
||||
local char = string.char(tonumber(hex, 16))
|
||||
if string.match(char, "[a-zA-Z0-9._~-]") then
|
||||
return char
|
||||
end
|
||||
-- Hex encodings that are not unreserved must be preserved.
|
||||
return nil
|
||||
end)
|
||||
-- get fragment
|
||||
url = string.gsub(url, "#(.*)$", function(f)
|
||||
parsed.fragment = f
|
||||
return ""
|
||||
end)
|
||||
-- get scheme. Lower-case according to RFC 3986 section 3.1.
|
||||
url = string.gsub(url, "^(%w[%w.+-]*):",
|
||||
function(s) parsed.scheme = string.lower(s); return "" end)
|
||||
-- get authority
|
||||
url = string.gsub(url, "^//([^/]*)", function(n)
|
||||
authority = n
|
||||
return ""
|
||||
end)
|
||||
-- get query stringing
|
||||
url = string.gsub(url, "%?(.*)", function(q)
|
||||
parsed.query = q
|
||||
return ""
|
||||
end)
|
||||
-- get params
|
||||
url = string.gsub(url, "%;(.*)", function(p)
|
||||
parsed.params = p
|
||||
return ""
|
||||
end)
|
||||
|
||||
-- path is whatever was left
|
||||
parsed.path = url
|
||||
|
||||
-- Represents host:port, port = nil if not used.
|
||||
if authority then
|
||||
authority = string.gsub(authority, ":(%d+)$",
|
||||
function(p) parsed.port = tonumber(p); return "" end)
|
||||
if authority ~= "" then
|
||||
parsed.host = authority
|
||||
end
|
||||
end
|
||||
return parsed
|
||||
end
|
||||
|
||||
function rttp.get(url)
|
||||
local modem = device.wireless_modem or error('Modem not found')
|
||||
local parsed = parse(url, { port = 80 })
|
||||
|
||||
parsed.host = tonumber(parsed.host) or error('Invalid url')
|
||||
|
||||
for i = 16384, 32767 do
|
||||
if not modem.isOpen(i) then
|
||||
modem.open(i)
|
||||
local path = parsed.query and parsed.path .. '?' .. parsed.query or parsed.path
|
||||
|
||||
modem.transmit(parsed.port, parsed.host, {
|
||||
method = 'GET',
|
||||
replyAddress = computerId,
|
||||
replyPort = i,
|
||||
path = path,
|
||||
})
|
||||
local timerId = os.startTimer(3)
|
||||
repeat
|
||||
local event, id, dport, dhost, response = os.pullEvent()
|
||||
if event == 'modem_message' and
|
||||
dport == i and
|
||||
dhost == computerId and
|
||||
type(response) == 'table' then
|
||||
modem.close(i)
|
||||
return true, response
|
||||
end
|
||||
until event == 'timer' and id == timerId
|
||||
return false, 'timeout'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return rttp
|
Reference in New Issue
Block a user