env.go RawHistoryFolder
1package domain
2
3import (
4 "bufio"
5 "bytes"
6 "regexp"
7 "strings"
8)
9
10var envKeyRegex = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`)
11var containerNameRegex = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_-]*$`)
12
13// SanitizeDomainForEnvFile validates and sanitizes a domain name for env file storage.
14// Returns the collision-resistant storage key used for filenames.
15func SanitizeDomainForEnvFile(domainName string) (string, error) {
16 safeDomain, err := NewEnvStorageKey(domainName)
17 if err != nil {
18 return "", err
19 }
20
21 return string(safeDomain), nil
22}
23
24// ParseEnvData parses env data into a key-value map.
25func ParseEnvData(data []byte) (map[string]string, error) {
26 secrets := make(map[string]string)
27 scanner := bufio.NewScanner(bytes.NewReader(data))
28 // Allow large env values (certs/keys) without hitting the default ~64KB limit.
29 scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
30 for scanner.Scan() {
31 line := strings.TrimSpace(scanner.Text())
32 if line == "" || strings.HasPrefix(line, "#") {
33 continue
34 }
35
36 parts := strings.SplitN(line, "=", 2)
37 if len(parts) != 2 {
38 continue
39 }
40
41 key := strings.TrimSpace(parts[0])
42 rawValue := parts[1]
43
44 trimmedValue := strings.TrimSpace(rawValue)
45 value := trimmedValue
46
47 if len(trimmedValue) >= 2 {
48 if (strings.HasPrefix(trimmedValue, "\"") && strings.HasSuffix(trimmedValue, "\"")) ||
49 (strings.HasPrefix(trimmedValue, "'") && strings.HasSuffix(trimmedValue, "'")) {
50 value = trimmedValue[1 : len(trimmedValue)-1]
51 }
52 }
53
54 if key != "" {
55 secrets[key] = value
56 }
57 }
58
59 if err := scanner.Err(); err != nil {
60 return nil, err
61 }
62
63 return secrets, nil
64}
65
66// ValidateEnvKey validates an env key for storage.
67func ValidateEnvKey(key string) error {
68 if key == "" {
69 return ErrInvalidEnvKey
70 }
71 if strings.Contains(key, "..") || strings.ContainsAny(key, "/\\") {
72 return ErrPathTraversal
73 }
74 if !envKeyRegex.MatchString(key) {
75 return ErrInvalidEnvKey
76 }
77 return nil
78}
79
80// ValidateContainerName validates a container name for attachment storage.
81// Container names can contain alphanumeric characters, hyphens, and underscores,
82// but must start with a letter.
83func ValidateContainerName(name string) error {
84 if name == "" {
85 return ErrInvalidContainerName
86 }
87 if strings.Contains(name, "..") || strings.ContainsAny(name, "/\\") {
88 return ErrPathTraversal
89 }
90 if !containerNameRegex.MatchString(name) {
91 return ErrInvalidContainerName
92 }
93 return nil
94}