Fix #104338: Error performing BAT pack

Use RFC 2047 (aka MIME encoding) to send the original filename when
uploading a file to the Shaman server.

HTTP headers should be ASCII-only, and some systems use Latin-1 as
fallback. That's not suitable in general, though, because almost all
characters fall outside the Latin-1 range.
This commit is contained in:
Sybren A. Stüvel 2024-09-30 11:25:46 +02:00
parent 1f562b3cbc
commit 2e0e211b26
3 changed files with 33 additions and 2 deletions

View File

@ -17,6 +17,7 @@ bugs in actually-released versions.
- Security updates of dependencies:
- [GO-2024-3106: Stack exhaustion in Decoder.Decode in encoding/gob](https://pkg.go.dev/vuln/GO-2024-3106)
- Fix bug where database foreign key constraints could be deactivated ([#104305](https://projects.blender.org/studio/flamenco/issues/104305)).
- Fix bug when submitting a file with a non-ASCII name via Shaman ([#104338](https://projects.blender.org/studio/flamenco/issues/104338)).
## 3.5 - released 2024-04-16

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
"""BAT interface for sending files to the Manager via the Shaman API."""
import email.header
import logging
import random
import platform
@ -366,6 +367,7 @@ class Transferrer(submodules.transfer.FileTransferer): # type: ignore
)
local_filepath = self._rel_to_local_path[file_spec.path]
filename_header = _encode_original_filename_header(file_spec.path)
try:
with local_filepath.open("rb") as file_reader:
self.shaman_api.shaman_file_store(
@ -373,7 +375,7 @@ class Transferrer(submodules.transfer.FileTransferer): # type: ignore
filesize=file_spec.size,
body=file_reader,
x_shaman_can_defer_upload=can_defer,
x_shaman_original_filename=file_spec.path,
x_shaman_original_filename=filename_header,
)
except ApiException as ex:
if ex.status == 425:
@ -527,3 +529,16 @@ def _root_path_strip(path: PurePath) -> PurePosixPath:
if path.is_absolute():
return PurePosixPath(*path.parts[1:])
return PurePosixPath(path)
def _encode_original_filename_header(filename: str) -> str:
"""Encode the 'original filename' as valid HTTP Header.
See the specs for the X-Shaman-Original-Filename header in the OpenAPI
operation `shamanFileStore`, defined in flamenco-openapi.yaml.
"""
# This is a no-op when the filename is already in ASCII.
fake_header = email.header.Header()
fake_header.append(filename, charset="utf-8")
return fake_header.encode()

View File

@ -3,6 +3,7 @@ package api_impl
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"mime"
"net/http"
"github.com/labstack/echo/v4"
@ -110,8 +111,22 @@ func (f *Flamenco) ShamanFileStore(e echo.Context, checksum string, filesize int
canDefer = *params.XShamanCanDeferUpload
logCtx = logCtx.Bool("canDefer", canDefer)
}
if params.XShamanOriginalFilename != nil {
origFilename = *params.XShamanOriginalFilename
rawHeadervalue := *params.XShamanOriginalFilename
decoder := mime.WordDecoder{}
var err error // origFilename has to be used from the outer scope.
origFilename, err = decoder.DecodeHeader(rawHeadervalue)
if err != nil {
logger := logCtx.Logger()
logger.Error().
Str("headerValue", rawHeadervalue).
Err(err).
Msg("shaman: received invalid X-Shaman-Original-Filename header")
return sendAPIError(e, http.StatusBadRequest, "invalid X-Shaman-Original-Filename header: %q", rawHeadervalue)
}
logCtx = logCtx.Str("originalFilename", origFilename)
}
logger := logCtx.Logger()