dolibarr 18.0.6
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
22if (!defined('NOTOKENRENEWAL')) {
23 define('NOTOKENRENEWAL', '1'); // Disables token renewal
24}
25if (!defined('NOREQUIREHTML')) {
26 define('NOREQUIREHTML', '1');
27}
28if (!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
36if (!defined('NOREQUIREMENU')) {
37 define('NOREQUIREMENU', '1');
38}
39// If there is no need to load and show top and left menu
40if (!defined("NOLOGIN")) {
41 define("NOLOGIN", '1');
42}
43if (!defined('NOIPCHECK')) {
44 define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
45}
46if (!defined('NOBROWSERNOTIF')) {
47 define('NOBROWSERNOTIF', '1');
48}
49$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
50if (is_numeric($entity)) {
51 define("DOLENTITY", $entity);
52}
53include '../../main.inc.php';
54require_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 = '';
71if ($type == 'proposal') {
72 $securekeyseed = getDolGlobalString('PROPOSAL_ONLINE_SIGNATURE_SECURITY_TOKEN');
73}
74
75if (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
92
93if ($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 $langs->loadLangs(array("main", "companies"));
345
346 $default_font_size = pdf_getPDFFontSize($langs); // Must be after pdf_getInstance
347 $default_font = pdf_getPDFFont($langs); // Must be
348
349 $upload_dir = !empty($conf->ficheinter->multidir_output[$object->entity])?$conf->ficheinter->multidir_output[$object->entity]:$conf->ficheinter->dir_output;
350 $upload_dir .= '/'.dol_sanitizeFileName($object->ref).'/';
351 $date = dol_print_date(dol_now(), "%Y%m%d%H%M%S");
352 $filename = "signatures/".$date."_signature.png";
353 if (!is_dir($upload_dir."signatures/")) {
354 if (!dol_mkdir($upload_dir."signatures/")) {
355 $response ="Error mkdir. Failed to create dir ".$upload_dir."signatures/";
356 $error++;
357 }
358 }
359
360 if (!$error) {
361 $return = file_put_contents($upload_dir.$filename, $data);
362 if ($return == false) {
363 $error++;
364 $response = 'Error file_put_content: failed to create signature file.';
365 }
366 }
367
368 if (!$error) {
369 // Defined modele of doc
370 $last_main_doc_file = $object->last_main_doc;
371 $directdownloadlink = $object->getLastMainDocLink('fichinter'); // url to download the $object->last_main_doc
372 if (preg_match('/\.pdf/i', $last_main_doc_file)) {
373 // TODO Use the $last_main_doc_file to defined the $newpdffilename and $sourcefile
374 $newpdffilename = $upload_dir.$ref."_signed-".$date.".pdf";
375 $sourcefile = $upload_dir.$ref.".pdf";
376
377 if (dol_is_file($sourcefile)) {
378 // We build the new PDF
379 $pdf = pdf_getInstance();
380 if (class_exists('TCPDF')) {
381 $pdf->setPrintHeader(false);
382 $pdf->setPrintFooter(false);
383 }
384 $pdf->SetFont(pdf_getPDFFont($langs));
385
386 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
387 $pdf->SetCompression(false);
388 }
389
390
391 //$pdf->Open();
392 $pagecount = $pdf->setSourceFile($sourcefile); // original PDF
393 $s = array(); // Array with size of each page. Exemple array(w'=>210, 'h'=>297);
394 for ($i=1; $i<($pagecount+1); $i++) {
395 try {
396 $tppl = $pdf->importPage($i);
397 $s = $pdf->getTemplatesize($tppl);
398 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
399 $pdf->useTemplate($tppl);
400 } catch (Exception $e) {
401 dol_syslog("Error when manipulating some PDF by onlineSign: ".$e->getMessage(), LOG_ERR);
402 $response = $e->getMessage();
403 $error++;
404 }
405 }
406
407 // A signature image file is 720 x 180 (ratio 1/4) but we use only the size into PDF
408
409
410
411 // TODO Get position of box from PDF template
412 $xforimgstart = 105;
413 $yforimgstart = (empty($s['h']) ? 250 : $s['h'] - 57);
414 $wforimg = $s['w']/1 - ($xforimgstart + 16);
415
416 $pdf->SetXY(111, 235 +25);
417 $pdf->SetFont($default_font, '', $default_font_size - 1);
418 $pdf->MultiCell($wforimg, 4, $langs->trans("DateSigning").': '.dol_print_date(dol_now(), "daytext", false, $langs, true), 0, 'L');
419 $pdf->SetXY(111, $pdf->GetY());
420 $pdf->MultiCell($wforimg, 4, $langs->trans("Lastname").': '.$online_sign_name, 0, 'L');
421
422
423 $pdf->Image($upload_dir.$filename, $xforimgstart, $yforimgstart, $wforimg, round($wforimg / 4));
424 //$pdf->Close();
425 $pdf->Output($newpdffilename, "F");
426
427 // Index the new file and update the last_main_doc property of object.
428 $object->indexFile($newpdffilename, 1);
429 }
430 if (!$error) {
431 $response = "success";
432 }
433 } elseif (preg_match('/\.odt/i', $last_main_doc_file)) {
434 // Adding signature on .ODT not yet supported
435 // TODO
436 } else {
437 // Document format not supported to insert online signature.
438 // We should just create an image file with the signature.
439 }
440 }
441 }
442 } else {
443 $error++;
444 $response = 'error signature_not_found';
445 }
446}
447
448if ($error) {
449 http_response_code(501);
450}
451
452echo $response;
Class to manage contracts.
Class to manage interventions.
Class to manage proposals.
Class to manage Dolibarr users.
dol_is_file($pathoffile)
Return if path is a file.
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.
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.
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.