|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef FORM_H |
|
#define FORM_H |
|
|
|
#include "Annot.h" |
|
#include "CharTypes.h" |
|
#include "Object.h" |
|
#include "poppler_private_export.h" |
|
|
|
#include <ctime> |
|
|
|
#include <optional> |
|
#include <set> |
|
#include <vector> |
|
|
|
class GooString; |
|
class Array; |
|
class Dict; |
|
class Annot; |
|
class AnnotWidget; |
|
class Annots; |
|
class LinkAction; |
|
class GfxResources; |
|
class PDFDoc; |
|
class SignatureInfo; |
|
class X509CertificateInfo; |
|
namespace CryptoSign { |
|
class VerificationInterface; |
|
} |
|
|
|
enum FormFieldType |
|
{ |
|
formButton, |
|
formText, |
|
formChoice, |
|
formSignature, |
|
formUndef |
|
}; |
|
|
|
enum FormButtonType |
|
{ |
|
formButtonCheck, |
|
formButtonPush, |
|
formButtonRadio |
|
}; |
|
|
|
enum FormSignatureType |
|
{ |
|
adbe_pkcs7_sha1, |
|
adbe_pkcs7_detached, |
|
ETSI_CAdES_detached, |
|
unknown_signature_type, |
|
unsigned_signature_field |
|
}; |
|
|
|
enum FillValueType |
|
{ |
|
fillValue, |
|
fillDefaultValue |
|
}; |
|
|
|
class Form; |
|
class FormField; |
|
class FormFieldButton; |
|
class FormFieldText; |
|
class FormFieldSignature; |
|
class FormFieldChoice; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormWidget |
|
{ |
|
public: |
|
virtual ~FormWidget(); |
|
|
|
|
|
bool inRect(double x, double y) const; |
|
|
|
|
|
void getRect(double *x1, double *y1, double *x2, double *y2) const; |
|
|
|
unsigned getID() { return ID; } |
|
void setID(unsigned int i) { ID = i; } |
|
|
|
FormField *getField() { return field; } |
|
FormFieldType getType() { return type; } |
|
|
|
Object *getObj() { return &obj; } |
|
Ref getRef() { return ref; } |
|
|
|
void setChildNum(unsigned i) { childNum = i; } |
|
unsigned getChildNum() { return childNum; } |
|
|
|
const GooString *getPartialName() const; |
|
void setPartialName(const GooString &name); |
|
const GooString *getAlternateUiName() const; |
|
const GooString *getMappingName() const; |
|
GooString *getFullyQualifiedName(); |
|
|
|
bool isModified() const; |
|
|
|
bool isReadOnly() const; |
|
void setReadOnly(bool value); |
|
|
|
LinkAction *getActivationAction(); |
|
std::unique_ptr<LinkAction> getAdditionalAction(Annot::FormAdditionalActionsType type); |
|
bool setAdditionalAction(Annot::FormAdditionalActionsType t, const std::string &js); |
|
|
|
|
|
static int encodeID(unsigned pageNum, unsigned fieldNum); |
|
|
|
static void decodeID(unsigned id, unsigned *pageNum, unsigned *fieldNum); |
|
|
|
void createWidgetAnnotation(); |
|
AnnotWidget *getWidgetAnnotation() const { return widget; } |
|
void setWidgetAnnotation(AnnotWidget *_widget) { widget = _widget; } |
|
|
|
virtual void updateWidgetAppearance() = 0; |
|
|
|
void print(int indent = 0); |
|
|
|
protected: |
|
FormWidget(PDFDoc *docA, Object *aobj, unsigned num, Ref aref, FormField *fieldA); |
|
|
|
AnnotWidget *widget; |
|
FormField *field; |
|
FormFieldType type; |
|
Object obj; |
|
Ref ref; |
|
PDFDoc *doc; |
|
XRef *xref; |
|
|
|
|
|
unsigned childNum; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned ID; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormWidgetButton : public FormWidget |
|
{ |
|
public: |
|
FormWidgetButton(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
|
~FormWidgetButton() override; |
|
|
|
FormButtonType getButtonType() const; |
|
|
|
void setState(bool state); |
|
bool getState() const; |
|
|
|
const char *getOnStr() const; |
|
void setAppearanceState(const char *state); |
|
void updateWidgetAppearance() override; |
|
|
|
protected: |
|
FormFieldButton *parent() const; |
|
GooString *onStr; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormWidgetText : public FormWidget |
|
{ |
|
public: |
|
FormWidgetText(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
|
|
|
const GooString *getContent() const; |
|
|
|
|
|
void setContent(const GooString *new_content); |
|
|
|
void setAppearanceContent(const GooString *new_content); |
|
|
|
void updateWidgetAppearance() override; |
|
|
|
bool isMultiline() const; |
|
bool isPassword() const; |
|
bool isFileSelect() const; |
|
bool noSpellCheck() const; |
|
bool noScroll() const; |
|
bool isComb() const; |
|
bool isRichText() const; |
|
int getMaxLen() const; |
|
|
|
double getTextFontSize(); |
|
|
|
void setTextFontSize(int fontSize); |
|
|
|
protected: |
|
FormFieldText *parent() const; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormWidgetChoice : public FormWidget |
|
{ |
|
public: |
|
FormWidgetChoice(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
|
~FormWidgetChoice() override; |
|
|
|
int getNumChoices() const; |
|
|
|
const GooString *getChoice(int i) const; |
|
const GooString *getExportVal(int i) const; |
|
|
|
void select(int i); |
|
|
|
|
|
void toggle(int i); |
|
|
|
|
|
void deselectAll(); |
|
|
|
|
|
|
|
void setEditChoice(const GooString *new_content); |
|
|
|
const GooString *getEditChoice() const; |
|
|
|
void updateWidgetAppearance() override; |
|
bool isSelected(int i) const; |
|
|
|
bool isCombo() const; |
|
bool hasEdit() const; |
|
bool isMultiSelect() const; |
|
bool noSpellCheck() const; |
|
bool commitOnSelChange() const; |
|
bool isListBox() const; |
|
|
|
protected: |
|
bool _checkRange(int i) const; |
|
FormFieldChoice *parent() const; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormWidgetSignature : public FormWidget |
|
{ |
|
public: |
|
FormWidgetSignature(PDFDoc *docA, Object *dictObj, unsigned num, Ref ref, FormField *p); |
|
void updateWidgetAppearance() override; |
|
|
|
FormSignatureType signatureType() const; |
|
void setSignatureType(FormSignatureType fst); |
|
|
|
|
|
SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA); |
|
|
|
|
|
|
|
std::vector<Goffset> getSignedRangeBounds() const; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool signDocument(const std::string &filename, const std::string &certNickname, const std::string &password, const GooString *reason = nullptr, const GooString *location = nullptr, const std::optional<GooString> &ownerPassword = {}, |
|
const std::optional<GooString> &userPassword = {}); |
|
|
|
|
|
bool signDocumentWithAppearance(const std::string &filename, const std::string &certNickname, const std::string &password, const GooString *reason = nullptr, const GooString *location = nullptr, |
|
const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {}, const GooString &signatureText = {}, const GooString &signatureTextLeft = {}, double fontSize = {}, |
|
double leftFontSize = {}, std::unique_ptr<AnnotColor> &&fontColor = {}, double borderWidth = {}, std::unique_ptr<AnnotColor> &&borderColor = {}, std::unique_ptr<AnnotColor> &&backgroundColor = {}); |
|
|
|
|
|
|
|
|
|
std::optional<GooString> getCheckedSignature(Goffset *checkedFileSize); |
|
|
|
const GooString *getSignature() const; |
|
|
|
private: |
|
bool createSignature(Object &vObj, Ref vRef, const GooString &name, int placeholderLength, const GooString *reason = nullptr, const GooString *location = nullptr); |
|
bool getObjectStartEnd(const GooString &filename, int objNum, Goffset *objStart, Goffset *objEnd, const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword); |
|
bool updateOffsets(FILE *f, Goffset objStart, Goffset objEnd, Goffset *sigStart, Goffset *sigEnd, Goffset *fileSize); |
|
|
|
bool updateSignature(FILE *f, Goffset sigStart, Goffset sigEnd, const GooString &signature); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormField |
|
{ |
|
public: |
|
FormField(PDFDoc *docA, Object &&aobj, const Ref aref, FormField *parent, std::set<int> *usedParents, FormFieldType t = formUndef); |
|
|
|
virtual ~FormField(); |
|
|
|
|
|
FormFieldType getType() const { return type; } |
|
Object *getObj() { return &obj; } |
|
Ref getRef() { return ref; } |
|
|
|
void setReadOnly(bool value); |
|
bool isReadOnly() const { return readOnly; } |
|
void setStandAlone(bool value) { standAlone = value; } |
|
bool isStandAlone() const { return standAlone; } |
|
|
|
GooString *getDefaultAppearance() const { return defaultAppearance; } |
|
void setDefaultAppearance(const std::string &appearance); |
|
|
|
bool hasTextQuadding() const { return hasQuadding; } |
|
VariableTextQuadding getTextQuadding() const { return quadding; } |
|
|
|
const GooString *getPartialName() const { return partialName; } |
|
void setPartialName(const GooString &name); |
|
const GooString *getAlternateUiName() const { return alternateUiName; } |
|
const GooString *getMappingName() const { return mappingName; } |
|
GooString *getFullyQualifiedName(); |
|
|
|
FormWidget *findWidgetByRef(Ref aref); |
|
int getNumWidgets() const { return terminal ? numChildren : 0; } |
|
FormWidget *getWidget(int i) const { return terminal ? widgets[i] : nullptr; } |
|
int getNumChildren() const { return !terminal ? numChildren : 0; } |
|
FormField *getChildren(int i) const { return children[i]; } |
|
|
|
|
|
virtual void fillChildrenSiblingsID(); |
|
|
|
void createWidgetAnnotations(); |
|
|
|
void printTree(int indent = 0); |
|
virtual void print(int indent = 0); |
|
virtual void reset(const std::vector<std::string> &excludedFields); |
|
void resetChildren(const std::vector<std::string> &excludedFields); |
|
FormField *findFieldByRef(Ref aref); |
|
FormField *findFieldByFullyQualifiedName(const std::string &name); |
|
|
|
protected: |
|
void _createWidget(Object *obj, Ref aref); |
|
void createChildren(std::set<int> *usedParents); |
|
void updateChildrenAppearance(); |
|
bool isAmongExcludedFields(const std::vector<std::string> &excludedFields); |
|
|
|
FormFieldType type; |
|
Ref ref; |
|
bool terminal; |
|
Object obj; |
|
PDFDoc *doc; |
|
XRef *xref; |
|
FormField **children; |
|
FormField *parent; |
|
int numChildren; |
|
FormWidget **widgets; |
|
bool readOnly; |
|
|
|
GooString *partialName; |
|
GooString *alternateUiName; |
|
GooString *mappingName; |
|
GooString *fullyQualifiedName; |
|
|
|
|
|
GooString *defaultAppearance; |
|
bool hasQuadding; |
|
VariableTextQuadding quadding; |
|
|
|
|
|
bool standAlone; |
|
|
|
private: |
|
FormField() { } |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class FormFieldButton : public FormField |
|
{ |
|
public: |
|
FormFieldButton(PDFDoc *docA, Object &&dict, const Ref ref, FormField *parent, std::set<int> *usedParents); |
|
|
|
FormButtonType getButtonType() const { return btype; } |
|
|
|
bool noToggleToOff() const { return noAllOff; } |
|
|
|
|
|
bool setState(const char *state, bool ignoreToggleOff = false); |
|
bool getState(const char *state) const; |
|
|
|
const char *getAppearanceState() const { return appearanceState.isName() ? appearanceState.getName() : nullptr; } |
|
const char *getDefaultAppearanceState() const { return defaultAppearanceState.isName() ? defaultAppearanceState.getName() : nullptr; } |
|
|
|
void fillChildrenSiblingsID() override; |
|
|
|
void setNumSiblings(int num); |
|
void setSibling(int i, FormFieldButton *id) { siblings[i] = id; } |
|
|
|
|
|
FormFieldButton *getSibling(int i) const { return siblings[i]; } |
|
int getNumSiblings() const { return numSiblings; } |
|
|
|
void print(int indent) override; |
|
void reset(const std::vector<std::string> &excludedFields) override; |
|
|
|
~FormFieldButton() override; |
|
|
|
protected: |
|
void updateState(const char *state); |
|
|
|
FormFieldButton **siblings; |
|
|
|
int numSiblings; |
|
|
|
FormButtonType btype; |
|
int size; |
|
int active_child; |
|
bool noAllOff; |
|
Object appearanceState; |
|
Object defaultAppearanceState; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class FormFieldText : public FormField |
|
{ |
|
public: |
|
FormFieldText(PDFDoc *docA, Object &&dictObj, const Ref ref, FormField *parent, std::set<int> *usedParents); |
|
|
|
const GooString *getContent() const { return content; } |
|
const GooString *getAppearanceContent() const { return internalContent ? internalContent : content; } |
|
void setContentCopy(const GooString *new_content); |
|
void setAppearanceContentCopy(const GooString *new_content); |
|
~FormFieldText() override; |
|
|
|
bool isMultiline() const { return multiline; } |
|
bool isPassword() const { return password; } |
|
bool isFileSelect() const { return fileSelect; } |
|
bool noSpellCheck() const { return doNotSpellCheck; } |
|
bool noScroll() const { return doNotScroll; } |
|
bool isComb() const { return comb; } |
|
bool isRichText() const { return richText; } |
|
|
|
int getMaxLen() const { return maxLen; } |
|
|
|
|
|
double getTextFontSize(); |
|
|
|
void setTextFontSize(int fontSize); |
|
|
|
void print(int indent) override; |
|
void reset(const std::vector<std::string> &excludedFields) override; |
|
|
|
static int tokenizeDA(const std::string &daString, std::vector<std::string> *daToks, const char *searchTok); |
|
|
|
protected: |
|
int parseDA(std::vector<std::string> *daToks); |
|
void fillContent(FillValueType fillType); |
|
|
|
GooString *content; |
|
GooString *internalContent; |
|
GooString *defaultContent; |
|
bool multiline; |
|
bool password; |
|
bool fileSelect; |
|
bool doNotSpellCheck; |
|
bool doNotScroll; |
|
bool comb; |
|
bool richText; |
|
int maxLen; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class FormFieldChoice : public FormField |
|
{ |
|
public: |
|
FormFieldChoice(PDFDoc *docA, Object &&aobj, const Ref ref, FormField *parent, std::set<int> *usedParents); |
|
|
|
~FormFieldChoice() override; |
|
|
|
int getNumChoices() const { return numChoices; } |
|
const GooString *getChoice(int i) const { return choices ? choices[i].optionName : nullptr; } |
|
const GooString *getExportVal(int i) const { return choices ? choices[i].exportVal : nullptr; } |
|
|
|
const GooString *getSelectedChoice() const; |
|
|
|
|
|
void select(int i); |
|
|
|
|
|
void toggle(int i); |
|
|
|
|
|
void deselectAll(); |
|
|
|
|
|
void setEditChoice(const GooString *new_content); |
|
|
|
const GooString *getEditChoice() const; |
|
|
|
bool isSelected(int i) const { return choices[i].selected; } |
|
|
|
int getNumSelected(); |
|
|
|
bool isCombo() const { return combo; } |
|
bool hasEdit() const { return edit; } |
|
bool isMultiSelect() const { return multiselect; } |
|
bool noSpellCheck() const { return doNotSpellCheck; } |
|
bool commitOnSelChange() const { return doCommitOnSelChange; } |
|
bool isListBox() const { return !combo; } |
|
|
|
int getTopIndex() const { return topIdx; } |
|
|
|
void print(int indent) override; |
|
void reset(const std::vector<std::string> &excludedFields) override; |
|
|
|
protected: |
|
void unselectAll(); |
|
void updateSelection(); |
|
void fillChoices(FillValueType fillType); |
|
|
|
bool combo; |
|
bool edit; |
|
bool multiselect; |
|
bool doNotSpellCheck; |
|
bool doCommitOnSelChange; |
|
|
|
struct ChoiceOpt |
|
{ |
|
GooString *exportVal; |
|
GooString *optionName; |
|
bool selected; |
|
}; |
|
|
|
int numChoices; |
|
ChoiceOpt *choices; |
|
bool *defaultChoices; |
|
GooString *editedChoice; |
|
int topIdx; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormFieldSignature : public FormField |
|
{ |
|
public: |
|
FormFieldSignature(PDFDoc *docA, Object &&dict, const Ref ref, FormField *parent, std::set<int> *usedParents); |
|
|
|
|
|
SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime, bool ocspRevocationCheck, bool enableAIA); |
|
|
|
|
|
|
|
std::vector<Goffset> getSignedRangeBounds() const; |
|
|
|
|
|
|
|
|
|
std::optional<GooString> getCheckedSignature(Goffset *checkedFileSize); |
|
|
|
~FormFieldSignature() override; |
|
Object *getByteRange() { return &byte_range; } |
|
const GooString *getSignature() const { return signature; } |
|
void setSignature(const GooString &sig); |
|
FormSignatureType getSignatureType() const { return signature_type; } |
|
void setSignatureType(FormSignatureType t) { signature_type = t; } |
|
|
|
const GooString &getCustomAppearanceContent() const; |
|
void setCustomAppearanceContent(const GooString &s); |
|
|
|
const GooString &getCustomAppearanceLeftContent() const; |
|
void setCustomAppearanceLeftContent(const GooString &s); |
|
|
|
double getCustomAppearanceLeftFontSize() const; |
|
void setCustomAppearanceLeftFontSize(double size); |
|
|
|
|
|
Ref getImageResource() const; |
|
void setImageResource(const Ref imageResourceA); |
|
|
|
void setCertificateInfo(std::unique_ptr<X509CertificateInfo> &); |
|
|
|
FormWidget *getCreateWidget(); |
|
|
|
private: |
|
void parseInfo(); |
|
void hashSignedDataBlock(CryptoSign::VerificationInterface *handler, Goffset block_len); |
|
|
|
FormSignatureType signature_type; |
|
Object byte_range; |
|
GooString *signature; |
|
SignatureInfo *signature_info; |
|
GooString customAppearanceContent; |
|
GooString customAppearanceLeftContent; |
|
double customAppearanceLeftFontSize = 20; |
|
Ref imageResource = Ref::INVALID(); |
|
std::unique_ptr<X509CertificateInfo> certificate_info; |
|
|
|
void print(int indent) override; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT Form |
|
{ |
|
public: |
|
explicit Form(PDFDoc *doc); |
|
|
|
~Form(); |
|
|
|
Form(const Form &) = delete; |
|
Form &operator=(const Form &) = delete; |
|
|
|
|
|
static Object fieldLookup(Dict *field, const char *key); |
|
|
|
|
|
|
|
|
|
static FormField *createFieldFromDict(Object &&obj, PDFDoc *docA, const Ref aref, FormField *parent, std::set<int> *usedParents); |
|
|
|
|
|
|
|
std::string findFontInDefaultResources(const std::string &fontFamily, const std::string &fontStyle) const; |
|
|
|
|
|
|
|
std::string findPdfFontNameToUseForSigning(); |
|
|
|
struct AddFontResult |
|
{ |
|
std::string fontName; |
|
Ref ref; |
|
}; |
|
|
|
|
|
|
|
|
|
AddFontResult addFontToDefaultResources(const std::string &fontFamily, const std::string &fontStyle, bool forceName = false); |
|
|
|
|
|
|
|
std::string getFallbackFontForChar(Unicode uChar, const GfxFont &fontToEmulate) const; |
|
|
|
|
|
|
|
|
|
|
|
std::vector<AddFontResult> ensureFontsForAllCharacters(const GooString *unicodeText, const std::string &pdfFontNameToEmulate, GfxResources *fieldResources = nullptr); |
|
|
|
bool getNeedAppearances() const { return needAppearances; } |
|
int getNumFields() const { return numFields; } |
|
FormField *getRootField(int i) const { return rootFields[i]; } |
|
const GooString *getDefaultAppearance() const { return defaultAppearance; } |
|
VariableTextQuadding getTextQuadding() const { return quadding; } |
|
GfxResources *getDefaultResources() const { return defaultResources; } |
|
Object *getDefaultResourcesObj() { return &resDict; } |
|
|
|
FormWidget *findWidgetByRef(Ref aref); |
|
FormField *findFieldByRef(Ref aref) const; |
|
FormField *findFieldByFullyQualifiedName(const std::string &name) const; |
|
|
|
void postWidgetsLoad(); |
|
|
|
const std::vector<Ref> &getCalculateOrder() const { return calculateOrder; } |
|
|
|
void reset(const std::vector<std::string> &fields, bool excludeFields); |
|
|
|
private: |
|
|
|
|
|
|
|
AddFontResult addFontToDefaultResources(const std::string &filepath, int faceIndex, const std::string &fontFamily, const std::string &fontStyle, bool forceName = false); |
|
|
|
AddFontResult doGetAddFontToDefaultResources(Unicode uChar, const GfxFont &fontToEmulate); |
|
|
|
FormField **rootFields; |
|
int numFields; |
|
int size; |
|
PDFDoc *const doc; |
|
bool needAppearances; |
|
GfxResources *defaultResources; |
|
Object resDict; |
|
std::vector<Ref> calculateOrder; |
|
|
|
|
|
GooString *defaultAppearance; |
|
VariableTextQuadding quadding; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class POPPLER_PRIVATE_EXPORT FormPageWidgets |
|
{ |
|
public: |
|
FormPageWidgets(Annots *annots, unsigned int page, Form *form); |
|
~FormPageWidgets(); |
|
|
|
FormPageWidgets(const FormPageWidgets &) = delete; |
|
FormPageWidgets &operator=(const FormPageWidgets &) = delete; |
|
|
|
int getNumWidgets() const { return numWidgets; } |
|
FormWidget *getWidget(int i) const { return widgets[i]; } |
|
void addWidgets(const std::vector<FormField *> &addedWidgets, unsigned int page); |
|
|
|
private: |
|
FormWidget **widgets; |
|
int numWidgets; |
|
int size; |
|
}; |
|
|
|
#endif |
|
|