def GetBuddyByPublicKey(self, key):
     buddy = self._buddies_by_pubkey.get(key)
     if buddy is not None:
         if buddy.props.valid:
             return buddy.object_path()
     keyid = pubkey_to_keyid(key)
     buddy = self._buddies.get('keyid/' + keyid)
     if buddy is not None:
         if buddy.props.valid:
             return buddy.object_path()
     raise NotFoundError("The buddy was not found.")
    def __init__(self, ps, bus):
        """Initialize the ShellOwner instance

        ps -- presenceservice.PresenceService object
        bus -- a connection to the D-Bus session bus

        Retrieves initial property values from the profile
        module.  Loads the buddy icon from file as well.
            XXX note: no error handling on that

        calls GenericOwner.__init__
        """
        client = gconf.client_get_default()    
        profile = get_profile()

        key_hash = profile.privkey_hash
        key = profile.pubkey

        color = client.get_string("/desktop/sugar/user/color")
        tags = client.get_string("/desktop/sugar/user/tags")
        nick = client.get_string("/desktop/sugar/user/nick")

        if not isinstance(nick, unicode):
            nick = unicode(nick, 'utf-8')

        GenericOwner.__init__(self, ps, bus,
                'keyid/' + psutils.pubkey_to_keyid(key),
                key=key, nick=nick, color=color, icon=None, key_hash=key_hash,
                tags=tags)

        # Ask to get notifications on Owner object property changes in the
        # shell. If it's not currently running, no problem - we'll get the
        # signals when it does run
        for (signal, cb) in (('IconChanged', self._icon_changed_cb),
                             ('ColorChanged', self._color_changed_cb),
                             ('NickChanged', self._nick_changed_cb),
                             ('TagsChanged', self._tags_changed_cb),
                             ('CurrentActivityChanged',
                              self._cur_activity_changed_cb)):
            self._bus.add_signal_receiver(cb, signal_name=signal,
                dbus_interface=self._SHELL_OWNER_INTERFACE,
                bus_name=self._SHELL_SERVICE,
                path=self._SHELL_PATH)

        # we already know our own nick, color, key
        self._awaiting = None
    def sync_friends(self, keys):
        if self._friends_channel is None or self._subscribe_channel is None:
            # not ready yet
            return

        client = gconf.client_get_default()        
        server = client.get_string("/desktop/sugar/collaboration/jabber_server")

        friends_handles = set()
        friends = set()
        for key in keys:
            identity = psutils.pubkey_to_keyid(key)
            # this assumes that all our friends are on the same server as us
            jid = '%s@%s' % (identity, server)
            friends.add(jid)

        def error_syncing_friends(e):
            _logger.debug('error syncing friends: %r' % e)

        def friends_group_synced():
            _logger.debug('friends group synced')

        def friends_subscribed():
            _logger.debug('friends subscribed')

        def got_friends_handles(handles):
            friends_handles.update(handles)

            # subscribe friends
            self._subscribe_channel[CHANNEL_INTERFACE_GROUP].AddMembers(
                friends_handles, "New friend",
                reply_handler=friends_subscribed,
                error_handler=error_syncing_friends)

            # add friends to the "Friends" group
            self._friends_channel[CHANNEL_INTERFACE_GROUP].AddMembers(
                friends_handles, "New friend",
                reply_handler=friends_group_synced,
                error_handler=error_syncing_friends)

        self._conn[CONN_INTERFACE].RequestHandles(
            HANDLE_TYPE_CONTACT, friends,
            reply_handler=got_friends_handles,
            error_handler=error_syncing_friends)
    def __init__(self, ps, bus, test_num, randomize):
        self._cp = ConfigParser()
        self._section = "Info"
        self._test_activities = []
        self._test_cur_act = ""
        self._change_timeout = 0

        self._cfg_file = os.path.join(env.get_profile_path(), 'test-buddy-%d' % test_num)

        (pubkey, privkey, registered) = self._load_config()
        if not pubkey or not len(pubkey) or not privkey or not len(privkey):
            (pubkey, privkey) = _get_new_keypair(test_num)

        if not pubkey or not privkey:
            raise RuntimeError("Couldn't get or create test buddy keypair")

        self._save_config(pubkey, privkey, registered)
        privkey_hash = util.printable_hash(util._sha_data(privkey))

        nick = _get_random_name()
        from sugar.graphics import xocolor
        color = xocolor.XoColor().to_string()
        icon = _get_random_image()

        _logger.debug("pubkey is %s" % pubkey)
        GenericOwner.__init__(self, ps, bus,
                'keyid/' + pubkey_to_keyid(pubkey),
                key=pubkey, nick=nick, color=color, icon=icon,
                registered=registered, key_hash=privkey_hash)

        # we already know our own nick, color, key
        self._awaiting = None

        # Only do the random stuff if randomize is true
        if randomize:
            self._ps.connect('connection-status', self._ps_connection_status_cb)
print "Running test_psutils..."

from psutils import escape_identifier, pubkey_to_keyid

assert pubkey_to_keyid('abc') == 'a9993e364706816aba3e25717850c26c9cd0d89d'

assert escape_identifier('') == '_'
assert escape_identifier('_') == '_5f'
assert escape_identifier('1') == '_31'
assert escape_identifier('a1') == 'a1'
assert escape_identifier('1a') == '_31a'
assert escape_identifier("0123abc_xyz\x01\xff") == '_30123abc_5fxyz_01_ff'
    def __init__(self):
        self._next_object_id = 0

        # all Buddy objects
        # identifier -> Buddy, GC'd when no more refs exist
        self._buddies = WeakValueDictionary()

        # the online buddies for whom we know the full public key
        # base64 public key -> Buddy
        self._buddies_by_pubkey = {}

        # The online buddies (those who're available via some CM)
        # TP plugin -> (handle -> Buddy)
        self._handles_buddies = {}

        # activity id -> Activity
        self._activities_by_id = {}
        #: Tp plugin -> (handle -> Activity)
        self._activities_by_handle = {}

        #: Connection -> list of SignalMatch
        self._conn_matches = {}

        self._session_bus = dbus.SessionBus()
        self._session_bus.add_signal_receiver(self._connection_disconnected_cb,
                signal_name="Disconnected",
                dbus_interface="org.freedesktop.DBus")

        # Create the Owner object
        self._owner = self._create_owner()
        key = self._owner.props.key
        keyid = pubkey_to_keyid(key)
        self._buddies['keyid/' + keyid] = self._owner
        self._buddies_by_pubkey[key] = self._owner

        self._registry = ManagerRegistry()
        self._registry.LoadManagers()

        # Set up the Telepathy plugins
        self._plugins = []
        debug_flags = set(environ.get('PRESENCE_SERVICE_DEBUG', '').split(','))
        _logger.debug('Debug flags: %r', debug_flags)
        if 'disable-gabble' in debug_flags:
            self._server_plugin = None
        else:
            server = self._owner.get_server()
            if server and len(server):
                self._server_plugin = ServerPlugin(self._registry, self._owner)
                self._plugins.append(self._server_plugin)
            else:
                self._server_plugin = None
        if 'disable-salut' in debug_flags:
            self._ll_plugin = None
        else:
            self._ll_plugin = LinkLocalPlugin(self._registry, self._owner)
            self._plugins.append(self._ll_plugin)
        self._connected_plugins = set()

        for tp in self._plugins:
            self._handles_buddies[tp] = {}
            self._activities_by_handle[tp] = {}

            tp.connect('status', self._tp_status_cb)
            tp.connect('contacts-online', self._contacts_online)
            tp.connect('contacts-offline', self._contacts_offline)
            tp.connect('activity-invitation',
                                        self._activity_invitation)
            tp.connect('private-invitation',
                                        self._private_invitation)
            tp.connect('want-to-connect', self._want_to_connect)

            connection = tp.get_connection()
            if connection is not None:
                status = connection.GetStatus()
                self._tp_status_cb(tp, status, CONNECTION_STATUS_REASON_NONE_SPECIFIED)

        self._contacts_online_queue = []

        ExportedGObject.__init__(self, self._session_bus, _PRESENCE_PATH)

        # for activation to work in a race-free way, we should really
        # export the bus name only after we export our initial object;
        # so this comes after the parent __init__
        self._bus_name = dbus.service.BusName(_PRESENCE_SERVICE,
                                              bus=self._session_bus)
    def identify_contacts(self, tp_chan, handles, identifiers=None):
        """Work out the "best" unique identifier we can for the given handles,
        in the context of the given channel (which may be None), using only
        'fast' connection manager API (that does not involve network
        round-trips).

        For the XMPP server case, we proceed as follows:

        * Find the owners of the given handles, if the channel has
          channel-specific handles
        * If the owner (globally-valid JID) is on a trusted server, return
          'keyid/' plus the 'key fingerprint' (the user part of their JID,
          currently implemented as the SHA-1 of the Base64 blob in
          owner.key.pub)
        * If the owner (globally-valid JID) cannot be found or is on an
          untrusted server, return 'xmpp/' plus an escaped form of the JID

        The idea is that we identify buddies by key-ID (i.e. by key, assuming
        no collisions) if we can find it without making network round-trips,
        but if that's not possible we just use their JIDs.

        :Parameters:
            `tp_chan` : telepathy.client.Channel or None
                The channel in which the handles were found, or None if they
                are known to be channel-specific handles
            `handles` : iterable over (int or long)
                The contacts' handles in that channel
        :Returns:
            A dict mapping the provided handles to the best available
            unique identifier, which is a string that could be used as a
            suffix to an object path
        """
        # we need to be able to index into handles, so force them to
        # be a sequence
        if not isinstance(handles, (tuple, list)):
            handles = tuple(handles)

        # we happen to know that Salut has no channel-specific handles

        if identifiers is None:
            identifiers = self._conn[CONN_INTERFACE].InspectHandles(
                HANDLE_TYPE_CONTACT, handles)

        ret = {}
        for handle, ident in izip(handles, identifiers):
            # special-case the Owner - we always know who we are
            if handle == self.self_handle:
                ret[handle] = self._owner.props.objid
                continue

            # we also happen to know that on Salut, getting properties
            # is immediate, and the key is (well, will be) trustworthy

            if CONN_INTERFACE_BUDDY_INFO in self._conn:
                props = self._conn[CONN_INTERFACE_BUDDY_INFO].GetProperties(
                    handle, byte_arrays=True, utf8_strings=True)
                key = props.get('key')
            else:
                key = None

            if key is not None:
                khash = psutils.pubkey_to_keyid(key)
                ret[handle] = 'keyid/' + khash
            else:
                ret[handle] = 'salut/' + psutils.escape_identifier(ident)

        return ret