prewikka/master: Implement simplified inline filter.

[email protected]
Newsgroups gmane.comp.security.ids.prelude.cvs
Message-ID <[email protected]>
commit 75ce474e3ef6310366270d535ae0bb587d414035
Author: Yoann Vandoorselaere <[email protected]>
Date:   Wed May 20 12:08:17 2009 +0200

    Implement simplified inline filter.
    
    Inline filter now present a single input field (with no path and operator
    selection). Using this field, the user can filter on what is seen in the
    associated column. For example, in the classification column, the filter
    will trigger a search on classification.text, classification.reference.name
    and classification.reference.origin.
    
    There is also an [expert] button allowing the user to specify both the
    path and the operator.


========================================

 prewikka/templates/AlertListing.tmpl |   49 +++++++++++++++++++++----
 prewikka/views/alertlisting.py       |   65 +++++++++++++++++++++++++++++++---
 2 files changed, 101 insertions(+), 13 deletions(-)

========================================

diff --git a/prewikka/templates/AlertListing.tmpl b/prewikka/templates/AlertListing.tmpl
index 4935f8f..27eb894 100644
--- a/prewikka/templates/AlertListing.tmpl
+++ b/prewikka/templates/AlertListing.tmpl
@@ -52,6 +52,21 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
 
 \$(document).ready(function() {
 
+ \$(".expert_mode").live("click", function() {
+        if ( ! \$(this).parent().parent().children(".td_container_path").children().is(":visible") ) {
+                \$(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).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")
+                \$(this).parent().parent().children(".td_container_path").children("select").attr("disabled", "disabled")
+        }
+});
+
+
  \$(".remove_entry").live("click", function() {
         \$(this).parent().parent().remove();
  });
@@ -75,10 +90,9 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
         \$(select).attr("name", div_id + "_object_" + global_id);
    }
 
+   \$(this).parents(".inline_filter").after(tr);
    \$(select).trigger("change");
-
    \$(tr).children("td.td_container_remove").html("<a class=\"remove_entry\">-</a>");
-   \$(this).parents(".inline_filter").after(tr);
  });
 
 
@@ -89,8 +103,13 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
 
           if ( operator_array[str] ) {
                 var old_select = \$(td).siblings(".td_container_operator").children();
+                var display = \$(old_select).is(":visible")
                 var old_value = \$(old_select).children(":selected").attr("value");
+
                 select = createSelectFromArray(operator_array[str], "popup_operator_select", \$(old_select).attr("name"), old_value);
+                if ( ! display )
+                        \$(select).hide();
+
                 \$(old_select).replaceWith(select);
           }
 
@@ -112,11 +131,11 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
 
 
  #for $type, $table in ("classification", $classification), ("source", $source), ("target", $target), ("analyzer", $analyzer)
-  #set $cnt = 0
 
   /* 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
@@ -128,8 +147,15 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
    #continue
   #end if
 
-  \$("#$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");
+  #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
@@ -159,8 +185,11 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
       <table class="inline_filter_content filter_table">
        <tr class="inline_filter">
         <th>$_('Filter on:')</th>
+        <td><a class="expert_mode">[exp]</a></td>
+
         <td class="td_container_path">
-         <select class="popup_select_field" name="${obname}_object_0">
+         <input type="hidden" name="${obname}_object_0" value="__all__" />
+         <select style="display:none;" disabled="disabled" class="popup_select_field" name="${obname}_object_0">
           #for $name, $path, $oplist, $value in $all_filters[$obname]
 
            #if $value or $oplist
@@ -186,12 +215,15 @@ function createSelectFromArray(varray, sclass, name_attr, selected, defsel) {
           #end for
          </select>
         </td>
+
         <td class="td_container_operator">
-         <select class="popup_operator_select" name="${obname}_operator_0"></select>
+         <select style="display:none;" class="popup_operator_select" name="${obname}_operator_0" />
         </td>
+
         <td class="td_container_value">
-         <input class="popup_input_field" type="text" name="${obname}_value_0"></input>
+         <input class="popup_input_field" type="text" name="${obname}_value_0" />
         </td>
+
         <td class="td_container_remove">&nbsp;</td>
         <td class="td_container_add"><a class="append_entry">+</a></td>
        </tr>
@@ -203,6 +235,7 @@ 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>&nbsp;</td>
         <td class="td_container_path">
          <select class="popup_input_field" name="aggregated_${obname}">
           #for $name, $path, $unuseda, $unusedb in $all_aggregs[$obname]
diff --git a/prewikka/views/alertlisting.py b/prewikka/views/alertlisting.py
index f6f6801..76943c1 100644
--- a/prewikka/views/alertlisting.py
+++ b/prewikka/views/alertlisting.py
@@ -144,16 +144,31 @@ def _getAnalyzerPath(add_empty=False, add_index=None):
 
 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" ]
 
 SOURCE_FILTERS = _getSourcePath()
 SOURCE_AGGREGATIONS = _getSourcePath(add_empty=True, add_index="(0)")
+SOURCE_GENERIC_SEARCH_FIELDS = [ "alert.source.node.address.address", "alert.source.user.user_id.name",
+                                 "alert.source.user.user_id.number", "alert.source.process.name", "alert.source.process.pid",
+                                 "alert.source.service.protocol", "alert.source.service.iana_protocol_name", "alert.source.service.iana_protocol_number",
+                                 "alert.source.service.port" ]
 
 TARGET_FILTERS = _getTargetPath()
 TARGET_AGGREGATIONS = _getTargetPath(add_empty=True, add_index="(0)")
+TARGET_GENERIC_SEARCH_FIELDS = [ "alert.target.node.address.address", "alert.target.user.user_id.name",
+                                 "alert.target.user.user_id.number", "alert.target.process.name", "alert.target.process.pid",
+                                 "alert.target.service.protocol", "alert.target.service.iana_protocol_name", "alert.target.service.iana_protocol_number",
+                                 "alert.target.service.port" ]
+
 
 ANALYZER_FILTERS = _getAnalyzerPath()
 ANALYZER_AGGREGATIONS = _getAnalyzerPath(add_empty=True, add_index="(0)")
+ANALYZER_GENERIC_SEARCH_FIELDS = [ "alert.analyzer.name", "alert.analyzer.node.name" ]
 
+GENERIC_SEARCH_TABLE = { "classification": CLASSIFICATION_GENERIC_SEARCH_FIELDS,
+                         "source": SOURCE_GENERIC_SEARCH_FIELDS,
+                         "target": TARGET_GENERIC_SEARCH_FIELDS,
+                         "analyzer": ANALYZER_GENERIC_SEARCH_FIELDS }
 
 
 class AlertListingParameters(MessageListingParameters):
@@ -784,8 +799,34 @@ class AlertListing(MessageListing, view.View):
         self._applyOptionalEnumFilter(criteria, "classification", "alert.assessment.impact.type",
                                       ["other", "admin", "dos", "file", "recon", "user"])
 
+
+    def _adjustFilterValue(self, op, value):
+        value = value.strip()
+        if op == "<>*" or op == "<>":
+            return "*" + value + "*"
+        else:
+            return value
+
     def _filterTupleToString(self, (object, operator, value)):
-        return "%s %s '%s'" % (object, operator, utils.escape_criteria(value))
+        return "%s %s '%s'" % (object, operator, utils.escape_criteria(self._adjustFilterValue(operator, value)))
+
+    def _getOperatorForPath(self, path, value):
+        # Check whether the path can handle substring comparison
+        # this need to be done first, since enum check with * won't work with "=" operator.
+        try:
+            c = prelude.idmef_criteria_new_from_string(path + " <>* '" + utils.escape_criteria(value) + "'")
+        except:
+            # Check whether this path can handle the provided value.
+            try:
+                c = prelude.idmef_criteria_new_from_string(path + " = '" + utils.escape_criteria(value) + "'")
+            except:
+                return None
+
+            prelude.idmef_criteria_destroy(c)
+            return "="
+
+        prelude.idmef_criteria_destroy(c)
+        return "<>*"
 
     def _applyFiltersForCategory(self, criteria, type):
         if not self.parameters[type]:
@@ -799,13 +840,26 @@ class AlertListing(MessageListing, view.View):
         # We apply an AND operator between the different objects.
 
         merge = { }
+        newcrit = ""
         for obj in self.parameters[type]:
-            if merge.has_key(obj[0]):
-                merge[obj[0]] += [ obj ]
+            if obj[0] == "__all__":
+                # We want to lookup the value in our set of predefined path, but also in aggregated
+                # value (which the user can see in the filtered columns).
+                for path in GENERIC_SEARCH_TABLE[type] + self.parameters.get("aggregated_%s" % type):
+                    op = self._getOperatorForPath(path, obj[2])
+                    if op:
+                        if len(newcrit) > 0:
+                            newcrit += " || "
+                        newcrit += self._filterTupleToString((path, op, obj[2]))
             else:
-                merge[obj[0]] =  [ obj ]
+                if merge.has_key(obj[0]):
+                    merge[obj[0]] += [ obj ]
+                else:
+                    merge[obj[0]] =  [ obj ]
+
+        if len(newcrit):
+            newcrit = "(" + newcrit + ")"
 
-        newcrit = ""
         for key in iter(merge):
             if len(newcrit) > 0:
                 newcrit += " && "
@@ -826,6 +880,7 @@ class AlertListing(MessageListing, view.View):
         self._applyFiltersForCategory(criteria, "target")
         self._applyFiltersForCategory(criteria, "analyzer")
 
+        print criteria
 
     def _getMissingAggregatedInfos(self, message, path_value_hash, parameters, criteria2, aggregated_count):
         selection = [ ]
_______________________________________________
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.