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 '
'; print ''; print ''; -$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 - -form_constantes($constantes, 3, $helptext); +form_constantes($constantes, 3, ''); print '
'; 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 .= ' -