summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxuri <xuri.me@gmail.com>2021-08-15 00:06:40 +0800
committerxuri <xuri.me@gmail.com>2021-08-15 00:06:40 +0800
commit48c16de8bf74df0fa94a30d29e2e7e3446d48433 (patch)
tree329a2e4ab896982581bd348a1700d75aeb40a517
parentf6f14f507ee1adf4883cb1b12f27932a63afb286 (diff)
Improve security and simplify code
- Make variable name more semantic - Reduce cyclomatic complexities for the formula calculate function - Support specified unzip size limit on open file options, avoid zip bombs vulnerability attack - Typo fix for documentation and error message
-rw-r--r--calc.go59
-rw-r--r--comment_test.go8
-rw-r--r--crypt.go10
-rw-r--r--crypt_test.go8
-rw-r--r--datavalidation_test.go8
-rw-r--r--date_test.go2
-rw-r--r--errors.go12
-rw-r--r--errors_test.go2
-rw-r--r--excelize.go44
-rw-r--r--excelize_test.go15
-rw-r--r--file.go16
-rw-r--r--file_test.go12
-rw-r--r--lib.go28
-rw-r--r--merge_test.go6
-rw-r--r--picture.go14
-rw-r--r--picture_test.go10
-rw-r--r--sheet.go8
-rw-r--r--sheetpr.go10
-rw-r--r--stream.go4
-rw-r--r--xmlChartSheet.go8
-rw-r--r--xmlDrawing.go1
21 files changed, 165 insertions, 120 deletions
diff --git a/calc.go b/calc.go
index a03520b..eb6ff75 100644
--- a/calc.go
+++ b/calc.go
@@ -6026,6 +6026,39 @@ func (fn *formulaFuncs) DATE(argsList *list.List) formulaArg {
return newStringFormulaArg(timeFromExcelTime(daysBetween(excelMinTime1900.Unix(), d)+1, false).String())
}
+// calcDateDif is an implementation of the formula function DATEDIF,
+// calculation difference between two dates.
+func calcDateDif(unit string, diff float64, seq []int, startArg, endArg formulaArg) float64 {
+ ey, sy, em, sm, ed, sd := seq[0], seq[1], seq[2], seq[3], seq[4], seq[5]
+ switch unit {
+ case "d":
+ diff = endArg.Number - startArg.Number
+ case "md":
+ smMD := em
+ if ed < sd {
+ smMD--
+ }
+ diff = endArg.Number - daysBetween(excelMinTime1900.Unix(), makeDate(ey, time.Month(smMD), sd)) - 1
+ case "ym":
+ diff = float64(em - sm)
+ if ed < sd {
+ diff--
+ }
+ if diff < 0 {
+ diff += 12
+ }
+ case "yd":
+ syYD := sy
+ if em < sm || (em == sm && ed < sd) {
+ syYD++
+ }
+ s := daysBetween(excelMinTime1900.Unix(), makeDate(syYD, time.Month(em), ed))
+ e := daysBetween(excelMinTime1900.Unix(), makeDate(sy, time.Month(sm), sd))
+ diff = s - e
+ }
+ return diff
+}
+
// DATEDIF function calculates the number of days, months, or years between
// two dates. The syntax of the function is:
//
@@ -6051,8 +6084,6 @@ func (fn *formulaFuncs) DATEDIF(argsList *list.List) formulaArg {
ey, emm, ed := endDate.Date()
sm, em, diff := int(smm), int(emm), 0.0
switch unit {
- case "d":
- return newNumberFormulaArg(endArg.Number - startArg.Number)
case "y":
diff = float64(ey - sy)
if em < sm || (em == sm && ed < sd) {
@@ -6069,28 +6100,8 @@ func (fn *formulaFuncs) DATEDIF(argsList *list.List) formulaArg {
mdiff += 12
}
diff = float64(ydiff*12 + mdiff)
- case "md":
- smMD := em
- if ed < sd {
- smMD--
- }
- diff = endArg.Number - daysBetween(excelMinTime1900.Unix(), makeDate(ey, time.Month(smMD), sd)) - 1
- case "ym":
- diff = float64(em - sm)
- if ed < sd {
- diff--
- }
- if diff < 0 {
- diff += 12
- }
- case "yd":
- syYD := sy
- if em < sm || (em == sm && ed < sd) {
- syYD++
- }
- s := daysBetween(excelMinTime1900.Unix(), makeDate(syYD, time.Month(em), ed))
- e := daysBetween(excelMinTime1900.Unix(), makeDate(sy, time.Month(sm), sd))
- diff = s - e
+ case "d", "md", "ym", "yd":
+ diff = calcDateDif(unit, diff, []int{ey, sy, em, sm, ed, sd}, startArg, endArg)
default:
return newErrorFormulaArg(formulaErrorVALUE, "DATEDIF has invalid unit")
}
diff --git a/comment_test.go b/comment_test.go
index f1b60dc..fb36d29 100644
--- a/comment_test.go
+++ b/comment_test.go
@@ -3,9 +3,11 @@
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX files. Support reads and writes XLSX file generated by
-// Microsoft Excel™ 2007 and later. Support save file without losing original
-// charts of XLSX. This library needs Go version 1.15 or later.
+// and read from XLSX / XLSM / XLTM files. Supports reading and writing
+// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
+// complex components by high compatibility, and provided streaming API for
+// generating or reading data from a worksheet with huge amounts of data. This
+// library needs Go version 1.15 or later.
package excelize
diff --git a/crypt.go b/crypt.go
index a0096c9..24ac7ec 100644
--- a/crypt.go
+++ b/crypt.go
@@ -3,9 +3,11 @@
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX files. Support reads and writes XLSX file generated by
-// Microsoft Excel™ 2007 and later. Support save file without losing original
-// charts of XLSX. This library needs Go version 1.15 or later.
+// and read from XLSX / XLSM / XLTM files. Supports reading and writing
+// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
+// complex components by high compatibility, and provided streaming API for
+// generating or reading data from a worksheet with huge amounts of data. This
+// library needs Go version 1.15 or later.
package excelize
@@ -15,6 +17,7 @@ import (
"crypto/cipher"
"crypto/hmac"
"crypto/md5"
+ "crypto/rand"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
@@ -22,7 +25,6 @@ import (
"encoding/binary"
"encoding/xml"
"hash"
- "math/rand"
"reflect"
"strings"
diff --git a/crypt_test.go b/crypt_test.go
index 6a882e5..68ff5b8 100644
--- a/crypt_test.go
+++ b/crypt_test.go
@@ -3,9 +3,11 @@
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX files. Support reads and writes XLSX file generated by
-// Microsoft Excel™ 2007 and later. Support save file without losing original
-// charts of XLSX. This library needs Go version 1.15 or later.
+// and read from XLSX / XLSM / XLTM files. Supports reading and writing
+// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
+// complex components by high compatibility, and provided streaming API for
+// generating or reading data from a worksheet with huge amounts of data. This
+// library needs Go version 1.15 or later.
package excelize
diff --git a/datavalidation_test.go b/datavalidation_test.go
index f0afe5f..0cb5929 100644
--- a/datavalidation_test.go
+++ b/datavalidation_test.go
@@ -3,9 +3,11 @@
// the LICENSE file.
//
// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX files. Support reads and writes XLSX file generated by
-// Microsoft Excel™ 2007 and later. Support save file without losing original
-// charts of XLSX. This library needs Go version 1.15 or later.
+// and read from XLSX / XLSM / XLTM files. Supports reading and writing
+// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
+// complex components by high compatibility, and provided streaming API for
+// generating or reading data from a worksheet with huge amounts of data. This
+// library needs Go version 1.15 or later.
package excelize
diff --git a/date_test.go b/date_test.go
index 38898b0..2addc4a 100644
--- a/date_test.go
+++ b/date_test.go
@@ -85,5 +85,5 @@ func TestExcelDateToTime(t *testing.T) {
}
// Check error case
_, err := ExcelDateToTime(-1, false)
- assert.EqualError(t, err, "invalid date value -1.000000, negative values are not supported supported")
+ assert.EqualError(t, err, "invalid date value -1.000000, negative values are not supported")
}
diff --git a/errors.go b/errors.go
index 0edb697..aee4420 100644
--- a/errors.go
+++ b/errors.go
@@ -16,26 +16,36 @@ import (
"fmt"
)
+// newInvalidColumnNameError defined the error message on receiving the invalid column name.
func newInvalidColumnNameError(col string) error {
return fmt.Errorf("invalid column name %q", col)
}
+// newInvalidRowNumberError defined the error message on receiving the invalid row number.
func newInvalidRowNumberError(row int) error {
return fmt.Errorf("invalid row number %d", row)
}
+// newInvalidCellNameError defined the error message on receiving the invalid cell name.
func newInvalidCellNameError(cell string) error {
return fmt.Errorf("invalid cell name %q", cell)
}
+// newInvalidExcelDateError defined the error message on receiving the data with negative values.
func newInvalidExcelDateError(dateValue float64) error {
- return fmt.Errorf("invalid date value %f, negative values are not supported supported", dateValue)
+ return fmt.Errorf("invalid date value %f, negative values are not supported", dateValue)
}
+// newUnsupportChartType defined the error message on receiving the chart type are unsupported.
func newUnsupportChartType(chartType string) error {
return fmt.Errorf("unsupported chart type %s", chartType)
}
+// newUnzipSizeLimitError defined the error message on unzip size exceeds the limit.
+func newUnzipSizeLimitError(unzipSizeLimit int64) error {
+ return fmt.Errorf("unzip size exceeds the %d bytes limit", unzipSizeLimit)
+}
+
var (
// ErrStreamSetColWidth defined the error message on set column width in
// stream writing mode.
diff --git a/errors_test.go b/errors_test.go
index 207e80a..971802f 100644
--- a/errors_test.go
+++ b/errors_test.go
@@ -21,5 +21,5 @@ func TestNewInvalidCellNameError(t *testing.T) {
}
func TestNewInvalidExcelDateError(t *testing.T) {
- assert.EqualError(t, newInvalidExcelDateError(-1), "invalid date value -1.000000, negative values are not supported supported")
+ assert.EqualError(t, newInvalidExcelDateError(-1), "invalid date value -1.000000, negative values are not supported")
}
diff --git a/excelize.go b/excelize.go
index 0091c82..fafa57f 100644
--- a/excelize.go
+++ b/excelize.go
@@ -21,6 +21,7 @@ import (
"io/ioutil"
"os"
"path"
+ "path/filepath"
"strconv"
"strings"
"sync"
@@ -59,21 +60,27 @@ type charsetTranscoderFn func(charset string, input io.Reader) (rdr io.Reader, e
// Options define the options for open spreadsheet.
type Options struct {
- Password string
+ Password string
+ UnzipSizeLimit int64
}
-// OpenFile take the name of an spreadsheet file and returns a populated spreadsheet file struct
-// for it. For example, open spreadsheet with password protection:
+// OpenFile take the name of an spreadsheet file and returns a populated
+// spreadsheet file struct for it. For example, open spreadsheet with
+// password protection:
//
// f, err := excelize.OpenFile("Book1.xlsx", excelize.Options{Password: "password"})
// if err != nil {
// return
// }
//
-// Note that the excelize just support decrypt and not support encrypt currently, the spreadsheet
-// saved by Save and SaveAs will be without password unprotected.
+// Note that the excelize just support decrypt and not support encrypt
+// currently, the spreadsheet saved by Save and SaveAs will be without
+// password unprotected.
+//
+// UnzipSizeLimit specified the unzip size limit in bytes on open the
+// spreadsheet, the default size limit is 16GB.
func OpenFile(filename string, opt ...Options) (*File, error) {
- file, err := os.Open(filename)
+ file, err := os.Open(filepath.Clean(filename))
if err != nil {
return nil, err
}
@@ -89,6 +96,7 @@ func OpenFile(filename string, opt ...Options) (*File, error) {
// newFile is object builder
func newFile() *File {
return &File{
+ options: &Options{UnzipSizeLimit: UnzipSizeLimit},
xmlAttr: make(map[string][]xml.Attr),
checked: make(map[string]bool),
sheetMap: make(map[string]string),
@@ -111,10 +119,13 @@ func OpenReader(r io.Reader, opt ...Options) (*File, error) {
return nil, err
}
f := newFile()
- if bytes.Contains(b, oleIdentifier) && len(opt) > 0 {
- for _, o := range opt {
- f.options = &o
+ for i := range opt {
+ f.options = &opt[i]
+ if f.options.UnzipSizeLimit == 0 {
+ f.options.UnzipSizeLimit = UnzipSizeLimit
}
+ }
+ if bytes.Contains(b, oleIdentifier) {
b, err = Decrypt(b, f.options)
if err != nil {
return nil, fmt.Errorf("decrypted file failed")
@@ -124,8 +135,7 @@ func OpenReader(r io.Reader, opt ...Options) (*File, error) {
if err != nil {
return nil, err
}
-
- file, sheetCount, err := ReadZipReader(zr)
+ file, sheetCount, err := ReadZipReader(zr, f.options)
if err != nil {
return nil, err
}
@@ -316,18 +326,18 @@ func (f *File) UpdateLinkedValue() error {
// recalculate formulas
wb.CalcPr = nil
for _, name := range f.GetSheetList() {
- xlsx, err := f.workSheetReader(name)
+ ws, err := f.workSheetReader(name)
if err != nil {
if err.Error() == fmt.Sprintf("sheet %s is chart sheet", trimSheetName(name)) {
continue
}
return err
}
- for indexR := range xlsx.SheetData.Row {
- for indexC, col := range xlsx.SheetData.Row[indexR].C {
+ for indexR := range ws.SheetData.Row {
+ for indexC, col := range ws.SheetData.Row[indexR].C {
if col.F != nil && col.V != "" {
- xlsx.SheetData.Row[indexR].C[indexC].V = ""
- xlsx.SheetData.Row[indexR].C[indexC].T = ""
+ ws.SheetData.Row[indexR].C[indexC].V = ""
+ ws.SheetData.Row[indexR].C[indexC].T = ""
}
}
}
@@ -381,7 +391,7 @@ func (f *File) AddVBAProject(bin string) error {
Type: SourceRelationshipVBAProject,
})
}
- file, _ := ioutil.ReadFile(bin)
+ file, _ := ioutil.ReadFile(filepath.Clean(bin))
f.Pkg.Store("xl/vbaProject.bin", file)
return err
}
diff --git a/excelize_test.go b/excelize_test.go
index cc3a1b2..918279b 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -184,13 +184,9 @@ func TestSaveFile(t *testing.T) {
func TestSaveAsWrongPath(t *testing.T) {
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
- if assert.NoError(t, err) {
- // Test write file to not exist directory.
- err = f.SaveAs("")
- if assert.Error(t, err) {
- assert.True(t, os.IsNotExist(err), "Error: %v: Expected os.IsNotExists(err) == true", err)
- }
- }
+ assert.NoError(t, err)
+ // Test write file to not exist directory.
+ assert.EqualError(t, f.SaveAs(""), "open .: is a directory")
}
func TestCharsetTranscoder(t *testing.T) {
@@ -204,6 +200,10 @@ func TestOpenReader(t *testing.T) {
_, err = OpenReader(bytes.NewReader(oleIdentifier), Options{Password: "password"})
assert.EqualError(t, err, "decrypted file failed")
+ // Test open spreadsheet with unzip size limit.
+ _, err = OpenFile(filepath.Join("test", "Book1.xlsx"), Options{UnzipSizeLimit: 100})
+ assert.EqualError(t, err, newUnzipSizeLimitError(100).Error())
+
// Test open password protected spreadsheet created by Microsoft Office Excel 2010.
f, err := OpenFile(filepath.Join("test", "encryptSHA1.xlsx"), Options{Password: "password"})
assert.NoError(t, err)
@@ -1226,6 +1226,7 @@ func TestWorkSheetReader(t *testing.T) {
f.Pkg.Store("xl/worksheets/sheet1.xml", MacintoshCyrillicCharset)
_, err := f.workSheetReader("Sheet1")
assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, f.UpdateLinkedValue(), "xml decode error: XML syntax error on line 1: invalid UTF-8")
// Test on no checked worksheet.
f = NewFile()
diff --git a/file.go b/file.go
index abb0305..bfb6abf 100644
--- a/file.go
+++ b/file.go
@@ -17,6 +17,7 @@ import (
"fmt"
"io"
"os"
+ "path/filepath"
"sync"
)
@@ -69,14 +70,14 @@ func (f *File) SaveAs(name string, opt ...Options) error {
return ErrMaxFileNameLength
}
f.Path = name
- file, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
+ file, err := os.OpenFile(filepath.Clean(name), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
if err != nil {
return err
}
defer file.Close()
f.options = nil
- for _, o := range opt {
- f.options = &o
+ for i := range opt {
+ f.options = &opt[i]
}
return f.Write(file)
}
@@ -102,7 +103,8 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
return 0, nil
}
-// WriteToBuffer provides a function to get bytes.Buffer from the saved file. And it allocate space in memory. Be careful when the file size is large.
+// WriteToBuffer provides a function to get bytes.Buffer from the saved file,
+// and it allocates space in memory. Be careful when the file size is large.
func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
buf := new(bytes.Buffer)
zw := zip.NewWriter(buf)
@@ -130,7 +132,7 @@ func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
func (f *File) writeDirectToWriter(w io.Writer) error {
zw := zip.NewWriter(w)
if err := f.writeToZip(zw); err != nil {
- zw.Close()
+ _ = zw.Close()
return err
}
return zw.Close()
@@ -157,14 +159,14 @@ func (f *File) writeToZip(zw *zip.Writer) error {
var from io.Reader
from, err = stream.rawData.Reader()
if err != nil {
- stream.rawData.Close()
+ _ = stream.rawData.Close()
return err
}
_, err = io.Copy(fi, from)
if err != nil {
return err
}
- stream.rawData.Close()
+ _ = stream.rawData.Close()
}
var err error
f.Pkg.Range(func(path, content interface{}) bool {
diff --git a/file_test.go b/file_test.go
index d86ce53..956ff92 100644
--- a/file_test.go
+++ b/file_test.go
@@ -37,9 +37,7 @@ func BenchmarkWrite(b *testing.B) {
func TestWriteTo(t *testing.T) {
// Test WriteToBuffer err
{
- f := File{}
- buf := bytes.Buffer{}
- f.Pkg = sync.Map{}
+ f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
f.Pkg.Store("/d/", []byte("s"))
_, err := f.WriteTo(bufio.NewWriter(&buf))
assert.EqualError(t, err, "zip: write to directory")
@@ -47,9 +45,7 @@ func TestWriteTo(t *testing.T) {
}
// Test file path overflow
{
- f := File{}
- buf := bytes.Buffer{}
- f.Pkg = sync.Map{}
+ f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
const maxUint16 = 1<<16 - 1
f.Pkg.Store(strings.Repeat("s", maxUint16+1), nil)
_, err := f.WriteTo(bufio.NewWriter(&buf))
@@ -57,9 +53,7 @@ func TestWriteTo(t *testing.T) {
}
// Test StreamsWriter err
{
- f := File{}
- buf := bytes.Buffer{}
- f.Pkg = sync.Map{}
+ f, buf := File{Pkg: sync.Map{}}, bytes.Buffer{}
f.Pkg.Store("s", nil)
f.streams = make(map[string]*StreamWriter)
file, _ := os.Open("123")
diff --git a/lib.go b/lib.go
index 912f738..712576d 100644
--- a/lib.go
+++ b/lib.go
@@ -26,15 +26,22 @@ import (
// ReadZipReader can be used to read the spreadsheet in memory without touching the
// filesystem.
-func ReadZipReader(r *zip.Reader) (map[string][]byte, int, error) {
- var err error
- var docPart = map[string]string{
- "[content_types].xml": "[Content_Types].xml",
- "xl/sharedstrings.xml": "xl/sharedStrings.xml",
- }
- fileList := make(map[string][]byte, len(r.File))
- worksheets := 0
+func ReadZipReader(r *zip.Reader, o *Options) (map[string][]byte, int, error) {
+ var (
+ err error
+ docPart = map[string]string{
+ "[content_types].xml": "[Content_Types].xml",
+ "xl/sharedstrings.xml": "xl/sharedStrings.xml",
+ }
+ fileList = make(map[string][]byte, len(r.File))
+ worksheets int
+ unzipSize int64
+ )
for _, v := range r.File {
+ unzipSize += v.FileInfo().Size()
+ if unzipSize > o.UnzipSizeLimit {
+ return fileList, worksheets, newUnzipSizeLimitError(o.UnzipSizeLimit)
+ }
fileName := strings.Replace(v.Name, "\\", "/", -1)
if partName, ok := docPart[strings.ToLower(fileName)]; ok {
fileName = partName
@@ -61,7 +68,7 @@ func (f *File) readXML(name string) []byte {
}
// saveFileList provides a function to update given file content in file list
-// of XLSX.
+// of spreadsheet.
func (f *File) saveFileList(name string, content []byte) {
f.Pkg.Store(name, append([]byte(XMLHeader), content...))
}
@@ -75,8 +82,7 @@ func readFile(file *zip.File) ([]byte, error) {
dat := make([]byte, 0, file.FileInfo().Size())
buff := bytes.NewBuffer(dat)
_, _ = io.Copy(buff, rc)
- rc.Close()
- return buff.Bytes(), nil
+ return buff.Bytes(), rc.Close()
}
// SplitCellName splits cell name to column name and row number.
diff --git a/merge_test.go b/merge_test.go
index a370126..02d92fb 100644
--- a/merge_test.go
+++ b/merge_test.go
@@ -148,16 +148,16 @@ func TestUnmergeCell(t *testing.T) {
}
sheet1 := f.GetSheetName(0)
- xlsx, err := f.workSheetReader(sheet1)
+ sheet, err := f.workSheetReader(sheet1)
assert.NoError(t, err)
- mergeCellNum := len(xlsx.MergeCells.Cells)
+ mergeCellNum := len(sheet.MergeCells.Cells)
assert.EqualError(t, f.UnmergeCell("Sheet1", "A", "A"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
// unmerge the mergecell that contains A1
assert.NoError(t, f.UnmergeCell(sheet1, "A1", "A1"))
- if len(xlsx.MergeCells.Cells) != mergeCellNum-1 {
+ if len(sheet.MergeCells.Cells) != mergeCellNum-1 {
t.FailNow()
}
diff --git a/picture.go b/picture.go
index c37899e..e3601dd 100644
--- a/picture.go
+++ b/picture.go
@@ -94,7 +94,7 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
if !ok {
return ErrImgExt
}
- file, _ := ioutil.ReadFile(picture)
+ file, _ := ioutil.ReadFile(filepath.Clean(picture))
_, name := filepath.Split(picture)
return f.AddPictureFromBytes(sheet, cell, format, name, ext, file)
}
@@ -199,8 +199,8 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
// addSheetLegacyDrawing provides a function to add legacy drawing element to
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
- xlsx, _ := f.workSheetReader(sheet)
- xlsx.LegacyDrawing = &xlsxLegacyDrawing{
+ ws, _ := f.workSheetReader(sheet)
+ ws.LegacyDrawing = &xlsxLegacyDrawing{
RID: "rId" + strconv.Itoa(rID),
}
}
@@ -208,8 +208,8 @@ func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
// addSheetDrawing provides a function to add drawing element to
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
func (f *File) addSheetDrawing(sheet string, rID int) {
- xlsx, _ := f.workSheetReader(sheet)
- xlsx.Drawing = &xlsxDrawing{
+ ws, _ := f.workSheetReader(sheet)
+ ws.Drawing = &xlsxDrawing{
RID: "rId" + strconv.Itoa(rID),
}
}
@@ -217,8 +217,8 @@ func (f *File) addSheetDrawing(sheet string, rID int) {
// addSheetPicture provides a function to add picture element to
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
func (f *File) addSheetPicture(sheet string, rID int) {
- xlsx, _ := f.workSheetReader(sheet)
- xlsx.Picture = &xlsxPicture{
+ ws, _ := f.workSheetReader(sheet)
+ ws.Picture = &xlsxPicture{
RID: "rId" + strconv.Itoa(rID),
}
}
diff --git a/picture_test.go b/picture_test.go
index 913ed3d..3e12f5f 100644
--- a/picture_test.go
+++ b/picture_test.go
@@ -71,24 +71,24 @@ func TestAddPicture(t *testing.T) {
}
func TestAddPictureErrors(t *testing.T) {
- xlsx, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
+ f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
assert.NoError(t, err)
// Test add picture to worksheet with invalid file path.
- err = xlsx.AddPicture("Sheet1", "G21", filepath.Join("test", "not_exists_dir", "not_exists.icon"), "")
+ err = f.AddPicture("Sheet1", "G21", filepath.Join("test", "not_exists_dir", "not_exists.icon"), "")
if assert.Error(t, err) {
assert.True(t, os.IsNotExist(err), "Expected os.IsNotExist(err) == true")
}
// Test add picture to worksheet with unsupported file type.
- err = xlsx.AddPicture("Sheet1", "G21", filepath.Join("test", "Book1.xlsx"), "")
+ err = f.AddPicture("Sheet1", "G21", filepath.Join("test", "Book1.xlsx"), "")
assert.EqualError(t, err, ErrImgExt.Error())
- err = xlsx.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", "jpg", make([]byte, 1))
+ err = f.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", "jpg", make([]byte, 1))
assert.EqualError(t, err, ErrImgExt.Error())
// Test add picture to worksheet with invalid file data.
- err = xlsx.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", ".jpg", make([]byte, 1))
+ err = f.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", ".jpg", make([]byte, 1))
assert.EqualError(t, err, "image: unknown format")
}
diff --git a/sheet.go b/sheet.go
index 1c4b355..7e15bbe 100644
--- a/sheet.go
+++ b/sheet.go
@@ -480,7 +480,7 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
if !ok {
return ErrImgExt
}
- file, _ := ioutil.ReadFile(picture)
+ file, _ := ioutil.ReadFile(filepath.Clean(picture))
name := f.addMedia(file, ext)
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels"
rID := f.addRels(sheetRels, SourceRelationshipImage, strings.Replace(name, "xl", "..", 1), "")
@@ -655,13 +655,13 @@ func (f *File) SetSheetVisible(name string, visible bool) error {
}
}
for k, v := range content.Sheets.Sheet {
- xlsx, err := f.workSheetReader(v.Name)
+ ws, err := f.workSheetReader(v.Name)
if err != nil {
return err
}
tabSelected := false
- if len(xlsx.SheetViews.SheetView) > 0 {
- tabSelected = xlsx.SheetViews.SheetView[0].TabSelected
+ if len(ws.SheetViews.SheetView) > 0 {
+ tabSelected = ws.SheetViews.SheetView[0].TabSelected
}
if v.Name == name && count > 1 && !tabSelected {
content.Sheets.Sheet[k].State = "hidden"
diff --git a/sheetpr.go b/sheetpr.go
index 8bc4bfe..6f46040 100644
--- a/sheetpr.go
+++ b/sheetpr.go
@@ -182,14 +182,14 @@ func (o *AutoPageBreaks) getSheetPrOption(pr *xlsxSheetPr) {
// AutoPageBreaks(bool)
// OutlineSummaryBelow(bool)
func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
- sheet, err := f.workSheetReader(name)
+ ws, err := f.workSheetReader(name)
if err != nil {
return err
}
- pr := sheet.SheetPr
+ pr := ws.SheetPr
if pr == nil {
pr = new(xlsxSheetPr)
- sheet.SheetPr = pr
+ ws.SheetPr = pr
}
for _, opt := range opts {
@@ -208,11 +208,11 @@ func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
// AutoPageBreaks(bool)
// OutlineSummaryBelow(bool)
func (f *File) GetSheetPrOptions(name string, opts ...SheetPrOptionPtr) error {
- sheet, err := f.workSheetReader(name)
+ ws, err := f.workSheetReader(name)
if err != nil {
return err
}
- pr := sheet.SheetPr
+ pr := ws.SheetPr
for _, opt := range opts {
opt.getSheetPrOption(pr)
diff --git a/stream.go b/stream.go
index 9939016..125b58c 100644
--- a/stream.go
+++ b/stream.go
@@ -346,8 +346,8 @@ func (sw *StreamWriter) SetRow(axis string, values []interface{}, opts ...RowOpt
// marshalRowAttrs prepare attributes of the row by given options.
func marshalRowAttrs(opts ...RowOpts) (attrs string, err error) {
var opt *RowOpts
- for _, o := range opts {
- opt = &o
+ for i := range opts {
+ opt = &opts[i]
}
if opt == nil {
return
diff --git a/xmlChartSheet.go b/xmlChartSheet.go
index 4ef2ded..fcc3443 100644
--- a/xmlChartSheet.go
+++ b/xmlChartSheet.go
@@ -5,9 +5,11 @@
// struct code generated by github.com/xuri/xgen
//
// Package excelize providing a set of functions that allow you to write to
-// and read from XLSX files. Support reads and writes XLSX file generated by
-// Microsoft Excel™ 2007 and later. Support save file without losing original
-// charts of XLSX. This library needs Go version 1.15 or later.
+// and read from XLSX / XLSM / XLTM files. Supports reading and writing
+// spreadsheet documents generated by Microsoft Excel™ 2007 and later. Supports
+// complex components by high compatibility, and provided streaming API for
+// generating or reading data from a worksheet with huge amounts of data. This
+// library needs Go version 1.15 or later.
package excelize
diff --git a/xmlDrawing.go b/xmlDrawing.go
index 4e35fcf..b49ae9d 100644
--- a/xmlDrawing.go
+++ b/xmlDrawing.go
@@ -94,6 +94,7 @@ const (
// Excel specifications and limits
const (
+ UnzipSizeLimit = 1000 << 24
StreamChunkSize = 1 << 24
MaxFontFamilyLength = 31
MaxFontSize = 409