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 $response = "success";
292 }
293 } else {
294 $response = "success";
295 }
296 } else {
297 $error++;
298 $response = "error sql";
299 }
300
301 if (!$error) {
302 $db->commit();
303 $response = "success";
304 setEventMessages("PropalSigned", null, 'warnings');
305 } else {
306 $db->rollback();
307 }
308 }
309 } elseif ($mode == 'contract') {
310 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
311 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
312 $object = new Contrat($db);
313 $object->fetch(0, $ref);
314
315 $upload_dir = !empty($conf->contrat->multidir_output[$object->entity]) ? $conf->contrat->multidir_output[$object->entity] : $conf->contrat->dir_output;
316 $upload_dir .= '/' . dol_sanitizeFileName($object->ref) . '/';
317
318 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
319 $filename = "signatures/" . $date . "_signature.png";
320 if (!is_dir($upload_dir . "signatures/")) {
321 if (!dol_mkdir($upload_dir . "signatures/")) {
322 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
323 $error++;
324 }
325 }
326
327 if (!$error) {
328 $return = file_put_contents($upload_dir . $filename, $data);
329 if ($return == false) {
330 $error++;
331 $response = 'Error file_put_content: failed to create signature file.';
332 }
333 }
334
335 if (!$error) {
336 // Defined modele of doc
337 $last_main_doc_file = $object->last_main_doc;
338 $directdownloadlink = $object->getLastMainDocLink('contrat'); // url to download the $object->last_main_doc
339
340 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
341 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
342 $newpdffilename = $upload_dir . $ref . "_signed-" . $date . ".pdf";
343 $sourcefile = $upload_dir . $ref . ".pdf";
344
345 if (dol_is_file($sourcefile)) {
346 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
347 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
348 if ($reshook < 0) {
349 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
350 }
351
352 if (empty($reshook)) {
353 // We build the new PDF
354 $pdf = pdf_getInstance();
355 if (class_exists('TCPDF')) {
356 $pdf->setPrintHeader(false);
357 $pdf->setPrintFooter(false);
358 }
359 $pdf->SetFont(pdf_getPDFFont($langs));
360
361 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
362 $pdf->SetCompression(false);
363 }
364
365 //$pdf->Open();
366 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
367
368 $param = array();
369 $param['online_sign_name'] = $online_sign_name;
370 $param['pathtoimage'] = $upload_dir . $filename;
371
372 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
373 for ($i = 1; $i < ($pagecount + 1); $i++) {
374 try {
375 $tppl = $pdf->importPage($i);
376 $s = $pdf->getTemplatesize($tppl);
377 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
378 $pdf->useTemplate($tppl);
379
380 if (getDolGlobalString("CONTRACT_SIGNATURE_ON_ALL_PAGES")) {
381 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
382 // TODO Get position of box from PDF template
383
384 if (getDolGlobalString("CONTRACT_SIGNATURE_XFORIMGSTART")) {
385 $param['xforimgstart'] = getDolGlobalString("CONTRACT_SIGNATURE_XFORIMGSTART");
386 } else {
387 $param['xforimgstart'] = 10;
388 }
389 if (getDolGlobalString("CONTRACT_SIGNATURE_YFORIMGSTART")) {
390 $param['yforimgstart'] = getDolGlobalString("CONTRACT_SIGNATURE_YFORIMGSTART");
391 } else {
392 $param['yforimgstart'] = (empty($s['h']) ? 240 : $s['h'] - 65);
393 }
394 if (getDolGlobalString("CONTRACT_SIGNATURE_WFORIMG")) {
395 $param['wforimg'] = getDolGlobalString("CONTRACT_SIGNATURE_WFORIMG");
396 } else {
397 $param['wforimg'] = $s['w'] / 2 - $param['xforimgstart'];
398 }
399
400 dolPrintSignatureImage($pdf, $langs, $param);
401 }
402 } catch (Exception $e) {
403 dol_syslog("Error when manipulating some PDF by onlineSign: " . $e->getMessage(), LOG_ERR);
404 $response = $e->getMessage();
405 $error++;
406 }
407 }
408
409 if (!getDolGlobalString("CONTRACT_SIGNATURE_ON_ALL_PAGES")) {
410 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
411 // TODO Get position of box from PDF template
412
413 $param['xforimgstart'] = 10;
414 $param['yforimgstart'] = (empty($s['h']) ? 240 : $s['h'] - 65);
415 $param['wforimg'] = $s['w'] / 2 - $param['xforimgstart'];
416
417 dolPrintSignatureImage($pdf, $langs, $param);
418 }
419
420 //$pdf->Close();
421 $pdf->Output($newpdffilename, "F");
422
423 // Index the new file and update the last_main_doc property of object.
424 $object->indexFile($newpdffilename, 1);
425 }
426 }
427 if (!$error) {
428 $response = "success";
429 }
430 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
431 // Adding signature on .ODT not yet supported
432 // TODO
433 } else {
434 // Document format not supported to insert online signature.
435 // We should just create an image file with the signature.
436 }
437 }
438 } elseif ($mode == 'fichinter') {
439 require_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php';
440 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
441 $object = new Fichinter($db);
442 $object->fetch(0, $ref);
443
444 $upload_dir = !empty($conf->ficheinter->multidir_output[$object->entity]) ? $conf->ficheinter->multidir_output[$object->entity] : $conf->ficheinter->dir_output;
445 $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
446
447 $langs->loadLangs(array("main", "companies"));
448
449 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
450 $default_font = pdf_getPDFFont($langs); // Must be
451
452 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
453 $filename = "signatures/" . $date . "_signature.png";
454 if (!is_dir($upload_dir . "signatures/")) {
455 if (!dol_mkdir($upload_dir . "signatures/")) {
456 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
457 $error++;
458 }
459 }
460
461 if (!$error) {
462 $return = file_put_contents($upload_dir . $filename, $data);
463 if ($return == false) {
464 $error++;
465 $response = 'Error file_put_content: failed to create signature file.';
466 }
467 }
468
469 if (!$error) {
470 // Defined modele of doc
471 $last_main_doc_file = $object->last_main_doc;
472 $directdownloadlink = $object->getLastMainDocLink('fichinter'); // url to download the $object->last_main_doc
473
474 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
475 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
476 $newpdffilename = $upload_dir . $ref . "_signed-" . $date . ".pdf";
477 $sourcefile = $upload_dir . $ref . ".pdf";
478
479 if (dol_is_file($sourcefile)) {
480 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
481 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
482 if ($reshook < 0) {
483 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
484 }
485
486 if (empty($reshook)) {
487 // We build the new PDF
488 $pdf = pdf_getInstance();
489 if (class_exists('TCPDF')) {
490 $pdf->setPrintHeader(false);
491 $pdf->setPrintFooter(false);
492 }
493 $pdf->SetFont(pdf_getPDFFont($langs));
494
495 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
496 $pdf->SetCompression(false);
497 }
498
499 //$pdf->Open();
500 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
501
502 $param = array();
503 $param['online_sign_name'] = $online_sign_name;
504 $param['pathtoimage'] = $upload_dir . $filename;
505
506 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
507 for ($i = 1; $i < ($pagecount + 1); $i++) {
508 try {
509 $tppl = $pdf->importPage($i);
510 $s = $pdf->getTemplatesize($tppl);
511 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
512 $pdf->useTemplate($tppl);
513
514 if (getDolGlobalString("FICHINTER_SIGNATURE_ON_ALL_PAGES")) {
515 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
516 // TODO Get position of box from PDF template
517
518 if (getDolGlobalString("FICHINTER_SIGNATURE_XFORIMGSTART")) {
519 $param['xforimgstart'] = getDolGlobalString("FICHINTER_SIGNATURE_XFORIMGSTART");
520 } else {
521 $param['xforimgstart'] = 111;
522 }
523 if (getDolGlobalString("FICHINTER_SIGNATURE_YFORIMGSTART")) {
524 $param['yforimgstart'] = getDolGlobalString("FICHINTER_SIGNATURE_YFORIMGSTART");
525 } else {
526 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 60);
527 }
528 if (getDolGlobalString("FICHINTER_SIGNATURE_WFORIMG")) {
529 $param['wforimg'] = getDolGlobalString("FICHINTER_SIGNATURE_WFORIMG");
530 } else {
531 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
532 }
533
534 dolPrintSignatureImage($pdf, $langs, $param);
535 }
536 } catch (Exception $e) {
537 dol_syslog("Error when manipulating some PDF by onlineSign: " . $e->getMessage(), LOG_ERR);
538 $response = $e->getMessage();
539 $error++;
540 }
541 }
542
543 if (!getDolGlobalString("FICHINTER_SIGNATURE_ON_ALL_PAGES")) {
544 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
545 // TODO Get position of box from PDF template
546
547 $param['xforimgstart'] = 111;
548 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 60);
549 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
550
551 dolPrintSignatureImage($pdf, $langs, $param);
552 }
553
554 //$pdf->Close();
555 $pdf->Output($newpdffilename, "F");
556
557 // Index the new file and update the last_main_doc property of object.
558 $object->indexFile($newpdffilename, 1);
559 }
560 }
561 if (!$error) {
562 $response = "success";
563 }
564 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
565 // Adding signature on .ODT not yet supported
566 // TODO
567 } else {
568 // Document format not supported to insert online signature.
569 // We should just create an image file with the signature.
570 }
571 $user = new User($db);
572 $object->setSignedStatus($user, $object::SIGNED_STATUSES['STATUS_SIGNED_RECEIVER_ONLINE'], 0, 'FICHINTER_MODIFY');
573 }
574 } elseif ($mode == "societe_rib") {
575 $langs->load('withdrawals');
576 require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
577 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
578 $modelpath = "core/modules/bank/doc/";
579 $object = new CompanyBankAccount($db);
580 $object->fetch(0, $ref);
581 if (!empty($object->id)) {
582 $object->fetch_thirdparty();
583
584 $upload_dir = $conf->societe->multidir_output[$object->thirdparty->entity] . '/' . dol_sanitizeFileName($object->thirdparty->id) . '/';
585
586 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
587 $default_font = pdf_getPDFFont($langs); // Must be after pdf_getInstance
588 $langs->loadLangs(array("main", "companies"));
589
590 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
591 $filename = "signatures/" . $date . "_signature.png";
592 if (!dol_is_dir($upload_dir . "signatures/")) {
593 if (!dol_mkdir($upload_dir . "signatures/")) {
594 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
595 $error++;
596 }
597 }
598 if (!dol_is_writable($upload_dir . "signatures/")) {
599 $response = "Error directory " . $upload_dir . "signatures/ is not writable";
600 $error++;
601 }
602 if (!dol_is_writable(DOL_DATA_ROOT.'/admin/temp/')) { // This is used by TCPDF as working directory
603 $response = "Error directory " . DOL_DATA_ROOT."/admin/temp/ is not writable";
604 $error++;
605 }
606
607 if (!$error) {
608 $return = file_put_contents($upload_dir . $filename, $data);
609 if ($return == false) {
610 $error++;
611 $response = 'Error file_put_content: failed to create signature file.';
612 }
613 }
614
615 if (!$error) {
616 // Defined modele of doc
617 $last_main_doc_file = $object->last_main_doc;
618 $last_modelpdf = $object->model_pdf;
619 $directdownloadlink = $object->getLastMainDocLink('company'); // url to download the $object->last_main_doc
620
621 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
622 $sourcefile = '';
623 $newpdffilename = '';
624 if ($last_modelpdf == 'sepamandate') {
625 $newpdffilename = $upload_dir . $langs->transnoentitiesnoconv("SepaMandateShort") . ' ' . dol_sanitizeFileName($object->ref) . "-" . dol_sanitizeFileName($object->rum) . "_signed-" . $date . ".pdf";
626 $sourcefile = $upload_dir . $langs->transnoentitiesnoconv("SepaMandateShort") . ' ' . dol_sanitizeFileName($object->ref) . "-" . dol_sanitizeFileName($object->rum) . ".pdf";
627 }
628 if (dol_is_file($sourcefile)) {
629 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
630 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
631 if ($reshook < 0) {
632 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
633 }
634
635 if (empty($reshook)) {
636 // We build the new PDF
637 $pdf = pdf_getInstance();
638 if (class_exists('TCPDF')) {
639 $pdf->setPrintHeader(false);
640 $pdf->setPrintFooter(false);
641 }
642 $pdf->SetFont(pdf_getPDFFont($langs));
643
644 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
645 $pdf->SetCompression(false);
646 }
647
648 //$pdf->Open();
649 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
650
651 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
652 for ($i = 1; $i < ($pagecount + 1); $i++) {
653 try {
654 $tppl = $pdf->importPage($i);
655 $s = $pdf->getTemplatesize($tppl);
656 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
657 $pdf->useTemplate($tppl);
658 } catch (Exception $e) {
659 dol_syslog("Error when manipulating the PDF " . $sourcefile . " by onlineSign: " . $e->getMessage(), LOG_ERR);
660 $response = $e->getMessage();
661 $error++;
662 }
663 }
664
665
666 // Get position of box from PDF template
667 $file = '';
668 $classname = '';
669 $filefound = '';
670 $dirmodels = array('/');
671 if (is_array($conf->modules_parts['models'])) {
672 $dirmodels = array_merge($dirmodels, $conf->modules_parts['models']);
673 }
674 foreach ($dirmodels as $reldir) {
675 $file = "pdf_" . $last_modelpdf . ".modules.php";
676 // On vérifie l'emplacement du modele
677 $file = dol_buildpath($reldir . $modelpath . $file, 0);
678 if (file_exists($file)) {
679 $filefound = $file;
680 $classname = 'pdf_' . $last_modelpdf;
681 break;
682 }
683 }
684
685 if ($filefound === '') {
686 $response = $langs->trans("Error") . ' Failed to load doc generator with modelpaths=' . $modelpath . ' - modele=' . $last_modelpdf;
687 dol_syslog($response, LOG_ERR);
688 $error++;
689 }
690
691 if (!$error && $classname !== '') {
692 // If PDF template class was found
693 require_once $file;
694
695 $objPDF = new $classname($db);
696
697 $pdf->SetFont($default_font, '', $default_font_size - 1);
698
699 $xForDate = $objPDF->marge_gauche;
700 $yForDate = $objPDF->page_hauteur - $objPDF->heightforinfotot - $objPDF->heightforfreetext - $objPDF->heightforfooter + 10;
701 $pdf->SetXY($xForDate, $yForDate);
702 $pdf->MultiCell(100, 4, dol_print_date(dol_now(), "daytext", false, $langs, true), 0, 'L');
703
704 $xforimgstart = $objPDF->xPosSignArea;
705 $yforimgstart = $yForDate - 5;
706 $wforimg = $s['w'] - 20 - $xforimgstart;
707
708 $param = array();
709 $param['online_sign_name'] = $online_sign_name;
710 $param['pathtoimage'] = $upload_dir . $filename;
711
712 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
713 // TODO Get position of box from PDF template
714
715 $param['xforimgstart'] = $xforimgstart;
716 $param['yforimgstart'] = $yforimgstart;
717 $param['wforimg'] = $wforimg;
718
719 dolPrintSignatureImage($pdf, $langs, $param);
720 }
721 //$pdf->Close();
722 $pdf->Output($newpdffilename, "F");
723
724 // Index the new file and update the last_main_doc property of object.
725 $object->indexFile($newpdffilename, 1);
726 }
727 }
728 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
729 // Adding signature on .ODT not yet supported
730 // TODO
731 } else {
732 // Document format not supported to insert online signature.
733 // We should just create an image file with the signature.
734 }
735 }
736 } else {
737 $error++;
738 $response = "cannot find BAN/RIB";
739 }
740
741 if (!$error) {
742 $db->begin();
743
744 $online_sign_ip = getUserRemoteIP();
745
746 $sql = "UPDATE " . MAIN_DB_PREFIX . $object->table_element;
747 $sql .= " SET ";
748 $sql .= " date_signature = '" . $db->idate(dol_now()) . "',";
749 $sql .= " online_sign_ip = '" . $db->escape($online_sign_ip) . "'";
750 if ($online_sign_name) {
751 $sql .= ", online_sign_name = '" . $db->escape($online_sign_name) . "'";
752 }
753 //$sql .= ", last_main_doc = '" . $db->escape($object->element'..') . "'";
754
755 $sql .= " WHERE rowid = " . ((int) $object->id);
756
757 dol_syslog(__FILE__, LOG_DEBUG);
758 $resql = $db->query($sql);
759 if (!$resql) {
760 $error++;
761 } else {
762 $num = $db->affected_rows($resql);
763 }
764
765 if (!$error) {
766 $response = "success";
767 } else {
768 $error++;
769 $response = "error sql";
770 }
771
772 if (!$error) {
773 $db->commit();
774 $response = "success";
775 setEventMessages(dol_ucfirst($mode)."Signed", null, 'warnings');
776 } else {
777 $db->rollback();
778 }
779 }
780 } elseif ($mode == 'expedition') {
781 require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
782 require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php';
783
784 $object = new Expedition($db);
785 $object->fetch(0, $ref);
786
787 $upload_dir = $conf->expedition->dir_output."/sending/";
788 $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
789
790 $langs->loadLangs(array("main", "companies"));
791
792 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
793 $default_font = pdf_getPDFFont($langs); // Must be
794
795 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
796 $filename = "signatures/" . $date . "_signature.png";
797 if (!is_dir($upload_dir . "signatures/")) {
798 if (!dol_mkdir($upload_dir . "signatures/")) {
799 $response = "Error mkdir. Failed to create dir " . $upload_dir . "signatures/";
800 $error++;
801 }
802 }
803
804 if (!$error) {
805 $return = file_put_contents($upload_dir . $filename, $data);
806 if ($return == false) {
807 $error++;
808 $response = 'Error file_put_content: failed to create signature file.';
809 }
810 }
811
812 if (!$error) {
813 $last_main_doc_file = $object->last_main_doc;
814 // Defined modele of doc
815 if (empty($last_main_doc_file) || !dol_is_file(DOL_DATA_ROOT.'/'.$object->last_main_doc)) {
816 // It seems document has never been generated, or was generated and then deleted.
817 // So we try to regenerate it with its default template.
818 $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.
819 $object->generateDocument($defaulttemplate, $langs);
820 }
821 $last_main_doc_file = $object->last_main_doc;
822 $directdownloadlink = $object->getLastMainDocLink('expedition'); // url to download the $object->last_main_doc
823
824 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
825 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
826 $newpdffilename = $upload_dir . $ref . "_signed-" . $date . ".pdf";
827 $sourcefile = $upload_dir . $ref . ".pdf";
828
829 if (dol_is_file($sourcefile)) {
830 $parameters = array('sourcefile' => $sourcefile, 'newpdffilename' => $newpdffilename);
831 $reshook = $hookmanager->executeHooks('AddSignature', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
832 if ($reshook < 0) {
833 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
834 }
835
836 if (empty($reshook)) {
837 // We build the new PDF
838 $pdf = pdf_getInstance();
839 if (class_exists('TCPDF')) {
840 $pdf->setPrintHeader(false);
841 $pdf->setPrintFooter(false);
842 }
843 $pdf->SetFont(pdf_getPDFFont($langs));
844
845 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
846 $pdf->SetCompression(false);
847 }
848
849 //$pdf->Open();
850 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
851
852 $param = array();
853 $param['online_sign_name'] = $online_sign_name;
854 $param['pathtoimage'] = $upload_dir . $filename;
855
856 $s = array(); // Array with size of each page. Example array(w'=>210, 'h'=>297);
857 for ($i = 1; $i < ($pagecount + 1); $i++) {
858 try {
859 $tppl = $pdf->importPage($i);
860 $s = $pdf->getTemplatesize($tppl);
861 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
862 $pdf->useTemplate($tppl);
863
864 if (getDolGlobalString("SHIPMENT_SIGNATURE_ON_ALL_PAGES")) {
865 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
866 // TODO Get position of box from PDF template
867
868 $param['xforimgstart'] = 111;
869 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 60);
870 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
871
872 dolPrintSignatureImage($pdf, $langs, $param);
873 }
874 } catch (Exception $e) {
875 dol_syslog("Error when manipulating some PDF by onlineSign: " . $e->getMessage(), LOG_ERR);
876 $response = $e->getMessage();
877 $error++;
878 }
879 }
880
881 if (!getDolGlobalString("SHIPMENT_SIGNATURE_ON_ALL_PAGES")) {
882 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
883 // TODO Get position of box from PDF template
884
885 $param['xforimgstart'] = 111;
886 $param['yforimgstart'] = (empty($s['h']) ? 250 : $s['h'] - 60);
887 $param['wforimg'] = $s['w'] - ($param['xforimgstart'] + 16);
888
889 dolPrintSignatureImage($pdf, $langs, $param);
890 }
891
892 //$pdf->Close();
893 $pdf->Output($newpdffilename, "F");
894
895 // Index the new file and update the last_main_doc property of object.
896 $object->indexFile($newpdffilename, 1);
897 }
898 }
899 if (!$error) {
900 $response = "success";
901 }
902 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
903 // Adding signature on .ODT not yet supported
904 // TODO
905 } else {
906 // Document format not supported to insert online signature.
907 // We should just create an image file with the signature.
908 }
909 }
910
911 if (!$error) {
912 $db->begin();
913
914 $sql = "UPDATE " . MAIN_DB_PREFIX . "expedition";
915 $sql .= " SET signed_status = " . ((int) $object::STATUS_SIGNED) ;
916 $sql .= " WHERE rowid = " . ((int) $object->id);
917
918 dol_syslog(__FILE__, LOG_DEBUG);
919 $resql = $db->query($sql);
920 if (!$resql) {
921 $error++;
922 } else {
923 $num = $db->affected_rows($resql);
924 }
925
926 if (!$error) {
927 $db->commit();
928 $response = "success";
929 setEventMessages("ExpeditionSigned", null, 'warnings');
930 } else {
931 $db->rollback();
932 }
933 }
934 }
935 } else {
936 $error++;
937 $response = 'error signature_not_found';
938 }
939}
940
941if ($error) {
942 http_response_code(501);
943}
944
945echo $response;
946
947
956function dolPrintSignatureImage(TCPDF $pdf, $langs, $params)
957{
958 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
959 $default_font = pdf_getPDFFont($langs); // Must be
960 $xforimgstart = $params['xforimgstart'];
961 $yforimgstart = $params['yforimgstart'];
962 $wforimg = $params['wforimg'];
963
964 $pdf->SetXY($xforimgstart, $yforimgstart + round($wforimg / 4) - 4);
965 $pdf->SetFont($default_font, '', $default_font_size - 1);
966 $pdf->SetTextColor(80, 80, 80);
967 $pdf->MultiCell($wforimg, 4, $langs->trans("Signature") . ': ' . dol_print_date(dol_now(), "day", false, $langs, true). ' - '.$params['online_sign_name'], 0, 'L');
968 //$pdf->SetXY($xforimgstart, $yforimgstart + round($wforimg / 4));
969 //$pdf->MultiCell($wforimg, 4, $langs->trans("Lastname") . ': ' . $online_sign_name, 0, 'L');
970
971 $pdf->Image($params['pathtoimage'], $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
972
973 return;
974}
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 contracts.
Class to manage shipments.
Class to manage interventions.
Class to manage proposals.
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.
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
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:290
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:267
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,...