dolibarr 21.0.0-alpha
onlineSign.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
3 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
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
25if (!defined('NOTOKENRENEWAL')) {
26 define('NOTOKENRENEWAL', '1'); // Disables token renewal
27}
28if (!defined('NOREQUIREHTML')) {
29 define('NOREQUIREHTML', '1');
30}
31if (!defined('NOREQUIREAJAX')) {
32 define('NOREQUIREAJAX', '1');
33}
34// Needed to create other objects with workflow
35/*if (!defined('NOREQUIRESOC')) {
36 define('NOREQUIRESOC', '1');
37}*/
38// Do not check anti CSRF attack test
39if (!defined('NOREQUIREMENU')) {
40 define('NOREQUIREMENU', '1');
41}
42// If there is no need to load and show top and left menu
43if (!defined("NOLOGIN")) {
44 define("NOLOGIN", '1');
45}
46if (!defined('NOIPCHECK')) {
47 define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
48}
49if (!defined('NOBROWSERNOTIF')) {
50 define('NOBROWSERNOTIF', '1');
51}
52$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1)); // Keep $_GET and $_POST here. GETPOST not yet defined.
53if (is_numeric($entity)) {
54 define("DOLENTITY", $entity);
55}
56include '../../main.inc.php';
57require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
58
59$action = GETPOST('action', 'aZ09');
60
61$signature = GETPOST('signaturebase64');
62$ref = GETPOST('ref', 'aZ09');
63$mode = GETPOST('mode', 'aZ09'); // 'proposal', ...
64$SECUREKEY = GETPOST("securekey"); // Secure key
65$online_sign_name = GETPOST("onlinesignname");
66
67$error = 0;
68$response = "";
69
70$type = $mode;
71
72// Security check
73$securekeyseed = '';
74if ($type == 'proposal') {
75 $securekeyseed = getDolGlobalString('PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN');
76} elseif ($type == 'contract') {
77 $securekeyseed = getDolGlobalString('CONTRACT_ONLINE_SIGNATURE_SECURITY_TOKEN');
78} elseif ($type == 'fichinter') {
79 $securekeyseed = getDolGlobalString('FICHINTER_ONLINE_SIGNATURE_SECURITY_TOKEN');
80} else {
81 $securekeyseed = getDolGlobalString(strtoupper($type).'_ONLINE_SIGNATURE_SECURITY_TOKEN');
82}
83
84if (empty($SECUREKEY) || !dol_verifyHash($securekeyseed . $type . $ref . (!isModEnabled('multicompany') ? '' : $entity), $SECUREKEY, '0')) {
85 httponly_accessforbidden('Bad value for securitykey. Value provided ' . dol_escape_htmltag($SECUREKEY) . ' does not match expected value for ref=' . dol_escape_htmltag($ref), 403);
86}
87
88// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
89$hookmanager->initHooks(array('ajaxonlinesign'));
90
91
92/*
93 * Actions
94 */
95
96// None
97
98
99/*
100 * View
101 */
102
104
105if ($action == "importSignature") {
106 $issignatureok = (!empty($signature) && $signature[0] == "image/png;base64");
107 if ($issignatureok) {
108 $signature = $signature[1];
109 $data = base64_decode($signature);
110
111 if ($mode == "propale" || $mode == 'proposal') {
112 require_once DOL_DOCUMENT_ROOT . '/comm/propal/class/propal.class.php';
113 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
114 $object = new Propal($db);
115 $object->fetch(0, $ref);
116
117 $upload_dir = !empty($conf->propal->multidir_output[$object->entity]) ? $conf->propal->multidir_output[$object->entity] : $conf->propal->dir_output;
118 $upload_dir .= '/' . dol_sanitizeFileName($object->ref) . '/';
119
120 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
121 $default_font = pdf_getPDFFont($langs); // Must be after pdf_getInstance
122 $langs->loadLangs(array("main", "companies"));
123
124 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
125 $filename = "signatures/" . $date . "_signature.png";
126 if (!is_dir($upload_dir . "signatures/")) {
127 if (!dol_mkdir($upload_dir . "signatures/")) {
128 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
129 $error++;
130 }
131 }
132
133 if (!$error) {
134 $return = file_put_contents($upload_dir . $filename, $data);
135 if ($return == false) {
136 $error++;
137 $response = 'Error file_put_content: failed to create signature file.';
138 }
139 }
140
141 if (!$error) {
142 // Defined modele of doc
143 $last_main_doc_file = $object->last_main_doc;
144 $directdownloadlink = $object->getLastMainDocLink('proposal'); // url to download the $object->last_main_doc
145
146 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
147 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
148 $newpdffilename = $upload_dir . $ref . "_signed-" . $date . ".pdf";
149 $sourcefile = $upload_dir . $ref . ".pdf";
150
151 if (dol_is_file($sourcefile)) {
152 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
153 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
154 if ($reshook < 0) {
155 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
156 }
157
158 if (empty($reshook)) {
159 // We build the new PDF
160 $pdf = pdf_getInstance();
161 if (class_exists('TCPDF')) {
162 $pdf->setPrintHeader(false);
163 $pdf->setPrintFooter(false);
164 }
165 $pdf->SetFont(pdf_getPDFFont($langs));
166
167 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
168 $pdf->SetCompression(false);
169 }
170
171 //$pdf->Open();
172 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
173
174 $param = array();
175 $param['online_sign_name'] = $online_sign_name;
176 $param['pathtoimage'] = $upload_dir . $filename;
177
178 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
179 for ($i = 1; $i < ($pagecount + 1); $i++) {
180 try {
181 $tppl = $pdf->importPage($i);
182 $s = $pdf->getTemplatesize($tppl);
183 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
184 $pdf->useTemplate($tppl);
185 $propalsignonspecificpage = getDolGlobalInt("PROPAL_SIGNATURE_ON_SPECIFIC_PAGE");
186 if ($propalsignonspecificpage < 0) {
187 $propalsignonspecificpage = $pagecount - abs($propalsignonspecificpage);
188 }
189
190 if (getDolGlobalString("PROPAL_SIGNATURE_ON_ALL_PAGES") || $propalsignonspecificpage == $i) {
191 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
192 // TODO Get position of box from PDF template
193
194 if (getDolGlobalString("PROPAL_SIGNATURE_XFORIMGSTART")) {
195 $param['xforimgstart'] = getDolGlobalString("PROPAL_SIGNATURE_XFORIMGSTART");
196 } else {
197 $param['xforimgstart'] = (empty($s['w']) ? 120 : round($s['w'] / 2) + 15);
198 }
199 if (getDolGlobalString("PROPAL_SIGNATURE_YFORIMGSTART")) {
200 $param['yforimgstart'] = getDolGlobalString("PROPAL_SIGNATURE_YFORIMGSTART");
201 } else {
202 $param['yforimgstart'] = (empty($s['h']) ? 240 : $s['h'] - 60);
203 }
204 if (getDolGlobalString("PROPAL_SIGNATURE_WFORIMG")) {
205 $param['wforimg'] = getDolGlobalString("PROPAL_SIGNATURE_WFORIMG");
206 } else {
207 $param['wforimg'] = $s['w'] - 20 - $param['xforimgstart'];
208 }
209
210 dolPrintSignatureImage($pdf, $langs, $param);
211 }
212 } catch (Exception $e) {
213 dol_syslog("Error when manipulating the PDF " . $sourcefile . " by onlineSign: " . $e->getMessage(), LOG_ERR);
214 $response = $e->getMessage();
215 $error++;
216 }
217 }
218
219 if (!getDolGlobalString("PROPAL_SIGNATURE_ON_ALL_PAGES") && !getDolGlobalInt("PROPAL_SIGNATURE_ON_SPECIFIC_PAGE")) {
220 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
221 // TODO Get position of box from PDF template
222
223 if (getDolGlobalString("PROPAL_SIGNATURE_XFORIMGSTART")) {
224 $param['xforimgstart'] = getDolGlobalString("PROPAL_SIGNATURE_XFORIMGSTART");
225 } else {
226 $param['xforimgstart'] = (empty($s['w']) ? 120 : round($s['w'] / 2) + 15);
227 }
228 if (getDolGlobalString("PROPAL_SIGNATURE_YFORIMGSTART")) {
229 $param['yforimgstart'] = getDolGlobalString("PROPAL_SIGNATURE_YFORIMGSTART");
230 } else {
231 $param['yforimgstart'] = (empty($s['h']) ? 240 : $s['h'] - 60);
232 }
233 if (getDolGlobalString("PROPAL_SIGNATURE_WFORIMG")) {
234 $param['wforimg'] = getDolGlobalString("PROPAL_SIGNATURE_WFORIMG");
235 } else {
236 $param['wforimg'] = $s['w'] - 20 - $param['xforimgstart'];
237 }
238
239 dolPrintSignatureImage($pdf, $langs, $param);
240 }
241
242 //$pdf->Close();
243 $pdf->Output($newpdffilename, "F");
244
245 // Index the new file and update the last_main_doc property of object.
246 $object->indexFile($newpdffilename, 1);
247 }
248 }
249 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
250 // Adding signature on .ODT not yet supported
251 // TODO
252 } else {
253 // Document format not supported to insert online signature.
254 // We should just create an image file with the signature.
255 }
256 }
257
258 if (!$error) {
259 $db->begin();
260
261 $online_sign_ip = getUserRemoteIP();
262
263 $sql = "UPDATE " . MAIN_DB_PREFIX . "propal";
264 $sql .= " SET fk_statut = " . ((int) $object::STATUS_SIGNED) . ", note_private = '" . $db->escape($object->note_private) . "',";
265 $sql .= " date_signature = '" . $db->idate(dol_now()) . "',";
266 $sql .= " online_sign_ip = '" . $db->escape($online_sign_ip) . "'";
267 if ($online_sign_name) {
268 $sql .= ", online_sign_name = '" . $db->escape($online_sign_name) . "'";
269 }
270 $sql .= " WHERE rowid = " . ((int) $object->id);
271
272 dol_syslog(__FILE__, LOG_DEBUG);
273 $resql = $db->query($sql);
274 if (!$resql) {
275 $error++;
276 } else {
277 $num = $db->affected_rows($resql);
278 }
279
280 if (!$error) {
281 if (method_exists($object, 'call_trigger')) {
282 //customer is not a user !?! so could we use same user as validation ?
283 $user = new User($db);
284 $user->fetch($object->user_validation_id);
285 $object->context = array('closedfromonlinesignature' => 'closedfromonlinesignature');
286 $result = $object->call_trigger('PROPAL_CLOSE_SIGNED', $user);
287 if ($result < 0) {
288 $error++;
289 $response = "error in trigger " . $object->error;
290 } else {
291 $soc = new Societe($db);
292 $soc->id = $object->socid;
293 $result = $soc->setAsCustomer();
294 if ($result < 0) {
295 $error++;
296 $response = $db->lasterror();
297 } else {
298 $response = "success";
299 }
300 }
301 } else {
302 $response = "success";
303 }
304 } else {
305 $error++;
306 $response = "error sql";
307 }
308
309 if (!$error) {
310 $db->commit();
311 $response = "success";
312 setEventMessages("PropalSigned", null, 'warnings');
313 } else {
314 $db->rollback();
315 }
316 }
317 } elseif ($mode == 'contract') {
318 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
319 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
320 $object = new Contrat($db);
321 $object->fetch(0, $ref);
322
323 $upload_dir = !empty($conf->contrat->multidir_output[$object->entity]) ? $conf->contrat->multidir_output[$object->entity] : $conf->contrat->dir_output;
324 $upload_dir .= '/' . dol_sanitizeFileName($object->ref) . '/';
325
326 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
327 $filename = "signatures/" . $date . "_signature.png";
328 if (!is_dir($upload_dir . "signatures/")) {
329 if (!dol_mkdir($upload_dir . "signatures/")) {
330 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
331 $error++;
332 }
333 }
334
335 if (!$error) {
336 $return = file_put_contents($upload_dir . $filename, $data);
337 if ($return == false) {
338 $error++;
339 $response = 'Error file_put_content: failed to create signature file.';
340 }
341 }
342
343 if (!$error) {
344 // Defined modele of doc
345 $last_main_doc_file = $object->last_main_doc;
346 $directdownloadlink = $object->getLastMainDocLink('contrat'); // url to download the $object->last_main_doc
347
348 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
349 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
350 $newpdffilename = $upload_dir . $ref . "_signed-" . $date . ".pdf";
351 $sourcefile = $upload_dir . $ref . ".pdf";
352
353 if (dol_is_file($sourcefile)) {
354 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
355 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
356 if ($reshook < 0) {
357 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
358 }
359
360 if (empty($reshook)) {
361 // We build the new PDF
362 $pdf = pdf_getInstance();
363 if (class_exists('TCPDF')) {
364 $pdf->setPrintHeader(false);
365 $pdf->setPrintFooter(false);
366 }
367 $pdf->SetFont(pdf_getPDFFont($langs));
368
369 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
370 $pdf->SetCompression(false);
371 }
372
373 //$pdf->Open();
374 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
375
376 $param = array();
377 $param['online_sign_name'] = $online_sign_name;
378 $param['pathtoimage'] = $upload_dir . $filename;
379
380 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
381 for ($i = 1; $i < ($pagecount + 1); $i++) {
382 try {
383 $tppl = $pdf->importPage($i);
384 $s = $pdf->getTemplatesize($tppl);
385 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
386 $pdf->useTemplate($tppl);
387
388 if (getDolGlobalString("CONTRACT_SIGNATURE_ON_ALL_PAGES")) {
389 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
390 // TODO Get position of box from PDF template
391
392 if (getDolGlobalString("CONTRACT_SIGNATURE_XFORIMGSTART")) {
393 $param['xforimgstart'] = getDolGlobalString("CONTRACT_SIGNATURE_XFORIMGSTART");
394 } else {
395 $param['xforimgstart'] = (empty($s['w']) ? 110 : $s['w'] / 2 - 0);
396 }
397 if (getDolGlobalString("CONTRACT_SIGNATURE_YFORIMGSTART")) {
398 $param['yforimgstart'] = getDolGlobalString("CONTRACT_SIGNATURE_YFORIMGSTART");
399 } else {
400 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 62);
401 }
402 if (getDolGlobalString("CONTRACT_SIGNATURE_WFORIMG")) {
403 $param['wforimg'] = getDolGlobalString("CONTRACT_SIGNATURE_WFORIMG");
404 } else {
405 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
406 }
407
408 dolPrintSignatureImage($pdf, $langs, $param);
409 }
410 } catch (Exception $e) {
411 dol_syslog("Error when manipulating some PDF by onlineSign: " . $e->getMessage(), LOG_ERR);
412 $response = $e->getMessage();
413 $error++;
414 }
415 }
416
417 if (!getDolGlobalString("CONTRACT_SIGNATURE_ON_ALL_PAGES")) {
418 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
419 // TODO Get position of box from PDF template
420
421 $param['xforimgstart'] = (empty($s['w']) ? 110 : $s['w'] / 2 - 0);
422 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 62);
423 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
424
425 dolPrintSignatureImage($pdf, $langs, $param);
426 }
427
428 //$pdf->Close();
429 $pdf->Output($newpdffilename, "F");
430
431 // Index the new file and update the last_main_doc property of object.
432 $object->indexFile($newpdffilename, 1);
433 }
434 }
435 if (!$error) {
436 $response = "success";
437 }
438 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
439 // Adding signature on .ODT not yet supported
440 // TODO
441 } else {
442 // Document format not supported to insert online signature.
443 // We should just create an image file with the signature.
444 }
445 $user = new User($db);
446 $object->setSignedStatus($user, Contrat::$SIGNED_STATUSES['STATUS_SIGNED_RECEIVER_ONLINE'], 0, 'CONTRACT_MODIFY');
447 }
448 } elseif ($mode == 'fichinter') {
449 require_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php';
450 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
451 $object = new Fichinter($db);
452 $object->fetch(0, $ref);
453
454 $upload_dir = !empty($conf->ficheinter->multidir_output[$object->entity]) ? $conf->ficheinter->multidir_output[$object->entity] : $conf->ficheinter->dir_output;
455 $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
456
457 $langs->loadLangs(array("main", "companies"));
458
459 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
460 $default_font = pdf_getPDFFont($langs); // Must be
461
462 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
463 $filename = "signatures/" . $date . "_signature.png";
464 if (!is_dir($upload_dir . "signatures/")) {
465 if (!dol_mkdir($upload_dir . "signatures/")) {
466 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
467 $error++;
468 }
469 }
470
471 if (!$error) {
472 $return = file_put_contents($upload_dir . $filename, $data);
473 if ($return == false) {
474 $error++;
475 $response = 'Error file_put_content: failed to create signature file.';
476 }
477 }
478
479 if (!$error) {
480 // Defined modele of doc
481 $last_main_doc_file = $object->last_main_doc;
482 $directdownloadlink = $object->getLastMainDocLink('fichinter'); // url to download the $object->last_main_doc
483
484 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
485 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
486 $newpdffilename = $upload_dir . $ref . "_signed-" . $date . ".pdf";
487 $sourcefile = $upload_dir . $ref . ".pdf";
488
489 if (dol_is_file($sourcefile)) {
490 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
491 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
492 if ($reshook < 0) {
493 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
494 }
495
496 if (empty($reshook)) {
497 // We build the new PDF
498 $pdf = pdf_getInstance();
499 if (class_exists('TCPDF')) {
500 $pdf->setPrintHeader(false);
501 $pdf->setPrintFooter(false);
502 }
503 $pdf->SetFont(pdf_getPDFFont($langs));
504
505 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
506 $pdf->SetCompression(false);
507 }
508
509 //$pdf->Open();
510 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
511
512 $param = array();
513 $param['online_sign_name'] = $online_sign_name;
514 $param['pathtoimage'] = $upload_dir . $filename;
515
516 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
517 for ($i = 1; $i < ($pagecount + 1); $i++) {
518 try {
519 $tppl = $pdf->importPage($i);
520 $s = $pdf->getTemplatesize($tppl);
521 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
522 $pdf->useTemplate($tppl);
523
524 if (getDolGlobalString("FICHINTER_SIGNATURE_ON_ALL_PAGES")) {
525 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
526 // TODO Get position of box from PDF template
527
528 if (getDolGlobalString("FICHINTER_SIGNATURE_XFORIMGSTART")) {
529 $param['xforimgstart'] = getDolGlobalString("FICHINTER_SIGNATURE_XFORIMGSTART");
530 } else {
531 $param['xforimgstart'] = (empty($s['w']) ? 110 : $s['w'] / 2 - 2);
532 }
533 if (getDolGlobalString("FICHINTER_SIGNATURE_YFORIMGSTART")) {
534 $param['yforimgstart'] = getDolGlobalString("FICHINTER_SIGNATURE_YFORIMGSTART");
535 } else {
536 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 38);
537 }
538 if (getDolGlobalString("FICHINTER_SIGNATURE_WFORIMG")) {
539 $param['wforimg'] = getDolGlobalString("FICHINTER_SIGNATURE_WFORIMG");
540 } else {
541 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 20);
542 }
543
544 dolPrintSignatureImage($pdf, $langs, $param);
545 }
546 } catch (Exception $e) {
547 dol_syslog("Error when manipulating some PDF by onlineSign: " . $e->getMessage(), LOG_ERR);
548 $response = $e->getMessage();
549 $error++;
550 }
551 }
552
553 if (!getDolGlobalString("FICHINTER_SIGNATURE_ON_ALL_PAGES")) {
554 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
555 // TODO Get position of box from PDF template
556
557 $param['xforimgstart'] = (empty($s['w']) ? 110 : $s['w'] / 2 - 2);
558 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 38);
559 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 20);
560
561 dolPrintSignatureImage($pdf, $langs, $param);
562 }
563
564 //$pdf->Close();
565 $pdf->Output($newpdffilename, "F");
566
567 // Index the new file and update the last_main_doc property of object.
568 $object->indexFile($newpdffilename, 1);
569 }
570 }
571 if (!$error) {
572 $response = "success";
573 }
574 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
575 // Adding signature on .ODT not yet supported
576 // TODO
577 } else {
578 // Document format not supported to insert online signature.
579 // We should just create an image file with the signature.
580 }
581 $user = new User($db);
582 $object->setSignedStatus($user, Fichinter::$SIGNED_STATUSES['STATUS_SIGNED_RECEIVER_ONLINE'], 0, 'FICHINTER_MODIFY');
583 }
584 } elseif ($mode == "societe_rib") {
585 $langs->load('withdrawals');
586 require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
587 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
588 $modelpath = "core/modules/bank/doc/";
589 $object = new CompanyBankAccount($db);
590 $object->fetch(0, $ref);
591 if (!empty($object->id)) {
592 $object->fetch_thirdparty();
593
594 $upload_dir = $conf->societe->multidir_output[$object->thirdparty->entity] . '/' . dol_sanitizeFileName((string) $object->thirdparty->id) . '/';
595
596 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
597 $default_font = pdf_getPDFFont($langs); // Must be after pdf_getInstance
598 $langs->loadLangs(array("main", "companies"));
599
600 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
601 $filename = "signatures/" . $date . "_signature.png";
602 if (!dol_is_dir($upload_dir . "signatures/")) {
603 if (!dol_mkdir($upload_dir . "signatures/")) {
604 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
605 $error++;
606 }
607 }
608 if (!dol_is_writable($upload_dir . "signatures/")) {
609 $response = "Error directory " . $upload_dir . "signatures/ is not writable";
610 $error++;
611 }
612 if (!dol_is_writable(DOL_DATA_ROOT.'/admin/temp/')) { // This is used by TCPDF as working directory
613 $response = "Error directory " . DOL_DATA_ROOT."/admin/temp/ is not writable";
614 $error++;
615 }
616
617 if (!$error) {
618 $return = file_put_contents($upload_dir . $filename, $data);
619 if ($return == false) {
620 $error++;
621 $response = 'Error file_put_content: failed to create signature file.';
622 }
623 }
624
625 if (!$error) {
626 // Defined modele of doc
627 $last_main_doc_file = $object->last_main_doc;
628 $last_modelpdf = $object->model_pdf;
629 $directdownloadlink = $object->getLastMainDocLink('company'); // url to download the $object->last_main_doc
630
631 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
632 $sourcefile = '';
633 $newpdffilename = '';
634 if ($last_modelpdf == 'sepamandate') {
635 $newpdffilename = $upload_dir . $langs->transnoentitiesnoconv("SepaMandateShort") . ' ' . dol_sanitizeFileName($object->ref) . "-" . dol_sanitizeFileName($object->rum) . "_signed-" . $date . ".pdf";
636 $sourcefile = $upload_dir . $langs->transnoentitiesnoconv("SepaMandateShort") . ' ' . dol_sanitizeFileName($object->ref) . "-" . dol_sanitizeFileName($object->rum) . ".pdf";
637 }
638 if (dol_is_file($sourcefile)) {
639 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
640 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
641 if ($reshook < 0) {
642 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
643 }
644
645 if (empty($reshook)) {
646 // We build the new PDF
647 $pdf = pdf_getInstance();
648 if (class_exists('TCPDF')) {
649 $pdf->setPrintHeader(false);
650 $pdf->setPrintFooter(false);
651 }
652 $pdf->SetFont(pdf_getPDFFont($langs));
653
654 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
655 $pdf->SetCompression(false);
656 }
657
658 //$pdf->Open();
659 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
660
661 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
662 for ($i = 1; $i < ($pagecount + 1); $i++) {
663 try {
664 $tppl = $pdf->importPage($i);
665 $s = $pdf->getTemplatesize($tppl);
666 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
667 $pdf->useTemplate($tppl);
668 } catch (Exception $e) {
669 dol_syslog("Error when manipulating the PDF " . $sourcefile . " by onlineSign: " . $e->getMessage(), LOG_ERR);
670 $response = $e->getMessage();
671 $error++;
672 }
673 }
674
675
676 // Get position of box from PDF template
677 $file = '';
678 $classname = '';
679 $filefound = '';
680 $dirmodels = array('/');
681 if (is_array($conf->modules_parts['models'])) {
682 $dirmodels = array_merge($dirmodels, $conf->modules_parts['models']);
683 }
684 foreach ($dirmodels as $reldir) {
685 $file = "pdf_" . $last_modelpdf . ".modules.php";
686 // On vérifie l'emplacement du modele
687 $file = dol_buildpath($reldir . $modelpath . $file, 0);
688 if (file_exists($file)) {
689 $filefound = $file;
690 $classname = 'pdf_' . $last_modelpdf;
691 break;
692 }
693 }
694
695 if ($filefound === '') {
696 $response = $langs->trans("Error") . ' Failed to load doc generator with modelpaths=' . $modelpath . ' - modele=' . $last_modelpdf;
697 dol_syslog($response, LOG_ERR);
698 $error++;
699 }
700
701 if (!$error && $classname !== '') {
702 // If PDF template class was found
703 require_once $file;
704
705 $objPDF = new $classname($db);
706
707 $pdf->SetFont($default_font, '', $default_font_size - 1);
708
709 $xForDate = $objPDF->marge_gauche;
710 $yForDate = $objPDF->page_hauteur - $objPDF->heightforinfotot - $objPDF->heightforfreetext - $objPDF->heightforfooter + 10;
711 $pdf->SetXY($xForDate, $yForDate);
712 $pdf->MultiCell(100, 4, dol_print_date(dol_now(), "daytext", false, $langs, true), 0, 'L');
713
714 $xforimgstart = $objPDF->xPosSignArea;
715 $yforimgstart = $yForDate - 5;
716 $wforimg = $s['w'] - 20 - $xforimgstart;
717
718 $param = array();
719 $param['online_sign_name'] = $online_sign_name;
720 $param['pathtoimage'] = $upload_dir . $filename;
721
722 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
723 // TODO Get position of box from PDF template
724
725 $param['xforimgstart'] = $xforimgstart;
726 $param['yforimgstart'] = $yforimgstart;
727 $param['wforimg'] = $wforimg;
728
729 dolPrintSignatureImage($pdf, $langs, $param);
730 }
731 //$pdf->Close();
732 $pdf->Output($newpdffilename, "F");
733
734 // Index the new file and update the last_main_doc property of object.
735 $object->indexFile($newpdffilename, 1);
736 }
737 }
738 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
739 // Adding signature on .ODT not yet supported
740 // TODO
741 } else {
742 // Document format not supported to insert online signature.
743 // We should just create an image file with the signature.
744 }
745 }
746 } else {
747 $error++;
748 $response = "cannot find BAN/RIB";
749 }
750
751 if (!$error) {
752 $db->begin();
753
754 $online_sign_ip = getUserRemoteIP();
755
756 $sql = "UPDATE " . MAIN_DB_PREFIX . $object->table_element;
757 $sql .= " SET ";
758 $sql .= " date_signature = '" . $db->idate(dol_now()) . "',";
759 $sql .= " online_sign_ip = '" . $db->escape($online_sign_ip) . "'";
760 if ($online_sign_name) {
761 $sql .= ", online_sign_name = '" . $db->escape($online_sign_name) . "'";
762 }
763 //$sql .= ", last_main_doc = '" . $db->escape($object->element'..') . "'";
764
765 $sql .= " WHERE rowid = " . ((int) $object->id);
766
767 dol_syslog(__FILE__, LOG_DEBUG);
768 $resql = $db->query($sql);
769 if (!$resql) {
770 $error++;
771 } else {
772 $num = $db->affected_rows($resql);
773 }
774
775 if (!$error) {
776 $response = "success";
777 } else {
778 $error++;
779 $response = "error sql";
780 }
781
782 if (!$error) {
783 $db->commit();
784 $response = "success";
785 setEventMessages(dol_ucfirst($mode)."Signed", null, 'warnings');
786 } else {
787 $db->rollback();
788 }
789 }
790 } elseif ($mode == 'expedition') {
791 require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
792 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
793
794 $object = new Expedition($db);
795 $object->fetch(0, $ref);
796
797 $upload_dir = $conf->expedition->dir_output."/sending/";
798 $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
799
800 $langs->loadLangs(array("main", "companies"));
801
802 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
803 $default_font = pdf_getPDFFont($langs); // Must be
804
805 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
806 $filename = "signatures/" . $date . "_signature.png";
807 if (!is_dir($upload_dir . "signatures/")) {
808 if (!dol_mkdir($upload_dir . "signatures/")) {
809 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
810 $error++;
811 }
812 }
813
814 if (!$error) {
815 $return = file_put_contents($upload_dir . $filename, $data);
816 if ($return == false) {
817 $error++;
818 $response = 'Error file_put_content: failed to create signature file.';
819 }
820 }
821
822 if (!$error) {
823 $last_main_doc_file = $object->last_main_doc;
824 // Defined modele of doc
825 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
826 // It seems document has never been generated, or was generated and then deleted.
827 // So we try to regenerate it with its default template.
828 $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.
829 $object->generateDocument($defaulttemplate, $langs);
830 }
831 $last_main_doc_file = $object->last_main_doc;
832 $directdownloadlink = $object->getLastMainDocLink('expedition'); // url to download the $object->last_main_doc
833
834 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
835 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
836 $newpdffilename = $upload_dir . $ref . "_signed-" . $date . ".pdf";
837 $sourcefile = $upload_dir . $ref . ".pdf";
838
839 if (dol_is_file($sourcefile)) {
840 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
841 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
842 if ($reshook < 0) {
843 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
844 }
845
846 if (empty($reshook)) {
847 // We build the new PDF
848 $pdf = pdf_getInstance();
849 if (class_exists('TCPDF')) {
850 $pdf->setPrintHeader(false);
851 $pdf->setPrintFooter(false);
852 }
853 $pdf->SetFont(pdf_getPDFFont($langs));
854
855 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
856 $pdf->SetCompression(false);
857 }
858
859 //$pdf->Open();
860 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
861
862 $param = array();
863 $param['online_sign_name'] = $online_sign_name;
864 $param['pathtoimage'] = $upload_dir . $filename;
865
866 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
867 for ($i = 1; $i < ($pagecount + 1); $i++) {
868 try {
869 $tppl = $pdf->importPage($i);
870 $s = $pdf->getTemplatesize($tppl);
871 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
872 $pdf->useTemplate($tppl);
873
874 if (getDolGlobalString("SHIPMENT_SIGNATURE_ON_ALL_PAGES")) {
875 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
876 // TODO Get position of box from PDF template
877
878 $param['xforimgstart'] = 111;
879 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 60);
880 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
881
882 dolPrintSignatureImage($pdf, $langs, $param);
883 }
884 } catch (Exception $e) {
885 dol_syslog("Error when manipulating some PDF by onlineSign: " . $e->getMessage(), LOG_ERR);
886 $response = $e->getMessage();
887 $error++;
888 }
889 }
890
891 if (!getDolGlobalString("SHIPMENT_SIGNATURE_ON_ALL_PAGES")) {
892 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
893 // TODO Get position of box from PDF template
894
895 $param['xforimgstart'] = 111;
896 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 60);
897 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
898
899 dolPrintSignatureImage($pdf, $langs, $param);
900 }
901
902 //$pdf->Close();
903 $pdf->Output($newpdffilename, "F");
904
905 // Index the new file and update the last_main_doc property of object.
906 $object->indexFile($newpdffilename, 1);
907 }
908 }
909 if (!$error) {
910 $response = "success";
911 }
912 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
913 // Adding signature on .ODT not yet supported
914 // TODO
915 } else {
916 // Document format not supported to insert online signature.
917 // We should just create an image file with the signature.
918 }
919 }
920 $user = new User($db);
921 $object->setSignedStatus($user, Expedition::$SIGNED_STATUSES['STATUS_SIGNED_RECEIVER_ONLINE'], 0, 'SHIPPING_MODIFY');
922 }
923 } else {
924 $error++;
925 $response = 'error signature_not_found';
926 }
927}
928
929if ($error) {
930 http_response_code(501);
931}
932
933echo $response;
934
935
944function dolPrintSignatureImage(TCPDF $pdf, $langs, $params)
945{
946 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
947 $default_font = pdf_getPDFFont($langs); // Must be
948 $xforimgstart = $params['xforimgstart'];
949 $yforimgstart = $params['yforimgstart'];
950 $wforimg = $params['wforimg'];
951
952 $pdf->SetXY($xforimgstart, $yforimgstart + round($wforimg / 4) - 4);
953 $pdf->SetFont($default_font, '', $default_font_size - 1);
954 $pdf->SetTextColor(80, 80, 80);
955 $pdf->MultiCell($wforimg, 4, $langs->trans("Signature") . ': ' . dol_print_date(dol_now(), "day", false, $langs, true). ' - '.$params['online_sign_name'], 0, 'L');
956 //$pdf->SetXY($xforimgstart, $yforimgstart + round($wforimg / 4));
957 //$pdf->MultiCell($wforimg, 4, $langs->trans("Lastname") . ': ' . $online_sign_name, 0, 'L');
958
959 $pdf->Image($params['pathtoimage'], $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
960
961 return;
962}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
Class to manage bank accounts description of third parties.
Class to manage proposals.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
dol_is_writable($folderorfile)
Test if directory or filename is writable.
dol_is_file($pathoffile)
Return if path is a file.
dol_is_dir($folder)
Test if filename is a directory.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
dol_ucfirst($string, $encoding="UTF-8")
Convert first character of the first word of a string to upper.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
getUserRemoteIP()
Return the IP of remote user.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
dolPrintSignatureImage(TCPDF $pdf, $langs, $params)
Output the signature file into the PDF object.
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:288
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:265
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:128
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.
dol_verifyHash($chain, $hash, $type='0')
Compute a hash and compare it to the given one For backward compatibility reasons,...