Compare commits

...

4 commits

9 changed files with 110 additions and 43 deletions

5
.gitignore vendored
View file

@ -1,9 +1,8 @@
conf/*.json queue/*
conf/*.db archive/*
.DS_Store .DS_Store
node_modules/ node_modules/
__pycache__ __pycache__
storage/*
npm-debug*.log npm-debug*.log
ssl/*.pem ssl/*.pem
*.py[cod] *.py[cod]

62
dist/index.html vendored
View file

@ -1,22 +1,52 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" type="text/css" href="/static/css/iziToast.min.css"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="/static/js/iziToast.min.js"></script> <link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
<script src="/static/js/httprint.js"></script> <link rel="stylesheet" type="text/css" href="/static/css/jquery.toast.min.css">
<title>HTTPrint</title> <script src="/static/js/jquery-3.4.1.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<script src="/static/js/jquery.toast.min.js"></script>
<script src="/static/js/httprint.js"></script>
<title>HTTPrint</title>
</head> </head>
<body> <body>
<h1>Upload a file to print</h1> <div class="container">
<div class="row">
File to print: <input id="upload-file" type="file" /> <div class="col-sm">
<br> <div class="jumbotron jumbotron-fluid">
<br> <div class="container">
Number of copies: <input id="copies" type="number" min="1" max="10" value="1" /> <h1 class="display-4">HTTPrint</h1>
<br> <p class="lead">Upload and print a <strong>PDF file</strong>. The maximum number of pages that can be printed is <strong>10</strong>.</p>
<br> Instructions:
<button onClick="uploadFile();">print</button> <ol>
<li>Upload a file, select the number of copies and click the "print" button</li>
<li>Write down the code you will receive</li>
<li>head to the printer</li>
<li>insert the code in the touchpad</li>
</ol>
</div>
</div>
<div class="form-group">
<label for="upload-file">File to print</label>
<input id="upload-file" type="file" class="form-control-file">
</div>
<div class="form-group">
<label for="copies">Number of copies</label>
<input id="copies" type="number" min="1" max="10" value="1" class="form-control">
</div>
<button id="print-btn" class="btn-lg btn-primary">print</button>
</div>
</div>
</div>
<footer class="footer mt-auto py-3">
<div class="container">
<span class="text-muted">
HTTPrint <a href="https://github.com/alberanid/httprint">https://github.com/alberanid/httprint</a>
</span>
</div>
</footer>
</body> </body>
</html> </html>

7
dist/static/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/static/css/jquery.toast.min.css vendored Normal file
View file

@ -0,0 +1 @@
.jq-toast-wrap,.jq-toast-wrap *{margin:0;padding:0}.jq-toast-wrap{display:block;position:fixed;width:250px;pointer-events:none!important;letter-spacing:normal;z-index:9000!important}.jq-toast-wrap.bottom-left{bottom:20px;left:20px}.jq-toast-wrap.bottom-right{bottom:20px;right:40px}.jq-toast-wrap.top-left{top:20px;left:20px}.jq-toast-wrap.top-right{top:20px;right:40px}.jq-toast-single{display:block;width:100%;padding:10px;margin:0 0 5px;border-radius:4px;font-size:12px;font-family:arial,sans-serif;line-height:17px;position:relative;pointer-events:all!important;background-color:#444;color:#fff}.jq-toast-single h2{font-family:arial,sans-serif;font-size:14px;margin:0 0 7px;background:0 0;color:inherit;line-height:inherit;letter-spacing:normal}.jq-toast-single a{color:#eee;text-decoration:none;font-weight:700;border-bottom:1px solid #fff;padding-bottom:3px;font-size:12px}.jq-toast-single ul{margin:0 0 0 15px;background:0 0;padding:0}.jq-toast-single ul li{list-style-type:disc!important;line-height:17px;background:0 0;margin:0;padding:0;letter-spacing:normal}.close-jq-toast-single{position:absolute;top:3px;right:7px;font-size:14px;cursor:pointer}.jq-toast-loader{display:block;position:absolute;top:-2px;height:5px;width:0;left:0;border-radius:5px;background:red}.jq-toast-loaded{width:100%}.jq-has-icon{padding:10px 10px 10px 50px;background-repeat:no-repeat;background-position:10px}.jq-icon-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=);background-color:#31708f;color:#d9edf7;border-color:#bce8f1}.jq-icon-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=);background-color:#8a6d3b;color:#fcf8e3;border-color:#faebcc}.jq-icon-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=);background-color:#a94442;color:#f2dede;border-color:#ebccd1}.jq-icon-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==);color:#dff0d8;background-color:#3c763d;border-color:#d6e9c6}

7
dist/static/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,42 +1,61 @@
function uploadFile() { function uploadFile() {
let photo = document.getElementById("upload-file").files[0]; let photo = document.getElementById("upload-file").files[0];
let copies = document.getElementById('copies').value; let copies = document.getElementById("copies").value;
let formData = new FormData(); let formData = new FormData();
formData.append("file", photo); formData.append("file", photo);
formData.append("copies", copies); formData.append("copies", copies);
var uploadField = document.getElementById('upload-file'); var uploadField = document.getElementById("upload-file");
fetch("/api/upload", {method: "POST", body: formData}) fetch("/api/upload", {method: "POST", body: formData})
.then(function(response) { .then(function(response) {
return response.json(); return response.json();
}) })
.then(function(reply) { .then(function(reply) {
if (reply && !reply.error) { if (reply && !reply.error) {
iziToast.success({ $.toast({
title: "DONE!", text: reply.message || "file sent to printer",
message: reply.message, heading: "DONE!",
position: 'topCenter', icon: "success",
timeout: false, showHideTransition: "fade",
closeOnEscape: true, allowToastClose: true,
layout: 2 hideAfter: false,
stack: 5,
position: "top-center"
}); });
uploadField.value = null;
copies.value = 1;
} else { } else {
iziToast.error({ $.toast({
title: "ERROR!", text: reply.message || "unable to print file",
message: reply.message, heading: "ERROR!",
position: 'topCenter', icon: "error",
layout: 2 showHideTransition: "fade",
allowToastClose: true,
hideAfter: 5000,
stack: 5,
position: "top-center"
}); });
} }
uploadField.value = null;
}) })
.catch(function(err) { .catch(function(err) {
iziToast.error({ console.log(err);
title: "ERROR!", $.toast({
message: "failed to send file", text: "failed to send file",
position: 'topCenter', heading: "ERROR!",
layout: 2 icon: "error",
showHideTransition: "fade",
allowToastClose: true,
hideAfter: 5000,
stack: 5,
position: "top-center"
}); });
uploadField.value = null;
}); });
} }
document.addEventListener("DOMContentLoaded", function(event) {
let pbutton = document.getElementById("print-btn");
pbutton.addEventListener("click", function(event) {
uploadFile();
});
});

2
dist/static/js/jquery-3.4.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/static/js/jquery.toast.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -241,12 +241,13 @@ class UploadHandler(BaseHandler):
failure = True failure = True
out = out.decode('utf-8', errors='ignore') out = out.decode('utf-8', errors='ignore')
pages = int(re_pages.findall(out)[0]) pages = int(re_pages.findall(out)[0])
if pages * copies > self.cfg.max_pages and self.cfg.check_pdf_pages: if pages * copies > self.cfg.max_pages and self.cfg.check_pdf_pages and not failure:
self.build_error('too many pages to print (%d)' % (pages * copies)) self.build_error('too many pages to print (%d)' % (pages * copies))
failure = True failure = True
except Exception: except Exception:
self.build_error('unable to get PDF information') if not failure:
failure = True self.build_error('unable to get PDF information')
failure = True
pass pass
if failure: if failure:
for fn in glob.glob(pname + '*'): for fn in glob.glob(pname + '*'):