diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 153e2ac..f3650aa 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,16 +4,11 @@
-
-
-
-
+
+
-
-
-
-
+
@@ -47,44 +42,33 @@
- {
- "keyToString": {
- "ASKED_ADD_EXTERNAL_FILES": "true",
- "Python.INSTALL.executor": "Run",
- "Python.install.executor": "Run",
- "Python.main.executor": "Run",
- "Python.messagebox.executor": "Run",
- "Python.start_wg.executor": "Run",
- "Python.wg_func.executor": "Run",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "git-widget-placeholder": "main",
- "last_opened_file_path": "/home/punix/Pyapps/wire-py",
- "settings.editor.selected.configurable": "preferences.lookFeel"
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+}]]>
+
+
+
+
+
+
+
+
+
+
@@ -107,6 +91,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -129,54 +135,6 @@
1723279982210
-
-
- 1723666001005
-
-
-
- 1723666001005
-
-
-
- 1723666477079
-
-
-
- 1723666477079
-
-
-
- 1723847456806
-
-
-
- 1723847456806
-
-
-
- 1724013210356
-
-
-
- 1724013210356
-
-
-
- 1724013251954
-
-
-
- 1724013251954
-
-
-
- 1724048994613
-
-
-
- 1724048994613
-
1724102937260
@@ -361,9 +319,220 @@
1725991610908
-
+
+
+ 1726349168248
+
+
+
+ 1726349168248
+
+
+
+ 1726359012150
+
+
+
+ 1726359012150
+
+
+
+ 1726599446537
+
+
+
+ 1726599446538
+
+
+
+ 1726599588155
+
+
+
+ 1726599588155
+
+
+
+ 1726650691719
+
+
+
+ 1726650691719
+
+
+
+ 1726652747322
+
+
+
+ 1726652747322
+
+
+
+ 1726691611936
+
+
+
+ 1726691611936
+
+
+
+ 1726734843529
+
+
+
+ 1726734843529
+
+
+
+ 1726764877546
+
+
+
+ 1726764877546
+
+
+
+ 1726770649542
+
+
+
+ 1726770649542
+
+
+
+ 1726777434040
+
+
+
+ 1726777434040
+
+
+
+ 1726836930251
+
+
+
+ 1726836930251
+
+
+
+ 1726841190285
+
+
+
+ 1726841190285
+
+
+
+ 1726860371820
+
+
+
+ 1726860371820
+
+
+
+ 1726915238475
+
+
+
+ 1726915238475
+
+
+
+ 1726959423800
+
+
+
+ 1726959423800
+
+
+
+ 1727015078922
+
+
+
+ 1727015078922
+
+
+
+ 1727018233930
+
+
+
+ 1727018233930
+
+
+
+ 1727028762875
+
+
+
+ 1727028762875
+
+
+
+ 1727028915701
+
+
+
+ 1727028915701
+
+
+
+ 1727118598759
+
+
+
+ 1727118598760
+
+
+
+ 1727288788988
+
+
+
+ 1727288788988
+
+
+
+ 1727347126769
+
+
+
+ 1727347126769
+
+
+
+ 1727378355274
+
+
+
+ 1727378355275
+
+
+
+ 1727379755537
+
+
+
+ 1727379755537
+
+
+
+ 1727380793216
+
+
+
+ 1727380793216
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..00544a1
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,27 @@
+Changelog for Wire-Py
+
+## [Unreleased]
+ - os import in wg_func replaced by other methods
+ - Autoupdate in Options
+ - Guide to menu '?' with pictures
+ - Create file for settings (Autoupdate)
+ - UID and GID for another Systems (Fedora, Arch, ect.)
+ - installer optimize for another Systems
+ - In Gitea Readme enter text, images
+ - Dark Theme for Wire-Py
+ - Own filedialog for import
+
+### Added
+28-09-2024
+
+ - Changelog create
+
+ - When exporting, the folder is now copied to /tmp and the non .conf
+ files are deleted before the zip file is created.
+
+ - In main.py os import removed. Since os have been replaced by pathlib and shutil.
+
+ - Start with version number 1.4.7
+
+ - Message window size corrected so text is displayed better
+
diff --git a/Wire-Py.desktop b/Wire-Py.desktop
new file mode 100755
index 0000000..19e5690
--- /dev/null
+++ b/Wire-Py.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Type=Application
+Name=Wire-Py
+Exec=/usr/bin/wirepy.py
+Terminal=false
+Categories=Network;
+Icon=/usr/share/icons/wp-icons/128/wg_vpn.png
diff --git a/icons/warning_32.png b/icons/warning_32.png
deleted file mode 100644
index e695c2c..0000000
Binary files a/icons/warning_32.png and /dev/null differ
diff --git a/icons/wg-active.png b/icons/wg-active.png
deleted file mode 100644
index e79bf79..0000000
Binary files a/icons/wg-active.png and /dev/null differ
diff --git a/icons/wg-info.png b/icons/wg-info.png
deleted file mode 100644
index 5501cc5..0000000
Binary files a/icons/wg-info.png and /dev/null differ
diff --git a/icons/wg-trash-info.png b/icons/wg-trash-info.png
deleted file mode 100644
index c98fd74..0000000
Binary files a/icons/wg-trash-info.png and /dev/null differ
diff --git a/icons/wg-vpn-info.png b/icons/wg-vpn-info.png
deleted file mode 100644
index 4471b36..0000000
Binary files a/icons/wg-vpn-info.png and /dev/null differ
diff --git a/icons/wire-switch-off-256.png b/icons/wire-switch-off-256.png
deleted file mode 100644
index 8cc06f3..0000000
Binary files a/icons/wire-switch-off-256.png and /dev/null differ
diff --git a/icons/wire-switch-off-48.png b/icons/wire-switch-off-48.png
deleted file mode 100644
index c973b27..0000000
Binary files a/icons/wire-switch-off-48.png and /dev/null differ
diff --git a/icons/wire-switch-on-256.png b/icons/wire-switch-on-256.png
deleted file mode 100644
index 7a65c63..0000000
Binary files a/icons/wire-switch-on-256.png and /dev/null differ
diff --git a/install b/install
new file mode 100755
index 0000000..91f4ca8
--- /dev/null
+++ b/install
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+which sudo >/dev/null
+if [ $? -ne 0 ]
+ then
+ su -
+ apt install python3-tk -y && \
+ cp wg_main.py start_wg.py wg_func.py wirepy.py /usr/bin/ && \
+ mkdir -p /etc/wire_py && touch /etc/wire_py/.keys && cp -R wp-icons /usr/share/icons/ && \
+ chown -R root:root /etc/wire_py && chmod 755 /etc/wire_py && \
+ ln -sf /usr/bin/wirepy.py /usr/local/bin/wirepy >/dev/null && \
+ cp org.wirepy.policy /usr/share/polkit-1/actions/ && \
+ cp Wire-Py.desktop /usr/share/applications/ && \
+ cp wg_start.services /lib/systemd/system/ && \
+ systemctl enable wg_start.service
+
+else
+ sudo apt install python3-tk && \
+ sudo cp wg_main.py start_wg.py wg_func.py wirepy.py /usr/bin/ && \
+ sudo mkdir -p /etc/wire_py && sudo touch /etc/wire_py/.keys && sudo cp -R wp-icons /usr/share/icons/ && \
+ sudo chown -R root:root /etc/wire_py && sudo chmod 755 /etc/wire_py && \
+ sudo ln -sf /usr/bin/wirepy.py /usr/local/bin/wirepy && \
+ sudo cp org.wirepy.policy /usr/share/polkit-1/actions/ && \
+ sudo cp Wire-Py.desktop /usr/share/applications/ && \
+ sudo cp wg_start.service /lib/systemd/system/ && \
+ sudo systemctl enable wg_start.service
+
+fi
+read -n 1 -s -r -p $"To close the Window press a button"
+
+
+
+
diff --git a/install.py b/install.py
deleted file mode 100755
index 0ed4497..0000000
--- a/install.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/python3
-from pathlib import Path
-from getpass import getpass
-
-# for services file in /lib/systemd/system/
-config_path = Path.home() / ".config" / "wire_py" / "wg_py"
-
-start_file = f'''\
-#!/usr/bin/python3
-from subprocess import check_call
-
-path_to_file = {str(config_path)!r}
-
-with open(path_to_file, 'r') as file:
- *_, line = file
-a_con = line[5:]
-check_call(['nmcli', 'connection', 'up', a_con])
-'''
-
-Path("start_wg.py").write_text(start_file)
-
-config_path.parent.mkdir(exist_ok=True)
-if not Path.exists(config_path):
- config_path.write_text("false")
-
-# Prompt the user for the sudo password
-#sudo_password = getpass('Enter sudo password: ')
-#def cp_files():
-
-# Define the command to run the Python script with sudo
-#command = ['sudo', '-S', 'python3', 'script.py']
-
-# Run the command as a subprocess, passing the sudo password
-#subprocess.run(command, input=sudo_password.encode(), check=True)
diff --git a/org.wirepy.policy b/org.wirepy.policy
new file mode 100644
index 0000000..c4c1694
--- /dev/null
+++ b/org.wirepy.policy
@@ -0,0 +1,16 @@
+
+
+
+ Project Wire-Py
+ https://git.ilunix.de/punix/Wire-Py
+ wg-vpn
+
+
+ auth_admin_keep
+ auth_admin_keep
+ yes
+
+ /usr/bin/wg_main.py
+ true
+
+
diff --git a/start_wg.py b/start_wg.py
index 8c13876..41bb29b 100755
--- a/start_wg.py
+++ b/start_wg.py
@@ -1,9 +1,12 @@
#!/usr/bin/python3
from subprocess import check_call
+from pathlib import Path
-path_to_file = '/home/punix/.config/wire_py/wg_py'
+path_to_file = Path('/etc/wire_py/wg_py')
+
+if Path.exists(path_to_file):
+ a_con = Path.read_text(path_to_file)
+ check_call(['nmcli', 'connection', 'up', a_con])
+else:
+ pass
-with open(path_to_file, 'r') as file:
- *_, line = file
-a_con = line[5:]
-check_call(['nmcli', 'connection', 'up', a_con])
diff --git a/wg_func.py b/wg_func.py
index 34a91d7..b17d029 100755
--- a/wg_func.py
+++ b/wg_func.py
@@ -1,42 +1,62 @@
# Wireguard functions for Wire-Py
import os
import shutil
-from datetime import datetime
-from tkinter import filedialog, ttk
+import subprocess
import tkinter as tk
+import zipfile
+from datetime import datetime
from pathlib import Path
from subprocess import check_call
+from tkinter import filedialog
font_color = '#4011a7'
-path_to_file = Path.home() / '.config/wire_py/wg_py'
+dk_theme = '#2e2e2e'
+path_to_file = Path('/etc/wire_py/wg_py')
+_u = Path.read_text(Path('/tmp/_u'))
-def msg_window():
+def msg_window(img_w, img_i, w_title, w_txt, x, y):
+ """
+ Function for different message windows for the user. with 4 arguments to be passed.
+ To create messages with your own images, icons, and titles. As an alternative to Python Messagebox.
+ Paths to images must be specified: r'/usr/share/icons/wp-icons/64/info.png'
+ img_w = Image for Tk Window
+ img_i = Image for Icon
+ w_title = Windows Title
+ w_txt = Text for Tk Window
+ x = Window width
+ y = Window height
+ """
msg = tk.Toplevel()
msg.resizable(width=False, height=False)
- msg.x_width = 340
- msg.y_height = 140
- msg.title('Import error!')
+ msg.x_width = x
+ msg.y_height = y
+ msg.title(w_title)
msg.monitor_center_x = msg.winfo_screenwidth() / 2 - (msg.x_width / 2)
msg.monitor_center_y = msg.winfo_screenheight() / 2 - (msg.y_height / 2)
msg.geometry('%dx%d+%d+%d' % (msg.x_width, msg.y_height, msg.monitor_center_x, msg.monitor_center_y))
- msg.columnconfigure(0, weight=1)
- msg.configure(pady=20)
- msg.warning = tk.PhotoImage(file=r'icons/warning_64.png')
- msg.i_warning = tk.Label(msg, image=msg.warning)
- msg.i_warning.grid(column=0, row=0)
- label = tk.Label(msg, text='Oh... no valid Wireguard File!\nPlease select a valid Wireguard File')
- label.config(font=('Ubuntu', 11), padx=15, pady=15)
+ msg.configure(pady=15)
+ msg.img = tk.PhotoImage(file=img_w)
+ msg.i_window = tk.Label(msg, image=msg.img)
+ msg.i_window.grid(column=0, row=0)
+ label = tk.Label(msg, text=w_txt)
+ label.config(font=('Ubuntu', 11), padx=15)
label.grid(column=1, row=0)
button = tk.Button(msg, text='OK', command=msg.destroy)
- button.config(padx=15, pady=5)
+ button.config(padx=15)
button.grid(column=0, columnspan=2, row=1)
- wg_icon_2 = tk.PhotoImage(file=r'icons/wg-stop.png')
- msg.iconphoto(True, wg_icon_2)
+ img_i = tk.PhotoImage(file=img_i)
+ msg.iconphoto(True, img_i)
+ msg.columnconfigure(0, weight=1)
+ msg.rowconfigure(0, weight=1)
msg.winfo_toplevel()
class GreenLabel:
+ """
+ Show the active tunnel in green in the label
+ """
+
def __init__(self):
self.StrVar = None
self.lb_tunnel = None
@@ -56,12 +76,16 @@ class GreenLabel:
class StartStopBTN:
+ """
+ Show Start and Stop Button in Label
+ """
+
def __init__(self):
self.lb_frame_btn_lbox = None
self.wg_switch = None
self.btn_stst = None
- self.wg_vpn_start = tk.PhotoImage(file=r'icons/wg-vpn-start-48.png')
- self.wg_vpn_stop = tk.PhotoImage(file=r'icons/wg-vpn-stop-48.png')
+ self.wg_vpn_start = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_vpn-start.png')
+ self.wg_vpn_stop = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_vpn-stop.png')
def button_stop(self):
self.btn_stst = tk.Button(self.lb_frame_btn_lbox, image=self.wg_vpn_stop, bd=0, command=self.wg_switch)
@@ -73,6 +97,11 @@ class StartStopBTN:
class ConToDict:
+ """
+ The config file is packed into a dictionary,
+ to display the values Address , DNS and Peer in the labels
+ """
+
@classmethod
def covert_to_dict(cls, file):
dictlist = []
@@ -104,10 +133,18 @@ class ConToDict:
if ',' in dns:
dns = dns[:-1]
endpoint = final_dict['Endpoint']
- return address, dns, endpoint
+ if 'PresharedKey' in final_dict:
+ pre_key = final_dict['PresharedKey']
+ else:
+ pre_key = final_dict['PreSharedKey']
+ return address, dns, endpoint, pre_key
class TunnelActiv:
+ """
+ Shows the Active Tunnel
+ """
+
@staticmethod
def active(): # Shows the active tunnel
active = os.popen('nmcli con show --active | grep -iPo "(.*)(wireguard)"').read().split()
@@ -120,6 +157,11 @@ class TunnelActiv:
class ShowAddress:
+ """
+ Displays the value address, DNS and peer in the labels
+ or empty it again
+ """
+
def __init__(self):
self.lb_frame2 = None
self.lb_frame = None
@@ -160,6 +202,10 @@ class ShowAddress:
class ListTunnels:
+ """
+ Shows all existing Wireguard tunnels
+ """
+
@staticmethod
def tl_list():
wg_s = os.popen('nmcli con show | grep -iPo "(.*)(wireguard)"').read().split()
@@ -168,6 +214,16 @@ class ListTunnels:
class ImportTunnel:
+ """
+ Import Class for Wireguard config Files.
+ Before importing, it is checked whether PrivateKey and PublicKey are in the file.
+ If True then it is checked whether the PreSharedKey is already in the key file
+ to avoid an import error so that no double wgconf are imported.
+ Thus, tunnels can be renamed without the problems arise. If False then the key is written into the file.
+ Furthermore, it is checked whether the name is longer than 12 characters.
+ If True then the name is automatically shortened to 12 characters and then imported.
+ If in each case false comes out, a corresponding window comes to inform the user that something is wrong.
+ """
def __init__(self):
@@ -181,57 +237,96 @@ class ImportTunnel:
def wg_import_select(self):
try:
- filepath = filedialog.askopenfilename(initialdir=Path.home(), title='Select Wireguard config File',
+ filepath = filedialog.askopenfilename(initialdir=str(_u), title='Select Wireguard config File',
filetypes=[('WG config files', '*.conf')], )
+
with open(filepath, 'r') as file:
read = file.read()
path_split = filepath.split('/')
path_split1 = path_split[-1]
self.a = TunnelActiv.active()
if 'PrivateKey = ' in read and 'PublicKey = ' in read:
- if len(path_split1) > 17:
- p1 = shutil.copy(filepath, Path.home() / 'tester/')
- path_split = path_split1[len(path_split1) - 17:]
- os.rename(p1, Path.home() / 'tester/' / str(path_split))
+ with open(filepath, 'r') as file:
+ key = ConToDict.covert_to_dict(file)
+ pre_key = key[3]
+ if len(pre_key) != 0:
+ with open('/etc/wire_py/.keys', 'r') as readfile:
+ p_key = readfile.readlines()
+ if pre_key in p_key or pre_key + '\n' in p_key:
+ """img_w, img_i, w_title, w_txt hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/error.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Import Error'
+ msg_t = 'Tunnel already available!\nPlease use another file for import'
+ x = 340 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+ else:
+ with open('/etc/wire_py/.keys', 'a') as keyfile:
+ keyfile.write(pre_key + '\r')
+ if len(path_split1) > 17:
+ p1 = shutil.copy(filepath, Path('/etc/wire_py/'))
+ path_split = path_split1[len(path_split1) - 17:]
+ os.rename(p1, Path('/etc/wire_py') / str(path_split))
+ new_conf = '/etc/wire_py/' + path_split
+ if self.a != '':
+ check_call(['nmcli', 'connection', 'down', TunnelActiv.active()])
+ ShowAddress.label_empty(self)
- if self.a != '':
- check_call(['nmcli', 'connection', 'down', TunnelActiv.active()])
- ShowAddress.label_empty(self)
- check_call(['nmcli', 'connection', 'import', 'type', 'wireguard', 'file', Path.home() / 'tester' /
- path_split])
- else:
- shutil.copy(filepath, Path.home() / 'tester/')
- if self.a != '':
- check_call(['nmcli', 'connection', 'down', TunnelActiv.active()])
- ShowAddress.label_empty(self)
- check_call(['nmcli', 'connection', 'import', 'type', 'wireguard', 'file', filepath])
+ subprocess.check_output(['nmcli', 'connection', 'import', 'type',
+ 'wireguard', 'file', new_conf], text=True)
+
+ else:
+ shutil.copy(filepath, Path('/etc/wire_py/'))
+ if self.a != '':
+ check_call(['nmcli', 'connection', 'down', TunnelActiv.active()])
+ ShowAddress.label_empty(self)
+
+ subprocess.check_output(['nmcli', 'connection', 'import', 'type',
+ 'wireguard', 'file', filepath], text=True)
+
+ self.StrVar.set('')
+ self.a = TunnelActiv.active()
+ self.l_box.insert(0, self.a)
+ self.l_box.update()
+ self.StrVar = tk.StringVar()
+ self.StrVar.set(self.a)
+ GreenLabel.green_show_label(self)
+ StartStopBTN.button_stop(self)
+ wg_read = Path('/etc/wire_py') / str(self.a + '.conf')
+ with open(wg_read, 'r') as file_for_key:
+ data = ConToDict.covert_to_dict(file_for_key)
+ # Address Label
+ ShowAddress.init_and_report(self, data)
+ ShowAddress.show_data(self)
+ check_call(['nmcli', 'con', 'mod', self.a, 'connection.autoconnect', 'no'])
+ Path.chmod(wg_read, 0o600)
- self.StrVar.set('')
- self.a = TunnelActiv.active()
- self.l_box.insert(0, self.a)
- self.l_box.update()
- self.StrVar = tk.StringVar()
- self.StrVar.set(self.a)
- GreenLabel.green_show_label(self)
- StartStopBTN.button_stop(self)
- wg_read = Path.home() / 'tester/' / str(self.a + '.conf')
- with open(wg_read, 'r') as file:
- data = ConToDict.covert_to_dict(file)
- # Address Label
- ShowAddress.init_and_report(self, data)
- ShowAddress.show_data(self)
- check_call(['nmcli', 'con', 'mod', self.a, 'connection.autoconnect', 'no'])
if 'PrivateKey = ' not in read:
- msg_window()
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/error.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Import Error'
+ msg_t = 'Oh... no valid Wireguard File!\nPlease select a valid Wireguard File'
+ x = 340 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
except EOFError:
pass
except TypeError:
pass
except FileNotFoundError:
pass
+ except subprocess.CalledProcessError:
+ print('Tunnel exist!')
class FileHandle:
+ """
+ This class will display the autostart label which
+ Tunnel is automatically started regardless of the active tunnel.
+ The selected tunnel is written into a file to read it after the start of the system.
+ """
def __init__(self):
@@ -248,15 +343,12 @@ class FileHandle:
select_tunnel = self.l_box.curselection()
select_tl = self.l_box.get(select_tunnel[0])
if self.selected_option.get() == 0:
- with open(path_to_file, 'w') as off:
- off.write('false ' + '\n')
+ Path.unlink(path_to_file)
tl = ListTunnels.tl_list()
if len(tl) == 0:
self.wg_autostart.configure(state='disabled')
if self.selected_option.get() >= 1:
- with open(path_to_file, 'w') as set_on:
- set_on.write('true ' + select_tl)
-
+ Path.write_text(path_to_file, select_tl)
except IndexError:
self.selected_option.set(1)
@@ -264,6 +356,12 @@ class FileHandle:
class OnOff:
+ """
+ Here it is checked whether the path to the file is there if not it is created.
+ Set (on), the selected tunnel is displayed in the label.
+ At (off) the label is first emptied then filled with No Autoconnect
+ """
+
def __init__(self):
self.wg_autostart = None
self.selected_option = None
@@ -273,17 +371,16 @@ class OnOff:
self.lb_frame_buttons = None
def on_off(self):
- with open(path_to_file, 'r') as file:
- for line in file.readlines():
- a_connect = line
- if 'true' in a_connect:
- self.selected_option.set(1)
- self.autoconnect_var.set('')
- self.auto_con = a_connect[5:]
- else:
- self.wg_autostart.configure(state='disabled')
- self.auto_con = 'no Autoconnect'
-
+ if Path.exists(path_to_file):
+ self.selected_option.set(1)
+ self.autoconnect_var.set('')
+ if not Path.is_dir(Path('/etc/wire_py')):
+ Path.mkdir(Path('/etc/wire_py'))
+ self.auto_con = Path.read_text(path_to_file)
+ else:
+ self.wg_autostart.configure(state='disabled')
+ self.auto_con = 'no Autoconnect'
+ self.autoconnect_var.set('')
self.autoconnect_var = tk.StringVar()
self.autoconnect_var.set(self.auto_con)
self.autoconnect = tk.Label(self, textvariable=self.autoconnect_var, fg='blue', padx=5)
@@ -292,21 +389,58 @@ class OnOff:
class ExportTunnels:
+ """
+ This will export the tunnels.
+ A zipfile with current date and time is created
+ in the user's home directory with correct right
+ """
+
@staticmethod
def wg_export():
+ _u1 = str(_u[6:])
now_time = datetime.now()
now_datetime = now_time.strftime('wg-exp-' + '%m-%d-%Y' + '-' + '%H:%M')
tl = ListTunnels.tl_list()
try:
if len(tl) != 0:
- wg_tar = Path.home() / now_datetime
- p_to_conf = Path.home() / 'tester/'
- shutil.make_archive(wg_tar, 'zip', p_to_conf)
- #if zip_full != 0:
- #print('Export erfolgraeich')
- #else:
- #print('ups etwwas ging schief bitte Export wiederholen')
+ wg_tar = str(_u) + '/' + now_datetime
+ shutil.copytree('/etc/wire_py', '/tmp/wire_py', dirs_exist_ok=True)
+ source = Path('/tmp/wire_py')
+ Path.unlink(Path(source) / 'wg_py', missing_ok=True)
+ Path.unlink(Path(source) / '.keys', missing_ok=True)
+ shutil.make_archive(wg_tar, 'zip', source)
+ shutil.chown(wg_tar + '.zip', 1000, 1000)
+ shutil.rmtree(source)
+ with zipfile.ZipFile((wg_tar + '.zip'), 'r') as zf:
+ if len(zf.namelist()) != 0:
+ """img_w, img_i, w_title, w_txt hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_vpn.png'
+ wt = 'Export Successful'
+ msg_t = 'Your zip file is in home directory'
+ x = 340 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+ else:
+ """img_w, img_i, w_title, w_txt hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/error.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Export error'
+ msg_t = 'Export failed! Please try again'
+ x = 340 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
else:
- print('No Tunnel for Export')
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Select tunnel'
+ msg_t = 'Please first import tunnel.'
+ x = 280 # width
+ y = 130 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+
except TypeError:
pass
+
+
diff --git a/main.py b/wg_main.py
similarity index 52%
rename from main.py
rename to wg_main.py
index 99d97c8..f34df1f 100755
--- a/main.py
+++ b/wg_main.py
@@ -1,13 +1,16 @@
#!/usr/bin/python3
-import os
+
import tkinter as tk
from subprocess import check_call
-from tkinter import ttk
+from tkinter import *
from pathlib import Path
+from tkinter import ttk
+
from wg_func import (TunnelActiv, ListTunnels, ImportTunnel, ConToDict, GreenLabel, StartStopBTN, ShowAddress,
- FileHandle, ExportTunnels, OnOff)
+ FileHandle, ExportTunnels, OnOff, msg_window)
font_color = '#4011a7'
+dk_theme = '#2e2e2e'
class MainWindow(tk.Tk):
@@ -29,7 +32,7 @@ class MainWindow(tk.Tk):
self.style = ttk.Style(self)
self.style.theme_use('clam')
# Load the image file from disk.
- self.wg_icon = tk.PhotoImage(file=r'icons/wg-vpn-48.png')
+ self.wg_icon = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_vpn.png')
# Set it as the window icon.
self.iconphoto(True, self.wg_icon)
@@ -37,6 +40,8 @@ class MainWindow(tk.Tk):
self.app_menu = tk.Menu(self, borderwidth=0)
self.configure(menu=self.app_menu)
+ self.app_menu.add_cascade(label='v. 1.4.7')
+ self.app_menu.add_cascade(label='Options')
self.app_menu.add_cascade(label='?')
FrameWidgets(self).grid()
@@ -54,12 +59,12 @@ class FrameWidgets(ttk.Frame):
self.peer = None
self.lb_tunnel = None
self.wg_read = None
- self.wg_vpn_start = tk.PhotoImage(file=r'icons/wg-vpn-start-48.png')
- self.wg_vpn_stop = tk.PhotoImage(file=r'icons/wg-vpn-stop-48.png')
- self.imp_pic = tk.PhotoImage(file=r'icons/wg-import.png')
- self.tr_pic = tk.PhotoImage(file=r'icons/wg-trash-48.png')
- self.exp_pic = tk.PhotoImage(file=r'icons/wg-export-48.png')
- self.warning_pic = tk.PhotoImage(file=r'icons/warning_64.png')
+ self.wg_vpn_start = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_vpn-start.png')
+ self.wg_vpn_stop = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_vpn-stop.png')
+ self.imp_pic = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_import.png')
+ self.tr_pic = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_trash.png')
+ self.exp_pic = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/48/wg_export.png')
+ self.warning_pic = tk.PhotoImage(file=r'/usr/share/icons/wp-icons/64/error.png')
# Show active Tunnel
self.a = TunnelActiv.active()
@@ -107,6 +112,9 @@ class FrameWidgets(ttk.Frame):
tl = ListTunnels.tl_list()
if len(tl) != 0:
self.wg_autostart.configure(state='normal')
+ self.lb_rename.config(state='normal')
+ self.lb_rename.delete(0, tk.END)
+ self.btn_rename.config(state='normal')
self.l_box = tk.Listbox(self.lb_frame_btn_lbox, fg='#606060', selectmode='single')
self.l_box.config(highlightthickness=0, relief='ridge')
@@ -127,7 +135,7 @@ class FrameWidgets(ttk.Frame):
# Button Vpn
if self.a != '':
StartStopBTN.button_stop(self)
- wg_read = Path.home() / 'tester/' / str(self.a + '.conf')
+ wg_read = Path('/etc/wire_py') / str(self.a + '.conf')
with open(wg_read, 'r') as file:
data = ConToDict.covert_to_dict(file)
# Address Label
@@ -148,27 +156,36 @@ class FrameWidgets(ttk.Frame):
self.btn_i.grid(column=0, row=1, padx=15, pady=8)
def delete():
+
try:
self.select_tunnel = self.l_box.curselection()
select_tl = self.l_box.get(self.select_tunnel[0])
+ with open('/etc/wire_py/' + select_tl + '.conf', 'r+') as file2:
+ key = ConToDict.covert_to_dict(file2)
+ pre_key = key[3]
check_call(['nmcli', 'connection', 'delete', select_tl])
self.l_box.delete(self.select_tunnel[0])
- os.remove(Path.home() / 'tester/' / str(select_tl + '.conf'))
-
- path_to_file = Path.home() / '.config/wire_py/wg_py'
- with open(path_to_file, 'r') as file2:
- for line in file2.readlines():
- a_con = line[5:]
- if select_tl == a_con:
- self.selected_option.set(0)
- self.autoconnect_var.set('no Autoconnect')
+ if Path.is_file(Path('/etc/wire_py/wg_py')):
+ path_to_file = Path('/etc/wire_py') / 'wg_py'
+ a_con = Path.read_text(path_to_file)
+ if select_tl == a_con:
+ self.selected_option.set(0)
+ self.autoconnect_var.set('no Autoconnect')
+ self.wg_autostart.configure(state='disabled')
+ Path.unlink(path_to_file)
+ Path.unlink(Path('/etc/wire_py') / str(select_tl + '.conf'))
+ with open('/etc/wire_py/.keys', 'r') as readfile:
+ with open('/etc/wire_py/.keys2', 'w') as writefile:
+ for line in readfile:
+ if pre_key not in line.strip("\n"):
+ writefile.write(line)
+ file_one = Path('/etc/wire_py/.keys2')
+ file_two = file_one.with_name('.keys')
+ file_one.replace(file_two)
# for disable checkbox when Listbox empty
tl = ListTunnels.tl_list()
if len(tl) == 0:
self.wg_autostart.configure(state='disabled')
- with open(path_to_file, 'w') as file2:
- file2.write('false')
-
if self.a != '' and self.a == select_tl:
self.StrVar.set(value='')
StartStopBTN.button_start(self)
@@ -177,10 +194,27 @@ class FrameWidgets(ttk.Frame):
self.add.set('')
self.DNS.set('')
self.enp.set('')
-
return select_tl
except IndexError:
- pass
+ tl = ListTunnels.tl_list()
+ if len(tl) != 0:
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Select tunnel'
+ msg_t = 'Please select a tunnel from the list.'
+ x = 340 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+ else:
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Select tunnel'
+ msg_t = 'Please first import tunnel.'
+ x = 280 # width
+ y = 130 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
# Button Trash
self.btn_tr = tk.Button(self.lb_frame_btn_lbox, image=self.tr_pic, bd=0, command=delete)
@@ -190,9 +224,81 @@ class FrameWidgets(ttk.Frame):
self.btn_exp = tk.Button(self.lb_frame_btn_lbox, image=self.exp_pic, bd=0, command=ExportTunnels.wg_export)
self.btn_exp.grid(column=0, row=3, padx=15, pady=8)
+ # Label Entry
+ self.lb_rename = ttk.Entry(self, width=20)
+ self.lb_rename.grid(column=2, row=4, padx=30, pady=5, sticky='w')
+ self.lb_rename.insert(0, 'Max. 12 characters!')
+ self.lb_rename.config(state='disable')
+
+ def tl_rename():
+ special_characters = ['\\', '/', '{', '}', ' ']
+
+ if len(self.lb_rename.get()) > 12:
+ """img_w, img_i, w_title, w_txt hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Renaming not possible'
+ msg_t = 'The new name may contain only 12 characters.'
+ x = 420 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+
+ elif len(self.lb_rename.get()) == 0:
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Renaming not possible'
+ msg_t = 'At least one character must be entered.'
+ x = 380 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+
+ elif any(ch in special_characters for ch in self.lb_rename.get()):
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Renaming not possible'
+ msg_t = 'No valid sign. These must not be used.\nBlank, Slash, Backslash and { }\n'
+ x = 370 # width
+ y = 130 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+ else:
+ try:
+ self.select_tunnel = self.l_box.curselection()
+ select_tl = self.l_box.get(self.select_tunnel[0])
+ # nmcli connection modify old connection.id iphone
+ check_call(['nmcli', 'connection', 'modify', select_tl, 'connection.id', self.lb_rename.get()])
+ source = Path('/etc/wire_py') / str(select_tl + '.conf')
+ destination = source.with_name(str(self.lb_rename.get() + '.conf'))
+ source.replace(destination)
+ self.l_box.delete(self.select_tunnel[0])
+ self.l_box.insert("end", self.lb_rename.get())
+ self.l_box.update()
+ new_a_connect = self.lb_rename.get()
+ self.lb_rename.delete(0, tk.END)
+ if self.a != '' and self.a == select_tl:
+ self.a = TunnelActiv.active()
+ self.StrVar.set(value=self.a)
+ if Path.is_file(Path('/etc/wire_py/wg_py')):
+ path_to_file = Path('/etc/wire_py') / 'wg_py'
+ a_con = Path.read_text(path_to_file)
+ if select_tl == a_con:
+ self.autoconnect_var.set(value=new_a_connect)
+ Path.write_text(path_to_file, new_a_connect)
+ return select_tl
+ except IndexError:
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Renaming not possible'
+ msg_t = 'Please select a tunnel from the list.'
+ x = 340 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+
# Button Rename
- self.btn_rename = ttk.Button(self, text='Rename')
- self.btn_rename.grid(column=2, row=4, padx=20, pady=15, sticky='e')
+ self.btn_rename = ttk.Button(self, text='Rename', state='disable', command=tl_rename)
+ self.btn_rename.grid(column=2, row=4, padx=20, pady=10, sticky='e')
# Check Buttons
self.selected_option = tk.IntVar()
@@ -200,7 +306,7 @@ class FrameWidgets(ttk.Frame):
self.autoconnect_var.set(self.auto_con)
self.autoconnect = tk.Label(self, textvariable=self.autoconnect_var, fg='blue', padx=5)
self.autoconnect.config(font=('Ubuntu', 11))
- self.autoconnect.grid(column=0, row=4, sticky='ne', pady=20)
+ self.autoconnect.grid(column=0, row=4, sticky='ne', pady=10)
self.wg_autostart = tk.Checkbutton(self,
text='Autoconnect on:',
variable=self.selected_option,
@@ -221,7 +327,7 @@ class FrameWidgets(ttk.Frame):
self.select_tunnel = self.l_box.curselection()
select_tl = self.l_box.get(self.select_tunnel[0])
check_call(['nmcli', 'connection', 'up', select_tl])
- wg_read = Path.home() / 'tester/' / str(select_tl + '.conf')
+ wg_read = Path('/etc/wire_py') / str(select_tl + '.conf')
with open(wg_read, 'r') as file:
data = ConToDict.covert_to_dict(file)
# Address Label
@@ -248,9 +354,37 @@ class FrameWidgets(ttk.Frame):
self.enp.set('')
ShowAddress.show_data(self)
except IndexError:
- pass
+ tl = ListTunnels.tl_list()
+ if len(tl) != 0:
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Select tunnel'
+ msg_t = 'Please select a tunnel from the list.'
+ x = 340 # width
+ y = 140 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
+ else:
+ """img_w, img_i, w_title, w_txt x, y hand over"""
+ iw = r'/usr/share/icons/wp-icons/64/info.png'
+ ii = r'/usr/share/icons/wp-icons/48/wg_msg.png'
+ wt = 'Select tunnel'
+ msg_t = 'Please first import tunnel.'
+ x = 280 # width
+ y = 130 # height
+ msg_window(iw, ii, wt, msg_t, x, y)
if __name__ == '__main__':
window = MainWindow()
+ """
+ the hidden files are hidden in Filedialog
+ """
+ try:
+ window.tk.call('tk_getOpenFile', '-foobarbaz')
+ except TclError:
+ pass
+
+ window.tk.call('set', '::tk::dialog::file::showHiddenBtn', '0')
+ window.tk.call('set', '::tk::dialog::file::showHiddenVar', '0')
window.mainloop()
diff --git a/wg_py b/wg_py
deleted file mode 100644
index e69de29..0000000
diff --git a/wg_start.service b/wg_start.service
index 6d86638..cc5f2bb 100644
--- a/wg_start.service
+++ b/wg_start.service
@@ -4,7 +4,7 @@ After=network-online.target
[Service]
Type=oneshot
-ExecStartPre=/bin/sleep 3
-ExecStart=/bin/start_wg.py
+ExecStartPre=/bin/sleep 5
+ExecStart=/usr/bin/start_wg.py
[Install]
WantedBy=multi-user.target
diff --git a/wirepy.py b/wirepy.py
new file mode 100755
index 0000000..592fa67
--- /dev/null
+++ b/wirepy.py
@@ -0,0 +1,6 @@
+#!/usr/bin/python3
+from subprocess import check_call
+from pathlib import Path
+
+Path.write_text(Path('/tmp/_u'), str(Path.home()))
+check_call(['pkexec', '/usr/bin/wg_main.py'])
diff --git a/icons/warning_128.png b/wp-icons/128/error.png
similarity index 100%
rename from icons/warning_128.png
rename to wp-icons/128/error.png
diff --git a/wp-icons/128/info.png b/wp-icons/128/info.png
new file mode 100644
index 0000000..ccba611
Binary files /dev/null and b/wp-icons/128/info.png differ
diff --git a/wp-icons/128/wg_export.png b/wp-icons/128/wg_export.png
new file mode 100644
index 0000000..787e894
Binary files /dev/null and b/wp-icons/128/wg_export.png differ
diff --git a/wp-icons/128/wg_import.png b/wp-icons/128/wg_import.png
new file mode 100644
index 0000000..a65f8b2
Binary files /dev/null and b/wp-icons/128/wg_import.png differ
diff --git a/wp-icons/128/wg_msg.png b/wp-icons/128/wg_msg.png
new file mode 100644
index 0000000..dcc04cd
Binary files /dev/null and b/wp-icons/128/wg_msg.png differ
diff --git a/wp-icons/128/wg_trash.png b/wp-icons/128/wg_trash.png
new file mode 100644
index 0000000..16b06b1
Binary files /dev/null and b/wp-icons/128/wg_trash.png differ
diff --git a/wp-icons/128/wg_vpn-start.png b/wp-icons/128/wg_vpn-start.png
new file mode 100644
index 0000000..2555e35
Binary files /dev/null and b/wp-icons/128/wg_vpn-start.png differ
diff --git a/wp-icons/128/wg_vpn-stop.png b/wp-icons/128/wg_vpn-stop.png
new file mode 100644
index 0000000..ff02259
Binary files /dev/null and b/wp-icons/128/wg_vpn-stop.png differ
diff --git a/wp-icons/128/wg_vpn.png b/wp-icons/128/wg_vpn.png
new file mode 100644
index 0000000..e800c31
Binary files /dev/null and b/wp-icons/128/wg_vpn.png differ
diff --git a/icons/warning_256.png b/wp-icons/256/error.png
similarity index 100%
rename from icons/warning_256.png
rename to wp-icons/256/error.png
diff --git a/wp-icons/256/info.png b/wp-icons/256/info.png
new file mode 100644
index 0000000..8c1ca4f
Binary files /dev/null and b/wp-icons/256/info.png differ
diff --git a/icons/wg-export.png b/wp-icons/256/wg_export.png
similarity index 100%
rename from icons/wg-export.png
rename to wp-icons/256/wg_export.png
diff --git a/icons/wg-import-orig.png b/wp-icons/256/wg_import.png
similarity index 100%
rename from icons/wg-import-orig.png
rename to wp-icons/256/wg_import.png
diff --git a/icons/wg-stop.png b/wp-icons/256/wg_msg.png
similarity index 100%
rename from icons/wg-stop.png
rename to wp-icons/256/wg_msg.png
diff --git a/icons/wg-trash.png b/wp-icons/256/wg_trash.png
similarity index 100%
rename from icons/wg-trash.png
rename to wp-icons/256/wg_trash.png
diff --git a/icons/wg-vpn-start.png b/wp-icons/256/wg_vpn-start.png
similarity index 100%
rename from icons/wg-vpn-start.png
rename to wp-icons/256/wg_vpn-start.png
diff --git a/icons/wg-vpn-stop.png b/wp-icons/256/wg_vpn-stop.png
similarity index 100%
rename from icons/wg-vpn-stop.png
rename to wp-icons/256/wg_vpn-stop.png
diff --git a/icons/wg-vpn.png b/wp-icons/256/wg_vpn.png
similarity index 100%
rename from icons/wg-vpn.png
rename to wp-icons/256/wg_vpn.png
diff --git a/icons/wire-switch-on-48.png b/wp-icons/32/error.png
similarity index 55%
rename from icons/wire-switch-on-48.png
rename to wp-icons/32/error.png
index 1ced496..18e6c64 100644
Binary files a/icons/wire-switch-on-48.png and b/wp-icons/32/error.png differ
diff --git a/wp-icons/32/info.png b/wp-icons/32/info.png
new file mode 100644
index 0000000..f11ca97
Binary files /dev/null and b/wp-icons/32/info.png differ
diff --git a/wp-icons/32/wg_export.png b/wp-icons/32/wg_export.png
new file mode 100644
index 0000000..81bb65b
Binary files /dev/null and b/wp-icons/32/wg_export.png differ
diff --git a/wp-icons/32/wg_import.png b/wp-icons/32/wg_import.png
new file mode 100644
index 0000000..dbaa7e7
Binary files /dev/null and b/wp-icons/32/wg_import.png differ
diff --git a/wp-icons/32/wg_msg.png b/wp-icons/32/wg_msg.png
new file mode 100644
index 0000000..5bd0115
Binary files /dev/null and b/wp-icons/32/wg_msg.png differ
diff --git a/wp-icons/32/wg_trash.png b/wp-icons/32/wg_trash.png
new file mode 100644
index 0000000..57f604d
Binary files /dev/null and b/wp-icons/32/wg_trash.png differ
diff --git a/wp-icons/32/wg_vpn-start.png b/wp-icons/32/wg_vpn-start.png
new file mode 100644
index 0000000..149142f
Binary files /dev/null and b/wp-icons/32/wg_vpn-start.png differ
diff --git a/wp-icons/32/wg_vpn-stop.png b/wp-icons/32/wg_vpn-stop.png
new file mode 100644
index 0000000..f29cbe6
Binary files /dev/null and b/wp-icons/32/wg_vpn-stop.png differ
diff --git a/wp-icons/32/wg_vpn.png b/wp-icons/32/wg_vpn.png
new file mode 100644
index 0000000..55df4dd
Binary files /dev/null and b/wp-icons/32/wg_vpn.png differ
diff --git a/wp-icons/48/error.png b/wp-icons/48/error.png
new file mode 100644
index 0000000..92a731a
Binary files /dev/null and b/wp-icons/48/error.png differ
diff --git a/wp-icons/48/info.png b/wp-icons/48/info.png
new file mode 100644
index 0000000..52206e6
Binary files /dev/null and b/wp-icons/48/info.png differ
diff --git a/icons/wg-export-48.png b/wp-icons/48/wg_export.png
similarity index 100%
rename from icons/wg-export-48.png
rename to wp-icons/48/wg_export.png
diff --git a/icons/wg-import.png b/wp-icons/48/wg_import.png
similarity index 100%
rename from icons/wg-import.png
rename to wp-icons/48/wg_import.png
diff --git a/wp-icons/48/wg_msg.png b/wp-icons/48/wg_msg.png
new file mode 100644
index 0000000..732eabb
Binary files /dev/null and b/wp-icons/48/wg_msg.png differ
diff --git a/icons/wg-trash-48.png b/wp-icons/48/wg_trash.png
similarity index 100%
rename from icons/wg-trash-48.png
rename to wp-icons/48/wg_trash.png
diff --git a/icons/wg-vpn-start-48.png b/wp-icons/48/wg_vpn-start.png
similarity index 100%
rename from icons/wg-vpn-start-48.png
rename to wp-icons/48/wg_vpn-start.png
diff --git a/icons/wg-vpn-stop-48.png b/wp-icons/48/wg_vpn-stop.png
similarity index 100%
rename from icons/wg-vpn-stop-48.png
rename to wp-icons/48/wg_vpn-stop.png
diff --git a/icons/wg-vpn-48.png b/wp-icons/48/wg_vpn.png
similarity index 100%
rename from icons/wg-vpn-48.png
rename to wp-icons/48/wg_vpn.png
diff --git a/icons/warning_64.png b/wp-icons/64/error.png
similarity index 100%
rename from icons/warning_64.png
rename to wp-icons/64/error.png
diff --git a/wp-icons/64/info.png b/wp-icons/64/info.png
new file mode 100644
index 0000000..4917814
Binary files /dev/null and b/wp-icons/64/info.png differ
diff --git a/wp-icons/64/wg_export.png b/wp-icons/64/wg_export.png
new file mode 100644
index 0000000..7d14d17
Binary files /dev/null and b/wp-icons/64/wg_export.png differ
diff --git a/wp-icons/64/wg_import.png b/wp-icons/64/wg_import.png
new file mode 100644
index 0000000..c9b0c85
Binary files /dev/null and b/wp-icons/64/wg_import.png differ
diff --git a/wp-icons/64/wg_msg.png b/wp-icons/64/wg_msg.png
new file mode 100644
index 0000000..d821d13
Binary files /dev/null and b/wp-icons/64/wg_msg.png differ
diff --git a/icons/wg-trash-64.png b/wp-icons/64/wg_trash.png
similarity index 100%
rename from icons/wg-trash-64.png
rename to wp-icons/64/wg_trash.png
diff --git a/wp-icons/64/wg_vpn-start.png b/wp-icons/64/wg_vpn-start.png
new file mode 100644
index 0000000..3eeb910
Binary files /dev/null and b/wp-icons/64/wg_vpn-start.png differ
diff --git a/wp-icons/64/wg_vpn-stop.png b/wp-icons/64/wg_vpn-stop.png
new file mode 100644
index 0000000..03a5044
Binary files /dev/null and b/wp-icons/64/wg_vpn-stop.png differ
diff --git a/wp-icons/64/wg_vpn.png b/wp-icons/64/wg_vpn.png
new file mode 100644
index 0000000..d69ef68
Binary files /dev/null and b/wp-icons/64/wg_vpn.png differ