1"""Cold-open a notebook whose sections Snowbound protected in a fresh OneNote 2010, unlock each
2through OneNote's Protected Section dialog with its password, type into one through COM as an
3add-in may, and read every page back with the notebook OneNote leaves.
4
5Usage: native_protected.py NOTEBOOK_DIR PASSWORDS_JSON OUTPUT_DIR [EDITED_SECTION]
6"""
7import base64
8import json
9import sys
10from pathlib import Path
11
12sys.path.insert(0, str(Path(__file__).resolve().parent))
13import native_runner as runner
14
15windows = runner.windows
16ROOT = Path(__file__).resolve().parent.parent
17REMOTE = 'C:\\one-tests\\runs\\capture'
18
19
20def unlock_script(password):
21 return '''WinActivate("ahk_class Framework::CFrame")
22WinWaitActive("ahk_class Framework::CFrame", , 30)
23Sleep(2000)
24Send("{Enter}")
25if !WinWait("Protected Section", , 15)
26 throw Error("No Protected Section dialog")
27Sleep(500)
28SendText("%s")
29Send("{Enter}")
30Sleep(4000)
31FileAppend(WinGetTitle("A"), "*")
32''' % password.replace('"', '""')
33
34
35def interaction(passwords, edited):
36 def run(name, output):
37 result = windows.do_put(ROOT / 'tools/native/protected.ps1', 'C:\\one-tests\\protected.ps1', name)
38 if result.get('error'):
39 raise RuntimeError(result['error'])
40 script = 'powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\protected.ps1 -Root %s -Section "%s"'
41 for section, password in passwords.items():
42 if password is None:
43 continue
44 runner.command(name, script % (REMOTE, section), output)
45 result = windows.do_exec(unlock_script(password), target=name, timeout_ms=60000, shot_delay_ms=1000)
46 stem = Path(section).stem
47 (output / f'unlock-{stem}.json').write_text(json.dumps({k: v for k, v in result.items() if k != 'png_b64'}, indent=2))
48 if result.get('png_b64'):
49 (output / f'unlock-{stem}.png').write_bytes(base64.b64decode(result['png_b64']))
50 if result.get('error') or result.get('exit') != 0:
51 raise RuntimeError(f'Unlocking {section} failed; inspect unlock-{stem}.json.')
52 if edited:
53 runner.command(name, (script + ' -Edit') % (REMOTE, edited), output, 120000)
54 return run
55
56
57if __name__ == '__main__':
58 if len(sys.argv) not in (4, 5):
59 raise SystemExit(__doc__)
60 notebook, passwords, output = Path(sys.argv[1]), json.loads(Path(sys.argv[2]).read_text()), Path(sys.argv[3])
61 edited = sys.argv[4] if len(sys.argv) == 5 else None
62 runner.capture(notebook, output, collect_notebook=True, interaction=interaction(passwords, edited))
63 print('Captured native evidence in', output)