package server import ( "fmt" "net/http" "strings" "github.com/gin-gonic/gin" "warpbox/lib/boxstore" "warpbox/lib/models" ) func (app *App) requireAPI(ctx *gin.Context) bool { if app.config.APIEnabled { return true } ctx.JSON(http.StatusForbidden, gin.H{"error": "API access is disabled"}) return false } func (app *App) requireGuestUploads(ctx *gin.Context) bool { if app.config.GuestUploadsEnabled { return true } ctx.JSON(http.StatusForbidden, gin.H{"error": "Guest uploads are disabled"}) return false } func (app *App) validateCreateBoxRequest(request *models.CreateBoxRequest) error { if request == nil { return nil } if !app.retentionAllowed(request.RetentionKey) { return fmt.Errorf("Retention option is not allowed") } if !app.config.ZipDownloadsEnabled { allowZip := false request.AllowZip = &allowZip } if strings.TrimSpace(request.RetentionKey) == boxstore.OneTimeDownloadRetentionKey && !app.config.OneTimeDownloadsEnabled { return fmt.Errorf("One-time downloads are disabled") } totalSize := int64(0) for _, file := range request.Files { if err := app.validateFileSize(file.Size); err != nil { return err } totalSize += file.Size } return app.validateBoxSize(totalSize) } func (app *App) validateIncomingFile(boxID string, size int64) error { if err := app.validateFileSize(size); err != nil { return err } if app.config.GlobalMaxBoxSizeBytes <= 0 { return nil } files, err := boxstore.ListFiles(boxID) if err != nil { return nil } totalSize := size for _, file := range files { totalSize += file.Size } return app.validateBoxSize(totalSize) } func (app *App) validateManifestFileUpload(boxID string, fileID string, size int64) error { if err := app.validateFileSize(size); err != nil { return err } manifest, err := boxstore.ReadManifest(boxID) if err != nil { return app.validateIncomingFile(boxID, size) } if boxstore.IsExpired(manifest) { _ = boxstore.DeleteBox(boxID) return fmt.Errorf("Box expired") } if app.config.GlobalMaxBoxSizeBytes <= 0 { return nil } totalSize := int64(0) found := false for _, file := range manifest.Files { if file.ID == fileID { totalSize += size found = true continue } totalSize += file.Size } if !found { totalSize += size } return app.validateBoxSize(totalSize) } func (app *App) validateFileSize(size int64) error { if size < 0 { return fmt.Errorf("File size cannot be negative") } if app.config.GlobalMaxFileSizeBytes > 0 && size > app.config.GlobalMaxFileSizeBytes { return fmt.Errorf("File exceeds the global max file size") } return nil } func (app *App) validateBoxSize(size int64) error { if size < 0 { return fmt.Errorf("Box size cannot be negative") } if app.config.GlobalMaxBoxSizeBytes > 0 && size > app.config.GlobalMaxBoxSizeBytes { return fmt.Errorf("Box exceeds the global max box size") } return nil } func (app *App) rejectExpiredManifestBox(boxID string) error { manifest, err := boxstore.ReadManifest(boxID) if err != nil { return nil } if !boxstore.IsExpired(manifest) { return nil } _ = boxstore.DeleteBox(boxID) return fmt.Errorf("Box expired") } func (app *App) limitRequestBody(ctx *gin.Context) { limit := app.maxRequestBodyBytes() if limit <= 0 { return } ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, limit) } func (app *App) maxRequestBodyBytes() int64 { limit := app.config.GlobalMaxBoxSizeBytes if limit <= 0 || app.config.GlobalMaxFileSizeBytes > limit { limit = app.config.GlobalMaxFileSizeBytes } if limit <= 0 { return 0 } return limit + 10*1024*1024 }