unioffice/zippkg/zippkg.go
2022-01-15 21:17:38 +00:00

70 lines
11 KiB
Go

//
// 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/
package zippkg ;import (_af "archive/zip";_ab "bytes";_bf "encoding/xml";_e "fmt";_ce "github.com/unidoc/unioffice";_cd "github.com/unidoc/unioffice/algo";_bc "github.com/unidoc/unioffice/common/tempstorage";_dg "github.com/unidoc/unioffice/schema/soo/pkg/relationships";_fg "io";_c "path";_d "sort";_b "strings";_f "time";);func (_cda *DecodeMap )IndexFor (path string )int {return _cda ._ee [path ]};
// 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 *_af .Writer ,zipPath ,storagePath string )error {_gdg ,_ecd :=z .Create (zipPath );if _ecd !=nil {return _e .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_ecd );};_ecdg ,_ecd :=_bc .Open (storagePath );if _ecd !=nil {return _e .Errorf ("e\u0072r\u006f\u0072\u0020\u006f\u0070\u0065\u006e\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",storagePath ,_ecd );};defer _ecdg .Close ();_ ,_ecd =_fg .Copy (_gdg ,_ecdg );return _ecd ;};
// Decode loops decoding targets registered with AddTarget and calling th
func (_gb *DecodeMap )Decode (files []*_af .File )error {_gbf :=1;for _gbf > 0{for len (_gb ._df )> 0{_bfd :=_gb ._df [0];_gb ._df =_gb ._df [1:];_dfe :=_bfd .Ifc .(*_dg .Relationships );for _ ,_ba :=range _dfe .Relationship {_cc ,_ :=_gb ._bfa [_dfe ];_gb ._abg (_gb ,_cc +_ba .TargetAttr ,_ba .TypeAttr ,files ,_ba ,_bfd );};};for _fb ,_bcg :=range files {if _bcg ==nil {continue ;};if _eg ,_abf :=_gb ._fe [_bcg .Name ];_abf {delete (_gb ._fe ,_bcg .Name );if _gdc :=Decode (_bcg ,_eg .Ifc );_gdc !=nil {return _gdc ;};files [_fb ]=nil ;if _bag ,_ga :=_eg .Ifc .(*_dg .Relationships );_ga {_gb ._df =append (_gb ._df ,_eg );_eed ,_ :=_c .Split (_c .Clean (_bcg .Name +"\u002f\u002e\u002e\u002f"));_gb ._bfa [_bag ]=_eed ;_gbf ++;};};};_gbf --;};return nil ;};
// 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 (_ef *DecodeMap ,_ec ,_eb string ,_bd []*_af .File ,_fge *_dg .Relationship ,_g Target )error ;
// Decode unmarshals the content of a *zip.File as XML to a given destination.
func Decode (f *_af .File ,dest interface{})error {_dfeg ,_cca :=f .Open ();if _cca !=nil {return _e .Errorf ("e\u0072r\u006f\u0072\u0020\u0072\u0065\u0061\u0064\u0069n\u0067\u0020\u0025\u0073: \u0025\u0073",f .Name ,_cca );};defer _dfeg .Close ();_cg :=_bf .NewDecoder (_dfeg );if _fgc :=_cg .Decode (dest );_fgc !=nil {return _e .Errorf ("e\u0072\u0072\u006f\u0072 d\u0065c\u006f\u0064\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",f .Name ,_fgc );};if _dgbg ,_bfc :=dest .(*_dg .Relationships );_bfc {for _ff ,_eff :=range _dgbg .Relationship {switch _eff .TypeAttr {case _ce .OfficeDocumentTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .OfficeDocumentType ;case _ce .StylesTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .StylesType ;case _ce .ThemeTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .ThemeType ;case _ce .ControlTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .ControlType ;case _ce .SettingsTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .SettingsType ;case _ce .ImageTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .ImageType ;case _ce .CommentsTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .CommentsType ;case _ce .ThumbnailTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .ThumbnailType ;case _ce .DrawingTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .DrawingType ;case _ce .ChartTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .ChartType ;case _ce .ExtendedPropertiesTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .ExtendedPropertiesType ;case _ce .CustomXMLTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .CustomXMLType ;case _ce .WorksheetTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .WorksheetType ;case _ce .SharedStringsTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .SharedStringsType ;case _ce .TableTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .TableType ;case _ce .HeaderTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .HeaderType ;case _ce .FooterTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .FooterType ;case _ce .NumberingTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .NumberingType ;case _ce .FontTableTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .FontTableType ;case _ce .WebSettingsTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .WebSettingsType ;case _ce .FootNotesTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .FootNotesType ;case _ce .EndNotesTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .EndNotesType ;case _ce .SlideTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .SlideType ;case _ce .VMLDrawingTypeStrict :_dgbg .Relationship [_ff ].TypeAttr =_ce .VMLDrawingType ;};};_d .Slice (_dgbg .Relationship ,func (_bg ,_cfg int )bool {_baga :=_dgbg .Relationship [_bg ];_da :=_dgbg .Relationship [_cfg ];return _cd .NaturalLess (_baga .IdAttr ,_da .IdAttr );});};return nil ;};
// SelfClosingWriter wraps a writer and replaces XML tags of the
// type <foo></foo> with <foo/>
type SelfClosingWriter struct{W _fg .Writer ;};func MarshalXMLByTypeIndex (z *_af .Writer ,dt _ce .DocType ,typ string ,idx int ,v interface{})error {_cec :=_ce .AbsoluteFilename (dt ,typ ,idx );return MarshalXML (z ,_cec ,v );};
// SetOnNewRelationshipFunc sets the function to be called when a new
// relationship has been discovered.
func (_gd *DecodeMap )SetOnNewRelationshipFunc (fn OnNewRelationshipFunc ){_gd ._abg =fn };var _efcd =[]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 *_af .Writer ,filename string ,v interface{})error {_cfc :=&_af .FileHeader {};_cfc .Method =_af .Deflate ;_cfc .Name =filename ;_cfc .SetModTime (_f .Now ());_db ,_bdc :=z .CreateHeader (_cfc );if _bdc !=nil {return _e .Errorf ("\u0063\u0072\u0065\u0061ti\u006e\u0067\u0020\u0025\u0073\u0020\u0069\u006e\u0020\u007a\u0069\u0070\u003a\u0020%\u0073",filename ,_bdc );};_ ,_bdc =_db .Write ([]byte (XMLHeader ));if _bdc !=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 ,_bdc );};if _bdc =_bf .NewEncoder (SelfClosingWriter {_db }).Encode (v );_bdc !=nil {return _e .Errorf ("\u006d\u0061\u0072\u0073\u0068\u0061\u006c\u0069\u006e\u0067\u0020\u0025s\u003a\u0020\u0025\u0073",filename ,_bdc );};_ ,_bdc =_db .Write (_ca );return _bdc ;};func (_fdd SelfClosingWriter )Write (b []byte )(int ,error ){_gf :=0;_edc :=0;for _cdc :=0;_cdc < len (b )-2;_cdc ++{if b [_cdc ]=='>'&&b [_cdc +1]=='<'&&b [_cdc +2]=='/'{_gbc :=[]byte {};_eca :=_cdc ;for _dgbc :=_cdc ;_dgbc >=0;_dgbc --{if b [_dgbc ]==' '{_eca =_dgbc ;}else if b [_dgbc ]=='<'{_gbc =b [_dgbc +1:_eca ];break ;};};_cee :=[]byte {};for _fga :=_cdc +3;_fga < len (b );_fga ++{if b [_fga ]=='>'{_cee =b [_cdc +3:_fga ];break ;};};if !_ab .Equal (_gbc ,_cee ){continue ;};_gab ,_de :=_fdd .W .Write (b [_gf :_cdc ]);if _de !=nil {return _edc +_gab ,_de ;};_edc +=_gab ;_ ,_de =_fdd .W .Write (_efcd );if _de !=nil {return _edc ,_de ;};_edc +=3;for _ge :=_cdc +2;_ge < len (b )&&b [_ge ]!='>';_ge ++{_edc ++;_gf =_ge +2;_cdc =_gf ;};};};_cgg ,_geg :=_fdd .W .Write (b [_gf :]);return _cgg +_edc ,_geg ;};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";
// 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 (_fa *DecodeMap )AddTarget (filePath string ,ifc interface{},sourceFileType string ,idx uint32 )bool {if _fa ._fe ==nil {_fa ._fe =make (map[string ]Target );_fa ._bfa =make (map[*_dg .Relationships ]string );_fa ._ae =make (map[string ]struct{});_fa ._ee =make (map[string ]int );};_fd :=_c .Clean (filePath );if _ ,_dgb :=_fa ._ae [_fd ];_dgb {return false ;};_fa ._ae [_fd ]=struct{}{};_fa ._fe [_fd ]=Target {Path :filePath ,Typ :sourceFileType ,Ifc :ifc ,Index :idx };return true ;};func MarshalXMLByType (z *_af .Writer ,dt _ce .DocType ,typ string ,v interface{})error {_be :=_ce .AbsoluteFilename (dt ,typ ,0);return MarshalXML (z ,_be ,v );};
// RelationsPathFor returns the relations path for a given filename.
func RelationsPathFor (path string )string {_cfb :=_b .Split (path ,"\u002f");_gac :=_b .Join (_cfb [0:len (_cfb )-1],"\u002f");_abd :=_cfb [len (_cfb )-1];_gac +="\u002f_\u0072\u0065\u006c\u0073\u002f";_abd +="\u002e\u0072\u0065l\u0073";return _gac +_abd ;};
// DecodeMap is used to walk a tree of relationships, decoding files and passing
// control back to the document.
type DecodeMap struct{_fe map[string ]Target ;_bfa map[*_dg .Relationships ]string ;_df []Target ;_abg OnNewRelationshipFunc ;_ae map[string ]struct{};_ee map[string ]int ;};var _ca =[]byte {'\r','\n'};
// AddFileFromBytes takes a byte array and adds it at a given path to a zip file.
func AddFileFromBytes (z *_af .Writer ,zipPath string ,data []byte )error {_ade ,_fgg :=z .Create (zipPath );if _fgg !=nil {return _e .Errorf ("e\u0072\u0072\u006f\u0072 c\u0072e\u0061\u0074\u0069\u006e\u0067 \u0025\u0073\u003a\u0020\u0025\u0073",zipPath ,_fgg );};_ ,_fgg =_fg .Copy (_ade ,_ab .NewReader (data ));return _fgg ;};func (_cf *DecodeMap )RecordIndex (path string ,idx int ){_cf ._ee [path ]=idx };
// ExtractToDiskTmp extracts a zip file to a temporary file in a given path,
// returning the name of the file.
func ExtractToDiskTmp (f *_af .File ,path string )(string ,error ){_dfd ,_egf :=_bc .TempFile (path ,"\u007a\u007a");if _egf !=nil {return "",_egf ;};defer _dfd .Close ();_ed ,_egf :=f .Open ();if _egf !=nil {return "",_egf ;};defer _ed .Close ();_ ,_egf =_fg .Copy (_dfd ,_ed );if _egf !=nil {return "",_egf ;};return _dfd .Name (),nil ;};