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