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-11-09 01:00:18 +00:00
|
|
|
package zippkg ;import (_f "archive/zip";_gd "bytes";_ggb "encoding/xml";_e "fmt";_d "github.com/unidoc/unioffice";_fd "github.com/unidoc/unioffice/algo";_aef "github.com/unidoc/unioffice/common/tempstorage";_ae "github.com/unidoc/unioffice/schema/soo/pkg/relationships";_b "io";_aa "path";_a "sort";_c "strings";_gg "time";);
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +00:00
|
|
|
// DecodeMap is used to walk a tree of relationships, decoding files and passing
|
|
|
|
// control back to the document.
|
|
|
|
type DecodeMap struct{_acc map[string ]Target ;_dc map[*_ae .Relationships ]string ;_gb []Target ;_ef OnNewRelationshipFunc ;_fc map[string ]struct{};_ga map[string ]int ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +00:00
|
|
|
// RelationsPathFor returns the relations path for a given filename.
|
|
|
|
func RelationsPathFor (path string )string {_bb :=_c .Split (path ,"\u002f");_aab :=_c .Join (_bb [0:len (_bb )-1],"\u002f");_bdf :=_bb [len (_bb )-1];_aab +="\u002f_\u0072\u0065\u006c\u0073\u002f";_bdf +="\u002e\u0072\u0065l\u0073";return _aab +_bdf ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +00:00
|
|
|
// SetOnNewRelationshipFunc sets the function to be called when a new
|
|
|
|
// relationship has been discovered.
|
|
|
|
func (_fgf *DecodeMap )SetOnNewRelationshipFunc (fn OnNewRelationshipFunc ){_fgf ._ef =fn };
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +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 (_aaa *DecodeMap )AddTarget (filePath string ,ifc interface{},sourceFileType string ,idx uint32 )bool {if _aaa ._acc ==nil {_aaa ._acc =make (map[string ]Target );_aaa ._dc =make (map[*_ae .Relationships ]string );_aaa ._fc =make (map[string ]struct{});_aaa ._ga =make (map[string ]int );};_ab :=_aa .Clean (filePath );if _ ,_ce :=_aaa ._fc [_ab ];_ce {return false ;};_aaa ._fc [_ab ]=struct{}{};_aaa ._acc [_ab ]=Target {Path :filePath ,Typ :sourceFileType ,Ifc :ifc ,Index :idx };return true ;};func (_fe *DecodeMap )RecordIndex (path string ,idx int ){_fe ._ga [path ]=idx };type Target struct{Path string ;Typ string ;Ifc interface{};Index uint32 ;};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
|
|
|
|
|
|
|
// 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-11-09 01:00:18 +00:00
|
|
|
type OnNewRelationshipFunc func (_aea *DecodeMap ,_fg ,_fa string ,_bd []*_f .File ,_ac *_ae .Relationship ,_cb Target )error ;
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +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 *_f .Writer ,zipPath ,storagePath string )error {_ad ,_cgd :=z .Create (zipPath );if _cgd !=nil {return _e .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_cgd );};_efg ,_cgd :=_aef .Open (storagePath );if _cgd !=nil {return _e .Errorf ("e\u0072r\u006f\u0072\u0020\u006f\u0070\u0065\u006e\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",storagePath ,_cgd );};defer _efg .Close ();_ ,_cgd =_b .Copy (_ad ,_efg );return _cgd ;};var _cfa =[]byte {'/','>'};
|
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-11-09 01:00:18 +00:00
|
|
|
func (_aed *DecodeMap )Decode (files []*_f .File )error {_fba :=1;for _fba > 0{for len (_aed ._gb )> 0{_gbc :=_aed ._gb [len (_aed ._gb )-1];_aed ._gb =_aed ._gb [0:len (_aed ._gb )-1];_fec :=_gbc .Ifc .(*_ae .Relationships );for _ ,_ec :=range _fec .Relationship {_gdf ,_ :=_aed ._dc [_fec ];_aed ._ef (_aed ,_gdf +_ec .TargetAttr ,_ec .TypeAttr ,files ,_ec ,_gbc );};};for _bf ,_cg :=range files {if _cg ==nil {continue ;};if _acf ,_dcg :=_aed ._acc [_cg .Name ];_dcg {delete (_aed ._acc ,_cg .Name );if _df :=Decode (_cg ,_acf .Ifc );_df !=nil {return _df ;};files [_bf ]=nil ;if _gc ,_ff :=_acf .Ifc .(*_ae .Relationships );_ff {_aed ._gb =append (_aed ._gb ,_acf );_eb ,_ :=_aa .Split (_aa .Clean (_cg .Name +"\u002f\u002e\u002e\u002f"));_aed ._dc [_gc ]=_eb ;_fba ++;};};};_fba --;};return nil ;};func MarshalXMLByType (z *_f .Writer ,dt _d .DocType ,typ string ,v interface{})error {_bad :=_d .AbsoluteFilename (dt ,typ ,0);return MarshalXML (z ,_bad ,v );};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +00:00
|
|
|
// SelfClosingWriter wraps a writer and replaces XML tags of the
|
|
|
|
// type <foo></foo> with <foo/>
|
|
|
|
type SelfClosingWriter struct{W _b .Writer ;};var _acb =[]byte {'\r','\n'};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +00:00
|
|
|
// Decode unmarshals the content of a *zip.File as XML to a given destination.
|
|
|
|
func Decode (f *_f .File ,dest interface{})error {_cd ,_ebc :=f .Open ();if _ebc !=nil {return _e .Errorf ("e\u0072r\u006f\u0072\u0020\u0072\u0065\u0061\u0064\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",f .Name ,_ebc );};defer _cd .Close ();_fbag :=_ggb .NewDecoder (_cd );if _ge :=_fbag .Decode (dest );_ge !=nil {return _e .Errorf ("e\u0072\u0072\u006f\u0072 d\u0065c\u006f\u0064\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",f .Name ,_ge );};if _ece ,_bgd :=dest .(*_ae .Relationships );_bgd {for _bbg ,_fbf :=range _ece .Relationship {switch _fbf .TypeAttr {case _d .OfficeDocumentTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .OfficeDocumentType ;case _d .StylesTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .StylesType ;case _d .ThemeTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .ThemeType ;case _d .SettingsTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .SettingsType ;case _d .ImageTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .ImageType ;case _d .CommentsTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .CommentsType ;case _d .ThumbnailTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .ThumbnailType ;case _d .DrawingTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .DrawingType ;case _d .ChartTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .ChartType ;case _d .ExtendedPropertiesTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .ExtendedPropertiesType ;case _d .CustomXMLTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .CustomXMLType ;case _d .WorksheetTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .WorksheetType ;case _d .SharedStringsTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .SharedStringsType ;case _d .TableTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .TableType ;case _d .HeaderTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .HeaderType ;case _d .FooterTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .FooterType ;case _d .NumberingTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .NumberingType ;case _d .FontTableTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .FontTableType ;case _d .WebSettingsTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .WebSettingsType ;case _d .FootNotesTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .FootNotesType ;case _d .EndNotesTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .EndNotesType ;case _d .SlideTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .SlideType ;case _d .VMLDrawingTypeStrict :_ece .Relationship [_bbg ].TypeAttr =_d .VMLDrawingType ;};};_a .Slice (_ece .Relationship ,func (_bbf ,_ed int )bool {_dg :=_ece .Relationship [_bbf ];_ee :=_ece .Relationship [_ed ];return _fd .NaturalLess (_dg .IdAttr ,_ee .IdAttr );});};return nil ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +00:00
|
|
|
// AddFileFromBytes takes a byte array and adds it at a given path to a zip file.
|
|
|
|
func AddFileFromBytes (z *_f .Writer ,zipPath string ,data []byte )error {_adb ,_ba :=z .Create (zipPath );if _ba !=nil {return _e .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_ba );};_ ,_ba =_b .Copy (_adb ,_gd .NewReader (data ));return _ba ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-11-09 01:00:18 +00:00
|
|
|
// ExtractToDiskTmp extracts a zip file to a temporary file in a given path,
|
|
|
|
// returning the name of the file.
|
|
|
|
func ExtractToDiskTmp (f *_f .File ,path string )(string ,error ){_dbf ,_be :=_aef .TempFile (path ,"\u007a\u007a");if _be !=nil {return "",_be ;};defer _dbf .Close ();_bdc ,_be :=f .Open ();if _be !=nil {return "",_be ;};defer _bdc .Close ();_ ,_be =_b .Copy (_dbf ,_bdc );if _be !=nil {return "",_be ;};return _dbf .Name (),nil ;};func (_fb *DecodeMap )IndexFor (path string )int {return _fb ._ga [path ]};func (_bc SelfClosingWriter )Write (b []byte )(int ,error ){_aec :=0;_dfa :=0;for _ebg :=0;_ebg < len (b )-2;_ebg ++{if b [_ebg ]=='>'&&b [_ebg +1]=='<'&&b [_ebg +2]=='/'{_aeg :=[]byte {};_bgf :=_ebg ;for _fecf :=_ebg ;_fecf >=0;_fecf --{if b [_fecf ]==' '{_bgf =_fecf ;}else if b [_fecf ]=='<'{_aeg =b [_fecf +1:_bgf ];break ;};};_ea :=[]byte {};for _eba :=_ebg +3;_eba < len (b );_eba ++{if b [_eba ]=='>'{_ea =b [_ebg +3:_eba ];break ;};};if !_gd .Equal (_aeg ,_ea ){continue ;};_gcg ,_fdd :=_bc .W .Write (b [_aec :_ebg ]);if _fdd !=nil {return _dfa +_gcg ,_fdd ;};_dfa +=_gcg ;_ ,_fdd =_bc .W .Write (_cfa );if _fdd !=nil {return _dfa ,_fdd ;};_dfa +=3;for _acbf :=_ebg +2;_acbf < len (b )&&b [_acbf ]!='>';_acbf ++{_dfa ++;_aec =_acbf +2;_ebg =_aec ;};};};_cbf ,_gae :=_bc .W .Write (b [_aec :]);return _cbf +_dfa ,_gae ;};func MarshalXMLByTypeIndex (z *_f .Writer ,dt _d .DocType ,typ string ,idx int ,v interface{})error {_efa :=_d .AbsoluteFilename (dt ,typ ,idx );return MarshalXML (z ,_efa ,v );};
|
|
|
|
|
|
|
|
// MarshalXML creates a file inside of a zip and marshals an object as xml, prefixing it
|
|
|
|
// with a standard XML header.
|
|
|
|
func MarshalXML (z *_f .Writer ,filename string ,v interface{})error {_fgb :=&_f .FileHeader {};_fgb .Method =_f .Deflate ;_fgb .Name =filename ;_fgb .SetModTime (_gg .Now ());_af ,_cbb :=z .CreateHeader (_fgb );if _cbb !=nil {return _e .Errorf ("\u0063\u0072\u0065\u0061ti\u006e\u0067\u0020\u0025\u0073\u0020\u0069\u006e\u0020\u007a\u0069\u0070\u003a\u0020%\u0073",filename ,_cbb );};_ ,_cbb =_af .Write ([]byte (XMLHeader ));if _cbb !=nil {return _e .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 ,_cbb );};if _cbb =_ggb .NewEncoder (SelfClosingWriter {_af }).Encode (v );_cbb !=nil {return _e .Errorf ("\u006d\u0061\u0072\u0073\u0068\u0061\u006c\u0069\u006e\u0067\u0020\u0025s\u003a\u0020\u0025\u0073",filename ,_cbb );};_ ,_cbb =_af .Write (_acb );return _cbb ;};
|