mirror of https://github.com/subgraph/fw-daemon
parent
d8f63bc60a
commit
8678419026
@ -0,0 +1,114 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
"github.com/subgraph/fw-daemon/fw-settings/definitions"
|
||||
)
|
||||
|
||||
const (
|
||||
defsFolder = "definitions"
|
||||
xmlExtension = ".xml"
|
||||
)
|
||||
|
||||
func getDefinitionWithFileFallback(uiName string) string {
|
||||
// this makes sure a missing definition wont break only when the app is released
|
||||
uiDef := getDefinition(uiName)
|
||||
|
||||
fileName := filepath.Join(defsFolder, uiName+xmlExtension)
|
||||
if fileNotFound(fileName) {
|
||||
log.Printf("gui: loading compiled definition %q\n", uiName)
|
||||
return uiDef.String()
|
||||
}
|
||||
|
||||
return readFile(fileName)
|
||||
}
|
||||
|
||||
// This must be called from the UI thread - otherwise bad things will happen sooner or later
|
||||
func builderForDefinition(uiName string) *gtk.Builder {
|
||||
// assertInUIThread()
|
||||
|
||||
template := getDefinitionWithFileFallback(uiName)
|
||||
|
||||
builder, err := gtk.BuilderNew()
|
||||
if err != nil {
|
||||
//We cant recover from this
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = builder.AddFromString(template)
|
||||
if err != nil {
|
||||
//This is a programming error
|
||||
panic(fmt.Sprintf("gui: failed load %s: %s\n", uiName, err.Error()))
|
||||
}
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
func fileNotFound(fileName string) bool {
|
||||
_, fnf := os.Stat(fileName)
|
||||
return os.IsNotExist(fnf)
|
||||
}
|
||||
|
||||
func readFile(fileName string) string {
|
||||
file, _ := os.Open(fileName)
|
||||
reader := bufio.NewScanner(file)
|
||||
var content string
|
||||
for reader.Scan() {
|
||||
content = content + reader.Text()
|
||||
}
|
||||
file.Close()
|
||||
return content
|
||||
}
|
||||
|
||||
func getDefinition(uiName string) fmt.Stringer {
|
||||
def, ok := definitions.Get(uiName)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("No definition found for %s", uiName))
|
||||
}
|
||||
|
||||
return def
|
||||
}
|
||||
|
||||
type builder struct {
|
||||
*gtk.Builder
|
||||
}
|
||||
|
||||
func newBuilder(uiName string) *builder {
|
||||
return &builder{builderForDefinition(uiName)}
|
||||
}
|
||||
|
||||
func (b *builder) getItem(name string, target interface{}) {
|
||||
v := reflect.ValueOf(target)
|
||||
if v.Kind() != reflect.Ptr {
|
||||
panic("builder.getItem() target argument must be a pointer")
|
||||
}
|
||||
elem := v.Elem()
|
||||
elem.Set(reflect.ValueOf(b.get(name)))
|
||||
}
|
||||
|
||||
func (b *builder) getItems(args ...interface{}) {
|
||||
for len(args) >= 2 {
|
||||
name, ok := args[0].(string)
|
||||
if !ok {
|
||||
panic("string argument expected in builder.getItems()")
|
||||
}
|
||||
b.getItem(name, args[1])
|
||||
args = args[2:]
|
||||
}
|
||||
}
|
||||
|
||||
func (b *builder) get(name string) glib.IObject {
|
||||
obj, err := b.GetObject(name)
|
||||
if err != nil {
|
||||
panic("builder.GetObject() failed: " + err.Error())
|
||||
}
|
||||
return obj
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
"github.com/op/go-logging"
|
||||
)
|
||||
|
||||
var levelToId = map[int32]string{
|
||||
int32(logging.ERROR): "error",
|
||||
int32(logging.WARNING): "warning",
|
||||
int32(logging.NOTICE): "notice",
|
||||
int32(logging.INFO): "info",
|
||||
int32(logging.DEBUG): "debug",
|
||||
}
|
||||
|
||||
var idToLevel = func() map[string]int32 {
|
||||
m := make(map[string]int32)
|
||||
for k, v := range levelToId {
|
||||
m[v] = k
|
||||
}
|
||||
return m
|
||||
}()
|
||||
|
||||
func loadConfig(win *gtk.Window, b *builder, dbus *dbusObject) {
|
||||
var levelCombo *gtk.ComboBoxText
|
||||
var redactCheck *gtk.CheckButton
|
||||
|
||||
b.getItems(
|
||||
"level_combo", &levelCombo,
|
||||
"redact_checkbox", &redactCheck,
|
||||
)
|
||||
|
||||
conf, err := dbus.getConfig()
|
||||
if err != nil {
|
||||
failDialog(win, "Failed to load config from fw daemon: %v", err)
|
||||
}
|
||||
|
||||
if lvl, ok := conf["loglevel"].(int32); ok {
|
||||
if id, ok := levelToId[lvl]; ok {
|
||||
levelCombo.SetActiveID(id)
|
||||
}
|
||||
}
|
||||
if v, ok := conf["logredact"].(bool); ok {
|
||||
redactCheck.SetActive(v)
|
||||
}
|
||||
b.ConnectSignals(map[string]interface{}{
|
||||
"on_level_combo_changed": func() {
|
||||
if lvl, ok := idToLevel[levelCombo.GetActiveID()]; ok {
|
||||
dbus.setConfig("loglevel", lvl)
|
||||
}
|
||||
},
|
||||
"on_redact_checkbox_toggled": func() {
|
||||
dbus.setConfig("logredact", redactCheck.GetActive())
|
||||
},
|
||||
})
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/godbus/dbus"
|
||||
)
|
||||
|
||||
type dbusObject struct {
|
||||
dbus.BusObject
|
||||
}
|
||||
|
||||
type dbusRule struct {
|
||||
Id uint32
|
||||
App string
|
||||
Path string
|
||||
Verb uint32
|
||||
Target string
|
||||
}
|
||||
|
||||
func newDbusObject() (*dbusObject, error) {
|
||||
conn, err := dbus.SystemBus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dbusObject{conn.Object("com.subgraph.Firewall", "/com/subgraph/Firewall")}, nil
|
||||
}
|
||||
|
||||
func (ob *dbusObject) isEnabled() (bool, error) {
|
||||
var flag bool
|
||||
if err := ob.Call("com.subgraph.Firewall.IsEnabled", 0).Store(&flag); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return flag, nil
|
||||
}
|
||||
|
||||
func (ob *dbusObject) listRules() ([]dbusRule, error) {
|
||||
rules := []dbusRule{}
|
||||
if err := ob.Call("com.subgraph.Firewall.ListRules", 0).Store(&rules); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (ob *dbusObject) deleteRule(id uint32) {
|
||||
ob.Call("com.subgraph.Firewall.DeleteRule", 0, id)
|
||||
}
|
||||
|
||||
func (ob *dbusObject) updateRule(rule *dbusRule) {
|
||||
ob.Call("com.subgraph.Firewall.UpdateRule", 0, rule)
|
||||
}
|
||||
|
||||
func (ob *dbusObject) getConfig() (map[string]interface{}, error) {
|
||||
res := make(map[string]dbus.Variant)
|
||||
if err := ob.Call("com.subgraph.Firewall.GetConfig", 0).Store(&res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config := make(map[string]interface{})
|
||||
for k, v := range res {
|
||||
config[k] = v.Value()
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (ob *dbusObject) setConfig(key string, val interface{}) {
|
||||
ob.Call("com.subgraph.Firewall.SetConfig", 0, key, dbus.MakeVariant(val))
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.19.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="title" translatable="yes">Firewall Settings</property>
|
||||
<property name="default_width">600</property>
|
||||
<property name="default_height">400</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkNotebook" id="notebook">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="margin_bottom">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Firewall Rules</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">12</property>
|
||||
<property name="margin_top">8</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Rules</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">8</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Log Level:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="level_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<items>
|
||||
<item id="error" translatable="yes">Error</item>
|
||||
<item id="warning" translatable="yes">Warning</item>
|
||||
<item id="notice" translatable="yes">Notice</item>
|
||||
<item id="info" translatable="yes">Info</item>
|
||||
<item id="debug" translatable="yes">Debug</item>
|
||||
</items>
|
||||
<signal name="changed" handler="on_level_combo_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="redact_checkbox">
|
||||
<property name="label" translatable="yes">Remove host names and addresses from logs</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_redact_checkbox_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Logging</property>
|
||||
<property name="ellipsize">start</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Options</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@ -0,0 +1,8 @@
|
||||
generate:
|
||||
ruby ./generate.rb
|
||||
|
||||
touch:
|
||||
ls *.xml | xargs -n1 touch
|
||||
|
||||
doctor: touch generate
|
||||
git diff --exit-code .
|
@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.19.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkDialog" id="dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Edit Rule</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="dialog-action_area1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="cancel_button">
|
||||
<property name="label" translatable="yes">Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="ok_button">
|
||||
<property name="label" translatable="yes">Ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="yalign">0.60000002384185791</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="margin_bottom">24</property>
|
||||
<property name="row_spacing">24</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Enter changes for firewall rule below. The character <b>*</b> can entered alone into either the <b>host</b> or <b>port</b> fields to match any value.
|
||||
</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="max_width_chars">40</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="path_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="column_spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="verb_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<items>
|
||||
<item id="allow" translatable="yes">Allow</item>
|
||||
<item id="deny" translatable="yes">Deny</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Connections to <b>host:</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="host_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_width_chars">34</property>
|
||||
<property name="placeholder_text" translatable="yes">hostname or ip address</property>
|
||||
<signal name="changed" handler="on_host_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">on <b>port:</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="port_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_length">5</property>
|
||||
<property name="width_chars">4</property>
|
||||
<property name="max_width_chars">5</property>
|
||||
<property name="placeholder_text" translatable="yes">Port</property>
|
||||
<signal name="changed" handler="on_port_changed" swapped="no"/>
|
||||
<signal name="insert-text" handler="on_port_insert_text" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="label" translatable="yes">Path:</property>
|
||||
<property name="xalign">1</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="1">cancel_button</action-widget>
|
||||
<action-widget response="2">ok_button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.19.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="app_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin_left">8</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="verb_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="xalign">1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="target_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="edit_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="relief">none</property>
|
||||
<signal name="clicked" handler="on_edit_rule" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">document-properties-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="delete_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="relief">none</property>
|
||||
<signal name="clicked" handler="on_delete_rule" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">edit-delete-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@ -0,0 +1,200 @@
|
||||
package definitions
|
||||
|
||||
func init() {
|
||||
add(`Dialog`, &defDialog{})
|
||||
}
|
||||
|
||||
type defDialog struct{}
|
||||
|
||||
func (*defDialog) String() string {
|
||||
return `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.19.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="title" translatable="yes">Firewall Settings</property>
|
||||
<property name="default_width">600</property>
|
||||
<property name="default_height">400</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkNotebook" id="notebook">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="margin_bottom">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Firewall Rules</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">12</property>
|
||||
<property name="margin_top">8</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Rules</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_top">8</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Log Level:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="level_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<items>
|
||||
<item id="error" translatable="yes">Error</item>
|
||||
<item id="warning" translatable="yes">Warning</item>
|
||||
<item id="notice" translatable="yes">Notice</item>
|
||||
<item id="info" translatable="yes">Info</item>
|
||||
<item id="debug" translatable="yes">Debug</item>
|
||||
</items>
|
||||
<signal name="changed" handler="on_level_combo_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="redact_checkbox">
|
||||
<property name="label" translatable="yes">Remove host names and addresses from logs</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_redact_checkbox_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Logging</property>
|
||||
<property name="ellipsize">start</property>
|
||||
<property name="xalign">0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Options</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab_fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
||||
`
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'fileutils'
|
||||
|
||||
def parse_go_name(file_name)
|
||||
File.basename(file_name, ".xml").
|
||||
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
||||
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
||||
tr("-", "_").
|
||||
gsub(/\/_/, '/').
|
||||
downcase + ".go"
|
||||
end
|
||||
|
||||
def gen_go_file(xml_file, go_file)
|
||||
xml_definition = File.read(xml_file)
|
||||
ui_name = File.basename(xml_file, '.xml')
|
||||
File.open(go_file, 'w+') do |target|
|
||||
target.puts <<TEMPLATE
|
||||
package definitions
|
||||
|
||||
func init() {
|
||||
\tadd(`#{ui_name}`, &def#{ui_name}{})
|
||||
}
|
||||
|
||||
type def#{ui_name} struct{}
|
||||
|
||||
func (*def#{ui_name}) String() string {
|
||||
\treturn `
|
||||
#{xml_definition}
|
||||
`
|
||||
}
|
||||
TEMPLATE
|
||||
end
|
||||
end
|
||||
|
||||
def file_mtime(nm)
|
||||
return Time.at(0) unless File.exists?(nm)
|
||||
File.mtime(nm)
|
||||
end
|
||||
|
||||
Dir[File.join(File.dirname(__FILE__), '*.xml')].each do |file_name|
|
||||
go_file = parse_go_name file_name
|
||||
if file_mtime(file_name) > file_mtime(go_file) || file_mtime(__FILE__) > file_mtime(go_file)
|
||||
STDERR.puts " - #{file_name} -> #{go_file}"
|
||||
gen_go_file(file_name, go_file)
|
||||
end
|
||||
end
|
@ -0,0 +1,25 @@
|
||||
package definitions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var lock sync.RWMutex
|
||||
var definitions = make(map[string]fmt.Stringer)
|
||||
|
||||
// Get returns the XML description of a UI definition and whether it was found
|
||||
func Get(uiName string) (fmt.Stringer, bool) {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
|
||||
def, ok := definitions[uiName]
|
||||
return def, ok
|
||||
}
|
||||
|
||||
func add(uiName string, def fmt.Stringer) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
definitions[uiName] = def
|
||||
}
|
@ -0,0 +1,214 @@
|
||||
package definitions
|
||||
|
||||
func init() {
|
||||
add(`RuleEdit`, &defRuleEdit{})
|
||||
}
|
||||
|
||||
type defRuleEdit struct{}
|
||||
|
||||
func (*defRuleEdit) String() string {
|
||||
return `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.19.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkDialog" id="dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Edit Rule</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="dialog-action_area1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="cancel_button">
|
||||
<property name="label" translatable="yes">Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="ok_button">
|
||||
<property name="label" translatable="yes">Ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="yalign">0.60000002384185791</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">12</property>
|
||||
<property name="margin_top">12</property>
|
||||
<property name="margin_bottom">24</property>
|
||||
<property name="row_spacing">24</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Enter changes for firewall rule below. The character <b>*</b> can entered alone into either the <b>host</b> or <b>port</b> fields to match any value.
|
||||
</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="max_width_chars">40</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="path_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="column_spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="verb_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<items>
|
||||
<item id="allow" translatable="yes">Allow</item>
|
||||
<item id="deny" translatable="yes">Deny</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Connections to <b>host:</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="host_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_width_chars">34</property>
|
||||
<property name="placeholder_text" translatable="yes">hostname or ip address</property>
|
||||
<signal name="changed" handler="on_host_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">on <b>port:</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="port_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_length">5</property>
|
||||
<property name="width_chars">4</property>
|
||||
<property name="max_width_chars">5</property>
|
||||
<property name="placeholder_text" translatable="yes">Port</property>
|
||||
<signal name="changed" handler="on_port_changed" swapped="no"/>
|
||||
<signal name="insert-text" handler="on_port_insert_text" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">12</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="label" translatable="yes">Path:</property>
|
||||
<property name="xalign">1</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="1">cancel_button</action-widget>
|
||||
<action-widget response="2">ok_button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
|
||||
`
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package definitions
|
||||
|
||||
func init() {
|
||||
add(`RuleItem`, &defRuleItem{})
|
||||
}
|
||||
|
||||
type defRuleItem struct{}
|
||||
|
||||
func (*defRuleItem) String() string {
|
||||
return `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.19.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<object class="GtkGrid" id="grid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="app_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="verb_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="xalign">1</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="target_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="edit_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="relief">none</property>
|
||||
<signal name="clicked" handler="on_edit_rule" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">document-properties-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="delete_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="relief">none</property>
|
||||
<signal name="clicked" handler="on_delete_rule" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">edit-delete-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
||||
`
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"fmt"
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
func failDialog(parent *gtk.Window, format string, args ...interface{}) {
|
||||
d := gtk.MessageDialogNew(parent, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
|
||||
format, args...)
|
||||
d.Run()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func activate(app *gtk.Application) {
|
||||
win := app.GetActiveWindow()
|
||||
if win != nil {
|
||||
win.Present()
|
||||
return
|
||||
}
|
||||
|
||||
var scrolled *gtk.ScrolledWindow
|
||||
|
||||
b := newBuilder("Dialog")
|
||||
b.getItems(
|
||||
"window", &win,
|
||||
"scrolledwindow", &scrolled,
|
||||
)
|
||||
win.SetIconName("security-high-symbolic")
|
||||
|
||||
box, _ := gtk.ListBoxNew()
|
||||
scrolled.Add(box)
|
||||
|
||||
dbus, err := newDbusObject()
|
||||
if err != nil {
|
||||
failDialog(win, "Failed to connect to dbus system bus: %v", err)
|
||||
}
|
||||
|
||||
rl := NewRuleList(dbus, win, box)
|
||||
|
||||
if _, err := dbus.isEnabled(); err != nil {
|
||||
failDialog(win, "Unable is connect to firewall daemon. Is it running?")
|
||||
}
|
||||
rl.loadRules()
|
||||
loadConfig(win, b, dbus)
|
||||
app.AddWindow(win)
|
||||
win.ShowAll()
|
||||
}
|
||||
|
||||
func main() {
|
||||
app, err := gtk.ApplicationNew("com.subgraph.Firewall.settings", glib.APPLICATION_FLAGS_NONE)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("gtk.ApplicationNew() failed: %v", err))
|
||||
}
|
||||
app.Connect("activate", activate)
|
||||
app.Run(os.Args)
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
editDialogCancel = 1
|
||||
editDialogOk = 2
|
||||
)
|
||||
|
||||
type ruleEdit struct {
|
||||
row *ruleRow
|
||||
dialog *gtk.Dialog
|
||||
pathLabel *gtk.Label
|
||||
verbCombo *gtk.ComboBoxText
|
||||
hostEntry *gtk.Entry
|
||||
portEntry *gtk.Entry
|
||||
ok *gtk.Button
|
||||
}
|
||||
|
||||
func newRuleEdit(rr *ruleRow) *ruleEdit {
|
||||
redit := &ruleEdit{row: rr}
|
||||
b := newBuilder("RuleEdit")
|
||||
b.getItems(
|
||||
"dialog", &redit.dialog,
|
||||
"path_label", &redit.pathLabel,
|
||||
"verb_combo", &redit.verbCombo,
|
||||
"host_entry", &redit.hostEntry,
|
||||
"port_entry", &redit.portEntry,
|
||||
"ok_button", &redit.ok,
|
||||
)
|
||||
b.ConnectSignals(map[string]interface{}{
|
||||
"on_port_insert_text": redit.onPortInsertText,
|
||||
"on_port_changed": redit.onChanged,
|
||||
"on_host_changed": redit.onChanged,
|
||||
})
|
||||
return redit
|
||||
}
|
||||
|
||||
func (re *ruleEdit) updateDialogFields() {
|
||||
r := re.row.rule
|
||||
re.pathLabel.SetText(r.Path)
|
||||
if r.Verb == RULE_ALLOW {
|
||||
re.verbCombo.SetActiveID("allow")
|
||||
} else {
|
||||
re.verbCombo.SetActiveID("deny")
|
||||
}
|
||||
target := strings.Split(r.Target, ":")
|
||||
if len(target) != 2 {
|
||||
return
|
||||
}
|
||||
re.hostEntry.SetText(target[0])
|
||||
re.portEntry.SetText(target[1])
|
||||
}
|
||||
|
||||
func (re *ruleEdit) validateFields() bool {
|
||||
id := re.verbCombo.GetActiveID()
|
||||
if id != "allow" && id != "deny" {
|
||||
return false
|
||||
}
|
||||
host, _ := re.hostEntry.GetText()
|
||||
port, _ := re.portEntry.GetText()
|
||||
if !isValidHost(host) {
|
||||
return false
|
||||
}
|
||||
if !isValidPort(port) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isValidHost(host string) bool {
|
||||
if host == "*" {
|
||||
return true
|
||||
}
|
||||
if net.ParseIP(host) != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
parts := strings.Split(host, ".")
|
||||
if len(parts) < 2 {
|
||||
return false
|
||||
}
|
||||
for _, part := range parts {
|
||||
if part == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isValidPort(port string) bool {
|
||||
if port == "*" {
|
||||
return true
|
||||
}
|
||||
|
||||
pval, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return pval > 0 && pval <= 0xFFFF
|
||||
}
|
||||
|
||||
func (re *ruleEdit) updateRow() {
|
||||
if !re.validateFields() {
|
||||
return
|
||||
}
|
||||
r := re.row.rule
|
||||
switch re.verbCombo.GetActiveID() {
|
||||
case "allow":
|
||||
r.Verb = RULE_ALLOW
|
||||
case "deny":
|
||||
r.Verb = RULE_DENY
|
||||
}
|
||||
host, _ := re.hostEntry.GetText()
|
||||
port, _ := re.portEntry.GetText()
|
||||
r.Target = fmt.Sprintf("%s:%s", host, port)
|
||||
re.row.update()
|
||||
}
|
||||
|
||||
func (re *ruleEdit) run() {
|
||||
re.dialog.SetTransientFor(re.row.rl.win)
|
||||
if re.dialog.Run() == editDialogOk {
|
||||
re.updateRow()
|
||||
re.row.rl.dbus.updateRule(re.row.rule)
|
||||
}
|
||||
re.dialog.Destroy()
|
||||
}
|
||||
|
||||
func (rr *ruleRow) runEditor() {
|
||||
redit := newRuleEdit(rr)
|
||||
redit.updateDialogFields()
|
||||
redit.run()
|
||||
}
|
||||
|
||||
func (re *ruleEdit) onPortInsertText(entry *gtk.Entry, text string) {
|
||||
current, _ := entry.GetText()
|
||||
if current == "" && text == "*" {
|
||||
return
|
||||
}
|
||||
if current == "*" {
|
||||
entry.StopEmission("insert-text")
|
||||
return
|
||||
}
|
||||
for _, c := range text {
|
||||
if !unicode.IsDigit(c) {
|
||||
entry.StopEmission("insert-text")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (re *ruleEdit) onChanged() {
|
||||
re.ok.SetSensitive(re.validateFields())
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ruleList struct {
|
||||
dbus *dbusObject
|
||||
win *gtk.Window
|
||||
list *gtk.ListBox
|
||||
col1 *gtk.SizeGroup
|
||||
col2 *gtk.SizeGroup
|
||||
col3 *gtk.SizeGroup
|
||||
}
|
||||
|
||||
type ruleRow struct {
|
||||
rl *ruleList
|
||||
rule *dbusRule
|
||||
widget *gtk.ListBoxRow
|
||||
app_label *gtk.Label
|
||||
verb_label *gtk.Label
|
||||
target_label *gtk.Label
|
||||
}
|
||||
|
||||
func NewRuleList(dbus *dbusObject, win *gtk.Window, list *gtk.ListBox) *ruleList {
|
||||
rl := &ruleList{dbus: dbus, win: win, list: list}
|
||||
rl.col1, _ = gtk.SizeGroupNew(gtk.SIZE_GROUP_HORIZONTAL)
|
||||
rl.col2, _ = gtk.SizeGroupNew(gtk.SIZE_GROUP_HORIZONTAL)
|
||||
rl.col3, _ = gtk.SizeGroupNew(gtk.SIZE_GROUP_HORIZONTAL)
|
||||
return rl
|
||||
}
|
||||
|
||||
func (rl *ruleList) loadRules() error {
|
||||
rules, err := rl.dbus.listRules()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rl.addRules(rules)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rl *ruleList) addRules(rules []dbusRule) {
|
||||
for i := 0; i < len(rules); i++ {
|
||||
row := createWidget(&rules[i])
|
||||
row.rl = rl
|
||||
rl.col1.AddWidget(row.app_label)
|
||||
rl.col2.AddWidget(row.verb_label)
|
||||
rl.col3.AddWidget(row.target_label)
|
||||
rl.list.Add(row.widget)
|
||||
}
|
||||
}
|
||||
|
||||
const RULE_DENY = 0
|
||||
const RULE_ALLOW = 1
|
||||
|
||||
func createWidget(rule *dbusRule) *ruleRow {
|
||||
row := &ruleRow{}
|
||||
row.rule = rule
|
||||
builder := newBuilder("RuleItem")
|
||||
var grid *gtk.Grid
|
||||
builder.getItems(
|
||||
"grid", &grid,
|
||||
"app_label", &row.app_label,
|
||||
"verb_label", &row.verb_label,
|
||||
"target_label", &row.target_label,
|
||||
)
|
||||
builder.ConnectSignals(map[string]interface{}{
|
||||
"on_edit_rule": row.onEdit,
|
||||
"on_delete_rule": row.onDelete,
|
||||
})
|
||||
row.widget, _ = gtk.ListBoxRowNew()
|
||||
row.widget.Add(grid)
|
||||
row.update()
|
||||
return row
|
||||
}
|
||||
|
||||
func (rr *ruleRow) update() {
|
||||
rr.app_label.SetText(rr.rule.App)
|
||||
rr.app_label.SetTooltipText(rr.rule.Path)
|
||||
rr.verb_label.SetText(getVerbText(rr.rule))
|
||||
rr.target_label.SetText(getTargetText(rr.rule))
|
||||
}
|
||||
|
||||
func getVerbText(rule *dbusRule) string {
|
||||
if rule.Verb == RULE_ALLOW {
|
||||
return "ALLOW:"
|
||||
}
|
||||
return "DENY:"
|
||||
}
|
||||
|
||||
func getTargetText(rule *dbusRule) string {
|
||||
if rule.Target == "*:*" {
|
||||
return "All connections"
|
||||
}
|
||||
items := strings.Split(rule.Target, ":")
|
||||
|
||||
if len(items) != 2 {
|
||||
return rule.Target
|
||||
}
|
||||
|
||||
if items[0] == "*" {
|
||||
return fmt.Sprintf("Connections to All hosts on port %s", items[1])
|
||||
}
|
||||
if items[1] == "*" {
|
||||
return fmt.Sprintf("All connections to host %s")
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Connections to %s on port %s", items[0], items[1])
|
||||
}
|
||||
|
||||
func (rr *ruleRow) onEdit() {
|
||||
rr.runEditor()
|
||||
}
|
||||
|
||||
func (rr *ruleRow) onDelete() {
|
||||
body := fmt.Sprintf(`Are you sure you want to delete this rule:
|
||||
|
||||
<b>Path:</b> %s
|
||||
|
||||
<b>Rule:</b> %s %s`, rr.rule.Path, getVerbText(rr.rule), getTargetText(rr.rule))
|
||||
d := gtk.MessageDialogNewWithMarkup(
|
||||
rr.rl.win,
|
||||
gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
gtk.MESSAGE_QUESTION,
|
||||
gtk.BUTTONS_OK_CANCEL,
|
||||
"")
|
||||
d.SetMarkup(body)
|
||||
if d.Run() == (int)(gtk.RESPONSE_OK) {
|
||||
rr.delete()
|
||||
}
|
||||
d.Destroy()
|
||||
|
||||
}
|
||||
|
||||
func (rl *ruleList) remove(rr *ruleRow) {
|
||||
rl.col1.RemoveWidget(rr.app_label)
|
||||
rl.col2.RemoveWidget(rr.verb_label)
|
||||
rl.col3.RemoveWidget(rr.target_label)
|
||||
rl.list.Remove(rr.widget)
|
||||
}
|
||||
|
||||
func (rr *ruleRow) delete() {
|
||||
rr.rl.remove(rr)
|
||||
rr.rl.dbus.deleteRule(rr.rule.Id)
|
||||
}
|
Loading…
Reference in new issue