diff --git a/.travis.yml b/.travis.yml index b48a3667bb0..5d7eb7a1678 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,7 @@ jobs: php: nightly env: DB=mysql - stage: PHP Dev - if: type = push AND branch = 14.0 + if: type = push AND branch = 15.0 php: nightly env: DB=mysql @@ -411,6 +411,12 @@ script: php upgrade.php 13.0.0 14.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade13001400.log php upgrade2.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-2.log php step5.php 13.0.0 14.0.0 > $TRAVIS_BUILD_DIR/upgrade13001400-3.log + php upgrade.php 14.0.0 15.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade14001500.log + php upgrade2.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-2.log + php step5.php 14.0.0 15.0.0 > $TRAVIS_BUILD_DIR/upgrade14001500-3.log + php upgrade.php 15.0.0 16.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade15001600.log + php upgrade2.php 15.0.0 16.0.0 > $TRAVIS_BUILD_DIR/upgrade15001600-2.log + php step5.php 15.0.0 16.0.0 > $TRAVIS_BUILD_DIR/upgrade15001600-3.log ls -alrt $TRAVIS_BUILD_DIR/ - | diff --git a/ChangeLog b/ChangeLog index a8211da486a..030650d5863 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,7 +15,7 @@ NEW: Add option to disable globaly some notifications emails. NEW: #18326 Workflow: Close order on shipment closing. NEW: #18401 Add __NEWREF__ subtitute to get new object reference. NEW: #18403 Add __URL_SHIPMENT__ substitute to get the URL of a shipment -NEW: #18689 REST API module: add api key generate / modify right. +NEW: #18689 REST API module: add api key generate / modify pemrission. NEW: #18663 Make "L'Annuaire des Entreprises" the default provider for SIREN verification for French thirdparties. NEW: #18046 Add tags on ticket/categories NEW: #18326 Workflow: Close order on shipment closing. @@ -109,6 +109,13 @@ NEW: External backups can be downloaded from the "About info page". NEW: Add massaction to switch status on sale / on purchase of a product. + Modules +NEW: Stable module Knowledge Management +NEW: Experimental module Event Organization Management +NEW: Experimental module Workstations Management +NEW: Development of module Partnership Management + + For developers: --------------- @@ -116,6 +123,7 @@ NEW: Introduce method hasRight NEW: Can use textarea field into a confirm popup. NEW: Can use the result_mode of mysqli driver. Save memory for list count NEW: #18319 REST API - Shipment: Add 'close' action / endpoint / POST method. +NEW: Add API /approve and /makeOrder for purchase orders. NEW: add action trigger for member excluded NEW: add option MAIN_IBAN_IS_NEVER_MANDATORY, MAIN_IBAN_NOT_MANDATORY, PROPAL_NOT_BILLABLE, PROPAL_REOPEN_UNSIGNED_ONLY, PROPOSAL_ARE_NOT_BILLABLE, TICKETS_MESSAGE_FORCE_MAIL NEW: Add code codebar column on serial/lot structure diff --git a/SECURITY.md b/SECURITY.md index 4e7e5fa933a..cadd4a23791 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -67,7 +67,7 @@ Scope is the web application (back office) and the APIs. * Remote code execution (RCE) * Local files access and manipulation (LFI, RFI, XXE, SSRF, XSPA) * Code injections (HTML, JS, SQL, PHP, ...) -* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose or into module "Web site" when permission to edit website content is allowed). +* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose) and except into module "Web site" when permission to edit website content is allowed (injecting any data in this case is allowed too). * Cross-Site Requests Forgery (CSRF) with real security impact (when using GET URLs, CSRF are qualified only for creating, updating or deleting data from pages restricted to admin users) * Open redirect * Broken authentication & session management diff --git a/htdocs/adherents/cartes/carte.php b/htdocs/adherents/cartes/carte.php index 93054dad234..94621195ac9 100644 --- a/htdocs/adherents/cartes/carte.php +++ b/htdocs/adherents/cartes/carte.php @@ -275,7 +275,7 @@ dol_htmloutput_errors($mesg); print '
'; -print img_picto('', 'puce').' '.$langs->trans("DocForAllMembersCards", (!empty($conf->global->ADHERENT_CARD_TYPE) ? $conf->global->ADHERENT_CARD_TYPE : $langs->transnoentitiesnoconv("None"))).' '; +print img_picto('', 'card').' '.$langs->trans("DocForAllMembersCards", (!empty($conf->global->ADHERENT_CARD_TYPE) ? $conf->global->ADHERENT_CARD_TYPE : $langs->transnoentitiesnoconv("None"))).' '; print '
'; print ''; print ''; @@ -289,12 +289,12 @@ foreach (array_keys($_Avery_Labels) as $codecards) { } asort($arrayoflabels); print $form->selectarray('modelcard', $arrayoflabels, (GETPOST('modelcard') ? GETPOST('modelcard') : (empty($conf->global->ADHERENT_CARD_TYPE) ? '' : $conf->global->ADHERENT_CARD_TYPE)), 1, 0, 0, '', 0, 0, 0, '', '', 1); -print '
'; +print '
'; print '
'; print '

'; -print img_picto('', 'puce').' '.$langs->trans("DocForOneMemberCards", (!empty($conf->global->ADHERENT_CARD_TYPE) ? $conf->global->ADHERENT_CARD_TYPE : $langs->transnoentitiesnoconv("None"))).' '; +print img_picto('', 'card').' '.$langs->trans("DocForOneMemberCards", (!empty($conf->global->ADHERENT_CARD_TYPE) ? $conf->global->ADHERENT_CARD_TYPE : $langs->transnoentitiesnoconv("None"))).' '; print '
'; print ''; print ''; @@ -308,12 +308,12 @@ foreach (array_keys($_Avery_Labels) as $codecards) { asort($arrayoflabels); print $form->selectarray('model', $arrayoflabels, (GETPOST('model') ?GETPOST('model') : (empty($conf->global->ADHERENT_CARD_TYPE) ? '' : $conf->global->ADHERENT_CARD_TYPE)), 1, 0, 0, '', 0, 0, 0, '', '', 1); print '
'.$langs->trans("Login").': '; -print '
'; +print '
'; print '
'; print '

'; -print img_picto('', 'puce').' '.$langs->trans("DocForLabels", (empty($conf->global->ADHERENT_ETIQUETTE_TYPE) ? '' : $conf->global->ADHERENT_ETIQUETTE_TYPE)).' '; +print img_picto('', 'card').' '.$langs->trans("DocForLabels", (empty($conf->global->ADHERENT_ETIQUETTE_TYPE) ? '' : $conf->global->ADHERENT_ETIQUETTE_TYPE)).' '; print '
'; print ''; print ''; @@ -326,7 +326,7 @@ foreach (array_keys($_Avery_Labels) as $codecards) { } asort($arrayoflabels); print $form->selectarray('modellabel', $arrayoflabels, (GETPOST('modellabel') ? GETPOST('modellabel') : (empty($conf->global->ADHERENT_ETIQUETTE_TYPE) ? '' : $conf->global->ADHERENT_ETIQUETTE_TYPE)), 1, 0, 0, '', 0, 0, 0, '', '', 1); -print '
'; +print '
'; print '
'; // End of page diff --git a/htdocs/adherents/partnership.php b/htdocs/adherents/partnership.php index cf0e11d70e0..160a037c187 100644 --- a/htdocs/adherents/partnership.php +++ b/htdocs/adherents/partnership.php @@ -22,27 +22,6 @@ * \brief Page to create/edit/view partnership */ -//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db -//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user -//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc -//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs -//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters -//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters -//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). -//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) -//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data -//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu -//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php -//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library -//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. -//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip -//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value -//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler -//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message -//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies -//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET -//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification - // Load Dolibarr environment require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index e26db90c4ff..ac2555b4deb 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -1163,9 +1163,13 @@ if ($rowid > 0) { print dol_get_fiche_end(); print '
'; - print ''; - print '     '; - print ''; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); + if (empty($reshook)) { + print ''; + print '     '; + print ''; + } print '
'; print ''; diff --git a/htdocs/admin/agenda.php b/htdocs/admin/agenda.php index 730983ad090..a730f199213 100644 --- a/htdocs/admin/agenda.php +++ b/htdocs/admin/agenda.php @@ -192,6 +192,7 @@ if (!empty($triggers)) { } if ($search_event === '' || preg_match('/'.preg_quote($search_event, '/').'/i', $trigger['code'])) { + print ''; print ''; print ''.$trigger['code'].''; print ''.$trigger['label'].''; diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php index 1cce5388f90..8e50380e2ae 100644 --- a/htdocs/admin/agenda_other.php +++ b/htdocs/admin/agenda_other.php @@ -104,6 +104,8 @@ if ($action == 'set') { $resultCreat = $defaultValues->create($user); if ($resultCreat < 0) { setEventMessages($defaultValues->error, $defaultValues->errors, 'errors'); + } else { + setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); } } elseif ($action == 'specimen') { // For orders $modele = GETPOST('module', 'alpha'); @@ -316,6 +318,16 @@ print ' '."\n"; print ''.$langs->trans("Value").''."\n"; print ''."\n"; +// AGENDA_DEFAULT_VIEW +print ''."\n"; +$htmltext = $langs->trans("ThisValueCanOverwrittenOnUserLevel", $langs->transnoentitiesnoconv("UserGUISetup")); +print ''.$form->textwithpicto($langs->trans("AGENDA_DEFAULT_VIEW"), $htmltext).''."\n"; +print ' '."\n"; +print ''."\n"; +$tmplist = array(''=>' ', 'show_list'=>$langs->trans("ViewList"), 'show_month'=>$langs->trans("ViewCal"), 'show_week'=>$langs->trans("ViewWeek"), 'show_day'=>$langs->trans("ViewDay"), 'show_peruser'=>$langs->trans("ViewPerUser")); +print $form->selectarray('AGENDA_DEFAULT_VIEW', $tmplist, $conf->global->AGENDA_DEFAULT_VIEW); +print ''."\n"; + // Manual or automatic print ''."\n"; @@ -340,16 +352,6 @@ if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { print ''."\n"; } -// AGENDA_DEFAULT_VIEW -print ''."\n"; -$htmltext = $langs->trans("ThisValueCanOverwrittenOnUserLevel", $langs->transnoentitiesnoconv("UserGUISetup")); -print ''.$form->textwithpicto($langs->trans("AGENDA_DEFAULT_VIEW"), $htmltext).''."\n"; -print ' '."\n"; -print ''."\n"; -$tmplist = array(''=>' ', 'show_list'=>$langs->trans("ViewList"), 'show_month'=>$langs->trans("ViewCal"), 'show_week'=>$langs->trans("ViewWeek"), 'show_day'=>$langs->trans("ViewDay"), 'show_peruser'=>$langs->trans("ViewPerUser")); -print $form->selectarray('AGENDA_DEFAULT_VIEW', $tmplist, $conf->global->AGENDA_DEFAULT_VIEW); -print ''."\n"; - // AGENDA_EVENT_DEFAULT_STATUS print ''."\n"; print ''.$langs->trans("AGENDA_EVENT_DEFAULT_STATUS").''."\n"; diff --git a/htdocs/admin/const.php b/htdocs/admin/const.php index a632d5f1a41..1426c323c01 100644 --- a/htdocs/admin/const.php +++ b/htdocs/admin/const.php @@ -37,8 +37,6 @@ if (!$user->admin) { $rowid = GETPOST('rowid', 'int'); $entity = GETPOST('entity', 'int'); $action = GETPOST('action', 'aZ09'); -$update = GETPOST('update', 'alpha'); -$delete = GETPOST('delete', 'none'); // Do not use alpha here $debug = GETPOST('debug', 'int'); $consts = GETPOST('const', 'array'); $constname = GETPOST('constname', 'alphanohtml'); diff --git a/htdocs/admin/defaultvalues.php b/htdocs/admin/defaultvalues.php index 4d88675ffd4..58a72250d64 100644 --- a/htdocs/admin/defaultvalues.php +++ b/htdocs/admin/defaultvalues.php @@ -64,7 +64,7 @@ if (!$sortorder) { $defaulturl = GETPOST('defaulturl', 'alphanohtml'); $defaultkey = GETPOST('defaultkey', 'alphanohtml'); -$defaultvalue = GETPOST('defaultvalue', 'none'); +$defaultvalue = GETPOST('defaultvalue', 'restricthtml'); $defaulturl = preg_replace('/^\//', '', $defaulturl); diff --git a/htdocs/admin/dolistore/css/dolistore.css b/htdocs/admin/dolistore/css/dolistore.css index fb4dc2d5bb1..3d8f163caf2 100644 --- a/htdocs/admin/dolistore/css/dolistore.css +++ b/htdocs/admin/dolistore/css/dolistore.css @@ -1,6 +1,5 @@ div.divsearchfield { - float: left; margin: 4px 12px 4px 2px; padding-left: 2px; } diff --git a/htdocs/admin/eventorganization.php b/htdocs/admin/eventorganization.php index 06309a2706e..8edc61bf255 100644 --- a/htdocs/admin/eventorganization.php +++ b/htdocs/admin/eventorganization.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/eventorganization.lib.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; // Translations -$langs->loadLangs(array("admin", "eventorganization")); +$langs->loadLangs(array("admin", "eventorganization", "categories")); // Parameters $action = GETPOST('action', 'aZ09'); @@ -54,11 +54,11 @@ $arrayofparameters = array( 'EVENTORGANIZATION_TEMPLATE_EMAIL_ASK_BOOTH'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1), 'EVENTORGANIZATION_TEMPLATE_EMAIL_AFT_SUBS_BOOTH'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1), 'EVENTORGANIZATION_TEMPLATE_EMAIL_AFT_SUBS_EVENT'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1), - 'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_SPEAKER'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1), - 'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_ATTENDES'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1), - 'EVENTORGANIZATION_SECUREKEY'=>array('type'=>'securekey', 'enabled'=>1), + //'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_SPEAKER'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1), + //'EVENTORGANIZATION_TEMPLATE_EMAIL_BULK_ATTENDES'=>array('type'=>'emailtemplate:conferenceorbooth', 'enabled'=>1), 'SERVICE_BOOTH_LOCATION'=>array('type'=>'product', 'enabled'=>1), 'SERVICE_CONFERENCE_ATTENDEE_SUBSCRIPTION'=>array('type'=>'product', 'enabled'=>1), + 'EVENTORGANIZATION_SECUREKEY'=>array('type'=>'securekey', 'enabled'=>1), ); $error = 0; diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index f720e411717..29d2335a0f9 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -535,11 +535,11 @@ if ($mode == 'common' || $mode == 'commonkanban') { //$moreforfilter .= '
'.$moreinfo.' '.$moreinfo2.'
'; - $moreforfilter .= '
'; - $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= img_picto($langs->trans("Filter"), 'filter', 'class="paddingright opacityhigh hideonsmartphone"').''; $moreforfilter .= '
'; - $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= $form->selectarray('search_nature', $arrayofnatures, dol_escape_htmltag($search_nature), $langs->trans('Origin'), 0, 0, '', 0, 0, 0, '', 'maxwidth250', 1); $moreforfilter .= '
'; if (getDolGlobalInt('MAIN_FEATURES_LEVEL')) { @@ -553,16 +553,16 @@ if ($mode == 'common' || $mode == 'commonkanban') { if ($conf->global->MAIN_FEATURES_LEVEL > 1) { $array_version['development'] = $langs->trans("Development"); } - $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= $form->selectarray('search_version', $array_version, $search_version, $langs->trans('Version'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); $moreforfilter .= '
'; } - $moreforfilter .= '
'; + $moreforfilter .= '
'; $moreforfilter .= $form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, $langs->trans('Status'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); $moreforfilter .= '
'; $moreforfilter .= ' '; - $moreforfilter .= '
'; - $moreforfilter .= ''; + $moreforfilter .= '
'; + $moreforfilter .= ''; if ($search_keyword || ($search_nature && $search_nature != '-1') || ($search_version && $search_version != '-1') || ($search_status && $search_status != '-1')) { $moreforfilter .= ' '; $moreforfilter .= ''; @@ -1139,7 +1139,7 @@ if ($mode == 'deploy') { } if ($allowfromweb == 1) { - print $langs->trans("UnpackPackageInModulesRoot", $dirins).'
'; + print ''.$langs->trans("UnpackPackageInModulesRoot", $dirins).'
'; print '
'; diff --git a/htdocs/admin/oauth.php b/htdocs/admin/oauth.php index 9bf5be2c294..a0d82d1d6bd 100644 --- a/htdocs/admin/oauth.php +++ b/htdocs/admin/oauth.php @@ -27,6 +27,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; +// $supportedoauth2array is defined into oauth.lib.php // Define $urlwithroot $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); @@ -96,10 +97,12 @@ print ''; $i = 0; -// $list is defined into oauth.lib.php +// $list is defined into oauth.lib.php to the list of supporter OAuth providers. foreach ($list as $key) { $supported = 0; - if (in_array($key[0], array_keys($supportedoauth2array))) { + $keyforsupportedoauth2array = $key[0]; + + if (in_array($keyforsupportedoauth2array, array_keys($supportedoauth2array))) { $supported = 1; } if (!$supported) { @@ -110,20 +113,23 @@ foreach ($list as $key) { print ''; // Api Name - $label = $langs->trans($key[0]); - print ''; + $label = $langs->trans($keyforsupportedoauth2array); print ''; + print ''; print ''; if ($supported) { - $redirect_uri = $urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$key[0]].'_oauthcallback.php'; + $redirect_uri = $urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$keyforsupportedoauth2array]['callbackfile'].'_oauthcallback.php'; print ''; print ''; - print ''; } else { print ''; diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php index 8697b400a2b..73a9139f856 100644 --- a/htdocs/admin/oauthlogintokens.php +++ b/htdocs/admin/oauthlogintokens.php @@ -25,17 +25,13 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // This define $list +require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // This define $list and $supportedoauth2array require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; use OAuth\Common\Storage\DoliStorage; // Load translation files required by the page $langs->loadLangs(array('admin', 'printing', 'oauth')); -if (!$user->admin) { - accessforbidden(); -} - $action = GETPOST('action', 'aZ09'); $mode = GETPOST('mode', 'alpha'); $value = GETPOST('value', 'alpha'); @@ -50,6 +46,10 @@ if (!$mode) { $mode = 'setup'; } +if (!$user->admin) { + accessforbidden(); +} + /* * Action @@ -122,7 +122,7 @@ $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domai $form = new Form($db); -llxHeader('', $langs->trans("PrintingSetup")); +llxHeader('', $langs->trans("TokenManager")); $linkback = ''.$langs->trans("BackToModuleList").''; print load_fiche_titre($langs->trans('ConfigOAuth'), $linkback, 'title_setup'); @@ -140,7 +140,9 @@ if ($mode == 'setup' && $user->admin) { foreach ($list as $key) { $supported = 0; - if (in_array($key[0], array_keys($supportedoauth2array))) { + $keyforsupportedoauth2array = $key[0]; + + if (in_array($keyforsupportedoauth2array, array_keys($supportedoauth2array))) { $supported = 1; } if (!$supported) { @@ -148,34 +150,44 @@ if ($mode == 'setup' && $user->admin) { } - $OAUTH_SERVICENAME = 'Unknown'; - if ($key[0] == 'OAUTH_GITHUB_NAME') { - $OAUTH_SERVICENAME = 'GitHub'; + $OAUTH_SERVICENAME = empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name']; + + // Define $shortscope, $urltorenew, $urltodelete, $urltocheckperms + // TODO Use array $supportedoauth2array + if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') { // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). // We pass this param list in to 'state' because we need it before and after the redirect. $shortscope = 'user,public_repo'; $urltorenew = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = $urlwithroot.'/core/modules/oauth/github_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltocheckperms = 'https://github.com/settings/applications/'; - } elseif ($key[0] == 'OAUTH_GOOGLE_NAME') { - $OAUTH_SERVICENAME = 'Google'; + } elseif ($keyforsupportedoauth2array == 'OAUTH_GOOGLE_NAME') { // List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service). - // We pass this param list in to 'state' because we need it before and after the redirect. - $shortscope = 'userinfo_email,userinfo_profile,cloud_print'; - if (!empty($conf->global->OAUTH_GSUITE)) { + // List of scopes for Google are here: https://developers.google.com/identity/protocols/oauth2/scopes + // We pass this key list into the param 'state' because we need it before and after the redirect. + $shortscope = 'userinfo_email,userinfo_profile'; + $shortscope .= ',openid,email,profile'; // For openid connect + if (!empty($conf->printing->enabled)) { + $shortscope .= ',cloud_print'; + } + if (!empty($conf->global->OAUTH_GOOGLE_GSUITE)) { $shortscope .= ',admin_directory_user'; } - //$scope.=',gmail_full'; - $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); + if (!empty($conf->global->OAUTH_GOOGLE_GMAIL)) { + $shortscope.=',gmail_full'; + } + + $oauthstateanticsrf = bin2hex(random_bytes(128/8)); + $_SESSION['oauthstateanticsrf'] = $shortscope.'-'.$oauthstateanticsrf; + + $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'-'.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltocheckperms = 'https://security.google.com/settings/security/permissions'; - } elseif ($key[0] == 'OAUTH_STRIPE_TEST_NAME') { - $OAUTH_SERVICENAME = 'StripeTest'; + } elseif ($keyforsupportedoauth2array == 'OAUTH_STRIPE_TEST_NAME') { $urltorenew = $urlwithroot.'/core/modules/oauth/stripetest_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = ''; $urltocheckperms = ''; - } elseif ($key[0] == 'OAUTH_STRIPE_LIVE_NAME') { - $OAUTH_SERVICENAME = 'StripeLive'; + } elseif ($keyforsupportedoauth2array == 'OAUTH_STRIPE_LIVE_NAME') { $urltorenew = $urlwithroot.'/core/modules/oauth/stripelive_oauthcallback.php?backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php'); $urltodelete = ''; $urltocheckperms = ''; @@ -230,11 +242,14 @@ if ($mode == 'setup' && $user->admin) { print ''; print ''; - print '
'; + print '
'; print '
'.$label.''; - if (!empty($key[3])) { - print $langs->trans($key[3]); + print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); + print $label; + print ''; + if (!empty($supportedoauth2array[$keyforsupportedoauth2array]['urlforapp'])) { + print $langs->trans($supportedoauth2array[$keyforsupportedoauth2array]['urlforapp']); } print '
'.$langs->trans("UseTheFollowingUrlAsRedirectURI").''; + print ''; print '
'."\n"; print ''; - print ''; + print ''; print ''; print ''; print "\n"; @@ -244,7 +259,7 @@ if ($mode == 'setup' && $user->admin) { //var_dump($key); print $langs->trans("OAuthIDSecret").''; print ''; print ''; @@ -259,7 +274,7 @@ if ($mode == 'setup' && $user->admin) { if (is_object($tokenobj)) { print $langs->trans("HasAccessToken"); } else { - print $langs->trans("NoAccessToken"); + print ''.$langs->trans("NoAccessToken").''; } print ''; print ''; //Mail Model - print ''; - + if (getDolGlobalString('AGENDA_REMINDER_EMAIL')) { + print ''; + } print '
'.$langs->trans($key[0]).''; + print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"'); + print $langs->trans($keyforsupportedoauth2array); + print '
'; - print $langs->trans("SeePreviousTab"); + print ''.$langs->trans("SeePreviousTab").''; print ''; print ''; @@ -346,7 +361,7 @@ if ($mode == 'setup' && $user->admin) { if ($mode == 'test' && $user->admin) { print $langs->trans('PrintTestDesc'.$driver)."

\n"; - print '
'; + print '
'; print ''; if (!empty($driver)) { require_once DOL_DOCUMENT_ROOT.'/core/modules/printing/'.$driver.'.modules.php'; diff --git a/htdocs/admin/tools/export_files.php b/htdocs/admin/tools/export_files.php index 0b9272c2418..36be1f273ff 100644 --- a/htdocs/admin/tools/export_files.php +++ b/htdocs/admin/tools/export_files.php @@ -137,7 +137,7 @@ $dirtocompress = basename($fulldirtocompress); if ($compression == 'zip') { $file .= '.zip'; - $excludefiles = '/(\.back|\.old|\.log|[\/\\\]temp[\/\\\]|documents[\/\\\]admin[\/\\\]documents[\/\\\])/i'; + $excludefiles = '/(\.back|\.old|\.log|\.pdf_preview-.*\.png|[\/\\\]temp[\/\\\]|documents[\/\\\]admin[\/\\\]documents[\/\\\])/i'; //var_dump($fulldirtocompress); //var_dump($outputdir."/".$file);exit; @@ -173,7 +173,7 @@ if ($compression == 'zip') { // We also exclude '/temp/' dir and 'documents/admin/documents' // We make escapement here and call executeCLI without escapement because we don't want to have the '*.log' escaped. - $cmd = "tar -cf ".escapeshellcmd($outputdir."/".$file)." --exclude-vcs --exclude-caches-all --exclude='temp' --exclude='*.log' --exclude='documents/admin/documents' -C '".escapeshellcmd(dol_sanitizePathName($dirtoswitch))."' '".escapeshellcmd(dol_sanitizeFileName($dirtocompress))."'"; + $cmd = "tar -cf ".escapeshellcmd($outputdir."/".$file)." --exclude-vcs --exclude-caches-all --exclude='temp' --exclude='*.log' --exclude='*.pdf_preview-*.png' --exclude='documents/admin/documents' -C '".escapeshellcmd(dol_sanitizePathName($dirtoswitch))."' '".escapeshellcmd(dol_sanitizeFileName($dirtocompress))."'"; $result = $utils->executeCLI($cmd, $outputfile, 0, null, 1); diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php index 3cd8d3e0774..28dbef6887e 100644 --- a/htdocs/api/class/api_documents.class.php +++ b/htdocs/api/class/api_documents.class.php @@ -624,6 +624,9 @@ class Documents extends DolibarrApi } elseif ($modulepart == 'expensereport') { require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; $object = new ExpenseReport($this->db); + } elseif ($modulepart == 'fichinter') { + require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php'; + $object = new Fichinter($this->db); } elseif ($modulepart == 'adherent' || $modulepart == 'member') { $modulepart = 'adherent'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 63f18d2c046..52b93acdabb 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -937,7 +937,7 @@ if ($action == 'create') { $("#selectcomplete").change(function() { if ($("#selectcomplete").val() == 100) { - if ($("#doneby").val() <= 0) $("#doneby").val(\''.$user->id.'\'); + if ($("#doneby").val() <= 0) $("#doneby").val(\''.((int) $user->id).'\'); } if ($("#selectcomplete").val() == 0) { @@ -992,7 +992,8 @@ if ($action == 'create') { if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { print ''; } @@ -1000,7 +1001,7 @@ if ($action == 'create') { print 'global->AGENDA_USE_EVENT_TYPE) ? ' class="fieldrequired titlefieldcreate"' : '').'>'.$langs->trans("Label").''; // Full day - print ''; + print ''; $datep = ($datep ? $datep : (is_null($object->datep) ? '' : $object->datep)); if (GETPOST('datep', 'int', 1)) { @@ -1311,7 +1312,7 @@ if ($action == 'create') { print '
'.$langs->trans("Type").''; $default = (empty($conf->global->AGENDA_USE_EVENT_TYPE_DEFAULT) ? 'AC_RDV' : $conf->global->AGENDA_USE_EVENT_TYPE_DEFAULT); - $formactions->select_type_actions(GETPOSTISSET("actioncode") ? GETPOST("actioncode", 'aZ09') : ($object->type_code ? $object->type_code : $default), "actioncode", "systemauto", 0, -1); + print img_picto($langs->trans("ActionType"), 'square', 'class="fawidth30 inline-block" style="color: #ddd;"'); + print $formactions->select_type_actions(GETPOSTISSET("actioncode") ? GETPOST("actioncode", 'aZ09') : ($object->type_code ? $object->type_code : $default), "actioncode", "systemauto", 0, -1, 0, 1); // TODO Replace 0 with -2 in onlyautoornot print '
'.$langs->trans("EventOnFullDay").'
'; - if ($conf->global->AGENDA_REMINDER_EMAIL || $conf->global->AGENDA_REMINDER_BROWSER) { + if (getDolGlobalString('AGENDA_REMINDER_EMAIL') || getDolGlobalString('AGENDA_REMINDER_BROWSER')) { //checkbox create reminder print '
'; print '
'; @@ -1336,10 +1337,11 @@ if ($action == 'create') { print '
'.$langs->trans("EMailTemplates").''; - print $form->selectModelMail('actioncommsend', 'actioncomm_send', 1, 1); - print '
'.$langs->trans("EMailTemplates").''; + print $form->selectModelMail('actioncommsend', 'actioncomm_send', 1, 1); + print '
'; print '
'; diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index e2adf06425f..9ab13962bfa 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -123,16 +123,17 @@ class ActionComm extends CommonObject */ public $label; + /** + * @var string Agenda event label + * @deprecated Use $label + */ + public $libelle; + /** * @var integer Date creation record (datec) */ public $datec; - /** - * @var integer Date end record (datef) - */ - public $datef; - /** * @var integer Duration (duree) */ @@ -172,6 +173,21 @@ class ActionComm extends CommonObject */ public $datep; + /** + * @var integer Date action end (datef) + */ + public $datef; + + /** + * @var integer This is date start action (datep) but modified to not be outside calendar view. + */ + public $date_start_in_calendar; + + /** + * @var integer This is date end action (datef) but modified to not be outside calendar view. + */ + public $date_end_in_calendar; + /** * @var integer Date action end (datep2) */ @@ -188,6 +204,11 @@ class ActionComm extends CommonObject */ public $fulldayevent = 0; + /** + * @var int 1=??? + */ + public $ponctuel; + /** * @var integer Percentage */ @@ -219,8 +240,7 @@ class ActionComm extends CommonObject public $userownerid; /** - * @var int Id of user done (deprecated) - * @deprecated + * @var int Id of user that has done the event. Used only if AGENDA_ENABLE_DONEBY is set. */ public $userdoneid; @@ -239,20 +259,6 @@ class ActionComm extends CommonObject */ public $reminders = array(); - /** - * @var User Object user of owner - * @deprecated - * @see $userownerid - */ - public $usertodo; - - /** - * @var User Object user that did action - * @deprecated - * @see $userdoneid - */ - public $userdone; - /** * @var int thirdparty id linked to action */ @@ -827,18 +833,17 @@ class ActionComm extends CommonObject $this->usermodid = $obj->fk_user_mod; if (!is_object($this->author)) { - $this->author = new stdClass(); // To avoid warning + $this->author = new User($this->db); // To avoid warning } $this->author->id = $obj->fk_user_author; // deprecated $this->author->firstname = $obj->firstname; // deprecated $this->author->lastname = $obj->lastname; // deprecated if (!is_object($this->usermod)) { - $this->usermod = new stdClass(); // To avoid warning + $this->usermod = new User($this->db); // To avoid warning } $this->usermod->id = $obj->fk_user_mod; // deprecated $this->userownerid = $obj->fk_user_action; - $this->userdoneid = $obj->fk_user_done; $this->priority = $obj->priority; $this->fulldayevent = $obj->fulldayevent; $this->location = $obj->location; @@ -1130,18 +1135,18 @@ class ActionComm extends CommonObject $sql .= ", datep2 = ".(strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : 'null'); $sql .= ", durationp = ".(isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'".$this->db->escape($this->durationp)."'" : "null"); // deprecated $sql .= ", note = '".$this->db->escape($this->note_private)."'"; - $sql .= ", fk_project =".($this->fk_project > 0 ? $this->fk_project : "null"); - $sql .= ", fk_soc =".($socid > 0 ? $socid : "null"); - $sql .= ", fk_contact =".($contactid > 0 ? $contactid : "null"); + $sql .= ", fk_project =".($this->fk_project > 0 ? ((int) $this->fk_project) : "null"); + $sql .= ", fk_soc =".($socid > 0 ? ((int) $socid) : "null"); + $sql .= ", fk_contact =".($contactid > 0 ? ((int) $contactid) : "null"); $sql .= ", priority = '".$this->db->escape($this->priority)."'"; $sql .= ", fulldayevent = '".$this->db->escape($this->fulldayevent)."'"; $sql .= ", location = ".($this->location ? "'".$this->db->escape($this->location)."'" : "null"); $sql .= ", transparency = '".$this->db->escape($this->transparency)."'"; - $sql .= ", fk_user_mod = ".$user->id; - $sql .= ", fk_user_action = ".($userownerid > 0 ? "'".$this->db->escape($userownerid)."'" : "null"); - $sql .= ", fk_user_done = ".($userdoneid > 0 ? "'".$this->db->escape($userdoneid)."'" : "null"); + $sql .= ", fk_user_mod = ".((int) $user->id); + $sql .= ", fk_user_action = ".($userownerid > 0 ? ((int) $userownerid) : "null"); + $sql .= ", fk_user_done = ".($userdoneid > 0 ? ((int) $userdoneid) : "null"); if (!empty($this->fk_element)) { - $sql .= ", fk_element=".($this->fk_element ? $this->db->escape($this->fk_element) : "null"); + $sql .= ", fk_element=".($this->fk_element ? ((int) $this->fk_element) : "null"); } if (!empty($this->elementtype)) { $sql .= ", elementtype=".($this->elementtype ? "'".$this->db->escape($this->elementtype)."'" : "null"); @@ -1439,9 +1444,9 @@ class ActionComm extends CommonObject /** - * Return label of status + * Return the label of the status * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @param int $hidenastatus 1=Show nothing if status is "Not applicable" * @return string String with status */ @@ -1628,36 +1633,34 @@ class ActionComm extends CommonObject } if ($withpicto == 2) { - $libelle = $label; if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { - $libelle = $labeltype; + $label = $labeltype; } - $libelleshort = ''; + $labelshort = ''; } else { - $libelle = (empty($this->libelle) ? $label : $this->libelle.(($label && $label != $this->libelle) ? ' '.$label : '')); - if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && empty($libelle)) { - $libelle = $labeltype; + if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && empty($label)) { + $label = $labeltype; } if ($maxlength < 0) { - $libelleshort = $this->ref; + $labelshort = $this->ref; } else { - $libelleshort = dol_trunc($libelle, $maxlength); + $labelshort = dol_trunc($label, $maxlength); } } if ($withpicto) { if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { // Add code into () if ($labeltype) { - $libelle .= (preg_match('/'.preg_quote($labeltype, '/').'/', $libelle) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')'); + $label .= (preg_match('/'.preg_quote($labeltype, '/').'/', $label) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')'); } } } $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $langs->trans("ShowAction").': '.$libelle), ($overwritepicto ? $overwritepicto : 'action'), (($this->type_color && $overwritepicto) ? 'style="color: #'.$this->type_color.' !important;" ' : '').($notooltip ? 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"' : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $langs->trans("ShowAction").': '.$label), ($overwritepicto ? $overwritepicto : 'action'), (($this->type_color && $overwritepicto) ? 'style="color: #'.$this->type_color.' !important;" ' : '').($notooltip ? 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"' : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); } - $result .= $libelleshort; + $result .= $labelshort; $result .= $linkend; global $action; diff --git a/htdocs/comm/action/class/actioncommreminder.class.php b/htdocs/comm/action/class/actioncommreminder.class.php index aa693d2e41f..ff242430b0a 100644 --- a/htdocs/comm/action/class/actioncommreminder.class.php +++ b/htdocs/comm/action/class/actioncommreminder.class.php @@ -205,9 +205,9 @@ class ActionCommReminder extends CommonObject } /** - * Retourne le libelle du status d'un user (actif, inactif) + * Return label of the status of a reminder * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto * @return string Label of status */ public function getLibStatut($mode = 0) diff --git a/htdocs/comm/action/class/cactioncomm.class.php b/htdocs/comm/action/class/cactioncomm.class.php index a248482ee9d..32c2345a657 100644 --- a/htdocs/comm/action/class/cactioncomm.class.php +++ b/htdocs/comm/action/class/cactioncomm.class.php @@ -145,7 +145,7 @@ class CActionComm * @param string|int $active 1 or 0 to filter on event state active or not ('' by default = no filter) * @param string $idorcode 'id' or 'code' or 'all' * @param string $excludetype Type to exclude ('system' or 'systemauto') - * @param int $onlyautoornot 1=Group all type AC_XXX into 1 line AC_MANUAL. 0=Keep details of type, -1=Keep details and add a combined line per calendar (Default, Auto, BoothConf, ...) + * @param int $onlyautoornot 1=Group all type AC_XXX into 1 line AC_MANUAL. 0=Keep details of type, -1 or -2=Keep details and add a combined line per calendar (Default, Auto, BoothConf, ...) * @param string $morefilter Add more SQL filter * @param int $shortlabel 1=Get short label instead of long label * @return mixed Array of all event types if OK, <0 if KO. Key of array is id or code depending on parameter $idorcode. @@ -241,7 +241,7 @@ class CActionComm $transcode = $langs->trans($keyfortrans); } $label = (($transcode != $keyfortrans) ? $transcode : $langs->trans($obj->label)); - if ($onlyautoornot == -1 && !empty($conf->global->AGENDA_USE_EVENT_TYPE)) { + if (($onlyautoornot == -1 || $onlyautoornot == -2) && !empty($conf->global->AGENDA_USE_EVENT_TYPE)) { if ($typecalendar == 'system') { $label = '   '.$label; $repid[-99] = $langs->trans("ActionAC_MANUAL"); diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 77d2680c222..d3538c6a2c9 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -107,10 +107,10 @@ $year = GETPOST("year", "int") ?GETPOST("year", "int") : date("Y"); $month = GETPOST("month", "int") ?GETPOST("month", "int") : date("m"); $week = GETPOST("week", "int") ?GETPOST("week", "int") : date("W"); $day = GETPOST("day", "int") ?GETPOST("day", "int") : date("d"); -$pid = GETPOST("search_projectid", "int", 3) ?GETPOST("search_projectid", "int", 3) : GETPOST("projectid", "int", 3); -$status = GETPOST("search_status", 'aZ09') ?GETPOST("search_status", 'aZ09') : GETPOST("status", 'aZ09'); // status may be 0, 50, 100, 'todo' -$type = GETPOST("search_type", 'aZ09') ?GETPOST("search_type", 'aZ09') : GETPOST("type", 'aZ09'); -$maxprint = (isset($_GET["maxprint"]) ?GETPOST("maxprint") : $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW); +$pid = GETPOST("search_projectid", "int", 3) ? GETPOST("search_projectid", "int", 3) : GETPOST("projectid", "int", 3); +$status = GETPOSTISSET("search_status") ? GETPOST("search_status", 'aZ09') : GETPOST("status", 'aZ09'); // status may be 0, 50, 100, 'todo' +$type = GETPOSTISSET("search_type", 'aZ09') ? GETPOST("search_type", 'aZ09') : GETPOST("type", 'aZ09'); +$maxprint = GETPOSTISSET("maxprint") ? GETPOST("maxprint", 'int') : $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW; $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') $dateselect = dol_mktime(0, 0, 0, GETPOST('dateselectmonth', 'int'), GETPOST('dateselectday', 'int'), GETPOST('dateselectyear', 'int')); @@ -570,7 +570,7 @@ if (!empty($conf->use_javascript_ajax)) { // If javascript on $s .= 'console.log("found parent div.dayevent with id = "+newval);'."\n"; $s .= 'var frm=jQuery("#searchFormList");'."\n"; $s .= 'var newurl = ui.item.find("a.cal_event").attr("href");'."\n"; - $s .= 'console.log(newurl);'."\n"; + $s .= 'console.log("Found url on href of a.cal_event"+newurl+", we submit form with actionmove=mupdate");'."\n"; $s .= 'frm.attr("action", newurl).children("#newdate").val(newval);frm.submit();}'."\n"; $s .= '});'."\n"; } @@ -837,7 +837,7 @@ if ($resql) { $event->fk_project = $obj->fk_project; - $event->thirdparty_id = $obj->fk_soc; + $event->socid = $obj->fk_soc; $event->contact_id = $obj->fk_contact; // Defined date_start_in_calendar and date_end_in_calendar property @@ -848,10 +848,6 @@ if ($resql) { } else { $event->date_end_in_calendar = $event->datep; } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - } // Check values if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) { @@ -945,7 +941,6 @@ if ($showbirthday) { $event->date_start_in_calendar = $db->jdate($event->datep); $event->date_end_in_calendar = $db->jdate($event->datef); - $event->ponctuel = 0; // Add an entry in eventarray for each day $daycursor = $event->datep; @@ -1288,12 +1283,6 @@ if (count($listofextcals)) { $event->date_end_in_calendar = $event->datep; } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - //print 'x'.$datestart.'-'.$dateend;exit; - } - // Add event into $eventarray if date range are ok. if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) { //print 'x'.$datestart.'-'.$dateend;exit; @@ -1393,7 +1382,7 @@ if (empty($mode) || $mode == 'show_month') { // View by month print '
'; print '
'; - print ''; + print '
'; print ' '; // Column title of weeks numbers echo ' '; @@ -1482,7 +1471,7 @@ if (empty($mode) || $mode == 'show_month') { // View by month print ''; print ''; - print ''; + print ''; print ''; } elseif ($mode == 'show_week') { // View by week @@ -1502,7 +1491,7 @@ if (empty($mode) || $mode == 'show_month') { // View by month print ''; print '
'; - print '
#
'; + print '
'; print ' '; $i = 0; while ($i < 7) { @@ -1544,10 +1533,9 @@ if (empty($mode) || $mode == 'show_month') { // View by month print ''; echo ''; - echo ''; + echo ''; echo ''; -} else // View by day -{ +} else { // View by day $newparam = $param; // newparam is for birthday links $newparam = preg_replace('/mode=show_month&?/i', '', $newparam); $newparam = preg_replace('/mode=show_week&?/i', '', $newparam); @@ -1965,7 +1953,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa if ($event->type_code != 'ICALEVENT') { $savlabel = $event->label ? $event->label : $event->libelle; $event->label = $titletoshow; - $event->libelle = $titletoshow; + $event->libelle = $titletoshow; // deprecatd // Note: List of users are inside $event->userassigned. Link may be clickable depending on permissions of user. $titletoshow = (($event->type_picto || $event->type_code) ? $event->getTypePicto() : ''); $titletoshow .= $event->getNomUrl(0, $maxnbofchar, 'cal_event cal_event_title', '', 0, 0); @@ -1997,7 +1985,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa print '
('.dol_trunc($event->icalname, $maxnbofchar).')'; } - $thirdparty_id = ($event->thirdparty_id > 0 ? $event->thirdparty_id : ((is_object($event->societe) && $event->societe->id > 0) ? $event->societe->id : 0)); + $thirdparty_id = ($event->socid > 0 ? $event->socid : ((is_object($event->societe) && $event->societe->id > 0) ? $event->societe->id : 0)); $contact_id = ($event->contact_id > 0 ? $event->contact_id : ((is_object($event->contact) && $event->contact->id > 0) ? $event->contact->id : 0)); // If action related to company / contact diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index 8b6119eb294..eee8baa2b20 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -683,10 +683,6 @@ if ($resql) { $event->date_end_in_calendar = $datep; } } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - } // Check values if ($event->date_end_in_calendar < $firstdaytoshow || @@ -1236,9 +1232,9 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s $color2 = '222222'; } print '
'; - print ''; print '
'; + print '
'; print $string1; - print ''; + print ''; print $string2; print '
'; diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index e2bc5931d66..957ccd6e361 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -711,10 +711,6 @@ if ($resql) { $event->date_end_in_calendar = $datep; } } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) { - $event->ponctuel = 1; - } // Check values if ($event->date_end_in_calendar < $firstdaytoshow || @@ -1441,7 +1437,7 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, & } print 'class="'; print ($style1 ? $style1.' ' : ''); - print 'onclickopenref'.($title2 ? ' classfortooltip' : '').($title1 ? ' cursorpointer' : '').'" ref="ref_'.$username->id.'_'.sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day).'_'.sprintf("%02d", $h).'_00_'.($ids1 ? $ids1 : 'none').'"'.($title1 ? ' title="'.$title1.'"' : '').'>'; + print 'onclickopenref center'.($title2 ? ' classfortooltip' : '').($title1 ? ' cursorpointer' : '').'" ref="ref_'.$username->id.'_'.sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day).'_'.sprintf("%02d", $h).'_00_'.($ids1 ? $ids1 : 'none').'"'.($title1 ? ' title="'.$title1.'"' : '').'>'; print $string1; print ''; + print 'onclickopenref center'.($title2 ? ' classfortooltip' : '').($title1 ? ' cursorpointer' : '').'" ref="ref_'.$username->id.'_'.sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day).'_'.sprintf("%02d", $h).'_30_'.($ids2 ? $ids2 : 'none').'"'.($title2 ? ' title="'.$title2.'"' : '').'>'; print $string2; print ''; print ''; diff --git a/htdocs/comm/contact.php b/htdocs/comm/contact.php index 57a88bef157..62f57c008ba 100644 --- a/htdocs/comm/contact.php +++ b/htdocs/comm/contact.php @@ -157,10 +157,10 @@ if ($resql) { print ''; print ''.img_object($langs->trans("ShowContact"), "contact"); print ' '.$obj->name.''; - print "$obj->firstname"; + print ''.dol_escape_htmltag($obj->firstname).''; print ''.img_object($langs->trans("ShowCompany"), "company").' '; - print "rowid."\">$obj->name\n"; + print ''.$obj->name."\n"; print ''.dol_print_phone($obj->email, $obj->cidp, $obj->rowid, 'AC_EMAIL').''; diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 7f2410da136..79faf4b2cd2 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -493,9 +493,9 @@ if (empty($reshook)) { if ($action == 'add') { $mesgs = array(); - $object->email_from = (string) GETPOST("from", "none"); // Must allow 'name ' - $object->email_replyto = (string) GETPOST("replyto", "none"); // Must allow 'name ' - $object->email_errorsto = (string) GETPOST("errorsto", "none"); // Must allow 'name ' + $object->email_from = (string) GETPOST("from", 'alphawithlgt'); // Must allow 'name ' + $object->email_replyto = (string) GETPOST("replyto", 'alphawithlgt'); // Must allow 'name ' + $object->email_errorsto = (string) GETPOST("errorsto", 'alphawithlgt'); // Must allow 'name ' $object->title = (string) GETPOST("title"); $object->sujet = (string) GETPOST("sujet"); $object->body = (string) GETPOST("bodyemail", 'restricthtml'); @@ -531,11 +531,11 @@ if (empty($reshook)) { if ($action == 'settitle') { $object->title = trim(GETPOST('title', 'alpha')); } elseif ($action == 'setemail_from') { - $object->email_from = trim(GETPOST('email_from', 'none')); // Must allow 'name ' + $object->email_from = trim(GETPOST('email_from', 'alphawithlgt')); // Must allow 'name ' } elseif ($action == 'setemail_replyto') { - $object->email_replyto = trim(GETPOST('email_replyto', 'none')); // Must allow 'name ' + $object->email_replyto = trim(GETPOST('email_replyto', 'alphawithlgt')); // Must allow 'name ' } elseif ($action == 'setemail_errorsto') { - $object->email_errorsto = trim(GETPOST('email_errorsto', 'none')); // Must allow 'name ' + $object->email_errorsto = trim(GETPOST('email_errorsto', 'alphawithlgt')); // Must allow 'name ' } elseif ($action == 'settitle' && empty($object->title)) { $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("MailTitle")); } elseif ($action == 'setfrom' && empty($object->email_from)) { diff --git a/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php b/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php index cfdca4a1fc2..f4295fa6583 100644 --- a/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php +++ b/htdocs/comm/mailing/class/html.formadvtargetemailing.class.php @@ -230,7 +230,7 @@ class FormAdvTargetEmailing extends Form $InfoFieldList = explode(":", $param_list [0]); // 0 1 : tableName - // 1 2 : label field name Nom du champ contenant le libelle + // 1 2 : label field name Name of field that contains the label // 2 3 : key fields name (if differ of rowid) // 3 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value @@ -304,7 +304,7 @@ class FormAdvTargetEmailing extends Form if ($num) { while ($i < $num) { $obj = $this->db->fetch_object($resql); - // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut + // If a translation exists, we use it, else we use the default label $label = ($langs->trans("Civility".$obj->code) != "Civility".$obj->code ? $langs->trans("Civility".$obj->code) : ($obj->civilite != '-' ? $obj->civilite : '')); $options_array[$obj->code] = $label; diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php index cb900f7ac7b..8050b85f180 100644 --- a/htdocs/comm/mailing/class/mailing.class.php +++ b/htdocs/comm/mailing/class/mailing.class.php @@ -754,7 +754,7 @@ class Mailing extends CommonObject /** * Return label of status of emailing (draft, validated, ...) * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @return string Label */ public function getLibStatut($mode = 0) @@ -764,10 +764,10 @@ class Mailing extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Renvoi le libelle d'un statut donne + * Return the label of a given status * * @param int $status Id status - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @return string Label */ public function LibStatut($status, $mode = 0) @@ -792,11 +792,11 @@ class Mailing extends CommonObject /** - * Renvoi le libelle d'un statut donne + * Return the label of a given status of a recipient * TODO Add class mailin_target.class.php * * @param int $status Id status - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @param int $mode 0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto * @param string $desc Desc error * @return string Label */ diff --git a/htdocs/comm/prospect/index.php b/htdocs/comm/prospect/index.php index 1e1caa796b5..0bcf2662a44 100644 --- a/htdocs/comm/prospect/index.php +++ b/htdocs/comm/prospect/index.php @@ -77,7 +77,7 @@ if (!empty($conf->propal->enabled)) { * */ -$sql = "SELECT count(*) as cc, st.libelle, st.picto, st.id"; +$sql = "SELECT count(*) as cc, st.libelle as stcomm, st.picto, st.id"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= ", ".MAIN_DB_PREFIX."c_stcomm as st "; if (empty($user->rights->societe->client->voir) && !$socid) { diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index f60a91ae3df..652e7a72d4a 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -490,7 +490,8 @@ class Commande extends CommonOrder $sql .= " SET ref = '".$this->db->escape($num)."',"; $sql .= " fk_statut = ".self::STATUS_VALIDATED.","; $sql .= " date_valid='".$this->db->idate($now)."',"; - $sql .= " fk_user_valid = ".((int) $user->id); + $sql .= " fk_user_valid = ".((int) $user->id).","; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::valid", LOG_DEBUG); @@ -620,7 +621,8 @@ class Commande extends CommonOrder $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."commande"; - $sql .= " SET fk_statut = ".self::STATUS_DRAFT; + $sql .= " SET fk_statut = ".self::STATUS_DRAFT."',"; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); if ($this->db->query($sql)) { @@ -694,7 +696,8 @@ class Commande extends CommonOrder $this->db->begin(); $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande'; - $sql .= ' SET fk_statut='.self::STATUS_VALIDATED.', facture=0'; + $sql .= ' SET fk_statut='.self::STATUS_VALIDATED.', facture=0,'; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::set_reopen", LOG_DEBUG); @@ -755,7 +758,8 @@ class Commande extends CommonOrder $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql .= ' SET fk_statut = '.self::STATUS_CLOSED.','; $sql .= ' fk_user_cloture = '.((int) $user->id).','; - $sql .= " date_cloture = '".$this->db->idate($now)."'"; + $sql .= " date_cloture = '".$this->db->idate($now)."',"; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > '.self::STATUS_DRAFT; if ($this->db->query($sql)) { @@ -803,7 +807,8 @@ class Commande extends CommonOrder $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."commande"; - $sql .= " SET fk_statut = ".self::STATUS_CANCELED; + $sql .= " SET fk_statut = ".self::STATUS_CANCELED.","; + $sql .= " fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); $sql .= " AND fk_statut = ".self::STATUS_VALIDATED; @@ -1779,7 +1784,7 @@ class Commande extends CommonOrder return -1; } - $sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_statut'; + $sql = 'SELECT c.rowid, c.entity, c.date_creation, c.ref, c.fk_soc, c.fk_user_author, c.fk_user_valid, c.fk_user_modif, c.fk_statut'; $sql .= ', c.amount_ht, c.total_ht, c.total_ttc, c.total_tva, c.localtax1 as total_localtax1, c.localtax2 as total_localtax2, c.fk_cond_reglement, c.fk_mode_reglement, c.fk_availability, c.fk_input_reason'; $sql .= ', c.fk_account'; $sql .= ', c.date_commande, c.date_valid, c.tms'; @@ -1844,6 +1849,7 @@ class Commande extends CommonOrder $this->user_author_id = $obj->fk_user_author; $this->user_valid = $obj->fk_user_valid; + $this->user_modification = $obj->fk_user_modif; $this->total_ht = $obj->total_ht; $this->total_tva = $obj->total_tva; $this->total_localtax1 = $obj->total_localtax1; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 74d08ddef2a..63fee0085bb 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -527,9 +527,9 @@ class Facture extends CommonInvoice // Fields coming from GUI (priority on template). TODO Value of template should be used as default value on GUI so we can use here always value from GUI $this->fk_project = GETPOST('projectid', 'int') > 0 ? ((int) GETPOST('projectid', 'int')) : $_facrec->fk_project; - $this->note_public = GETPOST('note_public', 'none') ? GETPOST('note_public', 'restricthtml') : $_facrec->note_public; - $this->note_private = GETPOST('note_private', 'none') ? GETPOST('note_private', 'restricthtml') : $_facrec->note_private; - $this->model_pdf = GETPOST('model', 'alpha') ? GETPOST('model', 'alpha') : $_facrec->model_pdf; + $this->note_public = GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $_facrec->note_public; + $this->note_private = GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $_facrec->note_private; + $this->model_pdf = GETPOSTISSET('model') ? GETPOST('model', 'alpha') : $_facrec->model_pdf; $this->cond_reglement_id = GETPOST('cond_reglement_id', 'int') > 0 ? ((int) GETPOST('cond_reglement_id', 'int')) : $_facrec->cond_reglement_id; $this->mode_reglement_id = GETPOST('mode_reglement_id', 'int') > 0 ? ((int) GETPOST('mode_reglement_id', 'int')) : $_facrec->mode_reglement_id; $this->fk_account = GETPOST('fk_account') > 0 ? ((int) GETPOST('fk_account')) : $_facrec->fk_account; diff --git a/htdocs/compta/tva/card.php b/htdocs/compta/tva/card.php index 530d18d17f9..317838009c7 100644 --- a/htdocs/compta/tva/card.php +++ b/htdocs/compta/tva/card.php @@ -196,7 +196,8 @@ if ($action == 'add' && !$cancel) { } $object->amount = $amount; $object->label = GETPOST("label", 'alpha'); - $object->note = GETPOST("note", 'none'); + $object->note = GETPOST("note", 'restricthtml'); + $object->note_private = GETPOST("note", 'restricthtml'); if (empty($object->datep)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DatePayment")), null, 'errors'); @@ -236,7 +237,7 @@ if ($action == 'add' && !$cancel) { $paiement->amounts = array($object->id=>$amount); // Tableau de montant $paiement->paiementtype = GETPOST("type_payment", 'alphanohtml'); $paiement->num_payment = GETPOST("num_payment", 'alphanohtml'); - $paiement->note = GETPOST("note", 'none'); + $paiement->note = GETPOST("note", 'restricthtml'); if (!$error) { $paymentid = $paiement->create($user, (int) GETPOST('closepaidtva')); diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 5f161f88bfb..602897d34f9 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -81,7 +81,7 @@ if (!$error && $massaction == 'confirm_presend') { $listofobjectref = array(); $contactidtosend = array(); $attachedfilesThirdpartyObj = array(); - $oneemailperrecipient = (GETPOST('oneemailperrecipient') == 'on' ? 1 : 0); + $oneemailperrecipient = (GETPOST('oneemailperrecipient', 'int') ? 1 : 0); if (!$error) { $thirdparty = new Societe($db); diff --git a/htdocs/core/actions_setmoduleoptions.inc.php b/htdocs/core/actions_setmoduleoptions.inc.php index 43ddd23f13d..fbf526fd58e 100644 --- a/htdocs/core/actions_setmoduleoptions.inc.php +++ b/htdocs/core/actions_setmoduleoptions.inc.php @@ -29,13 +29,13 @@ // $formSetup may be defined -if ($action == 'update' && !empty($formSetup) && is_object($formSetup)) { +if ($action == 'update' && !empty($formSetup) && is_object($formSetup) && !empty($user->admin)) { $formSetup->saveConfFromPost(); return; } -if ($action == 'update' && is_array($arrayofparameters)) { +if ($action == 'update' && is_array($arrayofparameters) && !empty($user->admin)) { $db->begin(); foreach ($arrayofparameters as $key => $val) { @@ -72,8 +72,37 @@ if ($action == 'update' && is_array($arrayofparameters)) { } } +if ($action == 'deletefile' && $modulepart == 'doctemplates' && !empty($user->admin)) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + $keyforuploaddir = GETPOST('keyforuploaddir', 'aZ09'); + + $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString($keyforuploaddir)))); + foreach ($listofdir as $key => $tmpdir) { + $tmpdir = preg_replace('/DOL_DATA_ROOT\/*/', '', $tmpdir); // Clean string if we found a hardcoded DOL_DATA_ROOT + if (!$tmpdir) { + unset($listofdir[$key]); + continue; + } + $tmpdir = DOL_DATA_ROOT.'/'.$tmpdir; // Complete with DOL_DATA_ROOT. Only files into DOL_DATA_ROOT can be reach/set + if (!is_dir($tmpdir)) { + if (empty($nomessageinsetmoduleoptions)) { + setEventMessages($langs->trans("ErrorDirNotFound", $tmpdir), null, 'warnings'); + } + } else { + $upload_dir = $tmpdir; + break; // So we take the first directory found into setup $conf->global->$keyforuploaddir + } + } + + $filetodelete = $tmpdir.'/'.GETPOST('file'); + $result = dol_delete_file($filetodelete); + if ($result > 0) { + setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs'); + } +} + // Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) -if ($action == 'setModuleOptions') { +if ($action == 'setModuleOptions' && !empty($user->admin)) { $db->begin(); // Process common param fields @@ -97,20 +126,22 @@ if ($action == 'setModuleOptions') { if (GETPOST('upload', 'alpha') && GETPOST('keyforuploaddir', 'aZ09')) { include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $keyforuploaddir = GETPOST('keyforuploaddir', 'aZ09'); - $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->$keyforuploaddir))); + $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString($keyforuploaddir)))); foreach ($listofdir as $key => $tmpdir) { $tmpdir = trim($tmpdir); - $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir); + $tmpdir = preg_replace('/DOL_DATA_ROOT\/*/', '', $tmpdir); // Clean string if we found a hardcoded DOL_DATA_ROOT if (!$tmpdir) { unset($listofdir[$key]); continue; } + $tmpdir = DOL_DATA_ROOT.'/'.$tmpdir; // Complete with DOL_DATA_ROOT. Only files into DOL_DATA_ROOT can be reach/set if (!is_dir($tmpdir)) { if (empty($nomessageinsetmoduleoptions)) { setEventMessages($langs->trans("ErrorDirNotFound", $tmpdir), null, 'warnings'); } } else { $upload_dir = $tmpdir; + break; // So we take the first directory found into setup $conf->global->$keyforuploaddir } } if ($upload_dir) { diff --git a/htdocs/core/ajax/check_notifications.php b/htdocs/core/ajax/check_notifications.php index bbbc95a19c5..a5efb52e787 100644 --- a/htdocs/core/ajax/check_notifications.php +++ b/htdocs/core/ajax/check_notifications.php @@ -170,8 +170,10 @@ if (empty($_SESSION['auto_check_events_not_before']) || $time >= $_SESSION['auto $event['code'] = $obj->code; $event['label'] = $obj->label; $event['location'] = $obj->location; - $event['reminder_date_formated'] = dol_print_date($db->jdate($obj->dateremind), 'standard'); - $event['event_date_start_formated'] = dol_print_date($db->jdate($obj->datep), 'standard'); + $event['reminder_date_formated_tzserver'] = dol_print_date($db->jdate($obj->dateremind), 'standard', 'tzserver'); + $event['event_date_start_formated_tzserver'] = dol_print_date($db->jdate($obj->datep), 'standard', 'tzserver'); + $event['reminder_date_formated'] = dol_print_date($db->jdate($obj->dateremind), 'standard', 'tzuser'); + $event['event_date_start_formated'] = dol_print_date($db->jdate($obj->datep), 'standard', 'tzuser'); $eventfound[$obj->id_agenda] = $event; } diff --git a/htdocs/core/boxes/box_produits_alerte_stock.php b/htdocs/core/boxes/box_produits_alerte_stock.php index b9d3494d00b..14862f3cf43 100644 --- a/htdocs/core/boxes/box_produits_alerte_stock.php +++ b/htdocs/core/boxes/box_produits_alerte_stock.php @@ -94,12 +94,12 @@ class box_produits_alerte_stock extends ModeleBoxes $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as s on p.rowid = s.fk_product"; $sql .= ' WHERE p.entity IN ('.getEntity($productstatic->element).')'; - $sql .= " AND p.tosell = 1 AND p.seuil_stock_alerte > 0"; + $sql .= " AND p.seuil_stock_alerte > 0"; if (empty($user->rights->produit->lire)) { - $sql .= ' AND p.fk_product_type != 0'; + $sql .= ' AND p.fk_product_type <> 0'; } if (empty($user->rights->service->lire)) { - $sql .= ' AND p.fk_product_type != 1'; + $sql .= ' AND p.fk_product_type <> 1'; } // Add where from hooks if (is_object($hookmanager)) { diff --git a/htdocs/core/boxes/box_validated_projects.php b/htdocs/core/boxes/box_validated_projects.php index 574ee7b7d80..e57bb1f14d9 100644 --- a/htdocs/core/boxes/box_validated_projects.php +++ b/htdocs/core/boxes/box_validated_projects.php @@ -26,6 +26,7 @@ */ include_once DOL_DOCUMENT_ROOT."/core/boxes/modules_boxes.php"; + /** * Class to manage the box to show last projet */ @@ -63,7 +64,7 @@ class box_validated_projects extends ModeleBoxes $langs->loadLangs(array('boxes', 'projects')); $this->db = $db; - $this->boxlabel = "ProjectsWithTask"; + $this->boxlabel = "ProjectTasksWithoutTimeSpent"; $this->hidden = !($user->rights->projet->lire); @@ -116,7 +117,7 @@ class box_validated_projects extends ModeleBoxes $sql .= " INNER JOIN ".MAIN_DB_PREFIX."element_contact as ec ON ec.element_id = t.rowid AND fk_c_type_contact IN (-1, -2, -3)"; $sql .= " WHERE p.fk_statut = 1"; // Only open projects if ($projectsListId) { - $sql .= ' AND p.rowid IN ('.$this->db->sanitize($projectsListId).')'; // Only project are allowed + $sql .= ' AND p.rowid IN ('.$this->db->sanitize($projectsListId).')'; // Only projects that are allowed } $sql .= " AND t.rowid NOT IN (SELECT fk_task FROM ".MAIN_DB_PREFIX."projet_task_time WHERE fk_user = ".((int) $user->id).")"; $sql .= " GROUP BY p.rowid, p.ref, p.fk_soc, p.dateo"; diff --git a/htdocs/core/class/CSMSFile.class.php b/htdocs/core/class/CSMSFile.class.php index 8d5bcf7dc50..3f082ba6d53 100644 --- a/htdocs/core/class/CSMSFile.class.php +++ b/htdocs/core/class/CSMSFile.class.php @@ -29,8 +29,9 @@ /** * Class to send SMS - * Usage: $smsfile = new CSMSFile($subject,$sendto,$replyto,$message,$filepath,$mimetype,$filename,$cc,$ccc,$deliveryreceipt,$msgishtml,$errors_to); - * $smsfile->sendfile(); + * Usage: $smsfile = new CSMSFile($subject,$sendto,$replyto,$message,$filepath,$mimetype,$filename,$cc,$ccc,$deliveryreceipt,$msgishtml,$errors_to); + * $smsfile->socid=...; $smsfile->contact_id=...; $smsfile->member_id=...; $smsfile->fk_project=...; + * $smsfile->sendfile(); */ class CSMSFile { @@ -48,7 +49,8 @@ class CSMSFile public $nostop; public $socid; - public $contactid; + public $contact_id; + public $member_id; public $fk_project; @@ -135,6 +137,7 @@ class CSMSFile $sms->socid = $this->socid; $sms->contact_id = $this->contact_id; + $sms->member_id = $this->member_id; $sms->project = $this->fk_project; $res = $sms->SmsSend(); @@ -167,6 +170,7 @@ class CSMSFile $sms->socid = $this->socid; $sms->contact_id = $this->contact_id; + $sms->member_id = $this->member_id; $sms->fk_project = $this->fk_project; $res = $sms->SmsSend(); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 029ac6cbfc1..db004c117a0 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1215,17 +1215,20 @@ abstract class CommonObject public function delete_linked_contact($source = '', $code = '') { // phpcs:enable + $listId = ''; $temp = array(); $typeContact = $this->liste_type_contact($source, '', 0, 0, $code); - foreach ($typeContact as $key => $value) { - array_push($temp, $key); + if (!empty($typeContact)) { + foreach ($typeContact as $key => $value) { + array_push($temp, $key); + } + $listId = implode(",", $temp); } - $listId = implode(",", $temp); $sql = "DELETE FROM ".MAIN_DB_PREFIX."element_contact"; $sql .= " WHERE element_id = ".((int) $this->id); - if ($listId) { + if (!empty($listId)) { $sql .= " AND fk_c_type_contact IN (".$this->db->sanitize($listId).")"; } diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 2b19e0db134..c7d01cab586 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -258,7 +258,7 @@ class Conf // Define all global constants into $this->global->key=value $sql = "SELECT ".$db->decrypt('name')." as name,"; $sql .= " ".$db->decrypt('value')." as value, entity"; - $sql .= " FROM ".MAIN_DB_PREFIX."const"; + $sql .= " FROM ".$db->prefix()."const"; $sql .= " WHERE entity IN (0,".$this->entity.")"; $sql .= " ORDER BY entity"; // This is to have entity 0 first, then entity 1 that overwrite. diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index d1b1e08710e..a40ec3e30c3 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -111,7 +111,7 @@ class HookManager if (in_array($context, $arrayhooks) || in_array('all', $arrayhooks)) { // We instantiate action class only if initialized hook is handled by module // Include actions class overwriting hooks - if (empty($this->hooks[$context][$module]) || !is_object($this->hooks[$context][$module])) { // If set to an object value, class was already loaded + if (empty($this->hooks[$context][$module]) || !is_object($this->hooks[$context][$module])) { // If set to an object value, class was already loaded so we do nothing. $path = '/'.$module.'/class/'; $actionfile = 'actions_'.$module.'.class.php'; diff --git a/htdocs/core/class/html.formactions.class.php b/htdocs/core/class/html.formactions.class.php index d4f4779a606..f5502426b00 100644 --- a/htdocs/core/class/html.formactions.class.php +++ b/htdocs/core/class/html.formactions.class.php @@ -352,7 +352,7 @@ class FormActions * @param array|string $selected Type pre-selected (can be 'manual', 'auto' or 'AC_xxx'). Can be an array too. * @param string $htmlname Name of select field * @param string $excludetype A type to exclude ('systemauto', 'system', '') - * @param integer $onlyautoornot 1=Group all type AC_XXX into 1 line AC_MANUAL. 0=Keep details of type, -1=Keep details and add a combined line "All manual" + * @param integer $onlyautoornot 1=Group all type AC_XXX into 1 line AC_MANUAL. 0=Keep details of type, -1=Keep details and add a combined line "All manual", -2=Combined line is disabled (not implemented yet) * @param int $hideinfohelp 1=Do not show info help, 0=Show, -1=Show+Add info to tell how to set default value * @param int $multiselect 1=Allow multiselect of action type * @param int $nooutput 1=No output @@ -373,7 +373,7 @@ class FormActions $caction = new CActionComm($this->db); // Suggest a list with manual events or all auto events - $arraylist = $caction->liste_array(1, 'code', $excludetype, $onlyautoornot); + $arraylist = $caction->liste_array(1, 'code', $excludetype, $onlyautoornot, '', 0); // If we use param 'all' instead of 'code', there is no group by include in answer but the key 'type' of answer array contains the key for the group by. if (empty($multiselect)) { // Add empty line at start only if no multiselect array_unshift($arraylist, ' '); diff --git a/htdocs/core/class/html.formadmin.class.php b/htdocs/core/class/html.formadmin.class.php index 3240d64c893..99ce3bb0201 100644 --- a/htdocs/core/class/html.formadmin.class.php +++ b/htdocs/core/class/html.formadmin.class.php @@ -73,15 +73,19 @@ class FormAdmin $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 12, 0, $mainlangonly); - // If the language to select is not inside the list of available language and empty value is not available, we must find - // an alternative as the language code to pre-select (to avoid to have first element in list pre-selected). - if ($selected && !array_key_exists($selected, $langs_available) && empty($showempty)) { - $tmparray = explode('_', $selected); - if (!empty($tmparray[1])) { - $selected = getLanguageCodeFromCountryCode($tmparray[1]); - } - if (empty($selected)) { - $selected = $langs->defaultlang; + // If empty value is not allowed and the language to select is not inside the list of available language and we must find + // an alternative of the language code to pre-select (to avoid to have first element in list pre-selected). + if ($selected && empty($showempty)) { + if (!is_array($selected) && !array_key_exists($selected, $langs_available)) { + $tmparray = explode('_', $selected); + if (!empty($tmparray[1])) { + $selected = getLanguageCodeFromCountryCode($tmparray[1]); + } + if (empty($selected)) { + $selected = $langs->defaultlang; + } + } else { + // If the preselected value is an array, we do not try to find alternative to preselect } } diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 3539348e35a..b848e04b061 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -379,9 +379,10 @@ class FormFile * @param Object $object Object when method is called from an object card. * @param int $hideifempty Hide section of generated files if there is no file * @param string $removeaction (optional) The action to remove a file + * @param string $tooltipontemplatecombo Text to show on a tooltip after the combo list of templates * @return string Output string with HTML array of documents (might be empty string) */ - public function showdocuments($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed = 0, $modelselected = '', $allowgenifempty = 1, $forcenomultilang = 0, $iconPDF = 0, $notused = 0, $noform = 0, $param = '', $title = '', $buttonlabel = '', $codelang = '', $morepicto = '', $object = null, $hideifempty = 0, $removeaction = 'remove_file') + public function showdocuments($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed = 0, $modelselected = '', $allowgenifempty = 1, $forcenomultilang = 0, $iconPDF = 0, $notused = 0, $noform = 0, $param = '', $title = '', $buttonlabel = '', $codelang = '', $morepicto = '', $object = null, $hideifempty = 0, $removeaction = 'remove_file', $tooltipontemplatecombo = '') { global $dolibarr_main_url_root; @@ -769,6 +770,7 @@ class FormFile if ($conf->use_javascript_ajax) { $out .= ajax_combobox('model'); } + $out .= $form->textwithpicto('', $tooltipontemplatecombo, 1, 'help', 'marginrightonly', 0, 3, '', 0); } else { $out .= '
'.$langs->trans("Files").'
'; } diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 7ceca2f373b..72b4050f9b3 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -157,6 +157,7 @@ class FormMail extends Form public $lines_model; + // -1 suggest the checkbox 'one email per recipient' not checked, 0 = no suggestion, 1 = suggest and checked public $withoptiononeemailperrecipient; @@ -357,7 +358,7 @@ class FormMail extends Form // phpcs:enable global $conf, $langs, $user, $hookmanager, $form; - // Required to show preview of mail attachments + // Required to show preview wof mail attachments require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; $formfile = new Formfile($this->db); @@ -366,7 +367,7 @@ class FormMail extends Form } // Load translation files required by the page - $langs->loadLangs(array('other', 'mails')); + $langs->loadLangs(array('other', 'mails', 'members')); // Clear temp files. Must be done before call of triggers, at beginning (mode = init), or when we select a new template if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) { @@ -464,11 +465,10 @@ class FormMail extends Form $modelmail_array = array(); if ($this->param['models'] != 'none') { $result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs); - if ($result < 0) { setEventMessages($this->error, $this->errors, 'errors'); } - $langs->trans("members"); + foreach ($this->lines_model as $line) { $reg = array(); if (preg_match('/\((.*)\)/', $line->label, $reg)) { @@ -503,7 +503,7 @@ class FormMail extends Form } $out .= '   '; - $out .= ''; + $out .= ''; $out .= '   '; $out .= '
'; } elseif (!empty($this->param['models']) && in_array($this->param['models'], array( @@ -526,7 +526,7 @@ class FormMail extends Form } - $out .= ''."\n"; + $out .= '
'."\n"; // Substitution array/string $helpforsubstitution = ''; @@ -688,16 +688,20 @@ class FormMail extends Form // With option one email per recipient if (!empty($this->withoptiononeemailperrecipient)) { - $out .= ''; + if (abs($this->withoptiononeemailperrecipient) == 1) { + $out .= ''; + } else { + $out .= ''; + } } // CC @@ -813,8 +817,7 @@ class FormMail extends Form $out .= '
'; } } elseif (empty($this->withmaindocfile)) { - // Do not show message if we asked to show the checkbox - $out .= $langs->trans("NoAttachedFiles").'
'; + $out .= ''.$langs->trans("NoAttachedFiles").'
'; } if ($this->withfile == 2) { // Can add other files @@ -1217,6 +1220,7 @@ class FormMail extends Form global $conf, $langs, $form; $defaulttopic = GETPOST('subject', 'restricthtml'); + if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') { if ($arraydefaultmessage && $arraydefaultmessage->topic) { $defaulttopic = $arraydefaultmessage->topic; diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 81912207f57..6866bfa8356 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -1261,7 +1261,7 @@ class FormTicket // Zone to select its email template if (count($modelmail_array) > 0) { print '
'; - $out .= $langs->trans("GroupEmails"); - $out .= ''; - $out .= ' withoptiononeemailperrecipient > 0 ? ' checked="checked"' : '').'> '; - $out .= ''; - $out .= ''; - $out .= ' - '; - $out .= $langs->trans("WarningIfYouCheckOneRecipientPerEmail"); - $out .= ''; - $out .= '
'; + $out .= $langs->trans("GroupEmails"); + $out .= ''; + $out .= ' withoptiononeemailperrecipient > 0 ? ' checked="checked"' : '').'> '; + $out .= ''; + $out .= ''; + $out .= ' - '; + $out .= $langs->trans("WarningIfYouCheckOneRecipientPerEmail"); + $out .= ''; + $out .= '