Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions packages/lib/services/interop/InteropService_Importer_OneNote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export default class InteropService_Importer_OneNote extends InteropService_Impo
// other files.
fileNamePattern: '*.one',
});

await this.fixIncorrectLatin1Decoding_(extractPath);
} else {
throw new Error(`Unknown file extension: ${fileExtension}`);
}
Expand Down Expand Up @@ -295,4 +297,47 @@ export default class InteropService_Importer_OneNote extends InteropService_Impo
changed: true,
};
}

// Works around a decoding issue in which file names are extracted as latin1 strings,
// rather than UTF-8 strings. For example, OneNote seems to encode filenames as UTF-8 in .onepkg files.
// However, EXPAND.EXE reads the filenames as latin1. As a result, "é.one" becomes
// "é.one" when extracted from the archive.
// This workaround re-encodes filenames as UTF-8.
private async fixIncorrectLatin1Decoding_(parentDir: string) {
// Only seems to be necessary on Windows.
if (!shim.isWindows()) return;

const fixEncoding = async (basePath: string, fileName: string) => {
const originalPath = join(basePath, fileName);
let newPath;

let fixedFileName = Buffer.from(fileName, 'latin1').toString('utf8');
if (fixedFileName !== fileName) {
// In general, the path shouldn't start with "."s or contain path separators.
// However, if it does, these characters might cause import errors, so remove them:
fixedFileName = fixedFileName.replace(/^\.+/, '');
fixedFileName = fixedFileName.replace(/[/\\]/g, ' ');

// Avoid path traversal: Ensure that the file path is contained within the base directory
const newFullPathSafe = shim.fsDriver().resolveRelativePathWithinDir(basePath, fixedFileName);
await shim.fsDriver().move(originalPath, newFullPathSafe);

newPath = newFullPathSafe;
} else {
newPath = originalPath;
}

if (await shim.fsDriver().isDirectory(originalPath)) {
const children = await shim.fsDriver().readDirStats(newPath, { recursive: false });
for (const child of children) {
await fixEncoding(originalPath, child.path);
}
}
};

const stats = await shim.fsDriver().readDirStats(parentDir, { recursive: false });
for (const stat of stats) {
await fixEncoding(parentDir, stat.path);
}
}
}