fixed export with non-ASCII characters in note title, fixes #285, #331

This commit is contained in:
azivner 2019-01-13 10:22:17 +01:00
parent dbc312010b
commit 3d8905207e
5 changed files with 33 additions and 16 deletions

View File

@ -3,6 +3,7 @@
const noteService = require('../../services/notes'); const noteService = require('../../services/notes');
const protectedSessionService = require('../../services/protected_session'); const protectedSessionService = require('../../services/protected_session');
const repository = require('../../services/repository'); const repository = require('../../services/repository');
const utils = require('../../services/utils');
async function uploadFile(req) { async function uploadFile(req) {
const parentNoteId = req.params.parentNoteId; const parentNoteId = req.params.parentNoteId;
@ -49,7 +50,7 @@ async function downloadFile(req, res) {
const originalFileName = await note.getLabel('originalFileName'); const originalFileName = await note.getLabel('originalFileName');
const fileName = originalFileName ? originalFileName.value : note.title; const fileName = originalFileName ? originalFileName.value : note.title;
res.setHeader('Content-Disposition', 'file; filename="' + fileName + '"'); res.setHeader('Content-Disposition', utils.getContentDisposition(fileName));
res.setHeader('Content-Type', note.mime); res.setHeader('Content-Type', note.mime);
res.send(note.content); res.send(note.content);

View File

@ -1,13 +1,10 @@
"use strict"; "use strict";
const sanitize = require("sanitize-filename"); const repository = require("../repository");
const repository = require("../../services/repository"); const utils = require('../utils');
const utils = require('../../services/utils');
async function exportToOpml(branch, res) { async function exportToOpml(branch, res) {
const note = await branch.getNote(); const note = await branch.getNote();
const title = (branch.prefix ? (branch.prefix + ' - ') : '') + note.title;
const sanitizedTitle = sanitize(title);
async function exportNoteInner(branchId) { async function exportNoteInner(branchId) {
const branch = await repository.getBranch(branchId); const branch = await repository.getBranch(branchId);
@ -31,7 +28,9 @@ async function exportToOpml(branch, res) {
res.write('</outline>'); res.write('</outline>');
} }
res.setHeader('Content-Disposition', 'file; filename="' + sanitizedTitle + '.opml"'); const filename = (branch.prefix ? (branch.prefix + ' - ') : '') + note.title + ".opml";
res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
res.setHeader('Content-Type', 'text/x-opml'); res.setHeader('Content-Type', 'text/x-opml');
res.write(`<?xml version="1.0" encoding="UTF-8"?> res.write(`<?xml version="1.0" encoding="UTF-8"?>

View File

@ -1,9 +1,9 @@
"use strict"; "use strict";
const sanitize = require("sanitize-filename");
const TurndownService = require('turndown'); const TurndownService = require('turndown');
const mimeTypes = require('mime-types'); const mimeTypes = require('mime-types');
const html = require('html'); const html = require('html');
const utils = require('../utils');
async function exportSingleNote(branch, format, res) { async function exportSingleNote(branch, format, res) {
const note = await branch.getNote(); const note = await branch.getNote();
@ -42,11 +42,9 @@ async function exportSingleNote(branch, format, res) {
mime = 'application/json'; mime = 'application/json';
} }
const name = sanitize(note.title); const filename = note.title + "." + extension;
console.log(name, extension, mime); res.setHeader('Content-Disposition', utils.getContentDisposition(filename));
res.setHeader('Content-Disposition', `file; filename="${name}.${extension}"`);
res.setHeader('Content-Type', mime + '; charset=UTF-8'); res.setHeader('Content-Type', mime + '; charset=UTF-8');
res.send(payload); res.send(payload);

View File

@ -4,10 +4,10 @@ const html = require('html');
const repository = require('../repository'); const repository = require('../repository');
const tar = require('tar-stream'); const tar = require('tar-stream');
const path = require('path'); const path = require('path');
const sanitize = require("sanitize-filename");
const mimeTypes = require('mime-types'); const mimeTypes = require('mime-types');
const TurndownService = require('turndown'); const TurndownService = require('turndown');
const packageInfo = require('../../../package.json'); const packageInfo = require('../../../package.json');
const utils = require('../utils');
/** /**
* @param format - 'html' or 'markdown' * @param format - 'html' or 'markdown'
@ -219,9 +219,9 @@ async function exportToTar(branch, format, res) {
pack.finalize(); pack.finalize();
const note = await branch.getNote(); const note = await branch.getNote();
const tarFileName = sanitize((branch.prefix ? (branch.prefix + " - ") : "") + note.title); const tarFileName = (branch.prefix ? (branch.prefix + " - ") : "") + note.title + ".tar";
res.setHeader('Content-Disposition', `file; filename="${tarFileName}.tar"`); res.setHeader('Content-Disposition', utils.getContentDisposition(tarFileName));
res.setHeader('Content-Type', 'application/tar'); res.setHeader('Content-Type', 'application/tar');
pack.pipe(res); pack.pipe(res);

View File

@ -4,6 +4,7 @@ const crypto = require('crypto');
const randtoken = require('rand-token').generator({source: 'crypto'}); const randtoken = require('rand-token').generator({source: 'crypto'});
const unescape = require('unescape'); const unescape = require('unescape');
const escape = require('escape-html'); const escape = require('escape-html');
const sanitize = require("sanitize-filename");
function newEntityId() { function newEntityId() {
return randomString(12); return randomString(12);
@ -127,6 +128,22 @@ function crash() {
} }
} }
function sanitizeFilenameForHeader(filename) {
let sanitizedFilename = sanitize(filename);
if (sanitizedFilename.trim().length === 0) {
sanitizedFilename = "file";
}
return encodeURIComponent(sanitizedFilename)
}
function getContentDisposition(filename) {
const sanitizedFilename = sanitizeFilenameForHeader(filename);
return `file; filename="${sanitizedFilename}"; filename*=UTF-8''${sanitizedFilename}`;
}
module.exports = { module.exports = {
randomSecureToken, randomSecureToken,
randomString, randomString,
@ -147,5 +164,7 @@ module.exports = {
intersection, intersection,
union, union,
escapeRegExp, escapeRegExp,
crash crash,
sanitizeFilenameForHeader,
getContentDisposition
}; };