dolibarr 25.0.0-alpha
users.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
25if (!defined('NOTOKENRENEWAL')) {
26 define('NOTOKENRENEWAL', 1); // Disables token renewal
27}
28if (!defined('NOREQUIREMENU')) {
29 define('NOREQUIREMENU', '1');
30}
31if (!defined('NOREQUIREHTML')) {
32 define('NOREQUIREHTML', '1');
33}
34if (!defined('NOREQUIREAJAX')) {
35 define('NOREQUIREAJAX', '1');
36}
37if (!defined('NOREQUIRESOC')) {
38 define('NOREQUIRESOC', '1');
39}
40
41// Load Dolibarr environment
42require '../../main.inc.php';
50require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
51
52$htmlname = (string) GETPOST('htmlname', 'aZ09');
53$outjson = (GETPOSTINT('outjson') ? GETPOSTINT('outjson') : 0);
54$excludeids = GETPOST('exclude', 'intcomma');
55$include = GETPOST('include', 'alphanohtml');
56$forceentity = GETPOST('force_entity', 'alphanohtml');
57$showstatus = GETPOSTINT('showstatus');
58$notdisabled = GETPOSTINT('notdisabled');
59$maxlength = GETPOSTINT('maxlength');
60// select_dolusers()'s $morefilter is a raw Universal Search Filter forwarded to
61// forgeSQLFromUniversalSearchCriteria(); an unchecked value from the client would let any logged-in
62// user run arbitrary WHERE clauses on llx_user. So we only accept it when it exactly matches one of
63// the known-safe expressions of Form::$user_combo_allowed_morefilters (the same list select_dolusers()
64// uses to decide whether to put it in the URL) and reject anything else.
65$morefilter = (string) GETPOST('morefilter', 'nohtml');
66if ($morefilter !== '' && !Form::isUserComboMorefilterAllowed($morefilter)) {
67 httponly_accessforbidden('Call of user/ajax/users.php with a morefilter not in the allow-list', 400);
68}
69
70// Security check: a logged-in internal user is enough (select_dolusers() itself is not permission gated
71// on purpose, so any internal user allowed to open a form with a "assigned to" field can search the list).
72if (empty($user->id)) {
73 httponly_accessforbidden('Not logged', 403);
74}
75// External users (portal contacts, $user->socid > 0) have no legitimate use case for browsing the
76// internal user directory, but the combo may still appear on a screen they can reach. Instead of a
77// hard 403 that would break such a form, restrict every result to their own user record (see below).
78$restricttoself = ($user->socid > 0);
79
80/*
81 * View
82 */
83
84top_httphead('application/json');
85
86if ($htmlname === '') {
87 print json_encode(array());
88 $db->close();
89 return;
90}
91
92$minlength = getDolGlobalInt('USER_USE_SEARCH_TO_SELECT');
93
94// The typed term is sent by jQuery UI as a GET param named like $htmlname.
95$searchkey = (string) GETPOST($htmlname, 'alphanohtml');
96if ($searchkey === '' && $minlength >= 1) {
97 // Not in "infinite list" mode (USER_USE_SEARCH_TO_SELECT is not numeric): an empty term returns nothing.
98 print json_encode(array());
99 $db->close();
100 return;
101}
102
103// Anti-DoS protection: require at least USER_USE_SEARCH_TO_SELECT chars (no minimum in "infinite list" mode).
104if ($minlength >= 1 && dol_strlen($searchkey) < $minlength) {
105 httponly_accessforbidden('Call of user/ajax/users.php with a too short search string', 400);
106}
107
108$exclude = null;
109if ($excludeids !== '') {
110 $exclude = array_map('intval', explode(',', $excludeids));
111}
112
113// $include is either 'hierarchy', 'hierarchyme' or a comma separated list of user ids
114if ($include !== '' && $include !== 'hierarchy' && $include !== 'hierarchyme') {
115 $include = array_map('intval', explode(',', $include));
116}
117
118// An external user can only ever see themselves, whatever the caller asked for.
119if ($restricttoself) {
120 $include = array($user->id);
121 $exclude = null;
122}
123
124$form = new Form($db);
125
126// Cap the number of rows (mostly useful in "infinite list" mode where the term can be empty)
127$limit = getDolGlobalInt('USER_LIMIT_SIZE', 20);
128// select2 pages the list with a 1-based 'page' param: return the matching slice so the dropdown
129// stays scrollable through the whole directory.
130$page = GETPOSTINT('page');
131$limitoffset = ($page > 1) ? ($page - 1) * $limit : 0;
132
133$arrayresult = $form->select_dolusers('', $htmlname, 0, $exclude, 0, $include, '', $forceentity, $maxlength, $showstatus, $morefilter, 0, '', '', $notdisabled, 2, false, 0, $searchkey, $limit, $limitoffset);
134
135$outarray = array();
136if (is_array($arrayresult)) {
137 foreach ($arrayresult as $id => $val) {
138 if ((int) $id <= 0) {
139 continue;
140 }
141 // Keep the dropdown a plain single line (like the thirdparty autocomplete). We deliberately do not send
142 // 'labelhtml' here: select_dolusers() builds it with getNomUrl() which renders a block photo thumbnail
143 // and would break the layout of the jQuery UI autocomplete list.
144 $label = dol_string_nohtmltag($val['label']);
145 $outarray[] = array(
146 'key' => (int) $id,
147 'value' => $label,
148 'label' => $label,
149 );
150 }
151}
152
153print json_encode($outarray);
154
155$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
Class to manage generation of HTML components Only common components must be here.
static isUserComboMorefilterAllowed($morefilter)
Tell whether a $morefilter value is allowed to be forwarded to the user/ajax/users....
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.