From 84de310fa04cbf51799439bbc06715731e492c65 Mon Sep 17 00:00:00 2001 From: psy Date: Thu, 29 Aug 2013 08:45:30 -0700 Subject: [PATCH] first draft with GTK --- README | 11 + WM1.svg | 10768 +++++++++++++++++++++++++++++++++++++++++++++++ bc | 20 + bc_gtk.py | 20 + bordercheck.py | 73 - builder.xml | 18 + main.py | 196 + main_gtk.py | 108 + options.py | 21 + 9 files changed, 11162 insertions(+), 73 deletions(-) create mode 100644 WM1.svg create mode 100755 bc create mode 100644 bc_gtk.py delete mode 100644 bordercheck.py create mode 100644 builder.xml create mode 100644 main.py create mode 100644 main_gtk.py create mode 100644 options.py diff --git a/README b/README index e69de29..1e7a591 100644 --- a/README +++ b/README @@ -0,0 +1,11 @@ +Border Check (BC) is an art project to visualize the physical infrastructure of the internet using free software tools. +Currently working on v.01 of the software and a better version of this text. + +GPLv3 - 2013 + +----------- +Contacts: + +Roel Roscam Abbing (roel@roelroscamabbing.nl) +psy (epsylon@riseup.net) + diff --git a/WM1.svg b/WM1.svg new file mode 100644 index 0000000..a87f6d2 --- /dev/null +++ b/WM1.svg @@ -0,0 +1,10768 @@ + + + + + + + image/svg+xml + + + Blank World Map + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bc b/bc new file mode 100755 index 0000000..674ad1c --- /dev/null +++ b/bc @@ -0,0 +1,20 @@ +#!/usr/bin/python +# -*- coding: iso-8859-15 -*- +""" +BC (Border-Check) is a tool to retrieve info of traceroute tests over website navigation routes. +GPLv3 - 2013 by psy (epsylon@riseup.net) +""" +from main import bc + +class NullOutput(object): + def write(self, text): + pass + def flush(self): + pass + +if __name__ == "__main__": + app = bc() + options = app.create_options() + if options: + app.set_options(options) + app.run() diff --git a/bc_gtk.py b/bc_gtk.py new file mode 100644 index 0000000..cf36eab --- /dev/null +++ b/bc_gtk.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +# -*- coding: iso-8859-15 -*- +""" +BC (Border-Check) is a tool to retrieve info of traceroute tests over website navigation routes. +GPLv3 - 2013 by psy (epsylon@riseup.net) +""" +from main_gtk import GuiStarter, GuiUtils + +try: + import gtk, gtk.glade +except: + print ("\nError importing: Gtk/Glade libs. \n\nOn Debian based systems, please try like root:\n\n $ apt-get install python-gtk2\n") + sys.exit(2) + +class BCGTK(): + @staticmethod + def run(): + GuiStarter() + gtk.main() + diff --git a/bordercheck.py b/bordercheck.py deleted file mode 100644 index 4b42592..0000000 --- a/bordercheck.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/python - -import sqlite3, os, time, pygeoip,re -from urlparse import urlparse -import subprocess, socket - - - - -def getURL(): - ## function to get the last visited URL from the browser history database. This is only for Firefox. - ## However the Chrome database works in a similar way, just with different tables. I believe it's not to hard - ## to produce a function like this for every browser. The difficulty would be for a user to give the path to the - ## history file. - - conn = sqlite3.connect('path/to/firefox/places.sqlite') - c = conn.cursor() - c.execute('select url, last_visit_date from moz_places ORDER BY last_visit_date DESC') - url = c.fetchone() - return url[0] - - - -## Location of the GeoIP database. Currently using this one: http://dev.maxmind.com/geoip/legacy/geolite/ -## Perhaps better databases are available. -geoip= pygeoip.GeoIP('path/to/geoipdatabase.dat') - -old_url="" - -## the main loop, always running, checks once in 5 seconds if there is a new URL in the browser history. -while True: - - ## get the URL from the browser history, strip it down to the host, convert that to ip adress. - url = urlparse(getURL()).netloc - # url = url.replace('www.','') --> doing a tracert to for example.com and www.example.com yields different results most of the times. - url_ip = socket.gethostbyname(url) - if url != old_url: - count = 0 - print url - - ## Run LFT (layer four traceroute, http://pwhois.org/lft/) on the ip as a subprocess and pipe back into script. - ## In NL this has worked flawlessly for me - ## however since i'm in the Laboral all tracerts using TCP fail and the one with UDP find a path, but - ## fail to reach the destination. Perhaps it has to do with the network configuration here, but we should - ## look into it. - - #a = subprocess.Popen(['lft', '-S', '-n', '-e', url_ip], stdout=subprocess.PIPE) -> using tcp - a = subprocess.Popen(['lft', '-S', '-n', '-u', url_ip], stdout=subprocess.PIPE) # -> using udp - logfile = open('logfile', 'a') - - for line in a.stdout: - #log results. - logfile.write(line) - - ## Parsing the results from LFT. If it finds an ip adress compare it against the database and print the results - parts = line.split() - for ip in parts: - if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",ip): - record = geoip.record_by_addr(ip) - #print record - if record.has_key('country_name') and record['city'] is not '': - country = record['country_name'] - city = record['city'] - print count, "While surfing you got to "+ip+" which is in "+city+", "+country - elif record.has_key('country_name'): - country = record['country_name'] - print count, "While surfing you got to "+ip+" which is in "+country - time.sleep(0.1) - count+=1 - old_url = url - print"old url =",old_url - logfile.close() - time.sleep(5) diff --git a/builder.xml b/builder.xml new file mode 100644 index 0000000..befa3e8 --- /dev/null +++ b/builder.xml @@ -0,0 +1,18 @@ + + + + + + + + True + Border Check - GTK Version + center + + + True + WM1.svg + + + + diff --git a/main.py b/main.py new file mode 100644 index 0000000..842ff90 --- /dev/null +++ b/main.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +# -*- coding: iso-8859-15 -*- +""" +BC (Border-Check) is a tool to retrieve info of traceroute tests over website navigation routes. +GPLv3 - 2013 by psy (epsylon@riseup.net) +""" +import os, sys, time, re, traceback +from urlparse import urlparse +try: + import pygeoip +except: + print "\nError importing: pygeoip lib. \n\nOn Debian based systems, please try like root:\n\n $ apt-get install python-geoip\n" + sys.exit(2) +try: + import sqlite3 +except: + print "\nError importing: sqlite3 lib. \n\nOn Debian based systems, please try like root:\n\n $ apt-get install sqlite3\n" + sys.exit(2) + +import subprocess, socket +from options import BCOptions +from bc_gtk import BCGTK + +# set to emit debug messages about errors (0 = off). +DEBUG = 1 + +class bc(object): + """ + BC main Class + """ + def __init__(self): + """ + Init defaults + """ + self.browser = "" # "F" Firefox / "C" Chrome + self.browser_path = "" + self.url = "" + self.old_url = "" + + def set_options(self, options): + """ + Set program options + """ + self.options = options + + def create_options(self, args=None): + """ + Create options for OptionParser + """ + self.optionParser = BCOptions() + self.options = self.optionParser.get_options(args) + if not self.options: + return False + return self.options + + def try_running(self, func, error, args=None): + """ + Try running a function and print some error if it fails and exists with a fatal error. + """ + options = self.options + args = args or [] + try: + return func(*args) + except Exception as e: + if options.url: + print("[Error] - Something wrong fetching urls. Aborting..."), "\n" + sys.exit(2) + else: + print(error, "error") + if DEBUG: + traceback.print_exc() + + def check_browser(self): + """ + Check for browser used by system + """ + b = subprocess.Popen(['locate', 'places.sqlite']) # check for Firefox + if b != "": + self.browser = "F" #Firefox + self.browser_path = "/home/psy/.mozilla/firefox/cq3sfq0e.default/places.sqlite" #automatic extracion of path + else: + self.browser = "C" #Chrome + self.browser_path = "" + + def getURL(self): + """ + Set urls to visit + """ + print "Browser database:", self.browser_path, "\n" + conn = sqlite3.connect(self.browser_path) + c = conn.cursor() + + if self.browser == "F": #Firefox history database + c.execute('select url, last_visit_date from moz_places ORDER BY last_visit_date DESC') + elif self.browser == "C": #Chrome history database + # Linux: /home/$USER/.config/google-chrome/ + # Linux: /home/$USER/.config/chromium/ + # Windows Vista (and Win 7): C:\Users\[USERNAME]\AppData\Local\Google\Chrome\ + # Windows XP: C:\Documents and Settings\[USERNAME]\Local Settings\Application Data\Google\Chrome\ + c.execute('select urls.url, urls.title, urls.visit_count, urls.typed_count, urls.last_visit_time, urls.hidden, visits.visit_time, visits.from_visit, visits.transition from urls, visits where urls.id = visits.url') + else: # Browser not allowed + print "\nSorry, you haven't a compatible browser\n\n" + exit(2) + url = c.fetchone() + self.url = url + print "Fetching URL:", self.url[0], "\n" + return url[0] + + def getGEO(self): + """ + Get Geolocation database (http://dev.maxmind.com/geoip/legacy/geolite/) + """ + # Download and extract database + try: + urllib.urlretrieve('http://xsser.sf.net/map/GeoLiteCity.dat.gz', + geo_db_path+'.gz', reportfunc) + except: + try: + urllib.urlretrieve('http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz', + geo_db_path+'.gz', reportfunc) + except: + print("[Error] - Something wrong fetching GeoIP maps from the Internet. Aborting..."), "\n" + sys.exit(2) + + # Set database + geoip= pygeoip.GeoIP('GeoLiteCity.dat') + + def run(self, opts=None): + """ + Run BorderCheck + """ + #eprint = sys.stderr.write + # set options + if opts: + options = self.create_options(opts) + self.set_options(options) + options = self.options + p = self.optionParser + # banner + print('='*75) + print(str(p.version)) + print('='*75) + # extract browser type and path + browser = self.try_running(self.check_browser, "\nInternal error checking browser files path.") + # extract url + url = self.try_running(self.getURL, "\nInternal error getting urls from browser's database.") + print "url:", self.url + # start gtk mode + BCGTK.run() + + while True: + url = urlparse(self.url[0]).netloc + url = url.replace('www.','') #--> doing a tracert to for example.com and www.example.com yields different results most of the times. + url_ip = socket.gethostbyname(url) + print url_ip + if url != self.old_url: + count = 0 + print url + + a = subprocess.Popen(['lft', '-S', '-n', '-E', url_ip], stdout=subprocess.PIPE) # -> using tcp + #a = subprocess.Popen(['lft', '-S', '-n', '-u', url_ip], stdout=subprocess.PIPE) # -> using udp + logfile = open('logfile', 'a') + + for line in a.stdout: + logfile.write(line) + parts = line.split() + for ip in parts: + if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",ip): + record = geoip.record_by_addr(ip) + #print record + try: + if record.has_key('country_name') and record['city'] is not '': + country = record['country_name'] + city = record['city'] + print count, "While surfing you got to "+ip+" which is in "+city+", "+country + elif record.has_key('country_name'): + country = record['country_name'] + print count, "While surfing you got to "+ip+" which is in "+country + time.sleep(0.3) + count+=1 + except: + print "Not more records. Aborting...", "\n" + exit() + + self.old_url = url + print"old url =", self.old_url + logfile.close() + time.sleep(5) + +if __name__ == "__main__": + app = bc() + options = app.create_options() + if options: + app.set_options(options) + app.run() + diff --git a/main_gtk.py b/main_gtk.py new file mode 100644 index 0000000..4b64be7 --- /dev/null +++ b/main_gtk.py @@ -0,0 +1,108 @@ +#!/usr/bin/python +# -*- coding: iso-8859-15 -*- +""" +BC (Border-Check) is a tool to retrieve info of traceroute tests over website navigation routes. +GPLv3 - 2013 by psy (epsylon@riseup.net) +""" +import sys +try: + import gtk, gtk.glade +except: + print ("\nError importing: Gtk/Glade libs. \n\nOn Debian based systems, please try like root:\n\n $ apt-get install python-gtk2\n") + sys.exit(2) + +class GuiUtils(object): + @staticmethod + def GetBuilder(name): + builder = gtk.Builder() + if not builder.add_from_file('builder.xml'): + print 'XML file not found!' + sys.exit(1) + else: + return builder + + @staticmethod + def Error(title, text): + """Show error popup""" + dialog = gtk.MessageDialog( + parent = None, + flags = gtk.DIALOG_DESTROY_WITH_PARENT, + type = gtk.MESSAGE_ERROR, + buttons = gtk.BUTTONS_OK, + message_format = text) + dialog.set_title(title) + dialog.connect('response', lambda dialog, response: dialog.destroy()) + dialog.show() + print text + + @staticmethod + def Info(title, text): + """Show info popup""" + dialog = gtk.MessageDialog( + parent = None, + flags = gtk.DIALOG_DESTROY_WITH_PARENT, + type = gtk.MESSAGE_INFO, + buttons = gtk.BUTTONS_OK, + message_format = text) + dialog.set_title(title) + dialog.connect('response', lambda dialog, response: dialog.destroy()) + dialog.show() + + @staticmethod + def Loading(title, text): + """Show loading popup""" + dialog = gtk.MessageDialog( + parent = None, + flags = gtk.DIALOG_DESTROY_WITH_PARENT, + type = gtk.MESSAGE_INFO, + buttons = gtk.BUTTONS_NONE, + message_format = text) + dialog.set_title(title) + dialog.connect('response', lambda dialog, response: dialog.destroy()) + dialog.show() + return dialog + + @staticmethod + def Warning(title, text): + """Show warning popup""" + dialog = gtk.MessageDialog( + parent = None, + flags = gtk.DIALOG_DESTROY_WITH_PARENT, + type = gtk.MESSAGE_WARNING, + buttons = gtk.BUTTONS_OK, + message_format = text) + dialog.set_title(title) + dialog.connect('response', lambda dialog, response: dialog.destroy()) + dialog.show() + return dialog + + @staticmethod + def Question(title, text): + """Show question popup""" + dialog = gtk.MessageDialog( + parent = None, + flags = gtk.DIALOG_DESTROY_WITH_PARENT, + type = gtk.MESSAGE_QUESTION, + buttons = gtk.BUTTONS_YES_NO, + message_format = text) + dialog.set_title(title) + dialog.connect('response', lambda dialog, response: dialog.destroy()) + dialog.show() + return dialog + +class GuiStarter(object): + """ + Init the starter GUI box. + """ + def __init__(self): + """ + Start the GUI up and set the connections with the components. + """ + builder = GuiUtils.GetBuilder('builder') + + # get objects + self.window = builder.get_object('builder') + + # defaults + + # signals diff --git a/options.py b/options.py new file mode 100644 index 0000000..8600184 --- /dev/null +++ b/options.py @@ -0,0 +1,21 @@ +#!/usr/bin/python +# -*- coding: iso-8859-15 -*- +""" +BC (Border-Check) is a tool to retrieve info of traceroute tests over website navigation routes. +GPLv3 - 2013 by psy (epsylon@riseup.net) +""" +import optparse + +class BCOptions(optparse.OptionParser): + def __init__(self, *args): + optparse.OptionParser.__init__(self, + prog='bc.py', + version='\nBC (Border-Check) 0.1v - 2013 - (GPLv3.0) -> by psy\n', + usage= '\n\nbc [OPTIONS]') + + self.add_option("-d", "--debug", action="store_true", dest="debug", help="debug mode") + + def get_options(self, user_args=None): + (options, args) = self.parse_args(user_args) + return options +