This fix potential panic and file corrupted

- Fix the panic when set or get sheet view options on the sheet without views options
- Fix generated workbook corruption caused by empty created or modified dcterms in the document core properties
- Update the unit tests
This commit is contained in:
xuri 2022-07-14 00:17:51 +08:00
parent a65c5846e4
commit e37724c22b
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
4 changed files with 70 additions and 52 deletions

View File

@ -204,7 +204,12 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
Category: core.Category, Category: core.Category,
Version: core.Version, Version: core.Version,
}, nil }, nil
newProps.Created.Text, newProps.Created.Type, newProps.Modified.Text, newProps.Modified.Type = core.Created.Text, core.Created.Type, core.Modified.Text, core.Modified.Type if core.Created != nil {
newProps.Created = &xlsxDcTerms{Type: core.Created.Type, Text: core.Created.Text}
}
if core.Modified != nil {
newProps.Modified = &xlsxDcTerms{Type: core.Modified.Type, Text: core.Modified.Text}
}
fields = []string{ fields = []string{
"Category", "ContentStatus", "Creator", "Description", "Identifier", "Keywords", "Category", "ContentStatus", "Creator", "Description", "Identifier", "Keywords",
"LastModifiedBy", "Revision", "Subject", "Title", "Language", "Version", "LastModifiedBy", "Revision", "Subject", "Title", "Language", "Version",
@ -216,10 +221,10 @@ func (f *File) SetDocProps(docProperties *DocProperties) (err error) {
} }
} }
if docProperties.Created != "" { if docProperties.Created != "" {
newProps.Created.Text = docProperties.Created newProps.Created = &xlsxDcTerms{Type: "dcterms:W3CDTF", Text: docProperties.Created}
} }
if docProperties.Modified != "" { if docProperties.Modified != "" {
newProps.Modified.Text = docProperties.Modified newProps.Modified = &xlsxDcTerms{Type: "dcterms:W3CDTF", Text: docProperties.Modified}
} }
output, err = xml.Marshal(newProps) output, err = xml.Marshal(newProps)
f.saveFileList(defaultXMLPathDocPropsCore, output) f.saveFileList(defaultXMLPathDocPropsCore, output)
@ -239,19 +244,22 @@ func (f *File) GetDocProps() (ret *DocProperties, err error) {
ret, err = &DocProperties{ ret, err = &DocProperties{
Category: core.Category, Category: core.Category,
ContentStatus: core.ContentStatus, ContentStatus: core.ContentStatus,
Created: core.Created.Text,
Creator: core.Creator, Creator: core.Creator,
Description: core.Description, Description: core.Description,
Identifier: core.Identifier, Identifier: core.Identifier,
Keywords: core.Keywords, Keywords: core.Keywords,
LastModifiedBy: core.LastModifiedBy, LastModifiedBy: core.LastModifiedBy,
Modified: core.Modified.Text,
Revision: core.Revision, Revision: core.Revision,
Subject: core.Subject, Subject: core.Subject,
Title: core.Title, Title: core.Title,
Language: core.Language, Language: core.Language,
Version: core.Version, Version: core.Version,
}, nil }, nil
if core.Created != nil {
ret.Created = core.Created.Text
}
if core.Modified != nil {
ret.Modified = core.Modified.Text
}
return return
} }

View File

@ -163,6 +163,11 @@ func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if ws.SheetViews == nil {
ws.SheetViews = &xlsxSheetViews{
SheetView: []xlsxSheetView{{WorkbookViewID: 0}},
}
}
if viewIndex < 0 { if viewIndex < 0 {
if viewIndex < -len(ws.SheetViews.SheetView) { if viewIndex < -len(ws.SheetViews.SheetView) {
return nil, fmt.Errorf("view index %d out of range", viewIndex) return nil, fmt.Errorf("view index %d out of range", viewIndex)

View File

@ -210,4 +210,9 @@ func TestSheetViewOptionsErrors(t *testing.T) {
assert.NoError(t, f.SetSheetViewOptions(sheet, -1)) assert.NoError(t, f.SetSheetViewOptions(sheet, -1))
assert.Error(t, f.SetSheetViewOptions(sheet, 1)) assert.Error(t, f.SetSheetViewOptions(sheet, 1))
assert.Error(t, f.SetSheetViewOptions(sheet, -2)) assert.Error(t, f.SetSheetViewOptions(sheet, -2))
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
assert.True(t, ok)
ws.(*xlsxWorksheet).SheetViews = nil
assert.NoError(t, f.GetSheetViewOptions(sheet, 0))
} }

View File

@ -31,61 +31,61 @@ type DocProperties struct {
Version string Version string
} }
// decodeDcTerms directly maps the DCMI metadata terms for the coreProperties.
type decodeDcTerms struct {
Text string `xml:",chardata"`
Type string `xml:"http://www.w3.org/2001/XMLSchema-instance type,attr"`
}
// decodeCoreProperties directly maps the root element for a part of this // decodeCoreProperties directly maps the root element for a part of this
// content type shall coreProperties. In order to solve the problem that the // content type shall coreProperties. In order to solve the problem that the
// label structure is changed after serialization and deserialization, two // label structure is changed after serialization and deserialization, two
// different structures are defined. decodeCoreProperties just for // different structures are defined. decodeCoreProperties just for
// deserialization. // deserialization.
type decodeCoreProperties struct { type decodeCoreProperties struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/metadata/core-properties coreProperties"` XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/metadata/core-properties coreProperties"`
Title string `xml:"http://purl.org/dc/elements/1.1/ title,omitempty"` Title string `xml:"http://purl.org/dc/elements/1.1/ title,omitempty"`
Subject string `xml:"http://purl.org/dc/elements/1.1/ subject,omitempty"` Subject string `xml:"http://purl.org/dc/elements/1.1/ subject,omitempty"`
Creator string `xml:"http://purl.org/dc/elements/1.1/ creator"` Creator string `xml:"http://purl.org/dc/elements/1.1/ creator"`
Keywords string `xml:"keywords,omitempty"` Keywords string `xml:"keywords,omitempty"`
Description string `xml:"http://purl.org/dc/elements/1.1/ description,omitempty"` Description string `xml:"http://purl.org/dc/elements/1.1/ description,omitempty"`
LastModifiedBy string `xml:"lastModifiedBy"` LastModifiedBy string `xml:"lastModifiedBy"`
Language string `xml:"http://purl.org/dc/elements/1.1/ language,omitempty"` Language string `xml:"http://purl.org/dc/elements/1.1/ language,omitempty"`
Identifier string `xml:"http://purl.org/dc/elements/1.1/ identifier,omitempty"` Identifier string `xml:"http://purl.org/dc/elements/1.1/ identifier,omitempty"`
Revision string `xml:"revision,omitempty"` Revision string `xml:"revision,omitempty"`
Created struct { Created *decodeDcTerms `xml:"http://purl.org/dc/terms/ created"`
Text string `xml:",chardata"` Modified *decodeDcTerms `xml:"http://purl.org/dc/terms/ modified"`
Type string `xml:"http://www.w3.org/2001/XMLSchema-instance type,attr"` ContentStatus string `xml:"contentStatus,omitempty"`
} `xml:"http://purl.org/dc/terms/ created"` Category string `xml:"category,omitempty"`
Modified struct { Version string `xml:"version,omitempty"`
Text string `xml:",chardata"` }
Type string `xml:"http://www.w3.org/2001/XMLSchema-instance type,attr"`
} `xml:"http://purl.org/dc/terms/ modified"` // xlsxDcTerms directly maps the DCMI metadata terms for the coreProperties.
ContentStatus string `xml:"contentStatus,omitempty"` type xlsxDcTerms struct {
Category string `xml:"category,omitempty"` Text string `xml:",chardata"`
Version string `xml:"version,omitempty"` Type string `xml:"xsi:type,attr"`
} }
// xlsxCoreProperties directly maps the root element for a part of this // xlsxCoreProperties directly maps the root element for a part of this
// content type shall coreProperties. // content type shall coreProperties.
type xlsxCoreProperties struct { type xlsxCoreProperties struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/metadata/core-properties coreProperties"` XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/metadata/core-properties coreProperties"`
Dc string `xml:"xmlns:dc,attr"` Dc string `xml:"xmlns:dc,attr"`
Dcterms string `xml:"xmlns:dcterms,attr"` Dcterms string `xml:"xmlns:dcterms,attr"`
Dcmitype string `xml:"xmlns:dcmitype,attr"` Dcmitype string `xml:"xmlns:dcmitype,attr"`
XSI string `xml:"xmlns:xsi,attr"` XSI string `xml:"xmlns:xsi,attr"`
Title string `xml:"dc:title,omitempty"` Title string `xml:"dc:title,omitempty"`
Subject string `xml:"dc:subject,omitempty"` Subject string `xml:"dc:subject,omitempty"`
Creator string `xml:"dc:creator"` Creator string `xml:"dc:creator"`
Keywords string `xml:"keywords,omitempty"` Keywords string `xml:"keywords,omitempty"`
Description string `xml:"dc:description,omitempty"` Description string `xml:"dc:description,omitempty"`
LastModifiedBy string `xml:"lastModifiedBy"` LastModifiedBy string `xml:"lastModifiedBy"`
Language string `xml:"dc:language,omitempty"` Language string `xml:"dc:language,omitempty"`
Identifier string `xml:"dc:identifier,omitempty"` Identifier string `xml:"dc:identifier,omitempty"`
Revision string `xml:"revision,omitempty"` Revision string `xml:"revision,omitempty"`
Created struct { Created *xlsxDcTerms `xml:"dcterms:created"`
Text string `xml:",chardata"` Modified *xlsxDcTerms `xml:"dcterms:modified"`
Type string `xml:"xsi:type,attr"` ContentStatus string `xml:"contentStatus,omitempty"`
} `xml:"dcterms:created"` Category string `xml:"category,omitempty"`
Modified struct { Version string `xml:"version,omitempty"`
Text string `xml:",chardata"`
Type string `xml:"xsi:type,attr"`
} `xml:"dcterms:modified"`
ContentStatus string `xml:"contentStatus,omitempty"`
Category string `xml:"category,omitempty"`
Version string `xml:"version,omitempty"`
} }