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/
|
|
|
|
|
2021-09-22 16:41:01 +00:00
|
|
|
package zippkg ;import (_e "archive/zip";_dd "bytes";_ec "encoding/xml";_df "fmt";_cdc "github.com/unidoc/unioffice";_cb "github.com/unidoc/unioffice/algo";_cd "github.com/unidoc/unioffice/common/tempstorage";_c "github.com/unidoc/unioffice/schema/soo/pkg/relationships";_a "io";_eb "path";_d "sort";_fb "strings";_fd "time";);
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2021-09-22 16:41:01 +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 *_e .Writer ,zipPath ,storagePath string )error {_fg ,_efa :=z .Create (zipPath );if _efa !=nil {return _df .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_efa );};_bgf ,_efa :=_cd .Open (storagePath );if _efa !=nil {return _df .Errorf ("e\u0072r\u006f\u0072\u0020\u006f\u0070\u0065\u006e\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",storagePath ,_efa );};defer _bgf .Close ();_ ,_efa =_a .Copy (_fg ,_bgf );return _efa ;};func (_ag *DecodeMap )RecordIndex (path string ,idx int ){_ag ._ff [path ]=idx };
|
2021-03-16 20:51:18 +00:00
|
|
|
|
2021-09-22 16:41:01 +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')
|
|
|
|
type OnNewRelationshipFunc func (_dc *DecodeMap ,_b ,_g string ,_fe []*_e .File ,_bg *_c .Relationship ,_cg Target )error ;
|
|
|
|
|
|
|
|
// Decode loops decoding targets registered with AddTarget and calling th
|
|
|
|
func (_gfd *DecodeMap )Decode (files []*_e .File )error {_ef :=1;for _ef > 0{for len (_gfd ._fdf )> 0{_cgc :=_gfd ._fdf [0];_gfd ._fdf =_gfd ._fdf [1:];_bb :=_cgc .Ifc .(*_c .Relationships );for _ ,_ga :=range _bb .Relationship {_ggc ,_ :=_gfd ._da [_bb ];_gfd ._be (_gfd ,_ggc +_ga .TargetAttr ,_ga .TypeAttr ,files ,_ga ,_cgc );};};for _ca ,_aea :=range files {if _aea ==nil {continue ;};if _fa ,_ddg :=_gfd ._ae [_aea .Name ];_ddg {delete (_gfd ._ae ,_aea .Name );if _bgg :=Decode (_aea ,_fa .Ifc );_bgg !=nil {return _bgg ;};files [_ca ]=nil ;if _ebe ,_gaa :=_fa .Ifc .(*_c .Relationships );_gaa {_gfd ._fdf =append (_gfd ._fdf ,_fa );_bc ,_ :=_eb .Split (_eb .Clean (_aea .Name +"\u002f\u002e\u002e\u002f"));_gfd ._da [_ebe ]=_bc ;_ef ++;};};};_ef --;};return nil ;};func (_dca SelfClosingWriter )Write (b []byte )(int ,error ){_gab :=0;_bbe :=0;for _gcf :=0;_gcf < len (b )-2;_gcf ++{if b [_gcf ]=='>'&&b [_gcf +1]=='<'&&b [_gcf +2]=='/'{_gacc :=[]byte {};_dgg :=_gcf ;for _fgg :=_gcf ;_fgg >=0;_fgg --{if b [_fgg ]==' '{_dgg =_fgg ;}else if b [_fgg ]=='<'{_gacc =b [_fgg +1:_dgg ];break ;};};_aa :=[]byte {};for _de :=_gcf +3;_de < len (b );_de ++{if b [_de ]=='>'{_aa =b [_gcf +3:_de ];break ;};};if !_dd .Equal (_gacc ,_aa ){continue ;};_agd ,_ede :=_dca .W .Write (b [_gab :_gcf ]);if _ede !=nil {return _bbe +_agd ,_ede ;};_bbe +=_agd ;_ ,_ede =_dca .W .Write (_dfd );if _ede !=nil {return _bbe ,_ede ;};_bbe +=3;for _dac :=_gcf +2;_dac < len (b )&&b [_dac ]!='>';_dac ++{_bbe ++;_gab =_dac +2;_gcf =_gab ;};};};_eea ,_gfdb :=_dca .W .Write (b [_gab :]);return _eea +_bbe ,_gfdb ;};
|
|
|
|
|
|
|
|
// Decode unmarshals the content of a *zip.File as XML to a given destination.
|
|
|
|
func Decode (f *_e .File ,dest interface{})error {_ed ,_ggg :=f .Open ();if _ggg !=nil {return _df .Errorf ("e\u0072r\u006f\u0072\u0020\u0072\u0065\u0061\u0064\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",f .Name ,_ggg );};defer _ed .Close ();_fc :=_ec .NewDecoder (_ed );if _gec :=_fc .Decode (dest );_gec !=nil {return _df .Errorf ("e\u0072\u0072\u006f\u0072 d\u0065c\u006f\u0064\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",f .Name ,_gec );};if _db ,_aeg :=dest .(*_c .Relationships );_aeg {for _aega ,_eg :=range _db .Relationship {switch _eg .TypeAttr {case _cdc .OfficeDocumentTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .OfficeDocumentType ;case _cdc .StylesTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .StylesType ;case _cdc .ThemeTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .ThemeType ;case _cdc .ControlTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .ControlType ;case _cdc .SettingsTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .SettingsType ;case _cdc .ImageTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .ImageType ;case _cdc .CommentsTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .CommentsType ;case _cdc .ThumbnailTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .ThumbnailType ;case _cdc .DrawingTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .DrawingType ;case _cdc .ChartTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .ChartType ;case _cdc .ExtendedPropertiesTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .ExtendedPropertiesType ;case _cdc .CustomXMLTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .CustomXMLType ;case _cdc .WorksheetTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .WorksheetType ;case _cdc .SharedStringsTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .SharedStringsType ;case _cdc .TableTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .TableType ;case _cdc .HeaderTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .HeaderType ;case _cdc .FooterTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .FooterType ;case _cdc .NumberingTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .NumberingType ;case _cdc .FontTableTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .FontTableType ;case _cdc .WebSettingsTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .WebSettingsType ;case _cdc .FootNotesTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .FootNotesType ;case _cdc .EndNotesTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .EndNotesType ;case _cdc .SlideTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .SlideType ;case _cdc .VMLDrawingTypeStrict :_db .Relationship [_aega ].TypeAttr =_cdc .VMLDrawingType ;};};_d .Slice (_db .Relationship ,func (_ad ,_gc int )bool {_cccb :=_db .Relationship [_ad ];_caf :=_db .Relationship [_gc ];return _cb .NaturalLess (_cccb .IdAttr ,_caf .IdAttr );});};return nil ;};func MarshalXMLByType (z *_e .Writer ,dt _cdc .DocType ,typ string ,v interface{})error {_fac :=_cdc .AbsoluteFilename (dt ,typ ,0);return MarshalXML (z ,_fac ,v );};func MarshalXMLByTypeIndex (z *_e .Writer ,dt _cdc .DocType ,typ string ,idx int ,v interface{})error {_ddgb :=_cdc .AbsoluteFilename (dt ,typ ,idx );return MarshalXML (z ,_ddgb ,v );};
|
2021-07-30 17:03:26 +00:00
|
|
|
|
|
|
|
// SelfClosingWriter wraps a writer and replaces XML tags of the
|
|
|
|
// type <foo></foo> with <foo/>
|
2021-09-22 16:41:01 +00:00
|
|
|
type SelfClosingWriter struct{W _a .Writer ;};
|
|
|
|
|
|
|
|
// AddFileFromBytes takes a byte array and adds it at a given path to a zip file.
|
|
|
|
func AddFileFromBytes (z *_e .Writer ,zipPath string ,data []byte )error {_cafa ,_ade :=z .Create (zipPath );if _ade !=nil {return _df .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_ade );};_ ,_ade =_a .Copy (_cafa ,_dd .NewReader (data ));return _ade ;};
|
2021-05-31 16:22:30 +00:00
|
|
|
|
2021-08-23 20:44:48 +00:00
|
|
|
// SetOnNewRelationshipFunc sets the function to be called when a new
|
|
|
|
// relationship has been discovered.
|
2021-09-22 16:41:01 +00:00
|
|
|
func (_gf *DecodeMap )SetOnNewRelationshipFunc (fn OnNewRelationshipFunc ){_gf ._be =fn };type Target struct{Path string ;Typ string ;Ifc interface{};Index uint32 ;};func (_ac *DecodeMap )IndexFor (path string )int {return _ac ._ff [path ]};var _dfd =[]byte {'/','>'};
|
2021-08-23 20:44:48 +00:00
|
|
|
|
|
|
|
// ExtractToDiskTmp extracts a zip file to a temporary file in a given path,
|
|
|
|
// returning the name of the file.
|
2021-09-22 16:41:01 +00:00
|
|
|
func ExtractToDiskTmp (f *_e .File ,path string )(string ,error ){_efe ,_cdg :=_cd .TempFile (path ,"\u007a\u007a");if _cdg !=nil {return "",_cdg ;};defer _efe .Close ();_adf ,_cdg :=f .Open ();if _cdg !=nil {return "",_cdg ;};defer _adf .Close ();_ ,_cdg =_a .Copy (_efe ,_adf );if _cdg !=nil {return "",_cdg ;};return _efe .Name (),nil ;};
|
2021-08-23 20:44:48 +00:00
|
|
|
|
2021-09-22 16:41:01 +00:00
|
|
|
// RelationsPathFor returns the relations path for a given filename.
|
|
|
|
func RelationsPathFor (path string )string {_ccc :=_fb .Split (path ,"\u002f");_ee :=_fb .Join (_ccc [0:len (_ccc )-1],"\u002f");_ffe :=_ccc [len (_ccc )-1];_ee +="\u002f_\u0072\u0065\u006c\u0073\u002f";_ffe +="\u002e\u0072\u0065l\u0073";return _ee +_ffe ;};
|
2021-07-30 17:03:26 +00:00
|
|
|
|
2021-08-23 20:44:48 +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.
|
2021-09-22 16:41:01 +00:00
|
|
|
func (_gg *DecodeMap )AddTarget (filePath string ,ifc interface{},sourceFileType string ,idx uint32 )bool {if _gg ._ae ==nil {_gg ._ae =make (map[string ]Target );_gg ._da =make (map[*_c .Relationships ]string );_gg ._dfe =make (map[string ]struct{});_gg ._ff =make (map[string ]int );};_fdff :=_eb .Clean (filePath );if _ ,_gfe :=_gg ._dfe [_fdff ];_gfe {return false ;};_gg ._dfe [_fdff ]=struct{}{};_gg ._ae [_fdff ]=Target {Path :filePath ,Typ :sourceFileType ,Ifc :ifc ,Index :idx };return true ;};
|
2021-07-30 17:03:26 +00:00
|
|
|
|
2021-09-22 16:41:01 +00:00
|
|
|
// DecodeMap is used to walk a tree of relationships, decoding files and passing
|
|
|
|
// control back to the document.
|
|
|
|
type DecodeMap struct{_ae map[string ]Target ;_da map[*_c .Relationships ]string ;_fdf []Target ;_be OnNewRelationshipFunc ;_dfe map[string ]struct{};_ff map[string ]int ;};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";var _dag =[]byte {'\r','\n'};
|
2021-07-30 17:03:26 +00:00
|
|
|
|
2021-09-22 16:41:01 +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 *_e .Writer ,filename string ,v interface{})error {_dba :=&_e .FileHeader {};_dba .Method =_e .Deflate ;_dba .Name =filename ;_dba .SetModTime (_fd .Now ());_fab ,_aef :=z .CreateHeader (_dba );if _aef !=nil {return _df .Errorf ("\u0063\u0072\u0065\u0061ti\u006e\u0067\u0020\u0025\u0073\u0020\u0069\u006e\u0020\u007a\u0069\u0070\u003a\u0020%\u0073",filename ,_aef );};_ ,_aef =_fab .Write ([]byte (XMLHeader ));if _aef !=nil {return _df .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 ,_aef );};if _aef =_ec .NewEncoder (SelfClosingWriter {_fab }).Encode (v );_aef !=nil {return _df .Errorf ("\u006d\u0061\u0072\u0073\u0068\u0061\u006c\u0069\u006e\u0067\u0020\u0025s\u003a\u0020\u0025\u0073",filename ,_aef );};_ ,_aef =_fab .Write (_dag );return _aef ;};
|