Selaa lähdekoodia

Merge remote-tracking branch 'upstream/develop' into 14a22

Alexandre SPANGARO 4 vuotta sitten
vanhempi
commit
2a1cc04b66
100 muutettua tiedostoa jossa 838 lisäystä ja 902 poistoa
  1. 5 5
      SECURITY.md
  2. 2 64
      dev/examples/zapier/README.md
  3. 4 0
      htdocs/accountancy/admin/account.php
  4. 0 4
      htdocs/accountancy/admin/accountmodel.php
  5. 1 1
      htdocs/accountancy/admin/categories_list.php
  6. 2 2
      htdocs/accountancy/admin/fiscalyear_card.php
  7. 1 1
      htdocs/accountancy/class/accountancycategory.class.php
  8. 4 4
      htdocs/accountancy/class/lettering.class.php
  9. 4 4
      htdocs/accountancy/customer/lines.php
  10. 3 3
      htdocs/accountancy/customer/list.php
  11. 1 1
      htdocs/accountancy/expensereport/lines.php
  12. 4 4
      htdocs/accountancy/supplier/lines.php
  13. 3 3
      htdocs/accountancy/supplier/list.php
  14. 0 0
      htdocs/adherents/admin/member.php
  15. 26 10
      htdocs/adherents/admin/member_emails.php
  16. 1 1
      htdocs/adherents/admin/member_extrafields.php
  17. 1 1
      htdocs/adherents/admin/member_type_extrafields.php
  18. 2 2
      htdocs/adherents/admin/website.php
  19. 17 17
      htdocs/adherents/canvas/actions_adherentcard_common.class.php
  20. 166 26
      htdocs/adherents/card.php
  21. 58 5
      htdocs/adherents/class/adherent.class.php
  22. 21 3
      htdocs/adherents/class/adherent_type.class.php
  23. 6 1
      htdocs/adherents/class/api_members.class.php
  24. 1 1
      htdocs/adherents/class/api_memberstypes.class.php
  25. 16 245
      htdocs/adherents/index.php
  26. 10 6
      htdocs/adherents/list.php
  27. 28 27
      htdocs/adherents/subscription.php
  28. 7 4
      htdocs/adherents/subscription/list.php
  29. 2 0
      htdocs/adherents/type.php
  30. 2 2
      htdocs/admin/boxes.php
  31. 2 2
      htdocs/admin/company.php
  32. 1 1
      htdocs/admin/const.php
  33. 1 1
      htdocs/admin/delais.php
  34. 20 10
      htdocs/admin/dict.php
  35. 1 0
      htdocs/admin/dolistore/ajax/index.html
  36. 2 2
      htdocs/admin/eventorganization.php
  37. 16 12
      htdocs/admin/external_rss.php
  38. 1 1
      htdocs/admin/ihm.php
  39. 1 1
      htdocs/admin/index.php
  40. 15 9
      htdocs/admin/mailman.php
  41. 2 1
      htdocs/admin/mails_emailing.php
  42. 2 1
      htdocs/admin/mails_ticket.php
  43. 2 2
      htdocs/admin/menus/edit.php
  44. 10 6
      htdocs/admin/modules.php
  45. 2 2
      htdocs/admin/multicurrency.php
  46. 2 2
      htdocs/admin/notification.php
  47. 1 1
      htdocs/admin/perms.php
  48. 1 1
      htdocs/admin/sms.php
  49. 1 1
      htdocs/admin/system/constall.php
  50. 1 1
      htdocs/admin/system/dolibarr.php
  51. 41 59
      htdocs/admin/ticket_public.php
  52. 0 216
      htdocs/api/admin/explorer.php
  53. 87 0
      htdocs/api/admin/explorer_withredoc.php
  54. 11 4
      htdocs/api/admin/index.php
  55. 28 5
      htdocs/api/index.php
  56. 1 1
      htdocs/asset/class/asset_type.class.php
  57. 1 1
      htdocs/bom/bom_agenda.php
  58. 1 1
      htdocs/bom/bom_card.php
  59. 1 1
      htdocs/bom/bom_document.php
  60. 1 1
      htdocs/bom/bom_note.php
  61. 2 2
      htdocs/bom/class/api_boms.class.php
  62. 1 1
      htdocs/bookmarks/bookmarks.lib.php
  63. 1 0
      htdocs/cashdesk/admin/cashdesk.php
  64. 10 0
      htdocs/cashdesk/affContenu.php
  65. 4 0
      htdocs/cashdesk/affIndex.php
  66. 4 0
      htdocs/cashdesk/affPied.php
  67. 4 0
      htdocs/cashdesk/deconnexion.php
  68. 3 0
      htdocs/cashdesk/facturation.php
  69. 9 0
      htdocs/cashdesk/facturation_dhtml.php
  70. 8 0
      htdocs/cashdesk/facturation_verif.php
  71. 5 0
      htdocs/cashdesk/index.php
  72. 6 0
      htdocs/cashdesk/index_verif.php
  73. 9 0
      htdocs/cashdesk/validation_ticket.php
  74. 9 0
      htdocs/cashdesk/validation_verif.php
  75. 4 5
      htdocs/categories/class/categorie.class.php
  76. 0 1
      htdocs/categories/edit.php
  77. 4 4
      htdocs/categories/index.php
  78. 1 1
      htdocs/categories/photos.php
  79. 2 1
      htdocs/comm/action/card.php
  80. 4 4
      htdocs/comm/action/class/actioncomm.class.php
  81. 3 3
      htdocs/comm/action/class/api_agendaevents.class.php
  82. 6 6
      htdocs/comm/action/index.php
  83. 8 8
      htdocs/comm/action/list.php
  84. 5 5
      htdocs/comm/action/pertype.php
  85. 7 7
      htdocs/comm/action/peruser.php
  86. 1 1
      htdocs/comm/card.php
  87. 1 1
      htdocs/comm/contact.php
  88. 1 1
      htdocs/comm/index.php
  89. 1 1
      htdocs/comm/mailing/advtargetemailing.php
  90. 6 5
      htdocs/comm/mailing/card.php
  91. 24 24
      htdocs/comm/mailing/class/advtargetemailing.class.php
  92. 5 2
      htdocs/comm/multiprix.php
  93. 2 2
      htdocs/comm/propal/card.php
  94. 2 2
      htdocs/comm/propal/class/api_proposals.class.php
  95. 2 2
      htdocs/comm/propal/class/propal.class.php
  96. 2 2
      htdocs/comm/propal/index.php
  97. 13 13
      htdocs/comm/propal/list.php
  98. 1 1
      htdocs/comm/propal/stats/index.php
  99. 2 2
      htdocs/commande/class/api_orders.class.php
  100. 2 2
      htdocs/commande/class/commande.class.php

+ 5 - 5
SECURITY.md

@@ -12,7 +12,7 @@ This file contains some policies about the security reports on Dolibarr ERP CRM
 
 ## Reporting a Vulnerability
 
-To report a vulnerability, please use GitHub security advisory at https://github.com/Dolibarr/dolibarr/security/advisories/new (or alternatively send an email to security@dolibarr.org)
+To report a vulnerability, please use GitHub security advisory at https://github.com/Dolibarr/dolibarr/security/advisories/new (if you have permissions) or alternatively send an email to security@dolibarr.org (for everybody)
 
 
 ## Hunting vulnerabilities on Dolibarr
@@ -55,7 +55,7 @@ ONLY vulnerabilities discovered, when the following setup on test platform is us
 * $dolibarr_nocsrfcheck must be kept to the value 0 into conf.php (this is the default value)
 * $dolibarr_main_force_https must be set to something else than 0.
 * The constant MAIN_SECURITY_CSRF_WITH_TOKEN must be set to 1 into backoffice menu Home - Setup - Other (this protection should be set to 1 soon by default)
-* The module DebugBar and ModuleBuilder must NOT be enabled (by default, this module is not enabled. This is a developer tool)
+* The module DebugBar and ModuleBuilder must NOT be enabled (by default, these modules are not enabled. They are developer tools)
 * ONLY security reports on modules provided by default and with the "stable" status are valid (troubles into "experimental", "developement" or external modules are not valid vulnerabilities).
 * The root of web server must link to htdocs and the documents directory must be outside of the web server root (this is the default when using the default installer but may differs with external installer).
 * The web server setup must be done so only the documents directory is in write mode. The root directory called htdocs must be readonly.
@@ -65,12 +65,12 @@ ONLY vulnerabilities discovered, when the following setup on test platform is us
 Scope is the web application (back office) and the APIs.
 
 
-## Qualifying vulnerabilities for Bug bounty programs
+## Qualifying vulnerabilities for reporting
 
 * Remote code execution (RCE)
 * Local files access and manipulation (LFI, RFI, XXE, SSRF, XSPA)
 * Code injections (HTML, JS, SQL, PHP, ...)
-* Cross-Site Scripting (XSS)
+* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose or into module "Web site" when permission to edit website content is allowed).
 * Cross-Site Requests Forgery (CSRF) with real security impact (when using GET URLs, CSRF are qualified only for creating, updating or deleting data from pages restricted to admin users)
 * Open redirect
 * Broken authentication & session management
@@ -82,7 +82,7 @@ Scope is the web application (back office) and the APIs.
 * Stack traces or path disclosure (for non admin users only)
 
 
-## Non-qualifying vulnerabilities for Bug bounty programs, but qualified for reporting
+## Non-qualifying vulnerabilities for reporting
 
 * "Self" XSS
 * SSL/TLS best practices

+ 2 - 64
dev/examples/zapier/README.md

@@ -1,68 +1,6 @@
 # HOW TO BUILD
 
+Take a look at the dolibarr wiki page of Zapier module:
 
-## ENABLE MODULE ZAPIER ON DOLIBARR
-
-This should also enable the module API (required for authentication by Zapier service and to execute action in Dolibarr by Zapier).
-
-Create the Dolibarr login that will be used by Zapier to call APIs. Give the login the permissions on the action you plan to automate.
-
-
-## CREATE A ZAPIER DEVELOPPER ACCOUNT
-
-At first, you need to have a Zapier developper acoount, create it here [Zapier Platform](https://developer.zapier.com/)
-
-
-## INSTALL ZAPIER COMMAND LINE TOOLS WITH LINK TO ZAPIER ONLINE ACCOUNT
-
-### Install Node.js
-
-An easy option to get set up with Node.js is to visit [https://nodejs.org/en/download/](https://nodejs.org/en/download/) and download the official installer for your OS. If you're installing with a package manager it's even easier.
-
-After installation, confirm that Node.js is ready to use:
-  `node --version`
-
-### Install the Zapier CLI
-
-Next let's install the Zapier CLI tools. The CLI will allow you to build your app, deploy it to the Zapier platform, do local testing, manage users and testers, view remote logs, collaborate with your team, and more:
-
-  `cd dev/examples/zapier`
-
-  `npm install -g zapier-platform-cli` to install the CLI globally
-
-  `zapier --version` to return version of the CLI
-
-### Run Zapier Login
-
-Let's configure authentication between your dev environment and the Zapier platform. You'll use the email address and password you use to log in to the Zapier application.
-
-  `zapier login`
-
-This command will set up a .zapierrc file in your home directory.
-
-### Install the Project
-
-In zapier example directory, run:
-
-  `cd dev/examples/zapier`
-
-  `npm install`
-
-### Deploying your App
-
-Let's deploy it! When you're ready to try your code out on the Zapier platform use the push command. Only you will be able to see the app until you invite testers.
-
-  `zapier register`   (the first time, choose name for example "Dolibarr")
-  
-  `zapier push`
-
-After a push, the Application, with the name you defined during the register step, is available when creating a Zap.
-
-You will find original tutorial here : [https://zapier.com/developer/start/introduction](https://zapier.com/developer/start/introduction)
-
-
-### Create a Zap
-
-Create a ZAP that use the application you registered.
-For authentication, you must enter the login / pass of account used by Zapier to call APIs.
+https://wiki.dolibarr.org/index.php?title=Module_Zapier
 

+ 4 - 0
htdocs/accountancy/admin/account.php

@@ -582,6 +582,10 @@ if ($resql) {
 		$i++;
 	}
 
+	if ($num == 0) {
+		print '<tr><td colspan="'.$totalarray['nbfield'].'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
+	}
+
 	print "</table>";
 	print "</div>";
 	print '</form>';

+ 0 - 4
htdocs/accountancy/admin/accountmodel.php

@@ -180,10 +180,6 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
 		}
 	}
 	// Other checks
-	if ($tabname[$id] == MAIN_DB_PREFIX."c_actioncomm" && GETPOSTISSET("type") && in_array($_POST["type"], array('system', 'systemauto'))) {
-		$ok = 0;
-		setEventMessages($langs->transnoentities('ErrorReservedTypeSystemSystemAuto'), null, 'errors');
-	}
 	if (GETPOSTISSET("pcg_version")) {
 		if (GETPOST("pcg_version") == '0') {
 			$ok = 0;

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

@@ -185,7 +185,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
 		}
 	}
 	if (GETPOSTISSET("code")) {
-		if ($_POST["code"] == '0') {
+		if (GETPOST("code") == '0') {
 			$ok = 0;
 			setEventMessages($langs->transnoentities('ErrorCodeCantContainZero'), null, 'errors');
 		}

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

@@ -121,8 +121,8 @@ if ($action == 'confirm_delete' && $confirm == "yes") {
 	if (!GETPOST('cancel', 'alpha')) {
 		$result = $object->fetch($id);
 
-		$object->date_start = empty($_POST["fiscalyear"]) ? '' : $date_start;
-		$object->date_end = empty($_POST["fiscalyearend"]) ? '' : $date_end;
+		$object->date_start = GETPOST("fiscalyear") ? $date_start : '';
+		$object->date_end = GETPOST("fiscalyearend") ? $date_end : '';
 		$object->label = GETPOST('label', 'alpha');
 		$object->statut = GETPOST('statut', 'int');
 

+ 1 - 1
htdocs/accountancy/class/accountancycategory.class.php

@@ -743,7 +743,7 @@ class AccountancyCategory // extends CommonObject
 				}
 				$listofaccount .= "'".$cptcursor."'";
 			}
-			$sql .= " AND t.numero_compte IN (".$listofaccount.")";
+			$sql .= " AND t.numero_compte IN (".$this->db->sanitize($listofaccount).")";
 		} else {
 			$sql .= " AND t.numero_compte = '".$this->db->escape($cpt)."'";
 		}

+ 4 - 4
htdocs/accountancy/class/lettering.class.php

@@ -126,7 +126,7 @@ class Lettering extends BookKeeping
 					if (count($ids_fact)) {
 						$sql = 'SELECT bk.rowid, facf.ref, facf.ref_supplier ';
 						$sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn facf ";
-						$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON(  bk.fk_doc = facf.rowid AND facf.rowid IN (".implode(',', $ids_fact)."))";
+						$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON(  bk.fk_doc = facf.rowid AND facf.rowid IN (".$this->db->sanitize(implode(',', $ids_fact))."))";
 						$sql .= " WHERE bk.code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX."accounting_journal WHERE nature=3 AND entity=".$conf->entity.") ";
 						$sql .= " AND facf.entity = ".$conf->entity;
 						$sql .= " AND ( ";
@@ -185,7 +185,7 @@ class Lettering extends BookKeeping
 					if (count($ids_fact)) {
 						$sql = 'SELECT bk.rowid, fac.ref, fac.ref_supplier ';
 						$sql .= " FROM ".MAIN_DB_PREFIX."facture fac ";
-						$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON(  bk.fk_doc = fac.rowid AND fac.rowid IN (".implode(',', $ids_fact)."))";
+						$sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_bookkeeping as bk ON(  bk.fk_doc = fac.rowid AND fac.rowid IN (".$this->db->sanitize(implode(',', $ids_fact))."))";
 						$sql .= " WHERE code_journal IN (SELECT code FROM ".MAIN_DB_PREFIX."accounting_journal WHERE nature=2 AND entity=".$conf->entity.") ";
 						$sql .= " AND fac.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy
 						$sql .= " AND ( ";
@@ -255,7 +255,7 @@ class Lettering extends BookKeeping
 		}
 
 		$sql = "SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM ".MAIN_DB_PREFIX."accounting_bookkeeping WHERE ";
-		$sql .= " rowid IN (".implode(',', $ids).") AND date_validated IS NULL";
+		$sql .= " rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND date_validated IS NULL";
 		$result = $this->db->query($sql);
 		if ($result) {
 			$obj = $this->db->fetch_object($result);
@@ -276,7 +276,7 @@ class Lettering extends BookKeeping
 			$sql = "UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping SET";
 			$sql .= " lettering_code='".$this->db->escape($lettre)."'";
 			$sql .= " , date_lettering = '".$this->db->idate($now)."'"; // todo correct date it's false
-			$sql .= "  WHERE rowid IN (".implode(',', $ids).") AND date_validated IS NULL ";
+			$sql .= "  WHERE rowid IN (".$this->db->sanitize(implode(',', $ids)).") AND date_validated IS NULL ";
 			$this->db->begin();
 
 			dol_syslog(get_class($this)."::update sql=".$sql, LOG_DEBUG);

+ 4 - 4
htdocs/accountancy/customer/lines.php

@@ -129,7 +129,7 @@ if (is_array($changeaccount) && count($changeaccount) > 0 && $user->rights->acco
 
 		$sql1 = "UPDATE ".MAIN_DB_PREFIX."facturedet as l";
 		$sql1 .= " SET l.fk_code_ventilation=".(GETPOST('account_parent', 'int') > 0 ? GETPOST('account_parent', 'int') : '0');
-		$sql1 .= ' WHERE l.rowid IN ('.implode(',', $changeaccount).')';
+		$sql1 .= ' WHERE l.rowid IN ('.$db->sanitize(implode(',', $changeaccount)).')';
 
 		dol_syslog('accountancy/customer/lines.php::changeaccount sql= '.$sql1);
 		$resql1 = $db->query($sql1);
@@ -246,11 +246,11 @@ if (strlen(trim($search_country))) {
 	if ($search_country == 'special_allnotme') {
 		$sql .= " AND co.code <> '".$db->escape($mysoc->country_code)."'";
 	} elseif ($search_country == 'special_eec') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} elseif ($search_country == 'special_eecnotme') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC_without_me.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC_without_me, 1).")";
 	} elseif ($search_country == 'special_noteec') {
-		$sql .= " AND co.code NOT IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code NOT IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} else {
 		$sql .= natural_search("co.code", $search_country);
 	}

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

@@ -283,11 +283,11 @@ if (strlen(trim($search_country))) {
 	if ($search_country == 'special_allnotme') {
 		$sql .= " AND co.code <> '".$db->escape($mysoc->country_code)."'";
 	} elseif ($search_country == 'special_eec') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} elseif ($search_country == 'special_eecnotme') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC_without_me.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC_without_me, 1).")";
 	} elseif ($search_country == 'special_noteec') {
-		$sql .= " AND co.code NOT IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code NOT IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} else {
 		$sql .= natural_search("co.code", $search_country);
 	}

+ 1 - 1
htdocs/accountancy/expensereport/lines.php

@@ -119,7 +119,7 @@ if (is_array($changeaccount) && count($changeaccount) > 0 && $user->rights->acco
 
 		$sql1 = "UPDATE ".MAIN_DB_PREFIX."expensereport_det as erd";
 		$sql1 .= " SET erd.fk_code_ventilation=".(GETPOST('account_parent', 'int') > 0 ? GETPOST('account_parent', 'int') : '0');
-		$sql1 .= ' WHERE erd.rowid IN ('.implode(',', $changeaccount).')';
+		$sql1 .= ' WHERE erd.rowid IN ('.$db->sanitize(implode(',', $changeaccount)).')';
 
 		dol_syslog('accountancy/expensereport/lines.php::changeaccount sql= '.$sql1);
 		$resql1 = $db->query($sql1);

+ 4 - 4
htdocs/accountancy/supplier/lines.php

@@ -130,7 +130,7 @@ if (is_array($changeaccount) && count($changeaccount) > 0) {
 
 		$sql1 = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_det as l";
 		$sql1 .= " SET l.fk_code_ventilation=".(GETPOST('account_parent', 'int') > 0 ? GETPOST('account_parent', 'int') : '0');
-		$sql1 .= ' WHERE l.rowid IN ('.implode(',', $changeaccount).')';
+		$sql1 .= ' WHERE l.rowid IN ('.$db->sanitize(implode(',', $changeaccount)).')';
 
 		dol_syslog('accountancy/supplier/lines.php::changeaccount sql= '.$sql1);
 		$resql1 = $db->query($sql1);
@@ -238,11 +238,11 @@ if (strlen(trim($search_country))) {
 	if ($search_country == 'special_allnotme') {
 		$sql .= " AND co.code <> '".$db->escape($mysoc->country_code)."'";
 	} elseif ($search_country == 'special_eec') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} elseif ($search_country == 'special_eecnotme') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC_without_me.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC_without_me, 1).")";
 	} elseif ($search_country == 'special_noteec') {
-		$sql .= " AND co.code NOT IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code NOT IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} else {
 		$sql .= natural_search("co.code", $search_country);
 	}

+ 3 - 3
htdocs/accountancy/supplier/list.php

@@ -288,11 +288,11 @@ if (strlen(trim($search_country))) {
 	if ($search_country == 'special_allnotme') {
 		$sql .= " AND co.code <> '".$db->escape($mysoc->country_code)."'";
 	} elseif ($search_country == 'special_eec') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} elseif ($search_country == 'special_eecnotme') {
-		$sql .= " AND co.code IN (".$country_code_in_EEC_without_me.")";
+		$sql .= " AND co.code IN (".$db->sanitize($country_code_in_EEC_without_me, 1).")";
 	} elseif ($search_country == 'special_noteec') {
-		$sql .= " AND co.code NOT IN (".$country_code_in_EEC.")";
+		$sql .= " AND co.code NOT IN (".$db->sanitize($country_code_in_EEC, 1).")";
 	} else {
 		$sql .= natural_search("co.code", $search_country);
 	}

+ 0 - 0
htdocs/adherents/admin/adherent.php → htdocs/adherents/admin/member.php


+ 26 - 10
htdocs/adherents/admin/adherent_emails.php → htdocs/adherents/admin/member_emails.php

@@ -24,7 +24,7 @@
  */
 
 /**
- *   	\file       htdocs/adherents/admin/adherent.php
+ *   	\file       htdocs/adherents/admin/member_emails.php
  *		\ingroup    member
  *		\brief      Page to setup the module Foundation
  */
@@ -55,6 +55,7 @@ $constantes = array(
 	'ADHERENT_EMAIL_TEMPLATE_MEMBER_VALIDATION'	=>'emailtemplate:member', /* old was ADHERENT_MAIL_VALID */
 	'ADHERENT_EMAIL_TEMPLATE_SUBSCRIPTION'		=>'emailtemplate:member', /* old was ADHERENT_MAIL_COTIS */
 	'ADHERENT_EMAIL_TEMPLATE_CANCELATION'		=>'emailtemplate:member', /* old was ADHERENT_MAIL_RESIL */
+	'ADHERENT_EMAIL_TEMPLATE_EXCLUSION'		=>'emailtemplate:member',
 	'ADHERENT_MAIL_FROM'=>'string',
 	'ADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT'=>'string',
 	'ADHERENT_AUTOREGISTER_NOTIF_MAIL'=>'html',
@@ -69,9 +70,24 @@ $constantes = array(
 //
 if ($action == 'updateall') {
 	$db->begin();
-	$res1 = $res2 = $res3 = $res4 = $res5 = $res6 = 0;
-	$res1 = dolibarr_set_const($db, 'XXXX', GETPOST('ADHERENT_LOGIN_NOT_REQUIRED', 'alpha'), 'chaine', 0, '', $conf->entity);
-	if ($res1 < 0 || $res2 < 0 || $res3 < 0 || $res4 < 0 || $res5 < 0 || $res6 < 0) {
+
+	$res = 0;
+	foreach ($constantes as $constname => $value) {
+		$constvalue = (GETPOSTISSET('constvalue_'.$constname) ? GETPOST('constvalue_'.$constname, 'alphanohtml') : GETPOST('constvalue'));
+		$consttype = (GETPOSTISSET('consttype_'.$constname) ? GETPOST('consttype_'.$constname, 'alphanohtml') : GETPOST('consttype'));
+		$constnote = (GETPOSTISSET('constnote_'.$constname) ? GETPOST('constnote_'.$constname, 'restricthtml') : GETPOST('constnote'));
+
+		$typetouse = empty($oldtypetonewone[$consttype]) ? $consttype : $oldtypetonewone[$consttype];
+		$constvalue = preg_replace('/:member$/', '', $constvalue);
+
+		$res = dolibarr_set_const($db, $constname, $constvalue, $consttype, 0, $constnote, $conf->entity);
+		if ($res <= 0) {
+			$error++;
+			$action = 'list';
+		}
+	}
+
+	if ($error > 0) {
 		setEventMessages('ErrorFailedToSaveDate', null, 'errors');
 		$db->rollback();
 	} else {
@@ -126,19 +142,19 @@ $head = member_admin_prepare_head();
 print dol_get_fiche_head($head, 'emails', $langs->trans("Members"), -1, 'user');
 
 // TODO Use global form
-//print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
-//print '<input type="hidden" name="token" value="'.newToken().'">';
-//print '<input type="hidden" name="action" value="updateall">';
+print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
+print '<input type="hidden" name="token" value="'.newToken().'">';
+print '<input type="hidden" name="action" value="updateall">';
 
 $helptext = '*'.$langs->trans("FollowingConstantsWillBeSubstituted").'<br>';
 $helptext .= '__DOL_MAIN_URL_ROOT__, __ID__, __FIRSTNAME__, __LASTNAME__, __FULLNAME__, __LOGIN__, __PASSWORD__, ';
 $helptext .= '__COMPANY__, __ADDRESS__, __ZIP__, __TOWN__, __COUNTRY__, __EMAIL__, __BIRTH__, __PHOTO__, __TYPE__, ';
 //$helptext.='__YEAR__, __MONTH__, __DAY__';	// Not supported
 
-form_constantes($constantes, 0, $helptext);
+form_constantes($constantes, 3, $helptext);
 
-//print '<div class="center"><input type="submit" class="button" value="'.$langs->trans("Update").'" name="update"></div>';
-//print '</form>';
+print '<div class="center"><input type="submit" class="button" value="'.$langs->trans("Update").'" name="update"></div>';
+print '</form>';
 
 print dol_get_fiche_end();
 

+ 1 - 1
htdocs/adherents/admin/adherent_extrafields.php → htdocs/adherents/admin/member_extrafields.php

@@ -19,7 +19,7 @@
  */
 
 /**
- *      \file       htdocs/adherents/admin/adherent_extrafields.php
+ *      \file       htdocs/adherents/admin/member_extrafields.php
  *		\ingroup    member
  *		\brief      Page to setup extra fields of members
  */

+ 1 - 1
htdocs/adherents/admin/adherent_type_extrafields.php → htdocs/adherents/admin/member_type_extrafields.php

@@ -22,7 +22,7 @@
  */
 
 /**
- *      \file       htdocs/adherents/admin/adherent_type_extrafields.php
+ *      \file       htdocs/adherents/admin/member_type_extrafields.php
  *		\ingroup    member
  *		\brief      Page to setup extra fields of members
  */

+ 2 - 2
htdocs/adherents/admin/website.php

@@ -178,7 +178,7 @@ if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) {
 	print '</td><td class="right">';
 	$listofval = array();
 	$listofval += $adht->liste_array();
-	$forcetype = $conf->global->MEMBER_NEWFORM_FORCETYPE ?: -1;
+	$forcetype = empty($conf->global->MEMBER_NEWFORM_FORCETYPE) ? -1 : $conf->global->MEMBER_NEWFORM_FORCETYPE;
 	print $form->selectarray("MEMBER_NEWFORM_FORCETYPE", $listofval, $forcetype, count($listofval) > 1 ? 1 : 0);
 	print "</td></tr>\n";
 
@@ -232,7 +232,7 @@ if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) {
 	print '<br>';
 	//print $langs->trans('FollowingLinksArePublic').'<br>';
 	print img_picto('', 'globe').' '.$langs->trans('BlankSubscriptionForm').':<br>';
-	if ($conf->multicompany->enabled) {
+	if (!empty($conf->multicompany->enabled)) {
 		$entity_qr = '?entity='.$conf->entity;
 	} else {
 		$entity_qr = '';

+ 17 - 17
htdocs/adherents/canvas/actions_adherentcard_common.class.php

@@ -253,23 +253,23 @@ abstract class ActionsAdherentCardCommon
 		// phpcs:enable
 		global $langs, $mysoc;
 
-		$this->object->old_name = $_POST["old_name"];
-		$this->object->old_firstname = $_POST["old_firstname"];
-
-		$this->object->fk_soc = $_POST["fk_soc"];
-		$this->object->lastname			= $_POST["lastname"];
-		$this->object->firstname		= $_POST["firstname"];
-		$this->object->civility_id = $_POST["civility_id"];
-		$this->object->address = $_POST["address"];
-		$this->object->zip = $_POST["zipcode"];
-		$this->object->town = $_POST["town"];
-		$this->object->country_id = $_POST["country_id"] ? $_POST["country_id"] : $mysoc->country_id;
-		$this->object->state_id = $_POST["state_id"];
-		$this->object->phone_perso = $_POST["phone_perso"];
-		$this->object->phone_mobile = $_POST["phone_mobile"];
-		$this->object->email			= $_POST["email"];
-		$this->object->note				= $_POST["note"];
-		$this->object->canvas = $_POST["canvas"];
+		$this->object->old_name = GETPOST("old_name");
+		$this->object->old_firstname = GETPOST("old_firstname");
+
+		$this->object->fk_soc = GETPOST("fk_soc");
+		$this->object->lastname			= GETPOST("lastname");
+		$this->object->firstname		= GETPOST("firstname");
+		$this->object->civility_id = GETPOST("civility_id");
+		$this->object->address = GETPOST("address");
+		$this->object->zip = GETPOST("zipcode");
+		$this->object->town = GETPOST("town");
+		$this->object->country_id = GETPOST("country_id", 'int') ? GETPOST("country_id", 'int') : $mysoc->country_id;
+		$this->object->state_id = GETPOST("state_id", 'int');
+		$this->object->phone_perso = GETPOST("phone_perso");
+		$this->object->phone_mobile = GETPOST("phone_mobile");
+		$this->object->email			= GETPOST("email", 'alphawithlgt');
+		$this->object->note				= GETPOST("note", 'restricthtml');
+		$this->object->canvas = GETPOST("canvas");
 
 		// We set country_id, and country_code label of the chosen country
 		if ($this->object->country_id) {

+ 166 - 26
htdocs/adherents/card.php

@@ -655,7 +655,7 @@ if (empty($reshook)) {
 		$action = '';
 	}
 
-	if ($user->rights->adherent->supprimer && $action == 'confirm_resign') {
+	if ($user->rights->adherent->supprimer && $action == 'confirm_resiliate') {
 		$error = 0;
 
 		if ($confirm == 'yes') {
@@ -726,6 +726,77 @@ if (empty($reshook)) {
 		}
 	}
 
+	if ($user->rights->adherent->supprimer && $action == 'confirm_exclude') {
+		$error = 0;
+
+		if ($confirm == 'yes') {
+			$adht = new AdherentType($db);
+			$adht->fetch($object->typeid);
+
+			$result = $object->exclude($user);
+
+			if ($result >= 0 && !count($object->errors)) {
+				if ($object->email && GETPOST("send_mail")) {
+					$subject = '';
+					$msg = '';
+
+					// Send subscription email
+					include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
+					$formmail = new FormMail($db);
+					// Set output language
+					$outputlangs = new Translate('', $conf);
+					$outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang);
+					// Load traductions files required by page
+					$outputlangs->loadLangs(array("main", "members"));
+					// Get email content from template
+					$arraydefaultmessage = null;
+					$labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_EXCLUSION;
+
+					if (!empty($labeltouse)) {
+						$arraydefaultmessage = $formmail->getEMailTemplate($db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
+					}
+
+					if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
+						$subject = $arraydefaultmessage->topic;
+						$msg     = $arraydefaultmessage->content;
+					}
+
+					if (empty($labeltouse) || (int) $labeltouse === -1) {
+						//fallback on the old configuration.
+						setEventMessages('WarningMandatorySetupNotComplete', null, 'errors');
+						$error++;
+					} else {
+						$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
+						complete_substitutions_array($substitutionarray, $outputlangs, $object);
+						$subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs);
+						$texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnExclude()), $substitutionarray, $outputlangs);
+
+						$moreinheader = 'X-Dolibarr-Info: send_an_email by adherents/card.php'."\r\n";
+
+						$result = $object->send_an_email($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader);
+						if ($result < 0) {
+							$error++;
+							setEventMessages($object->error, $object->errors, 'errors');
+						}
+					}
+				}
+			} else {
+				$error++;
+
+				if ($object->error) {
+					setEventMessages($object->error, $object->errors, 'errors');
+				} else {
+					setEventMessages($object->error, $object->errors, 'errors');
+				}
+				$action = '';
+			}
+		}
+		if (!empty($backtopage) && !$error) {
+			header("Location: ".$backtopage);
+			exit;
+		}
+	}
+
 	// SPIP Management
 	if ($user->rights->adherent->supprimer && $action == 'confirm_del_spip' && $confirm == 'yes') {
 		if (!count($object->errors)) {
@@ -1434,8 +1505,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 			print $form->formconfirm("card.php?rowid=".$id, $langs->trans("ValidateMember"), $langs->trans("ConfirmValidateMember"), "confirm_valid", $formquestion, 'yes', 1, 220);
 		}
 
-		// Confirm terminate
-		if ($action == 'resign') {
+		// Confirm resiliate
+		if ($action == 'resiliate') {
 			$langs->load("mails");
 
 			$adht = new AdherentType($db);
@@ -1491,7 +1562,67 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 			if ($backtopage) {
 				$formquestion[] = array('type' => 'hidden', 'name' => 'backtopage', 'value' => ($backtopage != '1' ? $backtopage : $_SERVER["HTTP_REFERER"]));
 			}
-			print $form->formconfirm("card.php?rowid=".$id, $langs->trans("ResiliateMember"), $langs->trans("ConfirmResiliateMember"), "confirm_resign", $formquestion, 'no', 1, 240);
+			print $form->formconfirm("card.php?rowid=".$id, $langs->trans("ResiliateMember"), $langs->trans("ConfirmResiliateMember"), "confirm_resiliate", $formquestion, 'no', 1, 240);
+		}
+
+		// Confirm exclude
+		if ($action == 'exclude') {
+			$langs->load("mails");
+
+			$adht = new AdherentType($db);
+			$adht->fetch($object->typeid);
+
+			$subject = '';
+			$msg = '';
+
+			// Send subscription email
+			include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
+			$formmail = new FormMail($db);
+			// Set output language
+			$outputlangs = new Translate('', $conf);
+			$outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang);
+			// Load traductions files required by page
+			$outputlangs->loadLangs(array("main", "members"));
+			// Get email content from template
+			$arraydefaultmessage = null;
+			$labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_EXCLUSION;
+
+			if (!empty($labeltouse)) {
+				$arraydefaultmessage = $formmail->getEMailTemplate($db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
+			}
+
+			if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
+				$subject = $arraydefaultmessage->topic;
+				$msg     = $arraydefaultmessage->content;
+			}
+
+			$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
+			complete_substitutions_array($substitutionarray, $outputlangs, $object);
+			$subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs);
+			$texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnExclude()), $substitutionarray, $outputlangs);
+
+			$tmp = $langs->trans("SendingAnEMailToMember");
+			$tmp .= '<br>('.$langs->trans("MailFrom").': <b>'.$conf->global->ADHERENT_MAIL_FROM.'</b>, ';
+			$tmp .= $langs->trans("MailRecipient").': <b>'.$object->email.'</b>)';
+			$helpcontent = '';
+			$helpcontent .= '<b>'.$langs->trans("MailFrom").'</b>: '.$conf->global->ADHERENT_MAIL_FROM.'<br>'."\n";
+			$helpcontent .= '<b>'.$langs->trans("MailRecipient").'</b>: '.$object->email.'<br>'."\n";
+			$helpcontent .= '<b>'.$langs->trans("Subject").'</b>:<br>'."\n";
+			$helpcontent .= $subjecttosend."\n";
+			$helpcontent .= "<br>";
+			$helpcontent .= '<b>'.$langs->trans("Content").'</b>:<br>';
+			$helpcontent .= dol_htmlentitiesbr($texttosend)."\n";
+			$label = $form->textwithpicto($tmp, $helpcontent, 1, 'help');
+
+			// Create an array
+			$formquestion = array();
+			if ($object->email) {
+				$formquestion[] = array('type' => 'checkbox', 'name' => 'send_mail', 'label' => $label, 'value' => (!empty($conf->global->ADHERENT_DEFAULT_SENDINFOBYMAIL) ? 'true' : 'false'));
+			}
+			if ($backtopage) {
+				$formquestion[] = array('type' => 'hidden', 'name' => 'backtopage', 'value' => ($backtopage != '1' ? $backtopage : $_SERVER["HTTP_REFERER"]));
+			}
+			print $form->formconfirm("card.php?rowid=".$id, $langs->trans("ExcludeMember"), $langs->trans("ConfirmExcludeMember"), "confirm_exclude", $formquestion, 'no', 1, 240);
 		}
 
 		// Confirm remove member
@@ -1584,12 +1715,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 			} elseif (!$adht->subscription) {
 				print $langs->trans("SubscriptionNotRecorded");
 				if ($object->statut > 0) {
-					print " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
+					print " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft, not excluded and not resiliated
 				}
 			} else {
 				print $langs->trans("SubscriptionNotReceived");
 				if ($object->statut > 0) {
-					print " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
+					print " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft, not excluded and not resiliated
 				}
 			}
 		}
@@ -1699,7 +1830,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 				// Send
 				if (empty($user->socid)) {
 					if ($object->statut == 1) {
-						print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendMail').'</a></div>';
+						print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendMail').'</a></div>'."\n";
 					}
 				}
 
@@ -1725,35 +1856,44 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 
 				// Modify
 				if ($user->rights->adherent->creer) {
-					print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=edit">'.$langs->trans("Modify")."</a></div>";
+					print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=edit">'.$langs->trans("Modify").'</a></div>'."\n";
 				} else {
-					print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Modify").'</font></div>';
+					print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Modify").'</font></div>'."\n";
 				}
 
 				// Validate
 				if ($object->statut == -1) {
 					if ($user->rights->adherent->creer) {
-						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=valid">'.$langs->trans("Validate")."</a></div>\n";
+						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=valid">'.$langs->trans("Validate").'</a></div>'."\n";
 					} else {
-						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Validate").'</font></div>';
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Validate").'</font></div>'."\n";
 					}
 				}
 
 				// Reactivate
-				if ($object->statut == 0) {
+				if ($object->statut == 0 || $object->statut == -2) {
 					if ($user->rights->adherent->creer) {
 						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=valid">'.$langs->trans("Reenable")."</a></div>\n";
 					} else {
-						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Reenable")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Reenable").'</font></div>'."\n";
+					}
+				}
+
+				// Resiliate
+				if ($object->statut >= 1) {
+					if ($user->rights->adherent->supprimer) {
+						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=resiliate">'.$langs->trans("Resiliate")."</a></div>\n";
+					} else {
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Resiliate").'</font></div>'."\n";
 					}
 				}
 
-				// Terminate
+				// Exclude
 				if ($object->statut >= 1) {
 					if ($user->rights->adherent->supprimer) {
-						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=resign">'.$langs->trans("Resiliate")."</a></div>\n";
+						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$id.'&action=exclude">'.$langs->trans("Exclude")."</a></div>\n";
 					} else {
-						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Resiliate")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Exclude").'</font></div>'."\n";
 					}
 				}
 
@@ -1761,12 +1901,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 				if (!empty($conf->societe->enabled) && !$object->socid) {
 					if ($user->rights->societe->creer) {
 						if ($object->statut != -1) {
-							print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$object->id.'&amp;action=create_thirdparty">'.$langs->trans("CreateDolibarrThirdParty").'</a></div>';
+							print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$object->id.'&amp;action=create_thirdparty">'.$langs->trans("CreateDolibarrThirdParty").'</a></div>'."\n";;
 						} else {
-							print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrThirdParty").'</a></div>';
+							print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrThirdParty").'</a></div>'."\n";
 						}
 					} else {
-						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrThirdParty")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrThirdParty").'</font></div>'."\n";
 					}
 				}
 
@@ -1774,12 +1914,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 				if (!$user->socid && !$object->user_id) {
 					if ($user->rights->user->user->creer) {
 						if ($object->statut != -1) {
-							print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$object->id.'&amp;action=create_user">'.$langs->trans("CreateDolibarrLogin").'</a></div>';
+							print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?rowid='.$object->id.'&amp;action=create_user">'.$langs->trans("CreateDolibarrLogin").'</a></div>'."\n";
 						} else {
-							print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrLogin").'</a></div>';
+							print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("ValidateBefore")).'">'.$langs->trans("CreateDolibarrLogin").'</a></div>'."\n";
 						}
 					} else {
-						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrLogin")."</font></div>";
+						print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("CreateDolibarrLogin").'</font></div>'."\n";
 					}
 				}
 
@@ -1788,18 +1928,18 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 					$isinspip = $mailmanspip->is_in_spip($object);
 
 					if ($isinspip == 1) {
-						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$object->id.'&action=del_spip">'.$langs->trans("DeleteIntoSpip")."</a></div>\n";
+						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$object->id.'&action=del_spip">'.$langs->trans("DeleteIntoSpip").'</a></div>'."\n";
 					}
 					if ($isinspip == 0) {
-						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$object->id.'&action=add_spip">'.$langs->trans("AddIntoSpip")."</a></div>\n";
+						print '<div class="inline-block divButAction"><a class="butAction" href="card.php?rowid='.$object->id.'&action=add_spip">'.$langs->trans("AddIntoSpip").'</a></div>'."\n";
 					}
 				}
 
 				// Delete
 				if ($user->rights->adherent->supprimer) {
-					print '<div class="inline-block divButAction"><a class="butActionDelete" href="card.php?rowid='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete")."</a></div>\n";
+					print '<div class="inline-block divButAction"><a class="butActionDelete" href="card.php?rowid='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a></div>'."\n";
 				} else {
-					print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Delete")."</font></div>";
+					print '<div class="inline-block divButAction"><font class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("Delete").'</font></div>'."\n";
 				}
 			}
 		}

+ 58 - 5
htdocs/adherents/class/adherent.class.php

@@ -206,7 +206,7 @@ class Adherent extends CommonObject
 
 	public $public;
 
-	// -1:brouillon, 0:resilie, >=1:valide,paye
+	// -2:exclu, -1:brouillon, 0:resilie, >=1:valide,paye
 	// def in common object
 	//public $status;
 
@@ -326,7 +326,7 @@ class Adherent extends CommonObject
 		'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 190),
 		'canvas' => array('type' => 'varchar(32)', 'label' => 'Canvas', 'enabled' => 1, 'visible' => -1, 'position' => 195),
 		'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 500,
-		'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', -1 => 'MemberStatusResiliatedShort')),
+		'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', -1 => 'MemberStatusResiliatedShort', -2 => 'MemberStatusExcludedShort')),
 		'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 800),
 		'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 805)
 	);
@@ -1141,7 +1141,7 @@ class Adherent extends CommonObject
 		$this->db->begin();
 
 		// If user is linked to this member, remove old link to this member
-		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".$this->id;
+		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".((int) $this->id);
 		dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
 		$resql = $this->db->query($sql);
 		if (!$resql) {
@@ -1152,7 +1152,7 @@ class Adherent extends CommonObject
 
 		// Set link to user
 		if ($userid > 0) {
-			$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".$this->id;
+			$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".((int) $this->id);
 			$sql .= " WHERE rowid = ".$userid;
 			dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
 			$resql = $this->db->query($sql);
@@ -1917,6 +1917,55 @@ class Adherent extends CommonObject
 		}
 	}
 
+	/**
+	 *		Functiun to exlude (set adherent.status to -2) a member
+	 *		TODO
+	 *		A private note should be added to know why the member has been excluded
+	 *		For historical purpose it add an "extra-subscription" type excluded
+	 *
+	 *		@param	User	$user		User making change
+	 *		@return	int					<0 if KO, >0 if OK
+	 */
+	public function exclude($user)
+	{
+		global $langs, $conf;
+
+		$error = 0;
+
+		// Check parameters
+		if ($this->statut == 0) {
+			dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
+			return 0;
+		}
+
+		$this->db->begin();
+
+		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
+		$sql .= " statut = -2";
+		$sql .= ", fk_user_valid=".$user->id;
+		$sql .= " WHERE rowid = ".$this->id;
+
+		$result = $this->db->query($sql);
+		if ($result) {
+			$this->statut = 0;
+
+			// Call trigger
+			$result = $this->call_trigger('MEMBER_EXCLUDE', $user);
+			if ($result < 0) {
+				$error++;
+				$this->db->rollback();
+				return -1;
+			}
+			// End call triggers
+
+			$this->db->commit();
+			return 1;
+		} else {
+			$this->error = $this->db->error();
+			$this->db->rollback();
+			return -1;
+		}
+	}
 
 	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
 	/**
@@ -2173,7 +2222,7 @@ class Adherent extends CommonObject
 	}
 
 	/**
-	 *  Retourne le libelle du statut d'un adherent (brouillon, valide, resilie)
+	 *  Retourne le libelle du statut d'un adherent (brouillon, valide, resilie, exclu)
 	 *
 	 *  @param	int		$mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
 	 *  @return string				Label
@@ -2229,6 +2278,10 @@ class Adherent extends CommonObject
 			$statusType = 'status6';
 			$labelStatus = $langs->trans("MemberStatusResiliated");
 			$labelStatusShort = $langs->trans("MemberStatusResiliatedShort");
+		} elseif ($status == -2) {
+			$statusType = 'status10';
+			$labelStatus = $langs->trans("MemberStatusExcluded");
+			$labelStatusShort = $langs->trans("MemberStatusExcludedShort");
 		}
 
 		return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);

+ 21 - 3
htdocs/adherents/class/adherent_type.class.php

@@ -103,6 +103,9 @@ class AdherentType extends CommonObject
 	/** @var string Email sent after resiliation */
 	public $mail_resiliate = '';
 
+	/** @var string Email sent after exclude */
+	public $mail_exclude = '';
+
 	/** @var array Array of members */
 	public $members = array();
 
@@ -173,7 +176,7 @@ class AdherentType extends CommonObject
 				$sql = "SELECT rowid";
 				$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type_lang";
 				$sql .= " WHERE fk_type=".$this->id;
-				$sql .= " AND lang='".$key."'";
+				$sql .= " AND lang = '".$this->db->escape($key)."'";
 
 				$result = $this->db->query($sql);
 
@@ -199,7 +202,7 @@ class AdherentType extends CommonObject
 				$sql = "SELECT rowid";
 				$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type_lang";
 				$sql .= " WHERE fk_type=".$this->id;
-				$sql .= " AND lang='".$key."'";
+				$sql .= " AND lang = '".$this->db->escape($key)."'";
 
 				$result = $this->db->query($sql);
 
@@ -549,7 +552,7 @@ class AdherentType extends CommonObject
 		$sql = "SELECT a.rowid";
 		$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
 		$sql .= " WHERE a.entity IN (".getEntity('member').")";
-		$sql .= " AND a.fk_adherent_type = ".$this->id;
+		$sql .= " AND a.fk_adherent_type = ".((int) $this->id);
 		if (!empty($excludefilter)) {
 			$sql .= ' AND ('.$excludefilter.')';
 		}
@@ -820,4 +823,19 @@ class AdherentType extends CommonObject
 
 		return '';
 	}
+
+	/**
+	 *     getMailOnExclude
+	 *
+	 *     @return string     Return mail model content of type or empty
+	 */
+	public function getMailOnExclude()
+	{
+		// NOTE mail_exclude not defined so never used
+		if (!empty($this->mail_exclude) && trim(dol_htmlentitiesbr_decode($this->mail_exclude))) {  // Property not yet defined
+			return $this->mail_exclude;
+		}
+
+		return '';
+	}
 }

+ 6 - 1
htdocs/adherents/class/api_members.class.php

@@ -329,7 +329,7 @@ class Members extends DolibarrApi
 				continue;
 			}
 			// Process the status separately because it must be updated using
-			// the validate() and resiliate() methods of the class Adherent.
+			// the validate(), resiliate() and exclude() methods of the class Adherent.
 			if ($field == 'statut') {
 				if ($value == '0') {
 					$result = $member->resiliate(DolibarrApiAccess::$user);
@@ -341,6 +341,11 @@ class Members extends DolibarrApi
 					if ($result < 0) {
 						throw new RestException(500, 'Error when validating member: '.$member->error);
 					}
+				} elseif ($value == '-2') {
+					$result = $member->exclude(DolibarrApiAccess::$user);
+					if ($result < 0) {
+						throw new RestException(500, 'Error when excluding member: '.$member->error);
+					}
 				}
 			} else {
 				$member->$field = $value;

+ 1 - 1
htdocs/adherents/class/api_memberstypes.class.php

@@ -194,7 +194,7 @@ class MembersTypes extends DolibarrApi
 				continue;
 			}
 			// Process the status separately because it must be updated using
-			// the validate() and resiliate() methods of the class AdherentType.
+			// the validate(), resiliate() and exclude() methods of the class AdherentType.
 			$membertype->$field = $value;
 		}
 

+ 16 - 245
htdocs/adherents/index.php

@@ -1,8 +1,8 @@
 <?php
 /* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
- * Copyright (C) 2003		Jean-Louis Bergamo	<jlb@j1b.org>
- * Copyright (C) 2004-2020	Laurent Destailleur	<eldy@users.sourceforge.net>
- * Copyright (C) 2005-2012	Regis Houssin		<regis.houssin@inodbox.com>
+ * Copyright (C) 2003		Jean-Louis Bergamo		<jlb@j1b.org>
+ * Copyright (C) 2004-2020	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2005-2012	Regis Houssin			<regis.houssin@inodbox.com>
  * Copyright (C) 2019       Nicolas ZABOURI         <info@inovea-conseil.com>
  * Copyright (C) 2021		Frédéric France			<frederic.france@netlgic.fr>
  *
@@ -82,6 +82,7 @@ print load_fiche_titre($langs->trans("MembersArea"), $resultboxes['selectboxlist
 $MembersValidated = array();
 $MembersToValidate = array();
 $MembersUpToDate = array();
+$MembersExcluded = array();
 $MembersResiliated = array();
 
 $AdherentType = array();
@@ -116,6 +117,9 @@ if ($result) {
 		if ($objp->statut == 1) {
 			$MembersValidated[$objp->rowid] = $objp->somme;
 		}
+		if ($objp->statut == -2) {
+			$MembersExcluded[$objp->rowid] = $objp->somme;
+		}
 		if ($objp->statut == 0) {
 			$MembersResiliated[$objp->rowid] = $objp->somme;
 		}
@@ -195,9 +199,10 @@ if ($conf->use_javascript_ajax) {
 
 	$SumToValidate = 0;
 	$SumValidated = 0;
-
 	$SumUpToDate = 0;
 	$SumResiliated = 0;
+	$SumExcluded = 0;
+
 	$total = 0;
 	$dataval = array();
 	$i = 0;
@@ -205,17 +210,21 @@ if ($conf->use_javascript_ajax) {
 		$dataval['draft'][] = array($i, isset($MembersToValidate[$key]) ? $MembersToValidate[$key] : 0);
 		$dataval['notuptodate'][] = array($i, isset($MembersValidated[$key]) ? $MembersValidated[$key] - (isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0) : 0);
 		$dataval['uptodate'][] = array($i, isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0);
+		$dataval['excluded'][] = array($i, isset($MembersExcluded[$key]) ? $MembersExcluded[$key] : 0);
 		$dataval['resiliated'][] = array($i, isset($MembersResiliated[$key]) ? $MembersResiliated[$key] : 0);
+
 		$SumToValidate += isset($MembersToValidate[$key]) ? $MembersToValidate[$key] : 0;
 		$SumValidated += isset($MembersValidated[$key]) ? $MembersValidated[$key] - (isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0) : 0;
 		$SumUpToDate += isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0;
+		$SumExcluded += isset($MembersExcluded[$key]) ? $MembersExcluded [$key] : 0;
 		$SumResiliated += isset($MembersResiliated[$key]) ? $MembersResiliated[$key] : 0;
 		$i++;
 	}
-	$total = $SumToValidate + $SumValidated + $SumUpToDate + $SumResiliated;
+	$total = $SumToValidate + $SumValidated + $SumUpToDate + $SumExcluded + $SumResiliated;
 	$dataseries = array();
 	$dataseries[] = array($langs->transnoentitiesnoconv("OutOfDate"), round($SumValidated));
 	$dataseries[] = array($langs->transnoentitiesnoconv("UpToDate"), round($SumUpToDate));
+	$dataseries[] = array($langs->transnoentitiesnoconv("MembersStatusExcluded"), round($SumExcluded));
 	$dataseries[] = array($langs->transnoentitiesnoconv("MembersStatusResiliated"), round($SumResiliated));
 	$dataseries[] = array($langs->transnoentitiesnoconv("MembersStatusToValid"), round($SumToValidate));
 
@@ -224,7 +233,7 @@ if ($conf->use_javascript_ajax) {
 	include_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
 	$dolgraph = new DolGraph();
 	$dolgraph->SetData($dataseries);
-	$dolgraph->SetDataColor(array($badgeStatus1, $badgeStatus4, $badgeStatus6, '-'.$badgeStatus0));
+	$dolgraph->SetDataColor(array($badgeStatus1, $badgeStatus4, '-'.$badgeStatus8, $badgeStatus6, '-'.$badgeStatus0));
 	$dolgraph->setShowLegend(2);
 	$dolgraph->setShowPercent(1);
 	$dolgraph->SetType(array('pie'));
@@ -234,7 +243,7 @@ if ($conf->use_javascript_ajax) {
 
 	$boxgraph .= '</td></tr>';
 	$boxgraph .= '<tr class="liste_total"><td>'.$langs->trans("Total").'</td><td class="right">';
-	$boxgraph .= $SumToValidate + $SumValidated + $SumUpToDate + $SumResiliated;
+	$boxgraph .= $SumToValidate + $SumValidated + $SumUpToDate + $SumExcluded + $SumResiliated;
 	$boxgraph .= '</td></tr>';
 	$boxgraph .= '</table>';
 	$boxgraph .= '</div>';
@@ -251,250 +260,12 @@ print '<div class="firstcolumn fichehalfleft boxhalfleft" id="boxhalfleft">';
 print $searchbox;
 print $boxgraph;
 
-// List of subscription by year
-$Total = array();
-$Number = array();
-$tot = 0;
-$numb = 0;
-
-$sql = "SELECT c.subscription, c.dateadh as dateh";
-$sql .= " FROM ".MAIN_DB_PREFIX."adherent as d, ".MAIN_DB_PREFIX."subscription as c";
-$sql .= " WHERE d.entity IN (".getEntity('adherent').")";
-$sql .= " AND d.rowid = c.fk_adherent";
-
-
-$result = $db->query($sql);
-if ($result) {
-	$num = $db->num_rows($result);
-	$i = 0;
-	while ($i < $num) {
-		$objp = $db->fetch_object($result);
-		$year = dol_print_date($db->jdate($objp->dateh), "%Y");
-		$Total[$year] = (isset($Total[$year]) ? $Total[$year] : 0) + $objp->subscription;
-		$Number[$year] = (isset($Number[$year]) ? $Number[$year] : 0) + 1;
-		$tot += $objp->subscription;
-		$numb += 1;
-		$i++;
-	}
-}
-
-print '<div class="div-table-responsive-no-min">';
-print '<table class="noborder centpercent">';
-print '<tr class="liste_titre">';
-print '<th>'.$langs->trans("Year").'</th>';
-print '<th class="right">'.$langs->trans("Subscriptions").'</th>';
-print '<th class="right">'.$langs->trans("AmountTotal").'</th>';
-print '<th class="right">'.$langs->trans("AmountAverage").'</th>';
-print "</tr>\n";
-
-krsort($Total);
-$i = 0;
-foreach ($Total as $key=>$value) {
-	if ($i >= 8) {
-		print '<tr class="oddeven">';
-		print "<td>...</td>";
-		print "<td class=\"right\"></td>";
-		print "<td class=\"right\"></td>";
-		print "<td class=\"right\"></td>";
-		print "</tr>\n";
-		break;
-	}
-	print '<tr class="oddeven">';
-	print "<td><a href=\"./subscription/list.php?date_select=$key\">$key</a></td>";
-	print "<td class=\"right\">".$Number[$key]."</td>";
-	print "<td class=\"right\">".price($value)."</td>";
-	print "<td class=\"right\">".price(price2num($value / $Number[$key], 'MT'))."</td>";
-	print "</tr>\n";
-	$i++;
-}
-
-// Total
-print '<tr class="liste_total">';
-print '<td>'.$langs->trans("Total").'</td>';
-print "<td class=\"right\">".$numb."</td>";
-print '<td class="right">'.price($tot)."</td>";
-print "<td class=\"right\">".price(price2num($numb > 0 ? ($tot / $numb) : 0, 'MT'))."</td>";
-print "</tr>\n";
-print "</table></div>";
-
-print "<br>\n";
-
 print $resultboxes['boxlista'];
 
 print '</div>'."\n";
 
 print '<div class="secondcolumn fichehalfright boxhalfright" id="boxhalfright">';
 
-/*
- * Latest modified members
- */
-$max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT;
-
-$sql = "SELECT a.rowid, a.statut as status, a.lastname, a.firstname, a.societe as company, a.fk_soc,";
-$sql .= " a.gender, a.email, a.photo, a.morphy,";
-$sql .= " a.tms as datem, a.datefin as date_end_subscription,";
-$sql .= " ta.rowid as typeid, ta.libelle as label, ta.subscription as need_subscription";
-$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a, ".MAIN_DB_PREFIX."adherent_type as ta";
-$sql .= " WHERE a.entity IN (".getEntity('adherent').")";
-$sql .= " AND a.fk_adherent_type = ta.rowid";
-$sql .= $db->order("a.tms", "DESC");
-$sql .= $db->plimit($max, 0);
-
-$resql = $db->query($sql);
-if ($resql) {
-	print '<div class="div-table-responsive-no-min">';
-	print '<table class="noborder centpercent">';
-	print '<tr class="liste_titre">';
-	print '<th colspan="4">'.$langs->trans("LastMembersModified", $max).'</th></tr>';
-
-	$num = $db->num_rows($resql);
-	if ($num) {
-		$i = 0;
-		while ($i < $num) {
-			$obj = $db->fetch_object($resql);
-
-			$staticmember->id = $obj->rowid;
-			$staticmember->ref = $obj->rowid;
-			$staticmember->lastname = $obj->lastname;
-			$staticmember->firstname = $obj->firstname;
-			$staticmember->gender = $obj->gender;
-			$staticmember->email = $obj->email;
-			$staticmember->photo = $obj->photo;
-			$staticmember->morphy = $obj->morphy;
-			$staticmember->statut = $obj->status;
-			$staticmember->need_subscription = $obj->need_subscription;
-			$staticmember->datefin = $db->jdate($obj->date_end_subscription);
-			if (!empty($obj->fk_soc)) {
-				$staticmember->fk_soc = $obj->fk_soc;
-				$staticmember->fetch_thirdparty();
-				$staticmember->name = $staticmember->thirdparty->name;
-			} else {
-				$staticmember->name = $obj->company;
-			}
-
-			$statictype->id = $obj->typeid;
-			$statictype->label = $obj->label;
-			$statictype->subscription = $obj->need_subscription;
-
-			print '<tr class="oddeven">';
-			print '<td class="nowraponall">'.$staticmember->getNomUrl(-1, 32).'</td>';
-			print '<td>'.$statictype->getNomUrl(1, 32).'</td>';
-			print '<td>'.dol_print_date($db->jdate($obj->datem), 'dayhour').'</td>';
-			print '<td class="right">'.$staticmember->getLibStatut(3).'</td>';
-			print '</tr>';
-			$i++;
-		}
-	}
-	print "</table></div>";
-	print "<br>";
-} else {
-	dol_print_error($db);
-}
-
-
-/*
- * Last modified subscriptions
- */
-$max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT;
-
-$sql = "SELECT a.rowid, a.statut as status, a.lastname, a.firstname, a.societe as company, a.fk_soc,";
-$sql .= " a.gender, a.email, a.photo, a.morphy,";
-$sql .= " a.datefin as date_end_subscription,";
-$sql .= " ta.rowid as typeid, ta.libelle as label, ta.subscription as need_subscription,";
-$sql .= " c.rowid as cid, c.tms as datem, c.datec as datec, c.dateadh as date_start, c.datef as date_end, c.subscription";
-$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a, ".MAIN_DB_PREFIX."adherent_type as ta, ".MAIN_DB_PREFIX."subscription as c";
-$sql .= " WHERE a.entity IN (".getEntity('adherent').")";
-$sql .= " AND a.fk_adherent_type = ta.rowid";
-$sql .= " AND c.fk_adherent = a.rowid";
-$sql .= $db->order("c.tms", "DESC");
-$sql .= $db->plimit($max, 0);
-
-$resql = $db->query($sql);
-if ($resql) {
-	print '<div class="div-table-responsive-no-min">';
-	print '<table class="noborder centpercent">';
-	print '<tr class="liste_titre">';
-	print '<th colspan="5">'.$langs->trans("LastSubscriptionsModified", $max).'</th></tr>';
-
-	$num = $db->num_rows($resql);
-	if ($num) {
-		$i = 0;
-		while ($i < $num) {
-			$obj = $db->fetch_object($resql);
-
-			$staticmember->id = $obj->rowid;
-			$staticmember->ref = $obj->rowid;
-			$staticmember->lastname = $obj->lastname;
-			$staticmember->firstname = $obj->firstname;
-			$staticmember->gender = $obj->gender;
-			$staticmember->email = $obj->email;
-			$staticmember->photo = $obj->photo;
-			$staticmember->morphy = $obj->morphy;
-			$staticmember->statut = $obj->status;
-			$staticmember->need_subscription = $obj->need_subscription;
-			$staticmember->datefin = $db->jdate($obj->date_end_subscription);
-			if (!empty($obj->fk_soc)) {
-				$staticmember->fk_soc = $obj->fk_soc;
-				$staticmember->fetch_thirdparty();
-				$staticmember->name = $staticmember->thirdparty->name;
-			} else {
-				$staticmember->name = $obj->company;
-			}
-
-			$subscriptionstatic->id = $obj->cid;
-			$subscriptionstatic->ref = $obj->cid;
-
-			print '<tr class="oddeven">';
-			print '<td class="nowraponall">'.$subscriptionstatic->getNomUrl(1).'</td>';
-			print '<td class="nowraponall">'.$staticmember->getNomUrl(-1, 32, 'subscription').'</td>';
-			print '<td class="nowraponall">'.get_date_range($db->jdate($obj->date_start), $db->jdate($obj->date_end)).'</td>';
-			print '<td class="right">'.price($obj->subscription).'</td>';
-			//print '<td class="right">'.$staticmember->LibStatut($obj->statut,($obj->subscription=='yes'?1:0),$db->jdate($obj->date_end_subscription),5).'</td>';
-			print '<td class="right nowraponall">'.dol_print_date($db->jdate($obj->datem ? $obj->datem : $obj->datec), 'dayhour').'</td>';
-			print '</tr>';
-			$i++;
-		}
-	}
-	print "</table></div>";
-	print "<br>";
-} else {
-	dol_print_error($db);
-}
-
-
-// Summary of members by type
-print '<div class="div-table-responsive-no-min">';
-print '<table class="noborder centpercent">';
-print '<tr class="liste_titre">';
-print '<th>'.$langs->trans("MembersTypes").'</th>';
-print '<th class=right>'.$langs->trans("MembersStatusToValid").'</th>';
-print '<th class=right>'.$langs->trans("OutOfDate").'</th>';
-print '<th class=right>'.$langs->trans("UpToDate").'</th>';
-print '<th class=right>'.$langs->trans("MembersStatusResiliated").'</th>';
-print "</tr>\n";
-
-foreach ($AdherentType as $key => $adhtype) {
-	print '<tr class="oddeven">';
-	print '<td>'.$adhtype->getNomUrl(1, dol_size(32)).'</td>';
-	print '<td class="right">'.(isset($MembersToValidate[$key]) && $MembersToValidate[$key] > 0 ? $MembersToValidate[$key] : '').' '.$staticmember->LibStatut(-1, $adhtype->subscription, 0, 3).'</td>';
-	print '<td class="right">'.(isset($MembersValidated[$key]) && ($MembersValidated[$key] - (isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0) > 0) ? $MembersValidated[$key] - (isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0) : '').' '.$staticmember->LibStatut(1, $adhtype->subscription, 0, 3).'</td>';
-	print '<td class="right">'.(isset($MembersUpToDate[$key]) && $MembersUpToDate[$key] > 0 ? $MembersUpToDate[$key] : '').' '.$staticmember->LibStatut(1, $adhtype->subscription, $now, 3).'</td>';
-	print '<td class="right">'.(isset($MembersResiliated[$key]) && $MembersResiliated[$key] > 0 ? $MembersResiliated[$key] : '').' '.$staticmember->LibStatut(0, $adhtype->subscription, 0, 3).'</td>';
-	print "</tr>\n";
-}
-print '<tr class="liste_total">';
-print '<td class="liste_total">'.$langs->trans("Total").'</td>';
-print '<td class="liste_total right">'.$SumToValidate.' '.$staticmember->LibStatut(-1, $adhtype->subscription, 0, 3).'</td>';
-print '<td class="liste_total right">'.$SumValidated.' '.$staticmember->LibStatut(1, $adhtype->subscription, 0, 3).'</td>';
-print '<td class="liste_total right">'.$SumUpToDate.' '.$staticmember->LibStatut(1, $adhtype->subscription, $now, 3).'</td>';
-print '<td class="liste_total right">'.$SumResiliated.' '.$staticmember->LibStatut(0, $adhtype->subscription, 0, 3).'</td>';
-print '</tr>';
-
-print "</table>\n";
-print "</div>";
-
-print '<br>';
-
 print $resultboxes['boxlistb'];
 
 print '</div>'."\n";

+ 10 - 6
htdocs/adherents/list.php

@@ -76,7 +76,7 @@ if ($statut != '') {
 
 $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
 
-if ($search_status < -1) {
+if ($search_status < -2) {
 	$search_status = '';
 }
 
@@ -302,13 +302,13 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on (s.rowid = d.fk_soc)";
 $sql .= ", ".MAIN_DB_PREFIX."adherent_type as t";
 $sql .= " WHERE d.fk_adherent_type = t.rowid ";
 if ($catid > 0) {
-	$sql .= " AND cm.fk_categorie = ".$db->escape($catid);
+	$sql .= " AND cm.fk_categorie = ".((int) $catid);
 }
 if ($catid == -2) {
 	$sql .= " AND cm.fk_categorie IS NULL";
 }
 if ($search_categ > 0) {
-	$sql .= " AND cm.fk_categorie = ".$db->escape($search_categ);
+	$sql .= " AND cm.fk_categorie = ".((int) $search_categ);
 }
 if ($search_categ == -2) {
 	$sql .= " AND cm.fk_categorie IS NULL";
@@ -379,7 +379,7 @@ if ($search_phone_mobile) {
 	$sql .= natural_search("d.phone_mobile", $search_phone_mobile);
 }
 if ($search_country) {
-	$sql .= " AND d.country IN (".$search_country.')';
+	$sql .= " AND d.country IN (".$db->sanitize($search_country).')';
 }
 
 // Add where from extra fields
@@ -452,6 +452,9 @@ if (GETPOSTISSET("search_status")) {
 	if ($search_status == '0') {
 		$titre = $langs->trans("MembersListResiliated");
 	}
+	if ($search_status == '-2') {
+		$titre = $langs->trans("MembersListExcluded");
+	}
 } elseif ($action == 'search') {
 	$titre = $langs->trans("MembersListQualified");
 }
@@ -750,9 +753,10 @@ if (!empty($arrayfields['d.statut']['checked'])) {
 	$liststatus = array(
 		'-1'=>$langs->trans("Draft"),
 		'1'=>$langs->trans("Validated"),
-		'0'=>$langs->trans("Resiliated")
+		'0'=>$langs->trans("Resiliated"),
+		'-2'=>$langs->trans("Excluded")
 	);
-	print $form->selectarray('search_status', $liststatus, $search_status, -2);
+	print $form->selectarray('search_status', $liststatus, $search_status, -3);
 	print '</td>';
 }
 // Action column

+ 28 - 27
htdocs/adherents/subscription.php

@@ -44,6 +44,7 @@ $action = GETPOST('action', 'aZ09');
 $confirm = GETPOST('confirm', 'alpha');
 $rowid = GETPOST('rowid', 'int') ?GETPOST('rowid', 'int') : GETPOST('id', 'int');
 $typeid = GETPOST('typeid', 'int');
+$cancel = GETPOST('cancel');
 
 // Load variable for pagination
 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
@@ -148,19 +149,18 @@ if (empty($reshook) && $action == 'confirm_create_thirdparty' && $confirm == 'ye
 if (empty($reshook) && $action == 'setuserid' && ($user->rights->user->self->creer || $user->rights->user->user->creer)) {
 	$error = 0;
 	if (empty($user->rights->user->user->creer)) {    // If can edit only itself user, we can link to itself only
-		if ($_POST["userid"] != $user->id && $_POST["userid"] != $object->user_id) {
+		if (GETPOST("userid", 'int') != $user->id && GETPOST("userid", 'int') != $object->user_id) {
 			$error++;
 			setEventMessages($langs->trans("ErrorUserPermissionAllowsToLinksToItselfOnly"), null, 'errors');
 		}
 	}
 
 	if (!$error) {
-		if ($_POST["userid"] != $object->user_id) {  // If link differs from currently in database
-			$result = $object->setUserId($_POST["userid"]);
+		if (GETPOST("userid", 'int') != $object->user_id) {  // If link differs from currently in database
+			$result = $object->setUserId(GETPOST("userid", 'int'));
 			if ($result < 0) {
 				dol_print_error('', $object->error);
 			}
-			$_POST['action'] = '';
 			$action = '';
 		}
 	}
@@ -190,14 +190,13 @@ if (empty($reshook) && $action == 'setsocid') {
 				if ($result < 0) {
 					dol_print_error('', $object->error);
 				}
-				$_POST['action'] = '';
 				$action = '';
 			}
 		}
 	}
 }
 
-if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && !$_POST["cancel"]) {
+if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && !$cancel) {
 	$error = 0;
 
 	$langs->load("banks");
@@ -209,25 +208,25 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && !
 	$datesubscription = 0;
 	$datesubend = 0;
 	$paymentdate = 0;
-	if ($_POST["reyear"] && $_POST["remonth"] && $_POST["reday"]) {
-		$datesubscription = dol_mktime(0, 0, 0, $_POST["remonth"], $_POST["reday"], $_POST["reyear"]);
+	if (GETPOST("reyear", "int") && GETPOST("remonth", "int") && GETPOST("reday", "int")) {
+		$datesubscription = dol_mktime(0, 0, 0, GETPOST("remonth", "int"), GETPOST("reday", "int"), GETPOST("reyear", "int"));
 	}
-	if ($_POST["endyear"] && $_POST["endmonth"] && $_POST["endday"]) {
-		$datesubend = dol_mktime(0, 0, 0, $_POST["endmonth"], $_POST["endday"], $_POST["endyear"]);
+	if (GETPOST("endyear", 'int') && GETPOST("endmonth", 'int') && GETPOST("endday", 'int')) {
+		$datesubend = dol_mktime(0, 0, 0, GETPOST("endmonth", 'int'), GETPOST("endday", 'int'), GETPOST("endyear", 'int'));
 	}
-	if ($_POST["paymentyear"] && $_POST["paymentmonth"] && $_POST["paymentday"]) {
-		$paymentdate = dol_mktime(0, 0, 0, $_POST["paymentmonth"], $_POST["paymentday"], $_POST["paymentyear"]);
+	if (GETPOST("paymentyear", 'int') && GETPOST("paymentmonth", 'int') && GETPOST("paymentday", 'int')) {
+		$paymentdate = dol_mktime(0, 0, 0, GETPOST("paymentmonth", 'int'), GETPOST("paymentday", 'int'), GETPOST("paymentyear", 'int'));
 	}
 	$amount = price2num(GETPOST("subscription", 'alpha')); // Amount of subscription
-	$label = $_POST["label"];
+	$label = GETPOST("label");
 
 	// Payment informations
-	$accountid = $_POST["accountid"];
-	$operation = $_POST["operation"]; // Payment mode
+	$accountid = GETPOST("accountid", 'int');
+	$operation = GETPOST("operation", "alphanohtml"); // Payment mode
 	$num_chq = GETPOST("num_chq", "alphanohtml");
-	$emetteur_nom = $_POST["chqemetteur"];
-	$emetteur_banque = $_POST["chqbank"];
-	$option = $_POST["paymentsave"];
+	$emetteur_nom = GETPOST("chqemetteur");
+	$emetteur_banque = GETPOST("chqbank");
+	$option = GETPOST("paymentsave");
 	if (empty($option)) {
 		$option = 'none';
 	}
@@ -267,19 +266,19 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && !
 			$error++;
 			$action = 'addsubscription';
 		} else {
-			if (!empty($conf->banque->enabled) && $_POST["paymentsave"] != 'none') {
-				if ($_POST["subscription"]) {
-					if (!$_POST["label"]) {
+			if (!empty($conf->banque->enabled) && GETPOST("paymentsave") != 'none') {
+				if (GETPOST("subscription")) {
+					if (!GETPOST("label")) {
 						$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Label"));
 					}
-					if ($_POST["paymentsave"] != 'invoiceonly' && !$_POST["operation"]) {
+					if (GETPOST("paymentsave") != 'invoiceonly' && !GETPOST("operation")) {
 						$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode"));
 					}
-					if ($_POST["paymentsave"] != 'invoiceonly' && !($_POST["accountid"] > 0)) {
+					if (GETPOST("paymentsave") != 'invoiceonly' && !(GETPOST("accountid", 'int') > 0)) {
 						$errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("FinancialAccount"));
 					}
 				} else {
-					if ($_POST["accountid"]) {
+					if (GETPOST("accountid")) {
 						$errmsg = $langs->trans("ErrorDoNotProvideAccountsIfNullAmount");
 					}
 				}
@@ -453,7 +452,8 @@ if ($optioncss != '') {
 if ($rowid > 0) {
 	$res = $object->fetch($rowid);
 	if ($res < 0) {
-		dol_print_error($db, $object->error); exit;
+		dol_print_error($db, $object->error);
+		exit;
 	}
 
 	$adht->fetch($object->typeid);
@@ -645,7 +645,7 @@ if ($rowid > 0) {
 	 * Action bar
 	 */
 
-	// Button to create a new subscription if member no draft neither resiliated
+	// Button to create a new subscription if member no draft (-1) neither resiliated (0) neither excluded (-2)
 	if ($user->rights->adherent->cotisation->creer) {
 		if ($action != 'addsubscription' && $action != 'create_thirdparty') {
 			print '<div class="tabsAction">';
@@ -847,7 +847,7 @@ if ($rowid > 0) {
 						});
 						';
 			if (GETPOST('paymentsave')) {
-				print '$("#'.GETPOST('paymentsave').'").prop("checked",true);';
+				print '$("#'.GETPOST('paymentsave', 'aZ09').'").prop("checked", true);';
 			}
 			print '});';
 			print '</script>'."\n";
@@ -1038,6 +1038,7 @@ if ($rowid > 0) {
 
 				// Bank account
 				print '<tr class="bankswitchclass"><td class="fieldrequired">'.$langs->trans("FinancialAccount").'</td><td>';
+				print img_picto('', 'bank_account');
 				$form->select_comptes(GETPOST('accountid'), 'accountid', 0, '', 2);
 				print "</td></tr>\n";
 

+ 7 - 4
htdocs/adherents/subscription/list.php

@@ -191,7 +191,7 @@ if ($search_note) {
 	$sql .= natural_search('c.note', $search_note);
 }
 if ($search_account > 0) {
-	$sql .= " AND b.fk_account = ".urldecode($search_account);
+	$sql .= " AND b.fk_account = ".((int) $search_account);
 }
 if ($search_amount) {
 	$sql .= natural_search('c.subscription', $search_amount, 1);
@@ -496,11 +496,14 @@ while ($i < min($num, $limit)) {
 	$adherent->morphy = $obj->morphy;
 	$adherent->email = $obj->email;
 	$adherent->typeid = $obj->type;
+	$adherent->datefin = $db->jdate($obj->datef);
 
 	$typeid = ($obj->fk_type > 0 ? $obj->fk_type : $adherent->typeid);
 	$adht = new AdherentType($db);
 	$adht->fetch($typeid);
 
+	$adherent->need_subscription = $adht->subscription;
+
 	print '<tr class="oddeven">';
 
 	// Ref
@@ -547,8 +550,8 @@ while ($i < min($num, $limit)) {
 
 	// Label
 	if (!empty($arrayfields['t.libelle']['checked'])) {
-		print '<td>';
-		print dol_trunc($obj->note, 128);
+		print '<td class="tdoverflowmax500" title="'.dol_escape_htmltag($obj->note).'">';
+		print $obj->note;
 		print '</td>';
 		if (!$i) {
 			$totalarray['nbfield']++;
@@ -586,7 +589,7 @@ while ($i < min($num, $limit)) {
 	}
 	// Price
 	if (!empty($arrayfields['d.amount']['checked'])) {
-		print '<td class="right">'.price($obj->subscription).'</td>';
+		print '<td class="right amount">'.price($obj->subscription).'</td>';
 		if (!$i) {
 			$totalarray['nbfield']++;
 		}

+ 2 - 0
htdocs/adherents/type.php

@@ -566,6 +566,8 @@ if ($rowid > 0) {
 					$titre = $langs->trans("MembersListNotUpToDate");
 				} elseif ($status == '0') {
 					$titre = $langs->trans("MembersListResiliated");
+				} elseif ($status == '-2') {
+					$titre = $langs->trans("MembersListExcluded");
 				}
 			} elseif ($action == 'search') {
 				$titre = $langs->trans("MembersListQualified");

+ 2 - 2
htdocs/admin/boxes.php

@@ -49,8 +49,8 @@ $boxes = array();
  */
 
 if ($action == 'addconst') {
-	dolibarr_set_const($db, "MAIN_BOXES_MAXLINES", $_POST["MAIN_BOXES_MAXLINES"], '', 0, '', $conf->entity);
-	dolibarr_set_const($db, "MAIN_ACTIVATE_FILECACHE", $_POST["MAIN_ACTIVATE_FILECACHE"], 'chaine', 0, '', $conf->entity);
+	dolibarr_set_const($db, "MAIN_BOXES_MAXLINES", GETPOST("MAIN_BOXES_MAXLINES", 'int'), '', 0, '', $conf->entity);
+	dolibarr_set_const($db, "MAIN_ACTIVATE_FILECACHE", GETPOST("MAIN_ACTIVATE_FILECACHE", 'alpha'), 'chaine', 0, '', $conf->entity);
 }
 
 if ($action == 'add') {

+ 2 - 2
htdocs/admin/company.php

@@ -211,7 +211,7 @@ if (($action == 'update' && !GETPOST("cancel", 'alpha'))
 	dolibarr_set_const($db, "FACTURE_LOCAL_TAX1_OPTION", $uselocaltax1, 'chaine', 0, '', $conf->entity);
 	dolibarr_set_const($db, "FACTURE_LOCAL_TAX2_OPTION", $uselocaltax2, 'chaine', 0, '', $conf->entity);
 
-	if ($_POST["optionlocaltax1"] == "localtax1on") {
+	if (GETPOST("optionlocaltax1") == "localtax1on") {
 		if (!GETPOSTISSET('lt1')) {
 			dolibarr_set_const($db, "MAIN_INFO_VALUE_LOCALTAX1", 0, 'chaine', 0, '', $conf->entity);
 		} else {
@@ -219,7 +219,7 @@ if (($action == 'update' && !GETPOST("cancel", 'alpha'))
 		}
 		dolibarr_set_const($db, "MAIN_INFO_LOCALTAX_CALC1", GETPOST("clt1", 'aZ09'), 'chaine', 0, '', $conf->entity);
 	}
-	if ($_POST["optionlocaltax2"] == "localtax2on") {
+	if (GETPOST("optionlocaltax2") == "localtax2on") {
 		if (!GETPOSTISSET('lt2')) {
 			dolibarr_set_const($db, "MAIN_INFO_VALUE_LOCALTAX2", 0, 'chaine', 0, '', $conf->entity);
 		} else {

+ 1 - 1
htdocs/admin/const.php

@@ -237,7 +237,7 @@ $sql .= ", note";
 $sql .= ", tms";
 $sql .= ", entity";
 $sql .= " FROM ".MAIN_DB_PREFIX."const";
-$sql .= " WHERE entity IN (".$user->entity.",".$conf->entity.")";
+$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".$conf->entity).")";
 if ((empty($user->entity) || $user->admin) && $debug) {
 } elseif (!GETPOST('visible') || GETPOST('visible') != 'all') {
 	// to force for superadmin to debug

+ 1 - 1
htdocs/admin/delais.php

@@ -181,7 +181,7 @@ if ($action == 'update') {
 		}
 	}
 
-	dolibarr_set_const($db, "MAIN_DISABLE_METEO", $_POST["MAIN_DISABLE_METEO"], 'chaine', 0, '', $conf->entity);
+	dolibarr_set_const($db, "MAIN_DISABLE_METEO", GETPOST("MAIN_DISABLE_METEO"), 'chaine', 0, '', $conf->entity);
 	dolibarr_set_const($db, "MAIN_USE_METEO_WITH_PERCENTAGE", GETPOST("MAIN_USE_METEO_WITH_PERCENTAGE"), 'chaine', 0, '', $conf->entity);
 
 	// For update value with percentage

+ 20 - 10
htdocs/admin/dict.php

@@ -44,7 +44,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
 
 // Load translation files required by the page
-$langs->loadLangs(array("errors", "admin", "main", "companies", "resource", "holiday", "accountancy", "hrm", "orders", "contracts", "projects", "propal", "bills", "interventions"));
+$langs->loadLangs(array("errors", "admin", "main", "companies", "resource", "holiday", "accountancy", "hrm", "orders", "contracts", "projects", "propal", "bills", "interventions", "ticket"));
 
 $action = GETPOST('action', 'alpha') ?GETPOST('action', 'alpha') : 'view';
 $confirm = GETPOST('confirm', 'alpha');
@@ -788,7 +788,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) {
 			$msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'<br>';
 		}*/
 	}
-	if (GETPOSTISSET("country") && ($_POST["country"] == '0') && ($id != 2)) {
+	if (GETPOSTISSET("country") && (GETPOST("country") == '0') && ($id != 2)) {
 		if (in_array($tablib[$id], array('DictionaryCompanyType', 'DictionaryHolidayTypes'))) {	// Field country is no mandatory for such dictionaries
 			$_POST["country"] = '';
 		} else {
@@ -796,25 +796,25 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) {
 			setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities("Country")), null, 'errors');
 		}
 	}
-	if (($id == 3 || $id == 42) && !is_numeric($_POST["code"])) {
+	if (($id == 3 || $id == 42) && !is_numeric(GETPOST("code"))) {
 		$ok = 0;
 		setEventMessages($langs->transnoentities("ErrorFieldMustBeANumeric", $langs->transnoentities("Code")), null, 'errors');
 	}
 
 	// Clean some parameters
-	if ((!empty($_POST["localtax1_type"]) || ($_POST['localtax1_type'] == '0')) && empty($_POST["localtax1"])) {
+	if ((GETPOST("localtax1_type") || (GETPOST('localtax1_type') == '0')) && !GETPOST("localtax1")) {
 		$_POST["localtax1"] = '0'; // If empty, we force to 0
 	}
-	if ((!empty($_POST["localtax2_type"]) || ($_POST['localtax2_type'] == '0')) && empty($_POST["localtax2"])) {
+	if ((GETPOST("localtax2_type") || (GETPOST('localtax2_type') == '0')) && !GETPOST("localtax2")) {
 		$_POST["localtax2"] = '0'; // If empty, we force to 0
 	}
-	if ($_POST["accountancy_code"] <= 0) {
+	if (GETPOST("accountancy_code") <= 0) {
 		$_POST["accountancy_code"] = ''; // If empty, we force to null
 	}
-	if ($_POST["accountancy_code_sell"] <= 0) {
+	if (GETPOST("accountancy_code_sell") <= 0) {
 		$_POST["accountancy_code_sell"] = ''; // If empty, we force to null
 	}
-	if ($_POST["accountancy_code_buy"] <= 0) {
+	if (GETPOST("accountancy_code_buy") <= 0) {
 		$_POST["accountancy_code_buy"] = ''; // If empty, we force to null
 	}
 	if ($id == 10 && GETPOSTISSET("code")) {  // Spaces are not allowed into code for tax dictionary
@@ -1139,6 +1139,7 @@ if ($action == 'delete') {
 }
 //var_dump($elementList);
 
+
 /*
  * Show a dictionary
  */
@@ -1397,6 +1398,9 @@ if ($id) {
 			if ($fieldlist[$field] == 'unit_type') {
 				$valuetoshow = $langs->trans('TypeOfUnit');
 			}
+			if ($fieldlist[$field] == 'public' && $tablib[$id] == 'TicketDictCategory') {
+				$valuetoshow = $langs->trans('TicketGroupIsPublic'); $class = 'center';
+			}
 
 			if ($id == 2) {	// Special case for state page
 				if ($fieldlist[$field] == 'region_id') {
@@ -1738,6 +1742,9 @@ if ($id) {
 			if ($fieldlist[$field] == 'unit_type') {
 				$valuetoshow = $langs->trans('TypeOfUnit');
 			}
+			if ($fieldlist[$field] == 'public' && $tablib[$id] == 'TicketDictCategory') {
+				$valuetoshow = $langs->trans('TicketGroupIsPublic'); $cssprefix = 'center ';
+			}
 
 			if ($fieldlist[$field] == 'region_id' || $fieldlist[$field] == 'country_id') {
 				$showfield = 0;
@@ -1984,6 +1991,9 @@ if ($id) {
 							if ($fieldlist[$field] == 'use_default') {
 								$class .= ' center';
 							}
+							if ($fieldlist[$field] == 'public') {
+								$class .= ' center';
+							}
 							// Show value for field
 							if ($showfield) {
 								print '<!-- '.$fieldlist[$field].' --><td class="'.$class.'">'.$valuetoshow.'</td>';
@@ -2343,10 +2353,10 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '')
 			if ($fieldlist[$field] == 'code') {
 				$class = 'maxwidth100';
 			}
-			if (in_array($fieldlist[$field], array('dayrule', 'day', 'month', 'year', 'pos', 'use_default', 'affect', 'delay', 'position', 'sortorder', 'sens', 'category_type'))) {
+			if (in_array($fieldlist[$field], array('dayrule', 'day', 'month', 'year', 'pos', 'use_default', 'affect', 'delay', 'position', 'public', 'sortorder', 'sens', 'category_type'))) {
 				$class = 'maxwidth50 center';
 			}
-			if (in_array($fieldlist[$field], array('use_default'))) {
+			if (in_array($fieldlist[$field], array('use_default', 'public'))) {
 				$classtd = 'center';
 			}
 			if (in_array($fieldlist[$field], array('libelle', 'label', 'tracking'))) {

+ 1 - 0
htdocs/admin/dolistore/ajax/index.html

@@ -0,0 +1 @@
+

+ 2 - 2
htdocs/admin/eventorganization.php

@@ -201,7 +201,7 @@ if ($action == 'edit') {
 	print '<input type="hidden" name="action" value="update">';
 
 	print '<table class="noborder centpercent">';
-	print '<tr class="liste_titre"><td class="titlefield">'.$langs->trans("Parameter").'</td><td>'.$langs->trans("Value").'</td></tr>';
+	print '<tr class="liste_titre"><td class="titlefieldcreate">'.$langs->trans("Parameter").'</td><td>'.$langs->trans("Value").'</td></tr>';
 
 	foreach ($arrayofparameters as $constname => $val) {
 		if ($val['enabled']==1) {
@@ -266,7 +266,7 @@ if ($action == 'edit') {
 } else {
 	if (!empty($arrayofparameters)) {
 		print '<table class="noborder centpercent">';
-		print '<tr class="liste_titre"><td class="titlefield">'.$langs->trans("Parameter").'</td><td>'.$langs->trans("Value").'</td></tr>';
+		print '<tr class="liste_titre"><td class="titlefieldcreate">'.$langs->trans("Parameter").'</td><td>'.$langs->trans("Value").'</td></tr>';
 
 		foreach ($arrayofparameters as $constname => $val) {
 			if ($val['enabled']==1) {

+ 16 - 12
htdocs/admin/external_rss.php

@@ -41,7 +41,6 @@ if (!$user->admin) {
 	accessforbidden();
 }
 
-$def = array();
 $lastexternalrss = 0;
 $action = GETPOST('action', 'aZ09');
 
@@ -56,6 +55,7 @@ $sql .= " WHERE ".$db->decrypt('name')." LIKE 'EXTERNAL_RSS_URLRSS_%'";
 //print $sql;
 $result = $db->query($sql); // We can't use SELECT MAX() because EXTERNAL_RSS_URLRSS_10 is lower than EXTERNAL_RSS_URLRSS_9
 if ($result) {
+	$reg = array();
 	while ($obj = $db->fetch_object($result)) {
 		preg_match('/([0-9]+)$/i', $obj->name, $reg);
 		if ($reg[1] && $reg[1] > $lastexternalrss) {
@@ -70,17 +70,17 @@ if ($action == 'add' || GETPOST("modify")) {
 	$external_rss_title = "external_rss_title_".GETPOST("norss", 'int');
 	$external_rss_urlrss = "external_rss_urlrss_".GETPOST("norss", 'int');
 
-	if (!empty($_POST[$external_rss_urlrss])) {
+	if (GETPOST($external_rss_urlrss, 'alpha')) {
 		$boxlabel = '(ExternalRSSInformations)';
-		//$external_rss_url = "external_rss_url_" . $_POST["norss"];
+		//$external_rss_url = "external_rss_url_" . GETPOST("norss");
 
 		$db->begin();
 
-		if ($_POST["modify"]) {
+		if (GETPOST("modify")) {
 			// Supprime boite box_external_rss de definition des boites
 			/* $sql = "UPDATE ".MAIN_DB_PREFIX."boxes_def";
 			$sql.= " SET name = '".$db->escape($boxlabel)."'";
-			$sql.= " WHERE file ='box_external_rss.php' AND note like '".$db->escape($_POST["norss"])." %'";
+			$sql.= " WHERE file ='box_external_rss.php' AND note like '".$db->escape(GETPOST("norss"))." %'";
 
 			$resql=$db->query($sql);
 			if (! $resql)
@@ -95,13 +95,17 @@ if ($action == 'add' || GETPOST("modify")) {
 			$sql .= " VALUES ('box_external_rss.php','".$db->escape(GETPOST("norss", 'int').' ('.GETPOST($external_rss_title, 'alpha')).")')";
 			if (!$db->query($sql)) {
 				dol_print_error($db);
-				$err++;
+				$error++;
 			}
+			//print $sql;exit;
 		}
 
 		$result1 = dolibarr_set_const($db, "EXTERNAL_RSS_TITLE_".GETPOST("norss", 'int'), GETPOST($external_rss_title, 'alpha'), 'chaine', 0, '', $conf->entity);
 		if ($result1) {
-			$result2 = dolibarr_set_const($db, "EXTERNAL_RSS_URLRSS_".GETPOST("norss", 'int'), GETPOST($external_rss_urlrss, 'alpha'), 'chaine', 0, '', $conf->entity);
+			$consttosave = "EXTERNAL_RSS_URLRSS_".GETPOST("norss", 'int');
+			$urltosave = GETPOST($external_rss_urlrss, 'alpha');
+			$result2 = dolibarr_set_const($db, $consttosave, $urltosave, 'chaine', 0, '', $conf->entity);
+			//var_dump($result2);exit;
 		}
 
 		if ($result1 && $result2) {
@@ -115,7 +119,7 @@ if ($action == 'add' || GETPOST("modify")) {
 	}
 }
 
-if ($_POST["delete"]) {
+if (GETPOST("delete")) {
 	if (GETPOST("norss", 'int')) {
 		$db->begin();
 
@@ -258,14 +262,14 @@ if ($resql) {
 
 
 		print '<tr class="oddeven">';
-		print "<td width=\"100px\">".$langs->trans("Title")."</td>";
-		print "<td><input type=\"text\" class=\"flat minwidth300\" name=\"external_rss_title_".$idrss."\" value=\"".dol_escape_htmltag($conf->global->$keyrsstitle)."\"></td>";
+		print '<td class="titlefield">'.$langs->trans("Title")."</td>";
+		print '<td><input type="text" class="flat minwidth300" name="external_rss_title_'.$idrss.'" value="'.dol_escape_htmltag($conf->global->$keyrsstitle).'"></td>';
 		print '</tr>'."\n";
 
 
 		print '<tr class="oddeven">';
 		print "<td>".$langs->trans("URL")."</td>";
-		print "<td><input type=\"text\" class=\"flat minwidth300\" name=\"external_rss_urlrss_".$idrss."\" value=\"".dol_escape_htmltag($conf->global->$keyrssurl)."\"></td>";
+		print '<td><input type="text" class="flat minwidth300" name="external_rss_urlrss_'.$idrss.'" value="'.dol_escape_htmltag($conf->global->$keyrssurl).'"></td>';
 		print '</tr>'."\n";
 
 
@@ -307,7 +311,7 @@ if ($resql) {
 		// Active
 		$active = _isInBoxList($idrss, $boxlist) ? 'yes' : 'no';
 		print '<tr class="oddeven">';
-		print '<td>'.$langs->trans('WidgetEnabled').'</td>';
+		print '<td>'.$langs->trans('WidgetAvailable').'</td>';
 		print '<td>'.yn($active).'</td>';
 		print '</tr>'."\n";
 

+ 1 - 1
htdocs/admin/ihm.php

@@ -96,7 +96,7 @@ if ($action == 'removebackgroundlogin' && !empty($conf->global->MAIN_LOGIN_BACKG
 if ($action == 'update') {
 	dolibarr_set_const($db, "MAIN_LANG_DEFAULT", GETPOST("MAIN_LANG_DEFAULT", 'aZ09'), 'chaine', 0, '', $conf->entity);
 	dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity);
-	//dolibarr_set_const($db, "MAIN_MULTILANGS", $_POST["MAIN_MULTILANGS"], 'chaine', 0, '', $conf->entity);
+	//dolibarr_set_const($db, "MAIN_MULTILANGS", GETPOST("MAIN_MULTILANGS"), 'chaine', 0, '', $conf->entity);
 
 	dolibarr_set_const($db, "MAIN_THEME", GETPOST("main_theme", 'aZ09'), 'chaine', 0, '', $conf->entity);
 

+ 1 - 1
htdocs/admin/index.php

@@ -93,7 +93,7 @@ print '<br>';
 
 // Show info setup module
 print img_picto('', 'cog', 'class="paddingright"').' '.$langs->trans("SetupDescription4", DOL_URL_ROOT.'/admin/modules.php?mainmenu=home', $langs->transnoentities("Setup"), $langs->transnoentities("Modules"));
-if (count($conf->modules) <= (empty($conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING) ? 1 : $conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)) {	// If only user module enabled
+if (count($conf->modules) <= (empty($conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING) ? 1 : $conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)) {	// If only minimal initial modules enabled
 	$langs->load("errors");
 	$warnpicto = img_warning($langs->trans("WarningEnableYourModulesApplications"), 'style="padding-right: 6px;"');
 	print '<br><div class="warning"><a href="'.DOL_URL_ROOT.'/admin/modules.php?mainmenu=home">'.$warnpicto.$langs->trans("WarningEnableYourModulesApplications").'</a></div>';

+ 15 - 9
htdocs/admin/mailman.php

@@ -46,21 +46,27 @@ $action = GETPOST('action', 'aZ09');
 $testsubscribeemail = GETPOST("testsubscribeemail");
 $testunsubscribeemail = GETPOST("testunsubscribeemail");
 
+$error = 0;
+
+
 /*
  * Actions
  */
 
 // Action updated or added a constant
 if ($action == 'update' || $action == 'add') {
-	foreach ($_POST['constname'] as $key => $val) {
-		$constname = $_POST["constname"][$key];
-		$constvalue = $_POST["constvalue"][$key];
-		$consttype = $_POST["consttype"][$key];
-		$constnote = $_POST["constnote"][$key];
-		$res = dolibarr_set_const($db, $constname, $constvalue, $type[$consttype], 0, $constnote, $conf->entity);
-
-		if (!($res > 0)) {
-			$error++;
+	$tmparray = GETPOST('constname', 'array');
+	if (is_array($tmparray)) {
+		foreach ($tmparray as $key => $val) {
+			$constname = $tmparray[$key];
+			$constvalue = $tmparray[$key];
+			$consttype = $tmparray[$key];
+			$constnote = $tmparray[$key];
+			$res = dolibarr_set_const($db, $constname, $constvalue, $type[$consttype], 0, $constnote, $conf->entity);
+
+			if (!($res > 0)) {
+				$error++;
+			}
 		}
 	}
 

+ 2 - 1
htdocs/admin/mails_emailing.php

@@ -31,6 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
 $langs->loadLangs(array('companies', 'products', 'admin', 'mails', 'other', 'errors'));
 
 $action = GETPOST('action', 'aZ09');
+$cancel = GETPOST('cancel', 'alpha');
 
 if (!$user->admin) {
 	accessforbidden();
@@ -59,7 +60,7 @@ complete_substitutions_array($substitutionarrayfortest, $langs);
  * Actions
  */
 
-if ($action == 'update' && empty($_POST["cancel"])) {
+if ($action == 'update' && !$cancel) {
 	// Send mode parameters
 	dolibarr_set_const($db, "MAIN_MAIL_SENDMODE_EMAILING", GETPOST("MAIN_MAIL_SENDMODE_EMAILING"), 'chaine', 0, '', $conf->entity);
 	dolibarr_set_const($db, "MAIN_MAIL_SMTP_PORT_EMAILING", GETPOST("MAIN_MAIL_SMTP_PORT_EMAILING"), 'chaine', 0, '', $conf->entity);

+ 2 - 1
htdocs/admin/mails_ticket.php

@@ -31,6 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
 $langs->loadLangs(array('companies', 'products', 'admin', 'mails', 'other', 'errors'));
 
 $action = GETPOST('action', 'aZ09');
+$cancel = GETPOST('cancel', 'alpha');
 
 $usersignature = $user->signature;
 // For action = test or send, we ensure that content is not html, even for signature, because this we want a test with NO html.
@@ -59,7 +60,7 @@ if (!$user->admin) {
  * Actions
  */
 
-if ($action == 'update' && empty($_POST["cancel"])) {
+if ($action == 'update' && !$cancel) {
 	// Send mode parameters
 	dolibarr_set_const($db, "MAIN_MAIL_SENDMODE_TICKET", GETPOST("MAIN_MAIL_SENDMODE_TICKET"), 'chaine', 0, '', $conf->entity);
 	dolibarr_set_const($db, "MAIN_MAIL_SMTP_PORT_TICKET", GETPOST("MAIN_MAIL_SMTP_PORT_TICKET"), 'chaine', 0, '', $conf->entity);

+ 2 - 2
htdocs/admin/menus/edit.php

@@ -333,8 +333,8 @@ if ($action == 'create') {
 	} else {
 		print '<select name="type" class="flat" id="topleft">';
 		print '<option value="">&nbsp;</option>';
-		print '<option value="top"'.(!empty($_POST["type"]) && $_POST["type"] == 'top' ? ' selected' : '').'>'.$langs->trans('Top').'</option>';
-		print '<option value="left"'.(!empty($_POST["type"]) && $_POST["type"] == 'left' ? ' selected' : '').'>'.$langs->trans('Left').'</option>';
+		print '<option value="top"'.(GETPOST("type") == 'top' ? ' selected' : '').'>'.$langs->trans('Top').'</option>';
+		print '<option value="left"'.(GETPOST("type") == 'left' ? ' selected' : '').'>'.$langs->trans('Left').'</option>';
 		print '</select>';
 	}
 	print '</td><td>'.$langs->trans('DetailType').'</td></tr>';

+ 10 - 6
htdocs/admin/modules.php

@@ -463,11 +463,13 @@ asort($orders);
 //var_dump($modules);
 
 $nbofactivatedmodules = count($conf->modules);
-$moreinfo = $langs->trans("TitleNumberOfActivatedModules");
+
+//$conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING = 1000;
+/*$moreinfo = $langs->trans("TitleNumberOfActivatedModules");
 $moreinfo2 = '<b class="largenumber">'.($nbofactivatedmodules - 1).'</b> / <b class="largenumber">'.count($modules).'</b>';
-if ($nbofactivatedmodules <= 1) {
+if ($nbofactivatedmodules <= (empty($conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING) ? 1 : $conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)) {
 	$moreinfo2 .= ' '.img_warning($langs->trans("YouMustEnableOneModule"));
-}
+}*/
 
 print load_fiche_titre($langs->trans("ModulesSetup"), '', 'title_setup');
 
@@ -476,7 +478,9 @@ $deschelp  = '';
 if ($mode == 'common' || $mode == 'commonkanban') {
 	$desc = $langs->trans("ModulesDesc", '{picto}');
 	$desc = str_replace('{picto}', img_picto('', 'switch_off'), $desc);
-	$deschelp = '<div class="info hideonsmartphone">'.$desc."<br></div><br>\n";
+	if (count($conf->modules) <= (empty($conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING) ? 1 : $conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)) {	// If only minimal initial modules enabled
+		$deschelp = '<div class="info hideonsmartphone">'.$desc."<br></div><br>\n";
+	}
 }
 if ($mode == 'marketplace') {
 	//$deschelp = '<div class="info hideonsmartphone">'.$langs->trans("ModulesMarketPlaceDesc")."<br></div><br>\n";
@@ -488,7 +492,7 @@ if ($mode == 'develop') {
 	$deschelp = '<div class="info hideonsmartphone">'.$langs->trans("ModulesDevelopDesc")."<br></div><br>\n";
 }
 
-$head = modules_prepare_head();
+$head = modules_prepare_head($nbofactivatedmodules, count($modules));
 
 
 if ($mode == 'common' || $mode == 'commonkanban') {
@@ -521,7 +525,7 @@ if ($mode == 'common' || $mode == 'commonkanban') {
 	$moreforfilter .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-list-alt imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.$param, '', 1, array('morecss'=>'reposition'.($mode == 'commonkanban' ? '' : ' btnTitleSelected')));
 	$moreforfilter .= '</li></ul></div>';
 
-	$moreforfilter .= '<div class="floatright center marginrightonly hideonsmartphone" style="padding-top: 3px"><span class="paddingright">'.$moreinfo.'</span> '.$moreinfo2.'</div>';
+	//$moreforfilter .= '<div class="floatright center marginrightonly hideonsmartphone" style="padding-top: 3px"><span class="paddingright">'.$moreinfo.'</span> '.$moreinfo2.'</div>';
 
 	$moreforfilter .= '<div class="colorbacktimesheet float valignmiddle">';
 	$moreforfilter .= '<div class="divsearchfield paddingtop">';

+ 2 - 2
htdocs/admin/multicurrency.php

@@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
 $langs->loadLangs(array('admin', 'multicurrency'));
 
 // Access control
-if (!$user->admin) {
+if (!$user->admin || empty($conf->multicurrency->enabled)) {
 	accessforbidden();
 }
 
@@ -45,7 +45,7 @@ $action = GETPOST('action', 'aZ09');
  * Actions
  */
 
-
+$reg = array();
 if (preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) {
 	$code = $reg[1];
 	$value = GETPOST($code, 'alpha');

+ 2 - 2
htdocs/admin/notification.php

@@ -92,7 +92,7 @@ if ($action == 'settemplates') {
 if ($action == 'setvalue' && $user->admin) {
 	$db->begin();
 
-	$result = dolibarr_set_const($db, "NOTIFICATION_EMAIL_FROM", GETPOST("email_from", "restricthtml"), 'chaine', 0, '', $conf->entity);
+	$result = dolibarr_set_const($db, "NOTIFICATION_EMAIL_FROM", GETPOST("email_from", "alphawithlgt"), 'chaine', 0, '', $conf->entity);
 	if ($result < 0) {
 		$error++;
 	}
@@ -270,7 +270,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) {
 	}
 
 	$helptext = '';
-	form_constantes($constantes, 2, $helptext);
+	form_constantes($constantes, 3, $helptext);
 } else {
 	print '<table class="noborder centpercent">';
 	print '<tr class="liste_titre">';

+ 1 - 1
htdocs/admin/perms.php

@@ -132,7 +132,7 @@ print '</tr>'."\n";
 $sql = "SELECT r.id, r.libelle as label, r.module, r.module_position, r.perms, r.subperms, r.bydefault";
 $sql .= " FROM ".MAIN_DB_PREFIX."rights_def as r";
 $sql .= " WHERE r.libelle NOT LIKE 'tou%'"; // On ignore droits "tous"
-$sql .= " AND r.entity = ".$entity;
+$sql .= " AND r.entity = ".((int) $entity);
 if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) {
 	$sql .= " AND r.perms NOT LIKE '%_advance'"; // Hide advanced perms if option is not enabled
 }

+ 1 - 1
htdocs/admin/sms.php

@@ -66,7 +66,7 @@ if ($action == 'send' && !$_POST['cancel']) {
 	$error = 0;
 
 	$smsfrom = '';
-	if (!empty($_POST["fromsms"])) {
+	if (GETPOST("fromsms", 'alphanohtml')) {
 		$smsfrom = GETPOST("fromsms", 'alphanohtml');
 	}
 	if (empty($smsfrom)) {

+ 1 - 1
htdocs/admin/system/constall.php

@@ -223,7 +223,7 @@ if (empty($conf->multicompany->enabled)) {
 } else {
 	// If multicompany mode, superadmin (user->entity=0) can see everything, admin are limited to their entities.
 	if ($user->entity) {
-		$sql .= " WHERE entity IN (".$user->entity.",".$conf->entity.")";
+		$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".$conf->entity).")";
 	}
 }
 $sql .= " ORDER BY entity, name ASC";

+ 1 - 1
htdocs/admin/system/dolibarr.php

@@ -484,7 +484,7 @@ if (empty($conf->multicompany->enabled)) {
 } else {
 	// If multicompany mode, superadmin (user->entity=0) can see everything, admin are limited to their entities.
 	if ($user->entity) {
-		$sql .= " WHERE entity IN (".$user->entity.",".$conf->entity.")";
+		$sql .= " WHERE entity IN (".$db->sanitize($user->entity.",".$conf->entity).")";
 	}
 }
 $sql .= " ORDER BY entity, name ASC";

+ 41 - 59
htdocs/admin/ticket_public.php

@@ -59,6 +59,38 @@ if ($action == 'setTICKET_ENABLE_PUBLIC_INTERFACE') {
 if ($action == 'setvar') {
 	include_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
 
+	if (GETPOSTISSET('TICKET_ENABLE_PUBLIC_INTERFACE')) {	// only for no js case
+		$param_enable_public_interface = GETPOST('TICKET_ENABLE_PUBLIC_INTERFACE', 'alpha');
+		$res = dolibarr_set_const($db, 'TICKET_ENABLE_PUBLIC_INTERFACE', $param_enable_public_interface, 'chaine', 0, '', $conf->entity);
+		if (!($res > 0)) {
+			$error++;
+		}
+	}
+
+	if (GETPOSTISSET('TICKET_EMAIL_MUST_EXISTS')) {	// only for no js case
+		$param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha');
+		$res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity);
+		if (!($res > 0)) {
+			$error++;
+		}
+	}
+
+	if (GETPOSTISSET('TICKET_DISABLE_CUSTOMER_MAILS')) {	// only for no js case
+		$param_disable_email = GETPOST('TICKET_DISABLE_CUSTOMER_MAILS', 'alpha');
+		$res = dolibarr_set_const($db, 'TICKET_DISABLE_CUSTOMER_MAILS', $param_disable_email, 'chaine', 0, '', $conf->entity);
+		if (!($res > 0)) {
+			$error++;
+		}
+	}
+
+	if (GETPOSTISSET('TICKET_SHOW_COMPANY_LOGO')) {	// only for no js case
+		$param_show_module_logo = GETPOST('TICKET_SHOW_COMPANY_LOGO', 'alpha');
+		$res = dolibarr_set_const($db, 'TICKET_SHOW_COMPANY_LOGO', $param_show_module_logo, 'chaine', 0, '', $conf->entity);
+		if (!($res > 0)) {
+			$error++;
+		}
+	}
+
 	$topic_interface = GETPOST('TICKET_PUBLIC_INTERFACE_TOPIC', 'nohtml');
 	if (!empty($topic_interface)) {
 		$res = dolibarr_set_const($db, 'TICKET_PUBLIC_INTERFACE_TOPIC', $topic_interface, 'chaine', 0, '', $conf->entity);
@@ -114,32 +146,6 @@ if ($action == 'setvar') {
 	if (!($res > 0)) {
 		$error++;
 	}
-}
-
-if ($action == 'setvarother') {
-	$param_enable_public_interface = GETPOST('TICKET_ENABLE_PUBLIC_INTERFACE', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_ENABLE_PUBLIC_INTERFACE', $param_enable_public_interface, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_disable_email = GETPOST('TICKET_DISABLE_CUSTOMER_MAILS', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_DISABLE_CUSTOMER_MAILS', $param_disable_email, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
-
-	$param_show_module_logo = GETPOST('TICKET_SHOW_COMPANY_LOGO', 'alpha');
-	$res = dolibarr_set_const($db, 'TICKET_SHOW_COMPANY_LOGO', $param_show_module_logo, 'chaine', 0, '', $conf->entity);
-	if (!($res > 0)) {
-		$error++;
-	}
 
 	if ($conf->global->MAIN_FEATURES_LEVEL >= 2) {
 		$param_notification_also_main_addressemail = GETPOST('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS', 'alpha');
@@ -197,18 +203,16 @@ print '<input type="hidden" id="TICKET_ENABLE_PUBLIC_INTERFACE" name="TICKET_ENA
 print '<br><br>';
 
 if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
-	if (empty($conf->use_javascript_ajax)) {
-		print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
-		print '<input type="hidden" name="token" value="'.newToken().'">';
-		print '<input type="hidden" name="action" value="setvarother">';
-	}
+	print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
+	print '<input type="hidden" name="token" value="'.newToken().'">';
+	print '<input type="hidden" name="action" value="setvar">';
 
 	print '<div class="div-table-responsive-no-min">';
 	print '<table class="noborder centpercent">';
 	print '<tr class="liste_titre"><td>'.$langs->trans("Parameters").'</td>';
 	print '<td class="left">';
 	print '</td>';
-	print '<td class="center">';
+	print '<td class="center width75">';
 	print '</td>';
 	print '</tr>';
 
@@ -222,7 +226,7 @@ if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
 		print $form->selectarray("TICKET_EMAIL_MUST_EXISTS", $arrval, $conf->global->TICKET_EMAIL_MUST_EXISTS);
 	}
 	print '</td>';
-	print '<td class="center">';
+	print '<td class="center width75">';
 	print $form->textwithpicto('', $langs->trans("TicketsEmailMustExistHelp"), 1, 'help');
 	print '</td>';
 	print '</tr>';
@@ -255,7 +259,7 @@ if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
 		print $form->selectarray("TICKET_SHOW_COMPANY_LOGO", $arrval, $conf->global->TICKET_SHOW_COMPANY_LOGO);
 	}
 	print '</td>';
-	print '<td class="center">';
+	print '<td class="center width75">';
 	print $form->textwithpicto('', $langs->trans("TicketsShowCompanyLogoHelp"), 1, 'help');
 	print '</td>';
 	print '</tr>';
@@ -271,8 +275,8 @@ if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
 			print $form->selectarray("TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS", $arrval, $conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS);
 		}
 		print '</td>';
-		print '<td class="center">';
-		print $form->textwithpicto('', $langs->trans("TicketsEmailAlsoSendToMainAddressHelp"), 1, 'help');
+		print '<td class="center width75">';
+		print $form->textwithpicto('', $langs->trans("TicketsEmailAlsoSendToMainAddressHelp", $langs->transnoentitiesnoconv("TicketEmailNotificationTo").' ('.$langs->transnoentitiesnoconv("Creation").')', $langs->trans("Settings")), 1, 'help');
 		print '</td>';
 		print '</tr>';
 	}
@@ -282,28 +286,6 @@ if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
 		print '</tr>';
 	}
 
-	print '</table>';
-	print '</div>';
-	print '<br>';
-
-	if (!$conf->use_javascript_ajax) {
-		print '</form>';
-	}
-
-	// Admin var of module
-	print load_fiche_titre($langs->trans("TicketParamMail"));
-
-	print '<div class="div-table-responsive-no-min">';
-	print '<table class="noborder centpercent">';
-
-	print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
-	print '<input type="hidden" name="token" value="'.newToken().'">';
-	print '<input type="hidden" name="action" value="setvar">';
-
-	print '<tr class="liste_titre">';
-	print '<td colspan="3">'.$langs->trans("Parameter").'</td>';
-	print "</tr>\n";
-
 	if (empty($conf->global->FCKEDITOR_ENABLE_MAIL)) {
 		print '<tr>';
 		print '<td colspan="3"><div class="info">'.$langs->trans("TicketCkEditorEmailNotActivated").'</div></td>';
@@ -316,7 +298,7 @@ if (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) {
 	print '</td><td>';
 	print '<input type="text"   name="TICKET_PUBLIC_INTERFACE_TOPIC" value="'.$conf->global->TICKET_PUBLIC_INTERFACE_TOPIC.'" size="40" ></td>';
 	print '</td>';
-	print '<td class="center">';
+	print '<td class="center width75">';
 	print $form->textwithpicto('', $langs->trans("TicketPublicInterfaceTopicHelp"), 1, 'help');
 	print '</td></tr>';
 

+ 0 - 216
htdocs/api/admin/explorer.php

@@ -1,216 +0,0 @@
-<?php
-/* Copyright (C) 2015   Jean-François Ferry     <jfefe@aternatik.fr>
- * Copyright (C) 2016   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 <https://www.gnu.org/licenses/>.
- *
- * @deprecated      Old explorer. Not using Swagger. See instead explorer in htdocs/api/index.php.
- */
-
-/**
- * 	\defgroup   api     Module DolibarrApi
- *  \brief      API loader
- *				Search files htdocs/<module>/class/api_<module>.class.php
- *  \file       htdocs/api/admin/explorer.php
- */
-
-use Luracast\Restler\Routes;
-
-require_once '../../main.inc.php';
-require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
-require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php';
-require_once DOL_DOCUMENT_ROOT.'/api/class/api_access.class.php';
-
-// Load translation files required by the page
-$langs->load("admin");
-
-
-/*
- * View
- */
-
-// Enable and test if module Api is enabled
-if (empty($conf->global->MAIN_MODULE_API)) {
-	dol_syslog("Call Dolibarr API interfaces with module REST disabled");
-	print $langs->trans("WarningModuleNotActive", 'Api').'.<br><br>';
-	print $langs->trans("ToActivateModule");
-	exit;
-}
-
-
-$api = new DolibarrApi($db);
-
-$api->r->addAPIClass('Luracast\\Restler\\Resources'); //this creates resources.json at API Root
-$api->r->setSupportedFormats('JsonFormat', 'XmlFormat');
-$api->r->addAuthenticationClass('DolibarrApiAccess', '');
-
-$listofapis = array();
-
-$modulesdir = dolGetModulesDirs();
-foreach ($modulesdir as $dir) {
-	/*
-	 * Search available module
-	 */
-	//dol_syslog("Scan directory ".$dir." for API modules");
-
-	$handle = @opendir(dol_osencode($dir));
-	if (is_resource($handle)) {
-		while (($file = readdir($handle)) !== false) {
-			if (is_readable($dir.$file) && preg_match("/^(mod.*)\.class\.php$/i", $file, $reg)) {
-				$modulename = $reg[1];
-
-				// Defined if module is enabled
-				$enabled = true;
-				$module = $part = $obj = strtolower(preg_replace('/^mod/i', '', $modulename));
-				//if ($part == 'propale') $part='propal';
-				if ($module == 'societe') {
-					$obj = 'thirdparty';
-				}
-				if ($module == 'categorie') {
-					$part = 'categories';
-					$obj = 'category';
-				}
-				if ($module == 'facture') {
-					$part = 'compta/facture';
-					$obj = 'facture';
-				}
-				if ($module == 'ficheinter') {
-					$obj = 'fichinter';
-					$part = 'fichinter';
-					$module = 'fichinter';
-				}
-
-				if (empty($conf->$module->enabled)) {
-					$enabled = false;
-				}
-
-				if ($enabled) {
-					/*
-					 * If exists, load the API class for enable module
-					 *
-					 * Search files named api_<object>.class.php into /htdocs/<module>/class directory
-					 *
-					 * @todo : take care of externals module!
-					 * @todo : use getElementProperties() function ?
-					 */
-					$dir_part = DOL_DOCUMENT_ROOT.'/'.$part.'/class/';
-
-					$handle_part = @opendir(dol_osencode($dir_part));
-					if (is_resource($handle_part)) {
-						while (($file_searched = readdir($handle_part)) !== false) {
-							if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i", $file_searched, $reg)) {
-								$classname = ucwords($reg[1]);
-								require_once $dir_part.$file_searched;
-								if (class_exists($classname)) {
-									dol_syslog("Found API classname=".$classname." into ".$dir);
-									$listofapis[] = $classname;
-								}
-							}
-
-							/*
-							if (is_readable($dir_part.$file_searched) && preg_match("/^(api_.*)\.class\.php$/i",$file_searched,$reg))
-							{
-								$classname=$reg[1];
-								$classname = str_replace('Api_','',ucwords($reg[1])).'Api';
-								//$classname = str_replace('Api_','',ucwords($reg[1]));
-								$classname = ucfirst($classname);
-								require_once $dir_part.$file_searched;
-
-								// if (class_exists($classname))
-								// {
-								//     dol_syslog("Found API classname=".$classname);
-								//     $api->r->addAPIClass($classname,'');
-
-								//     require_once DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/Routes.php';
-								//     $tmpclass = new ReflectionClass($classname);
-								//     try {
-								//         $classMetadata = CommentParser::parse($tmpclass->getDocComment());
-								//     } catch (Exception $e) {
-								//         throw new RestException(500, "Error while parsing comments of `$classname` class. " . $e->getMessage());
-								//     }
-
-								//     //$listofapis[]=array('classname'=>$classname, 'fullpath'=>$file_searched);
-								// }
-							}*/
-						}
-					}
-				}
-			}
-		}
-	}
-}
-
-//var_dump($listofapis);
-$listofapis = Routes::toArray(); // @todo api for "status" is lost here
-//var_dump($listofapis);
-
-
-llxHeader();
-
-$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
-print load_fiche_titre($langs->trans("ApiSetup"), $linkback, 'title_setup');
-
-// 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
-
-// Show message
-print '<br>';
-$message = '';
-$url = '<a href="'.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword" target="_blank">'.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword[&reset=1]</a>';
-$message .= $langs->trans("UrlToGetKeyToUseAPIs").':<br>';
-$message .= img_picto('', 'globe').' '.$url;
-print $message;
-print '<br>';
-print '<br>';
-
-$oldclass = '';
-
-print $langs->trans("ListOfAvailableAPIs").':<br>';
-foreach ($listofapis['v1'] as $key => $val) {
-	if ($key == 'login') {
-		continue;
-	}
-	if ($key == 'index') {
-		continue;
-	}
-
-	if ($key) {
-		foreach ($val as $method => $val2) {
-			$newclass = $val2['className'];
-
-			if (preg_match('/restler/i', $newclass)) {
-				continue;
-			}
-
-			if ($oldclass != $newclass) {
-				print "\n<br>\n".$langs->trans("Class").': '.$newclass.'<br>'."\n";
-				$oldclass = $newclass;
-			}
-			//print $key.' - '.$val['classname'].' - '.$val['fullpath']." - ".DOL_MAIN_URL_ROOT.'/api/index.php/'.strtolower(preg_replace('/Api$/','',$val['classname']))."/xxx<br>\n";
-			$url = $urlwithroot.'/api/index.php/'.$key;
-			$url .= '?api_key=token';
-			print img_picto('', 'globe').' '.$method.' <a href="'.$url.'" target="_blank">'.$url."</a><br>\n";
-		}
-	}
-}
-
-print '<br>';
-print '<br>';
-print $langs->trans("OnlyActiveElementsAreExposed", DOL_URL_ROOT.'/admin/modules.php');
-
-
-llxFooter();
-$db->close();

+ 87 - 0
htdocs/api/admin/explorer_withredoc.php

@@ -0,0 +1,87 @@
+<?php
+/* Copyright (C) 2015   Jean-François Ferry     <jfefe@aternatik.fr>
+ * Copyright (C) 2016   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 <https://www.gnu.org/licenses/>.
+ *
+ * @deprecated      Old explorer. Not using Swagger. See instead explorer in htdocs/api/index.php.
+ */
+
+/**
+ * 	\defgroup   api     Module DolibarrApi
+ *  \brief      API explorer using the swagger.json file
+ *  \file       htdocs/api/admin/explorer_withredoc.php
+ */
+
+require_once '../../main.inc.php';
+
+// Enable and test if module Api is enabled
+if (empty($conf->global->MAIN_MODULE_API)) {
+	$langs->load("admin");
+	dol_syslog("Call of Dolibarr API interfaces with module API REST are disabled");
+	print $langs->trans("WarningModuleNotActive", 'Api').'.<br><br>';
+	print $langs->trans("ToActivateModule");
+	//session_destroy();
+	exit(0);
+}
+
+// Test if explorer is not disabled
+if (!empty($conf->global->API_EXPLORER_DISABLED)) {
+	$langs->load("admin");
+	dol_syslog("Call Dolibarr API interfaces with module REST disabled");
+	print $langs->trans("WarningAPIExplorerDisabled").'.<br><br>';
+	//session_destroy();
+	exit(0);
+}
+
+// Restrict API to some IPs
+if (!empty($conf->global->API_RESTRICT_ON_IP)) {
+	$allowedip = explode(' ', $conf->global->API_RESTRICT_ON_IP);
+	$ipremote = getUserRemoteIP();
+	if (!in_array($ipremote, $allowedip)) {
+		dol_syslog('Remote ip is '.$ipremote.', not into list '.$conf->global->API_RESTRICT_ON_IP);
+		print 'APIs are not allowed from the IP '.$ipremote;
+		header('HTTP/1.1 503 API not allowed from your IP '.$ipremote);
+		//session_destroy();
+		exit(0);
+	}
+}
+
+?>
+<!DOCTYPE html>
+<html>
+  <head>
+	<title>ReDoc</title>
+	<!-- needed for adaptive design -->
+	<meta charset="utf-8"/>
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
+
+	<!--
+	ReDoc doesn't change outer page styles
+	-->
+	<style>
+	  body {
+		margin: 0;
+		padding: 0;
+	  }
+	</style>
+  </head>
+  <body>
+	<redoc spec-url='<?php echo DOL_MAIN_URL_ROOT.'/api/index.php/explorer/swagger.json?DOLAPIKEY='.GETPOST('DOLAPIKEY', 'aZ09'); ?>'></redoc>
+	<!--<redoc spec-url='https://demo.dolibarr.org/api/index.php/explorer/swagger.json'></redoc>-->
+	<!--<redoc spec-url='http://petstore.swagger.io/v2/swagger.json'></redoc>-->
+	<script src="https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"> </script>
+  </body>
+</html>

+ 11 - 4
htdocs/api/admin/index.php

@@ -139,18 +139,25 @@ $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domai
 
 // Show message
 $message = '';
-$url = $urlwithroot.'/api/index.php/login?login=<strong>auserlogin</strong>&password=<strong>thepassword</strong>[&reset=1]';
+//$url = $urlwithroot.'/api/index.php/login?login=<strong>auserlogin</strong>&password=<strong>thepassword</strong>[&reset=1]';
+$url = $urlwithroot.'/api/index.php/login?login=auserlogin&password=thepassword[&reset=1]';
 $message .= '<span class="opacitymedium">'.$langs->trans("UrlToGetKeyToUseAPIs").':</span><br>';
-$message .= img_picto('', 'globe').' '.$url;
+$message .= '<div class="urllink soixantepercent">'.img_picto('', 'globe').' <input type="text" class="quatrevingtpercent" id="urltogettoken" value="'.$url.'"></div>';
 print $message;
+print ajax_autoselect("urltogettoken");
 print '<br>';
 print '<br>';
 
 // Explorer
-print '<u>'.$langs->trans("ApiExporerIs").':</u><br>';
+print '<span class="opacitymedium">'.$langs->trans("ApiExporerIs").':</span><br>';
 if (dol_is_dir(DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/explorer')) {
 	$url = DOL_MAIN_URL_ROOT.'/api/index.php/explorer';
-	print img_picto('', 'globe').' <a href="'.$url.'" target="_blank">'.$url."</a><br>\n";
+	print '<div class="urllink soixantepercent">'.img_picto('', 'globe').' <a href="'.$url.'" target="_blank">'.$url."</a></div><br>\n";
+	print '<div class="opacitymediumxxx"><br><span class="opacitymedium">'.$langs->trans("SwaggerDescriptionFile").':</span><br>';
+	$urlswagger = DOL_MAIN_URL_ROOT.'/api/index.php/explorer/swagger.json?DOLAPIKEY=youruserapikey';
+	//$urlswaggerreal = DOL_MAIN_URL_ROOT.'/api/index.php/explorer/swagger.json?DOLAPIKEY='.$user->api_key;
+	print '<div class="urllink soixantepercent">'.img_picto('', 'globe').' <a href="'.$urlswagger.'" target="_blank">'.$urlswagger."</a></div><br>\n";
+	print '</div>';
 } else {
 	$langs->load("errors");
 	print info_admin($langs->trans("ErrorNotAvailableWithThisDistribution"), 0, 0, 'error');

+ 28 - 5
htdocs/api/index.php

@@ -2,6 +2,7 @@
 /* Copyright (C) 2015	Jean-François Ferry		<jfefe@aternatik.fr>
  * Copyright (C) 2016	Laurent Destailleur		<eldy@users.sourceforge.net>
  * Copyright (C) 2017	Regis Houssin			<regis.houssin@inodbox.com>
+ * Copyright (C) 2021	Alexis LAURIER			<contact@alexislaurier.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
@@ -54,6 +55,12 @@ if (!empty($_SERVER['HTTP_DOLAPIENTITY'])) {
 	define("DOLENTITY", (int) $_SERVER['HTTP_DOLAPIENTITY']);
 }
 
+// When we request url to get the json file, we accept Cross site so we can include the descriptor into an external tool.
+if (preg_match('/\/explorer\/swagger\.json/', $_SERVER["PHP_SELF"])) {
+	header('Access-Control-Allow-Origin: *');
+	header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
+	header('Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY');
+}
 
 $res = 0;
 if (!$res && file_exists("../main.inc.php")) {
@@ -88,7 +95,7 @@ if (!empty($conf->global->MAIN_NGINX_FIX)) {
 // Enable and test if module Api is enabled
 if (empty($conf->global->MAIN_MODULE_API)) {
 	$langs->load("admin");
-	dol_syslog("Call Dolibarr API interfaces with module REST disabled");
+	dol_syslog("Call of Dolibarr API interfaces with module API REST are disabled");
 	print $langs->trans("WarningModuleNotActive", 'Api').'.<br><br>';
 	print $langs->trans("ToActivateModule");
 	//session_destroy();
@@ -307,12 +314,28 @@ if (!empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' &&
 //var_dump($api->r->apiVersionMap);
 //exit;
 
+// We do not want that restler output data if we use native compression (default behaviour) but we want to have it returned into a string.
+Luracast\Restler\Defaults::$returnResponse = (empty($conf->global->API_DISABLE_COMPRESSION) && !empty($_SERVER['HTTP_ACCEPT_ENCODING']));
+
 // Call API (we suppose we found it).
 // The handle will use the file api/temp/routes.php to get data to run the API. If the file exists and the entry for API is not found, it will return 404.
+$result = $api->r->handle();
+
+if (Luracast\Restler\Defaults::$returnResponse) {
+	// We try to compress data
+	if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && is_callable('brotli_compress')) {
+		header('Content-Encoding: br');
+		$result = brotli_compress($result, 11, BROTLI_TEXT);
+	} elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && is_callable('bzcompress')) {
+		header('Content-Encoding: bz');
+		$result = bzcompress($result, 9);
+	} elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && is_callable('gzencode')) {
+		header('Content-Encoding: gzip');
+		$result = gzencode($result, 9);
+	}
 
-//Luracast\Restler\Defaults::$returnResponse = true;
-//print $api->r->handle();
-
-$api->r->handle();
+	// Restler did not output data yet, we return it now
+	echo $result;
+}
 
 //session_destroy();

+ 1 - 1
htdocs/asset/class/asset_type.class.php

@@ -332,7 +332,7 @@ class AssetType extends CommonObject
 	/**
 	 * 	Return array of Asset objects for asset type this->id (or all if this->id not defined)
 	 *
-	 * 	@param	string	$excludefilter		Filter to exclude
+	 * 	@param	string	$excludefilter		Filter to exclude. This parameter must not be provided by input of users
 	 *  @param	int		$mode				0=Return array of asset instance
 	 *  									1=Return array of asset instance without extra data
 	 *  									2=Return array of asset id only

+ 1 - 1
htdocs/bom/bom_agenda.php

@@ -86,7 +86,7 @@ if ($id > 0 || !empty($ref)) {
 //if ($user->socid > 0) accessforbidden();
 //if ($user->socid > 0) $socid = $user->socid;
 $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
-restrictedArea($user, 'bom', $object->id, '', '', 'fk_soc', 'rowid', $isdraft);
+restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft);
 
 
 /*

+ 1 - 1
htdocs/bom/bom_card.php

@@ -76,7 +76,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be includ
 //if ($user->socid > 0) accessforbidden();
 //if ($user->socid > 0) $socid = $user->socid;
 $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
-$result = restrictedArea($user, 'bom', $object->id, '', '', 'fk_soc', 'rowid', $isdraft);
+$result = restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft);
 
 $permissionnote = $user->rights->bom->write; // Used by the include of actions_setnotes.inc.php
 $permissiondellink = $user->rights->bom->write; // Used by the include of actions_dellink.inc.php

+ 1 - 1
htdocs/bom/bom_document.php

@@ -83,7 +83,7 @@ if ($id > 0 || !empty($ref)) {
 //if ($user->socid > 0) accessforbidden();
 //if ($user->socid > 0) $socid = $user->socid;
 $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
-restrictedArea($user, 'bom', $object->id, '', '', 'fk_soc', 'rowid', $isdraft);
+restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft);
 
 
 /*

+ 1 - 1
htdocs/bom/bom_note.php

@@ -63,7 +63,7 @@ $permissionnote = $user->rights->bom->write; // Used by the include of actions_s
 //if ($user->socid > 0) accessforbidden();
 //if ($user->socid > 0) $socid = $user->socid;
 $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
-restrictedArea($user, 'bom', $object->id, '', '', 'fk_soc', 'rowid', $isdraft);
+restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft);
 
 
 /*

+ 2 - 2
htdocs/bom/class/api_boms.class.php

@@ -134,14 +134,14 @@ class Boms extends DolibarrApi
 			$sql .= " AND t.fk_soc = sc.fk_soc";
 		}
 		if ($restrictonsocid && $socid) {
-			$sql .= " AND t.fk_soc = ".$socid;
+			$sql .= " AND t.fk_soc = ".((int) $socid);
 		}
 		if ($restrictonsocid && $search_sale > 0) {
 			$sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
 		}
 		// Insert sale filter
 		if ($restrictonsocid && $search_sale > 0) {
-			$sql .= " AND sc.fk_user = ".$search_sale;
+			$sql .= " AND sc.fk_user = ".((int) $search_sale);
 		}
 		if ($sqlfilters) {
 			if (!DolibarrApi::_checkFilters($sqlfilters)) {

+ 1 - 1
htdocs/bookmarks/bookmarks.lib.php

@@ -53,7 +53,7 @@ function printDropdownBookmarksList()
 		if (is_array($_POST)) {
 			foreach ($_POST as $key => $val) {
 				if (preg_match('/^search_/', $key) && $val != '') {
-					$tmpurl .= ($tmpurl ? '&' : '').$key.'='.$val;
+					$tmpurl .= ($tmpurl ? '&' : '').http_build_query(array($key => $val));
 				}
 			}
 		}

+ 1 - 0
htdocs/cashdesk/admin/cashdesk.php

@@ -45,6 +45,7 @@ $langs->loadLangs(array("admin", "cashdesk"));
 /*
  * Actions
  */
+
 if (GETPOST('action', 'alpha') == 'set') {
 	$db->begin();
 

+ 10 - 0
htdocs/cashdesk/affContenu.php

@@ -22,6 +22,7 @@
  *	\ingroup    cashdesk
  *	\brief      Include to show main page for cashdesk module
  */
+
 require_once 'class/Facturation.class.php';
 
 // Si nouvelle vente, reinitialisation des donnees (destruction de l'objet et vidage de la table contenant la liste des articles)
@@ -39,6 +40,15 @@ if (isset($_SESSION['serObjFacturation'])) {
 	$obj_facturation = new Facturation();
 }
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
+
+/*
+ * View
+ */
+
 // $obj_facturation contains data for all invoice total + selection of current product
 
 $obj_facturation->calculTotaux(); // Redefine prix_total_ttc, prix_total_ht et montant_tva from $_SESSION['poscart']

+ 4 - 0
htdocs/cashdesk/affIndex.php

@@ -38,6 +38,10 @@ if ($_SESSION['uid'] <= 0) {
 // Load translation files required by the page
 $langs->loadLangs(array("companies", "compta", "cashdesk"));
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
 
 /*
  * View

+ 4 - 0
htdocs/cashdesk/affPied.php

@@ -21,6 +21,10 @@
  *	\brief      Bottom of main page of point of sale module
  */
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
 ?>
 <!-- affPied.php -->
 <div class="pied">

+ 4 - 0
htdocs/cashdesk/deconnexion.php

@@ -40,5 +40,9 @@ require_once '../main.inc.php';
 // This destroy tag that say "Point of Sale session is on".
 unset($_SESSION['uid']);
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
 header('Location: '.DOL_URL_ROOT.'/cashdesk/index.php');
 exit;

+ 3 - 0
htdocs/cashdesk/facturation.php

@@ -26,6 +26,9 @@
  */
 
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
 
 
 /*

+ 9 - 0
htdocs/cashdesk/facturation_dhtml.php

@@ -47,6 +47,15 @@ if (!defined('NOREQUIREAJAX')) {
 require '../main.inc.php';
 require_once DOL_DOCUMENT_ROOT.'/cashdesk/include/environnement.php';
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
+
+/*
+ * View
+ */
+
 top_httphead('text/html');
 
 $search = GETPOST("code", "alpha");

+ 8 - 0
htdocs/cashdesk/facturation_verif.php

@@ -34,6 +34,14 @@ $action = GETPOST('action', 'aZ09');
 $obj_facturation = unserialize($_SESSION['serObjFacturation']);
 unset($_SESSION['serObjFacturation']);
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
+
+/*
+ * View
+ */
 
 switch ($action) {
 	default:

+ 5 - 0
htdocs/cashdesk/index.php

@@ -43,6 +43,11 @@ $err = GETPOST("err");
 // Instantiate hooks of thirdparty module only if not already define
 $hookmanager->initHooks(array('cashdeskloginpage'));
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
+
 /*
  * View
  */

+ 6 - 0
htdocs/cashdesk/index_verif.php

@@ -41,6 +41,12 @@ $bankid_cash = (GETPOST("CASHDESK_ID_BANKACCOUNT_CASH") > 0) ?GETPOST("CASHDESK_
 $bankid_cheque = (GETPOST("CASHDESK_ID_BANKACCOUNT_CHEQUE") > 0) ?GETPOST("CASHDESK_ID_BANKACCOUNT_CHEQUE", 'int') : $conf->global->CASHDESK_ID_BANKACCOUNT_CHEQUE;
 $bankid_cb = (GETPOST("CASHDESK_ID_BANKACCOUNT_CB") > 0) ?GETPOST("CASHDESK_ID_BANKACCOUNT_CB", 'int') : $conf->global->CASHDESK_ID_BANKACCOUNT_CB;
 
+
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
+
 // Check username
 if (empty($username)) {
 	$retour = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Login"));

+ 9 - 0
htdocs/cashdesk/validation_ticket.php

@@ -26,6 +26,15 @@ require_once DOL_DOCUMENT_ROOT.'/cashdesk/include/environnement.php';
 require_once DOL_DOCUMENT_ROOT.'/cashdesk/class/Facturation.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
+
+/*
+ * Actions
+ */
+
 $obj_facturation = unserialize($_SESSION['serObjFacturation']);
 unset($_SESSION['serObjFacturation']);
 

+ 9 - 0
htdocs/cashdesk/validation_verif.php

@@ -36,6 +36,15 @@ $obj_facturation = unserialize($_SESSION['serObjFacturation']);
 $action = GETPOST('action', 'aZ09');
 $bankaccountid = GETPOST('cashdeskbank');
 
+if (empty($user->rights->cashdesk->run)) {
+	accessforbidden();
+}
+
+
+/*
+ * Actions
+ */
+
 switch ($action) {
 	default:
 		$redirection = DOL_URL_ROOT.'/cashdesk/affIndex.php?menutpl=validation';

+ 4 - 5
htdocs/categories/class/categorie.class.php

@@ -1300,7 +1300,7 @@ class Categorie extends CommonObject
 		$sql = "SELECT c.rowid";
 		$sql .= " FROM ".MAIN_DB_PREFIX."categorie as c ";
 		$sql .= " WHERE c.entity IN (".getEntity('category').")";
-		$sql .= " AND c.type = ".$type;
+		$sql .= " AND c.type = ".((int) $type);
 		$sql .= " AND c.fk_parent = ".$this->fk_parent;
 		$sql .= " AND c.label = '".$this->db->escape($this->label)."'";
 
@@ -1520,7 +1520,6 @@ class Categorie extends CommonObject
 		return $cats;
 	}
 
-
 	/**
 	 * 	Returns categories whose id or name match
 	 * 	add wildcards in the name unless $exact = true
@@ -1555,7 +1554,7 @@ class Categorie extends CommonObject
 		$sql .= " AND entity IN (".getEntity('category').")";
 		if ($nom) {
 			if (!$exact) {
-				$nom = '%'.str_replace('*', '%', $nom).'%';
+				$nom = '%'.$this->db->escape(str_replace('*', '%', $nom)).'%';
 			}
 			if (!$case) {
 				$sql .= " AND label LIKE '".$this->db->escape($nom)."'";
@@ -1564,7 +1563,7 @@ class Categorie extends CommonObject
 			}
 		}
 		if ($id) {
-			$sql .= " AND rowid = '".$id."'";
+			$sql .= " AND rowid = ".((int) $id);
 		}
 
 		$res = $this->db->query($sql);
@@ -1792,7 +1791,7 @@ class Categorie extends CommonObject
 			$sql = "SELECT rowid";
 			$sql .= " FROM ".MAIN_DB_PREFIX."categorie_lang";
 			$sql .= " WHERE fk_category=".$this->id;
-			$sql .= " AND lang='".$key."'";
+			$sql .= " AND lang = '".$this->db->escape($key)."'";
 
 			$result = $this->db->query($sql);
 

+ 0 - 1
htdocs/categories/edit.php

@@ -99,7 +99,6 @@ if ($action == 'update' && $user->rights->categorie->creer) {
 	$object->visible        = $visible;
 	$object->fk_parent = $parent != -1 ? $parent : 0;
 
-
 	if (empty($object->label)) {
 		$error++;
 		$action = 'edit';

+ 4 - 4
htdocs/categories/index.php

@@ -116,15 +116,15 @@ if (empty($nosearch)) {
 		print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("FoundCats").'</td></tr>';
 
 		foreach ($cats as $cat) {
-			$color = $categstatic->color ? ' style="background: #'.sprintf("%06s", $categstatic->color).';"' : ' style="background: #bbb"';
-
-			print "\t".'<tr class="oddeven">'."\n";
-			print "\t\t<td>";
 			$categstatic->id = $cat->id;
 			$categstatic->ref = $cat->label;
 			$categstatic->label = $cat->label;
 			$categstatic->type = $cat->type;
 			$categstatic->color = $cat->color;
+			$color = $categstatic->color ? ' style="background: #'.sprintf("%06s", $categstatic->color).';"' : ' style="background: #bbb"';
+
+			print "\t".'<tr class="oddeven">'."\n";
+			print "\t\t<td>";
 			print '<span class="noborderoncategories"'.$color.'>';
 			print $categstatic->getNomUrl(1, '');
 			print '</span>';

+ 1 - 1
htdocs/categories/photos.php

@@ -66,7 +66,7 @@ $upload_dir = $conf->categorie->multidir_output[$object->entity];
  * Actions
  */
 
-if (isset($_FILES['userfile']) && $_FILES['userfile']['size'] > 0 && $_POST["sendit"] && !empty($conf->global->MAIN_UPLOAD_DOC)) {
+if (isset($_FILES['userfile']) && $_FILES['userfile']['size'] > 0 && GETPOST("sendit") && !empty($conf->global->MAIN_UPLOAD_DOC)) {
 	if ($object->id) {
 		$file = $_FILES['userfile'];
 		if (is_array($file['name']) && count($file['name']) > 0) {

+ 2 - 1
htdocs/comm/action/card.php

@@ -1896,7 +1896,8 @@ if ($id > 0) {
 		if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) {
 			print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td>';
 			print $object->getTypePicto();
-			print $langs->trans($object->type).'</td></tr>';
+			print $langs->trans("Action".$object->type_code);
+			print '</td></tr>';
 		}
 
 		// Full day event

+ 4 - 4
htdocs/comm/action/class/actioncomm.class.php

@@ -1227,17 +1227,17 @@ class ActionComm extends CommonObject
 		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
 		$sql .= " WHERE a.entity IN (".getEntity('agenda').")";
 		if (!empty($socid)) {
-			$sql .= " AND a.fk_soc = ".$socid;
+			$sql .= " AND a.fk_soc = ".((int) $socid);
 		}
 		if (!empty($elementtype)) {
 			if ($elementtype == 'project') {
-				$sql .= ' AND a.fk_project = '.$fk_element;
+				$sql .= ' AND a.fk_project = '.((int) $fk_element);
 			} elseif ($elementtype == 'contact') {
 				$sql .= ' AND a.id IN';
 				$sql .= " (SELECT fk_actioncomm FROM ".MAIN_DB_PREFIX."actioncomm_resources WHERE";
-				$sql .= " element_type = 'socpeople' AND fk_element = ".$fk_element.')';
+				$sql .= " element_type = 'socpeople' AND fk_element = ".((int) $fk_element).')';
 			} else {
-				$sql .= " AND a.fk_element = ".(int) $fk_element." AND a.elementtype = '".$db->escape($elementtype)."'";
+				$sql .= " AND a.fk_element = ".((int) $fk_element)." AND a.elementtype = '".$db->escape($elementtype)."'";
 			}
 		}
 		if (!empty($filter)) {

+ 3 - 3
htdocs/comm/action/class/api_agendaevents.class.php

@@ -147,14 +147,14 @@ class AgendaEvents extends DolibarrApi
 			}
 		}
 		if ($user_ids) {
-			$sql .= " AND t.fk_user_action IN (".$user_ids.")";
+			$sql .= " AND t.fk_user_action IN (".$this->db->sanitize($user_ids).")";
 		}
 		if ($socid > 0) {
-			$sql .= " AND t.fk_soc = ".$socid;
+			$sql .= " AND t.fk_soc = ".((int) $socid);
 		}
 		// Insert sale filter
 		if ($search_sale > 0) {
-			$sql .= " AND sc.fk_user = ".$search_sale;
+			$sql .= " AND sc.fk_user = ".((int) $search_sale);
 		}
 		// Add sql filters
 		if ($sqlfilters) {

+ 6 - 6
htdocs/comm/action/index.php

@@ -115,8 +115,8 @@ if ($dateselect > 0) {
 }
 
 // Set actioncode (this code must be same for setting actioncode into peruser, listacton and index)
-if (GETPOST('search_actioncode', 'array')) {
-	$actioncode = GETPOST('search_actioncode', 'array', 3);
+if (GETPOST('search_actioncode', 'array:aZ09')) {
+	$actioncode = GETPOST('search_actioncode', 'array:aZ09', 3);
 	if (!count($actioncode)) {
 		$actioncode = '0';
 	}
@@ -669,18 +669,18 @@ if (!empty($actioncode)) {
 			$sql .= " AND ca.type = 'systemauto'";
 		} else {
 			if (is_array($actioncode)) {
-				$sql .= " AND ca.code IN ('".implode("','", $actioncode)."')";
+				$sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")";
 			} else {
-				$sql .= " AND ca.code IN ('".implode("','", explode(',', $actioncode))."')";
+				$sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")";
 			}
 		}
 	}
 }
 if ($resourceid > 0) {
-	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".$db->escape($resourceid);
+	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".((int) $resourceid);
 }
 if ($pid) {
-	$sql .= " AND a.fk_project=".$db->escape($pid);
+	$sql .= " AND a.fk_project=".((int) $pid);
 }
 if (!$user->rights->societe->client->voir && !$socid) {
 	$sql .= " AND (a.fk_soc IS NULL OR sc.fk_user = ".$user->id.")";

+ 8 - 8
htdocs/comm/action/list.php

@@ -429,31 +429,31 @@ if (!empty($actioncode)) {
 			$sql .= " AND c.type = 'systemauto'";
 		} else {
 			if (is_array($actioncode)) {
-				$sql .= " AND c.code IN ('".implode("','", $actioncode)."')";
+				$sql .= " AND c.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")";
 			} else {
-				$sql .= " AND c.code IN ('".implode("','", explode(',', $actioncode))."')";
+				$sql .= " AND c.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")";
 			}
 		}
 	}
 }
 if ($resourceid > 0) {
-	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".$db->escape($resourceid);
+	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".((int) $resourceid);
 }
 if ($pid) {
-	$sql .= " AND a.fk_project=".$db->escape($pid);
+	$sql .= " AND a.fk_project=".((int) $pid);
 }
 if (!$user->rights->societe->client->voir && !$socid) {
 	$sql .= " AND (a.fk_soc IS NULL OR sc.fk_user = ".$user->id.")";
 }
 if ($socid > 0) {
-	$sql .= " AND s.rowid = ".$socid;
+	$sql .= " AND s.rowid = ".((int) $socid);
 }
 // We must filter on assignement table
 if ($filtert > 0 || $usergroup > 0) {
 	$sql .= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'";
 }
 if ($type) {
-	$sql .= " AND c.id = ".(int) $type;
+	$sql .= " AND c.id = ".((int) $type);
 }
 if ($search_status == '0') {
 	$sql .= " AND a.percent = 0";
@@ -486,10 +486,10 @@ if ($search_note) {
 if ($filtert > 0 || $usergroup > 0) {
 	$sql .= " AND (";
 	if ($filtert > 0) {
-		$sql .= "(ar.fk_element = ".$filtert." OR (ar.fk_element IS NULL AND a.fk_user_action=".$filtert."))"; // The OR is for backward compatibility
+		$sql .= "(ar.fk_element = ".((int) $filtert)." OR (ar.fk_element IS NULL AND a.fk_user_action = ".((int) $filtert)."))"; // The OR is for backward compatibility
 	}
 	if ($usergroup > 0) {
-		$sql .= ($filtert > 0 ? " OR " : "")." ugu.fk_usergroup = ".$usergroup;
+		$sql .= ($filtert > 0 ? " OR " : "")." ugu.fk_usergroup = ".((int) $usergroup);
 	}
 	$sql .= ")";
 }

+ 5 - 5
htdocs/comm/action/pertype.php

@@ -540,24 +540,24 @@ if (!empty($actioncode)) {
 			$sql .= " AND ca.type = 'systemauto'";
 		} else {
 			if (is_array($actioncode)) {
-				$sql .= " AND ca.code IN ('".implode("','", $actioncode)."')";
+				$sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")";
 			} else {
-				$sql .= " AND ca.code IN ('".implode("','", explode(',', $actioncode))."')";
+				$sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")";
 			}
 		}
 	}
 }
 if ($resourceid > 0) {
-	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".$db->escape($resourceid);
+	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".((int) $resourceid);
 }
 if ($pid) {
-	$sql .= " AND a.fk_project=".$db->escape($pid);
+	$sql .= " AND a.fk_project=".((int) $pid);
 }
 if (!$user->rights->societe->client->voir && !$socid) {
 	$sql .= " AND (a.fk_soc IS NULL OR sc.fk_user = ".$user->id.")";
 }
 if ($socid > 0) {
-	$sql .= ' AND a.fk_soc = '.$socid;
+	$sql .= ' AND a.fk_soc = '.((int) $socid);
 }
 // We must filter on assignement table
 if ($filtert > 0 || $usergroup > 0) {

+ 7 - 7
htdocs/comm/action/peruser.php

@@ -105,8 +105,8 @@ $type = GETPOST("search_type", 'alpha') ?GETPOST("search_type", 'alpha') : GETPO
 $maxprint = ((GETPOST("maxprint", 'int') != '') ?GETPOST("maxprint", 'int') : $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW);
 $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
 // Set actioncode (this code must be same for setting actioncode into peruser, listacton and index)
-if (GETPOST('search_actioncode', 'array')) {
-	$actioncode = GETPOST('search_actioncode', 'array', 3);
+if (GETPOST('search_actioncode', 'array:aZ09')) {
+	$actioncode = GETPOST('search_actioncode', 'array:aZ09', 3);
 	if (!count($actioncode)) {
 		$actioncode = '0';
 	}
@@ -562,24 +562,24 @@ if (!empty($actioncode)) {
 			$sql .= " AND ca.type = 'systemauto'";
 		} else {
 			if (is_array($actioncode)) {
-				$sql .= " AND ca.code IN ('".implode("','", $actioncode)."')";
+				$sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")";
 			} else {
-				$sql .= " AND ca.code IN ('".implode("','", explode(',', $actioncode))."')";
+				$sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")";
 			}
 		}
 	}
 }
 if ($resourceid > 0) {
-	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".$db->escape($resourceid);
+	$sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".((int) $resourceid);
 }
 if ($pid) {
-	$sql .= " AND a.fk_project=".$db->escape($pid);
+	$sql .= " AND a.fk_project = ".((int) $pid);
 }
 if (!$user->rights->societe->client->voir && !$socid) {
 	$sql .= " AND (a.fk_soc IS NULL OR sc.fk_user = ".$user->id.")";
 }
 if ($socid > 0) {
-	$sql .= ' AND a.fk_soc = '.$socid;
+	$sql .= ' AND a.fk_soc = '.((int) $socid);
 }
 // We must filter on assignement table
 if ($filtert > 0 || $usergroup > 0) {

+ 1 - 1
htdocs/comm/card.php

@@ -162,7 +162,7 @@ if (empty($reshook)) {
 	// set accountancy code
 	if ($action == 'setcustomeraccountancycode') {
 		$result = $object->fetch($id);
-		$object->code_compta = $_POST["customeraccountancycode"];
+		$object->code_compta = GETPOST("customeraccountancycode");
 		$result = $object->update($object->id, $user, 1, 1, 0);
 		if ($result < 0) {
 			setEventMessages($object->error, $object->errors, 'errors');

+ 1 - 1
htdocs/comm/contact.php

@@ -101,7 +101,7 @@ if ($type == "f") {
 	$sql .= " AND s.fournisseur = 1";
 }
 if ($socid) {
-	$sql .= " AND s.rowid = ".$socid;
+	$sql .= " AND s.rowid = ".((int) $socid);
 }
 
 if (dol_strlen($stcomm)) {

+ 1 - 1
htdocs/comm/index.php

@@ -169,7 +169,7 @@ if (!empty($conf->propal->enabled) && $user->rights->propal->lire) {
 		$sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;
 	}
 	if ($socid) {
-		$sql .= " AND s.rowid = ".$socid;
+		$sql .= " AND s.rowid = ".((int) $socid);
 	}
 
 	$resql = $db->query($sql);

+ 1 - 1
htdocs/comm/mailing/advtargetemailing.php

@@ -397,7 +397,7 @@ if ($action == 'delete') {
 	}
 }
 
-if ($_POST["button_removefilter"]) {
+if (GETPOST("button_removefilter")) {
 	$search_nom = '';
 	$search_prenom = '';
 	$search_email = '';

+ 6 - 5
htdocs/comm/mailing/card.php

@@ -46,6 +46,7 @@ if (!$user->rights->mailing->lire || (empty($conf->global->EXTERNAL_USERS_ARE_AU
 
 $id = (GETPOST('mailid', 'int') ? GETPOST('mailid', 'int') : GETPOST('id', 'int'));
 $action = GETPOST('action', 'aZ09');
+$cancel = GETPOST('cancel');
 $confirm = GETPOST('confirm', 'alpha');
 $urlfrom = GETPOST('urlfrom');
 
@@ -393,12 +394,12 @@ if (empty($reshook)) {
 	}
 
 	// Action send test emailing
-	if ($action == 'send' && empty($_POST["cancel"])) {
+	if ($action == 'send' && ! $cancel) {
 		$error = 0;
 
 		$upload_dir = $conf->mailing->dir_output."/".get_exdir($object->id, 2, 0, 1, $object, 'mailing');
 
-		$object->sendto = $_POST["sendto"];
+		$object->sendto = GETPOST("sendto", 'alphawithlgt');
 		if (!$object->sendto) {
 			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("MailTo")), null, 'errors');
 			$error++;
@@ -537,7 +538,7 @@ if (empty($reshook)) {
 	}
 
 	// Action of file remove
-	if (!empty($_POST["removedfile"])) {
+	if (GETPOST("removedfile")) {
 		$upload_dir = $conf->mailing->dir_output."/".get_exdir($object->id, 2, 0, 1, $object, 'mailing');
 
 		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
@@ -548,7 +549,7 @@ if (empty($reshook)) {
 	}
 
 	// Action of emailing update
-	if ($action == 'update' && empty($_POST["removedfile"]) && empty($_POST["cancel"])) {
+	if ($action == 'update' && !GETPOST("removedfile") && !$cancel) {
 		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
 
 		$isupload = 0;
@@ -643,7 +644,7 @@ if (empty($reshook)) {
 		}
 	}
 
-	if (!empty($_POST["cancel"])) {
+	if ($cancel) {
 		$action = '';
 	}
 }

+ 24 - 24
htdocs/comm/mailing/class/advtargetemailing.class.php

@@ -559,34 +559,34 @@ class AdvanceTargetingMailing extends CommonObject
 				$sqlwhere[] = " (t.parent IN (SELECT rowid FROM ".MAIN_DB_PREFIX."societe WHERE (".$str.")))";
 			}
 			if (!empty($arrayquery['cust_status']) && count($arrayquery['cust_status']) > 0) {
-				$sqlwhere[] = " (t.status IN (".implode(',', $arrayquery['cust_status'])."))";
+				$sqlwhere[] = " (t.status IN (".$this->db->sanitize(implode(',', $arrayquery['cust_status']))."))";
 			}
 			if (!empty($arrayquery['cust_typecust']) && count($arrayquery['cust_typecust']) > 0) {
-				$sqlwhere[] = " (t.client IN (".implode(',', $arrayquery['cust_typecust'])."))";
+				$sqlwhere[] = " (t.client IN (".$this->db->sanitize(implode(',', $arrayquery['cust_typecust']))."))";
 			}
 			if (!empty($arrayquery['cust_comm_status']) && count($arrayquery['cust_comm_status'] > 0)) {
-				$sqlwhere[] = " (t.fk_stcomm IN (".implode(',', $arrayquery['cust_comm_status'])."))";
+				$sqlwhere[] = " (t.fk_stcomm IN (".$this->db->sanitize(implode(',', $arrayquery['cust_comm_status']))."))";
 			}
 			if (!empty($arrayquery['cust_prospect_status']) && count($arrayquery['cust_prospect_status']) > 0) {
-				$sqlwhere[] = " (t.fk_prospectlevel IN ('".implode("','", $arrayquery['cust_prospect_status'])."'))";
+				$sqlwhere[] = " (t.fk_prospectlevel IN (".$this->db->sanitize("'".implode("','", $arrayquery['cust_prospect_status'])."'", 1)."))";
 			}
 			if (!empty($arrayquery['cust_typeent']) && count($arrayquery['cust_typeent']) > 0) {
-				$sqlwhere[] = " (t.fk_typent IN (".implode(',', $arrayquery['cust_typeent'])."))";
+				$sqlwhere[] = " (t.fk_typent IN (".$this->db->sanitize(implode(',', $arrayquery['cust_typeent']))."))";
 			}
 			if (!empty($arrayquery['cust_saleman']) && count($arrayquery['cust_saleman']) > 0) {
-				$sqlwhere[] = " (saleman.fk_user IN (".implode(',', $arrayquery['cust_saleman'])."))";
+				$sqlwhere[] = " (saleman.fk_user IN (".$this->db->sanitize(implode(',', $arrayquery['cust_saleman']))."))";
 			}
 			if (!empty($arrayquery['cust_country']) && count($arrayquery['cust_country']) > 0) {
-				$sqlwhere[] = " (t.fk_pays IN (".implode(',', $arrayquery['cust_country'])."))";
+				$sqlwhere[] = " (t.fk_pays IN (".$this->db->sanitize(implode(',', $arrayquery['cust_country']))."))";
 			}
 			if (!empty($arrayquery['cust_effectif_id']) && count($arrayquery['cust_effectif_id']) > 0) {
-				$sqlwhere[] = " (t.fk_effectif IN (".implode(',', $arrayquery['cust_effectif_id'])."))";
+				$sqlwhere[] = " (t.fk_effectif IN (".$this->db->sanitize(implode(',', $arrayquery['cust_effectif_id']))."))";
 			}
 			if (!empty($arrayquery['cust_categ']) && count($arrayquery['cust_categ']) > 0) {
-				$sqlwhere[] = " (custcateg.fk_categorie IN (".implode(',', $arrayquery['cust_categ'])."))";
+				$sqlwhere[] = " (custcateg.fk_categorie IN (".$this->db->sanitize(implode(',', $arrayquery['cust_categ']))."))";
 			}
 			if (!empty($arrayquery['cust_language']) && count($arrayquery['cust_language']) > 0) {
-				$sqlwhere[] = " (t.default_lang IN ('".implode("','", $arrayquery['cust_language'])."'))";
+				$sqlwhere[] = " (t.default_lang IN (".$this->db->sanitize("'".implode("','", $arrayquery['cust_language'])."'", 1)."))";
 			}
 
 			//Standard Extrafield feature
@@ -618,7 +618,7 @@ class AdvanceTargetingMailing extends CommonObject
 						}
 					} else {
 						if (is_array($arrayquery['options_'.$key])) {
-							$sqlwhere[] = " (te.".$key." IN ('".implode("','", $arrayquery['options_'.$key])."'))";
+							$sqlwhere[] = " (te.".$key." IN (".$this->db->sanitize("'".implode("','", $arrayquery['options_'.$key])."'", 1)."))";
 						} elseif (!empty($arrayquery['options_'.$key])) {
 							$sqlwhere[] = " (te.".$key." LIKE '".$this->db->escape($arrayquery['options_'.$key])."')";
 						}
@@ -703,7 +703,7 @@ class AdvanceTargetingMailing extends CommonObject
 				$sqlwhere[] = " (t.statut IN (".$this->db->sanitize($this->db->escape(implode(',', $arrayquery['contact_status'])))."))";
 			}
 			if (!empty($arrayquery['contact_civility']) && count($arrayquery['contact_civility']) > 0) {
-				$sqlwhere[] = " (t.civility IN ('".$this->db->sanitize($this->db->escape(implode("','", $arrayquery['contact_civility'])))."'))";
+				$sqlwhere[] = " (t.civility IN (".$this->db->sanitize("'".implode("','", $arrayquery['contact_civility'])."'", 1)."))";
 			}
 			if ($arrayquery['contact_no_email'] != '') {
 				$tmpwhere = '';
@@ -762,7 +762,7 @@ class AdvanceTargetingMailing extends CommonObject
 						}
 					} else {
 						if (is_array($arrayquery['options_'.$key.'_cnct'])) {
-							$sqlwhere[] = " (te.".$key." IN ('".implode("','", $arrayquery['options_'.$key.'_cnct'])."'))";
+							$sqlwhere[] = " (te.".$key." IN (".$this->db->sanitize("'".implode("','", $arrayquery['options_'.$key.'_cnct'])."'", 1)."))";
 						} elseif (!empty($arrayquery['options_'.$key.'_cnct'])) {
 							$sqlwhere[] = " (te.".$key." LIKE '".$this->db->escape($arrayquery['options_'.$key.'_cnct'])."')";
 						}
@@ -797,34 +797,34 @@ class AdvanceTargetingMailing extends CommonObject
 						$sqlwhere[] = " (ts.parent IN (SELECT rowid FROM ".MAIN_DB_PREFIX."societe WHERE (".$str.")))";
 					}
 					if (!empty($arrayquery['cust_status']) && count($arrayquery['cust_status']) > 0) {
-						$sqlwhere[] = " (ts.status IN (".implode(',', $arrayquery['cust_status'])."))";
+						$sqlwhere[] = " (ts.status IN (".$this->db->sanitize(implode(',', $arrayquery['cust_status']))."))";
 					}
 					if (!empty($arrayquery['cust_typecust']) && count($arrayquery['cust_typecust']) > 0) {
-						$sqlwhere[] = " (ts.client IN (".implode(',', $arrayquery['cust_typecust'])."))";
+						$sqlwhere[] = " (ts.client IN (".$this->db->sanitize(implode(',', $arrayquery['cust_typecust']))."))";
 					}
 					if (!empty($arrayquery['cust_comm_status']) && count($arrayquery['cust_comm_status'] > 0)) {
-						$sqlwhere[] = " (ts.fk_stcomm IN (".implode(',', $arrayquery['cust_comm_status'])."))";
+						$sqlwhere[] = " (ts.fk_stcomm IN (".$this->db->sanitize(implode(',', $arrayquery['cust_comm_status']))."))";
 					}
 					if (!empty($arrayquery['cust_prospect_status']) && count($arrayquery['cust_prospect_status']) > 0) {
-						$sqlwhere[] = " (ts.fk_prospectlevel IN ('".implode("','", $arrayquery['cust_prospect_status'])."'))";
+						$sqlwhere[] = " (ts.fk_prospectlevel IN ('".$this->db->sanitize(implode("','", $arrayquery['cust_prospect_status']))."'))";
 					}
 					if (!empty($arrayquery['cust_typeent']) && count($arrayquery['cust_typeent']) > 0) {
-						$sqlwhere[] = " (ts.fk_typent IN (".implode(',', $arrayquery['cust_typeent'])."))";
+						$sqlwhere[] = " (ts.fk_typent IN (".$this->db->sanitize(implode(',', $arrayquery['cust_typeent']))."))";
 					}
 					if (!empty($arrayquery['cust_saleman']) && count($arrayquery['cust_saleman']) > 0) {
-						$sqlwhere[] = " (saleman.fk_user IN (".implode(',', $arrayquery['cust_saleman'])."))";
+						$sqlwhere[] = " (saleman.fk_user IN (".$this->db->sanitize(implode(',', $arrayquery['cust_saleman']))."))";
 					}
 					if (!empty($arrayquery['cust_country']) && count($arrayquery['cust_country']) > 0) {
-						$sqlwhere[] = " (ts.fk_pays IN (".implode(',', $arrayquery['cust_country'])."))";
+						$sqlwhere[] = " (ts.fk_pays IN (".$this->db->sanitize(implode(',', $arrayquery['cust_country']))."))";
 					}
 					if (!empty($arrayquery['cust_effectif_id']) && count($arrayquery['cust_effectif_id']) > 0) {
-						$sqlwhere[] = " (ts.fk_effectif IN (".implode(',', $arrayquery['cust_effectif_id'])."))";
+						$sqlwhere[] = " (ts.fk_effectif IN (".$this->db->sanitize(implode(',', $arrayquery['cust_effectif_id']))."))";
 					}
 					if (!empty($arrayquery['cust_categ']) && count($arrayquery['cust_categ']) > 0) {
-						$sqlwhere[] = " (custcateg.fk_categorie IN (".implode(',', $arrayquery['cust_categ'])."))";
+						$sqlwhere[] = " (custcateg.fk_categorie IN (".$this->db->sanitize(implode(',', $arrayquery['cust_categ']))."))";
 					}
 					if (!empty($arrayquery['cust_language']) && count($arrayquery['cust_language']) > 0) {
-						$sqlwhere[] = " (ts.default_lang IN ('".implode("','", $arrayquery['cust_language'])."'))";
+						$sqlwhere[] = " (ts.default_lang IN ('".$this->db->sanitize(implode("','", $arrayquery['cust_language']))."'))";
 					}
 
 					//Standard Extrafield feature
@@ -860,7 +860,7 @@ class AdvanceTargetingMailing extends CommonObject
 								}
 							} else {
 								if (is_array($arrayquery['options_'.$key])) {
-									$sqlwhere[] = " (tse.".$key." IN ('".implode("','", $arrayquery['options_'.$key])."'))";
+									$sqlwhere[] = " (tse.".$key." IN (".$this->db->sanitize("'".implode("','", $arrayquery['options_'.$key])."'", 1)."))";
 								} elseif (!empty($arrayquery['options_'.$key])) {
 									$sqlwhere[] = " (tse.".$key." LIKE '".$this->db->escape($arrayquery['options_'.$key])."')";
 								}

+ 5 - 2
htdocs/comm/multiprix.php

@@ -30,6 +30,9 @@ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
 // Load translation files required by the page
 $langs->loadLangs(array('orders', 'companies'));
 
+$action = GETPOST('action', 'alpha');
+$cancel = GETPOST('cancel', 'alpha');
+
 $id = GETPOST('id', 'int');
 $_socid = GETPOST("id", 'int');
 // Security check
@@ -42,10 +45,10 @@ if ($user->socid > 0) {
  * Actions
  */
 
-if ($_POST["action"] == 'setpricelevel') {
+if ($action == 'setpricelevel') {
 	$soc = new Societe($db);
 	$soc->fetch($id);
-	$soc->set_price_level($_POST["price_level"], $user);
+	$soc->set_price_level(GETPOST("price_level"), $user);
 
 	header("Location: multiprix.php?id=".$id);
 	exit;

+ 2 - 2
htdocs/comm/propal/card.php

@@ -775,9 +775,9 @@ if (empty($reshook)) {
 			$object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
 		}
 	} elseif ($action == "setabsolutediscount" && $usercancreate) {
-		if ($_POST["remise_id"]) {
+		if (GETPOST("remise_id", "int")) {
 			if ($object->id > 0) {
-				$result = $object->insert_discount($_POST["remise_id"]);
+				$result = $object->insert_discount(GETPOST("remise_id", "int"));
 				if ($result < 0) {
 					setEventMessages($object->error, $object->errors, 'errors');
 				}

+ 2 - 2
htdocs/comm/propal/class/api_proposals.class.php

@@ -181,14 +181,14 @@ class Proposals extends DolibarrApi
 			$sql .= " AND t.fk_soc = sc.fk_soc";
 		}
 		if ($socids) {
-			$sql .= " AND t.fk_soc IN (".$socids.")";
+			$sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")";
 		}
 		if ($search_sale > 0) {
 			$sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
 		}
 		// Insert sale filter
 		if ($search_sale > 0) {
-			$sql .= " AND sc.fk_user = ".$search_sale;
+			$sql .= " AND sc.fk_user = ".((int) $search_sale);
 		}
 		// Add sql filters
 		if ($sqlfilters) {

+ 2 - 2
htdocs/comm/propal/class/propal.class.php

@@ -2734,7 +2734,7 @@ class Propal extends CommonObject
 			$sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;
 		}
 		if ($socid) {
-			$sql .= " AND s.rowid = ".$socid;
+			$sql .= " AND s.rowid = ".((int) $socid);
 		}
 		if ($draft) {
 			$sql .= " AND p.fk_statut = ".self::STATUS_DRAFT;
@@ -2821,7 +2821,7 @@ class Propal extends CommonObject
 		if (count($linkedInvoices) > 0) {
 			$sql = "SELECT rowid as facid, ref, total, datef as df, fk_user_author, fk_statut, paye";
 			$sql .= " FROM ".MAIN_DB_PREFIX."facture";
-			$sql .= " WHERE rowid IN (".implode(',', $linkedInvoices).")";
+			$sql .= " WHERE rowid IN (".$this->db->sanitize(implode(',', $linkedInvoices)).")";
 
 			dol_syslog(get_class($this)."::InvoiceArrayList", LOG_DEBUG);
 			$resql = $this->db->query($sql);

+ 2 - 2
htdocs/comm/propal/index.php

@@ -106,7 +106,7 @@ if ($user->socid) {
 if (!$user->rights->societe->client->voir && !$socid) {
 	$sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;
 }
-$sql .= " AND p.fk_statut IN (".implode(" ,", $listofstatus).")";
+$sql .= " AND p.fk_statut IN (".$db->sanitize(implode(" ,", $listofstatus)).")";
 $sql .= " GROUP BY p.fk_statut";
 $resql = $db->query($sql);
 if ($resql) {
@@ -372,7 +372,7 @@ if (!empty($conf->propal->enabled) && $user->rights->propale->lire) {
 		$sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id;
 	}
 	if ($socid) {
-		$sql .= " AND s.rowid = ".$socid;
+		$sql .= " AND s.rowid = ".((int) $socid);
 	}
 	$sql .= " ORDER BY p.rowid DESC";
 

+ 13 - 13
htdocs/comm/propal/list.php

@@ -565,7 +565,7 @@ if ($socid > 0) {
 	$sql .= ' AND s.rowid = '.$socid;
 }
 if ($search_status != '' && $search_status != '-1') {
-	$sql .= ' AND p.fk_statut IN ('.$db->sanitize($db->escape($search_status)).')';
+	$sql .= ' AND p.fk_statut IN ('.$db->sanitize($search_status).')';
 }
 if ($search_date_start) {
 	$sql .= " AND p.datep >= '".$db->idate($search_date_start)."'";
@@ -1532,7 +1532,7 @@ if ($resql) {
 		}
 		// Amount HT
 		if (!empty($arrayfields['p.total_ht']['checked'])) {
-			print '<td class="nowrap right">'.price($obj->total_ht)."</td>\n";
+			print '<td class="nowrap right"><span class="amount">'.price($obj->total_ht)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
@@ -1543,7 +1543,7 @@ if ($resql) {
 		}
 		// Amount VAT
 		if (!empty($arrayfields['p.total_tva']['checked'])) {
-			print '<td class="nowrap right">'.price($obj->total_tva)."</td>\n";
+			print '<td class="nowrap right"><span class="amount">'.price($obj->total_tva)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
@@ -1554,7 +1554,7 @@ if ($resql) {
 		}
 		// Amount TTC
 		if (!empty($arrayfields['p.total_ttc']['checked'])) {
-			print '<td class="nowrap right">'.price($obj->total_ttc)."</td>\n";
+			print '<td class="nowrap right"><span class="amount">'.price($obj->total_ttc)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
@@ -1563,9 +1563,9 @@ if ($resql) {
 			}
 			$totalarray['val']['p.total_ttc'] += $obj->total_ttc;
 		}
-		// Amount invoiced
+		// Amount invoiced HT
 		if (!empty($arrayfields['p.total_ht_invoiced']['checked'])) {
-			print '<td class="nowrap right">'.price($totalInvoicedHT)."</td>\n";
+			print '<td class="nowrap right"><span class="amount">'.price($totalInvoicedHT)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
@@ -1574,9 +1574,9 @@ if ($resql) {
 			}
 			$totalarray['val']['p.total_ht_invoiced'] += $totalInvoicedHT;
 		}
-		// Amount invoiced
+		// Amount invoiced TTC
 		if (!empty($arrayfields['p.total_invoiced']['checked'])) {
-			print '<td class="nowrap right">'.price($totalInvoicedTTC)."</td>\n";
+			print '<td class="nowrap right"><span class="amount">'.price($totalInvoicedTTC)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
@@ -1604,35 +1604,35 @@ if ($resql) {
 		}
 		// Amount HT
 		if (!empty($arrayfields['p.multicurrency_total_ht']['checked'])) {
-			print '<td class="right nowrap">'.price($obj->multicurrency_total_ht)."</td>\n";
+			print '<td class="right nowrap"><span class="amount">'.price($obj->multicurrency_total_ht)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
 		}
 		// Amount VAT
 		if (!empty($arrayfields['p.multicurrency_total_tva']['checked'])) {
-			print '<td class="right nowrap">'.price($obj->multicurrency_total_tva)."</td>\n";
+			print '<td class="right nowrap"><span class="amount">'.price($obj->multicurrency_total_tva)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
 		}
 		// Amount TTC
 		if (!empty($arrayfields['p.multicurrency_total_ttc']['checked'])) {
-			print '<td class="right nowrap">'.price($obj->multicurrency_total_ttc)."</td>\n";
+			print '<td class="right nowrap"><span class="amount">'.price($obj->multicurrency_total_ttc)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
 		}
 		// Amount invoiced
 		if (!empty($arrayfields['p.multicurrency_total_ht_invoiced']['checked'])) {
-			print '<td class="nowrap right">'.price($multicurrency_totalInvoicedHT)."</td>\n";
+			print '<td class="nowrap right"><span class="amount">'.price($multicurrency_totalInvoicedHT)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}
 		}
 		// Amount invoiced
 		if (!empty($arrayfields['p.multicurrency_total_invoiced']['checked'])) {
-			print '<td class="nowrap right">'.price($multicurrency_totalInvoicedTTC)."</td>\n";
+			print '<td class="nowrap right"><span class="amount">'.price($multicurrency_totalInvoicedTTC)."</span></td>\n";
 			if (!$i) {
 				$totalarray['nbfield']++;
 			}

+ 1 - 1
htdocs/comm/propal/stats/index.php

@@ -103,7 +103,7 @@ dol_mkdir($dir);
 
 $stats = new PropaleStats($db, $socid, ($userid > 0 ? $userid : 0), $mode, ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0));
 if ($object_status != '' && $object_status >= 0) {
-	$stats->where .= ' AND p.fk_statut IN ('.$db->sanitize($db->escape($object_status)).')';
+	$stats->where .= ' AND p.fk_statut IN ('.$db->sanitize($object_status).')';
 }
 
 // Build graphic number of object

+ 2 - 2
htdocs/commande/class/api_orders.class.php

@@ -184,14 +184,14 @@ class Orders extends DolibarrApi
 			$sql .= " AND t.fk_soc = sc.fk_soc";
 		}
 		if ($socids) {
-			$sql .= " AND t.fk_soc IN (".$socids.")";
+			$sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")";
 		}
 		if ($search_sale > 0) {
 			$sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
 		}
 		// Insert sale filter
 		if ($search_sale > 0) {
-			$sql .= " AND sc.fk_user = ".$search_sale;
+			$sql .= " AND sc.fk_user = ".((int) $search_sale);
 		}
 		// Add sql filters
 		if ($sqlfilters) {

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

@@ -2300,8 +2300,8 @@ class Commande extends CommonOrder
 		if (count($array_of_product)) {
 			$sql = "SELECT fk_product, sum(ps.reel) as total";
 			$sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps";
-			$sql .= " WHERE ps.fk_product IN (".join(',', $array_of_product).")";
-			$sql .= ' GROUP BY fk_product ';
+			$sql .= " WHERE ps.fk_product IN (".$this->db->sanitize(join(',', $array_of_product)).")";
+			$sql .= ' GROUP BY fk_product';
 			$resql = $this->db->query($sql);
 			if ($resql) {
 				$num = $this->db->num_rows($resql);

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä