Index: /extensions/GrumPluginClasses/admin.php
===================================================================
--- /extensions/GrumPluginClasses/admin.php	(revision 16457)
+++ /extensions/GrumPluginClasses/admin.php	(revision 16458)
@@ -4,6 +4,5 @@
   Author     : Grum
     email    : grum@piwigo.org
-    website  : http://photos.grum.fr
-    PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+    website  : http://www.grum.fr
 
     << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/classes/CommonPlugin.class.inc.php
===================================================================
--- /extensions/GrumPluginClasses/classes/CommonPlugin.class.inc.php	(revision 16457)
+++ /extensions/GrumPluginClasses/classes/CommonPlugin.class.inc.php	(revision 16458)
@@ -9,6 +9,5 @@
   Author     : Grum
     email    : grum@piwigo.org
-    website  : http://photos.grum.fr
-    PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+    website  : http://www.grum.fr
 
     << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/classes/GPCCss.class.inc.php
===================================================================
--- /extensions/GrumPluginClasses/classes/GPCCss.class.inc.php	(revision 16457)
+++ /extensions/GrumPluginClasses/classes/GPCCss.class.inc.php	(revision 16458)
@@ -10,6 +10,5 @@
   Author     : Grum
     email    : grum@piwigo.org
-    website  : http://photos.grum.fr
-    PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+    website  : http://www.grum.fr
 
     << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php
===================================================================
--- /extensions/GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php	(revision 16457)
+++ /extensions/GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php	(revision 16458)
@@ -9,6 +9,5 @@
   Author     : Grum
     email    : grum@piwigo.org
-    website  : http://photos.grum.com
-    PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+    website  : http://www.grum.fr
 
     << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/classes/GPCUserAgent.class.inc.php
===================================================================
--- /extensions/GrumPluginClasses/classes/GPCUserAgent.class.inc.php	(revision 16457)
+++ /extensions/GrumPluginClasses/classes/GPCUserAgent.class.inc.php	(revision 16458)
@@ -5,4 +5,22 @@
 class GPCUserAgent
 {
+  /**
+   * parse a user agent string and return an array of normalized informations
+   *
+   * returned:
+   *  array(
+   *    'os'               => (integer)
+   *    'os_version'       => (string)
+   *    'browser'          => (integer)
+   *    'browser_name'     => (string)
+   *    'browser_type'     => (integer)
+   *    'browser_version'  => (string)
+   *    'engine'           => (integer)
+   *    'engine_version'   => (string)
+   *  )
+   *
+   * @param String $userAgent
+   * @return Array
+   */
   static public function parse($userAgent)
   {
@@ -10,39 +28,97 @@
 
     $returned=array(
-      'os' => '',
-      'os_version' => '',
-
-      'browser' => '',
-      'browser_name' => '',
-      'browser_type' => '',
-      'browser_version' => '',
-
-      'engine' => '',
-      'engine_version' => ''
+      UA_DATA_OS              => UA_OS_UNKNOWN,
+      UA_DATA_OS_VERSION      => '',
+
+      UA_DATA_BROWSER         => UA_BOT_UNKNOWN,
+      UA_DATA_BROWSER_NAME    => '',
+      UA_DATA_BROWSER_TYPE    => UA_PROP_TYPE_UNKNOWN,
+      UA_DATA_BROWSER_VERSION => '',
+
+      UA_DATA_ENGINE          => UA_ENGINE_UNKNOWN,
+      UA_DATA_ENGINE_VERSION  => ''
     );
 
     $bot=self::getBot($userAgent);
-    if($bot['crawler']!=='')
-    {
-      $returned['browser']=$bot['crawler'];
-      $returned['browser_name']=$bot['name'];
-      $returned['browser_type']=UA_PROP_TYPE_CRAWLER;
-      $returned['browser_version']=str_replace(array(';', '(', ')'), array('', '', ''), $bot['version']);
+    if($bot[UA_DATA_BROWSER]!=='')
+    {
+      $returned[UA_DATA_BROWSER]=$bot[UA_DATA_BROWSER];
+      $returned[UA_DATA_BROWSER_TYPE]=UA_BROWSER_TYPE_CRAWLER;
+      $returned[UA_DATA_BROWSER_VERSION]=str_replace(array(';', '(', ')'), array('', '', ''), $bot[UA_DATA_BROWSER_VERSION]);
       return($returned);
     }
 
     $tmp=self::getBrowser($userAgent);
-    $returned['browser']=$tmp['browser'];
-    $returned['browser_name']=$tmp['name'];
-    $returned['browser_type']=$UA_BrowserInfo[UA_DATA_BROWSER][$tmp['browser']][UA_PROP_TYPE];
-    $returned['browser_version']=str_replace(array(';', '(', ')'), array('', '', ''), $tmp['version']);
+    $returned[UA_DATA_BROWSER]=$tmp[UA_DATA_BROWSER];
+    $returned[UA_DATA_BROWSER_TYPE]=$UA_BrowserInfo[UA_DATA_BROWSER][$tmp[UA_DATA_BROWSER]][UA_PROP_TYPE];
+    $returned[UA_DATA_BROWSER_VERSION]=str_replace(array(';', '(', ')'), array('', '', ''), $tmp[UA_DATA_BROWSER_VERSION]);
 
     $tmp=self::getOs($userAgent);
-    $returned['os']=$tmp['os'];
-    $returned['os_version']=str_replace(array(';', '(', ')'), array('', '', ''), $tmp['version']);
+    $returned[UA_DATA_OS]=$tmp[UA_DATA_OS];
+    $returned[UA_DATA_OS_VERSION]=str_replace(array(';', '(', ')'), array('', '', ''), $tmp[UA_DATA_OS_VERSION]);
 
     $tmp=self::getEngine($userAgent);
-    $returned['engine']=$tmp['engine'];
-    $returned['engine_version']=str_replace(array(';', '(', ')'), array('', '', ''), $tmp['version']);
+    $returned[UA_DATA_ENGINE]=$tmp[UA_DATA_ENGINE];
+    $returned[UA_DATA_ENGINE_VERSION]=str_replace(array(';', '(', ')'), array('', '', ''), $tmp[UA_DATA_ENGINE_VERSION]);
+
+    // explicit OS for mobile device override the browser type
+    if($returned[UA_DATA_OS]==UA_OS_BLACKBERRY or
+        $returned[UA_DATA_OS]==UA_OS_SYMBIAN_OS or
+        $returned[UA_DATA_OS]==UA_OS_SYMBOS or
+        $returned[UA_DATA_OS]==UA_OS_ANDROID or
+        $returned[UA_DATA_OS]==UA_OS_IOS) $returned[UA_DATA_BROWSER_TYPE]=UA_BROWSER_TYPE_MOBILE;
+
+    // explicit OS for console device override the browser type
+    if($returned[UA_DATA_OS]==UA_OS_NINTENDO_DS or
+        $returned[UA_DATA_OS]==UA_OS_NINTENDO_WII or
+        $returned[UA_DATA_OS]==UA_OS_SONY_PS3 or
+        $returned[UA_DATA_OS]==UA_OS_SONY_PSP) $returned[UA_DATA_BROWSER_TYPE]=UA_BROWSER_TYPE_CONSOLE;
+
+    return($returned);
+  }
+
+
+  /**
+   * from a user agent array properties, return an array completed with associated
+   * properties
+   *
+   * @param Array $userAgent
+   * @return Array
+   */
+  static public function getProperties($userAgent)
+  {
+    global $UA_BrowserInfo;
+
+    $returned=array();
+    if(isset($userAgent[UA_DATA_BROWSER]) and isset($UA_BrowserInfo[UA_DATA_BROWSER][$userAgent[UA_DATA_BROWSER]]))
+    {
+      $returned[UA_DATA_BROWSER]=$userAgent[UA_DATA_BROWSER];
+      $returned[UA_DATA_BROWSER_NAME]=$UA_BrowserInfo[UA_DATA_BROWSER][$userAgent[UA_DATA_BROWSER]][UA_PROP_NAME];
+      $returned[UA_DATA_BROWSER_URL]=$UA_BrowserInfo[UA_DATA_BROWSER][$userAgent[UA_DATA_BROWSER]][UA_PROP_URL];
+    }
+
+    if(!isset($userAgent[UA_DATA_BROWSER_TYPE]) and isset($userAgent[UA_DATA_BROWSER]))
+      $userAgent[UA_DATA_BROWSER_TYPE]=$UA_BrowserInfo[UA_DATA_BROWSER][$userAgent[UA_DATA_BROWSER]][UA_PROP_TYPE];
+
+    if(isset($userAgent[UA_DATA_BROWSER_TYPE]) and isset($UA_BrowserInfo[UA_DATA_BROWSER_TYPE][$userAgent[UA_DATA_BROWSER_TYPE]]))
+    {
+      $returned[UA_DATA_BROWSER_TYPE]=$userAgent[UA_DATA_BROWSER_TYPE];
+      $returned[UA_DATA_BROWSER_TYPE_NAME]=$UA_BrowserInfo[UA_DATA_BROWSER_TYPE][$userAgent[UA_DATA_BROWSER_TYPE]];
+    }
+
+
+    if(isset($userAgent[UA_DATA_OS]) and isset($UA_BrowserInfo[UA_DATA_OS][$userAgent[UA_DATA_OS]]))
+    {
+      $returned[UA_DATA_OS]=$userAgent[UA_DATA_OS];
+      $returned[UA_DATA_OS_NAME]=$UA_BrowserInfo[UA_DATA_OS][$userAgent[UA_DATA_OS]][UA_PROP_NAME];
+      $returned[UA_DATA_OS_URL]=$UA_BrowserInfo[UA_DATA_OS][$userAgent[UA_DATA_OS]][UA_PROP_URL];
+    }
+
+    if(isset($userAgent[UA_DATA_ENGINE]) and isset($UA_BrowserInfo[UA_DATA_ENGINE][$userAgent[UA_DATA_ENGINE]]))
+    {
+      $returned[UA_DATA_ENGINE]=$userAgent[UA_DATA_ENGINE];
+      $returned[UA_DATA_ENGINE_NAME]=$UA_BrowserInfo[UA_DATA_ENGINE][$userAgent[UA_DATA_ENGINE]][UA_PROP_NAME];
+      $returned[UA_DATA_ENGINE_URL]=$UA_BrowserInfo[UA_DATA_ENGINE][$userAgent[UA_DATA_ENGINE]][UA_PROP_URL];
+    }
 
     return($returned);
@@ -89,6 +165,44 @@
       '(ichiro)\/(\S*)\('                               => UA_BOT_ICHIRO,
       '(ichiro)(?:\/(\S*))*'                            => UA_BOT_ICHIRO,
+      '(l.webis)(?:\/(\S*))*'                           => UA_BOT_LWEBIS,
+      '(larbin)'                                        => UA_BOT_LARBIN,
+      '(linkwalker)(?:\/(\S*))*'                        => UA_BOT_LINKWALKER,
+      '(lwp-trivial)(?:\/(\S*))*'                       => UA_BOT_LWPTRIVIAL,
+      '(mabontland)'                                    => UA_BOT_MABONLAND,
+      '(mnogosearch)'                                   => UA_BOT_MNOGOSEARCH,
+      '(mogimogi)(?:\/(\S*))*'                          => UA_BOT_MOGIMOGI,
+      '(morning\spaper)'                                => UA_BOT_MORNINGPAPER,
+      '(netresearchserver)\/(\S*)\('                    => UA_BOT_NETRESEARCHSERVER,
+      '(netresearchserver)(?:\/(\S*))*'                 => UA_BOT_NETRESEARCHSERVER,
+      '(newsgator)(?:\/(\S*))*'                         => UA_BOT_NEWSGATOR,
+      '(ng-search)(?:\/(\S*))*'                         => UA_BOT_NGSEARCH,
+      '(nymesis)(?:\/(\S*))*'                           => UA_BOT_NYMESIS,
+      '(oegp)'                                          => UA_BOT_OEGP,
+      '(pompos)(?:\/(\S*))*'                            => UA_BOT_POMPOS,
+      '(pycurl)(?:\/(\S*))*'                            => UA_BOT_PYCURL,
+      '(qseero)'                                        => UA_BOT_QSEERO,
+      '(sbider)(?:\/(\S*))*'                            => UA_BOT_SBIDER,
+      '(scoutjet)'                                      => UA_BOT_SCOUTJET,
+      '(scrubby)(?:\/(\S*))*'                           => UA_BOT_SCRUBBY,
+      '(searchsight)(?:\/(\S*))*'                       => UA_BOT_SEARCHSIGHT,
+      '(semanticdiscovery)(?:\/(\S*))*'                 => UA_BOT_SEMANTICDISCOVERY,
+
+      '(shoula)'                                        => UA_BOT_SHOULA,
+      '(snappy)(?:\/(\S*))*'                            => UA_BOT_SNAPPY,
+      '(stackrambler)(?:\/(\S*))*'                      => UA_BOT_STACKRAMBLER,
+      '(silk)(?:\/(\S*))*'                              => UA_BOT_SILK,
+      '(teoma)'                                         => UA_BOT_TEOMA,
+      '(tineye)(?:\/(\S*))*'                            => UA_BOT_TINEYE,
+      '(truwogps)(?:\/(\S*))*'                          => UA_BOT_TRUWOGPS,
+      '(updated)(?:\/(\S*))*'                           => UA_BOT_UPDATED,
+      '(voyager)(?:\/(\S*))*'                           => UA_BOT_VOYAGER,
+      '(vyu2)'                                          => UA_BOT_VYU2,
+      '(webcollage)(?:\/(\S*))*'                        => UA_BOT_WEBCOLLAGE,
+      '(yooglifetchagent)(?:\/(\S*))*'                  => UA_BOT_YOOGLIFETCHAGENT,
+      '(zao)(?:\/(\S*))*'                               => UA_BOT_ZAO,
+      '(zealbot)'                                       => UA_BOT_ZEALBOT,
       '(baiduspider)'                                   => UA_BOT_BAIDU,
       '(msnbot)\/(\d+(?:\.\d+)*)'                       => UA_BOT_MSN_SEARCH,
+      '(msnbot)\s(\d+(?:\.\d+)*)'                       => UA_BOT_MSN_SEARCH,
       '(exabot)\/(\d+(?:\.\d+)*)'                       => UA_BOT_EXALEAD,
       '(gamespyhttp)\/(\d+(?:\.\d+)*)'                  => UA_BOT_GAMESPY,
@@ -96,11 +210,12 @@
       '(inktomi)'                                       => UA_BOT_INKTOMI,
       '(Yahoo! Slurp)'                                  => UA_BOT_YAHOO_SEARCH,
+      '(yahooseeker)'                                   => UA_BOT_YAHOO_SEARCH,
       '\s*([a-z]*(?:bot|spyder|crawl|crawler|spider)[a-z]*)'  => UA_BOT_UNKNOWN
     );
 
     $returned=array(
-      'crawler' => '',
-      'name' => '',
-      'version' => ''
+      UA_DATA_BROWSER => '',
+      //'name' => '',
+      UA_DATA_BROWSER_VERSION => ''
     );
 
@@ -110,8 +225,12 @@
       if(preg_match('/'.$regExp.'/i',$userAgent,$result))
       {
+        // exclude some case
+        if($crawler==UA_BOT_UNKNOWN and preg_match('/(?:msiecrawler)/i', $userAgent))
+          return($returned);
+
         $returned=array(
-          'crawler' => $crawler,
-          'name' => $result[1],
-          'version' => isset($result[2])?$result[2]:''
+          UA_DATA_BROWSER => $crawler,
+          //'name' => $result[1], #retrieved from the code
+          UA_DATA_BROWSER_VERSION => isset($result[2])?$result[2]:''
         );
         return($returned);
@@ -180,4 +299,5 @@
       '(chrome)\/(\S*)'                                       => UA_BROWSER_CHROME,
       '(epiphany)\/(\S*)'                                     => UA_BROWSER_EPIPHANY,
+      '(epiphany)'                                            => UA_BROWSER_EPIPHANY,
       '(galeon)\/(\S*)'                                       => UA_BROWSER_GALEON,
       '(orca)\/(\S*)'                                         => UA_BROWSER_ORCA,
@@ -203,7 +323,7 @@
 
     $returned=array(
-      'browser' => UA_BROWSER_UNKNOWN,
-      'name' => '',
-      'version' => ''
+      UA_DATA_BROWSER => UA_BROWSER_UNKNOWN,
+      //'name' => '',
+      UA_DATA_BROWSER_VERSION => ''
     );
 
@@ -214,5 +334,5 @@
       {
         //echo print_r($userAgent, true).print_r($result, true);
-        if(is_array($result) and count($result)>2)
+        if(is_array($result) and count($result)>=2)
         {
           if($browser==UA_BROWSER_SAFARI and preg_match('/iphone|ipad|ipod/i', $userAgent))
@@ -220,7 +340,7 @@
 
           $returned=array(
-            'browser' => $browser,
-            'name' => $result[1],
-            'version' => isset($result[2])?$result[2]:''
+            UA_DATA_BROWSER => $browser,
+            //'name' => $result[1],
+            UA_DATA_BROWSER_VERSION => isset($result[2])?$result[2]:''
           );
         }
@@ -228,7 +348,7 @@
         {
           $returned=array(
-            'browser' => UA_BROWSER_UNKNOWN,
-            'name' => '',
-            'version' => ''
+            UA_DATA_BROWSER => UA_BROWSER_UNKNOWN,
+            //'name' => '',
+            UA_DATA_BROWSER_VERSION => ''
           );
         }
@@ -257,4 +377,5 @@
       '(sunos)'                                               => UA_OS_SUNOS,
       '(blackberry)\s?([^;.]*);'                              => UA_OS_BLACKBERRY,
+      '(blackberry)'                                          => UA_OS_BLACKBERRY,
       '(symbianos)'                                           => UA_OS_SYMBIAN_OS,
       '(symbos)'                                              => UA_OS_SYMBOS,
@@ -267,4 +388,7 @@
       '(windows)\s?(\S*)[\;\)]'                               => UA_OS_WINDOWS,
       '(windows)\s?(\S*)'                                     => UA_OS_WINDOWS,
+      '(winnt)'                                               => UA_OS_WINDOWS,
+      '(win98)'                                               => UA_OS_WINDOWS,
+      '(win95)'                                               => UA_OS_WINDOWS,
       '(mac_powerpc)'                                         => UA_OS_MACINTOSH,
       '(cpu\siphone\sos)\s?(\S*)'                             => UA_OS_IOS,
@@ -276,12 +400,23 @@
       '(playstation\s3)'                                      => UA_OS_SONY_PS3,
       '(playstation\sportable)'                               => UA_OS_SONY_PSP,
-      '(nintendo\sds)'                                        => UA_OS_NINTENDO_DS
-
+      '(nintendo\sds)'                                        => UA_OS_NINTENDO_DS,
+      '(cros)(?:\s*i\d*)(?:\s(\S*))'                          => UA_OS_CHROME_OS,
+      '(cros)'                                                => UA_OS_CHROME_OS,
+      '(beos)'                                                => UA_OS_BE_OS,
+      '(dragonfly)'                                           => UA_OS_DRAGONFLY,
+      '(unix)'                                                => UA_OS_UNIX,
+      '(darwin)'                                              => UA_OS_DARWIN,
+      '(macintosh)'                                           => UA_OS_MACINTOSH,
+      '(fedora)'                                              => UA_OS_LINUX,
+      '(os\/2).*(warp(?:\s\S*));'                             => UA_OS_OS2,
+      '(os\/2)'                                               => UA_OS_OS2,
+      '(amigaos)(?:\s(\S*))'                                  => UA_OS_AMIGAOS,
+      '(amigaos)'                                             => UA_OS_AMIGAOS
     );
 
     $returned=array(
-      'os' => UA_OS_UNKNOWN,
-      'name' => '',
-      'version' => ''
+      UA_DATA_OS => UA_OS_UNKNOWN,
+      //'name' => '',
+      UA_DATA_OS_VERSION => ''
     );
 
@@ -292,12 +427,12 @@
       {
         $returned=array(
-          'os' => $os,
-          'name' => $result[1],
-          'version' => isset($result[2])?$result[2]:''
+          UA_DATA_OS => $os,
+          //'name' => $result[1],
+          UA_DATA_OS_VERSION => isset($result[2])?$result[2]:''
         );
         switch($os)
         {
           case UA_OS_WINDOWS:
-            switch($returned['version'])
+            switch($returned[UA_DATA_OS_VERSION])
             {
               case 'NT 5.0':
@@ -338,16 +473,16 @@
   {
     $engineList=array(
-      '(presto)\/(\S*)'           => UA_ENGINE_PRESTO,
-      '(gecko)\/(\S*)'            => UA_ENGINE_GECKO,
-      '(applewebkit)\/(\S*)'      => UA_ENGINE_APPLEWEBKIT,
-      '(webkit)\/(\S*)'           => UA_ENGINE_WEBKIT,
-      '(khtml)\/(\S*)'            => UA_ENGINE_KHTML,
-      '(trident)\/(\S*)'          => UA_ENGINE_TRIDENT
+      '(presto)(?:\/(\S*))*'           => UA_ENGINE_PRESTO,
+      '(applewebkit)(?:\/(\S*))*'      => UA_ENGINE_APPLEWEBKIT,
+      '(webkit)(?:\/(\S*))*'           => UA_ENGINE_WEBKIT,
+      '(khtml)(?:\/(\S*))*'            => UA_ENGINE_KHTML,
+      '(gecko)(?:\/(\S*))*'            => UA_ENGINE_GECKO,
+      '(trident)(?:\/(\S*))*'          => UA_ENGINE_TRIDENT
     );
 
     $returned=array(
-      'engine' => UA_ENGINE_UNKNOWN,
-      'name' => '',
-      'version' => ''
+      UA_DATA_ENGINE => UA_ENGINE_UNKNOWN,
+      //'name' => '',
+      UA_DATA_ENGINE_VERSION => ''
     );
 
@@ -358,7 +493,7 @@
       {
         $returned=array(
-          'engine' => $engine,
-          'name' => $result[1],
-          'version' => isset($result[2])?$result[2]:''
+          UA_DATA_ENGINE => $engine,
+          //'name' => $result[1],
+          UA_DATA_ENGINE_VERSION => isset($result[2])?$result[2]:''
         );
         return($returned);
@@ -368,7 +503,5 @@
     return($returned);
   }
-
-
-}
+} // GPCUserAgent class
 
 
Index: /extensions/GrumPluginClasses/classes/GPCUserAgent.const.inc.php
===================================================================
--- /extensions/GrumPluginClasses/classes/GPCUserAgent.const.inc.php	(revision 16457)
+++ /extensions/GrumPluginClasses/classes/GPCUserAgent.const.inc.php	(revision 16458)
@@ -5,12 +5,28 @@
  * Data types : bot, browser, engine, os
  */
-define('UA_DATA',                     0x00);
-
-define('UA_DATA_BROWSER',             0x01);
-define('UA_DATA_ENGINE',              0x02);
-define('UA_DATA_OS',                  0x03);
-define('UA_DATA_BOT',                 0x04);
-
-define('UA_DATA_PROP_NAME',           0x10);
+define('UA_DATA',                     0x0000);
+
+define('UA_DATA_BROWSER',             0x0001);
+define('UA_DATA_ENGINE',              0x0002);
+define('UA_DATA_OS',                  0x0003);
+
+define('UA_DATA_BROWSER_NAME',        0x0011);
+define('UA_DATA_OS_NAME',             0x0012);
+define('UA_DATA_ENGINE_NAME',         0x0013);
+
+define('UA_DATA_BROWSER_VERSION',     0x0021);
+define('UA_DATA_ENGINE_VERSION',      0x0022);
+define('UA_DATA_OS_VERSION',          0x0023);
+
+define('UA_DATA_BROWSER_TYPE',        0x0031);
+define('UA_DATA_BROWSER_TYPE_NAME',   0x0131);
+define('UA_DATA_OS_TYPE',             0x0033);
+define('UA_DATA_OS_TYPE_NAME',        0x0133);
+
+define('UA_DATA_BROWSER_URL',         0x0041);
+define('UA_DATA_ENGINE_URL',          0x0042);
+define('UA_DATA_OS_URL',              0x0043);
+
+
 
 /**
@@ -23,12 +39,12 @@
 
 /**
- * -- UA_PROP_TYPE --
- * Indexes for UA_PROP_TYPE information (computer, mobile, console, ...)
- */
-define('UA_PROP_TYPE_UNKNOWN',          0x00);
-define('UA_PROP_TYPE_BROWSER_COMPUTER', 0x01);
-define('UA_PROP_TYPE_BROWSER_MOBILE',   0x02);
-define('UA_PROP_TYPE_BROWSER_CONSOLE',  0x03);
-define('UA_PROP_TYPE_CRAWLER',          0x04);
+ * -- UA_DATA_BROWSER_TYPE --
+ * Indexes for UA_DATA_BROWSER_TYPE information (computer, mobile, console, ...)
+ */
+define('UA_BROWSER_TYPE_UNKNOWN',   0x00);
+define('UA_BROWSER_TYPE_COMPUTER',  0x01);
+define('UA_BROWSER_TYPE_MOBILE',    0x02);
+define('UA_BROWSER_TYPE_CONSOLE',   0x03);
+define('UA_BROWSER_TYPE_CRAWLER',   0x04);
 
 /**
@@ -62,5 +78,41 @@
 define('UA_BOT_INKTOMI',              0x0018);
 define('UA_BOT_YAHOO_SEARCH',         0x0019);
-define('UA_BOT_ACCOONA_AI_AGENT',     0x0020);
+define('UA_BOT_ACCOONA_AI_AGENT',     0x001A);
+define('UA_BOT_LWEBIS',               0x001B);
+define('UA_BOT_LARBIN',               0x001C);
+define('UA_BOT_LINKWALKER',           0x001D);
+define('UA_BOT_LWPTRIVIAL',           0x001E);
+define('UA_BOT_MABONLAND',            0x001F);
+define('UA_BOT_MNOGOSEARCH',          0x0020);
+define('UA_BOT_MOGIMOGI',             0x0021);
+define('UA_BOT_MORNINGPAPER',         0x0022);
+define('UA_BOT_NETRESEARCHSERVER',    0x0023);
+define('UA_BOT_NEWSGATOR',            0x0024);
+define('UA_BOT_NGSEARCH',             0x0025);
+define('UA_BOT_NYMESIS',              0x0026);
+define('UA_BOT_OEGP',                 0x0027);
+define('UA_BOT_POMPOS',               0x0028);
+define('UA_BOT_PYCURL',               0x0029);
+define('UA_BOT_QSEERO',               0x002A);
+define('UA_BOT_SBIDER',               0x002B);
+define('UA_BOT_SCOUTJET',             0x002C);
+define('UA_BOT_SCRUBBY',              0x002D);
+define('UA_BOT_SEARCHSIGHT',          0x002E);
+define('UA_BOT_SEMANTICDISCOVERY',    0x002F);
+define('UA_BOT_SHOULA',               0x0030);
+define('UA_BOT_SNAPPY',               0x0031);
+define('UA_BOT_STACKRAMBLER',         0x0032);
+define('UA_BOT_SILK',                 0x0033);
+define('UA_BOT_TEOMA',                0x0034);
+define('UA_BOT_TINEYE',               0x0035);
+define('UA_BOT_TRUWOGPS',             0x0036);
+define('UA_BOT_UPDATED',              0x0037);
+define('UA_BOT_VOYAGER',              0x0038);
+define('UA_BOT_VYU2',                 0x0039);
+define('UA_BOT_WEBCOLLAGE',           0x003A);
+define('UA_BOT_YOOGLIFETCHAGENT',     0x003B);
+define('UA_BOT_ZAO',                  0x003C);
+define('UA_BOT_ZEALBOT',              0x003D);
+
 
 /**
@@ -142,4 +194,25 @@
 define('UA_OS_SONY_PS3',              0x10);
 define('UA_OS_SONY_PSP',              0x11);
+define('UA_OS_CHROME_OS',             0x12);
+define('UA_OS_BE_OS',                 0x13);
+define('UA_OS_DRAGONFLY',             0x14);
+define('UA_OS_UNIX',                  0x15);
+define('UA_OS_DARWIN',                0x16);
+define('UA_OS_OS2',                   0x17);
+define('UA_OS_AMIGAOS',               0x18);
+
+
+/**
+ * -- UA_OS_TYPE --
+ * Known OS type
+ */
+define('UA_OS_TYPE_UNKNOWN',          0x00);
+define('UA_OS_TYPE_LINUX',            0x01);
+define('UA_OS_TYPE_BSD',              0x02);
+define('UA_OS_TYPE_UNIX',             0x03);
+define('UA_OS_TYPE_WINDOWS',          0x04);
+define('UA_OS_TYPE_OS2',              0x05);
+
+
 
 /**
@@ -157,5 +230,4 @@
 $UA_BrowserInfo=array(
   UA_DATA => array(
-            UA_DATA_BOT     => array(UA_PROP_NAME => 'Robot'),
             UA_DATA_BROWSER => array(UA_PROP_NAME => 'Browser'),
             UA_DATA_ENGINE  => array(UA_PROP_NAME => 'Engine'),
@@ -163,125 +235,177 @@
           ),
   UA_DATA_BROWSER=> array(
-            UA_BOT_UNKNOWN           => array(UA_PROP_NAME => 'Unknown',              UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-
-            UA_BOT_008               => array(UA_PROP_NAME => '008',                  UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_ABACHOBOT         => array(UA_PROP_NAME => 'ABACHOBot',            UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_ACCOONA_AI_AGENT  => array(UA_PROP_NAME => 'Accoona-AI-Agent',     UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_ARACHMO           => array(UA_PROP_NAME => 'Arachmo',              UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_BLITZBOT          => array(UA_PROP_NAME => 'BlitzBOT',             UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_MICROSOFT_BING    => array(UA_PROP_NAME => 'Microsoft Bing',       UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_CHARLOTTE         => array(UA_PROP_NAME => 'Charlotte',            UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_CERBERIAN_DRTRS   => array(UA_PROP_NAME => 'Cerberian Drtrs',      UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_COSMOS            => array(UA_PROP_NAME => 'Cosmos',               UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_COVARIO_IDS       => array(UA_PROP_NAME => 'Covario IDS',          UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_DATAPARKSEARCH    => array(UA_PROP_NAME => 'DataparkSearch',       UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_GAISBOT           => array(UA_PROP_NAME => 'Gaisbot',              UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_GOOGLE            => array(UA_PROP_NAME => 'Google',               UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_GURUJIBOT         => array(UA_PROP_NAME => 'GurujiBot',            UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_HOLMES            => array(UA_PROP_NAME => 'Holmes',               UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_HTDIG             => array(UA_PROP_NAME => 'htdig',                UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_IA_ARCHIVER       => array(UA_PROP_NAME => 'ia_archiver',          UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_ICCRAWLER         => array(UA_PROP_NAME => 'iCCrawler',            UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_ICHIRO            => array(UA_PROP_NAME => 'Ichiro',               UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_BAIDU             => array(UA_PROP_NAME => 'Baidu',                UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_MSN_SEARCH        => array(UA_PROP_NAME => 'Microsoft MSN Search', UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_EXALEAD           => array(UA_PROP_NAME => 'Exalead',              UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_GAMESPY           => array(UA_PROP_NAME => 'GameSpy',              UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_INKTOMI           => array(UA_PROP_NAME => 'Inktomi',              UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-            UA_BOT_YAHOO_SEARCH      => array(UA_PROP_NAME => 'Yahoo! Search',        UA_PROP_TYPE=>UA_PROP_TYPE_CRAWLER, UA_PROP_URL => ''),
-
-
-            UA_BROWSER_UNKNOWN       => array(UA_PROP_NAME => 'Unknown',              UA_PROP_TYPE=>UA_PROP_TYPE_UNKNOWN, UA_PROP_URL => ''),
-
-            UA_BROWSER_ANDROID_WEBKIT=> array(UA_PROP_NAME => 'Android WebKit Browser',  UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-            UA_BROWSER_OPERA_MINI    => array(UA_PROP_NAME => 'Opera Mini',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => 'http://www.opera.com/'),
-            UA_BROWSER_OPERA_MOBILE  => array(UA_PROP_NAME => 'Opera Mobile',            UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => 'http://www.opera.com/'),
-            UA_BROWSER_BLACKBERRY    => array(UA_PROP_NAME => 'BlackBerry',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => 'http://worldwide.blackberry.com/'),
-            UA_BROWSER_FENNEC        => array(UA_PROP_NAME => 'Fennec',                  UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-            UA_BROWSER_GOBROWSER     => array(UA_PROP_NAME => 'Go Browser',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => 'http://www.3g.cn/'),
-            UA_BROWSER_IEMOBILE      => array(UA_PROP_NAME => 'IE Mobile',               UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-            UA_BROWSER_IRIS          => array(UA_PROP_NAME => 'Iris',                    UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => 'http://www.torchmobile.com/'),
-            UA_BROWSER_MAEMO_BROWSER => array(UA_PROP_NAME => 'Maemo Browser',           UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-            UA_BROWSER_MIB           => array(UA_PROP_NAME => 'MIB',                     UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => 'http://www.useragentstring.com/pages/MIB/www.motorola.com'),
-            UA_BROWSER_MINIMO        => array(UA_PROP_NAME => 'Minimo',                  UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-            UA_BROWSER_NETFRONT      => array(UA_PROP_NAME => 'NetFront',                UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => 'http://www.access-company.com/'),
-            UA_BROWSER_SEMC          => array(UA_PROP_NAME => 'SEMC-Browser',            UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-            UA_BROWSER_TEASHARK      => array(UA_PROP_NAME => 'TeaShark',                UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-            UA_BROWSER_SKYFIRE       => array(UA_PROP_NAME => 'Skyfire',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => ''),
-
-            UA_BROWSER_PS3           => array(UA_PROP_NAME => 'Playstation 3',           UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_CONSOLE, UA_PROP_URL => ''),
-            UA_BROWSER_PSP           => array(UA_PROP_NAME => 'Playstation Portable',    UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_CONSOLE, UA_PROP_URL => ''),
-            UA_BROWSER_BUNJALLOO     => array(UA_PROP_NAME => 'Bunjalloo',               UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_CONSOLE, UA_PROP_URL => ''),
-            UA_BROWSER_OPERA_WII     => array(UA_PROP_NAME => 'Opera',                   UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_CONSOLE, UA_PROP_URL => ''),
-
-            UA_BROWSER_OPERA         => array(UA_PROP_NAME => 'Opera',                  UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://www.opera.com/'),
-            UA_BROWSER_SHIIRA        => array(UA_PROP_NAME => 'Shiira',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://shiira.jp/en'),
-            UA_BROWSER_THUNDERBIRD   => array(UA_PROP_NAME => 'Thunderbird',            UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_NAMOROKA      => array(UA_PROP_NAME => 'Namoroka',               UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'https://wiki.mozilla.org/Firefox/Namoroka'),
-            UA_BROWSER_MINEFIELD     => array(UA_PROP_NAME => 'Minefield',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://www.mozilla.org/projects/minefield/'),
-            UA_BROWSER_LUNASCAPE     => array(UA_PROP_NAME => 'Lunascape',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_ARORA         => array(UA_PROP_NAME => 'Arora',                  UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_CAMINO        => array(UA_PROP_NAME => 'Camino',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://caminobrowser.org/'),
-            UA_BROWSER_KAPIKO        => array(UA_PROP_NAME => 'Kapiko',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://ufoxlab.googlepages.com/cooperation'),
-            UA_BROWSER_KAZEHAKAZE    => array(UA_PROP_NAME => 'Kazehakase',             UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_CHROMEPLUS    => array(UA_PROP_NAME => 'ChromePlus',             UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_CHROME        => array(UA_PROP_NAME => 'Chrome',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://www.google.com/chrome'),
-            UA_BROWSER_EPIPHANY      => array(UA_PROP_NAME => 'Epiphany',               UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_GALEON        => array(UA_PROP_NAME => 'Galeon',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_ORCA          => array(UA_PROP_NAME => 'Orca',                   UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_LOBO          => array(UA_PROP_NAME => 'Lobo',                   UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_SEAMONKEY     => array(UA_PROP_NAME => 'SeaMonkey',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_MIDORI        => array(UA_PROP_NAME => 'Midori',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_MAXTHON       => array(UA_PROP_NAME => 'Maxthon',                UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_ICEAPE        => array(UA_PROP_NAME => 'Iceape',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_ICEWEASEL     => array(UA_PROP_NAME => 'Iceweasel',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_NETSCAPE      => array(UA_PROP_NAME => 'Netscape',               UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_FIREBIRD      => array(UA_PROP_NAME => 'Firebird',               UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_FIREFOX       => array(UA_PROP_NAME => 'Firefox',                UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://www.firefox.com/'),
-            UA_BROWSER_INTERNET_EXPLORER=> array(UA_PROP_NAME => 'Internet Explorer',   UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => 'http://www.getthunderbird.com/'),
-            UA_BROWSER_KONQUEROR     => array(UA_PROP_NAME => 'Konqueror',              UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_LINKS         => array(UA_PROP_NAME => 'Links',                  UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_LYNX          => array(UA_PROP_NAME => 'Lynx',                   UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_SAFARI        => array(UA_PROP_NAME => 'Safari',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_COMPUTER, UA_PROP_URL => ''),
-            UA_BROWSER_SAFARI_MOBILE => array(UA_PROP_NAME => 'Safari',                 UA_PROP_TYPE=>UA_PROP_TYPE_BROWSER_MOBILE, UA_PROP_URL => '')
+            UA_BOT_UNKNOWN           => array(UA_PROP_NAME => 'Unknown',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+
+            UA_BOT_008               => array(UA_PROP_NAME => '008',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.80legs.com'),
+            UA_BOT_ABACHOBOT         => array(UA_PROP_NAME => 'ABACHOBot',            UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.abacho.com'),
+            UA_BOT_ACCOONA_AI_AGENT  => array(UA_PROP_NAME => 'Accoona-AI-Agent',     UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.accoona.com'),
+            UA_BOT_ARACHMO           => array(UA_PROP_NAME => 'Arachmo',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_BLITZBOT          => array(UA_PROP_NAME => 'BlitzBOT',             UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_MICROSOFT_BING    => array(UA_PROP_NAME => 'Microsoft Bing',       UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.bing.com/bingbot.htm'),
+            UA_BOT_CHARLOTTE         => array(UA_PROP_NAME => 'Charlotte',            UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.searchme.com'),
+            UA_BOT_CERBERIAN_DRTRS   => array(UA_PROP_NAME => 'Cerberian Drtrs',      UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_COSMOS            => array(UA_PROP_NAME => 'Cosmos',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.xyleme.com/'),
+            UA_BOT_COVARIO_IDS       => array(UA_PROP_NAME => 'Covario IDS',          UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.covario.com/ids'),
+            UA_BOT_DATAPARKSEARCH    => array(UA_PROP_NAME => 'DataparkSearch',       UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.dataparksearch.org'),
+            UA_BOT_GAISBOT           => array(UA_PROP_NAME => 'Gaisbot',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://gais.cs.ccu.edu.tw/'),
+            UA_BOT_GOOGLE            => array(UA_PROP_NAME => 'Google',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.google.com/bot.html'),
+            UA_BOT_GURUJIBOT         => array(UA_PROP_NAME => 'GurujiBot',            UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.guruji.com/en/WebmasterFAQ.html'),
+            UA_BOT_HOLMES            => array(UA_PROP_NAME => 'Holmes',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.ucw.cz/holmes'),
+            UA_BOT_HTDIG             => array(UA_PROP_NAME => 'htdig',                UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://htdig.sourceforge.net'),
+            UA_BOT_IA_ARCHIVER       => array(UA_PROP_NAME => 'ia_archiver',          UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.alexa.com/'),
+            UA_BOT_ICCRAWLER         => array(UA_PROP_NAME => 'iCCrawler',            UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.iccenter.net/bot.htm'),
+            UA_BOT_ICHIRO            => array(UA_PROP_NAME => 'Ichiro',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://help.goo.ne.jp/door/crawler.html'),
+            UA_BOT_BAIDU             => array(UA_PROP_NAME => 'Baidu',                UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.baidu.com'),
+            UA_BOT_MSN_SEARCH        => array(UA_PROP_NAME => 'Microsoft MSN Search', UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://search.msn.com/msnbot.htm'),
+            UA_BOT_EXALEAD           => array(UA_PROP_NAME => 'Exalead',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_GAMESPY           => array(UA_PROP_NAME => 'GameSpy',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_INKTOMI           => array(UA_PROP_NAME => 'Inktomi',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_YAHOO_SEARCH      => array(UA_PROP_NAME => 'Yahoo! Search',        UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.yahoo.com/'),
+            UA_BOT_LWEBIS            => array(UA_PROP_NAME => 'L.webis',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://webalgo.iit.cnr.it/index.php?pg=lwebis'),
+            UA_BOT_LARBIN            => array(UA_PROP_NAME => 'Larbin',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_LINKWALKER        => array(UA_PROP_NAME => 'LinkWalker',           UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.seventwentyfour.com/'),
+            UA_BOT_LWPTRIVIAL        => array(UA_PROP_NAME => 'lwp-trivial',          UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_MABONLAND         => array(UA_PROP_NAME => 'Mabontland',           UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.mabontland.com'),
+            UA_BOT_MNOGOSEARCH       => array(UA_PROP_NAME => 'Mnogosearch',          UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://mnogosearch.org'),
+            UA_BOT_MOGIMOGI          => array(UA_PROP_NAME => 'mogimogi',             UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_MORNINGPAPER      => array(UA_PROP_NAME => 'Morning Paper',        UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.boutell.com'),
+            UA_BOT_NETRESEARCHSERVER => array(UA_PROP_NAME => 'NetResearchServer',    UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.loopimprovements.com'),
+            UA_BOT_NEWSGATOR         => array(UA_PROP_NAME => 'NewsGator',            UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.newsgator.com'),
+            UA_BOT_NGSEARCH          => array(UA_PROP_NAME => 'NG-Search',            UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.ng-search.com'),
+            UA_BOT_NYMESIS           => array(UA_PROP_NAME => 'Nymesis',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.nymesis.com'),
+            UA_BOT_OEGP              => array(UA_PROP_NAME => 'oegp',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_POMPOS            => array(UA_PROP_NAME => 'Pompos',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://dir.com/pompos.html'),
+            UA_BOT_PYCURL            => array(UA_PROP_NAME => 'PycURL',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://pycurl.sourceforge.net'),
+            UA_BOT_QSEERO            => array(UA_PROP_NAME => 'Qseero',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_SBIDER            => array(UA_PROP_NAME => 'SBIder',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.sitesell.com'),
+            UA_BOT_SCOUTJET          => array(UA_PROP_NAME => 'ScoutJet',             UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.scoutjet.com'),
+            UA_BOT_SCRUBBY           => array(UA_PROP_NAME => 'Scrubby',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.scrubtheweb.com'),
+            UA_BOT_SEARCHSIGHT       => array(UA_PROP_NAME => 'SearchSight',          UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://searchsight.com'),
+            UA_BOT_SEMANTICDISCOVERY => array(UA_PROP_NAME => 'semanticdiscovery',    UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_SHOULA            => array(UA_PROP_NAME => 'Shoula',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_SNAPPY            => array(UA_PROP_NAME => 'Snappy',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.urltrends.com'),
+            UA_BOT_STACKRAMBLER      => array(UA_PROP_NAME => 'StackRambler',         UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_SILK              => array(UA_PROP_NAME => 'Silk',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.slider.com/silk.htm'),
+            UA_BOT_TEOMA             => array(UA_PROP_NAME => 'Teoma',                UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://sp.ask.com/docs/about/tech_crawling.html'),
+            UA_BOT_TINEYE            => array(UA_PROP_NAME => 'TinEye',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://tineye.com/crawler.html'),
+            UA_BOT_TRUWOGPS          => array(UA_PROP_NAME => 'truwoGPS',             UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.lan4lano.net/browser.html'),
+            UA_BOT_UPDATED           => array(UA_PROP_NAME => 'updated',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.updated.com'),
+            UA_BOT_VOYAGER           => array(UA_PROP_NAME => 'voyager',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.kosmix.com/crawler.html'),
+            UA_BOT_VYU2              => array(UA_PROP_NAME => 'vyu2',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_WEBCOLLAGE        => array(UA_PROP_NAME => 'WebCollage',           UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_YOOGLIFETCHAGENT  => array(UA_PROP_NAME => 'yoogliFetchAgent',     UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+            UA_BOT_ZAO               => array(UA_PROP_NAME => 'Zao',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => 'http://www.kototoi.org/zao'),
+            UA_BOT_ZEALBOT           => array(UA_PROP_NAME => 'Zealbot',              UA_PROP_TYPE=>UA_BROWSER_TYPE_CRAWLER, UA_PROP_URL => ''),
+
+
+            UA_BROWSER_UNKNOWN       => array(UA_PROP_NAME => 'Unknown',              UA_PROP_TYPE=>UA_BROWSER_TYPE_UNKNOWN, UA_PROP_URL => ''),
+
+            UA_BROWSER_ANDROID_WEBKIT=> array(UA_PROP_NAME => 'Android WebKit Browser',  UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => ''),
+            UA_BROWSER_OPERA_MINI    => array(UA_PROP_NAME => 'Opera Mini',              UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.opera.com/'),
+            UA_BROWSER_OPERA_MOBILE  => array(UA_PROP_NAME => 'Opera Mobile',            UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.opera.com/'),
+            UA_BROWSER_BLACKBERRY    => array(UA_PROP_NAME => 'BlackBerry',              UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://worldwide.blackberry.com'),
+            UA_BROWSER_FENNEC        => array(UA_PROP_NAME => 'Fennec',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.mozilla.org/en-US/mobile'),
+            UA_BROWSER_GOBROWSER     => array(UA_PROP_NAME => 'Go Browser',              UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.3g.cn/'),
+            UA_BROWSER_IEMOBILE      => array(UA_PROP_NAME => 'IE Mobile',               UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => ''),
+            UA_BROWSER_IRIS          => array(UA_PROP_NAME => 'Iris',                    UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.torchmobile.com'),
+            UA_BROWSER_MAEMO_BROWSER => array(UA_PROP_NAME => 'Maemo Browser',           UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://browser.garage.maemo.org'),
+            UA_BROWSER_MIB           => array(UA_PROP_NAME => 'MIB',                     UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.useragentstring.com/pages/MIB/www.motorola.com'),
+            UA_BROWSER_MINIMO        => array(UA_PROP_NAME => 'Minimo',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www-archive.mozilla.org/projects/minimo/'),
+            UA_BROWSER_NETFRONT      => array(UA_PROP_NAME => 'NetFront',                UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.access-company.com'),
+            UA_BROWSER_SEMC          => array(UA_PROP_NAME => 'SEMC-Browser',            UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => ''),
+            UA_BROWSER_TEASHARK      => array(UA_PROP_NAME => 'TeaShark',                UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.navire.fi/teashark/index.html'),
+            UA_BROWSER_SKYFIRE       => array(UA_PROP_NAME => 'Skyfire',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.skyfire.com'),
+            UA_BROWSER_SAFARI_MOBILE => array(UA_PROP_NAME => 'Safari',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_MOBILE, UA_PROP_URL => 'http://www.apple.com/safari'),
+
+            UA_BROWSER_PS3           => array(UA_PROP_NAME => 'Playstation 3',           UA_PROP_TYPE=>UA_BROWSER_TYPE_CONSOLE, UA_PROP_URL => 'http://us.playstation.com/ps3'),
+            UA_BROWSER_PSP           => array(UA_PROP_NAME => 'Playstation Portable',    UA_PROP_TYPE=>UA_BROWSER_TYPE_CONSOLE, UA_PROP_URL => 'http://us.playstation.com/psp'),
+            UA_BROWSER_BUNJALLOO     => array(UA_PROP_NAME => 'Bunjalloo',               UA_PROP_TYPE=>UA_BROWSER_TYPE_CONSOLE, UA_PROP_URL => 'http://code.google.com/p/quirkysoft/'),
+            UA_BROWSER_OPERA_WII     => array(UA_PROP_NAME => 'Opera',                   UA_PROP_TYPE=>UA_BROWSER_TYPE_CONSOLE, UA_PROP_URL => 'http://www.opera.com'),
+
+            UA_BROWSER_OPERA         => array(UA_PROP_NAME => 'Opera',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.opera.com'),
+            UA_BROWSER_SHIIRA        => array(UA_PROP_NAME => 'Shiira',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://shiira.jp/en'),
+            UA_BROWSER_THUNDERBIRD   => array(UA_PROP_NAME => 'Thunderbird',            UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.mozilla.org/thunderbird'),
+            UA_BROWSER_NAMOROKA      => array(UA_PROP_NAME => 'Namoroka',               UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'https://wiki.mozilla.org/Firefox/Namoroka'),
+            UA_BROWSER_MINEFIELD     => array(UA_PROP_NAME => 'Minefield',              UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.mozilla.org/projects/minefield'),
+            UA_BROWSER_LUNASCAPE     => array(UA_PROP_NAME => 'Lunascape',              UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.lunascape.tv'),
+            UA_BROWSER_ARORA         => array(UA_PROP_NAME => 'Arora',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://code.google.com/p/arora'),
+            UA_BROWSER_CAMINO        => array(UA_PROP_NAME => 'Camino',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://caminobrowser.org'),
+            UA_BROWSER_KAPIKO        => array(UA_PROP_NAME => 'Kapiko',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://ufoxlab.googlepages.com/cooperation'),
+            UA_BROWSER_KAZEHAKAZE    => array(UA_PROP_NAME => 'Kazehakase',             UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://kazehakase.sourceforge.jp'),
+            UA_BROWSER_CHROMEPLUS    => array(UA_PROP_NAME => 'ChromePlus',             UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://coolnovo.com'),
+            UA_BROWSER_CHROME        => array(UA_PROP_NAME => 'Chrome',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.google.com/chrome'),
+            UA_BROWSER_EPIPHANY      => array(UA_PROP_NAME => 'Epiphany',               UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://projects.gnome.org/epiphany'),
+            UA_BROWSER_GALEON        => array(UA_PROP_NAME => 'Galeon',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://galeon.sourceforge.net'),
+            UA_BROWSER_ORCA          => array(UA_PROP_NAME => 'Orca',                   UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.orcabrowser.com'),
+            UA_BROWSER_LOBO          => array(UA_PROP_NAME => 'Lobo',                   UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://lobobrowser.org'),
+            UA_BROWSER_SEAMONKEY     => array(UA_PROP_NAME => 'SeaMonkey',              UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.seamonkey-project.org'),
+            UA_BROWSER_MIDORI        => array(UA_PROP_NAME => 'Midori',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://twotoasts.de/?/pages/midori_summary.html'),
+            UA_BROWSER_MAXTHON       => array(UA_PROP_NAME => 'Maxthon',                UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.maxthon.com'),
+            UA_BROWSER_ICEAPE        => array(UA_PROP_NAME => 'Iceape',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://packages.debian.org/fr/squeeze/iceape-browser'),
+            UA_BROWSER_ICEWEASEL     => array(UA_PROP_NAME => 'Iceweasel',              UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.geticeweasel.org'),
+            UA_BROWSER_NETSCAPE      => array(UA_PROP_NAME => 'Netscape',               UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://isp.netscape.com'),
+            UA_BROWSER_FIREBIRD      => array(UA_PROP_NAME => 'Firebird',               UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.firefox.com'),
+            UA_BROWSER_FIREFOX       => array(UA_PROP_NAME => 'Firefox',                UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.firefox.com'),
+            UA_BROWSER_INTERNET_EXPLORER=> array(UA_PROP_NAME => 'Internet Explorer',   UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://windows.microsoft.com/en-us/internet-explorer/products/ie/home'),
+            UA_BROWSER_KONQUEROR     => array(UA_PROP_NAME => 'Konqueror',              UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.konqueror.org'),
+            UA_BROWSER_LINKS         => array(UA_PROP_NAME => 'Links',                  UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.jikos.cz/~mikulas/links'),
+            UA_BROWSER_LYNX          => array(UA_PROP_NAME => 'Lynx',                   UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://lynx.browser.org'),
+            UA_BROWSER_SAFARI        => array(UA_PROP_NAME => 'Safari',                 UA_PROP_TYPE=>UA_BROWSER_TYPE_COMPUTER, UA_PROP_URL => 'http://www.apple.com/safari')
           ),
 
   UA_DATA_OS => array(
-            UA_OS_UNKNOWN            => array(UA_PROP_NAME => 'Unknown',                UA_PROP_URL=>''),
-            UA_OS_LINUX              => array(UA_PROP_NAME => 'Linux',                  UA_PROP_URL=>'http://www.linux.com'),
-            UA_OS_FREEBSD            => array(UA_PROP_NAME => 'FreeBSD',                UA_PROP_URL=>'http://www.freebsd.org/'),
-            UA_OS_OPENBSD            => array(UA_PROP_NAME => 'OpenBSD',                UA_PROP_URL=>'http://www.openbsd.org/'),
-            UA_OS_NETBSD             => array(UA_PROP_NAME => 'NetBSD',                 UA_PROP_URL=>'http://www.netbsd.org/'),
-            UA_OS_WINDOWS            => array(UA_PROP_NAME => 'Windows',                UA_PROP_URL=>'http://windows.microsoft.com/'),
-            UA_OS_SUNOS              => array(UA_PROP_NAME => 'SunOS',                  UA_PROP_URL=>''),
-            UA_OS_BLACKBERRY         => array(UA_PROP_NAME => 'Blackberry OS',          UA_PROP_URL=>'http://us.blackberry.com/apps-software/devices'),
-            UA_OS_SYMBIAN_OS         => array(UA_PROP_NAME => 'Symbian OS',             UA_PROP_URL=>'http://symbian.nokia.com/'),
-            UA_OS_SYMBOS             => array(UA_PROP_NAME => 'SymbOS',                 UA_PROP_URL=>'http://www.symbos.de/'),
-            UA_OS_MACINTOSH          => array(UA_PROP_NAME => 'Macintosh',              UA_PROP_URL=>'http://www.apple.com/'),
-            UA_OS_MAC_OS_X           => array(UA_PROP_NAME => 'Mac OS X',               UA_PROP_URL=>'http://www.apple.com/'),
-            UA_OS_ANDROID            => array(UA_PROP_NAME => 'Android',                UA_PROP_URL=>'http://www.android.com/'),
-            UA_OS_IOS                => array(UA_PROP_NAME => 'iOS',                    UA_PROP_URL=>'http://www.apple.com/'),
-            UA_OS_NINTENDO_DS        => array(UA_PROP_NAME => 'Nintendo DS',            UA_PROP_URL=>''),
-            UA_OS_NINTENDO_WII       => array(UA_PROP_NAME => 'Nintendo Wii',           UA_PROP_URL=>''),
-            UA_OS_SONY_PS3           => array(UA_PROP_NAME => 'Sony PS3',               UA_PROP_URL=>''),
-            UA_OS_SONY_PSP           => array(UA_PROP_NAME => 'Sony PSP',               UA_PROP_URL=>'')
+            UA_OS_UNKNOWN            => array(UA_PROP_NAME => 'Unknown',                UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>''),
+            UA_OS_LINUX              => array(UA_PROP_NAME => 'Linux',                  UA_PROP_TYPE=>UA_OS_TYPE_LINUX,     UA_PROP_URL=>'http://www.linux.com'),
+            UA_OS_FREEBSD            => array(UA_PROP_NAME => 'FreeBSD',                UA_PROP_TYPE=>UA_OS_TYPE_BSD,       UA_PROP_URL=>'http://www.freebsd.org'),
+            UA_OS_OPENBSD            => array(UA_PROP_NAME => 'OpenBSD',                UA_PROP_TYPE=>UA_OS_TYPE_BSD,       UA_PROP_URL=>'http://www.openbsd.org'),
+            UA_OS_NETBSD             => array(UA_PROP_NAME => 'NetBSD',                 UA_PROP_TYPE=>UA_OS_TYPE_BSD,       UA_PROP_URL=>'http://www.netbsd.org'),
+            UA_OS_WINDOWS            => array(UA_PROP_NAME => 'Windows',                UA_PROP_TYPE=>UA_OS_TYPE_WINDOWS,   UA_PROP_URL=>'http://windows.microsoft.com'),
+            UA_OS_SUNOS              => array(UA_PROP_NAME => 'SunOS',                  UA_PROP_TYPE=>UA_OS_TYPE_UNIX,      UA_PROP_URL=>''),
+            UA_OS_BLACKBERRY         => array(UA_PROP_NAME => 'Blackberry OS',          UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://us.blackberry.com/apps-software/devices'),
+            UA_OS_SYMBIAN_OS         => array(UA_PROP_NAME => 'Symbian OS',             UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://symbian.nokia.com'),
+            UA_OS_SYMBOS             => array(UA_PROP_NAME => 'SymbOS',                 UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://www.symbos.de'),
+            UA_OS_MACINTOSH          => array(UA_PROP_NAME => 'Macintosh',              UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://www.apple.com'),
+            UA_OS_MAC_OS_X           => array(UA_PROP_NAME => 'Mac OS X',               UA_PROP_TYPE=>UA_OS_TYPE_BSD,       UA_PROP_URL=>'http://www.apple.com'),
+            UA_OS_ANDROID            => array(UA_PROP_NAME => 'Android',                UA_PROP_TYPE=>UA_OS_TYPE_LINUX,     UA_PROP_URL=>'http://www.android.com'),
+            UA_OS_IOS                => array(UA_PROP_NAME => 'iOS',                    UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://www.apple.com'),
+            UA_OS_NINTENDO_DS        => array(UA_PROP_NAME => 'Nintendo DS',            UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://www.nintendo.com/ds'),
+            UA_OS_NINTENDO_WII       => array(UA_PROP_NAME => 'Nintendo Wii',           UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://www.nintendo.com/wii'),
+            UA_OS_SONY_PS3           => array(UA_PROP_NAME => 'Sony PS3',               UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://us.playstation.com/ps3'),
+            UA_OS_SONY_PSP           => array(UA_PROP_NAME => 'Sony PSP',               UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://us.playstation.com/psp'),
+            UA_OS_CHROME_OS          => array(UA_PROP_NAME => 'Chrome OS',              UA_PROP_TYPE=>UA_OS_TYPE_LINUX,     UA_PROP_URL=>''),
+            UA_OS_BE_OS              => array(UA_PROP_NAME => 'BeOS',                   UA_PROP_TYPE=>UA_OS_TYPE_BSD,       UA_PROP_URL=>''),
+            UA_OS_DRAGONFLY          => array(UA_PROP_NAME => 'DragonFly BSD',          UA_PROP_TYPE=>UA_OS_TYPE_BSD,       UA_PROP_URL=>'http://www.dragonflybsd.org'),
+            UA_OS_UNIX               => array(UA_PROP_NAME => 'UNIX',                   UA_PROP_TYPE=>UA_OS_TYPE_UNIX,      UA_PROP_URL=>''),
+            UA_OS_DARWIN             => array(UA_PROP_NAME => 'Darwin',                 UA_PROP_TYPE=>UA_OS_TYPE_BSD,       UA_PROP_URL=>'developer.apple.com/darwin'),
+            UA_OS_OS2                => array(UA_PROP_NAME => 'IBM OS/2',               UA_PROP_TYPE=>UA_OS_TYPE_OS2,       UA_PROP_URL=>''),
+            UA_OS_AMIGAOS            => array(UA_PROP_NAME => 'AmigaOS',                UA_PROP_TYPE=>UA_OS_TYPE_UNKNOWN,   UA_PROP_URL=>'http://amiga.com')
           ),
   UA_DATA_ENGINE => array(
-            UA_ENGINE_UNKNOWN        => array(UA_PROP_NAME => 'Unknown'),
-            UA_ENGINE_GECKO          => array(UA_PROP_NAME => 'Gecko'),
-            UA_ENGINE_KHTML          => array(UA_PROP_NAME => 'KHTML'),
-            UA_ENGINE_PRESTO         => array(UA_PROP_NAME => 'Presto'),
-            UA_ENGINE_APPLEWEBKIT    => array(UA_PROP_NAME => 'AppleWebKit'),
-            UA_ENGINE_WEBKIT         => array(UA_PROP_NAME => 'WebKit'),
-            UA_ENGINE_TRIDENT        => array(UA_PROP_NAME => 'Trident')
+            UA_ENGINE_UNKNOWN        => array(UA_PROP_NAME => 'Unknown',                UA_PROP_URL=>''),
+            UA_ENGINE_GECKO          => array(UA_PROP_NAME => 'Gecko',                  UA_PROP_URL=>'https://developer.mozilla.org/en/Gecko'),
+            UA_ENGINE_KHTML          => array(UA_PROP_NAME => 'KHTML',                  UA_PROP_URL=>'http://api.kde.org/3.5-api/kdelibs-apidocs/khtml/html/index.html'),
+            UA_ENGINE_PRESTO         => array(UA_PROP_NAME => 'Presto',                 UA_PROP_URL=>'http://dev.opera.com/articles/view/presto-2-1-web-standards-supported-by'),
+            UA_ENGINE_APPLEWEBKIT    => array(UA_PROP_NAME => 'AppleWebKit',            UA_PROP_URL=>''),
+            UA_ENGINE_WEBKIT         => array(UA_PROP_NAME => 'WebKit',                 UA_PROP_URL=>'http://www.webkit.org'),
+            UA_ENGINE_TRIDENT        => array(UA_PROP_NAME => 'Trident',                UA_PROP_URL=>'http://msdn.microsoft.com/en-us/library/aa741317.aspx')
           ),
 
-  UA_DATA_PROP_NAME => array(
-            UA_PROP_TYPE_UNKNOWN          => 'Unknown',
-            UA_PROP_TYPE_BROWSER_COMPUTER => 'Computer',
-            UA_PROP_TYPE_BROWSER_CONSOLE  => 'Console',
-            UA_PROP_TYPE_BROWSER_MOBILE   => 'Mobile',
-            UA_PROP_TYPE_CRAWLER          => 'Crawler'
+  UA_DATA_BROWSER_TYPE => array(
+            UA_BROWSER_TYPE_UNKNOWN  => 'Unknown',
+            UA_BROWSER_TYPE_COMPUTER => 'Computer',
+            UA_BROWSER_TYPE_CONSOLE  => 'Console',
+            UA_BROWSER_TYPE_MOBILE   => 'Mobile',
+            UA_BROWSER_TYPE_CRAWLER  => 'Crawler'
+          ),
+
+  UA_DATA_OS_TYPE => array(
+            UA_OS_TYPE_UNKNOWN  => 'Unknown',
+            UA_OS_TYPE_LINUX    => 'Linux',
+            UA_OS_TYPE_BSD      => 'BSD',
+            UA_OS_TYPE_UNIX     => 'Unix',
+            UA_OS_TYPE_WINDOWS  => 'Windows',
+            UA_OS_TYPE_OS2      => 'OS/2'
           )
+
 );
 
Index: tensions/GrumPluginClasses/css/tagSelector_clear.css
===================================================================
--- /extensions/GrumPluginClasses/css/tagSelector_clear.css	(revision 16457)
+++ 	(revision )
@@ -1,62 +1,0 @@
-/* for tagSelector plugin */
-.ui-tag-selector-input { padding:1px; }
-.ui-tag-selector-input input { border:none; background:transparent; }
-.ui-tag-selector-list { margin-top:-1px; }
-.ui-tag-selector-selected-tag-list { list-style:none; margin:0; padding:0; }
-.ui-tag-selector-selected-tag-list li span {
-  font-family:sans;
-  font-size:80%;
-  font-weight:bold;
-  padding:0 3px;
-  position:relative;
-  top:-1px;
-}
-li.ui-tag-selector-list-item, .ui-tag-selector-text { padding:2px; }
-.ui-tag-selector-selected-tag-list li.ui-tag-selector-selected-tag {
-  -moz-border-radius:8px;
-  -webkit-border-radius:8px;
-  -khtml-border-radius:8px;
-  border-radius:8px;
-  float:left;
-  margin-bottom:1px;
-  margin-right:1px;
-  padding:0 4px;
-  cursor:default;
-}
-.ui-tag-selector-selected-tag-list li.ui-tag-selector-selected-tag span { cursor:pointer; }
-
-/* clear css */
-
-
-.ui-tag-selector-list, .ui-tag-selector-input {
-  background:#DDDDDD;
-  border:1px solid #999999;
-  color:#666666;
-}
-
-.ui-tag-selector-text {
-  font-style:italic;
-  font-size:80%;
-  border-top:1px dotted #999999;
-  background:#DDDDDD;
-  color:#666666;
-}
-
-li.ui-tag-selector-list-item:hover {
-  background:#AAAAAA;
-  color:#DDDDDD;
-  cursor:pointer;
-}
-
-.ui-tag-selector-selected-tag-list li.ui-tag-selector-selected-tag {
-  background:#999999;
-  color:#DDDDDD;
-  margin-top:1px;
-  padding-top:1px;
-}
-
-.ui-tag-selector-highlight {
-  color:#005E89;
-  font-weight:bold;
-  background:#999999;
-}
Index: tensions/GrumPluginClasses/css/tagSelector_roma.css
===================================================================
--- /extensions/GrumPluginClasses/css/tagSelector_roma.css	(revision 16457)
+++ 	(revision )
@@ -1,66 +1,0 @@
-/* for tagSelector plugin */
-.ui-tag-selector-input { padding:1px; }
-.ui-tag-selector-input input { border:none; background:transparent; }
-.ui-tag-selector-list { margin-top:-1px; }
-.ui-tag-selector-selected-tag-list { list-style:none; margin:0; padding:0; }
-.ui-tag-selector-selected-tag-list li span {
-  font-family:sans;
-  font-size:80%;
-  font-weight:bold;
-  padding:0 3px;
-  position:relative;
-  top:-1px;
-}
-li.ui-tag-selector-list-item, .ui-tag-selector-text { padding:2px; }
-.ui-tag-selector-selected-tag-list li.ui-tag-selector-selected-tag {
-  -moz-border-radius:8px;
-  -webkit-border-radius:8px;
-  -khtml-border-radius:8px;
-  border-radius:8px;
-  float:left;
-  margin-bottom:1px;
-  margin-right:1px;
-  padding:0 4px;
-  cursor:default;
-}
-.ui-tag-selector-selected-tag-list li.ui-tag-selector-selected-tag span { cursor:pointer; }
-
-/* roma css */
-
-.ui-tag-selector-list, .ui-tag-selector-input {
-  background:#444444;
-  border:1px solid #666666;
-  color:#999999;
-}
-
-.ui-tag-selector-text {
-  font-style:italic;
-  font-size:80%;
-  border-top:1px dotted #666666;
-  background:#444444;
-  color:#999999;
-}
-
-li.ui-tag-selector-list-item:hover {
-  background:#666666;
-  cursor:pointer;
-}
-
-.ui-tag-selector-selected-tag-list li.ui-tag-selector-selected-tag {
-  background:#666666;
-  color:#999999;
-  margin-top:1px;
-  padding-top:1px;
-}
-
-.ui-tag-selector-highlight {
-  color:#FF7700;
-  font-weight:bold;
-  background:#666666;
-}
-
-.ui-error, input[type='text'].ui-error {
-  background:#ff8080;
-  border-color:#800000;
-  color:#800000;
-}
Index: /extensions/GrumPluginClasses/js/markup.formMail.js
===================================================================
--- /extensions/GrumPluginClasses/js/markup.formMail.js	(revision 16457)
+++ /extensions/GrumPluginClasses/js/markup.formMail.js	(revision 16458)
@@ -10,6 +10,5 @@
  * Author     : Grum
  *   email    : grum@piwigo.com
- *   website  : http://photos.grum.fr
- *   PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+ *   website  : http://www.grum.fr
  *
  *   << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/js/markup.tabs.js
===================================================================
--- /extensions/GrumPluginClasses/js/markup.tabs.js	(revision 16457)
+++ /extensions/GrumPluginClasses/js/markup.tabs.js	(revision 16458)
@@ -10,6 +10,5 @@
  * Author     : Grum
  *   email    : grum@piwigo.com
- *   website  : http://photos.grum.fr
- *   PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+ *   website  : http://www.grum.fr
  *
  *   << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/js/pagesNavigator.js
===================================================================
--- /extensions/GrumPluginClasses/js/pagesNavigator.js	(revision 16457)
+++ /extensions/GrumPluginClasses/js/pagesNavigator.js	(revision 16458)
@@ -10,6 +10,5 @@
  * Author     : Grum
  *   email    : grum@piwigo.com
- *   website  : http://photos.grum.fr
- *   PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+ *   website  : http://www.grum.fr
  *
  *   << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/js/rbCriteriaBuilder.js
===================================================================
--- /extensions/GrumPluginClasses/js/rbCriteriaBuilder.js	(revision 16457)
+++ /extensions/GrumPluginClasses/js/rbCriteriaBuilder.js	(revision 16458)
@@ -10,6 +10,5 @@
  * Author     : Grum
  *   email    : grum@piwigo.com
- *   website  : http://photos.grum.fr
- *   PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+ *   website  : http://www.grum.fr
  *
  *   << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/js/rbSearch.js
===================================================================
--- /extensions/GrumPluginClasses/js/rbSearch.js	(revision 16457)
+++ /extensions/GrumPluginClasses/js/rbSearch.js	(revision 16458)
@@ -10,6 +10,5 @@
  * Author     : Grum
  *   email    : grum@piwigo.com
- *   website  : http://photos.grum.fr
- *   PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+ *   website  : http://www.grum.fr
  *
  *   << May the Little SpaceFrog be with you ! >>
Index: /extensions/GrumPluginClasses/js/simpleTip.js
===================================================================
--- /extensions/GrumPluginClasses/js/simpleTip.js	(revision 16457)
+++ /extensions/GrumPluginClasses/js/simpleTip.js	(revision 16458)
@@ -10,6 +10,5 @@
  * Author     : Grum
  *   email    : grum@piwigo.com
- *   website  : http://photos.grum.fr
- *   PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
+ *   website  : http://www.grum.fr
  *
  *   << May the Little SpaceFrog be with you ! >>
Index: tensions/GrumPluginClasses/js/ui.tagSelector.js
===================================================================
--- /extensions/GrumPluginClasses/js/ui.tagSelector.js	(revision 16457)
+++ 	(revision )
@@ -1,1314 +1,0 @@
-/**
- * -----------------------------------------------------------------------------
- * file: ui.tagSelector.js
- * file version: 1.0.0
- * date: 2010-10-22
- *
- * A jQuery plugin provided by the piwigo's plugin "GrumPluginClasses"
- *
- * -----------------------------------------------------------------------------
- * Author     : Grum
- *   email    : grum@piwigo.com
- *   website  : http://photos.grum.fr
- *   PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
- *
- *   << May the Little SpaceFrog be with you ! >>
- * -----------------------------------------------------------------------------
- *
- *
- *
- *
- * :: HISTORY ::
- *
- * | release | date       |
- * | 1.0.0   | 2010/10/10 | * first release
- * |         |            |
- * | 1.1.0   | 2010/11/03 | * add 'isValid' method
- * |         |            |
- * |         |            |
- * |         |            |
- * |         |            |
- * |         |            |
- *
- */
-
-
-
-(
-  function($)
-  {
-    /*
-     * plugin 'public' functions
-     */
-    var publicMethods =
-    {
-      init : function (opt)
-        {
-          return this.each(function()
-            {
-              // default values for the plugin
-              var $this=$(this),
-                  data = $this.data('options'),
-                  objects = $this.data('objects'),
-                  properties = $this.data('properties'),
-                  options =
-                    {
-                      ignoreCase:true,
-                      //allowCreate:false,
-                      serverUrl:'plugins/GrumPluginClasses/gpc_ajax.php',
-                      serverCallDelay:250,
-
-                      listMaxWidth:0,
-                      listMaxHeight:0,
-                      maximumTagLoaded:0,  //0 = no limits
-
-                      textStart:'Start to type text...',
-                      textFound:'%s tags found',
-                      textDisplay:'display only %s tags',
-
-                      mode:'public',
-                      filter:'affected',
-
-                      inputNumCar:5,
-
-                      add:null,
-                      remove:null,
-                      popup:null,
-                      load:null
-                    };
-
-              // if options given, merge it
-              // if(opt) $.extend(options, opt); ==> options are set by setters
-
-              $this.data('options', options);
-
-
-              if(!properties)
-              {
-                $this.data('properties',
-                  {
-                    initialized:false,
-                    selectorVisible:false,
-                    totalTags:0,
-                    tags:[], // a tag = {id:0, name:''}
-                    cache:[],
-                    timerHandle:null,
-                    isValid:true
-                  }
-                );
-                properties=$this.data('properties');
-              }
-
-              if(!objects)
-              {
-                objects =
-                  {
-                    container:$('<div/>',
-                        {
-                          'class':'ui-tag-selector-input',
-                          css:{
-                            width:'100%'
-                          }
-                        }
-                    ).bind('click.tagSelector',
-                        function ()
-                        {
-                          objects.input.focus();
-                        }
-                      ),
-                    selectedTagList:$('<ul/>',
-                      {
-                        html: '',
-                        'class':'ui-tag-selector-selected-tag-list'
-                      }
-                    ),
-                    input:$('<input>',
-                      {
-                        type:"text",
-                        value:''
-                      }
-                    ).bind('focusout.tagSelector',
-                        function ()
-                        {
-                          privateMethods.lostFocus($this);
-                        }
-                      )
-                      .bind('focus.tagSelector',
-                          function ()
-                          {
-                            privateMethods.getFocus($this);
-                          }
-                        )
-                      .bind('keypress.tagSelector',
-                          function ()
-                          {
-                            privateMethods.setTimerHandle($this);
-                          }
-                        ),
-                    selectorList:$('<div/>',
-                        {
-                          html: "",
-                          'class':'ui-tag-selector-list',
-                          css: {
-                            display:'none',
-                            position:'absolute',
-                            zIndex:9999
-                          }
-                        }
-                    ).bind('mouseleave.tagSelector',
-                        function ()
-                        {
-                          privateMethods.displaySelector($this, false);
-                        }
-                      ),
-                    tagList:$('<ul/>',
-                      {
-                        css: {
-                          listStyle:'none',
-                          padding:'0px',
-                          margin:'0px',
-                          overflow:"auto"
-                        }
-                      }
-                    ),
-                    textArea:$('<div/>',
-                      {
-                        html:'',
-                        'class':'ui-tag-selector-text'
-                      }
-                    )
-                  };
-
-                $this
-                  .html('')
-                  .append(objects.container.append(objects.selectedTagList.append($('<li/>').append(objects.input) ) ) )
-                  .append(objects.selectorList.append(objects.tagList).append(objects.textArea));
-
-                $this.data('objects', objects);
-              }
-
-              privateMethods.setOptions($this, opt);
-            }
-          );
-        }, // init
-      destroy : function ()
-        {
-          return this.each(
-            function()
-            {
-              // default values for the plugin
-              var $this=$(this),
-                  objects = $this.data('objects');
-              objects.selectedTagList.children().unbind();
-              objects.input.unbind().remove();
-              objects.container.unbind().remove();
-              objects.selectorList.unbind().remove();
-              objects.tagList.remove();
-              $this
-                .unbind('.categorySelector')
-                .css(
-                  {
-                    width:'',
-                    height:''
-                  }
-                );
-            }
-          );
-        }, // destroy
-
-      options: function (value)
-        {
-          return this.each(function()
-            {
-              privateMethods.setOptions($(this), value);
-            }
-          );
-        }, // autoLoad
-
-
-      ignoreCase: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setIgnoreCase($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.ignoreCase);
-            }
-            else
-            {
-              return(true);
-            }
-          }
-        }, // ignoreCase
-
-      inputNumCar: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setInputNumCar($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.inputNumCar);
-            }
-            else
-            {
-              return(true);
-            }
-          }
-        }, // ignoreCase
-
-/*
-      allowCreate: function (value)
-        {
-          if(value)
-          {
-            this.each(function()
-              {
-                var $this=$(this);
-                privateMethods.setAllowCreate($this, value);
-                return($this);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.allowCreate);
-            }
-            else
-            {
-              return(false);
-            }
-          }
-        }, // allowCreate
-*/
-      maximumTagLoaded: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setMaximumTagLoaded($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.maximumTagLoaded);
-            }
-            else
-            {
-              return(0);
-            }
-          }
-        }, // maximumTagLoaded
-
-      listMaxWidth: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setListMaxWidth($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.listMaxWidth);
-            }
-            else
-            {
-              return(0);
-            }
-          }
-        }, // listMaxWidth
-
-      listMaxHeight: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setListMaxHeight($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.listMaxHeight);
-            }
-            else
-            {
-              return(0);
-            }
-          }
-        }, // listMaxHeight
-
-
-      serverCallDelay: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setServerCallDelay($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.serverCallDelay);
-            }
-            else
-            {
-              return(0);
-            }
-          }
-        }, // serverCallDelay
-
-
-      serverUrl: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setServerUrl($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.serverUrl);
-            }
-            else
-            {
-              return('');
-            }
-          }
-        }, // serverUrl
-
-      textStart: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setTextStart($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.textStart);
-            }
-            else
-            {
-              return('');
-            }
-          }
-        }, // textStart
-
-      textFound: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setTextFound($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.textFound);
-            }
-            else
-            {
-              return('');
-            }
-          }
-        }, // textFound
-
-      textDisplay: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setTextDisplay($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.textDisplay);
-            }
-            else
-            {
-              return('');
-            }
-          }
-        }, // textDisplay
-
-      filter: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setFilter($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.filter);
-            }
-            else
-            {
-              return(true);
-            }
-          }
-        }, // filter
-
-      mode: function (value)
-        {
-          if(value!=null)
-          {
-            return this.each(function()
-              {
-                privateMethods.setMode($(this), value);
-              }
-            );
-          }
-          else
-          {
-            var options = this.data('options');
-
-            if(options)
-            {
-              return(options.mode);
-            }
-            else
-            {
-              return(true);
-            }
-          }
-        }, // mode
-
-      value: function (value)
-        {
-          if(value!=null)
-          {
-            // set selected value
-            return this.each(function()
-              {
-                privateMethods.setValue($(this), value);
-              }
-            );
-          }
-          else
-          {
-            // return the selected tags
-            var properties=this.data('properties');
-
-            return(properties.tags);
-          }
-        }, // value
-
-      isValid: function (value)
-        {
-          if(value!=null)
-          {
-            // set selected value
-            return this.each(function()
-              {
-                privateMethods.setIsValid($(this), value);
-              }
-            );
-          }
-          else
-          {
-            // return the selected tags
-            var properties=this.data('properties');
-
-            return(properties.isValid);
-          }
-        }, // isValid
-
-      load: function (value)
-        {
-          /*
-           * two functionnalities :
-           *  - if value is set, use it to set the load event function
-           *  - if no value, loads data from server
-           */
-          if(value && $.isFunction(value))
-          {
-            // set selected value
-            return this.each(function()
-              {
-                privateMethods.setEventLoad($(this), value);
-              }
-            );
-          }
-          else
-          {
-            // loads data from server
-            privateMethods.load(this);
-          }
-        },
-
-      popup: function (value)
-        {
-          if(value && $.isFunction(value))
-          {
-            // set selected value
-            return this.each(function()
-              {
-                privateMethods.setEventPopup($(this), value);
-              }
-            );
-          }
-          else
-          {
-            // return the selected value
-            var options=this.data('options');
-
-            if(options)
-            {
-              return(options.popup);
-            }
-            else
-            {
-              return(null);
-            }
-          }
-        }, // popup
-      add: function (value)
-        {
-          if(value && $.isFunction(value))
-          {
-            // set selected value
-            return this.each(function()
-              {
-                privateMethods.setEventAdd($(this), value);
-              }
-            );
-          }
-          else
-          {
-            // return the selected value
-            var options=this.data('options');
-
-            if(options)
-            {
-              return(options.add);
-            }
-            else
-            {
-              return(null);
-            }
-          }
-        }, // add
-      remove: function (value)
-        {
-          if(value && $.isFunction(value))
-          {
-            // set selected value
-            return this.each(function()
-              {
-                privateMethods.setEventRemove($(this), value);
-              }
-            );
-          }
-          else
-          {
-            // return the selected value
-            var options=this.data('options');
-
-            if(options)
-            {
-              return(options.remove);
-            }
-            else
-            {
-              return(null);
-            }
-          }
-        }, // remove
-      numberOfTags: function ()
-        {
-          var properties=this.data('properties');
-
-          if(properties)
-          {
-            return(properties.tags.length);
-          }
-          else
-          {
-            return(null);
-          }
-        } // numberOfTags
-
-    }; // methods
-
-
-    /*
-     * plugin 'private' methods
-     */
-    var privateMethods =
-    {
-      setOptions : function (object, value)
-        {
-          var properties=object.data('properties'),
-              options=object.data('options');
-
-          if(!$.isPlainObject(value)) return(false);
-
-          properties.initialized=false;
-
-          privateMethods.setIgnoreCase(object, (value.ignoreCase!=null)?value.ignoreCase:options.ignoreCase);
-          privateMethods.setInputNumCar(object, (value.inputNumCar!=null)?value.inputNumCar:options.inputNumCar);
-          //privateMethods.setAllowCreate(object, (value.allowCreate!=null)?value.allowCreate:options.allowCreate);
-          privateMethods.setValue(object, (value.value!=null)?value.value:[]);
-          privateMethods.setMaximumTagLoaded(object, (value.maximumTagLoaded!=null)?value.maximumTagLoaded:options.maximumTagLoaded);
-          privateMethods.setTextStart(object, (value.textStart!=null)?value.textStart:options.textStart);
-          privateMethods.setTextFound(object, (value.textFound!=null)?value.textFound:options.textFound);
-          privateMethods.setTextDisplay(object, (value.textDisplay!=null)?value.textDisplay:options.textDisplay);
-          privateMethods.setListMaxWidth(object, (value.listMaxWidth!=null)?value.listMaxWidth:options.listMaxWidth);
-          privateMethods.setListMaxHeight(object, (value.listMaxHeight!=null)?value.listMaxHeight:options.listMaxHeight);
-          privateMethods.setServerCallDelay(object, (value.serverCallDelay!=null)?value.serverCallDelay:options.serverCallDelay);
-          privateMethods.setServerUrl(object, (value.serverUrl!=null)?value.serverUrl:options.serverUrl);
-          privateMethods.setMode(object, (value.mode!=null)?value.mode:options.mode);
-          privateMethods.setFilter(object, (value.filter!=null)?value.filter:options.filter);
-          privateMethods.setEventPopup(object, (value.popup!=null)?value.popup:options.popup);
-          privateMethods.setEventAdd(object, (value.add!=null)?value.add:options.add);
-          privateMethods.setEventRemove(object, (value.remove!=null)?value.remove:options.remove);
-          privateMethods.setEventLoad(object, (value.load!=null)?value.load:options.load);
-
-          if(options.autoLoad) privateMethods.load(object);
-
-          properties.initialized=true;
-        },
-
-      setIsValid : function (object, value)
-        {
-          var objects=object.data('objects'),
-              properties=object.data('properties');
-
-          if(properties.isValid!=value)
-          {
-            properties.isValid=value;
-            if(properties.isValid)
-            {
-              objects.container.removeClass('ui-error');
-              objects.input.removeClass('ui-error');
-            }
-            else
-            {
-              objects.container.addClass('ui-error');
-              objects.input.addClass('ui-error');
-            }
-          }
-          return(properties.isValid);
-        },
-
-      setIgnoreCase : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if((!properties.initialized || options.ignoreCase!=value) && (value==true || value==false))
-          {
-            options.ignoreCase=value;
-          }
-          return(options.ignoreCase);
-        },
-
-      setInputNumCar : function (object, value)
-        {
-          var options=object.data('options'),
-              objects=object.data('objects'),
-              properties=object.data('properties');
-
-          if((!properties.initialized || options.inputNumCar!=value) && value>0)
-          {
-            options.inputNumCar=value;
-            objects.input.attr('size', options.inputNumCar);
-          }
-          return(options.inputNumCar);
-        },
-
-/*
-      setAllowCreate : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-          if((!properties.initialized || options.allowCreate!=value) && (value==true || value==false))
-          {
-            options.allowCreate=value;
-          }
-          return(options.allowCreate);
-        },
-*/
-
-      setMaximumTagLoaded : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if((!properties.initialized || options.setMaximumTagLoaded!=value) && value>=0)
-          {
-            options.maximumTagLoaded=value;
-          }
-          return(options.maximumTagLoaded);
-        },
-
-
-      setTextStart : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if(!properties.initialized || options.textStart!=value)
-          {
-            options.textStart=value;
-          }
-          return(options.textStart);
-        },
-
-      setTextFound : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if(!properties.initialized || options.textFound!=value)
-          {
-            options.textFound=value;
-          }
-          return(options.textFound);
-        },
-
-      setTextDisplay : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if(!properties.initialized || options.textDisplay!=value)
-          {
-            options.textDisplay=value;
-          }
-          return(options.textDisplay);
-        },
-
-      setListMaxWidth : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties'),
-              objects=object.data('objects');
-
-          if((!properties.initialized || options.listMaxWidth!=value) && value>=0)
-          {
-            options.listMaxWidth=value;
-            if(options.listMaxWidth>0)
-            {
-              objects.selectorList.css('max-width', options.listMaxWidth+'px');
-            }
-            else
-            {
-              objects.selectorList.css('max-width', '');
-            }
-          }
-          return(options.listMaxWidth);
-        },
-
-      setListMaxHeight : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties'),
-              objects=object.data('objects');
-
-          if((!properties.initialized || options.listMaxHeight!=value) && value>=0)
-          {
-            options.listMaxHeight=value;
-            if(options.listMaxHeight>0)
-            {
-              objects.tagList.css('max-height', options.listMaxHeight+'px');
-            }
-            else
-            {
-              objects.tagList.css('max-height', '');
-            }
-          }
-          return(options.listMaxHeight);
-        },
-
-      setServerCallDelay : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if((!properties.initialized || options.serverCallDelay!=value) && value>0 )
-          {
-            options.serverCallDelay=value;
-          }
-          return(options.serverCallDelay);
-        },
-
-      setServerUrl : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if(!properties.initialized || options.serverUrl!=value)
-          {
-            options.serverUrl=value;
-            if(options.autoLoad && properties.initialized) privateMethods.load(object);
-          }
-          return(options.serverUrl);
-        },
-
-
-      setMode : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if((!properties.initialized || options.mode!=value) && (value=='admin' || value=='public'))
-          {
-            options.mode=value;
-          }
-          return(options.mode);
-        },
-
-      setFilter : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties');
-
-          if((!properties.initialized || options.filter!=value) && (value=='all' || value=='affected'))
-          {
-            options.filter=value;
-          }
-          return(options.filter);
-        },
-
-
-      setValue : function (object, value)
-        {
-          var properties=object.data('properties'),
-              objects=object.data('objects');
-
-          if(value=='clear')
-          {
-            properties.tags=[];
-            objects.selectedTagList.children('.ui-tag-selector-selected-tag').remove();
-            privateMethods.cacheClear(object);
-            objects.input.val('');
-          }
-          else
-          {
-            if(!$.isArray(value))
-            {
-              value=[value]; //works with array only
-            }
-
-            for(var i=0;i<value.length;i++)
-            {
-              if(value[i].id!=null && value[i].name!=null)
-              {
-                // remove tag if present, otherwise add it
-                if(privateMethods.removeTag(object, value[i].id)==-1) privateMethods.addTag(object, value[i].id, value[i].name);
-              }
-              else
-              {
-                //not an object, consider it's a tag id to be removed
-                privateMethods.removeTag(object, value[i]);
-              }
-            }
-          }
-
-          return(null);
-        }, //setValue
-
-
-      displaySelector : function (object, value)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties'),
-              objects=object.data('objects'),
-              popup=false;
-
-          if(properties.selectorVisible!=value) popup=true;;
-
-          properties.selectorVisible=value;
-
-          if(properties.selectorVisible)
-          {
-            if(properties.cache.length>0)
-            {
-              objects.tagList.css('display', 'block');
-              if(properties.cache.length<properties.totalTags)
-              {
-                objects.textArea.html(
-                  options.textFound.replace('%s', properties.totalTags)+', '+
-                  options.textDisplay.replace('%s', properties.cache.length)
-                ).css('display', 'block');
-              }
-              else
-              {
-                objects.textArea.html(options.textFound.replace('%s', properties.cache.length)).css('display', 'block');
-              }
-            }
-            else if(options.textStart!='')
-            {
-              objects.tagList.css('display', 'none');
-              objects.textArea.html(options.textStart).css('display', 'block');
-            }
-            else
-            {
-              objects.textArea.html('').css('display', 'none');
-            }
-
-            objects.selectorList
-              .css(
-                {
-                  display:'block',
-                  'min-width':objects.selectorList.parent().css('width')
-                }
-              );
-          }
-          else
-          {
-            objects.selectorList.css('display', 'none');
-          }
-
-          if(options.popup && popup) object.trigger('tagSelectorPopup', [properties.selectorVisible]);
-
-          return(properties.selectorVisible);
-        }, //displaySelector
-
-      load : function (object)
-        {
-          // load datas from server through an asynchronous ajax call
-          var options=object.data('options'),
-              properties=object.data('properties'),
-              objects=object.data('objects');
-
-          privateMethods.clearTimerHandle(object);
-
-          if(objects.input.val()=='')
-          {
-            privateMethods.cacheClear(object);
-            privateMethods.displaySelector(object, true);
-            return(false);
-          }
-
-
-          $.ajax(
-            {
-              type: "POST",
-              url: options.serverUrl,
-              data: {
-                ajaxfct:options.mode+'.tagSelector.get',
-                filter:options.filter,
-                maxTags:options.maximumTagLoaded,
-                ignoreCase:options.ignoreCase,
-                letters:objects.input.val()
-              },
-              async: true,
-              success: function(msg)
-                {
-                  list=$.parseJSON(msg);
-
-                  properties.totalTags=list.totalNbTags;
-                  privateMethods.cacheClear(object);
-                  privateMethods.cacheAddItems(object, list.tags);
-                  if(options.load) object.trigger('tagSelectorLoad');
-
-                  privateMethods.displaySelector(object, true);
-                },
-              error: function(msg)
-                {
-                  objects.selectorList.html('Error ! '+msg);
-                }
-            }
-         );
-        },
-
-      cacheClear : function (object)
-        {
-          // clear the cache tag list
-          var objects=object.data('objects'),
-              properties=object.data('properties');
-
-          objects.tagList.children().unbind().remove();
-          properties.cache=[];
-        },
-
-      cacheAddItems : function (object, listItems)
-        {
-          // add the items to the cache list
-          var options=object.data('options'),
-              properties=object.data('properties'),
-              objects=object.data('objects');
-
-          for(var i=0;i<listItems.length;i++)
-          {
-            properties.cache.push(
-              {
-                id:listItems[i].id,
-                name:listItems[i].name
-              }
-            );
-
-            if(options.ignoreCase)
-            {
-              var re=new RegExp('(.*)('+objects.input.val()+')(.*)', 'i');
-            }
-            else
-            {
-              var re=new RegExp('(.*)('+objects.input.val()+')(.*)');
-            }
-            tmpResult=re.exec(listItems[i].name);
-            if(tmpResult!=null)
-            {
-              tmpResult=tmpResult[1]+'<span class="ui-tag-selector-highlight">'+tmpResult[2]+'</span>'+tmpResult[3];
-            }
-            else
-            {
-              tmpResult=listItems[i].name;
-            }
-
-            var li=$('<li/>',
-                      {
-                        html:tmpResult,
-                        value:listItems[i].id,
-                        'class':'ui-tag-selector-list-item'
-                      }
-                    ).bind('mousedown.tagSelector',
-                          {object:object},
-                          function (event)
-                          {
-                            privateMethods.addTag(event.data.object, $(this).attr('value'), $(this).text());
-                          }
-                      );
-            objects.tagList.append(li);
-          }
-        },
-
-      addTag : function (object, id, name)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties'),
-              objects=object.data('objects');
-
-          if(privateMethods.findTagById(object, id)==-1)
-          {
-            //add only if not already selected..
-            properties.tags.push({id:id, name:name});
-
-            var li=$('<li/>',
-                      {
-                        value:id,
-                        html:name,
-                        'class':'ui-tag-selector-selected-tag'
-                      }
-                    ).prepend(
-                      $('<span/>',
-                        {
-                          html:'x'
-                        }
-                       ).bind('click.tagSelector',
-                          {object:object},
-                          function (event)
-                          {
-                            privateMethods.removeTag(event.data.object, $(this).parent().attr('value'));
-                          }
-                        )
-                      );
-            objects.input.val('').parent().before(li);
-            if(options.add) object.trigger('tagSelectorAdd', id);
-          }
-        },
-
-      removeTag : function (object, id)
-        {
-          var options=object.data('options'),
-              properties=object.data('properties'),
-              objects=object.data('objects');
-
-          var index=privateMethods.findTagById(object, id);
-          if(index>-1)
-          {
-            properties.tags.splice(index,1);
-            objects.selectedTagList.children('[value='+id+']').remove();
-
-            if(options.remove) object.trigger('tagSelectorRemove', id);
-          }
-          return(index);
-        },
-
-      findTagById : function (object, value)
-        {
-          var properties=object.data('properties');
-
-          for(var i=0;i<properties.tags.length;i++)
-          {
-            if(properties.tags[i].id==value) return(i);
-          }
-          return(-1);
-        },
-
-      getFocus : function (object)
-        {
-          privateMethods.displaySelector(object, true);
-        },
-
-      lostFocus : function (object)
-        {
-          privateMethods.displaySelector(object, false);
-        },
-
-      setEventPopup : function (object, value)
-        {
-          var options=object.data('options');
-
-          options.popup=value;
-          object.unbind('tagSelectorPopup');
-          if(value) object.bind('tagSelectorPopup', options.popup);
-          return(options.popup);
-        },
-
-      setEventAdd : function (object, value)
-        {
-          var options=object.data('options');
-
-          options.add=value;
-          object.unbind('tagSelectorAdd');
-          if(value) object.bind('tagSelectorAdd', options.add);
-          return(options.add);
-        },
-
-      setEventRemove : function (object, value)
-        {
-          var options=object.data('options');
-
-          options.remove=value;
-          object.unbind('tagSelectorRemove');
-          if(value) object.bind('tagSelectorRemove', options.remove);
-          return(options.remove);
-        },
-
-      setEventLoad : function (object, value)
-        {
-          var options=object.data('options');
-          options.load=value;
-          object.unbind('categorySelectorLoad');
-          if(value) object.bind('tagSelectorLoad', options.load);
-          return(options.load);
-        },
-
-      clearTimerHandle : function(object)
-        {
-          var properties=object.data('properties');
-
-          if(properties.timerHandle!=null)
-          {
-            window.clearInterval(properties.timerHandle);
-            properties.timerHandle=null;
-          }
-        },
-
-      setTimerHandle : function(object)
-        {
-          var properties=object.data('properties'),
-              options=object.data('options');
-
-          privateMethods.clearTimerHandle(object);
-          properties.timerHandle=window.setInterval(function () { privateMethods.load(object); }, options.serverCallDelay);
-        },
-    };
-
-
-    $.fn.tagSelector = function(method)
-    {
-      if(publicMethods[method])
-      {
-        return publicMethods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
-      }
-      else if(typeof method === 'object' || ! method)
-      {
-        return publicMethods.init.apply(this, arguments);
-      }
-      else
-      {
-        $.error( 'Method ' +  method + ' does not exist on jQuery.tagSelector' );
-      }
-    } // $.fn.tagSelector
-
-  }
-)(jQuery);
-
-
