dolibarr 24.0.0-beta
oauth.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2015-2024 Frédéric France <frederic.france@free.fr>
3 * Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
4 * Copyright (C) 2022 Laurent Destailleur <eldy@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
27// Load Dolibarr environment
28require '../main.inc.php';
29require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
30require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php';
31
42$supportedoauth2array = getSupportedOauth2Array();
43
44// Define $urlwithroot
45$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
46$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
47//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
48
49// Load translation files required by the page
50$langs->loadLangs(array('admin', 'oauth', 'modulebuilder'));
51
52// Security check
53if (!$user->admin) {
55}
56
57$action = GETPOST('action', 'aZ09');
58$provider = GETPOST('provider', 'aZ09');
59$label = GETPOST('label', 'aZ09');
60
61$servicetoeditname = GETPOST('servicetoeditname', 'aZ09');
62
63$error = 0;
64
65
66/*
67 * Actions
68 */
69
70if ($action == 'add') { // $provider is OAUTH_XXX
71 if ($provider && $provider != '-1') {
72 $constname = strtoupper($provider).($label ? '-'.$label : '').'_ID';
73
74 if (getDolGlobalString($constname)) {
75 setEventMessages($langs->trans("AOAuthEntryForThisProviderAndLabelAlreadyHasAKey"), null, 'errors');
76 $error++;
77 } else {
78 dolibarr_set_const($db, $constname, $langs->trans('ToComplete'), 'chaine', 0, '', $conf->entity);
79 setEventMessages($langs->trans("OAuthProviderAdded"), null);
80 }
81 }
82}
83if ($action == 'update') {
84 foreach ($conf->global as $key => $val) {
85 if (!empty($val) && preg_match('/^OAUTH_.+_ID$/', $key)) {
86 $constvalue = str_replace('_ID', '', $key);
87 $newconstvalue = $constvalue;
88 if (GETPOSTISSET($constvalue.'_NAME')) {
89 $newconstvalue = preg_replace('/-.*$/', '', $constvalue).'-'.preg_replace('/[^a-z]/', '', GETPOST($constvalue.'_NAME'));
90 }
91
92 if (GETPOSTISSET($constvalue.'_ID')) {
93 if (!dolibarr_set_const($db, $newconstvalue.'_ID', GETPOST($constvalue.'_ID'), 'chaine', 0, '', $conf->entity)) {
94 $error++;
95 }
96 }
97 // If we reset this provider, we also remove the secret
98 if (GETPOSTISSET($constvalue.'_SECRET')) {
99 if (!dolibarr_set_const($db, $newconstvalue.'_SECRET', GETPOST($constvalue.'_ID') ? GETPOST($constvalue.'_SECRET') : '', 'chaine', 0, '', $conf->entity)) {
100 $error++;
101 }
102 }
103 if (GETPOSTISSET($constvalue.'_URL')) {
104 $cleanurl = GETPOST($constvalue.'_URL');
105 $cleanurl = preg_replace('/\/$/', '', $cleanurl);
106 if (!dolibarr_set_const($db, $newconstvalue.'_URL', $cleanurl, 'chaine', 0, '', $conf->entity)) {
107 $error++;
108 }
109 }
110 if (GETPOSTISSET($constvalue.'_URLAUTHORIZE')) {
111 if (!dolibarr_set_const($db, $newconstvalue.'_URLAUTHORIZE', GETPOST($constvalue.'_URLAUTHORIZE'), 'chaine', 0, '', $conf->entity)) {
112 $error++;
113 }
114 }
115 if (GETPOSTISSET($constvalue.'_TENANT')) {
116 if (!dolibarr_set_const($db, $constvalue.'_TENANT', GETPOST($constvalue.'_TENANT'), 'chaine', 0, '', $conf->entity)) {
117 $error++;
118 }
119 }
120 if (GETPOSTISSET($constvalue.'_SCOPE')) {
121 if (is_array(GETPOST($constvalue.'_SCOPE'))) {
122 $scopestring = implode(',', GETPOST($constvalue.'_SCOPE'));
123 } else {
124 $scopestring = GETPOST($constvalue.'_SCOPE');
125 }
126 if (!dolibarr_set_const($db, $newconstvalue.'_SCOPE', $scopestring, 'chaine', 0, '', $conf->entity)) {
127 $error++;
128 }
129 } elseif ($newconstvalue !== $constvalue) {
130 if (!dolibarr_set_const($db, $newconstvalue.'_SCOPE', '', 'chaine', 0, '', $conf->entity)) {
131 $error++;
132 }
133 }
134
135 // If name changed, we have to delete old const and proceed few other changes
136 if ($constvalue !== $newconstvalue) {
137 dolibarr_del_const($db, $constvalue.'_ID', $conf->entity);
138 dolibarr_del_const($db, $constvalue.'_SECRET', $conf->entity);
139 dolibarr_del_const($db, $constvalue.'_URL', $conf->entity);
140 dolibarr_del_const($db, $constvalue.'_URLAUTHORIZE', $conf->entity);
141 dolibarr_del_const($db, $constvalue.'_SCOPE', $conf->entity);
142
143 // Update name of token
144 $oldname = preg_replace('/^OAUTH_/', '', $constvalue);
145 $oldprovider = ucfirst(strtolower(preg_replace('/-.*$/', '', $oldname)));
146 $oldlabel = preg_replace('/^.*-/', '', $oldname);
147 $newlabel = preg_replace('/^.*-/', '', $newconstvalue);
148
149
150 $sql = "UPDATE ".MAIN_DB_PREFIX."oauth_token";
151 $sql.= " SET service = '".$db->escape($oldprovider."-".$newlabel)."'";
152 $sql.= " WHERE service = '".$db->escape($oldprovider."-".$oldlabel)."'";
153
154
155 $resql = $db->query($sql);
156 if (!$resql) {
157 $error++;
158 }
159
160 // Update other const that was using the renamed key as token (might not be exhaustive)
161 if (getDolGlobalString('MAIN_MAIL_SMTPS_OAUTH_SERVICE') == $oldname) {
162 if (!dolibarr_set_const($db, 'MAIN_MAIL_SMTPS_OAUTH_SERVICE', strtoupper($oldprovider).'-'.$newlabel, 'chaine', 0, '', $conf->entity)) {
163 $error++;
164 }
165 }
166 }
167 }
168 }
169
170
171 if (!$error) {
172 setEventMessages($langs->trans("SetupSaved"), null);
173 } else {
174 setEventMessages($langs->trans("Error"), null, 'errors');
175 }
176}
177
178if ($action == 'confirm_delete') {
179 $provider = GETPOST('provider', 'aZ09');
180 $label = GETPOST('label');
181
182 $globalkey = empty($provider) ? $label : $label.'-'.$provider;
183
184 if (getDolGlobalString($globalkey.'_ID') && getDolGlobalString($globalkey.'_SECRET')) { // If ID and secret exist, we delete first the token
185 $backtourl = DOL_URL_ROOT.'/admin/oauth.php?action=delete_entry&provider='.$provider.'&label='.$label.'&token='.newToken();
186 $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
187 $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT;
188 $callbacktodel = $urlwithroot;
189 if ($label == 'OAUTH_GOOGLE') {
190 $callbacktodel .= '/core/modules/oauth/google_oauthcallback.php?action=delete&keyforprovider='.$provider.'&token='.newToken().'&backtourl='.urlencode($backtourl);
191 } elseif ($label == 'OAUTH_GITHUB') {
192 $callbacktodel .= '/core/modules/oauth/github_oauthcallback.php?action=delete&keyforprovider='.$provider.'&token='.newToken().'&backtourl='.urlencode($backtourl);
193 } elseif ($label == 'OAUTH_STRIPELIVE') {
194 $callbacktodel .= '/core/modules/oauth/stripelive_oauthcallback.php?action=delete&keyforprovider='.$provider.'&token='.newToken().'&backtourl='.urlencode($backtourl);
195 } elseif ($label == 'OAUTH_STRIPETEST') {
196 $callbacktodel .= '/core/modules/oauth/stripetest_oauthcallback.php?action=delete&keyforprovider='.$provider.'&token='.newToken().'&backtourl='.urlencode($backtourl);
197 } elseif ($label == 'OAUTH_MICROSOFT') {
198 $callbacktodel .= '/core/modules/oauth/microsoft_oauthcallback.php?action=delete&keyforprovider='.$provider.'&token='.newToken().'&backtourl='.urlencode($backtourl);
199 } elseif ($label == 'OAUTH_MICROSOFT2') {
200 $callbacktodel .= '/core/modules/oauth/microsoft2_oauthcallback.php?action=delete&keyforprovider='.$provider.'&token='.newToken().'&backtourl='.urlencode($backtourl);
201 } elseif ($label == 'OAUTH_GENERIC') {
202 $callbacktodel .= '/core/modules/oauth/generic_oauthcallback.php?action=delete&keyforprovider='.$provider.'&token='.newToken().'&backtourl='.urlencode($backtourl);
203 }
204 header("Location: ".$callbacktodel);
205 exit;
206 } else {
207 $action = 'delete_entry';
208 }
209}
210
211if ($action == 'delete_entry') {
212 $provider = GETPOST('provider', 'aZ09');
213 $label = GETPOST('label');
214
215 $globalkey = empty($provider) ? $label : $label.'-'.$provider;
216
217 if (!dolibarr_del_const($db, $globalkey.'_NAME', $conf->entity)
218 || !dolibarr_del_const($db, $globalkey.'_ID', $conf->entity)
219 || !dolibarr_del_const($db, $globalkey.'_SECRET', $conf->entity)
220 || !dolibarr_del_const($db, $globalkey.'_URL', $conf->entity)
221 || !dolibarr_del_const($db, $globalkey.'_URLAUTHORIZE', $conf->entity)
222 || !dolibarr_del_const($db, $globalkey.'_SCOPE', $conf->entity)
223 || !dolibarr_del_const($db, $globalkey.'_TENANT', $conf->entity)) {
224 setEventMessages($langs->trans("ErrorInEntryDeletion"), null, 'errors');
225 $error++;
226 } else {
227 setEventMessages($langs->trans("EntryDeleted"), null);
228 }
229}
230
231/*
232 * View
233 */
234
235$form = new Form($db);
236
237$title = $langs->trans('ConfigOAuth');
238$help_url = 'EN:Module_OAuth|FR:Module_OAuth_FR|ES:Módulo_OAuth_ES';
239
240llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-admin page-oauth');
241
242// Confirmation of action process
243if ($action == 'delete') {
244 $formquestion = array();
245 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?provider='.GETPOST('provider').'&label='.GETPOST('label'), $langs->trans('OAuthServiceConfirmDeleteTitle'), $langs->trans('OAuthServiceConfirmDeleteMessage'), 'confirm_delete', $formquestion, 0, 1, 220);
246 print $formconfirm;
247}
248
249
250$linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
251
252print load_fiche_titre($title, $linkback, 'title_setup');
253
254print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
255print '<input type="hidden" name="token" value="'.newToken().'">';
256print '<input type="hidden" name="action" value="add">';
257
259
260print dol_get_fiche_head($head, 'services', '', -1, '');
261
262
263print '<span class="opacitymedium">'.$langs->trans("ListOfSupportedOauthProviders").'</span><br><br>';
264
265
266$list = getAllOauth2Array();
267
268
269print '<select name="provider" id="provider" class="minwidth150">';
270print '<option name="-1" value="-1">'.$langs->trans("OAuthProvider").'</option>';
271// TODO Make a loop directly on getSupportedOauth2Array() and remove getAllOauth2Array()
272foreach ($list as $key) {
273 $supported = 0;
274 $keyforsupportedoauth2array = $key[0];
275
276 if (in_array($keyforsupportedoauth2array, array_keys($supportedoauth2array))) {
277 $supported = 1;
278 }
279 if (!$supported) {
280 continue; // show only supported
281 }
282
283 print '<option name="'.$keyforsupportedoauth2array.'" value="'.str_replace('_NAME', '', $keyforsupportedoauth2array).'">';
284
285 $keyforsupportedoauth2array = preg_replace('/^OAUTH_/', '', $keyforsupportedoauth2array);
286 $keyforsupportedoauth2array = preg_replace('/_NAME$/', '', $keyforsupportedoauth2array);
287 $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
288 $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
289
290 $label = $langs->trans($keyforsupportedoauth2array);
291 if ($label == $keyforsupportedoauth2array) {
292 print $supportedoauth2array[$keyforsupportedoauth2array]['name'];
293 } else {
294 print $label;
295 }
296 print'</option>'."\n";
297}
298print '</select>';
299print ajax_combobox('provider');
300print ' <input type="text" name="label" value="" placeholder="'.$langs->trans("Label").'" pattern="^[a-zA-Z0-9]+$" title="'.$langs->trans("SpaceOrSpecialCharAreNotAllowed").'">';
301print ' <input type="submit" class="button small" name="add" value="'.$langs->trans("Add").'">';
302
303print '<br>';
304print '<br>';
305
306print dol_get_fiche_end();
307
308print '</form>';
309
310$listinsetup = [];
311// Define $listinsetup
312foreach ($conf->global as $key => $val) {
313 if (!empty($val) && preg_match('/^OAUTH_.*_ID$/', $key)) {
314 $provider = preg_replace('/_ID$/', '', $key);
315 $listinsetup[] = array(
316 $provider.'_NAME',
317 $provider.'_ID',
318 $provider.'_SECRET',
319 $provider.'_URL', // For custom oauth links
320 $provider.'_SCOPE' // For custom oauth links
321 );
322 }
323}
324
325
326if (count($listinsetup) > 0) {
327 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
328 print '<input type="hidden" name="token" value="'.newToken().'">';
329 print '<input type="hidden" name="action" value="update">';
330
331 print '<div class="div-table-responsive-no-min">';
332
333 $i = 0;
334
335 // $list is defined into oauth.lib.php to the list of supporter OAuth providers.
336 foreach ($listinsetup as $key) {
337 $supported = 0;
338 $keyforsupportedoauth2array = $key[0]; // May be OAUTH_GOOGLE_NAME or OAUTH_GOOGLE_xxx_NAME
339 $keyforsupportedoauth2array = preg_replace('/^OAUTH_/', '', $keyforsupportedoauth2array);
340 $keyforsupportedoauth2array = preg_replace('/_NAME$/', '', $keyforsupportedoauth2array);
341 if (preg_match('/^.*-/', $keyforsupportedoauth2array)) {
342 $keybeforeprovider = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
343 $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array);
344 } else {
345 $keybeforeprovider = $keyforsupportedoauth2array;
346 $keyforprovider = '';
347 }
348 $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
349 $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
350
351 if (in_array($keyforsupportedoauth2array, array_keys($supportedoauth2array))) {
352 $supported = 1;
353 }
354 if (!$supported) {
355 continue; // show only supported
356 }
357
358 $i++;
359
360 print '<table class="noborder centpercent">';
361
362 // OAUTH service name
363 $label = $langs->trans($keyforsupportedoauth2array);
364 print '<tr class="liste_titre'.($i > 1 ? ' liste_titre_add' : '').'">';
365 print '<td class="titlefieldcreate">';
366 print img_picto('', $supportedoauth2array[$keyforsupportedoauth2array]['picto'], 'class="pictofixedwidth"');
367 if ($label == $keyforsupportedoauth2array) {
368 print $supportedoauth2array[$keyforsupportedoauth2array]['name'];
369 } else {
370 print $label;
371 }
372 if ($servicetoeditname == $key[0]) {
373 print ' (<input style="width: 20%" type="text" name="'.$key[0].'" value="'.$keyforprovider.'" >)';
374 } elseif ($keyforprovider) {
375 print ' (<b>'.$keyforprovider.'</b>)';
376 } else {
377 print ' (<b>'.$langs->trans("NoName").'</b>)';
378 }
379 if (!($servicetoeditname == $key[0])) {
380 print '<a class="editfielda reposition" href="'.$_SERVER["PHP_SELF"].'?token='.newToken().'&servicetoeditname='.urlencode($key[0]).'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 1).'</a>';
381 }
382 print '</td>';
383 print '<td>';
384 if (!empty($supportedoauth2array[$keyforsupportedoauth2array]['urlforcredentials'])) {
385 print $langs->trans("OAUTH_URL_FOR_CREDENTIAL", $supportedoauth2array[$keyforsupportedoauth2array]['urlforcredentials']);
386 }
387 print '</td>';
388
389 // Delete
390 print '<td>';
391 $label = preg_replace('/_NAME$/', '', $keyforsupportedoauth2array);
392 print '<a href="'.$_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&provider='.urlencode($keyforprovider).'&label='.urlencode($label).'">';
393 print img_picto('', 'delete');
394 print '</a>';
395
396 print '</form>';
397 print '</td>';
398
399 print '</tr>';
400
401 if ($supported) {
402 $redirect_uri = $urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$keyforsupportedoauth2array]['callbackfile'].'_oauthcallback.php';
403 print '<tr class="oddeven value">';
404 print '<td>'.$form->textwithpicto($langs->trans("RedirectURL"), $langs->trans("UseTheFollowingUrlAsRedirectURI")).'</td>';
405 print '<td><input style="width: 80%" type="text" name="uri'.$keyforsupportedoauth2array.'" id="uri'.$keyforsupportedoauth2array.$keyforprovider.'" value="'.$redirect_uri.'" disabled>';
406 print ajax_autoselect('uri'.$keyforsupportedoauth2array.$keyforprovider);
407 print '</td>';
408 print '<td></td>';
409 print '</tr>';
410
411 if ($keyforsupportedoauth2array == 'OAUTH_GENERIC_NAME') {
412 print '<tr class="oddeven value">';
413 print '<td>';
414 $tooltiphelp = $langs->trans("Example").'<br>https://mastodon.example.com<br>https://mastodon.social';
415 print $form->textwithpicto($langs->trans("URLOfOAuthServiceEndpoints"), $tooltiphelp);
416 print '</td>';
417 print '<td><input style="width: 80%" type="text" name="'.$key[3].'" value="'.getDolGlobalString($key[3]).'" >';
418 print '</td>';
419 print '<td></td>';
420 print '</tr>';
421 }
422 } else {
423 print '<tr class="oddeven value">';
424 print '<td>'.$langs->trans("UseTheFollowingUrlAsRedirectURI").'</td>';
425 print '<td>'.$langs->trans("FeatureNotYetSupported").'</td>';
426 print '</td>';
427 print '<td></td>';
428 print '</tr>';
429 }
430
431 // Api Id
432 print '<tr class="oddeven value">';
433 print '<td><label for="'.$key[1].'">'.$langs->trans("OAUTH_ID").'</label></td>';
434 print '<td><input type="text" size="100" id="'.$key[1].'" name="'.$key[1].'" value="'.getDolGlobalString($key[1]).'">';
435 print '</td>';
436 print '<td></td>';
437 print '</tr>';
438
439 // Api Secret
440 print '<tr class="oddeven value">';
441 print '<td><label for="'.$key[2].'">'.$langs->trans("OAUTH_SECRET").'</label></td>';
442 print '<td><input type="password" size="100" id="'.$key[2].'" name="'.$key[2].'" value="'.getDolGlobalString($key[2]).'">';
443 print '</td>';
444 print '<td></td>';
445 print '</tr>';
446
447 // Tenant
448 if ($keybeforeprovider == 'MICROSOFT' || $keybeforeprovider == 'MICROSOFT2' || $keybeforeprovider == 'MICROSOFT3') {
449 print '<tr class="oddeven value">';
450 print '<td><label for="'.$key[2].'">'.$langs->trans("OAUTH_TENANT").'</label></td>';
451 print '<td><input type="text" size="100" id="OAUTH_'.$keybeforeprovider.($keyforprovider ? '-'.$keyforprovider : '').'_TENANT" name="OAUTH_'.$keybeforeprovider.($keyforprovider ? '-'.$keyforprovider : '').'_TENANT" value="'.getDolGlobalString('OAUTH_'.$keybeforeprovider.($keyforprovider ? '-'.$keyforprovider : '').'_TENANT').'">';
452 print '</td>';
453 print '<td></td>';
454 print '</tr>';
455 }
456
457 // TODO Move this into token generation ?
458 if ($supported) {
459 if ($keyforsupportedoauth2array == 'OAUTH_GENERIC_NAME') {
460 print '<tr class="oddeven value">';
461 print '<td>';
462 print $form->textwithpicto($langs->trans("Scopes"), $langs->trans("ScopesDesc"));
463 print '</td>';
464 print '<td>';
465 print '<input style="width: 80%" type"text" name="'.$key[4].'" value="'.getDolGlobalString($key[4]).'" >';
466 print '</td>';
467 print '<td></td>';
468 print '</tr>';
469 } else {
470 $availablescopes = array_flip(explode(',', $supportedoauth2array[$keyforsupportedoauth2array]['availablescopes']));
471 $currentscopes = explode(',', getDolGlobalString($key[4]));
472 $scopestodispay = array();
473 foreach ($availablescopes as $keyscope => $valscope) {
474 if (in_array($keyscope, $currentscopes)) {
475 $scopestodispay[$keyscope] = 1;
476 } else {
477 $scopestodispay[$keyscope] = 0;
478 }
479 }
480 // Api Scope
481 print '<tr class="oddeven value">';
482 print '<td>'.$langs->trans("Scopes").'</td>';
483 print '<td>';
484 foreach ($scopestodispay as $scope => $val) {
485 print '<input type="checkbox" id="'.$keyforprovider.$scope.'" name="'.$key[4].'[]" value="'.$scope.'"'.($val ? ' checked' : '').'>';
486 print '<label style="margin-right: 10px" for="'.$keyforprovider.$scope.'">'.$scope.'</label>';
487 }
488 print '</td>';
489 print '<td></td>';
490 print '</tr>';
491 }
492 } else {
493 print '<tr class="oddeven value">';
494 print '<td>'.$langs->trans("UseTheFollowingUrlAsRedirectURI").'</td>';
495 print '<td>'.$langs->trans("FeatureNotYetSupported").'</td>';
496 print '</td>';
497 print '<td></td>';
498 print '</tr>';
499 }
500
501 print '</table>'."\n";
502
503 print '<br>';
504 }
505
506 print '</div>';
507
508 print $form->buttonsSaveCancel("Save", '');
509
510 print '</form>';
511}
512
513// End of page
514llxFooter();
515$db->close();
global $dolibarr_main_url_root
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
dolibarr_del_const($db, $name, $entity=1)
Delete a constant.
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:476
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage generation of HTML components Only common components must be here.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
getAllOauth2Array()
Return array of possible OAUTH2 services.
Definition oauth.lib.php:35
getSupportedOauth2Array()
Return array of tabs to use on pages to setup cron module.
oauthadmin_prepare_head()
Return array of tabs to used on pages to setup cron module.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.