1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-11-26 22:41:17 +02:00

Desktop, Cli: Correctly import Evernote resources that do not have the encoding specified

This commit is contained in:
Laurent Cozic
2025-10-18 09:44:17 +01:00
parent 08371ef718
commit 3097c3e589
4 changed files with 35 additions and 4 deletions

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export4.dtd">
<en-export export-date="20230724T173816Z" application="Evernote" version="10.58.8">
<note>
<title>test.json</title>
<content><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note><en-media hash="ac91cc691d21261b222681dd38c1e4ad" type="application/json"/></en-note>
]]>
</content>
<created>20191002T075850Z</created>
<updated>20191002T075850Z</updated>
<note-attributes><latitude>48.79547119140625</latitude><longitude>9.809423921920198</longitude><altitude>398.0</altitude><author>Laurent</author><source>desktop.mac</source></note-attributes>
<resource><data>eyAidGVzdCI6IDEyMyB9</data><mime>application/json</mime><width>0</width><height>0</height><resource-attributes><file-name>test.json</file-name><attachment>false</attachment></resource-attributes></resource></note></en-export>

View File

@@ -202,6 +202,18 @@ describe('import-enex-md-gen', () => {
expect(Resource.fullPath(resource).endsWith('.mscz')).toBe(true); expect(Resource.fullPath(resource).endsWith('.mscz')).toBe(true);
}); });
it('should handle resources without encoding', async () => {
// Handle case where the resource has a certain extension, eg. "mscz"
// and a mime type that doesn't really match (application/zip). In that
// case we want to make sure that the file is not converted to a .zip
// file. Fixes https://discourse.joplinapp.org/t/import-issue-evernote-enex-containing-musescore-file-mscz/31394/1
await importEnexFile('resource_with_missing_encoding.enex');
const resource = (await Resource.all())[0];
const resourcePath = Resource.fullPath(resource);
const content = await readFile(resourcePath, 'utf-8');
expect(content).toBe('{ "test": 123 }');
});
it('should sanitize resource filenames with slashes', async () => { it('should sanitize resource filenames with slashes', async () => {
await importEnexFile('resource_filename_with_slashes.enex'); await importEnexFile('resource_filename_with_slashes.enex');
const resource: ResourceEntity = (await Resource.all())[0]; const resource: ResourceEntity = (await Resource.all())[0];

View File

@@ -150,12 +150,16 @@ async function processNoteResource(resource: ExtractedResource) {
// Some resources have no data, go figure, so we need a special case for this. // Some resources have no data, go figure, so we need a special case for this.
await handleNoDataResource(resource, true); await handleNoDataResource(resource, true);
} else { } else {
if (resource.dataEncoding === 'base64') { // If encoding is not specified, it defaults to base64.
// Source: enex.dtd: <!ATTLIST data encoding (base64) "base64">
const dataEncoding = resource.dataEncoding ? resource.dataEncoding : 'base64';
if (dataEncoding === 'base64') {
const decodedFilePath = `${resource.dataFilePath}.decoded`; const decodedFilePath = `${resource.dataFilePath}.decoded`;
await decodeBase64File(resource.dataFilePath, decodedFilePath); await decodeBase64File(resource.dataFilePath, decodedFilePath);
resource.dataFilePath = decodedFilePath; resource.dataFilePath = decodedFilePath;
} else if (resource.dataEncoding) { } else if (dataEncoding) {
throw new Error(`Cannot decode resource with encoding: ${resource.dataEncoding}`); throw new Error(`Cannot decode resource with encoding: ${dataEncoding}`);
} }
const stats = await shim.fsDriver().stat(resource.dataFilePath); const stats = await shim.fsDriver().stat(resource.dataFilePath);

View File

@@ -209,4 +209,5 @@ SPSSO
IDPSSO IDPSSO
nameid nameid
attrname attrname
dpkg dpkg
ATTLIST