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 8c52db8af69..a8211da486a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -138,6 +138,8 @@ NEW: Hidden option API_DISABLE_COMPRESSION is now visible in API setup page. NEW: Add hook printUnderHeaderPDFline on invoice PDF templates (can be used for example to add a barcode or more information on header of invoices). Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: +* ALL EXTERNAL MODULES THAT WERE NOT CORRECTLY DEVELOPPED WILL NOT WORK ON V15 (All modules that forgot to manage the security token field + into forms will be broken. The security token field is expected since Dolibarr v9 but a lot of external modules did not implement it). * Update hook 'printOriginObjectLine', removed check on product type and special code. Need now reshook. * Old deprecated module "SimplePOS" has been completely removed. Use module "TakePOS" is you need a Point Of Sale. * The method static ActionComm::getActions($db, ...) is no more static. Use $actioncomm->getActions(...) instead (without $db param). 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/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/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/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/action/rapport/index.php b/htdocs/comm/action/rapport/index.php index bfef8844ce5..9b3f9a27140 100644 --- a/htdocs/comm/action/rapport/index.php +++ b/htdocs/comm/action/rapport/index.php @@ -163,7 +163,7 @@ if ($resql) { // Button to build doc print ''; - print ''.img_picto($langs->trans('BuildDoc'), 'filenew').''; + print ''.img_picto($langs->trans('BuildDoc'), 'filenew').''; print ''; $name = "actions-".$obj->month."-".$obj->year.".pdf"; 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/card.php b/htdocs/commande/card.php index 88215cc55cf..958ff542fed 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -210,6 +210,8 @@ if (empty($reshook)) { // Remove a product line $result = $object->deleteline($user, $lineid); if ($result > 0) { + // reorder lines + $object->line_order(true); // Define output language $outputlangs = $langs; $newlang = ''; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 3f1deaba057..452d90efc12 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -265,6 +265,8 @@ if (empty($reshook)) { $result = $object->deleteline(GETPOST('lineid', 'int')); if ($result > 0) { + // reorder lines + $object->line_order(true); // Define output language $outputlangs = $langs; $newlang = ''; 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/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index bc3441a6dc2..00cbfc4158a 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1395,14 +1395,14 @@ class Contact extends CommonObject * @param string $moreparam Add more param into URL * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link * @return string String with URL */ - public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $moreparam = '', $save_lastsearch_value = -1, $notooltip = 0) + public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $moreparam = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '') { global $conf, $langs, $hookmanager; $result = ''; $label = ''; - if (!empty($this->photo) && class_exists('Form')) { $label .= '
'; $label .= Form::showphoto('contact', $this, 0, 40, 0, 'photoref', 'mini', 0); // Important, we must force height so image will have height tags and if image is inside a tooltip, the tooltip manager can calculate height and position correctly the tooltip. @@ -1454,7 +1454,7 @@ class Contact extends CommonObject $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; } $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; - $linkclose .= ' class="classfortooltip"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; /* $hookmanager->initHooks(array('contactdao')); @@ -1476,7 +1476,7 @@ class Contact extends CommonObject $result .= $linkstart; if ($withpicto) { if ($withpicto == -2) { - $result .= ''.Form::showphoto('contact', $this, 0, 0, 0, 'userphoto'.($withpicto == -3 ? 'small' : ''), 'mini', 0, 1).''; + $result .= ''.Form::showphoto('contact', $this, 0, 0, 0, 'userphoto'.($withpicto == -3 ? 'small' : ''), 'mini', 0, 1).''; } else { $result .= img_object(($notooltip ? '' : $label), ( $this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); } 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/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/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 184b97a3c98..4c0ec1ff5a5 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1947,8 +1947,8 @@ class ExtraFields if (!empty($onlykey) && $onlykey != '@GETPOSTISSET' && $key != $onlykey) { continue; } - if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && $this->attributes[$object->table_element]['type'][$key] != 'boolean') { - //when unticking boolean field, it's not set in POST + + if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && (! in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'chkbxlst')))) { continue; } 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/link.class.php b/htdocs/core/class/link.class.php index eaf4804b213..f69dcb2874d 100644 --- a/htdocs/core/class/link.class.php +++ b/htdocs/core/class/link.class.php @@ -249,7 +249,7 @@ class Link extends CommonObject $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); - dol_syslog(get_class($this)."::fetchAll ".$num."records", LOG_DEBUG); + dol_syslog(get_class($this)."::fetchAll num=".((int) $num), LOG_DEBUG); if ($num > 0) { while ($obj = $this->db->fetch_object($resql)) { $link = new Link($this->db); diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index e380dea8403..fafd1c015e8 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -56,7 +56,7 @@ if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) { } $search_yaxis = GETPOST('search_yaxis', 'array'); - $search_graph = GETPOST('search_graph', 'none'); + $search_graph = GETPOST('search_graph', 'restricthtml'); // Load variable for pagination $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; diff --git a/htdocs/core/db/DoliDB.class.php b/htdocs/core/db/DoliDB.class.php index daa5f657549..4476228d509 100644 --- a/htdocs/core/db/DoliDB.class.php +++ b/htdocs/core/db/DoliDB.class.php @@ -62,11 +62,26 @@ abstract class DoliDB implements Database /** @var string Last error number. For example: 'DB_ERROR_RECORD_ALREADY_EXISTS', '12345', ... */ public $lasterrno; + /** @var string If we need to set a prefix specific to the database so it can be reused (when defined instead of MAIN_DB_PREFIX) to forge requests */ + public $prefix_db; + /** @var bool Status */ public $ok; /** @var string */ public $error; + + + /** + * Return the DB prefix + * + * @return string The DB prefix + */ + public function prefix() + { + return (empty($this->prefix_db) ? MAIN_DB_PREFIX : $this->prefix_db); + } + /** * Format a SQL IF * diff --git a/htdocs/core/get_menudiv.php b/htdocs/core/get_menudiv.php index 77b0416956b..597031945f1 100644 --- a/htdocs/core/get_menudiv.php +++ b/htdocs/core/get_menudiv.php @@ -121,12 +121,13 @@ print ' display: none; } - a.alilevel0 { + a.alilevel0, span.spanlilevel0 { background-image: url(\''.DOL_URL_ROOT.'/theme/'.urlencode($conf->theme).'/img/next.png\') !important; background-repeat: no-repeat !important; background-position-x: 10px; background-position-y: 16px; padding: 1em 15px 1em 40px; + display: block; } li.lilevel0 font.vsmenudisabled { background-repeat: no-repeat !important; diff --git a/htdocs/core/js/lib_notification.js.php b/htdocs/core/js/lib_notification.js.php index f4a4e59526a..af5952f6026 100644 --- a/htdocs/core/js/lib_notification.js.php +++ b/htdocs/core/js/lib_notification.js.php @@ -64,7 +64,7 @@ print "jQuery(document).ready(function () {\n"; //print " console.log('referrer=".dol_escape_js($_SERVER['HTTP_REFERER'])."');\n"; print ' var nowtime = Date.now();'; -print ' var time_auto_update = '.$conf->global->MAIN_BROWSER_NOTIFICATION_FREQUENCY.';'."\n"; // Always defined +print ' var time_auto_update = '.max(1, getDolGlobalInt('MAIN_BROWSER_NOTIFICATION_FREQUENCY')).';'."\n"; // Always defined print ' var time_js_next_test;'."\n"; ?> diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index e806d9b5957..448677002df 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -240,6 +240,7 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle if (empty($nocommentremoval)) { $buf = preg_replace('/([,;ERLT\)])\s*--.*$/i', '\1', $buf); //remove comment from a line that not start with -- before add it to the buffer } + if ($buffer) $buffer .= ' '; $buffer .= trim($buf); } @@ -639,7 +640,7 @@ function modules_prepare_head($nbofactivatedmodules, $nboftotalmodules) if ($nbofactivatedmodules <= (empty($conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING) ? 1 : $conf->global->MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING)) { // If only minimal initial modules enabled) //$head[$h][1] = $form->textwithpicto($langs->trans("AvailableModules"), $desc); $head[$h][1] = $langs->trans("AvailableModules"); - $head[$h][1] .= $form->textwithpicto('', $langs->trans("YouMustEnableOneModule").'.

'.$desc.'', 1, warning); + $head[$h][1] .= $form->textwithpicto('', $langs->trans("YouMustEnableOneModule").'.

'.$desc.'', 1, 'warning'); } else { //$head[$h][1] = $langs->trans("AvailableModules").$form->textwithpicto(''.$nbofactivatedmodules.' / '.$nboftotalmodules.'', $desc, 1, 'help', '', 1, 3); $head[$h][1] = $langs->trans("AvailableModules").''.$nbofactivatedmodules.' / '.$nboftotalmodules.''; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4713542bf5b..ce8e02e9cee 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -641,7 +641,7 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null } // Check rule - if (preg_match('/^array/', $check)) { // If 'array' or 'array:restricthtml' or 'array:aZ09' + if (preg_match('/^array/', $check)) { // If 'array' or 'array:restricthtml' or 'array:aZ09' or 'array:intcomma' if (!is_array($out) || empty($out)) { $out = array(); } else { @@ -828,7 +828,10 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = // We replace chars from a/A to z/Z encoded with numeric HTML entities with the real char so we won't loose the chars at the next step (preg_replace). // No need to use a loop here, this step is not to sanitize (this is done at next step, this is to try to save chars, even if they are // using a non coventionnel way to be encoded, to not have them sanitized just after) - $out = preg_replace_callback('/&#(x?[0-9][0-9a-f]+;?)/i', 'realCharForNumericEntities', $out); + //$out = preg_replace_callback('/&#(x?[0-9][0-9a-f]+;?)/i', 'realCharForNumericEntities', $out); + $out = preg_replace_callback('/&#(x?[0-9][0-9a-f]+;?)/i', function ($m) { + return realCharForNumericEntities($m); }, $out); + // Now we remove all remaining HTML entities starting with a number. We don't want such entities. $out = preg_replace('/&#x?[0-9]+/i', '', $out); // For example if we have javascript with an entities without the ; to hide the 'a' of 'javascript'. @@ -1894,7 +1897,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi if ($object->element == 'product') { $width = 80; - $cssclass = 'photoref'; + $cssclass = 'photowithmargin photoref'; $showimage = $object->is_photo_available($conf->product->multidir_output[$entity]); $maxvisiblephotos = (isset($conf->global->PRODUCT_MAX_VISIBLE_PHOTO) ? $conf->global->PRODUCT_MAX_VISIBLE_PHOTO : 5); if ($conf->browser->layout == 'phone') { @@ -1996,7 +1999,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi } } } elseif (!$phototoshow) { // example if modulepart = 'societe' or 'photo' - $phototoshow .= $form->showphoto($modulepart, $object, 0, 0, 0, 'photoref', 'small', 1, 0, $maxvisiblephotos); + $phototoshow .= $form->showphoto($modulepart, $object, 0, 0, 0, 'photowithmargin photoref', 'small', 1, 0, $maxvisiblephotos); } if ($phototoshow) { @@ -3640,7 +3643,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ '1downarrow', '1uparrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected', 'accountancy', 'accounting_account', 'account', 'accountline', 'action', 'add', 'address', 'angle-double-down', 'angle-double-up', 'asset', 'bank_account', 'barcode', 'bank', 'bell', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'bug', 'building', - 'calendar', 'calendarmonth', 'calendarweek', 'calendarday', 'calendarperuser', 'calendarpertype', + 'card', 'calendar', 'calendarmonth', 'calendarweek', 'calendarday', 'calendarperuser', 'calendarpertype', 'cash-register', 'category', 'chart', 'check', 'clock', 'close_title', 'cog', 'collab', 'company', 'contact', 'country', 'contract', 'conversation', 'cron', 'cubes', 'multicurrency', 'delete', 'dolly', 'dollyrevert', 'donation', 'download', 'dynamicprice', @@ -3652,9 +3655,10 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'label', 'language', 'link', 'list', 'list-alt', 'listlight', 'loan', 'lot', 'long-arrow-alt-right', 'margin', 'map-marker-alt', 'member', 'meeting', 'money-bill-alt', 'movement', 'mrp', 'note', 'next', 'off', 'on', 'order', - 'paiment', 'paragraph', 'play', 'pdf', 'phone', 'phoning', 'phoning_mobile', 'phoning_fax', 'playdisabled', 'previous', 'poll', 'pos', 'printer', 'product', 'propal', 'stock', 'resize', 'service', 'stats', 'trip', + 'paiment', 'paragraph', 'play', 'pdf', 'phone', 'phoning', 'phoning_mobile', 'phoning_fax', 'playdisabled', 'previous', 'poll', 'pos', 'printer', 'product', 'propal', 'puce', + 'stock', 'resize', 'service', 'stats', 'trip', 'security', 'setup', 'share-alt', 'sign-out', 'split', 'stripe', 'stripe-s', 'switch_off', 'switch_on', 'switch_on_red', 'tools', 'unlink', 'uparrow', 'user', 'vcard', 'wrench', - 'github', 'jabber', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'youtube', 'google-plus-g', 'whatsapp', + 'github', 'google', 'jabber', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'youtube', 'google-plus-g', 'whatsapp', 'chevron-left', 'chevron-right', 'chevron-down', 'chevron-top', 'commercial', 'companies', 'generic', 'home', 'hrm', 'members', 'products', 'invoicing', 'partnership', 'payment', 'payment_vat', 'pencil-ruler', 'preview', 'project', 'projectpub', 'projecttask', 'question', 'refresh', 'region', @@ -3671,10 +3675,10 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ $facolor = ''; $fasize = ''; $fa = 'fas'; - if (in_array($pictowithouttext, array('bell', 'clock', 'establishment', 'generic', 'minus-square', 'object_generic', 'pdf', 'plus-square', 'timespent', 'note', 'off', 'on', 'object_bookmark', 'bookmark', 'vcard'))) { + if (in_array($pictowithouttext, array('card', 'bell', 'clock', 'establishment', 'generic', 'minus-square', 'object_generic', 'pdf', 'plus-square', 'timespent', 'note', 'off', 'on', 'object_bookmark', 'bookmark', 'vcard'))) { $fa = 'far'; } - if (in_array($pictowithouttext, array('black-tie', 'github', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'stripe', 'stripe-s', 'youtube', 'google-plus-g', 'whatsapp'))) { + if (in_array($pictowithouttext, array('black-tie', 'github', 'google', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'stripe', 'stripe-s', 'youtube', 'google-plus-g', 'whatsapp'))) { $fa = 'fab'; } @@ -3684,7 +3688,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'bill'=>'file-invoice-dollar', 'billa'=>'file-excel', 'billr'=>'file-invoice-dollar', 'billd'=>'file-medical', 'supplier_invoice'=>'file-invoice-dollar', 'supplier_invoicea'=>'file-excel', 'supplier_invoicer'=>'file-invoice-dollar', 'supplier_invoiced'=>'file-medical', 'bom'=>'shapes', - 'chart'=>'chart-line', 'company'=>'building', 'contact'=>'address-book', 'contract'=>'suitcase', 'collab'=>'people-arrows', 'conversation'=>'comments', 'country'=>'globe-americas', 'cron'=>'business-time', + 'card'=>'address-card', 'chart'=>'chart-line', 'company'=>'building', 'contact'=>'address-book', 'contract'=>'suitcase', 'collab'=>'people-arrows', 'conversation'=>'comments', 'country'=>'globe-americas', 'cron'=>'business-time', 'donation'=>'file-alt', 'dynamicprice'=>'hand-holding-usd', 'setup'=>'cog', 'companies'=>'building', 'products'=>'cube', 'commercial'=>'suitcase', 'invoicing'=>'coins', 'accounting'=>'search-dollar', 'category'=>'tag', 'dollyrevert'=>'dolly', @@ -3704,10 +3708,11 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'error'=>'exclamation-triangle', 'warning'=>'exclamation-triangle', 'other'=>'square', 'playdisabled'=>'play', 'pdf'=>'file-pdf', 'poll'=>'check-double', 'pos'=>'cash-register', 'preview'=>'binoculars', 'project'=>'project-diagram', 'projectpub'=>'project-diagram', 'projecttask'=>'tasks', 'propal'=>'file-signature', - 'partnership'=>'handshake', 'payment'=>'money-check-alt', 'payment_vat'=>'money-check-alt', 'phoning'=>'phone', 'phoning_mobile'=>'mobile-alt', 'phoning_fax'=>'fax', 'previous'=>'arrow-alt-circle-left', 'printer'=>'print', 'product'=>'cube', 'service'=>'concierge-bell', + 'partnership'=>'handshake', 'payment'=>'money-check-alt', 'payment_vat'=>'money-check-alt', 'phoning'=>'phone', 'phoning_mobile'=>'mobile-alt', 'phoning_fax'=>'fax', 'previous'=>'arrow-alt-circle-left', 'printer'=>'print', 'product'=>'cube', 'puce'=>'angle-right', 'recent' => 'question', 'reception'=>'dolly', 'recruitmentjobposition'=>'id-card-alt', 'recruitmentcandidature'=>'id-badge', 'resize'=>'crop', 'supplier_order'=>'dol-order_supplier', 'supplier_proposal'=>'file-signature', 'refresh'=>'redo', 'region'=>'map-marked', 'resource'=>'laptop-house', 'recurring'=>'history', + 'service'=>'concierge-bell', 'state'=>'map-marked-alt', 'security'=>'key', 'salary'=>'wallet', 'shipment'=>'dolly', 'stock'=>'box-open', 'stats' => 'chart-bar', 'split'=>'code-branch', 'stripe'=>'stripe-s', 'supplier'=>'building', 'technic'=>'cogs', 'timespent'=>'clock', 'title_setup'=>'tools', 'title_accountancy'=>'money-check-alt', 'title_bank'=>'university', 'title_hrm'=>'umbrella-beach', diff --git a/htdocs/core/lib/geturl.lib.php b/htdocs/core/lib/geturl.lib.php index be7e1ffa80b..50ae7c33561 100644 --- a/htdocs/core/lib/geturl.lib.php +++ b/htdocs/core/lib/geturl.lib.php @@ -214,11 +214,14 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation = } } - // Common check (local and external) - if (in_array($iptocheck, array('100.100.100.200'))) { - $info['http_code'] = 400; - $info['content'] = 'Error bad hostname IP (Used by Alibaba metadata). Must be an external URL.'; - break; + // Common check on ip (local and external) + $arrayofmetadataserver = array('100.100.100.200' => 'Alibaba', '192.0.0.192'=> 'Oracle', '192.80.8.124'=>'Packet'); + foreach ($arrayofmetadataserver as $ipofmetadataserver => $nameofmetadataserver) { + if ($iptocheck == $ipofmetadataserver) { + $info['http_code'] = 400; + $info['content'] = 'Error bad hostname IP (Used by '.$nameofmetadataserver.' metadata server). This IP is forbidden.'; + break 2; // exit the foreach and the do... + } } // Set CURLOPT_CONNECT_TO so curl will not try another resolution that may give a different result. Possible only on PHP v7+ diff --git a/htdocs/core/lib/oauth.lib.php b/htdocs/core/lib/oauth.lib.php index 48356868143..ab1b5a217b8 100644 --- a/htdocs/core/lib/oauth.lib.php +++ b/htdocs/core/lib/oauth.lib.php @@ -25,13 +25,13 @@ // Supported OAUTH (a provider is supported when a file xxx_oauthcallback.php is available into htdocs/core/modules/oauth) $supportedoauth2array = array( - 'OAUTH_GOOGLE_NAME'=>'google', + 'OAUTH_GOOGLE_NAME'=>array('callbackfile' => 'google', 'picto' => 'google', 'urlforapp' => 'OAUTH_GOOGLE_DESC', 'name'=>'Google'), ); -if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { - $supportedoauth2array['OAUTH_STRIPE_TEST_NAME'] = 'stripetest'; - $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = 'stripelive'; +if (!empty($conf->stripe->enabled)) { + $supportedoauth2array['OAUTH_STRIPE_TEST_NAME'] = array('callbackfile' => 'stripetest', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeTest'); + $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = array('callbackfile' => 'stripelive', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeLive'); } -$supportedoauth2array['OAUTH_GITHUB_NAME'] = 'github'; +$supportedoauth2array['OAUTH_GITHUB_NAME'] = array('callbackfile' => 'github', 'picto' => 'github', 'urlforapp' => 'OAUTH_GITHUB_DESC', 'name'=>'GitHub'); diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index e9e06708f7c..7f5daf77c4a 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -679,22 +679,23 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t // Title of task if (count($arrayfields) > 0 && !empty($arrayfields['t.label']['checked'])) { - print ''; + $labeltoshow = ''; if ($showlineingray) { - print ''; + $labeltoshow .= ''; } //else print ''; for ($k = 0; $k < $level; $k++) { - print '
'; + $labeltoshow .= '
'; } - print $lines[$i]->label; + $labeltoshow .= dol_escape_htmltag($lines[$i]->label); for ($k = 0; $k < $level; $k++) { - print '
'; + $labeltoshow .= '
'; } if ($showlineingray) { - print '
'; + $labeltoshow .= '
'; } - //else print ''; + print ''; + print $labeltoshow; print "\n"; } @@ -822,29 +823,7 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t } } - // Contacts of tasks. Disabled, because available by default just after - /* - if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) { - print ''; - foreach (array('internal', 'external') as $source) { - $tab = $lines[$i]->liste_contact(-1, $source); - $num = count($tab); - if (!empty($num)) { - foreach ($tab as $contacttask) { - //var_dump($contacttask); - if ($source == 'internal') { - $c = new User($db); - } else { - $c = new Contact($db); - } - $c->fetch($contacttask['id']); - print $c->getNomUrl(1).' ('.$contacttask['libelle'].')
'; - } - } - } - print ''; - }*/ - if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) { + if (count($arrayfields) > 0 && !empty($arrayfields['c.budget_amount']['checked'])) { print ''; print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency); $total_budget_amount += $lines[$i]->budget_amount; @@ -854,10 +833,11 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t // Contacts of task if (count($arrayfields) > 0 && !empty($arrayfields['c.assigned']['checked'])) { print ''; + $ifisrt = 1; foreach (array('internal', 'external') as $source) { $tab = $lines[$i]->liste_contact(-1, $source); - $num = count($tab); - if (!empty($num)) { + $numcontact = count($tab); + if (!empty($numcontact)) { foreach ($tab as $contacttask) { //var_dump($contacttask); if ($source == 'internal') { @@ -867,14 +847,19 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t } $c->fetch($contacttask['id']); if (!empty($c->photo)) { - print $c->getNomUrl(-2).' '; + if (get_class($c) == 'User') { + print $c->getNomUrl(-2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst')); + } else { + print $c->getNomUrl(-2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst')); + } } else { if (get_class($c) == 'User') { - print $c->getNomUrl(2, '', 0, 0, 24, 1);//.' '; + print $c->getNomUrl(2, '', 0, 0, 24, 1, '', ($ifisrt ? '' : 'notfirst')); } else { - print $c->getNomUrl(2);//.' '; + print $c->getNomUrl(2, '', 0, '', -1, 0, ($ifisrt ? '' : 'notfirst')); } } + $ifisrt = 0; } } } diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php index f102cd2f358..292ce1b44f5 100644 --- a/htdocs/core/login/functions_dolibarr.php +++ b/htdocs/core/login/functions_dolibarr.php @@ -2,6 +2,7 @@ /* Copyright (C) 2007-2015 Laurent Destailleur * Copyright (C) 2007-2015 Regis Houssin * Copyright (C) 2010-2011 Juanjo Menent + * Copyright (C) 2022 Harry Winner Kamdem * * 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 @@ -104,7 +105,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes } // Check crypted password according to crypt algorithm if ($cryptType == 'auto') { - if (dol_verifyHash($passtyped, $passcrypted, '0')) { + if ($passcrypted && dol_verifyHash($passtyped, $passcrypted, '0')) { $passok = true; dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ok - hash ".$cryptType." of pass is ok"); } diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 58d39fe8aa4..625022e6bbf 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1817,7 +1817,7 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM $newmenu->add("/hrm/evaluation_list.php?mainmenu=hrm&leftmenu=hrm_sm", $langs->trans("Evalutions"), 1, $user->rights->hrm->evaluation->read, '', $mainmenu, 'hrm_sm', 0, '', '', '', img_picto('', 'user', 'class="pictofixedwidth"')); //$newmenu->add("/hrm/evaluation_card.php?mainmenu=hrm&leftmenu=hrm_sm&action=create", $langs->trans("NewEval"), 1, $user->rights->hrm->evaluation->write); //$newmenu->add("/hrm/evaluation_list.php?mainmenu=hrm&leftmenu=hrm_sm", $langs->trans("List"), 1, $user->rights->hrm->evaluation->read); - $newmenu->add("/hrm/compare.php?mainmenu=hrm&leftmenu=hrm_sm", $langs->trans("SkillComparison"), 1, $user->rights->hrm->evaluation->read || $user->rights->hrm->compare->read); + $newmenu->add("/hrm/compare.php?mainmenu=hrm&leftmenu=hrm_sm", $langs->trans("SkillComparison"), 1, $user->rights->hrm->evaluation->read || $user->rights->hrm->compare_advance->read); } } diff --git a/htdocs/core/menus/standard/eldy_menu.php b/htdocs/core/menus/standard/eldy_menu.php index 35186e423ef..5b426199a6e 100644 --- a/htdocs/core/menus/standard/eldy_menu.php +++ b/htdocs/core/menus/standard/eldy_menu.php @@ -317,7 +317,7 @@ class MenuManager print ''; } if ($val['enabled'] == 2) { - print ''; + print ''; // Add font-awesome if ($val['level'] == 0 && !empty($val['prefix'])) { print $val['prefix']; diff --git a/htdocs/core/modules/modCommande.class.php b/htdocs/core/modules/modCommande.class.php index cc6f8baab80..d8ba1f98146 100644 --- a/htdocs/core/modules/modCommande.class.php +++ b/htdocs/core/modules/modCommande.class.php @@ -210,6 +210,13 @@ class modCommande extends DolibarrModules $this->export_fields_array[$r]['c.multicurrency_total_tva'] = 'MulticurrencyAmountVAT'; $this->export_fields_array[$r]['c.multicurrency_total_ttc'] = 'MulticurrencyAmountTTC'; } + // Add multicompany field + if (!empty($conf->global->MULTICOMPANY_ENTITY_IN_EXPORT_IF_SHARED)) { + $nbofallowedentities = count(explode(',', getEntity('commande'))); + if (!empty($conf->multicompany->enabled) && $nbofallowedentities > 1) { + $this->export_fields_array[$r]['c.entity'] = 'Entity'; + } + } //$this->export_TypeFields_array[$r]=array( // 's.rowid'=>"List:societe:nom",'s.nom'=>'Text','s.address'=>'Text','s.zip'=>'Text','s.town'=>'Text','co.label'=>'List:c_country:label:label', // 'co.code'=>'Text','s.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','c.ref'=>"Text",'c.ref_client'=>"Text", @@ -224,7 +231,8 @@ class modCommande extends DolibarrModules 'c.date_commande'=>"Date", 'c.date_livraison'=>"Date", 'c.amount_ht'=>"Numeric", 'c.remise_percent'=>"Numeric", 'c.total_ht'=>"Numeric", 'c.total_ttc'=>"Numeric", 'c.facture'=>"Boolean", 'c.fk_statut'=>'Status', 'c.note_public'=>"Text", 'c.date_livraison'=>'Date', 'pj.ref'=>'Text', 'cd.description'=>"Text", 'cd.product_type'=>'Boolean', 'cd.tva_tx'=>"Numeric", 'cd.qty'=>"Numeric", 'cd.total_ht'=>"Numeric", 'cd.total_tva'=>"Numeric", - 'cd.total_ttc'=>"Numeric", 'p.rowid'=>'List:product:ref::product', 'p.ref'=>'Text', 'p.label'=>'Text', 'd.nom'=>'Text' + 'cd.total_ttc'=>"Numeric", 'p.rowid'=>'List:product:ref::product', 'p.ref'=>'Text', 'p.label'=>'Text', 'd.nom'=>'Text', + 'c.entity'=>'List:entity:label:rowid', ); $this->export_entities_array[$r] = array( 's.rowid'=>"company", 's.nom'=>'company', 'ps.nom'=>'company', 's.address'=>'company', 's.zip'=>'company', 's.town'=>'company', 'd.nom'=>'company', 'co.label'=>'company', diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index ef341c83e89..fac768b9c60 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -270,6 +270,13 @@ class modFacture extends DolibarrModules $this->export_fields_array[$r]['f.module_source'] = 'Module'; $this->export_fields_array[$r]['f.pos_source'] = 'POSTerminal'; } + // Add multicompany field + if (!empty($conf->global->MULTICOMPANY_ENTITY_IN_EXPORT_IF_SHARED)) { + $nbofallowedentities = count(explode(',', getEntity('invoice'))); + if (!empty($conf->multicompany->enabled) && $nbofallowedentities > 1) { + $this->export_fields_array[$r]['f.entity'] = 'Entity'; + } + } $this->export_TypeFields_array[$r] = array( 's.rowid'=>'Numeric', 's.nom'=>'Text', 'ps.nom'=>'Text', 's.code_client'=>'Text', 's.address'=>'Text', 's.zip'=>'Text', 's.town'=>'Text', 'c.code'=>'Text', 'cd.nom'=>'Text', 's.phone'=>'Text', 's.siren'=>'Text', 's.siret'=>'Text', 's.ape'=>'Text', 's.idprof4'=>'Text', 's.code_compta'=>'Text', 's.code_compta_fournisseur'=>'Text', 's.tva_intra'=>'Text', @@ -280,7 +287,8 @@ class modFacture extends DolibarrModules 'pj.ref'=>'Text', 'pj.title'=>'Text', 'fd.rowid'=>'Numeric', 'fd.label'=>'Text', 'fd.description'=>"Text", 'fd.subprice'=>"Numeric", 'fd.tva_tx'=>"Numeric", 'fd.qty'=>"Numeric", 'fd.total_ht'=>"Numeric", 'fd.total_tva'=>"Numeric", 'fd.total_ttc'=>"Numeric", 'fd.date_start'=>"Date", 'fd.date_end'=>"Date", 'fd.special_code'=>'Numeric', 'fd.product_type'=>"Numeric", 'fd.fk_product'=>'List:product:label', 'p.ref'=>'Text', 'p.label'=>'Text', - $alias_product_perentity . '.accountancy_code_sell'=>'Text' + $alias_product_perentity . '.accountancy_code_sell'=>'Text', + 'f.entity'=>'List:entity:label:rowid', ); if (!empty($conf->cashdesk->enabled) || !empty($conf->takepos->enabled) || !empty($conf->global->INVOICE_SHOW_POS)) { $this->export_TypeFields_array[$r]['f.module_source'] = 'Text'; diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index 63c76e24548..53f69dfefaf 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -199,7 +199,7 @@ class modHoliday extends DolibarrModules $this->rights[$r][0] = 20005; // Permission id (must not be already used) $this->rights[$r][1] = 'Create/modify leave requests for everybody'; // Permission label $this->rights[$r][3] = 0; // Permission by default for new user (0/1) - $this->rights[$r][4] = 'writeall_advance'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) + $this->rights[$r][4] = 'writeall'; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->permkey->level1->level2) $r++; diff --git a/htdocs/core/modules/modPrinting.class.php b/htdocs/core/modules/modPrinting.class.php index 4c104b30ecf..c9e99b3d933 100644 --- a/htdocs/core/modules/modPrinting.class.php +++ b/htdocs/core/modules/modPrinting.class.php @@ -34,7 +34,6 @@ include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; */ class modPrinting extends DolibarrModules { - /** * Constructor * diff --git a/htdocs/core/modules/modPropale.class.php b/htdocs/core/modules/modPropale.class.php index 53647db5dae..4f0633cd578 100644 --- a/htdocs/core/modules/modPropale.class.php +++ b/htdocs/core/modules/modPropale.class.php @@ -204,6 +204,13 @@ class modPropale extends DolibarrModules $this->export_fields_array[$r]['c.multicurrency_total_tva'] = 'MulticurrencyAmountVAT'; $this->export_fields_array[$r]['c.multicurrency_total_ttc'] = 'MulticurrencyAmountTTC'; } + // Add multicompany field + if (!empty($conf->global->MULTICOMPANY_ENTITY_IN_EXPORT_IF_SHARED)) { + $nbofallowedentities = count(explode(',', getEntity('propal'))); + if (!empty($conf->multicompany->enabled) && $nbofallowedentities > 1) { + $this->export_fields_array[$r]['c.entity'] = 'Entity'; + } + } //$this->export_TypeFields_array[$r]=array( // 's.rowid'=>"List:societe:nom",'s.nom'=>'Text','s.address'=>'Text','s.zip'=>'Text','s.town'=>'Text','co.code'=>'Text','s.phone'=>'Text', // 's.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','c.ref'=>"Text",'c.ref_client'=>"Text",'c.datec'=>"Date",'c.datep'=>"Date", @@ -216,7 +223,8 @@ class modPropale extends DolibarrModules 's.ape'=>'Text', 's.idprof4'=>'Text', 'c.ref'=>"Text", 'c.ref_client'=>"Text", 'c.datec'=>"Date", 'c.datep'=>"Date", 'c.fin_validite'=>"Date", 'c.remise_percent'=>"Numeric", 'c.total_ht'=>"Numeric", 'c.total_ttc'=>"Numeric", 'c.fk_statut'=>'Status', 'c.note_public'=>"Text", 'c.date_livraison'=>'Date', 'pj.ref'=>'Text', 'cd.description'=>"Text", 'cd.product_type'=>'Boolean', 'cd.tva_tx'=>"Numeric", 'cd.qty'=>"Numeric", 'cd.total_ht'=>"Numeric", - 'cd.total_tva'=>"Numeric", 'cd.total_ttc'=>"Numeric", 'p.ref'=>'Text', 'p.label'=>'Text' + 'cd.total_tva'=>"Numeric", 'cd.total_ttc'=>"Numeric", 'p.ref'=>'Text', 'p.label'=>'Text', + 'c.entity'=>'List:entity:label:rowid', ); $this->export_entities_array[$r] = array( 's.rowid'=>"company", 's.nom'=>'company', 'ps.nom'=>'company', 's.address'=>'company', 's.zip'=>'company', 's.town'=>'company', 'co.code'=>'company', 's.phone'=>'company', diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index e70011a2195..a733484d043 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -327,7 +327,7 @@ class modSociete extends DolibarrModules 'payterm.libelle'=>'Text', 'paymode.libelle'=>'Text', 's.outstanding_limit'=>'Numeric', 'pbacc.ref'=>'Text', 'incoterm.code'=>'Text', 'u.login'=>'Text', 'u.firstname'=>'Text', 'u.lastname'=>'Text', - 's.entity'=>'Numeric', 's.price_level'=>'Numeric', + 's.entity'=>'List:entity:label:rowid', 's.price_level'=>'Numeric', 's.accountancy_code_sell'=>'Text', 's.accountancy_code_buy'=>'Text' ); @@ -376,6 +376,20 @@ class modSociete extends DolibarrModules 's.address'=>'Address', 's.zip'=>"Zip", 's.town'=>"Town", 's.phone'=>'Phone', 's.email'=>"Email", 't.libelle'=>"ThirdPartyType" ); + // Add multicompany field + if (! empty($conf->global->MULTICOMPANY_ENTITY_IN_EXPORT_IF_SHARED)) { + if (!empty($conf->multicompany->enabled)) { + $nbofallowedentities = count(explode(',', getEntity('socpeople'))); + if ($nbofallowedentities > 1) { + $this->export_fields_array[$r]['c.entity'] = 'Entity'; + } + + $nbofallowedentities = count(explode(',', getEntity('societe'))); + if ($nbofallowedentities > 1) { + $this->export_fields_array[$r]['s.entity'] = 'Entity'; + } + } + } $this->export_examplevalues_array[$r] = array('s.client'=>'0 (no customer no prospect)/1 (customer)/2 (prospect)/3 (customer and prospect)', 's.fournisseur'=>'0 (not a supplier) or 1 (supplier)'); $this->export_TypeFields_array[$r] = array( 'c.civility'=>"List:c_civility:label:code", 'c.lastname'=>'Text', 'c.firstname'=>'Text', 'c.poste'=>'Text', 'c.datec'=>"Date", 'c.priv'=>"Boolean", @@ -386,14 +400,17 @@ class modSociete extends DolibarrModules 's.code_compta'=>"Text", 's.code_compta_fournisseur'=>"Text", 's.client'=>"Text", 's.fournisseur'=>"Text", 's.address'=>"Text", 's.zip'=>"Text", 's.town'=>"Text", 's.phone'=>"Text", 's.email'=>"Text", - 't.libelle'=>"Text" + 't.libelle'=>"Text", + 'c.entity'=>'List:entity:label:rowid', + 's.entity'=>'List:entity:label:rowid', ); $this->export_entities_array[$r] = array( 's.rowid'=>"company", 's.nom'=>"company", 's.status'=>'company', 's.code_client'=>"company", 's.code_fournisseur'=>"company", 's.code_compta'=>"company", 's.code_compta_fournisseur'=>"company", 's.client'=>"company", 's.fournisseur'=>"company", 's.address'=>"company", 's.zip'=>"company", 's.town'=>"company", 's.phone'=>"company", 's.email'=>"company", - 't.libelle'=>"company" + 't.libelle'=>"company", + 's.entity'=>'company', ); // We define here only fields that use another picto if (empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { unset($this->export_fields_array[$r]['s.code_fournisseur']); diff --git a/htdocs/core/modules/oauth/google_oauthcallback.php b/htdocs/core/modules/oauth/google_oauthcallback.php index 4f9fded878f..9fbc38ef156 100644 --- a/htdocs/core/modules/oauth/google_oauthcallback.php +++ b/htdocs/core/modules/oauth/google_oauthcallback.php @@ -16,6 +16,9 @@ * along with this program. If not, see . */ +// This page should make the process to login and get token as described here: +// https://developers.google.com/identity/protocols/oauth2/openid-connect#server-flow + /** * \file htdocs/core/modules/oauth/google_oauthcallback.php * \ingroup oauth @@ -70,9 +73,13 @@ $credentials = new Credentials( $currentUri->getAbsoluteUri() ); +$state = GETPOST('state'); + $requestedpermissionsarray = array(); -if (GETPOST('state')) { - $requestedpermissionsarray = explode(',', GETPOST('state')); // Example: 'userinfo_email,userinfo_profile,cloud_print'. 'state' parameter is standard to store a hash value and can be used to retrieve some parameters back +if ($state) { + // 'state' parameter is standard to store a hash value and can be used to retrieve some parameters back + $statewithscopeonly = preg_replace('/\-.*$/', '', $state); + $requestedpermissionsarray = explode(',', $statewithscopeonly); // Example: 'userinfo_email,userinfo_profile,openid,email,profile,cloud_print'. } if ($action != 'delete' && empty($requestedpermissionsarray)) { print 'Error, parameter state is not defined'; @@ -80,6 +87,8 @@ if ($action != 'delete' && empty($requestedpermissionsarray)) { } //var_dump($requestedpermissionsarray);exit; + + // Instantiate the Api service using the credentials, http client and storage mechanism for the token // $requestedpermissionsarray contains list of scopes. // Conversion into URL is done by Reflection on constant with name SCOPE_scope_in_uppercase @@ -89,7 +98,6 @@ $apiService = $serviceFactory->createService('Google', $credentials, $storage, $ // also note that a refresh token is sent only after a prompt $apiService->setAccessType('offline'); -$apiService->setApprouvalPrompt('force'); $langs->load("oauth"); @@ -108,48 +116,86 @@ if ($action == 'delete') { exit(); } -if (!empty($_GET['code'])) { // We are coming from oauth provider page +if (GETPOST('code')) { // We are coming from oauth provider page. dol_syslog("We are coming from the oauth provider page"); - //llxHeader('',$langs->trans("OAuthSetup")); - //$linkback=''.$langs->trans("BackToModuleList").''; - //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup'); + // We must validate that the $state is the same than the one into $_SESSION['oauthstateanticsrf'], return error if not. + if (isset($_SESSION['oauthstateanticsrf']) && $state != $_SESSION['oauthstateanticsrf']) { + print 'Value for state = '.dol_escape_htmltag($state).' differs from value in $_SESSION["oauthstateanticsrf"]. Code is refused.'; + unset($_SESSION['oauthstateanticsrf']); + } else { + // This was a callback request from service, get the token + try { + //var_dump($_GET['code']); + //var_dump($state); + //var_dump($apiService); // OAuth\OAuth2\Service\Google - //print dol_get_fiche_head(); - // retrieve the CSRF state parameter - $state = isset($_GET['state']) ? $_GET['state'] : null; - //print ''; + // This request the token + // Result is stored into object managed by class DoliStorage into includes/OAuth/Common/Storage/DoliStorage.php, so into table llx_oauth_token + $token = $apiService->requestAccessToken(GETPOST('code'), $state); - // This was a callback request from service, get the token - try { - //var_dump($_GET['code']); - //var_dump($state); - //var_dump($apiService); // OAuth\OAuth2\Service\Google + // Note: The extraparams has the 'id_token' than contains a lot of information about the user. + $extraparams = $token->getExtraParams(); + $jwt = explode('.', $extraparams['id_token']); - $token = $apiService->requestAccessToken($_GET['code'], $state); + // Extract the middle part, base64 decode, then json_decode it + if (!empty($jwt[1])) { + $userinfo = json_decode(base64_decode($jwt[1]), true); - setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token + // TODO + // We should make the 5 steps of validation of id_token + // Verify that the ID token is properly signed by the issuer. Google-issued tokens are signed using one of the certificates found at the URI specified in the jwks_uri metadata value of the Discovery document. + // Verify that the value of the iss claim in the ID token is equal to https://accounts.google.com or accounts.google.com. + // Verify that the value of the aud claim in the ID token is equal to your app's client ID. + // Verify that the expiry time (exp claim) of the ID token has not passed. + // If you specified a hd parameter value in the request, verify that the ID token has a hd claim that matches an accepted G Suite hosted domain. - $backtourl = $_SESSION["backtourlsavedbeforeoauthjump"]; - unset($_SESSION["backtourlsavedbeforeoauthjump"]); + /* + $useremailuniq = $userinfo['sub']; + $useremail = $userinfo['email']; + $useremailverified = $userinfo['email_verified']; + $username = $userinfo['name']; + $userfamilyname = $userinfo['family_name']; + $usergivenname = $userinfo['given_name']; + $hd = $userinfo['hd']; + */ + } - header('Location: '.$backtourl); - exit(); - } catch (Exception $e) { - print $e->getMessage(); + setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); + + $backtourl = $_SESSION["backtourlsavedbeforeoauthjump"]; + unset($_SESSION["backtourlsavedbeforeoauthjump"]); + + header('Location: '.$backtourl); + exit(); + } catch (Exception $e) { + print $e->getMessage(); + } } -} else // If entry on page with no parameter, we arrive here -{ +} else { + // If we enter this page without 'code' parameter, we arrive here. this is the case when we want to get the redirect + // to the OAuth provider login page $_SESSION["backtourlsavedbeforeoauthjump"] = $backtourl; + if (!preg_match('/^forlogin/', $state)) { + $apiService->setApprouvalPrompt('force'); + } + // This may create record into oauth_state before the header redirect. // Creation of record with state in this tables depend on the Provider used (see its constructor). - if (GETPOST('state')) { - $url = $apiService->getAuthorizationUri(array('state'=>GETPOST('state'))); + if ($state) { + $url = $apiService->getAuthorizationUri(array('state' => $state)); } else { $url = $apiService->getAuthorizationUri(); // Parameter state will be randomly generated } + // Add more param + $url .= '&nonce='.bin2hex(random_bytes(64/8)); + // TODO Add param hd and/or login_hint + if (!preg_match('/^forlogin/', $state)) { + //$url .= 'hd=xxx'; + } + // we go on oauth provider authorization page header('Location: '.$url); exit(); @@ -160,6 +206,6 @@ if (!empty($_GET['code'])) { // We are coming from oauth provider page * View */ -// No view at all, just actions +// No view at all, just actions, so we never reach this line. $db->close(); diff --git a/htdocs/core/modules/stock/doc/pdf_standard.modules.php b/htdocs/core/modules/stock/doc/pdf_standard.modules.php index 1597ee32c18..f66e7e6e5d1 100644 --- a/htdocs/core/modules/stock/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/stock/doc/pdf_standard.modules.php @@ -179,6 +179,8 @@ class pdf_standard extends ModelePDFStock $this->localtax2 = array(); $this->atleastoneratenotnull = 0; $this->atleastonediscount = 0; + + $this->tabTitleHeight = 11; } @@ -321,7 +323,6 @@ class pdf_standard extends ModelePDFStock $i = 0; $nblines = $num; - $this->tabTitleHeight = 10; $nexY = $tab_top + $this->tabTitleHeight; for ($i = 0; $i < $nblines; $i++) { @@ -733,7 +734,7 @@ class pdf_standard extends ModelePDFStock if (empty($hidetop)) { $pdf->SetDrawColor(200, 200, 200); $pdf->SetLineStyle(array('dash' => '0', 'color' => array(200, 200, 200))); - $pdf->line($this->marge_gauche, $tab_top + 10, $this->page_largeur - $this->marge_droite, $tab_top + 10); + $pdf->line($this->marge_gauche, $tab_top + $this->tabTitleHeight, $this->page_largeur - $this->marge_droite, $tab_top + $this->tabTitleHeight); $pdf->SetLineStyle(array('dash' => 0)); } } @@ -767,8 +768,8 @@ class pdf_standard extends ModelePDFStock pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); // Show Draft Watermark - if ($object->statut == 0 && (!empty($conf->global->COMMANDE_DRAFT_WATERMARK))) { - pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->COMMANDE_DRAFT_WATERMARK); + if ($object->statut == 0 && (!empty($conf->global->STOCK_DRAFT_WATERMARK))) { + pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->STOCK_DRAFT_WATERMARK); } $pdf->SetTextColor(0, 0, 60); @@ -780,6 +781,7 @@ class pdf_standard extends ModelePDFStock $pdf->SetXY($this->marge_gauche, $posy); // Logo + $height = 0; $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo; if ($this->emetteur->logo) { if (is_readable($logo)) { @@ -796,29 +798,19 @@ class pdf_standard extends ModelePDFStock $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); } + $yafterleft = $pdf->GetY() + $height; + $pdf->SetFont('', 'B', $default_font_size + 3); $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $title = $outputlangs->transnoentities("Warehouse"); - $pdf->MultiCell(100, 3, $title, '', 'R'); - $pdf->SetFont('', 'B', $default_font_size); + $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Warehouse").' '.$outputlangs->convToOutputCharset($object->label), '', 'R'); - $posy += 5; - $pdf->SetXY($posx, $posy); - $pdf->SetTextColor(0, 0, 60); - - $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->label), '', 'R'); - - $posy += 5; + $posy += 6; $pdf->SetFont('', '', $default_font_size - 1); $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("LocationSummary").' :', '', 'R'); - - $posy += 4; - $pdf->SetXY($posx - 50, $posy); - $pdf->MultiCell(150, 3, $object->lieu, '', 'R'); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Label").' : '.$object->lieu, '', 'R'); $posy += 4; $pdf->SetXY($posx, $posy); @@ -836,8 +828,10 @@ class pdf_standard extends ModelePDFStock $pdf->MultiCell(150, 3, $e->label, '', 'R'); } + $yafterright = $pdf->GetY(); + // Description - $nexY = $pdf->GetY(); + $nexY = max($yafterleft, $yafterright); $nexY += 5; $pdf->SetXY($posx, $posy); $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("Description").' : '.nl2br($object->description), 0, 1); @@ -859,6 +853,9 @@ class pdf_standard extends ModelePDFStock $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("EstimatedStockValueShort").' : '.price((empty($calcproducts['value']) ? '0' : price2num($calcproducts['value'], 'MT')), 0, $langs, 0, -1, -1, $conf->currency), 0, 1); $nexY = $pdf->GetY(); + // Value + $pdf->writeHTMLCell(190, 2, $this->marge_gauche, $nexY, ''.$outputlangs->transnoentities("Date").' : '.dol_print_date(dol_now(), 'dayhour'), 0, 1); + $nexY = $pdf->GetY(); // Last movement $sql = "SELECT max(m.datem) as datem"; diff --git a/htdocs/core/tpl/admin_extrafields_add.tpl.php b/htdocs/core/tpl/admin_extrafields_add.tpl.php index d9c0f650395..9b46fba6c67 100644 --- a/htdocs/core/tpl/admin_extrafields_add.tpl.php +++ b/htdocs/core/tpl/admin_extrafields_add.tpl.php @@ -185,7 +185,7 @@ $listofexamplesforlink = 'Societe:societe/class/societe.class.php
Contact:con - + diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index 338d2bd1a19..d7e9bda13dd 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -33,6 +33,8 @@ if (empty($conf) || !is_object($conf)) { require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + header('Cache-Control: Public, must-revalidate'); header("Content-type: text/html; charset=".$conf->file->character_set_client); @@ -316,6 +318,32 @@ if (isset($conf->file->main_authentication) && preg_match('/openid/', $conf->fil echo ''; } +if (isset($conf->file->main_authentication) && preg_match('/google/', $conf->file->main_authentication)) { + $langs->load("users"); + + global $dolibarr_main_url_root; + + // Define $urlwithroot + $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); + $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file + //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + + echo '
'; + echo '
'; + + //$shortscope = 'userinfo_email,userinfo_profile'; + $shortscope = 'openid,email,profile'; // For openid connect + + $oauthstateanticsrf = bin2hex(random_bytes(128/8)); + $_SESSION['oauthstateanticsrf'] = $shortscope.'-'.$oauthstateanticsrf; + $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state=forlogin-'.$shortscope.'-'.$oauthstateanticsrf; + + $url = $urltorenew; + + print img_picto('', 'google', 'class="pictofixedwidth"').''.$langs->trans("LoginWith", "Google").''; + + echo '
'; +} ?> diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index d441d364f4b..2ff5d3f9c43 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -66,7 +66,7 @@ class InterfaceActionsAuto extends DolibarrTriggers * $object->elementtype (->element of object to link action to) * $object->module (if defined, elementtype in llx_actioncomm will be elementtype@module) * - * @param string $action Event action code ('CONTRACT_MODIFY', 'RECRUITMENTCANDIDATURE_MODIFIY', ...) + * @param string $action Event action code ('CONTRACT_MODIFY', 'RECRUITMENTCANDIDATURE_MODIFIY', or example by external module: 'SENTBYSMS'...) * @param Object $object Object * @param User $user Object user * @param Translate $langs Object langs @@ -88,6 +88,7 @@ class InterfaceActionsAuto extends DolibarrTriggers //var_dump($action.' - '.$conf->global->$key);exit; // Do not log events not enabled for this action + // GUI allow to set this option only if entry exists into table llx_c_action_trigger if (empty($conf->global->$key)) { return 0; } @@ -887,8 +888,9 @@ class InterfaceActionsAuto extends DolibarrTriggers } else { // TODO Merge all previous cases into this generic one // $action = BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ... + // Can also be a value defined by an external module like SENTBYSMS, COMPANY_SENTBYSMS, MEMBER_SENTBYSMS, ... // Note: We are here only if $conf->global->MAIN_AGENDA_ACTIONAUTO_action is on (tested at begining of this function). - // Note that these key can be set in agenda setup, only if defined into c_action_trigger + // Note that these key can be set in agenda setup, only if defined into llx_c_action_trigger // Load translation files required by the page if (empty($object->actionmsg2)) { $langs->loadLangs(array("agenda", "other")); diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 913b7b08a55..ff29e56b1e7 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2365,7 +2365,7 @@ class EmailCollector extends CommonObject // this code action is hook..... for support this call global $hookmanager; - if (!is_object($hookmanager)) { + if (is_object($hookmanager)) { $hookmanager->initHooks(array('emailcollectorcard')); } diff --git a/htdocs/eventorganization/conferenceorboothattendee_note.php b/htdocs/eventorganization/conferenceorboothattendee_note.php index 19d413daaa0..b8fb87d39fa 100644 --- a/htdocs/eventorganization/conferenceorboothattendee_note.php +++ b/htdocs/eventorganization/conferenceorboothattendee_note.php @@ -39,7 +39,6 @@ //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 diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 8d5dbd6ec7f..064dfc3a52c 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -1206,6 +1206,10 @@ if ($action == 'create') { print ''; print ''; } else { + if (! empty($conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS)) { + print ''; + } + print $langs->trans("NA"); } print ''; @@ -1385,6 +1389,10 @@ if ($action == 'create') { print ''; print ''; } else { + if (! empty($conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS)) { + print ''; + } + print $langs->trans("NA"); } print ''; diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 1b82eb777b0..307294d5422 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -134,6 +134,14 @@ if ($object->id > 0) { } } +$candelete = 0; +if (!empty($user->rights->expensereport->supprimer)) { + $candelete = 1; +} +if ($object->statut == ExpenseReport::STATUS_DRAFT && $user->rights->expensereport->write && in_array($object->fk_user_author, $childids)) { + $candelete = 1; +} + // Security check if ($user->socid) { $socid = $user->socid; @@ -226,7 +234,7 @@ if (empty($reshook)) { } } - if ($action == 'confirm_delete' && GETPOST("confirm", 'alpha') == "yes" && $id > 0 && $user->rights->expensereport->supprimer) { + if ($action == 'confirm_delete' && GETPOST("confirm", 'alpha') == "yes" && $id > 0 && $candelete) { $object = new ExpenseReport($db); $result = $object->fetch($id); $result = $object->delete($user); @@ -2737,7 +2745,7 @@ if ($action != 'create' && $action != 'edit' && $action != 'editline') { if ($user->rights->expensereport->creer && $user->id == $object->fk_user_author && $object->status < ExpenseReport::STATUS_APPROVED) { // Delete print ''; - } elseif ($user->rights->expensereport->supprimer && $object->status != ExpenseReport::STATUS_CLOSED) { + } elseif ($candelete && $object->status != ExpenseReport::STATUS_CLOSED) { // Delete print ''; } diff --git a/htdocs/externalsite/admin/index.php b/htdocs/externalsite/admin/index.php index ba23b88e68e..0b55a297be9 100644 --- a/htdocs/externalsite/admin/index.php +++ b/htdocs/externalsite/admin/index.php @@ -57,7 +57,7 @@ if ($action == 'update') { $label = GETPOST('EXTERNALSITE_LABEL', 'alphanohtml'); // exturl can be an url or a HTML string - $exturl = GETPOST('EXTERNALSITE_URL', 'none'); + $exturl = GETPOST('EXTERNALSITE_URL', 'restricthtml'); $exturl = dol_string_onlythesehtmltags($exturl, 1, 1, 0, 1); $exturl = dol_string_onlythesehtmlattributes($exturl); @@ -110,7 +110,7 @@ print ''; print '"; print '
textwithpicto($langs->trans("ComputedFormula"), $langs->trans("ComputedFormulaDesc")).$form->textwithpicto($langs->trans("Computedpersistent"), $langs->trans("ComputedpersistentDesc"), 1, 'warning'); ?>
trans("DefaultValue").' ('.$langs->trans("Database").')'; ?>
'.$langs->trans("ExternalSiteURL")."