def dirbrowser_html(path): """Get the directory browser web page. Args: path: The directory path. Return: The HTML of the web page. """ title = "Browse directory: {}".format(path) if is_root(path): parent = None else: parent = parent_dir(path) try: all_files = os.listdir(path) except OSError as e: html = jinja.render('error.html', title="Error while reading directory", url='file:///{}'.format(path), error=str(e)) return html.encode('UTF-8', errors='xmlcharrefreplace') files = get_file_list(path, all_files, os.path.isfile) directories = get_file_list(path, all_files, os.path.isdir) html = jinja.render('dirbrowser.html', title=title, url=path, parent=parent, files=files, directories=directories) return html.encode('UTF-8', errors='xmlcharrefreplace')
def qute_history(url): """Handler for qute://history. Display and serve history.""" if url.path() == '/data': # Use start_time in query or current time. try: start_time = QUrlQuery(url).queryItemValue("start_time") start_time = float(start_time) if start_time else time.time() except ValueError as e: raise QuteSchemeError("Query parameter start_time is invalid", e) return 'text/html', json.dumps(history_data(start_time)) else: if ( config.get('content', 'allow-javascript') and (objects.backend == usertypes.Backend.QtWebEngine or qtutils.is_qtwebkit_ng()) ): return 'text/html', jinja.render( 'history.html', title='History', session_interval=config.get('ui', 'history-session-interval') ) else: # Get current date from query parameter, if not given choose today. curr_date = datetime.date.today() try: query_date = QUrlQuery(url).queryItemValue("date") if query_date: curr_date = datetime.datetime.strptime(query_date, "%Y-%m-%d").date() except ValueError: log.misc.debug("Invalid date passed to qute:history: " + query_date) one_day = datetime.timedelta(days=1) next_date = curr_date + one_day prev_date = curr_date - one_day # start_time is the last second of curr_date start_time = time.mktime(next_date.timetuple()) - 1 history = [ (i["url"], i["title"], datetime.datetime.fromtimestamp(i["time"]/1000), QUrl(i["url"]).host()) for i in history_data(start_time) if "next" not in i ] return 'text/html', jinja.render( 'history_nojs.html', title='History', history=history, curr_date=curr_date, next_date=next_date, prev_date=prev_date, today=datetime.date.today(), )
def qute_warning(url): """Handler for qute://warning.""" path = url.path() if path == '/old-qt': src = jinja.render('warning-old-qt.html', title='Old Qt warning', qt_version=qVersion()) elif path == '/webkit': src = jinja.render('warning-webkit.html', title='QtWebKit backend warning') else: raise NotFoundError("Invalid warning page {}".format(path)) return 'text/html', src
def qute_help(url): """Handler for qute:help.""" try: utils.read_file('html/doc/index.html') except OSError: html = jinja.render( 'error.html', title="Error while loading documentation", url=url.toDisplayString(), error="This most likely means the documentation was not generated " "properly. If you are running qutebrowser from the git " "repository, please run scripts/asciidoc2html.py. " "If you're running a released version this is a bug, please " "use :report to report it.", icon='', qutescheme=True) return 'text/html', html urlpath = url.path() if not urlpath or urlpath == '/': urlpath = 'index.html' else: urlpath = urlpath.lstrip('/') if not docutils.docs_up_to_date(urlpath): message.error("Your documentation is outdated! Please re-run " "scripts/asciidoc2html.py.") path = 'html/doc/{}'.format(urlpath) if urlpath.endswith('.png'): return 'image/png', utils.read_file(path, binary=True) else: data = utils.read_file(path) return 'text/html', data
def qute_settings(url): """Handler for qute://settings. View/change qute configuration.""" global csrf_token if url.path() == '/set': if url.password() != csrf_token: message.error("Invalid CSRF token for qute://settings!") raise RequestDeniedError("Invalid CSRF token!") return _qute_settings_set(url) # Requests to qute://settings/set should only be allowed from # qute://settings. As an additional security precaution, we generate a CSRF # token to use here. if secrets: csrf_token = secrets.token_urlsafe() else: # On Python < 3.6, from secrets.py token = base64.urlsafe_b64encode(os.urandom(32)) csrf_token = token.rstrip(b'=').decode('ascii') src = jinja.render('settings.html', title='settings', configdata=configdata, confget=config.instance.get_str, csrf_token=csrf_token) return 'text/html', src
def _on_proxy_authentication_required(self, url, authenticator, proxy_host): """Called when a proxy needs authentication.""" msg = "<b>{}</b> requires a username and password.".format( html_utils.escape(proxy_host)) answer = message.ask( title="Proxy authentication required", text=msg, mode=usertypes.PromptMode.user_pwd, abort_on=[self.shutting_down, self.load_started]) if answer is not None: authenticator.setUser(answer.user) authenticator.setPassword(answer.password) else: try: # pylint: disable=no-member, useless-suppression sip.assign(authenticator, QAuthenticator()) # pylint: enable=no-member, useless-suppression except AttributeError: url_string = url.toDisplayString() error_page = jinja.render( 'error.html', title="Error loading page: {}".format(url_string), url=url_string, error="Proxy authentication required", icon='') self.set_html(error_page)
def qute_help(win_id, request): """Handler for qute:help. Return HTML content as bytes.""" try: utils.read_file('html/doc/index.html') except OSError: html = jinja.render( 'error.html', title="Error while loading documentation", url=request.url().toDisplayString(), error="This most likely means the documentation was not generated " "properly. If you are running qutebrowser from the git " "repository, please run scripts/asciidoc2html.py. " "If you're running a released version this is a bug, please " "use :report to report it.", icon='') return html.encode('UTF-8', errors='xmlcharrefreplace') urlpath = request.url().path() if not urlpath or urlpath == '/': urlpath = 'index.html' else: urlpath = urlpath.lstrip('/') if not docutils.docs_up_to_date(urlpath): message.error(win_id, "Your documentation is outdated! Please re-run " "scripts/asciidoc2html.py.") path = 'html/doc/{}'.format(urlpath) if urlpath.endswith('.png'): return utils.read_file(path, binary=True) else: data = utils.read_file(path) return data.encode('UTF-8', errors='xmlcharrefreplace')
def test_data_url(): """Test data_url() which can be used from templates.""" data = jinja.render('test3.html') print(data) url = QUrl(data) assert url.isValid() assert data == 'data:text/plain;base64,Zm9v' # 'foo'
def generate_pdfjs_page(filename, url): """Return the html content of a page that displays a file with pdfjs. Returns a string. Args: filename: The filename of the PDF to open. url: The URL being opened. """ if not is_available(): pdfjs_dir = os.path.join(standarddir.data(), 'pdfjs') return jinja.render('no_pdfjs.html', url=url.toDisplayString(), title="PDF.js not found", pdfjs_dir=pdfjs_dir) html = get_pdfjs_res('web/viewer.html').decode('utf-8') script = _generate_pdfjs_script(filename) html = html.replace('</body>', '</body><script>{}</script>'.format(script)) # WORKAROUND for the fact that PDF.js tries to use the Fetch API even with # qute:// URLs. pdfjs_script = '<script src="../build/pdf.js"></script>' html = html.replace(pdfjs_script, '<script>window.Response = undefined;</script>\n' + pdfjs_script) return html
def _on_renderer_process_terminated(self, tab, status, code): """Show an error when a renderer process terminated.""" if status == browsertab.TerminationStatus.normal: return messages = { browsertab.TerminationStatus.abnormal: "Renderer process exited with status {}".format(code), browsertab.TerminationStatus.crashed: "Renderer process crashed", browsertab.TerminationStatus.killed: "Renderer process was killed", browsertab.TerminationStatus.unknown: "Renderer process did not start", } msg = messages[status] def show_error_page(html): tab.set_html(html) log.webview.error(msg) if qtutils.version_check('5.9', compiled=False): url_string = tab.url(requested=True).toDisplayString() error_page = jinja.render( 'error.html', title="Error loading {}".format(url_string), url=url_string, error=msg) QTimer.singleShot(100, lambda: show_error_page(error_page)) else: # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-58698 message.error(msg) self._remove_tab(tab, crashed=True) if self.count() == 0: self.tabopen(QUrl('about:blank'))
def certificateError(self, error): """Handle certificate errors coming from Qt.""" self.certificate_error.emit() url = error.url() error = certificateerror.CertificateErrorWrapper(error) log.webview.debug("Certificate error: {}".format(error)) url_string = url.toDisplayString() error_page = jinja.render( 'error.html', title="Error loading page: {}".format(url_string), url=url_string, error=str(error), icon='') if error.is_overridable(): ignore = shared.ignore_certificate_errors( url, [error], abort_on=[self.loadStarted, self.shutting_down]) else: log.webview.error("Non-overridable certificate error: " "{}".format(error)) ignore = False # We can't really know when to show an error page, as the error might # have happened when loading some resource. # However, self.url() is not available yet and self.requestedUrl() # might not match the URL we get from the error - so we just apply a # heuristic here. # See https://bugreports.qt.io/browse/QTBUG-56207 log.webview.debug("ignore {}, URL {}, requested {}".format( ignore, url, self.requestedUrl())) if not ignore and url.matches(self.requestedUrl(), QUrl.RemoveScheme): self.setHtml(error_page) return ignore
def qute_plainlog(_win_id, _request): """Handler for qute:plainlog. Return HTML content as bytes.""" if log.ram_handler is None: text = "Log output was disabled." else: text = log.ram_handler.dump_log() html = jinja.render('pre.html', title='log', content=text) return html.encode('UTF-8', errors='xmlcharrefreplace')
def test_not_found(caplog): """Test with a template which does not exist.""" with caplog.at_level(logging.ERROR): data = jinja.render('does_not_exist.html') assert "The does_not_exist.html template could not be found!" in data assert caplog.records[0].msg.startswith("The does_not_exist.html template" " could not be loaded from")
def wrong_backend_handler(self, url): """Show an error page about using the invalid backend.""" html = jinja.render('error.html', title="Error while opening qute://url", url=url.toDisplayString(), error='{} is not available with this ' 'backend'.format(url.toDisplayString())) return 'text/html', html
def qute_log(_win_id, _request): """Handler for qute:log. Return HTML content as bytes.""" if log.ram_handler is None: html_log = None else: html_log = log.ram_handler.dump_log(html=True) html = jinja.render('log.html', title='log', content=html_log) return html.encode('UTF-8', errors='xmlcharrefreplace')
def qute_backend_warning(_url): """Handler for qute://backend-warning.""" html = jinja.render('backend-warning.html', distribution=version.distribution(), Distribution=version.Distribution, version=pkg_resources.parse_version, title="Legacy backend warning") return 'text/html', html
def qute_back(url): """Handler for qute://back. Simple page to free ram / lazy load a site, goes back on focusing the tab. """ src = jinja.render( 'back.html', title='Suspended: ' + urllib.parse.unquote(url.fragment())) return 'text/html', src
def _show_error_page(self, url, error): """Show an error page in the tab.""" log.misc.debug("Showing error page for {}".format(error)) url_string = url.toDisplayString() error_page = jinja.render( 'error.html', title="Error loading page: {}".format(url_string), url=url_string, error=error) self.set_html(error_page)
def qute_settings(url): """Handler for qute://settings. View/change qute configuration.""" if url.path() == '/set': return _qute_settings_set(url) html = jinja.render('settings.html', title='settings', configdata=configdata, confget=config.instance.get_str) return 'text/html', html
def _show_source_fallback(self, source: str) -> None: """Show source with pygments unavailable.""" html = jinja.render( 'pre.html', title='Source', content=source, preamble="Note: The optional Pygments dependency wasn't found - " "showing unhighlighted source.", ) self._show_html_source(html)
def test_utf8(): """Test rendering with an UTF8 template. This was an attempt to get a failing test case for #127 but it seems the issue is elsewhere. https://github.com/The-Compiler/qutebrowser/issues/127 """ data = jinja.render('test.html', var='\u2603') assert data == "Hello \u2603"
def _show_pdfjs(self, reply): """Show the reply with pdfjs.""" try: page = pdfjs.generate_pdfjs_page(reply.url()) except pdfjs.PDFJSNotFound: page = jinja.render('no_pdfjs.html', url=reply.url().toDisplayString()) self.mainFrame().setContent(page.encode('utf-8'), 'text/html', reply.url()) reply.deleteLater()
def test_undefined_function(caplog): """Make sure we don't crash if an undefined function is called.""" with caplog.at_level(logging.ERROR): data = jinja.render('undef.html') assert 'There was an error while rendering undef.html' in data assert "'does_not_exist' is undefined" in data assert data.startswith('<!DOCTYPE html>') assert len(caplog.records) == 1 assert caplog.records[0].msg == "UndefinedError while rendering undef.html"
def qute_bookmarks(_win_id, _request): """Handler for qute:bookmarks. Display all quickmarks / bookmarks.""" bookmarks = sorted(objreg.get('bookmark-manager').marks.items(), key=lambda x: x[1]) # Sort by title quickmarks = sorted(objreg.get('quickmark-manager').marks.items(), key=lambda x: x[0]) # Sort by name html = jinja.render('bookmarks.html', title='Bookmarks', bookmarks=bookmarks, quickmarks=quickmarks) return html.encode('UTF-8', errors='xmlcharrefreplace')
def qute_bookmarks(_url): """Handler for qute://bookmarks. Display all quickmarks / bookmarks.""" bookmarks = sorted(objreg.get('bookmark-manager').marks.items(), key=lambda x: x[1]) # Sort by title quickmarks = sorted(objreg.get('quickmark-manager').marks.items(), key=lambda x: x[0]) # Sort by name src = jinja.render('bookmarks.html', title='Bookmarks', bookmarks=bookmarks, quickmarks=quickmarks) return 'text/html', src
def qute_bindings(_url): """Handler for qute://bindings. View keybindings.""" bindings = {} defaults = config.val.bindings.default modes = set(defaults.keys()).union(config.val.bindings.commands) modes.remove('normal') modes = ['normal'] + sorted(list(modes)) for mode in modes: bindings[mode] = config.key_instance.get_bindings_for(mode) src = jinja.render('bindings.html', title='Bindings', bindings=bindings) return 'text/html', src
def qute_bookmarks(_url): """Handler for qute:bookmarks. Display all quickmarks / bookmarks.""" bookmarks = sorted(objreg.get('bookmark-manager').marks.items(), key=lambda x: x[1]) # Sort by title quickmarks = sorted(objreg.get('quickmark-manager').marks.items(), key=lambda x: x[0]) # Sort by name html = jinja.render('bookmarks.html', title='Bookmarks', bookmarks=bookmarks, quickmarks=quickmarks) return 'text/html', html
def qute_start(_url: QUrl) -> _HandlerRet: """Handler for qute://start.""" bookmarks = sorted(objreg.get('bookmark-manager').marks.items(), key=lambda x: x[1]) # Sort by title quickmarks = sorted(objreg.get('quickmark-manager').marks.items(), key=lambda x: x[0]) # Sort by name searchurl = config.val.url.searchengines['DEFAULT'] page = jinja.render('startpage.html', title='Welcome to qutebrowser', bookmarks=bookmarks, search_url=searchurl, quickmarks=quickmarks) return 'text/html', page
def _on_authentication_required(self, url, authenticator): # FIXME:qtwebengine support .netrc answer = shared.authentication_required( url, authenticator, abort_on=[self.shutting_down, self.load_started]) if answer is None: # WORKAROUND for # https://www.riverbankcomputing.com/pipermail/pyqt/2016-December/038400.html url_string = url.toDisplayString() error_page = jinja.render( 'error.html', title="Error loading page: {}".format(url_string), url=url_string, error="Authentication required", icon='') self.set_html(error_page)
def dirbrowser_html(path): """Get the directory browser web page. Args: path: The directory path. Return: The HTML of the web page. """ title = "Browse directory: {}".format(path) if is_root(path): parent = None else: parent = parent_dir(path) try: all_files = os.listdir(path) except OSError as e: html = jinja.render('error.html', title="Error while reading directory", url='file:///{}'.format(path), error=str(e), icon='') return html.encode('UTF-8', errors='xmlcharrefreplace') files = get_file_list(path, all_files, os.path.isfile) directories = get_file_list(path, all_files, os.path.isdir) html = jinja.render('dirbrowser.html', title=title, url=path, icon='', parent=parent, files=files, directories=directories) return html.encode('UTF-8', errors='xmlcharrefreplace')
def _on_renderer_process_terminated(self, tab, status, code): """Show an error when a renderer process terminated.""" if status == browsertab.TerminationStatus.normal: return messages = { browsertab.TerminationStatus.abnormal: "Renderer process exited", browsertab.TerminationStatus.crashed: "Renderer process crashed", browsertab.TerminationStatus.killed: "Renderer process was killed", browsertab.TerminationStatus.unknown: "Renderer process did not start", } msg = messages[status] + f" (status {code})" # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-91715 versions = version.qtwebengine_versions() is_qtbug_91715 = (status == browsertab.TerminationStatus.unknown and code == 1002 and versions.webengine == utils.VersionNumber( 5, 15, 3)) def show_error_page(html): tab.set_html(html) log.webview.error(msg) if is_qtbug_91715: log.webview.error(msg) log.webview.error('') log.webview.error( 'NOTE: If you see this and "Network service crashed, restarting ' 'service.", please see:') log.webview.error( 'https://github.com/qutebrowser/qutebrowser/issues/6235') log.webview.error( 'You can set the "qt.workarounds.locale" setting in qutebrowser to ' 'work around the issue.') log.webview.error( 'A proper fix is likely available in QtWebEngine soon (which is why ' 'the workaround is disabled by default).') log.webview.error('') else: url_string = tab.url(requested=True).toDisplayString() error_page = jinja.render( 'error.html', title="Error loading {}".format(url_string), url=url_string, error=msg) QTimer.singleShot(100, lambda: show_error_page(error_page))
def qute_tabs(_url): """Handler for qute://tabs. Display information about all open tabs.""" tabs = collections.defaultdict(list) for win_id, window in objreg.window_registry.items(): if sip.isdeleted(window): continue tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) for tab in tabbed_browser.widgets(): if tab.url() not in [QUrl("qute://tabs/"), QUrl("qute://tabs")]: urlstr = tab.url().toDisplayString() tabs[str(win_id)].append((tab.title(), urlstr)) src = jinja.render('tabs.html', title='Tabs', tab_list_by_window=tabs) return 'text/html', src
def test_resource_url(): """Test resource_url() which can be used from templates.""" data = jinja.render('resource_url.html') print(data) url = QUrl(data) assert url.isValid() assert url.scheme() == 'file' path = url.path() if os.name == "nt": path = path.lstrip('/') path = path.replace('/', os.sep) with open(path, 'r', encoding='utf-8') as f: assert f.read().splitlines()[0] == "Hello World!"
def test_resource_url(): """Test resource_url() which can be used from templates.""" data = jinja.render('test2.html') print(data) url = QUrl(data) assert url.isValid() assert url.scheme() == 'file' path = url.path() if os.name == "nt": path = path.lstrip('/') path = path.replace('/', os.sep) with open(path, 'r', encoding='utf-8') as f: assert f.read().splitlines()[0] == "Hello World!"
def qute_plainlog(url): """Handler for qute://plainlog. An optional query parameter specifies the minimum log level to print. For example, qute://log?level=warning prints warnings and errors. Level can be one of: vdebug, debug, info, warning, error, critical. """ if log.ram_handler is None: text = "Log output was disabled." else: level = QUrlQuery(url).queryItemValue('level') if not level: level = 'vdebug' text = log.ram_handler.dump_log(html=False, level=level) src = jinja.render('pre.html', title='log', content=text) return 'text/html', src
def qute_plainlog(_win_id, request): """Handler for qute:plainlog. Return HTML content as bytes. An optional query parameter specifies the minimum log level to print. For example, qute://log?level=warning prints warnings and errors. Level can be one of: vdebug, debug, info, warning, error, critical. """ if log.ram_handler is None: text = "Log output was disabled." else: try: level = urllib.parse.parse_qs(request.url().query())['level'][0] except KeyError: level = 'vdebug' text = log.ram_handler.dump_log(html=False, level=level) html = jinja.render('pre.html', title='log', content=text) return html.encode('UTF-8', errors='xmlcharrefreplace')
def qute_plainlog(url): """Handler for qute:plainlog. An optional query parameter specifies the minimum log level to print. For example, qute://log?level=warning prints warnings and errors. Level can be one of: vdebug, debug, info, warning, error, critical. """ if log.ram_handler is None: text = "Log output was disabled." else: try: level = urllib.parse.parse_qs(url.query())['level'][0] except KeyError: level = 'vdebug' text = log.ram_handler.dump_log(html=False, level=level) html = jinja.render('pre.html', title='log', content=text) return 'text/html', html
def qute_log(url): """Handler for qute://log. An optional query parameter specifies the minimum log level to print. For example, qute://log?level=warning prints warnings and errors. Level can be one of: vdebug, debug, info, warning, error, critical. """ if log.ram_handler is None: html_log = None else: level = QUrlQuery(url).queryItemValue('level') if not level: level = 'vdebug' html_log = log.ram_handler.dump_log(html=True, level=level) html = jinja.render('log.html', title='log', content=html_log) return 'text/html', html
def qute_process(url: QUrl) -> _HandlerRet: """Handler for qute://process.""" path = url.path()[1:] try: pid = int(path) except ValueError: raise UrlInvalidError(f"Invalid PID {path}") try: proc = guiprocess.all_processes[pid] except KeyError: raise NotFoundError(f"No process {pid}") if proc is None: raise NotFoundError(f"Data for process {pid} got cleaned up.") src = jinja.render('process.html', title=f'Process {pid}', proc=proc) return 'text/html', src
def generate_pdfjs_page(filename, url): """Return the html content of a page that displays a file with pdfjs. Returns a string. Args: filename: The filename of the PDF to open. url: The URL being opened. """ if not is_available(): return jinja.render('no_pdfjs.html', url=url.toDisplayString(), title="PDF.js not found") viewer = get_pdfjs_res('web/viewer.html').decode('utf-8') script = _generate_pdfjs_script(filename) html_page = viewer.replace('</body>', '</body><script>{}</script>'.format(script)) return html_page
def _on_authentication_required(self, url, authenticator): # FIXME:qtwebengine support .netrc answer = shared.authentication_required( url, authenticator, abort_on=[self.shutting_down, self.load_started]) if answer is None: try: # pylint: disable=no-member, useless-suppression sip.assign(authenticator, QAuthenticator()) except AttributeError: # WORKAROUND for # https://www.riverbankcomputing.com/pipermail/pyqt/2016-December/038400.html url_string = url.toDisplayString() error_page = jinja.render( 'error.html', title="Error loading page: {}".format(url_string), url=url_string, error="Authentication required") self.set_html(error_page)
def qute_settings(url: QUrl) -> _HandlerRet: """Handler for qute://settings. View/change qute configuration.""" global csrf_token if url.path() == '/set': if url.password() != csrf_token: message.error("Invalid CSRF token for qute://settings!") raise RequestDeniedError("Invalid CSRF token!") return _qute_settings_set(url) # Requests to qute://settings/set should only be allowed from # qute://settings. As an additional security precaution, we generate a CSRF # token to use here. csrf_token = secrets.token_urlsafe() src = jinja.render('settings.html', title='settings', configdata=configdata, confget=config.instance.get_str, csrf_token=csrf_token) return 'text/html', src
def qute_history(url): """Handler for qute://history. Display and serve history.""" if url.path() == '/data': try: offset = QUrlQuery(url).queryItemValue("offset") offset = int(offset) if offset else None except ValueError: raise UrlInvalidError("Query parameter offset is invalid") # Use start_time in query or current time. try: start_time = QUrlQuery(url).queryItemValue("start_time") start_time = float(start_time) if start_time else time.time() except ValueError: raise UrlInvalidError("Query parameter start_time is invalid") return 'text/html', json.dumps(history_data(start_time, offset)) else: return 'text/html', jinja.render( 'history.html', title='History', gap_interval=config.val.history_gap_interval)
def qute_log(url: QUrl) -> _HandlerRet: """Handler for qute://log. There are three query parameters: - level: The minimum log level to print. For example, qute://log?level=warning prints warnings and errors. Level can be one of: vdebug, debug, info, warning, error, critical. - plain: If given (and not 'false'), plaintext is shown. - logfilter: A filter string like the --logfilter commandline argument accepts. """ query = QUrlQuery(url) plain = (query.hasQueryItem('plain') and query.queryItemValue('plain').lower() != 'false') if log.ram_handler is None: content = "Log output was disabled." if plain else None else: level = query.queryItemValue('level') if not level: level = 'vdebug' filter_str = query.queryItemValue('logfilter') try: logfilter = (log.LogFilter.parse(filter_str, only_debug=False) if filter_str else None) except log.InvalidLogFilterError as e: raise UrlInvalidError(e) content = log.ram_handler.dump_log(html=not plain, level=level, logfilter=logfilter) template = 'pre.html' if plain else 'log.html' src = jinja.render(template, title='log', content=content) return 'text/html', src
def qute_history(url): """Handler for qute://history. Display and serve history.""" if url.path() == '/data': try: offset = QUrlQuery(url).queryItemValue("offset") offset = int(offset) if offset else None except ValueError as e: raise QuteSchemeError("Query parameter offset is invalid", e) # Use start_time in query or current time. try: start_time = QUrlQuery(url).queryItemValue("start_time") start_time = float(start_time) if start_time else time.time() except ValueError as e: raise QuteSchemeError("Query parameter start_time is invalid", e) return 'text/html', json.dumps(history_data(start_time, offset)) else: if not config.val.content.javascript.enabled: return 'text/plain', b'JavaScript is required for qute://history' return 'text/html', jinja.render( 'history.html', title='History', gap_interval=config.val.history_gap_interval)
def _on_authentication_required(self, url, authenticator): netrc_success = False if not self.data.netrc_used: self.data.netrc_used = True netrc_success = shared.netrc_authentication(url, authenticator) if not netrc_success: abort_on = [self.shutting_down, self.load_started] answer = shared.authentication_required(url, authenticator, abort_on) if not netrc_success and answer is None: try: # pylint: disable=no-member, useless-suppression sip.assign(authenticator, QAuthenticator()) # pylint: enable=no-member, useless-suppression except AttributeError: # WORKAROUND for # https://www.riverbankcomputing.com/pipermail/pyqt/2016-December/038400.html url_string = url.toDisplayString() error_page = jinja.render( 'error.html', title="Error loading page: {}".format(url_string), url=url_string, error="Authentication required") self.set_html(error_page)
def _on_proxy_authentication_required(self, url, authenticator, proxy_host): """Called when a proxy needs authentication.""" msg = "<b>{}</b> requires a username and password.".format( html_utils.escape(proxy_host)) answer = message.ask( title="Proxy authentication required", text=msg, mode=usertypes.PromptMode.user_pwd, abort_on=[self.shutting_down, self.load_started]) if answer is not None: authenticator.setUser(answer.user) authenticator.setPassword(answer.password) else: try: # pylint: disable=no-member, useless-suppression sip.assign(authenticator, QAuthenticator()) except AttributeError: url_string = url.toDisplayString() error_page = jinja.render( 'error.html', title="Error loading page: {}".format(url_string), url=url_string, error="Proxy authentication required", icon='') self.set_html(error_page)
def generate_pdfjs_page(filename, url): """Return the html content of a page that displays a file with pdfjs. Returns a string. Args: filename: The filename of the PDF to open. url: The URL being opened. """ if not is_available(): return jinja.render('no_pdfjs.html', url=url.toDisplayString(), title="PDF.js not found") html = get_pdfjs_res('web/viewer.html').decode('utf-8') script = _generate_pdfjs_script(filename) html = html.replace('</body>', '</body><script>{}</script>'.format(script)) # WORKAROUND for the fact that PDF.js tries to use the Fetch API even with # qute:// URLs. pdfjs_script = '<script src="../build/pdf.js"></script>' html = html.replace( pdfjs_script, '<script>window.Response = undefined;</script>\n' + pdfjs_script) return html
def _on_renderer_process_terminated(self, tab, status, code): """Show an error when a renderer process terminated.""" if status == browsertab.TerminationStatus.normal: return messages = { browsertab.TerminationStatus.abnormal: "Renderer process exited", browsertab.TerminationStatus.crashed: "Renderer process crashed", browsertab.TerminationStatus.killed: "Renderer process was killed", browsertab.TerminationStatus.unknown: "Renderer process did not start", } msg = messages[status] + f" (status {code})" def show_error_page(html): tab.set_html(html) log.webview.error(msg) url_string = tab.url(requested=True).toDisplayString() error_page = jinja.render('error.html', title="Error loading {}".format(url_string), url=url_string, error=msg) QTimer.singleShot(100, lambda: show_error_page(error_page))
def _handle_errorpage(self, info, errpage): """Display an error page if needed. Loosely based on Helpviewer/HelpBrowserWV.py from eric5 (line 260 @ 5d937eb378dd) Args: info: The QWebPage.ErrorPageExtensionOption instance. errpage: The QWebPage.ErrorPageExtensionReturn instance, where the error page will get written to. Return: False if no error page should be displayed, True otherwise. """ ignored_errors = [ (QWebPage.QtNetwork, QNetworkReply.OperationCanceledError), # "Loading is handled by the media engine" (QWebPage.WebKit, 203), # "Frame load interrupted by policy change" (QWebPage.WebKit, 102), ] errpage.baseUrl = info.url urlstr = info.url.toDisplayString() if (info.domain, info.error) == (QWebPage.QtNetwork, QNetworkReply.ProtocolUnknownError): # For some reason, we get a segfault when we use # QDesktopServices::openUrl with info.url directly - however it # works when we construct a copy of it. url = QUrl(info.url) scheme = url.scheme() message.confirm_async( title="Open external application for {}-link?".format(scheme), text="URL: <b>{}</b>".format(html.escape( url.toDisplayString())), yes_action=functools.partial(QDesktopServices.openUrl, url)) return True elif (info.domain, info.error) in ignored_errors: log.webview.debug("Ignored error on {}: {} (error domain: {}, " "error code: {})".format(urlstr, info.errorString, info.domain, info.error)) return False else: error_str = info.errorString if error_str == networkmanager.HOSTBLOCK_ERROR_STRING: # We don't set error_occurred in this case. error_str = "Request blocked by host blocker." main_frame = info.frame.page().mainFrame() if info.frame != main_frame: # Content in an iframe -> Hide the frame so it doesn't use # any space. We can't hide the frame's documentElement # directly though. for elem in main_frame.documentElement().findAll('iframe'): if QUrl(elem.attribute('src')) == info.url: elem.setAttribute('style', 'display: none') return False else: self._ignore_load_started = True self.error_occurred = True log.webview.error("Error while loading {}: {}".format( urlstr, error_str)) log.webview.debug("Error domain: {}, error code: {}".format( info.domain, info.error)) title = "Error loading page: {}".format(urlstr) error_html = jinja.render('error.html', title=title, url=urlstr, error=error_str) errpage.content = error_html.encode('utf-8') errpage.encoding = 'utf-8' return True
def qute_spawn_output(_url): """Handler for qute://spawn-output.""" src = jinja.render('pre.html', title='spawn output', content=spawn_output) return 'text/html', src