mirror of https://github.com/subgraph/fw-daemon
Updated fw-settings to reflect all recent changes Moved rule notifications to dbus signal Lots of various fixes Local changes to gtk bindings ... And so much more...shw-merge
parent
61710110d2
commit
cfaf7b84ff
@ -0,0 +1,573 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.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="role">SubgraphFirewallNewRule</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="icon_name">alacarte</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="deletable">False</property>
|
||||
<property name="startup_id">SubgraphFirewallNewRule</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="action_btnbox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="layout_style">spread</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="allow_button">
|
||||
<property name="label" translatable="yes">_Allow</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="use_underline">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="cancel_button">
|
||||
<property name="label" translatable="yes">_Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</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="can_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<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>
|
||||
<signal name="changed" handler="on_verb_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">5</property>
|
||||
<property name="column_spacing">10</property>
|
||||
<property name="row_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="path_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Path:</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="GtkLabel" id="sandbox_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Sandbox:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="uid_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">UID:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="gid_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">GID:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFileChooserButton" id="path_chooser">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="create_folders">False</property>
|
||||
<property name="preview_widget_active">False</property>
|
||||
<property name="use_preview_label">False</property>
|
||||
<property name="title" translatable="yes">Select Executable Path</property>
|
||||
<signal name="file-set" handler="on_path_changed" swapped="no"/>
|
||||
<signal name="file-set" handler="on_path_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="scope_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Scope:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="sandbox_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="proto_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Protocol:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="host_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Host:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="host_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="width_chars">64</property>
|
||||
<property name="max_width_chars">34</property>
|
||||
<property name="primary_icon_tooltip_markup" translatable="yes" context="The character * can be use to match any value.">The character <b>*</b> can be use to match any value.</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">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="port_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="max_length">5</property>
|
||||
<property name="width_chars">4</property>
|
||||
<property name="max_width_chars">5</property>
|
||||
<property name="primary_icon_tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</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">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="port_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Port:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="sandbox_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">SANDBOX</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pid_title">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Pid:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pid_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">PID_LABEL</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="scope_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">SCOPE_LABEL</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="baseline_position">top</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="uid_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<property name="active_id">-1</property>
|
||||
<items>
|
||||
<item id="-1">Any User</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="uid_checkbox">
|
||||
<property name="label" translatable="yes">Apply</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="gid_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<property name="active_id">-1</property>
|
||||
<items>
|
||||
<item id="-1">Any Group</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="gid_checkbox">
|
||||
<property name="label" translatable="yes">Apply</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="path_entry">
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="origin_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Origin:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="origin_entry">
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="scope_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<property name="active_id">0</property>
|
||||
<items>
|
||||
<item id="2" translatable="yes">Permanent</item>
|
||||
<item id="0" translatable="yes">Session</item>
|
||||
<item id="1" translatable="yes">Process</item>
|
||||
<item id="4" translatable="yes">Once</item>
|
||||
<item id="3" translatable="yes">System</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="proto_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">1</property>
|
||||
<property name="active_id">1</property>
|
||||
<items>
|
||||
<item translatable="yes">Any</item>
|
||||
<item id="tcp" translatable="yes">TCP</item>
|
||||
<item id="udp" translatable="yes">UDP</item>
|
||||
<item id="icmp" translatable="yes">ICMP</item>
|
||||
</items>
|
||||
<signal name="changed" handler="on_proto_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="tls_check">
|
||||
<property name="label" translatable="yes">TLS Only</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="3">allow_button</action-widget>
|
||||
<action-widget response="1">cancel_button</action-widget>
|
||||
<action-widget response="2">ok_button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
@ -0,0 +1,586 @@
|
||||
package definitions
|
||||
|
||||
func init() {
|
||||
add(`RuleNew`, &defRuleNew{})
|
||||
}
|
||||
|
||||
type defRuleNew struct{}
|
||||
|
||||
func (*defRuleNew) String() string {
|
||||
return `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.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="role">SubgraphFirewallNewRule</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="icon_name">alacarte</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="skip_taskbar_hint">True</property>
|
||||
<property name="deletable">False</property>
|
||||
<property name="startup_id">SubgraphFirewallNewRule</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="action_btnbox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="layout_style">spread</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="allow_button">
|
||||
<property name="label" translatable="yes">_Allow</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="use_underline">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="cancel_button">
|
||||
<property name="label" translatable="yes">_Cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</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="can_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<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>
|
||||
<signal name="changed" handler="on_verb_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="grid3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">5</property>
|
||||
<property name="column_spacing">10</property>
|
||||
<property name="row_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="path_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Path:</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="GtkLabel" id="sandbox_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Sandbox:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="uid_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">UID:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="gid_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">GID:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFileChooserButton" id="path_chooser">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="create_folders">False</property>
|
||||
<property name="preview_widget_active">False</property>
|
||||
<property name="use_preview_label">False</property>
|
||||
<property name="title" translatable="yes">Select Executable Path</property>
|
||||
<signal name="file-set" handler="on_path_changed" swapped="no"/>
|
||||
<signal name="file-set" handler="on_path_set" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="scope_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Scope:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="sandbox_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="proto_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Protocol:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="host_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Host:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="host_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="width_chars">64</property>
|
||||
<property name="max_width_chars">34</property>
|
||||
<property name="primary_icon_tooltip_markup" translatable="yes" context="The character * can be use to match any value.">The character <b>*</b> can be use to match any value.</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">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="port_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="max_length">5</property>
|
||||
<property name="width_chars">4</property>
|
||||
<property name="max_width_chars">5</property>
|
||||
<property name="primary_icon_tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</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">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="port_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Port:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="sandbox_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">SANDBOX</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pid_title">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Pid:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="pid_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">PID_LABEL</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="scope_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">SCOPE_LABEL</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<property name="baseline_position">top</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="uid_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<property name="active_id">-1</property>
|
||||
<items>
|
||||
<item id="-1">Any User</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="uid_checkbox">
|
||||
<property name="label" translatable="yes">Apply</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="gid_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<property name="active_id">-1</property>
|
||||
<items>
|
||||
<item id="-1">Any Group</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="gid_checkbox">
|
||||
<property name="label" translatable="yes">Apply</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="path_entry">
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="origin_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="tooltip_markup" translatable="yes">The character <b>*</b> can be use to match any value.</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="label" translatable="yes">Origin:</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="origin_entry">
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="no_show_all">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="scope_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">0</property>
|
||||
<property name="active_id">0</property>
|
||||
<items>
|
||||
<item id="2" translatable="yes">Permanent</item>
|
||||
<item id="0" translatable="yes">Session</item>
|
||||
<item id="1" translatable="yes">Process</item>
|
||||
<item id="4" translatable="yes">Once</item>
|
||||
<item id="3" translatable="yes">System</item>
|
||||
</items>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="proto_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">1</property>
|
||||
<property name="active_id">1</property>
|
||||
<items>
|
||||
<item translatable="yes">Any</item>
|
||||
<item id="tcp" translatable="yes">TCP</item>
|
||||
<item id="udp" translatable="yes">UDP</item>
|
||||
<item id="icmp" translatable="yes">ICMP</item>
|
||||
</items>
|
||||
<signal name="changed" handler="on_proto_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="tls_check">
|
||||
<property name="label" translatable="yes">TLS Only</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="3">allow_button</action-widget>
|
||||
<action-widget response="1">cancel_button</action-widget>
|
||||
<action-widget response="2">ok_button</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
|
||||
`
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/subgraph/oz"
|
||||
)
|
||||
|
||||
var ozProfiles oz.Profiles
|
||||
|
||||
func init() {
|
||||
c, err := oz.LoadConfig(oz.DefaultConfigPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to read oz config...")
|
||||
os.Exit(1)
|
||||
}
|
||||
p, err := oz.LoadProfiles(c.ProfileDir)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Unable to read oz profiles...")
|
||||
os.Exit(1)
|
||||
}
|
||||
ozProfiles = p
|
||||
}
|
||||
|
||||
func (fa *fwApp) initOZProfiles() {
|
||||
for _, p := range ozProfiles {
|
||||
// XXX: This actually should match against sgfw's opened sockets
|
||||
switch {
|
||||
case string(p.Networking.Nettype) == "host":
|
||||
fallthrough
|
||||
case len(p.Networking.Sockets) == 0:
|
||||
continue
|
||||
default:
|
||||
fa.ozProfiles = append(fa.ozProfiles, p.Name)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,901 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
spath "path"
|
||||
"strings"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/subgraph/fw-daemon/sgfw"
|
||||
|
||||
"github.com/gotk3/gotk3/gdk"
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
type Prompt struct {
|
||||
app *fwApp
|
||||
tv *gtk.TreeView
|
||||
ts *gtk.TreeStore
|
||||
stack *gtk.Stack
|
||||
pecols []*gtk.TreeViewColumn
|
||||
pncol *gtk.TreeViewColumn
|
||||
promptLock *sync.Mutex
|
||||
recentLock *sync.Mutex
|
||||
config *sgfw.FirewallConfigs
|
||||
recentlyRemoved []string
|
||||
}
|
||||
|
||||
const (
|
||||
COL_NO_NREFS = iota
|
||||
COL_NO_ICON_PIXBUF
|
||||
COL_NO_GUID
|
||||
COL_NO_PATH
|
||||
COL_NO_SANDBOX
|
||||
COL_NO_ICON
|
||||
COL_NO_PROTO
|
||||
COL_NO_PID
|
||||
COL_NO_DSTIP
|
||||
COL_NO_HOSTNAME
|
||||
COL_NO_PORT
|
||||
COL_NO_UID
|
||||
COL_NO_GID
|
||||
COL_NO_ORIGIN
|
||||
COL_NO_TIMESTAMP
|
||||
COL_NO_IS_SOCKS
|
||||
COL_NO_OPTSTRING
|
||||
COL_NO_ACTION
|
||||
COL_NO_FILLER
|
||||
COL_NO_LAST
|
||||
)
|
||||
|
||||
|
||||
type ruleColumns struct {
|
||||
nrefs int
|
||||
Path string
|
||||
Sandbox string
|
||||
GUID string
|
||||
Icon string
|
||||
Proto string
|
||||
Pid int
|
||||
Target string
|
||||
Hostname string
|
||||
Port int
|
||||
UID int
|
||||
GID int
|
||||
Uname string
|
||||
Gname string
|
||||
Origin string
|
||||
Timestamp string
|
||||
IsSocks bool
|
||||
ForceTLS bool
|
||||
Scope int
|
||||
}
|
||||
|
||||
func createPromptView(app *fwApp, sw *gtk.ScrolledWindow) (*Prompt, error) {
|
||||
var err error
|
||||
p := &Prompt{}
|
||||
p.app = app
|
||||
p.promptLock = &sync.Mutex{}
|
||||
p.recentLock = &sync.Mutex{}
|
||||
|
||||
p.tv, err = gtk.TreeViewNew()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.tv.SetSizeRequest(300, 300)
|
||||
p.tv.SetHeadersClickable(true)
|
||||
p.tv.SetEnableSearch(false)
|
||||
|
||||
p.tv.AppendColumn(createColumnText("#", COL_NO_NREFS))
|
||||
p.tv.AppendColumn(createColumnImg("", COL_NO_ICON_PIXBUF))
|
||||
|
||||
guidcol := createColumnText("GUID", COL_NO_GUID)
|
||||
guidcol.SetVisible(false)
|
||||
p.tv.AppendColumn(guidcol)
|
||||
|
||||
p.tv.AppendColumn(createColumnText("Path", COL_NO_PATH))
|
||||
|
||||
sbcol := createColumnText("Sandbox", COL_NO_SANDBOX)
|
||||
sbcol.SetVisible(false)
|
||||
p.tv.AppendColumn(sbcol)
|
||||
|
||||
icol := createColumnText("Icon", COL_NO_ICON)
|
||||
icol.SetVisible(false)
|
||||
p.tv.AppendColumn(icol)
|
||||
|
||||
var pecol *gtk.TreeViewColumn
|
||||
p.tv.AppendColumn(createColumnText("Protocol", COL_NO_PROTO))
|
||||
pecol = createColumnText("PID", COL_NO_PID)
|
||||
p.tv.AppendColumn(pecol)
|
||||
p.pecols = append(p.pecols, pecol)
|
||||
p.tv.AppendColumn(createColumnText("IP Address", COL_NO_DSTIP))
|
||||
pecol = createColumnText("Hostname", COL_NO_HOSTNAME)
|
||||
pecol.SetMinWidth(64)
|
||||
p.tv.AppendColumn(pecol)
|
||||
p.tv.AppendColumn(createColumnText("Port", COL_NO_PORT))
|
||||
pecol = createColumnText("UID", COL_NO_UID)
|
||||
p.tv.AppendColumn(pecol)
|
||||
p.pecols = append(p.pecols, pecol)
|
||||
pecol = createColumnText("GID", COL_NO_GID)
|
||||
p.tv.AppendColumn(pecol)
|
||||
p.pecols = append(p.pecols, pecol)
|
||||
pecol = createColumnText("Origin", COL_NO_ORIGIN)
|
||||
p.tv.AppendColumn(pecol)
|
||||
p.pecols = append(p.pecols, pecol)
|
||||
pecol = createColumnText("Timestamp", COL_NO_TIMESTAMP)
|
||||
p.tv.AppendColumn(pecol)
|
||||
p.pecols = append(p.pecols, pecol)
|
||||
|
||||
scol := createColumnText("Is SOCKS", COL_NO_IS_SOCKS)
|
||||
scol.SetVisible(false)
|
||||
p.tv.AppendColumn(scol)
|
||||
|
||||
pecol = createColumnText("Details", COL_NO_OPTSTRING)
|
||||
p.tv.AppendColumn(pecol)
|
||||
p.pecols = append(p.pecols, pecol)
|
||||
|
||||
acol := createColumnText("Scope", COL_NO_ACTION)
|
||||
acol.SetVisible(false)
|
||||
p.tv.AppendColumn(acol)
|
||||
|
||||
pncol := createColumnImg("", COL_NO_FILLER)
|
||||
pncol.SetVisible(false)
|
||||
pncol.SetSortIndicator(false)
|
||||
p.tv.AppendColumn(pncol)
|
||||
p.pncol = pncol
|
||||
|
||||
p.togglePECols()
|
||||
|
||||
p.ts = createTreeStore(true)
|
||||
|
||||
p.tv.SetModel(p.ts)
|
||||
p.tv.Connect("row-activated", func() {
|
||||
p.promptLock.Lock()
|
||||
seldata, _, _, err := p.getSelectedRule()
|
||||
p.promptLock.Unlock()
|
||||
if err != nil {
|
||||
warnDialog(&p.app.win.Window, "Unexpected error reading selected rule: " + err.Error() + "\n" + fmt.Sprintf("%+v", seldata))
|
||||
return
|
||||
}
|
||||
|
||||
rl := &ruleList{app: p.app}
|
||||
target := seldata.Hostname
|
||||
if target == "" {
|
||||
target = seldata.Target
|
||||
}
|
||||
rr := &ruleRow{ rl: rl, rule: &sgfw.DbusRule{
|
||||
Path: seldata.Path,
|
||||
Sandbox: seldata.Sandbox,
|
||||
Pid: uint32(seldata.Pid),
|
||||
UID: int32(seldata.UID),
|
||||
GID: int32(seldata.GID),
|
||||
Target: strings.Join([]string{target, strconv.Itoa(seldata.Port)}, ":"),
|
||||
Proto: seldata.Proto,
|
||||
Origin: seldata.Origin,
|
||||
IsSocks: seldata.IsSocks,
|
||||
}}
|
||||
redit := newRuleAdd(rr, DIALOG_MODE_PROMPT)
|
||||
redit.update()
|
||||
redit.run(seldata.GUID, p.buttonAction)
|
||||
return
|
||||
})
|
||||
|
||||
p.app.appendConfigCallback(p.togglePECols)
|
||||
|
||||
sw.SetSizeRequest(600, 400)
|
||||
p.createShortcuts()
|
||||
sw.Add(p.tv)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Prompt) HasItems() bool {
|
||||
return p.ts.IterNChildren(nil) > 0
|
||||
}
|
||||
|
||||
func (p *Prompt) togglePECols() {
|
||||
v := p.app.Config.PromptExpanded
|
||||
for _, pc := range p.pecols {
|
||||
pc.SetVisible(v)
|
||||
}
|
||||
p.pncol.SetVisible(!v)
|
||||
}
|
||||
|
||||
func (p *Prompt) createShortcuts() {
|
||||
// We register here since the shortcuts are bound in an ephemeral window
|
||||
p.app.RegisterShortcutHelp("<Alt>a", "prompt", "Allow")
|
||||
p.app.RegisterShortcutHelp("<Alt>d Escape", "prompt", "Deny")
|
||||
p.app.RegisterShortcutHelp("<Alt>c", "prompt", "Cancel")
|
||||
p.app.RegisterShortcutHelp("<Alt>h", "prompt", "Select the hostname/IP entry")
|
||||
p.app.RegisterShortcutHelp("<Alt>p", "prompt", "Select the port entry")
|
||||
p.app.RegisterShortcutHelp("<Alt>o", "prompt", "Select protocol")
|
||||
p.app.RegisterShortcutHelp("<Alt>t", "prompt", "Toggle allow TLS only")
|
||||
p.app.RegisterShortcutHelp("<Alt>s", "prompt", "Select scope")
|
||||
p.app.RegisterShortcutHelp("<Alt>u", "prompt", "Toggle apply UID")
|
||||
p.app.RegisterShortcutHelp("<Alt>g", "prompt", "Toggle apply GID")
|
||||
|
||||
p.app.ConnectShortcut("<Primary><Alt>space", "", "", p.app.win.Window, func (win gtk.Window) {
|
||||
vis := p.app.tlStack.GetVisibleChildName()
|
||||
iter, found := p.ts.GetIterFirst()
|
||||
if iter == nil || found == false && vis != "prompt" {
|
||||
return
|
||||
}
|
||||
if vis != "prompt" {
|
||||
p.app.tlStack.SetVisibleChildFull("prompt", gtk.STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT)
|
||||
p.app.onStackChanged()
|
||||
}
|
||||
pi, _ := p.ts.GetPath(iter)
|
||||
if pi != nil {
|
||||
p.tv.SetCursor(pi, nil, false)
|
||||
p.tv.Emit("row-activated")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createColumnImg(title string, id int) *gtk.TreeViewColumn {
|
||||
cellRenderer, err := gtk.CellRendererPixbufNew()
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create image cell renderer:", err)
|
||||
}
|
||||
|
||||
column, err := gtk.TreeViewColumnNewWithAttribute(title, cellRenderer, "pixbuf", id)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create cell column:", err)
|
||||
}
|
||||
|
||||
return column
|
||||
}
|
||||
|
||||
func createColumnText(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 createTreeStore(general bool) *gtk.TreeStore {
|
||||
colData := []glib.Type{glib.TYPE_INT, glib.TYPE_OBJECT, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, 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, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_OBJECT}
|
||||
|
||||
treeStore, err := gtk.TreeStoreNew(colData...)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create list store:", err)
|
||||
}
|
||||
|
||||
return treeStore
|
||||
}
|
||||
|
||||
|
||||
func (p *Prompt) addRequestInc(guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int,
|
||||
origin, timestamp string, is_socks bool, optstring string, sandbox string, action int) bool {
|
||||
duplicated := false
|
||||
|
||||
p.promptLock.Lock()
|
||||
defer p.promptLock.Unlock()
|
||||
for ridx := 0; ridx < p.ts.IterNChildren(nil); ridx++ {
|
||||
rule, iter, err := p.getRuleByIdx(ridx, -1)
|
||||
if err != nil {
|
||||
break
|
||||
// XXX: not compared: optstring/sandbox
|
||||
} else if (rule.Path == path) && (rule.Proto == proto) && (rule.Pid == pid) && (rule.Target == ipaddr) && (rule.Hostname == hostname) &&
|
||||
(rule.Port == port) && (rule.UID == uid) && (rule.GID == gid) && (rule.Origin == origin) && (rule.IsSocks == is_socks) {
|
||||
rule.nrefs++
|
||||
|
||||
err := p.ts.SetValue(iter, 0, rule.nrefs)
|
||||
if err != nil {
|
||||
fmt.Println("Error creating duplicate firewall prompt entry:", err)
|
||||
break
|
||||
}
|
||||
|
||||
duplicated = true
|
||||
subiter := p.ts.Append(iter)
|
||||
p.storeNewEntry(subiter, guid, path, sandbox, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, timestamp, is_socks, optstring, action)
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return duplicated
|
||||
}
|
||||
|
||||
func (p *Prompt) AddRequest(guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int,
|
||||
origin, timestamp string, is_socks bool, optstring string, sandbox string, action int) bool {
|
||||
if p.ts == nil {
|
||||
waitTimes := []int{1, 2, 5, 10}
|
||||
|
||||
if p.ts == nil {
|
||||
fmt.Println("SGFW prompter was not ready to receive firewall request... waiting")
|
||||
|
||||
for _, wtime := range waitTimes {
|
||||
time.Sleep(time.Duration(wtime) * time.Second)
|
||||
|
||||
if p.ts != nil {
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Println("SGFW prompter is still waiting...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.ts == nil {
|
||||
log.Fatal("SGFW prompter GUI failed to load for unknown reasons")
|
||||
}
|
||||
|
||||
if p.addRequestInc(guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, timestamp, is_socks, optstring, sandbox, action) {
|
||||
fmt.Println("Request was duplicate: ", guid)
|
||||
p.promptLock.Lock()
|
||||
p.toggleHover()
|
||||
p.promptLock.Unlock()
|
||||
return true
|
||||
}
|
||||
|
||||
p.promptLock.Lock()
|
||||
defer p.promptLock.Unlock()
|
||||
|
||||
iter := p.ts.Append(nil)
|
||||
p.storeNewEntry(iter, guid, path, sandbox, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, timestamp, is_socks, optstring, action)
|
||||
|
||||
p.toggleHover()
|
||||
return true
|
||||
}
|
||||
|
||||
// Needs to be locked by caller
|
||||
func (p *Prompt)storeNewEntry(iter *gtk.TreeIter, guid, path, sandbox, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin,
|
||||
timestamp string, is_socks bool, optstring string, action int) {
|
||||
var colVals = [COL_NO_LAST]interface{}{}
|
||||
|
||||
if is_socks {
|
||||
if (optstring != "") && (strings.Index(optstring, "SOCKS") == -1) {
|
||||
optstring = "SOCKS5 / " + optstring
|
||||
} else if optstring == "" {
|
||||
optstring = "SOCKS5"
|
||||
}
|
||||
}
|
||||
|
||||
colVals[COL_NO_NREFS] = 1
|
||||
colVals[COL_NO_ICON_PIXBUF] = nil
|
||||
colVals[COL_NO_GUID] = guid
|
||||
colVals[COL_NO_PATH] = path
|
||||
colVals[COL_NO_SANDBOX] = sandbox
|
||||
colVals[COL_NO_ICON] = icon
|
||||
colVals[COL_NO_PROTO] = proto
|
||||
colVals[COL_NO_PID] = pid
|
||||
|
||||
if ipaddr == "" {
|
||||
colVals[COL_NO_DSTIP] = "---"
|
||||
} else {
|
||||
colVals[COL_NO_DSTIP] = ipaddr
|
||||
}
|
||||
|
||||
colVals[COL_NO_HOSTNAME] = hostname
|
||||
colVals[COL_NO_PORT] = port
|
||||
colVals[COL_NO_UID] = uid
|
||||
colVals[COL_NO_GID] = gid
|
||||
colVals[COL_NO_ORIGIN] = origin
|
||||
colVals[COL_NO_TIMESTAMP] = timestamp
|
||||
colVals[COL_NO_IS_SOCKS] = 0
|
||||
|
||||
if is_socks {
|
||||
colVals[COL_NO_IS_SOCKS] = 1
|
||||
}
|
||||
|
||||
colVals[COL_NO_OPTSTRING] = optstring
|
||||
colVals[COL_NO_ACTION] = action
|
||||
colVals[COL_NO_FILLER] = nil
|
||||
|
||||
itheme, err := gtk.IconThemeGetDefault()
|
||||
if err != nil {
|
||||
log.Fatal("Could not load default icon theme:", err)
|
||||
}
|
||||
|
||||
in := []string{spath.Base(path)}
|
||||
if sandbox != "" {
|
||||
in = append([]string{sandbox}, in...)
|
||||
}
|
||||
if icon != "" {
|
||||
in = append(in, icon)
|
||||
}
|
||||
in = append(in, "terminal")
|
||||
if path == "[unknown]" {
|
||||
in = []string{"image-missing"}
|
||||
}
|
||||
|
||||
for _, ia := range in {
|
||||
pb, _ := itheme.LoadIcon(ia, int(gtk.ICON_SIZE_BUTTON), gtk.ICON_LOOKUP_GENERIC_FALLBACK)
|
||||
if pb != nil {
|
||||
colVals[COL_NO_ICON_PIXBUF] = pb
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
pb, err := gdk.PixbufNew(gdk.COLORSPACE_RGB, true, 8, 24, 24)
|
||||
if err != nil {
|
||||
log.Println("Error creating blank icon:", err)
|
||||
} else {
|
||||
colVals[COL_NO_FILLER] = pb
|
||||
|
||||
img, err := gtk.ImageNewFromPixbuf(pb)
|
||||
if err != nil {
|
||||
log.Println("Error creating image from pixbuf:", err)
|
||||
} else {
|
||||
img.Clear()
|
||||
pb = img.GetPixbuf()
|
||||
colVals[COL_NO_FILLER] = pb
|
||||
}
|
||||
}
|
||||
|
||||
for n := 0; n < len(colVals); n++ {
|
||||
err := p.ts.SetValue(iter, n, colVals[n])
|
||||
if err != nil {
|
||||
log.Fatal("Unable to add row:", err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Prompt) getRuleByIdx(idx, subidx int) (ruleColumns, *gtk.TreeIter, error) {
|
||||
rule := ruleColumns{}
|
||||
tpath := fmt.Sprintf("%d", idx)
|
||||
|
||||
if subidx != -1 {
|
||||
tpath = fmt.Sprintf("%d:%d", idx, subidx)
|
||||
}
|
||||
|
||||
path, err := gtk.TreePathNewFromString(tpath)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
iter, err := p.ts.GetIter(path)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.nrefs, err = p.lsGetInt(iter, COL_NO_NREFS)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.GUID, err = p.lsGetStr(iter, COL_NO_GUID)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Path, err = p.lsGetStr(iter, COL_NO_PATH)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Sandbox, err = p.lsGetStr(iter, COL_NO_SANDBOX)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Icon, err = p.lsGetStr(iter, COL_NO_ICON)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Proto, err = p.lsGetStr(iter, COL_NO_PROTO)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Pid, err = p.lsGetInt(iter, COL_NO_PID)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Target, err = p.lsGetStr(iter, COL_NO_DSTIP)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Hostname, err = p.lsGetStr(iter, COL_NO_HOSTNAME)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Port, err = p.lsGetInt(iter, COL_NO_PORT)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.UID, err = p.lsGetInt(iter, COL_NO_UID)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.GID, err = p.lsGetInt(iter, COL_NO_GID)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Origin, err = p.lsGetStr(iter, COL_NO_ORIGIN)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.Timestamp, err = p.lsGetStr(iter, COL_NO_TIMESTAMP)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
rule.IsSocks = false
|
||||
is_socks, err := p.lsGetInt(iter, COL_NO_IS_SOCKS)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
if is_socks != 0 {
|
||||
rule.IsSocks = true
|
||||
}
|
||||
|
||||
rule.Scope, err = p.lsGetInt(iter, COL_NO_ACTION)
|
||||
if err != nil {
|
||||
return rule, nil, err
|
||||
}
|
||||
|
||||
return rule, iter, nil
|
||||
}
|
||||
|
||||
func (p *Prompt) lsGetInt(iter *gtk.TreeIter, idx int) (int, error) {
|
||||
val, err := p.ts.GetValue(iter, idx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
ival, err := val.GoValue()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ival.(int), nil
|
||||
}
|
||||
|
||||
|
||||
func (p *Prompt) lsGetStr(iter *gtk.TreeIter, idx int) (string, error) {
|
||||
val, err := p.ts.GetValue(iter, idx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sval, err := val.GetString()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return sval, nil
|
||||
}
|
||||
|
||||
func (p *Prompt) toggleHover() {
|
||||
nitems := p.ts.IterNChildren(nil)
|
||||
stack := p.app.tlStack.GetChildByName("prompt")
|
||||
|
||||
if nitems > 0 {
|
||||
if p.app.Settings.GetToplevelPrompt() {
|
||||
//p.win.SetModal(true)
|
||||
p.app.win.Deiconify()
|
||||
p.app.win.SetKeepAbove(true)
|
||||
p.app.win.Stick()
|
||||
}
|
||||
p.app.win.SetUrgencyHint(true)
|
||||
p.app.win.Present()
|
||||
if p.app.tlStack.GetVisibleChildName() != "prompt" {
|
||||
err := p.app.tlStack.ChildSetProperty(stack, "needs-attention", true)
|
||||
if err != nil {
|
||||
fmt.Println("Error setting stack attention")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//p.win.SetModal(false)
|
||||
p.app.win.SetUrgencyHint(false)
|
||||
if p.app.Settings.GetToplevelPrompt() {
|
||||
p.app.win.SetKeepAbove(false)
|
||||
p.app.win.Unstick()
|
||||
}
|
||||
p.app.tlStack.ChildSetProperty(stack, "needs-attention", false)
|
||||
}
|
||||
}
|
||||
|
||||
// Needs to be locked by the caller
|
||||
func (p *Prompt) getSelectedRule() (ruleColumns, int, int, error) {
|
||||
rule := ruleColumns{}
|
||||
|
||||
sel, err := p.tv.GetSelection()
|
||||
if err != nil {
|
||||
return rule, -1, -1, err
|
||||
}
|
||||
|
||||
rows := sel.GetSelectedRows(p.ts)
|
||||
|
||||
if rows.Length() <= 0 {
|
||||
return rule, -1, -1, errors.New("no selection was made")
|
||||
}
|
||||
|
||||
rdata := rows.NthData(0)
|
||||
tpath := rdata.(*gtk.TreePath).String()
|
||||
|
||||
subidx := -1
|
||||
ptoks := strings.Split(tpath, ":")
|
||||
|
||||
if len(ptoks) > 2 {
|
||||
return rule, -1, -1, errors.New("internal error parsing selected item tree path")
|
||||
} else if len(ptoks) == 2 {
|
||||
subidx, err = strconv.Atoi(ptoks[1])
|
||||
if err != nil {
|
||||
return rule, -1, -1, err
|
||||
}
|
||||
tpath = ptoks[0]
|
||||
}
|
||||
|
||||
lIndex, err := strconv.Atoi(tpath)
|
||||
if err != nil {
|
||||
return rule, -1, -1, err
|
||||
}
|
||||
|
||||
// fmt.Printf("lindex = %d : %d\n", lIndex, subidx)
|
||||
rule, _, err = p.getRuleByIdx(lIndex, subidx)
|
||||
if err != nil {
|
||||
return rule, -1, -1, err
|
||||
}
|
||||
|
||||
return rule, lIndex, subidx, nil
|
||||
}
|
||||
|
||||
// Needs to be locked by the caller
|
||||
func (p *Prompt) numSelections() int {
|
||||
sel, err := p.tv.GetSelection()
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
rows := sel.GetSelectedRows(p.ts)
|
||||
return int(rows.Length())
|
||||
}
|
||||
|
||||
|
||||
func (p *Prompt) removeSelectedRule(idx, subidx int) error {
|
||||
fmt.Printf("XXX: attempting to remove idx = %v, %v\n", idx, subidx)
|
||||
ppathstr := fmt.Sprintf("%d", idx)
|
||||
pathstr := ppathstr
|
||||
|
||||
if subidx > -1 {
|
||||
pathstr = fmt.Sprintf("%d:%d", idx, subidx)
|
||||
}
|
||||
|
||||
iter, err := p.ts.GetIterFromString(pathstr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nchildren := p.ts.IterNChildren(iter)
|
||||
|
||||
if nchildren >= 1 {
|
||||
firstpath := fmt.Sprintf("%d:0", idx)
|
||||
citer, err := p.ts.GetIterFromString(firstpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gnrefs, err := p.ts.GetValue(iter, COL_NO_NREFS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vnrefs, err := gnrefs.GoValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nrefs := vnrefs.(int) - 1
|
||||
|
||||
for n := 0; n < COL_NO_LAST; n++ {
|
||||
val, err := p.ts.GetValue(citer, n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n == COL_NO_NREFS {
|
||||
err = p.ts.SetValue(iter, n, nrefs)
|
||||
} else {
|
||||
err = p.ts.SetValue(iter, n, val)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
p.ts.Remove(citer)
|
||||
return nil
|
||||
}
|
||||
|
||||
p.ts.Remove(iter)
|
||||
|
||||
if subidx > -1 {
|
||||
ppath, err := gtk.TreePathNewFromString(ppathstr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
piter, err := p.ts.GetIter(ppath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nrefs, err := p.lsGetInt(piter, COL_NO_NREFS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = p.ts.SetValue(piter, COL_NO_NREFS, nrefs-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
p.toggleHover()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Prompt) addRecentlyRemoved(guid string) {
|
||||
p.recentLock.Lock()
|
||||
defer p.recentLock.Unlock()
|
||||
fmt.Println("RECENTLY REMOVED: ", guid)
|
||||
p.recentlyRemoved = append(p.recentlyRemoved, guid)
|
||||
}
|
||||
|
||||
func (p *Prompt) wasRecentlyRemoved(guid string) bool {
|
||||
p.recentLock.Lock()
|
||||
defer p.recentLock.Unlock()
|
||||
|
||||
for gind, g := range p.recentlyRemoved {
|
||||
if g == guid {
|
||||
p.recentlyRemoved = append(p.recentlyRemoved[:gind], p.recentlyRemoved[gind+1:]...)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Prompt) RemoveRequest(guid string) {
|
||||
if p.wasRecentlyRemoved(guid) {
|
||||
fmt.Printf("Entry for %s was recently removed; deleting from cache\n", guid)
|
||||
return
|
||||
}
|
||||
|
||||
removed := false
|
||||
|
||||
if p.ts == nil {
|
||||
return
|
||||
}
|
||||
|
||||
p.promptLock.Lock()
|
||||
defer p.promptLock.Unlock()
|
||||
|
||||
remove_outer:
|
||||
for ridx := 0; ridx < p.ts.IterNChildren(nil); ridx++ {
|
||||
nchildren := 0
|
||||
this_iter, err := p.ts.GetIterFromString(fmt.Sprintf("%d", ridx))
|
||||
if err != nil {
|
||||
log.Println("Strange condition; couldn't get iter of known tree index:", err)
|
||||
} else {
|
||||
nchildren = p.ts.IterNChildren(this_iter)
|
||||
}
|
||||
|
||||
for cidx := 0; cidx < nchildren-1; cidx++ {
|
||||
sidx := cidx
|
||||
if cidx == nchildren {
|
||||
cidx = -1
|
||||
}
|
||||
|
||||
rule, _, err := p.getRuleByIdx(ridx, sidx)
|
||||
if err != nil {
|
||||
break remove_outer
|
||||
} else if rule.GUID == guid {
|
||||
p.removeSelectedRule(ridx, sidx)
|
||||
removed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !removed {
|
||||
fmt.Printf("Unexpected condition: SGFW requested prompt removal for non-existent GUID %v\n", guid)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Prompt) RemoveAll() {
|
||||
p.promptLock.Lock()
|
||||
defer p.promptLock.Unlock()
|
||||
p.recentLock.Lock()
|
||||
defer p.recentLock.Unlock()
|
||||
|
||||
p.recentlyRemoved = p.recentlyRemoved[:0]
|
||||
|
||||
for {
|
||||
iter, found := p.ts.GetIterFirst()
|
||||
if iter == nil || found == false {
|
||||
break
|
||||
}
|
||||
pi, _ := p.ts.GetPath(iter)
|
||||
if pi == nil {
|
||||
break
|
||||
}
|
||||
p.tv.SetCursor(pi, nil, false)
|
||||
_, idx, subidx, err := p.getSelectedRule()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
p.removeSelectedRule(idx, subidx)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Prompt) makeDecision(rule string, scope int, guid string) error {
|
||||
return p.app.Dbus.answerPrompt(uint32(scope), rule, guid)
|
||||
}
|
||||
|
||||
func (p *Prompt) buttonAction(guid string, rr *sgfw.DbusRule) {
|
||||
p.promptLock.Lock()
|
||||
rule, idx, subidx, err := p.getSelectedRule()
|
||||
if err != nil {
|
||||
p.promptLock.Unlock()
|
||||
warnDialog(&p.app.win.Window, "Error occurred processing request: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
tk := strings.Split(rr.Target, ":")
|
||||
// Overlay the rules
|
||||
rule.Scope = int(rr.Mode)
|
||||
//rule.Path = urule.Path
|
||||
rule.Port, _ = strconv.Atoi(tk[1])
|
||||
rule.Target = tk[0]
|
||||
rule.Proto = rr.Proto
|
||||
rule.UID = int(rr.UID)
|
||||
rule.GID = int(rr.GID)
|
||||
// rule.Uname = urule.Uname
|
||||
// rule.Gname = urule.Gname
|
||||
|
||||
fmt.Println("rule = ", rule)
|
||||
|
||||
action := sgfw.RuleActionString[sgfw.RuleAction(rr.Verb)]
|
||||
rulestr := action
|
||||
|
||||
proto := rule.Proto
|
||||
if proto == "any" || proto == "" {
|
||||
proto = "*"
|
||||
}
|
||||
rulestr += "|" + proto + ":" + rule.Target + ":" + strconv.Itoa(rule.Port)
|
||||
rulestr += "|" + sgfw.RuleModeString[sgfw.RuleMode(rule.Scope)]
|
||||
rulestr += "|" + strconv.Itoa(rule.UID) + ":" + strconv.Itoa(rule.GID)
|
||||
if rule.Sandbox != "" {
|
||||
rulestr += "|" + rule.Sandbox
|
||||
}
|
||||
fmt.Println("RULESTR = ", rulestr)
|
||||
p.makeDecision(rulestr, int(rule.Scope), guid)
|
||||
err = p.removeSelectedRule(idx, subidx)
|
||||
p.addRecentlyRemoved(guid)
|
||||
p.promptLock.Unlock()
|
||||
if err != nil {
|
||||
warnDialog(&p.app.win.Window, "Error setting new rule: %s", err.Error())
|
||||
}
|
||||
}
|
@ -0,0 +1,551 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
"github.com/subgraph/fw-daemon/sgfw"
|
||||
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
const (
|
||||
newDialogCancel = 1
|
||||
newDialogOk = 2
|
||||
newDialogAllow = 3
|
||||
)
|
||||
|
||||
const (
|
||||
COLUMN_ID = iota
|
||||
COLUMN_NAME
|
||||
)
|
||||
|
||||
type DialogMode uint
|
||||
|
||||
const (
|
||||
DIALOG_MODE_NEW DialogMode = iota
|
||||
DIALOG_MODE_EDIT
|
||||
DIALOG_MODE_SAVEAS
|
||||
DIALOG_MODE_PROMPT
|
||||
DIALOG_MODE_INFO
|
||||
)
|
||||
|
||||
const (
|
||||
Setuid uint32 = 1 << (12 - 1 - iota)
|
||||
Setgid
|
||||
Sticky
|
||||
UserRead
|
||||
UserWrite
|
||||
UserExecute
|
||||
GroupRead
|
||||
GroupWrite
|
||||
GroupExecute
|
||||
OtherRead
|
||||
OtherWrite
|
||||
OtherExecute
|
||||
)
|
||||
|
||||
type ruleNew struct {
|
||||
dialog *gtk.Dialog
|
||||
row *ruleRow
|
||||
mode DialogMode
|
||||
nbSelected int
|
||||
comboUID *gtk.ComboBoxText
|
||||
checkUID *gtk.CheckButton
|
||||
comboGID *gtk.ComboBoxText
|
||||
checkGID *gtk.CheckButton
|
||||
titleScope *gtk.Label
|
||||
comboScope *gtk.ComboBoxText
|
||||
labelScope *gtk.Label
|
||||
comboVerb *gtk.ComboBoxText
|
||||
checkTLS *gtk.CheckButton
|
||||
titleSandbox *gtk.Label
|
||||
labelSandbox *gtk.Label
|
||||
comboSandbox *gtk.ComboBoxText
|
||||
btnPathChooser *gtk.FileChooserButton
|
||||
entryPath *gtk.Entry
|
||||
hostEntry *gtk.Entry
|
||||
portEntry *gtk.Entry
|
||||
titlePort *gtk.Label
|
||||
comboProto *gtk.ComboBoxText
|
||||
ok *gtk.Button
|
||||
allow *gtk.Button
|
||||
cancel *gtk.Button
|
||||
labelPID *gtk.Label
|
||||
titlePID *gtk.Label
|
||||
entryOrigin *gtk.Entry
|
||||
labelOrigin *gtk.Label
|
||||
}
|
||||
|
||||
func newRuleAdd(rr *ruleRow, mode DialogMode) *ruleNew{
|
||||
rnew := &ruleNew{}
|
||||
rnew.mode = mode
|
||||
rnew.nbSelected = rr.rl.app.nbRules.GetCurrentPage()
|
||||
b := newBuilder("RuleNew")
|
||||
b.getItems(
|
||||
"dialog", &rnew.dialog,
|
||||
"uid_combo", &rnew.comboUID,
|
||||
"uid_checkbox", &rnew.checkUID,
|
||||
"gid_combo", &rnew.comboGID,
|
||||
"gid_checkbox", &rnew.checkGID,
|
||||
"scope_title", &rnew.titleScope,
|
||||
"scope_combo", &rnew.comboScope,
|
||||
"scope_label", &rnew.labelScope,
|
||||
"verb_combo", &rnew.comboVerb,
|
||||
"tls_check", &rnew.checkTLS,
|
||||
"sandbox_title", &rnew.titleSandbox,
|
||||
"sandbox_combo", &rnew.comboSandbox,
|
||||
"sandbox_label", &rnew.labelSandbox,
|
||||
"path_chooser", &rnew.btnPathChooser,
|
||||
"path_entry", &rnew.entryPath,
|
||||
"host_entry", &rnew.hostEntry,
|
||||
"port_entry", &rnew.portEntry,
|
||||
"port_title", &rnew.titlePort,
|
||||
"proto_combo", &rnew.comboProto,
|
||||
"ok_button", &rnew.ok,
|
||||
"allow_button", &rnew.allow,
|
||||
"cancel_button", &rnew.cancel,
|
||||
"pid_label", &rnew.labelPID,
|
||||
"pid_title", &rnew.titlePID,
|
||||
"origin_entry", &rnew.entryOrigin,
|
||||
"origin_label", &rnew.labelOrigin,
|
||||
)
|
||||
|
||||
b.ConnectSignals(map[string]interface{}{
|
||||
"on_proto_changed": rnew.onProtoChanged,
|
||||
"on_verb_changed": rnew.onVerbChanged,
|
||||
"on_port_insert_text": rnew.onPortInsertText,
|
||||
"on_port_changed": rnew.onChanged,
|
||||
"on_host_changed": rnew.onChanged,
|
||||
"on_path_changed": rnew.onChanged,
|
||||
"on_path_set": rnew.onPathSet,
|
||||
})
|
||||
|
||||
rnew.row = rr
|
||||
switch rnew.mode {
|
||||
case DIALOG_MODE_EDIT:
|
||||
rnew.dialog.SetTitle("Edit Rule")
|
||||
case DIALOG_MODE_NEW:
|
||||
rnew.dialog.SetTitle("Add New Rule")
|
||||
case DIALOG_MODE_SAVEAS:
|
||||
rnew.ok.SetLabel("Save As New")
|
||||
rnew.dialog.SetTitle("Save As New Rule")
|
||||
case DIALOG_MODE_PROMPT:
|
||||
rnew.connectShortcutsPromptWindow()
|
||||
rnew.dialog.SetTitle("Firewall Prompt")
|
||||
case DIALOG_MODE_INFO:
|
||||
rnew.cancel.SetLabel("Close")
|
||||
rnew.dialog.SetTitle("Rule Information")
|
||||
}
|
||||
|
||||
return rnew
|
||||
}
|
||||
|
||||
func (re *ruleNew) connectShortcutsPromptWindow() {
|
||||
app := re.row.rl.app
|
||||
// Shortcuts Help Registered in Prompt
|
||||
app.ConnectShortcut("<Alt>h", "", "", re.dialog.Window, func(win gtk.Window) {re.hostEntry.Widget.GrabFocus()})
|
||||
app.ConnectShortcut("<Alt>p", "", "", re.dialog.Window, func(win gtk.Window) {re.portEntry.Widget.GrabFocus()})
|
||||
app.ConnectShortcut("<Alt>o", "", "", re.dialog.Window, func(win gtk.Window) {re.comboProto.ComboBox.Popup()})
|
||||
app.ConnectShortcut("<Alt>t", "", "", re.dialog.Window, func(win gtk.Window) {
|
||||
if re.checkTLS.GetSensitive() {
|
||||
re.checkTLS.SetActive(!re.checkTLS.GetActive())
|
||||
}
|
||||
})
|
||||
app.ConnectShortcut("<Alt>s", "", "", re.dialog.Window, func(win gtk.Window) {re.comboScope.ComboBox.Popup()})
|
||||
app.ConnectShortcut("<Alt>u", "", "", re.dialog.Window, func(win gtk.Window) {re.checkUID.SetActive(!re.checkUID.GetActive())})
|
||||
app.ConnectShortcut("<Alt>g", "", "", re.dialog.Window, func(win gtk.Window) {re.checkGID.SetActive(!re.checkGID.GetActive())})
|
||||
}
|
||||
|
||||
func (re *ruleNew) updateRow(res int) {
|
||||
if !re.validateFields() {
|
||||
return
|
||||
}
|
||||
r := re.row.rule
|
||||
if re.mode == DIALOG_MODE_PROMPT {
|
||||
if res == newDialogOk {
|
||||
r.Verb = uint16(sgfw.RULE_ACTION_DENY)
|
||||
} else if res == newDialogAllow {
|
||||
r.Verb = uint16(sgfw.RULE_ACTION_ALLOW)
|
||||
}
|
||||
mid, _ := strconv.Atoi(re.comboScope.GetActiveID())
|
||||
r.Mode = uint16(mid)
|
||||
} else {
|
||||
switch re.comboVerb.GetActiveID() {
|
||||
case "allow":
|
||||
r.Verb = uint16(sgfw.RULE_ACTION_ALLOW)
|
||||
// case "allow_tls":
|
||||
// r.Verb = uint16(sgfw.RULE_ACTION_ALLOW_TLSONLY)
|
||||
case "deny":
|
||||
r.Verb = uint16(sgfw.RULE_ACTION_DENY)
|
||||
}
|
||||
}
|
||||
|
||||
r.Proto = re.comboProto.GetActiveID()
|
||||
if r.Proto == "any" {
|
||||
r.Proto = "*"
|
||||
}
|
||||
if r.Proto == "tcp" && r.Verb == uint16(sgfw.RULE_ACTION_ALLOW) && re.checkTLS.GetActive() {
|
||||
r.Verb = uint16(sgfw.RULE_ACTION_ALLOW_TLSONLY)
|
||||
}
|
||||
|
||||
host, _ := re.hostEntry.GetText()
|
||||
port, _ := re.portEntry.GetText()
|
||||
r.Target = fmt.Sprintf("%s:%s", host, port)
|
||||
if re.mode != DIALOG_MODE_PROMPT || re.checkUID.GetActive() == true {
|
||||
uid, _ := strconv.ParseInt(re.comboUID.GetActiveID(), 10, 32)
|
||||
r.UID = int32(uid)
|
||||
} else {
|
||||
r.UID = -1
|
||||
}
|
||||
if re.mode != DIALOG_MODE_PROMPT || re.checkGID.GetActive() == true {
|
||||
gid, _ := strconv.ParseInt(re.comboGID.GetActiveID(), 10, 32)
|
||||
r.GID = int32(gid)
|
||||
} else {
|
||||
r.GID = -1
|
||||
}
|
||||
|
||||
if re.mode == DIALOG_MODE_NEW {
|
||||
r.Path = re.btnPathChooser.FileChooser.GetFilename()
|
||||
mid, _ := strconv.Atoi(re.comboScope.GetActiveID())
|
||||
r.Mode = uint16(mid)
|
||||
r.Sandbox = re.comboSandbox.GetActiveID()
|
||||
}
|
||||
|
||||
if re.mode != DIALOG_MODE_NEW && re.mode != DIALOG_MODE_PROMPT {
|
||||
re.row.update()
|
||||
}
|
||||
}
|
||||
|
||||
type cbPromptRequest func(guid string, rule *sgfw.DbusRule)
|
||||
|
||||
func (re *ruleNew) run(guid string, cb cbPromptRequest) {
|
||||
re.dialog.SetTransientFor(re.row.rl.app.win)
|
||||
re.dialog.ShowAll()
|
||||
if re.mode == DIALOG_MODE_INFO {
|
||||
re.dialog.Run()
|
||||
} else if re.mode == DIALOG_MODE_PROMPT {
|
||||
res := re.dialog.Run()
|
||||
if res != newDialogCancel {
|
||||
re.updateRow(res)
|
||||
cb(guid, re.row.rule)
|
||||
}
|
||||
} else if re.mode == DIALOG_MODE_NEW {
|
||||
if re.dialog.Run() == newDialogOk {
|
||||
re.updateRow(newDialogOk)
|
||||
r := *re.row.rule
|
||||
res, err := re.row.rl.app.Dbus.addRule(&r)
|
||||
if res == false || err != nil {
|
||||
warnDialog(&re.row.rl.app.win.Window, "Error notifying SGFW of asynchronous rule addition:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if re.mode == DIALOG_MODE_SAVEAS {
|
||||
if re.dialog.Run() == newDialogOk {
|
||||
re.updateRow(newDialogOk)
|
||||
r := *re.row.rule
|
||||
re.row.rl.app.Dbus.addRule(&r)
|
||||
re.row.rl.remove(re.row)
|
||||
}
|
||||
} else {
|
||||
if re.dialog.Run() == newDialogOk {
|
||||
re.updateRow(newDialogOk)
|
||||
re.row.rl.app.Dbus.updateRule(re.row.rule)
|
||||
}
|
||||
}
|
||||
re.dialog.Destroy()
|
||||
}
|
||||
|
||||
func (rr *ruleRow) runNewEditor(mode DialogMode) {
|
||||
redit := newRuleAdd(rr, mode)
|
||||
redit.update()
|
||||
redit.run("", nil)
|
||||
}
|
||||
|
||||
func (re *ruleNew) update() {
|
||||
re.populateUID()
|
||||
re.populateGID()
|
||||
r := re.row.rule
|
||||
|
||||
if re.mode != DIALOG_MODE_INFO {
|
||||
re.comboScope.Remove(4)
|
||||
}
|
||||
|
||||
if re.mode != DIALOG_MODE_PROMPT && re.mode != DIALOG_MODE_INFO {
|
||||
re.comboScope.Remove(3)
|
||||
re.comboScope.Remove(2)
|
||||
}
|
||||
|
||||
re.onVerbChanged()
|
||||
|
||||
if re.mode == DIALOG_MODE_NEW {
|
||||
if re.nbSelected < 2 {
|
||||
re.comboScope.SetActive(re.nbSelected)
|
||||
} else {
|
||||
re.comboScope.SetActive(0)
|
||||
}
|
||||
//re.titleSandbox.SetNoShowAll(true)
|
||||
//re.titleSandbox.SetVisible(false)
|
||||
//re.comboSandbox.SetNoShowAll(true)
|
||||
//re.comboSandbox.SetVisible(false)
|
||||
//re.comboSandbox.SetNoShowAll(true)
|
||||
//re.comboSandbox.SetVisible(false)
|
||||
re.comboSandbox.Append("", "")
|
||||
for _, pn := range re.row.rl.app.ozProfiles {
|
||||
re.comboSandbox.Append(pn, pn)
|
||||
}
|
||||
re.comboSandbox.SetActive(0)
|
||||
re.btnPathChooser.SetCurrentFolder("/")
|
||||
re.ok.SetSensitive(false)
|
||||
re.onProtoChanged()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if r.Proto == "" {
|
||||
re.comboProto.SetActiveID("any")
|
||||
} else {
|
||||
re.comboProto.SetActiveID(strings.ToLower(r.Proto))
|
||||
}
|
||||
|
||||
re.comboSandbox.SetVisible(false)
|
||||
re.comboSandbox.SetSensitive(false)
|
||||
re.comboSandbox.SetNoShowAll(true)
|
||||
|
||||
if sgfw.RuleAction(r.Verb) == sgfw.RULE_ACTION_ALLOW || sgfw.RuleAction(r.Verb) == sgfw.RULE_ACTION_ALLOW_TLSONLY {
|
||||
re.comboVerb.SetActiveID("allow")
|
||||
} else {
|
||||
re.comboVerb.SetActiveID("deny")
|
||||
}
|
||||
|
||||
if sgfw.RuleAction(r.Verb) == sgfw.RULE_ACTION_ALLOW_TLSONLY {
|
||||
re.checkTLS.SetActive(true)
|
||||
}
|
||||
|
||||
if r.Sandbox == "" {
|
||||
re.titleSandbox.SetNoShowAll(true)
|
||||
re.titleSandbox.SetVisible(false)
|
||||
re.labelSandbox.SetNoShowAll(true)
|
||||
re.labelSandbox.SetVisible(false)
|
||||
} else {
|
||||
re.titleSandbox.SetVisible(true)
|
||||
re.labelSandbox.SetNoShowAll(false)
|
||||
re.labelSandbox.SetVisible(true)
|
||||
re.labelSandbox.SetNoShowAll(false)
|
||||
re.labelSandbox.SetText(r.Sandbox)
|
||||
}
|
||||
|
||||
re.btnPathChooser.SetNoShowAll(true)
|
||||
re.btnPathChooser.SetVisible(false)
|
||||
re.btnPathChooser.SetSensitive(false)
|
||||
re.entryPath.SetNoShowAll(false)
|
||||
re.entryPath.SetVisible(true)
|
||||
re.entryPath.SetText(r.Path)
|
||||
|
||||
target := strings.Split(r.Target, ":")
|
||||
if len(target) != 2 {
|
||||
return
|
||||
}
|
||||
re.hostEntry.SetText(target[0])
|
||||
re.portEntry.SetText(target[1])
|
||||
|
||||
if r.UID > -1 {
|
||||
re.comboUID.SetActiveID(strconv.FormatInt(int64(r.UID), 10))
|
||||
}
|
||||
if r.GID > -1 {
|
||||
re.comboGID.SetActiveID(strconv.FormatInt(int64(r.GID), 10))
|
||||
}
|
||||
|
||||
if re.mode == DIALOG_MODE_EDIT {
|
||||
re.comboScope.SetVisible(false)
|
||||
re.comboScope.SetNoShowAll(true)
|
||||
re.comboScope.SetSensitive(false)
|
||||
re.labelScope.SetNoShowAll(false)
|
||||
re.labelScope.SetVisible(true)
|
||||
re.labelScope.SetText(strings.Title(strings.ToLower(sgfw.RuleModeString[sgfw.RuleMode(r.Mode)])))
|
||||
}
|
||||
if re.mode == DIALOG_MODE_PROMPT || r.Mode == uint16(sgfw.RULE_MODE_PROCESS) {
|
||||
re.titlePID.SetNoShowAll(false)
|
||||
re.titlePID.SetVisible(true)
|
||||
re.labelPID.SetNoShowAll(false)
|
||||
re.labelPID.SetVisible(true)
|
||||
pid := strconv.FormatUint(uint64(r.Pid), 10)
|
||||
re.labelPID.SetText(pid)
|
||||
}
|
||||
if re.mode == DIALOG_MODE_SAVEAS {
|
||||
re.comboScope.Remove(1)
|
||||
re.comboScope.SetSensitive(false)
|
||||
}
|
||||
if re.mode == DIALOG_MODE_PROMPT {
|
||||
re.entryOrigin.SetNoShowAll(false)
|
||||
re.entryOrigin.SetVisible(true)
|
||||
re.entryOrigin.SetSensitive(false)
|
||||
re.entryOrigin.SetText(r.Origin)
|
||||
re.labelOrigin.SetNoShowAll(false)
|
||||
re.labelOrigin.SetVisible(true)
|
||||
re.comboUID.SetSensitive(false)
|
||||
re.comboGID.SetSensitive(false)
|
||||
re.comboScope.SetActiveID(strconv.Itoa(int(sgfw.RuleModeValue[strings.ToUpper(re.row.rl.app.Config.DefaultAction)])))
|
||||
|
||||
re.checkUID.SetNoShowAll(false)
|
||||
re.checkUID.SetVisible(true)
|
||||
re.checkUID.SetSensitive(true)
|
||||
re.checkGID.SetNoShowAll(false)
|
||||
re.checkGID.SetVisible(true)
|
||||
re.checkGID.SetSensitive(true)
|
||||
|
||||
re.comboVerb.SetNoShowAll(true)
|
||||
re.comboVerb.SetVisible(false)
|
||||
re.comboVerb.SetSensitive(false)
|
||||
|
||||
re.setPromptButtons()
|
||||
|
||||
ctv := r.IsSocks
|
||||
if !ctv {
|
||||
re.checkTLS.SetSensitive(false)
|
||||
re.checkTLS.SetActive(false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if re.mode == DIALOG_MODE_INFO {
|
||||
re.comboScope.SetActiveID(strconv.Itoa(int(r.Mode)))
|
||||
re.comboScope.SetSensitive(false)
|
||||
re.comboVerb.SetSensitive(false)
|
||||
re.hostEntry.SetSensitive(false)
|
||||
re.portEntry.SetSensitive(false)
|
||||
re.comboUID.SetSensitive(false)
|
||||
re.comboGID.SetSensitive(false)
|
||||
re.checkUID.SetSensitive(false)
|
||||
re.checkGID.SetSensitive(false)
|
||||
re.comboProto.SetSensitive(false)
|
||||
re.checkTLS.SetSensitive(false)
|
||||
re.ok.SetNoShowAll(true)
|
||||
re.ok.SetSensitive(false)
|
||||
re.ok.SetVisible(false)
|
||||
}
|
||||
|
||||
re.onProtoChanged()
|
||||
}
|
||||
|
||||
func (re *ruleNew) setPromptButtons() {
|
||||
re.allow.SetNoShowAll(false)
|
||||
re.allow.SetVisible(true)
|
||||
re.allow.SetSensitive(true)
|
||||
re.ok.SetLabel("_Deny")
|
||||
}
|
||||
|
||||
func (re *ruleNew) toggleCheckTLS(val bool) {
|
||||
if val && re.row.rule.IsSocks && re.mode != DIALOG_MODE_NEW && re.mode != DIALOG_MODE_INFO {
|
||||
re.checkTLS.SetSensitive(true)
|
||||
} else {
|
||||
re.checkTLS.SetSensitive(false)
|
||||
}
|
||||
}
|
||||
|
||||
func (re *ruleNew) onProtoChanged() {
|
||||
re.toggleCheckTLS( (re.comboProto.GetActiveID() == "tcp") )
|
||||
if re.comboProto.GetActiveID() == "icmp" {
|
||||
re.titlePort.SetText("Code:")
|
||||
re.portEntry.SetPlaceholderText("Code")
|
||||
} else {
|
||||
re.titlePort.SetText("Port:")
|
||||
re.portEntry.SetPlaceholderText("Port")
|
||||
}
|
||||
re.onChanged()
|
||||
}
|
||||
|
||||
func (re *ruleNew) onVerbChanged() {
|
||||
re.toggleCheckTLS( (re.comboVerb.GetActiveID() == "allow") )
|
||||
}
|
||||
|
||||
func (re *ruleNew) validateFields() bool {
|
||||
id := re.comboVerb.GetActiveID()
|
||||
if id != "allow" && id != "allow_tls" && id != "deny" {
|
||||
return false
|
||||
}
|
||||
proto := re.comboProto.GetActiveID()
|
||||
protos := []string{"", "tcp", "udp", "icmp"}
|
||||
found := false
|
||||
for _, p := range protos {
|
||||
if proto == p {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
host, _ := re.hostEntry.GetText()
|
||||
port, _ := re.portEntry.GetText()
|
||||
if !isValidHost(host) {
|
||||
return false
|
||||
}
|
||||
if !isValidPort(port, re.comboProto.GetActiveID()) {
|
||||
return false
|
||||
}
|
||||
if re.mode == DIALOG_MODE_NEW {
|
||||
fp := re.btnPathChooser.FileChooser.GetFilename()
|
||||
if fp == "" || !isExecutableFile(fp) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isExecutableFile(file string) bool {
|
||||
fi, _ := os.Stat(file)
|
||||
fm := fi.Mode()
|
||||
perm := uint32(fm.Perm())
|
||||
return !( (perm&UserExecute == 0) && (perm&GroupExecute == 0) && (perm&OtherExecute == 0) )
|
||||
|
||||
}
|
||||
|
||||
func (re *ruleNew) 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 *ruleNew) onChanged() {
|
||||
valid := re.validateFields()
|
||||
re.ok.SetSensitive(valid)
|
||||
if re.mode == DIALOG_MODE_PROMPT {
|
||||
re.allow.SetSensitive(valid)
|
||||
}
|
||||
}
|
||||
|
||||
func (re *ruleNew) onPathSet(btnChooser *gtk.FileChooserButton) {
|
||||
fp := btnChooser.FileChooser.GetFilename()
|
||||
if !isExecutableFile(fp) {
|
||||
warnDialog(&re.row.rl.app.win.Window, "%s", "File not an executable!")
|
||||
} else {
|
||||
btnChooser.SetTooltipText(fp)
|
||||
}
|
||||
}
|
||||
|
||||
func (re *ruleNew) populateUID() {
|
||||
for _, id := range re.row.rl.app.userIDs {
|
||||
re.comboUID.Append(strconv.FormatInt(int64(id), 10), re.row.rl.app.userMap[id])
|
||||
}
|
||||
}
|
||||
|
||||
func (re *ruleNew) populateGID() {
|
||||
for _, id := range re.row.rl.app.groupIDs {
|
||||
re.comboGID.Append(strconv.FormatInt(int64(id), 10), re.row.rl.app.groupMap[id])
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
.PHONY: generate
|
||||
|
||||
all: generate
|
||||
|
||||
gschemas.compiled: *.xml
|
||||
glib-compile-schemas .
|
||||
|
||||
schemas.go: gschemas.compiled
|
||||
ruby ./generate.rb
|
||||
|
||||
generate: touch schemas.go
|
||||
|
||||
touch:
|
||||
ls *.xml | xargs -n1 touch
|
||||
|
||||
doctor: touch generate
|
||||
git diff --exit-code .
|
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<schemalist>
|
||||
<schema id="com.subgraph.Firewall.Settings">
|
||||
<key name="window-height" type="u">
|
||||
<default>0</default>
|
||||
<summary>Main window height</summary>
|
||||
<description>Preserved height of the main window</description>
|
||||
</key>
|
||||
<key name="window-width" type="u">
|
||||
<default>0</default>
|
||||
<summary>Main window width</summary>
|
||||
<description>Preserved width of the main window</description>
|
||||
</key>
|
||||
<key name="window-top" type="u">
|
||||
<default>0</default>
|
||||
<summary>Main window top</summary>
|
||||
<description>Preserved top coordinate of the main window</description>
|
||||
</key>
|
||||
<key name="window-left" type="u">
|
||||
<default>0</default>
|
||||
<summary>Main window left</summary>
|
||||
<description>Preserved left coordinate of the main window</description>
|
||||
</key>
|
||||
<key name="prompt-toplevel" type="b">
|
||||
<default>true</default>
|
||||
<summary>GTK Prompt As Top Level</summary>
|
||||
<description>Bring the prompt window as front most and sticky on new prompt requests</description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
@ -0,0 +1,23 @@
|
||||
package definitions
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
)
|
||||
|
||||
func fileContent() []byte {
|
||||
decoded, _ := hex.DecodeString(schemaDefinition)
|
||||
return decoded
|
||||
}
|
||||
|
||||
func writeSchemaToDir(dir string) {
|
||||
ioutil.WriteFile(path.Join(dir, "gschemas.compiled"), fileContent(), 0664)
|
||||
}
|
||||
|
||||
// SchemaInTempDir will create a new temporary directory and put the gsettings schema file in there. It is the callers responsibility to remove the directory
|
||||
func SchemaInTempDir() string {
|
||||
dir, _ := ioutil.TempDir("", "fw-settings-gschema")
|
||||
writeSchemaToDir(dir)
|
||||
return dir
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
def gen_go_file
|
||||
binary_definition = File.binread("gschemas.compiled")
|
||||
hex = binary_definition.each_byte.map { |b| "%02x" % b }.join
|
||||
|
||||
File.open("schemas.go", "w") do |f|
|
||||
sliced = hex.chars.each_slice(80).map{ |s| s.join }.join "\"+\n\t\""
|
||||
|
||||
f.puts <<TEMPLATE
|
||||
package definitions
|
||||
|
||||
const schemaDefinition = ""+
|
||||
\t"#{sliced}"
|
||||
TEMPLATE
|
||||
end
|
||||
end
|
||||
|
||||
gen_go_file
|
Binary file not shown.
@ -0,0 +1,14 @@
|
||||
package definitions
|
||||
|
||||
const schemaDefinition = ""+
|
||||
"4756617269616e740000000000000000180000005800000000000028020000000000000000000000"+
|
||||
"05150000ffffffff5800000000004c00580000005c00000091f48b72000000005c0000001e004800"+
|
||||
"7c0000002c01000001000000636f6d2e73756267726170682e4669726577616c6c2e53657474696e"+
|
||||
"67730000000000280600000000000000000000000200000003000000040000000400000055c38862"+
|
||||
"040000002c0100000b00760038010000400100001d8e1b7f04000000400100000a00760050010000"+
|
||||
"58010000ea646ab404000000580100000c0076006801000070010000c3c5731e0400000070010000"+
|
||||
"0d007600800100008801000005150000ffffffff8801000000004c00880100009c0100007ffe7dcf"+
|
||||
"040000009c0100000f007600b0010000b501000077696e646f772d6c656674000000000000287529"+
|
||||
"77696e646f772d746f70000000000000000000000028752977696e646f772d776964746800000000"+
|
||||
"000000000028752977696e646f772d68656967687400000000000000002875290500000003000000"+
|
||||
"00000000010000000200000070726f6d70742d746f706c6576656c00000000000100286229"
|
@ -0,0 +1,129 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/subgraph/fw-daemon/fw-settings/settings/definitions"
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
)
|
||||
|
||||
var cachedSchema *glib.SettingsSchemaSource
|
||||
|
||||
func getSchemaSource() *glib.SettingsSchemaSource {
|
||||
if cachedSchema == nil {
|
||||
dir := definitions.SchemaInTempDir()
|
||||
defer os.Remove(dir)
|
||||
cachedSchema = glib.SettingsSchemaSourceNewFromDirectory(dir, nil, true)
|
||||
}
|
||||
|
||||
return cachedSchema
|
||||
}
|
||||
|
||||
func getSchema() *glib.SettingsSchema {
|
||||
return getSchemaSource().Lookup("com.subgraph.Firewall.Settings", false)
|
||||
}
|
||||
|
||||
func getDefaultSettings() *glib.Settings {
|
||||
return glib.SettingsNewFull(getSchema(), nil, "/com/subgraph/firewall/settings/")
|
||||
}
|
||||
|
||||
type Settings struct {
|
||||
def, spec *glib.Settings
|
||||
}
|
||||
|
||||
func Init() *Settings {
|
||||
s := &Settings{}
|
||||
s.def = getDefaultSettings()
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Settings) settingsForGet(name string) *glib.Settings {
|
||||
if s.spec != nil {
|
||||
return s.spec
|
||||
}
|
||||
return s.def
|
||||
}
|
||||
|
||||
func (s *Settings) settingsForSet() *glib.Settings {
|
||||
if s.spec != nil {
|
||||
return s.spec
|
||||
}
|
||||
return s.def
|
||||
}
|
||||
|
||||
func (s *Settings) getBooleanSetting(name string) bool {
|
||||
return s.settingsForGet(name).GetBoolean(name)
|
||||
}
|
||||
|
||||
func (s *Settings) setBooleanSetting(name string, val bool) {
|
||||
sets := s.settingsForSet()
|
||||
sets.SetBoolean(name, val)
|
||||
}
|
||||
|
||||
func (s *Settings) getIntegerSetting(name string) int {
|
||||
return s.settingsForGet(name).GetInt(name)
|
||||
}
|
||||
|
||||
func (s *Settings) setIntegerSetting(name string, val int) {
|
||||
sets := s.settingsForSet()
|
||||
sets.SetInt(name, val)
|
||||
}
|
||||
|
||||
|
||||
func (s *Settings) getUIntegerSetting(name string) uint {
|
||||
return s.settingsForGet(name).GetUInt(name)
|
||||
}
|
||||
|
||||
func (s *Settings) setUIntegerSetting(name string, val uint) {
|
||||
sets := s.settingsForSet()
|
||||
sets.SetUInt(name, val)
|
||||
}
|
||||
|
||||
func (s *Settings) getStringSetting(name string) string {
|
||||
return s.settingsForGet(name).GetString(name)
|
||||
}
|
||||
|
||||
func (s *Settings) setStringSetting(name string, val string) {
|
||||
sets := s.settingsForSet()
|
||||
sets.SetString(name, val)
|
||||
}
|
||||
|
||||
func (s *Settings) GetWindowHeight() uint {
|
||||
return s.getUIntegerSetting("window-height")
|
||||
}
|
||||
|
||||
func (s *Settings) SetWindowHeight(v uint) {
|
||||
s.setUIntegerSetting("window-height", v)
|
||||
}
|
||||
|
||||
func (s *Settings) GetWindowWidth() uint {
|
||||
return s.getUIntegerSetting("window-width")
|
||||
}
|
||||
|
||||
func (s *Settings) SetWindowWidth(v uint) {
|
||||
s.setUIntegerSetting("window-width", v)
|
||||
}
|
||||
|
||||
func (s *Settings) GetWindowTop() uint {
|
||||
return s.getUIntegerSetting("window-top")
|
||||
}
|
||||
|
||||
func (s *Settings) SetWindowTop(v uint) {
|
||||
s.setUIntegerSetting("window-top", v)
|
||||
}
|
||||
|
||||
func (s *Settings) GetWindowLeft() uint {
|
||||
return s.getUIntegerSetting("window-left")
|
||||
}
|
||||
|
||||
func (s *Settings) SetWindowLeft(v uint) {
|
||||
s.setUIntegerSetting("window-left", v)
|
||||
}
|
||||
|
||||
func (s *Settings) GetToplevelPrompt() bool {
|
||||
return s.getBooleanSetting("prompt-toplevel")
|
||||
}
|
||||
|
||||
func (s *Settings) SetToplevelPrompt(v bool) {
|
||||
s.setBooleanSetting("prompt-toplevel", v)
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// +build go1.8
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/subgraph/fw-daemon/sgfw"
|
||||
)
|
||||
|
||||
func (rl *ruleList) sortRules(rules []sgfw.DbusRule) []sgfw.DbusRule {
|
||||
sort.SliceStable(rules, func(i, j int) bool {
|
||||
//sgfw.RuleActionString[sgfw.RuleAction(rules[i].Verb)]
|
||||
//sgfw.RuleActionString[sgfw.RuleAction(rules[j].Verb)]
|
||||
in := rules[i].Sandbox + rules[i].App + rules[i].Target
|
||||
jn := rules[j].Sandbox + rules[j].App + rules[j].Target
|
||||
order := []string{in,jn}
|
||||
sort.Strings(order)
|
||||
if rules[i].App == rules[j].App && rules[i].Sandbox == rules[j].Sandbox {
|
||||
if sgfw.RuleAction(rules[i].Verb) == sgfw.RULE_ACTION_DENY || sgfw.RuleAction(rules[j].Verb) == sgfw.RULE_ACTION_DENY {
|
||||
if rules[i].Verb != rules[j].Verb {
|
||||
return (sgfw.RuleAction(rules[i].Verb) == sgfw.RULE_ACTION_DENY)
|
||||
}
|
||||
}
|
||||
}
|
||||
return (order[0] == in)
|
||||
})
|
||||
return rules
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
// +build !go1.8
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"reflect"
|
||||
|
||||
"github.com/subgraph/fw-daemon/sgfw"
|
||||
)
|
||||
|
||||
// Copied from golang 1.8 sources
|
||||
// START sort.SliceStable
|
||||
type lessSwap struct {
|
||||
Less func(i, j int) bool
|
||||
Swap func(i, j int)
|
||||
}
|
||||
|
||||
func SliceStable(slice interface{}, less func(i, j int) bool) {
|
||||
rv := reflect.ValueOf(slice)
|
||||
swap := reflect.Swapper(slice)
|
||||
stable_func(lessSwap{less, swap}, rv.Len())
|
||||
}
|
||||
|
||||
func symMerge_func(data lessSwap, a, m, b int) {
|
||||
if m-a == 1 {
|
||||
i := m
|
||||
j := b
|
||||
for i < j {
|
||||
h := int(uint(i+j) >> 1)
|
||||
if data.Less(h, a) {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
for k := a; k < i-1; k++ {
|
||||
data.Swap(k, k+1)
|
||||
}
|
||||
return
|
||||
}
|
||||
if b-m == 1 {
|
||||
i := a
|
||||
j := m
|
||||
for i < j {
|
||||
h := int(uint(i+j) >> 1)
|
||||
if !data.Less(m, h) {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
for k := m; k > i; k-- {
|
||||
data.Swap(k, k-1)
|
||||
}
|
||||
return
|
||||
}
|
||||
mid := int(uint(a+b) >> 1)
|
||||
n := mid + m
|
||||
var start, r int
|
||||
if m > mid {
|
||||
start = n - b
|
||||
r = mid
|
||||
} else {
|
||||
start = a
|
||||
r = m
|
||||
}
|
||||
p := n - 1
|
||||
for start < r {
|
||||
c := int(uint(start+r) >> 1)
|
||||
if !data.Less(p-c, c) {
|
||||
start = c + 1
|
||||
} else {
|
||||
r = c
|
||||
}
|
||||
}
|
||||
end := n - start
|
||||
if start < m && m < end {
|
||||
rotate_func(data, start, m, end)
|
||||
}
|
||||
if a < start && start < mid {
|
||||
symMerge_func(data, a, start, mid)
|
||||
}
|
||||
if mid < end && end < b {
|
||||
symMerge_func(data, mid, end, b)
|
||||
}
|
||||
}
|
||||
|
||||
func swapRange_func(data lessSwap, a, b, n int) {
|
||||
for i := 0; i < n; i++ {
|
||||
data.Swap(a+i, b+i)
|
||||
}
|
||||
}
|
||||
|
||||
func rotate_func(data lessSwap, a, m, b int) {
|
||||
i := m - a
|
||||
j := b - m
|
||||
for i != j {
|
||||
if i > j {
|
||||
swapRange_func(data, m-i, m, j)
|
||||
i -= j
|
||||
} else {
|
||||
swapRange_func(data, m-i, m+j-i, i)
|
||||
j -= i
|
||||
}
|
||||
}
|
||||
swapRange_func(data, m-i, m, i)
|
||||
}
|
||||
|
||||
func insertionSort_func(data lessSwap, a, b int) {
|
||||
for i := a + 1; i < b; i++ {
|
||||
for j := i; j > a && data.Less(j, j-1); j-- {
|
||||
data.Swap(j, j-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-generated variant of sort.go:stable
|
||||
func stable_func(data lessSwap, n int) {
|
||||
blockSize := 20
|
||||
a, b := 0, blockSize
|
||||
for b <= n {
|
||||
insertionSort_func(data, a, b)
|
||||
a = b
|
||||
b += blockSize
|
||||
}
|
||||
insertionSort_func(data, a, n)
|
||||
for blockSize < n {
|
||||
a, b = 0, 2*blockSize
|
||||
for b <= n {
|
||||
symMerge_func(data, a, a+blockSize, b)
|
||||
a = b
|
||||
b += 2 * blockSize
|
||||
}
|
||||
if m := a + blockSize; m < n {
|
||||
symMerge_func(data, a, m, n)
|
||||
}
|
||||
blockSize *= 2
|
||||
}
|
||||
}
|
||||
// END sort.SliceStable
|
||||
|
||||
|
||||
func (rl *ruleList) sortRules(rules []sgfw.DbusRule) []sgfw.DbusRule {
|
||||
SliceStable(rules, func(i, j int) bool {
|
||||
in := rules[i].Sandbox + rules[i].App + rules[i].Target
|
||||
jn := rules[j].Sandbox + rules[j].App + rules[j].Target
|
||||
order := []string{in,jn}
|
||||
sort.Strings(order)
|
||||
if rules[i].App == rules[j].App && rules[i].Sandbox == rules[j].Sandbox {
|
||||
if sgfw.RuleAction(rules[i].Verb) == sgfw.RULE_ACTION_DENY || sgfw.RuleAction(rules[j].Verb) == sgfw.RULE_ACTION_DENY {
|
||||
if rules[i].Verb != rules[j].Verb {
|
||||
return (sgfw.RuleAction(rules[i].Verb) == sgfw.RULE_ACTION_DENY)
|
||||
}
|
||||
}
|
||||
}
|
||||
return (order[0] == in)
|
||||
})
|
||||
return rules
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Name=Subgraph Firewall Settings
|
||||
Comment=Launch the Subgraph Firewall Settings
|
||||
Keywords=Network;Security;Settings;Subgraph;Firewall;fwdaemon;
|
||||
TryExec=fw-settings
|
||||
Exec=fw-settings
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=security-medium
|
||||
Categories=Security;Settings;
|
||||
X-Desktop-File-Install-Version=0.23
|
||||
DBusActivatable=true
|
@ -1,4 +1,5 @@
|
||||
[D-BUS Service]
|
||||
Name=com.subgraph.FirewallPrompt
|
||||
Exec=/usr/bin/fw-prompt -display :0
|
||||
Exec=/usr/bin/fw-settings --prompt-only --display :0
|
||||
User=user
|
||||
#SystemdService=fw-settings.service
|
||||
|
@ -0,0 +1,31 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- tip
|
||||
|
||||
env:
|
||||
- GOARCH=amd64
|
||||
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq -y gtk+3.0 libgtk-3-dev
|
||||
- sudo apt-get install -qq -y xvfb
|
||||
- "export DISPLAY=:99.0"
|
||||
- sudo /usr/bin/Xvfb $DISPLAY 2>1 > /dev/null &
|
||||
- "export GTK_VERSION=$(pkg-config --modversion gtk+-3.0 | tr . _| cut -d '_' -f 1-2)"
|
||||
- "export Glib_VERSION=$(pkg-config --modversion glib-2.0)"
|
||||
- "export Cairo_VERSION=$(pkg-config --modversion cairo)"
|
||||
- "export Pango_VERSION=$(pkg-config --modversion pango)"
|
||||
- echo "GTK version ${GTK_VERSION} (Glib ${Glib_VERSION}, Cairo ${Cairo_VERSION}, Pango ${Pango_VERSION})"
|
||||
|
||||
install:
|
||||
- go get -t -tags "gtk_${GTK_VERSION}" github.com/gotk3/gotk3/...
|
||||
|
||||
script:
|
||||
- go test -tags "gtk_${GTK_VERSION}" ./...
|
@ -0,0 +1,210 @@
|
||||
package glib
|
||||
|
||||
// #cgo pkg-config: glib-2.0 gobject-2.0
|
||||
// #include <gio/gio.h>
|
||||
// #include <glib.h>
|
||||
// #include <glib-object.h>
|
||||
// #include "glib.go.h"
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
/*
|
||||
type ActionType int
|
||||
|
||||
const (
|
||||
ACTION_TYPE_ ActionType = C.GTK_
|
||||
)
|
||||
*/
|
||||
|
||||
// ActionGroup is a representation of GActionGroup.
|
||||
type ActionGroup struct {
|
||||
*Object
|
||||
}
|
||||
|
||||
// native() returns a pointer to the underlying GActionGroup.
|
||||
func (v *ActionGroup) native() *C.GActionGroup {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
return C.toGActionGroup(unsafe.Pointer(v.GObject))
|
||||
}
|
||||
|
||||
func (v *ActionGroup) Native() uintptr {
|
||||
return uintptr(unsafe.Pointer(v.native()))
|
||||
}
|
||||
|
||||
func marshalActionGroup(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
return wrapActionGroup(wrapObject(unsafe.Pointer(c))), nil
|
||||
}
|
||||
|
||||
func wrapActionGroup(obj *Object) *ActionGroup {
|
||||
return &ActionGroup{obj}
|
||||
}
|
||||
|
||||
// ActionGroup is a representation of GActionGroup.
|
||||
type Action struct {
|
||||
*Object
|
||||
}
|
||||
|
||||
// native() returns a pointer to the underlying GActionGroup.
|
||||
func (v *Action) native() *C.GAction {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
return C.toGAction(unsafe.Pointer(v.GObject))
|
||||
}
|
||||
|
||||
func (v *Action) Native() uintptr {
|
||||
return uintptr(unsafe.Pointer(v.native()))
|
||||
}
|
||||
|
||||
func marshalAction(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
return wrapAction(wrapObject(unsafe.Pointer(c))), nil
|
||||
}
|
||||
|
||||
func wrapAction(obj *Object) *Action {
|
||||
return &Action{obj}
|
||||
}
|
||||
|
||||
func (v *Action) NameIsValid(name string) bool {
|
||||
cstr := (*C.gchar)(C.CString(name))
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
return gobool(C.g_action_name_is_valid(cstr))
|
||||
}
|
||||
|
||||
func (v *Action) GetName() string {
|
||||
c := C.g_action_get_name(v.native())
|
||||
|
||||
return C.GoString((*C.char)(c))
|
||||
}
|
||||
|
||||
// XXX: g_action_get_parameter_type
|
||||
// XXX: g_action_get_state_type
|
||||
// XXX: g_action_get_state_hint
|
||||
|
||||
func (v *Action) GetEnabled() bool {
|
||||
return gobool(C.g_action_get_enabled(v.native()))
|
||||
}
|
||||
|
||||
// XXX: g_action_get_state
|
||||
// XXX: g_action_change_state
|
||||
|
||||
func (v *Action) Activate(p *Variant) {
|
||||
C.g_action_activate(v.native(), p.native())
|
||||
}
|
||||
|
||||
// XXX: g_action_parse_detailed_name
|
||||
// XXX: g_action_print_detailed_name
|
||||
|
||||
|
||||
|
||||
// ActionGroup is a representation of GActionGroup.
|
||||
type SimpleAction struct {
|
||||
Action
|
||||
}
|
||||
|
||||
// native() returns a pointer to the underlying GActionGroup.
|
||||
func (v *SimpleAction) native() *C.GSimpleAction {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
return C.toGSimpleAction(unsafe.Pointer(v.GObject))
|
||||
}
|
||||
|
||||
func (v *SimpleAction) Native() uintptr {
|
||||
return uintptr(unsafe.Pointer(v.native()))
|
||||
}
|
||||
|
||||
func marshalSimpleAction(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
return wrapSimpleAction(wrapObject(unsafe.Pointer(c))), nil
|
||||
}
|
||||
|
||||
func wrapSimpleAction(obj *Object) *SimpleAction {
|
||||
return &SimpleAction{*wrapAction(obj)}
|
||||
}
|
||||
|
||||
func SimpleActionNew(name string, t *VariantType) *SimpleAction {
|
||||
cstr := (*C.gchar)(C.CString(name))
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
c := C.g_simple_action_new(cstr, t.native())
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return wrapSimpleAction(wrapObject(unsafe.Pointer(c)))
|
||||
}
|
||||
|
||||
func (v *SimpleAction) NewStateful(name string, t *VariantType, state *Variant) *SimpleAction {
|
||||
cstr := (*C.gchar)(C.CString(name))
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
c := C.g_simple_action_new_stateful(cstr, t.native(), state.native())
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return wrapSimpleAction(wrapObject(unsafe.Pointer(c)))
|
||||
}
|
||||
|
||||
func (v *SimpleAction) SetEnabled(state bool) {
|
||||
C.g_simple_action_set_enabled(v.native(), gbool(state))
|
||||
}
|
||||
|
||||
func (v *SimpleAction) SetState(state Variant) {
|
||||
C.g_simple_action_set_state(v.native(), state.ToGVariant())
|
||||
}
|
||||
|
||||
// XXX: g_simple_action_set_state_hint
|
||||
|
||||
|
||||
// ActionGroup is a representation of GActionGroup.
|
||||
type ActionMap struct {
|
||||
*Object
|
||||
}
|
||||
|
||||
// native() returns a pointer to the underlying GActionGroup.
|
||||
func (v *ActionMap) native() *C.GActionMap {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
return C.toGActionMap(unsafe.Pointer(v.GObject))
|
||||
}
|
||||
|
||||
func (v *ActionMap) Native() uintptr {
|
||||
return uintptr(unsafe.Pointer(v.native()))
|
||||
}
|
||||
|
||||
func marshalActionMap(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
return wrapActionMap(wrapObject(unsafe.Pointer(c))), nil
|
||||
}
|
||||
|
||||
func wrapActionMap(obj *Object) *ActionMap {
|
||||
return &ActionMap{obj}
|
||||
}
|
||||
|
||||
func (v *ActionMap) LookupAction(name string) *Action {
|
||||
cstr := (*C.gchar)(C.CString(name))
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
c := C.g_action_map_lookup_action(v.native(), cstr)
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return wrapAction(wrapObject(unsafe.Pointer(c)))
|
||||
}
|
||||
/*
|
||||
// Requires GActionEntry
|
||||
func (v *ActionMap) AddActionEntries() {
|
||||
|
||||
}
|
||||
*/
|
||||
func (v *ActionMap) AddAction(action *Action) {
|
||||
C.g_action_map_add_action(v.native(), action.native())
|
||||
}
|
||||
|
||||
func (v *ActionMap) RemoveAction(name string) {
|
||||
cstr := (*C.gchar)(C.CString(name))
|
||||
defer C.free(unsafe.Pointer(cstr))
|
||||
C.g_action_map_remove_action(v.native(), cstr)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,26 @@
|
||||
// +build !gtk_3_6,!gtk_3_8
|
||||
|
||||
package gtk
|
||||
|
||||
// #cgo pkg-config: gtk+-3.0
|
||||
// #include <gtk/gtk.h>
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
)
|
||||
|
||||
//export goListBoxFilterFuncs
|
||||
func goListBoxFilterFuncs(row *C.GtkListBoxRow, userData C.gpointer) C.gboolean {
|
||||
id := int(uintptr(userData))
|
||||
|
||||
listBoxFilterFuncRegistry.Lock()
|
||||
r := listBoxFilterFuncRegistry.m[id]
|
||||
// TODO: figure out a way to determine when we can clean up
|
||||
//delete(printSettingsCallbackRegistry.m, id)
|
||||
listBoxFilterFuncRegistry.Unlock()
|
||||
|
||||
return gbool(r.fn(wrapListBoxRow(glib.Take(unsafe.Pointer(row))), r.userData))
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
// +build !gtk_3_6,!gtk_3_8,!gtk_3_10,!gtk_3_12,!gtk_3_14,!gtk_3_16,!gtk_3_18,gtk_3_20
|
||||
|
||||
// See: https://developer.gnome.org/gtk3/3.20/api-index-3-20.html
|
||||
|
||||
package gtk
|
||||
|
||||
// #cgo pkg-config: gtk+-3.0
|
||||
// #include <gtk/gtk.h>
|
||||
// #include "gtk_since_3_20.go.h"
|
||||
import "C"
|
@ -0,0 +1,33 @@
|
||||
// Same copyright and license as the rest of the files in this project
|
||||
// This file contains accelerator related functions and structures
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static GtkShortcutsWindow *
|
||||
toGtkShortcutsWindow(void *p)
|
||||
{
|
||||
return (GTK_SHORTCUTS_WINDOW(p));
|
||||
}
|
||||
|
||||
static GtkShortcutsSection *
|
||||
toGtkShortcutsSection(void *p)
|
||||
{
|
||||
return (GTK_SHORTCUTS_SECTION(p));
|
||||
}
|
||||
|
||||
static GtkShortcutsGroup *
|
||||
toGtkShortcutsGroup(void *p)
|
||||
{
|
||||
return (GTK_SHORTCUTS_GROUP(p));
|
||||
}
|
||||
|
||||
static GtkShortcutsShortcut *
|
||||
toGtkShortcutsShortcut(void *p)
|
||||
{
|
||||
return (GTK_SHORTCUTS_SHORTCUT(p));
|
||||
}
|
||||
|
@ -0,0 +1,147 @@
|
||||
// +build !gtk_3_6,!gtk_3_8,!gtk_3_10,!gtk_3_12,!gtk_3_14, !gtk_3_16, !gtk_3_18
|
||||
|
||||
// See: https://developer.gnome.org/gtk3/3.20/api-index-3-20.html
|
||||
|
||||
package gtk
|
||||
|
||||
// #include <gtk/gtk.h>
|
||||
// #include "gtk.go.h"
|
||||
// #include "gtk_since_3_20.go.h"
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
)
|
||||
|
||||
func init() {
|
||||
tm := []glib.TypeMarshaler{
|
||||
{glib.Type(C.gtk_shortcuts_window_get_type()), marshalShortcutsWindow},
|
||||
{glib.Type(C.gtk_shortcuts_section_get_type()), marshalShortcutsSection},
|
||||
{glib.Type(C.gtk_shortcuts_group_get_type()), marshalShortcutsGroup},
|
||||
{glib.Type(C.gtk_shortcuts_shortcut_get_type()), marshalShortcutsShortcut},
|
||||
}
|
||||
|
||||
glib.RegisterGValueMarshalers(tm)
|
||||
|
||||
WrapMap["GtkShortcutsWindow"] = wrapShortcutsWindow
|
||||
WrapMap["GtkShortcutsSection"] = wrapShortcutsSection
|
||||
WrapMap["GtkShortcutsGroup"] = wrapShortcutsGroup
|
||||
WrapMap["GtkShortcutsShortcut"] = wrapShortcutsShortcut
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GtkShortcutsWindow
|
||||
*/
|
||||
|
||||
// ShortcutsWindow is a representation of GTK's GtkShortcutsWindow.
|
||||
type ShortcutsWindow struct {
|
||||
Window
|
||||
}
|
||||
|
||||
// native returns a pointer to the underlying GtkAboutDialog.
|
||||
func (v *ShortcutsWindow) native() *C.GtkShortcutsWindow {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
p := unsafe.Pointer(v.GObject)
|
||||
return C.toGtkShortcutsWindow(p)
|
||||
}
|
||||
|
||||
func marshalShortcutsWindow(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
obj := glib.Take(unsafe.Pointer(c))
|
||||
return wrapShortcutsWindow(obj), nil
|
||||
}
|
||||
|
||||
func wrapShortcutsWindow(obj *glib.Object) *ShortcutsWindow {
|
||||
return &ShortcutsWindow{Window{Bin{Container{Widget{glib.InitiallyUnowned{obj}}}}}}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GtkShortcutsSection
|
||||
*/
|
||||
|
||||
// ShortcutsWindow is a representation of GTK's GtkShortcutsWindow.
|
||||
type ShortcutsSection struct {
|
||||
Box
|
||||
}
|
||||
|
||||
// native returns a pointer to the underlying GtkAboutDialog.
|
||||
func (v *ShortcutsSection) native() *C.GtkShortcutsSection {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
p := unsafe.Pointer(v.GObject)
|
||||
return C.toGtkShortcutsSection(p)
|
||||
}
|
||||
|
||||
func marshalShortcutsSection(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
obj := glib.Take(unsafe.Pointer(c))
|
||||
return wrapShortcutsSection(obj), nil
|
||||
}
|
||||
|
||||
func wrapShortcutsSection(obj *glib.Object) *ShortcutsSection {
|
||||
return &ShortcutsSection{Box{Container{Widget{glib.InitiallyUnowned{obj}}}}}
|
||||
}
|
||||
|
||||
/*
|
||||
* GtkShortcutsSection
|
||||
*/
|
||||
|
||||
// ShortcutsWindow is a representation of GTK's GtkShortcutsWindow.
|
||||
type ShortcutsGroup struct {
|
||||
Box
|
||||
}
|
||||
|
||||
// native returns a pointer to the underlying GtkAboutDialog.
|
||||
func (v *ShortcutsGroup) native() *C.GtkShortcutsGroup {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
p := unsafe.Pointer(v.GObject)
|
||||
return C.toGtkShortcutsGroup(p)
|
||||
}
|
||||
|
||||
func marshalShortcutsGroup(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
obj := glib.Take(unsafe.Pointer(c))
|
||||
return wrapShortcutsGroup(obj), nil
|
||||
}
|
||||
|
||||
func wrapShortcutsGroup(obj *glib.Object) *ShortcutsGroup {
|
||||
return &ShortcutsGroup{Box{Container{Widget{glib.InitiallyUnowned{obj}}}}}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GtkShortcutsShortcut
|
||||
*/
|
||||
|
||||
// ShortcutsWindow is a representation of GTK's GtkShortcutsWindow.
|
||||
type ShortcutsShortcut struct {
|
||||
Box
|
||||
}
|
||||
|
||||
// native returns a pointer to the underlying GtkAboutDialog.
|
||||
func (v *ShortcutsShortcut) native() *C.GtkShortcutsShortcut {
|
||||
if v == nil || v.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
p := unsafe.Pointer(v.GObject)
|
||||
return C.toGtkShortcutsShortcut(p)
|
||||
}
|
||||
|
||||
func marshalShortcutsShortcut(p uintptr) (interface{}, error) {
|
||||
c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
|
||||
obj := glib.Take(unsafe.Pointer(c))
|
||||
return wrapShortcutsShortcut(obj), nil
|
||||
}
|
||||
|
||||
func wrapShortcutsShortcut(obj *glib.Object) *ShortcutsShortcut {
|
||||
return &ShortcutsShortcut{Box{Container{Widget{glib.InitiallyUnowned{obj}}}}}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
language: go
|
||||
|
||||
build_image: shippableimages/ubuntu1404_go
|
||||
|
||||
go:
|
||||
- tip
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -y
|
||||
- sudo apt-get install -y libglib2.0-dev libcairo2-dev libgtk-3-dev xvfb
|
||||
- source $HOME/.gvm/scripts/gvm;
|
||||
- if [[ $SHIPPABLE_GO_VERSION == "tip" ]]; then gvm install tip; gvm use tip; fi
|
||||
- if [[ $SHIPPABLE_GO_VERSION == *release* ]]; then gvm install release; gvm use release; fi
|
||||
- if [[ $SHIPPABLE_GO_VERSION =~ [0-9].[0-9] ]]; then gvm install go$SHIPPABLE_GO_VERSION; gvm use go$SHIPPABLE_GO_VERSION; fi
|
||||
- export GOPATH=$SHIPPABLE_GOPATH
|
||||
- go get github.com/t-yuki/gocover-cobertura
|
||||
- go get github.com/onsi/gomega
|
||||
- go get github.com/onsi/ginkgo
|
||||
- go get code.google.com/p/go.tools/cmd/cover
|
||||
- "export DISPLAY=:99.0"
|
||||
- /usr/bin/Xvfb :99 &
|
||||
|
||||
install:
|
||||
- go build -tags gtk_3_10 -v ./...
|
||||
|
||||
script:
|
||||
- go test -tags gtk_3_10 -coverprofile=coverage_gtk.txt -covermode count ./gtk
|
||||
- go test -tags gtk_3_10 ./glib
|
||||
- $GOPATH/bin/gocover-cobertura < coverage_gtk.txt > shippable/codecoverage/coverage_gtk.xml
|
Loading…
Reference in new issue