diff --git a/dev/skeletons/skeleton_list.php b/dev/skeletons/skeleton_list.php
index 3c47498c52ef76ff011da08c1c60b54343f5f2c2..2321b76aac8905ce366c25924b61a5062b51e753 100644
--- a/dev/skeletons/skeleton_list.php
+++ b/dev/skeletons/skeleton_list.php
@@ -58,6 +58,7 @@ $myparam	= GETPOST('myparam','alpha');
 
 $search_field1=GETPOST("search_field1");
 $search_field2=GETPOST("search_field2");
+$search_myfield=GETPOST('search_myfield');
 $optioncss = GETPOST('optioncss','alpha');
 
 // Load variable for pagination
@@ -274,6 +275,11 @@ if ($resql)
         print $langs->trans("FilterOnInto", $all) . join(', ',$fieldstosearchall);
     }
     
+    $moreforfilter = '';
+    $moreforfilter.='<div class="divsearchfield">';
+    $moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escpae_htmltag($search_myfield).'">';
+    $moreforfilter.= '</div>';
+    
 	if (! empty($moreforfilter))
 	{
 		print '<div class="liste_titre liste_titre_bydiv centpercent">';
diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php
index 4bb41747ea9c4800aac2f3e259dceb5d14158bc7..8cc02613f6c705442407837df5979aa86f81596c 100644
--- a/htdocs/admin/modules.php
+++ b/htdocs/admin/modules.php
@@ -38,6 +38,9 @@ $mode=GETPOST('mode', 'alpha')?GETPOST('mode', 'alpha'):(isset($_SESSION['mode']
 $action=GETPOST('action','alpha');
 $value=GETPOST('value', 'alpha');
 $page_y=GETPOST('page_y','int');
+$search_keyword=GETPOST('search_keyword','alpha');
+$search_status=GETPOST('search_status','alpha');
+$search_nature=GETPOST('search_nature','alpha');
 
 if (! $user->admin)
 	accessforbidden();
@@ -59,6 +62,11 @@ $familyinfo=array(
 	'other'=>array('position'=>'100', 'label'=>$langs->trans("ModuleFamilyOther")),
 );
 
+$param='';
+if ($search_keyword) $param.='&search_keyword='.urlencode($search_keyword);
+if ($search_status) $param.='&search_status='.urlencode($search_status);
+if ($search_nature) $param.='&search_nature='.urlencode($search_nature);
+
 
 
 /*
@@ -69,7 +77,7 @@ if ($action == 'set' && $user->admin)
 {
     $result=activateModule($value);
     if ($result) setEventMessages($result, null, 'errors');
-    header("Location: modules.php?mode=".$mode.($page_y?'&page_y='.$page_y:''));
+    header("Location: modules.php?mode=".$mode.$param.($page_y?'&page_y='.$page_y:''));
 	exit;
 }
 
@@ -77,10 +85,18 @@ if ($action == 'reset' && $user->admin)
 {
     $result=unActivateModule($value);
     if ($result) setEventMessages($result, null, 'errors');
-    header("Location: modules.php?mode=".$mode.($page_y?'&page_y='.$page_y:''));
+    header("Location: modules.php?mode=".$mode.$param.($page_y?'&page_y='.$page_y:''));
 	exit;
 }
 
+if (GETPOST('buttonreset'))
+{
+    $search_keyword='';
+    $search_status='';
+    $search_nature='';
+}
+
+
 
 /*
  * View
@@ -231,16 +247,10 @@ print load_fiche_titre($langs->trans("ModulesSetup"),$moreinfo,'title_setup');
 // Start to show page
 if (empty($mode)) $mode='common';
 if ($mode==='common')      print $langs->trans("ModulesDesc")."<br>\n";
-//if ($mode==='other')       print $langs->trans("ModulesSpecialDesc")."<br>\n";
-//if ($mode==='interfaces')  print $langs->trans("ModulesInterfaceDesc")."<br>\n";
-//if ($mode==='functional')  print $langs->trans("ModulesJobDesc")."<br>\n";
 if ($mode==='marketplace') print $langs->trans("ModulesMarketPlaceDesc")."<br>\n";
 if ($mode==='expdev')      print $langs->trans("ModuleFamilyExperimental")."<br>\n";
 
 
-//print '<br>'."\n";
-
-
 $h = 0;
 
 $categidx='common';    // Main
@@ -252,35 +262,6 @@ if (! empty($categ[$categidx]))
 	$h++;
 }
 
-/*
-$categidx='other';    // Other
-if (! empty($categ[$categidx]))
-{
-	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
-	$head[$h][1] = $langs->trans("ModulesOther");
-	$head[$h][2] = 'other';
-	$h++;
-}
-
-$categidx='interfaces';    // Interfaces
-if (! empty($categ[$categidx]))
-{
-	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
-	$head[$h][1] = $langs->trans("ModulesInterfaces");
-	$head[$h][2] = 'interfaces';
-	$h++;
-}
-
-$categidx='functional';    // Not used
-if (! empty($categ[$categidx]))
-{
-	$head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=".$categidx;
-	$head[$h][1] = $langs->trans("ModulesSpecial");
-	$head[$h][2] = 'functional';
-	$h++;
-}
-*/
-
 $categidx='expdev';
 if (! empty($categ[$categidx]))
 {
@@ -307,20 +288,46 @@ $var=true;
 
 if ($mode != 'marketplace')
 {
-    print "<table summary=\"list_of_modules\" class=\"noborder\" width=\"100%\">\n";
-
-    /*
-    print '<tr class="liste_titre">'."\n";
-    print "  <td colspan=\"2\">".$langs->trans("Module")."</td>\n";
-    print "  <td>".$langs->trans("Description")."</td>\n";
-    print "  <td align=\"center\">".$langs->trans("Version")."</td>\n";
-    print '  <td align="center">'.$langs->trans("Status").'</td>'."\n";
-    print '  <td align="right">'.$langs->trans("SetupShort").'</td>'."\n";
-    print "</tr>\n";
-	*/
-
+    print '<form method="GET" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
+    if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
+    print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+    print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
+    print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
+    
+    $moreforfilter = '';
+    $moreforfilter.='<div class="divsearchfield">';
+    $moreforfilter.= $langs->trans('Keyword') . ': <input type="text" name="search_keyword" value="'.dol_escape_htmltag($search_keyword).'">';
+    $moreforfilter.= '</div>';
+    $moreforfilter.='<div class="divsearchfield">';
+    $moreforfilter.= $langs->trans('Status') . ': '.$form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, 1);
+    $moreforfilter.= '</div>';
+    $moreforfilter.='<div class="divsearchfield">';
+    $moreforfilter.= $langs->trans('Nature') . ': '.$form->selectarray('search_nature', array('standard'=>$langs->transnoentitiesnoconv("Standard"), 'external'=>$langs->transnoentitiesnoconv("External")), $search_nature, 1);
+    $moreforfilter.= '</div>';
+    $moreforfilter.=' ';
+    $moreforfilter.='<div class="divsearchfield">';
+    $moreforfilter.='<input type="submit" name="buttonsubmit" class="button" value="'.dol_escape_htmltag($langs->trans("Refresh")).'">';
+    $moreforfilter.=' ';
+    $moreforfilter.='<input type="submit" name="buttonreset" class="button" value="'.dol_escape_htmltag($langs->trans("Reset")).'">';
+    $moreforfilter.= '</div>';
+    
+    if (! empty($moreforfilter))
+    {
+        //print '<div class="liste_titre liste_titre_bydiv centpercent">';
+        print $moreforfilter;
+        $parameters=array();
+        $reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters);    // Note that $action and $object may have been modified by hook
+        print $hookmanager->resPrint;
+        //print '</div>';
+    }    
+    
+    print '<br><br><br>';
+    
+    
     // Show list of modules
 
+    print '<table summary="list_of_modules" id="list_of_modules" class="liste" width="100%">'."\n";
+
     $oldfamily='';
 
     foreach ($orders as $key => $value)
@@ -343,8 +350,34 @@ if ($mode != 'marketplace')
         	dol_syslog("Error for module ".$key." - Property name of module looks empty", LOG_WARNING);
       		continue;
         }
-
+        
         $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
+        
+        // Check filters
+        $modulename=$objMod->getName();
+        $moduledesc=$objMod->getDesc();
+        $moduledesclong=$objMod->getDescLong();
+        $moduleauthor=$objMod->getPublisher();
+        if ($search_keyword)
+        {
+            $qualified=0;
+            if (preg_match('/'.preg_quote($search_keyword).'/i', $modulename) 
+                || preg_match('/'.preg_quote($search_keyword).'/i', $moduledesc)
+                || preg_match('/'.preg_quote($search_keyword).'/i', $moduledesclong)
+                || preg_match('/'.preg_quote($search_keyword).'/i', $moduleauthor)
+                ) $qualified=1;
+            if (! $qualified) continue;
+        }
+        if ($search_status)
+        {
+            if ($search_status == 'active' && empty($conf->global->$const_name)) continue;
+            if ($search_status == 'disabled' && ! empty($conf->global->$const_name)) continue;
+        }
+        if ($search_nature)
+        {
+            if ($search_nature == 'external' && $objMod->isCoreOrExternalModule() != 'external') continue;
+            if ($search_nature == 'standard' && $objMod->isCoreOrExternalModule() == 'external') continue;
+        }
 
         // Load all lang files of module
         if (isset($objMod->langfiles) && is_array($objMod->langfiles))
@@ -440,7 +473,7 @@ if ($mode != 'marketplace')
         	}
         	else
         	{
-        		print '<a class="reposition" href="modules.php?id='.$objMod->numero.'&amp;module_position='.$module_position.'&amp;action=reset&amp;value=' . $modName . '&amp;mode=' . $mode . '">';
+        		print '<a class="reposition" href="modules.php?id='.$objMod->numero.'&amp;module_position='.$module_position.'&amp;action=reset&amp;value=' . $modName . '&amp;mode=' . $mode . $param . '">';
         		print img_picto($langs->trans("Activated"),'switch_on');
         		print '</a>';
         	}
@@ -504,7 +537,7 @@ if ($mode != 'marketplace')
         	else
         	{
 	        	// Module non actif
-	        	print '<a class="reposition" href="modules.php?id='.$objMod->numero.'&amp;module_position='.$module_position.'&amp;action=set&amp;value=' . $modName . '&amp;mode=' . $mode . '">';
+	        	print '<a class="reposition" href="modules.php?id='.$objMod->numero.'&amp;module_position='.$module_position.'&amp;action=set&amp;value=' . $modName . '&amp;mode=' . $mode . $param . '">';
 	        	print img_picto($langs->trans("Disabled"),'switch_off');
 	        	print "</a>\n";
         	}
@@ -529,7 +562,7 @@ else
 
     $var=!$var;
     print "<tr ".$bc[$var].">\n";
-    $url='http://www.dolistore.com';
+    $url='https://www.dolistore.com';
     print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" width="180" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.png"></a></td>';
     print '<td>'.$langs->trans("DoliStoreDesc").'</td>';
     print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>';
@@ -537,7 +570,7 @@ else
 
     $var=!$var;
     print "<tr ".$bc[$var].">\n";
-    $url='http://partners.dolibarr.org';
+    $url='https://partners.dolibarr.org';
     print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" width="180" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner_int.png"></a></td>';
     print '<td>'.$langs->trans("DoliPartnersDesc").'</td>';
     print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>';
diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php
index 8f0d161bb5bff0772c063b9bf1cbfda5e1fc29cb..3a5112e331703d269e05a8e28be75dfbd71b1a09 100644
--- a/htdocs/core/modules/DolibarrModules.class.php
+++ b/htdocs/core/modules/DolibarrModules.class.php
@@ -44,6 +44,16 @@ class DolibarrModules           // Can not be abstract, because we need to insta
      */
     public $numero;
 
+    /**
+     * @var string  Publisher name
+     */
+    public $editor_name;
+    
+    /**
+     * @var string  URL of module at publisher site
+     */
+    public $editor_web;    
+    
     /**
      * @var string Family
      */
@@ -153,10 +163,15 @@ class DolibarrModules           // Can not be abstract, because we need to insta
     public $version;
 
     /**
-     * @var string Module description
+     * @var string Module description (short text)
      */
     public $description;
 
+    /**
+     * @var string Module description (long text)
+     */
+    public $descriptionlong;
+    
     /**
      * @var string[] Module language files
      */
@@ -444,7 +459,47 @@ class DolibarrModules           // Can not be abstract, because we need to insta
         }
     }
 
-
+    /**
+     * Gives the translated module description if translation exists in admin.lang or the default module description
+     *
+     * @return  string  Translated module description
+     */
+    function getDescLong()
+    {
+        global $langs;
+        $langs->load("admin");
+        
+        // If module description translation does not exist using its unique id, we can use its name to find translation
+        if (is_array($this->langfiles))
+        {
+            foreach($this->langfiles as $val)
+            {
+                if ($val) $langs->load($val);
+            }
+        }
+        return $langs->trans($this->descriptionlong);
+    }
+    
+    /**
+     * Gives the publisher name
+     *
+     * @return  string  Publisher name
+     */
+    function getPublisher()
+    {
+        return $this->editor_name;
+    }
+    
+    /**
+     * Gives the publisher url
+     *
+     * @return  string  Publisher url
+     */
+    function getPublisherUrl()
+    {
+        return $this->editor_url;
+    }
+    
     /**
      * Gives module version
      * For 'experimental' modules, gives 'experimental' translation
diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php
index 65c232c673782434d32f62770000a011b8b327c3..3fbbff6173740922787789835ff621e43075c09f 100644
--- a/htdocs/theme/eldy/style.css.php
+++ b/htdocs/theme/eldy/style.css.php
@@ -2494,11 +2494,10 @@ div.liste_titre {
 	border-top-style: solid;
 }
 div.liste_titre_bydiv {
-	box-shadow: none;
 	border-collapse: collapse;
 	display: table;
 	padding: 2px 0px 2px 0;
-	box-shadow: 2px 2px 4px #CCC;
+	box-shadow: none;
 	width: calc(100% - 1px);	/* 1px more, i don't know why */
 }
 tr.liste_titre, tr.liste_titre_sel, form.liste_titre, form.liste_titre_sel, table.dataTable.tr