From 621eb4cf95ea57bd180e4b0a6b54ce7c6f38c20a Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 29 May 2021 03:43:30 +0200 Subject: [PATCH] add multitag example --- README.md | 1 + bin/mtag/exe.py | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 bin/mtag/exe.py diff --git a/README.md b/README.md index f2f34c4a..35f244c2 100644 --- a/README.md +++ b/README.md @@ -327,6 +327,7 @@ copyparty can invoke external programs to collect additional metadata for files *but wait, there's more!* `-mtp` can be used for non-audio files as well using the `a` flag: `ay` only do audio files, `an` only do non-audio files, or `ad` do all files (d as in dontcare) * `-mtp ext=an,~/bin/file-ext.py` runs `~/bin/file-ext.py` to get the `ext` tag only if file is not audio (`an`) +* `-mtp arch,built,ver,orig=an,~/bin/mtag/exe.py` runs `~/bin/mtag/exe.py` to get properties about windows-binaries only if file is not audio (`an`) ## complete examples diff --git a/bin/mtag/exe.py b/bin/mtag/exe.py new file mode 100644 index 00000000..bd5d1ef9 --- /dev/null +++ b/bin/mtag/exe.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +import sys +import time +import json +import pefile + +""" +retrieve exe info, +example for multivalue providers +""" + + +def unk(v): + return "unk({:04x})".format(v) + + +class PE2(pefile.PE): + def __init__(self, *a, **ka): + for k in [ + # -- parse_data_directories: + "parse_import_directory", + "parse_export_directory", + # "parse_resources_directory", + "parse_debug_directory", + "parse_relocations_directory", + "parse_directory_tls", + "parse_directory_load_config", + "parse_delay_import_directory", + "parse_directory_bound_imports", + # -- full_load: + "parse_rich_header", + ]: + setattr(self, k, self.noop) + + super(PE2, self).__init__(*a, **ka) + + def noop(*a, **ka): + pass + + +try: + pe = PE2(sys.argv[1], fast_load=False) +except: + sys.exit(0) + +arch = pe.FILE_HEADER.Machine +if arch == 0x14C: + arch = "x86" +elif arch == 0x8664: + arch = "x64" +else: + arch = unk(arch) + +try: + buildtime = time.gmtime(pe.FILE_HEADER.TimeDateStamp) + buildtime = time.strftime("%Y-%m-%d_%H:%M:%S", buildtime) +except: + buildtime = "invalid" + +ui = pe.OPTIONAL_HEADER.Subsystem +if ui == 2: + ui = "GUI" +elif ui == 3: + ui = "cmdline" +else: + ui = unk(ui) + +extra = {} +if hasattr(pe, "FileInfo"): + for v1 in pe.FileInfo: + for v2 in v1: + if v2.name != "StringFileInfo": + continue + + for v3 in v2.StringTable: + for k, v in v3.entries.items(): + v = v.decode("utf-8", "replace").strip() + if not v: + continue + + if k in [b"FileVersion", b"ProductVersion"]: + extra["ver"] = v + + if k in [b"OriginalFilename", b"InternalName"]: + extra["orig"] = v + +r = { + "arch": arch, + "built": buildtime, + "ui": ui, + "cksum": "{:08x}".format(pe.OPTIONAL_HEADER.CheckSum), +} +r.update(extra) + +print(json.dumps(r, indent=4))