コード例 #1
0
ファイル: qtnetwork.py プロジェクト: thnguyn2/ECE_527_MP
class WebClient(BaseWebClient):
    """A webclient with a qtnetwork backend."""

    proxy_instance = None

    def __init__(self, *args, **kwargs):
        """Initialize this instance."""
        super(WebClient, self).__init__(*args, **kwargs)
        self.nam = QNetworkAccessManager(QCoreApplication.instance())
        self.nam.finished.connect(self._handle_finished)
        self.nam.authenticationRequired.connect(self._handle_authentication)
        self.nam.proxyAuthenticationRequired.connect(self.handle_proxy_auth)
        # Disabled until we make this a per-instance option
        #self.nam.sslErrors.connect(self._handle_ssl_errors)
        self.replies = {}
        self.proxy_retry = False
        self.setup_proxy()

    def setup_proxy(self):
        """Setup the proxy settings if needed."""
        # QtNetwork knows how to use the system settings on both Win and Mac
        if sys.platform.startswith("linux"):
            settings = gsettings.get_proxy_settings()
            enabled = len(settings) > 0
            if enabled and WebClient.proxy_instance is None:
                proxy = build_proxy(settings)
                QNetworkProxy.setApplicationProxy(proxy)
                WebClient.proxy_instance = proxy
            elif enabled and WebClient.proxy_instance:
                logger.info("Proxy already in use.")
            else:
                logger.info("Proxy is disabled.")
        else:
            if WebClient.proxy_instance is None:
                logger.info("Querying OS for proxy.")
                query = QNetworkProxyQuery(QUrl(PROXY_REQUEST))
                proxies = QNetworkProxyFactory.systemProxyForQuery(query)
                QNetworkProxy.setApplicationProxy(proxies[0])
                WebClient.proxy_instance = proxies[0]

    def handle_proxy_auth(self, proxy, authenticator):
        """Proxy authentication is required."""
        logger.info("auth_required %r, %r", self.proxy_username,
                                            proxy.hostName())
        if (self.proxy_username is not None and
                self.proxy_username != str(authenticator.user())):
            authenticator.setUser(self.proxy_username)
            WebClient.proxy_instance.setUser(self.proxy_username)
        if (self.proxy_password is not None and
                self.proxy_password != str(authenticator.password())):
            authenticator.setPassword(self.proxy_password)
            WebClient.proxy_instance.setPassword(self.proxy_password)

    def _perform_request(self, request, method, post_buffer):
        """Return a deferred that will be fired with a Response object."""
        d = defer.Deferred()
        if method == "GET":
            reply = self.nam.get(request)
        elif method == "HEAD":
            reply = self.nam.head(request)
        else:
            reply = self.nam.sendCustomRequest(request, method, post_buffer)
        self.replies[reply] = d
        return d

    @defer.inlineCallbacks
    def request(self, iri, method="GET", extra_headers=None,
                oauth_credentials=None, post_content=None):
        """Return a deferred that will be fired with a Response object."""
        uri = self.iri_to_uri(iri)
        request = QNetworkRequest(QUrl(uri))

        if extra_headers:
            headers = dict(extra_headers)
        else:
            headers = {}

        if oauth_credentials:
            timestamp = yield self.get_timestamp()
            oauth_headers = self.build_oauth_headers(method, uri,
                                                oauth_credentials, timestamp)
            headers.update(oauth_headers)

        for key, value in headers.iteritems():
            request.setRawHeader(key, value)

        post_buffer = QBuffer()
        post_buffer.setData(post_content)
        try:
            result = yield self._perform_request(request, method, post_buffer)
        except ProxyUnauthorizedError, e:
            app_proxy = QNetworkProxy.applicationProxy()
            proxy_host = app_proxy.hostName() if app_proxy else "proxy server"
            got_creds = yield self.request_proxy_auth_credentials(
                                            proxy_host, self.proxy_retry)
            if got_creds:
                self.proxy_retry = True
                result = yield self.request(iri, method, extra_headers,
                                            oauth_credentials, post_content)
            else:
                excp = WebClientError('Proxy creds needed.', e)
                defer.returnValue(excp)
        defer.returnValue(result)
コード例 #2
0
ファイル: qtnetwork.py プロジェクト: pombreda/dist-packages
class WebClient(BaseWebClient):
    """A webclient with a qtnetwork backend."""

    proxy_instance = None

    def __init__(self, *args, **kwargs):
        """Initialize this instance."""
        super(WebClient, self).__init__(*args, **kwargs)
        self.nam = QNetworkAccessManager(QCoreApplication.instance())
        self.nam.finished.connect(self._handle_finished)
        self.nam.authenticationRequired.connect(self._handle_authentication)
        self.nam.proxyAuthenticationRequired.connect(self.handle_proxy_auth)
        self.nam.sslErrors.connect(self._handle_ssl_errors)
        self.replies = {}
        self.proxy_retry = False
        self.setup_proxy()

        # Force Qt to load the system certificates
        QSslSocket.setDefaultCaCertificates(QSslSocket.systemCaCertificates())
        # Apply our local certificates as the SSL configuration to be used
        # for all QNetworkRequest calls.
        self.ssl_config = QSslConfiguration.defaultConfiguration()
        ca_certs = self.ssl_config.caCertificates()
        try:
            for path in glob.glob(
                    os.path.join(get_cert_dir(), "UbuntuOne*.pem")):
                with open(path) as f:
                    cert = QSslCertificate(f.read())
                    if cert.isValid():
                        ca_certs.append(cert)
                    else:
                        logger.error("invalid certificate: {}".format(path))
        except (IndexError, IOError) as err:
            raise WebClientError(
                "Unable to configure SSL certificates: {}".format(err))

        self.ssl_config.setCaCertificates(ca_certs)

    def _set_proxy(self, proxy):
        """Set the proxy to be used."""
        QNetworkProxy.setApplicationProxy(proxy)
        self.nam.setProxy(proxy)

    def setup_proxy(self):
        """Setup the proxy settings if needed."""
        # QtNetwork knows how to use the system settings on both Win and Mac
        if sys.platform.startswith("linux"):
            settings = gsettings.get_proxy_settings()
            enabled = len(settings) > 0
            if enabled and WebClient.proxy_instance is None:
                proxy = build_proxy(settings)
                self._set_proxy(proxy)
                WebClient.proxy_instance = proxy
            elif enabled and WebClient.proxy_instance:
                logger.info("Proxy already in use.")
            else:
                logger.info("Proxy is disabled.")
        else:
            if WebClient.proxy_instance is None:
                logger.info("Querying OS for proxy.")
                QNetworkProxyFactory.setUseSystemConfiguration(True)

    def handle_proxy_auth(self, proxy, authenticator):
        """Proxy authentication is required."""
        logger.info("auth_required %r, %r", self.proxy_username,
                    proxy.hostName())
        if (self.proxy_username is not None
                and self.proxy_username != str(authenticator.user())):
            authenticator.setUser(self.proxy_username)
            WebClient.proxy_instance.setUser(self.proxy_username)
        if (self.proxy_password is not None
                and self.proxy_password != str(authenticator.password())):
            authenticator.setPassword(self.proxy_password)
            WebClient.proxy_instance.setPassword(self.proxy_password)

    def _perform_request(self, request, method, post_buffer):
        """Return a deferred that will be fired with a Response object."""
        d = defer.Deferred()
        if method == "GET":
            reply = self.nam.get(request)
        elif method == "HEAD":
            reply = self.nam.head(request)
        else:
            reply = self.nam.sendCustomRequest(request, method, post_buffer)
        self.replies[reply] = d
        return d

    @defer.inlineCallbacks
    def request(self,
                iri,
                method="GET",
                extra_headers=None,
                oauth_credentials=None,
                post_content=None):
        """Return a deferred that will be fired with a Response object."""
        uri = self.iri_to_uri(iri)
        request = QNetworkRequest(QUrl(uri))
        request.setSslConfiguration(self.ssl_config)
        headers = yield self.build_request_headers(uri, method, extra_headers,
                                                   oauth_credentials)

        for key, value in headers.items():
            request.setRawHeader(key, value)

        post_buffer = QBuffer()
        post_buffer.setData(post_content)
        try:
            result = yield self._perform_request(request, method, post_buffer)
        except ProxyUnauthorizedError as e:
            app_proxy = QNetworkProxy.applicationProxy()
            proxy_host = app_proxy.hostName() if app_proxy else "proxy server"
            got_creds = yield self.request_proxy_auth_credentials(
                proxy_host, self.proxy_retry)
            if got_creds:
                self.proxy_retry = True
                result = yield self.request(iri, method, extra_headers,
                                            oauth_credentials, post_content)
            else:
                excp = WebClientError('Proxy creds needed.', e)
                defer.returnValue(excp)
        defer.returnValue(result)

    def _handle_authentication(self, reply, authenticator):
        """The reply needs authentication."""
        if authenticator.user() != self.username:
            authenticator.setUser(self.username)
        if authenticator.password() != self.password:
            authenticator.setPassword(self.password)

    def _handle_finished(self, reply):
        """The reply has finished processing."""
        assert reply in self.replies
        d = self.replies.pop(reply)
        error = reply.error()
        content = reply.readAll()
        if not error:
            headers = HeaderDict()
            for key, value in reply.rawHeaderPairs():
                headers[str(key)].append(str(value))
            response = Response(bytes(content), headers)
            d.callback(response)
        else:
            content = unicode(content)
            error_string = unicode(reply.errorString())
            logger.debug('_handle_finished error (%s,%s).', error,
                         error_string)
            if error == QNetworkReply.AuthenticationRequiredError:
                exception = UnauthorizedError(error_string, content)
            elif error == QNetworkReply.ProxyAuthenticationRequiredError:
                # we are going thru a proxy and we did not auth
                exception = ProxyUnauthorizedError(error_string, content)
            else:
                exception = WebClientError(error_string, content)
            d.errback(exception)

    def _get_certificate_details(self, cert):
        """Return an string with the details of the certificate."""
        detail_titles = {
            QSslCertificate.Organization: 'organization',
            QSslCertificate.CommonName: 'common_name',
            QSslCertificate.LocalityName: 'locality_name',
            QSslCertificate.OrganizationalUnitName: 'unit',
            QSslCertificate.CountryName: 'country_name',
            QSslCertificate.StateOrProvinceName: 'state_name'
        }
        details = {}
        for info, title in detail_titles.items():
            details[title] = str(cert.issuerInfo(info))
        return self.format_ssl_details(details)

    def _get_certificate_host(self, cert):
        """Return the host of the cert."""
        return str(cert.issuerInfo(QSslCertificate.CommonName))

    def _handle_ssl_errors(self, reply, errors):
        """Handle the case in which we got an ssl error."""
        msg = StringIO()
        msg.write('SSL errors found; url: %s\n' %
                  reply.request().url().toString())
        for error in errors:
            msg.write('========Error=============\n%s (%s)\n' %
                      (error.errorString(), error.error()))
            msg.write('--------Cert Details------\n%s\n' %
                      self._get_certificate_details(error.certificate()))
            msg.write('==========================\n')
        logger.error(msg.getvalue())

    def force_use_proxy(self, https_settings):
        """Setup this webclient to use the given proxy settings."""
        settings = {"https": https_settings}
        proxy = build_proxy(settings)
        self._set_proxy(proxy)
        WebClient.proxy_instance = proxy

    def shutdown(self):
        """Shut down all pending requests (if possible)."""
        self.nam.deleteLater()
コード例 #3
0
class WebClient(BaseWebClient):
    """A webclient with a qtnetwork backend."""

    proxy_instance = None

    def __init__(self, *args, **kwargs):
        """Initialize this instance."""
        super(WebClient, self).__init__(*args, **kwargs)
        self.nam = QNetworkAccessManager(QCoreApplication.instance())
        self.nam.finished.connect(self._handle_finished)
        self.nam.authenticationRequired.connect(self._handle_authentication)
        self.nam.proxyAuthenticationRequired.connect(self.handle_proxy_auth)
        self.nam.sslErrors.connect(self._handle_ssl_errors)
        self.replies = {}
        self.proxy_retry = False
        self.setup_proxy()

        # Force Qt to load the system certificates
        QSslSocket.setDefaultCaCertificates(QSslSocket.systemCaCertificates())
        # Apply our local certificates as the SSL configuration to be used
        # for all QNetworkRequest calls.
        self.ssl_config = QSslConfiguration.defaultConfiguration()
        ca_certs = self.ssl_config.caCertificates()
        try:
            for path in glob.glob(os.path.join(get_cert_dir(),
                                               "UbuntuOne*.pem")):
                with open(path) as f:
                    cert = QSslCertificate(f.read())
                    if cert.isValid():
                        ca_certs.append(cert)
                    else:
                        logger.error("invalid certificate: {}".format(path))
        except (IndexError, IOError) as err:
            raise WebClientError(
                    "Unable to configure SSL certificates: {}".format(err))

        self.ssl_config.setCaCertificates(ca_certs)

    def _set_proxy(self, proxy):
        """Set the proxy to be used."""
        QNetworkProxy.setApplicationProxy(proxy)
        self.nam.setProxy(proxy)

    def setup_proxy(self):
        """Setup the proxy settings if needed."""
        # QtNetwork knows how to use the system settings on both Win and Mac
        if sys.platform.startswith("linux"):
            settings = gsettings.get_proxy_settings()
            enabled = len(settings) > 0
            if enabled and WebClient.proxy_instance is None:
                proxy = build_proxy(settings)
                self._set_proxy(proxy)
                WebClient.proxy_instance = proxy
            elif enabled and WebClient.proxy_instance:
                logger.info("Proxy already in use.")
            else:
                logger.info("Proxy is disabled.")
        else:
            if WebClient.proxy_instance is None:
                logger.info("Querying OS for proxy.")
                QNetworkProxyFactory.setUseSystemConfiguration(True)

    def handle_proxy_auth(self, proxy, authenticator):
        """Proxy authentication is required."""
        logger.info("auth_required %r, %r", self.proxy_username,
                                            proxy.hostName())
        if (self.proxy_username is not None and
                self.proxy_username != str(authenticator.user())):
            authenticator.setUser(self.proxy_username)
            WebClient.proxy_instance.setUser(self.proxy_username)
        if (self.proxy_password is not None and
                self.proxy_password != str(authenticator.password())):
            authenticator.setPassword(self.proxy_password)
            WebClient.proxy_instance.setPassword(self.proxy_password)

    def _perform_request(self, request, method, post_buffer):
        """Return a deferred that will be fired with a Response object."""
        d = defer.Deferred()
        if method == "GET":
            reply = self.nam.get(request)
        elif method == "HEAD":
            reply = self.nam.head(request)
        else:
            reply = self.nam.sendCustomRequest(request, method, post_buffer)
        self.replies[reply] = d
        return d

    @defer.inlineCallbacks
    def request(self, iri, method="GET", extra_headers=None,
                oauth_credentials=None, post_content=None):
        """Return a deferred that will be fired with a Response object."""
        uri = self.iri_to_uri(iri)
        request = QNetworkRequest(QUrl(uri))
        request.setSslConfiguration(self.ssl_config)
        headers = yield self.build_request_headers(uri, method, extra_headers,
                                                   oauth_credentials)

        for key, value in headers.items():
            request.setRawHeader(key, value)

        post_buffer = QBuffer()
        post_buffer.setData(post_content)
        try:
            result = yield self._perform_request(request, method, post_buffer)
        except ProxyUnauthorizedError as e:
            app_proxy = QNetworkProxy.applicationProxy()
            proxy_host = app_proxy.hostName() if app_proxy else "proxy server"
            got_creds = yield self.request_proxy_auth_credentials(
                                            proxy_host, self.proxy_retry)
            if got_creds:
                self.proxy_retry = True
                result = yield self.request(iri, method, extra_headers,
                                            oauth_credentials, post_content)
            else:
                excp = WebClientError('Proxy creds needed.', e)
                defer.returnValue(excp)
        defer.returnValue(result)

    def _handle_authentication(self, reply, authenticator):
        """The reply needs authentication."""
        if authenticator.user() != self.username:
            authenticator.setUser(self.username)
        if authenticator.password() != self.password:
            authenticator.setPassword(self.password)

    def _handle_finished(self, reply):
        """The reply has finished processing."""
        assert reply in self.replies
        d = self.replies.pop(reply)
        error = reply.error()
        content = reply.readAll()
        if not error:
            headers = HeaderDict()
            for key, value in reply.rawHeaderPairs():
                headers[str(key)].append(str(value))
            response = Response(bytes(content), headers)
            d.callback(response)
        else:
            content = unicode(content)
            error_string = unicode(reply.errorString())
            logger.debug('_handle_finished error (%s,%s).', error,
                         error_string)
            if error == QNetworkReply.AuthenticationRequiredError:
                exception = UnauthorizedError(error_string, content)
            elif error == QNetworkReply.ProxyAuthenticationRequiredError:
                # we are going thru a proxy and we did not auth
                exception = ProxyUnauthorizedError(error_string, content)
            else:
                exception = WebClientError(error_string, content)
            d.errback(exception)

    def _get_certificate_details(self, cert):
        """Return an string with the details of the certificate."""
        detail_titles = {QSslCertificate.Organization: 'organization',
                         QSslCertificate.CommonName: 'common_name',
                         QSslCertificate.LocalityName: 'locality_name',
                         QSslCertificate.OrganizationalUnitName: 'unit',
                         QSslCertificate.CountryName: 'country_name',
                         QSslCertificate.StateOrProvinceName: 'state_name'}
        details = {}
        for info, title in detail_titles.items():
            details[title] = str(cert.issuerInfo(info))
        return self.format_ssl_details(details)

    def _get_certificate_host(self, cert):
        """Return the host of the cert."""
        return str(cert.issuerInfo(QSslCertificate.CommonName))

    def _handle_ssl_errors(self, reply, errors):
        """Handle the case in which we got an ssl error."""
        msg = StringIO()
        msg.write('SSL errors found; url: %s\n' %
                  reply.request().url().toString())
        for error in errors:
            msg.write('========Error=============\n%s (%s)\n' %
                     (error.errorString(), error.error()))
            msg.write('--------Cert Details------\n%s\n' %
                      self._get_certificate_details(error.certificate()))
            msg.write('==========================\n')
        logger.error(msg.getvalue())

    def force_use_proxy(self, https_settings):
        """Setup this webclient to use the given proxy settings."""
        settings = {"https": https_settings}
        proxy = build_proxy(settings)
        self._set_proxy(proxy)
        WebClient.proxy_instance = proxy

    def shutdown(self):
        """Shut down all pending requests (if possible)."""
        self.nam.deleteLater()