add netrc support for webengine. resolves #2785.

This commit is contained in:
Marc Jauvin 2018-01-18 18:06:47 -05:00
parent cb2cd615e0
commit a2ca59b822
4 changed files with 46 additions and 30 deletions

View File

@ -99,6 +99,7 @@ class TabData:
Only used for QtWebKit. Only used for QtWebKit.
pinned: Flag to pin the tab. pinned: Flag to pin the tab.
fullscreen: Whether the tab has a video shown fullscreen currently. fullscreen: Whether the tab has a video shown fullscreen currently.
netrc_used: flag to avoid endless loop when using netrc
""" """
keep_icon = attr.ib(False) keep_icon = attr.ib(False)
@ -107,6 +108,7 @@ class TabData:
override_target = attr.ib(None) override_target = attr.ib(None)
pinned = attr.ib(False) pinned = attr.ib(False)
fullscreen = attr.ib(False) fullscreen = attr.ib(False)
netrc_used = False
class AbstractAction: class AbstractAction:
@ -724,6 +726,7 @@ class AbstractTab(QWidget):
self._progress = 0 self._progress = 0
self._has_ssl_errors = False self._has_ssl_errors = False
self.data.viewing_source = False self.data.viewing_source = False
self.data.netrc_used = False
self._set_load_status(usertypes.LoadStatus.loading) self._set_load_status(usertypes.LoadStatus.loading)
self.load_started.emit() self.load_started.emit()
@ -764,7 +767,6 @@ class AbstractTab(QWidget):
self.load_finished.emit(ok) self.load_finished.emit(ok)
if not self.title(): if not self.title():
self.title_changed.emit(self.url().toDisplayString()) self.title_changed.emit(self.url().toDisplayString())
self.zoom.set_current() self.zoom.set_current()
@pyqtSlot() @pyqtSlot()

View File

@ -19,7 +19,9 @@
"""Various utilities shared between webpage/webview subclasses.""" """Various utilities shared between webpage/webview subclasses."""
import os
import html import html
import netrc
from qutebrowser.config import config from qutebrowser.config import config
from qutebrowser.utils import usertypes, message, log, objreg, jinja, utils from qutebrowser.utils import usertypes, message, log, objreg, jinja, utils
@ -260,3 +262,29 @@ def get_user_stylesheet():
css += '\nhtml > ::-webkit-scrollbar { width: 0px; height: 0px; }' css += '\nhtml > ::-webkit-scrollbar { width: 0px; height: 0px; }'
return css return css
def netrc_authentication(url, authenticator):
"""performs authorization using netrc."""
if 'HOME' in os.environ:
# We'll get an OSError by netrc if 'HOME' isn't available in
# os.environ. We don't want to log that, so we prevent it
# altogether.
user, password = None, None
try:
net = netrc.netrc(config.val.content.netrc_file)
authenticators = net.authenticators(url.host())
if authenticators is not None:
(user, _account, password) = authenticators
except FileNotFoundError:
log.misc.debug("No .netrc file found")
except OSError:
log.misc.exception("Unable to read the netrc file")
except netrc.NetrcParseError:
log.misc.exception("Error when parsing the netrc file")
if user is not None:
authenticator.setUser(user)
authenticator.setPassword(password)
return True
return False

View File

@ -19,6 +19,7 @@
"""Wrapper over a QWebEngineView.""" """Wrapper over a QWebEngineView."""
import os
import math import math
import functools import functools
import html as html_utils import html as html_utils
@ -739,11 +740,15 @@ class WebEngineTab(browsertab.AbstractTab):
@pyqtSlot(QUrl, 'QAuthenticator*') @pyqtSlot(QUrl, 'QAuthenticator*')
def _on_authentication_required(self, url, authenticator): def _on_authentication_required(self, url, authenticator):
# FIXME:qtwebengine support .netrc netrc = None
answer = shared.authentication_required( if not self.data.netrc_used and 'HOME' in os.environ:
url, authenticator, abort_on=[self.shutting_down, self.data.netrc_used = True
self.load_started]) netrc = shared.netrc_authentication(url, authenticator)
if answer is None: if not netrc:
abort_on = [self.shutting_down, self.load_started]
answer = shared.authentication_required(url, authenticator,
abort_on)
if not netrc and answer is None:
try: try:
# pylint: disable=no-member, useless-suppression # pylint: disable=no-member, useless-suppression
sip.assign(authenticator, QAuthenticator()) sip.assign(authenticator, QAuthenticator())

View File

@ -19,9 +19,7 @@
"""Our own QNetworkAccessManager.""" """Our own QNetworkAccessManager."""
import os
import collections import collections
import netrc
import html import html
import attr import attr
@ -270,28 +268,11 @@ class NetworkManager(QNetworkAccessManager):
@pyqtSlot('QNetworkReply*', 'QAuthenticator*') @pyqtSlot('QNetworkReply*', 'QAuthenticator*')
def on_authentication_required(self, reply, authenticator): def on_authentication_required(self, reply, authenticator):
"""Called when a website needs authentication.""" """Called when a website needs authentication."""
user, password = None, None netrc = False
if not hasattr(reply, "netrc_used") and 'HOME' in os.environ: if not hasattr(reply, "netrc_used"):
# We'll get an OSError by netrc if 'HOME' isn't available in setattr(reply, "netrc_used", True)
# os.environ. We don't want to log that, so we prevent it netrc = shared.netrc_authentication(reply.url(), authenticator)
# altogether. if not netrc:
reply.netrc_used = True
try:
net = netrc.netrc(config.val.content.netrc_file)
authenticators = net.authenticators(reply.url().host())
if authenticators is not None:
(user, _account, password) = authenticators
except FileNotFoundError:
log.misc.debug("No .netrc file found")
except OSError:
log.misc.exception("Unable to read the netrc file")
except netrc.NetrcParseError:
log.misc.exception("Error when parsing the netrc file")
if user is not None:
authenticator.setUser(user)
authenticator.setPassword(password)
else:
abort_on = self._get_abort_signals(reply) abort_on = self._get_abort_signals(reply)
shared.authentication_required(reply.url(), authenticator, shared.authentication_required(reply.url(), authenticator,
abort_on=abort_on) abort_on=abort_on)