def fetch(self, code): resp = self._http_fetch(code) if resp.status == 200: return self._fetch_200(code) elif resp.status == 301: location = resp.getheader("Location") if not location: raise exceptions.CodeBlockedException( "No Location header after HTTP status 301") tiny = resp.getheader("X-tiny") if tiny and tiny[:3] == "aff": return self._preview(code) return location elif resp.status == 302: raise exceptions.CodeBlockedException() elif resp.status == 404: raise exceptions.NoRedirectException() elif resp.status == 500: # Some "errorhelp" URLs result in HTTP status 500, which goes away when trying a different server self._conn.close() raise exceptions.ServiceException("HTTP status 500") else: raise exceptions.ServiceException("Unknown HTTP status %i" % resp.status) return resp.status
def fetch(self, code): resp = self._http_fetch(code) if resp.status == 301: location = resp.getheader("Location") if not location: raise exceptions.ServiceException( "No Location header after HTTP status 301") if resp.reason == "Moved": # Normal bit.ly redirect return location elif resp.reason == "Moved Permanently": # Weird "bundles" redirect, forces connection close despite # sending Keep-Alive header self._conn.close() raise exceptions.CodeBlockedException() else: raise exceptions.ServiceException( "Unknown HTTP reason %s after HTTP status 301" % resp.reason) elif resp.status == 302: location = resp.getheader("Location") if not location: raise exceptions.ServiceException( "No Location header after HTTP status 302") return self._parse_warning_url(code, location) elif resp.status == 403: raise exceptions.BlockedException() elif resp.status == 404: raise exceptions.NoRedirectException() elif resp.status == 410: raise exceptions.CodeBlockedException() else: raise exceptions.ServiceException("Unknown HTTP status %i" % resp.status)
def _fetch_blocked(self, code): resp = self._http_fetch(code, "GET") data = resp.read() if resp.status != 200: raise exceptions.ServiceException( "HTTP status changed from 200 to %i on second request" % resp.status) if not data: raise exceptions.CodeBlockedException( "Empty response on status 200") if self.RATE_LIMIT_STRING in data: raise exceptions.BlockedException() position = data.find(self.BLOCKED_STRING_START) if position == -1: raise exceptions.ServiceException( "Unexpected response on status 200") data = data[position + len(self.BLOCKED_STRING_START):] position = data.find(self.BLOCKED_STRING_END) if position == -1: raise exceptions.ServiceException( "Unexpected response on status 200") url = data[:position].decode("utf-8") return HTMLParser.HTMLParser().unescape(url).encode("utf-8")
def fetch(self, code): if code == "500": raise exceptions.CodeBlockedException() url = super(Trimnew, self).fetch(code) if url == "http://tr.im/404": raise exceptions.NoRedirectException() return url
def fetch(self, code): location = super(Snipurl, self).fetch(code) try: if location.decode("ascii") == "/site/getprivate?snip=" + code: raise exceptions.CodeBlockedException("Private key required") except UnicodeDecodeError: pass return location
def _parse_blocked(self, code, data): match = re.search( "<p>For reference and to help those fighting spam the original destination of this URL is given below \(we strongly recommend you don't visit it since it may damage your PC\): -<br />(.*)</p><h2>is\.gd</h2><p>is\.gd is a free service used to shorten long URLs\.", data) if not match: raise exceptions.ServiceException( "Could not find target URL in 'Link Disabled' page") url = match.group(1).decode("utf-8") url = HTMLParser.HTMLParser().unescape(url).encode("utf-8") if url == "": raise exceptions.CodeBlockedException("Empty URL on preview") return url
def _parse_json(self, data): try: data = json.loads(data) except ValueError: raise exceptions.ServiceException("Could not decode response") if not "kind" in data or data["kind"] != "urlshortener#url": raise exceptions.ServiceException("No/bad type given") if not "status" in data: raise exceptions.ServiceException("No status given") if not "longUrl" in data: raise exceptions.CodeBlockedException("Status: %s" % data["status"]) return data["longUrl"]
def fetch(self, code): resp = self._http_fetch(code) if resp.status == 200: return self._fetch_blocked(code) elif resp.status == 301: location = resp.getheader("Location") if not location: raise exceptions.CodeBlockedException( "No Location header after HTTP status 301") return location elif resp.status == 404: raise exceptions.NoRedirectException() else: raise exceptions.ServiceException("Unknown HTTP status %i" % resp.status)
def fetch(self, code): resp = self._http_head(code) if resp.status in self.http_status_redirect: location = resp.getheader("Location") if not location: raise exceptions.ServiceException( "No Location header after HTTP status 301") return location elif resp.status in self.http_status_no_redirect: raise exceptions.NoRedirectException() elif resp.status in self.http_status_code_blocked: raise exceptions.CodeBlockedException() elif resp.status in self.http_status_blocked: raise exceptions.BlockedException() else: return self.unexpected_http_status(code, resp)
def unexpected_http_status(self, code, resp): if resp.status != 200: return super(Isgd, self).unexpected_http_status(code, resp) resp, data = self._http_get(code) if resp.status != 200: raise exceptions.ServiceException( "HTTP status changed from 200 to %i on second request" % resp.status) if not data: raise exceptions.CodeBlockedException( "Empty response on status 200") if "<div id=\"main\"><p>Rate limit exceeded - please wait 1 minute before accessing more shortened URLs</p></div>" in data: raise exceptions.BlockedException() if "<div id=\"disabled\"><h2>Link Disabled</h2>" in data: return self._parse_blocked(code, data) if "<p>The full original link is shown below. <b>Click the link</b> if you'd like to proceed to the destination shown:" in data: return self._parse_preview(code, data)