Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
421 changes: 421 additions & 0 deletions shortcuts/sheets/lark_sheets_cell_data.go

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import (
"context"
"fmt"
"io/fs"
"path/filepath"

"github.com/larksuite/cli/internal/output"
Expand Down Expand Up @@ -43,6 +44,10 @@
if err := validateSingleCellRange(runtime.Str("range")); err != nil {
return err
}
_, _, err := validateSheetWriteImageFile(runtime.Str("image"))
if err != nil {
return err
}
return nil
},
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
Expand Down Expand Up @@ -71,25 +76,12 @@
token = extractSpreadsheetToken(runtime.Str("url"))
}

// Resolve the target cell range (--range is required).
pointRange := normalizePointRange(runtime.Str("sheet-id"), runtime.Str("range"))

// Resolve image file.
imagePath := runtime.Str("image")
safePath, err := validate.SafeInputPath(imagePath)
if err != nil {
return output.ErrValidation("unsafe image path: %s", err)
}
stat, err := vfs.Stat(safePath)
safePath, stat, err := validateSheetWriteImageFile(imagePath)
if err != nil {
return output.ErrValidation("image file not found: %s", imagePath)
}
if !stat.Mode().IsRegular() {
return output.ErrValidation("image must be a regular file: %s", imagePath)
}
const maxImageSize int64 = 20 * 1024 * 1024 // 20 MB
if stat.Size() > maxImageSize {
return output.ErrValidation("image %.1fMB exceeds 20MB limit", float64(stat.Size())/1024/1024)
return err

Check warning on line 84 in shortcuts/sheets/lark_sheets_cell_images.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/sheets/lark_sheets_cell_images.go#L84

Added line #L84 was not covered by tests
}

imageBytes, err := vfs.ReadFile(safePath)
Expand All @@ -104,8 +96,6 @@

fmt.Fprintf(runtime.IO().ErrOut, "Writing image: %s (%d bytes) → %s\n", imageName, stat.Size(), pointRange)

// The sheets v2 values_image API expects a JSON body with the image
// as an inline byte array, not multipart/form-data.
data, err := runtime.CallAPI("POST", fmt.Sprintf("/open-apis/sheets/v2/spreadsheets/%s/values_image", validate.EncodePathSegment(token)), nil, map[string]interface{}{
"range": pointRange,
"image": imageBytes,
Expand All @@ -118,3 +108,22 @@
return nil
},
}

func validateSheetWriteImageFile(imagePath string) (string, fs.FileInfo, error) {
safePath, err := validate.SafeInputPath(imagePath)
if err != nil {
return "", nil, output.ErrValidation("unsafe image path: %s", err)
}
stat, err := vfs.Stat(safePath)
if err != nil {
return "", nil, output.ErrValidation("image file not found: %s", imagePath)
}
if !stat.Mode().IsRegular() {
return "", nil, output.ErrValidation("image must be a regular file: %s", imagePath)
}
const maxImageSize int64 = 20 * 1024 * 1024
if stat.Size() > maxImageSize {
return "", nil, output.ErrValidation("image %.1fMB exceeds 20MB limit", float64(stat.Size())/1024/1024)
}
return safePath, stat, nil
}
Loading
Loading