dolibarr  19.0.0-dev
onlineSign.php
Go to the documentation of this file.
1 <?php
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 3 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <https://www.gnu.org/licenses/>.
15  */
16 
22 if (!defined('NOTOKENRENEWAL')) {
23  define('NOTOKENRENEWAL', '1'); // Disables token renewal
24 }
25 if (!defined('NOREQUIREHTML')) {
26  define('NOREQUIREHTML', '1');
27 }
28 if (!defined('NOREQUIREAJAX')) {
29  define('NOREQUIREAJAX', '1');
30 }
31 // Needed to create other objects with workflow
32 /*if (!defined('NOREQUIRESOC')) {
33  define('NOREQUIRESOC', '1');
34 }*/
35 // Do not check anti CSRF attack test
36 if (!defined('NOREQUIREMENU')) {
37  define('NOREQUIREMENU', '1');
38 }
39 // If there is no need to load and show top and left menu
40 if (!defined("NOLOGIN")) {
41  define("NOLOGIN", '1');
42 }
43 if (!defined('NOIPCHECK')) {
44  define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
45 }
46 if (!defined('NOBROWSERNOTIF')) {
47  define('NOBROWSERNOTIF', '1');
48 }
49 $entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
50 if (is_numeric($entity)) {
51  define("DOLENTITY", $entity);
52 }
53 include '../../main.inc.php';
54 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
55 
56 $action = GETPOST('action', 'aZ09');
57 
58 $signature = GETPOST('signaturebase64');
59 $ref = GETPOST('ref', 'aZ09');
60 $mode = GETPOST('mode', 'aZ09'); // 'proposal', ...
61 $SECUREKEY = GETPOST("securekey"); // Secure key
62 $online_sign_name = GETPOST("onlinesignname") ? GETPOST("onlinesignname") : '';
63 
64 $error = 0;
65 $response = "";
66 
67 $type = $mode;
68 
69 // Security check
70 $securekeyseed = '';
71 if ($type == 'proposal') {
72  $securekeyseed = getDolGlobalString('PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN');
73 }
74 
75 if (empty($SECUREKEY) || !dol_verifyHash($securekeyseed.$type.$ref.(!isModEnabled('multicompany') ? '' : $entity), $SECUREKEY, '0')) {
76  httponly_accessforbidden('Bad value for securitykey. Value provided '.dol_escape_htmltag($SECUREKEY).' does not match expected value for ref='.dol_escape_htmltag($ref), 403);
77 }
78 
79 
80 /*
81  * Actions
82  */
83 
84 // None
85 
86 
87 /*
88  * View
89  */
90 
91 top_httphead();
92 
93 if ($action == "importSignature") {
94  $issignatureok = (!empty($signature) && $signature[0] == "image/png;base64");
95  if ($issignatureok) {
96  $signature = $signature[1];
97  $data = base64_decode($signature);
98 
99  if ($mode == "propale" || $mode == 'proposal') {
100  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
101  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
102  $object = new Propal($db);
103  $object->fetch(0, $ref);
104 
105  $upload_dir = !empty($conf->propal->multidir_output[$object->entity])?$conf->propal->multidir_output[$object->entity]:$conf->propal->dir_output;
106  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
107 
108  $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
109  $default_font = pdf_getPDFFont($langs); // Must be after pdf_getInstance
110  $langs->loadLangs(array("main", "companies"));
111 
112  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
113  $filename = "signatures/".$date."_signature.png";
114  if (!is_dir($upload_dir."signatures/")) {
115  if (!dol_mkdir($upload_dir."signatures/")) {
116  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
117  $error++;
118  }
119  }
120 
121  if (!$error) {
122  $return = file_put_contents($upload_dir.$filename, $data);
123  if ($return == false) {
124  $error++;
125  $response = 'Error file_put_content: failed to create signature file.';
126  }
127  }
128 
129  if (!$error) {
130  // Defined modele of doc
131  $last_main_doc_file = $object->last_main_doc;
132  $directdownloadlink = $object->getLastMainDocLink('proposal'); // url to download the $object->last_main_doc
133 
134  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
135  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
136  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
137  $sourcefile = $upload_dir.$ref.".pdf";
138 
139  if (dol_is_file($sourcefile)) {
140  // We build the new PDF
141  $pdf = pdf_getInstance();
142  if (class_exists('TCPDF')) {
143  $pdf->setPrintHeader(false);
144  $pdf->setPrintFooter(false);
145  }
146  $pdf->SetFont(pdf_getPDFFont($langs));
147 
148  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
149  $pdf->SetCompression(false);
150  }
151 
152  //$pdf->Open();
153  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
154 
155  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
156  for ($i=1; $i<($pagecount+1); $i++) {
157  try {
158  $tppl = $pdf->importPage($i);
159  $s = $pdf->getTemplatesize($tppl);
160  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
161  $pdf->useTemplate($tppl);
162  } catch (Exception $e) {
163  dol_syslog("Error when manipulating the PDF ".$sourcefile." by onlineSign: ".$e->getMessage(), LOG_ERR);
164  $response = $e->getMessage();
165  $error++;
166  }
167  }
168 
169  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
170  // TODO Get position of box from PDF template
171  $xforimgstart = (empty($s['w']) ? 120 : round($s['w'] / 2) + 15);
172  $yforimgstart = (empty($s['h']) ? 240 : $s['h'] - 60);
173  $wforimg = $s['w'] - 20 - $xforimgstart;
174 
175  $pdf->SetXY($xforimgstart, $yforimgstart + round($wforimg / 4) - 4);
176  $pdf->SetFont($default_font, '', $default_font_size - 1);
177  $pdf->MultiCell($wforimg, 4, $langs->trans("DateSigning").': '.dol_print_date(dol_now(), "daytext", false, $langs, true), 0, 'L');
178  $pdf->SetXY($xforimgstart, $yforimgstart + round($wforimg / 4));
179  $pdf->MultiCell($wforimg, 4, $langs->trans("Lastname").': '.$online_sign_name, 0, 'L');
180 
181  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
182 
183  //$pdf->Close();
184  $pdf->Output($newpdffilename, "F");
185 
186  // Index the new file and update the last_main_doc property of object.
187  $object->indexFile($newpdffilename, 1);
188  }
189  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
190  // Adding signature on .ODT not yet supported
191  // TODO
192  } else {
193  // Document format not supported to insert online signature.
194  // We should just create an image file with the signature.
195  }
196  }
197 
198  if (!$error) {
199  $db->begin();
200 
201  $online_sign_ip = getUserRemoteIP();
202 
203  $sql = "UPDATE ".MAIN_DB_PREFIX."propal";
204  $sql .= " SET fk_statut = ".((int) $object::STATUS_SIGNED).", note_private = '".$db->escape($object->note_private)."',";
205  $sql .= " date_signature = '".$db->idate(dol_now())."',";
206  $sql .= " online_sign_ip = '".$db->escape($online_sign_ip)."'";
207  if ($online_sign_name) {
208  $sql .= ", online_sign_name = '".$db->escape($online_sign_name)."'";
209  }
210  $sql .= " WHERE rowid = ".((int) $object->id);
211 
212  dol_syslog(__METHOD__, LOG_DEBUG);
213  $resql = $db->query($sql);
214  if (!$resql) {
215  $error++;
216  } else {
217  $num = $db->affected_rows($resql);
218  }
219 
220  if (!$error) {
221  if (method_exists($object, 'call_trigger')) {
222  //customer is not a user !?! so could we use same user as validation ?
223  $user = new User($db);
224  $user->fetch($object->user_valid_id);
225  $object->context = array('closedfromonlinesignature' => 'closedfromonlinesignature');
226  $result = $object->call_trigger('PROPAL_CLOSE_SIGNED', $user);
227  if ($result < 0) {
228  $error++;
229  $response = "error in trigger ".$object->error;
230  } else {
231  $response = "success";
232  }
233  } else {
234  $response = "success";
235  }
236  } else {
237  $error++;
238  $response = "error sql";
239  }
240 
241  if (!$error) {
242  $db->commit();
243  $response = "success";
244  setEventMessages("PropalSigned", null, 'warnings');
245  } else {
246  $db->rollback();
247  }
248  }
249  } elseif ($mode == 'contract') {
250  require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
251  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
252  $object = new Contrat($db);
253  $object->fetch(0, $ref);
254 
255  $upload_dir = !empty($conf->contrat->multidir_output[$object->entity])?$conf->contrat->multidir_output[$object->entity]:$conf->contrat->dir_output;
256  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
257 
258  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
259  $filename = "signatures/".$date."_signature.png";
260  if (!is_dir($upload_dir."signatures/")) {
261  if (!dol_mkdir($upload_dir."signatures/")) {
262  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
263  $error++;
264  }
265  }
266 
267  if (!$error) {
268  $return = file_put_contents($upload_dir.$filename, $data);
269  if ($return == false) {
270  $error++;
271  $response = 'Error file_put_content: failed to create signature file.';
272  }
273  }
274 
275  if (!$error) {
276  // Defined modele of doc
277  $last_main_doc_file = $object->last_main_doc;
278  $directdownloadlink = $object->getLastMainDocLink('contrat'); // url to download the $object->last_main_doc
279  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
280  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
281  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
282  $sourcefile = $upload_dir.$ref.".pdf";
283 
284  if (dol_is_file($sourcefile)) {
285  // We build the new PDF
286  $pdf = pdf_getInstance();
287  if (class_exists('TCPDF')) {
288  $pdf->setPrintHeader(false);
289  $pdf->setPrintFooter(false);
290  }
291  $pdf->SetFont(pdf_getPDFFont($langs));
292 
293  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
294  $pdf->SetCompression(false);
295  }
296 
297 
298  //$pdf->Open();
299  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
300  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
301  for ($i=1; $i<($pagecount+1); $i++) {
302  try {
303  $tppl = $pdf->importPage($i);
304  $s = $pdf->getTemplatesize($tppl);
305  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
306  $pdf->useTemplate($tppl);
307  } catch (Exception $e) {
308  dol_syslog("Error when manipulating some PDF by onlineSign: ".$e->getMessage(), LOG_ERR);
309  $response = $e->getMessage();
310  $error++;
311  }
312  }
313 
314  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
315  // TODO Get position of box from PDF template
316  $xforimgstart = 5;
317  $yforimgstart = (empty($s['h']) ? 240 : $s['h'] - 65);
318  $wforimg = $s['w']/2 - $xforimgstart;
319 
320  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
321  //$pdf->Close();
322  $pdf->Output($newpdffilename, "F");
323 
324  // Index the new file and update the last_main_doc property of object.
325  $object->indexFile($newpdffilename, 1);
326  }
327  if (!$error) {
328  $response = "success";
329  }
330  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
331  // Adding signature on .ODT not yet supported
332  // TODO
333  } else {
334  // Document format not supported to insert online signature.
335  // We should just create an image file with the signature.
336  }
337  }
338  } elseif ($mode == 'fichinter') {
339  require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
340  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
341  $object = new Fichinter($db);
342  $object->fetch(0, $ref);
343 
344  $upload_dir = !empty($conf->ficheinter->multidir_output[$object->entity])?$conf->ficheinter->multidir_output[$object->entity]:$conf->ficheinter->dir_output;
345  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
346  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
347  $filename = "signatures/".$date."_signature.png";
348  if (!is_dir($upload_dir."signatures/")) {
349  if (!dol_mkdir($upload_dir."signatures/")) {
350  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
351  $error++;
352  }
353  }
354 
355  if (!$error) {
356  $return = file_put_contents($upload_dir.$filename, $data);
357  if ($return == false) {
358  $error++;
359  $response = 'Error file_put_content: failed to create signature file.';
360  }
361  }
362 
363  if (!$error) {
364  // Defined modele of doc
365  $last_main_doc_file = $object->last_main_doc;
366  $directdownloadlink = $object->getLastMainDocLink('fichinter'); // url to download the $object->last_main_doc
367  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
368  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
369  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
370  $sourcefile = $upload_dir.$ref.".pdf";
371 
372  if (dol_is_file($sourcefile)) {
373  // We build the new PDF
374  $pdf = pdf_getInstance();
375  if (class_exists('TCPDF')) {
376  $pdf->setPrintHeader(false);
377  $pdf->setPrintFooter(false);
378  }
379  $pdf->SetFont(pdf_getPDFFont($langs));
380 
381  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
382  $pdf->SetCompression(false);
383  }
384 
385 
386  //$pdf->Open();
387  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
388  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
389  for ($i=1; $i<($pagecount+1); $i++) {
390  try {
391  $tppl = $pdf->importPage($i);
392  $s = $pdf->getTemplatesize($tppl);
393  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
394  $pdf->useTemplate($tppl);
395  } catch (Exception $e) {
396  dol_syslog("Error when manipulating some PDF by onlineSign: ".$e->getMessage(), LOG_ERR);
397  $response = $e->getMessage();
398  $error++;
399  }
400  }
401 
402  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
403  // TODO Get position of box from PDF template
404  $xforimgstart = 105;
405  $yforimgstart = (empty($s['h']) ? 250 : $s['h'] - 57);
406  $wforimg = $s['w']/1 - ($xforimgstart + 16);
407  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
408  //$pdf->Close();
409  $pdf->Output($newpdffilename, "F");
410 
411  // Index the new file and update the last_main_doc property of object.
412  $object->indexFile($newpdffilename, 1);
413  }
414  if (!$error) {
415  $response = "success";
416  }
417  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
418  // Adding signature on .ODT not yet supported
419  // TODO
420  } else {
421  // Document format not supported to insert online signature.
422  // We should just create an image file with the signature.
423  }
424  }
425  }
426  } else {
427  $error++;
428  $response = 'error signature_not_found';
429  }
430 }
431 
432 if ($error) {
433  http_response_code(501);
434 }
435 
436 echo $response;
Class to manage contracts.
Class to manage interventions.
Class to manage proposals.
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->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') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:483
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
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.
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:1494
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:289
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:127
dol_verifyHash($chain, $hash, $type='0')
Compute a hash and compare it to the given one For backward compatibility reasons,...
httponly_accessforbidden($message=1, $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.