Compare commits

...

12 Commits

8 changed files with 114 additions and 53 deletions

View File

@ -1,4 +1,4 @@
FROM php:7.4-apache
FROM php:8.2-apache
ENV SERVERNAME=localhost
ENV UPLOAD_MAX_FILESIZE=24M

22
app.php
View File

@ -10,6 +10,8 @@ $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('COMMIT', getCommit());
$f3->config(__DIR__.'/config/config.ini');
if($f3->get('PDF_STORAGE_PATH') && !preg_match('|/$|', $f3->get('PDF_STORAGE_PATH'))) {
@ -359,6 +361,26 @@ $f3->route('GET /metadata',
}
);
function getCommit() {
if(!file_exists(__DIR__.'/.git/HEAD')) {
return null;
}
$head = str_replace(["ref: ", "\n"], "", file_get_contents(__DIR__.'/.git/HEAD'));
$commit = null;
if(strpos($head, "refs/") !== 0) {
$commit = $head;
}
if(file_exists(__DIR__.'/.git/'.$head)) {
$commit = str_replace("\n", "", file_get_contents(__DIR__.'/.git/'.$head));
}
return substr($commit, 0, 7);
}
function convertPHPSizeToBytes($sSize)
{
$sSuffix = strtoupper(substr($sSize, -1));

View File

@ -6,6 +6,7 @@ envsubst < /usr/local/signaturepdf/config/config.ini.tpl > /usr/local/signaturep
if [[ ! -z $PDF_STORAGE_PATH ]] ; then
mkdir -p $PDF_STORAGE_PATH
chown www-data:www-data $PDF_STORAGE_PATH
fi
apache2-foreground

View File

@ -556,6 +556,24 @@ var degreesToOrientation = function(degrees) {
return null;
}
var uploadAndLoadPDF = async function(input_upload) {
const cache = await caches.open('pdf');
for (let i = 0; i < input_upload.files.length; i++) {
if(input_upload.files[i].size > maxSize) {
alert("Le PDF ne doit pas dépasser " + Math.round(maxSize/1024/1024) + " Mo");
break;
}
let filename = input_upload.files[i].name;
let response = new Response(input_upload.files[i], { "status" : 200, "statusText" : "OK" });
let urlPdf = '/pdf/'+filename;
await cache.put(urlPdf, response);
let pdfBlob = await getPDFBlobFromCache(urlPdf);
nbPDF++;
await loadPDF(pdfBlob, filename, nbPDF);
}
}
var createEventsListener = function() {
document.getElementById('save-select_mobile').addEventListener('click', function(event) {
document.getElementById('save').click();
@ -592,21 +610,7 @@ var createEventsListener = function() {
document.getElementById('save').click();
});
document.getElementById('input_pdf_upload_2').addEventListener('change', async function(event) {
for (let i = 0; i < this.files.length; i++) {
if(this.files[i].size > maxSize) {
alert("Le PDF ne doit pas dépasser " + Math.round(maxSize/1024/1024) + " Mo");
break;
}
const cache = await caches.open('pdf');
let filename = this.files[i].name;
let response = new Response(this.files[i], { "status" : 200, "statusText" : "OK" });
let urlPdf = '/pdf/'+filename;
await cache.put(urlPdf, response);
let pdfBlob = await getPDFBlobFromCache(urlPdf);
nbPDF++;
await loadPDF(pdfBlob, filename, nbPDF);
}
await uploadAndLoadPDF(this);
this.value = '';
});
document.getElementById('btn-zoom-decrease').addEventListener('click', function(event) {
@ -749,39 +753,19 @@ var pageUpload = async function() {
return;
}
document.getElementById('input_pdf_upload').addEventListener('change', async function(event) {
if(document.getElementById('input_pdf_upload').files[0].size > maxSize) {
alert("Le PDF ne doit pas dépasser " + Math.round(maxSize/1024/1024) + " Mo");
document.getElementById('input_pdf_upload').value = "";
return;
}
let filename = document.getElementById('input_pdf_upload').files[0].name;
let response = new Response(document.getElementById('input_pdf_upload').files[0], { "status" : 200, "statusText" : "OK" });
let urlPdf = '/pdf/'+filename;
await cache.put(urlPdf, response);
history.pushState({}, '', '/organization#'+filename);
pageOrganization(urlPdf)
uploadAndLoadPDF(this);
pageOrganization(null);
});
}
var pageOrganization = async function(url) {
let filename = url.replace('/pdf/', '');
document.title = filename + ' - ' + document.title;
var pageOrganization = async function() {
document.querySelector('body').classList.add('bg-light');
document.getElementById('page-upload').classList.add('d-none');
document.getElementById('page-organization').classList.remove('d-none');
menu = document.getElementById('sidebarTools');
menuOffcanvas = new bootstrap.Offcanvas(menu);
responsiveDisplay();
let pdfBlob = await getPDFBlobFromCache(url);
if(!pdfBlob) {
document.location = '/organization';
return;
}
createEventsListener();
loadPDF(pdfBlob, filename, nbPDF);
};
(function () {
@ -789,8 +773,6 @@ var pageOrganization = async function(url) {
let hashUrl = window.location.hash.replace(/^\#/, '');
pageUpload();
uploadFromUrl(hashUrl);
} else if(window.location.hash) {
pageOrganization('/pdf/'+window.location.hash.replace(/^\#/, ''));
} else {
pageUpload();
}

View File

@ -17,6 +17,8 @@ var menuOffcanvas = null;
var currentCursor = null;
var signaturePad = null;
var nblayers = null;
var hasModifications = false;
var currentTextScale = 1;
var loadPDF = async function(pdfBlob, filename) {
const pdfjsLib = window['pdfjs-dist/build/pdf'];
@ -135,6 +137,10 @@ var loadPDF = async function(pdfBlob, filename) {
}
});
canvasEdition.on('object:scaled', function(event) {
if (event.target instanceof fabric.IText) {
currentTextScale = event.target.scaleX;
return;
}
var item = getSvgItem(event.target.svgOrigin);
if(!item) {
return;
@ -495,9 +501,15 @@ var addObjectInCanvas = function(canvas, item) {
};
var createAndAddSvgInCanvas = function(canvas, item, x, y, height = null) {
if(document.querySelector('#alert-signature-help')) {
document.querySelector('#alert-signature-help').classList.add('d-none');
}
if(document.getElementById('save')) {
document.getElementById('save').removeAttribute('disabled');
}
hasModifications = true;
if(document.getElementById('save_mobile')) {
document.getElementById('save_mobile').removeAttribute('disabled');
}
@ -526,6 +538,8 @@ var createAndAddSvgInCanvas = function(canvas, item, x, y, height = null) {
addObjectInCanvas(canvas, textbox).setActiveObject(textbox);
textbox.keysMap[13] = "exitEditing";
textbox.lockScalingFlip = true;
textbox.scaleX = currentTextScale;
textbox.scaleY = currentTextScale;
textbox.enterEditing();
textbox.selectAll();
@ -709,6 +723,10 @@ var createEventsListener = function() {
}
document.querySelector('#'+svg_list_id+' label:last-child').click();
if(document.querySelector('#save').disabled && document.querySelector('#alert-signature-help.auto-open') && !is_mobile()) {
document.querySelector('#alert-signature-help').classList.remove('d-none');
}
});
@ -762,6 +780,17 @@ var createEventsListener = function() {
event.preventDefault();
});
if(document.querySelector('#alert-signature-help')) {
document.getElementById('btn-signature-help').addEventListener('click', function(event) {
document.querySelector('#alert-signature-help').classList.remove('d-none');
event.preventDefault();
});
document.querySelector('#alert-signature-help .btn-close').addEventListener('click', function(event) {
document.querySelector('#alert-signature-help').classList.add('d-none');
event.preventDefault();
});
}
if(document.getElementById('save')) {
document.getElementById('save').addEventListener('click', function(event) {
let dataTransfer = new DataTransfer();
@ -771,6 +800,7 @@ var createEventsListener = function() {
}));
})
document.getElementById('input_svg').files = dataTransfer.files;
hasModifications = false;
});
}
@ -785,6 +815,7 @@ var createEventsListener = function() {
})
}
document.getElementById('input_svg_share').files = dataTransfer.files;
hasModifications = false;
});
}
@ -903,6 +934,15 @@ var createEventsListener = function() {
zoomChange(1)
});
window.addEventListener('beforeunload', function(event) {
if(!hasModifications) {
return;
}
event.preventDefault();
return true;
});
if(hash) {
updateNbLayers();
setInterval(function() {
@ -1057,6 +1097,10 @@ var pageSignature = async function(url) {
svgCollections = JSON.parse(localStorage.getItem('svgCollections'));
}
if(svgCollections.length == 0 && document.querySelector('#alert-signature-help')) {
document.querySelector('#alert-signature-help').classList.add('auto-open');
}
opentype.load('/vendor/fonts/Caveat-Regular.ttf', function(err, font) {
fontCaveat = font;
});

View File

@ -7,7 +7,7 @@
<link href="/vendor/bootstrap.min.css?5.1.1" rel="stylesheet">
<link href="/vendor/bootstrap-icons.css?1.5.0" rel="stylesheet">
<link href="/css/app.css?202210080134" rel="stylesheet">
<link href="/css/app.css?<?php echo ($COMMIT) ? $COMMIT : filemtime($ROOT."/public/css/app.css") ?>" rel="stylesheet">
<link rel="icon" type="image/x-icon" href="/favicon-metadata.ico">
<title>Édition des métadonnées d'un PDF</title>
@ -45,7 +45,7 @@
</div>
</div>
<footer class="text-center text-muted mb-2 fixed-bottom opacity-75">
<small>Logiciel libre <span class="d-none d-md-inline">sous license AGPL-3.0 </span>: <a href="https://github.com/24eme/signaturepdf">voir le code source</a></small>
<small>Logiciel libre <span class="d-none d-md-inline">sous license AGPL-3.0</span> : <a href="https://github.com/24eme/signaturepdf">voir le code source </a><?php if($COMMIT): ?> <span class="d-none d-md-inline small">[<a href="https://github.com/24eme/signaturepdf/tree/<?php echo $COMMIT ?>"><?php echo $COMMIT ?></a>]</span><?php endif; ?></small>
</footer>
</div>
<div id="page-metadata" class="d-none">
@ -102,6 +102,6 @@
<script>
var defaultFields = <?php echo json_encode(isset($METADATA_DEFAULT_FIELDS) ? $METADATA_DEFAULT_FIELDS : array()); ?>;
</script>
<script src="/js/metadata.js?202304030148"></script>
<script src="/js/metadata.js?<?php echo ($COMMIT) ? $COMMIT : filemtime($ROOT."/public/js/metadata.js") ?>"></script>
</body>
</html>

View File

@ -7,7 +7,7 @@
<link href="/vendor/bootstrap.min.css?5.1.1" rel="stylesheet">
<link href="/vendor/bootstrap-icons.css?1.5.0" rel="stylesheet">
<link href="/css/app.css?202210080134" rel="stylesheet">
<link href="/css/app.css?<?php echo ($COMMIT) ? $COMMIT : filemtime($ROOT."/public/css/app.css") ?>" rel="stylesheet">
<link rel="icon" type="image/x-icon" href="/favicon-organization.ico">
<title>Organiser un PDF</title>
@ -36,7 +36,7 @@
<div class="col-md-6 col-lg-5 col-xl-4 col-xxl-3 mx-auto">
<div class="col-12">
<label class="form-label mt-3" for="input_pdf_upload">Choisir un PDF <small class="opacity-75" style="cursor: help" title="Le PDF ne doit pas dépasser <?php echo round($maxSize / 1024 / 1024) ?> Mo"><i class="bi bi-info-circle"></i></small></label>
<input id="input_pdf_upload" placeholder="Choisir un PDF" class="form-control form-control-lg" type="file" accept=".pdf,application/pdf" />
<input id="input_pdf_upload" placeholder="Choisir un PDF" class="form-control form-control-lg" type="file" accept=".pdf,application/pdf" multiple="true" />
<p class="mt-2 small fw-light text-dark">Le PDF sera traité par le serveur sans être conservé ni stocké</p>
<?php if($PDF_DEMO_LINK): ?>
<a class="btn btn-sm btn-link opacity-75" href="#<?php echo $PDF_DEMO_LINK ?>">Tester avec un PDF de démo</a>
@ -45,7 +45,7 @@
</div>
</div>
<footer class="text-center text-muted mb-2 fixed-bottom opacity-75">
<small>Logiciel libre <span class="d-none d-md-inline">sous license AGPL-3.0 </span>: <a href="https://github.com/24eme/signaturepdf">voir le code source</a></small>
<small>Logiciel libre <span class="d-none d-md-inline">sous license AGPL-3.0</span> : <a href="https://github.com/24eme/signaturepdf">voir le code source </a><?php if($COMMIT): ?> <span class="d-none d-md-inline small">[<a href="https://github.com/24eme/signaturepdf/tree/<?php echo $COMMIT ?>"><?php echo $COMMIT ?></a>]</span><?php endif; ?></small>
</footer>
</div>
<div id="page-organization" style="padding-right: 350px;" class="d-none">
@ -157,6 +157,6 @@
<script>
var maxSize = <?php echo $maxSize ?>;
</script>
<script src="/js/organization.js?202304030148"></script>
<script src="/js/organization.js?<?php echo ($COMMIT) ? $COMMIT : filemtime($ROOT."/public/js/organization.js") ?>"></script>
</body>
</html>

View File

@ -7,7 +7,7 @@
<meta name="description" content="Logiciel libre de signature de PDF en ligne">
<link href="/vendor/bootstrap.min.css?5.1.1" rel="stylesheet">
<link href="/vendor/bootstrap-icons.css?1.8.1" rel="stylesheet">
<link href="/css/app.css" rel="stylesheet">
<link href="/css/app.css?<?php echo ($COMMIT) ? $COMMIT : filemtime($ROOT."/public/css/app.css") ?>" rel="stylesheet">
<title>Signature PDF</title>
</head>
<body>
@ -45,10 +45,20 @@
</div>
</div>
<footer class="text-center text-muted mb-2 fixed-bottom opacity-75">
<small>Logiciel libre <span class="d-none d-md-inline">sous license AGPL-3.0 </span>: <a href="https://github.com/24eme/signaturepdf">voir le code source</a></small>
<small>Logiciel libre <span class="d-none d-md-inline">sous license AGPL-3.0</span> : <a href="https://github.com/24eme/signaturepdf">voir le code source </a><?php if($COMMIT): ?> <span class="d-none d-md-inline small">[<a href="https://github.com/24eme/signaturepdf/tree/<?php echo $COMMIT ?>"><?php echo $COMMIT ?></a>]</span><?php endif; ?></small>
</footer>
</div>
<div id="page-signature" style="padding-right: 350px;" class="d-none">
<?php if(isset($hash)): ?>
<div id="alert-signature-help" class="position-relative d-none">
<div class="alert alert-primary alert-dismissible position-absolute top-0 start-50 translate-middle-x text-center mt-4 pb-2 w-50 opacity-100" style="z-index: 100;" role="alert">
<h5 class="alert-heading">Comment signer ?</h5>
<strong>En cliquant directement sur la page du document</strong> pour insérer l'élément séléctionné dans la colonne de droite <small>(signature, paraphe, texte, tampon, etc ...)</small>
<div class="mt-1 fs-3"><i class="bi bi-box-arrow-down"></i></div>
<button type="button" class="btn-close btn-sm" aria-label="Close"></button>
</div>
</div>
<?php endif; ?>
<div style="height: 65px;" class="d-md-none"></div>
<div id="container-pages" class="col-12 pt-1 pb-1 text-center vh-100">
</div>
@ -104,8 +114,10 @@
<button class="btn btn-primary w-100 mt-2" disabled="disabled" type="submit" id="save"><i class="bi bi-download"></i> Télécharger le PDF signé</button>
</form>
<?php elseif(!isset($noSharingMode)): ?>
<div class="d-none d-sm-none d-md-block">
<p id="nblayers_text" class="small d-none mb-2 opacity-75">Vous êtes <span class="badge rounded-pill border border-dark text-dark"><span class="nblayers">0</span> <i class="bi bi-people-fill"></i></span> à avoir signé ce PDF</p></div>
<div class="d-none d-sm-none d-md-block position-relative">
<a id="btn-signature-help" class="position-absolute top-0 end-0 text-dark" href="" style="z-index: 5;"><i class="bi bi-question-circle"></i></a>
<p id="nblayers_text" class="small d-none mb-2 opacity-75">Vous êtes <span class="badge rounded-pill border border-dark text-dark"><span class="nblayers">0</span> <i class="bi bi-people-fill"></i></span> à avoir signé ce PDF</p>
</div>
<div class="btn-group w-100">
<a id="btn_download" class="btn btn-outline-dark w-100" href="/signature/<?php echo $hash ?>/pdf"><i class="bi bi-download"></i> Télécharger le PDF</a>
<button class="btn btn-outline-dark" type="button" id="btn_share" data-bs-toggle="modal" data-bs-target="#modal-share-informations"><i class="bi bi-share"></i></button>
@ -265,6 +277,6 @@
hash = "<?php echo $hash ?>";
<?php endif; ?>
</script>
<script src="/js/signature.js?202304030148"></script>
<script src="/js/signature.js?<?php echo ($COMMIT) ? $COMMIT : filemtime($ROOT."/public/js/signature.js") ?>"></script>
</body>
</html>