-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.v
More file actions
157 lines (139 loc) · 3.55 KB
/
main.v
File metadata and controls
157 lines (139 loc) · 3.55 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
module main
import os
import flag
import json
const app_version = '0.9.0'
const app_name = 'pfjson'
const app_author = 'Felix Ehlers'
const app_license = 'MIT License'
struct Config {
mut:
encode bool
decode bool
check bool
dry_run bool
verify bool
force bool
json_output bool
input string
output string
}
struct FileMetadata {
filename string
timestamp string // when the parsing was done
filesize i64
checksums Checksums
}
struct Checksums {
sha256 string
sha512 string
}
struct PfJsonOutput {
metadata FileMetadata
raw_text string @[omitempty] // Keep for compatibility but usually empty
lines []PfLine // Primary line-by-line structure
}
struct JsonResponse {
success bool
message string
data map[string]string @[optional]
error string @[optional]
}
struct ConfigElement {
line_num int
element_type string
content string
}
fn main() {
mut fp := flag.new_flag_parser(os.args)
fp.application(app_name)
fp.version("v${app_version}")
fp.description('A CLI tool to convert OpenBSD Packet Filter configuration files (`pf.conf`) to JSON and vice versa.')
encode := fp.bool('encode', `e`, false, 'Encode pf.conf to JSON')
decode := fp.bool('decode', `d`, false, 'Decode JSON to pf.conf')
check := fp.bool('check', `c`, false, 'Syntax check only')
dry_run := fp.bool('dry-run', `n`, false, 'Dry run mode')
verify := fp.bool('verify', `v`, false, 'Strict checksum verification (fail on mismatch)')
force := fp.bool('force', `f`, false, 'Force overwrite existing output files')
json_output := fp.bool('json', `j`, false, 'Machine-parsable JSON output')
additional_args := fp.finalize() or {
eprintln(err)
exit(1)
}
if !encode && !decode {
eprintln('Error: Must specify either -e (encode) or -d (decode)')
exit(1)
}
if encode && decode {
eprintln('Error: Cannot specify both -e and -d')
exit(1)
}
// Skip the program name in additional_args
actual_args := if additional_args.len > 0 && additional_args[0] == os.args[0] {
additional_args[1..]
} else {
additional_args
}
// Handle argument parsing for input/output
mut input_file := ''
mut output_file := ''
if actual_args.len == 0 {
// No arguments - use stdin for input
input_file = '-'
} else if actual_args.len == 1 {
// One argument - could be input file or output file (if stdin is implied)
// Check if it looks like a readable file
if actual_args[0] == '-' || os.exists(actual_args[0]) {
// It's an input file (stdin or existing file)
input_file = actual_args[0]
} else {
// It's likely an output file, assume stdin for input
input_file = '-'
output_file = actual_args[0]
}
} else {
// Two or more arguments - first is input, second is output
input_file = actual_args[0]
output_file = actual_args[1]
}
mut config := Config{
encode: encode
decode: decode
check: check
dry_run: dry_run
verify: verify
force: force
json_output: json_output
input: input_file
output: output_file
}
if config.encode {
encode_pf_to_json(config) or {
if config.json_output {
response := JsonResponse{
success: false
message: 'Encoding failed'
error: err.msg()
}
eprintln(json.encode(response))
} else {
eprintln('Error encoding: ${err}')
}
exit(1)
}
} else if config.decode {
decode_json_to_pf(config) or {
if config.json_output {
response := JsonResponse{
success: false
message: 'Decoding failed'
error: err.msg()
}
eprintln(json.encode(response))
} else {
eprintln('Error decoding: ${err}')
}
exit(1)
}
}
}