mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-11-13 12:23:34 +01:00
Update comic book extractor file path sanitization
Co-authored-by: Finn Dittmar <finn@dittmar-ldk.de>
This commit is contained in:
1 parent
fb43db4f75
commit
e4e212cca7
1 file changed
+32
-5
@@ -6,6 +6,21 @@ const fs = require('../libs/fsExtra')
|
||||
const StreamZip = require('../libs/nodeStreamZip')
|
||||
const Archive = require('../libs/libarchive/archive')
|
||||
const { isWritable } = require('./fileUtils')
|
||||
const { sanitizePath } = require('../libs/archiver/archiverUtils')
|
||||
|
||||
/**
|
||||
* Sanitize a path from an archive
|
||||
*
|
||||
* @param {string} filename
|
||||
* @returns {string}
|
||||
*/
|
||||
function sanitizeArchivePath(filename) {
|
||||
const sanitizedPath = Path.normalize(sanitizePath(filename))
|
||||
if (!sanitizedPath || sanitizedPath === '.' || sanitizedPath === '..' || sanitizedPath.startsWith(`..${Path.sep}`) || Path.isAbsolute(sanitizedPath)) {
|
||||
throw new Error(`[CbrComicBookExtractor] Unsafe archive path "${filename}"`)
|
||||
}
|
||||
return sanitizedPath
|
||||
}
|
||||
|
||||
class AbstractComicBookExtractor {
|
||||
constructor(comicPath) {
|
||||
@@ -57,7 +72,11 @@ class CbrComicBookExtractor extends AbstractComicBookExtractor {
|
||||
this.tmpDir = global.MetadataPath ? Path.join(global.MetadataPath, 'tmp') : os.tmpdir()
|
||||
await fs.ensureDir(this.tmpDir)
|
||||
if (!(await isWritable(this.tmpDir))) throw new Error(`[CbrComicBookExtractor] Temp directory "${this.tmpDir}" is not writable`)
|
||||
this.archive = await unrar.createExtractorFromFile({ filepath: this.comicPath, targetPath: this.tmpDir })
|
||||
this.archive = await unrar.createExtractorFromFile({
|
||||
filepath: this.comicPath,
|
||||
targetPath: this.tmpDir,
|
||||
filenameTransform: sanitizeArchivePath
|
||||
})
|
||||
Logger.debug(`[CbrComicBookExtractor] Opened comic book "${this.comicPath}". Using temp directory "${this.tmpDir}" for extraction.`)
|
||||
}
|
||||
|
||||
@@ -81,14 +100,22 @@ class CbrComicBookExtractor extends AbstractComicBookExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
getExtractedFilePath(file) {
|
||||
const sanitizedFile = sanitizeArchivePath(file)
|
||||
return {
|
||||
filePath: Path.join(this.tmpDir, sanitizedFile),
|
||||
relativePath: sanitizedFile
|
||||
}
|
||||
}
|
||||
|
||||
async extractToBuffer(file) {
|
||||
if (!this.archive) return null
|
||||
const extracted = this.archive.extract({ files: [file] })
|
||||
const files = [...extracted.files]
|
||||
const filePath = Path.join(this.tmpDir, files[0].fileHeader.name)
|
||||
const { filePath, relativePath } = this.getExtractedFilePath(files[0].fileHeader.name)
|
||||
const fileData = await fs.readFile(filePath)
|
||||
await fs.remove(filePath)
|
||||
await this.removeEmptyParentDirs(files[0].fileHeader.name)
|
||||
await this.removeEmptyParentDirs(relativePath)
|
||||
Logger.debug(`[CbrComicBookExtractor] Extracted file "${file}" from comic book "${this.comicPath}" to buffer, size: ${fileData.length}`)
|
||||
return fileData
|
||||
}
|
||||
@@ -97,9 +124,9 @@ class CbrComicBookExtractor extends AbstractComicBookExtractor {
|
||||
if (!this.archive) return false
|
||||
const extracted = this.archive.extract({ files: [file] })
|
||||
const files = [...extracted.files]
|
||||
const extractedFilePath = Path.join(this.tmpDir, files[0].fileHeader.name)
|
||||
const { filePath: extractedFilePath, relativePath } = this.getExtractedFilePath(files[0].fileHeader.name)
|
||||
await fs.move(extractedFilePath, outputFilePath, { overwrite: true })
|
||||
await this.removeEmptyParentDirs(files[0].fileHeader.name)
|
||||
await this.removeEmptyParentDirs(relativePath)
|
||||
Logger.debug(`[CbrComicBookExtractor] Extracted file "${file}" from comic book "${this.comicPath}" to "${outputFilePath}"`)
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user