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) if str then 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, " ", "+") end 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("HEAD "..urlPath..urlFile.." HTTP/1.0\r\n") 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 Found.*") 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) gPrint("Feed redirects to "..newURL..".\n") cL, hL = getContentLength(newURL) return cL, hL 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) end function downloadFile(url, title, defaultFilename, fix) -- This is still extremely touchy for poor connections... local urlType, urlDomain, urlPath, urlFile = parseURL(url) local contentLength, headerLength = getContentLength(url) local totalLength = contentLength + headerLength if contentLength == nil then error("Invalid content length. Malformed headers??") end if fix 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 --gPrint(server..":80\n") 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 --gPrint("GET "..urlPath..urlFile.." HTTP/1.0\n") --gPrint("host: "..urlDomain.."\n") 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 filedata = "" while not Controls.read():start() do line = httpsock:recv() -- receive the next piece of the download filedata = filedata..line -- write the new piece if string.len(filedata) >= totalLength then break end screen.waitVblankStart() end httpsock:close() fileStart = headerLength + 4 filedata = string.sub(filedata, fileStart) --gPrint(fixFileName(rssFilename).."\n") if fix then outfile = assert(io.open("feeds/"..fixFileName(rssFilename),"w")) -- open output file else outfile = assert(io.open(rssFilename, "w")) end size = string.len(filedata) if size ~= 0 then outfile:write(filedata) 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 outfile:close() end