// List and extract embedded files in a PDF document.

if (scriptArgs.length != 1 && scriptArgs.length != 3) {
	print("usage: mutool run pdf-portfolio.js input.pdf [index filename]");
	print("    List embedded files, or extract an embedded file from a PDF document.")
	quit();
}

var doc = Document.openDocument(scriptArgs[0]);
var Root = doc.getTrailer().Root;
if (Root.Names == undefined || !("EmbeddedFiles" in Root.Names)) {
	print("Document has no embedded files!");
	quit();
}

function mapNameTree(N, fn) {
	function mapNameTreeNames(NN) {
		var i, n = NN.length;
		for (i = 0; i < n; i += 2)
			fn(NN[i], NN[i+1]);
	}
	function mapNameTreeKids(NK) {
		var i, n = NK.length;
		for (i = 0; i < n; ++i)
			mapNameTree(NK[i], fn)
	}
	if ("Names" in N)
		mapNameTreeNames(N.Names);
	if ("Kids" in N)
		mapNameTreeKids(N.Kids);
}

function fileNameFromFS(fs) {
	if ("UF" in fs) return fs.UF.asString();
	if ("F" in fs) return fs.F.asString();
	if ("Unix" in fs) return fs.Unix.asString();
	if ("DOS" in fs) return fs.DOS.asString();
	if ("Mac" in fs) return fs.Mac.asString();
	return "Untitled";
}

if (scriptArgs.length == 1) {
	var idx = 1;
	mapNameTree(Root.Names.EmbeddedFiles, function (name,fs) {
		print(idx, name.asString());
		print("\tFilename:", fileNameFromFS(fs));
		if ("Desc" in fs)
			print("\tDescription:", fs.Desc.asString());
		++idx;
	});
}

if (scriptArgs.length == 3) {
	var idx = 1;
	mapNameTree(Root.Names.EmbeddedFiles, function (name,fs) {
		if (idx == scriptArgs[1]) {
			print("Saving embedded file", idx, "as:", scriptArgs[2]);
			fs.EF.F.readStream().save(scriptArgs[2]);
		}
		++idx;
	});
}
