From eb42a1547fad895ba50579a5bf9df2804a10901c Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 10:47:12 +0200 Subject: [PATCH 01/50] Storage configuration --- app.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app.php b/app.php index 8b587b0..1b054cf 100644 --- a/app.php +++ b/app.php @@ -10,6 +10,7 @@ $f3->set('XFRAME', null); // Allow use in an iframe $f3->set('ROOT', __DIR__); $f3->set('UI', $f3->get('ROOT')."/templates/"); $f3->set('UPLOADS', sys_get_temp_dir()."/"); +$f3->set('STORAGE', sys_get_temp_dir()."/pdf/"); function convertPHPSizeToBytes($sSize) { From b3c7c186a8606f184e6f50a1d9d3338de0dbf220 Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 11:08:46 +0200 Subject: [PATCH 02/50] Form and button to share pdf --- templates/signature.html.php | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/templates/signature.html.php b/templates/signature.html.php index d5f34e6..488fd17 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -70,14 +70,21 @@
- -
- - -
- -
-
+
+
+ +
+ +
+
+
+ + +
+ +
+
+
From a41155c9509501f65a06445d264fd3337f7462c5 Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 11:46:03 +0200 Subject: [PATCH 03/50] Share upload file original and redirect to a new route with a hash --- app.php | 39 +++++++++++++++++++++++++++++++++++++++ public/js/signature.js | 1 + 2 files changed, 40 insertions(+) diff --git a/app.php b/app.php index 1b054cf..53c6298 100644 --- a/app.php +++ b/app.php @@ -53,6 +53,18 @@ $f3->route('GET /signature', echo View::instance()->render('signature.html.php'); } ); + +$f3->route('GET /signature/@hash', + function($f3, $param) { + $f3->set('hash', $param['hash']); + + $f3->set('maxSize', min(array(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize'))))); + $f3->set('maxPage', ini_get('max_file_uploads') - 1); + + echo View::instance()->render('signature.html.php'); + } +); + $f3->route('GET /organization', function($f3) { $f3->set('maxSize', min(array(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize'))))); @@ -151,6 +163,33 @@ $f3->route('POST /sign', } ); +$f3->route('POST /share', + function($f3) { + $hash = substr(hash('sha512', uniqid().rand()), 0, 20); + $sharingFolder = $f3->get('STORAGE').$hash."/"; + $f3->set('UPLOADS', $sharingFolder); + mkdir($sharingFolder); + $filename = "original.pdf"; + + $files = Web::instance()->receive(function($file,$formFieldName){ + if(strpos(Web::instance()->mime($file['tmp_name'], true), 'application/pdf') !== 0) { + $f3->error(403); + } + + return true; + }, false, function($fileBaseName, $formFieldName) use ($filename) { + + return $filename; + }); + + if(!count($files)) { + $f3->error(403); + } + $f3->reroute('/signature/'.$hash); + } + +); + $f3->route('POST /organize', function($f3) { $filename = null; diff --git a/public/js/signature.js b/public/js/signature.js index f04f321..262ee0e 100644 --- a/public/js/signature.js +++ b/public/js/signature.js @@ -28,6 +28,7 @@ var loadPDF = async function(pdfBlob, filename) { type: 'application/pdf' })); document.getElementById('input_pdf').files = dataTransfer.files; + document.getElementById('input_pdf_share').files = dataTransfer.files; var loadingTask = pdfjsLib.getDocument(url); loadingTask.promise.then(function(pdf) { From b6dad1dcf50a4eae3be746ce1062d8fd5307a8a7 Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 11:53:55 +0200 Subject: [PATCH 04/50] Loading pdf from hash --- public/js/signature.js | 15 ++++++++++++++- templates/signature.html.php | 4 ++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/public/js/signature.js b/public/js/signature.js index 262ee0e..d5fccb6 100644 --- a/public/js/signature.js +++ b/public/js/signature.js @@ -947,7 +947,15 @@ var pageSignature = async function(url) { fontCaveat = font; }); - let pdfBlob = await getPDFBlobFromCache(url); + if(hash) { + var response = await fetch(url); + if(response.status != 200) { + return; + } + let pdfBlob = await response.blob(); + } else { + let pdfBlob = await getPDFBlobFromCache(url); + } if(!pdfBlob) { document.location = '/signature'; return; @@ -962,6 +970,11 @@ var pageSignature = async function(url) { }; (function () { + if(hash) { + pageSignature('/signature/'+hash+'/pdf'); + return; + } + if(window.location.hash && window.location.hash.match(/^\#http/)) { let hashUrl = window.location.hash.replace(/^\#/, ''); pageUpload(); diff --git a/templates/signature.html.php b/templates/signature.html.php index 488fd17..b8d61a0 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -157,6 +157,10 @@ From c452c325278599cf53ba7fcf59f917a24a03fb53 Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 12:15:26 +0200 Subject: [PATCH 05/50] add /signature/@hash/pdf route for concatenation of multiple signature --- app.php | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/app.php b/app.php index 1b054cf..208952c 100644 --- a/app.php +++ b/app.php @@ -185,4 +185,30 @@ $f3->route('POST /organize', } ); -return $f3; \ No newline at end of file +$f3->route('GET /signature/@hash/pdf', + function($f3) { + $targetDir = $f3->get('STORAGE').$f3->get('PARAMS.hash'); + $files = array_diff(scandir($targetDir), array('..', '.'));; + $original = null; + $originalFilename = null; + $layers = []; + foreach($files as $file) { + if (strpos($file, 'svg.pdf') === false) { + $original = $targetDir.'/'.$file; + $originalFilename = $file; + } else { + $layers[] = $targetDir.'/'.$file; + } + } + if (!$original) { + $f3->error(404); + } + if (!$layers||1==1) { + Web::instance()->send($original, null, 0, TRUE, str_replace('.pdf', '_signe.pdf', $originalFilename)); + } + shell_exec(sprintf("pdftk %s multibackground %s output %s", implode(' ', $layers), $original, str_replace('.pdf', '_signe.pdf', $original))); + Web::instance()->send(str_replace('.pdf', '_signe.pdf', $original), null, 0, TRUE, str_replace('.pdf', '_signe.pdf', $originalFilename)); + } +); + +return $f3; From b5d3b990fb77436604e6f30ec439e93e331d8faf Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 13:25:29 +0200 Subject: [PATCH 06/50] Fix javascript bug --- public/js/signature.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/js/signature.js b/public/js/signature.js index d5fccb6..f82e0db 100644 --- a/public/js/signature.js +++ b/public/js/signature.js @@ -947,14 +947,16 @@ var pageSignature = async function(url) { fontCaveat = font; }); + let pdfBlob = null; + if(hash) { var response = await fetch(url); if(response.status != 200) { return; } - let pdfBlob = await response.blob(); + pdfBlob = await response.blob(); } else { - let pdfBlob = await getPDFBlobFromCache(url); + pdfBlob = await getPDFBlobFromCache(url); } if(!pdfBlob) { document.location = '/signature'; From 814793f847fd33928c7815ced7416242a1b9aeb7 Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 13:29:38 +0200 Subject: [PATCH 07/50] Hide button share and download when in sharing mode --- public/js/signature.js | 39 ++++++++++++++++++++++-------------- templates/signature.html.php | 4 +++- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/public/js/signature.js b/public/js/signature.js index f82e0db..3da414c 100644 --- a/public/js/signature.js +++ b/public/js/signature.js @@ -27,9 +27,12 @@ var loadPDF = async function(pdfBlob, filename) { dataTransfer.items.add(new File([pdfBlob], filename, { type: 'application/pdf' })); - document.getElementById('input_pdf').files = dataTransfer.files; - document.getElementById('input_pdf_share').files = dataTransfer.files; - + if(document.getElementById('input_pdf')) { + document.getElementById('input_pdf').files = dataTransfer.files; + } + if(document.getElementById('input_pdf_share')) { + document.getElementById('input_pdf_share').files = dataTransfer.files; + } var loadingTask = pdfjsLib.getDocument(url); loadingTask.promise.then(function(pdf) { @@ -52,7 +55,7 @@ var loadPDF = async function(pdfBlob, filename) { var pageIndex = page.pageNumber - 1; - document.getElementById('form_pdf').insertAdjacentHTML('beforeend', ''); + document.getElementById('form_block').insertAdjacentHTML('beforeend', ''); document.getElementById('container-pages').insertAdjacentHTML('beforeend', '
'); var canvasPDF = document.getElementById('canvas-pdf-' + pageIndex); @@ -475,8 +478,12 @@ var addObjectInCanvas = function(canvas, item) { }; var createAndAddSvgInCanvas = function(canvas, item, x, y, height = null) { - save.removeAttribute('disabled'); - save_mobile.removeAttribute('disabled'); + if(document.getElementById('save')) { + document.getElementById('save').removeAttribute('disabled'); + } + if(document.getElementById('save_mobile')) { + document.getElementById('save_mobile').removeAttribute('disabled'); + } if(!height) { height = 100; @@ -729,15 +736,17 @@ var createEventsListener = function() { event.preventDefault(); }); - document.getElementById('save').addEventListener('click', function(event) { - var dataTransfer = new DataTransfer(); - canvasEditions.forEach(function(canvasEdition, index) { - dataTransfer.items.add(new File([canvasEdition.toSVG()], index+'.svg', { - type: 'image/svg+xml' - })); - }) - document.getElementById('input_svg').files = dataTransfer.files; - }); + if(document.getElementById('save')) { + document.getElementById('save').addEventListener('click', function(event) { + var dataTransfer = new DataTransfer(); + canvasEditions.forEach(function(canvasEdition, index) { + dataTransfer.items.add(new File([canvasEdition.toSVG()], index+'.svg', { + type: 'image/svg+xml' + })); + }) + document.getElementById('input_svg').files = dataTransfer.files; + }); + } document.getElementById('save_mobile').addEventListener('click', function(event) { document.getElementById('save').click(); diff --git a/templates/signature.html.php b/templates/signature.html.php index b8d61a0..54e955e 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -70,7 +70,8 @@
-
+
+
@@ -84,6 +85,7 @@
+
From 6c109acdbeb1153c5ba8ddb661e717c66c95c7cb Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 14:54:14 +0200 Subject: [PATCH 08/50] duplicate error --- app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.php b/app.php index e92cc92..d6068c3 100644 --- a/app.php +++ b/app.php @@ -227,7 +227,7 @@ $f3->route('POST /organize', $f3->route('GET /signature/@hash/pdf', function($f3) { $targetDir = $f3->get('STORAGE').$f3->get('PARAMS.hash'); - $files = array_diff(scandir($targetDir), array('..', '.'));; + $files = array_diff(scandir($targetDir), array('..', '.')); $original = null; $originalFilename = null; $layers = []; From 0d81740d090266145a709a39a1d3ccf114055624 Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 14:55:45 +0200 Subject: [PATCH 09/50] improved files identification --- app.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app.php b/app.php index d6068c3..deda5f5 100644 --- a/app.php +++ b/app.php @@ -232,12 +232,15 @@ $f3->route('GET /signature/@hash/pdf', $originalFilename = null; $layers = []; foreach($files as $file) { - if (strpos($file, 'svg.pdf') === false) { - $original = $targetDir.'/'.$file; - $originalFilename = $file; - } else { - $layers[] = $targetDir.'/'.$file; + if (strpos($file, 'signe.pdf') !== false) { + continue; } + if(strpos($file, 'svg.pdf') !== false) { + $layers[] = $targetDir.'/'.$file; + continue; + } + $original = $targetDir.'/'.$file; + $originalFilename = $file; } if (!$original) { $f3->error(404); From b432256ccce7b7121685e505b286c43802671a5c Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 14:58:27 +0200 Subject: [PATCH 10/50] increase layer on original pdf with pdftk overlay --- app.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app.php b/app.php index deda5f5..925cc03 100644 --- a/app.php +++ b/app.php @@ -248,8 +248,13 @@ $f3->route('GET /signature/@hash/pdf', if (!$layers||1==1) { Web::instance()->send($original, null, 0, TRUE, str_replace('.pdf', '_signe.pdf', $originalFilename)); } - shell_exec(sprintf("pdftk %s multibackground %s output %s", implode(' ', $layers), $original, str_replace('.pdf', '_signe.pdf', $original))); - Web::instance()->send(str_replace('.pdf', '_signe.pdf', $original), null, 0, TRUE, str_replace('.pdf', '_signe.pdf', $originalFilename)); + $newFile = str_replace('.pdf', '_signe.pdf', $original); + $newFilename = str_replace('.pdf', '_signe.pdf', $originalFilename); + shell_exec(sprintf("pdftk %s multibackground %s output %s", $layers[0], $original, $newFile)); + for($i = 1, $max = count($layers); $i < $max; $i++) { + shell_exec(sprintf("pdftk %1\$s multibackground %2\$s output %3\$s && mv %3\$s %2\$s", $layers[$i], $newFile, str_replace('_signe.pdf', '_tmp_signe.pdf', $newFile))); + } + Web::instance()->send($newFile, null, 0, TRUE, $newFilename); } ); From be2d9a794cfaf1d2a5355633a9e87dabaa650ad9 Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 14:59:48 +0200 Subject: [PATCH 11/50] deleting generated file from server --- app.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app.php b/app.php index 925cc03..9fc0cd9 100644 --- a/app.php +++ b/app.php @@ -255,6 +255,11 @@ $f3->route('GET /signature/@hash/pdf', shell_exec(sprintf("pdftk %1\$s multibackground %2\$s output %3\$s && mv %3\$s %2\$s", $layers[$i], $newFile, str_replace('_signe.pdf', '_tmp_signe.pdf', $newFile))); } Web::instance()->send($newFile, null, 0, TRUE, $newFilename); + + if($f3->get('DEBUG')) { + return; + } + unlink($newFile); } ); From 6f8c2fb4edae8a789a794b2a969cc7f19020e44d Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 15:00:42 +0200 Subject: [PATCH 12/50] end of forcing --- app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.php b/app.php index 9fc0cd9..ac4f3aa 100644 --- a/app.php +++ b/app.php @@ -245,7 +245,7 @@ $f3->route('GET /signature/@hash/pdf', if (!$original) { $f3->error(404); } - if (!$layers||1==1) { + if (!$layers) { Web::instance()->send($original, null, 0, TRUE, str_replace('.pdf', '_signe.pdf', $originalFilename)); } $newFile = str_replace('.pdf', '_signe.pdf', $original); From c1c86fb88145b3b45c331acbf2beea842b3de774 Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 16:05:19 +0200 Subject: [PATCH 13/50] exclusive pdf file for treatment (for debug mode) --- app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.php b/app.php index ac4f3aa..a83546b 100644 --- a/app.php +++ b/app.php @@ -232,7 +232,7 @@ $f3->route('GET /signature/@hash/pdf', $originalFilename = null; $layers = []; foreach($files as $file) { - if (strpos($file, 'signe.pdf') !== false) { + if (strpos($file, '.pdf') === false || strpos($file, 'signe.pdf') !== false) { continue; } if(strpos($file, 'svg.pdf') !== false) { From 2f7c1f5156420a293faffb44c45081532222fdc5 Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 16:05:45 +0200 Subject: [PATCH 14/50] save pdf for sharing mode --- app.php | 35 +++++++++++++++++++++++++++++++++++ templates/signature.html.php | 7 +++++++ 2 files changed, 42 insertions(+) diff --git a/app.php b/app.php index a83546b..af25c69 100644 --- a/app.php +++ b/app.php @@ -263,4 +263,39 @@ $f3->route('GET /signature/@hash/pdf', } ); +$f3->route('POST /signature/@hash/save', + function($f3) { + $targetDir = $f3->get('STORAGE').$f3->get('PARAMS.hash').'/'; + $f3->set('UPLOADS', $targetDir); + $tmpfile = tempnam($targetDir, 'pdfsignature_sign'); + unlink($tmpfile); + $svgFiles = ""; + + + $files = Web::instance()->receive(function($file,$formFieldName){ + if($formFieldName == "svg" && strpos(Web::instance()->mime($file['tmp_name'], true), 'image/svg+xml') !== 0) { + $f3->error(403); + } + return true; + }, false, function($fileBaseName, $formFieldName) use ($f3, $tmpfile, &$svgFiles) { + if($formFieldName == "svg") { + $svgFiles .= " ".$tmpfile."_".$fileBaseName; + return basename($tmpfile."_".$fileBaseName); + } + }); + + if(!$svgFiles) { + $f3->error(403); + } + + shell_exec(sprintf("rsvg-convert -f pdf -o %s %s", $tmpfile.'.svg.pdf', $svgFiles)); + + if(!$f3->get('DEBUG')) { + array_map('unlink', $svgFiles); + } + + $f3->reroute('/signature/'.$f3->get('PARAMS.hash')); + } +); + return $f3; diff --git a/templates/signature.html.php b/templates/signature.html.php index 54e955e..4aec855 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -85,6 +85,13 @@ + +
+ +
+ +
+
From bb48a9acd85d977dd766af40674585e2d662ad33 Mon Sep 17 00:00:00 2001 From: Jb Lm Date: Thu, 31 Mar 2022 16:17:12 +0200 Subject: [PATCH 15/50] pdf download button for sharing mode --- templates/signature.html.php | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/signature.html.php b/templates/signature.html.php index 4aec855..904de74 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -86,6 +86,7 @@ + Télécharger le PDF
From 6537d1ae1c20c5e4b55cb8c02e0702c1c109c7ca Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 16:35:26 +0200 Subject: [PATCH 16/50] Modal share informations on the first open --- app.php | 4 +++- public/js/signature.js | 7 +++++++ templates/signature.html.php | 28 ++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app.php b/app.php index e92cc92..391014f 100644 --- a/app.php +++ b/app.php @@ -57,6 +57,8 @@ $f3->route('GET /signature', $f3->route('GET /signature/@hash', function($f3, $param) { $f3->set('hash', $param['hash']); + $port = $f3->get('PORT'); + $f3->set('shareLink', $f3->set('urlbase', $f3->get('SCHEME').'://'.$_SERVER['SERVER_NAME'].(!in_array($port,[80,443])?(':'.$port):'').$f3->get('BASE')).$f3->get('URI')); $f3->set('maxSize', min(array(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize'))))); $f3->set('maxPage', ini_get('max_file_uploads') - 1); @@ -185,7 +187,7 @@ $f3->route('POST /share', if(!count($files)) { $f3->error(403); } - $f3->reroute('/signature/'.$hash); + $f3->reroute('/signature/'.$hash."#informations"); } ); diff --git a/public/js/signature.js b/public/js/signature.js index 3da414c..0579a09 100644 --- a/public/js/signature.js +++ b/public/js/signature.js @@ -938,6 +938,12 @@ var pageUpload = async function() { } var pageSignature = async function(url) { + + if(window.location.hash == '#informations') { + let modalInformations = new bootstrap.Modal(document.getElementById('modal-share-informations')); + modalInformations.show(); + } + let filename = url.replace('/pdf/', ''); document.title = filename + ' - ' + document.title; document.getElementById('page-upload').classList.add('d-none'); @@ -986,6 +992,7 @@ var pageSignature = async function(url) { return; } + if(window.location.hash && window.location.hash.match(/^\#http/)) { let hashUrl = window.location.hash.replace(/^\#/, ''); pageUpload(); diff --git a/templates/signature.html.php b/templates/signature.html.php index 54e955e..cdff974 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -35,6 +35,7 @@
Signature du PDF
+

document.pdf

@@ -75,7 +76,7 @@
- +
@@ -148,7 +149,30 @@
- + + + + + From 9a225a261a978cecb6050dc1e8c5b2bdfcb1cc0e Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 18:23:45 +0200 Subject: [PATCH 17/50] Buttons color --- templates/signature.html.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/templates/signature.html.php b/templates/signature.html.php index 6a4a001..8b3ea1a 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -75,24 +75,18 @@ -
- -
+
-
- -
+
- Télécharger le PDF + Télécharger le PDF
-
- -
+
From 175555a06e009944ea4e25126496910bd9509ea2 Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 31 Mar 2022 18:24:10 +0200 Subject: [PATCH 18/50] Modal share copy to clipboard --- templates/signature.html.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/templates/signature.html.php b/templates/signature.html.php index 8b3ea1a..42aa4f4 100644 --- a/templates/signature.html.php +++ b/templates/signature.html.php @@ -154,18 +154,19 @@