2020-08-23 14:15:53 +00:00
|
|
|
//
|
|
|
|
// Copyright 2020 FoxyUtils ehf. All rights reserved.
|
|
|
|
//
|
|
|
|
// This is a commercial product and requires a license to operate.
|
|
|
|
// A trial license can be obtained at https://unidoc.io
|
|
|
|
//
|
|
|
|
// DO NOT EDIT: generated by unitwist Go source code obfuscator.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by the UniDoc End User License Agreement
|
|
|
|
// terms that can be accessed at https://unidoc.io/eula/
|
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
package zippkg ;import (_a "archive/zip";_fb "bytes";_aae "encoding/xml";_af "fmt";_dge "github.com/unidoc/unioffice";_dg "github.com/unidoc/unioffice/algo";_dc "github.com/unidoc/unioffice/common/tempstorage";_dd "github.com/unidoc/unioffice/schema/soo/pkg/relationships";_aa "io";_d "path";_gg "sort";_ae "strings";_g "time";);func MarshalXMLByType (z *_a .Writer ,dt _dge .DocType ,typ string ,v interface{})error {_efa :=_dge .AbsoluteFilename (dt ,typ ,0);return MarshalXML (z ,_efa ,v );};func MarshalXMLByTypeIndex (z *_a .Writer ,dt _dge .DocType ,typ string ,idx int ,v interface{})error {_ad :=_dge .AbsoluteFilename (dt ,typ ,idx );return MarshalXML (z ,_ad ,v );};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// AddFileFromBytes takes a byte array and adds it at a given path to a zip file.
|
|
|
|
func AddFileFromBytes (z *_a .Writer ,zipPath string ,data []byte )error {_afg ,_dea :=z .Create (zipPath );if _dea !=nil {return _af .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_dea );};_ ,_dea =_aa .Copy (_afg ,_fb .NewReader (data ));return _dea ;};var _ege =[]byte {'/','>'};func (_edg SelfClosingWriter )Write (b []byte )(int ,error ){_afb :=0;_egg :=0;for _gda :=0;_gda < len (b )-2;_gda ++{if b [_gda ]=='>'&&b [_gda +1]=='<'&&b [_gda +2]=='/'{_acaf :=[]byte {};_afe :=_gda ;for _gfg :=_gda ;_gfg >=0;_gfg --{if b [_gfg ]==' '{_afe =_gfg ;}else if b [_gfg ]=='<'{_acaf =b [_gfg +1:_afe ];break ;};};_ggd :=[]byte {};for _dfc :=_gda +3;_dfc < len (b );_dfc ++{if b [_dfc ]=='>'{_ggd =b [_gda +3:_dfc ];break ;};};if !_fb .Equal (_acaf ,_ggd ){continue ;};_cec ,_dca :=_edg .W .Write (b [_afb :_gda ]);if _dca !=nil {return _egg +_cec ,_dca ;};_egg +=_cec ;_ ,_dca =_edg .W .Write (_ege );if _dca !=nil {return _egg ,_dca ;};_egg +=3;for _gde :=_gda +2;_gde < len (b )&&b [_gde ]!='>';_gde ++{_egg ++;_afb =_gde +2;_gda =_afb ;};};};_bc ,_eba :=_edg .W .Write (b [_afb :]);return _bc +_egg ,_eba ;};func (_bg *DecodeMap )IndexFor (path string )int {return _bg ._fbc [path ]};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// SelfClosingWriter wraps a writer and replaces XML tags of the
|
|
|
|
// type <foo></foo> with <foo/>
|
|
|
|
type SelfClosingWriter struct{W _aa .Writer ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// ExtractToDiskTmp extracts a zip file to a temporary file in a given path,
|
|
|
|
// returning the name of the file.
|
|
|
|
func ExtractToDiskTmp (f *_a .File ,path string )(string ,error ){_cda ,_ed :=_dc .TempFile (path ,"\u007a\u007a");if _ed !=nil {return "",_ed ;};defer _cda .Close ();_eee ,_ed :=f .Open ();if _ed !=nil {return "",_ed ;};defer _eee .Close ();_ ,_ed =_aa .Copy (_cda ,_eee );if _ed !=nil {return "",_ed ;};return _cda .Name (),nil ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-08-31 22:58:25 +00:00
|
|
|
// Decode unmarshals the content of a *zip.File as XML to a given destination.
|
2020-10-12 13:59:12 +00:00
|
|
|
func Decode (f *_a .File ,dest interface{})error {_efc ,_fbe :=f .Open ();if _fbe !=nil {return _af .Errorf ("e\u0072r\u006f\u0072\u0020\u0072\u0065\u0061\u0064\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",f .Name ,_fbe );};defer _efc .Close ();_efg :=_aae .NewDecoder (_efc );if _dfd :=_efg .Decode (dest );_dfd !=nil {return _af .Errorf ("e\u0072\u0072\u006f\u0072 d\u0065c\u006f\u0064\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",f .Name ,_dfd );};if _fbcg ,_ggc :=dest .(*_dd .Relationships );_ggc {for _ba ,_cbca :=range _fbcg .Relationship {switch _cbca .TypeAttr {case _dge .OfficeDocumentTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .OfficeDocumentType ;case _dge .StylesTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .StylesType ;case _dge .ThemeTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .ThemeType ;case _dge .SettingsTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .SettingsType ;case _dge .ImageTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .ImageType ;case _dge .CommentsTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .CommentsType ;case _dge .ThumbnailTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .ThumbnailType ;case _dge .DrawingTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .DrawingType ;case _dge .ChartTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .ChartType ;case _dge .ExtendedPropertiesTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .ExtendedPropertiesType ;case _dge .CustomXMLTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .CustomXMLType ;case _dge .WorksheetTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .WorksheetType ;case _dge .SharedStringsTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .SharedStringsType ;case _dge .TableTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .TableType ;case _dge .HeaderTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .HeaderType ;case _dge .FooterTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .FooterType ;case _dge .NumberingTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .NumberingType ;case _dge .FontTableTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .FontTableType ;case _dge .WebSettingsTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .WebSettingsType ;case _dge .FootNotesTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .FootNotesType ;case _dge .EndNotesTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .EndNotesType ;case _dge .SlideTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .SlideType ;case _dge .VMLDrawingTypeStrict :_fbcg .Relationship [_ba ].TypeAttr =_dge .VMLDrawingType ;};};_gg .Slice (_fbcg .Relationship ,func (_gcb ,_aaa int )bool {_ee :=_fbcg .Relationship [_gcb ];_bf :=_fbcg .Relationship [_aaa ];return _dg .NaturalLess (_ee .IdAttr ,_bf .IdAttr );});};return nil ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// MarshalXML creates a file inside of a zip and marshals an object as xml, prefixing it
|
|
|
|
// with a standard XML header.
|
|
|
|
func MarshalXML (z *_a .Writer ,filename string ,v interface{})error {_dbcc :=&_a .FileHeader {};_dbcc .Method =_a .Deflate ;_dbcc .Name =filename ;_dbcc .SetModTime (_g .Now ());_eda ,_ec :=z .CreateHeader (_dbcc );if _ec !=nil {return _af .Errorf ("\u0063\u0072\u0065\u0061ti\u006e\u0067\u0020\u0025\u0073\u0020\u0069\u006e\u0020\u007a\u0069\u0070\u003a\u0020%\u0073",filename ,_ec );};_ ,_ec =_eda .Write ([]byte (XMLHeader ));if _ec !=nil {return _af .Errorf ("\u0063\u0072e\u0061\u0074\u0069\u006e\u0067\u0020\u0078\u006d\u006c\u0020\u0068\u0065\u0061\u0064\u0065\u0072\u0020\u0074\u006f\u0020\u0025\u0073: \u0025\u0073",filename ,_ec );};if _ec =_aae .NewEncoder (SelfClosingWriter {_eda }).Encode (v );_ec !=nil {return _af .Errorf ("\u006d\u0061\u0072\u0073\u0068\u0061\u006c\u0069\u006e\u0067\u0020\u0025s\u003a\u0020\u0025\u0073",filename ,_ec );};_ ,_ec =_eda .Write (_ga );return _ec ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
|
|
|
// OnNewRelationshipFunc is called when a new relationship has been discovered.
|
|
|
|
//
|
|
|
|
// target is a resolved path that takes into account the location of the
|
|
|
|
// relationships file source and should be the path in the zip file.
|
|
|
|
//
|
|
|
|
// files are passed so non-XML files that can't be handled by AddTarget can be
|
|
|
|
// decoded directly (e.g. images)
|
|
|
|
//
|
|
|
|
// rel is the actual relationship so its target can be modified if the source
|
|
|
|
// target doesn't match where unioffice will write the file (e.g. read in
|
|
|
|
// 'xl/worksheets/MyWorksheet.xml' and we'll write out
|
|
|
|
// 'xl/worksheets/sheet1.xml')
|
2020-10-12 13:59:12 +00:00
|
|
|
type OnNewRelationshipFunc func (_c *DecodeMap ,_fa ,_ag string ,_cb []*_a .File ,_gb *_dd .Relationship ,_db Target )error ;
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// AddTarget allows documents to register decode targets. Path is a path that
|
|
|
|
// will be found in the zip file and ifc is an XML element that the file will be
|
|
|
|
// unmarshaled to. filePath is the absolute path to the target, ifc is the
|
|
|
|
// object to decode into, sourceFileType is the type of file that the reference
|
|
|
|
// was discovered in, and index is the index of the source file type.
|
|
|
|
func (_ac *DecodeMap )AddTarget (filePath string ,ifc interface{},sourceFileType string ,idx uint32 )bool {if _ac ._gf ==nil {_ac ._gf =make (map[string ]Target );_ac ._gd =make (map[*_dd .Relationships ]string );_ac ._ab =make (map[string ]struct{});_ac ._fbc =make (map[string ]int );};_gbb :=_d .Clean (filePath );if _ ,_e :=_ac ._ab [_gbb ];_e {return false ;};_ac ._ab [_gbb ]=struct{}{};_ac ._gf [_gbb ]=Target {Path :filePath ,Typ :sourceFileType ,Ifc :ifc ,Index :idx };return true ;};var _ga =[]byte {'\r','\n'};const XMLHeader ="\u003c\u003f\u0078\u006d\u006c\u0020\u0076e\u0072\u0073\u0069o\u006e\u003d\u00221\u002e\u0030\"\u0020\u0065\u006e\u0063\u006f\u0064i\u006eg=\u0022\u0055\u0054\u0046\u002d\u0038\u0022\u0020\u0073\u0074\u0061\u006e\u0064\u0061\u006c\u006f\u006e\u0065\u003d\u0022\u0079\u0065\u0073\u0022\u003f\u003e"+"\u000a";
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-08-31 22:58:25 +00:00
|
|
|
// Decode loops decoding targets registered with AddTarget and calling th
|
2020-10-12 13:59:12 +00:00
|
|
|
func (_df *DecodeMap )Decode (files []*_a .File )error {_gc :=1;for _gc > 0{for len (_df ._ggb )> 0{_cf :=_df ._ggb [len (_df ._ggb )-1];_df ._ggb =_df ._ggb [0:len (_df ._ggb )-1];_cbc :=_cf .Ifc .(*_dd .Relationships );for _ ,_bb :=range _cbc .Relationship {_be ,_ :=_df ._gd [_cbc ];_df ._b (_df ,_be +_bb .TargetAttr ,_bb .TypeAttr ,files ,_bb ,_cf );};};for _eb ,_cd :=range files {if _cd ==nil {continue ;};if _fbf ,_fc :=_df ._gf [_cd .Name ];_fc {delete (_df ._gf ,_cd .Name );if _egb :=Decode (_cd ,_fbf .Ifc );_egb !=nil {return _egb ;};files [_eb ]=nil ;if _ebd ,_aef :=_fbf .Ifc .(*_dd .Relationships );_aef {_df ._ggb =append (_df ._ggb ,_fbf );_deb ,_ :=_d .Split (_d .Clean (_cd .Name +"\u002f\u002e\u002e\u002f"));_df ._gd [_ebd ]=_deb ;_gc ++;};};};_gc --;};return nil ;};type Target struct{Path string ;Typ string ;Ifc interface{};Index uint32 ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// SetOnNewRelationshipFunc sets the function to be called when a new
|
|
|
|
// relationship has been discovered.
|
|
|
|
func (_ge *DecodeMap )SetOnNewRelationshipFunc (fn OnNewRelationshipFunc ){_ge ._b =fn };
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// DecodeMap is used to walk a tree of relationships, decoding files and passing
|
|
|
|
// control back to the document.
|
|
|
|
type DecodeMap struct{_gf map[string ]Target ;_gd map[*_dd .Relationships ]string ;_ggb []Target ;_b OnNewRelationshipFunc ;_ab map[string ]struct{};_fbc map[string ]int ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-08-31 22:58:25 +00:00
|
|
|
// RelationsPathFor returns the relations path for a given filename.
|
2020-10-12 13:59:12 +00:00
|
|
|
func RelationsPathFor (path string )string {_ef :=_ae .Split (path ,"\u002f");_aca :=_ae .Join (_ef [0:len (_ef )-1],"\u002f");_aaf :=_ef [len (_ef )-1];_aca +="\u002f_\u0072\u0065\u006c\u0073\u002f";_aaf +="\u002e\u0072\u0065l\u0073";return _aca +_aaf ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-10-12 13:59:12 +00:00
|
|
|
// AddFileFromDisk reads a file from internal storage and adds it at a given path to a zip file.
|
|
|
|
// TODO: Rename to AddFileFromStorage in next major version release (v2).
|
|
|
|
// NOTE: If disk storage cannot be used, memory storage can be used instead by calling memstore.SetAsStorage().
|
|
|
|
func AddFileFromDisk (z *_a .Writer ,zipPath ,storagePath string )error {_ce ,_faf :=z .Create (zipPath );if _faf !=nil {return _af .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_faf );};_fg ,_faf :=_dc .Open (storagePath );if _faf !=nil {return _af .Errorf ("e\u0072r\u006f\u0072\u0020\u006f\u0070\u0065\u006e\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",storagePath ,_faf );};defer _fg .Close ();_ ,_faf =_aa .Copy (_ce ,_fg );return _faf ;};func (_de *DecodeMap )RecordIndex (path string ,idx int ){_de ._fbc [path ]=idx };
|