diff --git a/com.umorist47.meowrelaygui/contents/config/main.xml b/com.umorist47.meowrelaygui/contents/config/main.xml
index 559530b..5a64469 100644
--- a/com.umorist47.meowrelaygui/contents/config/main.xml
+++ b/com.umorist47.meowrelaygui/contents/config/main.xml
@@ -57,6 +57,9 @@
true
+
+ true
+
true
diff --git a/com.umorist47.meowrelaygui/contents/ui/config/General.qml b/com.umorist47.meowrelaygui/contents/ui/config/General.qml
index 37b20bc..9105fdd 100644
--- a/com.umorist47.meowrelaygui/contents/ui/config/General.qml
+++ b/com.umorist47.meowrelaygui/contents/ui/config/General.qml
@@ -26,6 +26,7 @@ KCM.SimpleKCM {
property alias cfg_BIpostebalka: showSwitchEbalkaBI.checked
property alias cfg_BIdevicesupdate: showDevicesActionsBI.checked
property alias cfg_BIfeaturesupdate: showFeaturesActionsBI.checked
+ property alias cfg_BIpostfirewall: showFirewallActionsBI.checked
property alias cfg_BIautoupdate: showAutoUpdateBI.checked
property alias cfg_SBdisplay: showSB.checked
@@ -84,6 +85,7 @@ KCM.SimpleKCM {
}
RowLayout {
Kirigami.FormData.label: i18n("Ping")
+ enabled: false
CheckBox {
id: enablePing
}
@@ -137,6 +139,10 @@ KCM.SimpleKCM {
id: showFeaturesActionsBI
text: i18n("Features actions")
}
+ CheckBox {
+ id: showFirewallActionsBI
+ text: i18n("Firewall actions")
+ }
CheckBox {
id: showAutoUpdateBI
text: i18n("AutoUpdate actions")
diff --git a/com.umorist47.meowrelaygui/contents/ui/main.qml b/com.umorist47.meowrelaygui/contents/ui/main.qml
index 6b64a3e..5300251 100644
--- a/com.umorist47.meowrelaygui/contents/ui/main.qml
+++ b/com.umorist47.meowrelaygui/contents/ui/main.qml
@@ -23,18 +23,17 @@ PlasmoidItem {
//me/profile
property var profileData: null
- property alias profileDataAlias: root.profileData
- property string user: profileData.user
- property bool is_admin: profileData.user_data.is_admin
- property bool share: profileData.user_data.share
- property bool ebalka: profileData.ebalka
- property string current_device: profileData.current_device
- property string current: profileData.current
- property string provider: profileData.provider
- property string ip: profileData.ip
- property var features: profileData.features
- property var devices: profileData.devices
+ property string user: profileData ? profileData.user : ""
+ property bool is_admin: profileData ? profileData.user_data.is_admin : false
+ property bool share: profileData ? profileData.user_data.share : false
+ property bool ebalka: profileData ? profileData.ebalka : false
+ property string current_device: profileData ? profileData.current_device : ""
+ property string current: profileData ? profileData.current : ""
+ property string provider: profileData ? profileData.provider : ""
+ property string ip: profileData ? profileData.ip : ""
+ property var features: profileData ? profileData.features : null
+ property var devices: profileData ? profileData.devices : null
//routes
property var routesData: null
@@ -42,8 +41,38 @@ PlasmoidItem {
//stats
property var statsData: null
- property double uptime: statsData.uptime
- property var servers: statsData.servers
+ //firewall
+ property var firewallData: null
+ property bool firewallAccess: firewallData ? (firewallData.state === 0) : false
+ property bool firewallEnabled: false
+
+ property double uptime: statsData ? statsData.uptime : 0
+ property var servers: statsData ? statsData.servers : null
+
+ // tabs
+ ListModel {
+ id: tabs
+ ListElement {
+ name: "Route"
+ visible: true
+ }
+ ListElement {
+ name: "Devices"
+ visible: true
+ }
+ ListElement {
+ name: "Firewall"
+ visible: false
+ }
+ ListElement {
+ name: "Stats"
+ visible: true
+ }
+ ListElement {
+ name: "Features"
+ visible: true
+ }
+ }
// tabs json responses
ListModel { id: routeModel }
@@ -51,6 +80,9 @@ PlasmoidItem {
ListModel { id: profileModel }
ListModel { id: devicesModel }
ListModel { id: featuresModel }
+ ListModel { id: firewallModel }
+ ListModel { id: ownedipsModel }
+ ListModel { id: ownedlocalipsModel }
// buttons blocker (antispam)
property int isLoadingItems: 0
@@ -62,6 +94,8 @@ PlasmoidItem {
property bool countriesBlocked: false
property bool devicesBlocked: false
property bool featuresBlocked: false
+ property bool firewallBlocked: false
+ property bool timeouted: false
onIsLoadingItemsChanged: {
if (isLoadingItems > 0) {
@@ -100,11 +134,7 @@ PlasmoidItem {
repeat: false
onTriggered: {
console.error("MeowRelay unreachable!") //ваша няшка умерла
- routeModel.clear()
- routeModel.append({"code":"ERR","name":"Error, MeowRelay unreachable :<","provider":"NONE"})
- routesData = [{"code":"ERR","name":"Error, MeowRelay unreachable :<","provider":"NONE"}]
- profileData = {"provider":"NONE"}
- statsData = null
+ timeouted = true
isBlocked = false
isLoadingItems = 0
countriesBlocked = true
@@ -112,6 +142,7 @@ PlasmoidItem {
ebalkaBlocked = true
devicesBlocked = true
featuresBlocked = true
+ firewallBlocked = true
Plasmoid.configuration.OnErrorRefresh ? (
meowRelayWatchdog.start(),
isLoadingItems += Plasmoid.configuration.BIrefresh,
@@ -119,19 +150,62 @@ PlasmoidItem {
superWorker.sendMessage({ "action": "fetch_routes" }),
superWorker.sendMessage({ "action": "fetch_profile" }),
superWorker.sendMessage({ "action": "fetch_stats" }),
+ superWorker.sendMessage({ "action": "fetch_firewall" }),
fetchRoutesTimer.restart(),
fetchProfileTimer.restart(),
fetchStatsTimer.restart()
) : null
}
}
+ Timer {
+ id: meowRelayWatchdogRoutes
+ interval: 10000
+ repeat: false
+ onTriggered: {
+ console.error("MeowRelay unreachable!") //ваша няшка умерла
+ timeouted = true
+ refreshBlocked = false
+ Plasmoid.configuration.OnErrorRefresh ? (
+ meowRelayWatchdogRoutes.start(),
+ isLoadingItems += Plasmoid.configuration.BIrefresh,
+ //isBlocked = true,
+ superWorker.sendMessage({ "action": "fetch_routes" }),
+ fetchRoutesTimer.restart()
+ ) : null
+ }
+ }
+ Timer {
+ id: meowRelayWatchdogProfile
+ interval: 10000
+ repeat: false
+ onTriggered: {
+ console.error("MeowRelay unreachable!") //ваша няшка умерла
+ timeouted = true
+ refreshBlocked = false
+ Plasmoid.configuration.OnErrorRefresh ? (
+ meowRelayWatchdogProfile.start(),
+ isLoadingItems += Plasmoid.configuration.BIrefresh,
+ //isBlocked = true,
+ superWorker.sendMessage({ "action": "fetch_profile" }),
+ fetchProfileTimer.restart()
+ ) : null
+ }
+ }
Timer {
id: meowRelayWatchdogStats
interval: 10000
repeat: false
onTriggered: {
console.error("MeowRelay unreachable!") //ваша няшка умерла
+ timeouted = true
refreshBlocked = false
+ Plasmoid.configuration.OnErrorRefresh ? (
+ meowRelayWatchdogStats.start(),
+ isLoadingItems += Plasmoid.configuration.BIrefresh,
+ //isBlocked = true,
+ superWorker.sendMessage({ "action": "fetch_stats" }),
+ fetchStatsTimer.restart()
+ ) : null
}
}
Timer {
@@ -160,7 +234,9 @@ PlasmoidItem {
if (Plasmoid.configuration.BIrefresh || Plasmoid.configuration.BIautoupdate) {
isLoadingItems -= 1
};
+ meowRelayWatchdogRoutes.stop();
refreshBlocked = false;
+ timeouted = false;
},
"fetch_stats": ({ data }) => {
statsModel.clear();
@@ -187,11 +263,13 @@ PlasmoidItem {
};
meowRelayWatchdogStats.stop();
refreshBlocked = false;
+ timeouted = false;
},
"fetch_profile": ({ data }) => {
profileModel.clear();
devicesModel.clear();
featuresModel.clear();
+ ownedlocalipsModel.clear();
profileData = data;
for (let i = 0; i < data.length; i++) {
profileModel.append(data[i]);
@@ -199,13 +277,24 @@ PlasmoidItem {
for (let i = 0; i < data.devices.length; i++) {
devicesModel.append(data.devices[i])
}
+ if (Array.isArray(data.devices)) {
+ data.devices.forEach(function(device) {
+ ownedlocalipsModel.append({ "ip": device.ip });
+ });
+ }
for (let i = 0; i < data.features.length; i++) {
featuresModel.append(data.features[i])
+ if (data.features[i].name == "FEATURE_PORTCONFIGURATOR") {
+ firewallEnabled = data.features[i].value
+ tabs.setProperty(2, "visible", firewallEnabled)
+ }
}
if (Plasmoid.configuration.BIrefresh || Plasmoid.configuration.BIautoupdate) {
isLoadingItems -= 1
}
meowRelayWatchdog.stop();
+ meowRelayWatchdogProfile.stop();
+ timeouted = false;
isBlocked = false;
refreshBlocked = false;
countriesBlocked = false;
@@ -214,6 +303,37 @@ PlasmoidItem {
devicesBlocked = false;
featuresBlocked = false;
},
+ "fetch_firewall": ({ data }) => {
+ firewallModel.clear();
+ ownedipsModel.clear();
+ firewallData = data;
+ if (data.state === 0 && data.own && Array.isArray(data.own)) {
+ data.own.forEach(function(ip) {
+ ownedipsModel.append({ ip });
+ });
+ }
+ if (data.state === 0 && data.rules) {
+ Object.keys(data.rules).forEach(function(ipKey) {
+ var rulesArray = data.rules[ipKey];
+
+ rulesArray.forEach(function(rule) {
+ firewallModel.append({
+ "ip": ipKey,
+ "dst": rule.dst,
+ "port": rule.port,
+ "local_port": rule.local_port,
+ "proto": rule.proto,
+ "packets": (rule.packets ? rule.packets : 0),
+ "bytes": (rule.bytes ? rule.bytes : 0)
+ });
+ });
+ });
+ }
+ firewallBlocked = false;
+ if (Plasmoid.configuration.BIpostfirewall) {
+ isLoadingItems -= 1
+ };
+ },
"post_country": ({ status }) => {
if (status === 200) {
superWorker.sendMessage({ "action": "fetch_profile" })
@@ -286,6 +406,18 @@ PlasmoidItem {
if (Plasmoid.configuration.BIpostcountry) {
isLoadingItems -= 1
}
+ },
+ "post_ruleadd": ({ status }) => {
+ superWorker.sendMessage({ "action": "fetch_firewall" });
+ if (Plasmoid.configuration.BIpostfirewall) {
+ isLoadingItems -= 1
+ }
+ },
+ "post_ruledrop": ({ status }) => {
+ superWorker.sendMessage({ "action": "fetch_firewall" });
+ if (Plasmoid.configuration.BIpostfirewall) {
+ isLoadingItems -= 1
+ }
}
})
@@ -304,10 +436,11 @@ PlasmoidItem {
superWorker.sendMessage({ "action": "fetch_routes" })
superWorker.sendMessage({ "action": "fetch_stats" })
superWorker.sendMessage({ "action": "fetch_profile" })
+ superWorker.sendMessage({ "action": "fetch_firewall" })
fetchRoutesTimer.start()
fetchStatsTimer.start()
fetchProfileTimer.start()
- meowRelayPing.start()
+ // meowRelayPing.start()
}
// autoupdate fetch
@@ -318,8 +451,9 @@ PlasmoidItem {
repeat: true
triggeredOnStart: false
onTriggered: {
- refreshBlocked = true
+ //refreshBlocked = true
isLoadingItems += Plasmoid.configuration.BIautoupdate
+ meowRelayWatchdogRoutes.start()
superWorker.sendMessage({ "action": "fetch_routes" })
}
}
@@ -330,7 +464,7 @@ PlasmoidItem {
repeat: true
triggeredOnStart: false
onTriggered: {
- refreshBlocked = true
+ //refreshBlocked = true
isLoadingItems += Plasmoid.configuration.BIautoupdate
meowRelayWatchdogStats.start()
superWorker.sendMessage({ "action": "fetch_stats" })
@@ -343,109 +477,14 @@ PlasmoidItem {
repeat: true
triggeredOnStart: false
onTriggered: {
- refreshBlocked = true
+ //refreshBlocked = true
isLoadingItems += Plasmoid.configuration.BIautoupdate
- meowRelayWatchdog.start()
+ meowRelayWatchdogProfile.start()
superWorker.sendMessage({ "action": "fetch_profile" })
}
}
- compactRepresentation: Item {
- Layout.minimumWidth: govnoLayout.implicitWidth
- Layout.minimumHeight: Kirigami.Units.iconSizes.medium
-
- Layout.maximumWidth: govnoLayout.implicitWidth
- Layout.maximumHeight: Layout.minimumHeight
-
- Layout.preferredWidth: govnoLayout.implicitWidth
- Layout.preferredHeight: Layout.minimumHeight
-
- MouseArea {
- id: mouseArea
- //property bool wasExpanded
-
- Accessible.name: Plasmoid.title
- Accessible.role: Accessible.Button
- //Accessible.description: desc
-
- //onPressed: wasExpanded = root.expanded
- //onClicked: root.expanded = !wasExpanded
-
- onClicked: Plasmoid.activated();
-
- Keys.onPressed: {
- switch (event.key) {
- case Qt.Key_Space:
- case Qt.Key_Enter:
- case Qt.Key_Return:
- case Qt.Key_Select:
- Plasmoid.activated();
- break;
- }
- }
-
- // иконки не будет без этой залупы
- anchors.fill: parent
- anchors.leftMargin: 0
-
- activeFocusOnTab: true
- hoverEnabled: true
-
- Component {
- id: meowIconComponent
- Kirigami.Icon {
- Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5
- Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
- Layout.alignment: Qt.AlignVCenter
- source: Qt.resolvedUrl("../images/dogfood.svg")
- isMask: true
- active: mouseArea.containsMouse
- }
- }
- Component {
- id: genericLabelComponent
- Label {
- property string labelText: "yaebalrot"
- text: labelText === "yaebalrot" ? "" : labelText
- color: text === "error" ? "red" : Kirigami.Theme.textColor
- font.pointSize: Kirigami.Theme.mediumFont.pointSize
- verticalAlignment: Text.AlignVCenter
- }
- }
-
- property var configArray: Plasmoid.configuration.ExtraLayout === true ? Plasmoid.configuration.StringLayoutPlacement.split(" ") : ["meow_icon"]
- RowLayout {
- id: govnoLayout
- anchors.fill: parent
- spacing: Kirigami.Units.smallSpacing
-
- Repeater {
- model: mouseArea.configArray
-
- Loader {
- id: govnoebanoe
- // Logic to choose WHICH component to spawn
- sourceComponent: (modelData === "meow_icon") ? meowIconComponent : genericLabelComponent
-
- // Logic to pass DATA to that component
- Binding {
- target: govnoebanoe.item // The Label we just created
- property: "labelText" // The property on the Label
- value: root[modelData] // The live variable in root
- when: govnoebanoe.status === Loader.Ready && modelData !== "meow_icon"
- }
- Layout.fillHeight: true
- }
- }
- }
- // Kirigami.Icon {
- // anchors.fill: parent
- // source: Qt.resolvedUrl("../images/dogfood.svg")
- // isMask: true
- // active: mouseArea.containsMouse
- // }
- }
- }
+ compactRepresentation: Compact {}
fullRepresentation: PlasmaExtras.Representation {
//id: fullRoot
@@ -456,6 +495,11 @@ PlasmoidItem {
//spacing: 0
header: PlasmaExtras.PlasmoidHeading {
+ // Make this toolbar's buttons align vertically with the ones above
+ rightPadding: -1
+ // Allow tabbar to touch the header's bottom border
+ bottomPadding: -bottomInset
+
contentItem: ColumnLayout {
spacing: Kirigami.Units.smallSpacing
@@ -520,9 +564,11 @@ PlasmoidItem {
Layout.fillWidth: true
Repeater {
- model: ["Route", "Devices", "Stats", "Features"]
+ model: tabs
delegate: PlasmaComponents.TabButton {
- text: modelData
+ text: model.name
+ visible: model.visible
+ width: firewallEnabled ? (mainTabBar.width / 5) : ((model.name == "Firewall") ? 0 : (mainTabBar.width / 4)) // это пизда или нармалды
}
}
}
@@ -542,6 +588,114 @@ PlasmoidItem {
Layout.fillWidth: true
}
+ // Tab 3 util buttons
+ RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+ visible: (mainTabBar.currentIndex === 2 && firewallAccess && firewallEnabled)
+ PlasmaComponents.ComboBox {
+ id: firewallProto
+ model: ["tcp", "udp"]
+ currentIndex: 0
+ }
+ Kirigami.ContextualHelpButton {
+ toolTipText: i18n(
+ 'All ' + firewallProto.currentValue + ' traffic from ' + firewallIp.currentValue + ':' + firewallPortSpinner.value + ' will be forwarded to ' + firewallLocalIp.currentValue + ':' + firewallLocalPortSpinner.value
+ )
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.Button {
+ text: "Update"
+ icon.name: "view-refresh"
+ enabled: !(isBlocked)
+ onClicked: {
+ isLoadingItems += Plasmoid.configuration.BIpostfirewall
+ firewallBlocked = true
+ superWorker.sendMessage({ "action": "fetch_firewall" })
+ }
+ }
+ PlasmaComponents.Button {
+ text: "Add"
+ enabled: !(isBlocked || firewallBlocked)
+ onClicked: {
+ isLoadingItems += Plasmoid.configuration.BIpostfirewall
+ firewallBlocked = true
+ superWorker.sendMessage({ "action": "post_ruleadd", "dst": firewallLocalIp.currentValue, "ext": firewallIp.currentValue, "local_port": firewallLocalPortSpinner.value, "port": firewallPortSpinner.value, "proto": firewallProto.currentValue })
+ }
+ }
+ }
+ RowLayout {
+ spacing: Kirigami.Units.smallSpacing
+ visible: (mainTabBar.currentIndex === 2 && firewallAccess && firewallEnabled)
+ PlasmaComponents.ComboBox {
+ id: firewallIp
+ model: ownedipsModel
+ currentIndex: 0
+ Connections {
+ target: ownedipsModel
+
+ function onCountChanged() {
+ if (ownedipsModel.count > 0) {
+ firewallIp.currentIndex = 0;
+ }
+ }
+ }
+ }
+ PlasmaComponents.Label {
+ text: ":"
+ font.bold: true
+ }
+ SpinBox {
+ id: firewallPortSpinner
+ from: 1
+ to: 65535
+ value: 1
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.Label {
+ text: "→"
+ font.bold: true
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.ComboBox {
+ id: firewallLocalIp
+ model: ownedlocalipsModel
+ currentIndex: 0
+ Connections {
+ target: ownedlocalipsModel
+
+ function onCountChanged() {
+ if (ownedlocalipsModel.count > 0) {
+ firewallLocalIp.currentIndex = 0;
+ }
+ }
+ }
+ }
+ PlasmaComponents.Label {
+ text: ":"
+ font.bold: true
+ }
+ SpinBox {
+ id: firewallLocalPortSpinner
+ from: 1
+ to: 65535
+ value: 1
+ }
+ }
+ Rectangle {
+ visible: (mainTabBar.currentIndex === 2 && firewallAccess && firewallEnabled)
+ height: 1
+ Layout.alignment: AlignVCenter
+ Layout.fillWidth: true
+ color: PlasmaCore.Theme.dividerColor
+ opacity: 0.2
+ }
+
RowLayout {
spacing: Kirigami.Units.smallSpacing
PlasmaComponents.Label {
@@ -617,6 +771,7 @@ PlasmoidItem {
superWorker.sendMessage({ "action": "fetch_routes" })
superWorker.sendMessage({ "action": "fetch_profile" })
superWorker.sendMessage({ "action": "fetch_stats" })
+ superWorker.sendMessage({ "action": "fetch_firewall" })
fetchRoutesTimer.restart()
fetchProfileTimer.restart()
fetchStatsTimer.restart()
@@ -629,6 +784,20 @@ PlasmoidItem {
implicitWidth: 28
implicitHeight: 28
}
+ Kirigami.Icon {
+ source: "network-limited-symbolic"
+ visible: timeouted
+ implicitWidth: 30
+ implicitHeight: 30
+ //isMask: true
+ //active: mouseArea.containsMouse
+ }
+ Kirigami.ContextualHelpButton {
+ visible: timeouted
+ toolTipText: i18n(
+ "MeowRelay unreachable! (timeout)"
+ )
+ }
Item {
Layout.fillWidth: true
}
@@ -674,411 +843,555 @@ PlasmoidItem {
currentIndex: mainTabBar.currentIndex
// Tab 1 Routes
- PlasmaComponents.ScrollView {
- id: routeScroll
- anchors.fill: parent
- ScrollBar.vertical.policy: scrollbartype
-
- Column {
- id: listContainer
- width: routeScroll.availableWidth
- spacing: 0
-
- // Countries
- Repeater {
- model: routeModel
- delegate: PlasmaComponents.RadioDelegate {
- width: listContainer.width
- height: Kirigami.Units.gridUnit * 3
- enabled: !countriesBlocked
- checked: (model.code === current && model.provider === provider)
-
- contentItem: RowLayout {
- spacing: Kirigami.Units.largeSpacing
- PlasmaComponents.Label {
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- wrapMode: Text.Wrap
- font.pixelSize: 24
- text: getFlag(model.code)
- }
-
- ColumnLayout {
- spacing: 0
- Layout.fillWidth: true
- PlasmaComponents.Label {
- text: model.name
- font.bold: true
- Layout.fillWidth: true
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: model.provider
- font.pointSize: Kirigami.Theme.smallFont.pointSize
- opacity: 0.7
- Layout.fillWidth: true
- verticalAlignment: Text.AlignVCenter
- }
- }
- }
- onClicked: {
- isLoadingItems += Plasmoid.configuration.BIpostcountry
- superWorker.sendMessage({ "action": "post_country", "code": model.code, "provider": model.provider })
- }
- }
- }
+ Item {
+ PlasmaExtras.PlaceholderMessage {
+ anchors.centerIn: parent
+ text: "Connecting to\nMeowRelay"
+ iconName: "akregator-symbolic"
+ visible: routesData === null
}
- }
+ PlasmaComponents.ScrollView {
+ id: routeScroll
+ anchors.fill: parent
+ ScrollBar.vertical.policy: scrollbartype
- PlasmaComponents.ScrollView {
- id: devicesScroll
- anchors.fill: parent
- ScrollBar.vertical.policy: scrollbartype
+ Column {
+ id: listContainer
+ width: routeScroll.availableWidth
+ spacing: 0
- Column {
- id: deviceListContainer
- width: devicesScroll.availableWidth
- spacing: Kirigami.Units.smallSpacing
- Item {
- width: deviceListContainer.width
- height: Kirigami.Units.smallSpacing/2
- }
+ // countries
+ Repeater {
+ model: routeModel
+ delegate: PlasmaComponents.RadioDelegate {
+ width: listContainer.width
+ height: Kirigami.Units.gridUnit * 3
+ enabled: !countriesBlocked
+ checked: (model.code === current && model.provider === provider)
- // devices
- Repeater {
- model: devicesModel
- delegate: PlasmaComponents.Button {
- id: devicesButton
- width: deviceListContainer.width
- height: Kirigami.Units.gridUnit * 4
-
- contentItem: RowLayout {
- x: Kirigami.Units.largeSpacing
- y: Kirigami.Units.largeSpacing
- width: devicesButton.availableWidth
- spacing: Kirigami.Units.smallSpacing
- ColumnLayout {
- spacing: 0
- RowLayout {
- Layout.fillWidth: true
- PlasmaComponents.Label {
- text: model.name
- font.bold: true
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: "(LOSS 80%)"
- color: "#f38ba8"
- visible: model.ebalka
- Layout.fillWidth: true
- }
- }
- RowLayout {
- PlasmaComponents.Label {
- text: model.ip
- font.pointSize: Kirigami.Theme.smallFont.pointSize
- opacity: 0.7
- verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: "↓"
- color: "#00ff00"
- }
- PlasmaComponents.Label {
- text: formatTraffic(model.rx)
- font.pointSize: Kirigami.Theme.smallFont.pointSize
- verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: "↑"
- color: "#00aaff"
- }
- PlasmaComponents.Label {
- text: formatTraffic(model.tx)
- font.pointSize: Kirigami.Theme.smallFont.pointSize
- verticalAlignment: Text.AlignVCenter
- }
- }
- RowLayout {
- PlasmaComponents.Label {
- text: getFlag(model.country)
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: model.country + " " + model.provider
- opacity: 0.7
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: (model.online ? "online" : "offline")
- color: (model.online ? "#a6e3a1" : "#f38ba8")
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
- }
- }
- Item {
- Layout.fillWidth: true
- }
- ColumnLayout {
- RowLayout {
- Item {
- Layout.fillWidth: true
- }
- PlasmaComponents.Switch {
- text: "80% loss"
- checked: model.ebalka
- enabled: !(isBlocked || devicesBlocked)
- onClicked: {
- isLoadingItems += Plasmoid.configuration.BIdevicesupdate
- devicesBlocked = true
- superWorker.sendMessage({ "action": "post_ebalka", "bool": !model.ebalka, "ip": model.ip })
- // ebalka = !ebalka
- }
- }
- }
- RowLayout {
- Item {
- Layout.fillWidth: true
- }
- PlasmaComponents.Button {
- id: menuButton
- text: "Rename"
- PlasmaComponents.Menu {
- id: inputMenu
- padding: Kirigami.Units.largeSpacing
-
- function confirmAction() {
- superWorker.sendMessage({ "action": "post_name", "ip": model.ip, "name": textInput.text })
- inputMenu.close();
- textInput.text = "";
- }
-
- ColumnLayout {
- spacing: Kirigami.Units.smallSpacing
- RowLayout {
- PlasmaComponents.Label {
- text: "Enter new name:"
- font.pixelSize: Kirigami.Units.gridUnit * 0.8
- }
- }
- RowLayout {
- PlasmaComponents.TextField {
- id: textInput
- placeholderText: (model.name).split(" ").slice(2).join(" ")
- focus: true
- onAccepted: inputMenu.confirmAction()
- }
- PlasmaComponents.Button {
- icon.name: "dialog-ok-apply"
- onClicked: inputMenu.confirmAction()
- }
- }
- }
- }
-
- onClicked: {
- inputMenu.open();
- textInput.forceActiveFocus();
- }
- }
- }
- }
- }
- //onClicked: {
- //}
- }
- }
- Item {
- width: deviceListContainer.width
- height: Kirigami.Units.smallSpacing/2
- }
- }
- }
-
- PlasmaComponents.ScrollView {
- id: statsScroll
- anchors.fill: parent
- ScrollBar.vertical.policy: scrollbartype
-
- Column {
- id: statsListContainer
- width: statsScroll.availableWidth
- spacing: Kirigami.Units.smallSpacing
- Item {
- width: statsListContainer.width
- height: Kirigami.Units.smallSpacing/2
- }
-
- // stats
- Repeater {
- model: statsModel
- delegate: PlasmaComponents.Button {
- id: statsButton
- width: statsListContainer.width
- height: Kirigami.Units.gridUnit * 4
- enabled: !(isBlocked || countriesBlocked)
-
- contentItem: RowLayout {
- x: Kirigami.Units.largeSpacing
- y: Kirigami.Units.largeSpacing
- width: statsButton.availableWidth
- spacing: Kirigami.Units.smallSpacing
- ColumnLayout {
- spacing: 0
- RowLayout {
- Layout.fillWidth: true
- PlasmaComponents.Label {
- text: getFlag(model.country)
- elide: Text.ElideRight
- font.pixelSize: 16
- verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: model.name
- font.bold: true
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
- }
+ contentItem: RowLayout {
+ spacing: Kirigami.Units.largeSpacing
PlasmaComponents.Label {
- text: "Up: " + (Math.floor(model.uptime / 86400)) + "d " + (Math.floor((model.uptime % 86400) / 3600)) + "h " + (Math.floor(((model.uptime % 86400) % 3600) / 60)) + "m"
- }
- }
- Item {
- Layout.fillWidth: true
- }
- ColumnLayout {
- spacing: 0
- RowLayout {
- Item {
- Layout.fillWidth: true
- }
- PlasmaComponents.Label {
- text: model.connected + " peers (online: " + model.online + ")"
- color: "#a6e3a1"
- font.bold: true
- }
- }
- RowLayout {
- Item {
- Layout.fillWidth: true
- }
- PlasmaComponents.Label {
- text: "↓"
- color: "#00ff00"
- }
- PlasmaComponents.Label {
- text: formatTraffic(model.trafficString.split(" ")[0])
- }
- PlasmaComponents.Label {
- text: "(" + formatTraffic(model.speedString.split(" ")[0]) + ")"
- opacity: 0.7
- }
- PlasmaComponents.Label {
- text: "↑"
- color: "#00aaff"
- }
- PlasmaComponents.Label {
- text: formatTraffic(model.trafficString.split(" ")[1])
- }
- PlasmaComponents.Label {
- text: "(" + formatTraffic(model.speedString.split(" ")[1]) + ")"
- opacity: 0.7
- }
- }
- RowLayout {
- Item {
- Layout.fillWidth: true
- }
- PlasmaComponents.Label {
- text: model.pingString.split(" ").join(", ") + " ms"
- color: "#a6e3a1"
- font.bold: true
- }
- }
- }
- }
- onClicked: {
- isLoadingItems += Plasmoid.configuration.BIpostcountry
- superWorker.sendMessage({ "action": "post_idconnect", "iface": model.name })
- }
- }
- }
- Item {
- width: statsListContainer.width
- height: Kirigami.Units.smallSpacing/2
- }
- }
- }
-
- PlasmaComponents.ScrollView {
- id: featuresScroll
- anchors.fill: parent
- ScrollBar.vertical.policy: scrollbartype
-
- Column {
- id: featuresListContainer
- width: featuresScroll.availableWidth
- spacing: Kirigami.Units.smallSpacing
- Item {
- width: featuresListContainer.width
- height: Kirigami.Units.smallSpacing/2
- }
-
- // features
- Repeater {
- model: featuresModel
- delegate: PlasmaComponents.Button {
- id: featuresButton
- width: featuresListContainer.width
- height: Kirigami.Units.gridUnit * 4
-
- contentItem: RowLayout {
- x: Kirigami.Units.largeSpacing
- y: Kirigami.Units.largeSpacing
- width: featuresButton.availableWidth
- spacing: Kirigami.Units.smallSpacing
- ColumnLayout {
- spacing: 2
- Layout.fillWidth: true
- PlasmaComponents.Label {
- text: model.name
- elide: Text.ElideRight
- //font.pixelSize: 16
+ horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
- }
- PlasmaComponents.Label {
- text: model.desc
wrapMode: Text.Wrap
- opacity: 0.7
- //font.bold: true
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 24
+ text: getFlag(model.code)
+ }
+
+ ColumnLayout {
+ spacing: 0
Layout.fillWidth: true
+ PlasmaComponents.Label {
+ text: model.name
+ font.bold: true
+ Layout.fillWidth: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: model.provider
+ font.pointSize: Kirigami.Theme.smallFont.pointSize
+ opacity: 0.7
+ Layout.fillWidth: true
+ verticalAlignment: Text.AlignVCenter
+ }
}
}
- PlasmaComponents.Switch {
- checked: model.value
- enabled: !(isBlocked || featuresBlocked)
- onClicked: {
- isLoadingItems += Plasmoid.configuration.BIfeaturesupdate
- //featuresBlocked = true
- superWorker.sendMessage({ "action": "post_feature", "name": model.name, "value": !model.value })
+ onClicked: {
+ isLoadingItems += Plasmoid.configuration.BIpostcountry
+ superWorker.sendMessage({ "action": "post_country", "code": model.code, "provider": model.provider })
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Tab 2 Devices
+ Item {
+ PlasmaExtras.PlaceholderMessage {
+ anchors.centerIn: parent
+ text: "Connecting to\nMeowRelay"
+ iconName: "akregator-symbolic"
+ visible: devices === null
+ }
+ PlasmaComponents.ScrollView {
+ id: devicesScroll
+ anchors.fill: parent
+ ScrollBar.vertical.policy: scrollbartype
+
+ Column {
+ id: deviceListContainer
+ width: devicesScroll.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ Item {
+ width: deviceListContainer.width
+ height: Kirigami.Units.smallSpacing/2
+ }
+
+ // devices
+ Repeater {
+ model: devicesModel
+ delegate: PlasmaComponents.Button {
+ id: devicesButton
+ width: deviceListContainer.width
+ height: Kirigami.Units.gridUnit * 4
+
+ contentItem: RowLayout {
+ x: Kirigami.Units.largeSpacing
+ y: Kirigami.Units.largeSpacing
+ width: devicesButton.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ ColumnLayout {
+ spacing: 0
+ RowLayout {
+ Layout.fillWidth: true
+ PlasmaComponents.Label {
+ text: model.name
+ font.bold: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: "(LOSS 80%)"
+ color: "#f38ba8"
+ visible: model.ebalka
+ Layout.fillWidth: true
+ }
+ }
+ RowLayout {
+ PlasmaComponents.Label {
+ text: model.ip
+ //opacity: 0.7
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: "↓"
+ color: "#00ff00"
+ }
+ PlasmaComponents.Label {
+ text: formatTraffic(model.rx)
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: "↑"
+ color: "#00aaff"
+ }
+ PlasmaComponents.Label {
+ text: formatTraffic(model.tx)
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ RowLayout {
+ PlasmaComponents.Label {
+ text: getFlag(model.country)
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: model.country + " " + model.provider
+ opacity: 0.7
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: (model.online ? "online" : "offline")
+ color: (model.online ? "#a6e3a1" : "#f38ba8")
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ ColumnLayout {
+ RowLayout {
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.Switch {
+ text: "80% loss"
+ checked: model.ebalka
+ enabled: !(isBlocked || devicesBlocked)
+ onClicked: {
+ isLoadingItems += Plasmoid.configuration.BIdevicesupdate
+ devicesBlocked = true
+ superWorker.sendMessage({ "action": "post_ebalka", "bool": !model.ebalka, "ip": model.ip })
+ // ebalka = !ebalka
+ }
+ }
+ }
+ RowLayout {
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.Button {
+ id: menuButton
+ text: "Rename"
+ enabled: !(isBlocked || devicesBlocked)
+ PlasmaComponents.Menu {
+ id: inputMenu
+ padding: Kirigami.Units.largeSpacing
+
+ function confirmAction() {
+ superWorker.sendMessage({ "action": "post_name", "ip": model.ip, "name": textInput.text })
+ inputMenu.close();
+ textInput.text = "";
+ }
+
+ ColumnLayout {
+ spacing: Kirigami.Units.smallSpacing
+ RowLayout {
+ PlasmaComponents.Label {
+ text: "Enter new name:"
+ font.pixelSize: Kirigami.Units.gridUnit * 0.8
+ }
+ }
+ RowLayout {
+ PlasmaComponents.TextField {
+ id: textInput
+ placeholderText: (model.name).split(" ").slice(2).join(" ")
+ focus: true
+ onAccepted: inputMenu.confirmAction()
+ }
+ PlasmaComponents.Button {
+ icon.name: "dialog-ok-apply"
+ onClicked: inputMenu.confirmAction()
+ }
+ }
+ }
+ }
+
+ onClicked: {
+ inputMenu.open();
+ textInput.forceActiveFocus();
+ }
+ }
+ }
+ }
+ }
+ //onClicked: {
+ //}
+ }
+ }
+ Item {
+ width: deviceListContainer.width
+ height: Kirigami.Units.smallSpacing/2
+ }
+ }
+ }
+ }
+
+ // Tab 3 Firewall
+ Item {
+ PlasmaExtras.PlaceholderMessage {
+ anchors.centerIn: parent
+ text: "Connecting to\nMeowRelay"
+ iconName: "akregator-symbolic"
+ visible: firewallData === null
+ }
+ PlasmaExtras.PlaceholderMessage {
+ anchors.centerIn: parent
+ text: "Nothing to see here"
+ iconName: "face-sad"
+ visible: (!firewallAccess && firewallData)
+ }
+ PlasmaComponents.ScrollView {
+ id: firewallScroll
+ anchors.fill: parent
+ ScrollBar.vertical.policy: scrollbartype
+
+ Column {
+ id: firewallListContainer
+ width: firewallScroll.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ Item {
+ width: firewallListContainer.width
+ height: Kirigami.Units.smallSpacing/2
+ }
+
+ // firewall
+ Repeater {
+ model: firewallModel
+ delegate: PlasmaComponents.Button {
+ id: firewallButton
+ width: firewallListContainer.width
+ height: Kirigami.Units.gridUnit * 4
+
+ contentItem: RowLayout {
+ x: Kirigami.Units.largeSpacing
+ y: Kirigami.Units.largeSpacing
+ width: firewallButton.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ ColumnLayout {
+ spacing: 0
+ RowLayout {
+ Layout.fillWidth: true
+ PlasmaComponents.Label {
+ text: model.ip + ":" + model.port
+ font.bold: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: "→"
+ font.bold: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: model.dst + ":" + model.local_port
+ font.bold: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: "(" + model.proto + ")"
+ opacity: 0.7
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ RowLayout {
+ Layout.fillWidth: true
+ PlasmaComponents.Label {
+ text: model.packets + " pcks /"
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: formatTraffic(model.bytes)
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ ColumnLayout {
+ spacing: 0
+ PlasmaComponents.Button {
+ id: dropFirewallButton
+ text: "Drop"
+ enabled: !(isBlocked || firewallBlocked)
+ onClicked: {
+ isLoadingItems += Plasmoid.configuration.BIpostfirewall
+ firewallBlocked = true
+ superWorker.sendMessage({ "action": "post_ruledrop", "dst": model.dst, "ext": model.ip, "local_port": model.local_port, "port": model.port, "proto": model.proto })
+ }
+ }
}
}
}
- //onClicked: {
- //}
+ }
+ Item {
+ width: firewallListContainer.width
+ height: Kirigami.Units.smallSpacing/2
}
}
- Item {
- width: featuresListContainer.width
- height: Kirigami.Units.smallSpacing/2
+ }
+ }
+
+ // Tab 4 Stats
+ Item {
+ PlasmaExtras.PlaceholderMessage {
+ anchors.centerIn: parent
+ text: "Connecting to\nMeowRelay"
+ iconName: "akregator-symbolic"
+ visible: statsData === null
+ }
+ PlasmaComponents.ScrollView {
+ id: statsScroll
+ anchors.fill: parent
+ ScrollBar.vertical.policy: scrollbartype
+
+ Column {
+ id: statsListContainer
+ width: statsScroll.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ Item {
+ width: statsListContainer.width
+ height: Kirigami.Units.smallSpacing/2
+ }
+
+ // stats
+ Repeater {
+ model: statsModel
+ delegate: PlasmaComponents.Button {
+ id: statsButton
+ width: statsListContainer.width
+ height: Kirigami.Units.gridUnit * 4
+ enabled: !(isBlocked || countriesBlocked)
+
+ contentItem: RowLayout {
+ x: Kirigami.Units.largeSpacing
+ y: Kirigami.Units.largeSpacing
+ width: statsButton.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ ColumnLayout {
+ spacing: 0
+ RowLayout {
+ Layout.fillWidth: true
+ PlasmaComponents.Label {
+ text: getFlag(model.country)
+ elide: Text.ElideRight
+ font.pixelSize: 16
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: model.name
+ font.bold: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ }
+ PlasmaComponents.Label {
+ text: "Up: " + (Math.floor(model.uptime / 86400)) + "d " + (Math.floor((model.uptime % 86400) / 3600)) + "h " + (Math.floor(((model.uptime % 86400) % 3600) / 60)) + "m"
+ }
+ }
+ Item {
+ Layout.fillWidth: true
+ }
+ ColumnLayout {
+ spacing: 0
+ RowLayout {
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.Label {
+ text: model.connected + " peers (online: " + model.online + ")"
+ color: "#a6e3a1"
+ font.bold: true
+ }
+ }
+ RowLayout {
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.Label {
+ text: "↓"
+ color: "#00ff00"
+ }
+ PlasmaComponents.Label {
+ text: formatTraffic(model.trafficString.split(" ")[0])
+ }
+ PlasmaComponents.Label {
+ text: "(" + formatTraffic(model.speedString.split(" ")[0]) + ")"
+ opacity: 0.7
+ }
+ PlasmaComponents.Label {
+ text: "↑"
+ color: "#00aaff"
+ }
+ PlasmaComponents.Label {
+ text: formatTraffic(model.trafficString.split(" ")[1])
+ }
+ PlasmaComponents.Label {
+ text: "(" + formatTraffic(model.speedString.split(" ")[1]) + ")"
+ opacity: 0.7
+ }
+ }
+ RowLayout {
+ Item {
+ Layout.fillWidth: true
+ }
+ PlasmaComponents.Label {
+ text: model.pingString.split(" ").join(", ") + " ms"
+ color: "#a6e3a1"
+ font.bold: true
+ }
+ }
+ }
+ }
+ onClicked: {
+ isLoadingItems += Plasmoid.configuration.BIpostcountry
+ superWorker.sendMessage({ "action": "post_idconnect", "iface": model.name })
+ }
+ }
+ }
+ Item {
+ width: statsListContainer.width
+ height: Kirigami.Units.smallSpacing/2
+ }
+ }
+ }
+ }
+
+ // Tab 5 Features
+ Item {
+ PlasmaExtras.PlaceholderMessage {
+ anchors.centerIn: parent
+ text: "Connecting to\nMeowRelay"
+ iconName: "akregator-symbolic"
+ visible: features === null
+ }
+ PlasmaComponents.ScrollView {
+ id: featuresScroll
+ anchors.fill: parent
+ ScrollBar.vertical.policy: scrollbartype
+
+ Column {
+ id: featuresListContainer
+ width: featuresScroll.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ Item {
+ width: featuresListContainer.width
+ height: Kirigami.Units.smallSpacing/2
+ }
+
+ // features
+ Repeater {
+ model: featuresModel
+ delegate: PlasmaComponents.Button {
+ id: featuresButton
+ width: featuresListContainer.width
+ height: Kirigami.Units.gridUnit * 4
+
+ contentItem: RowLayout {
+ x: Kirigami.Units.largeSpacing
+ y: Kirigami.Units.largeSpacing
+ width: featuresButton.availableWidth
+ spacing: Kirigami.Units.smallSpacing
+ ColumnLayout {
+ spacing: 2
+ Layout.fillWidth: true
+ PlasmaComponents.Label {
+ text: model.name
+ elide: Text.ElideRight
+ //font.pixelSize: 16
+ verticalAlignment: Text.AlignVCenter
+ }
+ PlasmaComponents.Label {
+ text: model.desc
+ wrapMode: Text.Wrap
+ opacity: 0.7
+ //font.bold: true
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ Layout.fillWidth: true
+ }
+ }
+ PlasmaComponents.Switch {
+ checked: model.value
+ enabled: !(isBlocked || featuresBlocked)
+ onClicked: {
+ isLoadingItems += Plasmoid.configuration.BIfeaturesupdate
+ //featuresBlocked = true
+ superWorker.sendMessage({ "action": "post_feature", "name": model.name, "value": !model.value })
+ }
+ }
+ }
+ //onClicked: {
+ //}
+ }
+ }
+ Item {
+ width: featuresListContainer.width
+ height: Kirigami.Units.smallSpacing/2
+ }
}
}
}
diff --git a/com.umorist47.meowrelaygui/contents/ui/worker.mjs b/com.umorist47.meowrelaygui/contents/ui/worker.mjs
index f4c9a57..c3753d7 100644
--- a/com.umorist47.meowrelaygui/contents/ui/worker.mjs
+++ b/com.umorist47.meowrelaygui/contents/ui/worker.mjs
@@ -134,6 +134,30 @@ function fetchStats() {
xhr.send();
}
+// GET firewall
+function fetchFirewall() {
+
+ let xhr = getXhr();
+
+ if (!xhr) {
+ console.log("Pool full, retrying...");
+ setTimeout(() => fetchFirewall(), 100);
+ return;
+ }
+ xhr.open("GET", "http://10.7.0.1:7777/meowrok/get");
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+ if (xhr.status === 200) {
+ let response = JSON.parse(xhr.responseText);
+ WorkerScript.sendMessage({ "action": "fetch_firewall", "data": response });
+ } else {
+ console.error("Failed to fetch firewall:", xhr.status);
+ }
+ }
+ }
+ xhr.send();
+}
+
// POST select country
function selectCountry(code, provider) {
//isLoading = true;
@@ -336,17 +360,94 @@ function connectById(iface) {
xhr.send(data);
}
+// POST aff rule to firewall
+function firewallAddRule(dst, ext, local_port, port, proto) {
+ //isLoading = true;
+
+ let xhr = getXhr();
+
+ if (!xhr) {
+ console.log("Pool full, retrying...");
+ setTimeout(() => firewallAddRule(dst, ext, local_port, port, proto), 100);
+ return;
+ }
+ xhr.open("POST", "http://10.7.0.1:7777/meowrok/add");
+ xhr.setRequestHeader("Content-Type", "application/json");
+
+ var data = JSON.stringify({
+ "dst": dst,
+ "ext": ext,
+ "local_port": local_port,
+ "port": port,
+ "proto": proto
+ });
+
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+ //isLoading = false;
+ if (xhr.status === 200) {
+ console.log("Success: rule added!");
+ WorkerScript.sendMessage({ "action": "post_ruleadd", "status": xhr.status});
+ } else {
+ console.error("POST failed:", xhr.status);
+ WorkerScript.sendMessage({ "action": "post_ruleadd", "status": xhr.status});
+ }
+ }
+ }
+ xhr.send(data);
+}
+
+// POST drop rule from firewall
+function firewallDropRule(dst, ext, local_port, port, proto) {
+ //isLoading = true;
+
+ let xhr = getXhr();
+
+ if (!xhr) {
+ console.log("Pool full, retrying...");
+ setTimeout(() => firewallDropRule(dst, ext, local_port, port, proto), 100);
+ return;
+ }
+ xhr.open("POST", "http://10.7.0.1:7777/meowrok/drop");
+ xhr.setRequestHeader("Content-Type", "application/json");
+
+ var data = JSON.stringify({
+ "dst": dst,
+ "ext": ext,
+ "local_port": local_port,
+ "port": port,
+ "proto": proto
+ });
+
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+ //isLoading = false;
+ if (xhr.status === 200) {
+ console.log("Success: rule dropped!");
+ WorkerScript.sendMessage({ "action": "post_ruledrop", "status": xhr.status});
+ } else {
+ console.error("POST failed:", xhr.status);
+ WorkerScript.sendMessage({ "action": "post_ruledrop", "status": xhr.status});
+ }
+ }
+ }
+ xhr.send(data);
+}
+
WorkerScript.onMessage = function(message) {
const actions = {
"fetch_routes": () => fetchRoutes(message),
"fetch_stats": () => fetchStats(message),
"fetch_profile": () => fetchProfile(message),
+ "fetch_firewall": () => fetchFirewall(message),
"post_country": () => selectCountry(message.code, message.provider),
"post_share": () => switchShare(message.bool),
"post_ebalka": () => switchEbalka(message.bool, message.ip),
"post_name": () => renameDevice(message.ip, message.name),
"post_feature": () => switchFeature(message.name, message.value),
"post_idconnect": () => connectById(message.iface),
+ "post_ruleadd": () => firewallAddRule(message.dst, message.ext, message.local_port, message.port, message.proto),
+ "post_ruledrop": () => firewallDropRule(message.dst, message.ext, message.local_port, message.port, message.proto),
"ping": () => keepAlivePing(message)
};
diff --git a/com.umorist47.meowrelaygui/metadata.json b/com.umorist47.meowrelaygui/metadata.json
index 84b7d22..cb34d75 100644
--- a/com.umorist47.meowrelaygui/metadata.json
+++ b/com.umorist47.meowrelaygui/metadata.json
@@ -13,7 +13,7 @@
"Icon": "preferences-system-network-proxy",
"Id": "com.umorist47.meowrelaygui",
"Name": "MeowRelay",
- "Version": "1.0",
+ "Version": "1.1",
"Website": "",
"License": "GPL3"
},