mirror of
https://github.com/24eme/signaturepdf
synced 2026-03-14 13:55:44 +01:00
Compilation du pdf signé en mode makefile
This commit is contained in:
parent
1252fc6e09
commit
45e71e38af
3 changed files with 151 additions and 60 deletions
38
app.php
38
app.php
|
|
@ -171,7 +171,7 @@ $f3->route('POST /image2svg',
|
|||
$f3->route('POST /sign',
|
||||
function($f3) {
|
||||
$filename = null;
|
||||
$tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_sign');
|
||||
$tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_sign_'.uniqid(null, true));
|
||||
unlink($tmpfile);
|
||||
$svgFiles = [];
|
||||
|
||||
|
|
@ -220,10 +220,6 @@ $f3->route('POST /sign',
|
|||
|
||||
$f3->route('POST /share',
|
||||
function($f3) {
|
||||
$hash = Web::instance()->slug($_POST['hash']);
|
||||
$sharingFolder = $f3->get('PDF_STORAGE_PATH').$hash;
|
||||
$symmetricKey = (isset($_COOKIE[$hash])) ? GPGCryptography::protectSymmetricKey($_COOKIE[$hash]) : null;
|
||||
|
||||
if (!is_dir($f3->get('PDF_STORAGE_PATH'))) {
|
||||
$f3->error(500, 'Sharing folder doesn\'t exist');
|
||||
}
|
||||
|
|
@ -231,15 +227,15 @@ $f3->route('POST /share',
|
|||
$f3->error(500, 'Sharing folder is not writable');
|
||||
}
|
||||
|
||||
$pdfSignature = new PDFSignature($sharingFolder, $symmetricKey);
|
||||
$pdfSignature->createShare($f3->get('POST.duration'));
|
||||
$hash = Web::instance()->slug($_POST['hash']);
|
||||
$symmetricKey = (isset($_COOKIE[$hash])) ? GPGCryptography::protectSymmetricKey($_COOKIE[$hash]) : null;
|
||||
|
||||
$f3->set('UPLOADS', $sharingFolder."/");
|
||||
|
||||
$filename = "original.pdf";
|
||||
$tmpfile = tempnam($sharingFolder, date('YmdHis'));
|
||||
$tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_share_'.uniqid($hash, true));
|
||||
unlink($tmpfile);
|
||||
|
||||
$svgFiles = [];
|
||||
$originalFile = $tmpfile."_original.pdf";
|
||||
$originalFileBaseName = null;
|
||||
$files = Web::instance()->receive(function($file,$formFieldName){
|
||||
if($formFieldName == "pdf" && strpos(Web::instance()->mime($file['tmp_name'], true), 'application/pdf') !== 0) {
|
||||
$f3->error(403);
|
||||
|
|
@ -249,10 +245,10 @@ $f3->route('POST /share',
|
|||
}
|
||||
|
||||
return true;
|
||||
}, false, function($fileBaseName, $formFieldName) use ($tmpfile, $filename, $sharingFolder, &$svgFiles) {
|
||||
}, false, function($fileBaseName, $formFieldName) use ($tmpfile, $originalFile, &$svgFiles, &$originalFileBaseName) {
|
||||
if($formFieldName == "pdf") {
|
||||
file_put_contents($sharingFolder."/filename.txt", $fileBaseName);
|
||||
return $filename;
|
||||
$originalFileBaseName = $fileBaseName;
|
||||
return basename($originalFile);
|
||||
}
|
||||
if($formFieldName == "svg") {
|
||||
$svgFiles[] = $tmpfile."_".$fileBaseName;
|
||||
|
|
@ -264,10 +260,10 @@ $f3->route('POST /share',
|
|||
$f3->error(403);
|
||||
}
|
||||
|
||||
$pdfSignature->saveShare();
|
||||
|
||||
$pdfSignature = new PDFSignature($f3->get('PDF_STORAGE_PATH').$hash, $symmetricKey);
|
||||
$pdfSignature->createShare($originalFile, $originalFileBaseName, $f3->get('POST.duration'));
|
||||
if(count($svgFiles)) {
|
||||
$pdfSignature->addSignature($svgFiles, $tmpfile.".svg.pdf");
|
||||
$pdfSignature->addSignature($svgFiles);
|
||||
}
|
||||
|
||||
if(!$f3->get('DEBUG')) {
|
||||
|
|
@ -302,9 +298,7 @@ $f3->route('POST /signature/@hash/save',
|
|||
function($f3) {
|
||||
$hash = Web::instance()->slug($f3->get('PARAMS.hash'));
|
||||
$symmetricKey = (isset($_COOKIE[$hash])) ? GPGCryptography::protectSymmetricKey($_COOKIE[$hash]) : null;
|
||||
|
||||
$f3->set('UPLOADS', $f3->get('PDF_STORAGE_PATH').$hash."/");
|
||||
$tmpfile = tempnam($f3->get('PDF_STORAGE_PATH').$hash, date('YmdHis'));
|
||||
$tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_save_'.uniqid($hash, true));
|
||||
unlink($tmpfile);
|
||||
$svgFiles = [];
|
||||
$files = Web::instance()->receive(function($file,$formFieldName){
|
||||
|
|
@ -323,7 +317,7 @@ $f3->route('POST /signature/@hash/save',
|
|||
}
|
||||
|
||||
$pdfSignature = new PDFSignature($f3->get('PDF_STORAGE_PATH').$hash, $symmetricKey);
|
||||
$pdfSignature->addSignature($svgFiles, $tmpfile.".svg.pdf");
|
||||
$pdfSignature->addSignature($svgFiles);
|
||||
|
||||
if(!$f3->get('DEBUG')) {
|
||||
$pdfSignature->clean();
|
||||
|
|
@ -402,7 +396,7 @@ $f3->route('GET /compress',
|
|||
$f3->route ('POST /compress',
|
||||
function($f3) {
|
||||
$filename = null;
|
||||
$tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_sign');
|
||||
$tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_compress_'.uniqid());
|
||||
unlink($tmpfile);
|
||||
|
||||
$files = Web::instance()->receive(function($file,$formFieldName) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ class GPGCryptography
|
|||
putenv('HOME='.sys_get_temp_dir());
|
||||
foreach ($this->getFiles(false) as $file) {
|
||||
$outputFile = $file.".gpg";
|
||||
if(file_exists($outputFile)) {
|
||||
unlink($outputFile);
|
||||
}
|
||||
$command = "gpg --batch --passphrase $this->symmetricKey --symmetric --cipher-algo AES256 -o $outputFile $file > /dev/null";
|
||||
$result = shell_exec($command);
|
||||
if ($result) {
|
||||
|
|
@ -40,6 +43,20 @@ class GPGCryptography
|
|||
return true;
|
||||
}
|
||||
|
||||
public function decryptFile($file) {
|
||||
if (!file_exists($file.'.gpg')) {
|
||||
return $file;
|
||||
}
|
||||
if (!$this->symmetricKey) {
|
||||
return false;
|
||||
}
|
||||
$decryptTmpFile = sys_get_temp_dir()."/".uniqid('pdfsignature.decrypted.'.getmypid().md5($file), true).'_'.basename($file);
|
||||
|
||||
$this->runDecryptFile($file.'.gpg', $decryptTmpFile);
|
||||
|
||||
return $decryptTmpFile;
|
||||
}
|
||||
|
||||
public function decrypt() {
|
||||
if (!$this->isEncrypted()) {
|
||||
return $this->pathHash;
|
||||
|
|
@ -48,19 +65,18 @@ class GPGCryptography
|
|||
return false;
|
||||
}
|
||||
$decryptFolder = sys_get_temp_dir()."/".uniqid('pdfsignature.decrypted.'.getmypid(), true);
|
||||
putenv('HOME='.sys_get_temp_dir());
|
||||
mkdir($decryptFolder);
|
||||
foreach ($this->getFiles(true) as $file) {
|
||||
$outputFile = $decryptFolder."/".str_replace(".gpg", "", basename($file));
|
||||
$command = "gpg --batch --passphrase $this->symmetricKey --decrypt -o $outputFile $file > /dev/null";
|
||||
$result = shell_exec($command);
|
||||
if ($result) {
|
||||
throw new Exception("Decipher failure");
|
||||
}
|
||||
$this->runDecryptFile($file, $decryptFolder."/".str_replace(".gpg", "", basename($file)));
|
||||
}
|
||||
return $decryptFolder;
|
||||
}
|
||||
|
||||
public function runDecryptFile($file, $outputFile) {
|
||||
putenv('HOME='.sys_get_temp_dir());
|
||||
shell_exec("gpg --batch --passphrase $this->symmetricKey --decrypt -o $outputFile $file > /dev/null");
|
||||
}
|
||||
|
||||
public function isEncrypted() {
|
||||
return self::isPathEncrypted($this->pathHash);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,62 +7,131 @@ class PDFSignature
|
|||
protected $hash = null;
|
||||
protected $gpg = null;
|
||||
protected $toClean = [];
|
||||
protected $lockFile = null;
|
||||
|
||||
public function __construct($pathHash, $symmetricKey = null) {
|
||||
$this->symmetricKey = $symmetricKey;
|
||||
$this->pathHash = $pathHash;
|
||||
$this->hash = basename($this->pathHash);
|
||||
$this->gpg = new GPGCryptography($symmetricKey, $pathHash);
|
||||
}
|
||||
$this->lockFile = $this->pathHash.'/.lock';
|
||||
}
|
||||
|
||||
public function createShare($duration) {
|
||||
public function createShare($originalFile, $originFileBaseName, $duration) {
|
||||
mkdir($this->pathHash);
|
||||
$expireFile = $this->pathHash.".expire";
|
||||
file_put_contents($expireFile, $duration);
|
||||
touch($expireFile, date_format(date_modify(date_create(), file_get_contents($expireFile)), 'U'));
|
||||
}
|
||||
|
||||
public function saveShare() {
|
||||
rename($originalFile, $this->pathHash.'/original.pdf');
|
||||
file_put_contents($this->pathHash.'/filename.txt', $originFileBaseName);
|
||||
if($this->symmetricKey) {
|
||||
$this->gpg->encrypt();
|
||||
}
|
||||
}
|
||||
|
||||
public function isEncrypted() {
|
||||
return $this->isEncrypted();
|
||||
}
|
||||
|
||||
public function getDecryptFile($file) {
|
||||
if($this->isEncrypted()) {
|
||||
$file = $this->gpg->decryptFile($file);
|
||||
$this->toClean[] = $file;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
public function getPDF() {
|
||||
$originalPathHash = $this->pathHash;
|
||||
$this->pathHash = $this->gpg->decrypt();
|
||||
if ($this->pathHash == false) {
|
||||
$this->compile();
|
||||
|
||||
return $this->getDecryptFile($this->pathHash.'/final.pdf');
|
||||
}
|
||||
|
||||
public function needToCompile() {
|
||||
$needToCompile = false;
|
||||
foreach($this->getLayers() as $layerFile) {
|
||||
if(!file_exists(str_replace('.svg.pdf', '.sign.pdf', $layerFile))) {
|
||||
$needToCompile = true;
|
||||
}
|
||||
}
|
||||
if(!$this->isEncrypted() && !file_exists($this->pathHash.'/final.pdf')) {
|
||||
$needToCompile = true;
|
||||
}
|
||||
if($this->isEncrypted() && !file_exists($this->pathHash.'/final.pdf.gpg')) {
|
||||
$needToCompile = true;
|
||||
}
|
||||
|
||||
return $needToCompile;
|
||||
}
|
||||
|
||||
protected function isCompileLock() {
|
||||
if(file_exists(touch($this->lockFile)) && filemtime($this->lockFile) > time() + 30) {
|
||||
unlink($this->lockFile);
|
||||
}
|
||||
|
||||
return file_exists(touch($this->lockFile));
|
||||
}
|
||||
|
||||
protected function lockCompile() {
|
||||
touch($this->lockFile);
|
||||
}
|
||||
|
||||
protected function unlockCompile() {
|
||||
unlink($this->lockFile);
|
||||
}
|
||||
|
||||
public function compile() {
|
||||
if(!$this->needToCompile()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->isCompileLock()) {
|
||||
sleep(5);
|
||||
$this->compile();
|
||||
}
|
||||
|
||||
$this->lockCompile();
|
||||
|
||||
$pathHashDecrypted = $this->gpg->decrypt();
|
||||
|
||||
if ($pathHashDecrypted == false) {
|
||||
throw new Exception("PDF file could not be decrypted. Cookie encryption key might be missing.");
|
||||
}
|
||||
if ($this->pathHash != $originalPathHash && $this->gpg->isEncrypted()) {
|
||||
$this->toClean[] = $this->pathHash;
|
||||
if ($this->pathHash != $pathHashDecrypted && $this->isEncrypted()) {
|
||||
$this->toClean[] = $pathHashDecrypted;
|
||||
}
|
||||
|
||||
$originalFile = $this->pathHash.'/original.pdf';
|
||||
$finalFile = $this->pathHash.'/'.$this->hash.uniqid().'.pdf';
|
||||
$layers = $this->getLayers();
|
||||
if(!count($layers)) {
|
||||
return $originalFile;
|
||||
}
|
||||
|
||||
copy($originalFile, $finalFile);
|
||||
$bufferFile = $finalFile.".tmp";
|
||||
$layers = $this->getLayers($pathHashDecrypted);
|
||||
$currentSignedFile = $pathHashDecrypted.'/original.pdf';
|
||||
$signedFileToCopy = [];
|
||||
foreach($layers as $layerFile) {
|
||||
self::addSvgToPDF($finalFile, $layerFile, $bufferFile, false);
|
||||
rename($bufferFile, $finalFile);
|
||||
$signedFile = str_replace('.svg.pdf', '.sign.pdf', $layerFile);
|
||||
if(!file_exists($signedFile)) {
|
||||
self::addSvgToPDF($currentSignedFile, $layerFile, $signedFile, false);
|
||||
if ($this->pathHash != $pathHashDecrypted && $this->isEncrypted()) {
|
||||
copy($signedFile, str_replace($pathHashDecrypted ,$this->pathHash, $signedFile));
|
||||
}
|
||||
}
|
||||
$currentSignedFile = $signedFile;
|
||||
}
|
||||
|
||||
if ($this->pathHash == $originalPathHash && !$this->gpg->isEncrypted()) {
|
||||
$this->toClean[] = $finalFile;
|
||||
copy($currentSignedFile, $this->pathHash.'/final.pdf');
|
||||
|
||||
if($this->isEncrypted()) {
|
||||
$this->gpg->encrypt();
|
||||
}
|
||||
|
||||
return $finalFile;
|
||||
$this->unlockCompile();
|
||||
}
|
||||
|
||||
public function getPublicFilename() {
|
||||
$filename = $this->hash.'.pdf';
|
||||
if(file_exists($this->pathHash."/filename.txt")) {
|
||||
$filename = file_get_contents($this->pathHash."/filename.txt");
|
||||
|
||||
$file = $this->getDecryptFile($this->pathHash."/filename.txt");
|
||||
|
||||
if(file_exists($file)) {
|
||||
$filename = file_get_contents($file);
|
||||
}
|
||||
|
||||
$filename = str_replace('.pdf', '_signe-'.count($this->getLayers()).'x.pdf', $filename);
|
||||
|
|
@ -70,27 +139,36 @@ class PDFSignature
|
|||
return $filename;
|
||||
}
|
||||
|
||||
protected function getLayers() {
|
||||
$files = scandir($this->pathHash);
|
||||
protected function getLayers($pathHash = null) {
|
||||
if(is_null($pathHash)) {
|
||||
$pathHash = $this->pathHash;
|
||||
}
|
||||
$files = scandir($pathHash);
|
||||
$layers = [];
|
||||
foreach($files as $file) {
|
||||
if(strpos($file, '.svg.pdf') !== false) {
|
||||
$layers[] = $this->pathHash.'/'.$file;
|
||||
$layers[] = $pathHash.'/'.$file;
|
||||
}
|
||||
}
|
||||
return $layers;
|
||||
}
|
||||
|
||||
public function addSignature(array $svgFiles, $outputPdfFile) {
|
||||
public function addSignature(array $svgFiles) {
|
||||
$expireFile = $this->pathHash.".expire";
|
||||
touch($expireFile, date_format(date_modify(date_create(), file_get_contents($expireFile)), 'U'));
|
||||
|
||||
self::createPDFFromSvg($svgFiles, $outputPdfFile);
|
||||
do {
|
||||
if(isset($svgPDFFile)) { usleep(1); }
|
||||
$svgPDFFile = $this->pathHash."/".(new DateTime())->format('YmdHisu').'.svg.pdf';
|
||||
} while (file_exists($svgPDFFile));
|
||||
|
||||
if($this->gpg->isEncrypted()) {
|
||||
self::createPDFFromSvg($svgFiles, $svgPDFFile);
|
||||
|
||||
if($this->isEncrypted()) {
|
||||
$this->gpg->encrypt();
|
||||
}
|
||||
$this->toClean = array_merge($this->toClean, $svgFiles);
|
||||
$this->compile();
|
||||
}
|
||||
|
||||
public static function createPDFFromSvg(array $svgFiles, $outputPdfFile) {
|
||||
|
|
@ -106,6 +184,9 @@ class PDFSignature
|
|||
|
||||
public function clean() {
|
||||
foreach($this->toClean as $path) {
|
||||
if(strpos($path, $this->pathHash) !== false) {
|
||||
continue;
|
||||
}
|
||||
GPGCryptography::hardUnlink($path);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue