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