mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
201
lua/pac3/core/shared/http.lua
Normal file
201
lua/pac3/core/shared/http.lua
Normal file
@@ -0,0 +1,201 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local CL_LIMIT, CL_LIMIT_OVERRIDE, CL_NO_CLENGTH
|
||||
|
||||
if CLIENT then
|
||||
CL_LIMIT = CreateConVar("pac_webcontent_limit", "-1", {FCVAR_ARCHIVE}, "webcontent limit in kb, -1 = unlimited")
|
||||
CL_NO_CLENGTH = CreateConVar("pac_webcontent_allow_no_content_length", "0", {FCVAR_ARCHIVE}, "allow downloads with no content length")
|
||||
CL_LIMIT_OVERRIDE = CreateConVar("pac_webcontent_limit_force", "0", {FCVAR_ARCHIVE}, "Override serverside setting")
|
||||
end
|
||||
|
||||
local SV_LIMIT = CreateConVar("sv_pac_webcontent_limit", "-1", CLIENT and {FCVAR_REPLICATED} or {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "webcontent limit in kb, -1 = unlimited")
|
||||
local SV_NO_CLENGTH = CreateConVar("sv_pac_webcontent_allow_no_content_length", "-1", CLIENT and {FCVAR_REPLICATED} or {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "allow downloads with no content length")
|
||||
|
||||
function pac.FixGMODUrl(url)
|
||||
-- to avoid "invalid url" errors
|
||||
-- gmod does not allow urls containing "10.", "172.16.", "192.168.", "127." or "://localhost"
|
||||
-- we escape 10. and 127. can occur (mydomain.com/model10.zip) and assume the server supports
|
||||
-- the escaped request
|
||||
return url:Replace("10.", "%31%30%2e"):Replace("127.", "%31%32%37%2e")
|
||||
end
|
||||
|
||||
local function http(method, url, headers, cb, failcb)
|
||||
|
||||
url = pac.FixGMODUrl(url)
|
||||
|
||||
return HTTP({
|
||||
method = method,
|
||||
url = url,
|
||||
headers = headers,
|
||||
success = function(code, data, headers)
|
||||
if code < 400 then
|
||||
cb(data, #data, headers)
|
||||
else
|
||||
local header = {}
|
||||
for k,v in pairs(headers) do
|
||||
table.insert(header, tostring(k) .. ": " .. tostring(v))
|
||||
end
|
||||
|
||||
local err = "server returned code " .. code .. ":\n\n"
|
||||
err = err .. "url: "..url.."\n"
|
||||
err = err .. "================\n"
|
||||
|
||||
err = err .. "HEADER:\n"
|
||||
err = err .. table.concat(header, "\n") .. "\n"
|
||||
|
||||
err = err .. "================\n"
|
||||
|
||||
err = err .. "BODY:\n"
|
||||
err = err .. data .. "\n"
|
||||
|
||||
err = err .. "================\n"
|
||||
failcb(err, code >= 400, code)
|
||||
end
|
||||
end,
|
||||
failed = function(err)
|
||||
if failcb then
|
||||
failcb("_G.HTTP error: " .. err)
|
||||
else
|
||||
pac.Message("_G.HTTP error: " .. err)
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function pac.FixUrl(url)
|
||||
url = url:Trim()
|
||||
url = url:gsub("[\"'<>\n\\]+", "")
|
||||
|
||||
if url:find("dropbox", 1, true) then
|
||||
url = url:gsub([[^http%://dl%.dropboxusercontent%.com/]], [[https://dl.dropboxusercontent.com/]])
|
||||
url = url:gsub([[^https?://dl.dropbox.com/]], [[https://www.dropbox.com/]])
|
||||
url = url:gsub([[^https?://www.dropbox.com/s/(.+)%?dl%=[01]$]], [[https://dl.dropboxusercontent.com/s/%1]])
|
||||
url = url:gsub([[^https?://www.dropbox.com/s/(.+)$]], [[https://dl.dropboxusercontent.com/s/%1]])
|
||||
url = url:gsub([[^https?://www.dropbox.com/scl/(.+)$]], [[https://dl.dropboxusercontent.com/scl/%1]]) --Fix for new dropbox format.
|
||||
return url
|
||||
end
|
||||
|
||||
if url:find("drive.google.com", 1, true) and not url:find("export=download", 1, true) then
|
||||
local id =
|
||||
url:match("https://drive.google.com/file/d/(.-)/") or
|
||||
url:match("https://drive.google.com/file/d/(.-)$") or
|
||||
url:match("https://drive.google.com/open%?id=(.-)$")
|
||||
|
||||
if id then
|
||||
return "https://drive.google.com/uc?export=download&id=" .. id
|
||||
end
|
||||
return url
|
||||
end
|
||||
|
||||
if url:find("gitlab.com", 1, true) then
|
||||
return url:gsub("^(https?://.-/.-/.-/)blob", "%1raw")
|
||||
end
|
||||
|
||||
url = url:gsub([[^http%://onedrive%.live%.com/redir?]],[[https://onedrive.live.com/download?]])
|
||||
url = url:gsub("pastebin.com/([a-zA-Z0-9]*)$", "pastebin.com/raw.php?i=%1")
|
||||
url = url:gsub("github.com/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/blob/", "github.com/%1/%2/raw/")
|
||||
|
||||
return url
|
||||
end
|
||||
|
||||
function pac.getContentLength(url, cb, failcb)
|
||||
return http("HEAD", url, {["Accept-Encoding"] = "none"}, function(_, _, headers)
|
||||
local length
|
||||
|
||||
-- server have rights to send headers in any case
|
||||
for key, value in pairs(headers) do
|
||||
if string.lower(key) == "content-length" then
|
||||
length = tonumber(value)
|
||||
|
||||
if not length or math.floor(length) ~= length then
|
||||
return failcb(string.format("malformed server reply with header content-length (got %q, expected valid integer number)", value), true)
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if length then return cb(length) end
|
||||
|
||||
return pac.contentLengthFallback(url, cb, failcb)
|
||||
end, function(err, over400, code)
|
||||
if code == 405 then
|
||||
return pac.contentLengthFallback(url, cb, failcb)
|
||||
end
|
||||
|
||||
return failcb(err, over400)
|
||||
end )
|
||||
end
|
||||
|
||||
-- Performs a GET but requests 0 bytes
|
||||
-- We can then read the response headers to determine the content size.
|
||||
-- This allows Google Drive and other hosts to work with PAC even with content-length limits set
|
||||
-- (They typically block HEAD requests)
|
||||
function pac.contentLengthFallback(url, cb, failcb)
|
||||
local function fail()
|
||||
return failcb("unable to determine content length", true)
|
||||
end
|
||||
|
||||
return http("GET", url, {["Range"] = "bytes=0-0"}, function(data, data_length, headers)
|
||||
-- e.g. "bytes 0-0/11784402"
|
||||
local contentRange = headers["Content-Range"]
|
||||
if not contentRange then return fail() end
|
||||
|
||||
local spl = string.Split(contentRange, "/")
|
||||
local contentLength = spl[2]
|
||||
|
||||
if contentLength then return cb(tonumber(contentLength)) end
|
||||
|
||||
return fail()
|
||||
end )
|
||||
end
|
||||
|
||||
function pac.HTTPGet(url, cb, failcb)
|
||||
if not url or url:len() < 4 then
|
||||
failcb("url length is less than 4 (" .. tostring(url) .. ")", true)
|
||||
return
|
||||
end
|
||||
|
||||
url = pac.FixUrl(url)
|
||||
|
||||
local limit = SV_LIMIT:GetInt()
|
||||
|
||||
if CLIENT and (CL_LIMIT_OVERRIDE:GetBool() or limit == -1) then
|
||||
limit = CL_LIMIT:GetInt()
|
||||
end
|
||||
|
||||
if limit == -1 then
|
||||
return http("GET", url, nil, cb, failcb)
|
||||
end
|
||||
|
||||
return pac.getContentLength(url, function(length)
|
||||
if length then
|
||||
if length <= (limit * 1024) then
|
||||
http("GET", url, nil, cb, failcb)
|
||||
else
|
||||
failcb("download is too big (" .. string.NiceSize(length) .. ")", true)
|
||||
end
|
||||
else
|
||||
local allow_no_contentlength = SV_NO_CLENGTH:GetInt()
|
||||
|
||||
if CLIENT and (CL_LIMIT_OVERRIDE:GetBool() or allow_no_contentlength < 0) then
|
||||
allow_no_contentlength = CL_NO_CLENGTH:GetInt()
|
||||
end
|
||||
|
||||
if allow_no_contentlength > 0 then
|
||||
http("GET", url, nil, cb, failcb)
|
||||
else
|
||||
failcb("unknown file size when allow_no_contentlength is " .. allow_no_contentlength, true)
|
||||
end
|
||||
end
|
||||
end, failcb)
|
||||
end
|
||||
Reference in New Issue
Block a user