def noop_presence_update(q, stream):
    # At the moment Gabble does not optimize away presence updates that
    # have no effect. When it does, we can forbid those events here.

    #events = [EventPattern('stream-presence')]
    #q.forbid_events(events)
    sync_stream(q, stream)
def test(q, bus, conn, stream):
    event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    acknowledge_iq(stream, event.stanza)
    # Force Gabble to process the vCard before calling any methods.
    sync_stream(q, stream)

    # Request our alias and avatar, expect them to be resolved from cache.

    handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    call_async(q, conn.Avatars, 'RequestAvatars', [handle])
    call_async(q, conn.Aliasing, 'RequestAliases', [handle])

    # FIXME - find out why RequestAliases returns before RequestAvatar even
    # though everything's cached. Probably due to queueing, which means
    # conn-avatars don't look into the cache before making a request. Prolly
    # should make vcard_request look into the cache itself, and return
    # immediately. Or not, if it's g_idle()'d. So it's better if conn-aliasing
    # look into the cache itself.

    r1, r2 = q.expect_many(
        EventPattern('dbus-return', method='RequestAliases'),
        EventPattern('dbus-return', method='RequestAvatars'))

    # Default alias is our jid
    assert r1.value[0] == ['test@localhost']
def test(q, bus, conn, stream):
    conn.Connect()
    _, event = q.expect_many(
        EventPattern('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]),
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'))

    acknowledge_iq(stream, event.stanza)
    # Force Gabble to process the vCard before calling any methods.
    sync_stream(q, stream)

    handle = conn.GetSelfHandle()
    call_async(q, conn.Avatars, 'SetAvatar', 'william shatner',
        'image/x-actor-name')

    event = q.expect('stream-iq', iq_type='get', to=None,
        query_ns='vcard-temp', query_name='vCard')
    reply = make_result_iq(stream, event.stanza)
    reply['type'] = 'error'
    reply.addChild(elem('error')(
        elem(ns.STANZA, 'forbidden')(),
        elem(ns.STANZA, 'text')(u'zomg whoops')))
    stream.send(reply)

    event = q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
示例#4
0
    def sign_in_a_cat(jid, identities, show=None):
        caps['ver'] = compute_caps_hash(identities, features, {})

        presence_and_disco(q, conn, stream, jid, expect_disco, client, caps, features,
            identities=identities, initial=False, show=show)
        # Make sure Gabble's got the caps
        sync_stream(q, stream)
示例#5
0
def sending_request_to_cappy_contact(q, bus, conn, stream, chan):
    """
    Test that Gabble requests a receipt from a contact whom we know supports
    this extension, but only if asked.
    """

    # Convince Gabble that Guybrush supports this extension
    caps = { 'node': 'http://whatever',
             'ver': caps_helper.compute_caps_hash([], [ns.RECEIPTS], {}),
             'hash': 'sha-1',
           }
    caps_helper.presence_and_disco(q, conn, stream, GUYBRUSH_FULL_JID,
        disco=True,
        client=caps['node'],
        caps=caps,
        features=[ns.RECEIPTS])
    sync_stream(q, stream)

    # Don't ask, don't tell — even if we know Guybrush does support this.
    not_sending_request_to_contact(q, bus, conn, stream, chan)

    # Ask, tell.
    message = [
      { 'message-type': cs.MT_NORMAL,
      },
      { 'content-type': 'text/plain',
        'content': 'Ulysses?',
      }]
    chan.Messages.SendMessage(message, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY)

    e = q.expect('stream-message', to=GUYBRUSH)
    assertLength(1, list(e.stanza.elements(uri=ns.RECEIPTS, name='request')))
    def announce_contact(self, name=CONTACT_NAME):
        self.contact_name = name
        self.contact_full_jid = '%s/Telepathy' % name
        self.handle = self.conn.RequestHandles(cs.HT_CONTACT, [name])[0]

        presence = domish.Element(('jabber:client', 'presence'))
        presence['from'] = self.contact_full_jid
        presence['to'] = 'test@localhost/Resource'
        c = presence.addElement('c')
        c['xmlns'] = 'http://jabber.org/protocol/caps'
        c['node'] = 'http://example.com/ISupportFT'
        c['ver'] = '1.0'
        self.stream.send(presence)

        disco_event, presence_event = self.q.expect_many(
            EventPattern('stream-iq', iq_type='get',
                query_ns='http://jabber.org/protocol/disco#info', to=self.contact_full_jid),
            EventPattern('dbus-signal', signal='PresencesChanged', args=[
                {self.handle: (cs.PRESENCE_AVAILABLE, u'available', u'')}]))

        assert disco_event.query['node'] == \
            'http://example.com/ISupportFT#1.0'
        result = make_result_iq(self.stream, disco_event.stanza)
        query = result.firstChildElement()
        feature = query.addElement('feature')
        feature['var'] = ns.FILE_TRANSFER
        self.stream.send(result)

        sync_stream(self.q, self.stream)
def test(q, bus, conn, stream, bytestream_cls, access_control):
    disco_event = q.expect('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    t.check_conn_properties(q, conn)

    self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    alice_handle = conn.get_contact_handle_sync('alice@localhost')

    # send Alice's presence
    caps =  { 'ext': '', 'ver': '0.0.0',
        'node': 'http://example.com/fake-client0' }
    presence = make_presence('alice@localhost/Test', caps=caps)
    stream.send(presence)

    _, disco_event = q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged',
            args = [{alice_handle: (2L, u'available', u'')}]),
        EventPattern('stream-iq', to='alice@localhost/Test',
            query_ns=ns.DISCO_INFO),
        )

    # reply to disco query
    send_disco_reply(stream, disco_event.stanza, [], [ns.TUBES])

    sync_stream(q, stream)

    offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle, bytestream_cls, access_control)
示例#8
0
def test(q, bus, conn, stream, is_google):
    iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    result = make_result_iq(stream, iq_event.stanza)

    # Testing reveals that Google's vCard server does not actually support
    # NICKNAME (or indeed any fields beside FN, N and PHOTO): if you set a
    # vCard including it, it accepts the request but strips out the unsupported
    # fields. So if the server looks like Google, it's a redundant set
    # operation on FN that we want to avoid.
    if is_google:
        vcard = result.firstChildElement()
        vcard.addElement('FN', content='oh hello there')
    else:
        vcard = result.firstChildElement()
        vcard.addElement('NICKNAME', content='oh hello there')

    stream.send(result)

    q.forbid_events([
        EventPattern('stream-iq', iq_type='set', query_ns='vcard-temp',
            query_name='vCard')
        ])
    sync_stream(q, stream)
    sync_dbus(bus, q, conn)
def test(q, bus, conn, stream):
    roster_event = q.expect('stream-iq', query_ns=ns.ROSTER)
    roster_event.stanza['type'] = 'result'

    call_async(q, conn, "RequestHandles", cs.HT_GROUP, ['test'])

    event = q.expect('dbus-return', method='RequestHandles')
    test_handle = event.value[0][0]

    call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_CONTACT_LIST,
        cs.HT_GROUP, test_handle, True)

    # A previous incarnation of this test --- written with the intention that
    # RequestChannel would be called before the roster was received, to expose
    # a bug in Gabble triggered by that ordering --- was racy: if the D-Bus
    # daemon happened to be particularly busy, the call to RequestChannel
    # reached Gabble after the roster stanza. (The race was discovered when
    # that reversed order triggered a newly-introduced instance of the
    # opposite bug to the one the test was targetting!) So we sync the XMPP
    # stream and D-Bus queue here.
    sync_stream(q, stream)
    sync_dbus(bus, q, conn)

    # send an empty roster
    stream.send(roster_event.stanza)

    event = q.expect('dbus-return', method='RequestChannel')
    path = event.value[0]

    while True:
        event = q.expect('dbus-signal', signal='NewChannel')
        assert event.args[0] == path, (event.args, path)
        _, type, handle_type, handle, suppress_handler = event.args
        if handle_type == cs.HT_GROUP and handle == test_handle:
            break
def test(q, bus, conn, stream):
    conn.Connect()

    roster_event = q.expect('stream-iq', query_ns=ns.ROSTER)
    roster_event.stanza['type'] = 'result'

    call_async(q, conn, "RequestHandles", cs.HT_GROUP, ['test'])

    event = q.expect('dbus-return', method='RequestHandles')
    test_handle = event.value[0][0]

    # send an empty roster
    stream.send(roster_event.stanza)

    sync_stream(q, stream)
    sync_dbus(bus, q, conn)

    call_async(q, conn.Requests, 'CreateChannel',
            { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_LIST,
              cs.TARGET_HANDLE_TYPE: cs.HT_GROUP,
              cs.TARGET_HANDLE: test_handle,
              })

    event = q.expect('dbus-return', method='CreateChannel')
    ret_path, ret_props = event.value

    event = q.expect('dbus-signal', signal='NewChannels')
    path, props = event.args[0][0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CONTACT_LIST, props
    assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_GROUP, props
    assert props[cs.TARGET_HANDLE] == test_handle, props
    assert props[cs.TARGET_ID] == 'test', props

    assert ret_path == path, (ret_path, path)
    assert ret_props == props, (ret_props, props)
def test(q, bus, conn, stream):
    conn.Connect()

    # Initial vCard request. Respond only after we call SetAliases().
    vcard_get_event = q.expect('stream-iq', iq_type='get', to=None,
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    sync_stream(q, stream)

    handle = conn.GetSelfHandle()
    call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Some Guy'})
    sync_dbus(bus, q, conn)
    acknowledge_iq(stream, vcard_get_event.stanza)

    # Gabble sets a new vCard with our nickname.
    vcard_set_event = q.expect('stream-iq', iq_type='set',
        query_ns=ns.VCARD_TEMP, query_name='vCard')

    # Before the server replies, the user sets their avatar.
    call_async(q, conn.Avatars, 'SetAvatar', 'hello', 'image/png')
    sync_dbus(bus, q, conn)
    acknowledge_iq(stream, vcard_set_event.stanza)

    vcard_set_event = q.expect('stream-iq', iq_type='set',
        query_ns=ns.VCARD_TEMP, query_name='vCard')
    acknowledge_iq(stream, vcard_set_event.stanza)
    q.expect('dbus-return', method='SetAvatar')

    # And then crashes.
    sync_stream(q, stream)

    conn.Disconnect()
    q.expect('dbus-signal', signal='StatusChanged', args=[2, 1])
示例#12
0
def test_39464(q, bus, conn, stream):
    """
    Regression test for an issue where a form with no type='' attribute on the
    <x/> node would crash Gabble.
    """
    client = 'fake:qutim'
    hash = 'blahblah'
    contact = '[email protected]/foo'
    caps = {
        'node': client,
        'ver': hash,
        'hash': 'sha-1',
        }
    presence = make_presence(contact, status='hello', caps=caps)
    stream.send(presence)

    # Gabble looks up our capabilities
    event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO)

    # Send a reply with a form without a type=''
    result = make_result_iq(stream, event.stanza, add_query_node=False)
    result.addChild(
        elem(ns.DISCO_INFO, 'query', node='%s#%s' % (client, hash))(
          # NB. no type='' attribute
          elem(ns.X_DATA, 'x')
        )
      )
    stream.send(result)
    # We don't really care what Gabble does, as long as it doesn't crash.
    sync_stream(q, stream)
def test(q, bus, conn, stream):
    conn.Connect()

    expect_and_handle_get_vcard(q, stream)
    sync_stream(q, stream)

    call_async(q, conn.Avatars, 'SetAvatar', 'william shatner',
        'image/x-actor-name')
    # Gabble request the last version of the vCard before changing it
    expect_and_handle_get_vcard(q, stream)

    set_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP,
        query_name='vCard', iq_type='set')
    iq = set_vcard_event.stanza

    error = domish.Element((None, 'error'))
    error['code'] = '400'
    error['type'] = 'modify'
    error.addElement((ns.STANZA, 'bad-request'))

    send_error_reply(stream, iq, error)

    event = q.expect('dbus-error', method='SetAvatar')

    assert event.error.get_dbus_name() == cs.INVALID_ARGUMENT, \
        event.error.get_dbus_name()
示例#14
0
def receive_caps(q, conn, stream, contact, contact_handle, features,
                 expected_caps, expect_disco=True, expect_ccc=True):

    caps = {'node': client,
            'ver': compute_caps_hash([], features, {}),
            'hash': 'sha-1'}

    presence_and_disco(q, conn, stream, contact, expect_disco,
                       client, caps, features, initial=False)

    if expect_ccc:
        event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged')
        announced_ccs, = event.args
        assertSameElements(expected_caps, announced_ccs[contact_handle])
    else:
        # Make sure Gabble's got the caps
        sync_stream(q, stream)

    caps = get_contacts_capabilities_sync(conn, [contact_handle])
    assertSameElements(expected_caps, caps[contact_handle])

    # test again, to check GetContactCapabilities does not have side effect
    caps = get_contacts_capabilities_sync(conn, [contact_handle])
    assertSameElements(expected_caps, caps[contact_handle])

    # check the Contacts interface give the same caps
    caps_via_contacts_iface = conn.Contacts.GetContactAttributes(
            [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \
            [contact_handle][cs.ATTR_CONTACT_CAPABILITIES]
    assertSameElements(caps[contact_handle], caps_via_contacts_iface)
def proxy_error(q, bus, conn, stream):
    # Test if another proxy is queried if a query failed
    connect_and_announce_alice(q, bus, conn, stream)

    send_file_to_alice(q, conn)

    return_event, e1, e2, e3 = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS),
        EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS),
        EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS))

    # Return errors for all the requests; the bugged proxies shouldn't be queried again
    q.forbid_events([EventPattern('stream-iq', to=e1.stanza['to'],
        iq_type='get', query_ns=ns.BYTESTREAMS)])
    send_error_reply(stream, e1.stanza)

    # the fourth proxy is queried
    q.expect('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS)

    q.forbid_events([EventPattern('stream-iq', to=e2.stanza['to'],
        iq_type='get', query_ns=ns.BYTESTREAMS)])
    send_error_reply(stream, e2.stanza)
    sync_stream(q, stream)

    q.forbid_events([EventPattern('stream-iq', to=e3.stanza['to'],
        iq_type='get', query_ns=ns.BYTESTREAMS)])
    send_error_reply(stream, e3.stanza)
    sync_stream(q, stream)
示例#16
0
def test_deny_unblock_remove(q, bus, conn, stream, stored, deny):
    """
    Test unblocking a contact, and, while that request is pending, deleting
    them.
    """
    self_handle = conn.GetSelfHandle()

    # This contact was on our roster, blocked and subscribed, when we started.
    contact = '*****@*****.**'
    handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0]

    # They're blocked, and we have a bidi subscription, so they should be on
    # deny and stored. (We already checked this earlier, but we've been messing
    # with the roster so let's be sure the preconditions are okay...)
    assertContains(handle,
        deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members"))
    assertContains(handle,
        stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members"))

    # Unblock them.
    call_async(q, deny.Group, 'RemoveMembers', [handle], "")

    roster_event = q.expect('stream-iq', query_ns=ns.ROSTER)
    item = roster_event.query.firstChildElement()
    assertEquals(contact, item['jid'])
    assertDoesNotContain((ns.GOOGLE_ROSTER, 't'), item.attributes)

    # If we now remove them from stored, the edit shouldn't be sent until the
    # unblock event has had a reply.
    q.forbid_events(remove_events)
    call_async(q, stored.Group, 'RemoveMembers', [handle], "")

    # Make sure if the remove is sent prematurely, we catch it.
    sync_stream(q, stream)
    q.unforbid_events(remove_events)

    # So now we send a roster push and reply for the unblock request.
    stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact,
        'both', False, attrs={}))
    acknowledge_iq(stream, roster_event.stanza)

    # And on receiving the push and reply, Gabble should show them being
    # removed from deny, and send a remove.

    _, roster_event = q.expect_many(
        EventPattern('dbus-signal', signal='MembersChanged',
            args=['', [], [handle], [], [], self_handle, cs.GC_REASON_NONE],
            predicate=is_deny),
        remove_events[0],
        )
    item = roster_event.query.firstChildElement()
    assertEquals(contact, item['jid'])

    stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact,
        'remove', False, attrs={}))
    acknowledge_iq(stream, roster_event.stanza)

    q.expect('dbus-signal', signal='MembersChanged',
        args=['', [], [handle], [], [], 0, cs.GC_REASON_NONE],
        predicate=is_stored)
def test(q, bus, conn, stream):
    # event node without NS
    message = elem('message', from_='*****@*****.**')(elem('event')(elem(
        'items', node=ns.GEOLOC)(elem('item', id='12345')(elem(
            ns.GEOLOC, 'geoloc')(elem('country')(u'France'))))))
    stream.send(message)

    # event node with a wrong NS
    message = elem('message', from_='*****@*****.**')(elem('badger', 'event')(
        elem('items', node=ns.GEOLOC)(elem('item', id='12345')(elem(
            ns.GEOLOC, 'geoloc')(elem('country')(u'France'))))))
    stream.send(message)

    # event node without 'from'
    message = elem('message')(elem(
        (ns.PUBSUB_EVENT),
        'event')(elem('items', node=ns.GEOLOC)(elem('item', id='12345')(elem(
            ns.GEOLOC, 'geoloc')(elem('country')(u'France'))))))
    stream.send(message)

    # event node with an invalid 'from'
    message = elem('message', from_='aaaa')(elem(
        (ns.PUBSUB_EVENT),
        'event')(elem('items', node=ns.GEOLOC)(elem('item', id='12345')(elem(
            ns.GEOLOC, 'geoloc')(elem('country')(u'France'))))))
    stream.send(message)

    # no items node
    message = elem('message', from_='*****@*****.**')(elem((ns.PUBSUB_EVENT),
                                                        'event')())
    stream.send(message)

    # no item node
    message = elem('message', from_='*****@*****.**')(elem(
        (ns.PUBSUB_EVENT), 'event')(elem('items', node=ns.GEOLOC)()))
    stream.send(message)

    # item node doesn't have any child
    message = elem('message', from_='*****@*****.**')(elem(
        (ns.PUBSUB_EVENT), 'event')(elem('items',
                                         node=ns.GEOLOC)(elem('item',
                                                              id='12345')())))
    stream.send(message)

    # the child of the item node doesn't have a NS
    message = elem('message', from_='*****@*****.**')(elem(
        (ns.PUBSUB_EVENT), 'event')(elem('items', node=ns.GEOLOC)(elem(
            'item', id='12345')(elem('geoloc')(elem('country')(u'France'))))))
    stream.send(message)

    # valid but unknown pubsub notification
    message = elem('message', from_='*****@*****.**')(elem(
        (ns.PUBSUB_EVENT),
        'event')(elem('items', node='http://www.badger.com')(elem(
            'item', id='12345')(elem('http://www.badger.com',
                                     'badger')(elem('mushroom')(u'snake'))))))
    stream.send(message)

    sync_stream(q, stream)
示例#18
0
def test_deny_overlap_two(q, bus, conn, stream,
                          subscribe, publish, stored, deny):
    """
    Here's another tricky case: editing a contact (setting an alias, say), and
    then while that edit's in flight, blocking and remove the contact.
    """

    # This contact was on our roster when we started.
    contact = '*****@*****.**'
    handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0]

    assertContains(handle,
        stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members"))
    assertContains(handle,
        subscribe.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members"))
    assertContains(handle,
        publish.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members"))

    # Once again, at no point in this test should anyone be removed outright.
    q.forbid_events(remove_events)

    # First up, we edit the contact's alias, triggering a roster update from
    # the client.
    conn.Aliasing.SetAliases({handle: 'oh! the huge manatee!'})
    event = q.expect('stream-iq', query_ns=ns.ROSTER)
    item = event.query.firstChildElement()
    assertEquals(contact, item['jid'])
    assertEquals('oh! the huge manatee!', item['name'])

    # Before the server responds, we block and remove the contact. The edits
    # should be queued...
    patterns = [
        EventPattern('stream-iq', query_ns=ns.ROSTER),
        EventPattern('stream-presence', presence_type='unsubscribed'),
        EventPattern('stream-presence', presence_type='unsubscribe'),
        ]
    q.forbid_events(patterns)

    call_async(q, deny.Group, 'AddMembers', [handle], "")
    call_async(q, stored.Group, 'RemoveMembers', [handle], "")

    # Make sure if the edits are sent prematurely, we've got them.
    sync_stream(q, stream)
    q.unforbid_events(patterns)

    # Okay, now we respond to the alias update. At this point we expect an
    # update to gr:t=B, leaving subscription=both intact, and subscription
    # cancellations.
    acknowledge_iq(stream, event.stanza)
    roster_event, _, _ = q.expect_many(*patterns)

    item = roster_event.query.firstChildElement()
    assertEquals(contact, item['jid'])
    assertEquals('B', item[(ns.GOOGLE_ROSTER, 't')])

    # And we're done. Clean up.
    q.unforbid_events(remove_events)
示例#19
0
def test(q, bus, conn, stream):
    self_presence = q.expect('stream-presence')

    c = xpath.queryForNodes('/presence/c', self_presence.stanza)[0]

    jid = '[email protected]/omg'

    # Gabble shouldn't send any disco requests to our contact during this test.
    q.forbid_events([
        EventPattern('stream-iq', to=jid, iq_type='get',
            query_ns=ns.DISCO_INFO),
    ])

    # Check that Gabble doesn't disco other clients with the same caps hash.
    p = make_presence(jid,
        caps={'node': c['node'],
              'hash': c['hash'],
              'ver':  c['ver'],
             })
    stream.send(p)
    sync_stream(q, stream)

    # Check that Gabble doesn't disco its own ext='' bundles (well, its own
    # bundles as advertised by Gabbles that don't do hashed caps)
    p = make_presence(jid,
        caps={'node': c['node'],
              'ver':  c['ver'],
              # omitting hash='' so Gabble doesn't ignore ext=''
              'ext':  'voice-v1 video-v1',
            })
    stream.send(p)
    sync_stream(q, stream)

    # Advertise some different capabilities, to change our own caps hash.
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, 2L**32-1),
           (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1),
           (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)

    self_presence = q.expect('stream-presence')
    c_ = xpath.queryForNodes('/presence/c', self_presence.stanza)[0]
    assertNotEquals(c['ver'], c_['ver'])

    # But then someone asks us for our old caps
    iq = IQ(stream, 'get')
    iq['from'] = jid
    query = iq.addElement((ns.DISCO_INFO, 'query'))
    query['node'] = c['node'] + '#' + c['ver']
    stream.send(iq)

    # Gabble should still know what they are, and reply. This is actually quite
    # important: there's a bug in iChat where if you return an error to a disco
    # query, it just asks again, and again, and again...
    reply = q.expect('stream-iq', to=jid)
    assertEquals('result', reply.iq_type)
示例#20
0
def test(q, bus, conn, stream):
    jid = '[email protected]/hi'
    caps = { 'node': 'oh:hi',
             'ver': "dere",
           }
    h = caps_helper.send_presence(q, conn, stream, jid, caps, initial=False)
    request = caps_helper.expect_disco(q, jid, caps['node'], caps)
    result = make_result_iq(stream, request, add_query_node=False)
    stream.send(result)
    sync_stream(q, stream)
def test_deny_unblock_remove(q, bus, conn, stream):
    """
    Test unblocking a contact, and, while that request is pending, deleting
    them.
    """

    # This contact was on our roster, blocked and subscribed, when we started.
    contact = '*****@*****.**'
    handle = conn.get_contact_handle_sync(contact)

    check_contact_roster(conn, contact, [],
            cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES)

    # They're blocked, and we have a bidi subscription, so they should be on
    # deny and stored. (We already checked this earlier, but we've been messing
    # with the roster so let's be sure the preconditions are okay...)
    assertContains(handle,
        conn.ContactBlocking.RequestBlockedContacts().keys())

    # Unblock them.
    call_async(q, conn.ContactBlocking, 'UnblockContacts', [handle])

    roster_event = q.expect('stream-iq', query_ns=ns.ROSTER)
    item = roster_event.query.firstChildElement()
    assertEquals(contact, item['jid'])
    assertDoesNotContain((ns.GOOGLE_ROSTER, 't'), item.attributes)

    # If we now remove them from stored, the edit shouldn't be sent until the
    # unblock event has had a reply.
    q.forbid_events(remove_events)
    call_async(q, conn.ContactList, 'RemoveContacts', [handle])

    # Make sure if the remove is sent prematurely, we catch it.
    sync_stream(q, stream)
    q.unforbid_events(remove_events)

    # So now we send a roster push and reply for the unblock request.
    stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact,
        'both', False, attrs={}))
    acknowledge_iq(stream, roster_event.stanza)

    # And on receiving the push and reply, Gabble should show them being
    # removed from deny, and send a remove.

    _, roster_event = q.expect_many(
        EventPattern('dbus-signal', signal='BlockedContactsChanged',
            predicate=lambda e: blocked_contacts_changed_predicate(e, [], [contact])),
        remove_events[0],
        )
    item = roster_event.query.firstChildElement()
    assertEquals(contact, item['jid'])

    stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact,
        'remove', False, attrs={}))
    acknowledge_iq(stream, roster_event.stanza)
def test_get_roster(q, bus, conn, stream):
    # DownloadAtConnection = True, so gabble should get the roster
    # automatically
    q.expect('stream-iq', query_ns=ns.ROSTER)

    # but calling ContactList.Download should not try and get the
    # roster again
    q.forbid_events(forbidden)
    conn.ContactList.Download()
    sync_stream(q, stream)
    q.unforbid_events(forbidden)
def normally_close_text(q, bus, conn, stream):
    jid = '*****@*****.**'

    text_chan, text_path, _ = text_channel(q, bus, conn, stream, 'CreateChannel', jid)

    sync_stream(q, stream)

    text_chan.Close()
    expect_close(q, text_path, stream, jid)

    assert_not_on_bus(q, text_chan)
def test_get_roster(q, bus, conn, stream):
    # DownloadAtConnection = True, so gabble should get the roster
    # automatically
    q.expect('stream-iq', query_ns=ns.ROSTER)

    # but calling ContactList.Download should not try and get the
    # roster again
    q.forbid_events(forbidden)
    conn.ContactList.Download()
    sync_stream(q, stream)
    q.unforbid_events(forbidden)
def test(q, bus, conn, stream):
    conn.Connect()

    expect_and_handle_get_vcard(q, stream)

    # Ensure that Gabble's actually got the initial vCard reply; if it hasn't
    # processed it by the time we call SetAliases, the latter will wait for it
    # to reply and then set immediately.
    sync_stream(q, stream)

    handle = conn.GetSelfHandle()

    call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Some Guy'})

    # SetAliases requests vCard v1
    get_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP,
        query_name='vCard', iq_type='get')

    iq = get_vcard_event.stanza
    vcard = iq.firstChildElement()
    assert vcard.name == 'vCard', vcard.toXml()

    call_async(q, conn.Avatars, 'SetAvatar', 'hello', 'image/png')

    # We don't expect Gabble to send a second vCard request, since there's one
    # outstanding. But we want to ensure that SetAvatar reaches Gabble before
    # the empty vCard does.
    sync_dbus(bus, q, conn)

    # Send back current empty vCard
    result = make_result_iq(stream, iq)
    # result already includes the <vCard/> from the query, which is all we need
    stream.send(result)

    def has_nickname_and_photo(vcard):
        nicknames = xpath.queryForNodes('/vCard/NICKNAME', vcard)
        assert nicknames is not None
        assert len(nicknames) == 1
        assert str(nicknames[0]) == 'Some Guy'

        photos = xpath.queryForNodes('/vCard/PHOTO', vcard)
        assert photos is not None and len(photos) == 1, repr(photos)
        types = xpath.queryForNodes('/PHOTO/TYPE', photos[0])
        binvals = xpath.queryForNodes('/PHOTO/BINVAL', photos[0])
        assert types is not None and len(types) == 1, repr(types)
        assert binvals is not None and len(binvals) == 1, repr(binvals)
        assert str(types[0]) == 'image/png'
        got = str(binvals[0])
        exp = base64.b64encode('hello')
        assert got == exp, (got, exp)

    # Now Gabble should set a new vCard with both of the above changes.
    expect_and_handle_set_vcard(q, stream, has_nickname_and_photo)
def test_deny_overlap_two(q, bus, conn, stream):
    """
    Here's another tricky case: editing a contact (setting an alias, say), and
    then while that edit's in flight, blocking and remove the contact.
    """

    # This contact was on our roster when we started.
    contact = '*****@*****.**'
    handle = conn.get_contact_handle_sync(contact)

    check_contact_roster(conn, contact, [],
            cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES)

    # Once again, at no point in this test should anyone be removed outright.
    q.forbid_events(remove_events)

    # First up, we edit the contact's alias, triggering a roster update from
    # the client.
    conn.Aliasing.SetAliases({handle: 'oh! the huge manatee!'})
    event = q.expect('stream-iq', query_ns=ns.ROSTER)
    item = event.query.firstChildElement()
    assertEquals(contact, item['jid'])
    assertEquals('oh! the huge manatee!', item['name'])

    # Before the server responds, we block and remove the contact. The edits
    # should be queued...
    patterns = [
        EventPattern('stream-iq', query_ns=ns.ROSTER),
        EventPattern('stream-presence', presence_type='unsubscribed'),
        EventPattern('stream-presence', presence_type='unsubscribe'),
        ]
    q.forbid_events(patterns)

    call_async(q, conn.ContactBlocking, 'BlockContacts', [handle], "")
    call_async(q, conn.ContactList, 'RemoveContacts', [handle])

    # Make sure if the edits are sent prematurely, we've got them.
    sync_stream(q, stream)
    q.unforbid_events(patterns)

    # Okay, now we respond to the alias update. At this point we expect an
    # update to gr:t=B, leaving subscription=both intact, and subscription
    # cancellations.
    acknowledge_iq(stream, event.stanza)
    roster_event, _, _ = q.expect_many(*patterns)

    item = roster_event.query.firstChildElement()
    assertEquals(contact, item['jid'])
    assertEquals('B', item[(ns.GOOGLE_ROSTER, 't')])

    # And we're done. Clean up.
    q.unforbid_events(remove_events)
示例#27
0
def receive_caps(q, conn, stream, contact, contact_handle, features,
                 expected_caps, expect_disco=True, expect_ccc=True):
    presence = make_presence(contact, status='hello')
    c = presence.addElement((ns.CAPS, 'c'))
    c['node'] = client
    c['ver'] = compute_caps_hash([],
        features if features is not None else [],
        {})
    c['hash'] = 'sha-1'
    stream.send(presence)

    if expect_disco:
        # Gabble looks up our capabilities
        event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO)
        query_node = xpath.queryForNodes('/iq/query', event.stanza)[0]
        assert query_node.attributes['node'] == \
            client + '#' + c['ver']

        # send good reply
        result = make_result_iq(stream, event.stanza)
        query = result.firstChildElement()
        query['node'] = client + '#' + c['ver']

        for f in features:
            feature = query.addElement('feature')
            feature['var'] = f

        stream.send(result)

    if expect_ccc:
        event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged')
        announced_ccs, = event.args
        assertSameElements(expected_caps, announced_ccs)
    else:
        # Make sure Gabble's got the caps
        sync_stream(q, stream)

    caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle])
    assertSameElements(expected_caps, caps)

    # test again, to check GetContactCapabilities does not have side effect
    caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle])
    assertSameElements(expected_caps, caps)

    # check the Contacts interface give the same caps
    caps_via_contacts_iface = conn.Contacts.GetContactAttributes(
            [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \
            [contact_handle][cs.ATTR_CONTACT_CAPABILITIES]
    assertSameElements(caps[contact_handle], caps_via_contacts_iface)
def test(q, bus, conn, stream):
    event = q.expect('stream-iq',
                     to=None,
                     query_ns='vcard-temp',
                     query_name='vCard')

    acknowledge_iq(stream, event.stanza)
    sync_stream(q, stream)
    sync_dbus(bus, q, conn)

    # A presence from a contact
    stream.send(
        make_presence('contact1@localhost/client', 'SHA1SUM-FOR-CONTACT1'))
    event = q.expect('dbus-signal', signal='AvatarUpdated')
    assert event.args[0] == 2, event.args
    assert event.args[1] == "SHA1SUM-FOR-CONTACT1", event.args

    AvatarRetrieved_event = EventPattern('dbus-signal',
                                         signal='AvatarRetrieved')
    AvatarUpdated_event = EventPattern('dbus-signal', signal='AvatarUpdated')
    StreamPresence_event = EventPattern('stream-presence')
    StreamIqVcard_event = EventPattern('stream-iq', query_ns='vcard-temp')

    # A presence from myself on another resource
    stream.send(
        make_presence('test@localhost/resource1', 'SHA1SUM-FOR-MYSELF-RES1'))
    q.forbid_events([AvatarRetrieved_event, AvatarUpdated_event])
    stream_presence, stream_iq = q.expect_many(
        EventPattern('stream-presence'),
        EventPattern('stream-iq',
                     to=None,
                     query_ns='vcard-temp',
                     query_name='vCard'))
    sync_dbus(bus, q, conn)
    q.unforbid_events([AvatarRetrieved_event, AvatarUpdated_event])

    # If the server wrongly send a presence stanza with our resource,
    # AvatarUpdated must not be emitted
    q.forbid_events([
        StreamPresence_event, StreamIqVcard_event, AvatarRetrieved_event,
        AvatarUpdated_event
    ])
    stream.send(make_presence('test@localhost/Resource', 'SHA1SUM-FOR-MYSELF'))
    sync_dbus(bus, q, conn)
    sync_stream(q, stream)
    q.unforbid_events([
        StreamPresence_event, StreamIqVcard_event, AvatarRetrieved_event,
        AvatarUpdated_event
    ])
示例#29
0
def test(q, bus, conn, stream):
    expect_get_and_send_item_not_found(q, stream)

    sync_stream(q, stream)

    call_async(
        q, conn.Avatars, 'SetAvatar', 'Guy.brush', 'image/x-mighty-pirate')

    # Gabble checks again, but we still don't have a vCard
    expect_get_and_send_item_not_found(q, stream)

    # Never mind! It creates a new one.
    expect_and_handle_set_vcard(q, stream)

    q.expect('dbus-return', method='SetAvatar')
示例#30
0
    def send_presence_and_caps(self):
        # We need remote end's presence for capabilities
        self.stream.send(self.jp.xml(
            self.jp.Presence(self.peer, self.jid, self.remote_caps)))

        # Gabble doesn't trust it, so makes a disco
        event = self.q.expect('stream-iq', query_ns=ns.DISCO_INFO, to=self.peer)

        # jt.send_remote_disco_reply(event.stanza)
        self.stream.send(self.jp.xml(self.jp.ResultIq(self.jid, event.stanza,
            [ self.jp.Query(None, ns.DISCO_INFO,
                [ self.jp.Feature(x) for x in self.jp.features ]) ]) ))

        # Force Gabble to process the caps before doing any more Jingling
        sync_stream(self.q, self.stream)
def setup_tests(q, bus, conn, stream, announce=False):
    bare_jid = "*****@*****.**"
    full_jid = bare_jid + "/HotHotResource"

    if announce:
        presence_and_disco(q, conn, stream, full_jid,
                           True, client, caps,
                           features, identity, {},
                           True, None)

        sync_stream(q, stream)

    handle = conn.RequestHandles(cs.HT_CONTACT, [full_jid])[0]

    return handle, bare_jid, full_jid
def test_dont_get_roster(q, bus, conn, stream):
    # DownloadAtConnection = False, so let's make sure the roster
    # isn't fetched automatically
    q.forbid_events(forbidden)

    conn.Connect()
    q.expect_many(EventPattern('dbus-signal', signal='StatusChanged',
                args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))
    sync_stream(q, stream)
    q.unforbid_events(forbidden)

    # seems fine, now calling Download should try and get the roster
    # successfully.
    call_async(q, conn.ContactList, 'Download')

    q.expect_many(EventPattern('stream-iq', query_ns=ns.ROSTER),
                  EventPattern('dbus-return', method='Download'))
def test(q, bus, conn, stream):
    expect_and_handle_get_vcard(q, stream)
    sync_stream(q, stream)

    call_async(
        q, conn.Avatars, 'SetAvatar', b'Guy.brush', 'image/x-mighty-pirate')
    expect_and_handle_get_vcard(q, stream)
    iq_event = q.expect(
        'stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard')
    call_async(
        q, conn.Avatars, 'SetAvatar', b'LeChuck.brush', 'image/x-ghost-pirate')

    disconnect_conn(q, conn, stream)

    q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
    q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
    sync_dbus(bus, q, conn)
def receive_caps(q,
                 conn,
                 stream,
                 contact,
                 contact_handle,
                 features,
                 expected_caps,
                 expect_disco=True,
                 expect_ccc=True):

    caps = {
        'node': client,
        'ver': compute_caps_hash([], features, {}),
        'hash': 'sha-1'
    }

    presence_and_disco(q,
                       conn,
                       stream,
                       contact,
                       expect_disco,
                       client,
                       caps,
                       features,
                       initial=False)

    if expect_ccc:
        event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged')
        announced_ccs, = event.args
        assertSameElements(expected_caps, announced_ccs[contact_handle])
    else:
        # Make sure Gabble's got the caps
        sync_stream(q, stream)

    caps = get_contacts_capabilities_sync(conn, [contact_handle])
    assertSameElements(expected_caps, caps[contact_handle])

    # test again, to check GetContactCapabilities does not have side effect
    caps = get_contacts_capabilities_sync(conn, [contact_handle])
    assertSameElements(expected_caps, caps[contact_handle])

    # check the Contacts interface give the same caps
    caps_via_contacts_iface = conn.Contacts.GetContactAttributes(
            [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \
            [contact_handle][cs.ATTR_CONTACT_CAPABILITIES]
    assertSameElements(caps[contact_handle], caps_via_contacts_iface)
def connect_and_announce_alice(q, bus, conn, stream):
    q.forbid_events(proxy_query_events)

    # Send Alice's presence
    caps =  { 'ext': '', 'ver': '0.0.0',
        'node': 'http://example.com/fake-client0' }
    presence = make_presence('alice@localhost/Test', caps=caps)
    stream.send(presence)

    disco_event = q.expect('stream-iq', to='alice@localhost/Test',
        query_ns=ns.DISCO_INFO)

    send_disco_reply(
        stream, disco_event.stanza, [], [ns.TUBES, ns.FILE_TRANSFER])
    sync_stream(q, stream)

    q.unforbid_events(proxy_query_events)
def test(q, bus, conn, stream):
    # Gabble asks for the roster; the server sends back an empty roster.
    event = q.expect('stream-iq', query_ns=ns.ROSTER)
    acknowledge_iq(stream, event.stanza)

    q.expect('dbus-signal',
             signal='ContactListStateChanged',
             args=[cs.CONTACT_LIST_STATE_SUCCESS])

    # The server sends us a roster push without an id=''. WTF!
    iq = make_roster_push(stream, jid, 'both')
    del iq['id']
    stream.send(iq)

    h = conn.get_contact_handle_sync(jid)
    q.expect_many(
        EventPattern(
            'dbus-signal',
            signal='ContactsChangedWithID',
            args=[{
                h: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''),
            }, {
                h: jid
            }, {}],
        ), )

    # Verify that Gabble didn't crash while trying to ack the push.
    sync_stream(q, stream)

    # Just for completeness, let's repeat this test with a malicious roster
    # push from a contact (rather than from our server). Our server's *really*
    # broken if it allows this. Nonetheless...
    iq = make_roster_push(stream, '*****@*****.**', 'both')
    del iq['id']
    iq['from'] = '*****@*****.**'
    stream.send(iq)

    q.forbid_events([
        EventPattern('dbus-signal', signal='ContactsChangedWithID'),
    ])
    # Make sure Gabble's got the evil push...
    sync_stream(q, stream)
    # ...and make sure it's not emitted anything.
    sync_dbus(bus, q, conn)
def test_dont_get_roster(q, bus, conn, stream):
    # DownloadAtConnection = False, so let's make sure the roster
    # isn't fetched automatically
    q.forbid_events(forbidden)

    conn.Connect()
    q.expect_many(
        EventPattern('dbus-signal',
                     signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))
    sync_stream(q, stream)
    q.unforbid_events(forbidden)

    # seems fine, now calling Download should try and get the roster
    # successfully.
    call_async(q, conn.ContactList, 'Download')

    q.expect_many(EventPattern('stream-iq', query_ns=ns.ROSTER),
                  EventPattern('dbus-return', method='Download'))
示例#38
0
def proxy_error(q, bus, conn, stream):
    # Test if another proxy is queried if a query failed
    connect_and_announce_alice(q, bus, conn, stream)

    send_file_to_alice(q, conn)

    return_event, e1, e2, e3 = q.expect_many(
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS),
        EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS),
        EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS))

    # Return errors for all the requests; the bugged proxies shouldn't be queried again
    q.forbid_events([
        EventPattern('stream-iq',
                     to=e1.stanza['to'],
                     iq_type='get',
                     query_ns=ns.BYTESTREAMS)
    ])
    send_error_reply(stream, e1.stanza)

    # the fourth proxy is queried
    q.expect('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS)

    q.forbid_events([
        EventPattern('stream-iq',
                     to=e2.stanza['to'],
                     iq_type='get',
                     query_ns=ns.BYTESTREAMS)
    ])
    send_error_reply(stream, e2.stanza)
    sync_stream(q, stream)

    q.forbid_events([
        EventPattern('stream-iq',
                     to=e3.stanza['to'],
                     iq_type='get',
                     query_ns=ns.BYTESTREAMS)
    ])
    send_error_reply(stream, e3.stanza)
    sync_stream(q, stream)
示例#39
0
def connect_and_announce_alice(q, bus, conn, stream):
    q.forbid_events(proxy_query_events)

    # Send Alice's presence
    caps = {
        'ext': '',
        'ver': '0.0.0',
        'node': 'http://example.com/fake-client0'
    }
    presence = make_presence('alice@localhost/Test', caps=caps)
    stream.send(presence)

    disco_event = q.expect('stream-iq',
                           to='alice@localhost/Test',
                           query_ns=ns.DISCO_INFO)

    send_disco_reply(stream, disco_event.stanza, [],
                     [ns.TUBES, ns.FILE_TRANSFER])
    sync_stream(q, stream)

    q.unforbid_events(proxy_query_events)