-
Notifications
You must be signed in to change notification settings - Fork 4
/
config.go
132 lines (110 loc) · 3.66 KB
/
config.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* Copyright 2020-2021 by Matthew R. Wilson <[email protected]>
*
* This file is part of proxy3270.
*
* proxy3270 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* proxy3270 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with proxy3270. If not, see <https://www.gnu.org/licenses/>.
*/
package main
import (
"encoding/json"
"fmt"
"os"
"regexp"
"strings"
)
const MaxServers = 999
const MaxNameLength = 65
const MaxAppTitleLength = 79
const MaxDisclaimerLineLength = 79
const defaultTitle = "3270 Proxy Application"
type Config struct {
Title string `json:"title"`
Disclaimer string `json:"disclaimer"`
Servers []ServerConfig `json:"servers"`
}
type ServerConfig struct {
Name string `json:"name"`
Host string `json:"host"`
Port uint `json:"port"`
UseTLS bool `json:"secure"`
IgnoreCertValidation bool `json:"ignoreCertValidation"`
}
func loadConfig(path string) (*Config, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
decoder := json.NewDecoder(f)
var config Config
err = decoder.Decode(&config)
if err != nil {
return nil, err
}
// Ensure a title is set
config.Title = strings.TrimSpace(config.Title)
if config.Title == "" {
config.Title = defaultTitle
}
// Trim the disclaimer, but blank is permitted
config.Disclaimer = strings.TrimSpace(config.Disclaimer)
return &config, nil
}
func validateConfig(config *Config) error {
if len(config.Title) > MaxAppTitleLength {
return fmt.Errorf("Application title is too long: max %d characters",
MaxAppTitleLength)
}
if !validateEbcdicString(config.Title) {
return fmt.Errorf("Application title contains illegal character")
}
if !validateEbcdicString(config.Disclaimer) {
return fmt.Errorf("Disclaimer text contains illegal character")
}
if _, line2 := wrapDisclaimer(
config.Disclaimer, MaxDisclaimerLineLength); len(line2) > MaxDisclaimerLineLength {
return fmt.Errorf("The word-wrapped disclaimer text exceeds two lines")
}
if len(config.Servers) > MaxServers {
return fmt.Errorf("Too many server configurations (%d): max %d",
len(config.Servers), MaxServers)
}
for i := range config.Servers {
if len(strings.TrimSpace(config.Servers[i].Name)) == 0 {
return fmt.Errorf("Server index %d has a blank name", i)
}
if len(config.Servers[i].Name) > MaxNameLength {
return fmt.Errorf("Server `%s` name too long: max %d characters",
config.Servers[i].Name, MaxNameLength)
}
if len(strings.TrimSpace(config.Servers[i].Host)) == 0 {
return fmt.Errorf("Host missing on server `%s`", config.Servers[i].Name)
}
if config.Servers[i].Port == 0 {
return fmt.Errorf("Port missing on server `%s`", config.Servers[i].Name)
}
if config.Servers[i].Port > 65535 {
return fmt.Errorf("Port %d invalid on server `%s`",
config.Servers[i].Port, config.Servers[i].Name)
}
}
return nil
}
// validateEbcdicString will return true if the input string contains only
// allowed characters, false otherwise.
var validEdcdicStringRegexp = regexp.MustCompile("^[a-zA-Z0-9 ,.;:!|\\\\/<>@#$%^&*(){}\\-_+=~`\"']*$")
func validateEbcdicString(input string) bool {
return validEdcdicStringRegexp.MatchString(input)
}