mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Document requirements
This commit is contained in:
@ -973,4 +973,151 @@ std::optional<PDFLegalAttestation> PDFLegalAttestation::parse(const PDFObjectSto
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFDocumentRequirements::ValidationResult PDFDocumentRequirements::validate(Requirements supported) const
|
||||
{
|
||||
ValidationResult result;
|
||||
|
||||
QStringList unsatisfiedRequirements;
|
||||
for (const RequirementEntry& entry : m_requirements)
|
||||
{
|
||||
if (entry.requirement == None)
|
||||
{
|
||||
// Unrecognized entry, just add the penalty
|
||||
result.penalty += entry.penalty;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!supported.testFlag(entry.requirement))
|
||||
{
|
||||
result.penalty += entry.penalty;
|
||||
unsatisfiedRequirements << getRequirementName(entry.requirement);
|
||||
}
|
||||
}
|
||||
|
||||
if (!unsatisfiedRequirements.isEmpty())
|
||||
{
|
||||
result.message = PDFTranslationContext::tr("Required features %1 are unsupported. Document processing can be limited.").arg(unsatisfiedRequirements.join(", "));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString PDFDocumentRequirements::getRequirementName(Requirement requirement)
|
||||
{
|
||||
switch (requirement)
|
||||
{
|
||||
case OCInteract:
|
||||
return PDFTranslationContext::tr("Optional Content User Interaction");
|
||||
case OCAutoStates:
|
||||
return PDFTranslationContext::tr("Optional Content Usage");
|
||||
case AcroFormInteract:
|
||||
return PDFTranslationContext::tr("Acrobat Forms");
|
||||
case Navigation:
|
||||
return PDFTranslationContext::tr("Navigation");
|
||||
case Markup:
|
||||
return PDFTranslationContext::tr("Markup Annotations");
|
||||
case _3DMarkup:
|
||||
return PDFTranslationContext::tr("Markup of 3D Content");
|
||||
case Multimedia:
|
||||
return PDFTranslationContext::tr("Multimedia");
|
||||
case U3D:
|
||||
return PDFTranslationContext::tr("U3D Format of PDF 3D");
|
||||
case PRC:
|
||||
return PDFTranslationContext::tr("PRC Format of PDF 3D");
|
||||
case Action:
|
||||
return PDFTranslationContext::tr("Actions");
|
||||
case EnableJavaScripts:
|
||||
return PDFTranslationContext::tr("JavaScript");
|
||||
case Attachment:
|
||||
return PDFTranslationContext::tr("Attached Files");
|
||||
case AttachmentEditing:
|
||||
return PDFTranslationContext::tr("Attached Files Modification");
|
||||
case Collection:
|
||||
return PDFTranslationContext::tr("Collections of Attached Files");
|
||||
case CollectionEditing:
|
||||
return PDFTranslationContext::tr("Collections of Attached Files (editation)");
|
||||
case DigSigValidation:
|
||||
return PDFTranslationContext::tr("Digital Signature Validation");
|
||||
case DigSig:
|
||||
return PDFTranslationContext::tr("Apply Digital Signature");
|
||||
case DigSigMDP:
|
||||
return PDFTranslationContext::tr("Digital Signature Validation (with MDP)");
|
||||
case RichMedia:
|
||||
return PDFTranslationContext::tr("Rich Media");
|
||||
case Geospatial2D:
|
||||
return PDFTranslationContext::tr("Geospatial 2D Features");
|
||||
case Geospatial3D:
|
||||
return PDFTranslationContext::tr("Geospatial 3D Features");
|
||||
case DPartInteract:
|
||||
return PDFTranslationContext::tr("Navigation for Document Parts");
|
||||
case SeparationSimulation:
|
||||
return PDFTranslationContext::tr("Separation Simulation");
|
||||
case Transitions:
|
||||
return PDFTranslationContext::tr("Transitions/Presentations");
|
||||
case Encryption:
|
||||
return PDFTranslationContext::tr("Encryption");
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
PDFDocumentRequirements PDFDocumentRequirements::parse(const PDFObjectStorage* storage, const PDFObject& object)
|
||||
{
|
||||
PDFDocumentRequirements requirements;
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
requirements.m_requirements = loader.readObjectList<RequirementEntry>(object);
|
||||
|
||||
return requirements;
|
||||
}
|
||||
|
||||
PDFDocumentRequirements::RequirementEntry PDFDocumentRequirements::RequirementEntry::parse(const PDFObjectStorage* storage, const PDFObject& object)
|
||||
{
|
||||
RequirementEntry entry;
|
||||
|
||||
if (const PDFDictionary* dictionary = storage->getDictionaryFromObject(object))
|
||||
{
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
|
||||
constexpr const std::array requirementTypes = {
|
||||
std::pair<const char*, Requirement>{ "OCInteract", OCInteract },
|
||||
std::pair<const char*, Requirement>{ "OCAutoStates", OCAutoStates },
|
||||
std::pair<const char*, Requirement>{ "AcroFormInteract", AcroFormInteract },
|
||||
std::pair<const char*, Requirement>{ "Navigation", Navigation },
|
||||
std::pair<const char*, Requirement>{ "Markup", Markup },
|
||||
std::pair<const char*, Requirement>{ "3DMarkup", _3DMarkup },
|
||||
std::pair<const char*, Requirement>{ "Multimedia", Multimedia },
|
||||
std::pair<const char*, Requirement>{ "U3D", U3D },
|
||||
std::pair<const char*, Requirement>{ "PRC", PRC },
|
||||
std::pair<const char*, Requirement>{ "Action", Action },
|
||||
std::pair<const char*, Requirement>{ "EnableJavaScripts", EnableJavaScripts },
|
||||
std::pair<const char*, Requirement>{ "Attachment", Attachment },
|
||||
std::pair<const char*, Requirement>{ "AttachmentEditing", AttachmentEditing },
|
||||
std::pair<const char*, Requirement>{ "Collection", Collection },
|
||||
std::pair<const char*, Requirement>{ "CollectionEditing", CollectionEditing },
|
||||
std::pair<const char*, Requirement>{ "DigSigValidation", DigSigValidation },
|
||||
std::pair<const char*, Requirement>{ "DigSig", DigSig },
|
||||
std::pair<const char*, Requirement>{ "DigSigMDP", DigSigMDP },
|
||||
std::pair<const char*, Requirement>{ "RichMedia", RichMedia },
|
||||
std::pair<const char*, Requirement>{ "Geospatial2D", Geospatial2D },
|
||||
std::pair<const char*, Requirement>{ "Geospatial3D", Geospatial3D },
|
||||
std::pair<const char*, Requirement>{ "DPartInteract", DPartInteract },
|
||||
std::pair<const char*, Requirement>{ "SeparationSimulation", SeparationSimulation },
|
||||
std::pair<const char*, Requirement>{ "Transitions", Transitions },
|
||||
std::pair<const char*, Requirement>{ "Encryption", Encryption }
|
||||
};
|
||||
|
||||
entry.requirement = loader.readEnumByName(dictionary->get("S"), requirementTypes.begin(), requirementTypes.end(), None);
|
||||
entry.handler = dictionary->get("RH");
|
||||
entry.version = loader.readNameFromDictionary(dictionary, "V");
|
||||
entry.penalty = loader.readIntegerFromDictionary(dictionary, "Penalty", 100);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -450,6 +450,82 @@ private:
|
||||
QString m_attestation;
|
||||
};
|
||||
|
||||
/// Document can contain requirements for viewer application. This class
|
||||
/// verifies, if this library and viewer application satisfies these requirements
|
||||
/// and returns result.
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFDocumentRequirements
|
||||
{
|
||||
public:
|
||||
|
||||
enum Requirement
|
||||
{
|
||||
None = 0x00000000,
|
||||
OCInteract = 0x00000001,
|
||||
OCAutoStates = 0x00000002,
|
||||
AcroFormInteract = 0x00000004,
|
||||
Navigation = 0x00000008,
|
||||
Markup = 0x00000010,
|
||||
_3DMarkup = 0x00000020,
|
||||
Multimedia = 0x00000040,
|
||||
U3D = 0x00000080,
|
||||
PRC = 0x00000100,
|
||||
Action = 0x00000200,
|
||||
EnableJavaScripts = 0x00000400,
|
||||
Attachment = 0x00000800,
|
||||
AttachmentEditing = 0x00001000,
|
||||
Collection = 0x00002000,
|
||||
CollectionEditing = 0x00004000,
|
||||
DigSigValidation = 0x00008000,
|
||||
DigSig = 0x00010000,
|
||||
DigSigMDP = 0x00020000,
|
||||
RichMedia = 0x00040000,
|
||||
Geospatial2D = 0x00080000,
|
||||
Geospatial3D = 0x00100000,
|
||||
DPartInteract = 0x00200000,
|
||||
SeparationSimulation = 0x00400000,
|
||||
Transitions = 0x00800000,
|
||||
Encryption = 0x01000000
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(Requirements, Requirement)
|
||||
|
||||
struct RequirementEntry
|
||||
{
|
||||
Requirement requirement = None;
|
||||
PDFInteger penalty = 100;
|
||||
QByteArray version;
|
||||
PDFObject handler;
|
||||
|
||||
static RequirementEntry parse(const PDFObjectStorage* storage, const PDFObject& object);
|
||||
};
|
||||
|
||||
struct ValidationResult
|
||||
{
|
||||
Requirements unsatisfied = None;
|
||||
PDFInteger penalty = 0;
|
||||
QString message;
|
||||
|
||||
bool isOk() const { return penalty < 100; }
|
||||
bool isError() const { return !isOk(); }
|
||||
bool isWarning() const { return isOk() && !message.isEmpty(); }
|
||||
};
|
||||
|
||||
/// Validates requirements against supported requirements
|
||||
ValidationResult validate(Requirements supported) const;
|
||||
|
||||
/// Returns string version of requirement
|
||||
static QString getRequirementName(Requirement requirement);
|
||||
|
||||
/// Parses document requirements. If error occurs, empty
|
||||
/// document requirements are returned.
|
||||
/// \param storage Storage
|
||||
/// \param object Object
|
||||
static PDFDocumentRequirements parse(const PDFObjectStorage* storage, const PDFObject& object);
|
||||
|
||||
private:
|
||||
std::vector<RequirementEntry> m_requirements;
|
||||
};
|
||||
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFCatalog
|
||||
{
|
||||
public:
|
||||
|
@ -1051,6 +1051,23 @@ void PDFViewerMainWindow::onDocumentReadingFinished()
|
||||
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
|
||||
setDocument(document);
|
||||
|
||||
pdf::PDFDocumentRequirements requirements = pdf::PDFDocumentRequirements::parse(&m_pdfDocument->getStorage(), m_pdfDocument->getCatalog()->getRequirements());
|
||||
constexpr pdf::PDFDocumentRequirements::Requirements requirementFlags = pdf::PDFDocumentRequirements::OCInteract |
|
||||
pdf::PDFDocumentRequirements::OCAutoStates |
|
||||
pdf::PDFDocumentRequirements::Navigation |
|
||||
pdf::PDFDocumentRequirements::Attachment |
|
||||
pdf::PDFDocumentRequirements::DigSigValidation |
|
||||
pdf::PDFDocumentRequirements::Encryption;
|
||||
pdf::PDFDocumentRequirements::ValidationResult requirementResult = requirements.validate(requirementFlags);
|
||||
if (requirementResult.isError())
|
||||
{
|
||||
QMessageBox::critical(this, tr("PDF Viewer"), requirementResult.message);
|
||||
}
|
||||
else if (requirementResult.isWarning())
|
||||
{
|
||||
QMessageBox::warning(this, tr("PDF Viewer"), requirementResult.message);
|
||||
}
|
||||
|
||||
statusBar()->showMessage(tr("Document '%1' was successfully loaded!").arg(m_fileInfo.fileName), 4000);
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user