7z: encrypted headers are known from the encoded header, without bsdtar
85% of the 7z archives inspected have encrypted headers (-mhe). Their encoded header lists the 7zAES coder, so the packed header stream is no longer downloaded and bsdtar no longer runs for them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ae15ed26f
commit
4d3cb6474c
3 files changed
+97
-2
No files matched your search
@@ -11,6 +11,7 @@ import { decodeSegment, type DecodedSegment } from '#lib/yenc/index'
|
||||
import type { RarInfo } from '#lib/rar/index'
|
||||
import {
|
||||
checkHeader,
|
||||
encodedHeaderEncrypted,
|
||||
listingStart,
|
||||
parseBsdtarListing,
|
||||
parseSevenZipStart,
|
||||
@@ -70,6 +71,8 @@ class SevenZipService {
|
||||
|
||||
const tail = await this.readTail(volumes[volumes.length - 1], start)
|
||||
if (!tail) return null
|
||||
// Encrypted headers (-mhe): known from the header alone, no listing possible (most 7z uploads).
|
||||
if ('headersEncrypted' in tail) return this.info([], true, true, volumes.length > 1)
|
||||
|
||||
const dir = await mkdtemp(path.join(tmpdir(), '7z-'))
|
||||
try {
|
||||
@@ -140,7 +143,7 @@ class SevenZipService {
|
||||
* CRC) and, for an encoded header, the packed stream before it. `from` is
|
||||
* its position in the whole archive.
|
||||
*/
|
||||
private async readTail(last: any, start: SevenZipStart): Promise<{ from: number; data: Buffer } | null> {
|
||||
private async readTail(last: any, start: SevenZipStart): Promise<{ from: number; data: Buffer } | { headersEncrypted: true } | null> {
|
||||
const ids = new Map(segmentsOf(last).map((s) => [s.number, s]))
|
||||
const numbers = [...ids.keys()]
|
||||
if (numbers.length === 0) return null
|
||||
@@ -180,6 +183,7 @@ class SevenZipService {
|
||||
|
||||
const header = await read(start.headerStart, start.archiveSize)
|
||||
if (!header || !checkHeader(start, header)) return null
|
||||
if (encodedHeaderEncrypted(header)) return { headersEncrypted: true }
|
||||
const from = Math.min(listingStart(start, header), start.headerStart)
|
||||
if (start.archiveSize - from > MAX_TAIL_BYTES) return null
|
||||
const data = await read(from, start.archiveSize)
|
||||
|
||||
Reference in new issue
Block a user