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-01-04 16:11:39 +00:00
|
|
|
package zippkg ;import (_d "archive/zip";_ed "bytes";_e "encoding/xml";_a "fmt";_ge "github.com/unidoc/unioffice";_fe "github.com/unidoc/unioffice/algo";_bcd "github.com/unidoc/unioffice/common/tempstorage";_bc "github.com/unidoc/unioffice/schema/soo/pkg/relationships";_c "io";_gb "path";_g "sort";_b "strings";_fa "time";);
|
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.
|
2021-01-04 16:11:39 +00:00
|
|
|
func RelationsPathFor (path string )string {_bd :=_b .Split (path ,"\u002f");_gd :=_b .Join (_bd [0:len (_bd )-1],"\u002f");_daf :=_bd [len (_bd )-1];_gd +="\u002f_\u0072\u0065\u006c\u0073\u002f";_daf +="\u002e\u0072\u0065l\u0073";return _gd +_daf ;};
|
|
|
|
|
|
|
|
// Decode unmarshals the content of a *zip.File as XML to a given destination.
|
|
|
|
func Decode (f *_d .File ,dest interface{})error {_gfa ,_ad :=f .Open ();if _ad !=nil {return _a .Errorf ("e\u0072r\u006f\u0072\u0020\u0072\u0065\u0061\u0064\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",f .Name ,_ad );};defer _gfa .Close ();_edf :=_e .NewDecoder (_gfa );if _gg :=_edf .Decode (dest );_gg !=nil {return _a .Errorf ("e\u0072\u0072\u006f\u0072 d\u0065c\u006f\u0064\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",f .Name ,_gg );};if _aga ,_ac :=dest .(*_bc .Relationships );_ac {for _bfb ,_gcb :=range _aga .Relationship {switch _gcb .TypeAttr {case _ge .OfficeDocumentTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .OfficeDocumentType ;case _ge .StylesTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .StylesType ;case _ge .ThemeTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .ThemeType ;case _ge .SettingsTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .SettingsType ;case _ge .ImageTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .ImageType ;case _ge .CommentsTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .CommentsType ;case _ge .ThumbnailTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .ThumbnailType ;case _ge .DrawingTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .DrawingType ;case _ge .ChartTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .ChartType ;case _ge .ExtendedPropertiesTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .ExtendedPropertiesType ;case _ge .CustomXMLTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .CustomXMLType ;case _ge .WorksheetTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .WorksheetType ;case _ge .SharedStringsTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .SharedStringsType ;case _ge .TableTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .TableType ;case _ge .HeaderTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .HeaderType ;case _ge .FooterTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .FooterType ;case _ge .NumberingTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .NumberingType ;case _ge .FontTableTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .FontTableType ;case _ge .WebSettingsTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .WebSettingsType ;case _ge .FootNotesTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .FootNotesType ;case _ge .EndNotesTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .EndNotesType ;case _ge .SlideTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .SlideType ;case _ge .VMLDrawingTypeStrict :_aga .Relationship [_bfb ].TypeAttr =_ge .VMLDrawingType ;};};_g .Slice (_aga .Relationship ,func (_ebc ,_af int )bool {_gbg :=_aga .Relationship [_ebc ];_acd :=_aga .Relationship [_af ];return _fe .NaturalLess (_gbg .IdAttr ,_acd .IdAttr );});};return nil ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-12-17 22:07:08 +00:00
|
|
|
// ExtractToDiskTmp extracts a zip file to a temporary file in a given path,
|
|
|
|
// returning the name of the file.
|
2021-01-04 16:11:39 +00:00
|
|
|
func ExtractToDiskTmp (f *_d .File ,path string )(string ,error ){_aea ,_db :=_bcd .TempFile (path ,"\u007a\u007a");if _db !=nil {return "",_db ;};defer _aea .Close ();_cgd ,_db :=f .Open ();if _db !=nil {return "",_db ;};defer _cgd .Close ();_ ,_db =_c .Copy (_aea ,_cgd );if _db !=nil {return "",_db ;};return _aea .Name (),nil ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2021-01-04 16:11:39 +00:00
|
|
|
// AddFileFromBytes takes a byte array and adds it at a given path to a zip file.
|
|
|
|
func AddFileFromBytes (z *_d .Writer ,zipPath string ,data []byte )error {_fg ,_dc :=z .Create (zipPath );if _dc !=nil {return _a .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_dc );};_ ,_dc =_c .Copy (_fg ,_ed .NewReader (data ));return _dc ;};type Target struct{Path string ;Typ string ;Ifc interface{};Index uint32 ;};var _ddb =[]byte {'/','>'};
|
|
|
|
|
|
|
|
// MarshalXML creates a file inside of a zip and marshals an object as xml, prefixing it
|
|
|
|
// with a standard XML header.
|
|
|
|
func MarshalXML (z *_d .Writer ,filename string ,v interface{})error {_eba :=&_d .FileHeader {};_eba .Method =_d .Deflate ;_eba .Name =filename ;_eba .SetModTime (_fa .Now ());_adg ,_aae :=z .CreateHeader (_eba );if _aae !=nil {return _a .Errorf ("\u0063\u0072\u0065\u0061ti\u006e\u0067\u0020\u0025\u0073\u0020\u0069\u006e\u0020\u007a\u0069\u0070\u003a\u0020%\u0073",filename ,_aae );};_ ,_aae =_adg .Write ([]byte (XMLHeader ));if _aae !=nil {return _a .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 ,_aae );};if _aae =_e .NewEncoder (SelfClosingWriter {_adg }).Encode (v );_aae !=nil {return _a .Errorf ("\u006d\u0061\u0072\u0073\u0068\u0061\u006c\u0069\u006e\u0067\u0020\u0025s\u003a\u0020\u0025\u0073",filename ,_aae );};_ ,_aae =_adg .Write (_ff );return _aae ;};
|
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')
|
2021-01-04 16:11:39 +00:00
|
|
|
type OnNewRelationshipFunc func (_df *DecodeMap ,_ca ,_ef string ,_ag []*_d .File ,_cb *_bc .Relationship ,_cac Target )error ;func (_aa *DecodeMap )RecordIndex (path string ,idx int ){_aa ._gf [path ]=idx };func (_bcg SelfClosingWriter )Write (b []byte )(int ,error ){_gcd :=0;_afa :=0;for _ade :=0;_ade < len (b )-2;_ade ++{if b [_ade ]=='>'&&b [_ade +1]=='<'&&b [_ade +2]=='/'{_dde :=[]byte {};_bgd :=_ade ;for _agb :=_ade ;_agb >=0;_agb --{if b [_agb ]==' '{_bgd =_agb ;}else if b [_agb ]=='<'{_dde =b [_agb +1:_bgd ];break ;};};_dda :=[]byte {};for _ada :=_ade +3;_ada < len (b );_ada ++{if b [_ada ]=='>'{_dda =b [_ade +3:_ada ];break ;};};if !_ed .Equal (_dde ,_dda ){continue ;};_baf ,_de :=_bcg .W .Write (b [_gcd :_ade ]);if _de !=nil {return _afa +_baf ,_de ;};_afa +=_baf ;_ ,_de =_bcg .W .Write (_ddb );if _de !=nil {return _afa ,_de ;};_afa +=3;for _fef :=_ade +2;_fef < len (b )&&b [_fef ]!='>';_fef ++{_afa ++;_gcd =_fef +2;_ade =_gcd ;};};};_fd ,_gbd :=_bcg .W .Write (b [_gcd :]);return _fd +_afa ,_gbd ;};func MarshalXMLByTypeIndex (z *_d .Writer ,dt _ge .DocType ,typ string ,idx int ,v interface{})error {_ea :=_ge .AbsoluteFilename (dt ,typ ,idx );return MarshalXML (z ,_ea ,v );};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2021-01-04 16:11:39 +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 *_d .Writer ,zipPath ,storagePath string )error {_adc ,_fcb :=z .Create (zipPath );if _fcb !=nil {return _a .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_fcb );};_bfd ,_fcb :=_bcd .Open (storagePath );if _fcb !=nil {return _a .Errorf ("e\u0072r\u006f\u0072\u0020\u006f\u0070\u0065\u006e\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",storagePath ,_fcb );};defer _bfd .Close ();_ ,_fcb =_c .Copy (_adc ,_bfd );return _fcb ;};
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-12-17 22:07:08 +00:00
|
|
|
// SetOnNewRelationshipFunc sets the function to be called when a new
|
|
|
|
// relationship has been discovered.
|
2021-01-04 16:11:39 +00:00
|
|
|
func (_dd *DecodeMap )SetOnNewRelationshipFunc (fn OnNewRelationshipFunc ){_dd ._be =fn };
|
2020-08-23 14:15:53 +00:00
|
|
|
|
2020-12-17 22:07:08 +00:00
|
|
|
// SelfClosingWriter wraps a writer and replaces XML tags of the
|
|
|
|
// type <foo></foo> with <foo/>
|
2021-01-04 16:11:39 +00:00
|
|
|
type SelfClosingWriter struct{W _c .Writer ;};
|
2020-12-17 22:07:08 +00:00
|
|
|
|
|
|
|
// DecodeMap is used to walk a tree of relationships, decoding files and passing
|
|
|
|
// control back to the document.
|
2021-01-04 16:11:39 +00:00
|
|
|
type DecodeMap struct{_dff map[string ]Target ;_efc map[*_bc .Relationships ]string ;_ee []Target ;_be OnNewRelationshipFunc ;_da map[string ]struct{};_gf map[string ]int ;};var _ff =[]byte {'\r','\n'};func (_aad *DecodeMap )IndexFor (path string )int {return _aad ._gf [path ]};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";
|
|
|
|
|
|
|
|
// 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 (_fc *DecodeMap )AddTarget (filePath string ,ifc interface{},sourceFileType string ,idx uint32 )bool {if _fc ._dff ==nil {_fc ._dff =make (map[string ]Target );_fc ._efc =make (map[*_bc .Relationships ]string );_fc ._da =make (map[string ]struct{});_fc ._gf =make (map[string ]int );};_eea :=_gb .Clean (filePath );if _ ,_ba :=_fc ._da [_eea ];_ba {return false ;};_fc ._da [_eea ]=struct{}{};_fc ._dff [_eea ]=Target {Path :filePath ,Typ :sourceFileType ,Ifc :ifc ,Index :idx };return true ;};
|
|
|
|
|
|
|
|
// Decode loops decoding targets registered with AddTarget and calling th
|
|
|
|
func (_eb *DecodeMap )Decode (files []*_d .File )error {_ec :=1;for _ec > 0{for len (_eb ._ee )> 0{_edg :=_eb ._ee [len (_eb ._ee )-1];_eb ._ee =_eb ._ee [0:len (_eb ._ee )-1];_gc :=_edg .Ifc .(*_bc .Relationships );for _ ,_beg :=range _gc .Relationship {_bag ,_ :=_eb ._efc [_gc ];_eb ._be (_eb ,_bag +_beg .TargetAttr ,_beg .TypeAttr ,files ,_beg ,_edg );};};for _cg ,_caf :=range files {if _caf ==nil {continue ;};if _ae ,_gbc :=_eb ._dff [_caf .Name ];_gbc {delete (_eb ._dff ,_caf .Name );if _gfg :=Decode (_caf ,_ae .Ifc );_gfg !=nil {return _gfg ;};files [_cg ]=nil ;if _bab ,_feg :=_ae .Ifc .(*_bc .Relationships );_feg {_eb ._ee =append (_eb ._ee ,_ae );_cd ,_ :=_gb .Split (_gb .Clean (_caf .Name +"\u002f\u002e\u002e\u002f"));_eb ._efc [_bab ]=_cd ;_ec ++;};};};_ec --;};return nil ;};func MarshalXMLByType (z *_d .Writer ,dt _ge .DocType ,typ string ,v interface{})error {_cacc :=_ge .AbsoluteFilename (dt ,typ ,0);return MarshalXML (z ,_cacc ,v );};
|