dolibarr 25.0.0-alpha
newonlinesign.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2023 anthony Berton <anthony.berton@bb2a.fr>
6 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
8 * Copyright (C) 2026 Lenin Rivas <lenin.rivas777@gmail.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
33if (!defined('NOLOGIN')) {
34 define("NOLOGIN", 1); // This means this output page does not require to be logged.
35}
36if (!defined('NOCSRFCHECK')) {
37 define("NOCSRFCHECK", 1); // We accept to go on this page from external web site.
38}
39if (!defined('NOIPCHECK')) {
40 define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
41}
42if (!defined('NOBROWSERNOTIF')) {
43 define('NOBROWSERNOTIF', '1');
44}
45
46// For MultiCompany module.
47// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
48// Because 2 entities can have the same ref.
49$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
50if (is_numeric($entity)) {
51 define("DOLENTITY", $entity);
52}
53
54// Load Dolibarr environment
55require '../../main.inc.php';
66require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
67require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
68require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
69require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
70require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
71require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
72
73// Load translation files
74$langs->loadLangs(array("main", "other", "dict", "bills", "companies", "errors", "members", "paybox", "stripe", "propal", "commercial"));
75
76// Security check
77// No check on module enabled. Done later according to $validpaymentmethod
78
79// Get parameters
80$action = GETPOST('action', 'aZ09');
81$cancel = GETPOST('cancel', 'alpha');
82$confirm = GETPOST('confirm', 'alpha');
83
84
85$refusepropal = GETPOST('refusepropal', 'alpha');
86$message = GETPOST('message', 'aZ09');
87
88// Input are:
89// type ('invoice','order','contractline'),
90// id (object id),
91// amount (required if id is empty),
92// tag (a free text, required if type is empty)
93// currency (iso code)
94
95$suffix = GETPOST("suffix", 'aZ09');
96$source = (string) GETPOST("source", 'alpha');
97$ref = $REF = GETPOST("ref", 'alpha');
98$urlok = '';
99$urlko = '';
100
101if ($source == '') {
102 $source = 'proposal';
103}
104if (!empty($refusepropal)) {
105 $action = "refusepropal";
106}
107
108// Define $urlwithroot
109//$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
110//$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
111$urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost.
112
113
114// Complete urls for post treatment
115$SECUREKEY = GETPOST("securekey"); // Secure key
116
117if (!empty($source)) {
118 $urlok .= 'source='.urlencode($source).'&';
119 $urlko .= 'source='.urlencode($source).'&';
120}
121if (!empty($REF)) {
122 $urlok .= 'ref='.urlencode($REF).'&';
123 $urlko .= 'ref='.urlencode($REF).'&';
124}
125if (!empty($SECUREKEY)) {
126 $urlok .= 'securekey='.urlencode($SECUREKEY).'&';
127 $urlko .= 'securekey='.urlencode($SECUREKEY).'&';
128}
129if (!empty($entity)) {
130 $urlok .= 'entity='.urlencode((string) ($entity)).'&';
131 $urlko .= 'entity='.urlencode((string) ($entity)).'&';
132}
133$urlok = preg_replace('/&$/', '', $urlok); // Remove last &
134$urlko = preg_replace('/&$/', '', $urlko); // Remove last &
135
136$creditor = $mysoc->name;
137
138$type = $source;
139if (!$action) {
140 if ($source && !$ref) {
141 httponly_accessforbidden($langs->trans('ErrorBadParameters')." - ref missing", 400, 1);
142 }
143}
144
145global $dolibarr_main_instance_unique_id;
146$defaultsalt = substr(dol_hash('dolibarr'.$dolibarr_main_instance_unique_id, 'sha256'), 0, 32); // Fallback if no specific salt was set
147
148// Check securitykey
149$securekeyseed = '';
150if ($source == 'proposal') {
151 $securekeyseed = getDolGlobalString('PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN', $defaultsalt);
152} elseif ($source == 'contract') {
153 $securekeyseed = getDolGlobalString('CONTRACT_ONLINE_SIGNATURE_SECURITY_TOKEN', $defaultsalt);
154} elseif ($source == 'fichinter') {
155 $securekeyseed = getDolGlobalString('FICHINTER_ONLINE_SIGNATURE_SECURITY_TOKEN', $defaultsalt);
156} elseif ($source == 'societe_rib') {
157 $securekeyseed = getDolGlobalString('SOCIETE_RIB_ONLINE_SIGNATURE_SECURITY_TOKEN', $defaultsalt);
158} elseif ($source == 'order') {
159 $securekeyseed = getDolGlobalString('ORDER_ONLINE_SIGNATURE_SECURITY_TOKEN');
160} else {
161 $securekeyseed = getDolGlobalString(dol_strtoupper((string) $source).'_ONLINE_SIGNATURE_SECURITY_TOKEN', $defaultsalt);
162}
163if (!dol_verifyHash($securekeyseed.$type.$ref.(isModEnabled('multicompany') ? $entity : ''), $SECUREKEY, 'hash')) {
164 httponly_accessforbidden('Bad value for securitykey. Value provided '.dol_escape_htmltag($SECUREKEY).' does not match expected value for ref='.dol_escape_htmltag($ref), 403, 1);
165}
166
167if ($source == 'proposal') {
168 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
169 $object = new Propal($db);
170 $result = $object->fetch(0, $ref, '', $entity);
171} elseif ($source == 'contract') {
172 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
173 $object = new Contrat($db);
174 $result = $object->fetch(0, $ref);
175} elseif ($source == 'fichinter') {
176 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
177 $object = new Fichinter($db);
178 $result = $object->fetch(0, $ref);
179} elseif ($source == 'societe_rib') {
180 require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
181 $object = new CompanyBankAccount($db);
182 $result = $object->fetch(0, $ref);
183} elseif ($source == 'order') {
184 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
185 $object = new Commande($db);
186 $result = $object->fetch(0, $ref);
187} elseif ($source == 'expedition') {
188 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
189 $object = new Expedition($db);
190 $result = $object->fetch(0, $ref);
191} else {
192 httponly_accessforbidden($langs->trans('ErrorBadParameters')." - Bad value for source. Value not supported.", 400, 1);
193}
194
195// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
196$hookmanager->initHooks(array('onlinesign'));
197
198$error = 0;
199
200
201/*
202 * Actions
203 */
204
205if ($action == 'confirm_refusepropal' && $confirm == 'yes') { // Test on permission not required here. Public form. Security checked on the securekey and on mitigation
206 $db->begin();
207
208 $sql = "UPDATE ".MAIN_DB_PREFIX."propal";
209 $sql .= " SET fk_statut = ".((int) $object::STATUS_NOTSIGNED).", note_private = '".$db->escape($object->note_private)."', date_signature = '".$db->idate(dol_now())."'";
210 $sql .= " WHERE rowid = ".((int) $object->id);
211
212 dol_syslog(__FILE__, LOG_DEBUG);
213 $resql = $db->query($sql);
214 if (!$resql) {
215 $error++;
216 }
217
218 if (!$error) {
219 $db->commit();
220
221 $message = 'refused';
222 setEventMessages("PropalRefused", null, 'warnings');
223 $object->context = array('closedfromonlinesignature' => 'closedfromonlinesignature');
224 $result = $object->call_trigger('PROPAL_CLOSE_REFUSED', $user);
225 if ($result < 0) {
226 $error++;
227 }
228 } else {
229 $db->rollback();
230 }
231
232 $object->fetch(0, $ref);
233}
234
235// $action == "dosign" is handled later...
236
237
238/*
239 * View
240 */
241
242$form = new Form($db);
243
244$head = '';
245if (getDolGlobalString('MAIN_SIGN_CSS_URL')) {
246 $head = '<link rel="stylesheet" type="text/css" href="' . getDolGlobalString('MAIN_SIGN_CSS_URL').'?lang='.$langs->defaultlang.'">'."\n";
247}
248
249$conf->dol_hide_topmenu = 1;
250$conf->dol_hide_leftmenu = 1;
251
252$title = $langs->trans("OnlineSignature");
253
254$replacemainarea = (empty($conf->dol_hide_leftmenu) ? '<div>' : '').'<div>';
255llxHeader($head, $title, '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea, 1);
256
257htmlPrintOnlineHeader($mysoc, $langs, 1, '', 'ONLINE_SIGN_IMAGE_PUBLIC_INTERFACE', 'ONLINE_SIGN_LOGO_'.$suffix, 'ONLINE_SIGN_LOGO');
258
259if ($action == 'refusepropal') {
260 print $form->formconfirm($_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&securekey='.urlencode($SECUREKEY).(isModEnabled('multicompany') ? '&entity='.$entity : ''), $langs->trans('RefusePropal'), $langs->trans('ConfirmRefusePropal', $object->ref), 'confirm_refusepropal', '', '', 1);
261}
262
263// Check link validity for param 'source' to avoid use of the examples as value
264if (/* $source !== '' :never empty && */ in_array($ref, array('member_ref', 'contractline_ref', 'invoice_ref', 'order_ref', 'proposal_ref', ''))) {
265 $langs->load("errors");
266 dol_print_error_email('BADREFINONLINESIGNFORM', $langs->trans("ErrorBadLinkSourceSetButBadValueForRef", $source, $ref));
267 // End of page
268 llxFooter();
269 $db->close();
270 exit;
271}
272
273print '<span id="dolpaymentspan"></span>'."\n";
274print '<div class="center">'."\n";
275print '<form id="dolpaymentform" class="center" name="paymentform" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
276print '<input type="hidden" name="token" value="'.newToken().'">'."\n";
277print '<input type="hidden" name="action" value="dosign">'."\n";
278print '<input type="hidden" name="tag" value="'.GETPOST("tag", 'alpha').'">'."\n";
279print '<input type="hidden" name="suffix" value="'.GETPOST("suffix", 'alpha').'">'."\n";
280print '<input type="hidden" name="securekey" value="'.$SECUREKEY.'">'."\n";
281print '<input type="hidden" name="entity" value="'.$entity.'" />';
282print '<input type="hidden" name="page_y" value="" />';
283print '<input type="hidden" name="source" value="'.$source.'" />';
284print '<input type="hidden" name="ref" value="'.$ref.'" />';
285print "\n";
286print '<!-- Form to sign -->'."\n";
287
288if ($source == 'proposal' && getDolGlobalString('PROPOSAL_IMAGE_PUBLIC_SIGN')) {
289 print '<div class="backimagepublicproposalsign">';
290 print '<img id="idPROPOSAL_IMAGE_PUBLIC_INTERFACE" src="' . getDolGlobalString('PROPOSAL_IMAGE_PUBLIC_SIGN').'">';
291 print '</div>';
292}
293
294print '<table id="dolpublictable" summary="Payment form" class="center">'."\n";
295
296// Output introduction text
297$text = '';
298if (getDolGlobalString('ONLINE_SIGN_NEWFORM_TEXT')) {
299 $reg = array();
300 if (preg_match('/^\‍((.*)\‍)$/', $conf->global->ONLINE_SIGN_NEWFORM_TEXT, $reg)) {
301 $text .= $langs->trans($reg[1])."<br>\n";
302 } else {
303 $text .= getDolGlobalString('ONLINE_SIGN_NEWFORM_TEXT') . "<br>\n";
304 }
305 $text = '<tr><td align="center"><br>'.$text.'<br></td></tr>'."\n";
306}
307if (empty($text)) {
308 if ($source == 'proposal') {
309 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageProposal", $mysoc->name).'</strong></td></tr>'."\n";
310 $text .= '<tr><td class="textpublicpayment small opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromProposal", $creditor).'<br><br></td></tr>'."\n";
311 } elseif ($source == 'contract') {
312 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageContract", $mysoc->name).'</strong></td></tr>'."\n";
313 $text .= '<tr><td class="textpublicpayment small opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromContract", $creditor).'<br><br></td></tr>'."\n";
314 } elseif ($source == 'fichinter') {
315 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageFichinter", $mysoc->name).'</strong></td></tr>'."\n";
316 $text .= '<tr><td class="textpublicpayment small opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromFichinter", $creditor).'<br><br></td></tr>'."\n";
317 } elseif ($source == 'expedition') {
318 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePageExpedition", $mysoc->name).'</strong></td></tr>'."\n";
319 $text .= '<tr><td class="textpublicpayment small opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFromExpedition", $creditor).'<br><br></td></tr>'."\n";
320 } else {
321 $text .= '<tr><td class="textpublicpayment"><br><strong>'.$langs->trans("WelcomeOnOnlineSignaturePage".dol_ucfirst($source), $mysoc->name).'</strong></td></tr>'."\n";
322 $text .= '<tr><td class="textpublicpayment small opacitymedium">'.$langs->trans("ThisScreenAllowsYouToSignDocFrom".dol_ucfirst($source), $creditor).'<br><br></td></tr>'."\n";
323 }
324}
325print $text;
326
327// Output payment summary form
328print '<tr><td align="center">';
329print '<table with="100%" id="tablepublicpayment">';
330if ($source == 'proposal') {
331 print '<tr><td colspan="2" class="left small opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignProposal").'<br><br></td></tr>'."\n";
332} elseif ($source == 'contract') {
333 print '<tr><td colspan="2" class="left small opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignContract").'<br><br></td></tr>'."\n";
334} elseif ($source == 'fichinter') {
335 print '<tr><td colspan="2" class="left small opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignFichinter").'<br><br></td></tr>'."\n";
336} elseif ($source == 'expedition') {
337 print '<tr><td colspan="2" class="left small opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSignExpedition").'<br><br></td></tr>'."\n";
338} else {
339 print '<tr><td colspan="2" class="left small opacitymedium">'.$langs->trans("ThisIsInformationOnDocumentToSign".dol_ucfirst($source)).'<br><br></td></tr>'."\n";
340}
341$found = false;
342$error = 0;
343
344// Signature on commercial proposal
345if ($source == 'proposal') {
346 $found = true;
347 $langs->load("proposal");
348
349 $result = $object->fetch_thirdparty($object->socid);
350
351 // Creditor
352 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
353 print '</td><td class="CTableRow2">';
354 print img_picto('', 'company', 'class="pictofixedwidth"');
355 print '<b>'.$creditor.'</b>';
356 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
357 print '</td></tr>'."\n";
358
359 // Debitor
360 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
361 print '</td><td class="CTableRow2">';
362 print img_picto('', 'company', 'class="pictofixedwidth"');
363 print '<b>'.$object->thirdparty->name.'</b>';
364 print '</td></tr>'."\n";
365
366 // Amount
367
368 $amount = '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
369 $amount .= '</td><td class="CTableRow2">';
370 $amount .= '<b>'.price($object->total_ttc, 0, $langs, 1, -1, -1, getDolCurrency()).'</b>';
371 if ($object->multicurrency_code != getDolCurrency()) {
372 $amount .= ' ('.price($object->multicurrency_total_ttc, 0, $langs, 1, -1, -1, $object->multicurrency_code).')';
373 }
374 $amount .= '</td></tr>'."\n";
375
376 // Call Hook amountPropalSign
377 $parameters = array('source' => $source);
378 $reshook = $hookmanager->executeHooks('amountPropalSign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
379 if (empty($reshook)) {
380 $amount .= $hookmanager->resPrint;
381 } elseif ($reshook > 0) {
382 $amount = $hookmanager->resPrint;
383 }
384
385 print $amount;
386
387 // Object
388 $text = '<b>'.$langs->trans("SignatureProposalRef", $object->ref).'</b>';
389 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
390 print '</td><td class="CTableRow2">'.$text;
391
392 $last_main_doc_file = $object->last_main_doc;
393
394 if ($object->status == $object::STATUS_VALIDATED) {
395 $object->last_main_doc = preg_replace('/_signed-(\d+)/', '', $object->last_main_doc); // We want to be sure to not work on the signed version
396
397 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
398 // It seems document has never been generated, or was generated and then deleted.
399 // So we try to regenerate it with its default template.
400 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
401 $object->generateDocument($defaulttemplate, $langs);
402 }
403
404 $directdownloadlink = $object->getLastMainDocLink('proposal');
405 if ($directdownloadlink) {
406 print '<br><a href="'.$directdownloadlink.'">';
407 print img_mime($object->last_main_doc, '');
408 print $langs->trans("DownloadDocument").'</a>';
409 }
410 } else {
411 if ($object->status == $object::STATUS_NOTSIGNED) {
412 $directdownloadlink = $object->getLastMainDocLink('proposal');
413 if ($directdownloadlink) {
414 print '<br><a href="'.$directdownloadlink.'">';
415 print img_mime($last_main_doc_file, '');
416 print $langs->trans("DownloadDocument").'</a>';
417 }
418 } elseif ($object->status == $object::STATUS_SIGNED || $object->status == $object::STATUS_BILLED) {
419 if (preg_match('/_signed-(\d+)/', $last_main_doc_file)) { // If the last main doc has been signed
420 $last_main_doc_file_not_signed = preg_replace('/_signed-(\d+)/', '', $last_main_doc_file);
421
422 $datefilesigned = dol_filemtime($last_main_doc_file);
423 $datefilenotsigned = dol_filemtime($last_main_doc_file_not_signed);
424
425 if (empty($datefilenotsigned) || $datefilesigned > $datefilenotsigned) { // If file signed is more recent
426 $directdownloadlink = $object->getLastMainDocLink('proposal');
427 if ($directdownloadlink) {
428 print '<br><a href="'.$directdownloadlink.'">';
429 print img_mime($object->last_main_doc, '');
430 print $langs->trans("DownloadDocument").'</a>';
431 }
432 }
433 }
434 }
435 }
436
437 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
438 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
439 print '</td></tr>'."\n";
440} elseif ($source == 'order') {
441 $found = true;
442 $langs->load("orders");
443
444 $result = $object->fetch_thirdparty($object->socid);
445
446 // Creditor
447 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Creditor");
448 print '</td><td class="CTableRow2">';
449 print img_picto('', 'company', 'class="pictofixedwidth"');
450 print '<b>'.$creditor.'</b>';
451 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
452 print '</td></tr>'."\n";
453
454 // Debitor
455 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
456 print '</td><td class="CTableRow2">';
457 print img_picto('', 'company', 'class="pictofixedwidth"');
458 print '<b>'.$object->thirdparty->name.'</b>';
459 print '</td></tr>'."\n";
460
461 // Amount
462 $amount = '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
463 $amount .= '</td><td class="CTableRow2">';
464 $amount .= '<b>'.price($object->total_ttc, 0, $langs, 1, -1, -1, getDolCurrency()).'</b>';
465 if ($object->multicurrency_code != getDolCurrency()) {
466 $amount .= ' ('.price($object->multicurrency_total_ttc, 0, $langs, 1, -1, -1, $object->multicurrency_code).')';
467 }
468 $amount .= '</td></tr>'."\n";
469
470 print $amount;
471
472 // Object
473 $text = '<b>'.$langs->trans("SignatureOrderRef", $object->ref).'</b>';
474 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
475 print '</td><td class="CTableRow2">'.$text;
476
477 $last_main_doc_file = $object->last_main_doc;
478
479 if ($object->status == $object::STATUS_VALIDATED) {
480 $object->last_main_doc = preg_replace('/_signed-(\d+)/', '', $object->last_main_doc); // We want to be sure to not work on the signed version
481
482 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
483 // It seems document has never been generated, or was generated and then deleted.
484 // So we try to regenerate it with its default template.
485 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
486 $object->generateDocument($defaulttemplate, $langs);
487 }
488
489 $directdownloadlink = $object->getLastMainDocLink('order');
490 if ($directdownloadlink) {
491 print '<br><a href="'.$directdownloadlink.'">';
492 print img_mime($object->last_main_doc, '');
493 print $langs->trans("DownloadDocument").'</a>';
494 }
495 } else {
496 if ($object->status == $object::STATUS_DRAFT) {
497 $directdownloadlink = $object->getLastMainDocLink('order');
498 if ($directdownloadlink) {
499 print '<br><a href="'.$directdownloadlink.'">';
500 print img_mime($last_main_doc_file, '');
501 print $langs->trans("DownloadDocument").'</a>';
502 }
503 } else {
504 if (preg_match('/_signed-(\d+)/', $last_main_doc_file)) { // If the last main doc has been signed
505 $last_main_doc_file_not_signed = preg_replace('/_signed-(\d+)/', '', $last_main_doc_file);
506
507 $datefilesigned = dol_filemtime($last_main_doc_file);
508 $datefilenotsigned = dol_filemtime($last_main_doc_file_not_signed);
509
510 if (empty($datefilenotsigned) || $datefilesigned > $datefilenotsigned) { // If file signed is more recent
511 $directdownloadlink = $object->getLastMainDocLink('order');
512 if ($directdownloadlink) {
513 print '<br><a href="'.$directdownloadlink.'">';
514 print img_mime($object->last_main_doc, '');
515 print $langs->trans("DownloadDocument").'</a>';
516 }
517 }
518 }
519 }
520 }
521
522 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
523 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
524 print '</td></tr>'."\n";
525} elseif ($source == 'contract') { // Signature on contract
526 $found = true;
527 $langs->load("contract");
528
529 $result = $object->fetch_thirdparty($object->socid);
530
531 // Proposer
532 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
533 print '</td><td class="CTableRow2">';
534 print img_picto('', 'company', 'class="pictofixedwidth"');
535 print '<b>'.$creditor.'</b>';
536 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
537 print '</td></tr>'."\n";
538
539 // Target
540 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
541 print '</td><td class="CTableRow2">';
542 print img_picto('', 'company', 'class="pictofixedwidth"');
543 print '<b>'.$object->thirdparty->name.'</b>';
544 print '</td></tr>'."\n";
545
546 // Object
547 $text = '<b>'.$langs->trans("SignatureContractRef", $object->ref).'</b>';
548 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
549 print '</td><td class="CTableRow2">'.$text;
550
551 $last_main_doc_file = $object->last_main_doc;
552
553 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
554 // It seems document has never been generated, or was generated and then deleted.
555 // So we try to regenerate it with its default template.
556 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
557 $object->generateDocument($defaulttemplate, $langs);
558 }
559
560 $directdownloadlink = $object->getLastMainDocLink('contract');
561 if ($directdownloadlink) {
562 print '<br><a href="'.$directdownloadlink.'">';
563 print img_mime($object->last_main_doc, '');
564 if ($message == "signed") {
565 print $langs->trans("DownloadSignedDocument").'</a>';
566 } else {
567 print $langs->trans("DownloadDocument").'</a>';
568 }
569 }
570
571
572 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
573 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
574 print '</td></tr>'."\n";
575} elseif ($source == 'fichinter') {
576 // Signature on fichinter
577 $found = true;
578 $langs->load("interventions");
579
580 $result = $object->fetch_thirdparty($object->socid);
581
582 // Proposer
583 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
584 print '</td><td class="CTableRow2">';
585 print img_picto('', 'company', 'class="pictofixedwidth"');
586 print '<b>'.$creditor.'</b>';
587 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
588 print '</td></tr>'."\n";
589
590 // Target
591 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
592 print '</td><td class="CTableRow2">';
593 print img_picto('', 'company', 'class="pictofixedwidth"');
594 print '<b>'.$object->thirdparty->name.'</b>';
595 print '</td></tr>'."\n";
596
597 // Object
598 $text = '<b>'.$langs->trans("SignatureFichinterRef", $object->ref).'</b>';
599 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
600 print '</td><td class="CTableRow2">'.$text;
601
602 $last_main_doc_file = $object->last_main_doc;
603
604 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
605 // It seems document has never been generated, or was generated and then deleted.
606 // So we try to regenerate it with its default template.
607 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
608 $object->generateDocument($defaulttemplate, $langs);
609 }
610
611 $directdownloadlink = $object->getLastMainDocLink('fichinter');
612 if ($directdownloadlink) {
613 print '<br><a href="'.$directdownloadlink.'">';
614 print img_mime($object->last_main_doc, '');
615 if ($message == "signed") {
616 print $langs->trans("DownloadSignedDocument").'</a>';
617 } else {
618 print $langs->trans("DownloadDocument").'</a>';
619 }
620 }
621 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
622 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
623 print '</td></tr>'."\n";
624} elseif ($source == 'societe_rib') {
625 $found = true;
626 $langs->loadLangs(array("companies", "commercial", "withdrawals"));
627
628 $result = $object->fetch_thirdparty();
629
630 // Proposer
631 print '<tr class="CTableRow2"><td class="CTableRow2">' . $langs->trans("CreditorName");
632 print '</td><td class="CTableRow2">';
633 print img_picto('', 'company', 'class="pictofixedwidth"');
634 print '<b>' . $creditor . '</b>';
635 print '<input type="hidden" name="creditor" value="' . $creditor . '">';
636 print '</td></tr>' . "\n";
637
638 // Target
639 print '<tr class="CTableRow2"><td class="CTableRow2">' . $langs->trans("ThirdParty");
640 print '</td><td class="CTableRow2">';
641 print img_picto('', 'company', 'class="pictofixedwidth"');
642 print '<b>' . $object->thirdparty->name . '</b>';
643 print '</td></tr>' . "\n";
644
645 // Object
646 $text = '<b>' . $langs->trans("Signature" . dol_ucfirst($source) . "Ref", $object->ref) . '</b>';
647 print '<tr class="CTableRow2"><td class="CTableRow2">' . $langs->trans("Designation");
648 print '</td><td class="CTableRow2">' . $text;
649
650 $last_main_doc_file = $object->last_main_doc;
651 $diroutput = $conf->societe->multidir_output[$object->thirdparty->entity].'/'
652 .dol_sanitizeFileName((string) $object->thirdparty->id).'/';
653 if ((empty($last_main_doc_file) ||
654 !dol_is_file($diroutput
655 .$langs->transnoentitiesnoconv("SepaMandateShort").' '.$object->id."-".dol_sanitizeFileName($object->rum).".pdf"))
656 && $message != "signed") {
657 // It seems document has never been generated, or was generated and then deleted.
658 // So we try to regenerate it with its default template.
659 //$defaulttemplate = 'sepamandate';
660 $defaulttemplate = getDolGlobalString("BANKADDON_PDF");
661
662 $object->setDocModel($user, $defaulttemplate);
663 $moreparams = array(
664 'use_companybankid' => $object->id,
665 'force_dir_output' => $diroutput
666 );
667 $result = $object->thirdparty->generateDocument($defaulttemplate, $langs, 0, 0, 0, $moreparams);
668 $object->last_main_doc = $object->thirdparty->last_main_doc;
669 }
670 $directdownloadlink = $object->getLastMainDocLink('company');
671 if ($directdownloadlink) {
672 print '<br><a href="'.$directdownloadlink.'">';
673 print img_mime($object->last_main_doc, '');
674 if ($message == "signed") {
675 print $langs->trans("DownloadSignedDocument").'</a>';
676 } else {
677 print $langs->trans("DownloadDocument").'</a>';
678 }
679 }
680} elseif ($source == 'expedition') {
681 // Signature on expedition
682 $found = true;
683 $langs->load("interventions");
684
685 $result = $object->fetch_thirdparty($object->socid);
686
687 // Proposer
688 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
689 print '</td><td class="CTableRow2">';
690 print img_picto('', 'company', 'class="pictofixedwidth"');
691 print '<b>'.$creditor.'</b>';
692 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
693 print '</td></tr>'."\n";
694
695 // Target
696 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
697 print '</td><td class="CTableRow2">';
698 print img_picto('', 'company', 'class="pictofixedwidth"');
699 print '<b>'.$object->thirdparty->name.'</b>';
700 print '</td></tr>'."\n";
701
702 // Object
703 $text = '<b>'.$langs->trans("SignatureFichinterRef", $object->ref).'</b>';
704 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
705 print '</td><td class="CTableRow2">'.$text;
706
707 $last_main_doc_file = $object->last_main_doc;
708 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
709 // It seems document has never been generated, or was generated and then deleted.
710 // So we try to regenerate it with its default template.
711 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
712 $object->generateDocument($defaulttemplate, $langs);
713 }
714 $directdownloadlink = $object->getLastMainDocLink('', 0, 0);
715 if ($directdownloadlink) {
716 print '<br><a href="'.$directdownloadlink.'">';
717 print img_mime($object->last_main_doc, '');
718 if ($message == "signed") {
719 print $langs->trans("DownloadSignedDocument").'</a>';
720 } else {
721 print $langs->trans("DownloadDocument").'</a>';
722 }
723 }
724 print '<input type="hidden" name="source" value="'.GETPOST("source", 'alpha').'">';
725 print '<input type="hidden" name="ref" value="'.$object->ref.'">';
726 print '</td></tr>'."\n";
727} else {
728 $found = true;
729 $langs->load('companies');
730
731 if (!empty($object->socid) || !empty($object->fk_soc)) {
732 $result = $object->fetch_thirdparty();
733 }
734
735 // Proposer
736 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Proposer");
737 print '</td><td class="CTableRow2">';
738 print img_picto('', 'company', 'class="pictofixedwidth"');
739 print '<b>'.$creditor.'</b>';
740 print '<input type="hidden" name="creditor" value="'.$creditor.'">';
741 print '</td></tr>'."\n";
742
743 // Target
744 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("ThirdParty");
745 print '</td><td class="CTableRow2">';
746 print img_picto('', 'company', 'class="pictofixedwidth"');
747 print '<b>'.$object->thirdparty->name.'</b>';
748 print '</td></tr>'."\n";
749
750 // Object
751 $text = '<b>'.$langs->trans("Signature".dol_ucfirst($source)."Ref", $object->ref).'</b>';
752 print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Designation");
753 print '</td><td class="CTableRow2">'.$text;
754
755 $last_main_doc_file = $object->last_main_doc;
756
757 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
758 // It seems document has never been generated, or was generated and then deleted.
759 // So we try to regenerate it with its default template.
760 $defaulttemplate = ''; // We force the use an empty string instead of $object->model_pdf to be sure to use a "main" default template and not the last one used.
761 $object->generateDocument($defaulttemplate, $langs);
762 }
763
764 $directdownloadlink = $object->getLastMainDocLink($source);
765 if ($directdownloadlink) {
766 print '<br><a href="'.$directdownloadlink.'">';
767 print img_mime($object->last_main_doc, '');
768 if ($message == "signed") {
769 print $langs->trans("DownloadSignedDocument").'</a>';
770 } else {
771 print $langs->trans("DownloadDocument").'</a>';
772 }
773 }
774}
775
776// Call Hook addFormSign
777$parameters = array('source' => $source);
778$reshook = $hookmanager->executeHooks('addFormSign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
779
780if (!$found) {
781 print '<tr><td class="center" colspan="2"><br><div class="warning">'.dol_escape_htmltag($langs->transnoentitiesnoconv("ErrorBadParameters")).'</div></td></tr>'."\n";
782}
783
784print '</table>'."\n";
785print "\n";
786
787if ($action != 'dosign') {
788 if ($found && !$error) {
789 // We are in a management option and no error
790 } else {
791 dol_print_error_email('ERRORNEWONLINESIGN');
792 }
793} else {
794 // Print
795}
796
797print '</td></tr>'."\n";
798print '<tr><td class="center">';
799
800
801if ($action == "dosign" && empty($cancel)) {
802 // Show the field to sign
803 print '<div class="tablepublicpayment">';
804 print '<input type="text" class="paddingleftonly marginleftonly paddingright marginrightonly marginbottomonly borderbottom" id="name" placeholder="'.$langs->trans("Lastname").'" spellcheck="false" autofocus>';
805 print '<div id="signature" style="border:solid;"></div>';
806 print '</div>';
807 print '<input type="button" class="small noborderall cursorpointer buttonreset" id="clearsignature" value="'.$langs->trans("ClearSignature").'">';
808
809 // Do not use class="reposition" here: It breaks the submit and there is a message on top to say it's ok, so going back top is better.
810 print '<div>';
811 print '<input type="button" class="button butActionSign marginleftonly marginrightonly" id="signbutton" value="'.$langs->trans("Sign").'">';
812 print '<input type="submit" class="button butActionDelete marginleftonly marginrightonly" name="cancel" value="'.$langs->trans("Cancel").'">';
813 print '</div>';
814
815 // Define $urlwithroot
816 $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
817 $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
818 //$urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost.
819 // TODO Replace DOL_URL_ROOT with $urlwithroot ?
820
821 // Add js code managed into the div #signature
822 $urltogo = $_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&source='.urlencode($source).'&message=signed&securekey='.urlencode($SECUREKEY).(isModEnabled('multicompany') ? '&entity='.(int) $entity : '');
823 print '<script language="JavaScript" type="text/javascript" src="'.DOL_URL_ROOT.'/public/includes/jquery/plugins/jSignature/jSignature.js"></script>
824 <script type="text/javascript">
825 $(document).ready(function() {
826 $("#signature").jSignature({ color:"#000", lineWidth:0, '.(empty($conf->dol_optimize_smallscreen) ? '' : 'width: 280, ').'height: 180});
827
828 $("#signature").on("change",function(){
829 $("#clearsignature").css("display","");
830 $("#signbutton").attr("disabled",false);
831 if(!$._data($("#signbutton")[0], "events")){
832 $("#signbutton").on("click",function(){
833 console.log("We click on button sign");
834 document.body.style.cursor = \'wait\';
835 var signature = $("#signature").jSignature("getData", "image");
836 var name = document.getElementById("name").value;
837 $.ajax({
838 type: "POST",
839 url: \''.DOL_URL_ROOT.'/core/ajax/onlineSign.php\',
840 dataType: "text",
841 data: {
842 "action" : \'importSignature\',
843 "token" : \''.newToken().'\',
844 "signaturebase64" : signature,
845 "onlinesignname" : name,
846 "ref" : \''.dol_escape_js($REF).'\',
847 "securekey" : \''.dol_escape_js($SECUREKEY).'\',
848 "mode" : \''.dol_escape_js($source).'\',
849 "entity" : \''.dol_escape_js((string) $entity).'\',
850 },
851 success: function(response) {
852 if (response.trim() === "success") {
853 console.log("Success on saving signature");
854 window.location.replace(\''.dol_escape_js($urltogo).'\');
855 } else {
856 document.body.style.cursor = \'auto\';
857 console.error(response);
858 alert("Error on calling the core/ajax/onlineSign.php. See console log.");
859 }
860 },
861 error: function(response) {
862 document.body.style.cursor = \'auto\';
863 console.error(response);
864 alert("Error on calling the core/ajax/onlineSign.php. "+response.responseText);
865 }
866 });
867 });
868 }
869 });
870
871 $("#clearsignature").on("click",function(){
872 $("#signature").jSignature("clear");
873 $("#signbutton").attr("disabled",true);
874 // document.getElementById("onlinesignname").value = "";
875 });
876
877 $("#signbutton").attr("disabled",true);
878 });
879 </script>';
880} else {
881 if ($source == 'proposal') {
882 if ($object->status == $object::STATUS_SIGNED) {
883 print '<br>';
884 if ($message == 'signed') {
885 print img_picto('', 'check', '', 0, 0, 0, '', 'size2x').'<br>';
886 print '<span class="ok">'.$langs->trans("PropalSigned").'</span>';
887 } else {
888 print img_picto('', 'check', '', 0, 0, 0, '', 'size2x').'<br>';
889 print '<span class="ok">'.$langs->trans("PropalAlreadySigned").'</span>';
890 }
891 } elseif ($object->status == $object::STATUS_NOTSIGNED) {
892 print '<br>';
893 if ($message == 'refused') {
894 print img_picto('', 'cross', '', 0, 0, 0, '', 'size2x').'<br>';
895 print '<span class="ok">'.$langs->trans("PropalRefused").'</span>';
896 } else {
897 print img_picto('', 'cross', '', 0, 0, 0, '', 'size2x').'<br>';
898 print '<span class="warning">'.$langs->trans("PropalAlreadyRefused").'</span>';
899 }
900 } else {
901 print '<input type="submit" class="butAction butActionSign small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignPropal").'">';
902 print '<input name="refusepropal" type="submit" class="butActionDelete small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("RefusePropal").'">';
903 }
904 } elseif ($source == 'contract') {
905 if ($message == 'signed') {
906 print '<span class="ok">'.$langs->trans("ContractSigned").'</span>';
907 } else {
908 print '<input type="submit" class="butAction butActionSign small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignContract").'">';
909 }
910 } elseif ($source == 'fichinter') {
911 if ($message == 'signed') {
912 print '<span class="ok">'.$langs->trans("FichinterSigned").'</span>';
913 } else {
914 print '<input type="submit" class="butAction butActionSign small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignFichinter").'">';
915 }
916 } elseif ($source == 'expedition') {
917 if ($message == 'signed' || $object->signed_status == Expedition::$SIGNED_STATUSES['STATUS_SIGNED_SENDER']) {
918 print '<span class="ok">'.$langs->trans("ExpeditionSigned").'</span>';
919 } else {
920 print '<input type="submit" class="butAction butActionSign small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("SignExpedition").'">';
921 }
922 } else {
923 if ($message == 'signed') {
924 print '<span class="ok">'.$langs->trans(dol_ucfirst($source)."Signed").'</span>';
925 } else {
926 print '<input type="submit" class="butAction butActionSign small wraponsmartphone marginbottomonly marginleftonly marginrightonly reposition" value="'.$langs->trans("Sign".dol_ucfirst($source)).'">';
927 }
928 }
929}
930print '</td></tr>'."\n";
931print '</table>'."\n";
932
933print '</form>'."\n";
934print '</div>'."\n";
935print '<br>';
936
937
939
940llxFooter('', 'public');
941
942$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
global $dolibarr_main_url_root
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
$object ref
Definition info.php:90
Class to manage customers orders.
Class to manage bank accounts description of third parties.
Class to manage generation of HTML components Only common components must be here.
Class to manage proposals.
htmlPrintOnlineHeader($mysoc, $langs, $showlogo=1, $alttext='', $subimageconst='', $altlogo1='', $altlogo2='')
Show the header of a company in HTML public pages.
htmlPrintOnlineFooter($fromcompany, $langs, $addformmessage=0, $suffix='', $object=null)
Show footer of company in HTML public pages.
global $mysoc
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_filemtime($pathoffile)
Return time of a file.
dol_is_file($pathoffile)
Return if path is a file.
dol_now($mode='gmt')
Return date for now.
dol_ucfirst($string, $encoding="UTF-8")
Convert first character of the first word of a string to upper.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
dol_strtoupper($string, $encoding="UTF-8")
Convert a string to upper.
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
dol_print_error_email($prefixcode, $errormessage='', $errormessages=array(), $morecss='error', $email='')
Show a public email and error code to contact if technical error.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.
dol_hash($chain, $type='0', $nosalt=0, $mode=0)
Returns a hash (non reversible encryption) of a string.
dol_verifyHash($chain, $hash, $type='0')
Compute a hash and compare it to the given one For backward compatibility reasons,...