/
digest_base64url_decode.go
88 lines (76 loc) · 2.52 KB
/
digest_base64url_decode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Code generated by __generator__/interpreter.go at once
package builtin
import (
"bufio"
"bytes"
"encoding/base64"
"io"
"strings"
"github.com/ysugimoto/falco/interpreter/context"
"github.com/ysugimoto/falco/interpreter/function/errors"
"github.com/ysugimoto/falco/interpreter/value"
)
const Digest_base64url_decode_Name = "digest.base64url_decode"
var Digest_base64url_decode_ArgumentTypes = []value.Type{value.StringType}
func Digest_base64url_decode_Validate(args []value.Value) error {
if len(args) != 1 {
return errors.ArgumentNotEnough(Digest_base64url_decode_Name, 1, args)
}
for i := range args {
if args[i].Type() != Digest_base64url_decode_ArgumentTypes[i] {
return errors.TypeMismatch(Digest_base64url_decode_Name, i+1, Digest_base64url_decode_ArgumentTypes[i], args[i].Type())
}
}
return nil
}
// Fastly built-in function implementation of digest.base64url_decode
// Arguments may be:
// - STRING
// Reference: https://developer.fastly.com/reference/vcl/functions/cryptographic/digest-base64url-decode/
func Digest_base64url_decode(ctx *context.Context, args ...value.Value) (value.Value, error) {
// Argument validations
if err := Digest_base64url_decode_Validate(args); err != nil {
return value.Null, err
}
input := value.Unwrap[*value.String](args[0])
removed := Digest_base64url_decode_removeInvalidCharacters(input.Value)
dec, _ := base64.URLEncoding.DecodeString(removed)
return &value.String{Value: string(terminateNullByte(dec))}, nil
}
func Digest_base64url_decode_removeInvalidCharacters(input string) string {
removed := new(bytes.Buffer)
r := bufio.NewReader(strings.NewReader(input))
for {
b, err := r.ReadByte()
if err == io.EOF {
break
}
switch {
case b >= 0x41 && b <= 0x5A: // A-Z
removed.WriteByte(b)
case b >= 0x61 && b <= 0x7A: // a-z
removed.WriteByte(b)
case b >= 0x31 && b <= 0x39: // 0-9
removed.WriteByte(b)
case b == 0x2B: // + should replace to -
removed.WriteByte(0x2D)
case b == 0x2F: // / should replace to _
removed.WriteByte(0x5F)
case b == 0x2D || b == 0x5F: // + or /
removed.WriteByte(b)
case b == 0x3D: // =
// If "=" sign found, next byte must also be "="
if peek, err := r.Peek(1); err != nil && peek[0] == 0x3D {
removed.WriteByte(b)
removed.WriteByte(b)
r.ReadByte() // skip next "=" character
continue
}
// Otherwise, treat as invalid character, stop decoding
return string(base64_padding(removed.Bytes()))
default:
// Invalid characters, skip it
}
}
return string(base64_padding(removed.Bytes()))
}