Tag Mapper: Do not allow the user to create rules with invalid regular expressions

This commit is contained in:
Kovid Goyal 2016-01-09 14:50:49 +05:30
parent 51043aab41
commit 98070ce97f
2 changed files with 15 additions and 4 deletions

View File

@ -10,6 +10,9 @@ from collections import deque
REGEX_FLAGS = regex.VERSION1 | regex.WORD | regex.FULLCASE | regex.IGNORECASE | regex.UNICODE REGEX_FLAGS = regex.VERSION1 | regex.WORD | regex.FULLCASE | regex.IGNORECASE | regex.UNICODE
def compile_pat(pat):
return regex.compile(pat, flags=REGEX_FLAGS)
def matcher(rule): def matcher(rule):
mt = rule['match_type'] mt = rule['match_type']
if mt == 'one_of': if mt == 'one_of':
@ -21,11 +24,11 @@ def matcher(rule):
return lambda x: x not in tags return lambda x: x not in tags
if mt == 'matches': if mt == 'matches':
pat = regex.compile(rule['query'], flags=REGEX_FLAGS) pat = compile_pat(rule['query'])
return lambda x: pat.match(x) is not None return lambda x: pat.match(x) is not None
if mt == 'not_matches': if mt == 'not_matches':
pat = regex.compile(rule['query'], flags=REGEX_FLAGS) pat = compile_pat(rule['query'])
return lambda x: pat.match(x) is None return lambda x: pat.match(x) is None
return lambda x: False return lambda x: False

View File

@ -14,7 +14,7 @@ from PyQt5.Qt import (
QStaticText, Qt, QStyle, QToolButton, QInputDialog, QMenu QStaticText, Qt, QStyle, QToolButton, QInputDialog, QMenu
) )
from calibre.ebooks.metadata.tag_mapper import map_tags from calibre.ebooks.metadata.tag_mapper import map_tags, compile_pat
from calibre.gui2 import error_dialog, elided_text, Application, question_dialog from calibre.gui2 import error_dialog, elided_text, Application, question_dialog
from calibre.gui2.widgets2 import Dialog from calibre.gui2.widgets2 import Dialog
from calibre.utils.config import JSONConfig from calibre.utils.config import JSONConfig
@ -60,6 +60,7 @@ class RuleEdit(QWidget):
h.addWidget(q) h.addWidget(q)
for action, text in self.MATCH_TYPE_MAP.iteritems(): for action, text in self.MATCH_TYPE_MAP.iteritems():
q.addItem(text, action) q.addItem(text, action)
q.currentIndexChanged.connect(self.update_state)
self.la2 = la = QLabel(':\xa0') self.la2 = la = QLabel(':\xa0')
h.addWidget(la) h.addWidget(la)
self.query = q = QLineEdit(self) self.query = q = QLineEdit(self)
@ -83,7 +84,7 @@ class RuleEdit(QWidget):
replace = self.action.currentData() == 'replace' replace = self.action.currentData() == 'replace'
self.la3.setVisible(replace), self.replace.setVisible(replace) self.la3.setVisible(replace), self.replace.setVisible(replace)
tt = _('A comma separated list of tags') tt = _('A comma separated list of tags')
if 'pattern' in self.match_type.currentData(): if 'matches' in self.match_type.currentData():
tt = _('A regular expression') tt = _('A regular expression')
self.query.setToolTip(tt) self.query.setToolTip(tt)
@ -114,6 +115,13 @@ class RuleEdit(QWidget):
error_dialog(self, _('Query required'), _( error_dialog(self, _('Query required'), _(
'You must provide a value for the tag to match'), show=True) 'You must provide a value for the tag to match'), show=True)
return False return False
if 'matches' in rule['match_type']:
try:
compile_pat(rule['query'])
except Exception:
error_dialog(self, _('Query invalid'), _(
'%s is not a valid regular expression') % rule['query'], show=True)
return False
return True return True
class RuleEditDialog(Dialog): class RuleEditDialog(Dialog):