function urldecode(str) -- Decode special chars in URLs such as %20 str = string.gsub (str, "+", " ") str = string.gsub (str, "%%(%x%x)", function(h) return string.char(tonumber(h,16)) end) str = string.gsub (str, "\r\n", "\n") return str end function url_encode(str) str = string.gsub (str, "\n", "\r\n") str = string.gsub (str, "([^%w ])", function (c) return string.format ("%%%02X", string.byte(c)) end) str = string.gsub (str, " ", "+") return str end function parseURL(url) local ty = findpattern(url, '([a-zA-Z0-9-]*)://') ty = string.sub(ty, 0, string.len(ty) - 3) local dom = findpattern(url, '([a-zA-Z0-9-]*\.[a-zA-Z0-9-^/]*\.?[a-zA-Z0-9-]*/)', string.len(ty) + 4) dom = string.sub(dom, 0, string.len(dom) - 1) local pa = string.sub(url, string.len(ty) + string.len(dom) + 4) pos = -1 while pos ~= nil do oldpos = pos pos = string.find(pa, '/', pos + 1) end local fi = string.sub(pa, oldpos + 1) pa = string.sub(pa, 0, string.len(pa) - string.len(fi)) return ty, dom, pa, fi end function getContentLength(url) local urlType, urlDomain, urlPath, urlFile = parseURL(url) server = getIPFromDNS(urlDomain) -- get the IP for the server to connect to if IP=="-1" then gPrint("Error getting IP.\n") do return end end headersock = Socket.connect(server, 80) while not headersock:isConnected() do System.sleep(100) end bytesSent = headersock:send("GET "..urlPath..urlFile.." HTTP/1.0\r\n") -- using GET instead of HEAD to ensure we get the right headers bytesSent = headersock:send("User-Agent: pspRSS "..appVersion.."\r\n") -- just to be nice... bytesSent = headersock:send("HOST: "..urlDomain.."\r\n\r\n") local line, headers = " ", "" while headersock:isConnected() and string.find(line, "\r\n\r\n") == nil and not Controls.read():cross() do line = headersock:recv() headers = headers..line screen.waitVblankStart() end headersock:close() local redirect = string.find(headers, "HTTP.....302.*") if redirect ~= nil then urlStart = string.find(headers, " ", string.find(headers, "Location[:]")) + 1 urlEnd = string.find(headers, "\n", urlStart) - 1 newURL = string.sub(headers, urlStart, urlEnd) redir_log:write(url.." redirects to "..newURL..".\n") gPrint("Feed redirects to "..newURL..".\n") cL, hL = getContentLength(newURL) return cL, hL, newURL end local _, _, contentLength = string.find(headers, "[Cc][Oo][Nn][Tt][Ee][Nn][Tt][-][Ll][Ee][Nn][Gg][Tt][Hh][:][ ]*([0-9]*)") if contentLength == nil then Wlan.term() error("Invalid content length. Malformed headers?") end return contentLength, string.len(headers), url end function downloadFile(url, title, defaultFilename, isFeed) local urlType, urlDomain, urlPath, urlFile = parseURL(url) local contentLength, headerLength, url = getContentLength(url) local urlType, urlDomain, urlPath, urlFile = parseURL(url) if contentLength == nil then error("Invalid content length. Malformed headers? ("..url..")") end if isFeed then if title ~= "" then rssFilename = title..".xml" -- use title (for feeds) elseif title == "" then rssFilename = defaultFilename -- no title, use default file name (for enclosures) else rssFilename = urlFile end -- use file name else rssFilename = defaultFilename end --server = getIPFromDNSOld(urlDomain) -- get the IP for the server to connect to server = getIPFromDNS(urlDomain) -- get the IP for the server to connect to if IP=="-1" then gPrint("Error getting IP.\n") do return end end httpsock = Socket.connect(server, 80) -- connect to the server while not httpsock:isConnected() and not Controls.read():start() do System.sleep(100) end -- wait for the connection bytesSent = httpsock:send("GET "..urlPath..urlFile.." HTTP/1.0\r\n") -- HTTP 1.0 GET request bytesSent = httpsock:send("User-Agent: pspRSS "..appVersion.."\r\n") -- just to be nice... bytesSent = httpsock:send("host: "..urlDomain.."\r\n\r\n") -- HTTP 1.0 GET request if isFeed then fileToOpen = "feeds/"..fixFileName(rssFilename) -- get correct filename else fileToOpen = rssFilename end outfile = assert(io.open(fileToOpen, "w")) -- open output file filedata = "" while not Controls.read():square() do line = httpsock:recv() -- receive the next piece of the download filedata = filedata..line if string.len(filedata) >= headerLength then fileStart = string.find(filedata, "\r\n\r\n")+4 outfile:write(string.sub(filedata, fileStart)) break end screen.waitVblankStart() end size = fileStart while true do line = httpsock:recv() -- receive the next piece of the download outfile:write(line) size = size + string.len(line) if size >= tonumber(contentLength) and line == "" then break end screen.waitVblankStart() end size = outfile:seek("end") outfile:close() httpsock:close() if size ~= 0 then if size > 1048576 then gPrint("Saved ("..round(size/1048576, 2).." MB).\n") else gPrint("Saved ("..round(size/1024, 2).." KB).\n") end else gPrint("Download error.\n") --error("Download error.") end end