#!/usr/bin/python # -*- coding: UTF-8 -*- # +-----------------------------------------------------------------------------+ # | GPL | # +-----------------------------------------------------------------------------+ # | Copyright (c) Brian Lewis Cairns | # | | # | This program 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; either version 2 | # | of the License, or (at your option) any later version. | # | | # | This program is distributed in the hope that it will be useful, | # | but WITHOUT ANY WARRANTY; without even the implied warranty of | # | MERCHANTABILITY or FITNESS FOR A PARTICULAR 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, write to the Free Software | # | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | # +-----------------------------------------------------------------------------+ import logging logging.getLogger().setLevel(logging.DEBUG) import time import sys import pygtk pygtk.require('2.0') import binascii import gtk import gobject import commands try: import gnomeapplet except ImportError: import gnome.applet gnomeapplet = gnome.applet import gnome.ui import os import re import string import pickle import gconf import htmlentitydefs global settings global status # Contains distro-specific settings class settingsClass: def __init__(self): self.max_signal = -40 # dBm, may vary depending on hardware self.disassociation_signal = -100 # dBm, may vary depending on hardware self.settings_script_name = "/usr/local/bin/simpleppp-settings-client" self.icon_wireless_large = "/usr/share/pixmaps/gtkwifi.png" self.icon_lock = "/usr/share/icons/hicolor/16x16/stock/data/stock_lock.png" self.icon_lock_large = "/usr/share/icons/hicolor/32x32/stock/data/stock_lock.png" self.icon_preferred = "/usr/share/icons/hicolor/16x16/stock/object/stock_bookmark.png" self.icon_preferred_large = "/usr/share/icons/hicolor/32x32/stock/object/stock_bookmark.png" self.icon_active = "/usr/share/icons/hicolor/16x16/stock/generic/stock_mark.png" self.icon_hidden_large = "/usr/share/icons/hicolor/32x32/stock/net/stock_channel.png" self.sutil_command = 'sudo -u root ' + self.settings_script_name self.bar_image = {} self.bar_image[0] = "/usr/share/pixmaps/bar0.png" self.bar_image[10] = "/usr/share/pixmaps/bar10.png" self.bar_image[30] = "/usr/share/pixmaps/bar30.png" self.bar_image[50] = "/usr/share/pixmaps/bar50.png" self.bar_image[70] = "/usr/share/pixmaps/bar70.png" self.bar_image[90] = "/usr/share/pixmaps/bar90.png" self.bar_image["Disconnecting..."] = "/usr/share/pixmaps/associate.png" self.bar_image["Connecting..."] = "/usr/share/pixmaps/connect.png" self.bar_image["Connected"] = "/usr/share/pixmaps/complete.png" #self.bar_image["Association Failed"]= "/usr/share/pixmaps/associatefail.png" self.bar_image["Failed to Connect"] = "/usr/share/pixmaps/connectfail.png" self.bar_image["Disconnected"] = "/usr/share/pixmaps/nocard.png" #self.bar_image["nonetworks"] = "/usr/share/pixmaps/nonetworks.png" #self.bar_image["unassociated"] = "/usr/share/pixmaps/unassociated.png" self.disconnect_wait = 15 self.connect_wait = 45 def get_bar_image(self,signal): if signal >= -1 and signal < 10: # AP's with no signal data get this image return self.bar_image[0] if signal >= 10 and signal < 30: return self.bar_image[10] if signal >= 30 and signal < 50: return self.bar_image[30] if signal >= 50 and signal < 70: return self.bar_image[50] if signal >= 70 and signal < 90: return self.bar_image[70] if signal >= 90: return self.bar_image[90] # Contains program-wide information about connection status, preferences, etc. # Also has functions for saving / restoring preferences, key lists, etc. # Also verifies and updates the ns_linkstatus, and other status info class statusClass: def __init__(self): # Initialize GConf to load / save preferences & other saved info self.gconf_client = gconf.client_get_default() self.ns_status = '' self.ns_checkcount = 0 #self.ns_ipaddr = 'XXX' # Set up the "main applet" variable which holds the object for the applet self.main_applet = None try: self.ifname = self.gconf_client.get_string("/apps/simpleppp/ifname") except (TypeError, KeyError): self.ifname = None if self.ifname is None: self.ifname = 'ppp0' # Load display preferences from gconf logging.debug("loading show_label") try: settings.show_label = self.gconf_client.get_bool("/apps/simpleppp/show_label") except (TypeError, KeyError): settings.show_label = None if settings.show_label is None: logging.debug("show_label is None") # Load the defaults instead - and write them to gconf settings.show_label = True self.gconf_client.set_bool("/apps/simpleppp/show_label", settings.show_label) settings.show_label = True def write_settings(self): # Write out the device selection adaptor settings if self.device_mac != None: self.gconf_client.set_string("/apps/simpleppp/ifname", self.ifname) # Refresh the preference dialog if it's open if self.main_applet != None and self.main_applet.prefsdialog != None: self.main_applet.prefsdialog.refresh_preference_display() def check_ns_status(self): try: self.ifcout = commands.getoutput("ip addr show dev '" + status.ifname + "' primary") except IOError: self.ifcout = "" logging.debug(status.ns_status + " / " + self.ifcout) if status.ns_status == "Disconnecting...": if self.ns_checkcount >= settings.disconnect_wait / 2: # Give time for disconnect self.ns_status = "" self.ns_checkcount = 0 if (self.ifcout.find("UP") == -1): self.ns_status = "Disconnected" self.ns_checkcount = 0 else: self.ns_checkcount = self.ns_checkcount + 1 if self.ns_status == "Connecting...": if self.ns_checkcount >= settings.connect_wait / 2: # Give time for dialing, DHCP, etc. self.ns_status = "Failed to Connect" self.ns_checkcount = 0 if (self.ifcout.find("UP") > -1): self.ns_status = "Connected" self.ns_checkcount = 0 else: self.ns_checkcount = self.ns_checkcount + 1 if self.ns_status == "Failed to Connect": if self.ns_checkcount == 4: self.ns_status = "" else: self.ns_checkcount = self.ns_checkcount + 1 if self.ns_status in ("", "Connected", "Disconnected"): if (self.ifcout.find("UP") > -1): self.ns_status = "Connected" else: self.ns_status = "Disconnected" # Utility functions for escaping / unescaping Pango markup pattern = re.compile(r"[&<>\"\x80-\xff]+") entity_map = {} for i in range(256): entity_map[chr(i)] = "&%d;" % i for entity, char in htmlentitydefs.entitydefs.items(): if entity_map.has_key(char): entity_map[char] = "&%s;" % entity def escape_entity(m, get=entity_map.get): return string.join(map(get, m.group()), "") def escape(string): return pattern.sub(escape_entity, string) # Main applet code that creates the applet interface and updates the display class SimplePPPApplet: def cleanup(self,event,widget): del self.applet # Update the display on a regular interval def timeout_callback(self,event): #status.updateNSInfo() o_ns_status = status.ns_status status.check_ns_status() if status.ns_status != o_ns_status: self.update_display() return 1 def update_display(self): self.bars.show() self.ttext = "" #self.ltext = "" + escape(status.ns_status) + "" self.ltext = escape(status.ns_status) # Update the graphic display if status.ns_status <> "": self.ttext = status.ns_status #if status.ns_status == "Connected" and status.ns_ipaddr <> "": # self.ttext = self.ttext + "\nNetwork (IP) Address: " + status.ns_ipaddr # If there is a status string, show it with the graphic self.bars.set_from_file(settings.bar_image[status.ns_status]) # Set the tooltip self.tooltips.set_tip(self.ev_box, self.ttext) # Set the label if settings.show_label: self.label.set_markup(self.ltext) def button_press(self,widget,event): if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: self.create_menu() if event.type == gtk.gdk.BUTTON_RELEASE and event.button == 1: if status.ns_status == "Connected": self.ppp_disconnect() elif status.ns_status == "Disconnected": self.ppp_connect() def ppp_connect(self, event=None, data=None): status.ns_status = "Connecting..." self.update_display() settings.settings_pipe.write(binascii.b2a_hex("ifup" + "\n" + status.ifname) + "\n") settings.settings_pipe.flush() def ppp_disconnect(self, event=None, data=None): status.ns_status = "Disconnecting..." self.update_display() settings.settings_pipe.write(binascii.b2a_hex("ifdown" + "\n" + status.ifname) + "\n") settings.settings_pipe.flush() # Handle Gnome Panel background def panel_bg(self, applet, bg_type, color, pixmap): # Reset styles rc_style = gtk.RcStyle() self.applet.set_style(None) self.ev_box.set_style(None) self.applet.modify_style(rc_style) self.ev_box.modify_style(rc_style) if bg_type == gnomeapplet.PIXMAP_BACKGROUND: style = self.applet.get_style() style.bg_pixmap[gtk.STATE_NORMAL] = pixmap self.applet.set_style(style) self.ev_box.set_style(style) if bg_type == gnomeapplet.COLOR_BACKGROUND: self.applet.modify_bg(gtk.STATE_NORMAL, color) self.ev_box.modify_bg(gtk.STATE_NORMAL, color) def about_info(self,event,data=None): about = gnome.ui.About("Simple PPP Applet", "0.1", "© 2005 by Nathaniel W. Turner, Brian Cairns, Flavio Martins. Released under the GPL.", "Simple applet to manage a PPP interface.", ["Nathaniel W. Turner ", "(based on gtkwifi by Brian Cairns and Flavio Martins)"], None, None, self.logo_pixbuf) about.show() def __init__(self,applet,iid): self.apselect = None self.prefsdialog = None self.dict = {} self.tooltip_text = "" self.propxml = """ """ self.verbs = [ ( "Connect", self.ppp_connect ), ( "Disconnect", self.ppp_disconnect ), ( "About", self.about_info ) ] gnome.init("SimplePPPApplet", "0.1") self.logo_pixbuf = gtk.gdk.pixbuf_new_from_file(settings.icon_wireless_large) self.applet = applet self.tooltips = gtk.Tooltips() #self.hbox = gtk.HBox() #applet.add(self.hbox) self.ev_box = gtk.EventBox() self.applet.set_size_request(-1,26) self.ev_box.connect("event",self.button_press) self.applet.connect("change-background",self.panel_bg) self.label = gtk.Label("") self.bars = gtk.Image() self.bars.set_from_file(settings.bar_image[0]) self.main_hbox = gtk.HBox() self.main_hbox.pack_start(self.bars, False, False, 5) self.main_hbox.pack_start(self.label, False, False, 0) self.ev_box.add(self.main_hbox) applet.add(self.ev_box) gobject.timeout_add(2000, self.timeout_callback, self) # self.label.show() applet.connect("destroy",self.cleanup,None) applet.show_all() self.timeout_callback(None) def create_menu(self): self.applet.setup_menu(self.propxml,self.verbs,None) if len(sys.argv) != 2 or sys.argv[1] != "run-in-window": print "WARNING: SimplePPP is not intended to be run directly from the command line." print "Use 'simpleppp run-in-window' to run SimplePPP in a window." # Create the global classes so we can use them later settings = settingsClass() status = statusClass() # Open a pipe to the settings utility settings.settings_pipe = os.popen2(settings.sutil_command)[0] def SimplePPP_applet_factory(applet, iid): status.main_applet = SimplePPPApplet(applet,iid) return True if len(sys.argv) == 2 and sys.argv[1] == "run-in-window": main_window = gtk.Window(gtk.WINDOW_TOPLEVEL) main_window.set_title("SimplePPP Applet") main_window.connect("destroy", gtk.main_quit) app = gnomeapplet.Applet() SimplePPP_applet_factory(app, None) app.reparent(main_window) main_window.show_all() gtk.main() sys.exit() if __name__ == '__main__': gnomeapplet.bonobo_factory("OAFIID:GNOME_SimplePPPApplet_Factory",gnomeapplet.Applet.__gtype__,"", "0", SimplePPP_applet_factory)