Плагины Preflight и XML MRR

pfXML сериализует встроенные проверки, предупреждения, подсказки, стабильные ID правил, ссылки на спецификации и расположения — объект, страница или байт — в версионированный словарь urn:hotpdf:preflight:mrr:1

CreatePreflightMRR добавляет доверенные in-process плагины для извлечения фич и собственных правил валидации, а ValidatePDFWithPluginBundle объединяет эти правила с существующей THPDFValidationPolicy

Регистрация плагина с лимитами

function EvaluateVendorRules(
  const Context: THPDFPreflightPluginContext;
  out PluginResult: THPDFPreflightPluginResult;
  out ErrorMessage: AnsiString): Boolean;
begin
  SetLength(PluginResult.Findings, 1);
  PluginResult.Findings[0] := THPDFPreflightPluginFinding.Create(
    'vendor.metadata.required', 'Vendor metadata is present', True, ppsError);
  PluginResult.Findings[0].Scope := 'metadata';
  PluginResult.Findings[0].Path := '/Vendor';
  ErrorMessage := '';
  Result := True;
end;

Limits := THPDFPreflightPluginLimits.Default;
SetLength(Plugins, 1);
Plugins[0] := THPDFPreflightPluginDescriptor.Create(
  'vendor-policy', '1.0', [ppcValidationRules], EvaluateVendorRules);
XML := PDF.CreatePreflightMRR('Input.pdf', '', Plugins, Limits);

Детерминизм и граница доверия

HotPDF проверяет уникальные ASCII-ID плагинов и ABI версии 1, выполняет плагины в стабильном порядке ID, сортирует возвращённые фичи и findings, исключает дрожание таймингов из отчёта, экранирует XML-значения и отклоняет незаявленные capabilities или неверные ID правил

Лимиты ограничивают число плагинов, фич, findings, суммарные байты строк, байты XML-вывода, время каждого плагина и общее время; отклонённый плагин даёт детерминированный execution finding и не расходует общие бюджеты фич, findings или строк

Плагины выполняются внутри процесса вызывающей стороны и получают путь к источнику, пароль, базовый текстовый отчёт, имя политики, лимиты и cancellation token — регистрировать стоит только доверенный код плагинов

Временные лимиты проверяются после возврата evaluator'а, потому что in-process callback нельзя безопасно прервать; долго работающие evaluator'ы должны опрашивать Context.CancellationToken и быстро возвращаться

См. THotPDF.CreatePreflightMRR, THotPDF.ValidatePDFWithPluginBundle, THPDFPreflightPluginDescriptor и THPDFPreflightPluginLimits