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