Beispiel #1
0
    def run(self):
        # setup progress handler
        self.byteUpdate = time.time()
        self.recvTotal = 0

        def recvEvent(bytes):
            self.recvTotal += bytes
            self.recv.emit()

        addHook("httpRecv", recvEvent)
        client = AnkiRequestsClient()
        try:
            resp = client.get(aqt.appShared + "download/%s?v=2.1" % self.code)
            if resp.status_code == 200:
                data = client.streamContent(resp)
            elif resp.status_code in (403, 404):
                self.error = _(
                    "Invalid code, or add-on not available for your version of Anki."
                )
                return
            else:
                self.error = _("Unexpected response code: %s" %
                               resp.status_code)
                return
        except Exception as e:
            self.error = _(
                "Please check your internet connection.") + "\n\n" + str(e)
            return
        finally:
            remHook("httpRecv", recvEvent)

        self.fname = re.match("attachment; filename=(.+)",
                              resp.headers['content-disposition']).group(1)
        self.data = data
Beispiel #2
0
    def run(self):
        # setup progress handler
        self.byteUpdate = time.time()
        self.recvTotal = 0

        def recvEvent(bytes):
            self.recvTotal += bytes
            self.recv.emit()

        addHook("httpRecv", recvEvent)
        client = AnkiRequestsClient()
        try:
            resp = client.get(aqt.appShared + "download/%d" % self.code)
            if resp.status_code == 200:
                data = client.streamContent(resp)
            elif resp.status_code in (403, 404):
                self.error = _("Invalid code")
                return
            else:
                self.error = _("Error downloading: %s" % resp.status_code)
                return
        except Exception as e:
            exc = traceback.format_exc()
            try:
                self.error = str(e[0])
            except:
                self.error = str(exc)
            return
        finally:
            remHook("httpRecv", recvEvent)

        self.fname = re.match("attachment; filename=(.+)",
                              resp.headers['content-disposition']).group(1)
        self.data = data
Beispiel #3
0
 def download(url):
     contents = None
     client = AnkiRequestsClient()
     client.timeout = URL_TIMEOUT
     resp = client.get(url)
     if resp.status_code == 200:
         contents = client.streamContent(resp)
     return (resp.status_code, contents)
Beispiel #4
0
 def _getRemoteDirectoryListing(self):
     client = AnkiRequestsClient()
     resp = client.get(self._api_url + "?format=JSON")
     if resp.status_code != 200:
         raise Exception("Unexpected response code: {}".format(
             resp.status_code))
     # Strip 5-byte prefix that's used for XSSI prevention:
     json_content = resp.text[5:]
     entries = json.loads(json_content)["entries"]
     return entries
Beispiel #5
0
    def net_headers(self, url, headers=None):
        """Returns the headers for a URL."""

        self._logger.debug("GET %s for headers", url)
        self._netops += 1
        
        client = AnkiRequestsClient()
        response = client.get(url, headers=headers)

        return response.headers
Beispiel #6
0
def getImageFromUrl(url):

    URL_TIMEOUT = 5
    if anki == "set":
        client = AnkiRequestsClient()
        client.timeout = URL_TIMEOUT
        resp = client.get(url)
        content = client.streamContent(resp)
    else:
        resp = requests.get(url, timeout=URL_TIMEOUT)
        content = resp.content

    return content
Beispiel #7
0
 def _retrieveURL(self, url):
     "Download file into media folder and return local filename or None."
     # urllib doesn't understand percent-escaped utf8, but requires things like
     # '#' to be escaped.
     url = urllib.parse.unquote(url)
     if url.lower().startswith("file://"):
         url = url.replace("%", "%25")
         url = url.replace("#", "%23")
         local = True
     else:
         local = False
     # fetch it into a temporary folder
     self.mw.progress.start(immediate=not local, parent=self.parentWindow)
     ct = None
     try:
         if local:
             req = urllib.request.Request(
                 url, None,
                 {"User-Agent": "Mozilla/5.0 (compatible; Anki)"})
             filecontents = urllib.request.urlopen(req).read()
         else:
             reqs = AnkiRequestsClient()
             reqs.timeout = 30
             r = reqs.get(url)
             if r.status_code != 200:
                 showWarning(
                     _("Unexpected response code: %s") % r.status_code)
                 return
             filecontents = r.content
             ct = r.headers.get("content-type")
     except urllib.error.URLError as e:
         showWarning(_("An error occurred while opening %s") % e)
         return
     except requests.exceptions.RequestException as e:
         showWarning(_("An error occurred while opening %s") % e)
         return
     finally:
         self.mw.progress.finish()
     # strip off any query string
     url = re.sub(r"\?.*?$", "", url)
     path = urllib.parse.unquote(url)
     return self.mw.col.media.writeData(path, filecontents, typeHint=ct)
Beispiel #8
0
    def checkForUpdates(self):
        client = AnkiRequestsClient()

        # get mod times
        self.mw.progress.start(immediate=True)
        try:
            # ..of enabled items downloaded from ankiweb
            addons = []
            for dir in self.managedAddons():
                meta = self.addonMeta(dir)
                if not meta.get("disabled"):
                    addons.append(dir)

            mods = []
            while addons:
                chunk = addons[:25]
                del addons[:25]
                mods.extend(self._getModTimes(client, chunk))
            return self._updatedIds(mods)
        finally:
            self.mw.progress.finish()
Beispiel #9
0
 def _importNetResource(self, url, protocal=''):
     try:
         reqs = AnkiRequestsClient()
         reqs.timeout = 30
         r = reqs.get(protocal + url)
         if r.status_code != 200:
             if protocal:  #retry with http instead of https
                 return self._importNetResource('http:' + url)
             aqt.utils.showWarning(
                 _("Unexpected response code: %s") % r.status_code)
             return
         return r
     except urllib.error.URLError as e:
         if protocal:  #retry with http instead of https
             return self._importNetResource('http:' + url)
         aqt.utils.showWarning(_("An error occurred while opening %s") % e)
         return
     except requests.exceptions.RequestException as e:
         aqt.utils.showWarning(
             _("An error occurred while requesting %s") % e)
         return
Beispiel #10
0
    def net_stream(self, targets, require=None, method='GET',
                   awesome_ua=False, add_padding=False,
                   custom_quoter=None, custom_headers=None,
                   allow_redirects=True):
        """
        Returns the raw payload string from the specified target(s).
        If multiple targets are specified, their resulting payloads are
        glued together.

        Each "target" is a bare URL string or a tuple containing an
        address and a dict for what to tack onto the query string.

        Finally, a require dict may be passed to enforce a Content-Type
        using key 'mime' and/or a minimum payload size using key 'size'.
        If using multiple targets, these requirements apply to each
        response.

        The underlying library here already understands how to search
        the environment for proxy settings (e.g. HTTP_PROXY), so we do
        not need to do anything extra for that.

        If add_padding is True, then some additional null padding will
        be added onto the stream returned. This is helpful for some web
        services that sometimes return MP3s that `mplayer` clips early.

        To prevent redirects one can set allow_redirects to False.
        """

        assert method in ['GET', 'POST'], "method must be GET or POST"
        from urllib.parse import quote

        targets = targets if isinstance(targets, list) else [targets]
        targets = [
            (target, None) if isinstance(target, str)
            else (
                target[0],
                '&'.join(
                    '='.join([
                        key,
                        (
                            custom_quoter[key] if (custom_quoter and
                                                   key in custom_quoter)
                            else quote
                        )(
                            str(val),
                            safe='',
                        ),
                    ])
                    for key, val in list(target[1].items())
                ),
            )
            for target in targets
        ]

        require = require or {}

        payloads = []

        client = AnkiRequestsClient()

        for number, (url, params) in enumerate(targets, 1):
            desc = "web request" if len(targets) == 1 \
                else "web request (%d of %d)" % (number, len(targets))

            self._logger.debug("%s %s%s%s for %s", method, url,
                               "?" if params else "", params or "", desc)

            headers = {'User-Agent': (self.ecosystem.agent
                                      if awesome_ua else DEFAULT_UA)}
            if custom_headers:
                headers.update(custom_headers)

            self._netops += 1

            if method == 'GET':
                request_url = ('?'.join([url, params]) if params else url)
                self._logger.debug('request made: ' + repr((method, request_url, headers)))
                response = client.get(request_url, headers)
            else:
                from io import BytesIO
                self._logger.debug('request made: ' + repr((method, url, headers, (params if params else ''))))
                # note that this method of AnkiRequestsClient must take IO streams, not strings
                response = client.post(url, BytesIO((params if params else '').encode()), headers)

            if not response:
                raise IOError("No response for %s" % desc)

            if response.status_code != 200:
                value_error = ValueError(
                    "Got %d status for %s" %
                    (response.status_code, desc)
                )
                try:
                    value_error.payload = response.content
                    response.close()
                except Exception:
                    pass
                raise value_error

            got_mime = response.headers['Content-Type']
            simplified_mime = self.parse_mime_type(got_mime)
            
            #self._logger.debug('response got: ' + str(response.content))

            if 'mime' in require and require['mime'] != simplified_mime:

                value_error = ValueError(
                    f"Request got {got_mime} Content-Type for {desc};"
                    f" wanted {require['mime']}"
                )
                value_error.got_mime = got_mime
                value_error.wanted_mime = require['mime']
                raise value_error

            if not allow_redirects and response.url != url:
                raise ValueError("Request has been redirected")

            payload = response.content
            response.close()

            if 'size' in require and len(payload) < require['size']:
                raise self.TinyDownloadError(
                    "Request got %d-byte stream for %s; wanted %d+ bytes" %
                    (len(payload), desc, require['size'])
                )

            payloads.append(payload)

        if add_padding:
            payloads.append(PADDING)

        return b''.join(payloads)