"""Extract control->column bindings from the SGV executable's embedded Delphi binary DFM forms (READ-ONLY). python scripts/extract_sgv_dfm_bindings.py [--needle COD_ORIGEM_MERCADORIA] [--out file.json] Reads the exe bytes (never modifies it), locates every 'TPF0' form stream that contains the needle, parses the Delphi binary DFM and reports, for every data-aware control, its DataField/DataSource, Caption/Text-like properties and the chain of parent containers (group boxes, tab sheets) — i.e. the on-screen label context. """ import argparse import json import re import struct import sys VA = dict(NULL=0, LIST=1, INT8=2, INT16=3, INT32=4, EXTENDED=5, STRING=6, IDENT=7, FALSE=8, TRUE=9, BINARY=10, SET=11, LSTRING=12, NIL=13, COLLECTION=14, SINGLE=15, CURRENCY=16, DATE=17, WSTRING=18, INT64=19, UTF8=20, DOUBLE=21) class R: def __init__(self, data, pos=0): self.d, self.p = data, pos def u8(self): v = self.d[self.p]; self.p += 1; return v def take(self, n): v = self.d[self.p:self.p + n] if len(v) < n: raise ValueError("eof") self.p += n; return v def sstr(self): return self.take(self.u8()).decode("latin-1") def value(self): t = self.u8() if t == VA["NULL"] or t == VA["NIL"]: return None if t == VA["LIST"]: out = [] while self.d[self.p] != 0: out.append(self.value()) self.p += 1; return out if t == VA["INT8"]: return struct.unpack("" if t in (VA["STRING"], VA["IDENT"]): return self.sstr() if t == VA["FALSE"]: return False if t == VA["TRUE"]: return True if t == VA["BINARY"]: n = struct.unpack("" if t == VA["SET"]: out = [] while True: s = self.sstr() if not s: break out.append(s) return out if t == VA["LSTRING"] or t == VA["UTF8"]: n = struct.unpack("" if t == VA["CURRENCY"] or t == VA["DATE"] or t == VA["DOUBLE"] or t == VA["INT64"]: self.take(8); return "<8b>" if t == VA["COLLECTION"]: out = [] while self.d[self.p] != 0: if self.d[self.p] in (2, 3, 4): # optional collection order value self.value() if self.d[self.p] == 1: # vaList marker that opens every collection item self.p += 1 item = {} while self.d[self.p] != 0: key = self.sstr() # evaluate the name BEFORE the value (Python evaluates the RHS first) item[key] = self.value() self.p += 1; out.append(item) self.p += 1; return out raise ValueError(f"unknown value type {t} at {self.p}") def component(self): first = self.u8() if first & 0xF0 == 0xF0: # ObjInherit / ObjFlags prefix if first & 2: # ffChildPos self.value() cls = self.sstr() else: self.p -= 1; cls = self.sstr() name = self.sstr() props = {} while self.d[self.p] != 0: pn = self.sstr(); props[pn] = self.value() self.p += 1 kids = [] while self.d[self.p] != 0: kids.append(self.component()) self.p += 1 return {"class": cls, "name": name, "props": props, "children": kids} def walk(node, chain, out): cap = node["props"].get("Caption") here = chain + ([f"{node['class']}:{node['name']}" + (f"[{cap}]" if isinstance(cap, str) and cap else "")] if node["class"] != "TQuery" else []) p = node["props"] if "DataField" in p or node["class"].startswith(("TLabel", "TRz", "TGroup", "TTab", "TRadio")): out.append({"class": node["class"], "name": node["name"], "DataField": p.get("DataField"), "DataSource": p.get("DataSource"), "Caption": cap, "Items": p.get("Items"), "Values": p.get("Values"), "FocusControl": p.get("FocusControl"), "Left": p.get("Left"), "Top": p.get("Top"), "path": [c for c in chain]}) for k in node["children"]: walk(k, here, out) def find_forms(data, needle): forms = [] for m in re.finditer(b"TPF0", data): start = m.start() try: r = R(data, start + 4) tree = r.component() except Exception: continue blob = data[start:r.p] if needle in blob: forms.append((start, r.p, tree)) return forms def main(argv=None): ap = argparse.ArgumentParser() ap.add_argument("exe"); ap.add_argument("--needle", default="COD_ORIGEM_MERCADORIA"); ap.add_argument("--out") a = ap.parse_args(argv) data = open(a.exe, "rb").read() forms = find_forms(data, a.needle.encode()) result = [] for start, end, tree in forms: controls = [] walk(tree, [], controls) result.append({"offset": start, "size": end - start, "form_class": tree["class"], "form_name": tree["name"], "controls": controls}) text = json.dumps(result, ensure_ascii=False, indent=1, default=str) if a.out: open(a.out, "w", encoding="utf-8").write(text) print(f"forms containing {a.needle!r}: {[(f['form_class'], f['size'], len(f['controls'])) for f in result]}") if __name__ == "__main__": main()