properly handle invalid regular expressions supplied when testing filters, add some additional regexp checks (closes #427)

This commit is contained in:
Andrew Dolgov 2012-02-21 12:36:29 +04:00
parent 7b8ff151ed
commit 56fbb82cb0
4 changed files with 136 additions and 95 deletions

View File

@ -33,55 +33,65 @@ class Pref_Filters extends Protected_Handler {
else else
$feed = -4; $feed = -4;
$feed_title = getFeedTitle($this->link, $feed); $regexp_valid = preg_match('/' . $filter['reg_exp'] . '/',
$filter['reg_exp']) !== FALSE;
$qfh_ret = queryFeedHeadlines($this->link, $cat_filter ? $cat_id : $feed,
30, "", $cat_filter, false, false,
false, "date_entered DESC", 0, $_SESSION["uid"], $filter);
$result = $qfh_ret[0];
$articles = array();
$found = 0;
print __("Articles matching this filter:"); print __("Articles matching this filter:");
print "<div class=\"inactiveFeedHolder\">"; print "<div class=\"inactiveFeedHolder\">";
print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">"; print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
while ($line = db_fetch_assoc($result)) { if ($regexp_valid) {
$entry_timestamp = strtotime($line["updated"]); $feed_title = getFeedTitle($this->link, $feed);
$entry_tags = get_article_tags($this->link, $line["id"], $_SESSION["uid"]);
$content_preview = truncate_string( $qfh_ret = queryFeedHeadlines($this->link, $cat_filter ? $cat_id : $feed,
strip_tags($line["content_preview"]), 100, '...'); 30, "", $cat_filter, false, false,
false, "date_entered DESC", 0, $_SESSION["uid"], $filter);
if ($line["feed_title"]) $result = $qfh_ret[0];
$feed_title = $line["feed_title"];
print "<tr>"; $articles = array();
$found = 0;
print "<td width='5%' align='center'><input while ($line = db_fetch_assoc($result)) {
dojoType=\"dijit.form.CheckBox\" checked=\"1\"
disabled=\"1\" type=\"checkbox\"></td>";
print "<td>";
print $line["title"]; $entry_timestamp = strtotime($line["updated"]);
print "&nbsp;("; $entry_tags = get_article_tags($this->link, $line["id"], $_SESSION["uid"]);
print "<b>" . $feed_title . "</b>";
print "):&nbsp;";
print "<span class=\"insensitive\">" . $content_preview . "</span>";
print " " . mb_substr($line["date_entered"], 0, 16);
print "</td></tr>"; $content_preview = truncate_string(
strip_tags($line["content_preview"]), 100, '...');
$found++; if ($line["feed_title"])
} $feed_title = $line["feed_title"];
print "<tr>";
print "<td width='5%' align='center'><input
dojoType=\"dijit.form.CheckBox\" checked=\"1\"
disabled=\"1\" type=\"checkbox\"></td>";
print "<td>";
print $line["title"];
print "&nbsp;(";
print "<b>" . $feed_title . "</b>";
print "):&nbsp;";
print "<span class=\"insensitive\">" . $content_preview . "</span>";
print " " . mb_substr($line["date_entered"], 0, 16);
print "</td></tr>";
$found++;
}
if ($found == 0) {
print "<tr><td align='center'>" .
__("No articles matching this filter has been found.") . "</td></tr>";
}
} else {
print "<tr><td align='center' class='error'>" .
__("Invalid regular expression.") . "</td></tr>";
if ($found == 0) {
print "<tr><td align='center'>" .
__("No articles matching this filter has been found.") . "</td></tr>";
} }
print "</table>"; print "</table>";

View File

@ -4973,63 +4973,70 @@
function filter_to_sql($filter) { function filter_to_sql($filter) {
$query = ""; $query = "";
if (DB_TYPE == "pgsql") $regexp_valid = preg_match('/' . $filter['reg_exp'] . '/',
$reg_qpart = "~"; $filter['reg_exp']) !== FALSE;
else
$reg_qpart = "REGEXP";
switch ($filter["type"]) { if ($regexp_valid) {
case "title":
$query = "LOWER(ttrss_entries.title) $reg_qpart LOWER('".
$filter['reg_exp'] . "')";
break;
case "content":
$query = "LOWER(ttrss_entries.content) $reg_qpart LOWER('".
$filter['reg_exp'] . "')";
break;
case "both":
$query = "LOWER(ttrss_entries.title) $reg_qpart LOWER('".
$filter['reg_exp'] . "') OR LOWER(" .
"ttrss_entries.content) $reg_qpart LOWER('" . $filter['reg_exp'] . "')";
break;
case "tag":
$query = "LOWER(ttrss_user_entries.tag_cache) $reg_qpart LOWER('".
$filter['reg_exp'] . "')";
break;
case "link":
$query = "LOWER(ttrss_entries.link) $reg_qpart LOWER('".
$filter['reg_exp'] . "')";
break;
case "date":
if ($filter["filter_param"] == "before") if (DB_TYPE == "pgsql")
$cmp_qpart = "<"; $reg_qpart = "~";
else else
$cmp_qpart = ">="; $reg_qpart = "REGEXP";
$timestamp = date("Y-m-d H:N:s", strtotime($filter["reg_exp"])); switch ($filter["type"]) {
$query = "ttrss_entries.date_entered $cmp_qpart '$timestamp'"; case "title":
break; $query = "LOWER(ttrss_entries.title) $reg_qpart LOWER('".
case "author": $filter['reg_exp'] . "')";
$query = "LOWER(ttrss_entries.author) $reg_qpart LOWER('". break;
$filter['reg_exp'] . "')"; case "content":
break; $query = "LOWER(ttrss_entries.content) $reg_qpart LOWER('".
} $filter['reg_exp'] . "')";
break;
case "both":
$query = "LOWER(ttrss_entries.title) $reg_qpart LOWER('".
$filter['reg_exp'] . "') OR LOWER(" .
"ttrss_entries.content) $reg_qpart LOWER('" . $filter['reg_exp'] . "')";
break;
case "tag":
$query = "LOWER(ttrss_user_entries.tag_cache) $reg_qpart LOWER('".
$filter['reg_exp'] . "')";
break;
case "link":
$query = "LOWER(ttrss_entries.link) $reg_qpart LOWER('".
$filter['reg_exp'] . "')";
break;
case "date":
if ($filter["inverse"]) if ($filter["filter_param"] == "before")
$query = "NOT ($query)"; $cmp_qpart = "<";
else
$cmp_qpart = ">=";
if ($query) { $timestamp = date("Y-m-d H:N:s", strtotime($filter["reg_exp"]));
if (DB_TYPE == "pgsql") { $query = "ttrss_entries.date_entered $cmp_qpart '$timestamp'";
$query = " ($query) AND ttrss_entries.date_entered > NOW() - INTERVAL '14 days'"; break;
} else { case "author":
$query = " ($query) AND ttrss_entries.date_entered > DATE_SUB(NOW(), INTERVAL 14 DAY)"; $query = "LOWER(ttrss_entries.author) $reg_qpart LOWER('".
$filter['reg_exp'] . "')";
break;
} }
$query .= " AND ";
if ($filter["inverse"])
$query = "NOT ($query)";
if ($query) {
if (DB_TYPE == "pgsql") {
$query = " ($query) AND ttrss_entries.date_entered > NOW() - INTERVAL '14 days'";
} else {
$query = " ($query) AND ttrss_entries.date_entered > DATE_SUB(NOW(), INTERVAL 14 DAY)";
}
$query .= " AND ";
}
return $query;
} else {
return false;
} }
return $query;
} }
// Status codes: // Status codes:

View File

@ -982,19 +982,39 @@ function quickAddFilter() {
test: function() { test: function() {
if (this.validate()) { if (this.validate()) {
if (dijit.byId("filterTestDlg")) var query = "?op=rpc&method=verifyRegexp&reg_exp=" +
dijit.byId("filterTestDlg").destroyRecursive(); param_escape(dialog.attr('value').reg_exp);
tdialog = new dijit.Dialog({ notify_progress("Verifying regular expression...");
id: "filterTestDlg",
title: __("Filter Test Results"),
style: "width: 600px",
href: "backend.php?savemode=test&" +
dojo.objectToQuery(dialog.attr('value')),
});
tdialog.show(); new Ajax.Request("backend.php", {
parameters: query,
onComplete: function(transport) {
var reply = JSON.parse(transport.responseText);
if (reply) {
notify('');
if (!reply['status']) {
alert("Invalid regular expression.");
return;
} else {
if (dijit.byId("filterTestDlg"))
dijit.byId("filterTestDlg").destroyRecursive();
tdialog = new dijit.Dialog({
id: "filterTestDlg",
title: __("Filter Test Results"),
style: "width: 600px",
href: "backend.php?savemode=test&" +
dojo.objectToQuery(dialog.attr('value')),
});
tdialog.show();
}
}
}});
} }
}, },
execute: function() { execute: function() {
@ -1014,7 +1034,7 @@ function quickAddFilter() {
notify(''); notify('');
if (!reply['status']) { if (!reply['status']) {
alert("Match regular expression seems to be invalid."); alert("Invalid regular expression.");
return; return;
} else { } else {
notify_progress("Saving data...", true); notify_progress("Saving data...", true);

View File

@ -1407,3 +1407,7 @@ a.bookmarklet {
padding : 1em; padding : 1em;
color : gray; color : gray;
} }
td.error {
color : red;
}