From 77df19009db350893462e42caaad9bad2c50924e Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Thu, 1 Jun 2017 12:11:45 +0200
Subject: [PATCH] Removed duplicated code

---
 htdocs/admin/agenda_other.php                 |  57 +++----
 htdocs/admin/barcode.php                      |  36 +---
 htdocs/admin/commande.php                     |  31 +---
 htdocs/admin/contract.php                     |  31 +---
 htdocs/admin/expedition.php                   |  32 +---
 htdocs/admin/expensereport.php                |  32 +---
 htdocs/admin/facture.php                      |  27 +--
 htdocs/admin/fichinter.php                    |  32 +---
 htdocs/admin/livraison.php                    |  32 +---
 htdocs/admin/propal.php                       |  32 +---
 htdocs/admin/supplier_payment.php             |  35 +---
 htdocs/admin/supplier_proposal.php            |  36 +---
 htdocs/admin/user.php                         |  32 +---
 htdocs/admin/usergroup.php                    |  32 +---
 htdocs/core/actions_setmoduleoptions.inc.php  |  86 ++++++++++
 htdocs/core/lib/files.lib.php                 | 160 +++++++++---------
 .../doc/doc_generic_contract_odt.modules.php  |  41 +----
 htdocs/langs/en_US/admin.lang                 |   2 +
 htdocs/modulebuilder/template/admin/setup.php |   9 +-
 htdocs/product/admin/product.php              |  45 +----
 htdocs/projet/admin/project.php               |  39 +----
 htdocs/societe/admin/societe.php              |  32 +---
 22 files changed, 265 insertions(+), 626 deletions(-)
 create mode 100644 htdocs/core/actions_setmoduleoptions.inc.php

diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php
index bd9587a4440..44ec3ade889 100644
--- a/htdocs/admin/agenda_other.php
+++ b/htdocs/admin/agenda_other.php
@@ -49,6 +49,8 @@ $type = 'action';
  *	Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if (preg_match('/set_(.*)/',$action,$reg))
 {
 	$code=$reg[1];
@@ -77,21 +79,6 @@ if (preg_match('/del_(.*)/',$action,$reg))
 		dol_print_error($db);
 	}
 }
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-
-	if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-	if (! $res > 0) $error++;
-	if (! $error)
-	{
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-        setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
 if ($action == 'set')
 {
 	dolibarr_set_const($db, 'AGENDA_USE_EVENT_TYPE_DEFAULT', GETPOST('AGENDA_USE_EVENT_TYPE_DEFAULT'), 'chaine', 0, '', $conf->entity);
@@ -233,7 +220,7 @@ else
 if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
 {
     print load_fiche_titre($langs->trans("AgendaModelModule"),'','');
-    
+
     print '<table class="noborder" width="100%">'."\n";
     print '<tr class="liste_titre">'."\n";
     print '<td width="100">'.$langs->trans("Name").'</td>'."\n";
@@ -243,13 +230,13 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
     print '<td align="center" width="40">'.$langs->trans("ShortInfo").'</td>';
     print '<td align="center" width="40">'.$langs->trans("Preview").'</td>';
     print '</tr>'."\n";
-    
+
     clearstatcache();
-    
+
     foreach ($dirmodels as $reldir)
     {
     	$dir = dol_buildpath($reldir."core/modules/action/doc/");
-    
+
         if (is_dir($dir))
         {
             $handle=opendir($dir);
@@ -261,10 +248,10 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
                     {
             			$name = substr($file, 4, dol_strlen($file) -16);
             			$classname = substr($file, 0, dol_strlen($file) -12);
-            			
+
             			require_once $dir.'/'.$file;
-            			$module = new $classname($db, new ActionComm($db));           			
-            			
+            			$module = new $classname($db, new ActionComm($db));
+
             			print '<tr class="oddeven">'."\n";
             			print "<td>";
             			print (empty($module->name)?$name:$module->name);
@@ -272,16 +259,16 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
             			print "<td>\n";
             			require_once $dir.$file;
             			$module = new $classname($db,$specimenthirdparty);
-            			if (method_exists($module,'info')) 
+            			if (method_exists($module,'info'))
             				print $module->info($langs);
-            			else 
+            			else
             				print $module->description;
             			print "</td>\n";
-            			
+
             			// Active
             			if (in_array($name, $def))
             			{
-            			    
+
             			print '<td align="center">'."\n";
             			if ($conf->global->ACTION_EVENT_ADDON_PDF != "$name")
             			{
@@ -301,7 +288,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
             				print '<a href="'.$_SERVER["PHP_SELF"].'?action=setmodel&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type=action">'.img_picto($langs->trans("Disabled"),'switch_off').'</a>';
             				print "</td>";
             			}
-            			
+
             			// Default
             			print '<td align="center">';
             			if ($conf->global->ACTION_EVENT_ADDON_PDF == "$name")
@@ -313,7 +300,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
             				print '<a href="'.$_SERVER["PHP_SELF"].'?action=setdoc&amp;value='.$name.'&amp;scandir='.$module->scandir.'&amp;label='.urlencode($module->name).'&amp;type=action"" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').'</a>';
             			}
             			print '</td>';
-            			
+
             			// Info
             			$htmltooltip =    ''.$langs->trans("Name").': '.$module->name;
             			$htmltooltip.='<br>'.$langs->trans("Type").': '.($module->type?$module->type:$langs->trans("Unknown"));
@@ -326,7 +313,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
             			print '<td align="center">';
             			print '<a href="'.$_SERVER["PHP_SELF"].'?action=specimen&amp;module='.$name.'">'.img_object($langs->trans("Preview"),'order').'</a>';
             			print '</td>';
-            			
+
             			print "</tr>\n";
                     }
                 }
@@ -366,7 +353,7 @@ print '</td></tr>'."\n";
 
 if (! empty($conf->global->AGENDA_USE_EVENT_TYPE))
 {
-    
+
     print '<!-- AGENDA_USE_EVENT_TYPE_DEFAULT -->';
     print '<tr class="oddeven">'."\n";
     print '<td>'.$langs->trans("AGENDA_USE_EVENT_TYPE_DEFAULT").'</td>'."\n";
@@ -404,30 +391,30 @@ print '</td></tr>'."\n";
 // AGENDA NOTIFICATION
 if ($conf->global->MAIN_FEATURES_LEVEL > 0)
 {
-    
+
     print '<tr class="oddeven">'."\n";
     print '<td>'.$langs->trans('AGENDA_NOTIFICATION').'</td>'."\n";
     print '<td align="center">&nbsp;</td>'."\n";
     print '<td align="right">'."\n";
-    
+
     if (empty($conf->global->AGENDA_NOTIFICATION)) {
         print '<a href="'.$_SERVER['PHP_SELF'].'?action=set_AGENDA_NOTIFICATION">'.img_picto($langs->trans('Disabled'),'switch_off').'</a>';
         print '</td></tr>'."\n";
     } else {
         print '<a href="'.$_SERVER['PHP_SELF'].'?action=del_AGENDA_NOTIFICATION">'.img_picto($langs->trans('Enabled'),'switch_on').'</a>';
         print '</td></tr>'."\n";
-    	
+
         print '<tr class="oddeven">'."\n";
         print '<td>'.$langs->trans('AGENDA_NOTIFICATION_SOUND').'</td>'."\n";
         print '<td align="center">&nbsp;</td>'."\n";
         print '<td align="right">'."\n";
-    
+
         if (empty($conf->global->AGENDA_NOTIFICATION_SOUND)) {
             print '<a href="'.$_SERVER['PHP_SELF'].'?action=set_AGENDA_NOTIFICATION_SOUND">'.img_picto($langs->trans('Disabled'),'switch_off').'</a>';
         } else {
             print '<a href="'.$_SERVER['PHP_SELF'].'?action=del_AGENDA_NOTIFICATION_SOUND">'.img_picto($langs->trans('Enabled'),'switch_on').'</a>';
         }
-    
+
         print '</td></tr>'."\n";
     }
 }
diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php
index db81c9a325f..ba649fe9223 100644
--- a/htdocs/admin/barcode.php
+++ b/htdocs/admin/barcode.php
@@ -39,6 +39,8 @@ $action = GETPOST('action','alpha');
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'setbarcodeproducton')
 {
 	$res=dolibarr_set_const($db, "BARCODE_PRODUCT_ADDON_NUM", GETPOST('value'), 'chaine', 0, '', $conf->entity);
@@ -72,33 +74,7 @@ else if ($action == 'update')
 else if ($action == 'updateengine')
 {
     // TODO Update engines.
-    
-}
-
-// define constants for models generator that need parameters
-if ($action == 'setModuleOptions')
-{
-    $post_size=count($_POST);
-
-    for($i=0;$i < $post_size;$i++)
-    {
-        if (array_key_exists('param'.$i,$_POST))
-        {
-            $param=GETPOST("param".$i,'alpha');
-            $value=GETPOST("value".$i,'alpha');
-            if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-        }
-    }
-	if (! $res > 0) $error++;
 
- 	if (! $error)
-    {
-        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        setEventMessages($langs->trans("Error"), null, 'errors');
-    }
 }
 
 if ($action && $action != 'setcoder' && $action != 'setModuleOptions')
@@ -276,7 +252,7 @@ if ($resql)
 		print '<td align="center">';
 		print $formbarcode->setBarcodeEncoder($obj->coder,$barcodelist,$obj->rowid,'form'.$i);
 		print "</td></tr>\n";
-		
+
 		$i++;
 	}
 }
@@ -312,7 +288,7 @@ print '</tr>';
 // Chemin du binaire genbarcode sous linux
 if (! isset($_SERVER['WINDIR']))
 {
-	
+
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("GenbarcodeLocation").'</td>';
 	print '<td width="60" align="center">';
@@ -328,7 +304,7 @@ if (! isset($_SERVER['WINDIR']))
 // Module products
 if (! empty($conf->product->enabled))
 {
-	
+
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("SetDefaultBarcodeTypeProducts").'</td>';
 	print '<td width="60" align="right">';
@@ -339,7 +315,7 @@ if (! empty($conf->product->enabled))
 // Module thirdparty
 if (! empty($conf->societe->enabled))
 {
-	
+
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("SetDefaultBarcodeTypeThirdParties").'</td>';
 	print '<td width="60" align="right">';
diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php
index 6d92ad21999..3f3c997b0d8 100644
--- a/htdocs/admin/commande.php
+++ b/htdocs/admin/commande.php
@@ -54,6 +54,8 @@ $type = 'order';
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
 	$maskconstorder=GETPOST('maskconstorder','alpha');
@@ -118,35 +120,6 @@ else if ($action == 'specimen')
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-		setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 else if ($action == 'set')
 {
diff --git a/htdocs/admin/contract.php b/htdocs/admin/contract.php
index 47e53a05048..206d9020022 100644
--- a/htdocs/admin/contract.php
+++ b/htdocs/admin/contract.php
@@ -50,6 +50,8 @@ if (empty($conf->global->CONTRACT_ADDON))
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
     $maskconst = GETPOST('maskconstcontract','alpha');
@@ -113,35 +115,6 @@ else if ($action == 'specimen') // For contract
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-        setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 else if ($action == 'set')
 {
diff --git a/htdocs/admin/expedition.php b/htdocs/admin/expedition.php
index e9a9aaedb18..6182538f820 100644
--- a/htdocs/admin/expedition.php
+++ b/htdocs/admin/expedition.php
@@ -57,6 +57,9 @@ if (empty($conf->global->EXPEDITION_ADDON_NUMBER))
 /*
  * Actions
  */
+
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
 	$maskconst=GETPOST('maskconstexpedition','alpha');
@@ -142,35 +145,6 @@ else if ($action == 'specimen')
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-else if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-		setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 else if ($action == 'set')
 {
diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php
index 92ba9375927..6c659181c4c 100644
--- a/htdocs/admin/expensereport.php
+++ b/htdocs/admin/expensereport.php
@@ -51,6 +51,9 @@ $type='expensereport';
 /*
  * Actions
  */
+
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
 	$maskconst=GETPOST('maskconst','alpha');
@@ -116,35 +119,6 @@ else if ($action == 'specimen') // For fiche inter
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-		setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 else if ($action == 'set')
 {
diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php
index 64ae1abdde6..115a685a3f2 100644
--- a/htdocs/admin/facture.php
+++ b/htdocs/admin/facture.php
@@ -51,6 +51,8 @@ $type='invoice';
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
     $maskconstinvoice=GETPOST('maskconstinvoice','alpha');
@@ -123,31 +125,6 @@ if ($action == 'specimen')
     }
 }
 
-// define constants for models generator that need parameters
-if ($action == 'setModuleOptions')
-{
-    $post_size=count($_POST);
-    for($i=0;$i < $post_size;$i++)
-    {
-        if (array_key_exists('param'.$i,$_POST))
-        {
-            $param=GETPOST("param".$i,'alpha');
-            $value=GETPOST("value".$i,'alpha');
-            if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-        }
-    }
-	if (! $res > 0) $error++;
-
- 	if (! $error)
-    {
-        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        setEventMessages($langs->trans("Error"), null, 'errors');
-    }
-}
-
 // Activate a model
 else if ($action == 'set')
 {
diff --git a/htdocs/admin/fichinter.php b/htdocs/admin/fichinter.php
index e3000231c38..25c46164783 100644
--- a/htdocs/admin/fichinter.php
+++ b/htdocs/admin/fichinter.php
@@ -51,6 +51,9 @@ $type='ficheinter';
 /*
  * Actions
  */
+
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
 	$maskconst=GETPOST('maskconst','alpha');
@@ -114,35 +117,6 @@ else if ($action == 'specimen') // For fiche inter
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-		setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 else if ($action == 'set')
 {
diff --git a/htdocs/admin/livraison.php b/htdocs/admin/livraison.php
index cf97b397e44..ef73ec7a757 100644
--- a/htdocs/admin/livraison.php
+++ b/htdocs/admin/livraison.php
@@ -47,10 +47,13 @@ $label   = GETPOST('label','alpha');
 $scandir = GETPOST('scandir','alpha');
 $type='delivery';
 
+
 /*
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
     $maskconstdelivery=GETPOST('maskconstdelivery','alpha');
@@ -131,35 +134,6 @@ if ($action == 'specimen')
     }
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-		setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 if ($action == 'set')
 {
     $ret = addDocumentModel($value, $type, $label, $scandir);
diff --git a/htdocs/admin/propal.php b/htdocs/admin/propal.php
index e0dc1d3b5b4..9fa8dad0c0c 100644
--- a/htdocs/admin/propal.php
+++ b/htdocs/admin/propal.php
@@ -49,6 +49,9 @@ $type='propal';
 /*
  * Actions
  */
+
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 $error=0;
 if ($action == 'updateMask')
 {
@@ -180,35 +183,6 @@ if ($action == 'set_BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL')
     }
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-		setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 if ($action == 'set')
 {
diff --git a/htdocs/admin/supplier_payment.php b/htdocs/admin/supplier_payment.php
index adaa114b1ca..4227f4d4221 100644
--- a/htdocs/admin/supplier_payment.php
+++ b/htdocs/admin/supplier_payment.php
@@ -47,6 +47,8 @@ $type='supplier_payment';
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
     $maskconstsupplierpayment=GETPOST('maskconstsupplierpayment','alpha');
@@ -68,31 +70,6 @@ if ($action == 'updateMask')
     dolibarr_set_const($db, "SUPPLIER_PAYMENT_ADDON", $value, 'chaine', 0, '', $conf->entity);
 }
 
-// define constants for models generator that need parameters
-else if ($action == 'setModuleOptions')
-{
-    $post_size=count($_POST);
-    for($i=0;$i < $post_size;$i++)
-    {
-        if (array_key_exists('param'.$i,$_POST))
-        {
-            $param=GETPOST("param".$i,'alpha');
-            $value=GETPOST("value".$i,'alpha');
-            if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-        }
-    }
-	if (! $res > 0) $error++;
-
- 	if (! $error)
-    {
-        setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        setEventMessages($langs->trans("Error"), null, 'errors');
-    }
-}
-
 // Activate a model
 else if ($action == 'set')
 {
@@ -195,7 +172,7 @@ dol_fiche_head($head, 'supplierpayment', $langs->trans("Suppliers"), -1, 'compan
  */
 
 if (empty($conf->global->SUPPLIER_PAYMENT_ADDON)) $conf->global->SUPPLIER_PAYMENT_ADDON = 'mod_supplier_payment_bronan';
-    
+
 print load_fiche_titre($langs->trans("PaymentsNumberingModule"), '', '');
 
 // Load array def with activated templates
@@ -265,7 +242,7 @@ foreach ($dirmodels as $reldir)
                         require_once $dir.$filebis;
 
                         $module = new $classname($db);
-						
+
                         // Show modules according to features level
                         if ($module->version == 'development'  && $conf->global->MAIN_FEATURES_LEVEL < 2) continue;
                         if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue;
@@ -375,7 +352,7 @@ foreach ($dirmodels as $reldir)
         {
             while (($file = readdir($handle))!==false)
             {
-                if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file))            	
+                if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file))
                 {
                     $name = substr($file, 4, dol_strlen($file) -16);
                     $classname = substr($file, 0, dol_strlen($file) -12);
@@ -383,7 +360,7 @@ foreach ($dirmodels as $reldir)
 	                require_once $dir.'/'.$file;
 	                $module = new $classname($db, new PaiementFourn($db));
 
-                    
+
                     print "<tr class=\"oddeven\">\n";
                     print "<td>";
 	                print (empty($module->name)?$name:$module->name);
diff --git a/htdocs/admin/supplier_proposal.php b/htdocs/admin/supplier_proposal.php
index 82eeddd594c..210d601c33c 100644
--- a/htdocs/admin/supplier_proposal.php
+++ b/htdocs/admin/supplier_proposal.php
@@ -41,10 +41,15 @@ $label = GETPOST('label','alpha');
 $scandir = GETPOST('scandir','alpha');
 $type='supplier_proposal';
 
+$error=0;
+
+
 /*
  * Actions
  */
-$error=0;
+
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'updateMask')
 {
 	$maskconstsupplier_proposal=GETPOST('maskconstsupplier_proposal','alpha');
@@ -159,35 +164,6 @@ if ($action == 'set_BANK_ASK_PAYMENT_BANK_DURING_SUPPLIER_PROPOSAL')
     }
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-		setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 if ($action == 'set')
 {
diff --git a/htdocs/admin/user.php b/htdocs/admin/user.php
index 0c7574b7ec4..31efcb22474 100644
--- a/htdocs/admin/user.php
+++ b/htdocs/admin/user.php
@@ -47,37 +47,9 @@ $type='user';
  * Action
  */
 
-// Activate a model
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-    {
-    	if (array_key_exists('param'.$i,$_POST))
-    	{
-    		$param=GETPOST("param".$i,'alpha');
-    		$value=GETPOST("value".$i,'alpha');
-    		if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-	    	if (! $res > 0) $error++;
-    	}
-    }
-	if (! $error)
-    {
-        $db->commit();
-	    setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        $db->rollback();
-	    setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-elseif ($action == 'set_default')
+if ($action == 'set_default')
 {
 	$ret = addDocumentModel($value, $type, $label, $scandir);
 	$res = true;
diff --git a/htdocs/admin/usergroup.php b/htdocs/admin/usergroup.php
index 4642e6d3183..8d098ee6923 100644
--- a/htdocs/admin/usergroup.php
+++ b/htdocs/admin/usergroup.php
@@ -47,37 +47,9 @@ $type='group';
  * Action
  */
 
-// Activate a model
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-    {
-    	if (array_key_exists('param'.$i,$_POST))
-    	{
-    		$param=GETPOST("param".$i,'alpha');
-    		$value=GETPOST("value".$i,'alpha');
-    		if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-	    	if (! $res > 0) $error++;
-    	}
-    }
-	if (! $error)
-    {
-        $db->commit();
-	    setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        $db->rollback();
-	    setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-elseif ($action == 'set_default')
+if ($action == 'set_default')
 {
 	$ret = addDocumentModel($value, $type, $label, $scandir);
 	$res = true;
diff --git a/htdocs/core/actions_setmoduleoptions.inc.php b/htdocs/core/actions_setmoduleoptions.inc.php
new file mode 100644
index 00000000000..03b33b19eb1
--- /dev/null
+++ b/htdocs/core/actions_setmoduleoptions.inc.php
@@ -0,0 +1,86 @@
+<?php
+/* Copyright (C) 2014 Laurent Destailleur  <eldy@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ *	\file			htdocs/core/actions_setnotes.inc.php
+ *  \brief			Code for actions on setting notes of object page
+ */
+
+
+// $action must be defined
+// $_FILES may be defined
+// $nomessageinsetmoduleoptions can be set to 1
+
+// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
+if ($action == 'setModuleOptions')
+{
+    $db->begin();
+
+    // Process common param fields
+    foreach($_POST as $key => $val)
+    {
+        if (preg_match('/^param(\d*)$/', $key, $reg))    // Works for POST['param'], POST['param1'], POST['param2'], ...
+        {
+            $param=GETPOST("param".$reg[1],'alpha');
+            $value=GETPOST("value".$reg[1],'alpha');
+            if ($param)
+            {
+                $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
+                if (! $res > 0) $error++;
+            }
+        }
+    }
+
+    // Process upload fields
+    if (GETPOST('upload','alpha') && GETPOST('keyforuploaddir','aZ09'))
+    {
+        include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+        $keyforuploaddir=GETPOST('keyforuploaddir','aZ09');
+        $listofdir=explode(',',preg_replace('/[\r\n]+/',',',trim($conf->global->$keyforuploaddir)));
+        foreach($listofdir as $key=>$tmpdir)
+        {
+            $tmpdir=trim($tmpdir);
+            $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir);
+            if (! $tmpdir) {
+                unset($listofdir[$key]); continue;
+            }
+            if (! is_dir($tmpdir)) $texttitle.=img_warning($langs->trans("ErrorDirNotFound",$tmpdir),0);
+            else
+            {
+                $upload_dir=$tmpdir;
+            }
+        }
+        if ($upload_dir)
+        {
+            $result = dol_add_file_process($upload_dir, 0, 1, 'uploadfile', '');
+            if ($result <= 0) $error++;
+        }
+    }
+
+    if (! $error)
+    {
+        $db->commit();
+        if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
+    }
+    else
+    {
+        $db->rollback();
+        if (empty($nomessageinsetmoduleoptions)) setEventMessages($langs->trans("SetupNotSaved"), null, 'errors');
+    }
+}
+
diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php
index 95fca68aa5d..85aace9db0b 100644
--- a/htdocs/core/lib/files.lib.php
+++ b/htdocs/core/lib/files.lib.php
@@ -44,7 +44,7 @@ function dol_basename($pathfile)
  *  @param	string		$path        	Starting path from which to search. This is a full path.
  *  @param	string		$types        	Can be "directories", "files", or "all"
  *  @param	int			$recursive		Determines whether subdirectories are searched
- *  @param	string		$filter        	Regex filter to restrict list. This regex value must be escaped for '/' by doing preg_quote($var,'/'), since this char is used for preg_match function, 
+ *  @param	string		$filter        	Regex filter to restrict list. This regex value must be escaped for '/' by doing preg_quote($var,'/'), since this char is used for preg_match function,
  *                                      but must not contains the start and end '/'. Filter is checked into basename only.
  *  @param	array		$excludefilter  Array of Regex for exclude filter (example: array('(\.meta|_preview.*\.png)$','^\.')). Exclude is checked into fullpath.
  *  @param	string		$sortcriteria	Sort criteria ("","fullname","name","date","size")
@@ -71,9 +71,9 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil
 
 	$reshook = 0;
 	$file_list = array();
-	
+
 	$hookmanager->resArray=array();
-	
+
 	if (! $nohook)
 	{
 		$hookmanager->initHooks(array('fileslib'));
@@ -196,9 +196,9 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil
 			}
 		}
 	}
-	
+
 	$file_list = array_merge($file_list, $hookmanager->resArray);
-	
+
 	return $file_list;
 }
 
@@ -219,7 +219,7 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil
 function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0)
 {
     global $conf, $db;
-    
+
     $sql=" SELECT rowid, label, entity, filename, filepath, fullpath_orig, keywords, cover, gen_or_uploaded, extraparams, date_c, date_m, fk_user_c, fk_user_m, acl, position";
     if ($mode) $sql.=", description";
     $sql.=" FROM ".MAIN_DB_PREFIX."ecm_files";
@@ -234,7 +234,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc
         $i = 0;
         while ($i < $num)
         {
-            $obj = $db->fetch_object($resql);            
+            $obj = $db->fetch_object($resql);
             if ($obj)
             {
                 preg_match('/([^\/]+)\/[^\/]+$/',DOL_DATA_ROOT.'/'.$obj->filepath.'/'.$obj->filename,$reg);
@@ -258,7 +258,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc
             }
             $i++;
         }
-        
+
         // Obtain a list of columns
         if (! empty($sortcriteria))
         {
@@ -270,7 +270,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc
             // Sort the data
             if ($sortorder) array_multisort($myarray, $sortorder, $file_list);
         }
-        
+
         return $file_list;
     }
     else
@@ -279,7 +279,7 @@ function dol_dir_list_in_database($path, $filter="", $excludefilter=null, $sortc
         return array();
     }
 }
-    
+
 
 /**
  * Fast compare of 2 files identified by their properties ->name, ->date and ->size
@@ -460,10 +460,10 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0,
 
     if (empty($srcfile)) return -1;
     if (empty($destfile)) $destfile=$srcfile;
-    
+
     $destexists=dol_is_file($destfile);
     if (($destfile != $srcfile) && $destexists) return 0;
-    
+
     $tmpdestfile=$destfile.'.tmp';
 
     $newpathofsrcfile=dol_osencode($srcfile);
@@ -481,17 +481,17 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0,
         dol_syslog("files.lib.php::dolReplaceInFile failed Permission denied to write into target directory ".$newdirdestfile, LOG_WARNING);
         return -2;
     }
-   
+
     dol_delete_file($tmpdestfile);
-    
+
     // Create $newpathoftmpdestfile from $newpathofsrcfile
     $content=file_get_contents($newpathofsrcfile, 'r');
-    
+
     $content = make_substitutions($content, $arrayreplacement, null);
-    
+
     file_put_contents($newpathoftmpdestfile, $content);
     @chmod($newpathoftmpdestfile, octdec($newmask));
-    
+
     // Rename
     $result=dol_move($newpathoftmpdestfile, $newpathofdestfile, $newmask, (($destfile == $srcfile)?1:0), 0, $indexdatabase);
     if (! $result)
@@ -589,7 +589,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep
 
 	$destexists=dol_is_dir($destfile);
 	//if (! $overwriteifexists && $destexists) return 0;	// The overwriteifexists is for files only, so propagated to dol_copy only.
-    
+
     if (! $destexists)
     {
         // We must set mask just before creating dir, becaause it can be set differently by dol_copy
@@ -599,7 +599,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep
         $dirmaskdec |= octdec('0200');  // Set w bit required to be able to create content for recursive subdirs files
         dol_mkdir($destfile, '', decoct($dirmaskdec));
     }
-    
+
 	$ossrcfile=dol_osencode($srcfile);
 	$osdestfile=dol_osencode($destfile);
 
@@ -639,7 +639,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep
                     $result=$tmpresult;
                 }
                 if ($result < 0) break;
-                
+
             }
         }
         closedir($dir_handle);
@@ -656,10 +656,10 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayrep
 
 /**
  * Move a file into another name.
- * Note: 
+ * Note:
  *  - This function differs from dol_move_uploaded_file, because it can be called in any context.
  *  - Database of files is updated.
- *  - Test on antivirus is done only if param testvirus is provided and an antivirus was set. 
+ *  - Test on antivirus is done only if param testvirus is provided and an antivirus was set.
  *
  * @param	string  $srcfile            Source file (can't be a directory. use native php @rename() to move a directory)
  * @param   string	$destfile           Destination file (can't be a directory. use native php @rename() to move a directory)
@@ -679,12 +679,12 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi
     $srcexists=dol_is_file($srcfile);
     $destexists=dol_is_file($destfile);
 
-    if (! $srcexists) 
+    if (! $srcexists)
     {
         dol_syslog("files.lib.php::dol_move srcfile does not exists. we ignore the move request.");
         return false;
     }
-    
+
     if ($overwriteifexists || ! $destexists)
     {
         $newpathofsrcfile=dol_osencode($srcfile);
@@ -695,7 +695,7 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi
         if ($testvirus)
         {
             $testvirusarray=dolCheckVirus($newpathofsrcfile);
-            if (count($testvirusarray)) 
+            if (count($testvirusarray))
             {
                 dol_syslog("files.lib.php::dol_move canceled because a virus was found into source file. we ignore the move request.", LOG_WARNING);
                 return false;
@@ -729,14 +729,14 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi
 
                 dol_syslog("Try to rename also entries in database for full relative path before = ".$rel_filetorenamebefore." after = ".$rel_filetorenameafter, LOG_DEBUG);
                 include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
-                
+
                 $ecmfiletarget=new EcmFiles($db);
                 $resultecmtarget = $ecmfiletarget->fetch(0, '', $rel_filetorenameafter);
                 if ($resultecmtarget > 0)   // An entry for target name already exists for target, we delete it, a new one will be created.
                 {
                     $ecmfiletarget->delete($user);
                 }
-                
+
                 $ecmfile=new EcmFiles($db);
                 $resultecm = $ecmfile->fetch(0, '', $rel_filetorenamebefore);
                 if ($resultecm > 0)   // If an entry was found for src file, we use it to move entry
@@ -745,7 +745,7 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi
                     $rel_dir = dirname($rel_filetorenameafter);
                     $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
                     $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
-                    
+
                     $ecmfile->filepath = $rel_dir;
                     $ecmfile->filename = $filename;
                     $resultecm = $ecmfile->update($user);
@@ -756,7 +756,7 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi
                     $rel_dir = dirname($rel_filetorenameafter);
                     $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
                     $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
-                    	
+
                     $ecmfile->filepath = $rel_dir;
                     $ecmfile->filename = $filename;
                     $ecmfile->label = md5_file(dol_osencode($destfile));        // $destfile is a full path to file
@@ -774,12 +774,12 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi
                 {
                     setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings');
                 }
-                
+
                 if ($resultecm > 0) $result=true;
                 else $result = false;
-            }        
+            }
         }
-        
+
         if (empty($newmask)) $newmask=empty($conf->global->MAIN_UMASK)?'0755':$conf->global->MAIN_UMASK;
         $newmaskdec=octdec($newmask);
         // Currently method is restricted to files (dol_delete_files previously used is for files, and mask usage if for files too)
@@ -809,14 +809,14 @@ function dol_unescapefile($filename)
 
 /**
  * Check virus into a file
- * 
+ *
  * @param   string      $src_file       Source file to check
  * @return  array                       Array of errors or empty array if not virus found
  */
 function dolCheckVirus($src_file)
 {
     global $conf;
-    
+
     if (! empty($conf->global->MAIN_ANTIVIRUS_COMMAND))
     {
         if (! class_exists('AntiVir')) {
@@ -837,10 +837,10 @@ function dolCheckVirus($src_file)
 /**
  *	Make control on an uploaded file from an GUI page and move it to final destination.
  * 	If there is errors (virus found, antivir in error, bad filename), file is not moved.
- *  Note: 
+ *  Note:
  *  - This function can be used only into a HTML page context. Use dol_move if you are outside.
- *  - Database of files is not updated.
  *  - Test on antivirus is always done (if antivirus set).
+ *  - Database of files is NOT updated.
  *
  *	@param	string	$src_file			Source full path filename ($_FILES['field']['tmp_name'])
  *	@param	string	$dest_file			Target full path filename  ($_FILES['field']['name'])
@@ -867,7 +867,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
 		$parameters=array('dest_file' => $dest_file, 'src_file' => $src_file, 'file_name' => $file_name, 'varfiles' => $varfiles, 'allowoverwrite' => $allowoverwrite);
 		$reshook=$hookmanager->executeHooks('moveUploadedFile', $parameters, $object);
 	}
-    
+
 	if (empty($reshook))
 	{
     	// If an upload error has been reported
@@ -897,7 +897,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
     	            break;
     	    }
     	}
-    	
+
     	// If we need to make a virus scan
     	if (empty($disablevirusscan) && file_exists($src_file))
     	{
@@ -908,7 +908,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
     	       return 'ErrorFileIsInfectedWithAVirus: '.join(',',$checkvirusarray);
     	    }
     	}
-    	
+
     	// Security:
     	// Disallow file with some extensions. We renamed them.
     	// Car si on a mis le rep documents dans un rep de la racine web (pas bien), cela permet d'executer du code a la demande.
@@ -916,7 +916,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
     	{
     	    $file_name.= '.noexe';
     	}
-    	
+
     	// Security:
     	// We refuse cache files/dirs, upload using .. and pipes into filenames.
     	if (preg_match('/^\./',$src_file) || preg_match('/\.\./',$src_file) || preg_match('/[<>|]/',$src_file))
@@ -924,7 +924,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
     	    dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
     	    return -1;
     	}
-    	
+
     	// Security:
     	// On interdit fichiers caches, remontees de repertoire ainsi que les pipe dans les noms de fichiers.
     	if (preg_match('/^\./',$dest_file) || preg_match('/\.\./',$dest_file) || preg_match('/[<>|]/',$dest_file))
@@ -933,7 +933,7 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable
     	    return -2;
     	}
 	}
-	
+
 	if ($reshook < 0)	// At least one blocking error returned by one hook
 	{
 		$errmsg = join(',', $hookmanager->errors);
@@ -1005,7 +1005,7 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n
         dol_syslog("Refused to delete file ".$file, LOG_WARNING);
 	    return False;
 	}
-	
+
 	if (empty($nohook))
 	{
 		$hookmanager->initHooks(array('fileslib'));
@@ -1042,16 +1042,16 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n
 				{
 					if ($nophperrors) $ok=@unlink($filename);
 					else $ok=unlink($filename);
-					if ($ok) 
+					if ($ok)
 					{
 					    dol_syslog("Removed file ".$filename, LOG_DEBUG);
-					    
+
 	                    // Delete entry into ecm database
     				    $rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $filename);
     				    if (! preg_match('/(\/temp\/|\/thumbs\/|\.meta$)/', $rel_filetodelete))     // If not a tmp file
     				    {
     				        $rel_filetodelete = preg_replace('/^[\\/]/', '', $rel_filetodelete);
-    				        
+
     				        dol_syslog("Try to remove also entries in database for full relative path = ".$rel_filetodelete, LOG_DEBUG);
         				    include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
         				    $ecmfile=new EcmFiles($db);
@@ -1079,7 +1079,7 @@ function dol_delete_file($file,$disableglob=0,$nophperrors=0,$nohook=0,$object=n
 			if ($nophperrors) $ok=@unlink($file_osencoded);
 			else $ok=unlink($file_osencoded);
 			if ($ok) dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG);
-			else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING);      
+			else dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING);
 		}
 
 		return $ok;
@@ -1104,7 +1104,7 @@ function dol_delete_dir($dir,$nophperrors=0)
         dol_syslog("Refused to delete dir ".$dir, LOG_WARNING);
 	    return False;
 	}
-	
+
     $dir_osencoded=dol_osencode($dir);
     return ($nophperrors?@rmdir($dir_osencoded):rmdir($dir_osencoded));
 }
@@ -1340,7 +1340,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio
 	global $db,$user,$conf,$langs;
 
 	$res = 0;
-	
+
 	if (! empty($_FILES[$varfiles])) // For view $_FILES[$varfiles]['error']
 	{
 		dol_syslog('dol_add_file_process upload_dir='.$upload_dir.' allowoverwrite='.$allowoverwrite.' donotupdatesession='.$donotupdatesession.' savingdocmask='.$savingdocmask, LOG_DEBUG);
@@ -1354,17 +1354,17 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio
 					$val = array($val);
 				}
 			}
-			
+
 			$nbfile = count($TFile['name']);
-			
+
 			for ($i = 0; $i < $nbfile; $i++)
 			{
 				// Define $destfull (path to file including filename) and $destfile (only filename)
 				$destfull=$upload_dir . "/" . $TFile['name'][$i];
 				$destfile=$TFile['name'][$i];
-	
+
 				$savingdocmask = dol_sanitizeFileName($savingdocmask);
-	
+
 				if ($savingdocmask)
 				{
 					$destfull=$upload_dir . "/" . preg_replace('/__file__/',$TFile['name'][$i],$savingdocmask);
@@ -1378,26 +1378,26 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio
 				$destfile = $info['filename'].'.'.strtolower($info['extension']);
 
 				$resupload = dol_move_uploaded_file($TFile['tmp_name'][$i], $destfull, $allowoverwrite, 0, $TFile['error'][$i], 0, $varfiles);
-				
+
 				if (is_numeric($resupload) && $resupload > 0)   // $resupload can be 'ErrorFileAlreadyExists'
 				{
 					global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
-				
+
 					include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
-					
+
 					// Generate thumbs.
 					if (image_format_supported($destfull) == 1)
 					{
 					    // Create thumbs
 					    // We can't use $object->addThumbs here because there is no $object known
-					
+
 					    // Used on logon for example
 					    $imgThumbSmall = vignette($destfull, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
 					    // Create mini thumbs for image (Ratio is near 16/9)
 					    // Used on menu or for setup page for example
 					    $imgThumbMini = vignette($destfull, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
 					}
-					
+
 					// Update session
 					if (empty($donotupdatesession))
 					{
@@ -1406,18 +1406,18 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio
 						$formmail->trackid = $trackid;
 						$formmail->add_attached_files($destfull, $destfile, $TFile['type'][$i]);
 					}
-					
+
 					// Update table of files
-					if ($donotupdatesession) 
+					if ($donotupdatesession)
 					{
 					    $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir);
-				    
+
 					    if (! preg_match('/[\\/]temp[\\/]/', $rel_dir))     // If not a tmp dir
 					    {
 					        $filename = basename($destfile);
 					        $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir);
 					        $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir);
-    					    
+
     					    include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
     					    $ecmfile=new EcmFiles($db);
     					    $ecmfile->filepath = $rel_dir;
@@ -1455,7 +1455,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio
 					}
 				}
 			}
-			
+
 		}
 	} elseif ($link) {
 		require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php';
@@ -1478,7 +1478,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio
 		$langs->load("errors");
 		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("File")), null, 'errors');
 	}
-	
+
 	return $res;
 }
 
@@ -1718,11 +1718,11 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip")
             if (class_exists('ZipArchive'))
             {
                 $foundhandler=1;
-                
+
                 // Initialize archive object
                 $zip = new ZipArchive();
                 $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
-                
+
                 // Create recursive directory iterator
                 /** @var SplFileInfo[] $files */
                 $files = new RecursiveIteratorIterator(
@@ -1738,15 +1738,15 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip")
                         // Get real and relative path for current file
                         $filePath = $file->getRealPath();
                         $relativePath = substr($filePath, strlen($inputdir) + 1);
-                
+
                         // Add current file to archive
                         $zip->addFile($filePath, $relativePath);
                     }
                 }
-                
+
                 // Zip archive will be created only after closing object
-                $zip->close();                
-    
+                $zip->close();
+
                 return 1;
             }
         }
@@ -1793,7 +1793,7 @@ function dol_most_recent_file($dir,$regexfilter='',$excludefilter=array('(\.meta
  * @param	string	$entity				Restrict onto entity (0=no restriction)
  * @param  	User	$fuser				User object (forced)
  * @param	string	$refname			Ref of object to check permission for external users (autodetect if not provided)
- * @param   string  $mode               Check permission for 'read' or 'write'               
+ * @param   string  $mode               Check permission for 'read' or 'write'
  * @return	mixed						Array with access information : 'accessallowed' & 'sqlprotectagainstexternals' & 'original_file' (as a full path name)
  * @see restrictedArea
  */
@@ -1801,7 +1801,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
 {
 	global $user, $conf, $db;
 	global $dolibarr_main_data_root;
-	
+
 	if (! is_object($fuser)) $fuser=$user;
 
 	if (empty($modulepart)) return 'ErrorBadParameter';
@@ -1823,7 +1823,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
 	{
 	    $lire='creer'; $read='write'; $download='upload';
 	}
-	 
+
 	// Wrapping for some images
 	if (($modulepart == 'mycompany' || $modulepart == 'companylogo') && !empty($conf->mycompany->dir_output))
 	{
@@ -2022,7 +2022,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
 	    }
 	    $original_file=$conf->user->dir_output.'/'.$original_file;
 	}
-	
+
 	// Wrapping for third parties
 	else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output))
 	{
@@ -2119,7 +2119,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
 	    }
 	    $original_file=$conf->fournisseur->facture->dir_output.'/temp/massgeneration/'.$user->id.'/'.$original_file;
 	}
-	
+
 	// Wrapping for interventions
 	else if (($modulepart == 'fichinter' || $modulepart == 'ficheinter') && !empty($conf->ficheinter->dir_output))
 	{
@@ -2185,7 +2185,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
 	}
 
 	// Wrapping pour les commandes fournisseurs
-	else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) 
+	else if (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output))
 	{
 		if ($fuser->rights->fournisseur->commande->{$lire} || preg_match('/^specimen/i',$original_file))
 		{
@@ -2317,7 +2317,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
 		}
 		$original_file=$conf->resource->dir_output.'/'.$original_file;
 	}
-	
+
 	// Wrapping pour les remises de cheques
 	else if ($modulepart == 'remisecheque' && !empty($conf->banque->dir_output))
 	{
@@ -2361,14 +2361,14 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
 		$accessallowed=1;
 		$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
 	}
-	
+
 	// Wrapping for miscellaneous medias files
 	elseif ($modulepart == 'medias' && !empty($dolibarr_main_data_root))
 	{
 	    $accessallowed=1;
 	    $original_file=$dolibarr_main_data_root.'/medias/'.$original_file;
 	}
-	
+
 	// Wrapping for backups
 	else if ($modulepart == 'systemtools' && !empty($conf->admin->dir_output))
 	{
@@ -2416,7 +2416,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity,
     // If modulepart=module				Allows any module to open a file if file is in directory called DOL_DATA_ROOT/modulepart
     else
 	{
-	    if (preg_match('/^specimen/i',$original_file))	$accessallowed=1;    // If link to a file called specimen. Test must be done before changing $original_file int full path. 
+	    if (preg_match('/^specimen/i',$original_file))	$accessallowed=1;    // If link to a file called specimen. Test must be done before changing $original_file int full path.
 	    if ($fuser->admin) $accessallowed=1;    // If user is admin
 
 		// Define $accessallowed
diff --git a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php
index a58d00455e8..64d0da9b5fd 100644
--- a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php
+++ b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php
@@ -102,16 +102,10 @@ class doc_generic_contract_odt extends ModelePDFContract
 		$form = new Form($this->db);
 
 		$texte = $this->description.".<br>\n";
-		$texte.= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
+		$texte.= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" enctype="multipart/form-data">';
 		$texte.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 		$texte.= '<input type="hidden" name="action" value="setModuleOptions">';
 		$texte.= '<input type="hidden" name="param1" value="CONTRACT_ADDON_PDF_ODT_PATH">';
-		if ($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT > 0)
-		{
-			$texte.= '<input type="hidden" name="param2" value="CONTRACT_ADDON_PDF_ODT_DEFAULT">';
-			$texte.= '<input type="hidden" name="param3" value="CONTRACT_ADDON_PDF_ODT_TOBILL">';
-			$texte.= '<input type="hidden" name="param4" value="CONTRACT_ADDON_PDF_ODT_CLOSED">';
-		}
 		$texte.= '<table class="nobordernopadding" width="100%">';
 
 		// List of directories area
@@ -144,40 +138,21 @@ class doc_generic_contract_odt extends ModelePDFContract
 		$texte.=$conf->global->CONTRACT_ADDON_PDF_ODT_PATH;
 		$texte.= '</textarea>';
 		$texte.= '</div><div style="display: inline-block; vertical-align: middle;">';
-		$texte.= '<input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button">';
+		$texte.= '<input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Modify")).'" name="Button">';
 		$texte.= '<br></div></div>';
 
 		// Scan directories
 		if (count($listofdir))
 		{
 			$texte.=$langs->trans("NumberOfModelFilesFound").': <b>'.count($listoffiles).'</b>';
-
-			if ($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT > 0)
-			{
-				// Model for creation
-				$liste=ModelePDFContract::liste_modeles($this->db);
-				$texte.= '<table width="50%;">';
-				$texte.= '<tr>';
-				$texte.= '<td width="60%;">'.$langs->trans("DefaultModelPropalCreate").'</td>';
-				$texte.= '<td colspan="">';
-				$texte.= $form->selectarray('value2',$liste,$conf->global->CONTRACT_ADDON_PDF_ODT_DEFAULT);
-				$texte.= "</td></tr>";
-
-				$texte.= '<tr>';
-				$texte.= '<td width="60%;">'.$langs->trans("DefaultModelPropalToBill").'</td>';
-				$texte.= '<td colspan="">';
-				$texte.= $form->selectarray('value3',$liste,$conf->global->CONTRACT_ADDON_PDF_ODT_TOBILL);
-				$texte.= "</td></tr>";
-				$texte.= '<tr>';
-
-				$texte.= '<td width="60%;">'.$langs->trans("DefaultModelPropalClosed").'</td>';
-				$texte.= '<td colspan="">';
-				$texte.= $form->selectarray('value4',$liste,$conf->global->CONTRACT_ADDON_PDF_ODT_CLOSED);
-				$texte.= "</td></tr>";
-				$texte.= '</table>';
-			}
 		}
 
+		// Add select to upload a new template file. TODO Copy this feature on other admin pages.
+		$texte.= '<div>'.$langs->trans("UploadNewTemplate").' <input type="file" name="uploadfile">';
+		$texte.= '<input type="hidden" value="CONTRACT_ADDON_PDF_ODT_PATH" name="keyforuploaddir">';
+		$texte.= '<input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Upload")).'" name="upload">';
+        $texte.= '</div>';
+
 		$texte.= '</td>';
 
 		$texte.= '<td valign="top" rowspan="2" class="hideonsmartphone">';
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index fe547931908..5b213135878 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -48,6 +48,7 @@ InternalUsers=Internal users
 ExternalUsers=External users
 GUISetup=Display
 SetupArea=Setup area
+UploadNewTemplate=Upload new template(s)
 FormToTestFileUploadForm=Form to test file upload (according to setup)
 IfModuleEnabled=Note: yes is effective only if module <b>%s</b> is enabled
 RemoveLock=Remove file <b>%s</b> if it exists to allow usage of the update tool.
@@ -873,6 +874,7 @@ DictionaryProspectStatus=Prospection status
 DictionaryHolidayTypes=Types of leaves
 DictionaryOpportunityStatus=Opportunity status for project/lead
 SetupSaved=Setup saved
+SetupNotSaved=Setup not saved
 BackToModuleList=Back to modules list
 BackToDictionaryList=Back to dictionaries list
 VATManagement=VAT Management
diff --git a/htdocs/modulebuilder/template/admin/setup.php b/htdocs/modulebuilder/template/admin/setup.php
index 63b92bc6468..b3f2cc87d73 100644
--- a/htdocs/modulebuilder/template/admin/setup.php
+++ b/htdocs/modulebuilder/template/admin/setup.php
@@ -39,20 +39,23 @@ require_once '../lib/mymodule.lib.php';
 $langs->load("mymodule@mymodule");
 
 // Access control
-if (! $user->admin) {
-	accessforbidden();
-}
+if (! $user->admin) accessforbidden();
 
 // Parameters
 $action = GETPOST('action', 'alpha');
 
+
 /*
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
+
 /*
  * View
  */
+
 $page_name = "MyModuleSetup";
 llxHeader('', $langs->trans($page_name));
 
diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php
index 5183eeb3382..172bdd9354c 100644
--- a/htdocs/product/admin/product.php
+++ b/htdocs/product/admin/product.php
@@ -74,6 +74,9 @@ $error = 0;
  * Actions
  */
 
+$nomessageinsetmoduleoptions=1;
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'setcodeproduct')
 {
 	if (dolibarr_set_const($db, "PRODUCT_CODEPRODUCT_ADDON",$value,'chaine',0,'',$conf->entity) > 0)
@@ -87,36 +90,6 @@ if ($action == 'setcodeproduct')
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-    {
-    	if (array_key_exists('param'.$i,$_POST))
-    	{
-    		$param=GETPOST("param".$i,'alpha');
-    		$value=GETPOST("value".$i,'alpha');
-    		if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-	    	if (! $res > 0) $error++;
-    	}
-    }
-	if (! $error)
-    {
-        $db->commit();
-	//setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        $db->rollback();
-	// message yet present at the bottom if($action)
-	//setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 if ($action == 'other' && GETPOST('value_PRODUIT_LIMIT_SIZE') >= 0)
 {
 	$res = dolibarr_set_const($db, "PRODUIT_LIMIT_SIZE", GETPOST('value_PRODUIT_LIMIT_SIZE'),'chaine',0,'',$conf->entity);
@@ -278,7 +251,7 @@ if ($action)
     }
     else
     {
-	    setEventMessages($langs->trans("Error"), null, 'errors');
+	    setEventMessages($langs->trans("SetupNotError"), null, 'errors');
     }
 }
 
@@ -543,7 +516,7 @@ foreach ($dirmodels as $reldir)
 
 print '</table>';
 print "<br>";
-    
+
 /*
  * Other conf
  */
@@ -598,7 +571,7 @@ print '</tr>';
 // multiprix nombre de prix a proposer
 if (! empty($conf->global->PRODUIT_MULTIPRICES))
 {
-	
+
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("MultiPricesNumPrices").'</td>';
 	print '<td align="right"><input size="3" type="text" class="flat" name="value_PRODUIT_MULTIPRICES_LIMIT" value="'.$conf->global->PRODUIT_MULTIPRICES_LIMIT.'"></td>';
@@ -640,7 +613,7 @@ print '</tr>';
 
 if (empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT))
 {
-	
+
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("NumberOfProductShowInSelect").'</td>';
 	print '<td align="right"><input size="3" type="text" class="flat" name="value_PRODUIT_LIMIT_SIZE" value="'.$conf->global->PRODUIT_LIMIT_SIZE.'"></td>';
@@ -681,7 +654,7 @@ print '</tr>';
 // View product description in thirdparty language
 if (! empty($conf->global->MAIN_MULTILANGS))
 {
-	
+
 	print '<tr class="oddeven">';
 	print '<td>'.$langs->trans("ViewProductDescInThirdpartyLanguageAbility").'</td>';
 	print '<td width="60" align="right">';
@@ -723,7 +696,7 @@ if (! empty($conf->global->PRODUCT_CANVAS_ABILITY))
 
     				if ($conf->$module->enabled)
     				{
-    					
+
     					print "<tr ".$bc[$var]."><td>";
 
     					print $object->description;
diff --git a/htdocs/projet/admin/project.php b/htdocs/projet/admin/project.php
index fbcecf032cf..9e35ea77e0b 100644
--- a/htdocs/projet/admin/project.php
+++ b/htdocs/projet/admin/project.php
@@ -51,6 +51,8 @@ $type='project';
  * Actions
  */
 
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'setmainoptions')
 {
 	if (GETPOST('PROJECT_USE_OPPORTUNITIES')) dolibarr_set_const($db, "PROJECT_USE_OPPORTUNITIES",GETPOST('PROJECT_USE_OPPORTUNITIES'),'chaine',0,'',$conf->entity);
@@ -104,7 +106,7 @@ else if ($action == 'specimen')
 
 	$project = new Project($db);
 	$project->initAsSpecimen();
-    
+
 	// Search template files
 	$file=''; $classname=''; $filefound=0;
 	$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']);
@@ -188,35 +190,6 @@ else if ($action == 'specimentask')
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-	{
-		if (array_key_exists('param'.$i,$_POST))
-		{
-			$param=GETPOST("param".$i,'alpha');
-			$value=GETPOST("value".$i,'alpha');
-			if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-			if (! $res > 0) $error++;
-		}
-	}
-	if (! $error)
-	{
-		$db->commit();
-		setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-	}
-	else
-	{
-		$db->rollback();
-        setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a model
 else if ($action == 'set')
 {
@@ -414,7 +387,7 @@ foreach ($dirmodels as $reldir)
 
 					if ($module->isEnabled())
 					{
-						
+
 						print '<tr class="oddeven"><td>'.$module->name."</td><td>\n";
 						print $module->info();
 						print '</td>';
@@ -518,7 +491,7 @@ if (empty($conf->global->PROJECT_HIDE_TASKS))
 
 						if ($module->isEnabled())
 						{
-							
+
 							print '<tr class="oddeven"><td>'.$module->name."</td><td>\n";
 							print $module->info();
 							print '</td>';
@@ -660,7 +633,7 @@ foreach ($dirmodels as $reldir)
 
 							if ($modulequalified)
 							{
-								
+
 								print '<tr class="oddeven"><td width="100">';
 								print (empty($module->name)?$name:$module->name);
 								print "</td><td>\n";
diff --git a/htdocs/societe/admin/societe.php b/htdocs/societe/admin/societe.php
index 63ba12197fd..5c84be25521 100644
--- a/htdocs/societe/admin/societe.php
+++ b/htdocs/societe/admin/societe.php
@@ -42,6 +42,9 @@ if (!$user->admin) accessforbidden();
 /*
  * Actions
  */
+
+include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
+
 if ($action == 'setcodeclient')
 {
 	if (dolibarr_set_const($db, "SOCIETE_CODECLIENT_ADDON",$value,'chaine',0,'',$conf->entity) > 0)
@@ -101,35 +104,6 @@ if ($action == 'updateoptions')
 	}
 }
 
-// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...)
-if ($action == 'setModuleOptions')
-{
-	$post_size=count($_POST);
-
-	$db->begin();
-
-	for($i=0;$i < $post_size;$i++)
-    {
-    	if (array_key_exists('param'.$i,$_POST))
-    	{
-    		$param=GETPOST("param".$i,'alpha');
-    		$value=GETPOST("value".$i,'alpha');
-    		if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity);
-	    	if (! $res > 0) $error++;
-    	}
-    }
-	if (! $error)
-    {
-        $db->commit();
-	    setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
-    }
-    else
-    {
-        $db->rollback();
-	    setEventMessages($langs->trans("Error"), null, 'errors');
-	}
-}
-
 // Activate a document generator module
 if ($action == 'set')
 {
-- 
GitLab