dolibarr  17.0.4
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 
63 $error = 0;
64 $response = "";
65 
66 $type = $mode;
67 
68 // Check securitykey
69 $securekeyseed = '';
70 if ($type == 'proposal') {
71  $securekeyseed = getDolGlobalString('PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN');
72 }
73 
74 if (empty($SECUREKEY) || !dol_verifyHash($securekeyseed.$type.$ref.(!isModEnabled('multicompany') ? '' : $entity), $SECUREKEY, '0')) {
75  httponly_accessforbidden('Bad value for securitykey. Value provided '.dol_escape_htmltag($SECUREKEY).' does not match expected value for ref='.dol_escape_htmltag($ref), 403);
76 }
77 
78 
79 /*
80  * Actions
81  */
82 
83 // None
84 
85 
86 /*
87  * View
88  */
89 
90 top_httphead();
91 
92 if ($action == "importSignature") {
93  $issignatureok = (!empty($signature) && $signature[0] == "image/png;base64");
94  if ($issignatureok) {
95  $signature = $signature[1];
96  $data = base64_decode($signature);
97 
98  if ($mode == "propale" || $mode == 'proposal') {
99  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
100  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
101  $object = new Propal($db);
102  $object->fetch(0, $ref);
103 
104  $upload_dir = !empty($conf->propal->multidir_output[$object->entity])?$conf->propal->multidir_output[$object->entity]:$conf->propal->dir_output;
105  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
106 
107  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
108  $filename = "signatures/".$date."_signature.png";
109  if (!is_dir($upload_dir."signatures/")) {
110  if (!dol_mkdir($upload_dir."signatures/")) {
111  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
112  $error++;
113  }
114  }
115 
116  if (!$error) {
117  $return = file_put_contents($upload_dir.$filename, $data);
118  if ($return == false) {
119  $error++;
120  $response = 'Error file_put_content: failed to create signature file.';
121  }
122  }
123 
124  if (!$error) {
125  // Defined modele of doc
126  $last_main_doc_file = $object->last_main_doc;
127  $directdownloadlink = $object->getLastMainDocLink('proposal'); // url to download the $object->last_main_doc
128 
129  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
130  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
131  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
132  $sourcefile = $upload_dir.$ref.".pdf";
133 
134  if (dol_is_file($sourcefile)) {
135  // We build the new PDF
136  $pdf = pdf_getInstance();
137  if (class_exists('TCPDF')) {
138  $pdf->setPrintHeader(false);
139  $pdf->setPrintFooter(false);
140  }
141  $pdf->SetFont(pdf_getPDFFont($langs));
142 
143  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
144  $pdf->SetCompression(false);
145  }
146 
147  //$pdf->Open();
148  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
149 
150  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
151  for ($i=1; $i<($pagecount+1); $i++) {
152  try {
153  $tppl = $pdf->importPage($i);
154  $s = $pdf->getTemplatesize($tppl);
155  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
156  $pdf->useTemplate($tppl);
157  } catch (Exception $e) {
158  dol_syslog("Error when manipulating the PDF ".$sourcefile." by onlineSign: ".$e->getMessage(), LOG_ERR);
159  $response = $e->getMessage();
160  $error++;
161  }
162  }
163 
164  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
165  // TODO Get position of box from PDF template
166  $xforimgstart = (empty($s['w']) ? 120 : round($s['w'] / 2) + 15);
167  $yforimgstart = (empty($s['h']) ? 240 : $s['h'] - 60);
168  $wforimg = $s['w'] - 20 - $xforimgstart;
169 
170  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
171  //$pdf->Close();
172  $pdf->Output($newpdffilename, "F");
173 
174  // Index the new file and update the last_main_doc property of object.
175  $object->indexFile($newpdffilename, 1);
176  }
177  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
178  // Adding signature on .ODT not yet supported
179  // TODO
180  } else {
181  // Document format not supported to insert online signature.
182  // We should just create an image file with the signature.
183  }
184  }
185 
186  if (!$error) {
187  $db->begin();
188 
189  $online_sign_ip = getUserRemoteIP();
190  $online_sign_name = ''; // TODO Ask name on form to sign
191 
192  $sql = "UPDATE ".MAIN_DB_PREFIX."propal";
193  $sql .= " SET fk_statut = ".((int) $object::STATUS_SIGNED).", note_private = '".$db->escape($object->note_private)."',";
194  $sql .= " date_signature = '".$db->idate(dol_now())."',";
195  $sql .= " online_sign_ip = '".$db->escape($online_sign_ip)."'";
196  if ($online_sign_name) {
197  $sql .= ", online_sign_name = '".$db->escape($online_sign_name)."'";
198  }
199  $sql .= " WHERE rowid = ".((int) $object->id);
200 
201  dol_syslog(__METHOD__, LOG_DEBUG);
202  $resql = $db->query($sql);
203  if (!$resql) {
204  $error++;
205  } else {
206  $num = $db->affected_rows($resql);
207  }
208 
209  if (!$error) {
210  if (method_exists($object, 'call_trigger')) {
211  //customer is not a user !?! so could we use same user as validation ?
212  $user = new User($db);
213  $user->fetch($object->user_valid_id);
214  $object->context = array('closedfromonlinesignature' => 'closedfromonlinesignature');
215  $result = $object->call_trigger('PROPAL_CLOSE_SIGNED', $user);
216  if ($result < 0) {
217  $error++;
218  $response = "error in trigger ".$object->error;
219  } else {
220  $response = "success";
221  }
222  } else {
223  $response = "success";
224  }
225  } else {
226  $error++;
227  $response = "error sql";
228  }
229 
230  if (!$error) {
231  $db->commit();
232  $response = "success";
233  setEventMessages("PropalSigned", null, 'warnings');
234  } else {
235  $db->rollback();
236  }
237  }
238  } elseif ($mode == 'contract') {
239  require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
240  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
241  $object = new Contrat($db);
242  $object->fetch(0, $ref);
243 
244  $upload_dir = !empty($conf->contrat->multidir_output[$object->entity])?$conf->contrat->multidir_output[$object->entity]:$conf->contrat->dir_output;
245  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
246 
247  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
248  $filename = "signatures/".$date."_signature.png";
249  if (!is_dir($upload_dir."signatures/")) {
250  if (!dol_mkdir($upload_dir."signatures/")) {
251  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
252  $error++;
253  }
254  }
255 
256  if (!$error) {
257  $return = file_put_contents($upload_dir.$filename, $data);
258  if ($return == false) {
259  $error++;
260  $response = 'Error file_put_content: failed to create signature file.';
261  }
262  }
263 
264  if (!$error) {
265  // Defined modele of doc
266  $last_main_doc_file = $object->last_main_doc;
267  $directdownloadlink = $object->getLastMainDocLink('contrat'); // url to download the $object->last_main_doc
268  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
269  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
270  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
271  $sourcefile = $upload_dir.$ref.".pdf";
272 
273  if (dol_is_file($sourcefile)) {
274  // We build the new PDF
275  $pdf = pdf_getInstance();
276  if (class_exists('TCPDF')) {
277  $pdf->setPrintHeader(false);
278  $pdf->setPrintFooter(false);
279  }
280  $pdf->SetFont(pdf_getPDFFont($langs));
281 
282  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
283  $pdf->SetCompression(false);
284  }
285 
286 
287  //$pdf->Open();
288  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
289  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
290  for ($i=1; $i<($pagecount+1); $i++) {
291  try {
292  $tppl = $pdf->importPage($i);
293  $s = $pdf->getTemplatesize($tppl);
294  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
295  $pdf->useTemplate($tppl);
296  } catch (Exception $e) {
297  dol_syslog("Error when manipulating some PDF by onlineSign: ".$e->getMessage(), LOG_ERR);
298  $response = $e->getMessage();
299  $error++;
300  }
301  }
302 
303  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
304  // TODO Get position of box from PDF template
305  $xforimgstart = 5;
306  $yforimgstart = (empty($s['h']) ? 240 : $s['h'] - 65);
307  $wforimg = $s['w']/2 - $xforimgstart;
308 
309  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
310  //$pdf->Close();
311  $pdf->Output($newpdffilename, "F");
312 
313  // Index the new file and update the last_main_doc property of object.
314  $object->indexFile($newpdffilename, 1);
315  }
316  if (!$error) {
317  $response = "success";
318  }
319  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
320  // Adding signature on .ODT not yet supported
321  // TODO
322  } else {
323  // Document format not supported to insert online signature.
324  // We should just create an image file with the signature.
325  }
326  }
327  } elseif ($mode == 'fichinter') {
328  require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
329  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
330  $object = new Fichinter($db);
331  $object->fetch(0, $ref);
332 
333  $upload_dir = !empty($conf->ficheinter->multidir_output[$object->entity])?$conf->ficheinter->multidir_output[$object->entity]:$conf->ficheinter->dir_output;
334  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
335  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
336  $filename = "signatures/".$date."_signature.png";
337  if (!is_dir($upload_dir."signatures/")) {
338  if (!dol_mkdir($upload_dir."signatures/")) {
339  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
340  $error++;
341  }
342  }
343 
344  if (!$error) {
345  $return = file_put_contents($upload_dir.$filename, $data);
346  if ($return == false) {
347  $error++;
348  $response = 'Error file_put_content: failed to create signature file.';
349  }
350  }
351 
352  if (!$error) {
353  // Defined modele of doc
354  $last_main_doc_file = $object->last_main_doc;
355  $directdownloadlink = $object->getLastMainDocLink('fichinter'); // url to download the $object->last_main_doc
356  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
357  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
358  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
359  $sourcefile = $upload_dir.$ref.".pdf";
360 
361  if (dol_is_file($sourcefile)) {
362  // We build the new PDF
363  $pdf = pdf_getInstance();
364  if (class_exists('TCPDF')) {
365  $pdf->setPrintHeader(false);
366  $pdf->setPrintFooter(false);
367  }
368  $pdf->SetFont(pdf_getPDFFont($langs));
369 
370  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
371  $pdf->SetCompression(false);
372  }
373 
374 
375  //$pdf->Open();
376  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
377  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
378  for ($i=1; $i<($pagecount+1); $i++) {
379  try {
380  $tppl = $pdf->importPage($i);
381  $s = $pdf->getTemplatesize($tppl);
382  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
383  $pdf->useTemplate($tppl);
384  } catch (Exception $e) {
385  dol_syslog("Error when manipulating some PDF by onlineSign: ".$e->getMessage(), LOG_ERR);
386  $response = $e->getMessage();
387  $error++;
388  }
389  }
390 
391  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
392  // TODO Get position of box from PDF template
393  $xforimgstart = 105;
394  $yforimgstart = (empty($s['h']) ? 250 : $s['h'] - 57);
395  $wforimg = $s['w']/1 - ($xforimgstart + 16);
396  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
397  //$pdf->Close();
398  $pdf->Output($newpdffilename, "F");
399 
400  // Index the new file and update the last_main_doc property of object.
401  $object->indexFile($newpdffilename, 1);
402  }
403  if (!$error) {
404  $response = "success";
405  }
406  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
407  // Adding signature on .ODT not yet supported
408  // TODO
409  } else {
410  // Document format not supported to insert online signature.
411  // We should just create an image file with the signature.
412  }
413  }
414  }
415  } else {
416  $error++;
417  $response = 'error signature_not_found';
418  }
419 }
420 
421 if ($error) {
422  http_response_code(501);
423 }
424 
425 echo $response;
Class to manage contracts.
Class to manage interventions.
Class to manage proposals.
Class to manage Dolibarr users.
Definition: user.class.php:47
if(isModEnabled('facture') &&!empty($user->rights->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') &&!empty($user->rights->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)) $resql
Social contributions to pay.
Definition: index.php:745
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:481
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
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.
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) 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)
if(!defined('NOREQUIREMENU')) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
Definition: main.inc.php:1440
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:265
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:126
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.