Refactor Privacy and Blocking into own modules
This commit is contained in:
parent
3cfd82b0c2
commit
bd79fe629f
|
@ -103,11 +103,6 @@ class CommonConnection:
|
||||||
self.priority = app.get_priority(name, 'offline')
|
self.priority = app.get_priority(name, 'offline')
|
||||||
self.time_to_reconnect = None
|
self.time_to_reconnect = None
|
||||||
|
|
||||||
self.blocked_list = []
|
|
||||||
self.blocked_contacts = []
|
|
||||||
self.blocked_groups = []
|
|
||||||
self.blocked_all = False
|
|
||||||
|
|
||||||
self.seclabel_supported = False
|
self.seclabel_supported = False
|
||||||
self.seclabel_catalogues = {}
|
self.seclabel_catalogues = {}
|
||||||
|
|
||||||
|
@ -631,8 +626,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
# Register all modules
|
# Register all modules
|
||||||
modules.register(self)
|
modules.register(self)
|
||||||
|
|
||||||
app.ged.register_event_handler('privacy-list-received', ged.CORE,
|
|
||||||
self._nec_privacy_list_received)
|
|
||||||
app.ged.register_event_handler('agent-info-error-received', ged.CORE,
|
app.ged.register_event_handler('agent-info-error-received', ged.CORE,
|
||||||
self._nec_agent_info_error_received)
|
self._nec_agent_info_error_received)
|
||||||
app.ged.register_event_handler('agent-info-received', ged.CORE,
|
app.ged.register_event_handler('agent-info-received', ged.CORE,
|
||||||
|
@ -651,8 +644,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
ConnectionHandlers.cleanup(self)
|
ConnectionHandlers.cleanup(self)
|
||||||
modules.unregister(self)
|
modules.unregister(self)
|
||||||
|
|
||||||
app.ged.remove_event_handler('privacy-list-received', ged.CORE,
|
|
||||||
self._nec_privacy_list_received)
|
|
||||||
app.ged.remove_event_handler('agent-info-error-received', ged.CORE,
|
app.ged.remove_event_handler('agent-info-error-received', ged.CORE,
|
||||||
self._nec_agent_info_error_received)
|
self._nec_agent_info_error_received)
|
||||||
app.ged.remove_event_handler('agent-info-received', ged.CORE,
|
app.ged.remove_event_handler('agent-info-received', ged.CORE,
|
||||||
|
@ -702,7 +693,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
# Do not try to reco while we are already trying
|
# Do not try to reco while we are already trying
|
||||||
self.time_to_reconnect = None
|
self.time_to_reconnect = None
|
||||||
if self.connected < 2: # connection failed
|
if self.connected < 2: # connection failed
|
||||||
log.debug('reconnect')
|
log.info('Reconnect')
|
||||||
self.connected = 1
|
self.connected = 1
|
||||||
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
|
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
|
||||||
show='connecting'))
|
show='connecting'))
|
||||||
|
@ -710,12 +701,14 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
self.on_connect_auth = self._discover_server_at_connection
|
self.on_connect_auth = self._discover_server_at_connection
|
||||||
self.connect_and_init(self.old_show, self.status, self.USE_GPG)
|
self.connect_and_init(self.old_show, self.status, self.USE_GPG)
|
||||||
else:
|
else:
|
||||||
|
log.info('Reconnect successfull')
|
||||||
# reconnect succeeded
|
# reconnect succeeded
|
||||||
self.time_to_reconnect = None
|
self.time_to_reconnect = None
|
||||||
self.retrycount = 0
|
self.retrycount = 0
|
||||||
|
|
||||||
# We are doing disconnect at so many places, better use one function in all
|
# We are doing disconnect at so many places, better use one function in all
|
||||||
def disconnect(self, on_purpose=False):
|
def disconnect(self, on_purpose=False):
|
||||||
|
log.info('Disconnect: on_purpose: %s', on_purpose)
|
||||||
app.interface.music_track_changed(None, None, self.name)
|
app.interface.music_track_changed(None, None, self.name)
|
||||||
self.get_module('PEP').reset_stored_publish()
|
self.get_module('PEP').reset_stored_publish()
|
||||||
self.on_purpose = on_purpose
|
self.on_purpose = on_purpose
|
||||||
|
@ -798,7 +791,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
# END disconnectedReconnCB
|
# END disconnectedReconnCB
|
||||||
|
|
||||||
def _connection_lost(self):
|
def _connection_lost(self):
|
||||||
log.debug('_connection_lost')
|
log.info('_connection_lost')
|
||||||
self.disconnect(on_purpose = False)
|
self.disconnect(on_purpose = False)
|
||||||
if self.removing_account:
|
if self.removing_account:
|
||||||
return
|
return
|
||||||
|
@ -882,38 +875,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
app.nec.push_incoming_event(RegisterAgentInfoReceivedEvent(
|
app.nec.push_incoming_event(RegisterAgentInfoReceivedEvent(
|
||||||
None, conn=self, agent=data[0], config=conf,
|
None, conn=self, agent=data[0], config=conf,
|
||||||
is_form=is_form))
|
is_form=is_form))
|
||||||
elif realm == nbxmpp.NS_PRIVACY:
|
|
||||||
if event == nbxmpp.features_nb.PRIVACY_LISTS_RECEIVED:
|
|
||||||
# data is (list)
|
|
||||||
app.nec.push_incoming_event(PrivacyListsReceivedEvent(None,
|
|
||||||
conn=self, lists_list=data))
|
|
||||||
elif event == nbxmpp.features_nb.PRIVACY_LIST_RECEIVED:
|
|
||||||
# data is (resp)
|
|
||||||
if not data:
|
|
||||||
return
|
|
||||||
rules = []
|
|
||||||
name = data.getTag('query').getTag('list').getAttr('name')
|
|
||||||
for child in data.getTag('query').getTag('list').getChildren():
|
|
||||||
dict_item = child.getAttrs()
|
|
||||||
childs = []
|
|
||||||
if 'type' in dict_item:
|
|
||||||
for scnd_child in child.getChildren():
|
|
||||||
childs += [scnd_child.getName()]
|
|
||||||
rules.append({'action':dict_item['action'],
|
|
||||||
'type':dict_item['type'], 'order':dict_item['order'],
|
|
||||||
'value':dict_item['value'], 'child':childs})
|
|
||||||
else:
|
|
||||||
for scnd_child in child.getChildren():
|
|
||||||
childs.append(scnd_child.getName())
|
|
||||||
rules.append({'action':dict_item['action'],
|
|
||||||
'order':dict_item['order'], 'child':childs})
|
|
||||||
app.nec.push_incoming_event(PrivacyListReceivedEvent(None,
|
|
||||||
conn=self, list_name=name, rules=rules))
|
|
||||||
elif event == nbxmpp.features_nb.PRIVACY_LISTS_ACTIVE_DEFAULT:
|
|
||||||
# data is (dict)
|
|
||||||
app.nec.push_incoming_event(PrivacyListActiveDefaultEvent(
|
|
||||||
None, conn=self, active_list=data['active'],
|
|
||||||
default_list=data['default']))
|
|
||||||
|
|
||||||
def _select_next_host(self, hosts):
|
def _select_next_host(self, hosts):
|
||||||
"""
|
"""
|
||||||
|
@ -952,6 +913,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
if self.connection:
|
if self.connection:
|
||||||
return self.connection, ''
|
return self.connection, ''
|
||||||
|
|
||||||
|
log.info('Connect')
|
||||||
if self.sm.resuming and self.sm.location:
|
if self.sm.resuming and self.sm.location:
|
||||||
# If resuming and server gave a location, connect from there
|
# If resuming and server gave a location, connect from there
|
||||||
hostname = self.sm.location
|
hostname = self.sm.location
|
||||||
|
@ -1086,7 +1048,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
app.config.set_per('proxies', p, 'type', 'bosh')
|
app.config.set_per('proxies', p, 'type', 'bosh')
|
||||||
app.config.set_per('proxies', p, 'bosh_uri', url)
|
app.config.set_per('proxies', p, 'bosh_uri', url)
|
||||||
|
|
||||||
|
|
||||||
def _connect_to_next_host(self, retry=False):
|
def _connect_to_next_host(self, retry=False):
|
||||||
log.debug('Connection to next host')
|
log.debug('Connection to next host')
|
||||||
if not self._hosts:
|
if not self._hosts:
|
||||||
|
@ -1233,6 +1194,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
if not self.connected: # We went offline during connecting process
|
if not self.connected: # We went offline during connecting process
|
||||||
# FIXME - not possible, maybe it was when we used threads
|
# FIXME - not possible, maybe it was when we used threads
|
||||||
return
|
return
|
||||||
|
log.info('Connect successfull')
|
||||||
_con_type = con_type
|
_con_type = con_type
|
||||||
if _con_type != self._current_type:
|
if _con_type != self._current_type:
|
||||||
log.info('Connecting to next host beacuse desired type is %s and returned is %s'
|
log.info('Connecting to next host beacuse desired type is %s and returned is %s'
|
||||||
|
@ -1269,6 +1231,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
msg=_('Connection with account %s has been lost. Retry '
|
msg=_('Connection with account %s has been lost. Retry '
|
||||||
'connecting.') % self.name))
|
'connecting.') % self.name))
|
||||||
return
|
return
|
||||||
|
log.info('Connection accepted')
|
||||||
self._hosts = []
|
self._hosts = []
|
||||||
self.connection_auto_accepted = False
|
self.connection_auto_accepted = False
|
||||||
self.connected_hostname = self._current_host['host']
|
self.connected_hostname = self._current_host['host']
|
||||||
|
@ -1389,6 +1352,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
'Retry connecting.') % self.name))
|
'Retry connecting.') % self.name))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
log.info('SSL Cert accepted')
|
||||||
name = None
|
name = None
|
||||||
if not app.config.get_per('accounts', self.name, 'anonymous_auth'):
|
if not app.config.get_per('accounts', self.name, 'anonymous_auth'):
|
||||||
name = app.config.get_per('accounts', self.name, 'name')
|
name = app.config.get_per('accounts', self.name, 'name')
|
||||||
|
@ -1420,6 +1384,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
ConnectionHandlers._register_handlers(self, con, con_type)
|
ConnectionHandlers._register_handlers(self, con, con_type)
|
||||||
|
|
||||||
def __on_auth(self, con, auth):
|
def __on_auth(self, con, auth):
|
||||||
|
log.info('auth')
|
||||||
if not con:
|
if not con:
|
||||||
self.disconnect(on_purpose=True)
|
self.disconnect(on_purpose=True)
|
||||||
app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self,
|
app.nec.push_incoming_event(ConnectionLostEvent(None, conn=self,
|
||||||
|
@ -1472,207 +1437,11 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
def add_lang(self, stanza):
|
def add_lang(self, stanza):
|
||||||
stanza.setAttr('xml:lang', i18n.LANG)
|
stanza.setAttr('xml:lang', i18n.LANG)
|
||||||
|
|
||||||
def get_privacy_lists(self):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
nbxmpp.features_nb.getPrivacyLists(self.connection)
|
|
||||||
|
|
||||||
def send_keepalive(self):
|
def send_keepalive(self):
|
||||||
# nothing received for the last foo seconds
|
# nothing received for the last foo seconds
|
||||||
if self.connection:
|
if self.connection:
|
||||||
self.connection.send(' ')
|
self.connection.send(' ')
|
||||||
|
|
||||||
def get_active_default_lists(self):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
nbxmpp.features_nb.getActiveAndDefaultPrivacyLists(self.connection)
|
|
||||||
|
|
||||||
def del_privacy_list(self, privacy_list):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
def _on_del_privacy_list_result(result):
|
|
||||||
if result:
|
|
||||||
app.nec.push_incoming_event(PrivacyListRemovedEvent(None,
|
|
||||||
conn=self, list_name=privacy_list))
|
|
||||||
else:
|
|
||||||
app.nec.push_incoming_event(InformationEvent(
|
|
||||||
None, dialog_name='privacy-list-error', args=privacy_list))
|
|
||||||
nbxmpp.features_nb.delPrivacyList(self.connection, privacy_list,
|
|
||||||
_on_del_privacy_list_result)
|
|
||||||
|
|
||||||
def get_privacy_list(self, title):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
nbxmpp.features_nb.getPrivacyList(self.connection, title)
|
|
||||||
|
|
||||||
def set_privacy_list(self, listname, tags):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
nbxmpp.features_nb.setPrivacyList(self.connection, listname, tags)
|
|
||||||
|
|
||||||
def set_active_list(self, listname):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
nbxmpp.features_nb.setActivePrivacyList(self.connection, listname,
|
|
||||||
'active')
|
|
||||||
|
|
||||||
def set_default_list(self, listname):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
nbxmpp.features_nb.setDefaultPrivacyList(self.connection, listname)
|
|
||||||
|
|
||||||
def build_privacy_rule(self, name, action, order=1):
|
|
||||||
"""
|
|
||||||
Build a Privacy rule stanza for invisibility
|
|
||||||
"""
|
|
||||||
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, xmlns='')
|
|
||||||
l = iq.setQuery().setTag('list', {'name': name})
|
|
||||||
i = l.setTag('item', {'action': action, 'order': str(order)})
|
|
||||||
i.setTag('presence-out')
|
|
||||||
return iq
|
|
||||||
|
|
||||||
def build_invisible_rule(self):
|
|
||||||
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, xmlns='')
|
|
||||||
l = iq.setQuery().setTag('list', {'name': 'invisible'})
|
|
||||||
if self.name in app.interface.status_sent_to_groups and \
|
|
||||||
len(app.interface.status_sent_to_groups[self.name]) > 0:
|
|
||||||
for group in app.interface.status_sent_to_groups[self.name]:
|
|
||||||
i = l.setTag('item', {'type': 'group', 'value': group,
|
|
||||||
'action': 'allow', 'order': '1'})
|
|
||||||
i.setTag('presence-out')
|
|
||||||
if self.name in app.interface.status_sent_to_users and \
|
|
||||||
len(app.interface.status_sent_to_users[self.name]) > 0:
|
|
||||||
for jid in app.interface.status_sent_to_users[self.name]:
|
|
||||||
i = l.setTag('item', {'type': 'jid', 'value': jid,
|
|
||||||
'action': 'allow', 'order': '2'})
|
|
||||||
i.setTag('presence-out')
|
|
||||||
i = l.setTag('item', {'action': 'deny', 'order': '3'})
|
|
||||||
i.setTag('presence-out')
|
|
||||||
return iq
|
|
||||||
|
|
||||||
def set_invisible_rule(self):
|
|
||||||
if not app.account_is_connected(self.name):
|
|
||||||
return
|
|
||||||
iq = self.build_invisible_rule()
|
|
||||||
self.connection.send(iq)
|
|
||||||
|
|
||||||
def get_max_blocked_list_order(self):
|
|
||||||
max_order = 0
|
|
||||||
for rule in self.blocked_list:
|
|
||||||
order = int(rule['order'])
|
|
||||||
if order > max_order:
|
|
||||||
max_order = order
|
|
||||||
return max_order
|
|
||||||
|
|
||||||
def block_contacts(self, contact_list, message):
|
|
||||||
if self.privacy_default_list is None:
|
|
||||||
self.privacy_default_list = 'block'
|
|
||||||
if not self.privacy_rules_supported:
|
|
||||||
if self.blocking_supported: #XEP-0191
|
|
||||||
iq = nbxmpp.Iq('set', xmlns='')
|
|
||||||
query = iq.setQuery(name='block')
|
|
||||||
query.setNamespace(nbxmpp.NS_BLOCKING)
|
|
||||||
for contact in contact_list:
|
|
||||||
query.addChild(name='item', attrs={'jid': contact.jid})
|
|
||||||
self.connection.send(iq)
|
|
||||||
return
|
|
||||||
for contact in contact_list:
|
|
||||||
contact.show = 'offline'
|
|
||||||
self.send_custom_status('offline', message, contact.jid)
|
|
||||||
max_order = self.get_max_blocked_list_order()
|
|
||||||
new_rule = {'order': str(max_order + 1),
|
|
||||||
'type': 'jid',
|
|
||||||
'action': 'deny',
|
|
||||||
'value': contact.jid}
|
|
||||||
self.blocked_list.append(new_rule)
|
|
||||||
self.blocked_contacts.append(contact.jid)
|
|
||||||
self.set_privacy_list(self.privacy_default_list, self.blocked_list)
|
|
||||||
if len(self.blocked_list) == 1:
|
|
||||||
self.set_default_list(self.privacy_default_list)
|
|
||||||
|
|
||||||
def unblock_contacts(self, contact_list):
|
|
||||||
if not self.privacy_rules_supported:
|
|
||||||
if self.blocking_supported: #XEP-0191
|
|
||||||
iq = nbxmpp.Iq('set', xmlns='')
|
|
||||||
query = iq.setQuery(name='unblock')
|
|
||||||
query.setNamespace(nbxmpp.NS_BLOCKING)
|
|
||||||
for contact in contact_list:
|
|
||||||
query.addChild(name='item', attrs={'jid': contact.jid})
|
|
||||||
self.connection.send(iq)
|
|
||||||
return
|
|
||||||
self.new_blocked_list = []
|
|
||||||
self.to_unblock = []
|
|
||||||
for contact in contact_list:
|
|
||||||
self.to_unblock.append(contact.jid)
|
|
||||||
if contact.jid in self.blocked_contacts:
|
|
||||||
self.blocked_contacts.remove(contact.jid)
|
|
||||||
for rule in self.blocked_list:
|
|
||||||
if rule['action'] != 'deny' or rule['type'] != 'jid' \
|
|
||||||
or rule['value'] not in self.to_unblock:
|
|
||||||
self.new_blocked_list.append(rule)
|
|
||||||
if len(self.new_blocked_list) == 0:
|
|
||||||
self.blocked_list = []
|
|
||||||
self.blocked_contacts = []
|
|
||||||
self.blocked_groups = []
|
|
||||||
self.set_default_list('')
|
|
||||||
self.del_privacy_list(self.privacy_default_list)
|
|
||||||
else:
|
|
||||||
self.set_privacy_list(self.privacy_default_list, self.new_blocked_list)
|
|
||||||
if not app.interface.roster.regroup:
|
|
||||||
show = app.SHOW_LIST[self.connected]
|
|
||||||
else: # accounts merged
|
|
||||||
show = helpers.get_global_show()
|
|
||||||
if show == 'invisible':
|
|
||||||
return
|
|
||||||
for contact in contact_list:
|
|
||||||
self.send_custom_status(show, self.status, contact.jid)
|
|
||||||
# Send a presence Probe to get the current Status
|
|
||||||
probe = nbxmpp.Presence(contact.jid, 'probe', frm=self.get_own_jid())
|
|
||||||
self.connection.send(probe)
|
|
||||||
|
|
||||||
def block_group(self, group, contact_list, message):
|
|
||||||
if not self.privacy_rules_supported:
|
|
||||||
return
|
|
||||||
self.blocked_groups.append(group)
|
|
||||||
for contact in contact_list:
|
|
||||||
self.send_custom_status('offline', message, contact.jid)
|
|
||||||
max_order = self.get_max_blocked_list_order()
|
|
||||||
new_rule = {'order': str(max_order + 1),
|
|
||||||
'type': 'group',
|
|
||||||
'action': 'deny',
|
|
||||||
'value': group}
|
|
||||||
self.blocked_list.append(new_rule)
|
|
||||||
self.set_privacy_list(self.privacy_default_list, self.blocked_list)
|
|
||||||
if len(self.blocked_list) == 1:
|
|
||||||
self.set_default_list(self.privacy_default_list)
|
|
||||||
|
|
||||||
def unblock_group(self, group, contact_list):
|
|
||||||
if not self.privacy_rules_supported:
|
|
||||||
return
|
|
||||||
if group in self.blocked_groups:
|
|
||||||
self.blocked_groups.remove(group)
|
|
||||||
self.new_blocked_list = []
|
|
||||||
for rule in self.blocked_list:
|
|
||||||
if rule['action'] != 'deny' or rule['type'] != 'group' or \
|
|
||||||
rule['value'] != group:
|
|
||||||
self.new_blocked_list.append(rule)
|
|
||||||
if len(self.new_blocked_list) == 0:
|
|
||||||
self.blocked_list = []
|
|
||||||
self.blocked_contacts = []
|
|
||||||
self.blocked_groups = []
|
|
||||||
self.set_default_list('')
|
|
||||||
self.del_privacy_list(self.privacy_default_list)
|
|
||||||
else:
|
|
||||||
self.set_privacy_list(self.privacy_default_list, self.new_blocked_list)
|
|
||||||
if not app.interface.roster.regroup:
|
|
||||||
show = app.SHOW_LIST[self.connected]
|
|
||||||
else: # accounts merged
|
|
||||||
show = helpers.get_global_show()
|
|
||||||
if show == 'invisible':
|
|
||||||
return
|
|
||||||
for contact in contact_list:
|
|
||||||
self.send_custom_status(show, self.status, contact.jid)
|
|
||||||
|
|
||||||
def send_invisible_presence(self, msg, signed, initial = False):
|
def send_invisible_presence(self, msg, signed, initial = False):
|
||||||
if not app.account_is_connected(self.name):
|
if not app.account_is_connected(self.name):
|
||||||
return
|
return
|
||||||
|
@ -1694,15 +1463,17 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
self.connection.send(p)
|
self.connection.send(p)
|
||||||
|
|
||||||
# try to set the privacy rule
|
# try to set the privacy rule
|
||||||
iq = self.build_invisible_rule()
|
iq = self.get_module('PrivacyLists').set_invisible_rule(
|
||||||
self.connection.SendAndCallForResponse(iq, self._continue_invisible,
|
callback=self._continue_invisible,
|
||||||
{'msg': msg, 'signed': signed, 'initial': initial})
|
msg=msg,
|
||||||
|
signed=signed,
|
||||||
|
initial=initial)
|
||||||
|
|
||||||
def _continue_invisible(self, con, iq_obj, msg, signed, initial):
|
def _continue_invisible(self, con, iq_obj, msg, signed, initial):
|
||||||
if iq_obj.getType() == 'error': # server doesn't support privacy lists
|
if iq_obj.getType() == 'error': # server doesn't support privacy lists
|
||||||
return
|
return
|
||||||
# active the privacy rule
|
# active the privacy rule
|
||||||
self.set_active_list('invisible')
|
self.get_module('PrivacyLists').set_active_list('invisible')
|
||||||
self.connected = app.SHOW_LIST.index('invisible')
|
self.connected = app.SHOW_LIST.index('invisible')
|
||||||
self.status = msg
|
self.status = msg
|
||||||
priority = app.get_priority(self.name, 'invisible')
|
priority = app.get_priority(self.name, 'invisible')
|
||||||
|
@ -1777,42 +1548,35 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
if len(result_array) != 0:
|
if len(result_array) != 0:
|
||||||
self._stun_servers = self._hosts = [i for i in result_array]
|
self._stun_servers = self._hosts = [i for i in result_array]
|
||||||
|
|
||||||
def _request_privacy(self):
|
|
||||||
if not app.account_is_connected(self.name) or not self.connection:
|
|
||||||
return
|
|
||||||
iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVACY, xmlns='')
|
|
||||||
id_ = self.connection.getAnID()
|
|
||||||
iq.setID(id_)
|
|
||||||
self.awaiting_answers[id_] = (PRIVACY_ARRIVED, )
|
|
||||||
self.connection.send(iq)
|
|
||||||
|
|
||||||
def _request_blocking(self):
|
|
||||||
if not app.account_is_connected(self.name) or not self.connection:
|
|
||||||
return
|
|
||||||
iq = nbxmpp.Iq('get', xmlns=None)
|
|
||||||
iq.setQuery('blocklist').setNamespace(nbxmpp.NS_BLOCKING)
|
|
||||||
self.connection.send(iq)
|
|
||||||
|
|
||||||
def _continue_connection_request_privacy(self):
|
def _continue_connection_request_privacy(self):
|
||||||
if self.privacy_rules_supported:
|
if self.privacy_rules_supported:
|
||||||
if not self.privacy_rules_requested:
|
if not self.privacy_rules_requested:
|
||||||
self.privacy_rules_requested = True
|
self.privacy_rules_requested = True
|
||||||
self._request_privacy()
|
self.get_module('PrivacyLists').get_privacy_lists(
|
||||||
|
self._received_privacy)
|
||||||
else:
|
else:
|
||||||
if self.continue_connect_info and self.continue_connect_info[0]\
|
# Privacy lists not supported
|
||||||
== 'invisible':
|
log.info('Privacy Lists not supported')
|
||||||
|
self._received_privacy(False)
|
||||||
|
|
||||||
|
def _received_privacy(self, result):
|
||||||
|
if not result:
|
||||||
|
if (self.continue_connect_info and
|
||||||
|
self.continue_connect_info[0] == 'invisible'):
|
||||||
# Trying to login as invisible but privacy list not
|
# Trying to login as invisible but privacy list not
|
||||||
# supported
|
# supported
|
||||||
self.disconnect(on_purpose=True)
|
self.disconnect(on_purpose=True)
|
||||||
app.nec.push_incoming_event(OurShowEvent(None, conn=self,
|
app.nec.push_incoming_event(OurShowEvent(
|
||||||
show='offline'))
|
None, conn=self, show='offline'))
|
||||||
app.nec.push_incoming_event(InformationEvent(
|
app.nec.push_incoming_event(InformationEvent(
|
||||||
None, dialog_name='invisibility-not-supported', args=self.name))
|
None, dialog_name='invisibility-not-supported',
|
||||||
|
args=self.name))
|
||||||
return
|
return
|
||||||
if self.blocking_supported:
|
if self.blocking_supported:
|
||||||
self._request_blocking()
|
self.get_module('Blocking').get_blocking_list()
|
||||||
# Ask metacontacts before roster
|
|
||||||
self.get_metacontacts()
|
# Ask metacontacts before roster
|
||||||
|
self.get_metacontacts()
|
||||||
|
|
||||||
def _nec_agent_info_error_received(self, obj):
|
def _nec_agent_info_error_received(self, obj):
|
||||||
if obj.conn.name != self.name:
|
if obj.conn.name != self.name:
|
||||||
|
@ -1937,7 +1701,7 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
|
|
||||||
def _change_from_invisible(self):
|
def _change_from_invisible(self):
|
||||||
if self.privacy_rules_supported:
|
if self.privacy_rules_supported:
|
||||||
self.set_active_list('')
|
self.get_module('PrivacyLists').set_active_list(None)
|
||||||
|
|
||||||
def _update_status(self, show, msg, idle_time=None):
|
def _update_status(self, show, msg, idle_time=None):
|
||||||
xmpp_show = helpers.get_xmpp_show(show)
|
xmpp_show = helpers.get_xmpp_show(show)
|
||||||
|
@ -2156,43 +1920,6 @@ class Connection(CommonConnection, ConnectionHandlers):
|
||||||
iq2.setAttr('to', to)
|
iq2.setAttr('to', to)
|
||||||
self.connection.send(iq)
|
self.connection.send(iq)
|
||||||
|
|
||||||
def _nec_privacy_list_received(self, obj):
|
|
||||||
roster = app.interface.roster
|
|
||||||
if obj.conn.name != self.name:
|
|
||||||
return
|
|
||||||
if obj.list_name != self.privacy_default_list:
|
|
||||||
return
|
|
||||||
self.blocked_contacts = []
|
|
||||||
self.blocked_groups = []
|
|
||||||
self.blocked_list = []
|
|
||||||
self.blocked_all = False
|
|
||||||
for rule in obj.rules:
|
|
||||||
if rule['action'] == 'allow':
|
|
||||||
if not 'type' in rule:
|
|
||||||
self.blocked_all = False
|
|
||||||
elif rule['type'] == 'jid' and rule['value'] in \
|
|
||||||
self.blocked_contacts:
|
|
||||||
self.blocked_contacts.remove(rule['value'])
|
|
||||||
elif rule['type'] == 'group' and rule['value'] in \
|
|
||||||
self.blocked_groups:
|
|
||||||
self.blocked_groups.remove(rule['value'])
|
|
||||||
elif rule['action'] == 'deny':
|
|
||||||
if not 'type' in rule:
|
|
||||||
self.blocked_all = True
|
|
||||||
elif rule['type'] == 'jid' and rule['value'] not in \
|
|
||||||
self.blocked_contacts:
|
|
||||||
self.blocked_contacts.append(rule['value'])
|
|
||||||
elif rule['type'] == 'group' and rule['value'] not in \
|
|
||||||
self.blocked_groups:
|
|
||||||
self.blocked_groups.append(rule['value'])
|
|
||||||
self.blocked_list.append(rule)
|
|
||||||
|
|
||||||
if 'type' in rule:
|
|
||||||
if rule['type'] == 'jid':
|
|
||||||
roster.draw_contact(rule['value'], self.name)
|
|
||||||
if rule['type'] == 'group':
|
|
||||||
roster.draw_group(rule['value'], self.name)
|
|
||||||
|
|
||||||
def bookmarks_available(self):
|
def bookmarks_available(self):
|
||||||
if self.private_storage_supported:
|
if self.private_storage_supported:
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -771,8 +771,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
|
|
||||||
self.continue_connect_info = None
|
self.continue_connect_info = None
|
||||||
|
|
||||||
self.privacy_default_list = None
|
|
||||||
|
|
||||||
app.nec.register_incoming_event(StreamConflictReceivedEvent)
|
app.nec.register_incoming_event(StreamConflictReceivedEvent)
|
||||||
app.nec.register_incoming_event(MessageReceivedEvent)
|
app.nec.register_incoming_event(MessageReceivedEvent)
|
||||||
app.nec.register_incoming_event(ArchivingErrorReceivedEvent)
|
app.nec.register_incoming_event(ArchivingErrorReceivedEvent)
|
||||||
|
@ -798,8 +796,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
ged.POSTGUI, self._nec_unsubscribed_presence_received_end)
|
ged.POSTGUI, self._nec_unsubscribed_presence_received_end)
|
||||||
app.ged.register_event_handler('agent-removed', ged.CORE,
|
app.ged.register_event_handler('agent-removed', ged.CORE,
|
||||||
self._nec_agent_removed)
|
self._nec_agent_removed)
|
||||||
app.ged.register_event_handler('blocking', ged.CORE,
|
|
||||||
self._nec_blocking)
|
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
ConnectionHandlersBase.cleanup(self)
|
ConnectionHandlersBase.cleanup(self)
|
||||||
|
@ -823,7 +819,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
ged.POSTGUI, self._nec_unsubscribed_presence_received_end)
|
ged.POSTGUI, self._nec_unsubscribed_presence_received_end)
|
||||||
app.ged.remove_event_handler('agent-removed', ged.CORE,
|
app.ged.remove_event_handler('agent-removed', ged.CORE,
|
||||||
self._nec_agent_removed)
|
self._nec_agent_removed)
|
||||||
app.ged.remove_event_handler('blocking', ged.CORE, self._nec_blocking)
|
|
||||||
|
|
||||||
def add_sha(self, p, send_caps=True):
|
def add_sha(self, p, send_caps=True):
|
||||||
p = self.get_module('VCardAvatars').add_update_node(p)
|
p = self.get_module('VCardAvatars').add_update_node(p)
|
||||||
|
@ -912,21 +907,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
conn=self))
|
conn=self))
|
||||||
GLib.timeout_add_seconds(10, self.discover_servers)
|
GLib.timeout_add_seconds(10, self.discover_servers)
|
||||||
del self.awaiting_answers[id_]
|
del self.awaiting_answers[id_]
|
||||||
elif self.awaiting_answers[id_][0] == PRIVACY_ARRIVED:
|
|
||||||
del self.awaiting_answers[id_]
|
|
||||||
if iq_obj.getType() != 'error':
|
|
||||||
for list_ in iq_obj.getQueryPayload():
|
|
||||||
if list_.getName() == 'default':
|
|
||||||
self.privacy_default_list = list_.getAttr('name')
|
|
||||||
self.get_privacy_list(self.privacy_default_list)
|
|
||||||
break
|
|
||||||
# Ask metacontacts before roster
|
|
||||||
self.get_metacontacts()
|
|
||||||
else:
|
|
||||||
# That should never happen, but as it's blocking in the
|
|
||||||
# connection process, we don't take the risk
|
|
||||||
self.privacy_rules_supported = False
|
|
||||||
self._continue_connection_request_privacy()
|
|
||||||
|
|
||||||
def _nec_iq_error_received(self, obj):
|
def _nec_iq_error_received(self, obj):
|
||||||
if obj.conn.name != self.name:
|
if obj.conn.name != self.name:
|
||||||
|
@ -1181,27 +1161,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
app.nec.push_incoming_event(MucAdminReceivedEvent(None, conn=self,
|
app.nec.push_incoming_event(MucAdminReceivedEvent(None, conn=self,
|
||||||
stanza=iq_obj))
|
stanza=iq_obj))
|
||||||
|
|
||||||
def _PrivacySetCB(self, con, iq_obj):
|
|
||||||
"""
|
|
||||||
Privacy lists (XEP 016)
|
|
||||||
|
|
||||||
A list has been set.
|
|
||||||
"""
|
|
||||||
log.debug('PrivacySetCB')
|
|
||||||
if not self.connection or self.connected < 2:
|
|
||||||
return
|
|
||||||
result = iq_obj.buildReply('result')
|
|
||||||
q = result.getTag('query')
|
|
||||||
if q:
|
|
||||||
result.delChild(q)
|
|
||||||
self.connection.send(result)
|
|
||||||
|
|
||||||
for list_ in iq_obj.getQueryPayload():
|
|
||||||
if list_.getName() == 'list':
|
|
||||||
self.get_privacy_list(list_.getAttr('name'))
|
|
||||||
|
|
||||||
raise nbxmpp.NodeProcessed
|
|
||||||
|
|
||||||
def _getRoster(self):
|
def _getRoster(self):
|
||||||
log.debug('getRosterCB')
|
log.debug('getRosterCB')
|
||||||
if not self.connection:
|
if not self.connection:
|
||||||
|
@ -1342,42 +1301,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
jid_from = helpers.get_full_jid_from_iq(iq_obj)
|
jid_from = helpers.get_full_jid_from_iq(iq_obj)
|
||||||
jingle_xtls.handle_new_cert(con, iq_obj, jid_from)
|
jingle_xtls.handle_new_cert(con, iq_obj, jid_from)
|
||||||
|
|
||||||
def _BlockingSetCB(self, con, iq_obj):
|
|
||||||
log.debug('_BlockingSetCB')
|
|
||||||
app.nec.push_incoming_event(
|
|
||||||
BlockingEvent(None, conn=self, stanza=iq_obj))
|
|
||||||
reply = nbxmpp.Iq(typ='result', attrs={'id': iq_obj.getID()},
|
|
||||||
to=iq_obj.getFrom(), frm=iq_obj.getTo(), xmlns=None)
|
|
||||||
self.connection.send(reply)
|
|
||||||
raise nbxmpp.NodeProcessed
|
|
||||||
|
|
||||||
def _BlockingResultCB(self, con, iq_obj):
|
|
||||||
log.debug('_BlockingResultCB')
|
|
||||||
app.nec.push_incoming_event(
|
|
||||||
BlockingEvent(None, conn=self, stanza=iq_obj))
|
|
||||||
raise nbxmpp.NodeProcessed
|
|
||||||
|
|
||||||
def _nec_blocking(self, obj):
|
|
||||||
if obj.conn.name != self.name:
|
|
||||||
return
|
|
||||||
if obj.unblock_all:
|
|
||||||
self.blocked_contacts = []
|
|
||||||
elif obj.blocklist:
|
|
||||||
self.blocked_contacts = obj.blocklist
|
|
||||||
else:
|
|
||||||
for jid in obj.blocked_jids:
|
|
||||||
if jid not in self.blocked_contacts:
|
|
||||||
self.blocked_contacts.append(jid)
|
|
||||||
contact_list = app.contacts.get_contacts(self.name, jid)
|
|
||||||
for contact in contact_list:
|
|
||||||
contact.show = 'offline'
|
|
||||||
for jid in obj.unblocked_jids:
|
|
||||||
if jid in self.blocked_contacts:
|
|
||||||
self.blocked_contacts.remove(jid)
|
|
||||||
# Send a presence Probe to get the current Status
|
|
||||||
probe = nbxmpp.Presence(jid, 'probe', frm=self.get_own_jid())
|
|
||||||
self.connection.send(probe)
|
|
||||||
|
|
||||||
def _StreamCB(self, con, obj):
|
def _StreamCB(self, con, obj):
|
||||||
log.debug('StreamCB')
|
log.debug('StreamCB')
|
||||||
app.nec.push_incoming_event(StreamReceivedEvent(None,
|
app.nec.push_incoming_event(StreamReceivedEvent(None,
|
||||||
|
@ -1422,7 +1345,7 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
nbxmpp.NS_DISCO_INFO)
|
nbxmpp.NS_DISCO_INFO)
|
||||||
con.RegisterHandler('iq', self._DiscoverItemsGetCB, 'get',
|
con.RegisterHandler('iq', self._DiscoverItemsGetCB, 'get',
|
||||||
nbxmpp.NS_DISCO_ITEMS)
|
nbxmpp.NS_DISCO_ITEMS)
|
||||||
con.RegisterHandler('iq', self._PrivacySetCB, 'set', nbxmpp.NS_PRIVACY)
|
|
||||||
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM_1)
|
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM_1)
|
||||||
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM_2)
|
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_MAM_2)
|
||||||
con.RegisterHandler('iq', self._JingleCB, 'result')
|
con.RegisterHandler('iq', self._JingleCB, 'result')
|
||||||
|
@ -1437,10 +1360,6 @@ ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
|
||||||
nbxmpp.NS_PUBKEY_PUBKEY)
|
nbxmpp.NS_PUBKEY_PUBKEY)
|
||||||
con.RegisterHandler('iq', self._PubkeyResultCB, 'result',
|
con.RegisterHandler('iq', self._PubkeyResultCB, 'result',
|
||||||
nbxmpp.NS_PUBKEY_PUBKEY)
|
nbxmpp.NS_PUBKEY_PUBKEY)
|
||||||
con.RegisterHandler('iq', self._BlockingSetCB, 'set',
|
|
||||||
nbxmpp.NS_BLOCKING)
|
|
||||||
con.RegisterHandler('iq', self._BlockingResultCB, 'result',
|
|
||||||
nbxmpp.NS_BLOCKING)
|
|
||||||
|
|
||||||
for handler in modules.get_handlers(self):
|
for handler in modules.get_handlers(self):
|
||||||
con.RegisterHandler(*handler)
|
con.RegisterHandler(*handler)
|
||||||
|
|
|
@ -1759,22 +1759,6 @@ class UniqueRoomIdNotSupportedEvent(nec.NetworkIncomingEvent):
|
||||||
name = 'unique-room-id-not-supported'
|
name = 'unique-room-id-not-supported'
|
||||||
base_network_events = []
|
base_network_events = []
|
||||||
|
|
||||||
class PrivacyListsReceivedEvent(nec.NetworkIncomingEvent):
|
|
||||||
name = 'privacy-lists-received'
|
|
||||||
base_network_events = []
|
|
||||||
|
|
||||||
class PrivacyListReceivedEvent(nec.NetworkIncomingEvent):
|
|
||||||
name = 'privacy-list-received'
|
|
||||||
base_network_events = []
|
|
||||||
|
|
||||||
class PrivacyListRemovedEvent(nec.NetworkIncomingEvent):
|
|
||||||
name = 'privacy-list-removed'
|
|
||||||
base_network_events = []
|
|
||||||
|
|
||||||
class PrivacyListActiveDefaultEvent(nec.NetworkIncomingEvent):
|
|
||||||
name = 'privacy-list-active-default'
|
|
||||||
base_network_events = []
|
|
||||||
|
|
||||||
class NonAnonymousServerErrorEvent(nec.NetworkIncomingEvent):
|
class NonAnonymousServerErrorEvent(nec.NetworkIncomingEvent):
|
||||||
name = 'non-anonymous-server-error'
|
name = 'non-anonymous-server-error'
|
||||||
base_network_events = []
|
base_network_events = []
|
||||||
|
@ -2479,43 +2463,3 @@ class InformationEvent(nec.NetworkIncomingEvent):
|
||||||
else:
|
else:
|
||||||
self.args = (self.args,)
|
self.args = (self.args,)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
class BlockingEvent(nec.NetworkIncomingEvent):
|
|
||||||
name = 'blocking'
|
|
||||||
base_network_events = []
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
self.blocklist = []
|
|
||||||
self.blocked_jids = []
|
|
||||||
self.unblocked_jids = []
|
|
||||||
self.unblock_all = False
|
|
||||||
|
|
||||||
def generate(self):
|
|
||||||
block_list = self.stanza.getTag(
|
|
||||||
'blocklist', namespace=nbxmpp.NS_BLOCKING)
|
|
||||||
if block_list is not None:
|
|
||||||
for item in block_list.getTags('item'):
|
|
||||||
self.blocklist.append(item.getAttr('jid'))
|
|
||||||
app.log('blocking').info(
|
|
||||||
'Blocklist Received: %s', self.blocklist)
|
|
||||||
return True
|
|
||||||
|
|
||||||
block_tag = self.stanza.getTag('block', namespace=nbxmpp.NS_BLOCKING)
|
|
||||||
if block_tag is not None:
|
|
||||||
for item in block_tag.getTags('item'):
|
|
||||||
self.blocked_jids.append(item.getAttr('jid'))
|
|
||||||
app.log('blocking').info(
|
|
||||||
'Blocking Push - blocked JIDs: %s', self.blocked_jids)
|
|
||||||
|
|
||||||
unblock_tag = self.stanza.getTag(
|
|
||||||
'unblock', namespace=nbxmpp.NS_BLOCKING)
|
|
||||||
if unblock_tag is not None:
|
|
||||||
if not unblock_tag.getTags('item'):
|
|
||||||
self.unblock_all = True
|
|
||||||
app.log('blocking').info('Blocking Push - unblocked all')
|
|
||||||
return True
|
|
||||||
for item in unblock_tag.getTags('item'):
|
|
||||||
self.unblocked_jids.append(item.getAttr('jid'))
|
|
||||||
app.log('blocking').info(
|
|
||||||
'Blocking Push - unblocked JIDs: %s', self.unblocked_jids)
|
|
||||||
return True
|
|
||||||
|
|
|
@ -1385,12 +1385,15 @@ def update_optional_features(account = None):
|
||||||
app.connections[a].status)
|
app.connections[a].status)
|
||||||
|
|
||||||
def jid_is_blocked(account, jid):
|
def jid_is_blocked(account, jid):
|
||||||
return ((jid in app.connections[account].blocked_contacts) or \
|
con = app.connections[account]
|
||||||
app.connections[account].blocked_all)
|
return (jid in con.get_module('Blocking').blocked or
|
||||||
|
jid in con.get_module('PrivacyLists').blocked_contacts or
|
||||||
|
con.get_module('PrivacyLists').blocked_all)
|
||||||
|
|
||||||
def group_is_blocked(account, group):
|
def group_is_blocked(account, group):
|
||||||
return ((group in app.connections[account].blocked_groups) or \
|
con = app.connections[account]
|
||||||
app.connections[account].blocked_all)
|
return (group in con.get_module('PrivacyLists').blocked_groups or
|
||||||
|
con.get_module('PrivacyLists').blocked_all)
|
||||||
|
|
||||||
def get_subscription_request_msg(account=None):
|
def get_subscription_request_msg(account=None):
|
||||||
s = app.config.get_per('accounts', account, 'subscription_request_msg')
|
s = app.config.get_per('accounts', account, 'subscription_request_msg')
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
# This file is part of Gajim.
|
||||||
|
#
|
||||||
|
# Gajim 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; version 3 only.
|
||||||
|
#
|
||||||
|
# Gajim 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 Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# XEP-0191: Blocking Command
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import nbxmpp
|
||||||
|
|
||||||
|
from gajim.common import app
|
||||||
|
from gajim.common.nec import NetworkIncomingEvent
|
||||||
|
|
||||||
|
log = logging.getLogger('gajim.c.m.blocking')
|
||||||
|
|
||||||
|
|
||||||
|
class Blocking:
|
||||||
|
def __init__(self, con):
|
||||||
|
self._con = con
|
||||||
|
self._account = con.name
|
||||||
|
|
||||||
|
self.blocked = []
|
||||||
|
|
||||||
|
self.handlers = [
|
||||||
|
('iq', self._blocking_push_received, 'set', nbxmpp.NS_BLOCKING)
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_blocking_list(self):
|
||||||
|
iq = nbxmpp.Iq('get', nbxmpp.NS_BLOCKING)
|
||||||
|
iq.setQuery('blocklist')
|
||||||
|
log.info('Request list')
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._blocking_list_received)
|
||||||
|
|
||||||
|
def _blocking_list_received(self, stanza):
|
||||||
|
if not nbxmpp.isResultNode(stanza):
|
||||||
|
log.info('Error: %s', stanza.getError())
|
||||||
|
return
|
||||||
|
|
||||||
|
self.blocked = []
|
||||||
|
blocklist = stanza.getTag('blocklist', namespace=nbxmpp.NS_BLOCKING)
|
||||||
|
if blocklist is None:
|
||||||
|
log.error('No blocklist node')
|
||||||
|
return
|
||||||
|
|
||||||
|
for item in blocklist.getTags('item'):
|
||||||
|
self.blocked.append(item.getAttr('jid'))
|
||||||
|
log.info('Received list: %s', self.blocked)
|
||||||
|
|
||||||
|
app.nec.push_incoming_event(
|
||||||
|
BlockingEvent(None, conn=self._con, changed=self.blocked))
|
||||||
|
|
||||||
|
def _blocking_push_received(self, conn, stanza):
|
||||||
|
reply = stanza.buildReply('result')
|
||||||
|
childs = reply.getChildren()
|
||||||
|
for child in childs:
|
||||||
|
reply.delChild(child)
|
||||||
|
self._con.connection.send(reply)
|
||||||
|
|
||||||
|
changed_list = []
|
||||||
|
|
||||||
|
unblock = stanza.getTag('unblock', namespace=nbxmpp.NS_BLOCKING)
|
||||||
|
if unblock is not None:
|
||||||
|
items = unblock.getTags('item')
|
||||||
|
if not items:
|
||||||
|
# Unblock all
|
||||||
|
changed_list = list(self.blocked)
|
||||||
|
self.blocked = []
|
||||||
|
for jid in self.blocked:
|
||||||
|
self._presence_probe(jid)
|
||||||
|
log.info('Unblock all Push')
|
||||||
|
return
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
# Unblock some contacts
|
||||||
|
jid = item.getAttr('jid')
|
||||||
|
changed_list.append(jid)
|
||||||
|
if jid not in self.blocked:
|
||||||
|
continue
|
||||||
|
self.blocked.remove(jid)
|
||||||
|
self._presence_probe(jid)
|
||||||
|
log.info('Unblock Push: %s', jid)
|
||||||
|
|
||||||
|
block = stanza.getTag('block', namespace=nbxmpp.NS_BLOCKING)
|
||||||
|
if block is not None:
|
||||||
|
for item in block.getTags('item'):
|
||||||
|
jid = item.getAttr('jid')
|
||||||
|
if jid in self.blocked:
|
||||||
|
continue
|
||||||
|
changed_list.append(jid)
|
||||||
|
self.blocked.append(jid)
|
||||||
|
self._set_contact_offline(jid)
|
||||||
|
log.info('Block Push: %s', jid)
|
||||||
|
|
||||||
|
app.nec.push_incoming_event(
|
||||||
|
BlockingEvent(None, conn=self._con, changed=changed_list))
|
||||||
|
|
||||||
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
|
def _set_contact_offline(self, jid):
|
||||||
|
contact_list = app.contacts.get_contacts(self._account, jid)
|
||||||
|
for contact in contact_list:
|
||||||
|
contact.show = 'offline'
|
||||||
|
|
||||||
|
def _presence_probe(self, jid):
|
||||||
|
log.info('Presence probe: %s', jid)
|
||||||
|
# Send a presence Probe to get the current Status
|
||||||
|
probe = nbxmpp.Presence(jid, 'probe', frm=self._con.get_own_jid())
|
||||||
|
self._con.connection.send(probe)
|
||||||
|
|
||||||
|
def block(self, contact_list):
|
||||||
|
if not self._con.blocking_supported:
|
||||||
|
return
|
||||||
|
iq = nbxmpp.Iq('set', nbxmpp.NS_BLOCKING)
|
||||||
|
query = iq.setQuery(name='block')
|
||||||
|
|
||||||
|
for contact in contact_list:
|
||||||
|
query.addChild(name='item', attrs={'jid': contact.jid})
|
||||||
|
log.info('Block: %s', contact.jid)
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._default_result_handler, {})
|
||||||
|
|
||||||
|
def unblock(self, contact_list):
|
||||||
|
if not self._con.blocking_supported:
|
||||||
|
return
|
||||||
|
iq = nbxmpp.Iq('set', nbxmpp.NS_BLOCKING)
|
||||||
|
query = iq.setQuery(name='unblock')
|
||||||
|
|
||||||
|
for contact in contact_list:
|
||||||
|
query.addChild(name='item', attrs={'jid': contact.jid})
|
||||||
|
log.info('Unblock: %s', contact.jid)
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._default_result_handler, {})
|
||||||
|
|
||||||
|
def _default_result_handler(self, conn, stanza):
|
||||||
|
if not nbxmpp.isResultNode(stanza):
|
||||||
|
log.warning('Operation failed: %s', stanza.getError())
|
||||||
|
|
||||||
|
|
||||||
|
class BlockingEvent(NetworkIncomingEvent):
|
||||||
|
name = 'blocking'
|
||||||
|
base_network_events = []
|
||||||
|
|
||||||
|
|
||||||
|
def get_instance(*args, **kwargs):
|
||||||
|
return Blocking(*args, **kwargs), 'Blocking'
|
|
@ -0,0 +1,450 @@
|
||||||
|
# This file is part of Gajim.
|
||||||
|
#
|
||||||
|
# Gajim 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; version 3 only.
|
||||||
|
#
|
||||||
|
# Gajim 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 Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# XEP-0016: Privacy Lists
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import nbxmpp
|
||||||
|
|
||||||
|
from gajim.common import app
|
||||||
|
from gajim.common import helpers
|
||||||
|
from gajim.common.nec import NetworkIncomingEvent
|
||||||
|
from gajim.common.connection_handlers_events import InformationEvent
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger('gajim.c.m.privacylists')
|
||||||
|
|
||||||
|
|
||||||
|
class PrivacyLists:
|
||||||
|
def __init__(self, con):
|
||||||
|
self._con = con
|
||||||
|
self._account = con.name
|
||||||
|
|
||||||
|
self.default_list = None
|
||||||
|
self.active_list = None
|
||||||
|
self.blocked_contacts = []
|
||||||
|
self.blocked_groups = []
|
||||||
|
self.blocked_list = []
|
||||||
|
self.blocked_all = False
|
||||||
|
|
||||||
|
self.handlers = [
|
||||||
|
('iq', self._list_push_received, 'set', nbxmpp.NS_PRIVACY)
|
||||||
|
]
|
||||||
|
|
||||||
|
def _list_push_received(self, con, stanza):
|
||||||
|
result = stanza.buildReply('result')
|
||||||
|
result.delChild(result.getTag('query'))
|
||||||
|
self._con.connection.send(result)
|
||||||
|
|
||||||
|
for list_ in stanza.getQueryPayload():
|
||||||
|
if list_.getName() == 'list':
|
||||||
|
name = list_.getAttr('name')
|
||||||
|
log.info('Received Push: %s', name)
|
||||||
|
self.get_privacy_list(name)
|
||||||
|
|
||||||
|
raise nbxmpp.NodeProcessed
|
||||||
|
|
||||||
|
def get_privacy_lists(self, callback=None):
|
||||||
|
log.info('Request lists')
|
||||||
|
iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVACY)
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._privacy_lists_received, {'callback': callback})
|
||||||
|
|
||||||
|
def _privacy_lists_received(self, conn, stanza, callback):
|
||||||
|
lists = []
|
||||||
|
new_default = None
|
||||||
|
result = nbxmpp.isResultNode(stanza)
|
||||||
|
if not result:
|
||||||
|
log.warning('List not available: %s', stanza.getError())
|
||||||
|
else:
|
||||||
|
for list_ in stanza.getQueryPayload():
|
||||||
|
name = list_.getAttr('name')
|
||||||
|
if list_.getName() == 'active':
|
||||||
|
self.active_list = name
|
||||||
|
elif list_.getName() == 'default':
|
||||||
|
new_default = name
|
||||||
|
else:
|
||||||
|
lists.append(name)
|
||||||
|
|
||||||
|
log.info('Received lists: %s', lists)
|
||||||
|
|
||||||
|
# Download default list if we dont have it
|
||||||
|
if self.default_list != new_default:
|
||||||
|
self.default_list = new_default
|
||||||
|
if new_default is not None:
|
||||||
|
log.info('Found new default list: %s', new_default)
|
||||||
|
self.get_privacy_list(new_default)
|
||||||
|
|
||||||
|
if callback:
|
||||||
|
callback(result)
|
||||||
|
else:
|
||||||
|
app.nec.push_incoming_event(
|
||||||
|
PrivacyListsReceivedEvent(None,
|
||||||
|
conn=self._con,
|
||||||
|
active_list=self.active_list,
|
||||||
|
default_list=self.default_list,
|
||||||
|
lists=lists))
|
||||||
|
|
||||||
|
def get_privacy_list(self, name):
|
||||||
|
log.info('Request list: %s', name)
|
||||||
|
list_ = nbxmpp.Node('list', {'name': name})
|
||||||
|
iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVACY, payload=[list_])
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._privacy_list_received)
|
||||||
|
|
||||||
|
def _privacy_list_received(self, stanza):
|
||||||
|
if not nbxmpp.isResultNode(stanza):
|
||||||
|
log.warning('List not available: %s', stanza.getError())
|
||||||
|
return
|
||||||
|
|
||||||
|
rules = []
|
||||||
|
list_ = stanza.getQueryPayload()[0]
|
||||||
|
name = list_.getAttr('name')
|
||||||
|
|
||||||
|
for child in list_.getChildren():
|
||||||
|
|
||||||
|
item = child.getAttrs()
|
||||||
|
|
||||||
|
childs = []
|
||||||
|
for scnd_child in child.getChildren():
|
||||||
|
childs.append(scnd_child.getName())
|
||||||
|
|
||||||
|
item['child'] = childs
|
||||||
|
if len(item) not in (3, 5):
|
||||||
|
log.warning('Wrong count of attrs: %s', stanza)
|
||||||
|
continue
|
||||||
|
rules.append(item)
|
||||||
|
|
||||||
|
log.info('Received list: %s', name)
|
||||||
|
|
||||||
|
if name == self.default_list:
|
||||||
|
self._default_list_received(rules)
|
||||||
|
|
||||||
|
app.nec.push_incoming_event(PrivacyListReceivedEvent(
|
||||||
|
None, conn=self._con, list_name=name, rules=rules))
|
||||||
|
|
||||||
|
def del_privacy_list(self, name):
|
||||||
|
log.info('Remove list: %s', name)
|
||||||
|
|
||||||
|
def _del_privacy_list_result(stanza):
|
||||||
|
if not nbxmpp.isResultNode(stanza):
|
||||||
|
log.warning('List deletion failed: %s', stanza.getError())
|
||||||
|
app.nec.push_incoming_event(InformationEvent(
|
||||||
|
None, dialog_name='privacy-list-error', args=name))
|
||||||
|
else:
|
||||||
|
app.nec.push_incoming_event(PrivacyListRemovedEvent(
|
||||||
|
None, conn=self._con, list_name=name))
|
||||||
|
|
||||||
|
node = nbxmpp.Node('list', {'name': name})
|
||||||
|
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node])
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, _del_privacy_list_result)
|
||||||
|
|
||||||
|
def set_privacy_list(self, name, rules):
|
||||||
|
node = nbxmpp.Node('list', {'name': name})
|
||||||
|
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node])
|
||||||
|
for item in rules:
|
||||||
|
childs = item.get('child', [])
|
||||||
|
for child in childs:
|
||||||
|
node.setTag(child)
|
||||||
|
item.pop('child', None)
|
||||||
|
node.setTag('item', item)
|
||||||
|
log.info('Update list: %s %s', name, rules)
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._default_result_handler, {})
|
||||||
|
|
||||||
|
def _default_list_received(self, rules):
|
||||||
|
roster = app.interface.roster
|
||||||
|
|
||||||
|
for rule in rules:
|
||||||
|
if rule['action'] == 'allow':
|
||||||
|
if 'type' not in rule:
|
||||||
|
self.blocked_all = False
|
||||||
|
|
||||||
|
elif rule['type'] == 'jid':
|
||||||
|
if rule['value'] in self.blocked_contacts:
|
||||||
|
self.blocked_contacts.remove(rule['value'])
|
||||||
|
|
||||||
|
elif rule['type'] == 'group':
|
||||||
|
if rule['value'] in self.blocked_groups:
|
||||||
|
self.blocked_groups.remove(rule['value'])
|
||||||
|
|
||||||
|
elif rule['action'] == 'deny':
|
||||||
|
if 'type' not in rule:
|
||||||
|
self.blocked_all = True
|
||||||
|
|
||||||
|
elif rule['type'] == 'jid':
|
||||||
|
if rule['value'] not in self.blocked_contacts:
|
||||||
|
self.blocked_contacts.append(rule['value'])
|
||||||
|
|
||||||
|
elif rule['type'] == 'group':
|
||||||
|
if rule['value'] not in self.blocked_groups:
|
||||||
|
self.blocked_groups.append(rule['value'])
|
||||||
|
|
||||||
|
self.blocked_list.append(rule)
|
||||||
|
|
||||||
|
if 'type' in rule:
|
||||||
|
if rule['type'] == 'jid':
|
||||||
|
roster.draw_contact(rule['value'], self._account)
|
||||||
|
if rule['type'] == 'group':
|
||||||
|
roster.draw_group(rule['value'], self._account)
|
||||||
|
|
||||||
|
def set_active_list(self, name=None):
|
||||||
|
log.info('Set active list: %s', name)
|
||||||
|
attr = {}
|
||||||
|
if name:
|
||||||
|
attr['name'] = name
|
||||||
|
node = nbxmpp.Node('active', attr)
|
||||||
|
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node])
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._default_result_handler, {})
|
||||||
|
|
||||||
|
def set_default_list(self, name=None):
|
||||||
|
log.info('Set default list: %s', name)
|
||||||
|
attr = {}
|
||||||
|
if name:
|
||||||
|
attr['name'] = name
|
||||||
|
node = nbxmpp.Node('default', attr)
|
||||||
|
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node])
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, self._default_result_handler, {})
|
||||||
|
|
||||||
|
def _default_result_handler(self, conn, stanza):
|
||||||
|
if not nbxmpp.isResultNode(stanza):
|
||||||
|
log.warning('Operation failed: %s', stanza.getError())
|
||||||
|
|
||||||
|
def _build_invisible_rule(self):
|
||||||
|
node = nbxmpp.Node('list', {'name': 'invisible'})
|
||||||
|
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, payload=[node])
|
||||||
|
if self._account in app.interface.status_sent_to_groups and \
|
||||||
|
len(app.interface.status_sent_to_groups[self._account]) > 0:
|
||||||
|
for group in app.interface.status_sent_to_groups[self._account]:
|
||||||
|
item = node.setTag('item', {'type': 'group',
|
||||||
|
'value': group,
|
||||||
|
'action': 'allow',
|
||||||
|
'order': '1'})
|
||||||
|
item.setTag('presence-out')
|
||||||
|
|
||||||
|
if self._account in app.interface.status_sent_to_users and \
|
||||||
|
len(app.interface.status_sent_to_users[self._account]) > 0:
|
||||||
|
for jid in app.interface.status_sent_to_users[self._account]:
|
||||||
|
item = node.setTag('item', {'type': 'jid',
|
||||||
|
'value': jid,
|
||||||
|
'action': 'allow',
|
||||||
|
'order': '2'})
|
||||||
|
item.setTag('presence-out')
|
||||||
|
|
||||||
|
item = node.setTag('item', {'action': 'deny', 'order': '3'})
|
||||||
|
item.setTag('presence-out')
|
||||||
|
return iq
|
||||||
|
|
||||||
|
def set_invisible_rule(self, callback=None, **kwargs):
|
||||||
|
log.info('Update invisible list')
|
||||||
|
iq = self._build_invisible_rule()
|
||||||
|
if callback is None:
|
||||||
|
callback = self._default_result_handler
|
||||||
|
self._con.connection.SendAndCallForResponse(
|
||||||
|
iq, callback, kwargs)
|
||||||
|
|
||||||
|
def _get_max_blocked_list_order(self):
|
||||||
|
max_order = 0
|
||||||
|
for rule in self.blocked_list:
|
||||||
|
order = int(rule['order'])
|
||||||
|
if order > max_order:
|
||||||
|
max_order = order
|
||||||
|
return max_order
|
||||||
|
|
||||||
|
def block_gc_contact(self, jid):
|
||||||
|
if jid in self.blocked_contacts:
|
||||||
|
return
|
||||||
|
log.info('Block GC contact: %s', jid)
|
||||||
|
|
||||||
|
if self.default_list is None:
|
||||||
|
self.default_list = 'block'
|
||||||
|
|
||||||
|
max_order = self._get_max_blocked_list_order()
|
||||||
|
new_rule = {'order': str(max_order + 1),
|
||||||
|
'type': 'jid',
|
||||||
|
'action': 'deny',
|
||||||
|
'value': jid,
|
||||||
|
'child': ['message', 'iq', 'presence-out']}
|
||||||
|
self.blocked_list.append(new_rule)
|
||||||
|
self.blocked_contacts.append(jid)
|
||||||
|
self.set_privacy_list(self.default_list, self.blocked_list)
|
||||||
|
if len(self.blocked_list) == 1:
|
||||||
|
self.set_default_list(self.default_list)
|
||||||
|
|
||||||
|
def block_contacts(self, contact_list, message):
|
||||||
|
if not self._con.privacy_rules_supported:
|
||||||
|
self._con.get_module('Blocking').block(contact_list)
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.default_list is None:
|
||||||
|
self.default_list = 'block'
|
||||||
|
for contact in contact_list:
|
||||||
|
log.info('Block contacts: %s', contact.jid)
|
||||||
|
contact.show = 'offline'
|
||||||
|
self._con.send_custom_status('offline', message, contact.jid)
|
||||||
|
max_order = self._get_max_blocked_list_order()
|
||||||
|
new_rule = {'order': str(max_order + 1),
|
||||||
|
'type': 'jid',
|
||||||
|
'action': 'deny',
|
||||||
|
'value': contact.jid}
|
||||||
|
self.blocked_list.append(new_rule)
|
||||||
|
self.blocked_contacts.append(contact.jid)
|
||||||
|
self.set_privacy_list(self.default_list, self.blocked_list)
|
||||||
|
if len(self.blocked_list) == 1:
|
||||||
|
self.set_default_list(self.default_list)
|
||||||
|
|
||||||
|
def unblock_gc_contact(self, jid):
|
||||||
|
new_blocked_list = []
|
||||||
|
# needed for draw_contact:
|
||||||
|
if jid not in self.blocked_contacts:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.blocked_contacts.remove(jid)
|
||||||
|
|
||||||
|
log.info('Unblock GC contact: %s', jid)
|
||||||
|
for rule in self.blocked_list:
|
||||||
|
if rule['action'] != 'deny' or rule['type'] != 'jid' \
|
||||||
|
or rule['value'] != jid:
|
||||||
|
new_blocked_list.append(rule)
|
||||||
|
|
||||||
|
if len(new_blocked_list) == 0:
|
||||||
|
self.blocked_list = []
|
||||||
|
self.blocked_contacts = []
|
||||||
|
self.blocked_groups = []
|
||||||
|
self.set_default_list(None)
|
||||||
|
self.del_privacy_list(self.default_list)
|
||||||
|
else:
|
||||||
|
self.set_privacy_list(self.default_list, new_blocked_list)
|
||||||
|
|
||||||
|
def unblock_contacts(self, contact_list):
|
||||||
|
if not self._con.privacy_rules_supported:
|
||||||
|
self._con.get_module('Blocking').unblock(contact_list)
|
||||||
|
return
|
||||||
|
|
||||||
|
new_blocked_list = []
|
||||||
|
to_unblock = []
|
||||||
|
for contact in contact_list:
|
||||||
|
log.info('Unblock contacts: %s', contact.jid)
|
||||||
|
to_unblock.append(contact.jid)
|
||||||
|
if contact.jid in self.blocked_contacts:
|
||||||
|
self.blocked_contacts.remove(contact.jid)
|
||||||
|
for rule in self.blocked_list:
|
||||||
|
if rule['action'] != 'deny' or rule['type'] != 'jid' \
|
||||||
|
or rule['value'] not in to_unblock:
|
||||||
|
new_blocked_list.append(rule)
|
||||||
|
|
||||||
|
if len(new_blocked_list) == 0:
|
||||||
|
self.blocked_list = []
|
||||||
|
self.blocked_contacts = []
|
||||||
|
self.blocked_groups = []
|
||||||
|
self.set_default_list(None)
|
||||||
|
self.del_privacy_list(self.default_list)
|
||||||
|
else:
|
||||||
|
self.set_privacy_list(self.default_list, new_blocked_list)
|
||||||
|
if not app.interface.roster.regroup:
|
||||||
|
show = app.SHOW_LIST[self._con.connected]
|
||||||
|
else: # accounts merged
|
||||||
|
show = helpers.get_global_show()
|
||||||
|
if show == 'invisible':
|
||||||
|
return
|
||||||
|
for contact in contact_list:
|
||||||
|
self._con.send_custom_status(show, self._con.status, contact.jid)
|
||||||
|
self._presence_probe(contact.jid)
|
||||||
|
|
||||||
|
def block_group(self, group, contact_list, message):
|
||||||
|
if not self._con.privacy_rules_supported:
|
||||||
|
return
|
||||||
|
if group in self.blocked_groups:
|
||||||
|
return
|
||||||
|
self.blocked_groups.append(group)
|
||||||
|
|
||||||
|
log.info('Block group: %s', group)
|
||||||
|
|
||||||
|
if self.default_list is None:
|
||||||
|
self.default_list = 'block'
|
||||||
|
|
||||||
|
for contact in contact_list:
|
||||||
|
self._con.send_custom_status('offline', message, contact.jid)
|
||||||
|
|
||||||
|
max_order = self._get_max_blocked_list_order()
|
||||||
|
new_rule = {'order': str(max_order + 1),
|
||||||
|
'type': 'group',
|
||||||
|
'action': 'deny',
|
||||||
|
'value': group}
|
||||||
|
|
||||||
|
self.blocked_list.append(new_rule)
|
||||||
|
self.set_privacy_list(self.default_list, self.blocked_list)
|
||||||
|
if len(self.blocked_list) == 1:
|
||||||
|
self.set_default_list(self.default_list)
|
||||||
|
|
||||||
|
def unblock_group(self, group, contact_list):
|
||||||
|
if not self._con.privacy_rules_supported:
|
||||||
|
return
|
||||||
|
|
||||||
|
if group not in self.blocked_groups:
|
||||||
|
return
|
||||||
|
self.blocked_groups.remove(group)
|
||||||
|
|
||||||
|
log.info('Unblock group: %s', group)
|
||||||
|
new_blocked_list = []
|
||||||
|
for rule in self.blocked_list:
|
||||||
|
if rule['action'] != 'deny' or rule['type'] != 'group' or \
|
||||||
|
rule['value'] != group:
|
||||||
|
new_blocked_list.append(rule)
|
||||||
|
|
||||||
|
if len(new_blocked_list) == 0:
|
||||||
|
self.blocked_list = []
|
||||||
|
self.blocked_contacts = []
|
||||||
|
self.blocked_groups = []
|
||||||
|
self.set_default_list('')
|
||||||
|
self.del_privacy_list(self.default_list)
|
||||||
|
else:
|
||||||
|
self.set_privacy_list(self.default_list, new_blocked_list)
|
||||||
|
if not app.interface.roster.regroup:
|
||||||
|
show = app.SHOW_LIST[self._con.connected]
|
||||||
|
else: # accounts merged
|
||||||
|
show = helpers.get_global_show()
|
||||||
|
if show == 'invisible':
|
||||||
|
return
|
||||||
|
for contact in contact_list:
|
||||||
|
self._con.send_custom_status(show, self._con.status, contact.jid)
|
||||||
|
|
||||||
|
def _presence_probe(self, jid):
|
||||||
|
log.info('Presence probe: %s', jid)
|
||||||
|
# Send a presence Probe to get the current Status
|
||||||
|
probe = nbxmpp.Presence(jid, 'probe', frm=self._con.get_own_jid())
|
||||||
|
self._con.connection.send(probe)
|
||||||
|
|
||||||
|
|
||||||
|
class PrivacyListsReceivedEvent(NetworkIncomingEvent):
|
||||||
|
name = 'privacy-lists-received'
|
||||||
|
base_network_events = []
|
||||||
|
|
||||||
|
|
||||||
|
class PrivacyListReceivedEvent(NetworkIncomingEvent):
|
||||||
|
name = 'privacy-list-received'
|
||||||
|
base_network_events = []
|
||||||
|
|
||||||
|
|
||||||
|
class PrivacyListRemovedEvent(NetworkIncomingEvent):
|
||||||
|
name = 'privacy-list-removed'
|
||||||
|
base_network_events = []
|
||||||
|
|
||||||
|
|
||||||
|
def get_instance(*args, **kwargs):
|
||||||
|
return PrivacyLists(*args, **kwargs), 'PrivacyLists'
|
|
@ -4100,8 +4100,8 @@ class PrivacyListWindow:
|
||||||
|
|
||||||
app.ged.register_event_handler('privacy-list-received', ged.GUI1,
|
app.ged.register_event_handler('privacy-list-received', ged.GUI1,
|
||||||
self._nec_privacy_list_received)
|
self._nec_privacy_list_received)
|
||||||
app.ged.register_event_handler('privacy-list-active-default',
|
app.ged.register_event_handler('privacy-lists-received', ged.GUI1,
|
||||||
ged.GUI1, self._nec_privacy_list_active_default)
|
self._nec_privacy_lists_received)
|
||||||
|
|
||||||
self.window.show_all()
|
self.window.show_all()
|
||||||
self.add_edit_vbox.hide()
|
self.add_edit_vbox.hide()
|
||||||
|
@ -4118,10 +4118,10 @@ class PrivacyListWindow:
|
||||||
del app.interface.instances[self.account][key_name]
|
del app.interface.instances[self.account][key_name]
|
||||||
app.ged.remove_event_handler('privacy-list-received', ged.GUI1,
|
app.ged.remove_event_handler('privacy-list-received', ged.GUI1,
|
||||||
self._nec_privacy_list_received)
|
self._nec_privacy_list_received)
|
||||||
app.ged.remove_event_handler('privacy-list-active-default',
|
app.ged.remove_event_handler('privacy-lists-received', ged.GUI1,
|
||||||
ged.GUI1, self._nec_privacy_list_active_default)
|
self._nec_privacy_lists_received)
|
||||||
|
|
||||||
def _nec_privacy_list_active_default(self, obj):
|
def _nec_privacy_lists_received(self, obj):
|
||||||
if obj.conn.name != self.account:
|
if obj.conn.name != self.account:
|
||||||
return
|
return
|
||||||
if obj.active_list == self.privacy_list_name:
|
if obj.active_list == self.privacy_list_name:
|
||||||
|
@ -4166,7 +4166,8 @@ class PrivacyListWindow:
|
||||||
self.privacy_list_active_checkbutton.set_sensitive(True)
|
self.privacy_list_active_checkbutton.set_sensitive(True)
|
||||||
self.privacy_list_default_checkbutton.set_sensitive(True)
|
self.privacy_list_default_checkbutton.set_sensitive(True)
|
||||||
self.reset_fields()
|
self.reset_fields()
|
||||||
app.connections[self.account].get_active_default_lists()
|
con = app.connections[self.account]
|
||||||
|
con.get_module('PrivacyLists').get_privacy_lists()
|
||||||
|
|
||||||
def _nec_privacy_list_received(self, obj):
|
def _nec_privacy_list_received(self, obj):
|
||||||
if obj.conn.name != self.account:
|
if obj.conn.name != self.account:
|
||||||
|
@ -4176,7 +4177,8 @@ class PrivacyListWindow:
|
||||||
self.privacy_list_received(obj.rules)
|
self.privacy_list_received(obj.rules)
|
||||||
|
|
||||||
def refresh_rules(self):
|
def refresh_rules(self):
|
||||||
app.connections[self.account].get_privacy_list(self.privacy_list_name)
|
con = app.connections[self.account]
|
||||||
|
con.get_module('PrivacyLists').get_privacy_list(self.privacy_list_name)
|
||||||
|
|
||||||
def on_delete_rule_button_clicked(self, widget):
|
def on_delete_rule_button_clicked(self, widget):
|
||||||
model = self.list_of_rules_combobox.get_model()
|
model = self.list_of_rules_combobox.get_model()
|
||||||
|
@ -4186,8 +4188,9 @@ class PrivacyListWindow:
|
||||||
for rule in self.global_rules:
|
for rule in self.global_rules:
|
||||||
if rule != _rule:
|
if rule != _rule:
|
||||||
tags.append(self.global_rules[rule])
|
tags.append(self.global_rules[rule])
|
||||||
app.connections[self.account].set_privacy_list(
|
con = app.connections[self.account]
|
||||||
self.privacy_list_name, tags)
|
con.get_module('PrivacyLists').set_privacy_list(
|
||||||
|
self.privacy_list_name, tags)
|
||||||
self.privacy_list_received(tags)
|
self.privacy_list_received(tags)
|
||||||
self.add_edit_vbox.hide()
|
self.add_edit_vbox.hide()
|
||||||
if not tags: # we removed latest rule
|
if not tags: # we removed latest rule
|
||||||
|
@ -4279,18 +4282,20 @@ class PrivacyListWindow:
|
||||||
self.edit_send_status_checkbutton.set_sensitive(True)
|
self.edit_send_status_checkbutton.set_sensitive(True)
|
||||||
|
|
||||||
def on_privacy_list_active_checkbutton_toggled(self, widget):
|
def on_privacy_list_active_checkbutton_toggled(self, widget):
|
||||||
|
name = None
|
||||||
if widget.get_active():
|
if widget.get_active():
|
||||||
app.connections[self.account].set_active_list(
|
name = self.privacy_list_name
|
||||||
self.privacy_list_name)
|
|
||||||
else:
|
con = app.connections[self.account]
|
||||||
app.connections[self.account].set_active_list(None)
|
con.get_module('PrivacyLists').set_active_list(name)
|
||||||
|
|
||||||
def on_privacy_list_default_checkbutton_toggled(self, widget):
|
def on_privacy_list_default_checkbutton_toggled(self, widget):
|
||||||
|
name = None
|
||||||
if widget.get_active():
|
if widget.get_active():
|
||||||
app.connections[self.account].set_default_list(
|
name = self.privacy_list_name
|
||||||
self.privacy_list_name)
|
|
||||||
else:
|
con = app.connections[self.account]
|
||||||
app.connections[self.account].set_default_list(None)
|
con.get_module('PrivacyLists').set_default_list(name)
|
||||||
|
|
||||||
def on_new_rule_button_clicked(self, widget):
|
def on_new_rule_button_clicked(self, widget):
|
||||||
self.reset_fields()
|
self.reset_fields()
|
||||||
|
@ -4362,8 +4367,9 @@ class PrivacyListWindow:
|
||||||
else:
|
else:
|
||||||
tags.append(current_tags)
|
tags.append(current_tags)
|
||||||
|
|
||||||
app.connections[self.account].set_privacy_list(
|
con = app.connections[self.account]
|
||||||
self.privacy_list_name, tags)
|
con.get_module('PrivacyLists').set_privacy_list(
|
||||||
|
self.privacy_list_name, tags)
|
||||||
self.refresh_rules()
|
self.refresh_rules()
|
||||||
self.add_edit_vbox.hide()
|
self.add_edit_vbox.hide()
|
||||||
if 'privacy_lists' in app.interface.instances[self.account]:
|
if 'privacy_lists' in app.interface.instances[self.account]:
|
||||||
|
@ -4419,7 +4425,7 @@ class PrivacyListsWindow:
|
||||||
|
|
||||||
app.ged.register_event_handler('privacy-lists-received', ged.GUI1,
|
app.ged.register_event_handler('privacy-lists-received', ged.GUI1,
|
||||||
self._nec_privacy_lists_received)
|
self._nec_privacy_lists_received)
|
||||||
app.ged.register_event_handler('privacy-lists-removed', ged.GUI1,
|
app.ged.register_event_handler('privacy-list-removed', ged.GUI1,
|
||||||
self._nec_privacy_lists_removed)
|
self._nec_privacy_lists_removed)
|
||||||
|
|
||||||
self.window.show_all()
|
self.window.show_all()
|
||||||
|
@ -4435,14 +4441,18 @@ class PrivacyListsWindow:
|
||||||
del app.interface.instances[self.account]['privacy_lists']
|
del app.interface.instances[self.account]['privacy_lists']
|
||||||
app.ged.remove_event_handler('privacy-lists-received', ged.GUI1,
|
app.ged.remove_event_handler('privacy-lists-received', ged.GUI1,
|
||||||
self._nec_privacy_lists_received)
|
self._nec_privacy_lists_received)
|
||||||
app.ged.remove_event_handler('privacy-lists-removed', ged.GUI1,
|
app.ged.remove_event_handler('privacy-list-removed', ged.GUI1,
|
||||||
self._nec_privacy_lists_removed)
|
self._nec_privacy_lists_removed)
|
||||||
|
|
||||||
def remove_privacy_list_from_combobox(self, privacy_list):
|
def remove_privacy_list_from_combobox(self, privacy_list):
|
||||||
if privacy_list not in self.privacy_lists_save:
|
if privacy_list not in self.privacy_lists_save:
|
||||||
return
|
return
|
||||||
privacy_list_index = self.privacy_lists_save.index(privacy_list)
|
|
||||||
self.list_of_privacy_lists_combobox.remove_text(privacy_list_index)
|
model = self.list_of_privacy_lists_combobox.get_model()
|
||||||
|
for entry in model:
|
||||||
|
if entry[0] == privacy_list:
|
||||||
|
model.remove(entry.iter)
|
||||||
|
|
||||||
self.privacy_lists_save.remove(privacy_list)
|
self.privacy_lists_save.remove(privacy_list)
|
||||||
|
|
||||||
def add_privacy_list_to_combobox(self, privacy_list):
|
def add_privacy_list_to_combobox(self, privacy_list):
|
||||||
|
@ -4477,32 +4487,32 @@ class PrivacyListsWindow:
|
||||||
def on_delete_privacy_list_button_clicked(self, widget):
|
def on_delete_privacy_list_button_clicked(self, widget):
|
||||||
active_list = self.privacy_lists_save[
|
active_list = self.privacy_lists_save[
|
||||||
self.list_of_privacy_lists_combobox.get_active()]
|
self.list_of_privacy_lists_combobox.get_active()]
|
||||||
app.connections[self.account].del_privacy_list(active_list)
|
con = app.connections[self.account]
|
||||||
|
con.get_module('PrivacyLists').del_privacy_list(active_list)
|
||||||
|
|
||||||
def privacy_list_removed(self, active_list):
|
def privacy_list_removed(self, active_list):
|
||||||
self.privacy_lists_save.remove(active_list)
|
self.privacy_lists_save.remove(active_list)
|
||||||
self.privacy_lists_received({'lists': self.privacy_lists_save})
|
self.privacy_lists_received(self.privacy_lists_save)
|
||||||
|
|
||||||
def _nec_privacy_lists_removed(self, obj):
|
def _nec_privacy_lists_removed(self, obj):
|
||||||
if obj.conn.name != self.account:
|
if obj.conn.name != self.account:
|
||||||
return
|
return
|
||||||
self.privacy_list_removed(obj.lists_list)
|
self.privacy_list_removed(obj.list_name)
|
||||||
|
|
||||||
def privacy_lists_received(self, lists):
|
def privacy_lists_received(self, lists):
|
||||||
if not lists:
|
|
||||||
return
|
|
||||||
privacy_lists = []
|
privacy_lists = []
|
||||||
for privacy_list in lists['lists']:
|
for privacy_list in lists:
|
||||||
privacy_lists.append(privacy_list)
|
privacy_lists.append(privacy_list)
|
||||||
self.draw_privacy_lists_in_combobox(privacy_lists)
|
self.draw_privacy_lists_in_combobox(privacy_lists)
|
||||||
|
|
||||||
def _nec_privacy_lists_received(self, obj):
|
def _nec_privacy_lists_received(self, obj):
|
||||||
if obj.conn.name != self.account:
|
if obj.conn.name != self.account:
|
||||||
return
|
return
|
||||||
self.privacy_lists_received(obj.lists_list)
|
self.privacy_lists_received(obj.lists)
|
||||||
|
|
||||||
def privacy_lists_refresh(self):
|
def privacy_lists_refresh(self):
|
||||||
app.connections[self.account].get_privacy_lists()
|
con = app.connections[self.account]
|
||||||
|
con.get_module('PrivacyLists').get_privacy_lists()
|
||||||
|
|
||||||
def on_new_privacy_list_button_clicked(self, widget):
|
def on_new_privacy_list_button_clicked(self, widget):
|
||||||
name = self.new_privacy_list_entry.get_text()
|
name = self.new_privacy_list_entry.get_text()
|
||||||
|
|
|
@ -2919,46 +2919,15 @@ class GroupchatControl(ChatControlBase):
|
||||||
|
|
||||||
def on_block(self, widget, nick):
|
def on_block(self, widget, nick):
|
||||||
fjid = self.room_jid + '/' + nick
|
fjid = self.room_jid + '/' + nick
|
||||||
connection = app.connections[self.account]
|
con = app.connections[self.account]
|
||||||
default = connection.privacy_default_list
|
con.get_module('PrivacyLists').block_gc_contact(fjid)
|
||||||
if fjid in connection.blocked_contacts:
|
|
||||||
return
|
|
||||||
max_order = connection.get_max_blocked_list_order()
|
|
||||||
new_rule = {'order': str(max_order + 1), 'type': 'jid',
|
|
||||||
'action': 'deny', 'value' : fjid, 'child': ['message', 'iq',
|
|
||||||
'presence-out']}
|
|
||||||
connection.blocked_list.append(new_rule)
|
|
||||||
connection.blocked_contacts.append(fjid)
|
|
||||||
self.draw_contact(nick)
|
self.draw_contact(nick)
|
||||||
connection.set_privacy_list(default, connection.blocked_list)
|
|
||||||
if len(connection.blocked_list) == 1:
|
|
||||||
connection.set_default_list(default)
|
|
||||||
|
|
||||||
def on_unblock(self, widget, nick):
|
def on_unblock(self, widget, nick):
|
||||||
fjid = self.room_jid + '/' + nick
|
fjid = self.room_jid + '/' + nick
|
||||||
connection = app.connections[self.account]
|
con = app.connections[self.account]
|
||||||
default = connection.privacy_default_list
|
con.get_module('PrivacyLists').unblock_gc_contact(fjid)
|
||||||
connection.new_blocked_list = []
|
|
||||||
# needed for draw_contact:
|
|
||||||
if fjid in connection.blocked_contacts:
|
|
||||||
connection.blocked_contacts.remove(fjid)
|
|
||||||
self.draw_contact(nick)
|
self.draw_contact(nick)
|
||||||
for rule in connection.blocked_list:
|
|
||||||
if rule['action'] != 'deny' or rule['type'] != 'jid' \
|
|
||||||
or rule['value'] != fjid:
|
|
||||||
connection.new_blocked_list.append(rule)
|
|
||||||
|
|
||||||
if len(connection.new_blocked_list) == 0:
|
|
||||||
connection.blocked_list = []
|
|
||||||
connection.blocked_contacts = []
|
|
||||||
connection.blocked_groups = []
|
|
||||||
connection.set_default_list('')
|
|
||||||
connection.del_privacy_list(default)
|
|
||||||
if 'privay_list_block' in app.interface.instances[self.account]:
|
|
||||||
del app.interface.instances[self.account]\
|
|
||||||
['privay_list_block']
|
|
||||||
else:
|
|
||||||
connection.set_privacy_list(default, connection.new_blocked_list)
|
|
||||||
|
|
||||||
def on_voice_checkmenuitem_activate(self, widget, nick):
|
def on_voice_checkmenuitem_activate(self, widget, nick):
|
||||||
if widget.get_active():
|
if widget.get_active():
|
||||||
|
|
|
@ -2812,12 +2812,8 @@ class RosterWindow:
|
||||||
on_response_ok = (remove, list_), transient_for=self.window)
|
on_response_ok = (remove, list_), transient_for=self.window)
|
||||||
|
|
||||||
def _nec_blocking(self, obj):
|
def _nec_blocking(self, obj):
|
||||||
if obj.unblock_all or obj.blocklist:
|
for jid in obj.changed:
|
||||||
jids = app.contacts.get_jid_list(obj.conn.name)
|
self.draw_contact(jid, obj.conn.name)
|
||||||
self._idle_draw_jids_of_account(jids, obj.conn.name)
|
|
||||||
else:
|
|
||||||
for jid in obj.blocked_jids + obj.unblocked_jids:
|
|
||||||
self.draw_contact(jid, obj.conn.name)
|
|
||||||
|
|
||||||
def on_block(self, widget, list_, group=None):
|
def on_block(self, widget, list_, group=None):
|
||||||
"""
|
"""
|
||||||
|
@ -2834,13 +2830,15 @@ class RosterWindow:
|
||||||
if group is None:
|
if group is None:
|
||||||
for acct in accounts:
|
for acct in accounts:
|
||||||
l_ = [i[0] for i in list_ if i[1] == acct]
|
l_ = [i[0] for i in list_ if i[1] == acct]
|
||||||
app.connections[acct].block_contacts(l_, msg)
|
con = app.connections[acct]
|
||||||
|
con.get_module('PrivacyLists').block_contacts(l_, msg)
|
||||||
for contact in l_:
|
for contact in l_:
|
||||||
self.draw_contact(contact.jid, acct)
|
self.draw_contact(contact.jid, acct)
|
||||||
else:
|
else:
|
||||||
for acct in accounts:
|
for acct in accounts:
|
||||||
l_ = [i[0] for i in list_ if i[1] == acct]
|
l_ = [i[0] for i in list_ if i[1] == acct]
|
||||||
app.connections[acct].block_group(group, l_, msg)
|
con = app.connections[acct]
|
||||||
|
con.get_module('PrivacyLists').block_group(group, l_, msg)
|
||||||
self.draw_group(group, acct)
|
self.draw_group(group, acct)
|
||||||
for contact in l_:
|
for contact in l_:
|
||||||
self.draw_contact(contact.jid, acct)
|
self.draw_contact(contact.jid, acct)
|
||||||
|
@ -2874,13 +2872,15 @@ class RosterWindow:
|
||||||
if group is None:
|
if group is None:
|
||||||
for acct in accounts:
|
for acct in accounts:
|
||||||
l_ = [i[0] for i in list_ if i[1] == acct]
|
l_ = [i[0] for i in list_ if i[1] == acct]
|
||||||
app.connections[acct].unblock_contacts(l_)
|
con = app.connections[acct]
|
||||||
|
con.get_module('PrivacyLists').unblock_contacts(l_)
|
||||||
for contact in l_:
|
for contact in l_:
|
||||||
self.draw_contact(contact.jid, acct)
|
self.draw_contact(contact.jid, acct)
|
||||||
else:
|
else:
|
||||||
for acct in accounts:
|
for acct in accounts:
|
||||||
l_ = [i[0] for i in list_ if i[1] == acct]
|
l_ = [i[0] for i in list_ if i[1] == acct]
|
||||||
app.connections[acct].unblock_group(group, l_)
|
con = app.connections[acct]
|
||||||
|
con.get_module('PrivacyLists').unblock_group(group, l_)
|
||||||
self.draw_group(group, acct)
|
self.draw_group(group, acct)
|
||||||
for contact in l_:
|
for contact in l_:
|
||||||
self.draw_contact(contact.jid, acct)
|
self.draw_contact(contact.jid, acct)
|
||||||
|
@ -3462,7 +3462,8 @@ class RosterWindow:
|
||||||
for account in account_list:
|
for account in account_list:
|
||||||
if app.SHOW_LIST[app.connections[account].connected] == \
|
if app.SHOW_LIST[app.connections[account].connected] == \
|
||||||
'invisible':
|
'invisible':
|
||||||
app.connections[account].set_invisible_rule()
|
con = app.connections[account]
|
||||||
|
con.get_module('PrivacyLists').set_invisible_rule()
|
||||||
|
|
||||||
# 3. send directed presence
|
# 3. send directed presence
|
||||||
for (contact, account) in contact_list:
|
for (contact, account) in contact_list:
|
||||||
|
|
|
@ -20,8 +20,6 @@ class MockConnection(Mock, ConnectionHandlers):
|
||||||
|
|
||||||
self.connected = 2
|
self.connected = 2
|
||||||
self.pep = {}
|
self.pep = {}
|
||||||
self.blocked_contacts = {}
|
|
||||||
self.blocked_groups = {}
|
|
||||||
self.sessions = {}
|
self.sessions = {}
|
||||||
self.nested_group_delimiter = '::'
|
self.nested_group_delimiter = '::'
|
||||||
self.server_resource = 'Gajim'
|
self.server_resource = 'Gajim'
|
||||||
|
|
Loading…
Reference in New Issue