mirror of https://gitlab.com/aitzol76/macBank
455 lines
16 KiB
Python
455 lines
16 KiB
Python
# Copyright 2018 Wproject - Aitzol Berasategi - https://aitzol.eus
|
|
#
|
|
# This file is part of macBank Ver.1.0.0.
|
|
#
|
|
# This project is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; version 3.
|
|
#
|
|
# PyCalculator is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or ANY OTHER COMMERCIAL PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
from io import open
|
|
from time import sleep
|
|
import os.path
|
|
import urllib.request
|
|
import sqlite3
|
|
from development import parser
|
|
import re
|
|
import gi
|
|
gi.require_version('Gtk', '3.0')
|
|
from gi.repository import Gtk, Gdk, GLib
|
|
|
|
|
|
class AppWindow(Gtk.ApplicationWindow):
|
|
|
|
mode = "OUI"
|
|
repeatFactor = "1"
|
|
isValid = False
|
|
result = ""
|
|
UI_INFO = """
|
|
<ui>
|
|
<menubar name='MenuBar'>
|
|
<menu action='FileMenu'>
|
|
<menu action='Database'>
|
|
<menuitem action='Update' />
|
|
</menu>
|
|
<separator />
|
|
<menuitem action='FileQuit' />
|
|
</menu>
|
|
<menu action='HelpMenu'>
|
|
<menuitem action='? help' />
|
|
<menuitem action='About' />
|
|
</menu>
|
|
</menubar>
|
|
</ui>
|
|
"""
|
|
|
|
def __init__(self):
|
|
|
|
Gtk.Window.__init__(self, title=parser.manifest("name"))
|
|
self.set_default_size(300, 200)
|
|
|
|
# --- menu --- #
|
|
self.action_group = Gtk.ActionGroup("my_actions")
|
|
|
|
self.add_file_menu_actions(self.action_group)
|
|
self.add_help_menu_actions(self.action_group)
|
|
|
|
self.uimanager = self.create_ui_manager()
|
|
self.uimanager.insert_action_group(self.action_group)
|
|
|
|
self.menubar = self.uimanager.get_widget("/MenuBar")
|
|
|
|
self.menuBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=50)
|
|
self.menuBox.pack_start(self.menubar, False, False, 0)
|
|
|
|
# --- Label --- #
|
|
self.label = Gtk.Label()
|
|
self.label.set_text("Enter any MAC address, OUI, or IAB:")
|
|
self.label.set_justify(Gtk.Justification.LEFT)
|
|
self.label.set_hexpand(True)
|
|
|
|
# --- Result Treeview --- #
|
|
self.history = Gtk.ListStore(str, str)
|
|
self.treeview = Gtk.TreeView(model=self.history)
|
|
|
|
self.renderer_mac = Gtk.CellRendererText()
|
|
self.mac_column = Gtk.TreeViewColumn("MAC/OUI", self.renderer_mac, text=0)
|
|
self.treeview.append_column(self.mac_column)
|
|
|
|
self.renderer_vendor = Gtk.CellRendererText()
|
|
self.renderer_vendor.set_property("editable", False)
|
|
self.vendor_column = Gtk.TreeViewColumn("Vendor", self.renderer_vendor, text=1)
|
|
self.treeview.append_column(self.vendor_column)
|
|
self.treeview.set_margin_start(10)
|
|
self.treeview.set_margin_end(10)
|
|
self.treeview.set_margin_bottom(10)
|
|
|
|
# --- Entry --- #
|
|
self.entry = Gtk.Entry()
|
|
self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "edit-clear")
|
|
self.entry.set_max_length(8)
|
|
self.entry.set_placeholder_text("00:00:00")
|
|
self.entry.connect("key-release-event", self.on_key_release)
|
|
self.entry.connect("icon-press", self.entry_icon_event)
|
|
self.entry.set_margin_start(10)
|
|
self.entry.set_margin_end(10)
|
|
|
|
# --- Radio buttons --- #
|
|
self.box = Gtk.Box(spacing=10)
|
|
self.radioButton1 = Gtk.RadioButton.new_with_label_from_widget(None, "OUI")
|
|
self.radioButton1.connect("toggled", self.on_button_toggled, "OUI")
|
|
self.box.pack_start(self.radioButton1, False, False, 0)
|
|
self.box.set_margin_start(10)
|
|
self.box.set_margin_end(10)
|
|
|
|
self.radioButton2 = Gtk.RadioButton.new_from_widget(self.radioButton1)
|
|
self.radioButton2.set_label("MAC")
|
|
self.radioButton2.connect("toggled", self.on_button_toggled, "MAC")
|
|
self.box.pack_start(self.radioButton2, False, False, 0)
|
|
|
|
# --- Buttons --- #
|
|
self.search_button = Gtk.Button(label="Search")
|
|
self.search_button.connect("clicked", self.on_search_clicked)
|
|
self.search_button.set_margin_start(10)
|
|
self.search_button.set_margin_end(10)
|
|
|
|
# --- ProgressBar --- #
|
|
self.progressbar = Gtk.ProgressBar()
|
|
|
|
# --- Grid --- #
|
|
self.grid = Gtk.Grid()
|
|
self.grid.set_row_spacing(5)
|
|
|
|
self.grid.add(self.menuBox)
|
|
self.grid.attach(self.label, 0, 2, 1, 1)
|
|
self.grid.attach_next_to(self.entry, self.label, Gtk.PositionType.BOTTOM, 1, 1)
|
|
self.grid.attach_next_to(self.box, self.entry, Gtk.PositionType.BOTTOM, 1, 1)
|
|
self.grid.attach_next_to(self.search_button, self.box, Gtk.PositionType.BOTTOM, 1, 1)
|
|
self.grid.attach_next_to(self.treeview, self.search_button, Gtk.PositionType.BOTTOM, 1, 1)
|
|
self.grid.attach_next_to(self.progressbar, self.treeview, Gtk.PositionType.BOTTOM, 1, 1)
|
|
|
|
self.add(self.grid)
|
|
|
|
def on_key_release(self, widget, event):
|
|
self.colon = False
|
|
print(event.keyval)
|
|
keyname = Gdk.keyval_name(event.keyval)
|
|
print(keyname)
|
|
|
|
if len(self.entry.get_text()) == 2:
|
|
self.entry.set_text(self.entry.get_text() + ":")
|
|
self.colon = True
|
|
self.entry.set_position(-1)
|
|
elif len(self.entry.get_text()) == 5:
|
|
self.entry.set_text(self.entry.get_text() + ":")
|
|
self.colon = True
|
|
self.entry.set_position(-1)
|
|
elif len(self.entry.get_text()) == 8 and (self.mode == "MAC"):
|
|
self.entry.set_text(self.entry.get_text() + ":")
|
|
self.colon = True
|
|
self.entry.set_position(-1)
|
|
elif len(self.entry.get_text()) == 11 and (self.mode == "MAC"):
|
|
self.entry.set_text(self.entry.get_text() + ":")
|
|
self.colon = True
|
|
self.entry.set_position(-1)
|
|
elif len(self.entry.get_text()) == 14 and (self.mode == "MAC"):
|
|
self.entry.set_text(self.entry.get_text() + ":")
|
|
self.colon = True
|
|
self.entry.set_position(-1)
|
|
|
|
if ((keyname == 'BackSpace') or (event.keyval == 65288)) and self.colon:
|
|
self.entry.set_text(self.entry.get_text()[:-2])
|
|
self.entry.set_position(-1)
|
|
|
|
for i in range(len(self.entry.get_text())):
|
|
self.check_mac(self.entry.get_text())
|
|
|
|
def check_mac(self, mac):
|
|
if re.match("[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){" + self.repeatFactor + "}$", mac.lower()):
|
|
self.entry.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse("green"))
|
|
self.isValid = True
|
|
else:
|
|
self.entry.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(""))
|
|
self.isValid = False
|
|
|
|
def entry_icon_event(self, widget, icon, event):
|
|
self.entry.set_text("")
|
|
|
|
def on_search_clicked(self, widget):
|
|
if self.isValid:
|
|
if self.entry.get_text().find('-') != -1:
|
|
self.search = self.entry.get_text().replace('-', ':')
|
|
else:
|
|
self.search = self.entry.get_text()
|
|
|
|
self.dbCursor.execute("SELECT * FROM data WHERE mac=?", (self.search.upper(),))
|
|
self.rows = self.dbCursor.fetchall()
|
|
|
|
if self.rows:
|
|
for row in self.rows:
|
|
print(row)
|
|
self.result = row
|
|
else:
|
|
if self.mode == "MAC":
|
|
self.mac48 = self.search[:8] # mac address first 3 octets
|
|
self.dbCursor.execute("SELECT * FROM data WHERE mac=?", (self.mac48.upper(),))
|
|
self.rows = self.dbCursor.fetchall()
|
|
if self.rows:
|
|
for row in self.rows:
|
|
|
|
if row[1] == "IEEE Registration Authority":
|
|
self.iab_base = self.mac48+":00:00:00"
|
|
self.dbCursor.execute("SELECT * FROM data WHERE mac<=? AND mac>=? ORDER BY mac DESC LIMIT 1", (self.search.upper(), self.iab_base.upper()))
|
|
self.rows = self.dbCursor.fetchall()
|
|
|
|
if self.rows:
|
|
for row in self.rows:
|
|
print(row)
|
|
self.result = (self.search.upper(), row[1])
|
|
else:
|
|
self.result = (self.search.upper(), 'Sorry, No results found!')
|
|
print(self.result)
|
|
|
|
else:
|
|
self.result = (self.search.upper(), row[1])
|
|
|
|
else:
|
|
self.result = (self.search.upper(), 'Sorry, No results found!')
|
|
print(self.result)
|
|
|
|
else:
|
|
self.result = (self.search.upper(), 'Sorry, No results found!')
|
|
print(self.result)
|
|
|
|
self.history.append(self.result)
|
|
print(self.history)
|
|
|
|
def on_button_toggled(self, button, name):
|
|
if button.get_active():
|
|
self.mode = name
|
|
if self.mode == "OUI":
|
|
self.entry.set_max_length(8)
|
|
self.entry.set_placeholder_text("00:00:00")
|
|
self.repeatFactor = "1"
|
|
self.check_mac(self.entry.get_text())
|
|
|
|
else:
|
|
self.entry.set_max_length(17)
|
|
self.entry.set_placeholder_text("00:00:00:00:00:00")
|
|
self.repeatFactor = "4"
|
|
self.check_mac(self.entry.get_text())
|
|
if (len(self.entry.get_text()) == 8) and (self.mode == "MAC"):
|
|
if self.entry.get_text().find('-') != -1:
|
|
self.search = self.entry.get_text().replace('-', ':')
|
|
else:
|
|
self.search = self.entry.get_text()
|
|
|
|
self.entry.set_text(self.search + ":")
|
|
self.colon = True
|
|
self.entry.set_position(-1)
|
|
|
|
print("Search mode: ", self.mode)
|
|
print("Repeat: ", self.repeatFactor)
|
|
|
|
def file_check(self):
|
|
if not os.path.exists('source.txt'):
|
|
print("file does not exist")
|
|
download = self.on_update_clicked(self)
|
|
if download:
|
|
self.save_data()
|
|
else:
|
|
print(download)
|
|
|
|
else:
|
|
return True
|
|
|
|
def db_connect(self):
|
|
# database connection
|
|
self.dbConnection = sqlite3.connect("macDB")
|
|
self.dbCursor = self.dbConnection.cursor()
|
|
self.dbCursor.execute("CREATE TABLE IF NOT EXISTS data(mac VARCHAR(20), vendor VARCHAR(50), UNIQUE('mac'))")
|
|
|
|
def save_data(self):
|
|
# read source file using "r"(read) parameter
|
|
source_file = open("source.txt", "r")
|
|
line = source_file.readlines()
|
|
source_file.close()
|
|
|
|
data = []
|
|
for i in range(len(line)):
|
|
try:
|
|
if(line[i][0] != "#") and (line[i][0] != "\n"):
|
|
mac = line[i].split('\t', -1)[0][:17]
|
|
if mac == "00:00:00":
|
|
vendor = "Xerox Corporation"
|
|
else:
|
|
vendor = (line[i].split('\t', -1)[-1])[:-1]
|
|
data.append((mac, vendor))
|
|
except Exception as e:
|
|
print(e)
|
|
print(data)
|
|
|
|
self.dbCursor.executemany("INSERT OR REPLACE INTO data VALUES(?,?)", data)
|
|
self.dbConnection.commit()
|
|
|
|
# --- menu actions --- #
|
|
def add_file_menu_actions(self, action_group):
|
|
self.action_filemenu = Gtk.Action("FileMenu", "File", None, None)
|
|
action_group.add_action(self.action_filemenu)
|
|
|
|
self.action_database = Gtk.Action("Database", "Database", None, None)
|
|
action_group.add_action(self.action_database)
|
|
|
|
action_group.add_actions([
|
|
("Update", None, "Update", "<control><alt>U", "Update data base",
|
|
self.on_update_clicked)
|
|
])
|
|
|
|
self.action_filequit = Gtk.Action("FileQuit", None, None, Gtk.STOCK_QUIT)
|
|
self.action_filequit.connect("activate", self.on_menu_file_quit)
|
|
action_group.add_action(self.action_filequit)
|
|
|
|
def add_help_menu_actions(self, action_group):
|
|
action_group.add_actions([
|
|
("HelpMenu", None, "Help"),
|
|
("? help", None, "? help", "<control><alt>H", None,
|
|
lambda x: self.launch_generic_dialog(self, "Help")),
|
|
("About", None, "About", "<control><alt>A", None,
|
|
lambda x:self.launch_generic_dialog(self, "About"))
|
|
])
|
|
|
|
def create_ui_manager(self):
|
|
self.uimanager = Gtk.UIManager()
|
|
|
|
# Throws exception if something went wrong
|
|
self.uimanager.add_ui_from_string(self.UI_INFO)
|
|
|
|
# Add the accelerator group to the toplevel window
|
|
self.accelgroup = self.uimanager.get_accel_group()
|
|
self.add_accel_group(self.accelgroup)
|
|
return self.uimanager
|
|
|
|
def on_menu_file_quit(self, widget):
|
|
Gtk.main_quit()
|
|
|
|
# --- Database source update --- #
|
|
def on_update_clicked(self, widget):
|
|
|
|
print("Updating...")
|
|
self.progressbar.set_visible(True)
|
|
self.progressbar.set_fraction(0.10)
|
|
url = "https://gitlab.com/aitzol76/mac-vendors/raw/master/manuf"
|
|
# url = "https://github.com/wireshark/wireshark/raw/master/manuf"
|
|
try:
|
|
r = urllib.request.urlretrieve(url, "source.txt")
|
|
remote_file_size = r[1]["Content-Length"]
|
|
size = round(int(remote_file_size))
|
|
fraction = round(size/10)
|
|
print(size)
|
|
print(fraction)
|
|
|
|
def progress_bar():
|
|
i = 0
|
|
while i < size:
|
|
value = round(self.progressbar.get_fraction() + 0.1, 1)
|
|
self.progressbar.set_fraction(value)
|
|
print(self.progressbar.get_fraction())
|
|
sleep(0.3)
|
|
i = i + fraction
|
|
print(i)
|
|
yield True
|
|
# while Gtk.events_pending():
|
|
# Gtk.main_iteration()
|
|
if self.progressbar.get_fraction() == 1.0:
|
|
print("...updated!")
|
|
self.launch_dialog(self, "Database succesfully updated!", "Success")
|
|
break
|
|
|
|
def run_progressbar_generator(function):
|
|
gen = function()
|
|
GLib.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_LOW)
|
|
|
|
run_progressbar_generator(progress_bar)
|
|
return True
|
|
|
|
except Exception as e:
|
|
self.launch_dialog(self, str(e), "Error")
|
|
return e
|
|
|
|
def launch_dialog(self, widget, text, title):
|
|
dialog = UpdaterDialog(self, title)
|
|
dialog.label.set_text(text)
|
|
response = dialog.run()
|
|
|
|
if response == Gtk.ResponseType.OK:
|
|
print("The OK button was clicked")
|
|
self.progressbar.set_visible(False)
|
|
dialog.destroy()
|
|
|
|
def launch_generic_dialog(self, widget, title):
|
|
dialog = GenericDialog(self, title)
|
|
# dialog.label.set_text(text)
|
|
response = dialog.run()
|
|
|
|
if response == Gtk.ResponseType.OK:
|
|
print("The OK button was clicked")
|
|
dialog.destroy()
|
|
|
|
|
|
# --- Dialogs --- #
|
|
|
|
|
|
class UpdaterDialog(Gtk.Dialog):
|
|
|
|
def __init__(self, parent, title):
|
|
|
|
Gtk.Dialog.__init__(self, title, parent, 0,
|
|
(Gtk.STOCK_OK, Gtk.ResponseType.OK))
|
|
|
|
self.set_default_size(150, 100)
|
|
self.label = Gtk.Label()
|
|
box = self.get_content_area()
|
|
box.set_border_width(10)
|
|
box.add(self.label)
|
|
self.show_all()
|
|
|
|
|
|
class GenericDialog(Gtk.Dialog):
|
|
|
|
def __init__(self, parent, title):
|
|
|
|
Gtk.Dialog.__init__(self, title, parent, 0,
|
|
(Gtk.STOCK_OK, Gtk.ResponseType.OK))
|
|
|
|
self.set_default_size(150, 100)
|
|
self.label = Gtk.Label()
|
|
self.label.set_justify(Gtk.Justification.LEFT)
|
|
self.label.set_margin_bottom(20)
|
|
box = self.get_content_area()
|
|
box.set_border_width(10)
|
|
box.add(self.label)
|
|
|
|
if title == "Help":
|
|
self.label.set_markup(parser.file_parser("md", "README.md"))
|
|
elif title == "About":
|
|
self.label.set_markup(parser.file_parser("json", "manifest.json"))
|
|
|
|
self.show_all()
|
|
|
|
|
|
win = AppWindow()
|
|
win.connect("destroy", Gtk.main_quit)
|
|
win.db_connect()
|
|
win.show_all()
|
|
if win.file_check():
|
|
win.save_data()
|
|
win.progressbar.hide()
|
|
Gtk.main()
|