ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git), ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
78 lines
3.2 KiB
Bash
Executable File
78 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ElyPDF: a locked file keeps sealed points past engine ends.
|
|
set -euo pipefail
|
|
|
|
root=$(cd "$(dirname "$0")/../.." && pwd)
|
|
[ "$(uname)" = Darwin ] || { echo "SKIP: macOS only"; exit 0; }
|
|
work=$(mktemp -d)
|
|
cleanup() {
|
|
local status=$?
|
|
if [ -n "${pid:-}" ]; then
|
|
pkill -9 -P "$pid" 2>/dev/null || true
|
|
kill "$pid" 2>/dev/null || true
|
|
wait "$pid" 2>/dev/null || true
|
|
fi
|
|
[ "$status" = 0 ] && rm -rf "$work" || echo "kept $work" >&2
|
|
exit "$status"
|
|
}
|
|
trap cleanup EXIT
|
|
fail() {
|
|
echo "FAIL: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
cargo build -q -p ely-pdf-engine --bins -p ely-pdf --manifest-path "$root/Cargo.toml"
|
|
for tool in ax-values ax-press; do swiftc -O -o "$work/$tool" "$root/tests/scripts/$tool.swift"; done
|
|
[ "$("$work/ax-values" $$ | head -n 1)" != untrusted ] || { echo "SKIP: needs Accessibility permission"; exit 0; }
|
|
home="$work/home"
|
|
data="$home/Library/Application Support/ElyOffice/ely-pdf"
|
|
mkdir -p "$home"
|
|
cp "$root/tests/fixtures/pdf/aes128.pdf" "$work/locked.pdf"
|
|
keys() { osascript -e 'tell application "System Events"' -e "$1" -e 'end tell' >/dev/null; }
|
|
seen() {
|
|
for _ in $(seq 80); do "$work/ax-values" "$pid" | grep -q -- "$1" && return 0; sleep 0.25; done
|
|
return 1
|
|
}
|
|
opened() { { grep -c "ely-pdf: opened" "$data/ely.log" 2>/dev/null || true; } | head -n 1; }
|
|
start() {
|
|
ELY_SMOKE=hold ELY_LOCALE=en ELY_NO_DIALOG=1 HOME="$home" perl -e 'alarm 300; exec @ARGV' \
|
|
"$root/target/debug/ely-pdf" "$@" >"$work/out" 2>&1 &
|
|
pid=$!
|
|
for _ in $(seq 40); do "$work/ax-values" "$pid" | grep -q AXWindow && break; sleep 0.25; done
|
|
osascript -e "tell application \"System Events\" to set frontmost of (first process whose unix id is $pid) to true" >/dev/null
|
|
sleep 1
|
|
}
|
|
# The open-password dialog, answered; then the tab is there.
|
|
unlock() {
|
|
local before
|
|
before=$(opened)
|
|
seen "is locked" || fail "no password asked ($1)"
|
|
keys 'keystroke "owner"'
|
|
keys 'key code 36'
|
|
for _ in $(seq 80); do [ "$(opened)" -gt "${before:-0}" ] && break; sleep 0.25; done
|
|
[ "$(opened)" -gt "${before:-0}" ] || fail "the locked file did not open ($1)"
|
|
}
|
|
# A new sealed point, and never a plain one.
|
|
sealed() {
|
|
touch "$work/mark"
|
|
for _ in $(seq 100); do
|
|
find "$data/recovery" -name '*.enc' -newer "$work/mark" 2>/dev/null | grep -q . && break
|
|
sleep 0.25
|
|
done
|
|
find "$data/recovery" -name '*.enc' -newer "$work/mark" | grep -q . || fail "no sealed point ($1)"
|
|
[ -z "$(find "$data/recovery" -name '*.bin')" ] || fail "a plain point of a locked file ($1)"
|
|
}
|
|
start "$work/locked.pdf"
|
|
unlock "the file"
|
|
osascript -e "tell application \"System Events\" to tell (first process whose unix id is $pid) to click menu item \"Rotate Pages Right\" of menu \"Pages\" of menu bar 1" >/dev/null
|
|
sealed "while editing"
|
|
# The idle engine ends: told; the copy asks again.
|
|
pkill -9 -P "$pid" -f ely-pdf-worker || fail "no worker to stop"
|
|
seen "The document engine stopped" || fail "an idle engine's end is not told"
|
|
"$work/ax-press" "$pid" "Reopen documents" >/dev/null
|
|
unlock "the copy after the engine ended"
|
|
[ -n "$(find "$data/recovery" -name '*.enc')" ] || fail "the old points went before a new one"
|
|
grep -q "the engine is back, 0 tab(s) lost" "$data/ely.log" || fail "a tab is lost"
|
|
sealed "for the reopened copy"
|
|
echo "ok: pdf recovery"
|