diff --git a/.travis.yml b/.travis.yml
index eef14f01386..1f4fc328a49 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -473,7 +473,7 @@ script:
- |
echo "Unit testing"
- # Ensure we catch errors. Set this to +e if you want to go to the end to see dolibarr.log file.
+ # Ensure we catch errors. Set this to +e instead of -e if you want to go to the end to see dolibarr.log file.
set -e
phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php
phpunitresult=$?
@@ -501,7 +501,7 @@ after_failure:
# Show upgrade log files
for ficlog in `ls $TRAVIS_BUILD_DIR/*.log`
do
- echo "Debugging informations for file $ficlog"
+ #echo "Debugging informations for file $ficlog"
#cat $ficlog
done
# Show Apache log file
diff --git a/ChangeLog b/ChangeLog
index 8721e272aa7..bee9d148544 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -232,7 +232,51 @@ Following changes may create regressions for some external modules, but were nec
***** ChangeLog for 16.0.5 compared to 16.0.4 *****
-TODO
+FIX: 16.0 propalestats Unknown column 'p.fk_soc' in 'on clause'
+FIX: #23804
+FIX: #23860
+FIX: #23966 Error "Param dbt_keyfield is required but not defined"
+FIX: accountancy lettering: better error management
+FIX: accountancy lettering: correctly calculated number of lettering operations done
+FIX: accountancy lettering: error management and prevention
+FIX: accountancy lettering: prevent null results when fetching link with payments
+FIX: Add missing hook on LibStatut
+FIX: Add more context for selectForFormsListWhere Hook
+FIX: attach file and send by mail in ticket
+FIX: bad check on if in get_all_ways
+FIX: Cannot import find type_fees with cgenericdic.class because it has id and not rowid
+FIX: clicktodial backtopage
+FIX: discount wasn't taken into account when adding a line in BOM
+FIX: expense reports: error when selecting mileage fees expense type if MAIN_USE_EXPENSE_IK disabled
+FIX: expense reports: JS error when selecting mileage fees expense type if MAIN_USE_EXPENSE_IK disabled
+FIX: Extrafields in Notes to unify with orders or invoices.
+FIX: fatal error on clicktodial backtopage
+FIX: filter sql accounting account
+FIX: Get data back on product update
+FIX: Get data back when error on command create
+FIX: label dictionary is used by barcode and member module
+FIX: mandatory date for service didnt work for invoice
+FIX: missing "authorid" for getNomUrl link right access
+FIX: missing getEntity filter
+FIX: vulnerability: missing protection on ajax public ticket page for valid email.
+FIX: Missing right to edit service note when module product is disabled
+FIX: multicompany compatibility
+FIX: object $user is not defined
+FIX: Object of class LDAP\Connection could not be converted to string
+FIX: parse error and NAN
+FIX: product ref fourn same size in supplier order/invoice as in product price fourn
+FIX: Profit calculation on project preview tab.
+FIX: Remove orphelan $this->db->rollback() in the function insertExtrafields()
+FIX: request new password with "mc" and "twofactor" authentication
+FIX: Resolve error message due to missing arguments
+FIX: select for task in event card
+FIX: several email sent to the same recipient when adding message from ticket
+FIX: shipping list for external user
+FIX: SQL error "unknown column p.fk_soc" because ANSI-92 joins take precedence over ANSI-89 joins
+FIX: strato pdf
+FIX: typos in getAttchments() $arrayobject
+FIX: whitespaces
+FIX: wrong url param name action
***** ChangeLog for 16.0.4 compared to 16.0.3 *****
diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php
index 45d649d90d9..5614b5323bd 100755
--- a/build/generate_filelist_xml.php
+++ b/build/generate_filelist_xml.php
@@ -56,7 +56,7 @@ if (empty($argv[1])) {
$i=0;
-$result=array();
+$result = array();
while ($i < $argc) {
if (!empty($argv[$i])) {
parse_str($argv[$i], $result); // set all params $release, $includecustom, $includeconstant, $buildzip ...
diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php
index 565a3a59222..96555b960c0 100644
--- a/htdocs/accountancy/journal/sellsjournal.php
+++ b/htdocs/accountancy/journal/sellsjournal.php
@@ -158,7 +158,7 @@ if ($in_bookkeeping == 'notyet') {
$sql .= " AND f.rowid NOT IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')";
// $sql .= " AND fd.rowid NOT IN (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')"; // Useless, we save one line for all products with same account
}
-$sql .= " ORDER BY f.datef";
+$sql .= " ORDER BY f.datef, f.ref";
//print $sql; exit;
dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG);
diff --git a/htdocs/adherents/admin/member_emails.php b/htdocs/adherents/admin/member_emails.php
index 4f942d1f6a8..a1e28904d8c 100644
--- a/htdocs/adherents/admin/member_emails.php
+++ b/htdocs/adherents/admin/member_emails.php
@@ -48,18 +48,23 @@ $action = GETPOST('action', 'aZ09');
$error = 0;
+$helptext = '*'.$langs->trans("FollowingConstantsWillBeSubstituted").' ';
+$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
+
// Editing global variables not related to a specific theme
$constantes = array(
'MEMBER_REMINDER_EMAIL'=>array('type'=>'yesno', 'label'=>$langs->trans('MEMBER_REMINDER_EMAIL', $langs->transnoentities("Module2300Name"))),
- 'ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION' =>'emailtemplate:member',
- 'ADHERENT_EMAIL_TEMPLATE_AUTOREGISTER' =>'emailtemplate:member', // until Dolibarr 7 it was ADHERENT_AUTOREGISTER_MAIL
- 'ADHERENT_EMAIL_TEMPLATE_MEMBER_VALIDATION' =>'emailtemplate:member', // until Dolibarr 7 it was ADHERENT_MAIL_VALID
- 'ADHERENT_EMAIL_TEMPLATE_SUBSCRIPTION' =>'emailtemplate:member', // until Dolibarr 7 it was ADHERENT_MAIL_COTIS
- 'ADHERENT_EMAIL_TEMPLATE_CANCELATION' =>'emailtemplate:member', // until Dolibarr 7 it 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',
+ 'ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION' =>array('type'=>'emailtemplate:member'),
+ 'ADHERENT_EMAIL_TEMPLATE_AUTOREGISTER' =>array('type'=>'emailtemplate:member'),
+ 'ADHERENT_EMAIL_TEMPLATE_MEMBER_VALIDATION' =>array('type'=>'emailtemplate:member'),
+ 'ADHERENT_EMAIL_TEMPLATE_SUBSCRIPTION' =>array('type'=>'emailtemplate:member'),
+ 'ADHERENT_EMAIL_TEMPLATE_CANCELATION' =>array('type'=>'emailtemplate:member'),
+ 'ADHERENT_EMAIL_TEMPLATE_EXCLUSION' =>array('type'=>'emailtemplate:member'),
+ 'ADHERENT_MAIL_FROM' =>array('type'=>'string'),
+ 'ADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT' =>array('type'=>'string'),
+ 'ADHERENT_AUTOREGISTER_NOTIF_MAIL' =>array('type'=>'html', 'tooltip'=>$helptext)
);
@@ -147,12 +152,7 @@ print '
';
diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php
index 4dc5221cea3..e9ac1dfa28f 100644
--- a/htdocs/comm/action/card.php
+++ b/htdocs/comm/action/card.php
@@ -32,7 +32,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
-
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
@@ -154,7 +153,7 @@ if (!empty($conf->global->AGENDA_REMINDER_EMAIL)) {
$TDurationTypes = array('y'=>$langs->trans('Years'), 'm'=>$langs->trans('Month'), 'w'=>$langs->trans('Weeks'), 'd'=>$langs->trans('Days'), 'h'=>$langs->trans('Hours'), 'i'=>$langs->trans('Minutes'));
-$result = restrictedArea($user, 'agenda', $object->id, 'actioncomm&societe', 'myactions|allactions', 'fk_soc', 'id');
+$result = restrictedArea($user, 'agenda', $object, 'actioncomm&societe', 'myactions|allactions', 'fk_soc', 'id');
$usercancreate = $user->hasRight('agenda', 'allactions', 'create') || (($object->authorid == $user->id || $object->userownerid == $user->id) && $user->rights->agenda->myactions->create);
diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php
index 48c51840e83..94daee3164e 100644
--- a/htdocs/comm/action/class/actioncomm.class.php
+++ b/htdocs/comm/action/class/actioncomm.class.php
@@ -1319,15 +1319,17 @@ class ActionComm extends CommonObject
*/
public function getActions($socid = 0, $fk_element = 0, $elementtype = '', $filter = '', $sortfield = 'a.datep', $sortorder = 'DESC', $limit = 0)
{
- global $conf, $langs;
+ global $conf, $langs, $hookmanager;
$resarray = array();
dol_syslog(get_class()."::getActions", LOG_DEBUG);
- require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
- $hookmanager = new HookManager($this->db);
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
+ if (!is_object($hookmanager)) {
+ include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
+ $hookmanager = new HookManager($db);
+ }
$hookmanager->initHooks(array('agendadao'));
$sql = "SELECT a.id";
diff --git a/htdocs/core/ajax/ajaxdirpreview.php b/htdocs/core/ajax/ajaxdirpreview.php
index 2f763c4e576..b5f772212b9 100644
--- a/htdocs/core/ajax/ajaxdirpreview.php
+++ b/htdocs/core/ajax/ajaxdirpreview.php
@@ -117,14 +117,14 @@ if (empty($url)) { // autoset $url but it is better to have it defined before in
// Load translation files required by the page
$langs->loadLangs(array("ecm", "companies", "other"));
+if (empty($modulepart)) {
+ $modulepart = $module;
+}
+
// Security check
if ($user->socid > 0) {
$socid = $user->socid;
}
-
-//print 'xxx'.$upload_dir;
-
-// Security:
// On interdit les remontees de repertoire ainsi que les pipe dans les noms de fichiers.
if (preg_match('/\.\./', $upload_dir) || preg_match('/[<>|]/', $upload_dir)) {
dol_syslog("Refused to deliver file ".$upload_dir);
@@ -132,11 +132,6 @@ if (preg_match('/\.\./', $upload_dir) || preg_match('/[<>|]/', $upload_dir)) {
dol_print_error(0, $langs->trans("ErrorFileNameInvalid", $upload_dir));
exit;
}
-
-if (empty($modulepart)) {
- $modulepart = $module;
-}
-
// Check permissions
if ($modulepart == 'ecm') {
if (!$user->hasRight('ecm', 'read')) {
diff --git a/htdocs/core/ajax/ajaxdirtree.php b/htdocs/core/ajax/ajaxdirtree.php
index 61fdabb70c3..5c281eff5ca 100644
--- a/htdocs/core/ajax/ajaxdirtree.php
+++ b/htdocs/core/ajax/ajaxdirtree.php
@@ -103,7 +103,7 @@ if (empty($modulepart)) {
$modulepart = $module;
}
-// Check permissions
+// Security check
if ($modulepart == 'ecm') {
if (!$user->hasRight('ecm', 'read')) {
accessforbidden();
diff --git a/htdocs/core/ajax/ajaxtooltip.php b/htdocs/core/ajax/ajaxtooltip.php
index ae7b33f1f20..90c416100cb 100644
--- a/htdocs/core/ajax/ajaxtooltip.php
+++ b/htdocs/core/ajax/ajaxtooltip.php
@@ -1,5 +1,5 @@
+/* Copyright (C) 2007-2023 Laurent Destailleur
* Copyright (C) 2018-2023 Frédéric France
*
* This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,6 @@
* \brief This script returns content of tooltip
*/
-
if (!defined('NOTOKENRENEWAL')) {
define('NOTOKENRENEWAL', 1); // Disables token renewal
}
@@ -41,7 +40,7 @@ include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
$id = GETPOST('id', 'aZ09');
-$objecttype = GETPOST('objecttype', 'aZ09'); // 'module' or 'myobject@mymodule', 'mymodule_myobject'
+$objecttype = GETPOST('objecttype', 'aZ09arobase'); // 'module' or 'myobject@mymodule', 'mymodule_myobject'
$params = array();
if (GETPOSTISSET('infologin')) {
@@ -53,6 +52,9 @@ if (GETPOSTISSET('option')) {
// Load object according to $element
$object = fetchObjectByElement($id, $objecttype);
+if (empty($object->element)) {
+ httponly_accessforbidden('Failed to get object from objecttype='.$objecttype.' id='.$id);
+}
$module = $object->module;
$element = $object->element;
@@ -62,6 +64,8 @@ if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // The
$usesublevelpermission = '';
}
+//print $object->id.' - '.$object->module.' - '.$object->element.' - '.$object->table_element.' - '.$usesublevelpermission."\n";
+
// Security check
restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission);
diff --git a/htdocs/core/ajax/bankconciliate.php b/htdocs/core/ajax/bankconciliate.php
index 5407c30545d..c340dd47a06 100644
--- a/htdocs/core/ajax/bankconciliate.php
+++ b/htdocs/core/ajax/bankconciliate.php
@@ -44,6 +44,9 @@ require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
$action = GETPOST('action', 'aZ09');
+// Security check
+// Checks are done later
+
/*
* View
diff --git a/htdocs/core/ajax/box.php b/htdocs/core/ajax/box.php
index b08b1cd81c0..621d6878098 100644
--- a/htdocs/core/ajax/box.php
+++ b/htdocs/core/ajax/box.php
@@ -46,16 +46,16 @@ $boxorder = GETPOST('boxorder');
$zone = GETPOST('zone', 'int');
$userid = GETPOST('userid', 'int');
+// Security check
+if ($userid != $user->id) {
+ httponly_accessforbidden('Bad userid parameter. Must match logged user.');
+}
+
/*
* View
*/
-// Ajout directives pour resoudre bug IE
-//header('Cache-Control: Public, must-revalidate');
-//header('Pragma: public');
-
-//top_htmlhead("", "", 1); // Replaced with top_httphead. An ajax page does not need html header.
top_httphead();
print ''."\n";
diff --git a/htdocs/core/ajax/check_notifications.php b/htdocs/core/ajax/check_notifications.php
index 344a2b19229..18c1a1ece79 100644
--- a/htdocs/core/ajax/check_notifications.php
+++ b/htdocs/core/ajax/check_notifications.php
@@ -44,6 +44,9 @@ $time = dol_now();
$action = GETPOST('action', 'aZ09');
$listofreminderids = GETPOST('listofreminderids', 'aZ09');
+// Security check
+// No permission check at top, but action later are all done with a test on $user->id.
+
/*
* Actions
@@ -68,6 +71,7 @@ if ($action == 'stopreminder') {
// Clean database
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.'actioncomm_reminder';
$sql .= " WHERE dateremind < '".$db->idate(dol_time_plus_duree(dol_now(), -1, 'm'))."'";
+ $sql .= " AND fk_user = ".((int) $user->id).' AND entity = '.((int) $conf->entity);
$resql = $db->query($sql);
if (!$resql) {
dol_print_error($db);
@@ -124,18 +128,10 @@ if (empty($_SESSION['auto_check_events_not_before']) || $time >= $_SESSION['auto
$sql = 'SELECT a.id as id_agenda, a.code, a.datep, a.label, a.location, ar.rowid as id_reminder, ar.dateremind, ar.fk_user as id_user_reminder';
$sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a';
- if (!empty($user->conf->MAIN_USER_WANT_ALL_EVENTS_NOTIFICATIONS)) {
- $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_reminder as ar ON a.id = ar.fk_actioncomm AND ar.fk_user = '.((int) $user->id);
- $sql .= ' WHERE a.code <> "AC_OTH_AUTO"';
- $sql .= ' AND (';
- $sql .= " ar.typeremind = 'browser' AND ar.dateremind < '".$db->idate(dol_now())."' AND ar.status = 0 AND ar.entity = ".$conf->entity;
- $sql .= ' )';
- } else {
- $sql .= ' JOIN '.MAIN_DB_PREFIX.'actioncomm_reminder as ar ON a.id = ar.fk_actioncomm AND ar.fk_user = '.((int) $user->id);
- $sql .= " AND ar.typeremind = 'browser' AND ar.dateremind < '".$db->idate(dol_now())."' AND ar.status = 0 AND ar.entity = ".$conf->entity;
- }
+ $sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'actioncomm_reminder as ar ON a.id = ar.fk_actioncomm AND ar.fk_user = '.((int) $user->id);
+ $sql .= " AND ar.typeremind = 'browser' AND ar.dateremind < '".$db->idate(dol_now())."' AND ar.status = 0 AND ar.entity = ".((int) $conf->entity); // No sharing of entity for alerts
$sql .= $db->order('datep', 'ASC');
- $sql .= ' LIMIT 10'; // Avoid too many notification at once
+ $sql .= $db->plimit(10); // Avoid too many notification at once
$resql = $db->query($sql);
if ($resql) {
diff --git a/htdocs/core/ajax/constantonoff.php b/htdocs/core/ajax/constantonoff.php
index aff62dc6f6b..603de7408c0 100644
--- a/htdocs/core/ajax/constantonoff.php
+++ b/htdocs/core/ajax/constantonoff.php
@@ -52,6 +52,11 @@ $name = GETPOST('name', 'alpha');
$entity = GETPOST('entity', 'int');
$value = (GETPOST('value', 'aZ09') != '' ? GETPOST('value', 'aZ09') : 1);
+// Security check
+if (empty($user->admin)) {
+ httponly_accessforbidden('This ajax component can be called by admin user only');
+}
+
/*
* View
@@ -63,12 +68,10 @@ top_httphead();
// Registering the new value of constant
if (!empty($action) && !empty($name)) {
- if ($user->admin) {
- if ($action == 'set') {
- dolibarr_set_const($db, $name, $value, 'chaine', 0, '', $entity);
- } elseif ($action == 'del') {
- dolibarr_del_const($db, $name, $entity);
- }
+ if ($action == 'set') {
+ dolibarr_set_const($db, $name, $value, 'chaine', 0, '', $entity);
+ } elseif ($action == 'del') {
+ dolibarr_del_const($db, $name, $entity);
}
} else {
http_response_code(403);
diff --git a/htdocs/core/ajax/extraparams.php b/htdocs/core/ajax/extraparams.php
index ccd8d1bc2ce..80f280e7a06 100644
--- a/htdocs/core/ajax/extraparams.php
+++ b/htdocs/core/ajax/extraparams.php
@@ -17,7 +17,8 @@
/**
* \file /htdocs/core/ajax/extraparams.php
- * \brief File to make Ajax action on setting extra parameters of elements
+ * \brief File to make Ajax action on setting extra parameters of elements.
+ * Called bu bloc_showhide.tpl.php, itself called when MAIN_DISABLE_CONTACTS_TAB or MAIN_DISABLE_NOTES_TAB are set
*/
if (!defined('NOTOKENRENEWAL')) {
@@ -39,10 +40,29 @@ if (!defined('NOREQUIRESOC')) {
include '../../main.inc.php';
$id = GETPOST('id', 'int');
-$element = GETPOST('element', 'alpha');
+$element = GETPOST('element', 'aZ09arobase');
$htmlelement = GETPOST('htmlelement', 'alpha');
$type = GETPOST('type', 'alpha');
+// Load object according to $id and $element
+$object = fetchObjectByElement($id, $element);
+
+$module = $object->module;
+$element = $object->element;
+$usesublevelpermission = ($module != $element ? $element : '');
+if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // There is no permission on object defined, we will check permission on module directly
+ $usesublevelpermission = '';
+}
+
+//print $object->id.' - '.$object->module.' - '.$object->element.' - '.$object->table_element.' - '.$usesublevelpermission."\n";
+
+// Security check
+$result = restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission, 'fk_soc', 'rowid', 0, 1); // Call with mode return
+if (!$result) {
+ httponly_accessforbidden('Not allowed by restrictArea');
+}
+
+
/*
* View
*/
@@ -57,47 +77,10 @@ if (!empty($id) && !empty($element) && !empty($htmlelement) && !empty($type)) {
dol_syslog("AjaxSetExtraParameters id=".$id." element=".$element." htmlelement=".$htmlelement." type=".$type." value=".$value, LOG_DEBUG);
- $classpath = $subelement = $element;
+ if (is_object($object)) {
+ $params[$htmlelement] = array($type => $value);
+ $object->extraparams = array_merge($object->extraparams, $params);
- // For compatibility
- if ($element == 'order' || $element == 'commande') {
- $classpath = $subelement = 'commande';
- } elseif ($element == 'propal') {
- $classpath = 'comm/propal';
- $subelement = 'propal';
- } elseif ($element == 'facture') {
- $classpath = 'compta/facture';
- $subelement = 'facture';
- } elseif ($element == 'contract') {
- $classpath = $subelement = 'contrat';
- } elseif ($element == 'shipping') {
- $classpath = $subelement = 'expedition';
- } elseif ($element == 'deplacement') {
- $classpath = 'compta/deplacement';
- $subelement = 'deplacement';
- } elseif ($element == 'order_supplier') {
- $classpath = 'fourn';
- $subelement = 'fournisseur.commande';
- } elseif ($element == 'invoice_supplier') {
- $classpath = 'fourn';
- $subelement = 'fournisseur.facture';
+ $result = $object->setExtraParameters();
}
-
- dol_include_once('/'.$classpath.'/class/'.$subelement.'.class.php');
-
- if ($element == 'order_supplier') {
- $classname = 'CommandeFournisseur';
- } elseif ($element == 'invoice_supplier') {
- $classname = 'FactureFournisseur';
- } else {
- $classname = ucfirst($subelement);
- }
-
- $object = new $classname($db);
- $object->fetch($id);
-
- $params[$htmlelement] = array($type => $value);
- $object->extraparams = array_merge($object->extraparams, $params);
-
- $result = $object->setExtraParameters();
}
diff --git a/htdocs/core/ajax/fetchKnowledgeRecord.php b/htdocs/core/ajax/fetchKnowledgeRecord.php
index d4113d626f8..6e4f1ddd953 100644
--- a/htdocs/core/ajax/fetchKnowledgeRecord.php
+++ b/htdocs/core/ajax/fetchKnowledgeRecord.php
@@ -55,7 +55,7 @@ $idticketgroup = GETPOST('idticketgroup', 'aZ09');
$lang = GETPOST('lang', 'aZ09');
// Security check
-if (!defined("NOLOGIN")) { // No need for restrictedArea if not logged. Later the select will filter on public articles only if not logged.
+if (!defined("NOLOGIN")) { // No need of restrictedArea if not logged: Later the select will filter on public articles only if not logged.
restrictedArea($user, 'knowledgemanagement', 0, 'knowledgemanagement_knowledgerecord', 'knowledgerecord');
}
diff --git a/htdocs/core/ajax/fileupload.php b/htdocs/core/ajax/fileupload.php
index 4e05c7d8cb6..963fa60b05b 100644
--- a/htdocs/core/ajax/fileupload.php
+++ b/htdocs/core/ajax/fileupload.php
@@ -19,24 +19,25 @@
/**
* \file htdocs/core/ajax/fileupload.php
* \brief File to return Ajax response on file upload
- *
- * Option MAIN_USE_JQUERY_FILEUPLOAD must be enabled to have this feature working. Use is NOT secured !
*/
-if (!defined('NOTOKENRENEWAL')) {
- define('NOTOKENRENEWAL', '1');
-}
if (!defined('NOREQUIREMENU')) {
define('NOREQUIREMENU', '1'); // If there is no menu to show
}
if (!defined('NOREQUIREHTML')) {
define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php
}
-
+if (!defined('NOREQUIREAJAX')) {
+ define('NOREQUIREAJAX', '1');
+}
+if (!defined('NOREQUIRESOC')) {
+ define('NOREQUIRESOC', '1');
+}
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/fileupload.class.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php';
error_reporting(E_ALL | E_STRICT);
@@ -44,14 +45,33 @@ error_reporting(E_ALL | E_STRICT);
//print_r($_GET);
//print 'upload_dir='.GETPOST('upload_dir');
-$fk_element = GETPOST('fk_element', 'int');
-$element = GETPOST('element', 'alpha');
+$id = GETPOST('fk_element', 'int');
+$element = GETPOST('element', 'alpha'); // 'myobject' (myobject=mymodule) or 'myobject@mymodule' or 'myobject_mysubobject' (myobject=mymodule)
+$elementupload = $element;
-$upload_handler = new FileUpload(null, $fk_element, $element);
+// Load object according to $id and $element
+$object = fetchObjectByElement($id, $element);
-// Feature not enabled. Warning feature not used and not secured so disabled.
-if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return;
+$module = $object->module;
+$element = $object->element;
+$usesublevelpermission = ($module != $element ? $element : '');
+if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // There is no permission on object defined, we will check permission on module directly
+ $usesublevelpermission = '';
+}
+
+//print $object->id.' - '.$object->module.' - '.$object->element.' - '.$object->table_element.' - '.$usesublevelpermission."\n";
+
+// Security check
+if (!empty($user->socid)) {
+ $socid = $user->socid;
+ if (!empty($object->socid) && $socid != $object->socid) {
+ httponly_accessforbidden("Access on object not allowed for this external user."); // This includes the exit.
+ }
+}
+
+$result = restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission, 'fk_soc', 'rowid', 0, 1); // Call with mode return
+if (!$result) {
+ httponly_accessforbidden('Not allowed by restrictArea');
}
@@ -59,6 +79,8 @@ if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
* View
*/
+$upload_handler = new FileUpload(null, $id, $elementupload);
+
top_httphead();
header('Pragma: no-cache');
diff --git a/htdocs/core/ajax/flowjs-server.php b/htdocs/core/ajax/flowjs-server.php
index d520c57c9c5..901d119332f 100644
--- a/htdocs/core/ajax/flowjs-server.php
+++ b/htdocs/core/ajax/flowjs-server.php
@@ -1,5 +1,5 @@
+/* Copyright (C) 2023 Laurent Destailleur
*
* 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
@@ -16,8 +16,8 @@
*/
/**
- * \file htdocs/core/ajax/bankconciliate.php
- * \brief File to set data for bank concilation
+ * \file htdocs/core/ajax/flowjs-server.php
+ * \brief File to upload very large file, higher than PHP limit. Using flowjs library.
*/
if (!defined('NOTOKENRENEWAL')) {
@@ -46,20 +46,33 @@ require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$action = GETPOST('action', 'aZ09');
-$module = GETPOST('module', 'aZ09');
-$upload_dir = GETPOST('upload_dir', 'alpha');
+
+$module = GETPOST('module', 'aZ09arobase');
+
$flowFilename = GETPOST('flowFilename', 'alpha');
$flowIdentifier = GETPOST('flowIdentifier', 'alpha');
$flowChunkNumber = GETPOST('flowChunkNumber', 'alpha');
$flowChunkSize = GETPOST('flowChunkSize', 'alpha');
$flowTotalSize = GETPOST('flowTotalSize', 'alpha');
+$result = restrictedArea($user, $module, 0, '', 0, 'fk_soc', 'rowid', 0, 1); // Call with mode return
+
+if ($action != 'upload') {
+ httponly_accessforbidden("Param action must be 'upload'");
+}
+
+if (!empty($conf->$module->dir_temp)) {
+ $upload_dir = $conf->$module->dir_temp;
+} else {
+ httponly_accessforbidden("Param module does not has a dir_temp directory. Module does not exists or is not activated.");
+}
+
/*
* Action
*/
-
top_httphead();
+
dol_syslog(join(',', $_GET));
$result = false;
@@ -123,19 +136,19 @@ if ($result) {
/**
- * Check if all the parts exist, and
- * gather all the parts of the file together
- * @param string $temp_dir - the temporary directory holding all the parts of the file
- * @param string $upload_dir - the temporary directory to create file
- * @param string $fileName - the original file name
- * @param string $chunkSize - each chunk size (in bytes)
- * @param string $totalSize - original file size (in bytes)
- * @return bool true if Ok false else
+ * Check if all the parts exist, and gather all the parts of the file together.
+ *
+ * @param string $temp_dir the temporary directory holding all the parts of the file
+ * @param string $upload_dir the temporary directory to create file
+ * @param string $fileName the original file name
+ * @param string $chunkSize each chunk size (in bytes)
+ * @param string $totalSize original file size (in bytes)
+ * @return bool true if Ok false else
*/
function createFileFromChunks($temp_dir, $upload_dir, $fileName, $chunkSize, $totalSize)
{
-
dol_syslog(__METHOD__, LOG_DEBUG);
+
// count all the parts of this file
$total_files = 0;
$files = dol_dir_list($temp_dir, 'files');
@@ -164,5 +177,6 @@ function createFileFromChunks($temp_dir, $upload_dir, $fileName, $chunkSize, $to
// concurrent chunks uploads)
@rename($temp_dir, $temp_dir.'_UNUSED');
}
+
return true;
}
diff --git a/htdocs/core/ajax/getaccountcurrency.php b/htdocs/core/ajax/getaccountcurrency.php
index ff27812aaa2..20061dcdf2b 100644
--- a/htdocs/core/ajax/getaccountcurrency.php
+++ b/htdocs/core/ajax/getaccountcurrency.php
@@ -35,6 +35,9 @@ require '../../main.inc.php';
$id = GETPOST('id', 'int');
+// Security check
+$result = restrictedArea($user, 'banque', $id, 'bank_account&bank_account');
+
/*
* View
diff --git a/htdocs/core/ajax/loadinplace.php b/htdocs/core/ajax/loadinplace.php
index 59306740334..415e51af8e5 100644
--- a/htdocs/core/ajax/loadinplace.php
+++ b/htdocs/core/ajax/loadinplace.php
@@ -17,7 +17,7 @@
/**
* \file htdocs/core/ajax/loadinplace.php
- * \brief File to load field value
+ * \brief File to load field value. used only when option "Edit In Place" is set (MAIN_USE_JQUERY_JEDITABLE).
*/
if (!defined('NOTOKENRENEWAL')) {
@@ -41,6 +41,30 @@ $field = GETPOST('field', 'alpha');
$element = GETPOST('element', 'alpha');
$table_element = GETPOST('table_element', 'alpha');
$fk_element = GETPOST('fk_element', 'alpha');
+$id = $fk_element;
+
+// Load object according to $id and $element
+$object = fetchObjectByElement($id, $element);
+
+$module = $object->module;
+$element = $object->element;
+$usesublevelpermission = ($module != $element ? $element : '');
+if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // There is no permission on object defined, we will check permission on module directly
+ $usesublevelpermission = '';
+}
+
+//print $object->id.' - '.$object->module.' - '.$object->element.' - '.$object->table_element.' - '.$usesublevelpermission."\n";
+
+// Security check
+$result = restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission, 'fk_soc', 'rowid', 0, 1); // Call with mode return
+if (!$result) {
+ httponly_accessforbidden('Not allowed by restrictArea');
+}
+
+if (!getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE')) {
+ httponly_accessforbidden('Can be used only when option MAIN_USE_JQUERY_JEDITABLE is set');
+}
+
/*
* View
diff --git a/htdocs/core/ajax/locationincoterms.php b/htdocs/core/ajax/locationincoterms.php
index b6138c1e950..f3e621abc85 100644
--- a/htdocs/core/ajax/locationincoterms.php
+++ b/htdocs/core/ajax/locationincoterms.php
@@ -43,9 +43,12 @@ if (!defined('NOREQUIRESOC')) {
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
+// Security check
if (!isModEnabled('incoterm')) {
httponly_accessforbidden("Module incoterm not enabled"); // This includes the exit.
}
+// There is no other permission on this component. Everybody connected can read content of the incoterm table
+
/*
* View
@@ -73,12 +76,12 @@ if (GETPOST('location_incoterms')) {
if (!empty($conf->global->MAIN_USE_LOCATION_INCOTERMS_DICTIONNARY)) { // Use location_incoterms
$sql = "SELECT z.location as location_incoterms, z.label as label";
$sql .= " FROM ".MAIN_DB_PREFIX."c_location_incoterms as z";
- $sql .= " WHERE z.active = 1 AND UPPER(z.location) LIKE UPPER('%".$db->escape($db->escapeforlike($location_incoterms))."%')";
+ $sql .= " WHERE z.active = 1 AND z.location LIKE '%".$db->escape($db->escapeforlike($location_incoterms))."%'";
$sql .= " ORDER BY z.location";
$sql .= $db->plimit(100); // Avoid pb with bad criteria
} else { // Use table of sale orders
$sql = "SELECT DISTINCT s.location_incoterms FROM ".MAIN_DB_PREFIX.'commande as s';
- $sql .= " WHERE UPPER(s.location_incoterms) LIKE UPPER('%".$db->escape($db->escapeforlike($location_incoterms))."%')";
+ $sql .= " WHERE s.location_incoterms LIKE '%".$db->escape($db->escapeforlike($location_incoterms))."%'";
//Todo: merge with data from table of supplier order
/* $sql .=" UNION";
diff --git a/htdocs/core/ajax/objectonoff.php b/htdocs/core/ajax/objectonoff.php
index f3b292889e5..9225e8dbb5e 100644
--- a/htdocs/core/ajax/objectonoff.php
+++ b/htdocs/core/ajax/objectonoff.php
@@ -47,19 +47,24 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php';
$action = GETPOST('action', 'aZ09');
$id = GETPOST('id', 'int');
-$element = GETPOST('element', 'alpha'); // 'module' or 'myobject@mymodule' or 'mymodule_myobject'
+$element = GETPOST('element', 'alpha'); // 'myobject' (myobject=mymodule) or 'myobject@mymodule' or 'myobject_mysubobject' (myobject=mymodule)
$field = GETPOST('field', 'alpha');
$value = GETPOST('value', 'int');
$format = 'int';
-// Load object according to $element
+// Load object according to $id and $element
$object = fetchObjectByElement($id, $element);
$object->fields[$field] = array('type' => $format, 'enabled' => 1);
$module = $object->module;
$element = $object->element;
-//var_dump($object->module); var_dump($object->element); var_dump($object->table_element);
+$usesublevelpermission = ($module != $element ? $element : '');
+if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // There is no permission on object defined, we will check permission on module directly
+ $usesublevelpermission = '';
+}
+
+//print $object->id.' - '.$object->module.' - '.$object->element.' - '.$object->table_element.' - '.$usesublevelpermission."\n";
// Security check
if (!empty($user->socid)) {
@@ -72,12 +77,6 @@ if (!empty($user->socid)) {
// We check permission.
// Check is done on $user->rights->element->create or $user->rights->element->subelement->create (because $action = 'set')
if (preg_match('/status$/', $field)) {
- $module = $object->module;
- $element = $object->element;
- $usesublevelpermission = ($module != $element ? $element : '');
- if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // There is no permission on object defined, we will check permission on module directly
- $usesublevelpermission = '';
- }
restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission);
} elseif ($element == 'product' && in_array($field, array('tosell', 'tobuy', 'tobatch'))) { // Special case for products
restrictedArea($user, 'produit|service', $object, 'product&product', '', '', 'rowid');
diff --git a/htdocs/core/ajax/onlineSign.php b/htdocs/core/ajax/onlineSign.php
index ea5c33092ca..f45c511a917 100644
--- a/htdocs/core/ajax/onlineSign.php
+++ b/htdocs/core/ajax/onlineSign.php
@@ -66,7 +66,7 @@ $response = "";
$type = $mode;
-// Check securitykey
+// Security check
$securekeyseed = '';
if ($type == 'proposal') {
$securekeyseed = getDolGlobalString('PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN');
diff --git a/htdocs/core/ajax/pingresult.php b/htdocs/core/ajax/pingresult.php
index 73b740bdfaf..854188f7d6e 100644
--- a/htdocs/core/ajax/pingresult.php
+++ b/htdocs/core/ajax/pingresult.php
@@ -50,15 +50,16 @@ $hash_algo = GETPOST('hash_algo', 'alpha');
// Security check
-// None.
+// None. Beeing connected is enough.
-$now = dol_now();
/*
* View
*/
+$now = dol_now();
+
top_httphead();
print ''."\n";
diff --git a/htdocs/core/ajax/price.php b/htdocs/core/ajax/price.php
index 283afb77653..e2a8829fc14 100644
--- a/htdocs/core/ajax/price.php
+++ b/htdocs/core/ajax/price.php
@@ -40,6 +40,10 @@ $output = GETPOST('output', 'alpha');
$amount = price2num(GETPOST('amount', 'alpha'));
$tva_tx = str_replace('*', '', GETPOST('tva_tx', 'alpha'));
+// Security check
+// None. This is a formatting only component.
+
+
/*
* View
*/
diff --git a/htdocs/core/ajax/row.php b/htdocs/core/ajax/row.php
index ec3ee105420..a20034ba0fe 100644
--- a/htdocs/core/ajax/row.php
+++ b/htdocs/core/ajax/row.php
@@ -49,7 +49,9 @@ if (!defined('NOREQUIRETRAN')) {
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php';
+
$hookmanager->initHooks(array('rowinterface'));
+
// Security check
// This is done later into view.
diff --git a/htdocs/core/ajax/saveinplace.php b/htdocs/core/ajax/saveinplace.php
index 32fdae72835..9cbecc8e9c7 100644
--- a/htdocs/core/ajax/saveinplace.php
+++ b/htdocs/core/ajax/saveinplace.php
@@ -17,7 +17,7 @@
/**
* \file htdocs/core/ajax/saveinplace.php
- * \brief File to save field value
+ * \brief File to load field value. used only when option "Edit In Place" is set (MAIN_USE_JQUERY_JEDITABLE).
*/
if (!defined('NOTOKENRENEWAL')) {
@@ -41,6 +41,7 @@ $field = GETPOST('field', 'alpha', 2);
$element = GETPOST('element', 'alpha', 2);
$table_element = GETPOST('table_element', 'alpha', 2);
$fk_element = GETPOST('fk_element', 'alpha', 2);
+$id = $fk_element;
/* Example:
field:editval_ref_customer (8 first chars will removed to know name of property)
@@ -54,6 +55,28 @@ savemethod:
savemethodname:
*/
+// Load object according to $id and $element
+$object = fetchObjectByElement($id, $element);
+
+$module = $object->module;
+$element = $object->element;
+$usesublevelpermission = ($module != $element ? $element : '');
+if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // There is no permission on object defined, we will check permission on module directly
+ $usesublevelpermission = '';
+}
+
+//print $object->id.' - '.$object->module.' - '.$object->element.' - '.$object->table_element.' - '.$usesublevelpermission."\n";
+
+// Security check
+$result = restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission, 'fk_soc', 'rowid', 0, 1); // Call with mode return
+if (!$result) {
+ httponly_accessforbidden('Not allowed by restrictArea');
+}
+
+if (!getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE')) {
+ httponly_accessforbidden('Can be used only when option MAIN_USE_JQUERY_JEDITABLE is set');
+}
+
/*
* View
diff --git a/htdocs/core/ajax/security.php b/htdocs/core/ajax/security.php
index 2a836359e1c..8602190db73 100644
--- a/htdocs/core/ajax/security.php
+++ b/htdocs/core/ajax/security.php
@@ -17,8 +17,8 @@
/**
* \file htdocs/core/ajax/security.php
- * \brief This ajax component is used to generated hash keys for security purposes
- * like key to use into URL to protect them.
+ * \brief This ajax component is used to generated hash keys for security purposes,
+ * like the key to use into URL to protect them.
*/
if (!defined('NOTOKENRENEWAL')) {
@@ -46,6 +46,9 @@ require '../../main.inc.php';
$action = GETPOST('action');
+// Security check
+// None. This is public component with no effect on data.
+
/*
* View
diff --git a/htdocs/core/ajax/selectobject.php b/htdocs/core/ajax/selectobject.php
index 079224c62a2..14372a405b4 100644
--- a/htdocs/core/ajax/selectobject.php
+++ b/htdocs/core/ajax/selectobject.php
@@ -38,33 +38,18 @@ if (!defined('NOREQUIRESOC')) {
// Load Dolibarr environment
require '../../main.inc.php';
+require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
$objectdesc = GETPOST('objectdesc', 'alpha');
$htmlname = GETPOST('htmlname', 'aZ09');
$outjson = (GETPOST('outjson', 'int') ? GETPOST('outjson', 'int') : 0);
$id = GETPOST('id', 'int');
-$filter = GETPOST('filter', 'alphanohtml');
-
-
-/*
- * View
- */
-
-//print ''."\n";
-//print_r($_GET);
-
-require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
-$form = new Form($db);
-
-//$langs->load("companies");
-
-top_httphead();
+$filter = GETPOST('filter', 'alphanohtml'); // Universal Syntax filter
if (empty($htmlname)) {
- return;
+ httponly_accessforbidden('Bad value for param htmlname');
}
-
$InfoFieldList = explode(":", $objectdesc);
$classname = $InfoFieldList[0];
$classpath = $InfoFieldList[1];
@@ -75,16 +60,41 @@ if (!empty($classpath)) {
}
}
if (!is_object($objecttmp)) {
- dol_syslog('Error bad param objectdesc', LOG_WARNING);
- print 'Error bad param objectdesc';
+ httponly_accessforbidden('Bad value for param objectdesc');
}
+/*
+// Load object according to $id and $element
+$object = fetchObjectByElement($id, $element);
+
+$module = $object->module;
+$element = $object->element;
+$usesublevelpermission = ($module != $element ? $element : '');
+if ($usesublevelpermission && !isset($user->rights->$module->$element)) { // There is no permission on object defined, we will check permission on module directly
+ $usesublevelpermission = '';
+}
+*/
+
// When used from jQuery, the search term is added as GET param "term".
$searchkey = (($id && GETPOST($id, 'alpha')) ? GETPOST($id, 'alpha') : (($htmlname && GETPOST($htmlname, 'alpha')) ? GETPOST($htmlname, 'alpha') : ''));
// Add a security test to avoid to get content of all tables
restrictedArea($user, $objecttmp->element, $id);
+
+/*
+ * View
+ */
+
+//print ''."\n";
+//print_r($_GET);
+
+//$langs->load("companies");
+
+$form = new Form($db);
+
+top_httphead($outjson ? 'application/json' : 'text/html');
+
$arrayresult = $form->selectForFormsList($objecttmp, $htmlname, '', 0, $searchkey, '', '', '', 0, 1, 0, '', $filter);
$db->close();
diff --git a/htdocs/core/ajax/selectsearchbox.php b/htdocs/core/ajax/selectsearchbox.php
index d2379f46966..615872eb101 100644
--- a/htdocs/core/ajax/selectsearchbox.php
+++ b/htdocs/core/ajax/selectsearchbox.php
@@ -1,5 +1,5 @@
+/* Copyright (C) 2015-2023 Laurent Destailleur
*
* 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
@@ -18,7 +18,7 @@
/**
* \file htdocs/core/ajax/selectsearchbox.php
* \ingroup core
- * \brief This script returns content of possible search
+ * \brief This script returns json array of possible searches or just set the array if called by an include
*/
// This script is called with a POST method or as an include.
@@ -43,6 +43,9 @@ if (!isset($usedbyinclude) || empty($usedbyinclude)) {
$res = @include '../../main.inc.php';
+ // Security check
+ // None. Beeing connected is enough.
+
top_httphead('application/json');
if ($res == 'ERROR_NOT_LOGGED') {
diff --git a/htdocs/core/ajax/vatrates.php b/htdocs/core/ajax/vatrates.php
index 56cb4c788e3..1b4a0c79c80 100644
--- a/htdocs/core/ajax/vatrates.php
+++ b/htdocs/core/ajax/vatrates.php
@@ -17,7 +17,7 @@
/**
* \file htdocs/core/ajax/vatrates.php
- * \brief File to load vat rates combobox
+ * \brief File to load vat rates combobox according to thirdparty ID. Values are returned in JSON format.
*/
if (!defined('NOTOKENRENEWAL')) {
@@ -34,16 +34,20 @@ if (!defined('NOREQUIREAJAX')) {
require '../../main.inc.php';
$id = GETPOST('id', 'int');
-$action = GETPOST('action', 'aZ09');
+$action = GETPOST('action', 'aZ09'); // 'getSellerVATRates' or 'getBuyerVATRates'
$htmlname = GETPOST('htmlname', 'alpha');
$selected = (GETPOST('selected') ?GETPOST('selected') : '-1');
$productid = (GETPOST('productid', 'int') ?GETPOST('productid', 'int') : 0);
+// Security check
+$result = restrictedArea($user, 'societe', $id, '&societe', '', 'fk_soc', 'rowid', 0);
+
+
/*
* View
*/
-top_httphead();
+top_httphead('application/json');
//print ''."\n";
@@ -63,7 +67,6 @@ if (!empty($id) && !empty($action) && !empty($htmlname)) {
}
$return = array();
-
$return['value'] = $form->load_tva('tva_tx', $selected, $seller, $buyer, $productid, 0, '', true);
$return['num'] = $form->num;
$return['error'] = $form->error;
diff --git a/htdocs/core/ajax/ziptown.php b/htdocs/core/ajax/ziptown.php
index f6869e9ffcf..92db98c250d 100644
--- a/htdocs/core/ajax/ziptown.php
+++ b/htdocs/core/ajax/ziptown.php
@@ -42,6 +42,11 @@ if (!defined('NOREQUIRESOC')) {
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
+// Security check
+if (!getDolGlobalString('MAIN_USE_ZIPTOWN_DICTIONNARY')) {
+ // If MAIN_USE_ZIPTOWN_DICTIONNARY is set, we make a search into a public page. If not we search into societe so we must check we have read permission.
+ $result = restrictedArea($user, 'societe', 0, '&societe', '', 'fk_soc', 'rowid', 0);
+}
/*
@@ -53,11 +58,11 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
//header('Pragma: public');
//top_htmlhead("", "", 1); // Replaced with top_httphead. An ajax page does not need html header.
-top_httphead();
+top_httphead('application/json');
//print ''."\n";
-dol_syslog('ziptown call with MAIN_USE_ZIPTOWN_DICTIONNARY='.(empty($conf->global->MAIN_USE_ZIPTOWN_DICTIONNARY) ? '' : $conf->global->MAIN_USE_ZIPTOWN_DICTIONNARY));
+dol_syslog('ziptown call with MAIN_USE_ZIPTOWN_DICTIONNARY='.getDolGlobalString('MAIN_USE_ZIPTOWN_DICTIONNARY'));
//var_dump($_GET);
// Generation of list of zip-town
@@ -69,7 +74,7 @@ if (GETPOST('zipcode') || GETPOST('town')) {
$zipcode = GETPOST('zipcode');
$town = GETPOST('town');
- if (!empty($conf->global->MAIN_USE_ZIPTOWN_DICTIONNARY)) { // Use zip-town table
+ if (getDolGlobalString('MAIN_USE_ZIPTOWN_DICTIONNARY')) { // Use zip-town table
$sql = "SELECT z.rowid, z.zip, z.town, z.fk_county, z.fk_pays as fk_country";
$sql .= ", c.rowid as fk_country, c.code as country_code, c.label as country";
$sql .= ", d.rowid as fk_county, d.code_departement as county_code, d.nom as county";
@@ -80,15 +85,14 @@ if (GETPOST('zipcode') || GETPOST('town')) {
$sql .= " WHERE z.fk_pays = c.rowid";
$sql .= " AND z.active = 1 AND c.active = 1";
if ($zipcode) {
- $sql .= " AND z.zip LIKE '".$db->escape($zipcode)."%'";
+ $sql .= " AND z.zip LIKE '".$db->escape($db->escapeforlike($zipcode))."%'";
}
if ($town) {
- $sql .= " AND z.town LIKE '%".$db->escape($town)."%'";
+ $sql .= " AND z.town LIKE '%".$db->escape($db->escapeforlike($town))."%'";
}
$sql .= " ORDER BY z.zip, z.town";
$sql .= $db->plimit(100); // Avoid pb with bad criteria
- } else // Use table of third parties
- {
+ } else { // Use table of third parties
$sql = "SELECT DISTINCT s.zip, s.town, s.fk_departement as fk_county, s.fk_pays as fk_country";
$sql .= ", c.code as country_code, c.label as country";
$sql .= ", d.code_departement as county_code , d.nom as county";
@@ -97,10 +101,10 @@ if (GETPOST('zipcode') || GETPOST('town')) {
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX.'c_country as c ON s.fk_pays = c.rowid';
$sql .= " WHERE";
if ($zipcode) {
- $sql .= " s.zip LIKE '".$db->escape($zipcode)."%'";
+ $sql .= " s.zip LIKE '".$db->escape($db->escapeforlike($zipcode))."%'";
}
if ($town) {
- $sql .= " s.town LIKE '%".$db->escape($town)."%'";
+ $sql .= " s.town LIKE '%".$db->escape($db->escapeforlike($town))."%'";
}
$sql .= " ORDER BY s.fk_pays, s.zip, s.town";
$sql .= $db->plimit(100); // Avoid pb with bad criteria
diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php
index 01964313ea3..e350cae47bc 100644
--- a/htdocs/core/class/CMailFile.class.php
+++ b/htdocs/core/class/CMailFile.class.php
@@ -641,7 +641,7 @@ class CMailFile
*/
public function sendfile()
{
- global $conf, $db, $langs;
+ global $conf, $db, $langs, $hookmanager;
$errorlevel = error_reporting();
//error_reporting($errorlevel ^ E_WARNING); // Desactive warnings
@@ -649,8 +649,10 @@ class CMailFile
$res = false;
if (empty($conf->global->MAIN_DISABLE_ALL_MAILS)) {
- require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
- $hookmanager = new HookManager($db);
+ if (!is_object($hookmanager)) {
+ include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
+ $hookmanager = new HookManager($db);
+ }
$hookmanager->initHooks(array('mail'));
$parameters = array();
diff --git a/htdocs/core/class/fileupload.class.php b/htdocs/core/class/fileupload.class.php
index 4a4394a7049..4dcfb55f781 100644
--- a/htdocs/core/class/fileupload.class.php
+++ b/htdocs/core/class/fileupload.class.php
@@ -19,8 +19,6 @@
/**
* \file htdocs/core/class/fileupload.class.php
* \brief File to return Ajax response on file upload
- *
- * Option MAIN_USE_JQUERY_FILEUPLOAD must be enabled to have feature working. Use is NOT secured !
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
@@ -49,11 +47,6 @@ class FileUpload
global $object;
global $hookmanager;
- // Feature not enabled. Warning feature not used and not secured so disabled.
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return;
- }
-
$hookmanager->initHooks(array('fileupload'));
$this->fk_element = $fk_element;
@@ -266,9 +259,6 @@ class FileUpload
*/
protected function getFileObject($file_name)
{
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return null;
- }
$file_path = $this->options['upload_dir'].$file_name;
if (is_file($file_path) && $file_name[0] !== '.') {
@@ -310,10 +300,6 @@ class FileUpload
{
global $maxwidthmini, $maxheightmini;
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return false;
- }
-
$file_path = $this->options['upload_dir'].$file_name;
$new_file_path = $options['upload_dir'].$file_name;
@@ -345,10 +331,6 @@ class FileUpload
*/
protected function validate($uploaded_file, $file, $error, $index)
{
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return false;
- }
-
if ($error) {
$file->error = $error;
return false;
@@ -464,10 +446,6 @@ class FileUpload
*/
protected function handleFileUpload($uploaded_file, $name, $size, $type, $error, $index)
{
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return null;
- }
-
$file = new stdClass();
$file->name = $this->trimFileName($name, $type, $index);
$file->mime = dol_mimetype($file->name, '', 2);
@@ -514,10 +492,6 @@ class FileUpload
*/
public function get()
{
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return;
- }
-
$file_name = isset($_REQUEST['file']) ?
basename(stripslashes($_REQUEST['file'])) : null;
if ($file_name) {
@@ -536,10 +510,6 @@ class FileUpload
*/
public function post()
{
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return;
- }
-
if (isset($_REQUEST['_method']) && $_REQUEST['_method'] === 'DELETE') {
return $this->delete();
}
@@ -595,10 +565,6 @@ class FileUpload
*/
public function delete()
{
- if (!getDolGlobalInt('MAIN_USE_JQUERY_FILEUPLOAD')) {
- return null;
- }
-
$file_name = isset($_REQUEST['file']) ?
basename(stripslashes($_REQUEST['file'])) : null;
$file_path = $this->options['upload_dir'].$file_name;
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index e9a33390226..1c453d49a8a 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -1955,25 +1955,25 @@ class Form
/**
* Return select list of users
*
- * @param string $selected User id or user object of user preselected. If 0 or < -2, we use id of current user. If -1, keep unselected (if empty is allowed)
- * @param string $htmlname Field name in form
- * @param int|string $show_empty 0=list with no empty value, 1=add also an empty value into list
- * @param array $exclude Array list of users id to exclude
- * @param int $disabled If select list must be disabled
- * @param array|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me
- * @param array $enableonly Array list of users id to be enabled. If defined, it means that others will be disabled
- * @param string $force_entity '0' or Ids of environment to force
- * @param int $maxlength Maximum length of string into list (0=no limit)
- * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status
- * @param string $morefilter Add more filters into sql request (Example: 'employee = 1'). This value must not come from user input.
- * @param integer $show_every 0=default list, 1=add also a value "Everybody" at beginning of list
- * @param string $enableonlytext If option $enableonlytext is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty.
- * @param string $morecss More css
- * @param int $notdisabled Show only active users (this will also happened whatever is this option if USER_HIDE_INACTIVE_IN_COMBOBOX is on).
- * @param int $outputmode 0=HTML select string, 1=Array
- * @param bool $multiple add [] in the name of element and add 'multiple' attribut
- * @param int $forcecombo Force the component to be a simple combo box without ajax
- * @return array|string HTML select string
+ * @param string $selected User id or user object of user preselected. If 0 or < -2, we use id of current user. If -1, keep unselected (if empty is allowed)
+ * @param string $htmlname Field name in form
+ * @param int|string $show_empty 0=list with no empty value, 1=add also an empty value into list
+ * @param array $exclude Array list of users id to exclude
+ * @param int $disabled If select list must be disabled
+ * @param array|string $include Array list of users id to include. User '' for all users or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me
+ * @param array|string $enableonly Array list of users id to be enabled. If defined, it means that others will be disabled
+ * @param string $force_entity '0' or Ids of environment to force
+ * @param int $maxlength Maximum length of string into list (0=no limit)
+ * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status
+ * @param string $morefilter Add more filters into sql request (Example: 'employee = 1'). This value must not come from user input.
+ * @param integer $show_every 0=default list, 1=add also a value "Everybody" at beginning of list
+ * @param string $enableonlytext If option $enableonlytext is set, we use this text to explain into label why record is disabled. Not used if enableonly is empty.
+ * @param string $morecss More css
+ * @param int $notdisabled Show only active users (this will also happened whatever is this option if USER_HIDE_INACTIVE_IN_COMBOBOX is on).
+ * @param int $outputmode 0=HTML select string, 1=Array
+ * @param bool $multiple add [] in the name of element and add 'multiple' attribut
+ * @param int $forcecombo Force the component to be a simple combo box without ajax
+ * @return array|string HTML select string
* @see select_dolgroups()
*/
public function select_dolusers($selected = '', $htmlname = 'userid', $show_empty = 0, $exclude = null, $disabled = 0, $include = '', $enableonly = '', $force_entity = '0', $maxlength = 0, $showstatus = 0, $morefilter = '', $show_every = 0, $enableonlytext = '', $morecss = '', $notdisabled = 0, $outputmode = 0, $multiple = false, $forcecombo = 0)
@@ -2013,6 +2013,7 @@ class Form
$out = '';
$outarray = array();
+ $outarray2 = array();
// Forge request to select users
$sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut as status, u.login, u.admin, u.entity, u.photo";
@@ -2151,7 +2152,7 @@ class Form
}
}
$moreinfo .= ($moreinfo ? ')' : '');
- $moreinfohtml .= ($moreinfohtml ? ')' : '');
+ $moreinfohtml .= ($moreinfohtml ? ')' : '');
if ($disableline && $disableline != '1') {
// Add text from $enableonlytext parameter
$moreinfo .= ' - ' . $disableline;
@@ -2182,6 +2183,11 @@ class Form
$out .= '';
$outarray[$userstatic->id] = $userstatic->getFullName($langs, $fullNameMode, -1, $maxlength) . $moreinfo;
+ $outarray2[$userstatic->id] = array(
+ 'id'=>$userstatic->id,
+ 'label'=>$labeltoshow,
+ 'labelhtml'=>$labeltoshowhtml
+ );
$i++;
}
@@ -2200,7 +2206,9 @@ class Form
dol_print_error($this->db);
}
- if ($outputmode) {
+ if ($outputmode == 2) {
+ return $outarray2;
+ } elseif ($outputmode) {
return $outarray;
}
@@ -6993,7 +7001,12 @@ class Form
if (empty($labeladddateof)) {
$labeladddateof = $langs->trans("DateInvoice");
}
- $retstring .= ' -