Skip to content

Instantly share code, notes, and snippets.

@akx
Created October 13, 2020 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akx/92d6610bf9a54eaedcab5505ad3cc61e to your computer and use it in GitHub Desktop.
Save akx/92d6610bf9a54eaedcab5505ad3cc61e to your computer and use it in GitHub Desktop.
mupdf extract portfolio
// List and extract embedded files in a PDF document.
// extended from the example script
function usage() {
print("usage: mutool run pdf-portfolio.js input.pdf ['all' | index filename]");
print(
" List embedded files, or extract an embedded file from a PDF document.",
);
quit();
}
if (scriptArgs.length < 1) {
usage();
}
var doc = new PDFDocument(scriptArgs[0]);
var Root = doc.getTrailer().Root;
if (!("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;
});
} else if (scriptArgs.length == 2 && scriptArgs[1] == "all") {
var idx = 1;
mapNameTree(Root.Names.EmbeddedFiles, function (name, fs) {
var filename = fileNameFromFS(fs);
print("Saving embedded file", idx, "as:", filename);
fs.EF.F.readStream().save(filename);
++idx;
});
} else 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;
});
} else {
usage();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment