Message has safe link opening

Links in message body (if in HTML mode) now open, but it asks for a
confirmation in a dialog box.

Fixes #27
This commit is contained in:
mailchuck 2015-12-15 01:24:10 +01:00 committed by Peter Surda
parent 751f9108d8
commit 6557681a6c
2 changed files with 23 additions and 6 deletions

View File

@ -2,16 +2,21 @@ from PyQt4 import QtCore, QtGui
from safehtmlparser import * from safehtmlparser import *
class MessageView(QtGui.QTextEdit): class MessageView(QtGui.QTextBrowser):
MODE_PLAIN = 0 MODE_PLAIN = 0
MODE_HTML = 1 MODE_HTML = 1
TEXT_PLAIN = "HTML detected, click here to display" TEXT_PLAIN = "HTML detected, click here to display"
TEXT_HTML = "Click here to disable HTML" TEXT_HTML = "Click here to disable HTML"
CONFIRM_TITLE = "Follow external link"
CONFIRM_TEXT = "The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you or download malicious data. Are you sure?"
def __init__(self, parent = 0): def __init__(self, parent = 0):
super(MessageView, self).__init__(parent) super(MessageView, self).__init__(parent)
self.mode = MessageView.MODE_PLAIN self.mode = MessageView.MODE_PLAIN
self.html = None self.html = None
self.setOpenExternalLinks(False)
self.setOpenLinks(False)
self.anchorClicked.connect(self.confirmURL)
def mousePressEvent(self, event): def mousePressEvent(self, event):
#text = textCursor.block().text() #text = textCursor.block().text()
@ -23,17 +28,25 @@ class MessageView(QtGui.QTextEdit):
else: else:
super(MessageView, self).mousePressEvent(event) super(MessageView, self).mousePressEvent(event)
def confirmURL(self, link):
reply = QtGui.QMessageBox.question(self,
QtGui.QApplication.translate(type(self).__name__, MessageView.CONFIRM_TITLE),
QtGui.QApplication.translate(type(self).__name__, MessageView.CONFIRM_TEXT).arg(str(link.toString())),
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QDesktopServices.openUrl(link)
def showPlain(self): def showPlain(self):
self.mode = MessageView.MODE_PLAIN self.mode = MessageView.MODE_PLAIN
out = self.html.raw out = self.html.raw
if self.html.has_html: if self.html.has_html:
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + QtGui.QApplication.translate("MessageView", MessageView.TEXT_PLAIN) + "</b></div><br/>" + out out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_PLAIN) + "</b></div><br/>" + out
self.setHtml(QtCore.QString(out)) self.setHtml(QtCore.QString(out))
def showHTML(self): def showHTML(self):
self.mode = MessageView.MODE_HTML self.mode = MessageView.MODE_HTML
out = self.html.sanitised out = self.html.sanitised
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + QtGui.QApplication.translate("MessageView", MessageView.TEXT_HTML) + "</b></div><br/>" + out out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + QtGui.QApplication.translate(type(self).__name__, MessageView.TEXT_HTML) + "</b></div><br/>" + out
self.setHtml(QtCore.QString(out)) self.setHtml(QtCore.QString(out))
def setContent(self, data): def setContent(self, data):

View File

@ -39,7 +39,9 @@ class SafeHTMLParser(HTMLParser):
for attr in attrs: for attr in attrs:
if tag == "img" and attr[0] == "src" and not self.allow_picture: if tag == "img" and attr[0] == "src" and not self.allow_picture:
attr[1] = "" attr[1] = ""
self.sanitised += " " + quote_plus(attr[0]) + "=\"" + attr[1] + "\"" self.sanitised += " " + quote_plus(attr[0])
if attr[1] is not None:
self.sanitised += "=\"" + attr[1] + "\""
if inspect.stack()[1][3] == "handle_startendtag": if inspect.stack()[1][3] == "handle_startendtag":
self.sanitised += "/" self.sanitised += "/"
self.sanitised += ">" self.sanitised += ">"
@ -53,7 +55,9 @@ class SafeHTMLParser(HTMLParser):
for attr in attrs: for attr in attrs:
if tag == "img" and attr[0] == "src" and not self.allow_picture: if tag == "img" and attr[0] == "src" and not self.allow_picture:
attr[1] = "" attr[1] = ""
self.raw += " " + attr[0] + "=&quot;" + attr[1] + "&quot;" self.raw += " " + attr[0]
if attr[1] is not None:
self.raw + "=&quot;" + attr[1] + "&quot;"
if inspect.stack()[1][3] == "handle_startendtag": if inspect.stack()[1][3] == "handle_startendtag":
self.raw += "/" self.raw += "/"
self.raw += "&gt;" self.raw += "&gt;"