Merge changes from default branch into refactoring branch
This commit is contained in:
commit
01553e53c2
|
@ -581,11 +581,10 @@ class MetacontactManager():
|
||||||
#FIXME: can this append ?
|
#FIXME: can this append ?
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def get_metacontacts_tags(self, account):
|
def iter_metacontacts_families(self, account):
|
||||||
'''return a list of tags for a given account'''
|
for tag in self._metacontacts_tags[account]:
|
||||||
if not account in self._metacontacts_tags:
|
family = self._get_metacontacts_family_from_tag(account, tag)
|
||||||
return []
|
yield family
|
||||||
return self._metacontacts_tags[account].keys()
|
|
||||||
|
|
||||||
def _get_metacontacts_tag(self, account, jid):
|
def _get_metacontacts_tag(self, account, jid):
|
||||||
'''Returns the tag of a jid'''
|
'''Returns the tag of a jid'''
|
||||||
|
@ -643,7 +642,7 @@ class MetacontactManager():
|
||||||
tag = self._get_metacontacts_tag(account, jid)
|
tag = self._get_metacontacts_tag(account, jid)
|
||||||
if not tag:
|
if not tag:
|
||||||
return False
|
return False
|
||||||
meta_jids = self.get_metacontacts_jids(tag, accounts)
|
meta_jids = self._get_metacontacts_jids(tag, accounts)
|
||||||
return len(meta_jids) > 1 or len(meta_jids[account]) > 1
|
return len(meta_jids) > 1 or len(meta_jids[account]) > 1
|
||||||
|
|
||||||
def is_big_brother(self, account, jid, accounts):
|
def is_big_brother(self, account, jid, accounts):
|
||||||
|
@ -651,12 +650,12 @@ class MetacontactManager():
|
||||||
if family:
|
if family:
|
||||||
nearby_family = [data for data in family
|
nearby_family = [data for data in family
|
||||||
if account in accounts]
|
if account in accounts]
|
||||||
bb_data = self.get_metacontacts_big_brother(nearby_family)
|
bb_data = self._get_metacontacts_big_brother(nearby_family)
|
||||||
if bb_data['jid'] == jid and bb_data['account'] == account:
|
if bb_data['jid'] == jid and bb_data['account'] == account:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_metacontacts_jids(self, tag, accounts):
|
def _get_metacontacts_jids(self, tag, accounts):
|
||||||
'''Returns all jid for the given tag in the form {acct: [jid1, jid2],.}'''
|
'''Returns all jid for the given tag in the form {acct: [jid1, jid2],.}'''
|
||||||
answers = {}
|
answers = {}
|
||||||
for account in self._metacontacts_tags:
|
for account in self._metacontacts_tags:
|
||||||
|
@ -673,9 +672,9 @@ class MetacontactManager():
|
||||||
[{'account': acct, 'jid': jid, 'order': order}, ]
|
[{'account': acct, 'jid': jid, 'order': order}, ]
|
||||||
'order' is optional'''
|
'order' is optional'''
|
||||||
tag = self._get_metacontacts_tag(account, jid)
|
tag = self._get_metacontacts_tag(account, jid)
|
||||||
return self.get_metacontacts_family_from_tag(account, tag)
|
return self._get_metacontacts_family_from_tag(account, tag)
|
||||||
|
|
||||||
def get_metacontacts_family_from_tag(self, account, tag):
|
def _get_metacontacts_family_from_tag(self, account, tag):
|
||||||
if not tag:
|
if not tag:
|
||||||
return []
|
return []
|
||||||
answers = []
|
answers = []
|
||||||
|
@ -766,7 +765,29 @@ class MetacontactManager():
|
||||||
return -1
|
return -1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def get_metacontacts_big_brother(self, family):
|
def get_nearby_family_and_big_brother(self, family, account):
|
||||||
|
'''Return the nearby family and its Big Brother
|
||||||
|
|
||||||
|
Nearby family is the part of the family that is grouped with the metacontact.
|
||||||
|
A metacontact may be over different accounts. If accounts are not merged
|
||||||
|
then the given family is split account wise.
|
||||||
|
|
||||||
|
(nearby_family, big_brother_jid, big_brother_account)
|
||||||
|
'''
|
||||||
|
if common.gajim.config.get('mergeaccounts'):
|
||||||
|
# group all together
|
||||||
|
nearby_family = family
|
||||||
|
else:
|
||||||
|
# we want one nearby_family per account
|
||||||
|
nearby_family = [data for data in family if account == data['account']]
|
||||||
|
|
||||||
|
big_brother_data = self._get_metacontacts_big_brother(nearby_family)
|
||||||
|
big_brother_jid = big_brother_data['jid']
|
||||||
|
big_brother_account = big_brother_data['account']
|
||||||
|
|
||||||
|
return (nearby_family, big_brother_jid, big_brother_account)
|
||||||
|
|
||||||
|
def _get_metacontacts_big_brother(self, family):
|
||||||
'''which of the family will be the big brother under wich all
|
'''which of the family will be the big brother under wich all
|
||||||
others will be ?'''
|
others will be ?'''
|
||||||
family.sort(cmp=self._compare_metacontacts)
|
family.sort(cmp=self._compare_metacontacts)
|
||||||
|
|
|
@ -462,6 +462,9 @@ class XMPPDispatcher(PlugIn):
|
||||||
# we have released dispatcher, so self._owner has no methods
|
# we have released dispatcher, so self._owner has no methods
|
||||||
if not res:
|
if not res:
|
||||||
return
|
return
|
||||||
|
if 'remove_timeout' in self._owner.__dict__:
|
||||||
|
# When we receive data after we started disconnecting, Transport may
|
||||||
|
# already be plugged out
|
||||||
self._owner.remove_timeout()
|
self._owner.remove_timeout()
|
||||||
for (_id, _iq) in self._expected.items():
|
for (_id, _iq) in self._expected.items():
|
||||||
if _iq is None:
|
if _iq is None:
|
||||||
|
|
|
@ -645,13 +645,16 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
if self.get_state() == PROXY_CONNECTING:
|
if self.get_state() == PROXY_CONNECTING:
|
||||||
NonBlockingTCP._on_receive(self, data)
|
NonBlockingTCP._on_receive(self, data)
|
||||||
return
|
return
|
||||||
if not self.recvbuff:
|
|
||||||
# recvbuff empty - fresh HTTP message was received
|
# append currently received data to HTTP msg in buffer
|
||||||
try:
|
self.recvbuff = '%s%s' % (self.recvbuff or '', data)
|
||||||
statusline, headers, self.recvbuff = self.parse_http_message(data)
|
statusline, headers, httpbody, buffer_rest = self.parse_http_message(
|
||||||
except ValueError:
|
self.recvbuff)
|
||||||
self.disconnect()
|
|
||||||
|
if not (statusline and headers and httpbody):
|
||||||
|
log.debug('Received incomplete HTTP response')
|
||||||
return
|
return
|
||||||
|
|
||||||
if statusline[1] != '200':
|
if statusline[1] != '200':
|
||||||
log.error('HTTP Error: %s %s' % (statusline[1], statusline[2]))
|
log.error('HTTP Error: %s %s' % (statusline[1], statusline[2]))
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
@ -659,21 +662,18 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
self.expected_length = int(headers['Content-Length'])
|
self.expected_length = int(headers['Content-Length'])
|
||||||
if 'Connection' in headers and headers['Connection'].strip()=='close':
|
if 'Connection' in headers and headers['Connection'].strip()=='close':
|
||||||
self.close_current_connection = True
|
self.close_current_connection = True
|
||||||
else:
|
|
||||||
#sth in recvbuff - append currently received data to HTTP msg in buffer
|
|
||||||
self.recvbuff = '%s%s' % (self.recvbuff, data)
|
|
||||||
|
|
||||||
if self.expected_length > len(self.recvbuff):
|
if self.expected_length > len(httpbody):
|
||||||
# If we haven't received the whole HTTP mess yet, let's end the thread.
|
# If we haven't received the whole HTTP mess yet, let's end the thread.
|
||||||
# It will be finnished from one of following recvs on plugged socket.
|
# It will be finnished from one of following recvs on plugged socket.
|
||||||
log.info('not enough bytes in HTTP response - %d expected, %d got' %
|
log.info('not enough bytes in HTTP response - %d expected, %d got' %
|
||||||
(self.expected_length, len(self.recvbuff)))
|
(self.expected_length, len(self.recvbuff)))
|
||||||
return
|
else:
|
||||||
|
# First part of buffer has been extraced and is going to be handled,
|
||||||
|
# remove it from buffer
|
||||||
|
self.recvbuff = buffer_rest
|
||||||
|
|
||||||
# everything was received
|
# everything was received
|
||||||
httpbody = self.recvbuff
|
|
||||||
|
|
||||||
self.recvbuff = ''
|
|
||||||
self.expected_length = 0
|
self.expected_length = 0
|
||||||
|
|
||||||
if not self.http_persistent or self.close_current_connection:
|
if not self.http_persistent or self.close_current_connection:
|
||||||
|
@ -707,7 +707,7 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
headers.append('Connection: Keep-Alive')
|
headers.append('Connection: Keep-Alive')
|
||||||
headers.append('\r\n')
|
headers.append('\r\n')
|
||||||
headers = '\r\n'.join(headers)
|
headers = '\r\n'.join(headers)
|
||||||
return('%s%s\r\n' % (headers, httpbody))
|
return('%s%s' % (headers, httpbody))
|
||||||
|
|
||||||
def parse_http_message(self, message):
|
def parse_http_message(self, message):
|
||||||
'''
|
'''
|
||||||
|
@ -716,12 +716,19 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
headers - dictionary of headers e.g. {'Content-Length': '604',
|
headers - dictionary of headers e.g. {'Content-Length': '604',
|
||||||
'Content-Type': 'text/xml; charset=utf-8'},
|
'Content-Type': 'text/xml; charset=utf-8'},
|
||||||
httpbody - string with http body)
|
httpbody - string with http body)
|
||||||
|
http_rest - what is left in the message after a full HTTP header + body
|
||||||
'''
|
'''
|
||||||
message = message.replace('\r','')
|
message = message.replace('\r','')
|
||||||
# Remove latest \n
|
splitted = message.split('\n\n')
|
||||||
if message.endswith('\n'):
|
if len(splitted) < 2:
|
||||||
message = message[:-1]
|
# no complete http message. Keep filling the buffer until we find one
|
||||||
(header, httpbody) = message.split('\n\n', 1)
|
buffer_rest = message
|
||||||
|
return ('', '', '', buffer_rest)
|
||||||
|
else:
|
||||||
|
(header, httpbody) = splitted[:2]
|
||||||
|
if httpbody.endswith('\n'):
|
||||||
|
httpbody = httpbody[:-1]
|
||||||
|
buffer_rest = "\n\n".join(splitted[2:])
|
||||||
header = header.split('\n')
|
header = header.split('\n')
|
||||||
statusline = header[0].split(' ', 2)
|
statusline = header[0].split(' ', 2)
|
||||||
header = header[1:]
|
header = header[1:]
|
||||||
|
@ -729,7 +736,7 @@ class NonBlockingHTTP(NonBlockingTCP):
|
||||||
for dummy in header:
|
for dummy in header:
|
||||||
row = dummy.split(' ', 1)
|
row = dummy.split(' ', 1)
|
||||||
headers[row[0][:-1]] = row[1]
|
headers[row[0][:-1]] = row[1]
|
||||||
return (statusline, headers, httpbody)
|
return (statusline, headers, httpbody, buffer_rest)
|
||||||
|
|
||||||
|
|
||||||
class NonBlockingHTTPBOSH(NonBlockingHTTP):
|
class NonBlockingHTTPBOSH(NonBlockingHTTP):
|
||||||
|
|
|
@ -494,7 +494,7 @@ class P2PConnection(IdleObject, PlugIn):
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self, message=''):
|
||||||
''' Closes the socket. '''
|
''' Closes the socket. '''
|
||||||
gajim.idlequeue.remove_timeout(self.fd)
|
gajim.idlequeue.remove_timeout(self.fd)
|
||||||
gajim.idlequeue.unplug_idle(self.fd)
|
gajim.idlequeue.unplug_idle(self.fd)
|
||||||
|
|
|
@ -2145,7 +2145,7 @@ class Interface:
|
||||||
family = gajim.contacts.get_metacontacts_family(account, jid)
|
family = gajim.contacts.get_metacontacts_family(account, jid)
|
||||||
if family:
|
if family:
|
||||||
nearby_family, bb_jid, bb_account = \
|
nearby_family, bb_jid, bb_account = \
|
||||||
self.roster._get_nearby_family_and_big_brother(family, account)
|
gajim.contacts.get_nearby_family_and_big_brother(family, account)
|
||||||
else:
|
else:
|
||||||
bb_jid, bb_account = jid, account
|
bb_jid, bb_account = jid, account
|
||||||
self.roster.select_contact(bb_jid, bb_account)
|
self.roster.select_contact(bb_jid, bb_account)
|
||||||
|
|
|
@ -604,29 +604,7 @@ class RosterWindow:
|
||||||
big_brother_account=big_brother_account)
|
big_brother_account=big_brother_account)
|
||||||
|
|
||||||
def _get_nearby_family_and_big_brother(self, family, account):
|
def _get_nearby_family_and_big_brother(self, family, account):
|
||||||
'''Return the nearby family and its Big Brother
|
return gajim.contacts.get_nearby_family_and_big_brother(family, account)
|
||||||
|
|
||||||
Nearby family is the part of the family that is grouped with the metacontact.
|
|
||||||
A metacontact may be over different accounts. If regroup is s False the
|
|
||||||
given family is split account wise.
|
|
||||||
|
|
||||||
(nearby_family, big_brother_jid, big_brother_account)
|
|
||||||
'''
|
|
||||||
if self.regroup:
|
|
||||||
# group all together
|
|
||||||
nearby_family = family
|
|
||||||
else:
|
|
||||||
# we want one nearby_family per account
|
|
||||||
nearby_family = [data for data in family
|
|
||||||
if account == data['account']]
|
|
||||||
|
|
||||||
big_brother_data = gajim.contacts.get_metacontacts_big_brother(
|
|
||||||
nearby_family)
|
|
||||||
big_brother_jid = big_brother_data['jid']
|
|
||||||
big_brother_account = big_brother_data['account']
|
|
||||||
|
|
||||||
return (nearby_family, big_brother_jid, big_brother_account)
|
|
||||||
|
|
||||||
|
|
||||||
def _add_self_contact(self, account):
|
def _add_self_contact(self, account):
|
||||||
'''Add account's SelfContact to roster and draw it and the account.
|
'''Add account's SelfContact to roster and draw it and the account.
|
||||||
|
@ -649,10 +627,8 @@ class RosterWindow:
|
||||||
|
|
||||||
return contact
|
return contact
|
||||||
|
|
||||||
|
|
||||||
def redraw_metacontacts(self, account):
|
def redraw_metacontacts(self, account):
|
||||||
for tag in gajim.contacts.get_metacontacts_tags(account):
|
for family in gajim.contacts.iter_metacontacts_families(account):
|
||||||
family = gajim.contacts.get_metacontacts_family_from_tag(account, tag)
|
|
||||||
self._recalibrate_metacontact_family(family, account)
|
self._recalibrate_metacontact_family(family, account)
|
||||||
|
|
||||||
def add_contact(self, jid, account):
|
def add_contact(self, jid, account):
|
||||||
|
|
|
@ -382,7 +382,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
|
||||||
family = gajim.contacts.get_metacontacts_family(self.conn.name, jid)
|
family = gajim.contacts.get_metacontacts_family(self.conn.name, jid)
|
||||||
if family:
|
if family:
|
||||||
nearby_family, bb_jid, bb_account = \
|
nearby_family, bb_jid, bb_account = \
|
||||||
gajim.interface.roster._get_nearby_family_and_big_brother(family,
|
gajim.contacts.get_nearby_family_and_big_brother(family,
|
||||||
self.conn.name)
|
self.conn.name)
|
||||||
else:
|
else:
|
||||||
bb_jid, bb_account = jid, self.conn.name
|
bb_jid, bb_account = jid, self.conn.name
|
||||||
|
|
|
@ -227,9 +227,10 @@ class TestNonBlockingHTTP(AbstractTransportTest):
|
||||||
|
|
||||||
data = "<test>Please don't fail!</test>"
|
data = "<test>Please don't fail!</test>"
|
||||||
http_message = transport.build_http_message(data)
|
http_message = transport.build_http_message(data)
|
||||||
statusline, headers, http_body = transport.parse_http_message(
|
statusline, headers, http_body, buffer_rest = transport.parse_http_message(
|
||||||
http_message)
|
http_message)
|
||||||
|
|
||||||
|
self.assertFalse(bool(buffer_rest))
|
||||||
self.assertTrue(statusline and isinstance(statusline, list))
|
self.assertTrue(statusline and isinstance(statusline, list))
|
||||||
self.assertTrue(headers and isinstance(headers, dict))
|
self.assertTrue(headers and isinstance(headers, dict))
|
||||||
self.assertEqual(data, http_body, msg='Input and output are different')
|
self.assertEqual(data, http_body, msg='Input and output are different')
|
||||||
|
@ -250,26 +251,26 @@ class TestNonBlockingHTTP(AbstractTransportTest):
|
||||||
transport._on_receive(message)
|
transport._on_receive(message)
|
||||||
self.assertTrue(self.have_received_expected(), msg='Failed: In one go')
|
self.assertTrue(self.have_received_expected(), msg='Failed: In one go')
|
||||||
|
|
||||||
# FIXME: Not yet implemented.
|
def test_receive_http_message_in_chunks(self):
|
||||||
# def test_receive_http_message_in_chunks(self):
|
''' Let _on_receive handle some chunked http messages '''
|
||||||
# ''' Let _on_receive handle some chunked http messages '''
|
transport = self._get_transport(self.bosh_http_dict)
|
||||||
# transport = self._get_transport(self.bosh_http_dict)
|
|
||||||
#
|
header = ("HTTP/1.1 200 OK\r\nContent-Type: text/xml; charset=utf-8\r\n" +
|
||||||
# header = ("HTTP/1.1 200 OK\r\nContent-Type: text/xml; charset=utf-8\r\n" +
|
"Content-Length: 88\r\n\r\n")
|
||||||
# "Content-Length: 88\r\n\r\n")
|
payload = "<test>Please don't fail!</test>"
|
||||||
# payload = "<test>Please don't fail!</test>"
|
body = "<body xmlns='http://jabber.org/protocol/httpbind'>%s</body>" \
|
||||||
# body = "<body xmlns='http://jabber.org/protocol/httpbind'>%s</body>" \
|
% payload
|
||||||
# % payload
|
message = "%s%s" % (header, body)
|
||||||
# message = "%s%s" % (header, body)
|
|
||||||
#
|
chunk1, chunk2, chunk3, chunk4 = message[:20], message[20:73], \
|
||||||
# chunk1, chunk2, chunk3 = message[:20], message[20:73], message[73:]
|
message[73:85], message[85:]
|
||||||
# nextmessage_chunk = "\r\n\r\nHTTP/1.1 200 OK\r\nContent-Type: text/x"
|
nextmessage_chunk = "\r\n\r\nHTTP/1.1 200 OK\r\nContent-Type: text/x"
|
||||||
# chunks = (chunk1, chunk2, chunk3, nextmessage_chunk)
|
chunks = (chunk1, chunk2, chunk3, chunk4, nextmessage_chunk)
|
||||||
#
|
|
||||||
# transport.onreceive(self.expect_receive(body, msg='Failed: In chunks'))
|
transport.onreceive(self.expect_receive(body, msg='Failed: In chunks'))
|
||||||
# for chunk in chunks:
|
for chunk in chunks:
|
||||||
# transport._on_receive(chunk)
|
transport._on_receive(chunk)
|
||||||
# self.assertTrue(self.have_received_expected(), msg='Failed: In chunks')
|
self.assertTrue(self.have_received_expected(), msg='Failed: In chunks')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue