From 488402df7d37cf68d421229968632696a2a97bd7 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 06 Feb 2008 09:20:33 +0000 Subject: Split sugar-toolkit out of sugar shell. --- (limited to 'sugar/profile.py') diff --git a/sugar/profile.py b/sugar/profile.py new file mode 100644 index 0000000..11991dd --- /dev/null +++ b/sugar/profile.py @@ -0,0 +1,207 @@ +"""User settings/configuration loading""" +# Copyright (C) 2006-2007, Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import os +import logging +from ConfigParser import ConfigParser + +from sugar import env +from sugar import util +from sugar.graphics.xocolor import XoColor + +DEFAULT_JABBER_SERVER = 'olpc.collabora.co.uk' +DEFAULT_VOLUME = 81 + +_profile = None + +def _set_key(cp, section, key, value): + if not cp.has_section(section): + cp.add_section(section) + cp.set(section, key, value) + +class Profile(object): + """Local user's current options/profile information + + User settings are stored in an INI-style configuration + file. This object uses the ConfigParser module to load + the settings. (We only very rarely set keys, so we don't + keep the ConfigParser around between calls.) + + The profile is also responsible for loading the user's + public and private ssh keys from disk. + + Attributes: + + name -- child's name + color -- XoColor for the child's icon + server -- school server with which the child is + associated + server_registered -- whether the child has registered + with the school server or not + backup1 -- temporary backup info key for Trial-2 + + pubkey -- public ssh key + privkey_hash -- SHA has of the child's public key + """ + def __init__(self, path): + self.nick_name = None + self.color = None + self.jabber_server = DEFAULT_JABBER_SERVER + self.jabber_registered = False + self.backup1 = None + self.sound_volume = DEFAULT_VOLUME + + self._pubkey = None + self._privkey_hash = None + self._config_path = path + + self._load_config() + + def is_valid(self): + return self.nick_name is not None and \ + self.color is not None and \ + self.pubkey is not None and \ + self.privkey_hash is not None + + def is_registered(self): + return self.backup1 is not None + + def save(self): + cp = ConfigParser() + cp.read([self._config_path]) + + if self.nick_name: + _set_key(cp, 'Buddy', 'NickName', self.nick_name.encode('utf8')) + if self.color: + _set_key(cp, 'Buddy', 'Color', self.color.to_string()) + if self.backup1: + _set_key(cp, 'Server', 'Backup1', self.backup1) + if self.jabber_server: + _set_key(cp, 'Jabber', 'Server', self.jabber_server) + + _set_key(cp, 'Jabber', 'Registered', self.jabber_registered) + + _set_key(cp, 'Sound', 'Volume', self.sound_volume) + + f = open(self._config_path, 'w') + cp.write(f) + f.close() + + def _load_config(self): + cp = ConfigParser() + cp.read([self._config_path]) + + if cp.has_option('Buddy', 'NickName'): + name = cp.get('Buddy', 'NickName') + # decode nickname from ascii-safe chars to unicode + self.nick_name = name.decode("utf-8") + if cp.has_option('Buddy', 'Color'): + self.color = XoColor(cp.get('Buddy', 'Color')) + if cp.has_option('Jabber', 'Server'): + self.jabber_server = cp.get('Jabber', 'Server') + if cp.has_option('Jabber', 'Registered'): + registered = cp.get('Jabber', 'Registered') + if registered.lower() == "true": + self.jabber_registered = True + if cp.has_option('Server', 'Backup1'): + self.backup1 = cp.get('Server', 'Backup1') + if cp.has_option('Sound', 'Volume'): + self.sound_volume = float(cp.get('Sound', 'Volume')) + + del cp + + def _load_pubkey(self): + key_path = os.path.join(env.get_profile_path(), 'owner.key.pub') + try: + f = open(key_path, "r") + lines = f.readlines() + f.close() + except IOError, e: + logging.error("Error reading public key: %s" % e) + return None + + magic = "ssh-dss " + for l in lines: + l = l.strip() + if not l.startswith(magic): + continue + return l[len(magic):] + else: + logging.error("Error parsing public key.") + return None + + def _get_pubkey(self): + # load on-demand. + if not self._pubkey: + self._pubkey = self._load_pubkey() + return self._pubkey + + def _hash_private_key(self): + key_path = os.path.join(env.get_profile_path(), 'owner.key') + try: + f = open(key_path, "r") + lines = f.readlines() + f.close() + except IOError, e: + logging.error("Error reading private key: %s" % e) + return None + + key = "" + for l in lines: + l = l.strip() + if l.startswith("-----BEGIN DSA PRIVATE KEY-----"): + continue + if l.startswith("-----END DSA PRIVATE KEY-----"): + continue + key += l + if not len(key): + logging.error("Error parsing public key.") + return None + + # hash it + key_hash = util._sha_data(key) + return util.printable_hash(key_hash) + + def _get_privkey_hash(self): + # load on-demand. + if not self._privkey_hash: + self._privkey_hash = self._hash_private_key() + return self._privkey_hash + + privkey_hash = property(_get_privkey_hash) + pubkey = property(_get_pubkey) + +def get_profile(): + global _profile + + if not _profile: + path = os.path.join(env.get_profile_path(), 'config') + _profile = Profile(path) + + return _profile + +# Convenience methods for frequently used properties + +def get_nick_name(): + return get_profile().nick_name + +def get_color(): + return get_profile().color + +def get_pubkey(): + return get_profile().pubkey -- cgit v0.9.1