commit 51f11a7a41f644e562486847ab1541b14bb979fd
Author: Yoann Vandoorselaere <[email protected]>
Date: Mon Jun 1 15:46:45 2009 +0200
Inline filters improvements: reset switch, and distinction between applied/saved filters.
Implement a reset button in each inline filter column, that allow to switch
between different version of the filter: last saved filters, default filters,
or current filters.
Make the "[filtered]" information black when the filter has been saved as part
of the view, this make a difference between saved, and only applied filters.
========================================
htdocs/css/style.css | 10 +-
prewikka/templates/AlertListing.tmpl | 467 ++++++++++++++++++++++++++++----
prewikka/templates/MessageListing.tmpl | 2 +-
prewikka/view.py | 49 +++-
prewikka/views/alertlisting.py | 204 +++++++++++---
5 files changed, 623 insertions(+), 109 deletions(-)
========================================
diff --git a/htdocs/css/style.css b/htdocs/css/style.css
index 6e2c555..b1c4dd4 100755
--- a/htdocs/css/style.css
+++ b/htdocs/css/style.css
@@ -820,6 +820,7 @@ p {
padding: 5px;
margin: 0px;
_width: 150px;
+ text-align: left;
}
@@ -828,15 +829,10 @@ p {
* Filter popup
*/
-.filter_popup a {
+.filter_popup_link {
float: left;
}
-.filter_popup span {
- float: right;
- display: inline;
-}
-
.filter_popup div {
display: none;
margin-top: 15px;
@@ -989,6 +985,8 @@ p {
.filter_enabled_marker {
font-weight: bold;
color: red;
+ display: inline;
+ float: right;
}
diff --git a/prewikka/templates/AlertListing.tmpl b/prewikka/templates/AlertListing.tmpl
index 27eb894..9ad1de1 100644
--- a/prewikka/templates/AlertListing.tmpl
+++ b/prewikka/templates/AlertListing.tmpl
@@ -25,6 +25,84 @@ title_array["~"] = "$_("Regular expression")";
title_array["~*"] = "$_("Regular expression (case-insensitive)")";
+ var saved_state = [ "classification", "source", "target", "analyzer" ];
+
+ var saved_forms = new Array();
+ saved_forms["classification"] = [ "default", "saved", "current" ];
+ saved_forms["source"] = [ "default", "saved", "current" ];
+ saved_forms["target"] = [ "default", "saved", "current" ];
+ saved_forms["analyzer"] = [ "default", "saved", "current" ];
+
+
+function input_equal(a, b) {
+ if ( a.type == "button" && b.type == "button" )
+ return true;
+
+ if ( a.name != b.name )
+ return false;
+
+ if ( a.checked != b.checked )
+ return false;
+
+ if ( a.selected != b.selected )
+ return false;
+
+ if ( a.value != b.value )
+ return false;
+
+ return true;
+}
+
+function Equals(a, b) {
+ if( ! a || ! b )
+ return false;
+
+ if ( a.length != b.length )
+ return false;
+
+ for ( var k = 0; k < a.length; k++ ) {
+ r = input_equal(a[k], b[k]);
+ if ( r == false )
+ return false;
+ }
+
+ return true;
+}
+
+
+function get_next_state(id, cstate) {
+ var nextstate = null;
+
+ if ( cstate == "current" ) {
+ if ( saved_forms[id]["saved"] && ! Equals(\$("#" + id + " input"), saved_forms[id]["saved"]) )
+ nextstate = "saved";
+
+ else if ( saved_forms[id]["default"] && ! Equals(\$("#" + id + " input"), saved_forms[id]["default"]) )
+ nextstate = "default";
+ }
+
+ else if ( cstate == "saved" ) {
+ if ( saved_forms[id]["default"] && ! Equals(\$("#" + id + " input"), saved_forms[id]["default"]) )
+ nextstate = "default";
+
+ else if ( saved_forms[id]["current"] && ! Equals(\$("#" + id + " input"), saved_forms[id]["current"]) )
+ nextstate = "current";
+ }
+
+ else if ( cstate == "default" ) {
+ if ( saved_forms[id]["current"] && ! Equals(\$("#" + id + " input"), saved_forms[id]["current"]) )
+ nextstate = "current";
+
+ else if ( saved_forms[id]["saved"] && ! Equals(\$("#" + id + " input"), saved_forms[id]["saved"]) )
+ nextstate = "saved";
+
+ else nextstate = "default";
+ }
+
+ return nextstate;
+}
+
+
function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
var elem;
var select = document.createElement("select");
@@ -50,15 +128,271 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
}
+###
+### Aggreg set saved/default/current
+###
+ #for $type, $table in ("classification", $aggregated_classification_saved), ("source", $aggregated_source_saved), ("target", $aggregated_target_saved), ("analyzer", $aggregated_analyzer_saved)
+function ${type}_set_aggregation_saved() {
+ #set $cnt = 0
+ #for $path in $table
+
+ #if $cnt > 0
+ \$("#${type} table.aggregation_table tr:last a.append_entry").trigger('click');
+ #end if
+ #set $cnt += 1
+
+ \$("#$type table.aggregation_table tr:last .popup_input_field option[value='$path']").attr("selected", "selected");
+ #end for
+ }
+#end for
+
+ #for $type, $table in ("classification", $aggregated_classification_default), ("source", $aggregated_source_default), ("target", $aggregated_target_default), ("analyzer", $aggregated_analyzer_default)
+function ${type}_set_aggregation_default() {
+
+ #set $cnt = 0
+ #for $path in $table
+
+ #if $cnt > 0
+ \$("#${type} table.aggregation_table tr:last a.append_entry").trigger('click');
+ #end if
+ #set $cnt += 1
+
+ \$("#$type table.aggregation_table tr:last .popup_input_field option[value='$path']").attr("selected", "selected");
+ #end for
+ }
+#end for
+
+ #for $type, $table in ("classification", $aggregated_classification), ("source", $aggregated_source), ("target", $aggregated_target), ("analyzer", $aggregated_analyzer)
+function ${type}_set_aggregation_current() {
+
+ #set $cnt = 0
+ #for $path in $table
+
+ #if $cnt > 0
+ \$("#${type} table.aggregation_table tr:last a.append_entry").trigger('click');
+ #end if
+ #set $cnt += 1
+
+ \$("#$type table.aggregation_table tr:last .popup_input_field option[value='$path']").attr("selected", "selected");
+ #end for
+ }
+ #end for
+
+
+
+###
+### Filter set saved/default
+###
+function classification_special_current() {
+ #for $path in "alert.create_time", "alert.correlation_alert.name", "alert.overflow_alert.program", "alert.tool_alert.name"
+ #if path in $alert.type
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[value='${path}']").attr("checked", "$checked");
+ #end for
+
+ #for $item in $N_("info"), $N_("low"), $N_("medium"), $N_("high"), $N_("none")
+ #if $item in $alert.assessment.impact.severity
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[name='alert.assessment.impact.severity'][value='$item']").attr("checked", "$checked");
+ #end for
+
+ #for item in $N_("succeeded"), $N_("failed"), $N_("none")
+ #if item in $alert.assessment.impact.completion
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[name='alert.assessment.impact.completion'][value='$item']").attr("checked", "$checked");
+ #end for
+}
+
+
+function classification_special_saved() {
+ #for $path in "alert.create_time", "alert.correlation_alert.name", "alert.overflow_alert.program", "alert.tool_alert.name"
+ #if path in $alert.type_saved
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[value='${path}']").attr("checked", "$checked");
+ #end for
+
+ #for $item in $N_("info"), $N_("low"), $N_("medium"), $N_("high"), $N_("none")
+ #if $item in $alert.assessment.impact.severity_saved
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[name='alert.assessment.impact.severity'][value='$item']").attr("checked", "$checked");
+ #end for
+
+ #for item in $N_("succeeded"), $N_("failed"), $N_("none")
+ #if item in $alert.assessment.impact.completion_saved
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[name='alert.assessment.impact.completion'][value='$item']").attr("checked", "$checked");
+ #end for
+}
+
+function classification_special_default() {
+ #for $path in "alert.create_time", "alert.correlation_alert.name", "alert.overflow_alert.program", "alert.tool_alert.name"
+ #if path in $alert.type_default
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[value='${path}']").attr("checked", "$checked");
+ #end for
+
+ #for $item in $N_("info"), $N_("low"), $N_("medium"), $N_("high"), $N_("none")
+ #if $item in $alert.assessment.impact.severity_default
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[name='alert.assessment.impact.severity'][value='$item']").attr("checked", "$checked");
+ #end for
+
+ #for item in $N_("succeeded"), $N_("failed"), $N_("none")
+ #if item in $alert.assessment.impact.completion_default
+ #set $checked = "checked='checked'"
+ #else
+ #set $checked = ""
+ #end if
+ \$("input[name='alert.assessment.impact.completion'][value='$item']").attr("checked", "$checked");
+ #end for
+}
+
+
+ #for $type, $table in ("classification", $classification), ("source", $source), ("target", $target), ("analyzer", $analyzer)
+
+function ${type}_filters_set_from_string(state) {
+ if ( state == "saved" ) {
+ ${type}_set_filter_saved();
+ ${type}_set_aggregation_saved();
+ }
+
+ else if ( state == "default" ) {
+ ${type}_set_filter_default();
+ ${type}_set_aggregation_default();
+ }
+
+ else if ( state == "current" ) {
+ ${type}_set_filter_current();
+ ${type}_set_aggregation_current();
+ }
+}
+
+
+function ${type}_set_filter_current() {
+ ${type}_set_filter_default()
+
+ #if $type == "classification"
+ ${type}_special_current();
+ #end if
+
+ /* trigger change for each empty filter, so that operator/value are positionned correctly */
+ \$("#${type} table.filter_table tr .popup_select_field").trigger("change");
+
+ #set $cnt = 0
+ #for $path, $operator, $value in $table
+
+ #if $cnt > 0
+ \$("#${type} table.filter_table tr:last a.append_entry").trigger('click');
+ #end if
+ #set $cnt += 1
+
+ #if not $path
+ #continue
+ #end if
+
+ #if $path != "__all__"
+ \$("#$type table.filter_table tr:last .popup_select_field option[value='$path']").attr("selected", "selected");
+ \$("#$type table.filter_table tr:last .popup_operator_select option[value='$operator']").attr("selected", "selected");
+ \$("#$type table.filter_table tr:last .expert_mode").trigger("click");
+ #else
+ \$("#$type table.filter_table tr:last .popup_select_field").hide();
+ \$("#$type table.filter_table tr:last .popup_select_field").attr("disabled", "disabled");
+ #end if
+
+ \$("#$type table.filter_table tr:last .popup_input_field").attr("value", "$utils.escape_attribute($value)");
+ \$("#$type table.filter_table tr:last .popup_input_field option[value='$value']").attr("selected", "selected");
+ #end for
+ }
+
+ ${type}_set_filter_current();
+ #end for
+
+
+#for $type, $table in ("classification", $classification_saved), ("source", $source_saved), ("target", $target_saved), ("analyzer", $analyzer_saved)
+function ${type}_set_filter_default() {
+ \$("#${type} table.filter_table tr:not(':first'):not(':last')").remove()
+ \$("#${type} table.filter_table input[type=text]").val("")
+
+ #if $type == "classification"
+ ${type}_special_default();
+ #end if
+}
+
+function ${type}_set_filter_saved() {
+
+ ${type}_set_filter_default()
+
+ #if $type == "classification"
+ ${type}_special_saved();
+ #end if
+
+ /* trigger change for each empty filter, so that operator/value are positionned correctly */
+ \$("#${type} table.filter_table tr .popup_select_field").trigger("change");
+
+ #set $cnt = 0
+ #for $path, $operator, $value in $table
+
+ #if $cnt > 0
+ \$("#${type} table.filter_table tr:last a.append_entry").trigger('click');
+ #end if
+ #set $cnt += 1
+
+ #if not $path
+ #continue
+ #end if
+
+ #if $path != "__all__"
+ \$("#$type table.filter_table tr:last .popup_select_field option[value='$path']").attr("selected", "selected");
+ \$("#$type table.filter_table tr:last .popup_operator_select option[value='$operator']").attr("selected", "selected");
+ \$("#$type table.filter_table tr:last .expert_mode").trigger("click");
+ #else
+ \$("#$type table.filter_table tr:last .popup_select_field").hide();
+ \$("#$type table.filter_table tr:last .popup_select_field").attr("disabled", "disabled");
+ #end if
+
+ \$("#$type table.filter_table tr:last .popup_input_field").attr("value", "$utils.escape_attribute($value)");
+ \$("#$type table.filter_table tr:last .popup_input_field option[value='$value']").attr("selected", "selected");
+ #end for
+ }
+ #end for
+
+
+
\$(document).ready(function() {
\$(".expert_mode").live("click", function() {
if ( ! \$(this).parent().parent().children(".td_container_path").children().is(":visible") ) {
+ \$(this).text("simple");
\$(this).parent().parent().children(".td_container_operator").children().show()
\$(this).parent().parent().children(".td_container_path").children("select").show()
\$(this).parent().parent().children(".td_container_path").children("input").attr("disabled", "disabled")
\$(this).parent().parent().children(".td_container_path").children("select").removeAttr("disabled")
} else {
+ \$(this).text("advanced");
\$(this).parent().parent().children(".td_container_path").children().hide()
\$(this).parent().parent().children(".td_container_operator").children().hide()
\$(this).parent().parent().children(".td_container_path").children("input").removeAttr("disabled")
@@ -131,48 +465,53 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
#for $type, $table in ("classification", $classification), ("source", $source), ("target", $target), ("analyzer", $analyzer)
+ ${type}_set_filter_saved();
+ ${type}_set_aggregation_saved();
+ saved_forms["${type}"]["saved"] = \$("#${type} input").clone()
- /* trigger change for each empty filter, so that operator/value are positionned correctly */
- \$("#${type} table.filter_table tr .popup_select_field").trigger("change");
+ ${type}_set_filter_default();
+ ${type}_set_aggregation_default();
+ saved_forms["${type}"]["default"] = \$("#${type} input").clone()
- #set $cnt = 0
- #for $path, $operator, $value in $table
+ ${type}_set_filter_current();
+ ${type}_set_aggregation_current();
+ saved_forms["${type}"]["current"] = \$("#${type} input").clone()
- #if $cnt > 0
- \$("#${type} table.filter_table tr:last a.append_entry").trigger('click');
- #end if
- #set $cnt += 1
- #if not $path
- #continue
- #end if
+ if ( Equals(saved_forms["${type}"]["default"], saved_forms["${type}"]["saved"]) )
+ saved_forms["${type}"]["saved"] = null;
- #if $path != "__all__"
- \$("#$type table.filter_table tr:last .popup_select_field option[value='$path']").attr("selected", "selected");
- \$("#$type table.filter_table tr:last .popup_operator_select option[value='$operator']").attr("selected", "selected");
- \$("#$type table.filter_table tr:last .expert_mode").trigger("click");
- #else
- \$("#$type table.filter_table tr:last .popup_select_field").hide();
- \$("#$type table.filter_table tr:last .popup_select_field").attr("disabled", "disabled");
- #end if
+ if ( Equals(saved_forms["${type}"]["current"], saved_forms["${type}"]["default"]) )
+ saved_forms["${type}"]["current"] = null;
- \$("#$type table.filter_table tr:last .popup_input_field").attr("value", "$utils.escape_attribute($value)");
- \$("#$type table.filter_table tr:last .popup_input_field option[value='$value']").attr("selected", "selected");
- #end for
- #end for
+ ## Set the current state
+ if ( Equals(\$("#${type} input"), saved_forms["${type}"]["default"]) )
+ saved_state["$type"] = "default";
- #for $type, $table in ("classification", $aggregated_classification), ("source", $aggregated_source), ("target", $aggregated_target), ("analyzer", $aggregated_analyzer)
- #set $cnt = 0
- #for $path in $table
+ else if ( Equals(\$("#${type} input"), saved_forms["$type"]["saved"]) )
+ saved_state["$type"] = "saved";
+
+
+ else if ( Equals(\$("#${type} input"), saved_forms["$type"]["current"]) )
+ saved_state["$type"] = "current";
+
+ ##alert("$type: " + saved_state["$type"]);
+ \$("#${type} input.reset_filter").val("Reset to " + get_next_state("$type", saved_state["$type"]));
- #if $cnt > 0
- \$("#${type} table.aggregation_table tr:last a.append_entry").trigger('click');
- #end if
- #set $cnt += 1
- \$("#$type table.aggregation_table tr:last .popup_input_field option[value='$path']").attr("selected", "selected");
- #end for
#end for
+
+\$("input.reset_filter").click(function() {
+ var div_id = \$(this).parent().parent().parent().parent().parent().parent().parent().parent().parent().attr("id");
+ saved_state[div_id] = get_next_state(div_id, saved_state[div_id]);
+
+ #for $t in "classification", "source", "target", "analyzer"
+ if ( div_id == "$t" )
+ ${t}_filters_set_from_string(saved_state[div_id]);
+ #end for
+
+ \$(this).val("Reset to " + get_next_state(div_id, saved_state[div_id]));
+ });
});
//--></script>
@@ -180,13 +519,10 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
#end filter
#end block
-
#def define_inline_filter($obname, $preselect)
<table class="inline_filter_content filter_table">
<tr class="inline_filter">
- <th>$_('Filter on:')</th>
- <td><a class="expert_mode">[exp]</a></td>
-
+ <th>$_('Filter on') [<a class="expert_mode">advanced</a>]:</th>
<td class="td_container_path">
<input type="hidden" name="${obname}_object_0" value="__all__" />
<select style="display:none;" disabled="disabled" class="popup_select_field" name="${obname}_object_0">
@@ -235,7 +571,6 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
<table class="inline_filter_content aggregation_table">
<tr class="inline_filter">
<th>$_('Group entry by:')</th>
- <td> </td>
<td class="td_container_path">
<select class="popup_input_field" name="aggregated_${obname}">
#for $name, $path, $unuseda, $unusedb in $all_aggregs[$obname]
@@ -253,13 +588,35 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
</table>
#end def
+#def filter_enabled_marker($type)
+ <span style="float:right;">
+ #if $type == 2
+ <span class="filter_enabled_marker">[$_("filtered")]</span>
+ #else
+ <span class="filter_enabled_marker" style="color: gray;">[$_("filtered")]</span>
+ #end if
+ </span>
+#end def
-#block message_fields_header
+#def filter_reset()
+<tr><td>
+ <table class="inline_filter_content">
+ <tr class="inline_filter">
+ <td colspan="3"> </td>
+ <td>
+ <input type="submit" value="Apply" />
+ <input type="button" class="reset_filter" value="Reset" />
+ </td>
+ </tr>
+ </table>
+</td></tr>
+#end def
+#block message_fields_header
<thead>
<tr style="height: 20px;">
<th class="filter_popup">
- <a>$_("Classification")</a>
+ <a class="filter_popup_link">$_("Classification")</a>
<div id="classification">
<table>
<tr><td>$define_inline_filter("classification", "alert.classification.text")</td></tr>
@@ -289,12 +646,7 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
<tr>
<th>$_("Severity:")</th>
#for $item in $N_("info"), $N_("low"), $N_("medium"), $N_("high"), $N_("none")
- #if $item in $alert.assessment.impact.severity
- #set $checked = "checked='checked'"
- #else
- #set $checked = ""
- #end if
- <td>$_($item)<input class="checkbox" type="checkbox" name="alert.assessment.impact.severity" value="$item" $checked /></td>
+ <td>$_($item)<input class="checkbox" type="checkbox" name="alert.assessment.impact.severity" value="$item" /></td>
#end for
</tr>
@@ -303,63 +655,62 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
<td colspan="2"> </td>
#for item in $N_("succeeded"), $N_("failed"), $N_("none")
- #if item in $alert.assessment.impact.completion
- #set $checked = "checked='checked'"
- #else
- #set $checked = ""
- #end if
- <td>$_($item)<input class="checkbox" type="checkbox" name="alert.assessment.impact.completion" value="$item" $checked /></td>
+ <td>$_($item)<input class="checkbox" type="checkbox" name="alert.assessment.impact.completion" value="$item" /></td>
#end for
</tr>
</table>
</td></tr>
+ $filter_reset()
</table>
</div>
#if $classification_filtered
- <span class="filter_enabled_marker">[$_("filtered")]</span>
+ $filter_enabled_marker($classification_filtered)
#end if
</th>
<th class="filter_popup">
- <a>$_("Source")</a>
+ <a class="filter_popup_link">$_("Source")</a>
<div id="source">
<table>
<tr><td>$define_inline_filter("source", "alert.source.node.address.address")</td></tr>
<tr><td>$define_inline_aggreg("source")</td></tr>
+ $filter_reset()
</table>
</div>
#if $source_filtered
- <span class="filter_enabled_marker">[$_("filtered")]</span>
+ $filter_enabled_marker($source_filtered)
#end if
</th>
<th class="filter_popup">
- <a>$_("Target")</a>
+ <a class="filter_popup_link">$_("Target")</a>
<div id="target">
<table>
<tr><td>$define_inline_filter("target", "alert.target.node.address.address")</td></tr>
<tr><td>$define_inline_aggreg("target")</td></tr>
+ $filter_reset()
</table>
</div>
#if $target_filtered
- <span class="filter_enabled_marker">[$_("filtered")]</span>
+ $filter_enabled_marker($target_filtered)
#end if
</th>
<th class="filter_popup">
- <a>$_("Sensor")</a>
+ <a class="filter_popup_link">$_("Sensor")</a>
<div id="analyzer">
<table>
<tr><td>$define_inline_filter("analyzer", "alert.analyzer.name")</td></tr>
<tr><td>$define_inline_aggreg("analyzer")</td></tr>
+ $filter_reset()
</table>
</div>
#if $analyzer_filtered
- <span class="filter_enabled_marker">[$_("filtered")]</span>
+ $filter_enabled_marker($analyzer_filtered)
#end if
</th>
diff --git a/prewikka/templates/MessageListing.tmpl b/prewikka/templates/MessageListing.tmpl
index 440c52a..8620f97 100644
--- a/prewikka/templates/MessageListing.tmpl
+++ b/prewikka/templates/MessageListing.tmpl
@@ -20,7 +20,7 @@ var autorefresh_enabled = true;
\$("th.filter_popup > div").hide();
}
- \$("th.filter_popup > a").click(function(){
+ \$(".filter_popup_link").click(function(){
\$(this).next().popupUnique(function(data){data.show()}, function(data){data.hide()})
return false;
});
diff --git a/prewikka/view.py b/prewikka/view.py
index f35ec33..bca522b 100644
--- a/prewikka/view.py
+++ b/prewikka/view.py
@@ -48,6 +48,7 @@ class Parameters(dict):
def __init__(self, *args, **kwargs):
apply(dict.__init__, (self, ) + args, kwargs)
+ self._hard_default = {}
self._default = {}
self._parameters = { }
self.register()
@@ -63,14 +64,17 @@ class Parameters(dict):
def optional(self, name, type, default=None, save=False):
if default is not None:
- self._default[name] = default
+ self._hard_default[name] = default
self._parameters[name] = { "type": type, "mandatory": False, "default": default, "save": save }
def _parseValue(self, name, value):
parameter_type = self._parameters[name]["type"]
- if parameter_type is list and not type(value) is list:
- value = [ value ]
+ if parameter_type is list:
+ if not type(value) is list:
+ value = [ value ]
+
+ value.sort()
try:
value = parameter_type(value)
@@ -120,15 +124,48 @@ class Parameters(dict):
self._default[name] = value
if do_load and not got_param:
- self[name] = self._default[name]
+ self[name] = value
try: self.pop("_save")
except: pass
return do_load
- def getDefaultValues(self):
- return self._default
+ def getDefault(self, param, usedb=True):
+ return self.getDefaultValues(usedb)[param]
+
+ def getDefaultValues(self, usedb=True):
+ if not usedb:
+ return self._hard_default
+ else:
+ return self._default
+
+ def isSaved(self, param):
+ if not self._parameters.has_key(param):
+ return False
+
+ if not self._parameters[param].has_key("save") or not self._parameters[param]["save"]:
+ return False
+
+ val1 = self._hard_default[param]
+ val2 = self[param]
+
+ if type(val1) is list:
+ val1.sort()
+
+ if type(val2) is list:
+ val2.sort()
+
+ if val1 == val2:
+ return False
+
+ return True
+
+ def isDefault(self, param, usedb=True):
+ if not usedb:
+ return self._hard_default.has_key(param)
+ else:
+ return self._default.has_key(param)
def __add__(self, src):
dst = copy(self)
diff --git a/prewikka/views/alertlisting.py b/prewikka/views/alertlisting.py
index cd5c858..bf96d82 100644
--- a/prewikka/views/alertlisting.py
+++ b/prewikka/views/alertlisting.py
@@ -142,6 +142,8 @@ def _getAnalyzerPath(add_empty=False, add_index=None):
return empty + _getPathList(prelude.IDMEF_CLASS_ID_ANALYZER, "alert.analyzer(-1)", add_index=add_index)
+COLUMN_LIST = [ "classification", "source", "target", "analyzer" ]
+
CLASSIFICATION_FILTERS = _getClassificationPath()
CLASSIFICATION_AGGREGATIONS = _getClassificationPath(add_empty=True, add_index="(0)")
CLASSIFICATION_GENERIC_SEARCH_FIELDS = [ "alert.classification.text", "alert.classification.reference.name", "alert.classification.reference.origin" ]
@@ -174,6 +176,13 @@ GENERIC_SEARCH_TABLE = { "classification": CLASSIFICATION_GENERIC_SEARCH_FIELDS,
class AlertListingParameters(MessageListingParameters):
allow_extra_parameters = True
+ def __init__(self, *args, **kwargs):
+ apply(MessageListingParameters.__init__, (self, ) + args, kwargs)
+ MessageListingParameters.__init__(self)
+ self._dynamic_param = { "classification": {}, "source": {}, "target": {}, "analyzer": {} }
+ self._default_param = { "classification": {}, "source": {}, "target": {}, "analyzer": {} }
+ self._saved = { "classification": [], "source": [], "target": [], "analyzer": [] }
+
def register(self):
self.max_index = 0
MessageListingParameters.register(self)
@@ -182,10 +191,8 @@ class AlertListingParameters(MessageListingParameters):
self.optional("aggregated_classification", list, [ "none" ], save=True)
self.optional("aggregated_analyzer", list, [ "none" ], save=True)
self.optional("filter", str, save=True)
- self.optional("alert.classification.text", list, [ ], save=True)
self.optional("alert.assessment.impact.severity", list, [ "info", "low", "medium", "high", "none" ], save=True)
self.optional("alert.assessment.impact.completion", list, [ "succeeded", "failed", "none" ], save=True)
- self.optional("alert.assessment.impact.type", list, [ "other", "admin", "dos", "file", "recon", "user" ], save=True)
self.optional("alert.type", list, ["alert.create_time", "alert.correlation_alert.name", "alert.overflow_alert.program", "alert.tool_alert.name"], save=True)
def _checkOperator(self, operator):
@@ -195,11 +202,25 @@ class AlertListingParameters(MessageListingParameters):
if not operator in ("=", "<", ">", "<=", ">=", "~", "~*", "<>", "<>*"):
raise view.InvalidParameterValueError("operator", operator)
- def _loadColumnParam(self, view_name, user, paramlist, column, do_save):
+ def _setParam(self, view_name, user, column, param, value, is_default=False):
+ self._dynamic_param[column][param] = value
+
+ if is_default:
+ self._default_param[column][param] = value
+ user.setConfigValue(view_name, param, value)
+
+ elif user.configuration.has_key(view_name) and user.configuration[view_name].has_key(param) and user.configuration[view_name][param] != value:
+ self._default_param[column][param] = value
+
+ if not self.has_key(param):
+ # the parameter is loaded from config
+ self[param] = value
+
+ def _paramDictToList(self, params_dict, column):
+ sorted = []
ret = False
- sorted = [ ]
- for parameter, object in paramlist.items():
+ for parameter, object in params_dict.items():
idx = parameter.find(column + "_object_")
if idx == -1:
continue
@@ -209,11 +230,11 @@ class AlertListingParameters(MessageListingParameters):
self.max_index = num + 1
ret = True
- operator = paramlist.get(column + "_operator_" + str(num), "=")
+ operator = params_dict.get(column + "_operator_" + str(num), "=")
self._checkOperator(operator)
try:
- value = paramlist[column + "_value_" + str(num)]
+ value = params_dict[column + "_value_" + str(num)]
except KeyError:
continue
@@ -227,22 +248,27 @@ class AlertListingParameters(MessageListingParameters):
sorted.append((num, object, operator, value))
sorted.sort()
- self[column] = [ (i[1], i[2], i[3]) for i in sorted ]
+ return ret, sorted
+ def _loadColumnParam(self, view_name, user, paramlist, column, do_save):
+ is_saved = False
if do_save:
+ paramlist = copy.copy(paramlist)
user.delConfigValueMatch(view_name, "%s_object_" % (column))
user.delConfigValueMatch(view_name, "%s_operator_" % (column))
user.delConfigValueMatch(view_name, "%s_value_" % (column))
- for num, obj, operator, value in sorted:
- user.setConfigValue(view_name, "%s_object_%d" % (column, num), obj)
- user.setConfigValue(view_name, "%s_operator_%d" % (column, num), operator)
- user.setConfigValue(view_name, "%s_value_%d" % (column, num), value)
+ self[column] = []
+ ret, sorted = self._paramDictToList(paramlist, column)
+ for i in sorted:
+ self._setParam(view_name, user, column, "%s_object_%d" % (column, i[0]), i[1], is_default=do_save)
+ self._setParam(view_name, user, column, "%s_operator_%d" % (column, i[0]), i[2], is_default=do_save)
+ self._setParam(view_name, user, column, "%s_value_%d" % (column, i[0]), i[3], is_default=do_save)
+ self[column].append(i[1:]);
return ret
-
def normalize(self, view_name, user):
do_save = self.has_key("_save")
do_load = MessageListingParameters.normalize(self, view_name, user)
@@ -255,10 +281,6 @@ class AlertListingParameters(MessageListingParameters):
if not completion in ("succeeded", "failed", "none"):
raise view.InvalidParameterValueError("alert.assessment.impact.completion", completion)
- for type in self["alert.assessment.impact.type"]:
- if not type in ("other", "admin", "dos", "file", "recon", "user"):
- raise view.InvalidParameterValueError("alert.assessment.impact.type", type)
-
for type in self["alert.type"]:
if not type in ("alert.create_time", "alert.correlation_alert.name", "alert.overflow_alert.program", "alert.tool_alert.name"):
raise view.InvalidParameterValueError("alert.type", type)
@@ -273,18 +295,48 @@ class AlertListingParameters(MessageListingParameters):
for column in "classification", "source", "target", "analyzer":
self._loadColumnParam(view_name, user, user.configuration[view_name], column, do_save)
- for category in "classification", "source", "target", "analyzer":
- i = 0
- for path in self["aggregated_%s" % category]:
+ for column in COLUMN_LIST:
+ if user.configuration.has_key(view_name):
+ for i in self._paramDictToList(user.configuration[view_name], column)[1]:
+ self._saved[column].append(i[1:])
- if self["aggregated_%s" % category].count(path) > 1:
- self["aggregated_%s" % category].remove(path)
+ for i in user.configuration[view_name].keys():
+ if i.find(column + "_object_") != -1 or i.find(column + "_operator_") != -1 or i.find(column + "_value_") != -1:
+ self._default_param[column][i] = user.configuration[view_name][i]
+
+ i = 0
+ for path in self["aggregated_%s" % column]:
+ if self["aggregated_%s" % column].count(path) > 1:
+ self["aggregated_%s" % column].remove(path)
if path[0] == "!":
- self["aggregated_%s" % category][i] = path[1:]
+ self["aggregated_%s" % column][i] = path[1:]
i += 1
+ def getDefaultParams(self, column):
+ return self._default_param[column]
+
+ def getDynamicParams(self, column):
+ return self._dynamic_param[column]
+
+ def _isSaved(self, column, param):
+ if not self._default_param[column].has_key(param):
+ return False
+
+ if not self.has_key(param):
+ return False
+
+ if self._default_param[column][param] == self[param]:
+ return True
+
+ return False
+
+ def isSaved(self, column, param):
+ if self._isSaved(column, param):
+ return True
+
+ return MessageListingParameters.isSaved(self, param)
class SensorAlertListingParameters(AlertListingParameters):
@@ -300,8 +352,8 @@ class SensorAlertListingParameters(AlertListingParameters):
class CorrelationAlertListingParameters(AlertListingParameters):
def register(self):
AlertListingParameters.register(self)
- self.optional("aggregated_source", list, [ ], save=True)
- self.optional("aggregated_target", list, [ ], save=True)
+ self.optional("aggregated_source", list, [ "none" ], save=True)
+ self.optional("aggregated_target", list, [ "none" ], save=True)
self.optional("alert.type", list, ["alert.correlation_alert.name"], save=True)
def normalize(self, view_name, user):
@@ -311,8 +363,8 @@ class CorrelationAlertListingParameters(AlertListingParameters):
class ToolAlertListingParameters(AlertListingParameters):
def register(self):
AlertListingParameters.register(self)
- self.optional("aggregated_source", list, [ ], save=True)
- self.optional("aggregated_target", list, [ ], save=True)
+ self.optional("aggregated_source", list, [ "none" ], save=True)
+ self.optional("aggregated_target", list, [ "none" ], save=True)
self.optional("alert.type", list, ["alert.tool_alert.name"], save=True)
def normalize(self, view_name, user):
@@ -756,7 +808,6 @@ class AlertListing(MessageListing, view.View):
criteria.append("(" + " || ".join(new) + ")")
self.dataset[object] = self.parameters[object]
- self.dataset[column + "_filtered"] = True
else:
self.dataset[object] = values
@@ -786,9 +837,6 @@ class AlertListing(MessageListing, view.View):
else:
criteria.append("(" + " && ".join(new) + ")")
- if not self._lists_have_same_content(self.parameters["alert.type"], self.alert_type_default):
- self.dataset["classification_filtered"] = True
-
def _applyClassificationFilters(self, criteria):
self._applyAlertTypeFilters(criteria)
@@ -796,17 +844,39 @@ class AlertListing(MessageListing, view.View):
["info", "low", "medium", "high", "none"])
self._applyOptionalEnumFilter(criteria, "classification", "alert.assessment.impact.completion",
["failed", "succeeded", "none"])
- self._applyOptionalEnumFilter(criteria, "classification", "alert.assessment.impact.type",
- ["other", "admin", "dos", "file", "recon", "user"])
+ def _criteriaValueFind(self, str, clist=[]):
+ out=""
+ found = False
+ escaped = False
+
+ for c in str:
+ if escaped:
+ escaped = False
+ else:
+ if c in clist:
+ found = True
+
+ if c == '\\':
+ escaped = True
+
+ out += c
+
+ return out, found
+
def _adjustFilterValue(self, op, value):
value = value.strip()
- if op == "<>*" or op == "<>":
- return "*" + value + "*"
- else:
+
+ if op != "<>*" and op != "<>":
+ return value
+
+ value, has_wildcard = self._criteriaValueFind(value, ["*"])
+ if has_wildcard:
return value
+ return "*" + value + "*"
+
def _filterTupleToString(self, (object, operator, value)):
return "%s %s '%s'" % (object, operator, utils.escape_criteria(self._adjustFilterValue(operator, value)))
@@ -831,7 +901,6 @@ class AlertListing(MessageListing, view.View):
def _applyFiltersForCategory(self, criteria, type):
if not self.parameters[type]:
self.dataset[type] = [ ("", "", "") ]
- self.dataset["%s_filtered" % type] = False
return
# If one object is specified more than one time, and since this object
@@ -870,7 +939,6 @@ class AlertListing(MessageListing, view.View):
criteria.append(newcrit)
self.dataset[type] = [ (path.replace("(0)", "").replace("(-1)", ""), operator, value) for path, operator, value in self.parameters[type] ]
- self.dataset["%s_filtered" % type] = True
def _applyFilters(self, criteria):
self._applyFiltersForCategory(criteria, "classification")
@@ -1129,7 +1197,56 @@ class AlertListing(MessageListing, view.View):
return MessageListing._setMessages(self, criteria)
+ def _paramChanged(self, column, paramlist):
+ ret = 0
+
+ cd = self.parameters.getDefaultParams(column)
+ default = self.parameters.getDefaultValues()
+ default.update(cd)
+
+ for param in paramlist + cd.keys():
+ if ret != 2 and self.parameters.isSaved(column, param):
+ ret = 1
+
+ if not default.has_key(param):
+ if self.parameters.has_key(param):
+ if self.parameters[param] != []:
+ #print "[%s] -> %s" % (param, self.parameters[param])
+ ret = 2
+ break
+
+ continue
+
+ if not self.parameters.has_key(param):
+ #print "[%s] default=%s -> " % (param, default[param])
+ #continue
+ ret = 2
+ break
+
+ if type(default[param]) is list:
+ default[param].sort()
+
+ if type(self.parameters[param]) is list:
+ self.parameters[param].sort()
+
+ if default[param] != self.parameters[param]:
+ #print "[%s] %s -> %s" % (param, default[param], self.parameters[param])
+ ret = 2
+ break
+
+ return ret
+
def _setDatasetConstants(self):
+ for i in COLUMN_LIST:
+ n = "aggregated_" + i
+ self.dataset[n + "_saved"] = self.parameters.getDefault(n, usedb=True)
+ self.dataset[n + "_default"] = self.parameters.getDefault(n, usedb=False)
+ self.dataset[i + "_saved"] = self.parameters._saved[i]
+
+ for i in ("alert.type", "alert.assessment.impact.severity", "alert.assessment.impact.completion"):
+ self.dataset[i + "_saved"] = self.parameters.getDefault(i, usedb=True)
+ self.dataset[i + "_default"] = self.parameters.getDefault(i, usedb=False)
+
self.dataset["classification_filters"] = CLASSIFICATION_FILTERS
self.dataset["classification_aggregations"] = CLASSIFICATION_AGGREGATIONS
self.dataset["source_filters"] = SOURCE_FILTERS
@@ -1141,6 +1258,17 @@ class AlertListing(MessageListing, view.View):
self.dataset["all_filters"] = { "classification" : CLASSIFICATION_FILTERS, "source": SOURCE_FILTERS, "target": TARGET_FILTERS, "analyzer": ANALYZER_FILTERS }
self.dataset["all_aggregs"] = { "classification" : CLASSIFICATION_AGGREGATIONS, "source": SOURCE_AGGREGATIONS, "target": TARGET_AGGREGATIONS, "analyzer": ANALYZER_AGGREGATIONS }
+ c_params = ["aggregated_classification"] + self.parameters.getDynamicParams("classification").keys()
+ c_params += ["alert.type", "alert.assessment.impact.severity", "alert.assessment.impact.completion" ]
+ s_params = ["aggregated_source"] + self.parameters.getDynamicParams("source").keys()
+ t_params = ["aggregated_target"] + self.parameters.getDynamicParams("target").keys()
+ a_params = ["aggregated_analyzer"] + self.parameters.getDynamicParams("analyzer").keys()
+
+ self.dataset["classification_filtered"] = self._paramChanged("classification", c_params)
+ self.dataset["source_filtered"] = self._paramChanged("source", s_params)
+ self.dataset["target_filtered"] = self._paramChanged("target", t_params)
+ self.dataset["analyzer_filtered"] = self._paramChanged("analyzer", a_params)
+
def render(self):
MessageListing.render(self)
_______________________________________________
Prelude-cvslog site list
[email protected]
http://lists.prelude-ids.org/mailman/listinfo/prelude-cvslog
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.