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