dolibarr  x.y.z
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  if (!empty($signature) && $signature[0] == "image/png;base64") {
94  $signature = $signature[1];
95  $data = base64_decode($signature);
96 
97  if ($mode == "propale" || $mode == 'proposal') {
98  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
99  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
100  $object = new Propal($db);
101  $object->fetch(0, $ref);
102 
103  $upload_dir = !empty($conf->propal->multidir_output[$object->entity])?$conf->propal->multidir_output[$object->entity]:$conf->propal->dir_output;
104  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
105 
106  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
107  $filename = "signatures/".$date."_signature.png";
108  if (!is_dir($upload_dir."signatures/")) {
109  if (!dol_mkdir($upload_dir."signatures/")) {
110  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
111  $error++;
112  }
113  }
114 
115  if (!$error) {
116  $return = file_put_contents($upload_dir.$filename, $data);
117  if ($return == false) {
118  $error++;
119  $response = 'Error file_put_content: failed to create signature file.';
120  }
121  }
122 
123  if (!$error) {
124  // Defined modele of doc
125  $last_main_doc_file = $object->last_main_doc;
126  $directdownloadlink = $object->getLastMainDocLink('proposal'); // url to download the $object->last_main_doc
127 
128  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
129  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
130  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
131  $sourcefile = $upload_dir.$ref.".pdf";
132 
133  if (dol_is_file($sourcefile)) {
134  // We build the new PDF
135  $pdf = pdf_getInstance();
136  if (class_exists('TCPDF')) {
137  $pdf->setPrintHeader(false);
138  $pdf->setPrintFooter(false);
139  }
140  $pdf->SetFont(pdf_getPDFFont($langs));
141 
142  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
143  $pdf->SetCompression(false);
144  }
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 some PDF 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  $db->commit();
211  $response = "success";
212  setEventMessages("PropalSigned", null, 'warnings');
213  if (method_exists($object, 'call_trigger')) {
214  //customer is not a user !?! so could we use same user as validation ?
215  $user = new User($db);
216  $user->fetch($object->user_valid_id);
217  $object->context = array('closedfromonlinesignature' => 'closedfromonlinesignature');
218  $result = $object->call_trigger('PROPAL_CLOSE_SIGNED', $user);
219  if ($result < 0) {
220  $error++;
221  }
222  $result = $object->call_trigger('PROPAL_CLOSE_SIGNED_WEB', $user);
223  if ($result < 0) {
224  $error++;
225  }
226  }
227  } else {
228  $db->rollback();
229  $error++;
230  $response = "error sql";
231  }
232  }
233  } elseif ($mode == 'contract') {
234  require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
235  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
236  $object = new Contrat($db);
237  $object->fetch(0, $ref);
238 
239  $upload_dir = !empty($conf->contrat->multidir_output[$object->entity])?$conf->contrat->multidir_output[$object->entity]:$conf->contrat->dir_output;
240  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
241 
242  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
243  $filename = "signatures/".$date."_signature.png";
244  if (!is_dir($upload_dir."signatures/")) {
245  if (!dol_mkdir($upload_dir."signatures/")) {
246  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
247  $error++;
248  }
249  }
250 
251  if (!$error) {
252  $return = file_put_contents($upload_dir.$filename, $data);
253  if ($return == false) {
254  $error++;
255  $response = 'Error file_put_content: failed to create signature file.';
256  }
257  }
258 
259  if (!$error) {
260  // Defined modele of doc
261  $last_main_doc_file = $object->last_main_doc;
262  $directdownloadlink = $object->getLastMainDocLink('contrat'); // url to download the $object->last_main_doc
263  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
264  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
265  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
266  $sourcefile = $upload_dir.$ref.".pdf";
267 
268  if (dol_is_file($sourcefile)) {
269  // We build the new PDF
270  $pdf = pdf_getInstance();
271  if (class_exists('TCPDF')) {
272  $pdf->setPrintHeader(false);
273  $pdf->setPrintFooter(false);
274  }
275  $pdf->SetFont(pdf_getPDFFont($langs));
276 
277  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
278  $pdf->SetCompression(false);
279  }
280 
281 
282  //$pdf->Open();
283  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
284  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
285  for ($i=1; $i<($pagecount+1); $i++) {
286  try {
287  $tppl = $pdf->importPage($i);
288  $s = $pdf->getTemplatesize($tppl);
289  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
290  $pdf->useTemplate($tppl);
291  } catch (Exception $e) {
292  dol_syslog("Error when manipulating some PDF by onlineSign: ".$e->getMessage(), LOG_ERR);
293  $response = $e->getMessage();
294  $error++;
295  }
296  }
297 
298  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
299  // TODO Get position of box from PDF template
300  $xforimgstart = 5;
301  $yforimgstart = (empty($s['h']) ? 240 : $s['h'] - 65);
302  $wforimg = $s['w']/2 - $xforimgstart;
303 
304  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
305  //$pdf->Close();
306  $pdf->Output($newpdffilename, "F");
307 
308  // Index the new file and update the last_main_doc property of object.
309  $object->indexFile($newpdffilename, 1);
310  }
311  if (!$error) {
312  $response = "success";
313  }
314  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
315  // Adding signature on .ODT not yet supported
316  // TODO
317  } else {
318  // Document format not supported to insert online signature.
319  // We should just create an image file with the signature.
320  }
321  }
322  } elseif ($mode == 'fichinter') {
323  require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
324  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
325  $object = new Fichinter($db);
326  $object->fetch(0, $ref);
327 
328  $upload_dir = !empty($conf->ficheinter->multidir_output[$object->entity])?$conf->ficheinter->multidir_output[$object->entity]:$conf->ficheinter->dir_output;
329  $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
330  $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
331  $filename = "signatures/".$date."_signature.png";
332  if (!is_dir($upload_dir."signatures/")) {
333  if (!dol_mkdir($upload_dir."signatures/")) {
334  $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
335  $error++;
336  }
337  }
338 
339  if (!$error) {
340  $return = file_put_contents($upload_dir.$filename, $data);
341  if ($return == false) {
342  $error++;
343  $response = 'Error file_put_content: failed to create signature file.';
344  }
345  }
346 
347  if (!$error) {
348  // Defined modele of doc
349  $last_main_doc_file = $object->last_main_doc;
350  $directdownloadlink = $object->getLastMainDocLink('fichinter'); // url to download the $object->last_main_doc
351  if (preg_match('/\.pdf/i', $last_main_doc_file)) {
352  // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
353  $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
354  $sourcefile = $upload_dir.$ref.".pdf";
355 
356  if (dol_is_file($sourcefile)) {
357  // We build the new PDF
358  $pdf = pdf_getInstance();
359  if (class_exists('TCPDF')) {
360  $pdf->setPrintHeader(false);
361  $pdf->setPrintFooter(false);
362  }
363  $pdf->SetFont(pdf_getPDFFont($langs));
364 
365  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
366  $pdf->SetCompression(false);
367  }
368 
369 
370  //$pdf->Open();
371  $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
372  $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
373  for ($i=1; $i<($pagecount+1); $i++) {
374  try {
375  $tppl = $pdf->importPage($i);
376  $s = $pdf->getTemplatesize($tppl);
377  $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
378  $pdf->useTemplate($tppl);
379  } catch (Exception $e) {
380  dol_syslog("Error when manipulating some PDF by onlineSign: ".$e->getMessage(), LOG_ERR);
381  $response = $e->getMessage();
382  $error++;
383  }
384  }
385 
386  // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
387  // TODO Get position of box from PDF template
388  $xforimgstart = 105;
389  $yforimgstart = (empty($s['h']) ? 250 : $s['h'] - 57);
390  $wforimg = $s['w']/1 - ($xforimgstart + 16);
391  $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
392  //$pdf->Close();
393  $pdf->Output($newpdffilename, "F");
394 
395  // Index the new file and update the last_main_doc property of object.
396  $object->indexFile($newpdffilename, 1);
397  }
398  if (!$error) {
399  $response = "success";
400  }
401  } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
402  // Adding signature on .ODT not yet supported
403  // TODO
404  } else {
405  // Document format not supported to insert online signature.
406  // We should just create an image file with the signature.
407  }
408  }
409  }
410  } else {
411  $error++;
412  $response = 'error signature_not_found';
413  }
414 }
415 
416 if ($error) {
417  http_response_code(501);
418 }
419 
420 echo $response;
Class to manage contracts.
Class to manage interventions.
Class to manage proposals.
Class to manage Dolibarr users.
Definition: user.class.php:45
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:480
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:1436
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.