diff --git a/NEWS b/NEWS
index 946074d..c0f3a88 100644
--- a/NEWS
+++ b/NEWS
@@ -7,7 +7,7 @@
   as well as message summary (require twisted.names and twisted.internet),
   see the additional dns_max_delay settings parameters in prewikka.conf.
 
-- In the alert summary view, handle portlist and ip_version service fields, 
+- In the alert summary view, handle portlist and ip_version service fields,
   and show alert messageid.
 
 - Fix exception when rendering ToolAlert.
@@ -32,11 +32,11 @@
 
 - Only perform additional database request when using Sensor localtime:
   this bring a performance improvement of about 36% on aggregated query,
-  when using either frontend localtime (the default), or UTC time. 
+  when using either frontend localtime (the default), or UTC time.
 
 - JQuery support: Port most of the javascript code to make use of JQuery.
   Add show/hide effect to CSS popup. More filtering functionality in the
-  SensorListing view.  
+  SensorListing view.
 
 - Cleanup the Authentication class, so that uper Prewikka layer can act
   depending whether the backend support user creation / deletion. Anonymous
@@ -44,7 +44,7 @@
 
 - Better integration of CGI authentication allowing user listing and deletion.
 
-- Report template exception directly to the user.              
+- Report template exception directly to the user.
 
 - Fix exception if an alert analyzer name is empty.
 
@@ -56,11 +56,11 @@
   (which is a minor issue since the user is already authenticated). Thanks
   to Helmut Azbest <helmut.azbest@gmail.com> for the fix.
 
-- Fix a typo making mod_python use the parent method (patch from 
+- Fix a typo making mod_python use the parent method (patch from
   Helmut Azbest <helmut.azbest@gmail.com>).
 
-- In the configuration file, recognize section even if there are whitespace 
-  at the beginning of the line. 
+- In the configuration file, recognize section even if there are whitespace
+  at the beginning of the line.
 
 - Localization fixes, by Sebastien Tricaud <toady@gscore.org>, and
   Bjoern Weiland.
@@ -110,11 +110,11 @@
 
 * 2007-05-26, prewikka-0.9.11.2:
 
-        - In case a database schema upgrade is required, or the Prewikka 
+        - In case a database schema upgrade is required, or the Prewikka
           database does not exist, make the error available from the Prewikka
-          console, rather than exiting badly (which previously required the 
+          console, rather than exiting badly (which previously required the
           user to parse its web server log in order to find out the problem).
-          
+
 
 * 2007-05-25, prewikka-0.9.11.1:
 
@@ -122,90 +122,90 @@
 
 	- Fix incorrect locale switch when accessing certain pages.
 
-	
+
 * 2007-05-21, prewikka-0.9.11:
 
         - Prewikka has been internationalized: user might choose the language
           used in their settings tabs. Additionally, you might specify
           a default locale using the "default_locale" configuration keyword.
 
-        - Brazilian Portuguese translation, by Edelberto Franco Silva<edeunix@edeunix.com>. 
+        - Brazilian Portuguese translation, by Edelberto Franco Silva<edeunix@edeunix.com>.
         - French translation, by Sebastien Tricaud <sebastien@gscore.org>.
         - German translation, by Bjoern Weiland <mail@bjou.de>.
-        - Russian translation, by Valentin Bogdanov <bogdanov.valentin@gmail.com>. 
+        - Russian translation, by Valentin Bogdanov <bogdanov.valentin@gmail.com>.
         - Spanish translation, by Carlo G. Añez M. <carlo.anez@gmail.com>.
 
-        - New powerfull and scalable agent view, grouping agent together by 
-          Location and Node. 
-        
+        - New powerfull and scalable agent view, grouping agent together by
+          Location and Node.
+
         - In the Alert/Heartbeat summary view, number analyzers backward so that
           it reflect the ordering in the analyzer list.
-          
-        - Improved support for resizing menu. 
-        
-        - Fix a konqueror rendering bug with the inline filter. 
+
+        - Improved support for resizing menu.
+
+        - Fix a konqueror rendering bug with the inline filter.
 
         - Various bug fixes.
-        
-        
+
+
 * 2007-04-05, prewikka-0.9.10:
 
-        - Don't show all source and target when they reach a predefined limit, instead 
+        - Don't show all source and target when they reach a predefined limit, instead
           provide an expansion link.
-        
+
         - Add two new view in the Events section: CorrelationAlert and ToolAlert.
-        
-        - Ability to filter and aggregate on all IDMEF path. If the filtered path is 
-          an enumeration, automatically provide the list of possible value. 
-          
-        - Add a combo box for the user to choose which criteria operator to use. 
-        
-        - Provide an enumeration filter for the type of alert (Alert, CorrelationAlert, 
+
+        - Ability to filter and aggregate on all IDMEF path. If the filtered path is
+          an enumeration, automatically provide the list of possible value.
+
+        - Add a combo box for the user to choose which criteria operator to use.
+
+        - Provide an enumeration filter for the type of alert (Alert, CorrelationAlert,
           ToolAlert, OverflowAlert).
-        
+
         - Prewikka can now aggregate by analyzer.
-        
-        - When a session expire and the user login, the user is redirected to the page 
+
+        - When a session expire and the user login, the user is redirected to the page
           he attempted to access when the session expired.
-          
+
         - When an error occur, the default Prewikka layout is now preserved.
-        
-        - Correct handling of empty value for hash key generation. Fix #204. 
-        
-        - Use new libpreludedb function that return the results as well as the number 
-          of results. This avoid using COUNT() in some places (namely, this speedup 
+
+        - Correct handling of empty value for hash key generation. Fix #204.
+
+        - Use new libpreludedb function that return the results as well as the number
+          of results. This avoid using COUNT() in some places (namely, this speedup
           non aggregated view by ~50%).
-          
+
         - Avoid iterating the list of database result more than needed.
-        
+
         - Support IDMEF Action, SNMPService, and WebService class.
-        
+
         - Improved support for small screen resolution.
-        
-        
+
+
 
 * 2007-02-06, prewikka-0.9.9:
 
         - Improve database performance by reducing the number of query. (Paul Robert Marino)
-        
+
         - Activate CleanOutput filtering (lot of escaping fixes).
-      
+
         - More action logging.
-        
+
         - Bug fixes with the error pages Back/Retry buttons.
-          
+
         - Fix error on group by user (#191).
-        
+
         - Fix template compilation error with Cheetah version 2 (#184).
-        
+
 
 * 2006-11-23, prewikka-0.9.8:
-	
+
 	- Save/load user configuration when using CGI authentication mode (#181).
 
 	- Show Prewikka version in the About page (#177).
 
-	- Use Python logging facility (available backend: stderr, file, smtp, syslog), 
+	- Use Python logging facility (available backend: stderr, file, smtp, syslog),
 	  multiple simultaneous handler supported (#113).
 
 	- Fix anonymous authentication.
@@ -222,7 +222,7 @@
 
 
 * 2006-08-18, prewikka-0.9.7.1:
-	
+
 	- Fix filter interface bug introduced in 0.9.7.
 
 	- Improved error reporting on filter creation.
@@ -232,24 +232,24 @@
 
 * 2006-08-16, prewikka-0.9.7:
 
-	- Use preludedb_delete_(alert|heartbeat)_from_list(). Require 
-	  libpreludedb 0.9.9. Provide a deletion performance improvement 
+	- Use preludedb_delete_(alert|heartbeat)_from_list(). Require
+	  libpreludedb 0.9.9. Provide a deletion performance improvement
 	  of around 3000%.
 
-	- Handle multiple listed source/target properly. Separate 
+	- Handle multiple listed source/target properly. Separate
 	  source/target in the message listing.
 
 	- Make host command/Information link available from the Sensor
 	  listing.
 
-	- Always take care of the "external_link_new_window" configuration 
-	  parameter. 
-	  
-	- Make external command handling more generic. Allow to specify 
+	- Always take care of the "external_link_new_window" configuration
+	  parameter.
+
+	- Make external command handling more generic. Allow to specify
 	  command line arguments.
 
-	- Allow to define unlimited number of external commands rather than 
-	  only a defined subset (fix #134). 
+	- Allow to define unlimited number of external commands rather than
+	  only a defined subset (fix #134).
 
 	- Avoid toggling several popup at once in the HeartbeatListing.
 
@@ -257,7 +257,7 @@
 
 	- New address and node name lookup provided through prelude-ids.com service.
 
-	- Link to new prelude-ids.com port lookup instead of broken portsdb 
+	- Link to new prelude-ids.com port lookup instead of broken portsdb
           database (fix #162).
 
 	- Various bug fixes.
@@ -271,7 +271,7 @@
 
 	- Show multiple source/target in message listing/summary.
 
-	- Fix invalid use of socket.inet_ntoa() to read ICMP Gateway Address, 
+	- Fix invalid use of socket.inet_ntoa() to read ICMP Gateway Address,
 	  which is stored as string (#156).
 
 	- Fix aggregation on IDMEF-Path that are not string.
@@ -299,7 +299,7 @@
 	- Intelligent display for CorrelationAlert. Include correlated
 	  alert information in the alert listing.
 
-	- Intelligent printing of Network centric information. 
+	- Intelligent printing of Network centric information.
 
 	- Fix Cheetah compilation for the heartbeat page.
 
@@ -319,20 +319,20 @@
 	- Distribute SQLite schema.
 
 	- Fix exception in the heartbeat analysis view when the heartbeat_count
-	  or heartbeat_error_margin settings are explicitly set (#124). 
+	  or heartbeat_error_margin settings are explicitly set (#124).
 
-	- Fix Cheetah 1.0 heartbeat listing exception (#119). 
+	- Fix Cheetah 1.0 heartbeat listing exception (#119).
 
 	- Open external link in new windows by default. Add a configuration option
 	  to disable opening external link in new window (#61).
 
-	- Provide the ability to specify the configuration file that Prewikka 
+	- Provide the ability to specify the configuration file that Prewikka
 	  use (#117).
 
 	- Sanitize the limit parameter in case the input value is not correct
-	  instead of triggering an exception (#118). 
+	  instead of triggering an exception (#118).
 
-	- Handle the preludeDB "file" setting (for use with SQLite like database). 
+	- Handle the preludeDB "file" setting (for use with SQLite like database).
 
 	- Fix filter saving issue in the heartbeat listing.
 
@@ -348,24 +348,24 @@
 
 	- Add an "Unlimited" timeline option.
 
-	- Fix classification escaping problem that could lead to empty 
+	- Fix classification escaping problem that could lead to empty
 	  listing when unwiding alert with classification text containing backslash.
 
-	- Don't print un-necessary separator when the protocol field is 
+	- Don't print un-necessary separator when the protocol field is
 	  empty in the alert listing.
 
-	- Improve Correlation Alert display. Allow focus both on the Correlation Alert 
+	- Improve Correlation Alert display. Allow focus both on the Correlation Alert
 	  summary and on the correlated alert listing.
 
-	- Don't propagate the "save" parameter, so that the user don't end up saving 
-	  settings without knowing about it. 
+	- Don't propagate the "save" parameter, so that the user don't end up saving
+	  settings without knowing about it.
 
 
 * 2005-11-30, prewikka-0.9.1:
 
-	- Resolve the protocol number from the message summary view. 
+	- Resolve the protocol number from the message summary view.
 
-	- Separate port and protocol value, so that we don't end up 
+	- Separate port and protocol value, so that we don't end up
 	  linking the protocol to portdb if there is no port.
 
 	- Ability to setup IDMEF filter using iana_protocol_name and iana_protocol_number.
@@ -373,9 +373,9 @@
 	- Sanitize timeline years value on system which does not support time
 	  exceeding 2^31-1. Fix #104.
 
-	- Mark CorrelationAlert explicitly in the AlertListing. 
+	- Mark CorrelationAlert explicitly in the AlertListing.
 
-	- Make inline filter mark more visible. 
+	- Make inline filter mark more visible.
 
 	- Ability for the user to save settings for the current view.
 
@@ -384,7 +384,7 @@
 	- Fix a bug where clicking the IP address popup would cause
 	  Firefox to go back to the top of the page. Fix #112.
 
-	- Don't hardcode path to /usr/bin/python, but resort to 
+	- Don't hardcode path to /usr/bin/python, but resort to
 	  /usr/bin/env to find it.
 
 
@@ -394,7 +394,7 @@
 
 	- Minor rendering fix.
 
-	- Handle service.iana_protocol_name / service.iana_protocol_number 
+	- Handle service.iana_protocol_name / service.iana_protocol_number
 	  as well as service.protocol.
 
 
@@ -436,7 +436,7 @@
 
 	- Show target file in the message listing.
 
-	- Much more information in the alert summary view. 
+	- Much more information in the alert summary view.
 	  Especially useful for users of integrity checker.
 
 
@@ -488,7 +488,7 @@
 	- XHTML conformance in most of the code.
 
 	- Fix possible exception with filtered classification text.
-	
+
 	- Allow filtering on heartbeat.analyzer.name.
 
 
@@ -503,19 +503,19 @@
 	  Fix Javascript warnings. Correct URL escaping. Make it work
 	  better in Apple's Safari browser.
 
-	- More error checking when saving custom filter. Error out in case a 
+	- More error checking when saving custom filter. Error out in case a
 	  filter reference non existing criteria. Add the substr operator.
 
-	- Fix bug in the whole alert/heartbeat navigation system, simplify 
-	  and cleanup the code, always report the current filtered field 'action' to 
+	- Fix bug in the whole alert/heartbeat navigation system, simplify
+	  and cleanup the code, always report the current filtered field 'action' to
 	  the user.
 
-	- Make the mouse pointer behave like it does for javascript links on Alert 
+	- Make the mouse pointer behave like it does for javascript links on Alert
 	  listing table head.
 
-	- Fix alert mixup when expanding an aggregated classification with different 
+	- Fix alert mixup when expanding an aggregated classification with different
 	  severity.
-	
+
 	- Fix low/mid/high/none severity filtering.
 
 	- Fix a bug where agents with multiple address would disappear.
@@ -530,8 +530,8 @@
 	- Add an heartbeat_error_margin configuration keyword.
 
 	- Saving modification to an existing filter now work.
-	
-	- Make prewikka.cgi catch exceptions that are raised during the prewikka 
+
+	- Make prewikka.cgi catch exceptions that are raised during the prewikka
 	  initialization step and display an error screen to the user instead of
 	  a server internal error.
 
@@ -565,7 +565,7 @@
 	- Update Auth cookie expiration time.
 
 	- Fix escaping issue.
-	
+
 
 * 2005-04-05, prewikka-0.9.0-rc4:
 
@@ -581,8 +581,8 @@
           login for no appearent reasons.
 
 	- Set default session expiration time to 60 minutes.
-	
-	
+
+
 * 2005-03-31, prewikka-0.9.0-rc3:
 
 	- Installation cleanup / bugfix.
diff --git a/prewikka/IDMEFDatabase.py b/prewikka/IDMEFDatabase.py
index 83be2c2..25c6e88 100644
--- a/prewikka/IDMEFDatabase.py
+++ b/prewikka/IDMEFDatabase.py
@@ -36,7 +36,7 @@ def escape_value(value):
 class IDMEFTime(object):
     def __init__(self, res):
         self._res = res
-        
+
     def __del__(self):
         idmef_time_destroy(self._res)
 
@@ -45,13 +45,13 @@ class IDMEFTime(object):
 
     def __int__(self):
         return idmef_time_get_sec(self._res)
-                
+
     def __float__(self):
         return float(idmef_time_get_sec(self._res)) + float(idmef_time_get_usec(self._res)) / 10 ** 6
-        
+
     def toYMDHMS(self):
         return time_to_ymdhms(time.localtime(idmef_time_get_sec(self._res)))
-        
+
     def __getattribute__(self, name):
         if name is "sec":
             return idmef_time_get_sec(self._res)
@@ -98,14 +98,14 @@ def convert_idmef_value(value):
     except KeyError:
         return None
 
-    
-        
+
+
 class Message:
     def __init__(self, res, htmlsafe):
         self._res = res
         self._value_list = None
         self._htmlsafe = htmlsafe
-        
+
     def __del__(self):
         idmef_message_destroy(self._res)
 
@@ -115,7 +115,7 @@ class Message:
     def __iter__(self):
         if not self._value_list:
             raise TypeError, "iteration over a non-sequence"
-        
+
         self._list_iterator = 0
         return self
 
@@ -124,7 +124,7 @@ class Message:
             return idmef_value_get_count(self._value_list)
 
         return 1
-    
+
     def next(self):
         next = idmef_value_get_nth(self._value_list, self._list_iterate)
         if not next:
@@ -132,7 +132,7 @@ class Message:
 
         value = self._convert_value(next, self._root + "(%d)" % self._list_iterate)
         self._list_iterate += 1
-        
+
         return value
 
     def _convert_value(self, idmef_value, key):
@@ -143,33 +143,33 @@ class Message:
             value._value_list = idmef_value
             if self._value_list:
                 idmef_value_ref(idmef_value)
-                
+
         elif idmef_value_get_type(idmef_value) != IDMEF_VALUE_TYPE_CLASS:
             value = convert_idmef_value(idmef_value)
             if not self._value_list:
                 idmef_value_destroy(idmef_value)
-            
+
         else:
             if not self._value_list:
                 idmef_value_destroy(idmef_value)
-                
+
             value = Message(idmef_message_ref(self._res), self._htmlsafe)
             value._root = key
 
         return value
-    
+
     def _get_raw_value(self, key):
         path = idmef_path_new_fast(key)
         idmef_value = idmef_path_get(path, self._res)
-        
+
         if idmef_value:
             ret = self._convert_value(idmef_value, key)
         else:
-            if idmef_path_is_list(path, -1):
+            if idmef_path_is_ambiguous(path):
                 ret = []
             else:
                 ret = None
-            
+
         idmef_path_destroy(path)
         return ret
 
@@ -181,7 +181,7 @@ class Message:
             return escape_value(self._get_raw_value(key))
         else:
             return self._get_raw_value(key)
-             
+
     def match(self, criteria):
         if type(criteria) is list:
             criteria = " && ".join(criteria)
@@ -192,18 +192,18 @@ class Message:
 
         return ret
 
-    def get(self, key, default=None, htmlsafe=None):     
+    def get(self, key, default=None, htmlsafe=None):
         if htmlsafe != None:
             htmlsafe_bkp = self._htmlsafe
             self._htmlsafe = htmlsafe
-            
-        val = self[key] 
+
+        val = self[key]
         if val == None:
                 val = default
-        
+
         if htmlsafe != None:
             self._htmlsafe = htmlsafe_bkp
-        
+
         return val
 
     def getAdditionalData(self, searched, many_values=False):
@@ -213,13 +213,13 @@ class Message:
             meaning = self["%s.additional_data(%d).meaning" % (self._root, i)]
             if meaning is None:
                 break
-            
+
             if meaning == searched:
                 value = self["%s.additional_data(%d).data" % (self._root, i)]
-                
+
                 if not many_values:
                     return value
-                
+
                 values.append(value)
 
             i += 1
@@ -252,35 +252,35 @@ class DbResult:
         self._rows = [ ]
         self._has_cache = False
         self._res, self._len = results
-        
+
     def __iter__(self):
         if self._has_cache:
             return iter(self._rows)
         else:
             return self
-        
+
     def __len__(self):
         return self._len
-       
+
     def __del__(self):
         if self._res:
             self._db_delete(self._res)
-        
+
     def __getitem__(self, key):
         if isinstance(key, types.SliceType):
             start, stop, step = key.start, key.stop, key.step
             index = start + stop
         else:
             index = key
-        
+
         if not self._has_cache:
             for r in self:
                 if len(self._rows) >= index:
                     break
-                
+
         return self._rows[key]
-        
-    def next(self):        
+
+    def next(self):
         if self._res == None:
             raise StopIteration
 
@@ -292,26 +292,26 @@ class DbResult:
             raise StopIteration
 
         row = self._db_convert_row(values)
-       
+
         self._rows.append(row)
         return row
-            
+
 
 class DbResultValues(DbResult):
     def __init__(self, selection, results):
         self._selection = selection
         DbResult.__init__(self, results)
-                
+
     def _db_get_next(self):
         return preludedb_result_values_get_next(self._res)
-        
+
     def _db_delete(self, result):
         if self._selection:
             preludedb_path_selection_destroy(self._selection)
-            
+
         if result:
             preludedb_result_values_destroy(result)
-            
+
     def _db_convert_row(self, values):
         row = []
         for value in values:
@@ -319,25 +319,25 @@ class DbResultValues(DbResult):
                row.append(None)
            else:
                row.append(convert_idmef_value(value))
-               idmef_value_destroy(value)      
-               
+               idmef_value_destroy(value)
+
         return row
-        
+
 class DbResultIdents(DbResult):
     def _db_get_next(self):
         return preludedb_result_idents_get_next(self._res)
-        
+
     def _db_delete(self, result):
         if result:
             preludedb_result_idents_destroy(result)
-                    
+
     def _db_convert_row(self, value):
         return value
 
 class IDMEFDatabase:
     _db_destroy = preludedb_destroy
     _db = None
-    
+
     def __init__(self, config):
         settings = preludedb_sql_settings_new()
         for param in "file", "host", "port", "name", "user", "pass":
@@ -360,44 +360,44 @@ class IDMEFDatabase:
                 raise "libpreludedb %s or higher is required (%s found)." % (wanted_version, cur)
             else:
                 raise "libpreludedb %s or higher is required." % wanted_version
-        
+
         self._db = preludedb_new(sql, None)
 
     def __del__(self):
         if self._db:
             self._db_destroy(self._db)
-            
+
     def _getMessageIdents(self, get_message_idents, criteria, limit, offset, order_by):
         if type(criteria) is list:
             if len(criteria) == 0:
                 criteria = None
             else:
                 criteria = " && ".join(criteria)
-                
+
         if criteria:
             criteria = idmef_criteria_new_from_string(criteria)
 
         idents = [ ]
-    
+
         if order_by == "time_asc":
             order_by = PRELUDEDB_RESULT_IDENTS_ORDER_BY_CREATE_TIME_ASC
         else:
             order_by = PRELUDEDB_RESULT_IDENTS_ORDER_BY_CREATE_TIME_DESC
-            
-        try:    
+
+        try:
             result = get_message_idents(self._db, criteria, limit, offset, order_by)
         except:
             self._freeDbParams(criteria=criteria)
             raise
-                    
+
         if criteria:
             idmef_criteria_destroy(criteria)
-        
+
         if not result:
-            return [ ]            
-        
+            return [ ]
+
         return DbResultIdents(result)
-        
+
     def getAlertIdents(self, criteria=None, limit=-1, offset=-1, order_by="time_desc"):
         return self._getMessageIdents(preludedb_get_alert_idents2, criteria, limit, offset, order_by)
 
@@ -406,17 +406,20 @@ class IDMEFDatabase:
 
     def _getLastMessageIdent(self, type, get_message_idents, analyzerid):
         criteria = None
-        if analyzerid != None:
-            criteria = "%s.analyzer(-1).analyzerid == '%s'" % (type, str(analyzerid))
+        if analyzerid is not False:
+            if analyzerid is None:
+                criteria = "! %s.analyzer(-1).analyzerid" % (type)
+            else:
+                criteria = "%s.analyzer(-1).analyzerid == '%s'" % (type, str(analyzerid))
 
         idents = get_message_idents(criteria, limit=1)
 
         return idents[0]
 
-    def getLastAlertIdent(self, analyzer=None):
+    def getLastAlertIdent(self, analyzer=False):
         return self._getLastMessageIdent("alert", self.getAlertIdents, analyzer)
 
-    def getLastHeartbeatIdent(self, analyzer=None):
+    def getLastHeartbeatIdent(self, analyzer=False):
         return self._getLastMessageIdent("heartbeat", self.getHeartbeatIdents, analyzer)
 
     def getAlert(self, ident, htmlsafe=False):
@@ -442,20 +445,20 @@ class IDMEFDatabase:
     def _freeDbParams(self, selection=None, criteria=None):
         if selection:
             preludedb_path_selection_destroy(selection)
-        
+
         if criteria:
             idmef_criteria_destroy(criteria)
-            
+
     def getValues(self, selection, criteria=None, distinct=0, limit=-1, offset=-1):
         if type(criteria) is list:
             if len(criteria) == 0:
                 criteria = None
             else:
                 criteria = " && ".join([ "(" + c + ")" for c in criteria ])
-                            
+
         if criteria:
             criteria = idmef_criteria_new_from_string(criteria)
-            
+
         my_selection = preludedb_path_selection_new()
         for selected in selection:
             my_selected = preludedb_selected_path_new_string(selected)
@@ -466,19 +469,19 @@ class IDMEFDatabase:
         except:
             self._freeDbParams(my_selection, criteria)
             raise
-            
+
         if criteria:
-            idmef_criteria_destroy(criteria)       
-        
+            idmef_criteria_destroy(criteria)
+
         if not result:
             preludedb_path_selection_destroy(my_selection)
             return [ ]
-            
+
         return DbResultValues(my_selection, result)
-        
+
     def _countMessages(self, root, criteria):
         return self.getValues(["count(%s.create_time)" % root], criteria)[0][0]
-        
+
     def countAlerts(self, criteria=None):
         return self._countMessages("alert", criteria)
 
@@ -511,40 +514,31 @@ class IDMEFDatabase:
                 index += 1
             analyzer_paths.append(path)
 
-        return analyzer_paths            
+        return analyzer_paths
 
     def getAnalyzer(self, analyzerid):
         ident = self.getLastHeartbeatIdent(analyzerid)
         heartbeat = self.getHeartbeat(ident)
 
-        index = 0
-        while True:
-            if not heartbeat["heartbeat.analyzer(%d).name" % (index + 1)]:
-                break
-            index += 1
-
-        analyzer = { }
-        analyzer["analyzerid"] = analyzerid
-        analyzer["name"] = heartbeat.get("heartbeat.analyzer(%d).name" % index)
-        analyzer["model"] = heartbeat.get("heartbeat.analyzer(%d).model" % index) 
-        analyzer["version"] = heartbeat.get("heartbeat.analyzer(%d).version" % index)
-        analyzer["class"] = heartbeat.get("heartbeat.analyzer(%d).class" % index)
-        analyzer["ostype"] = heartbeat.get("heartbeat.analyzer(%d).ostype" % index)
-        analyzer["osversion"] = heartbeat.get("heartbeat.analyzer(%d).osversion" % index)
-        analyzer["node_name"] = heartbeat.get("heartbeat.analyzer(%d).node.name" % index)
-        analyzer["node_location"] = heartbeat.get("heartbeat.analyzer(%d).node.location" % index)
-                
-        i = 0
-        analyzer["node_addresses"] = [ ]
-        while True:
-            address = heartbeat.get("heartbeat.analyzer(%d).node.address(%d).address" % (index, i))
-            if not address:
-                break
-            analyzer["node_addresses"].append(address)
-            i += 1
-        
-        analyzer["last_heartbeat_time"] = heartbeat.get("heartbeat.create_time")
-        analyzer["last_heartbeat_interval"] = heartbeat["heartbeat.heartbeat_interval"]
-        analyzer["last_heartbeat_status"] = heartbeat.getAdditionalData("Analyzer status")
-        
-        return analyzer
+        path = []
+        analyzer = {}
+        analyzerd = { "path": path, "node_addresses": [], "node_name": None, "node_location": None }
+
+        for a in heartbeat["analyzer"]:
+            path.append(a["analyzerid"])
+            analyzer = a
+
+        for column in "analyzerid", "name", "model", "version", "class", "ostype", "osversion":
+            analyzerd[column] = analyzer.get(column, None)
+
+        analyzerd["node_name"] = analyzer.get("node.name")
+        analyzerd["node_location"] = analyzer.get("node.location")
+
+        for addr in analyzer.get("node.address.address", []):
+            analyzerd["node_addresses"].append(addr)
+
+        analyzerd["last_heartbeat_time"] = heartbeat.get("heartbeat.create_time")
+        analyzerd["last_heartbeat_interval"] = heartbeat.get("heartbeat.heartbeat_interval")
+        analyzerd["last_heartbeat_status"] = heartbeat.getAdditionalData("Analyzer status")
+
+        return analyzerd
diff --git a/prewikka/templates/SensorListing.tmpl b/prewikka/templates/SensorListing.tmpl
index 069ed77..fbf804e 100644
--- a/prewikka/templates/SensorListing.tmpl
+++ b/prewikka/templates/SensorListing.tmpl
@@ -24,8 +24,8 @@
   });
 
   \$(".fieldset_toggle2").click(function(){
-	\$(this).prev().find(".fieldset_toggle").click();
-	return false;
+        \$(this).prev().find(".fieldset_toggle").click();
+        return false;
   });
 
   \$("td.offline, td.online, td.missing, td.unknown").click(function(){
diff --git a/prewikka/templates/utils.tmpl b/prewikka/templates/utils.tmpl
index d6b9a82..01b2b50 100644
--- a/prewikka/templates/utils.tmpl
+++ b/prewikka/templates/utils.tmpl
@@ -13,7 +13,7 @@
     <tbody>
       <tr class="table_row_even">
         <td>#echo $analyzer.name or "n/a" #</td>
-	<td>
+        <td>
           #if $analyzer.model
             $analyzer.model
             #if $analyzer.version
@@ -23,7 +23,7 @@
             n/a
           #end if
         </td>
-	<td>
+        <td>
           #if $analyzer.ostype
             $analyzer.ostype
             #if $analyzer.osversion
@@ -33,9 +33,9 @@
             n/a
           #end if
         </td>
-	<td>#echo $analyzer.node_name or "n/a" #</td>
+        <td>#echo $analyzer.node_name or "n/a" #</td>
         <td>#echo $analyzer.node_location or "n/a" #</td>
-	<td>
+        <td>
           #if len($analyzer.node_addresses) > 0
             #for $address in $analyzer.node_addresses
               $address<br/>
@@ -43,7 +43,7 @@
           #else
             n/a
           #end if
-	</td>
+        </td>
       </tr>
     </tbody>
   </table>
diff --git a/prewikka/views/sensor.py b/prewikka/views/sensor.py
index 1fa1378..4236da7 100644
--- a/prewikka/views/sensor.py
+++ b/prewikka/views/sensor.py
@@ -55,29 +55,29 @@ def get_analyzer_status_from_latest_heartbeat(heartbeat_status, heartbeat_time,
 
     if time.time() - int(heartbeat_time) > int(heartbeat_interval) + error_margin:
         return "missing", _("Missing")
-    
+
     return "online", _("Online")
 
 
 def analyzer_cmp(x, y):
     xmiss = x["status"] == "missing"
     ymiss = y["status"] == "missing"
-    
+
     if xmiss and ymiss:
         return cmp(x["name"], y["name"])
-        
+
     elif xmiss or ymiss:
         return ymiss - xmiss
-        
+
     else:
         return cmp(x["name"], y["name"])
-        
+
 def node_cmp(x, y):
     xmiss = x["missing"]
     ymiss = y["missing"]
-    
+
     if xmiss or ymiss:
-        return ymiss - xmiss        
+        return ymiss - xmiss
     else:
         return cmp(x["node_name"], y["node_name"])
 
@@ -98,8 +98,7 @@ class SensorListing(view.View):
     def init(self, env):
         self._heartbeat_count = int(env.config.general.getOptionValue("heartbeat_count", 30))
         self._heartbeat_error_margin = int(env.config.general.getOptionValue("heartbeat_error_margin", 3))
-    
-        
+
     def render(self):
         analyzers = { }
 
@@ -110,11 +109,10 @@ class SensorListing(view.View):
 
         locations = { }
         nodes = { }
-        
-        for analyzer_path in self.env.idmef_db.getAnalyzerPaths():
-            analyzerid = analyzer_path[-1]          
+
+        for analyzerid in self.env.idmef_db.getAnalyzerids():
             analyzer = self.env.idmef_db.getAnalyzer(analyzerid)
-            
+
             parameters = { "analyzerid": analyzer["analyzerid"] }
             analyzer["alert_listing"] = utils.create_link("sensor_alert_listing", parameters)
             analyzer["heartbeat_listing"] = utils.create_link("sensor_heartbeat_listing", parameters)
@@ -124,17 +122,17 @@ class SensorListing(view.View):
                 analyzer["node_name_link"] = utils.create_link(self.view_name,
                                                                { "filter_path": "heartbeat.analyzer(-1).node.name",
                                                                  "filter_value": analyzer["node_name"] })
-                 
+
             if analyzer["node_location"]:
                 analyzer["node_location_link"] = utils.create_link(self.view_name,
                                                                    { "filter_path": "heartbeat.analyzer(-1).node.location",
                                                                      "filter_value": analyzer["node_location"] })
-                
+
             node_key = ""
             for i in range(len(analyzer["node_addresses"])):
                 addr = analyzer["node_addresses"][i]
                 node_key += addr
-                
+
                 analyzer["node_addresses"][i] = {}
                 analyzer["node_addresses"][i]["value"] = addr
                 analyzer["node_addresses"][i]["inline_filter"] = utils.create_link(self.view_name,
@@ -147,7 +145,7 @@ class SensorListing(view.View):
                                                                            utils.create_link("Command",
                                                                                              { "origin": self.view_name,
                                                                                                "command": command, "host": addr })))
-            
+
             analyzer["status"], analyzer["status_meaning"] = \
                                 get_analyzer_status_from_latest_heartbeat(analyzer["last_heartbeat_status"],
                                                                           analyzer["last_heartbeat_time"],
@@ -156,15 +154,15 @@ class SensorListing(view.View):
 
             analyzer["last_heartbeat_time"] = utils.time_to_ymdhms(time.localtime(int(analyzer["last_heartbeat_time"]))) + \
                                               " %+.2d:%.2d" % utils.get_gmt_offset()
-       
+
             node_location = analyzer["node_location"] or _("Node location n/a")
             node_name = analyzer.get("node_name") or _("Node name n/a")
             osversion = analyzer["osversion"] or _("OS version n/a")
             ostype = analyzer["ostype"] or _("OS type n/a")
             addresses = analyzer["node_addresses"]
-            
+
             node_key = node_name + osversion + ostype
-            
+
             if not locations.has_key(node_location):
                 locations[node_location] = { "total": 1, "missing": 0, "unknown": 0, "offline": 0, "online": 0, "nodes": { } }
             else:
@@ -174,11 +172,11 @@ class SensorListing(view.View):
                 locations[node_location]["nodes"][node_key] = { "total": 1, "missing": 0, "unknown": 0, "offline": 0, "online": 0,
                                                                 "analyzers": [ ],
                                                                 "node_name": node_name, "node_location": node_location,
-                                                                "ostype": ostype, "osversion": osversion, 
+                                                                "ostype": ostype, "osversion": osversion,
                                                                 "node_addresses": addresses, "node_key": node_key }
             else:
                 locations[node_location]["nodes"][node_key]["total"] += 1
-                  
+
             status = analyzer["status"]
             locations[node_location][status] += 1
             locations[node_location]["nodes"][node_key][status] += 1
@@ -187,9 +185,9 @@ class SensorListing(view.View):
                 locations[node_location]["nodes"][node_key]["analyzers"].insert(0, analyzer)
             else:
                 locations[node_location]["nodes"][node_key]["analyzers"].append(analyzer)
-                
+
         self.dataset["locations"] = locations
-        
+
 
 class SensorMessagesDelete(SensorListing):
     view_name = "sensor_messages_delete"
@@ -205,7 +203,7 @@ class SensorMessagesDelete(SensorListing):
             if self.parameters.has_key("heartbeats"):
                 criteria = "heartbeat.analyzer(-1).analyzerid == %d" % long(analyzerid)
                 self.env.idmef_db.deleteHeartbeat(self.env.idmef_db.getHeartbeatIdents(criteria))
-            
+
         SensorListing.render(self)
 
 
@@ -219,16 +217,16 @@ class HeartbeatAnalyze(view.View):
     def init(self, env):
         self._heartbeat_count = int(env.config.general.getOptionValue("heartbeat_count", 30))
         self._heartbeat_error_margin = int(env.config.general.getOptionValue("heartbeat_error_margin", 3))
-    
+
     def render(self):
         analyzerid = self.parameters["analyzerid"]
-        
+
         analyzer = self.env.idmef_db.getAnalyzer(analyzerid)
         analyzer["last_heartbeat_time"] = str(analyzer["last_heartbeat_time"])
         analyzer["events"] = [ ]
         analyzer["status"] = "abnormal_offline"
         analyzer["status_meaning"] = "abnormal offline"
-        
+
         start = time.time()
         idents = self.env.idmef_db.getHeartbeatIdents(criteria="heartbeat.analyzer(-1).analyzerid == %d" % analyzerid,
                                                       limit=self._heartbeat_count)
@@ -254,7 +252,7 @@ class HeartbeatAnalyze(view.View):
                     analyzer["events"].append({ "value": "sensor is down since %s" % older_time, "type": "down"})
             if newer:
                 event = None
-                
+
                 if newer_status == "starting":
                     if older_status == "exiting":
                         event = { "value": "normal sensor start at %s" % str(newer_time),
@@ -267,7 +265,7 @@ class HeartbeatAnalyze(view.View):
                     if abs(int(newer_time) - int(older_time) - int(older_interval)) > self._heartbeat_error_margin:
                         event = { "value": "abnormal heartbeat interval between %s and %s" % (str(older_time), str(newer_time)),
                                   "type": "abnormal_heartbeat_interval" }
-                                  
+
 
                 if newer_status == "exiting":
                     event = { "value": "normal sensor stop at %s" % str(newer_time),
