Created pre-functional replacement GUI for fw-daemon prompter that is independent of gnome-shell.

shw_dev
shw 8 years ago
parent c3635093fa
commit e3833190bf

@ -0,0 +1,3 @@
To get this to work, first edit /usr/share/gnome-shell/modes/subgraph.json
Remove the entry for "firewall@subgraph.com", hit CTRL+F2 and then issue the reload "r" command.
Reset these changes to revert back to the old gnome-shell prompt.

@ -0,0 +1,73 @@
package main
import (
"errors"
"github.com/godbus/dbus"
"log"
// "github.com/gotk3/gotk3/glib"
)
type dbusServer struct {
conn *dbus.Conn
run bool
}
type promptData struct {
Application string
Icon string
Path string
Address string
Port int
IP string
Origin string
Proto string
UID int
GID int
Username string
Groupname string
Pid int
OptString string
Expanded bool
Expert bool
Action int
}
func newDbusServer() (*dbusServer, error) {
conn, err := dbus.SystemBus()
if err != nil {
return nil, err
}
reply, err := conn.RequestName("com.subgraph.FirewallPrompt", dbus.NameFlagDoNotQueue)
if err != nil {
return nil, err
}
if reply != dbus.RequestNameReplyPrimaryOwner {
return nil, errors.New("Bus name is already owned")
}
ds := &dbusServer{}
if err := conn.Export(ds, "/com/subgraph/FirewallPrompt", "com.subgraph.FirewallPrompt"); err != nil {
return nil, err
}
ds.conn = conn
ds.run = true
return ds, nil
}
func (ds *dbusServer) RequestPrompt(application, icon, path, address string, port int32, ip, origin, proto string, uid, gid int32, username, groupname string, pid int32,
optstring string, expanded, expert bool, action int32) (int32, string, *dbus.Error) {
log.Printf("REALLY GOT IT!")
log.Printf("app = %s, icon = %s, path = %s, address = %s, action = %v\n", application, icon, path, address, action)
addRequest(nil, path, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, optstring)
// glib.IdleAdd(func, data)
return 0, "bla bla bla", nil
}

@ -0,0 +1,510 @@
package main
import (
"github.com/gotk3/gotk3/gtk"
"github.com/gotk3/gotk3/glib"
"log"
"fmt"
"os"
"io/ioutil"
"encoding/json"
"os/user"
"strconv"
)
type fpPreferences struct {
Winheight uint
Winwidth uint
Wintop uint
Winleft uint
}
var userPrefs fpPreferences
var mainWin *gtk.Window
var Notebook *gtk.Notebook
var globalLS *gtk.ListStore
func promptInfo(msg string) {
dialog := gtk.MessageDialogNew(mainWin, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Displaying full log info:")
// dialog.SetDefaultGeometry(500, 200)
tv, err := gtk.TextViewNew()
if err != nil {
log.Fatal("Unable to create TextView:", err)
}
tvbuf, err := tv.GetBuffer()
if err != nil {
log.Fatal("Unable to get buffer:", err)
}
tvbuf.SetText(msg)
tv.SetEditable(false)
tv.SetWrapMode(gtk.WRAP_WORD)
scrollbox, err := gtk.ScrolledWindowNew(nil, nil)
if err != nil {
log.Fatal("Unable to create scrolled window:", err)
}
scrollbox.Add(tv)
scrollbox.SetSizeRequest(600, 100)
box, err := dialog.GetContentArea()
if err != nil {
log.Fatal("Unable to get content area of dialog:", err)
}
box.Add(scrollbox)
dialog.ShowAll()
dialog.Run()
dialog.Destroy()
//self.set_default_size(150, 100)
}
func promptChoice(msg string) int {
dialog := gtk.MessageDialogNew(mainWin, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO, msg)
result := dialog.Run()
dialog.Destroy()
return result
}
func promptError(msg string) {
dialog := gtk.MessageDialogNew(mainWin, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, "Error: %s", msg)
dialog.Run()
dialog.Destroy()
}
func getConfigPath() string {
usr, err := user.Current()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: could not determine location of user preferences file:", err, "\n");
return ""
}
prefPath := usr.HomeDir + "/.fwprompt.json"
return prefPath
}
func savePreferences() bool {
usr, err := user.Current()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: could not determine location of user preferences file:", err, "\n");
return false
}
prefPath := usr.HomeDir + "/.fwprompt.json"
jsonPrefs, err := json.Marshal(userPrefs)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: could not generate user preferences data:", err, "\n")
return false
}
err = ioutil.WriteFile(prefPath, jsonPrefs, 0644)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: could not save user preferences data:", err, "\n")
return false
}
return true
}
func loadPreferences() bool {
usr, err := user.Current()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: could not determine location of user preferences file: %v", err, "\n");
return false
}
prefPath := usr.HomeDir + "/.fwprompt.json"
fmt.Println("xxxxxxxxxxxxxxxxxxxxxx preferences path = ", prefPath)
jfile, err := ioutil.ReadFile(prefPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: could not read preference data from file: %v", err, "\n")
return false
}
err = json.Unmarshal(jfile, &userPrefs)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: could not load preferences data from file: %v", err, "\n")
return false
}
fmt.Println(userPrefs)
return true
}
func get_hbox() *gtk.Box {
hbox, err := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
if err != nil {
log.Fatal("Unable to create horizontal box:", err)
}
return hbox
}
func get_label(text string) *gtk.Label {
label, err := gtk.LabelNew(text)
if err != nil {
log.Fatal("Unable to create label in GUI:", err)
return nil
}
return label
}
func createColumn(title string, id int) *gtk.TreeViewColumn {
cellRenderer, err := gtk.CellRendererTextNew()
if err != nil {
log.Fatal("Unable to create text cell renderer:", err)
}
column, err := gtk.TreeViewColumnNewWithAttribute(title, cellRenderer, "text", id)
if err != nil {
log.Fatal("Unable to create cell column:", err)
}
column.SetSortColumnID(id)
column.SetResizable(true)
return column
}
func createListStore(general bool) *gtk.ListStore {
colData := []glib.Type{glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_STRING}
listStore, err := gtk.ListStoreNew(colData...)
if err != nil {
log.Fatal("Unable to create list store:", err)
}
return listStore
}
func addRequest(listStore *gtk.ListStore, path, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin, optstring string) {
if listStore == nil {
listStore = globalLS
}
iter := listStore.Append()
colVals := make([]interface{}, 11)
colVals[0] = 1
colVals[1] = path
colVals[2] = proto
colVals[3] = pid
colVals[4] = ipaddr
colVals[5] = hostname
colVals[6] = port
colVals[7] = uid
colVals[8] = gid
colVals[9] = origin
colVals[10] = optstring
colNums := make([]int, len(colVals))
for n := 0; n < len(colVals); n++ {
colNums[n] = n
}
err := listStore.Set(iter, colNums, colVals)
if err != nil {
log.Fatal("Unable to add row:", err)
}
}
func setup_settings() {
box, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
if err != nil {
log.Fatal("Unable to create settings box:", err)
}
scrollbox, err := gtk.ScrolledWindowNew(nil, nil)
if err != nil {
log.Fatal("Unable to create settings scrolled window:", err)
}
hLabel, err := gtk.LabelNew("Settings")
if err != nil {
log.Fatal("Unable to create notebook label:", err)
}
scrollbox.Add(box)
scrollbox.SetSizeRequest(600, 800)
tv, err := gtk.TreeViewNew()
if err != nil {
log.Fatal("Unable to create treeview:", err)
}
h := get_hbox()
l := get_label("Log to file:")
b, err := gtk.ButtonNewWithLabel("Save")
if err != nil {
log.Fatal("Unable to create button:", err)
}
h.PackStart(l, false, true, 10)
h.PackStart(b, false, true, 10)
h.SetMarginTop(10)
box.Add(h)
h = get_hbox()
h.SetMarginTop(0)
h.SetMarginBottom(20)
box.Add(h)
box.Add(tv)
b.Connect("clicked", func() {
fmt.Println("CLICKED")
if err != nil {
promptError("Unexpected error saving log file info: "+err.Error())
return
}
})
Notebook.AppendPage(scrollbox, hLabel)
}
func main() {
_, err := newDbusServer();
if err != nil {
log.Fatal("Error:", err)
return
}
loadPreferences()
gtk.Init(nil)
// Create a new toplevel window, set its title, and connect it to the "destroy" signal to exit the GTK main loop when it is destroyed.
mainWin, err = gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
if err != nil {
log.Fatal("Unable to create window:", err)
}
mainWin.SetTitle("SGOS fw-daemon Prompter")
mainWin.Connect("destroy", func() {
fmt.Println("Shutting down...")
savePreferences()
gtk.MainQuit()
})
mainWin.Connect("configure-event", func() {
w, h := mainWin.GetSize()
userPrefs.Winwidth, userPrefs.Winheight = uint(w), uint(h)
l, t := mainWin.GetPosition()
userPrefs.Winleft, userPrefs.Wintop = uint(l), uint(t)
})
mainWin.SetPosition(gtk.WIN_POS_CENTER)
Notebook, err = gtk.NotebookNew()
if err != nil {
log.Fatal("Unable to create new notebook:", err)
}
loglevel := "Pending Approval"
nbLabel, err := gtk.LabelNew(loglevel)
if err != nil {
log.Fatal("Unable to create notebook label:", err)
}
box, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
if err != nil {
log.Fatal("Unable to create box:", err)
}
scrollbox, err := gtk.ScrolledWindowNew(nil, nil)
if err != nil {
log.Fatal("Unable to create scrolled window:", err)
}
scrollbox.Add(box)
tv, err := gtk.TreeViewNew()
if err != nil {
log.Fatal("Unable to create treeview:", err)
}
tv.SetSizeRequest(300, 300)
tv.SetHeadersClickable(true)
ab, err := gtk.ButtonNewWithLabel("Approve")
if err != nil {
log.Fatal("Unable to create button:", err)
}
db, err := gtk.ButtonNewWithLabel("Deny")
if err != nil {
log.Fatal("Unable to create button:", err)
}
ib, err := gtk.ButtonNewWithLabel("Ignore")
if err != nil {
log.Fatal("Unable to create button:", err)
}
bb := get_hbox()
bb.PackStart(ab, false, false, 5)
bb.PackStart(db, false, false, 5)
bb.PackStart(ib, false, false, 5)
// box.Add(tv)
box.PackStart(bb, false, false, 5)
box.PackStart(tv, false, true, 5)
tv.AppendColumn(createColumn("#", 0))
tv.AppendColumn(createColumn("Path", 1))
tv.AppendColumn(createColumn("Protocol", 2))
tv.AppendColumn(createColumn("PID", 3))
tv.AppendColumn(createColumn("IP Address", 4))
tv.AppendColumn(createColumn("Hostname", 5))
tv.AppendColumn(createColumn("Port", 6))
tv.AppendColumn(createColumn("UID", 7))
tv.AppendColumn(createColumn("GID", 8))
tv.AppendColumn(createColumn("Origin", 9))
tv.AppendColumn(createColumn("Details", 10))
listStore := createListStore(true)
globalLS = listStore
tv.SetModel(listStore)
ab.Connect("clicked", func() {
promptError("Approving firewall request.")
/* choice := promptChoice("hmm?")
if choice != int(gtk.RESPONSE_YES) {
return
} */
})
db.Connect("clicked", func() {
promptError("Denying firewall request.")
})
db.Connect("clicked", func() {
promptError("Ignoring firewall request.")
})
tv.Connect("row-activated", func() {
fmt.Println("DOUBLE CLICK")
sel, err := tv.GetSelection()
if err != nil {
promptError("Unexpected error retrieving selection: "+err.Error())
return
}
rows := sel.GetSelectedRows(listStore)
// func (v *TreeSelection) GetSelected() (model ITreeModel, iter *TreeIter, ok bool) ???
fmt.Println("RETURNED ROWS: ", rows.Length())
if rows.Length() > 0 {
rdata := rows.NthData(0)
lIndex, err := strconv.Atoi(rdata.(*gtk.TreePath).String())
if err != nil {
promptError("Unexpected error reading selection data: "+err.Error())
return
}
path, err := gtk.TreePathNewFromString(fmt.Sprintf("%d", lIndex))
if err != nil {
promptError("Unexpected error reading data from selection: "+err.Error())
return
}
iter, err := listStore.GetIter(path)
if err != nil {
promptError("Unexpected error looking up log entry: "+err.Error())
return
}
val, err := listStore.GetValue(iter, 6)
if err != nil {
promptError("Unexpected error getting data from log entry: "+err.Error())
return
}
sval, err := val.GetString()
if err != nil {
promptError("Unexpected error reading data from log entry: "+err.Error())
return
}
fmt.Println("HEH: ", sval)
promptInfo(sval)
}
})
scrollbox.SetSizeRequest(600, 800)
Notebook.AppendPage(scrollbox, nbLabel)
setup_settings()
mainWin.Add(Notebook)
if userPrefs.Winheight > 0 && userPrefs.Winwidth > 0 {
fmt.Printf("height was %d, width was %d\n", userPrefs.Winheight, userPrefs.Winwidth)
mainWin.Resize(int(userPrefs.Winwidth), int(userPrefs.Winheight))
} else {
mainWin.SetDefaultSize(800, 600)
}
if userPrefs.Wintop > 0 && userPrefs.Winleft > 0 {
mainWin.Move(int(userPrefs.Winleft), int(userPrefs.Wintop))
}
// addRequest(listStore, "/bin/bla", "proto", 666, "loglevel", "provider", 23, 100, 1000)
mainWin.ShowAll()
mainWin.SetKeepAbove(true)
gtk.Main()
}
Loading…
Cancel
Save