github.com/unidoc/unipdf/v3@v3.55.0/model/xmputil/xmputil.go (about) 1 // 2 // Copyright 2020 FoxyUtils ehf. All rights reserved. 3 // 4 // This is a commercial product and requires a license to operate. 5 // A trial license can be obtained at https://unidoc.io 6 // 7 // DO NOT EDIT: generated by unitwist Go source code obfuscator. 8 // 9 // Use of this source code is governed by the UniDoc End User License Agreement 10 // terms that can be accessed at https://unidoc.io/eula/ 11 12 // Package xmputil provides abstraction used by the pdf document XMP Metadata. 13 package xmputil ;import (_bd "errors";_fe "fmt";_be "github.com/trimmer-io/go-xmp/models/pdf";_db "github.com/trimmer-io/go-xmp/models/xmp_mm";_b "github.com/trimmer-io/go-xmp/xmp";_aab "github.com/unidoc/unipdf/v3/core";_ac "github.com/unidoc/unipdf/v3/internal/timeutils"; 14 _aa "github.com/unidoc/unipdf/v3/internal/uuid";_ba "github.com/unidoc/unipdf/v3/model/xmputil/pdfaextension";_g "github.com/unidoc/unipdf/v3/model/xmputil/pdfaid";_d "strconv";_a "time";); 15 16 // MediaManagementVersion is the version of the media management xmp metadata. 17 type MediaManagementVersion struct{VersionID string ;ModifyDate _a .Time ;Comments string ;Modifier string ;}; 18 19 // Document is an implementation of the xmp document. 20 // It is a wrapper over go-xmp/xmp.Document that provides some Pdf predefined functionality. 21 type Document struct{_fg *_b .Document }; 22 23 // PdfInfoOptions are the options used for setting pdf info. 24 type PdfInfoOptions struct{InfoDict _aab .PdfObject ;PdfVersion string ;Copyright string ;Marked bool ; 25 26 // Overwrite if set to true, overwrites all values found in the current pdf info xmp model to the ones provided. 27 Overwrite bool ;}; 28 29 // GetPdfInfo gets the document pdf info. 30 func (_dag *Document )GetPdfInfo ()(*PdfInfo ,bool ){_gb ,_fgf :=_dag ._fg .FindModel (_be .NsPDF ).(*_be .PDFInfo );if !_fgf {return nil ,false ;};_ebd :=PdfInfo {};var _ecd *_aab .PdfObjectDictionary ;_ebd .Copyright =_gb .Copyright ;_ebd .PdfVersion =_gb .PDFVersion ; 31 _ebd .Marked =bool (_gb .Marked );_cgd :=func (_dac string ,_fa _aab .PdfObject ){if _ecd ==nil {_ecd =_aab .MakeDict ();};_ecd .Set (_aab .PdfObjectName (_dac ),_fa );};if len (_gb .Title )> 0{_cgd ("\u0054\u0069\u0074l\u0065",_aab .MakeString (_gb .Title .Default ())); 32 };if len (_gb .Author )> 0{_cgd ("\u0041\u0075\u0074\u0068\u006f\u0072",_aab .MakeString (_gb .Author [0]));};if _gb .Keywords !=""{_cgd ("\u004b\u0065\u0079\u0077\u006f\u0072\u0064\u0073",_aab .MakeString (_gb .Keywords ));};if len (_gb .Subject )> 0{_cgd ("\u0053u\u0062\u006a\u0065\u0063\u0074",_aab .MakeString (_gb .Subject .Default ())); 33 };if _gb .Creator !=""{_cgd ("\u0043r\u0065\u0061\u0074\u006f\u0072",_aab .MakeString (string (_gb .Creator )));};if _gb .Producer !=""{_cgd ("\u0050\u0072\u006f\u0064\u0075\u0063\u0065\u0072",_aab .MakeString (string (_gb .Producer )));};if _gb .Trapped {_cgd ("\u0054r\u0061\u0070\u0070\u0065\u0064",_aab .MakeName ("\u0054\u0072\u0075\u0065")); 34 };if !_gb .CreationDate .IsZero (){_cgd ("\u0043\u0072\u0065a\u0074\u0069\u006f\u006e\u0044\u0061\u0074\u0065",_aab .MakeString (_ac .FormatPdfTime (_gb .CreationDate .Value ())));};if !_gb .ModifyDate .IsZero (){_cgd ("\u004do\u0064\u0044\u0061\u0074\u0065",_aab .MakeString (_ac .FormatPdfTime (_gb .ModifyDate .Value ()))); 35 };_ebd .InfoDict =_ecd ;return &_ebd ,true ;}; 36 37 // LoadDocument loads up the xmp document from provided input stream. 38 func LoadDocument (stream []byte )(*Document ,error ){_bg :=_b .NewDocument ();if _gd :=_b .Unmarshal (stream ,_bg );_gd !=nil {return nil ,_gd ;};return &Document {_fg :_bg },nil ;}; 39 40 // MediaManagementOptions are the options for the Media management xmp metadata. 41 type MediaManagementOptions struct{ 42 43 // OriginalDocumentID as media is imported and projects is started, an original-document ID 44 // must be created to identify a new document. This identifies a document as a conceptual entity. 45 // By default, this value is generated. 46 OriginalDocumentID string ; 47 48 // NewDocumentID is a flag which generates a new Document identifier while setting media management. 49 // This value should be set to true only if the document is stored and saved as new document. 50 // Otherwise, if the document is modified and overwrites previous file, it should be set to false. 51 NewDocumentID bool ; 52 53 // DocumentID when a document is copied to a new file path or converted to a new format with 54 // Save As, another new document ID should usually be assigned. This identifies a general version or 55 // branch of a document. You can use it to track different versions or extracted portions of a document 56 // with the same original-document ID. 57 // By default, this value is generated if NewDocumentID is true or previous doesn't exist. 58 DocumentID string ; 59 60 // InstanceID to track a document’s editing history, you must assign a new instance ID 61 // whenever a document is saved after any changes. This uniquely identifies an exact version of a 62 // document. It is used in resource references (to identify both the document or part itself and the 63 // referenced or referencing documents), and in document-history resource events (to identify the 64 // document instance that resulted from the change). 65 // By default, this value is generated. 66 InstanceID string ; 67 68 // DerivedFrom references the source document from which this one is derived, 69 // typically through a Save As operation that changes the file name or format. It is a minimal reference; 70 // missing components can be assumed to be unchanged. For example, a new version might only need 71 // to specify the instance ID and version number of the previous version, or a rendition might only need 72 // to specify the instance ID and rendition class of the original. 73 // By default, the derived from structure is filled from previous XMP metadata (if exists). 74 DerivedFrom string ; 75 76 // VersionID are meant to associate the document with a product version that is part of a release process. They can be useful in tracking the 77 // document history, but should not be used to identify a document uniquely in any context. 78 // Usually it simply works by incrementing integers 1,2,3... 79 // By default, this values is incremented or set to the next version number. 80 VersionID string ; 81 82 // ModifyComment is a comment to given modification 83 ModifyComment string ; 84 85 // ModifyDate is a custom modification date for the versions. 86 // By default, this would be set to time.Now(). 87 ModifyDate _a .Time ; 88 89 // Modifier is a person who did the modification. 90 Modifier string ;}; 91 92 // GetGoXmpDocument gets direct access to the go-xmp.Document. 93 // All changes done to specified document would result in change of this document 'd'. 94 func (_fge *Document )GetGoXmpDocument ()*_b .Document {return _fge ._fg }; 95 96 // GetPdfAID gets the pdfaid xmp metadata model. 97 func (_bc *Document )GetPdfAID ()(*PdfAID ,bool ){_cd ,_eea :=_bc ._fg .FindModel (_g .Namespace ).(*_g .Model );if !_eea {return nil ,false ;};return &PdfAID {Part :_cd .Part ,Conformance :_cd .Conformance },true ;}; 98 99 // PdfInfo is the xmp document pdf info. 100 type PdfInfo struct{InfoDict _aab .PdfObject ;PdfVersion string ;Copyright string ;Marked bool ;}; 101 102 // NewDocument creates a new document without any previous xmp information. 103 func NewDocument ()*Document {_ff :=_b .NewDocument ();return &Document {_fg :_ff }}; 104 105 // SetPdfAID sets up pdfaid xmp metadata. 106 // In example: Part: '1' Conformance: 'B' states for PDF/A 1B. 107 func (_eba *Document )SetPdfAID (part int ,conformance string )error {_fgfb ,_cfd :=_g .MakeModel (_eba ._fg );if _cfd !=nil {return _cfd ;};_fgfb .Part =part ;_fgfb .Conformance =conformance ;if _cgg :=_fgfb .SyncToXMP (_eba ._fg );_cgg !=nil {return _cgg ; 108 };return nil ;}; 109 110 // MediaManagementDerivedFrom is a structure that contains references of identifiers and versions 111 // from which given document was derived. 112 type MediaManagementDerivedFrom struct{OriginalDocumentID GUID ;DocumentID GUID ;InstanceID GUID ;VersionID string ;}; 113 114 // Marshal the document into xml byte stream. 115 func (_e *Document )Marshal ()([]byte ,error ){if _e ._fg .IsDirty (){if _fgd :=_e ._fg .SyncModels ();_fgd !=nil {return nil ,_fgd ;};};return _b .Marshal (_e ._fg );}; 116 117 // GetMediaManagement gets the media management metadata from provided xmp document. 118 func (_bda *Document )GetMediaManagement ()(*MediaManagement ,bool ){_gc :=_db .FindModel (_bda ._fg );if _gc ==nil {return nil ,false ;};_aca :=make ([]MediaManagementVersion ,len (_gc .Versions ));for _eef ,_bdd :=range _gc .Versions {_aca [_eef ]=MediaManagementVersion {VersionID :_bdd .Version ,ModifyDate :_bdd .ModifyDate .Value (),Comments :_bdd .Comments ,Modifier :_bdd .Modifier }; 119 };_fcfd :=&MediaManagement {OriginalDocumentID :GUID (_gc .OriginalDocumentID .Value ()),DocumentID :GUID (_gc .DocumentID .Value ()),InstanceID :GUID (_gc .InstanceID .Value ()),VersionID :_gc .VersionID ,Versions :_aca };if _gc .DerivedFrom !=nil {_fcfd .DerivedFrom =&MediaManagementDerivedFrom {OriginalDocumentID :GUID (_gc .DerivedFrom .OriginalDocumentID ),DocumentID :GUID (_gc .DerivedFrom .DocumentID ),InstanceID :GUID (_gc .DerivedFrom .InstanceID ),VersionID :_gc .DerivedFrom .VersionID }; 120 };return _fcfd ,true ;}; 121 122 // SetPdfInfo sets the pdf info into selected document. 123 func (_ga *Document )SetPdfInfo (options *PdfInfoOptions )error {if options ==nil {return _bd .New ("\u006ei\u006c\u0020\u0070\u0064\u0066\u0020\u006f\u0070\u0074\u0069\u006fn\u0073\u0020\u0070\u0072\u006f\u0076\u0069\u0064\u0065\u0064");};_efd ,_cb :=_be .MakeModel (_ga ._fg ); 124 if _cb !=nil {return _cb ;};if options .Overwrite {*_efd =_be .PDFInfo {};};if options .InfoDict !=nil {_cf ,_aac :=_aab .GetDict (options .InfoDict );if !_aac {return _fe .Errorf ("i\u006e\u0076\u0061\u006c\u0069\u0064 \u0070\u0064\u0066\u0020\u006f\u0062\u006a\u0065\u0063t\u0020\u0074\u0079p\u0065:\u0020\u0025\u0054",options .InfoDict ); 125 };var _dab *_aab .PdfObjectString ;for _ ,_af :=range _cf .Keys (){switch _af {case "\u0054\u0069\u0074l\u0065":_dab ,_aac =_aab .GetString (_cf .Get ("\u0054\u0069\u0074l\u0065"));if _aac {_efd .Title =_b .NewAltString (_dab );};case "\u0041\u0075\u0074\u0068\u006f\u0072":_dab ,_aac =_aab .GetString (_cf .Get ("\u0041\u0075\u0074\u0068\u006f\u0072")); 126 if _aac {_efd .Author =_b .NewStringList (_dab .String ());};case "\u004b\u0065\u0079\u0077\u006f\u0072\u0064\u0073":_dab ,_aac =_aab .GetString (_cf .Get ("\u004b\u0065\u0079\u0077\u006f\u0072\u0064\u0073"));if _aac {_efd .Keywords =_dab .String ();}; 127 case "\u0043r\u0065\u0061\u0074\u006f\u0072":_dab ,_aac =_aab .GetString (_cf .Get ("\u0043r\u0065\u0061\u0074\u006f\u0072"));if _aac {_efd .Creator =_b .AgentName (_dab .String ());};case "\u0053u\u0062\u006a\u0065\u0063\u0074":_dab ,_aac =_aab .GetString (_cf .Get ("\u0053u\u0062\u006a\u0065\u0063\u0074")); 128 if _aac {_efd .Subject =_b .NewAltString (_dab .String ());};case "\u0050\u0072\u006f\u0064\u0075\u0063\u0065\u0072":_dab ,_aac =_aab .GetString (_cf .Get ("\u0050\u0072\u006f\u0064\u0075\u0063\u0065\u0072"));if _aac {_efd .Producer =_b .AgentName (_dab .String ()); 129 };case "\u0054r\u0061\u0070\u0070\u0065\u0064":_fc ,_bb :=_aab .GetName (_cf .Get ("\u0054r\u0061\u0070\u0070\u0065\u0064"));if _bb {switch _fc .String (){case "\u0054\u0072\u0075\u0065":_efd .Trapped =true ;case "\u0046\u0061\u006cs\u0065":_efd .Trapped =false ; 130 default:_efd .Trapped =true ;};};case "\u0043\u0072\u0065a\u0074\u0069\u006f\u006e\u0044\u0061\u0074\u0065":if _fd ,_ec :=_aab .GetString (_cf .Get ("\u0043\u0072\u0065a\u0074\u0069\u006f\u006e\u0044\u0061\u0074\u0065"));_ec &&_fd .String ()!=""{_gf ,_ebe :=_ac .ParsePdfTime (_fd .String ()); 131 if _ebe !=nil {return _fe .Errorf ("\u0069\u006e\u0076\u0061\u006c\u0069\u0064\u0020\u0043\u0072e\u0061\u0074\u0069\u006f\u006e\u0044\u0061t\u0065\u0020\u0066\u0069\u0065\u006c\u0064\u003a\u0020\u0025\u0077",_ebe );};_efd .CreationDate =_b .NewDate (_gf ); 132 };case "\u004do\u0064\u0044\u0061\u0074\u0065":if _gda ,_fcd :=_aab .GetString (_cf .Get ("\u004do\u0064\u0044\u0061\u0074\u0065"));_fcd &&_gda .String ()!=""{_cg ,_eg :=_ac .ParsePdfTime (_gda .String ());if _eg !=nil {return _fe .Errorf ("\u0069n\u0076\u0061\u006c\u0069d\u0020\u004d\u006f\u0064\u0044a\u0074e\u0020f\u0069\u0065\u006c\u0064\u003a\u0020\u0025w",_eg ); 133 };_efd .ModifyDate =_b .NewDate (_cg );};};};};if options .PdfVersion !=""{_efd .PDFVersion =options .PdfVersion ;};if options .Marked {_efd .Marked =_b .Bool (options .Marked );};if options .Copyright !=""{_efd .Copyright =options .Copyright ;};if _cb =_efd .SyncToXMP (_ga ._fg ); 134 _cb !=nil {return _cb ;};return nil ;}; 135 136 // MarshalIndent the document into xml byte stream with predefined prefix and indent. 137 func (_aaf *Document )MarshalIndent (prefix ,indent string )([]byte ,error ){if _aaf ._fg .IsDirty (){if _c :=_aaf ._fg .SyncModels ();_c !=nil {return nil ,_c ;};};return _b .MarshalIndent (_aaf ._fg ,prefix ,indent );}; 138 139 // SetPdfAExtension sets the pdfaExtension XMP metadata. 140 func (_ae *Document )SetPdfAExtension ()error {_ef ,_bf :=_ba .MakeModel (_ae ._fg );if _bf !=nil {return _bf ;};if _bf =_ba .FillModel (_ae ._fg ,_ef );_bf !=nil {return _bf ;};if _bf =_ef .SyncToXMP (_ae ._fg );_bf !=nil {return _bf ;};return nil ;}; 141 142 143 // MediaManagement are the values from the document media management metadata. 144 type MediaManagement struct{ 145 146 // OriginalDocumentID as media is imported and projects is started, an original-document ID 147 // must be created to identify a new document. This identifies a document as a conceptual entity. 148 OriginalDocumentID GUID ; 149 150 // DocumentID when a document is copied to a new file path or converted to a new format with 151 // Save As, another new document ID should usually be assigned. This identifies a general version or 152 // branch of a document. You can use it to track different versions or extracted portions of a document 153 // with the same original-document ID. 154 DocumentID GUID ; 155 156 // InstanceID to track a document’s editing history, you must assign a new instance ID 157 // whenever a document is saved after any changes. This uniquely identifies an exact version of a 158 // document. It is used in resource references (to identify both the document or part itself and the 159 // referenced or referencing documents), and in document-history resource events (to identify the 160 // document instance that resulted from the change). 161 InstanceID GUID ; 162 163 // DerivedFrom references the source document from which this one is derived, 164 // typically through a Save As operation that changes the file name or format. It is a minimal reference; 165 // missing components can be assumed to be unchanged. For example, a new version might only need 166 // to specify the instance ID and version number of the previous version, or a rendition might only need 167 // to specify the instance ID and rendition class of the original. 168 DerivedFrom *MediaManagementDerivedFrom ; 169 170 // VersionID are meant to associate the document with a product version that is part of a release process. They can be useful in tracking the 171 // document history, but should not be used to identify a document uniquely in any context. 172 // Usually it simply works by incrementing integers 1,2,3... 173 VersionID string ; 174 175 // Versions is the history of the document versions along with the comments, timestamps and issuers. 176 Versions []MediaManagementVersion ;}; 177 178 // PdfAID is the result of the XMP pdfaid metadata. 179 type PdfAID struct{Part int ;Conformance string ;}; 180 181 // SetMediaManagement sets up XMP media management metadata: namespace xmpMM. 182 func (_fcf *Document )SetMediaManagement (options *MediaManagementOptions )error {_fde ,_cbc :=_db .MakeModel (_fcf ._fg );if _cbc !=nil {return _cbc ;};if options ==nil {options =new (MediaManagementOptions );};_gba :=_db .ResourceRef {};if _fde .OriginalDocumentID .IsZero (){if options .OriginalDocumentID !=""{_fde .OriginalDocumentID =_b .GUID (options .OriginalDocumentID ); 183 }else {_ebeg ,_cc :=_aa .NewUUID ();if _cc !=nil {return _cc ;};_fde .OriginalDocumentID =_b .GUID (_ebeg .String ());};}else {_gba .OriginalDocumentID =_fde .OriginalDocumentID ;};switch {case options .DocumentID !="":_fde .DocumentID =_b .GUID (options .DocumentID ); 184 case options .NewDocumentID ||_fde .DocumentID .IsZero ():if !_fde .DocumentID .IsZero (){_gba .DocumentID =_fde .DocumentID ;};_bdc ,_fcc :=_aa .NewUUID ();if _fcc !=nil {return _fcc ;};_fde .DocumentID =_b .GUID (_bdc .String ());};if !_fde .InstanceID .IsZero (){_gba .InstanceID =_fde .InstanceID ; 185 };_fde .InstanceID =_b .GUID (options .InstanceID );if _fde .InstanceID ==""{_dg ,_bgd :=_aa .NewUUID ();if _bgd !=nil {return _bgd ;};_fde .InstanceID =_b .GUID (_dg .String ());};if !_gba .IsZero (){_fde .DerivedFrom =&_gba ;};_ad :=options .VersionID ; 186 if _fde .VersionID !=""{_gfe ,_ca :=_d .Atoi (_fde .VersionID );if _ca !=nil {_ad =_d .Itoa (len (_fde .Versions )+1);}else {_ad =_d .Itoa (_gfe +1);};};if _ad ==""{_ad ="\u0031";};_fde .VersionID =_ad ;if _cbc =_fde .SyncToXMP (_fcf ._fg );_cbc !=nil {return _cbc ; 187 };return nil ;}; 188 189 // GetPdfaExtensionSchemas gets a pdfa extension schemas. 190 func (_fec *Document )GetPdfaExtensionSchemas ()([]_ba .Schema ,error ){_da :=_fec ._fg .FindModel (_ba .Namespace );if _da ==nil {return nil ,nil ;};_ee ,_ea :=_da .(*_ba .Model );if !_ea {return nil ,_fe .Errorf ("\u0069\u006eva\u006c\u0069\u0064 \u006d\u006f\u0064\u0065l f\u006fr \u0070\u0064\u0066\u0061\u0045\u0078\u0074en\u0073\u0069\u006f\u006e\u0073\u003a\u0020%\u0054",_da ); 191 };return _ee .Schemas ,nil ;}; 192 193 // GUID is a string representing a globally unique identifier. 194 type GUID string ;