{"record":{"id":"bde99dd39e81c5d6","repo":"cloudreve/cloudreve","slug":"utf7-bad-utf-7-encoding","errorCode":null,"errorMessage":"utf7: bad utf-7 encoding","messagePattern":"utf7: bad utf-7 encoding","errorType":"http","errorClass":"ErrBadUTF7","httpStatus":500,"severity":"warning","filePath":"pkg/wopi/utf7.go","lineNumber":80,"sourceCode":"}\n\nfunc (e *simpleEncoding) NewDecoder() *encoding.Decoder {\n\treturn &encoding.Decoder{Transformer: e.Decoder}\n}\n\nfunc (e *simpleEncoding) NewEncoder() *encoding.Encoder {\n\treturn &encoding.Encoder{Transformer: e.Encoder}\n}\n\nvar (\n\tUTF7 encoding.Encoding = &simpleEncoding{\n\t\tutf7Decoder{},\n\t\tutf7Encoder{},\n\t}\n)\n\n// ErrBadUTF7 is returned to indicate invalid modified UTF-7 encoding.\nvar ErrBadUTF7 = errors.New(\"utf7: bad utf-7 encoding\")\n\n// Base64 codec for code points outside of the 0x20-0x7E range.\nconst modifiedbase64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"\n\nvar u7enc = base64.NewEncoding(modifiedbase64)\n\nfunc isModifiedBase64(r byte) bool {\n\tif r >= 'A' && r <= 'Z' {\n\t\treturn true\n\t} else if r >= 'a' && r <= 'z' {\n\t\treturn true\n\t} else if r >= '0' && r <= '9' {\n\t\treturn true\n\t} else if r == '+' || r == '/' {\n\t\treturn true\n\t}\n\treturn false\n\t// bs := []byte(modifiedbase64)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/cloudreve/cloudreve/blob/20c95ad73f3a8bcb72887fea91ff31ab24fa1011/pkg/wopi/utf7.go#L62-L98","documentation":"wopi.ErrBadUTF7 signals invalid modified UTF-7 encoding while decoding (or encoding) strings. Modified UTF-7 (mUTF-7, the IMAP mailbox encoding) represents non-printable characters as base64 blocks delimited by '&' and terminating '-'; the decoder rejects malformed blocks, bad base64 characters, unterminated shifted sequences, or values that decode to invalid code points.","triggerScenarios":"A WOPI client sends a filename or mailbox-style path encoded in modified UTF-7 where a '&' shifted section contains characters outside the modified base64 alphabet, is never closed with '-', decodes to a rune sequence with surrogate issues, or the encoder is handed a rune it cannot represent. Decoding a plain UTF-8 string that happens to contain '&' followed by base64-looking characters also trips it.","commonSituations":"Integrating a WOPI office suite that URL-encodes names differently than expected; filenames with emoji/CJK characters double-encoded (UTF-8 bytes fed to the mUTF-7 decoder); protocol middleware corrupting '&' characters; clients sending UTF-7 where UTF-8 was required.","solutions":["Send the field as proper modified UTF-7 (&base64-) or plain ASCII, not raw UTF-8 with stray '&' characters","Escape literal '&' in mUTF-7 content as '&-'","Decode with UTF7.Decoder and treat ErrBadUTF7 as 'fall back to treating the input as UTF-8/ASCII'","Log the raw bytes on failure to identify double-encoding"],"exampleFix":"// before\nname, err := UTF7.NewDecoder().String(raw) // raw is actually UTF-8 -> may hit ErrBadUTF7\nif err != nil { return err }\n\n// after\nname, err := UTF7.NewDecoder().String(raw)\nif errors.Is(err, ErrBadUTF7) {\n    name = raw // input was not mUTF-7; treat as UTF-8\n} else if err != nil {\n    return err\n}","handlingStrategy":"fallback","validationCode":"// Cheap sanity check: only decode as mUTF-7 when '&' shifted sections look well-formed\nfunc looksLikeMUTF7(s string) bool {\n    inShift := false\n    for i := 0; i < len(s); i++ {\n        switch {\n        case s[i] == '&':\n            if inShift { return false }\n            inShift = true\n        case s[i] == '-':\n            inShift = false\n        case inShift && !isModifiedBase64Byte(s[i]):\n            return false\n        }\n    }\n    return !inShift // unterminated shift section is invalid\n}","typeGuard":null,"tryCatchPattern":"// Fall back to UTF-8 when mUTF-7 decoding fails\nname, err := UTF7.NewDecoder().String(raw)\nif errors.Is(err, ErrBadUTF7) {\n    name = raw // client sent UTF-8/ASCII; use as-is\n} else if err != nil {\n    return err\n}","preventionTips":["Escape literal '&' as '&-' when producing mUTF-7","Keep WOPI integration strings in one encoding end-to-end; log raw bytes on the first failure","Reject mUTF-7 encoder input containing '&' unless it is an intentional escape"],"tags":["utf-7","wopi","encoding","filenames"],"backgroundTag":null,"analyzedSha":"20c95ad73f3a8bcb72887fea91ff31ab24fa1011","analyzedAt":"2026-08-16T01:42:55.403Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}