Browse Source

Merge remote-tracking branch 'uptream/develop' into 6.0-stripe

Alexandre SPANGARO 8 years ago
parent
commit
586ea54bfc
78 changed files with 2051 additions and 286 deletions
  1. 1 1
      build/debian/install.forced.php.install
  2. 2 1
      build/makepack-dolibarr.pl
  3. 2 2
      htdocs/accountancy/admin/accountmodel.php
  4. 1 1
      htdocs/accountancy/admin/export.php
  5. 2 2
      htdocs/accountancy/admin/index.php
  6. 1 1
      htdocs/accountancy/admin/journals.php
  7. 2 2
      htdocs/accountancy/customer/list.php
  8. 6 3
      htdocs/accountancy/index.php
  9. 1 1
      htdocs/adherents/subscription/card.php
  10. 7 1
      htdocs/admin/chequereceipts.php
  11. 7 6
      htdocs/admin/commande.php
  12. 9 2
      htdocs/admin/contract.php
  13. 84 20
      htdocs/admin/defaultvalues.php
  14. 6 2
      htdocs/admin/dict.php
  15. 8 2
      htdocs/admin/expedition.php
  16. 8 2
      htdocs/admin/expensereport.php
  17. 10 6
      htdocs/admin/external_rss.php
  18. 7 6
      htdocs/admin/facture.php
  19. 9 2
      htdocs/admin/fichinter.php
  20. 7 1
      htdocs/admin/livraison.php
  21. 1 1
      htdocs/admin/payment.php
  22. 8 7
      htdocs/admin/propal.php
  23. 7 1
      htdocs/admin/supplier_invoice.php
  24. 8 1
      htdocs/admin/supplier_order.php
  25. 9 2
      htdocs/admin/supplier_proposal.php
  26. 21 5
      htdocs/admin/translation.php
  27. 17 32
      htdocs/admin/websites.php
  28. 8 4
      htdocs/comm/card.php
  29. 1 0
      htdocs/commande/class/commande.class.php
  30. 1 1
      htdocs/compta/bank/card.php
  31. 1 1
      htdocs/compta/facture/admin/facture_cust_extrafields.php
  32. 1 1
      htdocs/compta/facture/admin/facturedet_cust_extrafields.php
  33. 1 1
      htdocs/compta/facture/card.php
  34. 4 0
      htdocs/core/class/extrafields.class.php
  35. 1 1
      htdocs/core/class/html.form.class.php
  36. 12 5
      htdocs/core/db/DoliDB.class.php
  37. 13 1
      htdocs/core/lib/files.lib.php
  38. 66 18
      htdocs/core/lib/functions.lib.php
  39. 2 1
      htdocs/core/lib/functions2.lib.php
  40. 2 2
      htdocs/core/menus/standard/eldy.lib.php
  41. 24 23
      htdocs/core/modules/expedition/doc/pdf_rouget.modules.php
  42. 1 1
      htdocs/core/modules/import/import_xlsx.modules.php
  43. 4 2
      htdocs/core/modules/syslog/mod_syslog_file.php
  44. 1 1
      htdocs/core/tpl/admin_extrafields_view.tpl.php
  45. 0 1
      htdocs/fourn/card.php
  46. 2 3
      htdocs/fourn/paiement/card.php
  47. 0 0
      htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php
  48. 2 2
      htdocs/install/check.php
  49. 5 4
      htdocs/install/default.css
  50. 4 4
      htdocs/install/fileconf.php
  51. 8 0
      htdocs/install/mysql/migration/5.0.0-6.0.0.sql
  52. 2 2
      htdocs/install/mysql/migration/repair.sql
  53. 26 0
      htdocs/install/mysql/tables/llx_supplier_proposaldet.key.sql
  54. 4 3
      htdocs/install/mysql/tables/llx_website.sql
  55. 4 2
      htdocs/install/mysql/tables/llx_website_pages.sql
  56. 9 9
      htdocs/langs/en_US/accountancy.lang
  57. 9 6
      htdocs/langs/en_US/admin.lang
  58. 1 1
      htdocs/langs/en_US/bookmarks.lang
  59. 4 4
      htdocs/langs/en_US/companies.lang
  60. 1 0
      htdocs/langs/en_US/errors.lang
  61. 1 1
      htdocs/langs/en_US/mails.lang
  62. 1 1
      htdocs/langs/en_US/main.lang
  63. 1 1
      htdocs/langs/en_US/sendings.lang
  64. 2 2
      htdocs/langs/en_US/website.lang
  65. 1 1
      htdocs/master.inc.php
  66. 28 0
      htdocs/public/payment/index.php
  67. 1002 0
      htdocs/public/payment/newpayment.php
  68. 146 0
      htdocs/public/payment/paymentko.php
  69. 308 0
      htdocs/public/payment/paymentok.php
  70. 1 7
      htdocs/societe/agenda.php
  71. BIN
      htdocs/theme/eldy/img/save.png
  72. 5 1
      htdocs/theme/eldy/style.css.php
  73. BIN
      htdocs/theme/md/img/save.png
  74. 3 0
      htdocs/theme/md/style.css.php
  75. 2 2
      htdocs/user/class/user.class.php
  76. 18 29
      htdocs/websites/class/website.class.php
  77. 8 5
      htdocs/websites/class/websitepage.class.php
  78. 49 19
      htdocs/websites/index.php

+ 1 - 1
build/debian/install.forced.php.install

@@ -7,7 +7,7 @@
 //
 
 $force_install_packager='deb';
-$force_install_noedit=2;
+$force_install_noedit=1;
 $force_install_message='KeepDefaultValuesDeb';
 #$force_install_main_data_root='/usr/share/dolibarr/documents';
 $force_install_main_data_root='/var/lib/dolibarr/documents';

+ 2 - 1
build/makepack-dolibarr.pl

@@ -509,7 +509,7 @@ if ($nboftargetok) {
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/documents`;
 
 		# Removed known external modules to avoid any error when packaging from env where external modules are tested 
-	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/custom/*`;	# For custom we want to keep dir
+	    #$ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type d -exec rm -fr {} \;`;	# For custom we want to keep dir
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/allscreens*`;
 		$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/ancotec*`;
 	    $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/cabinetmed*`;
@@ -550,6 +550,7 @@ if ($nboftargetok) {
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/doc`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/example`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mike42/escpos-php/test`;
+        $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mobiledetect/mobiledetectlib/.gitmodules`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/lib/Mail`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/samples`;
         $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/php-iban/docs`;

+ 2 - 2
htdocs/accountancy/admin/accountmodel.php

@@ -901,8 +901,8 @@ if ($id)
         if ($id == 4) print '<td></td>';
         print '<td class="liste_titre"></td>';
     	print '<td class="liste_titre" colspan="2" align="right">';
-    	$searchpitco=$form->showFilterAndCheckAddButtons(0);
-    	print $searchpitco;
+    	$searchpicto=$form->showFilterAndCheckAddButtons(0);
+    	print $searchpicto;
     	print '</td>';
         print '</tr>';
             

+ 1 - 1
htdocs/accountancy/admin/export.php

@@ -130,7 +130,7 @@ print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">';
 print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
 print '<input type="hidden" name="action" value="update">';
 
-dol_fiche_head($head, 'export', $langs->trans("Configuration"), 0, 'cron');
+dol_fiche_head($head, 'export', $langs->trans("Configuration"), -1, 'cron');
 
 $var = true;
 

+ 2 - 2
htdocs/accountancy/admin/index.php

@@ -171,7 +171,7 @@ print '<form action="' . $_SERVER["PHP_SELF"] . '" method="post">';
 print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
 print '<input type="hidden" name="action" value="update">';
 
-dol_fiche_head($head, 'general', $langs->trans("Configuration"), 0, 'cron');
+dol_fiche_head($head, 'general', $langs->trans("Configuration"), -1, 'cron');
 
 
 // Default mode for calculating turnover (parameter ACCOUNTING_MODE)
@@ -299,7 +299,7 @@ print '<div class="center"><input type="submit" class="button" value="' . $langs
 print '<br>';
 print '<br>';
 
-print $langs->trans("AccountancySetupDoneFromAccountancyMenu", $langs->transnoentitiesnoconv("Home").'-'.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy"));
+print '<div class="opacitymedium">'.$langs->trans("AccountancySetupDoneFromAccountancyMenu", $langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy")).'</div>';
 
 print '<br>';
 print '</form>';

+ 1 - 1
htdocs/accountancy/admin/journals.php

@@ -94,7 +94,7 @@ print load_fiche_titre($langs->trans('ConfigAccountingExpert'), $linkback, 'titl
 
 $head = admin_accounting_prepare_head(null);
 
-dol_fiche_head($head, 'journal', $langs->trans("Configuration"), 0, 'cron');
+dol_fiche_head($head, 'journal', $langs->trans("Configuration"), -1, 'cron');
 
 $sql = "SELECT j.rowid, j.code, j.label, j.nature, j.active";
 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_journal as j";

+ 2 - 2
htdocs/accountancy/customer/list.php

@@ -285,7 +285,7 @@ if ($result) {
 	print '<td class="liste_titre"></td>';
 	print '<td class="liste_titre"></td>';
 	print '<td align="center" class="liste_titre">';
-	$searchpicto=$form->showFilterAndCheckAddButtons($massactionbutton?1:0, 'checkforselect', 1);
+	$searchpicto=$form->showFilterButtons();
 	print $searchpicto;
 	print '</td>';
 	print '</tr>';
@@ -303,7 +303,7 @@ if ($result) {
 	print_liste_field_titre($langs->trans("IntoAccount"), '', '', '', '', 'align="center"');
 	$checkpicto='';
 	if ($massactionbutton) $checkpicto=$form->showCheckAddButtons('checkforselect', 1);
-	print_liste_field_titre($checkpitco, '', '', '', '', 'align="center"');
+	print_liste_field_titre($checkpicto, '', '', '', '', 'align="center"');
 	print "</tr>\n";
 	
 	$facture_static = new Facture($db);

+ 6 - 3
htdocs/accountancy/index.php

@@ -129,15 +129,18 @@ if (! empty($conf->don->enabled))
     print "<br>\n";
     print "<br>\n";
 }*/
+
 $step++;
-$textlink='<strong>'.$langs->transnoentitiesnoconv("Home").'-'.$langs->transnoentitiesnoconv("MenuBankCash").'</strong>';
-print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBank", $step, $textlink);
+print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescProd", $step, '<strong>'.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("ProductsBinding").'</strong>');
 print "<br>\n";
 print "<br>\n";
 
 $step++;
-print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescProd", $step, '<strong>'.$langs->transnoentitiesnoconv("MenuFinancial").'-'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("ProductsBinding").'</strong>')."<br>\n";
+$textlink='<strong>'.$langs->transnoentitiesnoconv("MenuBankCash").'</strong>';
+print img_picto('', 'puce').' '.$langs->trans("AccountancyAreaDescBank", $step, $textlink);
 print "<br>\n";
+print "<br>\n";
+
 
 print "<br>\n";
 print_fiche_titre($langs->trans("AccountancyAreaDescActionFreq"), '', 'object_calendarweek');

+ 1 - 1
htdocs/adherents/subscription/card.php

@@ -145,7 +145,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->adherent-
     $result=$object->delete($user);
     if ($result > 0)
     {
-    	header("Location: card_subscriptions.php?rowid=".$object->fk_adherent);
+    	header("Location: ".DOL_URL_ROOT."/adherents/card.php?rowid=".$object->fk_adherent);
     	exit;
     }
     else

+ 7 - 1
htdocs/admin/chequereceipts.php

@@ -257,8 +257,14 @@ $var=true;
 
 $var=! $var;
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnChequeReceipts").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnChequeReceipts"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='BANK_CHEQUERECEIPT_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {

+ 7 - 6
htdocs/admin/commande.php

@@ -565,12 +565,18 @@ print "<td>&nbsp;</td>\n";
 print "</tr>\n";
 $var=true;
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_ORDER_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnOrders").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnOrders"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='ORDER_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -593,11 +599,6 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_COMMANDE_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
-$substitutionarray=pdf_getSubstitutionArray($langs);
-$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
-$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
-foreach($substitutionarray as $key => $val) $htmltext.=$key.'<br>';
-$htmltext.='</i>';
 print $form->textwithpicto($langs->trans("WatermarkOnDraftOrders"), $htmltext);
 print '</td><td>';
 print '<input class="flat minwidth200" type="text" name="COMMANDE_DRAFT_WATERMARK" value="'.$conf->global->COMMANDE_DRAFT_WATERMARK.'">';

+ 9 - 2
htdocs/admin/contract.php

@@ -502,9 +502,15 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print "</tr>\n";
 $var=true;
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnContracts").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnContracts"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='CONTRACT_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -521,7 +527,8 @@ print '</td></tr>'."\n";
 //Use draft Watermark
 
 print '<tr class="oddeven"><td>';
-print $langs->trans("WatermarkOnDraftContractCards").'</td><td>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftContractCards"), $htmltext);
+print '</td><td>';
 print '<input size="50" class="flat" type="text" name="CONTRACT_DRAFT_WATERMARK" value="'.$conf->global->CONTRACT_DRAFT_WATERMARK.'">';
 print '</td></tr>'."\n";
 

+ 84 - 20
htdocs/admin/defaultvalues.php

@@ -56,6 +56,10 @@ $defaultvalue = GETPOST('defaultvalue');
 
 $defaulturl=preg_replace('/^\//', '', $defaulturl);
 
+$urlpage = GETPOST('urlpage');
+$key = GETPOST('key');
+$value = GETPOST('value');
+
 
 /*
  * Actions
@@ -81,25 +85,51 @@ if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETP
 }
 
 
-if ($action == 'add' || (GETPOST('add') && $action != 'update'))
+if (($action == 'add' || (GETPOST('add') && $action != 'update')) || GETPOST('actionmodify'))
 {
 	$error=0;
 
-	if (empty($defaulturl))
+	if (($action == 'add' || (GETPOST('add') && $action != 'update')))
 	{
-		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Url")), null, 'errors');
-		$error++;
+    	if (empty($defaulturl))
+    	{
+    		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Url")), null, 'errors');
+    		$error++;
+    	}
+    	if (empty($defaultkey))
+    	{
+    		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Field")), null, 'errors');
+    		$error++;
+    	}
 	}
-	if (empty($defaultkey))
+	if (GETPOST('actionmodify'))
 	{
-		setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Key")), null, 'errors');
-		$error++;
+	    if (empty($urlpage))
+	    {
+	        setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Url")), null, 'errors');
+	        $error++;
+	    }
+	    if (empty($key))
+	    {
+	        setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Field")), null, 'errors');
+	        $error++;
+	    }
 	}
+	
 	if (! $error)
 	{
 	    $db->begin();
-	     
-		$sql = "INSERT INTO ".MAIN_DB_PREFIX."default_values(type, user_id, page, param, value, entity) VALUES ('".$db->escape($mode)."', 0, '".$db->escape($defaulturl)."','".$db->escape($defaultkey)."','".$db->escape($defaultvalue)."', ".$db->escape($conf->entity).")";
+	    
+	    if ($action == 'add' || (GETPOST('add') && $action != 'update'))
+	    {
+            $sql = "INSERT INTO ".MAIN_DB_PREFIX."default_values(type, user_id, page, param, value, entity) VALUES ('".$db->escape($mode)."', 0, '".$db->escape($defaulturl)."','".$db->escape($defaultkey)."','".$db->escape($defaultvalue)."', ".$db->escape($conf->entity).")";
+	    }
+	    if (GETPOST('actionmodify'))
+	    {
+		    $sql = "UPDATE ".MAIN_DB_PREFIX."default_values SET page = '".$db->escape($urlpage)."', param = '".$db->escape($key)."', value = '".$db->escape($value)."'";
+		    $sql.= " WHERE rowid = ".$id;
+	    }
+		
 		$result = $db->query($sql);
 		if ($result > 0)
 		{
@@ -176,6 +206,10 @@ $head=defaultvalues_prepare_head();
     
 dol_fiche_head($head, $mode, '', -1, '');
 
+if ($mode == 'sortorder')
+{
+    print info_admin($langs->trans("WarningSettingSortOrder")).'<br>';
+}
 
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" id="action" name="action" value="">';
@@ -187,29 +221,37 @@ $texthelp=$langs->trans("PageUrlForDefaultValues");
 if ($mode == 'createform') $texthelp.=$langs->trans("PageUrlForDefaultValuesCreate", 'societe/card.php');
 else $texthelp.=$langs->trans("PageUrlForDefaultValuesList", 'societe/list.php');
 $texturl=$form->textwithpicto($langs->trans("Url"), $texthelp);
-print_liste_field_titre($texturl,$_SERVER["PHP_SELF"],'defaulturl','',$param,'',$sortfield,$sortorder);
+print_liste_field_titre($texturl,$_SERVER["PHP_SELF"],'page,param','',$param,'',$sortfield,$sortorder);
 $texthelp=$langs->trans("TheKeyIsTheNameOfHtmlField");
-if ($mode != 'sortorder') $textkey=$form->textwithpicto($langs->trans("Key"), $texthelp);
-else $textkey=$form->textwithpicto($langs->trans("Key"), $texthelp);
-print_liste_field_titre($textkey,$_SERVER["PHP_SELF"],'defaultkey','',$param,'',$sortfield,$sortorder);
+if ($mode != 'sortorder') 
+{
+    $textkey=$form->textwithpicto($langs->trans("Field"), $texthelp);
+}
+else 
+{
+    $texthelp='field or alias.field';
+    $textkey=$form->textwithpicto($langs->trans("Field"), $texthelp);
+}
+print_liste_field_titre($textkey,$_SERVER["PHP_SELF"],'param','',$param,'',$sortfield,$sortorder);
 if ($mode != 'sortorder')
 {
     $texthelp=$langs->trans("FollowingConstantsWillBeSubstituted").'<br>';
     // See list into GETPOST
     $texthelp.='__USERID__<br>';
+    $texthelp.='__SUPERVISORID__<br>';
     $texthelp.='__MYCOUNTRYID__<br>';
     $texthelp.='__DAY__<br>';
     $texthelp.='__MONTH__<br>';
     $texthelp.='__YEAR__<br>';
     if (! empty($conf->multicompany->enabled)) $texthelp.='__ENTITYID__<br>';
-    $textvalue=$form->textwithpicto($langs->trans("Value"), $texthelp);
+    $textvalue=$form->textwithpicto($langs->trans("Value"), $texthelp, 1, 'help', '', 0, 2, '');
 }
 else
 {
     $texthelp='ASC or DESC';
     $textvalue=$form->textwithpicto($langs->trans("SortOrder"), $texthelp);
 }
-print_liste_field_titre($textvalue, $_SERVER["PHP_SELF"], 'defaultvalue', '', $param, '', $sortfield, $sortorder);
+print_liste_field_titre($textvalue, $_SERVER["PHP_SELF"], 'value', '', $param, '', $sortfield, $sortorder);
 if (! empty($conf->multicompany->enabled) && !$user->entity) print_liste_field_titre($langs->trans("Entity"),$_SERVER["PHP_SELF"],'entity,page','',$param,'',$sortfield,$sortorder);
 print '<td align="center"></td>';
 print "</tr>\n";
@@ -269,9 +311,17 @@ if ($result)
 
 		print '<tr class="oddeven">';
 		
-		print '<td>'.$obj->page.'</td>'."\n";
-   	    print '<td>'.$obj->param.'</td>'."\n";
-        
+		print '<td>';
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->page;
+		else print '<input type="text" name="urlpage" value="'.dol_escape_htmltag($obj->page).'">';
+		print '</td>'."\n";
+   	    
+		// Key
+		print '<td>';
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->param;
+		else print '<input type="text" name="key" value="'.dol_escape_htmltag($obj->param).'">';
+		print '</td>'."\n";
+
 		// Value
 		print '<td>';
 		/*print '<input type="hidden" name="const['.$i.'][rowid]" value="'.$obj->rowid.'">';
@@ -279,11 +329,25 @@ if ($result)
 		print '<input type="hidden" name="const['.$i.'][name]" value="'.$obj->transkey.'">';
 		print '<input type="text" id="value_'.$i.'" class="flat inputforupdate" size="30" name="const['.$i.'][value]" value="'.dol_escape_htmltag($obj->transvalue).'">';
 		*/
-		print $obj->value;
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->value;
+		else print '<input type="text" name="value" value="'.dol_escape_htmltag($obj->value).'">';
 		print '</td>';
 
 		print '<td align="center">';
-		print '<a href="'.$_SERVER['PHP_SELF'].'?rowid='.$obj->rowid.'&entity='.$obj->entity.'&mode='.$mode.'&action=delete'.((empty($user->entity) && $debug)?'&debug=1':'').'">'.img_delete().'</a>';
+		if ($action != 'edit' || GETPOST('rowid') != $obj->rowid)
+		{
+    		print '<a href="'.$_SERVER['PHP_SELF'].'?rowid='.$obj->rowid.'&entity='.$obj->entity.'&mode='.$mode.'&action=edit'.((empty($user->entity) && $debug)?'&debug=1':'').'">'.img_edit().'</a>';
+    		print ' &nbsp; ';
+    		print '<a href="'.$_SERVER['PHP_SELF'].'?rowid='.$obj->rowid.'&entity='.$obj->entity.'&mode='.$mode.'&action=delete'.((empty($user->entity) && $debug)?'&debug=1':'').'">'.img_delete().'</a>';
+		}
+		else
+		{
+		    print '<input type="hidden" name="page" value="'.$page.'">';
+		    print '<input type="hidden" name="rowid" value="'.$id.'">';
+		    print '<div name="'.(! empty($obj->rowid)?$obj->rowid:'none').'"></div>';
+		    print '<input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
+		    print '<input type="submit" class="button" name="actioncancel" value="'.$langs->trans("Cancel").'">';
+		}
 		print '</td>';
 		
 		print "</tr>\n";

+ 6 - 2
htdocs/admin/dict.php

@@ -660,7 +660,11 @@ if (GETPOST('actionadd') || GETPOST('actionmodify'))
 	if ($_POST["accountancy_code"] <= 0) $_POST["accountancy_code"]='';	// If empty, we force to null
 	if ($_POST["accountancy_code_sell"] <= 0) $_POST["accountancy_code_sell"]='';	// If empty, we force to null
 	if ($_POST["accountancy_code_buy"] <= 0) $_POST["accountancy_code_buy"]='';	// If empty, we force to null
-
+    if ($id == 10 && isset($_POST["code"]))  // Spaces are not allowed into code 
+    {
+        $_POST["code"]=preg_replace('/\s/','',$_POST["code"]);
+    }
+    
     // Si verif ok et action add, on ajoute la ligne
     if ($ok && GETPOST('actionadd'))
     {
@@ -1302,10 +1306,10 @@ if ($id)
                     if (empty($reshook)) fieldList($fieldlist,$obj,$tabname[$id],'edit');
 
                     print '<td colspan="3" align="center">';
+                    print '<div name="'.(! empty($obj->rowid)?$obj->rowid:$obj->code).'"></div>';
                     print '<input type="hidden" name="page" value="'.$page.'">';
                     print '<input type="hidden" name="rowid" value="'.$rowid.'">';
                     print '<input type="submit" class="button" name="actionmodify" value="'.$langs->trans("Modify").'">';
-                    print '<div name="'.(! empty($obj->rowid)?$obj->rowid:$obj->code).'"></div>';
                     print '<input type="submit" class="button" name="actioncancel" value="'.$langs->trans("Cancel").'">';
                     print '</td>';
                 }

+ 8 - 2
htdocs/admin/expedition.php

@@ -502,8 +502,14 @@ print "<tr class=\"liste_titre\">";
 print "<td>".$langs->trans("Parameter")."</td>\n";
 print "</tr>";
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr><td>';
-print $langs->trans("FreeLegalTextOnShippings").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnShippings"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SHIPPING_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -518,7 +524,7 @@ else
 print "</td></tr>\n";
 
 print '<tr><td>';
-print $langs->trans("WatermarkOnDraft").'<br>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftContractCards"), $htmltext).'<br>';
 print '<input size="50" class="flat" type="text" name="SHIPPING_DRAFT_WATERMARK" value="'.$conf->global->SHIPPING_DRAFT_WATERMARK.'">';
 print "</td></tr>\n";
 

+ 8 - 2
htdocs/admin/expensereport.php

@@ -505,9 +505,15 @@ print '<td align="center" width="60"></td>';
 print "</tr>\n";
 $var=true;
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnExpenseReports").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnExpenseReports"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='EXPENSEREPORT_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -524,7 +530,7 @@ print '</td></tr>'."\n";
 //Use draft Watermark
 
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("WatermarkOnDraftOrders").'<br>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftExpenseReports"), $htmltext).'<br>';
 print '<input size="50" class="flat" type="text" name="EXPENSEREPORT_DRAFT_WATERMARK" value="'.$conf->global->EXPENSEREPORT_DRAFT_WATERMARK.'">';
 print '</td></tr>'."\n";
 

+ 10 - 6
htdocs/admin/external_rss.php

@@ -206,13 +206,13 @@ print '<td>'.$langs->trans("Example").'</td>';
 print '</tr>';
 print '<tr class="impair">';
 print '<td width="100">'.$langs->trans("Title").'</td>';
-print '<td><input type="text" name="external_rss_title_'.($lastexternalrss+1).'" value="'.@constant("EXTERNAL_RSS_TITLE_" . ($lastexternalrss+1)).'" size="64"></td>';
+print '<td><input type="text" class="flat minwidth300" name="external_rss_title_'.($lastexternalrss+1).'" value=""></td>';
 print '<td>'.$langs->trans('RSSUrlExample').'</td>';
 print '</tr>';
 
 print '<tr class="pair">';
 print '<td>'.$langs->trans('RSSUrl').'</td>';
-print '<td><input type="text" name="external_rss_urlrss_'.($lastexternalrss+1).'" value="'.@constant("EXTERNAL_RSS_URLRSS_" . ($lastexternalrss+1)).'" size="64"></td>';
+print '<td><input type="text" class="flat minwidth300" name="external_rss_urlrss_'.($lastexternalrss+1).'" value=""></td>';
 print '<td>http://news.google.com/news?ned=us&topic=h&output=rss<br>http://www.dolibarr.org/rss</td>';
 print '</tr>';
 print '</table>';
@@ -243,10 +243,12 @@ if ($resql)
 
 	    preg_match('/^([0-9]+)/i',$obj->note,$reg);
 		$idrss = $reg[1];
-		//print "x".$idrss;
+        $keyrssurl="EXTERNAL_RSS_URLRSS_".$idrss;
+        $keyrsstitle="EXTERNAL_RSS_URLRSS_".$idrss;
+        //print "x".$idrss;
 
         $rssparser=new RssParser($db);
-		$result = $rssparser->parser(@constant("EXTERNAL_RSS_URLRSS_".$idrss), 5, 300, $conf->externalrss->dir_temp);
+		$result = $rssparser->parser($conf->global->$keyrssurl, 5, 300, $conf->externalrss->dir_temp);
 
 		$var=true;
 
@@ -269,13 +271,13 @@ if ($resql)
 		
 		print '<tr class="oddeven">';
 		print "<td width=\"100px\">".$langs->trans("Title")."</td>";
-		print "<td><input type=\"text\" class=\"flat\" name=\"external_rss_title_" . $idrss . "\" value=\"" . @constant("EXTERNAL_RSS_TITLE_" . $idrss) . "\" size=\"64\"></td>";
+		print "<td><input type=\"text\" class=\"flat minwidth300\" name=\"external_rss_title_" . $idrss . "\" value=\"" . $conf->global->$keyrsstitle . "\"></td>";
 		print "</tr>";
 
 		
 		print '<tr class="oddeven">';
 		print "<td>".$langs->trans("URL")."</td>";
-		print "<td><input type=\"text\" class=\"flat\" name=\"external_rss_urlrss_" . $idrss . "\" value=\"" . @constant("EXTERNAL_RSS_URLRSS_" . $idrss) . "\" size=\"64\"></td>";
+		print "<td><input type=\"text\" class=\"flat minwidth300\" name=\"external_rss_urlrss_" . $idrss . "\" value=\"" . $conf->global->$keyrssurl . "\"></td>";
 		print "</tr>";
 
 		
@@ -304,6 +306,8 @@ if ($resql)
 			print "<td>".$langs->trans("Logo")."</td>";
 			print '<td>';
 			$imageurl=$rssparser->getImageUrl();
+			$linkrss=$rssparser->getLink();
+			if (! preg_match('/^http/', $imageurl)) $imageurl=$linkrss.$imageurl;
 			if ($imageurl) print '<img height="32" src="'.$imageurl.'">';
 			else print $langs->trans("None");
 			print '</td>';

+ 7 - 6
htdocs/admin/facture.php

@@ -733,12 +733,18 @@ print '<input type="submit" class="button" value="'.$langs->trans("Modify").'" /
 print "</td></tr>\n";
 print '</form>';
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
 print '<input type="hidden" name="action" value="set_INVOICE_FREE_TEXT" />';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnInvoices").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnInvoices"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='INVOICE_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -760,11 +766,6 @@ print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
 print '<input type="hidden" name="action" value="set_FACTURE_DRAFT_WATERMARK" />';
 print '<tr class="oddeven"><td>';
-$substitutionarray=pdf_getSubstitutionArray($langs);
-$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
-$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
-foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
-$htmltext.='</i>';
 print $form->textwithpicto($langs->trans("WatermarkOnDraftBill"), $htmltext);
 print '</td>';
 print '<td><input size="50" class="flat" type="text" name="FACTURE_DRAFT_WATERMARK" value="'.$conf->global->FACTURE_DRAFT_WATERMARK.'" />';

+ 9 - 2
htdocs/admin/fichinter.php

@@ -534,12 +534,18 @@ print "<td>&nbsp;</td>\n";
 print "</tr>\n";
 $var=true;
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_FICHINTER_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnInterventions").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnInterventions"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='FICHINTER_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -562,7 +568,8 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_FICHINTER_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
-print $langs->trans("WatermarkOnDraftInterventionCards").'</td><td>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftInterventionCards"), $htmltext).'<br>';
+print '</td><td>';
 print '<input size="50" class="flat" type="text" name="FICHINTER_DRAFT_WATERMARK" value="'.$conf->global->FICHINTER_DRAFT_WATERMARK.'">';
 print '</td><td align="right">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';

+ 7 - 1
htdocs/admin/livraison.php

@@ -479,12 +479,18 @@ print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 $var=true;
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_DELIVERY_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnDeliveryReceipts").' ('.$langs->trans("AddCRIfTooLong").')<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnDeliveryReceipts"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='DELIVERY_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {

+ 1 - 1
htdocs/admin/payment.php

@@ -117,7 +117,7 @@ $linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToM
 print load_fiche_titre($langs->trans("BillsSetup"),$linkback,'title_setup');
 
 $head = invoice_admin_prepare_head();
-dol_fiche_head($head, 'payment', $langs->trans("Invoices"), 0, 'invoice');
+dol_fiche_head($head, 'payment', $langs->trans("Invoices"), -1, 'invoice');
 
 /*
  *  Numbering module

+ 8 - 7
htdocs/admin/propal.php

@@ -570,11 +570,17 @@ print "</td></tr>\n";
 print '</form>';
 */
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_PROPOSAL_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnProposal").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnProposal"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='PROPOSAL_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -596,12 +602,7 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_PROPALE_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
-$substitutionarray=pdf_getSubstitutionArray($langs);
-$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
-$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
-foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
-$htmltext.='</i>';
-print $form->textwithpicto($langs->trans("WatermarkOnDraftProposal"), $htmltext);
+print $form->textwithpicto($langs->trans("WatermarkOnDraftProposal"), $htmltext).'<br>';
 print '</td><td>';
 print '<input class="flat minwidth200" type="text" name="PROPALE_DRAFT_WATERMARK" value="'.$conf->global->PROPALE_DRAFT_WATERMARK.'">';
 print '</td><td align="right">';

+ 7 - 1
htdocs/admin/supplier_invoice.php

@@ -471,8 +471,14 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnInvoices").' '.img_info($langs->trans("AddCRIfTooLong")).'</br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnInvoices"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SUPPLIER_INVOICE_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {

+ 8 - 1
htdocs/admin/supplier_order.php

@@ -491,6 +491,7 @@ print '<td align="center" width="60">'.$langs->trans("Value").'</td>';
 print '<td width="80">&nbsp;</td>';
 print "</tr>\n";
 $var=false;
+
 //if ($conf->global->MAIN_FEATURES_LEVEL > 0)
 //{
 	print '<tr class="oddeven"><td>';
@@ -536,8 +537,14 @@ else
 }
 */
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnOrders").' '.img_info($langs->trans("AddCRIfTooLong")).'<br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnOrders"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SUPPLIER_ORDER_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {

+ 9 - 2
htdocs/admin/supplier_proposal.php

@@ -523,12 +523,18 @@ print '<td width="60" align="center">'.$langs->trans("Value")."</td>\n";
 print "<td>&nbsp;</td>\n";
 print "</tr>";
 
+$substitutionarray=pdf_getSubstitutionArray($langs);
+$substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation");
+$htmltext = '<i>'.$langs->trans("AvailableVariables").':<br>';
+foreach($substitutionarray as $key => $val)	$htmltext.=$key.'<br>';
+$htmltext.='</i>';
+
 $var=! $var;
 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print '<input type="hidden" name="action" value="set_SUPPLIER_PROPOSAL_FREE_TEXT">';
 print '<tr class="oddeven"><td colspan="2">';
-print $langs->trans("FreeLegalTextOnSupplierProposal").' '.img_info($langs->trans("AddCRIfTooLong")).'</br>';
+print $form->textwithpicto($langs->trans("FreeLegalTextOnSupplierProposal"), $langs->trans("AddCRIfTooLong").'<br><br>'.$htmltext).'<br>';
 $variablename='SUPPLIER_PROPOSAL_FREE_TEXT';
 if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
 {
@@ -550,7 +556,8 @@ print "<form method=\"post\" action=\"".$_SERVER["PHP_SELF"]."\">";
 print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
 print "<input type=\"hidden\" name=\"action\" value=\"set_SUPPLIER_PROPOSAL_DRAFT_WATERMARK\">";
 print '<tr class="oddeven"><td>';
-print $langs->trans("WatermarkOnDraftSupplierProposal").'</td><td>';
+print $form->textwithpicto($langs->trans("WatermarkOnDraftProposal"), $htmltext).'<br>';
+print '</td><td>';
 print '<input size="50" class="flat" type="text" name="SUPPLIER_PROPOSAL_DRAFT_WATERMARK" value="'.$conf->global->SUPPLIER_PROPOSAL_DRAFT_WATERMARK.'">';
 print '</td><td align="right">';
 print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';

+ 21 - 5
htdocs/admin/translation.php

@@ -71,7 +71,7 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e
 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
 
 // Purge search criteria
-if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
+if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
 {
     $transkey='';
     $transvalue='';
@@ -114,8 +114,16 @@ if ($action == 'add' || (GETPOST('add') && $action != 'update'))
 		}
 		else
 		{
-	        $db->rollback();
-		    setEventMessages($db->lasterror(), null, 'errors');
+
+		    $db->rollback();
+		    if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
+		    {
+		        setEventMessages($langs->trans("WarningAnEntryAlreadyExistForTransKey"), null, 'warnings');
+		    }
+		    else 
+		    {
+		        setEventMessages($db->lasterror(), null, 'errors');
+		    }
 			$action='';
 		}
 	}
@@ -407,9 +415,17 @@ if ($mode == 'searchkey')
         print '<tr class="oddeven"><td>'.$langcode.'</td><td>'.$key.'</td><td>';
         print dol_escape_htmltag($val);
         print '</td><td align="right">';
-        if ($val != $newlangfileonly->tab_translate[$key]) 
+        if (! empty($newlangfileonly->tab_translate[$key]))
+        {
+            if ($val != $newlangfileonly->tab_translate[$key]) 
+            {
+                $htmltext = $langs->trans("OriginalValueWas", $newlangfileonly->tab_translate[$key]);
+                print $form->textwithpicto('', $htmltext, 1, 'info');
+            }
+        }
+        else
         {
-            $htmltext = $langs->trans("OriginalValueWas", $newlangfileonly->tab_translate[$key]);
+            $htmltext = $langs->trans("TransKeyWithoutOriginalValue", $key);
             print $form->textwithpicto('', $htmltext, 1, 'warning');
         }
         /*if (! empty($conf->multicompany->enabled) && !$user->entity)

+ 17 - 32
htdocs/admin/websites.php

@@ -375,11 +375,11 @@ if ($id)
             // dans les dictionnaires de donnees
             $valuetoshow=ucfirst($fieldlist[$field]);   // Par defaut
             $valuetoshow=$langs->trans($valuetoshow);   // try to translate
-            $align="left";
+            $align='';
             if ($fieldlist[$field]=='lang')            { $valuetoshow=$langs->trans("Language"); }
             if ($valuetoshow != '')
             {
-                print '<td align="'.$align.'">';
+                print '<td class="'.$align.'">';
             	if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print '<a href="'.$tabhelp[$id][$value].'" target="_blank">'.$valuetoshow.' '.img_help(1,$valuetoshow).'</a>';
             	else if (! empty($tabhelp[$id][$value])) print $form->textwithpicto($valuetoshow,$tabhelp[$id][$value]);
             	else print $valuetoshow;
@@ -413,14 +413,11 @@ if ($id)
         $reshook=$hookmanager->executeHooks('createDictionaryFieldlist',$parameters, $obj, $tmpaction);    // Note that $action and $object may have been modified by some hooks
         $error=$hookmanager->error; $errors=$hookmanager->errors;
 
-        if ($id == 3) unset($fieldlist[2]);
-
         if (empty($reshook))
         {
        		fieldListWebsites($fieldlist,$obj,$tabname[$id],'add');
         }
 
-        if ($id == 4) print '<td></td>';
         print '<td colspan="3" align="right">';
         if ($action != 'edit')
         {
@@ -430,15 +427,9 @@ if ($id)
         print "</tr>";
 
         $colspan=count($fieldlist)+2;
-        if ($id == 4) $colspan++;
-
-        if (! empty($alabelisused) && $id != 25)  // If there is one label among fields, we show legend of *
-        {
-        	print '<tr><td colspan="'.$colspan.'">* '.$langs->trans("LabelUsedByDefault").'.</td></tr>';
-        }
-        print '<tr><td colspan="'.$colspan.'">&nbsp;</td></tr>';	// Keep &nbsp; to have a line with enough height
     }
 
+    print '</table>';
     print '</form>';
 
 
@@ -453,6 +444,15 @@ if ($id)
         $var=true;
         if ($num)
         {
+            print '<br>';
+            
+            print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
+            print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
+            print '<input type="hidden" name="page" value="'.$page.'">';
+            print '<input type="hidden" name="rowid" value="'.$rowid.'">';
+            
+            print '<table class="noborder" width="100%">';
+        
             // There is several pages
             if ($num > $listlimit)
             {
@@ -503,14 +503,9 @@ if ($id)
 
                 $obj = $db->fetch_object($resql);
                 //print_r($obj);
-                print '<tr '.$bc[$var].' id="rowid-'.$obj->rowid.'">';
+                print '<tr class="oddeven" id="rowid-'.$obj->rowid.'">';
                 if ($action == 'edit' && ($rowid == (! empty($obj->rowid)?$obj->rowid:$obj->code)))
                 {
-                    print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$id.'" method="POST">';
-                    print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-                    print '<input type="hidden" name="page" value="'.$page.'">';
-                    print '<input type="hidden" name="rowid" value="'.$rowid.'">';
-
                     $tmpaction='edit';
                     $parameters=array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]);
                     $reshook=$hookmanager->executeHooks('editDictionaryFieldlist',$parameters,$obj, $tmpaction);    // Note that $action and $object may have been modified by some hooks
@@ -548,16 +543,6 @@ if ($id)
 
                     $url = $_SERVER["PHP_SELF"].'?'.($page?'page='.$page.'&':'').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(! empty($obj->rowid)?$obj->rowid:(! empty($obj->code)?$obj->code:'')).'&amp;code='.(! empty($obj->code)?urlencode($obj->code):'').'&amp;id='.$id.'&amp;';
 
-					// Favorite
-					// Only activated on country dictionary
-                    if ($id == 4)
-					{
-						print '<td align="center" class="nowrap">';
-						if ($iserasable) print '<a href="'.$url.'action='.$acts[$obj->favorite].'_favorite">'.$actl[$obj->favorite].'</a>';
-						else print $langs->trans("AlwaysActive");
-						print '</td>';
-					}
-
                     // Active
                     print '<td align="center" class="nowrap">';
                     print '<a href="'.$url.'action='.$acts[$obj->status].'">'.$actl[$obj->status].'</a>';
@@ -575,15 +560,15 @@ if ($id)
                 }
                 $i++;
             }
+            
+            print '</table>';
+            
+            print '</form>';
         }
     }
     else {
         dol_print_error($db);
     }
-
-    print '</table>';
-
-    print '</form>';
 }
 
 print '<br>';

+ 8 - 4
htdocs/comm/card.php

@@ -1090,11 +1090,15 @@ if ($id > 0)
     
     				if (! empty($conf->commande->enabled))
     				{
-    					if (! empty($orders2invoice) && $orders2invoice > 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/orderstoinvoice.php?socid='.$object->id.'">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
-    					else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("NoOrdersToInvoice")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
+    				    if ($object->client != 0 && $object->client != 2)
+    				    {
+    					   if (! empty($orders2invoice) && $orders2invoice > 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/orderstoinvoice.php?socid='.$object->id.'">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
+    					   else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("NoOrdersToInvoice")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
+    				    }
+    				    else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     				}
-    
-    				if ($object->client != 0) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&socid='.$object->id.'">'.$langs->trans("AddBill").'</a></div>';
+
+    				if ($object->client != 0 && $object->client != 2) print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&socid='.$object->id.'">'.$langs->trans("AddBill").'</a></div>';
     				else print '<div class="inline-block divButAction"><a class="butActionRefused" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
     
     			}

+ 1 - 0
htdocs/commande/class/commande.class.php

@@ -464,6 +464,7 @@ class Commande extends CommonOrder
                     if ($this->lines[$i]->fk_product > 0)
                     {
                         $mouvP = new MouvementStock($this->db);
+                        $mouvP->origin = &$this;
                         // We increment stock of product (and sub-products)
                         $result=$mouvP->reception($user, $this->lines[$i]->fk_product, $idwarehouse, $this->lines[$i]->qty, 0, $langs->trans("OrderBackToDraftInDolibarr",$this->ref));
                         if ($result < 0) { $error++; $this->error=$mouvP->error; break; }

+ 1 - 1
htdocs/compta/bank/card.php

@@ -117,7 +117,7 @@ if ($action == 'add')
     
     if ($conf->global->MAIN_BANK_ACCOUNTANCY_CODE_ALWAYS_REQUIRED && empty($object->account_number))
     {
-        setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), null, 'error');
+        setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), null, 'errors');
         $action='create';       // Force chargement page en mode creation
         $error++;
     }

+ 1 - 1
htdocs/compta/facture/admin/facture_cust_extrafields.php

@@ -70,7 +70,7 @@ print load_fiche_titre($langs->trans("BillsSetup"),$linkback,'title_setup');
 
 $head = invoice_admin_prepare_head();
 
-dol_fiche_head($head, 'attributes', $langs->trans("Invoices"), 0, 'invoice');
+dol_fiche_head($head, 'attributes', $langs->trans("Invoices"), -1, 'invoice');
 
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 

+ 1 - 1
htdocs/compta/facture/admin/facturedet_cust_extrafields.php

@@ -71,7 +71,7 @@ print load_fiche_titre($langs->trans("BillsSetup"),$linkback,'title_setup');
 
 $head = invoice_admin_prepare_head();
 
-dol_fiche_head($head, 'attributeslines', $langs->trans("Invoices"), 0, 'invoice');
+dol_fiche_head($head, 'attributeslines', $langs->trans("Invoices"), -1, 'invoice');
 
 require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php';
 

+ 1 - 1
htdocs/compta/facture/card.php

@@ -2191,7 +2191,7 @@ if ($action == 'create')
 	else
 	{
 		print '<td colspan="2">';
-		print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty');
+		print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
 		// Option to reload page to retrieve customer informations. Note, this clear other input
 		if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE))
 		{

+ 4 - 0
htdocs/core/class/extrafields.class.php

@@ -727,6 +727,10 @@ class ExtraFields
     		{
     		    $showsize='minwidth400imp';
     		}
+    		elseif ($type == 'boolean')
+    		{
+    		    $showsize='';
+    		}
     		else
     		{
     			if (round($size) < 12)

+ 1 - 1
htdocs/core/class/html.form.class.php

@@ -994,7 +994,7 @@ class Form
     				print img_picto($langs->trans("Search"), 'search');
     			}
     		}
-            print '<input type="text" class="minwidth100" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->THIRDPARTY_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
+            print '<input type="text" class="'.$morecss.'" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->THIRDPARTY_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
     		if ($hidelabel == 3) {
     			print img_picto($langs->trans("Search"), 'search');
     		}

+ 12 - 5
htdocs/core/db/DoliDB.class.php

@@ -220,9 +220,9 @@ abstract class DoliDB implements Database
 	/**
 	 * Define sort criteria of request
 	 *
-	 * @param	string	$sortfield  List of sort fields, separated by comma. Example: 't1.fielda, t2.fieldb'
+	 * @param	string	        $sortfield  List of sort fields, separated by comma. Example: 't1.fielda, t2.fieldb'
 	 * @param	'ASC'|'DESC'	$sortorder  Sort order
-	 * @return	string      		String to provide syntax of a sort sql string
+	 * @return	string      		        String to provide syntax of a sort sql string
 	 */
 	function order($sortfield=null,$sortorder=null)
 	{
@@ -230,18 +230,25 @@ abstract class DoliDB implements Database
 		{
 			$return='';
 			$fields=explode(',',$sortfield);
+			$orders=explode(',',$sortorder);
+			$i=0;
 			foreach($fields as $val)
 			{
 				if (! $return) $return.=' ORDER BY ';
-				else $return.=',';
+				else $return.=', ';
 
 				$return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
+				
+				$tmpsortorder = trim($orders[$i]);
+				
 				// Only ASC and DESC values are valid SQL
-				if (strtoupper($sortorder) === 'ASC') {
+				if (strtoupper($tmpsortorder) === 'ASC') {
 					$return .= ' ASC';
-				} elseif (strtoupper($sortorder) === 'DESC') {
+				} elseif (strtoupper($tmpsortorder) === 'DESC') {
 					$return .= ' DESC';
 				}
+				
+				$i++;
 			}
 			return $return;
 		}

+ 13 - 1
htdocs/core/lib/files.lib.php

@@ -1584,7 +1584,7 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu
 	$sqlprotectagainstexternals='';
 	$ret=array();
 
-	// find the subdirectory name as the reference
+    // Find the subdirectory name as the reference. For exemple original_file='10/myfile.pdf' -> refname='10'
 	if (empty($refname)) $refname=basename(dirname($original_file)."/");
 
 	$relative_original_file = $original_file;
@@ -1752,6 +1752,18 @@ function dol_check_secure_access_document($modulepart,$original_file,$entity,$fu
 		$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
 	}
 
+	// Wrapping for users
+	else if ($modulepart == 'user' && !empty($conf->user->dir_output))
+	{
+        $canreaduser=(! empty($fuser->admin) || $fuser->rights->user->user->lire);
+        if ($fuser->id == (int) $refname) { $canreaduser=1; } // A user can always read its own card
+        if ($canreaduser || preg_match('/^specimen/i',$original_file))
+	    {
+	        $accessallowed=1;
+	    }
+	    $original_file=$conf->user->dir_output.'/'.$original_file;
+	}
+	
 	// Wrapping for third parties
 	else if (($modulepart == 'company' || $modulepart == 'societe') && !empty($conf->societe->dir_output))
 	{

+ 66 - 18
htdocs/core/lib/functions.lib.php

@@ -246,24 +246,64 @@ function dol_shutdown()
  *  @param  mixed   $options     Options to pass to filter_var when $check is set to custom
  *  @return string|string[]      Value found (string or array), or '' if check fails
  */
-function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL)
+function GETPOST($paramname, $check='', $method=0, $filter=NULL, $options=NULL)
 {
 	if (empty($method))
 	{
 		$out = isset($_GET[$paramname])?$_GET[$paramname]:(isset($_POST[$paramname])?$_POST[$paramname]:'');
-		
+
 		// Management of default values
-		if (! empty($_GET['action']) && $_GET['action'] == 'create' && ! empty($paramname) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname]))
+		if (! isset($_GET['sortfield']))	// If we did a click on a field to sort, we do no apply default values
 		{
-			$relativepathstring = preg_replace('/\.[a-z]+$/', '', $_SERVER["PHP_SELF"]);
-			if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring);
-			$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
-			$relativepathstring = preg_replace('/^\//', '', $relativepathstring);
-			$relativepathstring=dol_string_nospecial($relativepathstring, '-');
-			// $relativepathstring is now string that identify the page: '_societe_card', '_agenda_card', ...
-			$keyfordefaultvalue = 'MAIN_DEFAULT_FOR_'.$relativepathstring.'_'.$paramname;
-			global $conf;
-			if (isset($conf->global->$keyfordefaultvalue)) $out = $conf->global->$keyfordefaultvalue;
+		    if (! empty($_GET['action']) && $_GET['action'] == 'create' && ! empty($paramname) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname]))
+			{
+				$relativepathstring = $_SERVER["PHP_SELF"];
+				if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^\//', '', $relativepathstring);
+				global $user;
+				if (! empty($user->default_values))		// $user->default_values defined from menu default values, and values loaded not at first 
+				{
+					//var_dump($user->default_values[$relativepathstring]['createform']);
+					if (isset($user->default_values[$relativepathstring]['createform'][$paramname])) $out = $user->default_values[$relativepathstring]['createform'][$paramname];
+				}
+			}
+			// Management of default search_filters and sort order
+			elseif (preg_match('/list.php$/', $_SERVER["PHP_SELF"]) && ! empty($paramname) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname]))
+			{
+			    $relativepathstring = $_SERVER["PHP_SELF"];
+				if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
+				$relativepathstring = preg_replace('/^\//', '', $relativepathstring);
+				global $user;
+				if (! empty($user->default_values))		// $user->default_values defined from menu default values, and values loaded not at first 
+				{
+				    //var_dump($user->default_values[$relativepathstring]);
+        			if ($paramname == 'sortfield')
+        			{
+        			    if (isset($user->default_values[$relativepathstring]['sortorder'])) 
+        			    {
+        			        foreach($user->default_values[$relativepathstring]['sortorder'] as $key => $val)
+        			        {
+        			            if ($out) $out.=', ';
+        			            $out.=$key;
+        			        }
+        			    }
+        			}
+        			elseif ($paramname == 'sortorder')
+        			{
+        			    if (isset($user->default_values[$relativepathstring]['sortorder'])) 
+        			    {
+        			        foreach($user->default_values[$relativepathstring]['sortorder'] as $key => $val)
+        			        {
+        			            if ($out) $out.=', ';
+        			            $out.=$val;
+        			        }
+        			    }
+        			}
+				    elseif (isset($user->default_values[$relativepathstring]['filters'][$paramname])) $out = $user->default_values[$relativepathstring]['filters'][$paramname];
+				}
+			}
 		}
 	}
 	elseif ($method==1) $out = isset($_GET[$paramname])?$_GET[$paramname]:'';
@@ -303,6 +343,11 @@ function GETPOST($paramname,$check='',$method=0,$filter=NULL,$options=NULL)
 	            global $user;
 	            $out = $user->id;
 	        }
+	    	elseif ($reg[1] == 'SUPERVISORID')
+	        {
+	            global $user;
+	            $out = $user->fk_user;
+	        }
 	        elseif ($reg[1] == 'ENTITYID')
 	        {
 	            global $conf;
@@ -3155,6 +3200,9 @@ function getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $m
 	$tag='th';
 	if ($thead==2) $tag='div';
 
+	$tmpsortfield=explode(',',$sortfield);
+	$sortfield=trim($tmpsortfield[0]);
+	
 	// If field is used as sort criteria we use a specific class
 	// Example if (sortfield,field)=("nom","xxx.nom") or (sortfield,field)=("nom","nom")
 	if ($field && ($sortfield == $field || $sortfield == preg_replace("/^[^\.]+\./","",$field))) $out.= '<'.$tag.' class="'.$prefix.'liste_titre_sel" '. $moreattrib.'>';
@@ -3169,13 +3217,13 @@ function getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $m
 
 		if ($field != $sortfield)
 		{
-            if ($sortorder == 'DESC') $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
-            if ($sortorder == 'ASC' || ! $sortorder) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
+            if (preg_match('/^DESC/', $sortorder)) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
+            else $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
 		}
 		else
 		{
-            if ($sortorder == 'DESC' || ! $sortorder) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
-            if ($sortorder == 'ASC') $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
+            if (preg_match('/^ASC/', $sortorder)) $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">';
+		    else $out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">';
 		}
 	}
 
@@ -3204,12 +3252,12 @@ function getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $m
 		}
 		else
 		{
-			if ($sortorder == 'DESC' ) {
+			if (preg_match('/^DESC/', $sortorder)) {
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
 				$sortimg.= '<span class="nowrap">'.img_up("Z-A",0).'</span>';
 			}
-			if ($sortorder == 'ASC' ) {
+			if (preg_match('/^ASC/', $sortorder)) {
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
 				//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
 				$sortimg.= '<span class="nowrap">'.img_down("A-Z",0).'</span>';

+ 2 - 1
htdocs/core/lib/functions2.lib.php

@@ -5,6 +5,7 @@
  * Copyright (C) 2014-2016  Marcos García               <marcosgdf@gmail.com>
  * Copyright (C) 2015       Ferran Marcet               <fmarcet@2byte.es>
  * Copyright (C) 2015-2016  Raphaël Doursenaud          <rdoursenaud@gpcsolutions.fr>
+ * Copyright (C) 2017       Juanjo Menent               <jmenent@2byte.es>
  *
  * 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
@@ -1439,7 +1440,7 @@ function dol_print_reduction($reduction,$langs)
     }
     else
     {
-        $string = $reduction.'%';
+        $string = price($reduction).'%';
     }
 
     return $string;

+ 2 - 2
htdocs/core/menus/standard/eldy.lib.php

@@ -800,9 +800,9 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu
 			if (! empty($conf->facture->enabled))
 			{
 				$langs->load("bills");
-				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("BillsCustomers"),0,$user->rights->facture->lire);
+				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("BillsCustomers"),0,$user->rights->facture->lire, '', $mainmenu, 'customers_bills');
 				$newmenu->add("/compta/facture/card.php?action=create",$langs->trans("NewBill"),1,$user->rights->facture->creer);
-				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("List"),1,$user->rights->facture->lire);
+				$newmenu->add("/compta/facture/list.php?leftmenu=customers_bills",$langs->trans("List"),1,$user->rights->facture->lire, '', $mainmenu, 'customers_bills');
 
 				if ($usemenuhider || empty($leftmenu) || preg_match('/customers_bills/', $leftmenu))
 				{

+ 24 - 23
htdocs/core/modules/expedition/doc/pdf_rouget.modules.php

@@ -69,19 +69,18 @@ class pdf_rouget extends ModelePdfExpedition
 
 		// Define position of columns
 		$this->posxdesc=$this->marge_gauche+1;
-		$this->posxweightvol=$this->page_largeur - $this->marge_droite - 76;
+		$this->posxweightvol=$this->page_largeur - $this->marge_droite - 78;
 		$this->posxqtyordered=$this->page_largeur - $this->marge_droite - 56;
 		$this->posxqtytoship=$this->page_largeur - $this->marge_droite - 28;
 		$this->posxpuht=$this->page_largeur - $this->marge_droite;
 
-		if(!empty($conf->global->MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT)) {
+		if (!empty($conf->global->MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT)) {
 
-			$this->posxweightvol=$this->page_largeur - $this->marge_droite - 130;
-			$this->posxqtyordered=$this->page_largeur - $this->marge_droite - 100;
-			$this->posxqtytoship=$this->page_largeur - $this->marge_droite - 70;
+			$this->posxweightvol=$this->page_largeur - $this->marge_droite - 118;
+			$this->posxqtyordered=$this->page_largeur - $this->marge_droite - 96;
+			$this->posxqtytoship=$this->page_largeur - $this->marge_droite - 68;
 			$this->posxpuht=$this->page_largeur - $this->marge_droite - 40;
 			$this->posxtotalht=$this->page_largeur - $this->marge_droite - 20;
-
 		}
 
 		$this->posxpicture=$this->posxweightvol - (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH)?20:$conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH);	// width of images
@@ -344,7 +343,7 @@ class pdf_rouget extends ModelePdfExpedition
 					// Rect prend une longueur en 3eme param
 					$pdf->SetDrawColor(192,192,192);
 					$pdf->Rect($this->marge_gauche, $tab_top-1, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $height_note+1);
-
+					
 					$tab_height = $tab_height - $height_note;
 					$tab_top = $nexY+6;
 				}
@@ -459,16 +458,17 @@ class pdf_rouget extends ModelePdfExpedition
 					$weighttxt='';
 					if ($object->lines[$i]->fk_product_type == 0 && $object->lines[$i]->weight) 
 					{
-					    $weighttxt=$object->lines[$i]->weight*$object->lines[$i]->qty_shipped.' '.measuring_units_string($object->lines[$i]->weight_units,"weight");
+					    $weighttxt=round($object->lines[$i]->weight * $object->lines[$i]->qty_shipped, 5).' '.measuring_units_string($object->lines[$i]->weight_units,"weight");
 					}
 					$voltxt='';
 					if ($object->lines[$i]->fk_product_type == 0 && $object->lines[$i]->volume) 
 					{
-					    $voltxt=$object->lines[$i]->volume*$object->lines[$i]->qty_shipped.' '.measuring_units_string($object->lines[$i]->volume_units?$object->lines[$i]->volume_units:0,"volume");
+					    $voltxt=round($object->lines[$i]->volume * $object->lines[$i]->qty_shipped, 5).' '.measuring_units_string($object->lines[$i]->volume_units?$object->lines[$i]->volume_units:0,"volume");
 					}
-					
-					$pdf->MultiCell(($this->posxqtyordered - $this->posxweightvol), 3, $weighttxt.(($weighttxt && $voltxt)?', ':'').$voltxt,'','C');
-					
+	
+					$pdf->writeHTMLCell($this->posxqtyordered - $this->posxweightvol + 2, 3, $this->posxweightvol - 1, $curY, $weighttxt.(($weighttxt && $voltxt)?'<br>':'').$voltxt, 0, 0, false, true, 'C');
+					//$pdf->MultiCell(($this->posxqtyordered - $this->posxweightvol), 3, $weighttxt.(($weighttxt && $voltxt)?'<br>':'').$voltxt,'','C');
+				
 					if (empty($conf->global->SHIPPING_PDF_HIDE_ORDERED))
 					{
 					   $pdf->SetXY($this->posxqtyordered, $curY);
@@ -479,27 +479,27 @@ class pdf_rouget extends ModelePdfExpedition
 					$pdf->MultiCell(($this->posxpuht - $this->posxqtytoship), 3, $object->lines[$i]->qty_shipped,'','C');
 
 					if(!empty($conf->global->MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT)) 
-{
+					{
 						$pdf->SetXY($this->posxpuht, $curY);
 						$pdf->MultiCell(($this->posxtotalht - $this->posxpuht-1), 3, price($object->lines[$i]->subprice, 0, $outputlangs),'','R');
 
 						$pdf->SetXY($this->posxtotalht, $curY);
 						$pdf->MultiCell(($this->page_largeur - $this->marge_droite - $this->posxtotalht), 3, price($object->lines[$i]->total_ht, 0, $outputlangs),'','R');
-
 					}
 
+					$nexY+=3;
+					if ($weighttxt && $voltxt) $nexY+=2;
+					
 					// Add line
 					if (! empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblignes - 1))
 					{
 						$pdf->setPage($pageposafter);
 						$pdf->SetLineStyle(array('dash'=>'1,1','color'=>array(80,80,80)));
 						//$pdf->SetDrawColor(190,190,200);
-						$pdf->line($this->marge_gauche, $nexY+1, $this->page_largeur - $this->marge_droite, $nexY+1);
+						$pdf->line($this->marge_gauche, $nexY-1, $this->page_largeur - $this->marge_droite, $nexY-1);
 						$pdf->SetLineStyle(array('dash'=>0));
 					}
 
-					$nexY+=2;    // Passe espace entre les lignes
-
 					// Detect if some page were added automatically and output _tableau for past pages
 					while ($pagenb < $pageposafter)
 					{
@@ -650,7 +650,7 @@ class pdf_rouget extends ModelePdfExpedition
     	$pdf->SetXY($this->posxqtytoship, $tab2_top + $tab2_hl * $index);
     	$pdf->MultiCell($this->posxpuht - $this->posxqtytoship, $tab2_hl, $totalToShip, 0, 'C', 1);
         
-	if(!empty($conf->global->MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT)) {
+		if(!empty($conf->global->MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT)) {
 
 	    	$pdf->SetXY($this->posxpuht, $tab2_top + $tab2_hl * $index);
 	    	$pdf->MultiCell($this->posxtotalht - $this->posxpuht, $tab2_hl, '', 0, 'C', 1);
@@ -658,20 +658,20 @@ class pdf_rouget extends ModelePdfExpedition
 	    	$pdf->SetXY($this->posxtotalht, $tab2_top + $tab2_hl * $index);
 	    	$pdf->MultiCell($this->page_largeur - $this->marge_droite - $this->posxtotalht, $tab2_hl, price($object->total_ht, 0, $outputlangs), 0, 'C', 1);
 
-	}
+		}
     	 
 		// Total Weight
 		if ($totalWeighttoshow)
 		{
-    		$pdf->SetXY($col2x-20, $tab2_top + $tab2_hl * $index);
-    		$pdf->MultiCell($largcol2+20, $tab2_hl, $totalWeighttoshow, 0, 'R', 1);
+    		$pdf->SetXY($this->posxweightvol, $tab2_top + $tab2_hl * $index);
+    		$pdf->MultiCell(($this->posxqtyordered - $this->posxweightvol), $tab2_hl, $totalWeighttoshow, 0, 'C', 1);
     		
     		$index++;
 		}
 		if ($totalVolumetoshow)
 		{
-    		$pdf->SetXY($col2x-20, $tab2_top + $tab2_hl * $index);
-    		$pdf->MultiCell($largcol2+20, $tab2_hl, $totalVolumetoshow, 0, 'R', 1);
+    		$pdf->SetXY($this->posxweightvol, $tab2_top + $tab2_hl * $index);
+    		$pdf->MultiCell(($this->posxqtyordered - $this->posxweightvol), $tab2_hl, $totalVolumetoshow, 0, 'C', 1);
 		
 		    $index++;
 		}
@@ -949,6 +949,7 @@ class pdf_rouget extends ModelePdfExpedition
 			$pdf->SetFillColor(230,230,230);
 			$pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1);
 			$pdf->SetTextColor(0,0,60);
+			$pdf->SetFillColor(255,255,255);
 			
 			// Show sender name
 			$pdf->SetXY($posx+2,$posy+3);

+ 1 - 1
htdocs/core/modules/import/import_xlsx.modules.php

@@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT .'/core/modules/import/modules_import.php';
 /**
  *	Class to import Excel files
  */
-class Importxlsx extends ModeleImports
+class ImportXlsx extends ModeleImports
 {
     var $db;
     var $datatoimport;

+ 4 - 2
htdocs/core/modules/syslog/mod_syslog_file.php

@@ -104,8 +104,10 @@ class mod_syslog_file extends LogHandler implements LogHandlerInterface
 	private function getFilename($suffixinfilename='')
 	{
 	    global $conf;
-	    if (! empty($conf->global->SYSLOG_FILE)) $tmp=str_replace('DOL_DATA_ROOT', DOL_DATA_ROOT, $conf->global->SYSLOG_FILE);
-	    else $tmp='dolibarr.log';
+
+	    if (empty($conf->global->SYSLOG_FILE)) $tmp=DOL_DATA_ROOT.'/dolibarr.log';
+	    else $tmp=str_replace('DOL_DATA_ROOT', DOL_DATA_ROOT, $conf->global->SYSLOG_FILE);
+
 	    return $suffixinfilename?preg_replace('/\.log$/i', $suffixinfilename.'.log', $tmp):$tmp;
 	}
 

+ 1 - 1
htdocs/core/tpl/admin_extrafields_view.tpl.php

@@ -34,7 +34,7 @@ print '<br>';
 $extrafields->fetch_name_optionals_label($elementtype);
 
 print '<div class="div-table-responsive">';
-print "<table summary=\"listofattributes\" class=\"noborder\" width=\"100%\">";
+print '<table summary="listofattributes" class="noborder" width="100%">';
 
 print '<tr class="liste_titre">';
 print '<td align="left">'.$langs->trans("Position").'</td>';

+ 0 - 1
htdocs/fourn/card.php

@@ -753,7 +753,6 @@ if ($object->id > 0)
 	
 	print '</div>';
 	
-	print '<br>';
 
 	if (! empty($conf->global->MAIN_REPEATCONTACTONEACHTAB))
 	{

+ 2 - 3
htdocs/fourn/paiement/card.php

@@ -268,9 +268,8 @@ if ($result > 0)
 	    	print '<td colspan="2">'.$langs->trans('BankAccount').'</td>';
 			print '<td colspan="3">';
 			$accountstatic=new Account($db);
-	        $accountstatic->id=$bankline->fk_account;
-	        $accountstatic->label=$bankline->bank_account_ref.' - '.$bankline->bank_account_label;
-	        print $accountstatic->getNomUrl(0);
+			$accountstatic->fetch($bankline->fk_account);
+	        print $accountstatic->getNomUrl(1);
 	    	print '</td>';
 	    	print '</tr>';
         }

+ 0 - 0
htdocs/includes/swiftmailer/lib/swiftmailer_generate_mimes_config.php


+ 2 - 2
htdocs/install/check.php

@@ -363,7 +363,7 @@ else
 		// Show first install line
 		$choice = '<tr class="listofchoices"><td class="listofchoices nowrap" align="center"><b>'.$langs->trans("FreshInstall").'</b>';
 		$choice .= '</td>';
-		$choice .= '<td class="listofchoices">';
+		$choice .= '<td class="listofchoices listofchoicesdesc">';
 		$choice .= $langs->trans("FreshInstallDesc");
 		if (empty($dolibarr_main_db_host))	// This means install process was not run
 		{
@@ -459,7 +459,7 @@ else
 
             $choice .= '<tr class="listofchoices '.($recommended_choice ? 'choiceselected' : '').'">';
             $choice .= '<td class="listofchoices nowrap" align="center"><b>'.$langs->trans("Upgrade").'<br>'.$newversionfrom.$newversionfrombis.' -> '.$newversionto.'</b></td>';
-            $choice .= '<td class="listofchoices">';
+            $choice .= '<td class="listofchoices listofchoicesdesc">';
             $choice .= $langs->trans("UpgradeDesc");
 
             if ($recommended_choice)

+ 5 - 4
htdocs/install/default.css

@@ -1,5 +1,5 @@
 /* Copyright (C) 2004      Rodolphe Quiedeville <rodolphe@quiedeville.org> 
- * Copyright (C) 2009-2016 Laurent Destailleur  <eldy@users.sourceforge.net> 
+ * Copyright (C) 2009-2017 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
@@ -210,7 +210,9 @@ table.listofchoices, tr.listofchoices, td.listofchoices {
 tr.listofchoices {
     height: 42px;	
 }
-
+.listofchoicesdesc {
+	color: #999 !important;
+}
 .blinkwait {
 	font-weight: bold;
 	text-decoration:blink !important;	
@@ -244,9 +246,8 @@ font.warning {
 div.error {
 	color: #550000;
 	font-weight: bold;
-	padding: 0.2em 0.2em 0.2em 0.2em;
+	padding: 0.2em 0.2em 0.2em 0;
 	margin: 0.5em 0 0.5em 0;
-	border: 1px solid #6C7C8B;
 }
 font.error {
 	color: #550000;

+ 4 - 4
htdocs/install/fileconf.php

@@ -45,13 +45,13 @@ dolibarr_install_syslog("--- fileconf: entering fileconf.php page");
 // install.forced.php into directory htdocs/install (This is the case with some wizard
 // installer like DoliWamp, DoliMamp or DoliBuntu).
 // We first init "forced values" to nothing.
-if (! isset($force_install_noedit))			$force_install_noedit='';	// 1=To block var specific to distrib, 2 to block all technical parameters
+if (! isset($force_install_noedit))			    $force_install_noedit='';	// 1=To block vars specific to distrib, 2 to block all technical parameters
 if (! isset($force_install_type))				$force_install_type='';
 if (! isset($force_install_dbserver))			$force_install_dbserver='';
 if (! isset($force_install_port))				$force_install_port='';
 if (! isset($force_install_database))			$force_install_database='';
-if (! isset($force_install_prefix))			$force_install_prefix='';
-if (! isset($force_install_createdatabase))	$force_install_createdatabase='';
+if (! isset($force_install_prefix))			    $force_install_prefix='';
+if (! isset($force_install_createdatabase))	    $force_install_createdatabase='';
 if (! isset($force_install_databaselogin))		$force_install_databaselogin='';
 if (! isset($force_install_databasepass))		$force_install_databasepass='';
 if (! isset($force_install_databaserootlogin))	$force_install_databaserootlogin='';
@@ -324,7 +324,7 @@ if (! empty($force_install_message))
 		?>
 			<select id="db_type"
 			        name="db_type"
-				<?php if ($force_install_noedit && $force_install_type !== null) {
+				<?php if ($force_install_noedit == 2 && $force_install_type !== null) {
 					print ' disabled';
 				} ?>
 			>

+ 8 - 0
htdocs/install/mysql/migration/5.0.0-6.0.0.sql

@@ -137,6 +137,9 @@ ALTER TABLE llx_chargesociales ADD COLUMN fk_projet integer DEFAULT NULL;
 
 ALTER TABLE llx_cronjob ADD COLUMN processing integer NOT NULL DEFAULT 0;
 
+ALTER TABLE llx_website ADD COLUMN fk_user_create integer;
+ALTER TABLE llx_website ADD COLUMN fk_user_modif integer;
+
 
 create table llx_payment_various
 (
@@ -173,4 +176,9 @@ create table llx_default_values
 ALTER TABLE llx_default_values ADD UNIQUE INDEX uk_default_values(type, entity, user_id, page, param);
 
 
+ALTER TABLE llx_supplier_proposaldet ADD INDEX idx_supplier_proposaldet_fk_supplier_proposal (fk_supplier_proposal);
+ALTER TABLE llx_supplier_proposaldet ADD INDEX idx_supplier_proposaldet_fk_product (fk_product);
+
+ALTER TABLE llx_supplier_proposaldet ADD CONSTRAINT fk_supplier_proposaldet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid);
+ALTER TABLE llx_supplier_proposaldet ADD CONSTRAINT fk_supplier_proposaldet_fk_supplier_proposal FOREIGN KEY (fk_supplier_proposal) REFERENCES llx_supplier_proposal (rowid);
 

+ 2 - 2
htdocs/install/mysql/migration/repair.sql

@@ -15,8 +15,8 @@
 
 -- Requests to change character set and collation of a column
 
--- ALTER TABLE llx_accountingaccount MODIFY account_number VARCHAR(20) CHARACTER SET utf8;
--- ALTER TABLE llx_accountingaccount MODIFY account_number VARCHAR(20) COLLATE utf8_unicode_ci;
+-- ALTER TABLE llx_accounting_account MODIFY account_number VARCHAR(20) CHARACTER SET utf8;
+-- ALTER TABLE llx_accounting_account MODIFY account_number VARCHAR(20) COLLATE utf8_unicode_ci;
 -- You can check with "show full columns from llx_accountingaccount";
 
 

+ 26 - 0
htdocs/install/mysql/tables/llx_supplier_proposaldet.key.sql

@@ -0,0 +1,26 @@
+-- ===================================================================
+-- Copyright (C) 2009-2011 Regis Houssin  <regis.houssin@capnetworks.com>
+-- Copyright (C) 2012      Cédric Salvador      <csalvador@gpcsolutions.fr>
+--
+-- 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/>.
+--
+-- ===================================================================
+
+
+
+ALTER TABLE llx_supplier_proposaldet ADD INDEX idx_supplier_proposaldet_fk_supplier_proposal (fk_supplier_proposal);
+ALTER TABLE llx_supplier_proposaldet ADD INDEX idx_supplier_proposaldet_fk_product (fk_product);
+
+ALTER TABLE llx_supplier_proposaldet ADD CONSTRAINT fk_supplier_proposaldet_fk_unit FOREIGN KEY (fk_unit) REFERENCES llx_c_units (rowid);
+ALTER TABLE llx_supplier_proposaldet ADD CONSTRAINT fk_supplier_proposaldet_fk_supplier_proposal FOREIGN KEY (fk_supplier_proposal) REFERENCES llx_supplier_proposal (rowid);

+ 4 - 3
htdocs/install/mysql/tables/llx_website.sql

@@ -26,7 +26,8 @@ CREATE TABLE llx_website
 	status		  integer,
 	fk_default_home integer, 
 	virtualhost   varchar(255), 
-    date_creation     datetime,
-    date_modification datetime,
-	tms           timestamp
+    fk_user_create integer,
+    fk_user_modif  integer,
+    date_creation  datetime,
+	tms            timestamp
 ) ENGINE=innodb;

+ 4 - 2
htdocs/install/mysql/tables/llx_website_pages.sql

@@ -27,6 +27,8 @@ CREATE TABLE llx_website_page
 	keywords      varchar(255),
 	content		  mediumtext,		-- text is not enough in size
     status        integer,
-    date_creation     datetime,
-	tms           timestamp
+    fk_user_create integer,
+    fk_user_modif  integer,
+    date_creation  datetime,
+	tms            timestamp
 ) ENGINE=innodb;

+ 9 - 9
htdocs/langs/en_US/accountancy.lang

@@ -36,15 +36,15 @@ AccountancyAreaDescActionOnceBis=Next steps should be done to save you time in f
 AccountancyAreaDescActionFreq=The following actions are usually executed every month, week or day for very large companies...
 AccountancyAreaDescChartModel=STEP %s: Create a model of chart of account from menu %s
 AccountancyAreaDescChart=STEP %s: Create or check content of your chart of account from menu %s
-AccountancyAreaDescBank=STEP %s: Check the binding between bank accounts and accounting account is done. Complete missing bindings. For this, go on the card of each financial account. You can start from page %s.
-AccountancyAreaDescVat=STEP %s: Check the binding between vat rates and accounting account is done. Complete missing bindings. You can set accounting accounts to use for each VAT from page %s.    
-AccountancyAreaDescExpenseReport=STEP %s: Check the binding between type of expense report and accounting account is done. Complete missing bindings. You can set accounting accounts to use for each VAT from page %s.
-AccountancyAreaDescSal=STEP %s: Check the binding between salaries payment and accounting account is done. Complete missing bindings. For this you can use the menu entry %s.    
-AccountancyAreaDescContrib=STEP %s: Check the binding between special expences (miscellaneous taxes) and accounting account is done. Complete missing bindings. For this you can use the menu entry %s.    
-AccountancyAreaDescDonation=STEP %s: Check the binding between donation and accounting account is done. Complete missing bindings. You can set the account dedicated for that from the menu entry %s.
-AccountancyAreaDescMisc=STEP %s: Check the default binding between miscellaneous transaction lines and accounting account is done. Complete missing bindings. For this you can use the menu entry %s.
-AccountancyAreaDescProd=STEP %s: Check the binding between products/services and accounting account is done. Complete missing bindings. For this you can use the menu entry %s.
-AccountancyAreaDescLoan=STEP %s: Check the binding between loans payment and accounting account is done. Complete missing bindings. For this you can use the menu entry %s. 
+AccountancyAreaDescVat=STEP %s: Define accounting accounts for each VAT Rates. For this you can use the menu entry %s.    
+AccountancyAreaDescExpenseReport=STEP %s: Define default accounting accounts for type of expense report. For this you can use the menu entry %s.
+AccountancyAreaDescSal=STEP %s: Define default accounting accounts for payment of salaries. For this you can use the menu entry %s.    
+AccountancyAreaDescContrib=STEP %s: Define default accounting accounts for special expences (miscellaneous taxes). For this you can use the menu entry %s.    
+AccountancyAreaDescDonation=STEP %s: Define default accounting accounts for donation. For this you can use the menu entry %s.
+AccountancyAreaDescMisc=STEP %s: Define default accounting accounts for miscellaneous transactions. For this you can use the menu entry %s.
+AccountancyAreaDescLoan=STEP %s: Define default accounting accounts for loans. For this you can use the menu entry %s. 
+AccountancyAreaDescBank=STEP %s: Define accounting accounts for each bank and financial accounts. For this, go on the card of each financial account. You can start from page %s.
+AccountancyAreaDescProd=STEP %s: Define accounting accounts on your products. For this you can use the menu entry %s.
 
 AccountancyAreaDescCustomer=STEP %s: Check the binding between existing customer invoice lines and accounting account is done, so application will be able to journalize transactions in General Ledger in one click. Complete missing bindings. For this you can use the menu entry %s.
 AccountancyAreaDescSupplier=STEP %s: Check the binding between existing supplier invoice lines and accounting account is done, so application will be able to journalize transactions in General Ledger in one click. Complete missing bindings. For this you can use the menu entry %s.

+ 9 - 6
htdocs/langs/en_US/admin.lang

@@ -305,12 +305,12 @@ LastActivationDate=Latest activation date
 UpdateServerOffline=Update server offline
 WithCounter=Manage a counter
 GenericMaskCodes=You may enter any numbering mask. In this mask, the following tags could be used:<br><b>{000000}</b> corresponds to a number which will be incremented on each %s. Enter as many zeros as the desired length of the counter. The counter will be completed by zeros from the left in order to have as many zeros as the mask. <br><b>{000000+000}</b> same as previous but an offset corresponding to the number to the right of the + sign is applied starting on first %s. <br><b>{000000@x}</b> same as previous but the counter is reset to zero when month x is reached (x between 1 and 12, or 0 to use the early months of fiscal year defined in your configuration, or 99 to reset to zero every month). If this option is used and x is 2 or higher, then sequence {yy}{mm} or {yyyy}{mm} is also required. <br><b>{dd}</b> day (01 to 31).<br><b>{mm}</b> month (01 to 12).<br><b>{yy}</b>, <b>{yyyy}</b> or <b>{y}</b> year over 2, 4 or 1 numbers. <br>
-GenericMaskCodes2=<b>{cccc}</b> the client code on n characters<br><b>{cccc000}</b> the client code on n characters is followed by a counter dedicated for customer. This counter dedicated to customer is reset at same time than global counter.<br><b>{tttt}</b> The code of third party type on n characters (see dictionary-thirdparty types).<br>
+GenericMaskCodes2=<b>{cccc}</b> the client code on n characters<br><b>{cccc000}</b> the client code on n characters is followed by a counter dedicated for customer. This counter dedicated to customer is reset at same time than global counter.<br><b>{tttt}</b> The code of third party type on n characters (see menu Home - Setup - Dictionary - Types of third parties). If you add this tag, the counter will be different for each type of third party.<br>
 GenericMaskCodes3=All other characters in the mask will remain intact.<br>Spaces are not allowed.<br>
-GenericMaskCodes4a=<u>Example on the 99th %s of the third party TheCompany done 2007-01-31:</u><br>
+GenericMaskCodes4a=<u>Example on the 99th %s of the third party TheCompany, with date 2007-01-31:</u><br>
 GenericMaskCodes4b=<u>Example on third party created on 2007-03-01:</u><br>
 GenericMaskCodes4c=<u>Example on product created on 2007-03-01:</u><br>
-GenericMaskCodes5=<b>ABC{yy}{mm}-{000000}</b> will give <b>ABC0701-000099</b><br><b>{0000+100@1}-ZZZ/{dd}/XXX</b> will give <b>0199-ZZZ/31/XXX</b>
+GenericMaskCodes5=<b>ABC{yy}{mm}-{000000}</b> will give <b>ABC0701-000099</b><br><b>{0000+100@1}-ZZZ/{dd}/XXX</b> will give <b>0199-ZZZ/31/XXX</b><br><b>IN{yy}{mm}-{0000}-{t}</b> will give <b>IN0701-0099-A</b> if the type of company is 'Responsable Inscripto' with code for type that is 'A_RI'
 GenericNumRefModelDesc=Returns a customizable number according to a defined mask. 
 ServerAvailableOnIPOrPort=Server is available at address <b>%s</b> on port <b>%s</b>
 ServerNotAvailableOnIPOrPort=Server is not available at address <b>%s</b> on port <b>%s</b>
@@ -427,11 +427,13 @@ WarningPHPMail=WARNING: Some email providers (like Yahoo) does not allow you to
 ClickToShowDescription=Click to show description
 DependsOn=This module need the module(s)
 RequiredBy=This module is required by module(s)
-TheKeyIsTheNameOfHtmlField=The key is the name of the html field. This need to have technical knowledges to read the content of the HTML page to get the key name of a field.
-PageUrlForDefaultValues=You must enter here the relative url of the page. Examples:
+TheKeyIsTheNameOfHtmlField=This is the name of the HTML field. This need to have technical knowledges to read the content of the HTML page to get the key name of a field.
+PageUrlForDefaultValues=You must enter here the relative url of the page. If you include parameters in URL, the default values will be effective if all parameters are set to same value. Examples:
 PageUrlForDefaultValuesCreate=<br>For form to create a new thirdparty, it is <strong>%s</strong>
 PageUrlForDefaultValuesList=<br>For page that list thirdparties, it is <strong>%s</strong>
 GoIntoTranslationMenuToChangeThis=A translation has been found for the key with this code, so to change this value, you must edit it fom Home-Setup-translation.
+WarningSettingSortOrder=Warning, setting a default sort order may result in a technical error when going on the list page if field is an unknown field. If you experience such an error, come back to this page to remove the default sort order to retreive default behavior. 
+Field=Field
 # Modules
 Module0Name=Users & groups
 Module0Desc=Users / Employees and Groups management
@@ -1091,6 +1093,7 @@ CurrentTranslationString=Current translation string
 WarningAtLeastKeyOrTranslationRequired=A search criteria is required at least for key or translation string
 NewTranslationStringToShow=New translation string to show
 OriginalValueWas=The original translation is overwritten. Original value was:<br><br>%s
+TransKeyWithoutOriginalValue=You forced a new translation for the translation key '<strong>%s</strong>' that does not exists in any language files
 TotalNumberOfActivatedModules=Total number of activated feature modules: <b>%s</b> / <b>%s</b>
 YouMustEnableOneModule=You must at least enable 1 module
 ClassNotFoundIntoPathWarning=Class %s not found into PHP path
@@ -1527,7 +1530,7 @@ EndPointIs=SOAP clients must send their requests to the Dolibarr endpoint availa
 ApiSetup=API module setup
 ApiDesc=By enabling this module, Dolibarr become a REST server to provide miscellaneous web services.
 ApiProductionMode=Enable production mode (this will activate use of a cache for services management)
-ApiExporerIs=You can explore the APIs at url
+ApiExporerIs=You can explore and test the APIs at URL
 OnlyActiveElementsAreExposed=Only elements from enabled modules are exposed
 ApiKey=Key for API
 WarningAPIExplorerDisabled=The API explorer has been disabled. API explorer is not required to provide API services. It is a tool for developer to find/test REST APIs. If you need this tool, go into setup of module API REST to activate it. 

+ 1 - 1
htdocs/langs/en_US/bookmarks.lang

@@ -12,7 +12,7 @@ BookmarkTargetNewWindowShort=New window
 BookmarkTargetReplaceWindowShort=Current window
 BookmarkTitle=Bookmark title
 UrlOrLink=URL
-BehaviourOnClick=Behaviour when a URL is clicked
+BehaviourOnClick=Behaviour when a bookmark URL is selected
 CreateBookmark=Create bookmark
 SetHereATitleForLink=Set a title for the bookmark
 UseAnExternalHttpLinkOrRelativeDolibarrLink=Use an external http URL or a relative Dolibarr URL

+ 4 - 4
htdocs/langs/en_US/companies.lang

@@ -77,10 +77,10 @@ VATIsNotUsed=VAT is not used
 CopyAddressFromSoc=Fill address with third party address
 ThirdpartyNotCustomerNotSupplierSoNoRef=Thirdparty neither customer nor supplier, no available refering objects
 PaymentBankAccount=Payment bank account
-OverAllProposals=Total proposals
-OverAllOrders=Total orders
-OverAllInvoices=Total invoices
-OverAllSupplierProposals=Total price requests
+OverAllProposals=Proposals
+OverAllOrders=Orders
+OverAllInvoices=Invoices
+OverAllSupplierProposals=Price requests
 ##### Local Taxes #####
 LocalTax1IsUsed=Use second tax
 LocalTax1IsUsedES= RE is used

+ 1 - 0
htdocs/langs/en_US/errors.lang

@@ -206,3 +206,4 @@ WarningPaymentDateLowerThanInvoiceDate=Payment date (%s) is earlier than invoice
 WarningTooManyDataPleaseUseMoreFilters=Too many data (more than %s lines). Please use more filters or set the constant %s to a higher limit. 
 WarningSomeLinesWithNullHourlyRate=Some times were recorded by some users while their hourly rate was not defined. A value of 0 %s per hour was used but this may result in wrong valuation of time spent.
 WarningYourLoginWasModifiedPleaseLogin=Your login was modified. For security purpose you will have to login with your new login before next action.
+WarningAnEntryAlreadyExistForTransKey=An entry already exists for the translation key for this language

+ 1 - 1
htdocs/langs/en_US/mails.lang

@@ -35,7 +35,7 @@ MailingStatusSentPartialy=Sent partialy
 MailingStatusSentCompletely=Sent completely
 MailingStatusError=Error
 MailingStatusNotSent=Not sent
-MailSuccessfulySent=Email successfully accepted for delivery (from %s to %s)
+MailSuccessfulySent=Email (from %s to %s) successfully accepted for delivery
 MailingSuccessfullyValidated=EMailing successfully validated
 MailUnsubcribe=Unsubscribe
 MailingStatusNotContact=Don't contact anymore

+ 1 - 1
htdocs/langs/en_US/main.lang

@@ -823,5 +823,5 @@ SearchIntoContracts=Contracts
 SearchIntoCustomerShipments=Customer shipments
 SearchIntoExpenseReports=Expense reports
 SearchIntoLeaves=Leaves
-
+SetMultiCurrencyCode=Set currency
 BulkActions=Bulk actions

+ 1 - 1
htdocs/langs/en_US/sendings.lang

@@ -53,7 +53,7 @@ ShipmentCreationIsDoneFromOrder=For the moment, creation of a new shipment is do
 ShipmentLine=Shipment line
 ProductQtyInCustomersOrdersRunning=Product quantity into open customers orders
 ProductQtyInSuppliersOrdersRunning=Product quantity into open suppliers orders
-ProductQtyInShipmentAlreadySent=Product quantity from oped customer order already sent
+ProductQtyInShipmentAlreadySent=Product quantity from open customer order already sent
 ProductQtyInSuppliersShipmentAlreadyRecevied=Product quantity from open supplier order already received
 NoProductToShipFoundIntoStock=No product to ship found into warehouse <b>%s</b>. Correct stock or go back to choose another warehouse. 
 WeightVolShort=Weight/Vol.

+ 2 - 2
htdocs/langs/en_US/website.lang

@@ -24,5 +24,5 @@ SetAsHomePage=Set as Home page
 RealURL=Real URL
 ViewWebsiteInProduction=View web site using home URLs
 SetHereVirtualHost=If you can set, on your web server, a dedicated virtual host with a root directory on <strong>%s</strong>, define here the virtual hostname so the preview can be done also using this direct web server access and not only using Dolibarr server.
-PreviewSiteServedByWebServer=Preview %s in a new tab. The %s will be served by an external web server (like Apache, Nginx, IIS). You must instal and setup this server before.<br>URL of %s served by external server:<br><strong>%s</strong>
-PreviewSiteServedByDolibarr=Preview %s in a new tab. The %s will be served by Dolibarr server so it does not need any extra web server (like Apache, Nginx, IIS) to be installed.<br>The inconvenient is that URL of pages are not user friendly and start with path of your Dolibarr.<br>URL of %s served by Dolibarr:<br><strong>%s</strong>
+PreviewSiteServedByWebServer=Preview %s in a new tab.<br><br>The %s will be served by an external web server (like Apache, Nginx, IIS). You must install and setup this server before to point to directory:<br><strong>%s</strong><br>URL served by external server:<br><strong>%s</strong>
+PreviewSiteServedByDolibarr=Preview %s in a new tab.<br><br>The %s will be served by Dolibarr server so it does not need any extra web server (like Apache, Nginx, IIS) to be installed.<br>The inconvenient is that URL of pages are not user friendly and start with path of your Dolibarr.<br>URL served by Dolibarr:<br><strong>%s</strong><br><br>To use your own external web server to serve this web site, create a virtual host on your web server that point on directory<br><strong>%s</strong><br>then enter the name of this virtual server and clicking on the other preview button.  

+ 1 - 1
htdocs/master.inc.php

@@ -180,7 +180,7 @@ if (! defined('NOREQUIREDB'))
 
 	//print "Will work with data into entity instance number '".$conf->entity."'";
 
-	// Here we read database (llx_const table and llx_default_values) and define $conf->global->XXX var.
+	// Here we read database (llx_const table) and define $conf->global->XXX var.
 	$conf->setValues($db);
 }
 

+ 28 - 0
htdocs/public/payment/index.php

@@ -0,0 +1,28 @@
+<?php
+/* Copyright (C) 2009 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/>.
+ */
+
+/**
+ *     	\file       htdocs/public/payment/index.php
+ *		\ingroup    core
+ *		\brief      A redirect page to an error
+ *		\author	    Laurent Destailleur
+ */
+
+require '../../master.inc.php';
+
+header("Location: ".DOL_URL_ROOT.'/public/error-404.php');
+

+ 1002 - 0
htdocs/public/payment/newpayment.php

@@ -0,0 +1,1002 @@
+<?php
+/* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
+ * Copyright (C) 2006-2012	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2009-2012	Regis Houssin			<regis.houssin@capnetworks.com>
+ *
+ * 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/>.
+ *
+ * For test: https://developer.paypal.com/
+ */
+
+/**
+ *     	\file       htdocs/public/payment/newpayment.php
+ *		\ingroup    core
+ *		\brief      File to offer a way to make a payment for a particular Dolibarr entity
+ *		\author	    Laurent Destailleur
+ */
+
+define("NOLOGIN",1);		// This means this output page does not require to be logged.
+define("NOCSRFCHECK",1);	// We accept to go on this page from external web site.
+
+// For MultiCompany module.
+// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
+// TODO This should be useless. Because entity must be retreive from object ref and not from url.
+$entity=(! empty($_GET['entity']) ? (int) $_GET['entity'] : (! empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
+if (is_numeric($entity)) define("DOLENTITY", $entity);
+
+require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
+
+// Security check
+//if (empty($conf->paypal->enabled)) accessforbidden('',0,0,1);
+
+$langs->load("main");
+$langs->load("other");
+$langs->load("dict");
+$langs->load("bills");
+$langs->load("companies");
+$langs->load("errors");
+
+// Input are:
+// type ('invoice','order','contractline'),
+// id (object id),
+// amount (required if id is empty),
+// tag (a free text, required if type is empty)
+// currency (iso code)
+
+$suffix=GETPOST("suffix",'alpha');
+$amount=price2num(GETPOST("amount"));
+if (! GETPOST("currency",'alpha')) $currency=$conf->currency;
+else $currency=GETPOST("currency",'alpha');
+
+if (! GETPOST("action"))
+{
+    if (! GETPOST("amount") && ! GETPOST("source"))
+    {
+    	dol_print_error('',$langs->trans('ErrorBadParameters')." - amount or source");
+    	exit;
+    }
+    if (is_numeric($amount) && ! GETPOST("tag") && ! GETPOST("source"))
+    {
+    	dol_print_error('',$langs->trans('ErrorBadParameters')." - tag or source");
+    	exit;
+    }
+    if (GETPOST("source") && ! GETPOST("ref"))
+    {
+    	dol_print_error('',$langs->trans('ErrorBadParameters')." - ref");
+    	exit;
+    }
+}
+
+// Define $urlwithroot
+//$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
+//$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
+$urlwithroot=DOL_MAIN_URL_ROOT;						// This is to use same domain name than current
+
+$urlok=$urlwithroot.'/public/payment/paymentok.php?';
+$urlko=$urlwithroot.'/public/payment/paymentko.php?';
+
+// Complete urls for post treatment
+$SOURCE=GETPOST("source",'alpha');
+$ref=$REF=GETPOST('ref','alpha');
+$TAG=GETPOST("tag",'alpha');
+$FULLTAG=GETPOST("fulltag",'alpha');		// fulltag is tag with more informations
+$SECUREKEY=GETPOST("securekey");	        // Secure key
+
+if (! empty($SOURCE))
+{
+    $urlok.='source='.urlencode($SOURCE).'&';
+    $urlko.='source='.urlencode($SOURCE).'&';
+}
+if (! empty($REF))
+{
+    $urlok.='ref='.urlencode($REF).'&';
+    $urlko.='ref='.urlencode($REF).'&';
+}
+if (! empty($TAG))
+{
+    $urlok.='tag='.urlencode($TAG).'&';
+    $urlko.='tag='.urlencode($TAG).'&';
+}
+if (! empty($FULLTAG))
+{
+    $urlok.='fulltag='.urlencode($FULLTAG).'&';
+    $urlko.='fulltag='.urlencode($FULLTAG).'&';
+}
+if (! empty($SECUREKEY))
+{
+    $urlok.='securekey='.urlencode($SECUREKEY).'&';
+    $urlko.='securekey='.urlencode($SECUREKEY).'&';
+}
+if (! empty($entity))
+{
+	$urlok.='entity='.urlencode($entity).'&';
+	$urlko.='entity='.urlencode($entity).'&';
+}
+$urlok=preg_replace('/&$/','',$urlok);  // Remove last &
+$urlko=preg_replace('/&$/','',$urlko);  // Remove last &
+
+$paymentmethod=array();
+
+// Check parameters
+if (! empty($conf->paypal->enabled))
+{
+	$langs->load("paypal");
+	
+	require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php';
+	require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php';
+	
+	$PAYPAL_API_OK="";
+	if ($urlok) $PAYPAL_API_OK=$urlok;
+	$PAYPAL_API_KO="";
+	if ($urlko) $PAYPAL_API_KO=$urlko;
+	if (empty($PAYPAL_API_USER))
+	{
+	    dol_print_error('',"Paypal setup param PAYPAL_API_USER not defined");
+	    return -1;
+	}
+	if (empty($PAYPAL_API_PASSWORD))
+	{
+	    dol_print_error('',"Paypal setup param PAYPAL_API_PASSWORD not defined");
+	    return -1;
+	}
+	if (empty($PAYPAL_API_SIGNATURE))
+	{
+	    dol_print_error('',"Paypal setup param PAYPAL_API_SIGNATURE not defined");
+	    return -1;
+	}
+	
+	// Check security token
+	$valid=true;
+	if (! empty($conf->global->PAYPAL_SECURITY_TOKEN))
+	{
+	    if (! empty($conf->global->PAYPAL_SECURITY_TOKEN_UNIQUE))
+	    {
+		    if ($SOURCE && $REF) $token = dol_hash($conf->global->PAYPAL_SECURITY_TOKEN . $SOURCE . $REF, 2);    // Use the source in the hash to avoid duplicates if the references are identical
+		    else $token = dol_hash($conf->global->PAYPAL_SECURITY_TOKEN, 2);
+	    }
+	    else
+	    {
+	        $token = $conf->global->PAYPAL_SECURITY_TOKEN;
+	    }
+		if ($SECUREKEY != $token) $valid=false;
+	
+		if (! $valid)
+		{
+	    	print '<div class="error">Bad value for key.</div>';
+		    //print 'SECUREKEY='.$SECUREKEY.' token='.$token.' valid='.$valid;
+	    	exit;
+		}
+		else
+		{
+			$paymentmethod[]='paypal';
+		}
+	}
+}
+if (! empty($conf->paybox->enabled))
+{
+	$langs->load("paybox");
+	
+}
+// TODO Add check of other payment mode
+
+
+if (empty($paymentmethod)) accessforbidden('', 0, 0, 1);
+
+
+
+/*
+ * Actions
+ */
+
+if (GETPOST("action") == 'dopayment')
+{
+	if (GETPOST('paymentmethod') == 'paypal')
+	{ 
+		$PAYPAL_API_PRICE=price2num(GETPOST("newamount"),'MT');
+	    $PAYPAL_PAYMENT_TYPE='Sale';
+	
+	    $shipToName=GETPOST("shipToName");
+	    $shipToStreet=GETPOST("shipToStreet");
+	    $shipToCity=GETPOST("shipToCity");
+	    $shipToState=GETPOST("shipToState");
+	    $shipToCountryCode=GETPOST("shipToCountryCode");
+	    $shipToZip=GETPOST("shipToZip");
+	    $shipToStreet2=GETPOST("shipToStreet2");
+	    $phoneNum=GETPOST("phoneNum");
+	    $email=GETPOST("email");
+	    $desc=GETPOST("desc");
+	
+		$mesg='';
+		if (empty($PAYPAL_API_PRICE) || ! is_numeric($PAYPAL_API_PRICE))   $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Amount"));
+		//elseif (empty($EMAIL))          $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("YourEMail"));
+		//elseif (! isValidEMail($EMAIL)) $mesg=$langs->trans("ErrorBadEMail",$EMAIL);
+		elseif (empty($FULLTAG))        $mesg=$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("PaymentCode"));
+	
+	    //var_dump($_POST);
+		if (empty($mesg))
+		{
+			dol_syslog("newpayment.php call paypal api and do redirect", LOG_DEBUG);
+	
+			// Other
+			$PAYPAL_API_DEVISE="USD";
+			//if ($currency == 'EUR') $PAYPAL_API_DEVISE="EUR";
+			//if ($currency == 'USD') $PAYPAL_API_DEVISE="USD";
+	        if (! empty($currency)) $PAYPAL_API_DEVISE=$currency;
+	
+		    dol_syslog("Submit Paypal form", LOG_DEBUG);
+		    dol_syslog("PAYPAL_API_USER: $PAYPAL_API_USER", LOG_DEBUG);
+		    //dol_syslog("PAYPAL_API_PASSWORD: $PAYPAL_API_PASSWORD", LOG_DEBUG);  // No password into log files
+		    dol_syslog("PAYPAL_API_SIGNATURE: $PAYPAL_API_SIGNATURE", LOG_DEBUG);
+		    dol_syslog("PAYPAL_API_SANDBOX: $PAYPAL_API_SANDBOX", LOG_DEBUG);
+		    dol_syslog("PAYPAL_API_OK: $PAYPAL_API_OK", LOG_DEBUG);
+		    dol_syslog("PAYPAL_API_KO: $PAYPAL_API_KO", LOG_DEBUG);
+		    dol_syslog("PAYPAL_API_PRICE: $PAYPAL_API_PRICE", LOG_DEBUG);
+		    dol_syslog("PAYPAL_API_DEVISE: $PAYPAL_API_DEVISE", LOG_DEBUG);
+	        dol_syslog("shipToName: $shipToName", LOG_DEBUG);
+	        dol_syslog("shipToStreet: $shipToStreet", LOG_DEBUG);
+	        dol_syslog("shipToCity: $shipToCity", LOG_DEBUG);
+	        dol_syslog("shipToState: $shipToState", LOG_DEBUG);
+	        dol_syslog("shipToCountryCode: $shipToCountryCode", LOG_DEBUG);
+	        dol_syslog("shipToZip: $shipToZip", LOG_DEBUG);
+	        dol_syslog("shipToStreet2: $shipToStreet2", LOG_DEBUG);
+	        dol_syslog("phoneNum: $phoneNum", LOG_DEBUG);
+	        dol_syslog("email: $email", LOG_DEBUG);
+	        dol_syslog("desc: $desc", LOG_DEBUG);
+	
+	        dol_syslog("SCRIPT_URI: ".(empty($_SERVER["SCRIPT_URI"])?'':$_SERVER["SCRIPT_URI"]), LOG_DEBUG);	// If defined script uri must match domain of PAYPAL_API_OK and PAYPAL_API_KO
+		    //$_SESSION["PaymentType"]=$PAYPAL_PAYMENT_TYPE;
+		    //$_SESSION["currencyCodeType"]=$PAYPAL_API_DEVISE;
+		    //$_SESSION["Payment_Amount"]=$PAYPAL_API_PRICE;
+	
+		    // A redirect is added if API call successfull
+	        print_paypal_redirect($PAYPAL_API_PRICE,$PAYPAL_API_DEVISE,$PAYPAL_PAYMENT_TYPE,$PAYPAL_API_OK,$PAYPAL_API_KO, $FULLTAG);
+	
+			exit;
+		}
+	}
+}
+
+
+/*
+ * View
+ */
+
+llxHeaderPaypal($langs->trans("PaymentForm"));
+
+if (! empty($conf->paypal->enabled))
+{
+	if (! empty($PAYPAL_API_SANDBOX))
+	{
+		dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode'),'','warning');
+	}
+
+	// Common variables
+	$creditor=$mysoc->name;
+	$paramcreditor='PAYPAL_CREDITOR_'.$suffix;
+	if (! empty($conf->global->$paramcreditor)) $creditor=$conf->global->$paramcreditor;
+	else if (! empty($conf->global->PAYPAL_CREDITOR)) $creditor=$conf->global->PAYPAL_CREDITOR;
+}
+
+print '<span id="dolpaymentspan"></span>'."\n";
+print '<div class="center">'."\n";
+print '<form id="dolpaymentform" class="center" name="paymentform" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
+print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'."\n";
+print '<input type="hidden" name="action" value="dopayment">'."\n";
+print '<input type="hidden" name="tag" value="'.GETPOST("tag",'alpha').'">'."\n";
+print '<input type="hidden" name="suffix" value="'.GETPOST("suffix",'alpha').'">'."\n";
+print '<input type="hidden" name="securekey" value="'.$SECUREKEY.'">'."\n";
+print '<input type="hidden" name="entity" value="'.$entity.'" />';
+print "\n";
+print '<!-- Form to send a payment -->'."\n";
+if (! empty($conf->paypal->enabled))
+{
+	print '<!-- PAYPAL_API_SANDBOX = '.$conf->global->PAYPAL_API_SANDBOX.' -->'."\n";
+	print '<!-- PAYPAL_API_INTEGRAL_OR_PAYPALONLY = '.$conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY.' -->'."\n";
+	print '<!-- creditor = '.$creditor.' -->'."\n";
+}
+print '<!-- urlok = '.$urlok.' -->'."\n";
+print '<!-- urlko = '.$urlko.' -->'."\n";
+print "\n";
+
+print '<table id="dolpaymenttable" summary="Payment form" class="center">'."\n";
+
+// Show logo (search order: logo defined by PAYBOX_LOGO_suffix, then PAYBOX_LOGO, then small company logo, large company logo, theme logo, common logo)
+$width=0;
+// Define logo and logosmall
+$logosmall=$mysoc->logo_small;
+$logo=$mysoc->logo;
+$paramlogo='PAYMENT_LOGO_'.$suffix;
+if (! empty($conf->global->$paramlogo)) $logosmall=$conf->global->$paramlogo;
+else if (! empty($conf->global->PAYMENT_LOGO)) $logosmall=$conf->global->PAYBOX_LOGO;
+//print '<!-- Show logo (logosmall='.$logosmall.' logo='.$logo.') -->'."\n";
+// Define urllogo
+$urllogo='';
+if (! empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall))
+{
+	$urllogo=DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;file='.urlencode('thumbs/'.$logosmall);
+}
+elseif (! empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo))
+{
+	$urllogo=DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;file='.urlencode($logo);
+	$width=96;
+}
+// Output html code for logo
+if ($urllogo)
+{
+	print '<tr>';
+	print '<td align="center"><img id="dolpaymentlogo" title="'.$title.'" src="'.$urllogo.'"';
+	if ($width) print ' width="'.$width.'"';
+	print '></td>';
+	print '</tr>'."\n";
+}
+
+// Output introduction text
+$text='';
+if (! empty($conf->global->PAYPAL_NEWFORM_TEXT))
+{
+    $langs->load("members");
+    if (preg_match('/^\((.*)\)$/',$conf->global->PAYPAL_NEWFORM_TEXT,$reg)) $text.=$langs->trans($reg[1])."<br>\n";
+    else $text.=$conf->global->PAYPAL_NEWFORM_TEXT."<br>\n";
+    $text='<tr><td align="center"><br>'.$text.'<br></td></tr>'."\n";
+}
+if (empty($text))
+{
+    $text.='<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnPaymentPage").'</strong><br></td></tr>'."\n";
+    $text.='<tr><td class="textpublicpayment"><br>'.$langs->trans("ThisScreenAllowsYouToPay",$creditor).'<br><br></td></tr>'."\n";
+}
+print $text;
+
+// Output payment summary form
+print '<tr><td align="center">';
+print '<table with="100%" id="tablepublicpayment">';
+print '<tr class="liste_total"><td align="left" colspan="2">'.$langs->trans("ThisIsInformationOnPayment").' :</td></tr>'."\n";
+
+$found=false;
+$error=0;
+$var=false;
+
+// Free payment
+if (! GETPOST("source") && $valid)
+{
+	$found=true;
+	$tag=GETPOST("tag");
+	$fulltag=$tag;
+
+	// Creditor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Creditor");
+    print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$creditor.'</b>';
+    print '<input type="hidden" name="creditor" value="'.$creditor.'">';
+    print '</td></tr>'."\n";
+
+	// Amount
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Amount");
+	if (empty($amount)) print ' ('.$langs->trans("ToComplete").')';
+	print '</td><td class="CTableRow'.($var?'1':'2').'">';
+	if (empty($amount) || ! is_numeric($amount))
+	{
+        print '<input type="hidden" name="amount" value="'.GETPOST("amount",'int').'">';
+	    print '<input class="flat" size=8 type="text" name="newamount" value="'.GETPOST("newamount","int").'">';
+	}
+	else {
+		print '<b>'.price($amount).'</b>';
+        print '<input type="hidden" name="amount" value="'.$amount.'">';
+		print '<input type="hidden" name="newamount" value="'.$amount.'">';
+	}
+	// Currency
+	print ' <b>'.$langs->trans("Currency".$currency).'</b>';
+	print '<input type="hidden" name="currency" value="'.$currency.'">';
+	print '</td></tr>'."\n";
+
+	// Tag
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("PaymentCode");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$fulltag.'</b>';
+	print '<input type="hidden" name="tag" value="'.$tag.'">';
+	print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
+	print '</td></tr>'."\n";
+
+    // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum
+    // as they don't exists (buyer is unknown, tag is free).
+}
+
+
+// Payment on customer order
+if (GETPOST("source") == 'order' && $valid)
+{
+	$found=true;
+	$langs->load("orders");
+
+	require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
+
+	$order=new Commande($db);
+	$result=$order->fetch('',$ref);
+	if ($result < 0)
+	{
+		$mesg=$order->error;
+		$error++;
+	}
+	else
+	{
+		$result=$order->fetch_thirdparty($order->socid);
+	}
+
+	$amount=$order->total_ttc;
+    if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int');
+    $amount=price2num($amount);
+
+	$fulltag='ORD='.$order->ref.'.CUS='.$order->thirdparty->id;
+	//$fulltag.='.NAM='.strtr($order->thirdparty->name,"-"," ");
+	if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; }
+	$fulltag=dol_string_unaccent($fulltag);
+
+	// Creditor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Creditor");
+    print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$creditor.'</b>';
+    print '<input type="hidden" name="creditor" value="'.$creditor.'">';
+    print '</td></tr>'."\n";
+
+	// Debitor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("ThirdParty");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$order->thirdparty->name.'</b>';
+
+	// Object
+	
+	$text='<b>'.$langs->trans("PaymentOrderRef",$order->ref).'</b>';
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Designation");
+	print '</td><td class="CTableRow'.($var?'1':'2').'">'.$text;
+	print '<input type="hidden" name="source" value="'.GETPOST("source",'alpha').'">';
+	print '<input type="hidden" name="ref" value="'.$order->ref.'">';
+	print '</td></tr>'."\n";
+
+	// Amount
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Amount");
+	if (empty($amount)) print ' ('.$langs->trans("ToComplete").')';
+	print '</td><td class="CTableRow'.($var?'1':'2').'">';
+	if (empty($amount) || ! is_numeric($amount))
+	{
+        print '<input type="hidden" name="amount" value="'.GETPOST("amount",'int').'">';
+	    print '<input class="flat" size=8 type="text" name="newamount" value="'.GETPOST("newamount","int").'">';
+	}
+	else {
+		print '<b>'.price($amount).'</b>';
+        print '<input type="hidden" name="amount" value="'.$amount.'">';
+		print '<input type="hidden" name="newamount" value="'.$amount.'">';
+	}
+	// Currency
+	print ' <b>'.$langs->trans("Currency".$currency).'</b>';
+	print '<input type="hidden" name="currency" value="'.$currency.'">';
+	print '</td></tr>'."\n";
+
+	// Tag
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("PaymentCode");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$fulltag.'</b>';
+	print '<input type="hidden" name="tag" value="'.$tag.'">';
+	print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
+	print '</td></tr>'."\n";
+
+	// Shipping address
+	$shipToName=$order->thirdparty->name;
+    $shipToStreet=$order->thirdparty->address;
+    $shipToCity=$order->thirdparty->town;
+    $shipToState=$order->thirdparty->state_code;
+    $shipToCountryCode=$order->thirdparty->country_code;
+    $shipToZip=$order->thirdparty->zip;
+    $shipToStreet2='';
+    $phoneNum=$order->thirdparty->phone;
+    if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip)
+    {
+        print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
+        print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
+        print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
+        print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
+        print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
+        print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
+        print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
+        print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
+    }
+    else
+    {
+        print '<!-- Shipping address not complete, so we don t use it -->'."\n";
+    }
+    print '<input type="hidden" name="email" value="'.$order->thirdparty->email.'">'."\n";
+    print '<input type="hidden" name="desc" value="'.$langs->trans("Order").' '.$order->ref.'">'."\n";
+}
+
+
+// Payment on customer invoice
+if (GETPOST("source") == 'invoice' && $valid)
+{
+	$found=true;
+	$langs->load("bills");
+
+	require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
+
+	$invoice=new Facture($db);
+	$result=$invoice->fetch('',$ref);
+	if ($result < 0)
+	{
+		$mesg=$invoice->error;
+		$error++;
+	}
+	else
+	{
+		$result=$invoice->fetch_thirdparty($invoice->socid);
+	}
+
+	$amount=price2num($invoice->total_ttc - $invoice->getSommePaiement());
+    if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int');
+    $amount=price2num($amount);
+
+	$fulltag='INV='.$invoice->ref.'.CUS='.$invoice->thirdparty->id;
+	//$fulltag.='.NAM='.strtr($invoice->thirdparty->name,"-"," ");
+	if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; }
+	$fulltag=dol_string_unaccent($fulltag);
+
+	// Creditor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Creditor");
+    print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$creditor.'</b>';
+    print '<input type="hidden" name="creditor" value="'.$creditor.'">';
+    print '</td></tr>'."\n";
+
+	// Debitor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("ThirdParty");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$invoice->thirdparty->name.'</b>';
+
+	// Object
+	
+	$text='<b>'.$langs->trans("PaymentInvoiceRef",$invoice->ref).'</b>';
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Designation");
+	print '</td><td class="CTableRow'.($var?'1':'2').'">'.$text;
+	print '<input type="hidden" name="source" value="'.GETPOST("source",'alpha').'">';
+	print '<input type="hidden" name="ref" value="'.$invoice->ref.'">';
+	print '</td></tr>'."\n";
+
+	// Amount
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Amount");
+	if (empty($amount)) print ' ('.$langs->trans("ToComplete").')';
+	print '</td><td class="CTableRow'.($var?'1':'2').'">';
+	if (empty($amount) || ! is_numeric($amount))
+	{
+        print '<input type="hidden" name="amount" value="'.GETPOST("amount",'int').'">';
+	    print '<input class="flat" size=8 type="text" name="newamount" value="'.GETPOST("newamount","int").'">';
+	}
+	else {
+		print '<b>'.price($amount).'</b>';
+        print '<input type="hidden" name="amount" value="'.$amount.'">';
+		print '<input type="hidden" name="newamount" value="'.$amount.'">';
+	}
+	// Currency
+	print ' <b>'.$langs->trans("Currency".$currency).'</b>';
+	print '<input type="hidden" name="currency" value="'.$currency.'">';
+	print '</td></tr>'."\n";
+
+	// Tag
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("PaymentCode");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$fulltag.'</b>';
+	print '<input type="hidden" name="tag" value="'.$tag.'">';
+	print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
+	print '</td></tr>'."\n";
+
+    // Shipping address
+    $shipToName=$invoice->thirdparty->name;
+    $shipToStreet=$invoice->thirdparty->address;
+    $shipToCity=$invoice->thirdparty->town;
+    $shipToState=$invoice->thirdparty->state_code;
+    $shipToCountryCode=$invoice->thirdparty->country_code;
+    $shipToZip=$invoice->thirdparty->zip;
+    $shipToStreet2='';
+    $phoneNum=$invoice->thirdparty->phone;
+    if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip)
+    {
+        print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
+        print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
+        print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
+        print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
+        print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
+        print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
+        print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
+        print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
+    }
+    else
+    {
+        print '<!-- Shipping address not complete, so we don t use it -->'."\n";
+    }
+    print '<input type="hidden" name="email" value="'.$invoice->thirdparty->email.'">'."\n";
+    print '<input type="hidden" name="desc" value="'.$langs->trans("Invoice").' '.$invoice->ref.'">'."\n";
+}
+
+// Payment on contract line
+if (GETPOST("source") == 'contractline' && $valid)
+{
+	$found=true;
+	$langs->load("contracts");
+
+	require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
+
+	$contractline=new ContratLigne($db);
+	$result=$contractline->fetch('',$ref);
+	if ($result < 0)
+	{
+		$mesg=$contractline->error;
+		$error++;
+	}
+	else
+	{
+		if ($contractline->fk_contrat > 0)
+		{
+			$contract=new Contrat($db);
+			$result=$contract->fetch($contractline->fk_contrat);
+			if ($result > 0)
+			{
+				$result=$contract->fetch_thirdparty($contract->socid);
+			}
+			else
+			{
+				$mesg=$contract->error;
+				$error++;
+			}
+		}
+		else
+		{
+			$mesg='ErrorRecordNotFound';
+			$error++;
+		}
+	}
+
+	$amount=$contractline->total_ttc;
+	if ($contractline->fk_product)
+	{
+		$product=new Product($db);
+		$result=$product->fetch($contractline->fk_product);
+
+		// We define price for product (TODO Put this in a method in product class)
+		if (! empty($conf->global->PRODUIT_MULTIPRICES))
+		{
+			$pu_ht = $product->multiprices[$contract->thirdparty->price_level];
+			$pu_ttc = $product->multiprices_ttc[$contract->thirdparty->price_level];
+			$price_base_type = $product->multiprices_base_type[$contract->thirdparty->price_level];
+		}
+		else
+		{
+			$pu_ht = $product->price;
+			$pu_ttc = $product->price_ttc;
+			$price_base_type = $product->price_base_type;
+		}
+
+		$amount=$pu_ttc;
+		if (empty($amount))
+		{
+			dol_print_error('','ErrorNoPriceDefinedForThisProduct');
+			exit;
+		}
+	}
+    if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int');
+    $amount=price2num($amount);
+
+	$fulltag='COL='.$contractline->ref.'.CON='.$contract->ref.'.CUS='.$contract->thirdparty->id.'.DAT='.dol_print_date(dol_now(),'%Y%m%d%H%M');
+	//$fulltag.='.NAM='.strtr($contract->thirdparty->name,"-"," ");
+	if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; }
+	$fulltag=dol_string_unaccent($fulltag);
+
+	$qty=1;
+	if (GETPOST('qty')) $qty=GETPOST('qty');
+
+	// Creditor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Creditor");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$creditor.'</b>';
+    print '<input type="hidden" name="creditor" value="'.$creditor.'">';
+	print '</td></tr>'."\n";
+
+	// Debitor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("ThirdParty");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$contract->thirdparty->name.'</b>';
+
+	// Object
+	
+	$text='<b>'.$langs->trans("PaymentRenewContractId",$contract->ref,$contractline->ref).'</b>';
+	if ($contractline->fk_product)
+	{
+		$text.='<br>'.$product->ref.($product->label?' - '.$product->label:'');
+	}
+	if ($contractline->description) $text.='<br>'.dol_htmlentitiesbr($contractline->description);
+	//if ($contractline->date_fin_validite) {
+	//	$text.='<br>'.$langs->trans("DateEndPlanned").': ';
+	//	$text.=dol_print_date($contractline->date_fin_validite);
+	//}
+	if ($contractline->date_fin_validite)
+	{
+		$text.='<br>'.$langs->trans("ExpiredSince").': '.dol_print_date($contractline->date_fin_validite);
+	}
+
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Designation");
+	print '</td><td class="CTableRow'.($var?'1':'2').'">'.$text;
+	print '<input type="hidden" name="source" value="'.GETPOST("source",'alpha').'">';
+	print '<input type="hidden" name="ref" value="'.$contractline->ref.'">';
+	print '</td></tr>'."\n";
+
+	// Quantity
+	
+	$label=$langs->trans("Quantity");
+	$qty=1;
+	$duration='';
+	if ($contractline->fk_product)
+	{
+		if ($product->isService() && $product->duration_value > 0)
+		{
+			$label=$langs->trans("Duration");
+
+			// TODO Put this in a global method
+			if ($product->duration_value > 1)
+			{
+				$dur=array("h"=>$langs->trans("Hours"),"d"=>$langs->trans("DurationDays"),"w"=>$langs->trans("DurationWeeks"),"m"=>$langs->trans("DurationMonths"),"y"=>$langs->trans("DurationYears"));
+			}
+			else
+			{
+				$dur=array("h"=>$langs->trans("Hour"),"d"=>$langs->trans("DurationDay"),"w"=>$langs->trans("DurationWeek"),"m"=>$langs->trans("DurationMonth"),"y"=>$langs->trans("DurationYear"));
+			}
+			$duration=$product->duration_value.' '.$dur[$product->duration_unit];
+		}
+	}
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$label.'</td>';
+	print '<td class="CTableRow'.($var?'1':'2').'"><b>'.($duration?$duration:$qty).'</b>';
+	print '<input type="hidden" name="newqty" value="'.dol_escape_htmltag($qty).'">';
+	print '</b></td></tr>'."\n";
+
+	// Amount
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Amount");
+	if (empty($amount)) print ' ('.$langs->trans("ToComplete").')';
+	print '</td><td class="CTableRow'.($var?'1':'2').'">';
+	if (empty($amount) || ! is_numeric($amount))
+	{
+        print '<input type="hidden" name="amount" value="'.GETPOST("amount",'int').'">';
+	    print '<input class="flat" size=8 type="text" name="newamount" value="'.GETPOST("newamount","int").'">';
+	}
+	else {
+		print '<b>'.price($amount).'</b>';
+        print '<input type="hidden" name="amount" value="'.$amount.'">';
+		print '<input type="hidden" name="newamount" value="'.$amount.'">';
+	}
+	// Currency
+	print ' <b>'.$langs->trans("Currency".$currency).'</b>';
+	print '<input type="hidden" name="currency" value="'.$currency.'">';
+	print '</td></tr>'."\n";
+
+	// Tag
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("PaymentCode");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$fulltag.'</b>';
+	print '<input type="hidden" name="tag" value="'.$tag.'">';
+	print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
+	print '</td></tr>'."\n";
+
+    // Shipping address
+    $shipToName=$contract->thirdparty->name;
+    $shipToStreet=$contract->thirdparty->address;
+    $shipToCity=$contract->thirdparty->town;
+    $shipToState=$contract->thirdparty->state_code;
+    $shipToCountryCode=$contract->thirdparty->country_code;
+    $shipToZip=$contract->thirdparty->zip;
+    $shipToStreet2='';
+    $phoneNum=$contract->thirdparty->phone;
+    if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip)
+    {
+        print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
+        print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
+        print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
+        print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
+        print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
+        print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
+        print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
+        print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
+    }
+    else
+    {
+        print '<!-- Shipping address not complete, so we don t use it -->'."\n";
+    }
+    print '<input type="hidden" name="email" value="'.$contract->thirdparty->email.'">'."\n";
+    print '<input type="hidden" name="desc" value="'.$langs->trans("Contract").' '.$contract->ref.'">'."\n";
+}
+
+// Payment on member subscription
+if (GETPOST("source") == 'membersubscription' && $valid)
+{
+	$found=true;
+	$langs->load("members");
+
+	require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
+	require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
+
+	$member=new Adherent($db);
+	$result=$member->fetch('',$ref);
+	if ($result < 0)
+	{
+		$mesg=$member->error;
+		$error++;
+	}
+	else
+	{
+		$subscription=new Subscription($db);
+	}
+
+	$amount=$subscription->total_ttc;
+    if (GETPOST("amount",'int')) $amount=GETPOST("amount",'int');
+    $amount=price2num($amount);
+
+	$fulltag='MEM='.$member->id.'.DAT='.dol_print_date(dol_now(),'%Y%m%d%H%M');
+	if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; }
+	$fulltag=dol_string_unaccent($fulltag);
+
+	// Creditor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Creditor");
+    print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$creditor.'</b>';
+    print '<input type="hidden" name="creditor" value="'.$creditor.'">';
+    print '</td></tr>'."\n";
+
+	// Debitor
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Member");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>';
+	if ($member->morphy == 'mor' && ! empty($member->societe)) print $member->societe;
+	else print $member->getFullName($langs);
+	print '</b>';
+
+	// Object
+	
+	$text='<b>'.$langs->trans("PaymentSubscription").'</b>';
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Designation");
+	print '</td><td class="CTableRow'.($var?'1':'2').'">'.$text;
+	print '<input type="hidden" name="source" value="'.GETPOST("source",'alpha').'">';
+	print '<input type="hidden" name="ref" value="'.$member->ref.'">';
+	print '</td></tr>'."\n";
+
+	if ($member->last_subscription_date || $member->last_subscription_amount)
+	{
+		// Last subscription date
+		
+		print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("LastSubscriptionDate");
+		print '</td><td class="CTableRow'.($var?'1':'2').'">'.dol_print_date($member->last_subscription_date,'day');
+		print '</td></tr>'."\n";
+
+		// Last subscription amount
+		
+		print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("LastSubscriptionAmount");
+		print '</td><td class="CTableRow'.($var?'1':'2').'">'.price($member->last_subscription_amount);
+		print '</td></tr>'."\n";
+
+		if (empty($amount) && ! GETPOST('newamount')) $_GET['newamount']=$member->last_subscription_amount;
+	}
+
+	// Amount
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("Amount");
+	if (empty($amount))
+	{
+		print ' ('.$langs->trans("ToComplete");
+		if (! empty($conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO)) print ' - <a href="'.$conf->global->MEMBER_EXT_URL_SUBSCRIPTION_INFO.'" rel="external" target="_blank">'.$langs->trans("SeeHere").'</a>';
+		print ')';
+	}
+	print '</td><td class="CTableRow'.($var?'1':'2').'">';
+	if (empty($amount) || ! is_numeric($amount))
+	{
+	    $valtoshow=GETPOST("newamount",'int');
+	    if (! empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) $valtoshow=max($conf->global->MEMBER_MIN_AMOUNT,$valtoshow);
+        print '<input type="hidden" name="amount" value="'.GETPOST("amount",'int').'">';
+	    print '<input class="flat" size="8" type="text" name="newamount" value="'.$valtoshow.'">';
+	}
+	else {
+	    $valtoshow=$amount;
+	    if (! empty($conf->global->MEMBER_MIN_AMOUNT) && $valtoshow) $valtoshow=max($conf->global->MEMBER_MIN_AMOUNT,$valtoshow);
+	    print '<b>'.price($valtoshow).'</b>';
+        print '<input type="hidden" name="amount" value="'.$valtoshow.'">';
+		print '<input type="hidden" name="newamount" value="'.$valtoshow.'">';
+	}
+	// Currency
+	print ' <b>'.$langs->trans("Currency".$currency).'</b>';
+	print '<input type="hidden" name="currency" value="'.$currency.'">';
+	print '</td></tr>'."\n";
+
+	// Tag
+	
+	print '<tr class="CTableRow'.($var?'1':'2').'"><td class="CTableRow'.($var?'1':'2').'">'.$langs->trans("PaymentCode");
+	print '</td><td class="CTableRow'.($var?'1':'2').'"><b>'.$fulltag.'</b>';
+	print '<input type="hidden" name="tag" value="'.$tag.'">';
+	print '<input type="hidden" name="fulltag" value="'.$fulltag.'">';
+	print '</td></tr>'."\n";
+
+    // Shipping address
+    $shipToName=$member->getFullName($langs);
+    $shipToStreet=$member->address;
+    $shipToCity=$member->town;
+    $shipToState=$member->state_code;
+    $shipToCountryCode=$member->country_code;
+    $shipToZip=$member->zip;
+    $shipToStreet2='';
+    $phoneNum=$member->phone;
+    if ($shipToName && $shipToStreet && $shipToCity && $shipToCountryCode && $shipToZip)
+    {
+        print '<input type="hidden" name="shipToName" value="'.$shipToName.'">'."\n";
+        print '<input type="hidden" name="shipToStreet" value="'.$shipToStreet.'">'."\n";
+        print '<input type="hidden" name="shipToCity" value="'.$shipToCity.'">'."\n";
+        print '<input type="hidden" name="shipToState" value="'.$shipToState.'">'."\n";
+        print '<input type="hidden" name="shipToCountryCode" value="'.$shipToCountryCode.'">'."\n";
+        print '<input type="hidden" name="shipToZip" value="'.$shipToZip.'">'."\n";
+        print '<input type="hidden" name="shipToStreet2" value="'.$shipToStreet2.'">'."\n";
+        print '<input type="hidden" name="phoneNum" value="'.$phoneNum.'">'."\n";
+    }
+    else
+    {
+        print '<!-- Shipping address not complete, so we don t use it -->'."\n";
+    }
+    print '<input type="hidden" name="email" value="'.$member->email.'">'."\n";
+    print '<input type="hidden" name="desc" value="'.$langs->trans("PaymentSubscription").'">'."\n";
+}
+
+
+
+
+if (! $found && ! $mesg) $mesg=$langs->trans("ErrorBadParameters");
+
+if ($mesg) print '<tr><td align="center" colspan="2"><br><div class="warning">'.$mesg.'</div></td></tr>'."\n";
+
+print '</table>'."\n";
+print "\n";
+
+if ($found && ! $error)	// We are in a management option and no error
+{
+	if (empty($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY)) $conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY='integral';
+
+	if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'integral')
+	{
+		print '<br><input class="button" type="submit" name="dopayment" value="'.$langs->trans("PaypalOrCBDoPayment").'">';
+	}
+	if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'paypalonly')
+	{
+		print '<br><input class="button" type="submit" name="dopayment" value="'.$langs->trans("PaypalDoPayment").'">';
+	}
+}
+else
+{
+	dol_print_error_email('ERRORNEWPAYMENTPAYPAL');
+}
+
+print '</td></tr>'."\n";
+
+print '</table>'."\n";
+print '</form>'."\n";
+print '</div>'."\n";
+print '<br>';
+
+
+html_print_paypal_footer($mysoc,$langs);
+
+llxFooterPaypal();
+
+$db->close();

+ 146 - 0
htdocs/public/payment/paymentko.php

@@ -0,0 +1,146 @@
+<?php
+/* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
+ * Copyright (C) 2006-2013	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2012		Regis Houssin			<regis.houssin@capnetworks.com>
+ *
+ * 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/>.
+ */
+
+/**
+ *     	\file       htdocs/public/payment/paymentko.php
+ *		\ingroup    core
+ *		\brief      File to show page after a failed payment.
+ *                  This page is called by payment system with url provided to it competed with parameter TOKEN=xxx
+ *                  This token can be used to get more informations.
+ *		\author	    Laurent Destailleur
+ */
+
+define("NOLOGIN",1);		// This means this output page does not require to be logged.
+define("NOCSRFCHECK",1);	// We accept to go on this page from external web site.
+
+// For MultiCompany module.
+// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
+// TODO This should be useless. Because entity must be retreive from object ref and not from url.
+$entity=(! empty($_GET['entity']) ? (int) $_GET['entity'] : (! empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
+if (is_numeric($entity)) define("DOLENTITY", $entity);
+
+require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
+if (! empty($conf->paypal->enabled))
+{
+	require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php';
+	require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php';
+}
+
+$langs->load("main");
+$langs->load("other");
+$langs->load("dict");
+$langs->load("bills");
+$langs->load("companies");
+$langs->load("paybox");
+$langs->load("paypal");
+
+$PAYPALTOKEN=GETPOST('TOKEN');
+if (empty($PAYPALTOKEN)) $PAYPALTOKEN=GETPOST('token');
+$PAYPALPAYERID=GETPOST('PAYERID');
+if (empty($PAYPALPAYERID)) $PAYPALPAYERID=GETPOST('PayerID');
+$PAYPALFULLTAG=GETPOST('FULLTAG');
+if (empty($PAYPALFULLTAG)) $PAYPALFULLTAG=GETPOST('fulltag');
+
+$paymentmethod=array();
+if (! empty($conf->paypal->enabled)) $paymentmethod['paypal']='paypal';
+if (! empty($conf->paybox->enabled)) $paymentmethod['paybox']='paybox';
+
+
+// Security check
+if (empty($paymentmethod)) accessforbidden('', 0, 0, 1);
+
+
+/*
+ * Actions
+ */
+
+
+
+
+/*
+ * View
+ */
+
+dol_syslog("Callback url when a PayPal payment was canceled. query_string=".(empty($_SERVER["QUERY_STRING"])?'':$_SERVER["QUERY_STRING"])." script_uri=".(empty($_SERVER["SCRIPT_URI"])?'':$_SERVER["SCRIPT_URI"]), LOG_DEBUG, 0, '_payment');
+
+$tracepost = "";
+foreach($_POST as $k => $v) $tracepost .= "{$k} - {$v}\n";
+dol_syslog("POST=".$tracepost, LOG_DEBUG, 0, '_payment');
+
+
+// Send an email
+if (! empty($conf->paypal->enabled))
+{
+	if (! empty($conf->global->PAYPAL_PAYONLINE_SENDEMAIL))
+	{
+	    // Get on url call
+	    $token              = $PAYPALTOKEN;
+	    $fulltag            = $PAYPALFULLTAG;
+	    $payerID            = $PAYPALPAYERID;
+	    // Set by newpayment.php
+	    $paymentType        = $_SESSION['PaymentType'];
+	    $currencyCodeType   = $_SESSION['currencyCodeType'];
+	    $FinalPaymentAmt    = $_SESSION["Payment_Amount"];
+	    // From env
+	    $ipaddress          = $_SESSION['ipaddress'];
+	    
+	    
+		$sendto=$conf->global->PAYPAL_PAYONLINE_SENDEMAIL;
+		$from=$conf->global->MAILING_EMAIL_FROM;
+	
+		$urlback=$_SERVER["REQUEST_URI"];
+		$topic='['.$conf->global->MAIN_APPLICATION_TITLE.'] '.$langs->transnoentitiesnoconv("NewPaypalPaymentFailed");
+		$content=$langs->transnoentitiesnoconv("NewPaypalPaymentFailed")."\ntag=".$fulltag."\ntoken=".$token." paymentType=".$paymentType." currencycodeType=".$currencyCodeType." payerId=".$payerID." ipaddress=".$ipaddress." FinalPaymentAmt=".$FinalPaymentAmt;
+		require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+		$mailfile = new CMailFile($topic, $sendto, $from, $content);
+	
+		$result=$mailfile->sendfile();
+		if ($result)
+		{
+			dol_syslog("EMail sent to ".$sendto, LOG_DEBUG, 0, '_payment');
+		}
+		else
+		{
+			dol_syslog("Failed to send EMail to ".$sendto, LOG_ERR, 0, '_payment');
+		}
+	}
+}
+
+$head='';
+if (! empty($conf->global->PAYMENT_CSS_URL)) $head='<link rel="stylesheet" type="text/css" href="'.$conf->global->PAYMENT_CSS_URL.'?lang='.$langs->defaultlang.'">'."\n";
+
+llxHeader($head, $langs->trans("PaymentForm"));
+
+
+// Show ko message
+print '<span id="dolpaymentspan"></span>'."\n";
+print '<div id="dolpaymentdiv" align="center">'."\n";
+print $langs->trans("YourPaymentHasNotBeenRecorded")."<br><br>";
+
+if (! empty($conf->global->PAYPAL_MESSAGE_KO)) print $conf->global->PAYPAL_MESSAGE_KO;
+print "\n</div>\n";
+
+
+html_print_paypal_footer($mysoc,$langs);
+
+
+llxFooter();
+
+$db->close();

+ 308 - 0
htdocs/public/payment/paymentok.php

@@ -0,0 +1,308 @@
+<?php
+/* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
+ * Copyright (C) 2006-2013	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2012		Regis Houssin			<regis.houssin@capnetworks.com>
+ *
+ * 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/>.
+ */
+
+/**
+ *     	\file       htdocs/public/payment/paymentok.php
+ *		\ingroup    core
+ *		\brief      File to show page after a successful payment
+ *                  This page is called by payment system with url provided to it completed with parameter TOKEN=xxx
+ *                  This token can be used to get more informations.
+ *		\author	    Laurent Destailleur
+ */
+
+define("NOLOGIN",1);		// This means this output page does not require to be logged.
+define("NOCSRFCHECK",1);	// We accept to go on this page from external web site.
+
+// For MultiCompany module.
+// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
+// TODO This should be useless. Because entity must be retreive from object ref and not from url.
+$entity=(! empty($_GET['entity']) ? (int) $_GET['entity'] : (! empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
+if (is_numeric($entity)) define("DOLENTITY", $entity);
+
+require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
+if (! empty($conf->paypal->enabled))
+{
+	require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php';
+	require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php';
+}
+
+// Security check
+//if (empty($conf->paypal->enabled)) accessforbidden('',0,0,1);
+
+$langs->load("main");
+$langs->load("other");
+$langs->load("dict");
+$langs->load("bills");
+$langs->load("companies");
+$langs->load("paybox");
+$langs->load("paypal");
+
+// Clean parameters
+if (! empty($conf->paypal->enabled))
+{
+	$PAYPAL_API_USER="";
+	if (! empty($conf->global->PAYPAL_API_USER)) $PAYPAL_API_USER=$conf->global->PAYPAL_API_USER;
+	$PAYPAL_API_PASSWORD="";
+	if (! empty($conf->global->PAYPAL_API_PASSWORD)) $PAYPAL_API_PASSWORD=$conf->global->PAYPAL_API_PASSWORD;
+	$PAYPAL_API_SIGNATURE="";
+	if (! empty($conf->global->PAYPAL_API_SIGNATURE)) $PAYPAL_API_SIGNATURE=$conf->global->PAYPAL_API_SIGNATURE;
+	$PAYPAL_API_SANDBOX="";
+	if (! empty($conf->global->PAYPAL_API_SANDBOX)) $PAYPAL_API_SANDBOX=$conf->global->PAYPAL_API_SANDBOX;
+	$PAYPAL_API_OK="";
+	if ($urlok) $PAYPAL_API_OK=$urlok;
+	$PAYPAL_API_KO="";
+	if ($urlko) $PAYPAL_API_KO=$urlko;
+	if (empty($PAYPAL_API_USER))
+	{
+	    dol_print_error('',"Paypal setup param PAYPAL_API_USER not defined");
+	    return -1;
+	}
+	if (empty($PAYPAL_API_PASSWORD))
+	{
+	    dol_print_error('',"Paypal setup param PAYPAL_API_PASSWORD not defined");
+	    return -1;
+	}
+	if (empty($PAYPAL_API_SIGNATURE))
+	{
+	    dol_print_error('',"Paypal setup param PAYPAL_API_SIGNATURE not defined");
+	    return -1;
+	}
+}
+
+$source=GETPOST('source');
+$ref=GETPOST('ref');
+$PAYPALTOKEN=GETPOST('TOKEN');
+if (empty($PAYPALTOKEN)) $PAYPALTOKEN=GETPOST('token');
+$PAYPALPAYERID=GETPOST('PAYERID');
+if (empty($PAYPALPAYERID)) $PAYPALPAYERID=GETPOST('PayerID');
+$PAYPALFULLTAG=GETPOST('FULLTAG');
+if (empty($PAYPALFULLTAG)) $PAYPALFULLTAG=GETPOST('fulltag');
+
+$paymentmethod=array();
+if (! empty($conf->paypal->enabled)) $paymentmethod['paypal']='paypal';
+if (! empty($conf->paybox->enabled)) $paymentmethod['paybox']='paybox';
+
+
+// Security check
+if (empty($paymentmethod)) accessforbidden('', 0, 0, 1);
+
+
+/*
+ * Actions
+ */
+
+
+
+/*
+ * View
+ */
+
+dol_syslog("Callback url when a payment was done. query_string=".(empty($_SERVER["QUERY_STRING"])?'':$_SERVER["QUERY_STRING"])." script_uri=".(empty($_SERVER["SCRIPT_URI"])?'':$_SERVER["SCRIPT_URI"]), LOG_DEBUG, 0, '_payment');
+
+$tracepost = "";
+foreach($_POST as $k => $v) $tracepost .= "{$k} - {$v}\n";
+dol_syslog("POST=".$tracepost, LOG_DEBUG, 0, '_payment');
+
+$head='';
+if (! empty($conf->global->PAYMENT_CSS_URL)) $head='<link rel="stylesheet" type="text/css" href="'.$conf->global->PAYMENT_CSS_URL.'?lang='.$langs->defaultlang.'">'."\n";
+
+llxHeader($head, $langs->trans("PaymentForm"));
+
+
+// Show message
+print '<span id="dolpaymentspan"></span>'."\n";
+print '<div id="dolpaymentdiv" align="center">'."\n";
+
+if (! empty($conf->paypal->enabled))
+{
+	if ($PAYPALTOKEN)
+	{
+	    // Get on url call
+	    $token              = $PAYPALTOKEN;
+	    $fulltag            = $PAYPALFULLTAG;
+	    $payerID            = $PAYPALPAYERID;
+	    // Set by newpayment.php
+	    $paymentType        = $_SESSION['PaymentType'];
+	    $currencyCodeType   = $_SESSION['currencyCodeType'];
+	    $FinalPaymentAmt    = $_SESSION["Payment_Amount"];
+	    // From env
+	    $ipaddress          = $_SESSION['ipaddress'];
+	
+		dol_syslog("Call paymentok with token=".$token." paymentType=".$paymentType." currencyCodeType=".$currencyCodeType." payerID=".$payerID." ipaddress=".$ipaddress." FinalPaymentAmt=".$FinalPaymentAmt." fulltag=".$fulltag, LOG_DEBUG, 0, '_paypal');
+	
+	
+		// Validate record
+	    if (! empty($paymentType))
+	    {
+	        dol_syslog("We call GetExpressCheckoutDetails", LOG_DEBUG, 0, '_payment');
+	        $resArray=getDetails($token);
+	        //var_dump($resarray);
+	
+	        dol_syslog("We call DoExpressCheckoutPayment token=".$token." paymentType=".$paymentType." currencyCodeType=".$currencyCodeType." payerID=".$payerID." ipaddress=".$ipaddress." FinalPaymentAmt=".$FinalPaymentAmt." fulltag=".$fulltag, LOG_DEBUG, 0, '_payment');
+	        $resArray=confirmPayment($token, $paymentType, $currencyCodeType, $payerID, $ipaddress, $FinalPaymentAmt, $fulltag);
+	
+	        $ack = strtoupper($resArray["ACK"]);
+	        if($ack=="SUCCESS" || $ack=="SUCCESSWITHWARNING")
+	        {
+	        	$object = new stdClass();
+	
+	        	$object->source		= $source;
+	        	$object->ref		= $ref;
+	        	$object->payerID	= $payerID;
+	        	$object->fulltag	= $fulltag;
+	        	$object->resArray	= $resArray;
+	
+	            // resArray was built from a string like that
+	            // TOKEN=EC%2d1NJ057703V9359028&TIMESTAMP=2010%2d11%2d01T11%3a40%3a13Z&CORRELATIONID=1efa8c6a36bd8&ACK=Success&VERSION=56&BUILD=1553277&TRANSACTIONID=9B994597K9921420R&TRANSACTIONTYPE=expresscheckout&PAYMENTTYPE=instant&ORDERTIME=2010%2d11%2d01T11%3a40%3a12Z&AMT=155%2e57&FEEAMT=5%2e54&TAXAMT=0%2e00&CURRENCYCODE=EUR&PAYMENTSTATUS=Completed&PENDINGREASON=None&REASONCODE=None
+	            $PAYMENTSTATUS=urldecode($resArray["PAYMENTSTATUS"]);   // Should contains 'Completed'
+	            $TRANSACTIONID=urldecode($resArray["TRANSACTIONID"]);
+	            $TAXAMT=urldecode($resArray["TAXAMT"]);
+	            $NOTE=urldecode($resArray["NOTE"]);
+	
+	            print $langs->trans("YourPaymentHasBeenRecorded")."<br>\n";
+	            print $langs->trans("ThisIsTransactionId",$TRANSACTIONID)."<br><br>\n";
+	            if (! empty($conf->global->PAYPAL_MESSAGE_OK)) print $conf->global->PAYPAL_MESSAGE_OK;
+	
+	            // Appel des triggers
+	            include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
+	            $interface=new Interfaces($db);
+	            $result=$interface->run_triggers('PAYPAL_PAYMENT_OK',$object,$user,$langs,$conf);
+	            if ($result < 0) { $error++; $errors=$interface->errors; }
+	            // Fin appel triggers
+	
+	        	// Send an email
+				if (! empty($conf->global->PAYPAL_PAYONLINE_SENDEMAIL))
+				{
+					$sendto=$conf->global->PAYPAL_PAYONLINE_SENDEMAIL;
+					$from=$conf->global->MAILING_EMAIL_FROM;
+					// Define $urlwithroot
+					$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
+					$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
+					//$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
+	
+					$urlback=$_SERVER["REQUEST_URI"];
+					$topic='['.$conf->global->MAIN_APPLICATION_TITLE.'] '.$langs->transnoentitiesnoconv("NewPaypalPaymentReceived");
+					$tmptag=dolExplodeIntoArray($fulltag,'.','=');
+					$content="";
+					if (! empty($tmptag['MEM']))
+					{
+						$langs->load("members");
+						$url=$urlwithroot."/adherents/card_subscriptions.php?rowid=".$tmptag['MEM'];
+						$content.=$langs->trans("PaymentSubscription")."<br>\n";
+						$content.=$langs->trans("MemberId").': '.$tmptag['MEM']."<br>\n";
+						$content.=$langs->trans("Link").': <a href="'.$url.'">'.$url.'</a>'."<br>\n";
+					}
+					else
+					{
+						$content.=$langs->transnoentitiesnoconv("NewPaypalPaymentReceived")."<br>\n";
+					}
+					$content.="<br>\n";
+					$content.=$langs->transnoentitiesnoconv("TechnicalInformation").":<br>\n";
+					$content.=$langs->transnoentitiesnoconv("ReturnURLAfterPayment").': '.$urlback."<br>\n";
+					$content.="tag=".$fulltag." token=".$token." paymentType=".$paymentType." currencycodeType=".$currencyCodeType." payerId=".$payerID." ipaddress=".$ipaddress." FinalPaymentAmt=".$FinalPaymentAmt;
+	
+					$ishtml=dol_textishtml($content);	// May contain urls
+	
+					require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+					$mailfile = new CMailFile($topic, $sendto, $from, $content, array(), array(), array(), '', '', 0, $ishtml);
+	
+					$result=$mailfile->sendfile();
+					if ($result)
+					{
+						dol_syslog("EMail sent to ".$sendto, LOG_DEBUG, 0, '_payment');
+					}
+					else
+					{
+						dol_syslog("Failed to send EMail to ".$sendto, LOG_ERR, 0, '_payment');
+					}
+				}
+	        }
+	        else
+			{
+	            //Display a user friendly Error on the page using any of the following error information returned by PayPal
+	            $ErrorCode = urldecode($resArray["L_ERRORCODE0"]);
+	            $ErrorShortMsg = urldecode($resArray["L_SHORTMESSAGE0"]);
+	            $ErrorLongMsg = urldecode($resArray["L_LONGMESSAGE0"]);
+	            $ErrorSeverityCode = urldecode($resArray["L_SEVERITYCODE0"]);
+	
+	            echo $langs->trans('DoExpressCheckoutPaymentAPICallFailed') . "<br>\n";
+	            echo $langs->trans('DetailedErrorMessage') . ": " . $ErrorLongMsg."<br>\n";
+	            echo $langs->trans('ShortErrorMessage') . ": " . $ErrorShortMsg."<br>\n";
+	            echo $langs->trans('ErrorCode') . ": " . $ErrorCode."<br>\n";
+	            echo $langs->trans('ErrorSeverityCode') . ": " . $ErrorSeverityCode."<br>\n";
+	
+	            if ($mysoc->email) echo "\nPlease, send a screenshot of this page to ".$mysoc->email."<br>\n";
+	
+	           	// Send an email
+				if (! empty($conf->global->PAYPAL_PAYONLINE_SENDEMAIL))
+				{
+					$sendto=$conf->global->PAYPAL_PAYONLINE_SENDEMAIL;
+					$from=$conf->global->MAILING_EMAIL_FROM;
+					// Define $urlwithroot
+					$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
+					$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
+					//$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
+	
+					$urlback=$_SERVER["REQUEST_URI"];
+					$topic='['.$conf->global->MAIN_APPLICATION_TITLE.'] '.$langs->transnoentitiesnoconv("ValidationOfPaypalPaymentFailed");
+					$content="";
+					$content.=$langs->transnoentitiesnoconv("PaypalConfirmPaymentPageWasCalledButFailed")."\n";
+					$content.="\n";
+					$content.=$langs->transnoentitiesnoconv("TechnicalInformation").":\n";
+					$content.=$langs->transnoentitiesnoconv("ReturnURLAfterPayment").': '.$urlback."\n";
+					$content.="tag=".$fulltag."\ntoken=".$token." paymentType=".$paymentType." currencycodeType=".$currencyCodeType." payerId=".$payerID." ipaddress=".$ipaddress." FinalPaymentAmt=".$FinalPaymentAmt;
+	
+					$ishtml=dol_textishtml($content);	// May contain urls
+	
+					require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+					$mailfile = new CMailFile($topic, $sendto, $from, $content, array(), array(), array(), '', '', 0, $ishtml);
+	
+					$result=$mailfile->sendfile();
+					if ($result)
+					{
+						dol_syslog("EMail sent to ".$sendto, LOG_DEBUG, 0, '_payment');
+					}
+					else
+					{
+						dol_syslog("Failed to send EMail to ".$sendto, LOG_ERR, 0, '_payment');
+					}
+				}
+	        }
+	    }
+	    else
+	    {
+	        dol_print_error('','Session expired');
+	    }
+	}
+}
+else
+{
+    // No TOKEN parameter in URL
+    dol_print_error('','No TOKEN parameter in URL');
+}
+
+print "\n</div>\n";
+
+html_print_paypal_footer($mysoc,$langs);
+
+
+llxFooter();
+
+$db->close();

+ 1 - 7
htdocs/societe/agenda.php

@@ -83,7 +83,7 @@ if (empty($reshook))
     }
 
     // Purge search criteria
-    if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers
+    if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All tests are required to be compatible with all browsers
     {
         $actioncode='';
         $search_agenda_label='';
@@ -180,12 +180,6 @@ if ($socid > 0)
         
 		print load_fiche_titre($langs->trans("ActionsOnCompany"),'','');
 		
-        // List of todo actions
-        //show_actions_todo($conf,$langs,$db,$object,null,0,$actioncode);
-
-        // List of done actions
-        //show_actions_done($conf,$langs,$db,$object,null,0,$actioncode);
-     
         // List of all actions
 		$filters=array();
         $filters['search_agenda_label']=$search_agenda_label;

BIN
htdocs/theme/eldy/img/save.png


+ 5 - 1
htdocs/theme/eldy/style.css.php

@@ -253,7 +253,7 @@ a.tab { font-weight: bold !important; }
 a:link, a:visited, a:hover, a:active { font-family: <?php print $fontlist ?>; font-weight: normal; color: rgb(<?php print $colortextlink; ?>); text-decoration: none;  }
 a:hover { text-decoration: underline; color: rgb(<?php print $colortextlink; ?>); }
 a.commonlink { color: rgb(<?php print $colortextlink; ?>) !important; text-decoration: none; }
-
+th.liste_titre a div div:hover, th.liste_titre_sel a div div:hover { text-decoration: underline; }
 input, input.flat, textarea, textarea.flat, form.flat select, select, select.flat, .dataTables_length label select {
     background-color: #FFF;
 }
@@ -1973,6 +1973,10 @@ div.tabBar {
 	width: auto;
 	background: rgb(<?php echo $colorbacktabcard1; ?>);
 }
+div.tabBar div.titre {
+	padding-top: 10px;    
+}
+
 div.tabBarWithBottom {
 	padding-bottom: 18px;
 	border-bottom: 1px solid #aaa; 

BIN
htdocs/theme/md/img/save.png


+ 3 - 0
htdocs/theme/md/style.css.php

@@ -1992,6 +1992,9 @@ div.tabBar {
 	padding-bottom: 12px;
 	border-bottom: 1px solid #aaa; 
 }
+div.tabBar div.titre {
+	padding-top: 10px;    
+}
 div.tabBarWithBottom {
 	padding-bottom: 18px;
 	border-bottom: 1px solid #aaa; 

+ 2 - 2
htdocs/user/class/user.class.php

@@ -376,7 +376,7 @@ class User extends CommonObject
 			    {
 			        if (! empty($obj->page) && ! empty($obj->type) && ! empty($obj->param)) 
 			        {
-			            $user->default_values[$obj->page][$obj->type][$obj->param]=$obj->value;
+			            $this->default_values[$obj->page][$obj->type][$obj->param]=$obj->value;
 			        }
 			    }
 			    $this->db->free($resql);
@@ -387,7 +387,7 @@ class User extends CommonObject
 				return -3;
 			}
 		}
-
+		
 		return 1;
 	}
 

+ 18 - 29
htdocs/websites/class/website.class.php

@@ -73,10 +73,6 @@ class Website extends CommonObject
 	 * @var mixed
 	 */
 	public $date_creation;
-	/**
-	 * @var mixed
-	 */
-	public $date_modification;
 	/**
 	 * @var mixed
 	 */
@@ -123,7 +119,6 @@ class Website extends CommonObject
 		$error = 0;
 
 		// Clean parameters
-		
 		if (isset($this->entity)) {
 			 $this->entity = trim($this->entity);
 		}
@@ -136,36 +131,30 @@ class Website extends CommonObject
 		if (isset($this->status)) {
 			 $this->status = trim($this->status);
 		}
-
-		
+		if (empty($this->date_creation)) $this->date_creation = dol_now();
 
 		// Check parameters
 		// Put here code to add control on parameters values
 
 		// Insert request
 		$sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '(';
-		
 		$sql.= 'entity,';
 		$sql.= 'ref,';
 		$sql.= 'description,';
 		$sql.= 'status,';
 		$sql.= 'fk_default_home,';
 		$sql.= 'virtualhost,';
-		$sql.= 'date_creation,';
-		$sql.= 'date_modification';
-		
+		$sql.= 'fk_user_create';
+		$sql.= 'date_creation';
 		$sql .= ') VALUES (';
-		
 		$sql .= ' '.(! isset($this->entity)?'NULL':$this->entity).',';
 		$sql .= ' '.(! isset($this->ref)?'NULL':"'".$this->db->escape($this->ref)."'").',';
 		$sql .= ' '.(! isset($this->description)?'NULL':"'".$this->db->escape($this->description)."'").',';
 		$sql .= ' '.(! isset($this->status)?'NULL':$this->status).',';
 		$sql .= ' '.(! isset($this->fk_default_home)?'NULL':$this->fk_default_home).',';
 		$sql .= ' '.(! isset($this->virtualhost)?'NULL':$this->virtualhost).',';
-		$sql .= ' '.(! isset($this->date_creation) || dol_strlen($this->date_creation)==0?'NULL':"'".$this->db->idate($this->date_creation)."'").',';
-		$sql .= ' '.(! isset($this->date_modification) || dol_strlen($this->date_modification)==0?'NULL':"'".$this->db->idate($this->date_modification)."'");
-
-		
+		$sql .= ' '.(! isset($this->fk_user_create)?$user->id:$this->fk_user_create).',';
+		$sql .= ' '.(! isset($this->date_creation) || dol_strlen($this->date_creation)==0?'NULL':"'".$this->db->idate($this->date_creation)."'");
 		$sql .= ')';
 
 		$this->db->begin();
@@ -223,8 +212,9 @@ class Website extends CommonObject
 		$sql .= " t.status,";
 		$sql .= " t.fk_default_home,";
 		$sql .= " t.virtualhost,";
+		$sql .= " t.fk_user_create,";
+		$sql .= " t.fk_user_modif,";
 		$sql .= " t.date_creation,";
-		$sql .= " t.date_modification,";
 		$sql .= " t.tms";
 		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
 		if (null !== $ref) {
@@ -247,11 +237,10 @@ class Website extends CommonObject
 				$this->status = $obj->status;
 				$this->fk_default_home = $obj->fk_default_home;
 				$this->virtualhost = $obj->virtualhost;
+				$this->fk_user_create = $obj->fk_user_create;
+				$this->fk_user_modif = $obj->fk_user_modif;
 				$this->date_creation = $this->db->jdate($obj->date_creation);
-				$this->date_modification = $this->db->jdate($obj->date_modification);
 				$this->tms = $this->db->jdate($obj->tms);
-
-				
 			}
 			$this->db->free($resql);
 
@@ -292,8 +281,9 @@ class Website extends CommonObject
 		$sql .= " t.status,";
 		$sql .= " t.fk_default_home,";
 		$sql .= " t.virtualhost,";
+		$sql .= " t.fk_user_create,";
+		$sql .= " t.fk_user_modif,";
 		$sql .= " t.date_creation,";
-		$sql .= " t.date_modification,";
 		$sql .= " t.tms";
 		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t';
 
@@ -331,8 +321,9 @@ class Website extends CommonObject
 				$line->status = $obj->status;
 				$line->fk_default_home = $obj->fk_default_home;
 				$line->virtualhost = $obj->virtualhost;
+				$this->fk_user_create = $obj->fk_user_create;
+				$this->fk_user_modif = $obj->fk_user_modif;
 				$line->date_creation = $this->db->jdate($obj->date_creation);
-				$line->date_modification = $this->db->jdate($obj->date_modification);
 				$line->tms = $this->db->jdate($obj->tms);
 
 				$this->records[$line->id] = $line;
@@ -377,25 +368,20 @@ class Website extends CommonObject
 			 $this->status = trim($this->status);
 		}
 
-		
-
 		// Check parameters
 		// Put here code to add a control on parameters values
 
 		// Update request
 		$sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET';
-		
 		$sql .= ' entity = '.(isset($this->entity)?$this->entity:"null").',';
 		$sql .= ' ref = '.(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"null").',';
 		$sql .= ' description = '.(isset($this->description)?"'".$this->db->escape($this->description)."'":"null").',';
 		$sql .= ' status = '.(isset($this->status)?$this->status:"null").',';
 		$sql .= ' fk_default_home = '.(($this->fk_default_home > 0)?$this->fk_default_home:"null").',';
 		$sql .= ' virtualhost = '.(($this->virtualhost != '')?"'".$this->db->escape($this->virtualhost)."'":"null").',';
+		$sql .= ' fk_user_modif = '.(! isset($this->fk_user_modif) ? $user->id : $this->fk_user_modif).',';
 		$sql .= ' date_creation = '.(! isset($this->date_creation) || dol_strlen($this->date_creation) != 0 ? "'".$this->db->idate($this->date_creation)."'" : 'null').',';
-		$sql .= ' date_modification = '.(! isset($this->date_modification) || dol_strlen($this->date_modification) != 0 ? "'".$this->db->idate($this->date_modification)."'" : 'null').',';
 		$sql .= ' tms = '.(dol_strlen($this->tms) != 0 ? "'".$this->db->idate($this->tms)."'" : "'".$this->db->idate(dol_now())."'");
-
-        
 		$sql .= ' WHERE rowid=' . $this->id;
 
 		$this->db->begin();
@@ -631,6 +617,8 @@ class Website extends CommonObject
 	 */
 	public function initAsSpecimen()
 	{
+	    global $user;
+	    
 		$this->id = 0;
 		
 		$this->entity = 1;
@@ -639,8 +627,9 @@ class Website extends CommonObject
 		$this->status = '';
 		$this->fk_default_home = null;
 		$this->virtualhost = 'http://myvirtualhost';
+		$this->fk_user_create = $user->id;
+		$this->fk_user_modif = $user->id;
 		$this->date_creation = dol_now();
-		$this->date_modification = dol_now();
 		$this->tms = dol_now();
 
 		

+ 8 - 5
htdocs/websites/class/websitepage.class.php

@@ -181,7 +181,7 @@ class WebsitePage extends CommonObject
 	/**
 	 * Load object in memory from the database
 	 *
-	 * @param int    $id           Id object
+	 * @param int    $id           Id object. If this is 0, the default page of website_id will be used, if not defined, the first one. found
 	 * @param string $website_id   Web site id
 	 * @param string $page         Page name
 	 *
@@ -205,13 +205,16 @@ class WebsitePage extends CommonObject
 		$sql .= " t.tms as date_modification";
 
 		$sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
+		//$sql .= ' WHERE entity IN ('.getEntity('website', 1).')';       // entity is on website level
+		$sql .= ' WHERE 1 = 1';
 		if (null !== $website_id) {
-		    $sql .= ' WHERE t.fk_website = ' . '\'' . $website_id . '\'';
-		    $sql .= ' AND t.pageurl = ' . '\'' . $page . '\'';
+		    $sql .= " AND t.fk_website = '" . $this->db->escape($website_id) . "'";
+		    if ($page) $sql .= " AND t.pageurl = '" . $this->db->escape($page) . "'";
 		} else {
-			$sql .= ' WHERE t.rowid = ' . $id;
+			$sql .= ' AND t.rowid = ' . $id;
 		}
-
+        $sql .= $this->db->plimit(1);
+        
 		$resql = $this->db->query($sql);
 		if ($resql) {
 			$numrows = $this->db->num_rows($resql);

+ 49 - 19
htdocs/websites/index.php

@@ -438,16 +438,34 @@ if ($action == 'updatemeta')
 // Update page
 if ($action == 'updatecontent' || GETPOST('refreshsite') || GETPOST('refreshpage') || GETPOST('preview'))
 {
-    $db->begin();
     $object->fetch(0, $website);
 
+    /*if (GETPOST('savevirtualhost') && $object->virtualhost != GETPOST('previewsite'))
+    {
+        $object->virtualhost = GETPOST('previewsite', 'alpha');
+        $object->update($user);
+    }*/
+    
     $objectpage->fk_website = $object->id;
 
-    $res = $objectpage->fetch($pageid, $object->fk_website);
+    if ($pageid > 0) 
+    {
+        $res = $objectpage->fetch($pageid);
+    }
+    else 
+    {
+        $res = $objectpage->fetch($object->fk_default_home);
+        if (! $res > 0)
+        {
+            $res = $objectpage->fetch(0, $object->fk_website);
+        }
+    }
     if ($res > 0)
     {
         if ($action == 'updatecontent')
         {
+            $db->begin();
+            
             $objectpage->content = GETPOST('PAGE_CONTENT');
     
             // Clean data. We remove all the head section.
@@ -632,7 +650,7 @@ if (count($object->records) > 0)
     // List of websites
     print '<div class="websiteselection">';
     $out='';
-    $out.='<select name="website" id="website">';
+    $out.='<select name="website" class="minwidth100" id="website">';
     if (empty($object->records)) $out.='<option value="-1">&nbsp;</option>';
     // Loop on each sites
     $i=0;
@@ -654,9 +672,9 @@ if (count($object->records) > 0)
 
     if ($website)
     {
-        $realurl=$urlwithroot.'/public/websites/index.php?website='.$website;
+        $virtualurl='';
         $dataroot=DOL_DATA_ROOT.'/websites/'.$website;
-        if (! empty($object->virtualhost)) $realurl=$object->virtualhost; 
+        if (! empty($object->virtualhost)) $virtualurl=$object->virtualhost;
     }
     
     if ($website && $action == 'preview')
@@ -680,20 +698,23 @@ if (count($object->records) > 0)
     if ($action == 'preview')
     {
         print '<div class="websiteinputurl">';
-        print '<input type="text" id="previewsiteurl" class="minwidth200imp" name="previewsite" value="'.$realurl.'">';
+        print '<input type="text" id="previewsiteurl" class="minwidth200imp" name="previewsite" placeholder="'.$langs->trans("http://myvirtualhost").'" value="'.$virtualurl.'">';
         //print '<input type="submit" class="button" name="previewwebsite" target="tab'.$website.'" value="'.$langs->trans("ViewSiteInNewTab").'">';
         $htmltext=$langs->trans("SetHereVirtualHost", $dataroot);
         print $form->textwithpicto('', $htmltext);
         print '</div>';
         
-        $urlext=$realurl;
-        $urlint=DOL_URL_ROOT.'/public/websites/index.php?website='.$website;
-        print '<a class="websitebuttonsitepreview" id="previewsiteext" href="'.$urlext.'" target="tab'.$website.'" alt="'.dol_escape_htmltag($langs->trans("PreviewSiteServedByWebServer")).'">';
-        print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $urlext), 1, 'preview_ext');
-        print '</a>';
+        $urlext=$virtualurl;
+        $urlint=$urlwithroot.'/public/websites/index.php?website='.$website;
+        //if (! empty($object->virtualhost))
+        //{
+            print '<a class="websitebuttonsitepreview" id="previewsiteext" href="'.$urlext.'" target="tab'.$website.'" alt="'.dol_escape_htmltag($langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext)).'">';
+            print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext?$urlext:$langs->trans("VirtualHostUrlNotDefined")), 1, 'preview_ext');
+            print '</a>';
+        //}
         
-        print '<a class="websitebuttonsitepreview" id="previewsite" href="'.DOL_URL_ROOT.'/public/websites/index.php?website='.$website.'" target="tab'.$website.'" alt="'.dol_escape_htmltag($langs->trans("PreviewSiteServedByDolibarr")).'">';
-        print $form->textwithpicto('', $langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $urlint), 1, 'preview');
+        print '<a class="websitebuttonsitepreview" id="previewsite" href="'.$urlwithroot.'/public/websites/index.php?website='.$website.'" target="tab'.$website.'" alt="'.dol_escape_htmltag($langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $urlint)).'">';
+        print $form->textwithpicto('', $langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $urlint, $dataroot), 1, 'preview');
         print '</a>';
     }
 
@@ -803,13 +824,22 @@ if (count($object->records) > 0)
             print $form->textwithpicto('', $htmltext);
             print '</div>';
             
-            $urlext=$realurl.'/'.$pagealias.'.php';
-            print '<a class="websitebuttonsitepreview" id="previewpageext" href="'.$urlext.'" target="tab'.$website.'" alt="'.dol_escape_htmltag($langs->trans("PreviewSiteServedByWebServer")).'">';
-            print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $urlext), 1, 'preview_ext');
-            print '</a>';
+            if (! empty($object->virtualhost))
+            {
+                $urlext=$virtualurl.'/'.$pagealias.'.php';
+                print '<a class="websitebuttonsitepreview" id="previewpageext" href="'.$urlext.'" target="tab'.$website.'" alt="'.dol_escape_htmltag($langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $urlext)).'">';
+                print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $urlext?$urlext:$langs->trans("VirtualHostUrlNotDefined")), 1, 'preview_ext');
+                print '</a>';
+            }
+            else
+            {
+                print '<a class="websitebuttonsitepreview" id="previewpageextnoclick" href="#">';
+                print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $urlext?$urlext:$langs->trans("VirtualHostUrlNotDefined")), 1, 'preview_ext');
+                print '</a>';
+            }
             
-            print '<a class="websitebuttonsitepreview" id="previewpage" href="'.$realpage.'&nocache='.dol_now().'" class="button" target="tab'.$website.'">';
-            print $form->textwithpicto('', $langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $realpage), 1, 'preview'); 
+            print '<a class="websitebuttonsitepreview" id="previewpage" href="'.$realpage.'&nocache='.dol_now().'" class="button" target="tab'.$website.'" alt="'.dol_escape_htmltag($langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $realpage)).'">';
+            print $form->textwithpicto('', $langs->trans("PreviewSiteServedByDolibarr", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $realpage, $dataroot), 1, 'preview'); 
             print '</a>';       // View page in new Tab
             //print '<input type="submit" class="button" name="previewpage" target="tab'.$website.'"value="'.$langs->trans("ViewPageInNewTab").'">';