bookmark.py 7.14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
"""
Bookmarks module

Therein the bookmark class is defined, representing one conference room.
This object is used to generate elements for both local and remote
bookmark storage. It can also parse xml Elements.

This module also defines several functions for retrieving and updating
bookmarks, both local and remote.
"""
mathieui's avatar
mathieui committed
11
import logging
mathieui's avatar
mathieui committed
12
from sys import version_info
mathieui's avatar
mathieui committed
13

mathieui's avatar
mathieui committed
14
from sleekxmpp.plugins.xep_0048 import *
15
from common import safeJID
mathieui's avatar
mathieui committed
16 17
from config import config

mathieui's avatar
mathieui committed
18 19
log = logging.getLogger(__name__)

mathieui's avatar
mathieui committed
20 21 22 23 24 25
def iter(xml, tag=''):
    if version_info[1] >= 2:
        return xml.iter(tag)
    else:
        return xml.getiterator(tag)

mathieui's avatar
mathieui committed
26 27
preferred = config.get('use_bookmarks_method', 'pep').lower()
if preferred not in ('pep', 'privatexml'):
28
    preferred = 'privatexml'
mathieui's avatar
mathieui committed
29
not_preferred = 'privatexml' if preferred == 'pep' else 'privatexml'
mathieui's avatar
mathieui committed
30 31
methods = ('local', preferred, not_preferred)

mathieui's avatar
mathieui committed
32 33

class Bookmark(object):
mathieui's avatar
mathieui committed
34 35
    possible_methods = methods

mathieui's avatar
mathieui committed
36
    def __init__(self, jid, name=None, autojoin=False, nick=None, password=None, method='privatexml'):
mathieui's avatar
mathieui committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50
        self.jid = jid
        self.name = name or jid
        self.autojoin = autojoin
        self.nick = nick
        self.password = password
        self._method = method

    @property
    def method(self):
        return self._method

    @method.setter
    def method(self, value):
        if value not in self.possible_methods:
mathieui's avatar
mathieui committed
51
            log.debug('Could not set bookmark storing method: %s', value)
mathieui's avatar
mathieui committed
52 53 54
            return
        self._method = value

mathieui's avatar
mathieui committed
55
    def __repr__(self):
mathieui's avatar
mathieui committed
56
        return '<%s%s%s>' % (self.jid, ('/'+self.nick) if self.nick else '', '|autojoin' if self.autojoin else '')
mathieui's avatar
mathieui committed
57

mathieui's avatar
mathieui committed
58 59 60 61 62 63 64 65 66
    def stanza(self):
        """
        Generate a <conference/> stanza from the instance
        """
        el = Conference()
        el['name'] = self.name
        el['jid'] = self.jid
        el['autojoin'] = 'true' if self.autojoin else 'false'
        if self.nick:
mathieui's avatar
mathieui committed
67
            el['nick'] = self.nick
mathieui's avatar
mathieui committed
68
        if self.password:
mathieui's avatar
mathieui committed
69
            el['password'] = self.password
mathieui's avatar
mathieui committed
70
        return el
71

72 73 74 75 76 77
    def local(self):
        """Generate a str for local storage"""
        local = self.jid
        if self.nick:
            local += '/%s' % self.nick
        local += ':'
78 79
        if self.password:
            config.set_and_save('password', self.password, section=self.jid)
80 81
        return local

82
    @staticmethod
83 84 85 86 87 88
    def parse_from_element(el, method=None):
        """
        Generate a Bookmark object from a <conference/> element
        """
        jid = el.get('jid')
        name = el.get('name')
louiz’'s avatar
louiz’ committed
89
        autojoin = True if el.get('autojoin', 'false').lower() in ('true', '1') else False
90
        nick = None
mathieui's avatar
mathieui committed
91
        for n in iter(el, 'nick'):
92 93
            nick = nick.text
        password = None
mathieui's avatar
mathieui committed
94
        for p in iter(el, 'password'):
95 96 97 98
            password = p.text

        return Bookmark(jid, name, autojoin, nick, password, method)

99 100
bookmarks = []

101 102 103 104 105 106 107 108 109 110
def get_by_jid(value):
    """
    Get a bookmark by bare jid
    """
    for item in bookmarks:
        if item.jid == value:
            return item

def remove(value):
    """
111
    Remove a bookmark (with its jid or directly the Bookmark object).
112 113 114 115 116
    """
    if isinstance(value, str):
        value = get_by_jid(value)
    bookmarks.remove(value)

117 118
def stanza_storage(method):
    """Generate a <storage/> stanza with the conference elements."""
mathieui's avatar
mathieui committed
119
    storage = Bookmarks()
120
    for b in filter(lambda b: b.method == method, bookmarks):
121 122 123
        storage.append(b.stanza())
    return storage

124
def save_pep(xmpp):
125
    """Save the remote bookmarks via PEP."""
mathieui's avatar
mathieui committed
126 127
    xmpp.plugin['xep_0048'].set_bookmarks(stanza_storage('pep'),
            method='xep_0223')
128 129

def save_privatexml(xmpp):
130
    """"Save the remote bookmarks with privatexml."""
mathieui's avatar
mathieui committed
131 132
    xmpp.plugin['xep_0048'].set_bookmarks(stanza_storage('privatexml'),
            method='xep_0049')
133

134
def save_remote(xmpp, method=preferred):
135 136 137 138 139
    """Save the remote bookmarks."""
    method = "privatexml" if method != 'pep'  else 'pep'

    try:
        if method is 'privatexml':
mathieui's avatar
mathieui committed
140 141
            xmpp.plugin['xep_0048'].set_bookmarks(stanza_storage('privatexml'),
                    method='xep_0049')
142
        else:
mathieui's avatar
mathieui committed
143 144
            xmpp.plugin['xep_0048'].set_bookmarks(stanza_storage('pep'),
                    method='xep_0223')
145
    except:
mathieui's avatar
mathieui committed
146 147
        import traceback
        log.debug("Could not save the bookmarks:\n%s" % traceback.format_exc())
148 149
        return False
    return True
150 151

def save_local():
152
    """Save the local bookmarks."""
mathieui's avatar
mathieui committed
153
    all = ''.join(bookmark.local() for bookmark in bookmarks if bookmark.method is 'local')
154 155 156
    config.set_and_save('rooms', all)

def save(xmpp, core=None):
157
    """Save all the bookmarks."""
158
    save_local()
159
    if config.get('use_remote_bookmarks', True):
160 161 162
        preferred = config.get('use_bookmarks_method', 'privatexml')
        if not save_remote(xmpp, method=preferred) and core:
            core.information('Could not save bookmarks.', 'Error')
mathieui's avatar
mathieui committed
163
            return False
164
        elif core:
mathieui's avatar
mathieui committed
165
            core.information('Bookmarks saved', 'Info')
166
    return True
167

168
def get_pep(xmpp):
169
    """Add the remotely stored bookmarks via pep to the list."""
170
    try:
mathieui's avatar
mathieui committed
171
        iq = xmpp.plugin['xep_0048'].get_bookmarks(method='xep_0223', block=True)
172 173
    except:
        return False
mathieui's avatar
mathieui committed
174
    for conf in iter(iq.xml, '{storage:bookmarks}conference'):
175 176 177 178 179 180
        b = Bookmark.parse_from_element(conf, method='pep')
        if not get_by_jid(b.jid):
            bookmarks.append(b)
    return True

def get_privatexml(xmpp):
181
    """Add the remotely stored bookmarks via privatexml to the list."""
182
    try:
mathieui's avatar
mathieui committed
183
        iq = xmpp.plugin['xep_0048'].get_bookmarks(method='xep_0049', block=True)
184 185
    except:
        return False
mathieui's avatar
mathieui committed
186
    for conf in iter(iq.xml, '{storage:bookmarks}conference'):
187 188 189 190 191 192
        b = Bookmark.parse_from_element(conf, method='privatexml')
        if not get_by_jid(b.jid):
            bookmarks.append(b)
    return True

def get_remote(xmpp):
193
    """Add the remotely stored bookmarks to the list."""
194 195
    if xmpp.anon:
        return
mathieui's avatar
mathieui committed
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    method = config.get('use_bookmarks_method', '')
    if not method:
        pep, privatexml = True, True
        for method in methods[1:]:
            if method == 'pep':
                pep = get_pep(xmpp)
            else:
                privatexml = get_privatexml(xmpp)
        if pep and not privatexml:
            config.set_and_save('use_bookmarks_method', 'pep')
        elif privatexml and not pep:
            config.set_and_save('use_bookmarks_method', 'privatexml')
        elif not pep and not privatexml:
            config.set_and_save('use_bookmarks_method', '')
    else:
211
        if method == 'pep':
mathieui's avatar
mathieui committed
212
            get_pep(xmpp)
213
        else:
mathieui's avatar
mathieui committed
214
            get_privatexml(xmpp)
215 216

def get_local():
217
    """Add the locally stored bookmarks to the list."""
218 219 220 221 222
    rooms = config.get('rooms', '')
    if not rooms:
        return
    rooms = rooms.split(':')
    for room in rooms:
223
        jid = safeJID(room)
224 225 226 227 228 229
        if jid.bare == '':
            continue
        if jid.resource != '':
            nick = jid.resource
        else:
            nick = None
230 231
        passwd = config.get_by_tabname('password', '', jid.bare, fallback=False) or None
        b = Bookmark(jid.bare, autojoin=True, nick=nick, password=passwd, method='local')
232 233
        if not get_by_jid(b.jid):
            bookmarks.append(b)