aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2019-08-01 18:20:05 -0400
committerFranklin Wei <git@fwei.tk>2019-08-01 18:20:05 -0400
commit142af6c8a2e399b52a7c1a3c8ccb9a298c5d62d0 (patch)
tree0b2c532ede2b957c7fc2b46ccac1105a72e260c2
parentea4d2939c96ef00fa41e942b5b93dfe3fec57523 (diff)
downloadjobscope-142af6c8a2e399b52a7c1a3c8ccb9a298c5d62d0.zip
jobscope-142af6c8a2e399b52a7c1a3c8ccb9a298c5d62d0.tar.gz
jobscope-142af6c8a2e399b52a7c1a3c8ccb9a298c5d62d0.tar.bz2
jobscope-142af6c8a2e399b52a7c1a3c8ccb9a298c5d62d0.tar.xz
Add logging, clean up error handling, styling
-rw-r--r--.gitignore2
-rw-r--r--index.html35
-rw-r--r--package-lock.json25
-rw-r--r--package.json2
-rw-r--r--server.js78
-rwxr-xr-xsort.sh27
6 files changed, 125 insertions, 44 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..50a0c39
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*~
+node_modules/
diff --git a/index.html b/index.html
index d585f6d..49137ca 100644
--- a/index.html
+++ b/index.html
@@ -16,6 +16,24 @@
padding-right: 10px; /* 3 */
padding-left: 10px; /* 3 */
}
+
+ footer {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ text-align: center;
+ font-size: 8pt;
+ width: 100%;
+ }
+ label {
+ display: block;
+ font: 1rem 'Fira Sans', sans-serif;
+ }
+
+ input,
+ label {
+ margin: .4rem 0;
+ }
</style>
</head>
<body>
@@ -27,9 +45,22 @@
</p>
<form method="POST" action="/" enctype="multipart/form-data">
- PDF:<br><input type="file" name="file" /><br>
- <input type="submit" />
+ <div>
+ <label for="file">PDF:</label>
+ <input id="file" type="file" name="file" required />
+ </div>
+ <div>
+ <label for="reverse">
+ <input type="checkbox" id="reverse" name="reverse" /> Reverse order
+ </label>
+ </div>
+ <div>
+ <button type="submit">Sort</button>
+ </div>
</form>
</div>
+ <footer>
+ Jobscope-sorter v1.1. Copyright &copy; 2019 <a href="mailto:me@fwei.tk">Franklin Wei</a>.
+ </footer>
</body>
</html>
diff --git a/package-lock.json b/package-lock.json
index 00f75de..80c49d8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,6 +23,14 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
+ "basic-auth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
"body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
@@ -358,6 +366,18 @@
"brace-expansion": "^1.1.7"
}
},
+ "morgan": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
+ "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
+ "requires": {
+ "basic-auth": "~2.0.0",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "on-headers": "~1.0.1"
+ }
+ },
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -376,6 +396,11 @@
"ee-first": "1.1.1"
}
},
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
diff --git a/package.json b/package.json
index de08f66..385eb39 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"author": "",
"license": "ISC",
"dependencies": {
+ "body-parser": "^1.19.0",
"busboy": "^0.3.1",
"child_process": "^1.0.2",
"express": "^4.17.1",
@@ -17,6 +18,7 @@
"formidable": "^1.2.1",
"fs": "0.0.1-security",
"http": "0.0.0",
+ "morgan": "^1.9.1",
"os": "^0.1.1",
"tmp": "^0.1.0",
"unique-filename": "^1.1.1"
diff --git a/server.js b/server.js
index 34a118e..8cda512 100644
--- a/server.js
+++ b/server.js
@@ -2,15 +2,19 @@ const express = require('express');
const fileUpload = require('express-fileupload');
const fs = require('fs');
const http = require('http');
+const morgan = require('morgan')
const os = require('os');
const { exec } = require('child_process');
const tmp = require('tmp');
const uniqueFilename = require('unique-filename');
+const bodyParser = require('body-parser');
const app = express();
const page = fs.readFileSync('index.html');
app.use(fileUpload());
+app.use(morgan('combined'));
+app.use(bodyParser.urlencoded({ extended: true }));
const port = 8080;
@@ -18,54 +22,52 @@ const OUTDIR="/app/output";
function performSort(req, res)
{
+ console.log(req);
+
try {
- if(typeof req.files != 'undefined')
- {
- file = req.files.file;
- if(typeof file != 'undefined')
- {
- var options = {};
- var tmpname = uniqueFilename(os.tmpdir()) + '.pdf';
- file.mv(tmpname);
-
- var outname = uniqueFilename(OUTDIR) + '.pdf';
-
- exec("/app/sort.sh " + tmpname + ' ' + outname,
- (err, stdout, stderr) =>
+ reverse = Boolean(req.body.reverse);
+ file = req.files.file;
+ var options = {};
+ var tmpname = uniqueFilename(os.tmpdir()) + '.pdf';
+ file.mv(tmpname);
+
+ var outname = uniqueFilename(OUTDIR) + '.pdf';
+
+ var cmd = "/app/sort.sh " + tmpname + " " + outname;
+ if(reverse)
+ cmd += " -r";
+
+ exec(cmd, (err, stdout, stderr) =>
+ {
+ try {
+ if(err)
+ throw err;
+ else
{
- if(err)
+ try {
+ out = fs.readFileSync(outname);
+
+ res.header("Content-type", "application/pdf");
+
+ res.send(out);
+ } catch(err)
{
res.status(500);
- res.render('internal server error');
- }
- else
- {
- try {
- out = fs.readFileSync(outname);
-
- res.header("Content-type", "application/pdf");
-
- res.send(out);
- } catch(err)
- {
- res.status(500);
- res.json({message: 'bad input'});
- }
+ res.json({message: 'bad input'});
}
}
- );
- return;
- }
- }
+ } finally {
+ fs.unlink(tmpname, (err)=>{if(err) console.log('unlink error')});
+ fs.unlink(outname, (err)=>{if(err) console.log('unlink error')});
+ }
+ });
+ return;
}
catch(error)
{
- // no-op, fall through
+ res.status(500);
+ res.json({message: 'bad upload'});
}
-
- // error if here
- res.status(500);
- res.json({message: 'bad upload'});
}
app.get('/', (req, res) => { res.header("Content-type", "text/html"); res.send(page) });
diff --git a/sort.sh b/sort.sh
index 5a55b39..de50df8 100755
--- a/sort.sh
+++ b/sort.sh
@@ -6,22 +6,36 @@
# This takes a PDF file as input and sorts its pages based on a
# "Part:" field. Produced under contract for Piedmont Hoist & Crane.
-if [ $# -ne 2 ]
+if [ $# -ne 2 ] && [ $# -ne 3 ]
then
- echo "Usage: sort.sh INPUT OUTPUT"
+ echo "Usage: sort.sh INPUT OUTPUT [-r]"
+ echo ""
+ echo "INPUT and OUTPUT are PDFs. -r reverses sort order."
exit
fi
input="$1"
output="$2"
+if [ -n "$3" ] && [ ${3} = "-r" ]
+then
+ rev="-r"
+
+ # reverse pages (this preserves the ordering of pages with the
+ # same part number)
+ revtmp=$(mktemp -t jobscope-rev-XXXXXX)
+ pdftk $input cat end-1 output $revtmp
+ input=$revtmp
+fi
+
tmpdir=$(mktemp -d -t jobscope-XXXXXX)
-pdftk $input burst output $tmpdir/pg_%04d.pdf
+
+pdftk $input burst output $tmpdir/pg_%06d.pdf
for f in $tmpdir/pg_*.pdf
do
echo $(pdftotext $f - | awk -f extract_partnum.awk) $f
-done | sort -n > $tmpdir/list.txt
+done | sort -n $rev > $tmpdir/list.txt
awk '{print $2}' < $tmpdir/list.txt > $tmpdir/list_final.txt
@@ -29,3 +43,8 @@ awk '{print $2}' < $tmpdir/list.txt > $tmpdir/list_final.txt
pdftk $(tr '\n' ' ' < $tmpdir/list_final.txt) cat output $output
rm $tmpdir -rf
+
+if [ -n $revtmp ]
+then
+ rm -f $revtmp
+fi