You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
20 KiB
Python

"""
* GPRSPanel.py - SettingsGUI - GPRS Settings
*
* GPRS Connection Settings - using pppd until the LDISC interface is
* finished
*
* (C) 2007 by Kristian Mueller <kristian-m@kristian-m.de>
* All Rights Reserved
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
import sys
import os
import shutil # to create a backup of pppd config files
import threading
import time
import gtk
import gobject
from ProcessInterface import *
from SysFSAccess import *
from GSMPanel import *
from GlobalConfiguration import *
from pppdConfigParser import *
#from settingsgui.ProcessInterface import *
#from settingsgui.SysFSAccess import *
#from settingsgui.GSMPanel import *
#from settingsgui.GlobalConfiguration import *
#from settingsgui.pppdConfigParser import *
## ToDo
## from GSMPanel import GSMPanel ## to reach the operator name
## (name peer like operator)
################################################################################
# lots of methods - will devide them into block with big comments between them #
################################################################################
class GPRSPanel(gtk.VBox):
def __init__(self, GSM_Panel):
self.GSM_Panel = GSM_Panel
gtk.VBox.__init__(self, False, 0)
self.peer_entries = {}
self.entry_dict = {}
self.local_ip = ""
self.remote_ip = ""
self.nameserver_ip = ""
self.peer_entries.update(self.find_peers())
self.create_notebook_page()
self.peer_changed_callback(self.peer_combo)
self.set_state("disconnected")
################################################################################
############ search system for ppp peers (pppd config files) ###################
################################################################################
def find_peers(self):
new_dict = {}
if not os.path.exists(os.path.expanduser(PPP_PATH_TO_USER_PEERS)):
os.makedirs(os.path.expanduser(PPP_PATH_TO_USER_PEERS))
print "created %s" % os.path.expanduser(PPP_PATH_TO_USER_PEERS)
else:
try:
for key in os.listdir(
os.path.expanduser(PPP_PATH_TO_USER_PEERS)):
if (key[-1] != '~') \
and (key.find("-chat") < 0) \
and (key.find("latest_") < 0):
path_to_file = os.path.join(
os.path.expanduser(PPP_PATH_TO_USER_PEERS), key)
new_dict[key] = pppdConfigParser(path_to_file)
# print "Added and parsed <%s> (global)" % path_to_file
except: ## maybe we have no permissions for os.listdir
None # nothing we can do about it -
# ToDo: maybe throw a message box
## read in system wide peers
if os.path.exists(PPP_PATH_TO_GLOBAL_PEERS):
try:
for key in os.listdir(PPP_PATH_TO_GLOBAL_PEERS):
if ((key[-1] != '~') \
and (key.find("-chat") < 0) \
and (key.find("latest_") < 0) \
and (key.find(PPP_PATH_TO_USER_PEERS) < 0)):
path_to_file = os.path.join(
PPP_PATH_TO_GLOBAL_PEERS, key)
new_dict[key] = pppdConfigParser(path_to_file)
except: ## maybe we have no permissions for os.listdir
print "could no access %s" % PPP_PATH_TO_GLOBAL_PEERS
print "found %d peers" % len(new_dict)
## no peer found, creating default peer
if len(new_dict) <= 0:
## ToDo use users directory
print "Will create a default peer in /etc/ppp/peers"
if not os.path.exists(PPP_PATH_TO_GLOBAL_PEERS):
try:
os.makedirs(PPP_PATH_TO_GLOBAL_PEERS)
except:
print "Could not make %s dir" % PPP_PATH_TO_GLOBAL_PEERS
try:
filename = os.path.join(PPP_PATH_TO_GLOBAL_PEERS,
PPP_DEFAULT_CONFIG_NAME)
peer_fd = open(filename, 'w')
print "Creating default peer in %s " % filename
for line in PPP_DEFAULT_CONFIG.split('\n'):
peer_fd.write("%s\n" %line)
peer_fd.close()
## connect chat script
filename = os.path.join(PPP_PATH_TO_GLOBAL_PEERS,
"%s-connect-chat" % PPP_DEFAULT_CONFIG_NAME)
print "Creating default chat file in %s " % filename
peer_fd = open(filename, 'w')
for line in PPP_DEFAULT_CONNECT_SCRIPT.split('\n'):
peer_fd.write("%s\n" %line)
peer_fd.close()
## disconnect chat script
filename = os.path.join(PPP_PATH_TO_GLOBAL_PEERS,
"%s-disconnect-chat" % PPP_DEFAULT_CONFIG_NAME)
print "Creating default chat file in %s " % filename
peer_fd = open(filename, 'w')
for line in PPP_DEFAULT_DISCONNECT_SCRIPT.split('\n'):
peer_fd.write("%s\n" %line)
peer_fd.close()
filename = os.path.join(PPP_PATH_TO_GLOBAL_PEERS,
PPP_DEFAULT_CONFIG_NAME)
new_dict[PPP_DEFAULT_CONFIG_NAME] = pppdConfigParser(filename)
except:
print "Could not create peer <%s>" % os.path.join(
PPP_PATH_TO_GLOBAL_PEERS, PPP_DEFAULT_CONFIG_NAME)
return new_dict
################################################################################
############# interfacing the pppd subprocess, regestering callbacks ###########
################################################################################
## starting subprocess
## ToDo: use -b and parse a logfile
## to keep it running when SettingsGUI is quit
## => find out if pppd is running on start up
def start_pppd(self, config_file):
parameters = "debug call %s" % config_file
pppd = ProcessInterface(
"start-stop-daemon --start -x %s -- %s" % (PPP_INIT, parameters))
pppd.register_event_handler("ERROR", self.connection_error)
pppd.register_event_handler("", self.update_output)
pppd.register_event_handler("local IP address", self.update_local_ip)
pppd.register_event_handler("remote IP address", self.update_remote_ip)
## ToDo see start_pppd
def stop_pppd(self):
pppd = ProcessInterface("start-stop-daemon --stop -x %s" % (PPP_INIT))
pppd.register_event_handler("", self.update_output)
self.set_state("disconnected")
################################################################################
############## Callbacks from pppd subprocess output - as callbacks ############
################################################################################
## called from pppd parser subprocess
def update_local_ip(self, string):
if len(string.split()) >= 3:
self.local_ip = string.split()[3]
else:
self.local_ip = ""
self.IP_text_buffer.set_text("Local IP: %s\nRemote IP: %s\nNameserver: %s" %(
self.local_ip, self.remote_ip, self.nameserver_ip))
## called from pppd parser subprocess
def update_remote_ip(self, string):
if len(string.split()) >= 3:
self.remote_ip = string.split()[3]
self.set_state("connected")
else:
self.remote_ip = ""
self.IP_text_buffer.set_text("Local IP: %s\nRemote IP: %s\nNameserver: %s" %(
self.local_ip, self.remote_ip, self.nameserver_ip))
## called from pppd parser subprocess
def connection_error(self, dummy):
self.set_state("disconnected")
## called indirectly from pppd parser subprocess (from set state)
def update_nameserver(self):
self.nameserver_ip = ""
if self.state_string == "connected" and os.path.exists("/etc/resolv.conf"):
fd = open("/etc/resolv.conf", 'r')
for line in fd.readlines():
if line.find("nameserver") >= 0:
self.nameserver_ip = line.split()[1]
break
fd.close()
if not os.path.exists("/etc"):
try:
os.makedirs("/etc")
except:
print "could not make /etc directory"
if len(self.nameserver_ip) <= 0:
try:
fd = open("/etc/resolv.conf", 'w')
fd.write("nameserver %s\n" % DEFAULT_NAMESERVER)
except:
print "could not edit /etc/resolv.conf to add a default Nameserver"
self.IP_text_buffer.set_text("Local IP: %s\nRemote IP: %s\nNameserver: %s" %(
self.local_ip, self.remote_ip, self.nameserver_ip))
## called on init and from pppd parser subprocess
def set_state(self, state_string):
self.state_string = state_string
if state_string == "connected":
self.disconnect_btn.set_sensitive(1)
self.connect_btn.set_sensitive(0)
self.update_nameserver()
if state_string == "disconnected":
self.connect_btn.set_sensitive(1)
self.disconnect_btn.set_sensitive(0)
self.update_local_ip("")
self.update_remote_ip("")
self.update_nameserver()
def update_output(self, string):
## remove tailing and starting \n and \r - just in case
string = string.rstrip('\n').lstrip('\n').rstrip('\r').lstrip('\r')
print "pppd: <%s>" % string
self.update_state(string)
################################################################################
############################## Callbacks from UI ###############################
################################################################################
## called when drop down box selection changed
def peer_changed_callback(self, widget):
print "peers changed, filling in entries..."
entry = widget.get_active_text()
if not self.peer_entries.has_key(entry):
self.update_state("Could not open a peer file")
return False
self.current_peer_entry = self.peer_entries[entry]
if self.peer_entries.has_key(entry):
self.entry_dict["APN"].set_text(self.current_peer_entry.get_APN())
self.entry_dict["User"].set_text(self.current_peer_entry.get_user())
self.entry_dict["Password"].set_text(self.current_peer_entry.get_password())
self.entry_dict["Number"].set_text(self.current_peer_entry.get_number())
self.current_peer_entry.config_name = entry
return True
## user edited the settings
def settings_changed(self, widget):
self.entry_dict[widget.get_name()].set_text(widget.get_text())
self.add_peer_btn.set_sensitive(1)
## ToDo
def save_peer(self, widget):
file_path = os.path.join(os.path.expanduser(PPP_PATH_TO_USER_PEERS), \
self.current_peer_entry.config_name)
if not os.path.exists("%s-backup" % file_path):
print "will backup peer %s - %s" % (file_path, self.current_peer_entry.config_name)
try:
shutil.copyfile(file_path, "%s-backup" % file_path)
if os.path.exists("%s-connect-chat" % file_path) and \
not os.path.exists("%s-connect-chat-backup" % file_path):
shutil.copyfile("%s-connect-chat" % file_path, \
"%s-connect-chat-backup" % file_path)
if os.path.exists("%s-disconnect-chat" % file_path) and \
not os.path.exists("%s-disconnect-chat-backup" % file_path):
shutil.copyfile("%s-disconnect-chat" % file_path, \
"%s-disconnect-chat-backup" % file_path)
except:
self.update_state("Backup of old entry failed - aborting!")
return False
if self.current_peer_entry.generate_configuration(
os.path.expanduser(PPP_PATH_TO_USER_PEERS), \
self.current_peer_entry.config_name, \
self.entry_dict["APN"].get_text(), \
self.entry_dict["User"].get_text(), \
self.entry_dict["Password"].get_text(), \
self.entry_dict["Number"].get_text()):
self.update_state("%s saved to %s" % (\
self.current_peer_entry.config_name, \
os.path.expanduser(PPP_PATH_TO_USER_PEERS)))
return True
def connect_clicked(self, widget):
if self.GSM_Panel.stop_gsmd_btn.get_property("sensitive"):
mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO,
gtk.BUTTONS_YES_NO, "Do you want to terminate gsmd first?")
response = mbox.run()
mbox.hide()
mbox.destroy()
if response == gtk.RESPONSE_YES:
print "will terminate gsmd"
self.GSM_Panel.stop_gsmd(None)
if self.current_peer_entry.generate_configuration(
os.path.expanduser(PPP_PATH_TO_USER_PEERS), PPP_GENCONFIG_NAME, \
self.entry_dict["APN"].get_text(), \
self.entry_dict["User"].get_text(), \
self.entry_dict["Password"].get_text(), \
self.entry_dict["Number"].get_text()):
self.start_pppd(PPP_GENCONFIG_NAME)
def disconnect_clicked(self, widget):
self.stop_pppd()
################################################################################
############################## UI Helper fkts ##################################
################################################################################
## change output on "state bar"
def update_state(self, string):
self.state_entry.set_text(string)
## creating a label + entry box
def add_entry_with_name(self, name, default_text, password_mode, callback):
entry_box = gtk.HBox()
label = gtk.Label(name)
label.set_width_chars(8)
entry_box.set_spacing(15)
entry_box.pack_start(label, False, False, 0)
entry = gtk.Entry()
entry.set_text(default_text)
entry.set_visibility(password_mode)
entry.connect("changed", callback)
entry.set_name(name)
entry_box.add(entry)
self.entry_dict[name] = entry ## to access the text entry
entry_box.show()
return entry_box
################################################################################
################################# create UI ####################################
################################################################################
def create_notebook_page(self):
# start_time = time.time()
self.set_border_width(0)
peer_box = gtk.HBox()
# self.peer_combo = gtk.combo_box_new_text()
self.peer_combo = gtk.combo_box_entry_new_text()
if len(self.peer_entries) <= 0:
self.peer_combo.append_text("ERROR /etc/ppp/ access?") ## <- there was no peer and access to /etc/ppp was not possible
for entry in self.peer_entries:
self.peer_combo.append_text(entry)
self.peer_combo.set_focus_on_click(False)
# self.peer_combo.set_property("allow_empty", 0)
self.peer_combo.set_active(0)
# self.peer_combo.set_sensitive(0)
self.peer_combo.connect('changed', self.peer_changed_callback)
self.add_peer_btn = gtk.Button()
image = gtk.Image()
image.set_from_icon_name("gtk-save", gtk.ICON_SIZE_MENU)
self.add_peer_btn.add(image)
self.add_peer_btn.connect('clicked', self.save_peer)
peer_box.pack_start(self.add_peer_btn, False, False, 0)
peer_box.add (self.peer_combo)
if len(self.peer_entries) <= 0:
self.add_peer_btn.set_sensitive(1)
else:
self.add_peer_btn.set_sensitive(0)
self.pack_start(peer_box, False, False, 0)
# GPRS Settings
gprs_frame = gtk.Frame("GPRS Login Settings")
gprs_box = gtk.VBox()
gprs_box.set_border_width(10)
gprs_box.add(self.add_entry_with_name("APN", "internet.eplus.de", True, self.settings_changed))
gprs_box.add(self.add_entry_with_name("User", "gprs", True, self.settings_changed))
gprs_box.add(self.add_entry_with_name("Password", "gprs", False, self.settings_changed))
gprs_box.add(self.add_entry_with_name("Number", "*99***1#", True, self.settings_changed))
gprs_frame.add(gprs_box)
self.pack_start(gprs_frame, False, False, 0)
# buttons
btn_box = gtk.HBox()
self.connect_btn = gtk.Button("Connect\nto GPRS")
self.connect_btn.connect("clicked", self.connect_clicked)
btn_box.add(self.connect_btn)
## to prevent keyboard from beeing activated on startup
self.set_focus_child(self.connect_btn)
self.disconnect_btn = gtk.Button("Disconnect\nfrom GPRS")
self.disconnect_btn.connect("clicked", self.disconnect_clicked)
self.disconnect_btn.set_sensitive(0)
btn_box.add(self.disconnect_btn)
self.pack_start(btn_box, False, False, 0)
state_frame = gtk.Frame("GPRS State")
# IP infos
state_box = gtk.VBox()
self.IP_box = gtk.VBox()
self.IP_box.set_border_width(10)
self.IP_text_view = gtk.TextView()
self.IP_text_buffer = self.IP_text_view.get_buffer()
self.IP_text_buffer.set_text("Local IP: %s\nRemote IP: %s\nNameserver: %s" %(
self.local_ip, self.remote_ip, self.nameserver_ip))
self.IP_text_view.set_editable(0)
self.IP_box.add(self.IP_text_view)
state_box.add(self.IP_box)
self.state_entry = gtk.Entry()
self.state_entry.set_text("")
self.state_entry.set_sensitive(0)
state_box.add(self.state_entry)
state_frame.add(state_box)
self.pack_start(state_frame, False, False, 0)
## override the focus chain as OM will fire the keyboard
## if a textentry is active
focusable_widgets = [self.connect_btn,
gprs_box] + [self.entry_dict[x] for x in self.entry_dict] + [self.peer_combo]
self.show_all()
# print "time needed to init GPRS Panel = %s" % (time.time() - start_time)