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/
|
|
|
|
|
2022-06-27 19:44:23 +00:00
|
|
|
package zippkg ;import (_ce "archive/zip";_f "bytes";_e "encoding/xml";_ad "fmt";_fg "github.com/unidoc/unioffice";_gf "github.com/unidoc/unioffice/algo";_df "github.com/unidoc/unioffice/common/tempstorage";_fd "github.com/unidoc/unioffice/schema/soo/pkg/relationships";_a "io";_cc "path";_b "sort";_g "strings";_d "time";);
|
|
|
|
|
|
|
|
// MarshalXML creates a file inside of a zip and marshals an object as xml, prefixing it
|
|
|
|
// with a standard XML header.
|
|
|
|
func MarshalXML (z *_ce .Writer ,filename string ,v interface{})error {_gde :=&_ce .FileHeader {};_gde .Method =_ce .Deflate ;_gde .Name =filename ;_gde .SetModTime (_d .Now ());_gecf ,_gbe :=z .CreateHeader (_gde );if _gbe !=nil {return _ad .Errorf ("\u0063\u0072\u0065\u0061ti\u006e\u0067\u0020\u0025\u0073\u0020\u0069\u006e\u0020\u007a\u0069\u0070\u003a\u0020%\u0073",filename ,_gbe );};_ ,_gbe =_gecf .Write ([]byte (XMLHeader ));if _gbe !=nil {return _ad .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 ,_gbe );};if _gbe =_e .NewEncoder (SelfClosingWriter {_gecf }).Encode (v );_gbe !=nil {return _ad .Errorf ("\u006d\u0061\u0072\u0073\u0068\u0061\u006c\u0069\u006e\u0067\u0020\u0025s\u003a\u0020\u0025\u0073",filename ,_gbe );};_ ,_gbe =_gecf .Write (_bgf );return _gbe ;};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";
|
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.
|
2022-06-27 19:44:23 +00:00
|
|
|
func (_dfe *DecodeMap )AddTarget (filePath string ,ifc interface{},sourceFileType string ,idx uint32 )bool {if _dfe ._ec ==nil {_dfe ._ec =make (map[string ]Target );_dfe ._ae =make (map[*_fd .Relationships ]string );_dfe ._cef =make (map[string ]struct{});_dfe ._eg =make (map[string ]int );};_ag :=_cc .Clean (filePath );if _ ,_agf :=_dfe ._cef [_ag ];_agf {return false ;};_dfe ._cef [_ag ]=struct{}{};_dfe ._ec [_ag ]=Target {Path :filePath ,Typ :sourceFileType ,Ifc :ifc ,Index :idx };return true ;};
|
2022-02-25 19:20:45 +00:00
|
|
|
|
|
|
|
// SelfClosingWriter wraps a writer and replaces XML tags of the
|
|
|
|
// type <foo></foo> with <foo/>
|
2022-06-27 19:44:23 +00:00
|
|
|
type SelfClosingWriter struct{W _a .Writer ;};type Target struct{Path string ;Typ string ;Ifc interface{};Index uint32 ;};func MarshalXMLByTypeIndex (z *_ce .Writer ,dt _fg .DocType ,typ string ,idx int ,v interface{})error {_ga :=_fg .AbsoluteFilename (dt ,typ ,idx );return MarshalXML (z ,_ga ,v );};
|
2022-02-05 13:05:36 +00:00
|
|
|
|
2022-06-27 19:44:23 +00:00
|
|
|
// ExtractToDiskTmp extracts a zip file to a temporary file in a given path,
|
|
|
|
// returning the name of the file.
|
|
|
|
func ExtractToDiskTmp (f *_ce .File ,path string )(string ,error ){_gg ,_ea :=_df .TempFile (path ,"\u007a\u007a");if _ea !=nil {return "",_ea ;};defer _gg .Close ();_dcb ,_ea :=f .Open ();if _ea !=nil {return "",_ea ;};defer _dcb .Close ();_ ,_ea =_a .Copy (_gg ,_dcb );if _ea !=nil {return "",_ea ;};return _gg .Name (),nil ;};
|
2022-01-15 21:17:38 +00:00
|
|
|
|
2022-06-27 19:44:23 +00:00
|
|
|
// RelationsPathFor returns the relations path for a given filename.
|
|
|
|
func RelationsPathFor (path string )string {_dgg :=_g .Split (path ,"\u002f");_fgd :=_g .Join (_dgg [0:len (_dgg )-1],"\u002f");_cda :=_dgg [len (_dgg )-1];_fgd +="\u002f_\u0072\u0065\u006c\u0073\u002f";_cda +="\u002e\u0072\u0065l\u0073";return _fgd +_cda ;};
|
|
|
|
|
|
|
|
// SetOnNewRelationshipFunc sets the function to be called when a new
|
|
|
|
// relationship has been discovered.
|
|
|
|
func (_efb *DecodeMap )SetOnNewRelationshipFunc (fn OnNewRelationshipFunc ){_efb ._fc =fn };
|
2022-02-05 13:05:36 +00:00
|
|
|
|
2022-02-25 19:20:45 +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')
|
2022-06-27 19:44:23 +00:00
|
|
|
type OnNewRelationshipFunc func (_bg *DecodeMap ,_cd ,_cb string ,_ff []*_ce .File ,_ef *_fd .Relationship ,_bgb Target )error ;
|
2022-04-09 14:27:46 +00:00
|
|
|
|
2022-06-27 19:44:23 +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 *_ce .Writer ,zipPath ,storagePath string )error {_aa ,_dgge :=z .Create (zipPath );if _dgge !=nil {return _ad .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_dgge );};_dfb ,_dgge :=_df .Open (storagePath );if _dgge !=nil {return _ad .Errorf ("e\u0072r\u006f\u0072\u0020\u006f\u0070\u0065\u006e\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",storagePath ,_dgge );};defer _dfb .Close ();_ ,_dgge =_a .Copy (_aa ,_dfb );return _dgge ;};
|
2022-04-09 14:27:46 +00:00
|
|
|
|
2022-06-27 19:44:23 +00:00
|
|
|
// DecodeMap is used to walk a tree of relationships, decoding files and passing
|
|
|
|
// control back to the document.
|
|
|
|
type DecodeMap struct{_ec map[string ]Target ;_ae map[*_fd .Relationships ]string ;_da []Target ;_fc OnNewRelationshipFunc ;_cef map[string ]struct{};_eg map[string ]int ;};
|
2022-04-09 14:27:46 +00:00
|
|
|
|
2022-06-27 19:44:23 +00:00
|
|
|
// Decode loops decoding targets registered with AddTarget and calling th
|
|
|
|
func (_bf *DecodeMap )Decode (files []*_ce .File )error {_gd :=1;for _gd > 0{for len (_bf ._da )> 0{_gb :=_bf ._da [0];_bf ._da =_bf ._da [1:];_fe :=_gb .Ifc .(*_fd .Relationships );for _ ,_ba :=range _fe .Relationship {_eb ,_ :=_bf ._ae [_fe ];_bf ._fc (_bf ,_eb +_ba .TargetAttr ,_ba .TypeAttr ,files ,_ba ,_gb );};};for _ebg ,_dg :=range files {if _dg ==nil {continue ;};if _ac ,_cf :=_bf ._ec [_dg .Name ];_cf {delete (_bf ._ec ,_dg .Name );if _geg :=Decode (_dg ,_ac .Ifc );_geg !=nil {return _geg ;};files [_ebg ]=nil ;if _ebf ,_be :=_ac .Ifc .(*_fd .Relationships );_be {_bf ._da =append (_bf ._da ,_ac );_gbb ,_ :=_cc .Split (_cc .Clean (_dg .Name +"\u002f\u002e\u002e\u002f"));_bf ._ae [_ebf ]=_gbb ;_gd ++;};};};_gd --;};return nil ;};
|
2022-04-09 14:27:46 +00:00
|
|
|
|
2022-06-27 19:44:23 +00:00
|
|
|
// AddFileFromBytes takes a byte array and adds it at a given path to a zip file.
|
|
|
|
func AddFileFromBytes (z *_ce .Writer ,zipPath string ,data []byte )error {_dac ,_ecf :=z .Create (zipPath );if _ecf !=nil {return _ad .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_ecf );};_ ,_ecf =_a .Copy (_dac ,_f .NewReader (data ));return _ecf ;};func (_daf *DecodeMap )IndexFor (path string )int {return _daf ._eg [path ]};func MarshalXMLByType (z *_ce .Writer ,dt _fg .DocType ,typ string ,v interface{})error {_feb :=_fg .AbsoluteFilename (dt ,typ ,0);return MarshalXML (z ,_feb ,v );};var _bgf =[]byte {'\r','\n'};func (_ebb SelfClosingWriter )Write (b []byte )(int ,error ){_cg :=0;_gege :=0;for _bd :=0;_bd < len (b )-2;_bd ++{if b [_bd ]=='>'&&b [_bd +1]=='<'&&b [_bd +2]=='/'{_gbf :=[]byte {};_egc :=_bd ;for _af :=_bd ;_af >=0;_af --{if b [_af ]==' '{_egc =_af ;}else if b [_af ]=='<'{_gbf =b [_af +1:_egc ];break ;};};_bab :=[]byte {};for _ca :=_bd +3;_ca < len (b );_ca ++{if b [_ca ]=='>'{_bab =b [_bd +3:_ca ];break ;};};if !_f .Equal (_gbf ,_bab ){continue ;};_ecd ,_de :=_ebb .W .Write (b [_cg :_bd ]);if _de !=nil {return _gege +_ecd ,_de ;};_gege +=_ecd ;_ ,_de =_ebb .W .Write (_ffd );if _de !=nil {return _gege ,_de ;};_gege +=3;for _dgd :=_bd +2;_dgd < len (b )&&b [_dgd ]!='>';_dgd ++{_gege ++;_cg =_dgd +2;_bd =_cg ;};};};_gc ,_dda :=_ebb .W .Write (b [_cg :]);return _gc +_gege ,_dda ;};
|
2022-01-15 21:17:38 +00:00
|
|
|
|
2022-06-27 19:44:23 +00:00
|
|
|
// Decode unmarshals the content of a *zip.File as XML to a given destination.
|
|
|
|
func Decode (f *_ce .File ,dest interface{})error {_cfc ,_fgda :=f .Open ();if _fgda !=nil {return _ad .Errorf ("e\u0072r\u006f\u0072\u0020\u0072\u0065\u0061\u0064\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",f .Name ,_fgda );};defer _cfc .Close ();_acf :=_e .NewDecoder (_cfc );if _fga :=_acf .Decode (dest );_fga !=nil {return _ad .Errorf ("e\u0072\u0072\u006f\u0072 d\u0065c\u006f\u0064\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",f .Name ,_fga );};if _fcb ,_fee :=dest .(*_fd .Relationships );_fee {for _fcd ,_fa :=range _fcb .Relationship {switch _fa .TypeAttr {case _fg .OfficeDocumentTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .OfficeDocumentType ;case _fg .StylesTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .StylesType ;case _fg .ThemeTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .ThemeType ;case _fg .ControlTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .ControlType ;case _fg .SettingsTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .SettingsType ;case _fg .ImageTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .ImageType ;case _fg .CommentsTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .CommentsType ;case _fg .ThumbnailTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .ThumbnailType ;case _fg .DrawingTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .DrawingType ;case _fg .ChartTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .ChartType ;case _fg .ExtendedPropertiesTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .ExtendedPropertiesType ;case _fg .CustomXMLTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .CustomXMLType ;case _fg .WorksheetTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .WorksheetType ;case _fg .SharedStringsTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .SharedStringsType ;case _fg .TableTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .TableType ;case _fg .HeaderTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .HeaderType ;case _fg .FooterTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .FooterType ;case _fg .NumberingTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .NumberingType ;case _fg .FontTableTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .FontTableType ;case _fg .WebSettingsTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .WebSettingsType ;case _fg .FootNotesTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .FootNotesType ;case _fg .EndNotesTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .EndNotesType ;case _fg .SlideTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .SlideType ;case _fg .VMLDrawingTypeStrict :_fcb .Relationship [_fcd ].TypeAttr =_fg .VMLDrawingType ;};};_b .Slice (_fcb .Relationship ,func (_gec ,_bae int )bool {_gdb :=_fcb .Relationship [_gec ];_fdb :=_fcb .Relationship [_bae ];return _gf .NaturalLess (_gdb .IdAttr ,_fdb .IdAttr );});};return nil ;};var _ffd =[]byte {'/','>'};func (_dc *DecodeMap )RecordIndex (path string ,idx int ){_dc ._eg [path ]=idx };
|