"use strict";
/* Socket Lib - Built with rolldown */
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_primordials_error = require('../primordials/error.js');
const require_paths_normalize = require('../paths/normalize.js');
const require_primordials_array = require('../primordials/array.js');
const require_primordials_map_set = require('../primordials/map-set.js');
const require_node_path = require('../node/path.js');
const require_primordials_promise = require('../primordials/promise.js');
const require_archives__internal = require('./_internal.js');
const require_fs_safe = require('../fs/safe.js');

//#region src/archives/zip.ts
/**
* @file Zip extraction with security limits and path traversal validation. Uses
*   adm-zip under the hood; pre-validates every entry before extraction so the
*   disk-write phase can't be tricked into escaping the target directory.
*/
/**
* Extract a zip archive to a directory.
*
* @example
*   ;```typescript
*   await extractZip('/tmp/archive.zip', '/tmp/output')
*   await extractZip('/tmp/archive.zip', '/tmp/output', { strip: 1 })
*   ```
*
* @param archivePath - Path to zip file.
* @param outputDir - Directory to extract to.
* @param options - Extraction options.
*/
async function extractZip(archivePath, outputDir, options = {}) {
	require_archives__internal.assertArchiveExists(archivePath);
	const { maxEntries = require_archives__internal.DEFAULT_MAX_ENTRIES, maxFileSize = require_archives__internal.DEFAULT_MAX_FILE_SIZE, maxTotalSize = require_archives__internal.DEFAULT_MAX_TOTAL_SIZE, strip = 0 } = options;
	const normalizedOutputDir = /* @__PURE__ */ require_paths_normalize.normalizePath(outputDir);
	await require_fs_safe.safeMkdir(normalizedOutputDir);
	const zip = new (/* @__PURE__ */ require_archives__internal.getAdmZip())(archivePath);
	const path = /* @__PURE__ */ require_node_path.getNodePath();
	const entries = zip.getEntries();
	/* c8 ignore start */
	if (entries.length > maxEntries) throw new require_primordials_error.ErrorCtor(`Archive has too many entries: ${entries.length} (limit: ${maxEntries})`);
	/* c8 ignore stop */
	let totalExtractedSize = 0;
	for (const entry of entries) {
		if (entry.isDirectory) continue;
		/* c8 ignore start */
		if (entry.entryName.includes("\0")) throw new require_primordials_error.ErrorCtor(`Invalid null byte in archive entry name: ${entry.entryName}`);
		/* c8 ignore stop */
		const uncompressedSize = entry.header.size;
		if (uncompressedSize > maxFileSize) throw new require_primordials_error.ErrorCtor(`File size exceeds limit: ${entry.entryName} (${uncompressedSize} bytes > ${maxFileSize} bytes)`);
		totalExtractedSize += uncompressedSize;
		if (totalExtractedSize > maxTotalSize) throw new require_primordials_error.ErrorCtor(`Total extracted size exceeds limit: ${totalExtractedSize} bytes > ${maxTotalSize} bytes`);
		const parts = entry.entryName.split("/");
		if (parts.length <= strip) continue;
		const strippedPath = require_primordials_array.ArrayPrototypeSlice(parts, strip).join("/");
		require_archives__internal.validatePathWithinBase(path.join(normalizedOutputDir, strippedPath), normalizedOutputDir, entry.entryName);
	}
	/* c8 ignore start */
	if (strip === 0) {
		for (const entry of entries) if (!entry.isDirectory) require_archives__internal.validatePathWithinBase(path.join(normalizedOutputDir, entry.entryName), normalizedOutputDir, entry.entryName);
		zip.extractAllTo(normalizedOutputDir, true);
	} else {
		const path = /* @__PURE__ */ require_node_path.getNodePath();
		const entries = zip.getEntries();
		const dirsToCreate = new require_primordials_map_set.SetCtor();
		for (const entry of entries) {
			if (entry.isDirectory) continue;
			const parts = entry.entryName.split("/");
			if (parts.length <= strip) continue;
			const strippedPath = require_primordials_array.ArrayPrototypeSlice(parts, strip).join("/");
			const targetPath = path.join(normalizedOutputDir, strippedPath);
			dirsToCreate.add(path.dirname(targetPath));
		}
		await require_primordials_promise.PromiseAll(require_primordials_array.ArrayFrom(dirsToCreate).map((dir) => require_fs_safe.safeMkdir(dir)));
		for (const entry of entries) {
			if (entry.isDirectory) continue;
			const parts = entry.entryName.split("/");
			if (parts.length <= strip) continue;
			const strippedPath = require_primordials_array.ArrayPrototypeSlice(parts, strip).join("/");
			const targetPath = path.join(normalizedOutputDir, strippedPath);
			zip.extractEntryTo(entry, path.dirname(targetPath), false, true);
		}
	}
	/* c8 ignore stop */
}

//#endregion
exports.extractZip = extractZip;