diff --git a/htdocs/adherents/document.php b/htdocs/adherents/document.php index 5150bea861e..f2a7c6f3f55 100644 --- a/htdocs/adherents/document.php +++ b/htdocs/adherents/document.php @@ -93,6 +93,8 @@ if ($id) { $caneditfieldmember = $user->rights->adherent->creer; } +$permissiontoadd = $canaddmember; + // Security check $result = restrictedArea($user, 'adherent', $object->id, '', '', 'socid', 'rowid', 0); diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index f8a782a54e5..d03574d473b 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -871,8 +871,8 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { if ($value == 'price' || preg_match('/^amount/i', $value)) { $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); - } elseif ($value == 'taux' || $value == 'localtax1' || $value == 'localtax2') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); + } elseif ($value == 'taux' || $value == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z } elseif ($value == 'entity') { $_POST[$keycode] = getEntity($tabname[$id]); } @@ -940,8 +940,8 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { if ($field == 'price' || preg_match('/^amount/i', $field)) { $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); - } elseif ($field == 'taux' || $field == 'localtax1' || $field == 'localtax2') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); + } elseif ($field == 'taux' || $field == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z } elseif ($field == 'entity') { $_POST[$keycode] = getEntity($tabname[$id]); } @@ -1254,13 +1254,13 @@ if ($id) { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $class = "center"; $sortable = 0; } if ($value == 'localtax1') { - $valuetoshow = $langs->trans("Rate")." 2"; $class = "center"; + $valuetoshow = $langs->trans("RateOfTaxN", '2'); $class = "center"; } if ($value == 'localtax2_type') { $valuetoshow = $langs->trans("UseLocalTax")." 3"; $class = "center"; $sortable = 0; } if ($value == 'localtax2') { - $valuetoshow = $langs->trans("Rate")." 3"; $class = "center"; + $valuetoshow = $langs->trans("RateOfTaxN", '3'); $class = "center"; } if ($value == 'organization') { $valuetoshow = $langs->trans("Organization"); @@ -1598,17 +1598,18 @@ if ($id) { } $cssprefix = 'center '; } + if ($value == 'localtax1_type') { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $cssprefix = "center "; $sortable = 0; } if ($value == 'localtax1') { - $valuetoshow = $langs->trans("Rate")." 2"; $cssprefix = "center "; $sortable = 0; + $valuetoshow = $langs->trans("RateOfTaxN", '2'); $cssprefix = "center "; $sortable = 0; } if ($value == 'localtax2_type') { $valuetoshow = $langs->trans("UseLocalTax")." 3"; $cssprefix = "center "; $sortable = 0; } if ($value == 'localtax2') { - $valuetoshow = $langs->trans("Rate")." 3"; $cssprefix = "center "; $sortable = 0; + $valuetoshow = $langs->trans("RateOfTaxN", '3'); $cssprefix = "center "; $sortable = 0; } if ($value == 'organization') { $valuetoshow = $langs->trans("Organization"); diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 8fcbc898844..2d3133c9fce 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -48,7 +48,7 @@ $substitutionarrayfortest = array( '__DOL_MAIN_URL_ROOT__'=>DOL_MAIN_URL_ROOT, '__ID__' => 'RecipientIdRecord', //'__EMAIL__' => 'RecipientEMail', // Done into actions_sendmails - '__CHECK_READ__' => (is_object($object) && !empty($object->thirdparty) && is_object($object->thirdparty)) ? '' : '', + '__CHECK_READ__' => (!empty($object) && is_object($object) && is_object($object->thirdparty)) ? '' : '', '__USER_SIGNATURE__' => (($user->signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? $usersignature : ''), // Done into actions_sendmails '__LOGIN__' => 'RecipientLogin', '__LASTNAME__' => 'RecipientLastname', @@ -737,14 +737,14 @@ if ($action == 'edit') { print ''.$langs->trans('MAIN_MAIL_DEFAULT_FROMTYPE').''; print ''; - if (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) && $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE === 'robot') { + if (getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE') === 'robot') { print $langs->trans('RobotEmail'); - } elseif (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) && $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE === 'user') { + } elseif (getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE') === 'user') { print $langs->trans('UserEmail'); - } elseif (!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) && $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE === 'company') { + } elseif (getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE') === 'company') { print $langs->trans('CompanyEmail').' '.dol_escape_htmltag('<'.$mysoc->email.'>'); } else { - $id = preg_replace('/senderprofile_/', '', !empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE) ? $conf->global->MAIN_MAIL_DEFAULT_FROMTYPE : ''); + $id = preg_replace('/senderprofile_/', '', getDolGlobalString('MAIN_MAIL_DEFAULT_FROMTYPE')); if ($id > 0) { include_once DOL_DOCUMENT_ROOT.'/core/class/emailsenderprofile.class.php'; $emailsenderprofile = new EmailSenderProfile($db); @@ -756,7 +756,7 @@ if ($action == 'edit') { // Errors To print ''.$langs->trans("MAIN_MAIL_ERRORS_TO").''; - print ''.(!empty($conf->global->MAIN_MAIL_ERRORS_TO) ? $conf->global->MAIN_MAIL_ERRORS_TO : ''); + print ''.(getDolGlobalString('MAIN_MAIL_ERRORS_TO')); if (!empty($conf->global->MAIN_MAIL_ERRORS_TO) && !isValidEmail($conf->global->MAIN_MAIL_ERRORS_TO)) { print img_warning($langs->trans("ErrorBadEMail")); } diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php index 530860dee71..50b27b30964 100644 --- a/htdocs/admin/system/filecheck.php +++ b/htdocs/admin/system/filecheck.php @@ -53,8 +53,8 @@ print ''.$langs->trans("FileCheckDesc").'
print '
'; print ''; print ''."\n"; -print ''."\n"; -print ''."\n"; +print ''."\n"; +print ''."\n"; print '
'.$langs->trans("Version").''.$langs->trans("Value").'
'.$langs->trans("VersionLastInstall").''.$conf->global->MAIN_VERSION_LAST_INSTALL.'
'.$langs->trans("VersionLastUpgrade").''.$conf->global->MAIN_VERSION_LAST_UPGRADE.'
'.$langs->trans("VersionLastInstall").''.getDolGlobalString('MAIN_VERSION_LAST_INSTALL').'
'.$langs->trans("VersionLastUpgrade").''.getDolGlobalString('MAIN_VERSION_LAST_UPGRADE').'
'.$langs->trans("VersionProgram").''.DOL_VERSION; // If current version differs from last upgrade if (empty($conf->global->MAIN_VERSION_LAST_UPGRADE)) { @@ -171,7 +171,7 @@ if (GETPOST('target') == 'remote') { } -if (!$error && $xml) { +if (empty($error) && !empty($xml)) { $checksumconcat = array(); $file_list = array(); $out = ''; diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 0d4f60f3851..428c80676a2 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -157,7 +157,7 @@ $title = $langs->trans("BackupDumpWizard"); print load_fiche_titre($title); -print ''; +print '
'; print ''; print '\n"; if (!$i) { @@ -1731,7 +1749,9 @@ if ($resql) { $userstatic->entity = $val['entity']; $userstatic->photo = $val['photo']; $userstatic->login = $val['login']; - $userstatic->phone = $val['phone']; + $userstatic->office_phone = $val['office_phone']; + $userstatic->office_fax = $val['office_fax']; + $userstatic->user_mobile = $val['user_mobile']; $userstatic->job = $val['job']; $userstatic->gender = $val['gender']; //print '
': diff --git a/htdocs/commande/document.php b/htdocs/commande/document.php index b4dddc9a1bf..c289112ee9f 100644 --- a/htdocs/commande/document.php +++ b/htdocs/commande/document.php @@ -44,12 +44,6 @@ $confirm = GETPOST('confirm'); $id = GETPOST('id', 'int'); $ref = GETPOST('ref'); -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'commande', $id, ''); - // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST("sortfield", 'alpha'); @@ -78,6 +72,14 @@ if (!$sortfield) { $object = new Commande($db); +$permissiontoadd = $user->rights->commande->creer; + +// Security check +if ($user->socid) { + $socid = $user->socid; +} +$result = restrictedArea($user, 'commande', $id, ''); + /* * Actions diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 5bb8e6ccb0c..3485011c1e6 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -417,17 +417,18 @@ $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { $sql = 'SELECT DISTINCT'; } -$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; +$sql .= " country.code as country_code,"; $sql .= ' c.rowid, c.ref, c.total_ht, c.total_tva, c.total_ttc, c.ref_client, c.fk_user_author,'; $sql .= ' c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva as multicurrency_total_vat, c.multicurrency_total_ttc,'; $sql .= ' c.date_valid, c.date_commande, c.note_public, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed,'; $sql .= ' c.date_creation as date_creation, c.tms as date_update, c.date_cloture as date_cloture,'; -$sql .= " p.rowid as project_id, p.ref as project_ref, p.title as project_label,"; -$sql .= " u.login,"; -$sql .= ' c.fk_cond_reglement,c.fk_mode_reglement,c.fk_shipping_method'; -$sql .= ' ,c.fk_input_reason'; +$sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label,'; +$sql .= ' u.login, u.lastname, u.firstname, u.email, u.statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender,'; +$sql .= ' c.fk_cond_reglement,c.fk_mode_reglement,c.fk_shipping_method,'; +$sql .= ' c.fk_input_reason'; if ($search_categ_cus) { $sql .= ", cc.fk_categorie, cc.fk_soc"; } @@ -1383,10 +1384,16 @@ if ($resql) { $nbprod = 0; $companystatic->id = $obj->socid; - $companystatic->code_client = $obj->code_client; $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; $companystatic->client = $obj->client; + $companystatic->code_client = $obj->code_client; $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; if (!isset($getNomUrl_cache[$obj->socid])) { $getNomUrl_cache[$obj->socid] = $companystatic->getNomUrl(1, 'customer'); } @@ -1669,12 +1676,23 @@ if ($resql) { $userstatic->id = $obj->fk_user_author; $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->email; + $userstatic->statut = $obj->statut; + $userstatic->entity = $obj->entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; // Author if (!empty($arrayfields['u.login']['checked'])) { - print '
'; if (!$i) { @@ -1878,13 +1884,25 @@ if ($resql) { $totalarray['val']['f.total_ttc'] += $obj->total_ttc; } + $userstatic->id = $obj->fk_user_author; + $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->email; + $userstatic->statut = $obj->statut; + $userstatic->entity = $obj->entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; + // Author if (!empty($arrayfields['u.login']['checked'])) { - $userstatic->id = $obj->fk_user_author; - $userstatic->login = $obj->login; - print '
'; print $langs->trans("DatabaseName").' : '.$dolibarr_main_db_name.'
'; diff --git a/htdocs/admin/tools/listevents.php b/htdocs/admin/tools/listevents.php index 935804ada10..fbc2412a9df 100644 --- a/htdocs/admin/tools/listevents.php +++ b/htdocs/admin/tools/listevents.php @@ -42,7 +42,7 @@ if ($user->socid > 0) { } // Load translation files required by the page -$langs->loadLangs(array("companies", "admin", "users", "other")); +$langs->loadLangs(array("companies", "admin", "users", "other","withdrawals")); // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; @@ -285,7 +285,7 @@ if ($result) { $param .= "&date_endyear=".urlencode($date_endyear); } - $langs->load('withdrawals'); + $center = ''; if ($num) { $center = ''.$langs->trans("Purge").''; } diff --git a/htdocs/asset/document.php b/htdocs/asset/document.php index e6f5ed9b353..91e46269994 100644 --- a/htdocs/asset/document.php +++ b/htdocs/asset/document.php @@ -40,12 +40,6 @@ $socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result=restrictedArea($user, 'asset', $id, ''); - // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST("sortfield", 'alpha'); @@ -69,6 +63,14 @@ if ($object->fetch($id)) { $upload_dir = $conf->asset->dir_output."/".dol_sanitizeFileName($object->ref); } +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php + +// Security check +if ($user->socid) { + $socid = $user->socid; +} +$result=restrictedArea($user, 'asset', $id, ''); + /* * Actions diff --git a/htdocs/bom/bom_document.php b/htdocs/bom/bom_document.php index c0196670cfb..e59b22c45b2 100644 --- a/htdocs/bom/bom_document.php +++ b/htdocs/bom/bom_document.php @@ -85,6 +85,8 @@ if ($id > 0 || !empty($ref)) { $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); +$permissiontoadd = $user->rights->bom->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php + /* * Actions diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index f368378a281..10e96b50014 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1821,7 +1821,7 @@ if ($id > 0) { $linkback = ''; // Link to other agenda views - $linkback .= img_picto($langs->trans("BackToList"), 'object_list-alt', 'class="hideonsmartphone pictoactionview"'); + $linkback .= img_picto($langs->trans("BackToList"), 'object_list', 'class="hideonsmartphone pictoactionview"'); $linkback .= ''.$langs->trans("BackToList").''; $linkback .= ''; $linkback .= '
  • '; diff --git a/htdocs/comm/action/document.php b/htdocs/comm/action/document.php index f521fa2ab59..7465e613611 100644 --- a/htdocs/comm/action/document.php +++ b/htdocs/comm/action/document.php @@ -88,6 +88,8 @@ if ($user->socid && $socid) { $result = restrictedArea($user, 'societe', $socid); } +$permissiontoadd = $user->rights->agenda->myactions->read; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php + /* * Actions @@ -145,7 +147,7 @@ if ($object->id > 0) { $out = ''; $out .= '
  • '.img_picto($langs->trans("ViewPerUser"), 'object_calendarperuser', 'class="hideonsmartphone pictoactionview"'); $out .= ''.$langs->trans("ViewPerUser").''; - $out .= '
  • '.img_picto($langs->trans("ViewCal"), 'object_calendar', 'class="hideonsmartphone pictoactionview"'); + $out .= '
  • '.img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="hideonsmartphone pictoactionview"'); $out .= ''.$langs->trans("ViewCal").''; $out .= '
  • '.img_picto($langs->trans("ViewWeek"), 'object_calendarweek', 'class="hideonsmartphone pictoactionview"'); $out .= ''.$langs->trans("ViewWeek").''; diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index d5457447100..459ede423b1 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -480,13 +480,13 @@ print ''; $viewmode = ''; $viewmode .= ''; //$viewmode .= ''; -$viewmode .= img_picto($langs->trans("List"), 'object_list-alt', 'class="pictoactionview block"'); +$viewmode .= img_picto($langs->trans("List"), 'object_list', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewList").''; $viewmode .= ''; //$viewmode .= ''; -$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendar', 'class="pictoactionview block"'); +$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewCal").''; diff --git a/htdocs/comm/action/info.php b/htdocs/comm/action/info.php index f5d1c65b267..071d6409176 100644 --- a/htdocs/comm/action/info.php +++ b/htdocs/comm/action/info.php @@ -73,7 +73,7 @@ $linkback .= ''.$langs->trans(" $out = ''; $out .= '
  • '.img_picto($langs->trans("ViewPerUser"), 'object_calendarperuser', 'class="hideonsmartphone pictoactionview"'); $out .= ''.$langs->trans("ViewPerUser").''; -$out .= '
  • '.img_picto($langs->trans("ViewCal"), 'object_calendar', 'class="hideonsmartphone pictoactionview"'); +$out .= '
  • '.img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="hideonsmartphone pictoactionview"'); $out .= ''.$langs->trans("ViewCal").''; $out .= '
  • '.img_picto($langs->trans("ViewWeek"), 'object_calendarweek', 'class="hideonsmartphone pictoactionview"'); $out .= ''.$langs->trans("ViewWeek").''; diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 96a69403289..e3cc54f5a35 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -606,13 +606,13 @@ if ($resql) { $viewmode = ''; $viewmode .= ''; //$viewmode .= ''; - $viewmode .= img_picto($langs->trans("List"), 'object_list-alt', 'class="pictoactionview block"'); + $viewmode .= img_picto($langs->trans("List"), 'object_list', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewList").''; $viewmode .= ''; //$viewmode .= ''; - $viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendar', 'class="pictoactionview block"'); + $viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewCal").''; diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index 19f8a8ce31c..32eaccdcce1 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -416,13 +416,13 @@ $massactionbutton = ''; $viewmode = ''; $viewmode .= ''; //$viewmode .= ''; -$viewmode .= img_picto($langs->trans("List"), 'object_list-alt', 'class="pictoactionview block"'); +$viewmode .= img_picto($langs->trans("List"), 'object_list', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewList").''; $viewmode .= ''; //$viewmode .= ''; -$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendar', 'class="pictoactionview block"'); +$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewCal").''; diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index 62af33b34ee..76330d39453 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -426,13 +426,13 @@ $massactionbutton = ''; $viewmode = ''; $viewmode .= ''; //$viewmode .= ''; -$viewmode .= img_picto($langs->trans("List"), 'object_list-alt', 'class="pictoactionview block"'); +$viewmode .= img_picto($langs->trans("List"), 'object_list', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewList").''; $viewmode .= ''; //$viewmode .= ''; -$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendar', 'class="pictoactionview block"'); +$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="pictoactionview block"'); //$viewmode .= ''; $viewmode .= ''.$langs->trans("ViewCal").''; diff --git a/htdocs/comm/propal/document.php b/htdocs/comm/propal/document.php index 4e592c8371e..2b21c545c63 100644 --- a/htdocs/comm/propal/document.php +++ b/htdocs/comm/propal/document.php @@ -80,6 +80,8 @@ if (!$sortfield) { $object = new Propal($db); $object->fetch($id, $ref); +$permissiontoadd = $user->rights->propale->creer; + // Security check if (!empty($user->socid)) { $socid = $user->socid; diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index e1ec555837f..b810ab242b6 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -460,9 +460,10 @@ $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { $sql = 'SELECT DISTINCT'; } -$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client, '; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.phone, s.fax , s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client, '; $sql .= " typent.code as typent_code,"; $sql .= " ava.rowid as availability,"; +$sql .= " country.code as country_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= ' p.rowid, p.entity, p.note_private, p.total_ht, p.total_tva, p.total_ttc, p.localtax1, p.localtax2, p.ref, p.ref_client, p.fk_statut as status, p.fk_user_author, p.datep as dp, p.fin_validite as dfv,p.date_livraison as ddelivery,'; $sql .= ' p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc,'; @@ -470,7 +471,7 @@ $sql .= ' p.datec as date_creation, p.tms as date_update, p.date_cloture as date $sql .= ' p.note_public, p.note_private,'; $sql .= ' p.fk_cond_reglement,p.fk_mode_reglement,p.fk_shipping_method,p.fk_input_reason,'; $sql .= " pr.rowid as project_id, pr.ref as project_ref, pr.title as project_label,"; -$sql .= ' u.login'; +$sql .= ' u.login, u.lastname, u.firstname, u.email, u.statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender'; if (!$user->rights->societe->client->voir && !$socid) { $sql .= ", sc.fk_soc, sc.fk_user"; } @@ -1335,9 +1336,15 @@ if ($resql) { $companystatic->id = $obj->socid; $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; $companystatic->client = $obj->client; $companystatic->code_client = $obj->code_client; $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; $projectstatic->id = $obj->project_id; $projectstatic->ref = $obj->project_ref; @@ -1694,12 +1701,23 @@ if ($resql) { $userstatic->id = $obj->fk_user_author; $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->email; + $userstatic->statut = $obj->statut; + $userstatic->entity = $obj->entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; // Author if (!empty($arrayfields['u.login']['checked'])) { - print '
  • '; + print ''; if ($userstatic->id) { - print $userstatic->getLoginUrl(1); + print $userstatic->getNomUrl(-1); } print "'; + print ''; if ($userstatic->id) { - print $userstatic->getLoginUrl(1); + print $userstatic->getNomUrl(-1); } else { print ' '; } diff --git a/htdocs/compta/facture/document.php b/htdocs/compta/facture/document.php index 664b84d4444..16cdee4ac53 100644 --- a/htdocs/compta/facture/document.php +++ b/htdocs/compta/facture/document.php @@ -72,6 +72,8 @@ if ($object->fetch($id, $ref)) { $upload_dir = $conf->facture->dir_output."/".dol_sanitizeFileName($object->ref); } +$permissiontoadd = $user->rights->facture->creer; + // Security check if ($user->socid) { $socid = $user->socid; diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 1ac8765171d..7c9b71e458b 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -467,7 +467,7 @@ if (!empty($conf->margin->enabled)) { $bankaccountstatic = new Account($db); $facturestatic = new Facture($db); $formcompany = new FormCompany($db); -$thirdpartystatic = new Societe($db); +$companystatic = new Societe($db); $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { @@ -481,12 +481,12 @@ $sql .= ' f.datef, f.date_valid, f.date_lim_reglement as datelimite, f.module_so $sql .= ' f.paye as paye, f.fk_statut, f.close_code,'; $sql .= ' f.datec as date_creation, f.tms as date_update, f.date_closing as date_closing,'; $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; -$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; -$sql .= " typent.code as typent_code,"; -$sql .= " state.code_departement as state_code, state.nom as state_name,"; -$sql .= " country.code as country_code,"; -$sql .= " p.rowid as project_id, p.ref as project_ref, p.title as project_label,"; -$sql .= " u.login"; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; +$sql .= ' typent.code as typent_code,'; +$sql .= ' state.code_departement as state_code, state.nom as state_name,'; +$sql .= ' country.code as country_code,'; +$sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label,'; +$sql .= ' u.login, u.lastname, u.firstname, u.email, u.statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender'; // We need dynamount_payed to be able to sort on status (value is surely wrong because we can count several lines several times due to other left join or link with contacts. But what we need is just 0 or > 0) // TODO Better solution to be able to sort on already payed or remain to pay is to store amount_payed in a denormalized field. if (!$sall) { @@ -714,12 +714,12 @@ if (!$sall) { $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; $sql .= ' f.fk_user_author, f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva,'; $sql .= ' f.multicurrency_total_tva, f.multicurrency_total_ttc,'; - $sql .= ' s.rowid, s.nom, s.name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; + $sql .= ' s.rowid, s.nom, s.name_alias, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; $sql .= ' typent.code,'; $sql .= ' state.code_departement, state.nom,'; $sql .= ' country.code,'; $sql .= " p.rowid, p.ref, p.title,"; - $sql .= " u.login"; + $sql .= " u.login, u.lastname, u.firstname, u.email, u.statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender"; if ($search_categ_cus) { $sql .= ", cc.fk_categorie, cc.fk_soc"; } @@ -1539,16 +1539,22 @@ if ($resql) { $facturestatic->situation_cycle_ref = $obj->situation_cycle_ref; $facturestatic->situation_counter = $obj->situation_counter; } - $thirdpartystatic->id = $obj->socid; - $thirdpartystatic->name = $obj->name; - $thirdpartystatic->client = $obj->client; - $thirdpartystatic->fournisseur = $obj->fournisseur; - $thirdpartystatic->code_client = $obj->code_client; - $thirdpartystatic->code_compta_client = $obj->code_compta_client; - $thirdpartystatic->code_fournisseur = $obj->code_fournisseur; - $thirdpartystatic->code_compta_fournisseur = $obj->code_compta_fournisseur; - $thirdpartystatic->email = $obj->email; - $thirdpartystatic->country_code = $obj->country_code; + $companystatic->id = $obj->socid; + $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; + $companystatic->client = $obj->client; + $companystatic->fournisseur = $obj->fournisseur; + $companystatic->code_client = $obj->code_client; + $companystatic->code_compta_client = $obj->code_compta_client; + $companystatic->code_fournisseur = $obj->code_fournisseur; + $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur; + $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->fax = $obj->fax; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; $projectstatic->id = $obj->project_id; $projectstatic->ref = $obj->project_ref; @@ -1570,10 +1576,10 @@ if ($resql) { $multicurrency_remaintopay = 0; } if ($facturestatic->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1) { // If credit note closed, we take into account the amount not yet consummed - $remaincreditnote = $discount->getAvailableDiscounts($thirdpartystatic, '', 'rc.fk_facture_source='.$facturestatic->id); + $remaincreditnote = $discount->getAvailableDiscounts($companystatic, '', 'rc.fk_facture_source='.$facturestatic->id); $remaintopay = -$remaincreditnote; $totalpay = price2num($facturestatic->total_ttc - $remaintopay); - $multicurrency_remaincreditnote = $discount->getAvailableDiscounts($thirdpartystatic, '', 'rc.fk_facture_source='.$facturestatic->id, 0, 0, 1); + $multicurrency_remaincreditnote = $discount->getAvailableDiscounts($companystatic, '', 'rc.fk_facture_source='.$facturestatic->id, 0, 0, 1); $multicurrency_remaintopay = -$multicurrency_remaincreditnote; $multicurrency_totalpay = price2num($facturestatic->multicurrency_total_ttc - $multicurrency_remaintopay); } @@ -1704,9 +1710,9 @@ if ($resql) { if (!empty($arrayfields['s.nom']['checked'])) { print ''; if ($contextpage == 'poslist') { - print $thirdpartystatic->name; + print $companystatic->name; } else { - print $thirdpartystatic->getNomUrl(1, 'customer'); + print $companystatic->getNomUrl(1, 'customer'); } print ''; + print ''; if ($userstatic->id) { - print $userstatic->getLoginUrl(1); + print $userstatic->getNomUrl(-1); } else { print ' '; } diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index 2b0c3961759..db754390e5e 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -38,7 +38,7 @@ if (!empty($conf->projet->enabled)) { } // Load translation files required by the page -$langs->loadLangs(array('compta', 'banks', 'bills', 'hrm')); +$langs->loadLangs(array('compta', 'banks', 'bills', 'hrm', 'projects')); $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); diff --git a/htdocs/core/actions_linkedfiles.inc.php b/htdocs/core/actions_linkedfiles.inc.php index 13814511297..750ed2b2d9a 100644 --- a/htdocs/core/actions_linkedfiles.inc.php +++ b/htdocs/core/actions_linkedfiles.inc.php @@ -21,13 +21,14 @@ // Variable $upload_dir must be defined when entering here. // Variable $upload_dirold may also exists. // Variable $confirm must be defined. +// If variable $permissiontoadd is defined, we check it is true. Note: A test on permission should already have been done into the restrictedArea() method called by parent page. //var_dump($upload_dir); //var_dump($upload_dirold); // Submit file/link -if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC)) { +if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC) && (!isset($permissiontoadd) || $permissiontoadd)) { if (!empty($_FILES)) { if (is_array($_FILES['userfile']['tmp_name'])) { $userfiles = $_FILES['userfile']['tmp_name']; @@ -65,7 +66,7 @@ if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC)) { } } } -} elseif (GETPOST('linkit', 'restricthtml') && !empty($conf->global->MAIN_UPLOAD_DOC)) { +} elseif (GETPOST('linkit', 'restricthtml') && !empty($conf->global->MAIN_UPLOAD_DOC) && (!isset($permissiontoadd) || $permissiontoadd)) { $link = GETPOST('link', 'alpha'); if ($link) { if (substr($link, 0, 7) != 'http://' && substr($link, 0, 8) != 'https://' && substr($link, 0, 7) != 'file://' && substr($link, 0, 7) != 'davs://') { @@ -77,7 +78,7 @@ if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC)) { // Delete file/link -if ($action == 'confirm_deletefile' && $confirm == 'yes') { +if ($action == 'confirm_deletefile' && $confirm == 'yes' && (!isset($permissiontoadd) || $permissiontoadd)) { $urlfile = GETPOST('urlfile', 'alpha', 0, null, null, 1); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP). if (GETPOST('section', 'alpha')) { // For a delete from the ECM module, upload_dir is ECM root dir and urlfile contains relative path from upload_dir @@ -149,7 +150,7 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') { exit; } } -} elseif ($action == 'confirm_updateline' && GETPOST('save', 'alpha') && GETPOST('link', 'alpha')) { +} elseif ($action == 'confirm_updateline' && GETPOST('save', 'alpha') && GETPOST('link', 'alpha') && (!isset($permissiontoadd) || $permissiontoadd)) { require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; $langs->load('link'); $link = new Link($db); @@ -167,7 +168,7 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') { } else { //error fetching } -} elseif ($action == 'renamefile' && GETPOST('renamefilesave', 'alpha')) { +} elseif ($action == 'renamefile' && GETPOST('renamefilesave', 'alpha') && (!isset($permissiontoadd) || $permissiontoadd)) { // For documents pages, upload_dir contains already path to file from module dir, so we clean path into urlfile. if (!empty($upload_dir)) { $filenamefrom = dol_sanitizeFileName(GETPOST('renamefilefrom', 'alpha'), '_', 0); // Do not remove accents diff --git a/htdocs/core/ajax/row.php b/htdocs/core/ajax/row.php index 4662c3a1406..96dc792938f 100644 --- a/htdocs/core/ajax/row.php +++ b/htdocs/core/ajax/row.php @@ -49,6 +49,9 @@ if (!defined('NOREQUIRETRAN')) { require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php'; +// Security check +// This is done later into view. + /* * View @@ -59,16 +62,16 @@ top_httphead(); print ''."\n"; // Registering the location of boxes -if (GETPOST('roworder', 'alpha', 2) && GETPOST('table_element_line', 'aZ09', 2) - && GETPOST('fk_element', 'aZ09', 2) && GETPOST('element_id', 'int', 2)) { - $roworder = GETPOST('roworder', 'alpha', 2); - $table_element_line = GETPOST('table_element_line', 'aZ09', 2); - $fk_element = GETPOST('fk_element', 'aZ09', 2); - $element_id = GETPOST('element_id', 'int', 2); +if (GETPOST('roworder', 'alpha', 3) && GETPOST('table_element_line', 'aZ09', 3) + && GETPOST('fk_element', 'aZ09', 3) && GETPOST('element_id', 'int', 3)) { + $roworder = GETPOST('roworder', 'alpha', 3); + $table_element_line = GETPOST('table_element_line', 'aZ09', 3); + $fk_element = GETPOST('fk_element', 'aZ09', 3); + $element_id = GETPOST('element_id', 'int', 3); dol_syslog("AjaxRow roworder=".$roworder." table_element_line=".$table_element_line." fk_element=".$fk_element." element_id=".$element_id, LOG_DEBUG); - // Make test on pemrission + // Make test on permission $perm = 0; if ($table_element_line == 'propaldet' && $user->rights->propal->creer) { $perm = 1; @@ -92,6 +95,10 @@ if (GETPOST('roworder', 'alpha', 2) && GETPOST('table_element_line', 'aZ09', 2) $perm = 1; } elseif ($table_element_line == 'facture_fourn_det' && $user->rights->fourn->facture->creer) { $perm = 1; + } elseif ($table_element_line == 'ecm_files' && $fk_element == 'fk_product' && (!empty($user->rights->produit->creer) || !empty($user->rights->service->creer))) { + $perm = 1; + } elseif ($table_element_line == 'ecm_files' && $fk_element == 'fk_ticket' && !empty($user->rights->ticket->write)) { + $perm = 1; } else { $tmparray = explode('_', $table_element_line); $tmpmodule = $tmparray[0]; $tmpobject = preg_replace('/line$/', '', $tmparray[1]); @@ -101,7 +108,10 @@ if (GETPOST('roworder', 'alpha', 2) && GETPOST('table_element_line', 'aZ09', 2) } if (! $perm) { + // We should not be here. If we are not allowed to reorder rows, feature should not be visible on script. + // If we are here, it is a hack attempt, so we report a warning. print 'Bad permission to modify position of lines for object in table '.$table_element_line; + dol_syslog('Bad permission to modify position of lines for object in table '.$table_element_line.', fk_element '.$fk_element, LOG_WARNING); accessforbidden('Bad permission to modify position of lines for object in table '.$table_element_line); } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9b90ed0b30a..2d529cd55d6 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8754,8 +8754,8 @@ class Form } // Search all projects - $sql = 'SELECT f.rowid, f.ref as fref, "nolabel" as flabel, p.rowid as pid, f.ref, - p.title, p.fk_soc, p.fk_statut, p.public,'; + $sql = "SELECT f.rowid, f.ref as fref, 'nolabel' as flabel, p.rowid as pid, f.ref, + p.title, p.fk_soc, p.fk_statut, p.public,"; $sql .= ' s.nom as name'; $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON s.rowid = p.fk_soc,'; @@ -8765,7 +8765,7 @@ class Form //if ($projectsListId) $sql.= " AND p.rowid IN (".$this->db->sanitize($projectsListId).")"; //if ($socid == 0) $sql.= " AND (p.fk_soc=0 OR p.fk_soc IS NULL)"; //if ($socid > 0) $sql.= " AND (p.fk_soc=".$socid." OR p.fk_soc IS NULL)"; - $sql .= " GROUP BY f.ref ORDER BY p.ref, f.ref ASC"; + $sql .= " ORDER BY p.ref, f.ref ASC"; $resql = $this->db->query($sql); if ($resql) { diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 513b73658f7..303382f285b 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -906,7 +906,7 @@ function listOfSessions() if (preg_match('/dol_login/i', $sessValues) && // limit to dolibarr session (preg_match('/dol_entity\|i:'.$conf->entity.';/i', $sessValues) || preg_match('/dol_entity\|s:([0-9]+):"'.$conf->entity.'"/i', $sessValues)) && // limit to current entity - preg_match('/dol_company\|s:([0-9]+):"('.$conf->global->MAIN_INFO_SOCIETE_NOM.')"/i', $sessValues)) { // limit to company name + preg_match('/dol_company\|s:([0-9]+):"('.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').')"/i', $sessValues)) { // limit to company name $tmp = explode('_', $file); $idsess = $tmp[1]; $regs = array(); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 8251c850ddf..a4a2d736746 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -634,17 +634,17 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null $out = checkVal($out, $check, $filter, $options); } - // Sanitizing for special parameters. There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. + // Sanitizing for special parameters. + // Note: There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. if ($paramname == 'backtopage' || $paramname == 'backtolist' || $paramname == 'backtourl') { - $out = str_replace('\\', '/', $out); - $out = str_replace(array(':', ';', '@'), '', $out); - + $out = str_replace('\\', '/', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. + $out = str_replace(array(':', ';', '@'), '', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. do { $oldstringtoclean = $out; $out = str_ireplace(array('javascript', 'vbscript', '&colon', '&#'), '', $out); } while ($oldstringtoclean != $out); - $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); + $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); // We remove schema*// to remove external URL } // Code for search criteria persistence. @@ -684,7 +684,7 @@ function GETPOSTINT($paramname, $method = 0, $filter = null, $options = null, $n } /** - * Return a value after checking on a rule. + * Return a value after checking on a rule. A sanitization may also have been done. * * @param string $out Value to check/clear. * @param string $check Type of check/sanitizing @@ -777,6 +777,11 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = case 'restricthtml': // Recommended for most html textarea do { $oldstringtoclean = $out; + + // We replace chars encoded with numeric HTML entities with real char (to avoid to have numeric entities used for obfuscation of injections) + $out = preg_replace_callback('/&#(x?[0-9][0-9a-f]+);/i', 'realCharForNumericEntities', $out); + $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'. + $out = dol_string_onlythesehtmltags($out, 0, 1, 1); // We should also exclude non expected attributes @@ -797,7 +802,6 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = } - if (!function_exists('dol_getprefix')) { /** * Return a prefix to use for this Dolibarr instance, for session/cookie names or email id. @@ -3494,6 +3498,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ '1downarrow', '1uparrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected', 'accountancy', 'account', 'accountline', 'action', 'add', 'address', 'angle-double-down', 'angle-double-up', 'asset', 'bank_account', 'barcode', 'bank', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'bug', 'building', + 'calendar', 'calendarmonth', 'calendarweek', 'calendarday', 'calendarperuser', 'calendarpertype', 'cash-register', 'category', 'chart', 'check', 'clock', 'close_title', 'cog', 'collab', 'company', 'contact', 'country', 'contract', 'cron', 'cubes', 'multicurrency', 'delete', 'dolly', 'dollyrevert', 'donation', 'download', 'dynamicprice', 'edit', 'ellipsis-h', 'email', 'eraser', 'establishment', 'expensereport', 'external-link-alt', 'external-link-square-alt', @@ -3501,7 +3506,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'generate', 'globe', 'globe-americas', 'graph', 'grip', 'grip_title', 'group', 'help', 'holiday', 'images', 'incoterm', 'info', 'intervention', 'inventory', 'intracommreport', 'knowledgemanagement', - 'label', 'language', 'link', 'list', 'listlight', 'loan', 'lot', 'long-arrow-alt-right', + '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', 'playdisabled', 'previous', 'poll', 'pos', 'printer', 'product', 'propal', 'stock', 'resize', 'service', 'stats', 'trip', @@ -3547,7 +3552,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'sign-out'=>'sign-out-alt', 'switch_off'=>'toggle-off', 'switch_on'=>'toggle-on', 'check'=>'check', 'bookmark'=>'star', 'bookmark'=>'star', 'bank'=>'university', 'close_title'=>'times', 'delete'=>'trash', 'edit'=>'pencil-alt', 'filter'=>'filter', - 'list-alt'=>'list-alt', 'calendar'=>'calendar-alt', 'calendarweek'=>'calendar-week', 'calendarmonth'=>'calendar-alt', 'calendarday'=>'calendar-day', 'calendarperuser'=>'table', + 'list-alt'=>'list-alt', 'calendar'=>'calendar-alt', 'calendarmonth'=>'calendar-alt', 'calendarweek'=>'calendar-week', 'calendarmonth'=>'calendar-alt', 'calendarday'=>'calendar-day', 'calendarperuser'=>'table', 'intervention'=>'ambulance', 'invoice'=>'file-invoice-dollar', 'multicurrency'=>'dollar-sign', 'order'=>'file-invoice', 'error'=>'exclamation-triangle', 'warning'=>'exclamation-triangle', 'other'=>'square', @@ -9738,8 +9743,8 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = /** * Add space between dolGetButtonTitle * - * @param string $moreClass more css class label - * @return string html of title separator + * @param string $moreClass more css class label + * @return string html of title separator */ function dolGetButtonTitleSeparator($moreClass = "") { diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 1440a02983f..de4d67b1647 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -350,7 +350,7 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f // Check write permission from module (we need to know write permission to create but also to delete drafts record or to upload files) $createok = 1; $nbko = 0; - $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update'); + $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update') || GETPOST('roworder', 'alpha', 2); $wemustcheckpermissionfordeletedraft = ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete'); if ($wemustcheckpermissionforcreate || $wemustcheckpermissionfordeletedraft) { diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 83251c93499..d094916ef38 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -280,6 +280,11 @@ class CommandeFournisseur extends CommonOrder const STATUS_REFUSED = 9; + /** + * The constant used into source field to track the order was generated by the replenishement feature + */ + const SOURCE_ID_REPLENISHMENT = 42; + /** diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index d32e466444c..fb1891051e6 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -1284,6 +1284,7 @@ if ($resql) { $objectstatic->id = $obj->rowid; $objectstatic->ref = $obj->ref; $objectstatic->ref_supplier = $obj->ref_supplier; + $objectstatic->socid = $obj->socid; $objectstatic->total_ht = $obj->total_ht; $objectstatic->total_tva = $obj->total_tva; $objectstatic->total_ttc = $obj->total_ttc; diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index d91989190e0..72d78178cf1 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -430,6 +430,7 @@ LT1IN=CGST LT2IN=SGST LT1GC=Additionnal cents VATRate=Tax Rate +RateOfTaxN=Rate of tax %s VATCode=Tax Rate code VATNPR=Tax Rate NPR DefaultTaxRate=Default tax rate diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 79c974f6e24..2fda7e1df0e 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -267,9 +267,11 @@ InvoiceToUse=Draft invoice to use NewInvoice=New invoice OneLinePerTask=One line per task OneLinePerPeriod=One line per period +OneLinePerTimeSpentLine=One line for each time spent declaration RefTaskParent=Ref. Parent Task ProfitIsCalculatedWith=Profit is calculated using AddPersonToTask=Add also to tasks UsageOrganizeEvent=Usage: Event Organization PROJECT_CLASSIFY_CLOSED_WHEN_ALL_TASKS_DONE=Classify project as closed when all its tasks are completed (100%% progress) PROJECT_CLASSIFY_CLOSED_WHEN_ALL_TASKS_DONE_help=Note: existing projects with all tasks at 100 %% progress won't be affected: you will have to close them manually. This option only affects open projects. +SelectLinesOfTimeSpentToInvoice=Select lines of time spent that are unbilled, then bulk action "Generate Invoice" to bill them \ No newline at end of file diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index c9a7dd21ccc..7b40647ebcb 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -50,9 +50,33 @@ if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO'])) { } } + +/** + * Return the real char for a numeric entities. + * This function is required by testSqlAndScriptInject(). + * + * @param string $matches String of numeric entity + * @return string New value + */ +function realCharForNumericEntities($matches) +{ + $newstringnumentity = $matches[1]; + + if (preg_match('/^x/i', $newstringnumentity)) { + $newstringnumentity = hexdec(preg_replace('/^x/i', '', $newstringnumentity)); + } + + // The numeric value we don't want as entities + if (($newstringnumentity >= 65 && $newstringnumentity <= 90) || ($newstringnumentity >= 97 && $newstringnumentity <= 122)) { + return chr((int) $newstringnumentity); + } + + return '&#'.$matches[1]; +} + /** * Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF). - * Warning: Such a protection can't be enough. It is not reliable as it will alwyas be possible to bypass this. Good protection can + * Warning: Such a protection can't be enough. It is not reliable as it will always be possible to bypass this. Good protection can * only be guaranted by escaping data during output. * * @param string $val Value brut found int $_GET, $_POST or PHP_SELF @@ -61,7 +85,7 @@ if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO'])) { */ function testSqlAndScriptInject($val, $type) { - // Decode string first bcause a lot of things are obfuscated by encoding or multiple encoding. + // Decode string first because a lot of things are obfuscated by encoding or multiple encoding. // So 0 || !empty($ref)) { $upload_dir = $conf->mymodule->multidir_output[$object->entity ? $object->entity : $conf->entity]."/myobject/".get_exdir(0, 0, 0, 1, $object); } -$permissiontoadd = $user->rights->mymodule->myobject->write; // Used by the include of actions_addupdatedelete.inc.php +$permissiontoadd = $user->rights->mymodule->myobject->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php // Security check (enable the most restrictive one) //if ($user->socid > 0) accessforbidden(); diff --git a/htdocs/product/document.php b/htdocs/product/document.php index af44521dc05..372e3c19bdc 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -113,7 +113,7 @@ if ($reshook < 0) { if (empty($reshook)) { // Delete line if product propal merge is linked to a file if (!empty($conf->global->PRODUIT_PDF_MERGE_PROPAL)) { - if ($action == 'confirm_deletefile' && $confirm == 'yes') { + if ($action == 'confirm_deletefile' && $confirm == 'yes' && $permissiontoadd) { //extract file name $urlfile = GETPOST('urlfile', 'alpha'); $filename = basename($urlfile); @@ -131,7 +131,7 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; } -if ($action == 'filemerge') { +if ($action == 'filemerge' && $permissiontoadd) { $is_refresh = GETPOST('refresh'); if (empty($is_refresh)) { $filetomerge_file_array = GETPOST('filetoadd'); diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 73124fd7bad..5df8e3a7a5f 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -66,7 +66,7 @@ $fourn_id = GETPOST('fourn_id', 'int'); $fk_supplier = GETPOST('fk_supplier', 'int'); $fk_entrepot = GETPOST('fk_entrepot', 'int'); -//List all visible warehouses +// List all visible warehouses $resWar = $db->query("SELECT rowid FROM " . MAIN_DB_PREFIX . "entrepot WHERE entity IN (" . $db->sanitize(getEntity('stock')) .")"); $listofqualifiedwarehousesid = ""; $count = 0; @@ -103,6 +103,7 @@ if (!$sortorder) { $sortorder = 'ASC'; } +// Define virtualdiffersfromphysical $virtualdiffersfromphysical = 0; if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) @@ -224,17 +225,24 @@ if ($action == 'order' && GETPOST('valid')) { $suppliersid = array_keys($suppliers); foreach ($suppliers as $supplier) { $order = new CommandeFournisseur($db); + // Check if an order for the supplier exists $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."commande_fournisseur"; $sql .= " WHERE fk_soc = ".((int) $suppliersid[$i]); - $sql .= " AND source = 42 AND fk_statut = 0"; + $sql .= " AND source = ".((int) $order::SOURCE_ID_REPLENISHMENT)." AND fk_statut = ".$order::STATUS_DRAFT; $sql .= " AND entity IN (".getEntity('commande_fournisseur').")"; $sql .= " ORDER BY date_creation DESC"; $resql = $db->query($sql); if ($resql && $db->num_rows($resql) > 0) { $obj = $db->fetch_object($resql); + $order->fetch($obj->rowid); + $order->fetch_thirdparty(); + foreach ($supplier['lines'] as $line) { + if (empty($line->remise_percent)) { + $line->remise_percent = $order->thirdparty->remise_supplier_percent; + } $result = $order->addline( $line->desc, $line->subprice, @@ -268,13 +276,19 @@ if ($action == 'order' && GETPOST('valid')) { } else { $order->socid = $suppliersid[$i]; $order->fetch_thirdparty(); - //trick to know which orders have been generated this way - $order->source = 42; + + // Trick to know which orders have been generated using the replenishment feature + $order->source = $order::SOURCE_ID_REPLENISHMENT; + foreach ($supplier['lines'] as $line) { + if (empty($line->remise_percent)) { + $line->remise_percent = $order->thirdparty->remise_supplier_percent; + } $order->lines[] = $line; } $order->cond_reglement_id = $order->thirdparty->cond_reglement_supplier_id; $order->mode_reglement_id = $order->thirdparty->mode_reglement_supplier_id; + $id = $order->create($user); if ($id < 0) { $fail++; @@ -325,7 +339,7 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entre } $sql = 'SELECT p.rowid, p.ref, p.label, p.description, p.price,'; -$sql .= ' p.price_ttc, p.price_base_type,p.fk_product_type,'; +$sql .= ' p.price_ttc, p.price_base_type, p.fk_product_type,'; $sql .= ' p.tms as datem, p.duration, p.tobuy,'; $sql .= ' p.desiredstock, p.seuil_stock_alerte,'; if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { @@ -346,11 +360,8 @@ $sql .= $hookmanager->resPrint; $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as s ON p.rowid = s.fk_product AND s.fk_entrepot IN ('.$db->sanitize($listofqualifiedwarehousesid).')'; //$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot AS ent ON s.fk_entrepot = ent.rowid AND ent.entity IN('.getEntity('stock').')'; -if ($fk_supplier > 0) { - $sql .= ' INNER JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price pfp ON (pfp.fk_product = p.rowid AND pfp.fk_soc = '.$fk_supplier.')'; -} if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_warehouse_properties AS pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = '.$fk_entrepot.')'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_warehouse_properties AS pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = '.((int) $fk_entrepot).')'; } // Add fields from hooks @@ -377,9 +388,12 @@ if ($search_label) { $sql .= natural_search('p.label', $search_label); } $sql .= ' AND p.tobuy = 1'; -if (empty($conf->global->VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT)) { // Add test to exclude products that has variants +if (!empty($conf->variants->eabled) && empty($conf->global->VARIANT_ALLOW_STOCK_MOVEMENT_ON_VARIANT_PARENT)) { // Add test to exclude products that has variants $sql .= ' AND p.rowid NOT IN (SELECT pac.fk_product_parent FROM '.MAIN_DB_PREFIX.'product_attribute_combination as pac WHERE pac.entity IN ('.getEntity('product').'))'; } +if ($fk_supplier > 0) { + $sql .= ' AND EXISTS (SELECT pfp.rowid FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp WHERE pfp.fk_product = p.rowid AND pfp.fk_soc = '.((int) $fk_supplier).' AND pfp.entity IN ('.getEntity('product_fournisseur_price').'))'; +} $sql .= ' GROUP BY p.rowid, p.ref, p.label, p.description, p.price'; $sql .= ', p.price_ttc, p.price_base_type,p.fk_product_type, p.tms'; $sql .= ', p.duration, p.tobuy'; @@ -891,7 +905,9 @@ while ($i < ($limit ? min($num, $limit) : $num)) { print ''.($fk_entrepot > 0 ? $alertstockwarehouse : $alertstock).''; // Current stock (all warehouses) - print ''.$warning.$stock.''; + print ''.$warning.$stock; + print ''; + print ''; // Current stock (warehouse selected only) if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) { diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 0f84313b75a..0b8e21f5afd 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -1351,9 +1351,9 @@ class Task extends CommonObject } /** - * Load one record of time spent + * Load properties of timespent of a task from the time spent ID. * - * @param int $id Id object + * @param int $id Id in time spent table * @return int <0 if KO, >0 if OK */ public function fetchTimeSpent($id) diff --git a/htdocs/projet/document.php b/htdocs/projet/document.php index 3f9ec04d437..6bb905d6696 100644 --- a/htdocs/projet/document.php +++ b/htdocs/projet/document.php @@ -40,11 +40,6 @@ $ref = GETPOST('ref', 'alpha'); $mine = (GETPOST('mode', 'alpha') == 'mine' ? 1 : 0); //if (! $user->rights->projet->all->lire) $mine=1; // Special for projects -// Security check -$socid = 0; -//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. -$result = restrictedArea($user, 'projet', $id, 'projet&project'); - $object = new Project($db); include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once @@ -82,6 +77,11 @@ if (!$sortfield) { $sortfield = "name"; } +// Security check +$socid = 0; +//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. +$result = restrictedArea($user, 'projet', $id, 'projet&project'); + /* diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index a9f17f5439b..aa1229ccb42 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -297,7 +297,7 @@ if (empty($reshook)) { * View */ -$socstatic = new Societe($db); +$companystatic = new Societe($db); $form = new Form($db); $formother = new FormOther($db); $formproject = new FormProjets($db); @@ -330,12 +330,13 @@ if (count($listofprojectcontacttype) == 0) { } $distinct = 'DISTINCT'; // We add distinct until we are added a protection to be sure a contact of a project and task is only once. -$sql = "SELECT ".$distinct." p.rowid as id, p.ref, p.title, p.fk_statut as status, p.fk_opp_status, p.public, p.fk_user_creat"; -$sql .= ", p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.opp_percent, (p.opp_amount*p.opp_percent/100) as opp_weighted_amount, p.tms as date_update, p.budget_amount "; -$sql .= ", p.usage_opportunity, p.usage_task, p.usage_bill_time, p.usage_organize_event"; -$sql .= ", accept_conference_suggestions, accept_booth_suggestions, price_registration, price_booth"; -$sql .= ", s.rowid as socid, s.nom as name, s.email"; -$sql .= ", cls.code as opp_status_code"; +$sql = "SELECT ".$distinct." p.rowid as id, p.ref, p.title, p.fk_statut as status, p.fk_opp_status, p.public, p.fk_user_creat,"; +$sql .= " p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.opp_percent, (p.opp_amount*p.opp_percent/100) as opp_weighted_amount, p.tms as date_update, p.budget_amount,"; +$sql .= " p.usage_opportunity, p.usage_task, p.usage_bill_time, p.usage_organize_event,"; +$sql .= " accept_conference_suggestions, accept_booth_suggestions, price_registration, price_booth,"; +$sql .= " s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client,"; +$sql .= " country.code as country_code,"; +$sql .= " cls.code as opp_status_code"; // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { @@ -355,6 +356,7 @@ if (is_array($extrafields->attributes[$object->table_element]['label']) && count $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (p.rowid = ef.fk_object)"; } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_lead_status as cls on p.fk_opp_status = cls.rowid"; // We'll need this table joined to the select in order to filter by sale // No check is done on company permission because readability is managed by public status of project and assignement. @@ -978,9 +980,17 @@ while ($i < min($num, $limit)) { $userAccess = $object->restrictedProjectArea($user); // why this ? if ($userAccess >= 0) { - $socstatic->id = $obj->socid; - $socstatic->name = $obj->name; - $socstatic->email = $obj->email; + $companystatic->id = $obj->socid; + $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; + $companystatic->client = $obj->client; + $companystatic->code_client = $obj->code_client; + $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; print '
    '; @@ -1009,7 +1019,7 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['s.nom']['checked'])) { print ''; if ($obj->socid) { - print $socstatic->getNomUrl(1); + print $companystatic->getNomUrl(1); } else { print ' '; } @@ -1022,9 +1032,9 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['commercial']['checked'])) { print ''; if ($obj->socid) { - $socstatic->id = $obj->socid; - $socstatic->name = $obj->name; - $listsalesrepresentatives = $socstatic->getSalesRepresentatives($user); + $companystatic->id = $obj->socid; + $companystatic->name = $obj->name; + $listsalesrepresentatives = $companystatic->getSalesRepresentatives($user); $nbofsalesrepresentative = count($listsalesrepresentatives); if ($nbofsalesrepresentative > 6) { // We print only number @@ -1041,7 +1051,9 @@ while ($i < min($num, $limit)) { $userstatic->entity = $val['entity']; $userstatic->photo = $val['photo']; $userstatic->login = $val['login']; - $userstatic->phone = $val['phone']; + $userstatic->office_phone = $val['office_phone']; + $userstatic->office_fax = $val['office_fax']; + $userstatic->user_mobile = $val['user_mobile']; $userstatic->job = $val['job']; $userstatic->gender = $val['gender']; print ($nbofsalesrepresentative < 2) ? $userstatic->getNomUrl(-1, '', 0, 0, 12) : $userstatic->getNomUrl(-2); diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 8cac9adfd05..01622a41945 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -192,10 +192,10 @@ if ($action == 'addtimespent' && $user->rights->projet->lire) { $object->timespent_duration = GETPOSTINT("timespent_durationhour") * 60 * 60; // We store duration in seconds $object->timespent_duration += (GETPOSTINT('timespent_durationmin') ? GETPOSTINT('timespent_durationmin') : 0) * 60; // We store duration in seconds if (GETPOST("timehour") != '' && GETPOST("timehour") >= 0) { // If hour was entered - $object->timespent_date = dol_mktime(GETPOST("timehour"), GETPOST("timemin"), 0, GETPOST("timemonth"), GETPOST("timeday"), GETPOST("timeyear")); + $object->timespent_date = dol_mktime(GETPOST("timehour", 'int'), GETPOST("timemin", 'int'), 0, GETPOST("timemonth", 'int'), GETPOST("timeday", 'int'), GETPOST("timeyear", 'int')); $object->timespent_withhour = 1; } else { - $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timemonth"), GETPOST("timeday"), GETPOST("timeyear")); + $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timemonth", 'int'), GETPOST("timeday", 'int'), GETPOST("timeyear", 'int')); } $object->timespent_fk_user = GETPOST("userid", 'int'); $result = $object->addTimeSpent($user); @@ -402,7 +402,7 @@ if ($action == 'confirm_generateinvoice') { if (!$error) { if ($generateinvoicemode == 'onelineperuser') { - $arrayoftasks = array(); + $arrayoftasks = array(); foreach ($toselect as $key => $value) { // Get userid, timepent $object->fetchTimeSpent($value); @@ -437,22 +437,27 @@ if ($action == 'confirm_generateinvoice') { break; } } - } elseif ($generateinvoicemode == 'onelineperperiod') { - $arrayoftasks = array(); + } elseif ($generateinvoicemode == 'onelineperperiod') { // One line for each time spent line + $arrayoftasks = array(); foreach ($toselect as $key => $value) { // Get userid, timepent $object->fetchTimeSpent($value); + // $object->id is the task id + $ftask = new Task($db); + $ftask->fetch($object->id); + + $fuser->fetch($object->timespent_fk_user); + $username = $fuser->getFullName($langs); + $arrayoftasks[$object->timespent_id]['timespent'] = $object->timespent_duration; $arrayoftasks[$object->timespent_id]['totalvaluetodivideby3600'] = $object->timespent_duration * $object->timespent_thm; - $arrayoftasks[$object->timespent_id]['note'] = $object->timespent_note; + $arrayoftasks[$object->timespent_id]['note'] = $ftask->ref.' - '.$ftask->label.' - '.$username.($object->timespent_note ? ' - '.$object->timespent_note : ''); // TODO Add user name in note $arrayoftasks[$object->timespent_id]['user'] = $object->timespent_fk_user; } foreach ($arrayoftasks as $timespent_id => $value) { $userid = $value['user']; - $fuser->fetch($userid); //$pu_ht = $value['timespent'] * $fuser->thm; - $username = $fuser->getFullName($langs); // Define qty per hour $qtyhour = $value['timespent'] / 3600; @@ -465,6 +470,7 @@ if ($action == 'confirm_generateinvoice') { // Add lines $lineid = $tmpinvoice->addline($value['note'], $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); + //var_dump($lineid);exit; // Update lineid into line of timespent $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id); @@ -477,7 +483,7 @@ if ($action == 'confirm_generateinvoice') { } } } elseif ($generateinvoicemode == 'onelinepertask') { - $arrayoftasks = array(); + $arrayoftasks = array(); foreach ($toselect as $key => $value) { // Get userid, timepent $object->fetchTimeSpent($value); @@ -517,7 +523,10 @@ if ($action == 'confirm_generateinvoice') { if (!$error) { $urltoinvoice = $tmpinvoice->getNomUrl(0); - setEventMessages($langs->trans("InvoiceGeneratedFromTimeSpent", $urltoinvoice), null, 'mesgs'); + $mesg = $langs->trans("InvoiceGeneratedFromTimeSpent", '{s1}'); + $mesg = str_replace('{s1}', $urltoinvoice, $mesg); + setEventMessages($mesg, null, 'mesgs'); + //var_dump($tmpinvoice); $db->commit(); @@ -969,7 +978,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { $tmparray = array( 'onelineperuser'=>'OneLinePerUser', 'onelinepertask'=>'OneLinePerTask', - 'onelineperperiod'=>'OneLinePerPeriod', + 'onelineperperiod'=>'OneLinePerTimeSpentLine', ); print $form->selectarray('generateinvoicemode', $tmparray, 'onelineperuser', 0, 0, 0, '', 1); print ''; @@ -1315,7 +1324,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { print_liste_field_titre($arrayfields['value']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'right '); } if (!empty($arrayfields['valuebilled']['checked'])) { - print_liste_field_titre($arrayfields['valuebilled']['label'], $_SERVER['PHP_SELF'], 'il.total_ht', '', $param, '', $sortfield, $sortorder, 'center '); + print_liste_field_titre($arrayfields['valuebilled']['label'], $_SERVER['PHP_SELF'], 'il.total_ht', '', $param, '', $sortfield, $sortorder, 'center ', $langs->trans("SelectLinesOfTimeSpentToInvoice")); } /* // Extra fields diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 8e2188123db..aff3e4cce92 100755 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -359,7 +359,9 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->salaries- * View */ -llxHeader("", $langs->trans("Salary")); +$title = $langs->trans('Salary')." - ".$langs->trans('Card'); +$help_url = ""; +llxHeader("", $title, $help_url); $form = new Form($db); if (!empty($conf->projet->enabled)) $formproject = new FormProjets($db); diff --git a/htdocs/salaries/document.php b/htdocs/salaries/document.php index 4c88cefb8de..5950fc88798 100644 --- a/htdocs/salaries/document.php +++ b/htdocs/salaries/document.php @@ -91,7 +91,9 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; $form = new Form($db); -llxHeader("", $langs->trans("SalaryPayment")); +$title = $langs->trans('Salary')." - ".$langs->trans('Documents'); +$help_url = ""; +llxHeader("", $title, $help_url); if ($object->id) { $object->fetch_thirdparty(); diff --git a/htdocs/salaries/info.php b/htdocs/salaries/info.php index 1b81a80189f..0f94f405fa1 100644 --- a/htdocs/salaries/info.php +++ b/htdocs/salaries/info.php @@ -53,7 +53,9 @@ restrictedArea($user, 'salaries', $object->id, 'salary', ''); * View */ -llxHeader("", $langs->trans("SalaryPayment")); +$title = $langs->trans('Salary')." - ".$langs->trans('Info'); +$help_url = ""; +llxHeader("", $title, $help_url); $object = new Salary($db); $object->fetch($id); diff --git a/htdocs/societe/document.php b/htdocs/societe/document.php index 4ed26f67018..653069882e0 100644 --- a/htdocs/societe/document.php +++ b/htdocs/societe/document.php @@ -76,6 +76,7 @@ if ($id > 0 || !empty($ref)) { // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('thirdpartydocument', 'globalcard')); +$permissiontoadd = $user->rights->societe->creer; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php // Security check if ($user->socid > 0) { diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 3518518a5ef..27a889293f1 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -4929,8 +4929,8 @@ td.cal_other_month { /* ============================================================================== */ /* CSS for treeview */ -.treeview ul { background-color: transparent !important; margin-bottom: 4px !important; margin-top: 0 !important; padding-top: 4px !important; } -.treeview li { background-color: transparent !important; padding: 0 0 0 16px !important; min-height: 26px; } +.treeview ul { background-color: transparent !important; margin-bottom: 4px !important; margin-top: 0 !important; padding-top: 8px !important; } +.treeview li { background-color: transparent !important; padding: 0 0 0 16px !important; min-height: 30px; } .treeview .hover { color: var(--colortextlink) !important; text-decoration: underline !important; } .treeview .hitarea { margin-top: 3px; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 70a2ce1303e..0089248288a 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -4849,9 +4849,10 @@ td.gtaskname { /* ============================================================================== */ /* CSS for treeview */ -.treeview ul { background-color: transparent !important; margin-top: 0; } -.treeview li { background-color: transparent !important; padding: 0 0 0 16px !important; min-height: 20px; } -.treeview .hover { color: rgb() !important; text-decoration: underline !important; } +.treeview ul { background-color: transparent !important; margin-bottom: 4px !important; margin-top: 0 !important; padding-top: 8px !important; } +.treeview li { background-color: transparent !important; padding: 0 0 0 16px !important; min-height: 30px; } +.treeview .hover { color: var(--colortextlink) !important; text-decoration: underline !important; } +.treeview .hitarea { margin-top: 3px; } diff --git a/htdocs/ticket/agenda.php b/htdocs/ticket/agenda.php index 9bf6cbc13c4..fee91e959aa 100644 --- a/htdocs/ticket/agenda.php +++ b/htdocs/ticket/agenda.php @@ -81,12 +81,9 @@ if (!$action) { // Security check $id = GETPOST("id", 'int'); $socid = 0; -//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. +if ($user->socid > 0) $socid = $user->socid; $result = restrictedArea($user, 'ticket', $id, ''); -if (!$user->rights->ticket->read) { - accessforbidden(); -} // restrict access for externals users if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { accessforbidden(); diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index e04e3c51ce3..5e2ef1e804b 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -112,8 +112,8 @@ if ($id || $track_id || $ref) { $url_page_current = DOL_URL_ROOT.'/ticket/card.php'; // Security check - Protection if external user -//if ($user->socid > 0) accessforbidden(); -//if ($user->socid > 0) $socid = $user->socid; +$socid = 0; +if ($user->socid > 0) $socid = $user->socid; $result = restrictedArea($user, 'ticket', $object->id); $triggermodname = 'TICKET_MODIFY'; @@ -1320,15 +1320,28 @@ if ($action == 'create' || $action == 'presend') { // add a message if ($action == 'presend' || $action == 'presend_addmessage') { + if ($object->fk_soc > 0) { + $object->fetch_thirdparty(); + } + + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); + } + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($object->thirdparty)) { + $newlang = $object->thirdparty->default_lang; + } + $arrayoffamiliestoexclude = array('objectamount'); + $action = 'add_message'; // action to use to post the message $modelmail = 'ticket_send'; // Substitution array $morehtmlright = ''; $help = ""; - $substitutionarray = array(); + $substitutionarray = getCommonSubstitutionArray($newlang, 0, $arrayoffamiliestoexclude, $object); if ($object->fk_soc > 0) { - $object->fetch_thirdparty(); $substitutionarray['__THIRDPARTY_NAME__'] = $object->thirdparty->name; } $substitutionarray['__USER_SIGNATURE__'] = $user->signature; @@ -1361,16 +1374,6 @@ if ($action == 'create' || $action == 'presend') { print '

    '; - // Define output language - $outputlangs = $langs; - $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { - $newlang = GETPOST('lang_id', 'aZ09'); - } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { - $newlang = $object->default_lang; - } - $formticket = new FormTicket($db); $formticket->action = $action; diff --git a/htdocs/ticket/contact.php b/htdocs/ticket/contact.php index 7e04dd12104..8d450ffb44b 100644 --- a/htdocs/ticket/contact.php +++ b/htdocs/ticket/contact.php @@ -50,11 +50,6 @@ $source = GETPOST('source', 'alpha'); $ligne = GETPOST('ligne', 'int'); $lineid = GETPOST('lineid', 'int'); -// Protection if external user -if ($user->socid > 0) { - $socid = $user->socid; - accessforbidden(); -} // Store current page url $url_page_current = dol_buildpath('/ticket/contact.php', 1); @@ -62,6 +57,24 @@ $url_page_current = dol_buildpath('/ticket/contact.php', 1); $object = new Ticket($db); +$permissiontoadd = $user->rights->ticket->write; + +// Security check +$id = GETPOST("id", 'int'); +$socid = 0; +if ($user->socid > 0) $socid = $user->socid; +$result = restrictedArea($user, 'ticket', $object->id, ''); + +// restrict access for externals users +if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { + accessforbidden(); +} +// or for unauthorized internals users +if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { + accessforbidden(); +} + + /* * Actions */ diff --git a/htdocs/ticket/document.php b/htdocs/ticket/document.php index 5e4d80cd8be..8edd2787c44 100644 --- a/htdocs/ticket/document.php +++ b/htdocs/ticket/document.php @@ -43,11 +43,6 @@ $track_id = GETPOST('track_id', 'alpha'); $action = GETPOST('action', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); -// Security check -if (!$user->rights->ticket->read) { - accessforbidden(); -} - // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST("sortfield", 'alpha'); @@ -75,6 +70,21 @@ if ($result < 0) { $upload_dir = $conf->ticket->dir_output."/".dol_sanitizeFileName($object->ref); } +$permissiontoadd = $user->rights->ticket->write; + +// Security check - Protection if external user +$result = restrictedArea($user, 'ticket', $object->id); + +// restrict access for externals users +if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { + accessforbidden(); +} +// or for unauthorized internals users +if (!$user->socid && ($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { + accessforbidden(); +} + + /* * Actions diff --git a/htdocs/ticket/messaging.php b/htdocs/ticket/messaging.php index c3e70def7da..68615424abf 100644 --- a/htdocs/ticket/messaging.php +++ b/htdocs/ticket/messaging.php @@ -76,16 +76,14 @@ if (!$action) { $action = 'view'; } +$permissiontoadd = $user->rights->ticket->write; // Security check $id = GETPOST("id", 'int'); $socid = 0; -//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. -$result = restrictedArea($user, 'ticket', $id, ''); +if ($user->socid > 0) $socid = $user->socid; +$result = restrictedArea($user, 'ticket', $object->id, ''); -if (!$user->rights->ticket->read) { - accessforbidden(); -} // restrict access for externals users if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { accessforbidden(); @@ -96,7 +94,6 @@ if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && } - /* * Actions */ diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index f5f0b73a70f..e760997f3c8 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -21,6 +21,7 @@ use Luracast\Restler\RestException; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php'; + /** * API class for users * @@ -47,6 +48,7 @@ class Users extends DolibarrApi public function __construct() { global $db, $conf; + $this->db = $db; $this->useraccount = new User($this->db); } @@ -62,15 +64,15 @@ class Users extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @param string $user_ids User ids filter field. Example: '1' or '1,2,3' {@pattern /^[0-9,]*$/i} - * @param int $category Use this param to filter list by category + * @param int $category Use this param to filter list by category * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" * @return array Array of User objects */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $user_ids = 0, $category = 0, $sqlfilters = '') { - global $db, $conf; + global $conf; - if (!DolibarrApiAccess::$user->rights->user->user->lire) { + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "You are not allowed to read list of users"); } @@ -149,7 +151,7 @@ class Users extends DolibarrApi */ public function get($id, $includepermissions = 0) { - if (empty(DolibarrApiAccess::$user->rights->user->user->lire)) { + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, 'Not allowed'); } @@ -187,7 +189,7 @@ class Users extends DolibarrApi */ public function getByLogin($login, $includepermissions = 0) { - if (empty(DolibarrApiAccess::$user->rights->user->user->lire)) { + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, 'Not allowed'); } @@ -221,7 +223,7 @@ class Users extends DolibarrApi */ public function getByEmail($email, $includepermissions = 0) { - if (empty(DolibarrApiAccess::$user->rights->user->user->lire)) { + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, 'Not allowed'); } @@ -254,7 +256,7 @@ class Users extends DolibarrApi */ public function getInfo($includepermissions = 0) { - if (empty(DolibarrApiAccess::$user->rights->user->user->lire)) { + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, 'Not allowed'); } @@ -295,7 +297,7 @@ class Users extends DolibarrApi public function post($request_data = null) { // Check user authorization - if (empty(DolibarrApiAccess::$user->rights->user->user->creer)) { + if (empty(DolibarrApiAccess::$user->rights->user->creer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "User creation not allowed for login ".DolibarrApiAccess::$user->login); } @@ -345,7 +347,7 @@ class Users extends DolibarrApi public function put($id, $request_data = null) { // Check user authorization - if (empty(DolibarrApiAccess::$user->rights->user->creer)) { + if (empty(DolibarrApiAccess::$user->rights->user->user->creer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "User update not allowed"); } @@ -423,7 +425,7 @@ class Users extends DolibarrApi */ public function getGroups($id) { - if (!DolibarrApiAccess::$user->rights->user->user->lire) { + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(403); } @@ -463,7 +465,7 @@ class Users extends DolibarrApi { global $conf; - if (empty(DolibarrApiAccess::$user->rights->user->user->creer)) { + if (empty(DolibarrApiAccess::$user->rights->user->user->creer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401); } @@ -512,12 +514,12 @@ class Users extends DolibarrApi */ public function listGroups($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $group_ids = 0, $sqlfilters = '') { - global $db, $conf; + global $conf; $obj_ret = array(); - if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire)) || - !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read)) { + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) || + !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "You are not allowed to read groups"); } @@ -590,8 +592,8 @@ class Users extends DolibarrApi { global $db, $conf; - if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire)) || - !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read)) { + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) || + !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "You are not allowed to read groups"); } @@ -616,7 +618,7 @@ class Users extends DolibarrApi */ public function delete($id) { - if (empty(DolibarrApiAccess::$user->rights->user->user->supprimer)) { + if (empty(DolibarrApiAccess::$user->rights->user->user->supprimer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, 'Not allowed'); } $result = $this->useraccount->fetch($id); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 891c71867eb..981374996cf 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2411,8 +2411,18 @@ class User extends CommonObject $label .= '
    '.$langs->trans("Job").': '.dol_string_nohtmltag($this->job); } $label .= '
    '.$langs->trans("Email").': '.dol_string_nohtmltag($this->email); - if (!empty($this->phone)) { - $label .= '
    '.$langs->trans("Phone").': '.dol_string_nohtmltag($this->phone); + if (!empty($this->office_phone) || !empty($this->office_fax) || !empty($this->fax)) { + $phonelist = array(); + if ($this->office_phone) { + $phonelist[] = dol_print_phone($this->office_phone, $this->country_code, $this->id, 0, '', ' ', 'phone'); + } + if ($this->office_fax) { + $phonelist[] = dol_print_phone($this->office_fax, $this->country_code, $this->id, 0, '', ' ', 'fax'); + } + if ($this->user_mobile) { + $phonelist[] = dol_print_phone($this->user_mobile, $this->country_code, $this->id, 0, '', ' ', 'mobile'); + } + $label .= '
    '.$langs->trans('Phone').': '.implode(' ', $phonelist); } if (!empty($this->admin)) { $label .= '
    '.$langs->trans("Administrator").': '.yn($this->admin); diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 5c5274c0437..bd4d0e9b76d 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -198,20 +198,29 @@ class SecurityTest extends PHPUnit\Framework\TestCase $result=testSqlAndScriptInject($test, 0); $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject expected 0b'); - // Should detect XSS + + // Should detect attack $expectedresult=1; $_SERVER["PHP_SELF"]='/DIR WITH SPACE/htdocs/admin/index.php/'; $result=testSqlAndScriptInject($_SERVER["PHP_SELF"], 2); $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject for PHP_SELF that should detect XSS'); + $test = 'javascript:'; + $result=testSqlAndScriptInject($test, 0); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject for javascript1. Should find an attack and did not.'); + + $test = 'javascript:'; + $result=testSqlAndScriptInject($test, 0); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject for javascript2. Should find an attack and did not.'); + $test = 'javascript&colon;alert(1)'; $result=testSqlAndScriptInject($test, 0); - $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject expected 1a'); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject for javascript2'); $test=""; $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa'); + $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa1'); $test=""; $result=testSqlAndScriptInject($test, 2); @@ -328,9 +337,12 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST["param10"]='is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : \'objnotdefined\''; $_POST["param11"]=' Name '; $_POST["param12"]='aaa'; + $_POST["param13"]='n n > < " XSS'; + $_POST["param13b"]='n n > < " XSS'; //$_POST["param13"]='javascript%26colon%26%23x3B%3Balert(1)'; //$_POST["param14"]='javascripT&javascript#x3a alert(1)'; + $result=GETPOST('id', 'int'); // Must return nothing print __METHOD__." result=".$result."\n"; $this->assertEquals($result, ''); @@ -343,7 +355,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($result, 333, 'Test on param1 with 3rd param = 2'); - // Test alpha + // Test with alpha $result=GETPOST("param2", 'alpha'); print __METHOD__." result=".$result."\n"; @@ -357,7 +369,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($result, 'dir'); - // Test aZ09 + // Test with aZ09 $result=GETPOST("param1", 'aZ09'); print __METHOD__." result=".$result."\n"; @@ -379,25 +391,22 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($_GET["param5"], $result); - $result=GETPOST("param6", 'alpha'); - print __METHOD__." result=".$result."\n"; - $this->assertEquals('>', $result); + // Test with nohtml $result=GETPOST("param6", 'nohtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals('">', $result); - $result=GETPOST("param6b"); + // Test with alpha = alphanohtml. We must convert the html entities like n and disable all entities + + $result=GETPOST("param6", 'alphanohtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('>', $result); + + $result=GETPOST("param6b", 'alphanohtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals('abc', $result); - // With restricthtml we must remove html open/close tag and content but not htmlentities like n - - $result=GETPOST("param7", 'restricthtml'); - print __METHOD__." result=".$result."\n"; - $this->assertEquals('"c:\this is a path~1\aaan" abcdef', $result); - - // With alphanohtml, we must convert the html entities like n and disable all entities $result=GETPOST("param8a", 'alphanohtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals("Hackersvg onload='console.log(123)'", $result); @@ -434,24 +443,39 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals("Name", $result, 'Test an email string with alphanohtml'); + $result=GETPOST("param13", 'alphanohtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('n n > < XSS', $result, 'Test that html entities are decoded with alpha'); + + // Test with alphawithlgt + $result=GETPOST("param11", 'alphawithlgt'); print __METHOD__." result=".$result."\n"; $this->assertEquals(trim($_POST["param11"]), $result, 'Test an email string with alphawithlgt'); + // Test with restricthtml we must remove html open/close tag and content but not htmlentities (we can decode html entities for ascii chars like n) + + $result=GETPOST("param6", 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('">', $result); + + $result=GETPOST("param7", 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('"c:\this is a path~1\aaan" abcdef', $result); + $result=GETPOST("param12", 'restricthtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals(trim($_POST["param12"]), $result, 'Test a string with DOCTYPE and restricthtml'); - /*$result=GETPOST("param13", 'alphanohtml'); + $result=GETPOST("param13", 'restricthtml'); print __METHOD__." result=".$result."\n"; - $this->assertEquals(trim($_POST["param13"]), $result, 'Test a string and alphanohtml'); + $this->assertEquals('n n > < " XSS', $result, 'Test that HTML entities are decoded with restricthtml, but only for common alpha chars'); - $result=GETPOST("param14", 'alphanohtml'); + $result=GETPOST("param13b", 'restricthtml'); print __METHOD__." result=".$result."\n"; - $this->assertEquals(trim($_POST["param14"]), $result, 'Test a string and alphanohtml'); - */ + $this->assertEquals('n n > < " XSS', $result, 'Test that HTML entities are decoded with restricthtml, but only for common alpha chars'); - // Special test for GETPOST of backtopage or backtolist parameter + // Special test for GETPOST of backtopage, backtolist or backtourl parameter $_POST["backtopage"]='//www.google.com'; $result=GETPOST("backtopage");