Skip to content

Commit 6e2064a

Browse files
committed
Fix Edit feature + add README
1 parent 177c49a commit 6e2064a

File tree

3 files changed

+43
-29
lines changed

3 files changed

+43
-29
lines changed

LICENSE.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2018 Oliver Kuederle
3+
Copyright (c) 2022 Thomas Pellegatta
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# tufw
2+
3+
A terminal UI for `ufw`
4+
5+
## Licence
6+
[MIT](https://github.com/peltho/tufw/blob/main/LICENSE.txt)

main.go

+36-28
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"log"
77
"os/exec"
88
"regexp"
9+
"strconv"
910
"strings"
1011

1112
"github.com/gdamore/tcell/v2"
@@ -47,11 +48,11 @@ func (t *Tui) Init() {
4748
}
4849

4950
func (t *Tui) LoadTableData() ([]string, error) {
50-
err, out, _ := shellout("ufw status | sed '/^$/d' | awk '{$2=$2};1' | tail -n +4 | sed -r 's/^(([0-9]{1,3}\\.){3}[0-9])\\s(.*)(\\/[a-z]{3})/\\1\\4 \\3/;s/^(([0-9]*)\\/([a-z]{3}))/\\3 \\2/;s/(\\w)\\s(\\(v6\\))$/\\1\\2/;s/\\(v6\\)//'")
51+
err, out, _ := shellout("ufw status | sed '/^$/d' | awk '{$2=$2};1' | tail -n +4 | sed -r 's/^(([0-9]{1,3}\\.){3}[0-9]{1,3})\\s(.*)(\\/[a-z]{3})/\\1\\4 \\3/;s/^(([0-9]*)\\/([a-z]{3}))/\\3 \\2/;s/(\\w)\\s(\\(v6\\))$/\\1\\2/;s/\\(v6\\)//'")
52+
5153
if err != nil {
5254
log.Printf("error: %v\n", err)
5355
}
54-
5556
rows := strings.Split(out, "\n")
5657

5758
return rows, nil
@@ -78,18 +79,14 @@ func (t *Tui) CreateTable(rows []string) {
7879
cols := strings.Fields(row)
7980

8081
value := ""
81-
if len(cols) < len(columns) && c >= len(cols) {
82-
t.table.SetCell(r+1, c+1, tview.NewTableCell(value).SetTextColor(tcell.ColorWhite).SetAlign(tview.AlignCenter).SetExpansion(1))
83-
} else {
84-
// Conditional statement for displaying Comments if any
85-
if c >= 4 {
86-
value = strings.Join(cols[c:], " ")
87-
} else {
88-
value = cols[c]
89-
}
90-
91-
t.table.SetCell(r+1, c+1, tview.NewTableCell(value).SetTextColor(tcell.ColorWhite).SetAlign(tview.AlignCenter).SetExpansion(1))
82+
switch {
83+
case c >= 4:
84+
value = strings.Join(cols[c:], " ")
85+
default:
86+
value = cols[c]
9287
}
88+
89+
t.table.SetCell(r+1, c+1, tview.NewTableCell(value).SetTextColor(tcell.ColorWhite).SetAlign(tview.AlignCenter).SetExpansion(1))
9390
}
9491
}
9592

@@ -203,15 +200,25 @@ func (t *Tui) EditForm() {
203200
t.help.SetText("Use <Tab> and <Enter> keys to navigate through the form").SetBorderPadding(1, 0, 1, 1)
204201

205202
to := t.table.GetCell(row, 1).Text
206-
re := regexp.MustCompile(`((([0-9]{1,3}\.){3}[0-9]{1,3})/)?([a-z]{3})`)
207-
match := re.FindStringSubmatch(to)
203+
rip := regexp.MustCompile(`(([0-9]{1,3}\.){3}[0-9]{1,3})(/[0-9]{1,2})?`)
204+
rproto := regexp.MustCompile(`/?([a-z]{3})`)
205+
matchIP := rip.FindStringSubmatch(to)
206+
matchProto := rproto.FindStringSubmatch(to)
208207

209208
toValue := ""
210-
proto := match[0]
211-
if match[4] != "" {
212-
toValue = match[2]
213-
proto = match[4]
209+
proto := ""
210+
if len(matchIP) > 0 {
211+
toValue = matchIP[0]
214212
}
213+
if len(matchProto) > 1 {
214+
proto = matchProto[1]
215+
}
216+
217+
portValue := ""
218+
port := t.table.GetCell(row, 2).Text
219+
rport := regexp.MustCompile(`([0-9]*)(/[a-z]{3})?`)
220+
matchPort := rport.FindStringSubmatch(port)
221+
portValue = matchPort[1]
215222

216223
protocolOptionIndex := 1
217224
if proto == "tcp" {
@@ -238,13 +245,13 @@ func (t *Tui) EditForm() {
238245
comment := strings.ReplaceAll(t.table.GetCell(row, 5).Text, "# ", "")
239246

240247
t.form.AddInputField("To", toValue, 20, nil, nil).SetFieldTextColor(tcell.ColorWhite).
241-
AddInputField("Port *", t.table.GetCell(row, 2).Text, 20, nil, nil).SetFieldTextColor(tcell.ColorWhite).
248+
AddInputField("Port *", portValue, 20, validatePort, nil).SetFieldTextColor(tcell.ColorWhite).
242249
AddDropDown("Protocol *", []string{"tcp", "udp"}, protocolOptionIndex, nil).
243250
AddDropDown("Action *", []string{"ALLOW", "DENY", "REJECT", "LIMIT"}, actionOptionIndex, nil).
244251
AddInputField("From", fromValue, 20, nil, nil).
245252
AddInputField("Comment", comment, 40, nil, nil).
246253
AddButton("Save", func() { t.CreateRule(row); t.table.SetSelectable(false, false) }).
247-
AddButton("Cancel", func() { t.Cancel(); t.table.SetSelectable(false, false) }).
254+
AddButton("Cancel", func() { t.CreateRule(row); t.Reset(); t.table.SetSelectable(false, false) }).
248255
SetButtonTextColor(tcell.ColorWhite).
249256
SetButtonBackgroundColor(tcell.ColorDarkCyan).
250257
SetFieldBackgroundColor(tcell.ColorDarkCyan).
@@ -316,13 +323,13 @@ func (t *Tui) CreateForm() {
316323
t.help.SetText("Use <Tab> and <Enter> keys to navigate through the form").SetBorderPadding(1, 0, 1, 1)
317324

318325
t.form.AddInputField("To", "", 20, nil, nil).SetFieldTextColor(tcell.ColorWhite).
319-
AddInputField("Port *", "", 20, nil, nil).SetFieldTextColor(tcell.ColorWhite).
326+
AddInputField("Port *", "", 20, validatePort, nil).SetFieldTextColor(tcell.ColorWhite).
320327
AddDropDown("Protocol *", []string{"tcp", "udp"}, 0, nil).
321328
AddDropDown("Action *", []string{"ALLOW", "DENY", "REJECT", "LIMIT"}, 0, nil).
322329
AddInputField("From", "", 20, nil, nil).
323330
AddInputField("Comment", "", 40, nil, nil).
324331
AddButton("Save", func() { t.CreateRule() }).
325-
AddButton("Cancel", t.Cancel).
332+
AddButton("Cancel", t.Reset).
326333
SetButtonTextColor(tcell.ColorWhite).
327334
SetButtonBackgroundColor(tcell.ColorDarkCyan).
328335
SetFieldBackgroundColor(tcell.ColorDarkCyan).
@@ -331,6 +338,11 @@ func (t *Tui) CreateForm() {
331338
t.secondHelp.SetText("* Mandatory field\n\nTo and From fields match any and Anywhere if left empty").SetTextColor(tcell.ColorDarkCyan).SetBorderPadding(0, 0, 1, 1)
332339
}
333340

341+
func validatePort(text string, ch rune) bool {
342+
_, err := strconv.Atoi(text)
343+
return err == nil
344+
}
345+
334346
func (t *Tui) Reset() {
335347
t.pages.HidePage("form")
336348
t.form.Clear(true)
@@ -339,10 +351,6 @@ func (t *Tui) Reset() {
339351
t.app.SetFocus(t.menu)
340352
}
341353

342-
func (t *Tui) Cancel() {
343-
t.Reset()
344-
}
345-
346354
func (t *Tui) CreateLayout() *tview.Pages {
347355
columns := tview.NewFlex().SetDirection(tview.FlexColumn)
348356

@@ -377,7 +385,7 @@ func main() {
377385

378386
if len(data) <= 1 {
379387
tui.pages.HidePage("base")
380-
tui.CreateModal("ufw is disabled. Do you want to enable it?",
388+
tui.CreateModal("ufw is disabled.\nDo you want to enable it?",
381389
func() {
382390
shellout("ufw --force enable")
383391
},

0 commit comments

Comments
 (0)