diff --git a/index.js b/index.js index 0cf381c..8a3cbfc 100644 --- a/index.js +++ b/index.js @@ -109,7 +109,7 @@ const upload = multer({ fileFilter: (req, file, cb) => { // Fixes charset // https://github.com/expressjs/multer/issues/1104#issuecomment-1152987772 - file.originalname = doTransliterate(Buffer.from(file.originalname, 'latin1').toString('utf8')) + file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8') console.log('Incoming file:', file) const key = req.body.key.toUpperCase() @@ -159,13 +159,22 @@ router.post('/generate', async ctx => { if(ctx.keys.get(key) === info) removeKey(key) }, maxExpireDuration * 1000) + ctx.cookies.set('key', key, {overwrite: true, httpOnly: false, sameSite: 'strict', maxAge: expireDelay * 1000}) + ctx.body = key }) -router.get('/download/:key', async ctx => { - const key = ctx.params.key.toUpperCase() +async function downloadFile (ctx, next) { + const key = ctx.cookies.get('key') + if (!key) { + await next() + return + } + const filename = decodeURIComponent(ctx.params.filename) const info = ctx.keys.get(key) - if (!info || !info.file) { + + if (!info || !info.file || info.file.name !== filename) { + await next() return } if (info.agent !== ctx.get('user-agent')) { @@ -173,18 +182,13 @@ router.get('/download/:key', async ctx => { return } expireKey(key) - // const fallback = basename(info.file.path) - const sanename = info.file.name.replace(/[^\.\w\-"'\(\)]/g, '_') - console.log('Sending file', [info.file.path, info.file.name, sanename]) - await sendfile(ctx, info.file.path) + console.log('Sending file', [info.file.path, info.file.name]) if (info.agent.includes('Kindle')) { // Kindle needs a safe name or it thinks it's an invalid file - ctx.attachment(sanename) - } else { - // Kobo always uses fallback - ctx.attachment(info.file.name, {fallback: sanename}) + ctx.attachment(info.file.name) } -}) + await sendfile(ctx, info.file.path) +} router.post('/upload', async (ctx, next) => { @@ -282,8 +286,14 @@ router.post('/upload', async (ctx, next) => { let data = null filename = ctx.request.file.originalname + if (ctx.request.body.transliteration) { + filename = doTransliterate(filename) + } + if (info.agent.includes('Kindle')) { + filename = filename.replace(/[^\.\w\-"'\(\)]/g, '_') + } - if (mimetype === TYPE_EPUB && info.agent.includes('Kindle')) { + if (mimetype === TYPE_EPUB && info.agent.includes('Kindle') && ctx.request.body.kindlegen) { // convert to .mobi conversion = 'kindlegen' const outname = ctx.request.file.path.replace(/\.epub$/i, '.mobi') @@ -411,6 +421,7 @@ router.get('/status/:key', async ctx => { return } expireKey(key) + ctx.cookies.set('key', key, {overwrite: true, httpOnly: false, sameSite: 'strict', maxAge: expireDelay * 1000}) ctx.body = { alive: info.alive, file: info.file ? { @@ -431,10 +442,13 @@ router.get('/', async ctx => { await sendfile(ctx, agent.includes('Kobo') || agent.includes('Kindle') || agent.toLowerCase().includes('tolino') ? 'static/download.html' : 'static/upload.html') }) +router.get('/:filename', downloadFile) + +app.use(serve("static")) + app.use(router.routes()) app.use(router.allowedMethods()) -app.use(serve("static")) fs.rm('uploads', {recursive: true}, (err) => { if (err) throw err diff --git a/static/download.html b/static/download.html index 84eeaed..cd989e1 100644 --- a/static/download.html +++ b/static/download.html @@ -84,6 +84,7 @@ function pollFile () { if (data.file) { downloads.style.display = 'block' downloadlink.textContent = data.file.name + downloadlink.href = '/' + encodeURIComponent(data.file.name) } else { downloads.style.display = 'none' } @@ -111,7 +112,7 @@ function generateKey () { if (x.responseText !== 'error' && x.status === 200) { key = x.responseText keyOutput.textContent = key - downloadlink.href = './download/' + key + downloadlink.href = '' if (pollTimer) clearInterval(pollTimer) pollTimer = setInterval(pollFile, 5 * 1000) } else { diff --git a/static/upload.html b/static/upload.html index a52bec3..fd6e4f3 100644 --- a/static/upload.html +++ b/static/upload.html @@ -16,14 +16,16 @@
Go this this page on your Kobo/Kindle ereader and you see a unique key. Enter it in this form and upload an ebook and it will appear as a download link on the ereader.
-If you send an EPUB file to to a Kindle it will be converted to MOBI with KindleGen. If you send a MOBI file to a Kindle it will be sent unprocessed. If you send an EPUB file and tick the Kepubify checkbox, it will be converted into a Kobo EPUB using Kepubify. If you send a MOBI file to a Kobo, it will not be converted.
+If you send an EPUB file to to a Kindle it will be converted to MOBI with KindleGen. If you send a MOBI file to a Kindle it will be sent unprocessed. Files sent to Kindle eReaders will have their names stripped of special characters, a limitation of the Kindle browser. If you send an EPUB file and tick the Kepubify checkbox, it will be converted into a Kobo EPUB using Kepubify. If you send a MOBI file to a Kobo, it will not be converted.
Your ebook will be stored on the server as long as your Kobo/Kindle is viewing the unique key and is connected to wifi. It will be deleted irrevocably when the key expires about 30 seconds after you close the browser, generate a new key or disable wifi on your ereader.
By using this tool you agree that the ebook you upload is processed on the server and stored for a short time.