ZaStoGram/Tools/check_file_loader_invalid_location.py
loop-uh 08c1a9bbba Add ZaStoGram plugin engine with Chaquopy/Pine
Integrates the ZaStoGram Python plugin engine: embeds Chaquopy (CPython 3.11) and Pine (ART/Xposed-compatible hooking). Adds host-side Java implementation under TMessagesProj/src/main/java/org/telegram/plugins (PluginsController, PluginContext, PluginInfo, PluginUtils, PluginRequestInterceptor) to handle discovery, install/load/unload, settings bridge, request interception and hook lifecycle. Updates Gradle: apply Chaquopy plugin, add chaquopy gradle classpath, add Pine dependencies, configure Chaquopy (3.11, readable .py), and raise minSdkVersion to 24 across library and app modules to satisfy Chaquopy requirements.
2026-06-28 00:06:34 +03:00

149 lines
6 KiB
Python

#!/usr/bin/env python3
from pathlib import Path
import sys
ROOT = Path(__file__).resolve().parents[1]
FILE_LOADER = ROOT / "TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java"
FILE_LOAD_OPERATION = ROOT / "TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java"
ANIMATED_STREAM = ROOT / "TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java"
def read(path: Path) -> str:
return path.read_text(encoding="utf-8", errors="replace")
def require(condition: bool, message: str, failures: list[str]) -> None:
if not condition:
failures.append(message)
def extract_method(text: str, signature: str) -> str:
start = text.find(signature)
if start < 0:
return ""
brace = text.find("{", start)
if brace < 0:
return ""
depth = 0
for index in range(brace, len(text)):
char = text[index]
if char == "{":
depth += 1
elif char == "}":
depth -= 1
if depth == 0:
return text[start:index + 1]
return ""
def main() -> int:
failures: list[str] = []
file_loader = read(FILE_LOADER)
file_load_operation = read(FILE_LOAD_OPERATION)
animated_stream = read(ANIMATED_STREAM)
load_file_internal = extract_method(file_loader, "private FileLoadOperation loadFileInternal(")
invalid_name = extract_method(file_loader, "private boolean isInvalidAttachFileName(")
fail_invalid = extract_method(file_loader, "private boolean failInvalidFileLoad(")
require(load_file_internal, "FileLoader.loadFileInternal() must exist", failures)
require(invalid_name, "FileLoader must centralize invalid attach-name checks", failures)
require(fail_invalid, "FileLoader must have a soft-fail path for invalid file locations", failures)
require(
"public static final int ERROR_INVALID_LOCATION" in file_loader,
"FileLoader must expose ERROR_INVALID_LOCATION for invalid document/location failures",
failures,
)
require(
'FileLog.e(new RuntimeException("cant get hash' not in file_loader
and 'throw new RuntimeException("cant get hash' not in file_loader,
"missing document hash must not create or throw RuntimeException",
failures,
)
require(
"TextUtils.isEmpty(fileName)" in invalid_name
and 'fileName.contains("" + Integer.MIN_VALUE)' in invalid_name
and 'fileName.startsWith("0_0")' in invalid_name,
"invalid attach-name check must reject empty, Integer.MIN_VALUE, and 0_0 document hashes",
failures,
)
require(
"failInvalidFileLoad(fileName, document, secureDocument, webDocument, location, imageLocation, parentObject, priority, cacheType)" in load_file_internal,
"loadFileInternal() must route invalid locations through the soft-fail helper",
failures,
)
if "failInvalidFileLoad(" in load_file_internal and "loadOperationPathsUI.put" in load_file_internal:
require(
load_file_internal.index("failInvalidFileLoad(") < load_file_internal.index("loadOperationPathsUI.put"),
"invalid locations must fail before UI load state is registered",
failures,
)
require(
'FileLog.e("file_loader_missing_hash document=" + safeDocInfo(document)' in fail_invalid
and 'requestClass=" + classifyProxyWarmupRequest(' in fail_invalid,
"missing document hash log must include safe document info and request class without an exception stack",
failures,
)
require(
"loadOperationPathsUI.remove(safeFileName);" in fail_invalid
and "delegate.fileDidFailedLoad(safeFileName, ERROR_INVALID_LOCATION);" in fail_invalid,
"invalid locations must clean load UI state and notify the FileLoader delegate",
failures,
)
require(
"messageObject.getDocument() != null" in fail_invalid,
"invalid download cleanup must not call DownloadController with a MessageObject that has no document",
failures,
)
require(
"private String safeDocInfo(" in file_loader
and "document.id" in file_loader
and "document.dc_id" in file_loader
and "document.access_hash" in file_loader
and "document.file_reference" in file_loader,
"safeDocInfo() must log document identifiers without dumping the whole TL object",
failures,
)
require(
'throw new RuntimeException("!!!")' not in file_load_operation,
"FileLoadOperation must not crash file queues with placeholder RuntimeException(\"!!!\")",
failures,
)
require(
'throw new RuntimeException("Out of limit"' not in file_load_operation,
"FileLoadOperation encrypted padding size guard must fail the operation instead of throwing",
failures,
)
require(
"file_load_preload_offset_out_of_range" in file_load_operation
and "return 0;" in extract_method(file_load_operation, "private long findNextPreloadDownloadOffset("),
"FileLoadOperation preload offset overflow must log and abandon preload instead of throwing",
failures,
)
require(
"file_load_padding_limit_out_of_range" in file_load_operation,
"FileLoadOperation encrypted padding size guard must emit structured diagnostics",
failures,
)
require(
'FileLog.e(new RuntimeException("infinity stream reading!!!"))' not in animated_stream,
"AnimatedFileDrawableStream canceled read loop must not create RuntimeException stack logs",
failures,
)
require(
"animated_file_stream_cancelled_read_loop" in animated_stream,
"AnimatedFileDrawableStream canceled read loop must log a structured non-exception warning",
failures,
)
if failures:
print("FileLoader invalid location guard failed:", file=sys.stderr)
for failure in failures:
print(f" - {failure}", file=sys.stderr)
return 1
print("FileLoader invalid location guard passed.")
return 0
if __name__ == "__main__":
raise SystemExit(main())