Esempio n. 1
0
def test_invisible_on_connect_fail(q, bus, conn, stream):
    props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE)
    assertNotEquals({}, props['Statuses'])

    presence_event_pattern = EventPattern('stream-presence')

    q.forbid_events([presence_event_pattern])

    conn.SimplePresence.SetPresence("hidden", "")

    conn.Connect()

    stream.handle_get_all_privacy_lists(q, bus, conn)

    create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    # Check its name
    assertNotEquals([],
        xpath.queryForNodes('/query/list/item/presence-out', create_list.query))
    acknowledge_iq(stream, create_list.stanza)

    set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    active = xpath.queryForNodes('//active', set_active.query)[0]
    assertEquals('invisible', active['name'])
    send_error_reply(stream, set_active.stanza)

    q.unforbid_events([presence_event_pattern])

    # Darn! At least we should have our presence set to DND.
    q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged',
                     interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
                     args=[{1: (6, 'dnd', '')}]),
        EventPattern('dbus-signal', signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))
Esempio n. 2
0
def test_error(q, bus, conn, stream):
    assertContains(cs.CONN_IFACE_POWER_SAVING,
                  conn.Get(cs.CONN, "Interfaces",
                           dbus_interface=cs.PROPERTIES_IFACE))

    assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING,
                                  "PowerSavingActive",
                                  dbus_interface=cs.PROPERTIES_IFACE))

    call_async(q, conn.PowerSaving, 'SetPowerSaving', True)

    stanza = expect_command(q, 'enable')

    error = domish.Element((None, 'error'))

    error.addElement((ns.STANZA, 'service-unavailable'))

    send_error_reply(stream, stanza, error)

    q.expect('dbus-error', method='SetPowerSaving', name=cs.NOT_AVAILABLE)

    # Power saving state should remain false
    assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING,
                                  "PowerSavingActive",
                                  dbus_interface=cs.PROPERTIES_IFACE))
def test(q, bus, conn, stream):
    expect_and_handle_get_vcard(q, stream)
    sync_stream(q, stream)

    call_async(q, conn.Avatars, 'SetAvatar', b'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()
Esempio n. 4
0
def test_invisible_on_connect_fail_no_list(q, bus, conn, stream):
    props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE)
    assertNotEquals({}, props['Statuses'])

    presence_event_pattern = EventPattern('stream-presence')

    q.forbid_events([presence_event_pattern])

    conn.SimplePresence.SetPresence("hidden", "")

    conn.Connect()

    stream.handle_get_all_privacy_lists(q, bus, conn)

    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get')
    list_node = xpath.queryForNodes('//list', get_list.query)[0]
    assertEquals('invisible', list_node['name'])

    send_error_reply(stream, get_list.stanza)

    q.unforbid_events([presence_event_pattern])

    # Darn! At least we should have our presence set to DND.
    q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged',
                     interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
                     args=[{1: (6, 'dnd', '')}]),
        EventPattern('dbus-signal', signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))

    # 'hidden' should not be an available status.
    assertDoesNotContain("hidden",
        conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))
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()
Esempio n. 6
0
def test_create_invisible_list(q, bus, conn, stream):
    conn.SimplePresence.SetPresence("away", "")

    conn.Connect()

    stream.handle_get_all_privacy_lists(q, bus, conn)

    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get')
    list_node = xpath.queryForNodes('//list', get_list.query)[0]
    assertEquals('invisible', list_node['name'])

    error = domish.Element((None, 'error'))
    error['type'] = 'cancel'
    error.addElement((ns.STANZA, 'item-not-found'))
    send_error_reply (stream, get_list.stanza, error)

    create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    list_node = xpath.queryForNodes('//list', create_list.query)[0]
    assertEquals('invisible', list_node['name'])
    assertNotEquals([],
        xpath.queryForNodes('/query/list/item/presence-out', create_list.query))
    acknowledge_iq(stream, create_list.stanza)

    q.expect('dbus-signal', signal='StatusChanged',
        args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    assertContains("hidden",
        conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))
def test_create_invisible_list_failed(q, bus, conn, stream):
    conn.SimplePresence.SetPresence("away", "")

    conn.Connect()

    stream.handle_get_all_privacy_lists(q, bus, conn)

    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get')
    list_node = xpath.queryForNodes('//list', get_list.query)[0]
    assertEquals('invisible', list_node['name'])

    error = domish.Element((None, 'error'))
    error['type'] = 'cancel'
    error.addElement((ns.STANZA, 'item-not-found'))
    send_error_reply(stream, get_list.stanza, error)

    create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    list_node = xpath.queryForNodes('//list', create_list.query)[0]
    assertEquals('invisible', list_node['name'])
    assertNotEquals([],
                    xpath.queryForNodes('/query/list/item/presence-out',
                                        create_list.query))
    send_error_reply(stream, create_list.stanza)

    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    assertDoesNotContain(
        "hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE,
                                      "Statuses"))
Esempio n. 8
0
def test_error(q, bus, conn, stream):
    assertContains(
        cs.CONN_IFACE_POWER_SAVING,
        conn.Get(cs.CONN, "Interfaces", dbus_interface=cs.PROPERTIES_IFACE))

    assertEquals(
        False,
        conn.Get(cs.CONN_IFACE_POWER_SAVING,
                 "PowerSavingActive",
                 dbus_interface=cs.PROPERTIES_IFACE))

    call_async(q, conn.PowerSaving, 'SetPowerSaving', True)

    stanza = expect_command(q, 'enable')

    error = domish.Element((None, 'error'))

    error.addElement((ns.STANZA, 'service-unavailable'))

    send_error_reply(stream, stanza, error)

    q.expect('dbus-error', method='SetPowerSaving', name=cs.NOT_AVAILABLE)

    # Power saving state should remain false
    assertEquals(
        False,
        conn.Get(cs.CONN_IFACE_POWER_SAVING,
                 "PowerSavingActive",
                 dbus_interface=cs.PROPERTIES_IFACE))
def expect_get_and_send_item_not_found(q, stream):
    get_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP,
        query_name='vCard', iq_type='get')

    error = domish.Element((None, 'error'))
    error['type'] = 'cancel'
    error.addElement((ns.STANZA, 'item-not-found'))
    send_error_reply(stream, get_vcard_event.stanza, error)
def test(q, bus, conn, stream):
    statuses = conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, 'Statuses')

    # testbusy and testaway are provided by test plugin
    assertContains('testbusy', statuses)
    assertContains('testaway', statuses)

    assertEquals(statuses['testbusy'][0], cs.PRESENCE_BUSY)
    assertEquals(statuses['testaway'][0], cs.PRESENCE_AWAY)

    conn.SimplePresence.SetPresence('testbusy', '')

    conn.Connect()

    # ... gabble asks for all the available lists on the server ...
    stream.handle_get_all_privacy_lists(
        q, bus, conn, lists=["foo-list", "test-busy-list", "bar-list"])

    # ... gabble checks whether there's usable invisible list on the server ...
    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get')
    list_node = xpath.queryForNodes('//list', get_list.query)[0]
    assertEquals('invisible', list_node['name'])

    error = domish.Element((None, 'error'))
    error['type'] = 'cancel'
    error.addElement((ns.STANZA, 'item-not-found'))
    send_error_reply(stream, get_list.stanza, error)

    # ... since there is none, Gabble creates it ...
    create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    list_node = xpath.queryForNodes('//list', create_list.query)[0]
    assertEquals('invisible', list_node['name'])
    assertNotEquals([],
                    xpath.queryForNodes('/query/list/item/presence-out',
                                        create_list.query))
    acknowledge_iq(stream, create_list.stanza)

    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    list_node = xpath.queryForNodes('//active', get_list.query)[0]

    # ... and then activates the one linked with the requested status
    # Note: testbusy status is linked to test-busy-list by test plugin
    assertEquals('test-busy-list', list_node['name'])
    acknowledge_iq(stream, get_list.stanza)

    q.expect('dbus-signal',
             signal='PresencesChanged',
             args=[{
                 1: (cs.PRESENCE_BUSY, u'testbusy', '')
             }])
    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])

    # ... testaway is not supposed to be settable on us
    call_async(q, conn.SimplePresence, 'SetPresence', 'testaway', '')
    q.expect('dbus-error', method='SetPresence', name=cs.INVALID_ARGUMENT)
def forbidden(q, stream, conn):
    iq = call_create(q, conn, 'notforyou.localhost')

    e = domish.Element((None, 'error'))
    e['type'] = 'cancel'
    e.addElement((ns.STANZA, 'forbidden'))
    send_error_reply(stream, iq, e)

    event = q.expect('dbus-error', method='CreateChannel')
    assertDBusError(cs.PERMISSION_DENIED, event.error)
Esempio n. 12
0
def not_a_search_server(q, stream, conn):
    iq = call_create(q, conn, 'notajud.localhost')

    e = domish.Element((None, 'error'))
    e['type'] = 'cancel'
    e.addElement((ns.STANZA, 'service-unavailable'))
    send_error_reply(stream, iq, e)

    event = q.expect('dbus-error', method='CreateChannel')
    assertDBusError(cs.NOT_AVAILABLE, event.error)
def invalid_jid(q, stream, conn):
    iq = call_create(q, conn, 'invalid.localhost')

    e = domish.Element((None, 'error'))
    e['type'] = 'cancel'
    e.addElement((ns.STANZA, 'jid-malformed'))
    send_error_reply(stream, iq, e)

    event = q.expect('dbus-error', method='CreateChannel')
    assertDBusError(cs.INVALID_ARGUMENT, event.error)
Esempio n. 14
0
def forbidden(q, stream, conn):
    iq = call_create(q, conn, 'notforyou.localhost')

    e = domish.Element((None, 'error'))
    e['type'] = 'cancel'
    e.addElement((ns.STANZA, 'forbidden'))
    send_error_reply(stream, iq, e)

    event = q.expect('dbus-error', method='CreateChannel')
    assertDBusError(cs.PERMISSION_DENIED, event.error)
def not_a_search_server(q, stream, conn):
    iq = call_create(q, conn, 'notajud.localhost')

    e = domish.Element((None, 'error'))
    e['type'] = 'cancel'
    e.addElement((ns.STANZA, 'service-unavailable'))
    send_error_reply(stream, iq, e)

    event = q.expect('dbus-error', method='CreateChannel')
    assertDBusError(cs.NOT_AVAILABLE, event.error)
Esempio n. 16
0
def invalid_jid(q, stream, conn):
    iq = call_create(q, conn, 'invalid.localhost')

    e = domish.Element((None, 'error'))
    e['type'] = 'cancel'
    e.addElement((ns.STANZA, 'jid-malformed'))
    send_error_reply(stream, iq, e)

    event = q.expect('dbus-error', method='CreateChannel')
    assertDBusError(cs.INVALID_ARGUMENT, event.error)
def test_conflict(q, bus, conn, stream):
    iq = connect_and_send_form(q, conn, stream)

    error = domish.Element((None, 'error'))
    error['code'] = '409'
    error['type'] = 'cancel'
    error.addElement((ns.STANZA, 'conflict'))
    send_error_reply(stream, iq, error)

    q.expect('dbus-signal', signal='StatusChanged',
        args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NAME_IN_USE])
 def _cb_bare_jid_disco_iq(self, iq):
     """
     \o\ /o/ <o/ \o> /o> ...
     "Crap! It's the cops! Turn the music off!"
     """
     send_error_reply(self, iq,
         error_stanza=elem('error')(
             elem(ns.STANZA, 'feature-not-implemented'),
             elem(ns.STANZA, 'text')(
                 u'No, officer! This is certainly not an illegal party.')
             ))
Esempio n. 19
0
def test_not_acceptable(q, gateways_iface, stream):
    call_async(q, gateways_iface, 'Register',
            'fully-captcha-enabled.example.com', 'lalala', 'stoats')
    e = q.expect('stream-iq', iq_type='set', query_name='query',
            query_ns=ns.REGISTER, to='fully-captcha-enabled.example.com')
    assertEquals('lalala', xpath.queryForString('/query/username', e.query))
    assertEquals('stoats', xpath.queryForString('/query/password', e.query))
    error = domish.Element((None, 'error'))
    error['type'] = 'modify'
    error['code'] = '406'
    error.addElement((ns.STANZA, 'not-acceptable'))
    send_error_reply(stream, e.stanza, error)
    q.expect('dbus-error', method='Register', name=cs.NOT_AVAILABLE)
Esempio n. 20
0
def test_conflict(q, gateways_iface, stream):
    call_async(q, gateways_iface, 'Register',
            'sip.example.com', '8675309', 'jenny')
    e = q.expect('stream-iq', iq_type='set', query_name='query',
            query_ns=ns.REGISTER, to='sip.example.com')
    assertEquals('8675309', xpath.queryForString('/query/username', e.query))
    assertEquals('jenny', xpath.queryForString('/query/password', e.query))
    error = domish.Element((None, 'error'))
    error['type'] = 'cancel'
    error['code'] = '409'
    error.addElement((ns.STANZA, 'conflict'))
    send_error_reply(stream, e.stanza, error)
    q.expect('dbus-error', method='Register', name=cs.REGISTRATION_EXISTS)
Esempio n. 21
0
def test_invisible_on_connect_fails(q, bus, conn, stream):
    conn.SimplePresence.SetPresence("hidden", "")
    conn.Connect()

    event = q.expect('stream-iq', query_name='invisible')
    send_error_reply(stream, event.stanza)

    # Darn! At least we should have our presence set to DND.
    q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged',
                     interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
                     args=[{1: (6, 'dnd', '')}]),
        EventPattern('dbus-signal', signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))
def test_conflict(q, bus, conn, stream):
    iq = connect_and_send_form(q, conn, stream)

    error = domish.Element((None, 'error'))
    error['code'] = '409'
    error['type'] = 'cancel'
    error.addElement((ns.STANZA, 'conflict'))
    send_error_reply(stream, iq, error)

    e = q.expect('dbus-signal', signal='ConnectionError')
    assertEquals(cs.REGISTRATION_EXISTS, e.args[0])
    q.expect('dbus-signal',
             signal='StatusChanged',
             args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NAME_IN_USE])
Esempio n. 23
0
def test_invisible_fails(q, bus, conn, stream):
    assertContains("hidden",
        conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))

    conn.SimplePresence.SetPresence("hidden", "")

    # First we send an <invisible/> command.
    event = q.expect('stream-iq', query_name='invisible')
    send_error_reply(stream, event.stanza)

    # When that fails, we should expect our status to change to dnd.
    q.expect('dbus-signal', signal='PresencesChanged',
                     interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
                     args=[{1: (6, 'dnd', '')}])
Esempio n. 24
0
def test(q, bus, conn, stream):
    statuses = conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE,
        'Statuses')

    # testbusy and testaway are provided by test plugin
    assertContains('testbusy', statuses)
    assertContains('testaway', statuses)

    assertEquals(statuses['testbusy'][0], cs.PRESENCE_BUSY)
    assertEquals(statuses['testaway'][0], cs.PRESENCE_AWAY)

    conn.SimplePresence.SetPresence('testbusy', '')

    conn.Connect()

    # ... gabble asks for all the available lists on the server ...
    stream.handle_get_all_privacy_lists(q, bus, conn,
        lists=["foo-list", "test-busy-list", "bar-list"])

    # ... gabble checks whether there's usable invisible list on the server ...
    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get')
    list_node = xpath.queryForNodes('//list', get_list.query)[0]
    assertEquals('invisible', list_node['name'])

    error = domish.Element((None, 'error'))
    error['type'] = 'cancel'
    error.addElement((ns.STANZA, 'item-not-found'))
    send_error_reply (stream, get_list.stanza, error)

    # ... since there is none, Gabble creates it ...
    create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    list_node = xpath.queryForNodes('//list', create_list.query)[0]
    assertEquals('invisible', list_node['name'])
    assertNotEquals([],
        xpath.queryForNodes('/query/list/item/presence-out',
            create_list.query))
    acknowledge_iq(stream, create_list.stanza)

    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    list_node = xpath.queryForNodes('//active', get_list.query)[0]

    # ... and then activates the one linked with the requested status
    # Note: testbusy status is linked to test-busy-list by test plugin
    assertEquals('test-busy-list', list_node['name'])
    acknowledge_iq(stream, get_list.stanza)

    q.expect('dbus-signal', signal='PresencesChanged',
        args=[{1L: (cs.PRESENCE_BUSY, u'testbusy', '')}])
def test_conflict(q, gateways_iface, stream):
    call_async(q, gateways_iface, 'Register', 'sip.example.com', '8675309',
               'jenny')
    e = q.expect('stream-iq',
                 iq_type='set',
                 query_name='query',
                 query_ns=ns.REGISTER,
                 to='sip.example.com')
    assertEquals('8675309', xpath.queryForString('/query/username', e.query))
    assertEquals('jenny', xpath.queryForString('/query/password', e.query))
    error = domish.Element((None, 'error'))
    error['type'] = 'cancel'
    error['code'] = '409'
    error.addElement((ns.STANZA, 'conflict'))
    send_error_reply(stream, e.stanza, error)
    q.expect('dbus-error', method='Register', name=cs.REGISTRATION_EXISTS)
def test_not_acceptable(q, gateways_iface, stream):
    call_async(q, gateways_iface, 'Register',
               'fully-captcha-enabled.example.com', 'lalala', 'stoats')
    e = q.expect('stream-iq',
                 iq_type='set',
                 query_name='query',
                 query_ns=ns.REGISTER,
                 to='fully-captcha-enabled.example.com')
    assertEquals('lalala', xpath.queryForString('/query/username', e.query))
    assertEquals('stoats', xpath.queryForString('/query/password', e.query))
    error = domish.Element((None, 'error'))
    error['type'] = 'modify'
    error['code'] = '406'
    error.addElement((ns.STANZA, 'not-acceptable'))
    send_error_reply(stream, e.stanza, error)
    q.expect('dbus-error', method='Register', name=cs.NOT_AVAILABLE)
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)
def test_invisible_on_connect_fail(q, bus, conn, stream):
    props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE)
    assertNotEquals({}, props['Statuses'])

    presence_event_pattern = EventPattern('stream-presence')

    q.forbid_events([presence_event_pattern])

    conn.SimplePresence.SetPresence("hidden", "")

    conn.Connect()

    stream.handle_get_all_privacy_lists(q, bus, conn)

    create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    # Check its name
    assertNotEquals([],
                    xpath.queryForNodes('/query/list/item/presence-out',
                                        create_list.query))
    acknowledge_iq(stream, create_list.stanza)

    set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set')
    active = xpath.queryForNodes('//active', set_active.query)[0]
    assertEquals('invisible', active['name'])
    send_error_reply(stream, set_active.stanza)

    q.unforbid_events([presence_event_pattern])

    # Darn! At least we should have our presence set to DND.
    q.expect_many(
        EventPattern('dbus-signal',
                     signal='PresencesChanged',
                     interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
                     args=[{
                         1: (6, 'dnd', '')
                     }]),
        EventPattern('dbus-signal',
                     signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))
Esempio n. 29
0
def returns_error_from_search(q, stream, conn):
    server = 'nofunforyou.localhost'
    iq = call_create(q, conn, server)

    result = make_result_iq(stream, iq)
    query = result.firstChildElement()
    query.addElement("first")
    stream.send(result)

    event = q.expect('dbus-return', method='CreateChannel')
    c = make_channel_proxy(conn, event.value[0], 'Channel')
    c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH)

    call_async(q, c_search, 'Search', {'x-n-given': 'World of Goo'})
    iq_event, _ = q.expect_many(
        EventPattern('stream-iq', to=server, query_ns=ns.SEARCH),
        EventPattern('dbus-signal', signal='SearchStateChanged'),
    )

    iq = iq_event.stanza
    error = domish.Element((None, 'error'))
    error['type'] = 'modify'
    error.addElement((ns.STANZA, 'not-acceptable'))
    error.addElement((ns.STANZA, 'text'),
                     content="We don't believe in games here.")
    send_error_reply(stream, iq, error)

    ssc = q.expect('dbus-signal', signal='SearchStateChanged')
    new_state, reason, details = ssc.args

    assert new_state == cs.SEARCH_FAILED, new_state
    assert reason == cs.PERMISSION_DENIED, reason

    # We call stop after the search has failed; it should succeed and do nothing.
    call_async(q, c_search, 'Stop')
    event = q.expect('dbus-return', method='Stop')

    c.Close()
def test_invisible_on_connect_fail_no_list(q, bus, conn, stream):
    props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE)
    assertNotEquals({}, props['Statuses'])

    presence_event_pattern = EventPattern('stream-presence')

    q.forbid_events([presence_event_pattern])

    conn.SimplePresence.SetPresence("hidden", "")

    conn.Connect()

    stream.handle_get_all_privacy_lists(q, bus, conn)

    get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get')
    list_node = xpath.queryForNodes('//list', get_list.query)[0]
    assertEquals('invisible', list_node['name'])

    send_error_reply(stream, get_list.stanza)

    q.unforbid_events([presence_event_pattern])

    # Darn! At least we should have our presence set to DND.
    q.expect_many(
        EventPattern('dbus-signal',
                     signal='PresencesChanged',
                     interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
                     args=[{
                         1: (6, 'dnd', '')
                     }]),
        EventPattern('dbus-signal',
                     signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))

    # 'hidden' should not be an available status.
    assertDoesNotContain(
        "hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE,
                                      "Statuses"))
    def privacy_list_iq_cb(self, iq):
        if iq.getAttribute("type") == 'set':
            active = xpath.queryForNodes("//active", iq)

            if active and ('name' not in active[0].attributes
                           or active[0]['name'] == 'invisible'):
                acknowledge_iq(self, iq)
            else:
                # Don't allow other lists to be activated; and don't allow
                # modifications.
                send_error_reply(self, iq)
        else:
            requested_lists = xpath.queryForNodes('//list', iq)

            if not requested_lists:
                self.send_privacy_list_list(iq['id'], ['invisible'])
            elif requested_lists[0]['name'] == 'invisible':
                self.send_privacy_list(iq, [
                    elem('item', action='deny', order='1')(
                        elem('presence-out'))
                ])
            else:
                send_error_reply(self, iq, elem(ns.STANZA, 'item-not-found'))
def returns_error_from_search(q, stream, conn):
    server = 'nofunforyou.localhost'
    iq = call_create(q, conn, server)

    result = make_result_iq(stream, iq)
    query = result.firstChildElement()
    query.addElement("first")
    stream.send(result)

    event = q.expect('dbus-return', method='CreateChannel')
    c = make_channel_proxy(conn, event.value[0], 'Channel')
    c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH)

    call_async(q, c_search, 'Search', {'x-n-given': 'World of Goo'})
    iq_event, _ = q.expect_many(
        EventPattern('stream-iq', to=server, query_ns=ns.SEARCH),
        EventPattern('dbus-signal', signal='SearchStateChanged'),
        )

    iq = iq_event.stanza
    error = domish.Element((None, 'error'))
    error['type'] = 'modify'
    error.addElement((ns.STANZA, 'not-acceptable'))
    error.addElement((ns.STANZA, 'text'), content="We don't believe in games here.")
    send_error_reply(stream, iq, error)

    ssc = q.expect('dbus-signal', signal='SearchStateChanged')
    new_state, reason, details = ssc.args

    assert new_state == cs.SEARCH_FAILED, new_state
    assert reason == cs.PERMISSION_DENIED, reason

    # We call stop after the search has failed; it should succeed and do nothing.
    call_async(q, c_search, 'Stop')
    event = q.expect('dbus-return', method='Stop')

    c.Close()
Esempio n. 33
0
    def privacy_list_iq_cb(self, iq):
        if iq.getAttribute("type") == 'set':
            active = xpath.queryForNodes("//active", iq)

            if active and ('name' not in active[0].attributes or
                           active[0]['name'] == 'invisible'):
                acknowledge_iq(self, iq)
            else:
                # Don't allow other lists to be activated; and don't allow
                # modifications.
                send_error_reply(self, iq)
        else:
            requested_lists = xpath.queryForNodes('//list', iq)

            if not requested_lists:
                self.send_privacy_list_list(iq['id'], ['invisible'])
            elif requested_lists[0]['name'] == 'invisible':
                self.send_privacy_list(iq,
                    [elem('item', action='deny', order='1')(
                        elem('presence-out')
                      )
                    ])
            else:
                send_error_reply(self, iq, elem(ns.STANZA, 'item-not-found'))
Esempio n. 34
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)
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control,
         access_control_param):
    if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]:
        # disable SOCKS5 relay tests because proxy can't be used with muc
        # contacts atm
        return

    if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS:
        print("Skip Socket_Access_Control_Credentials (fdo #45445)")
        return

    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq',
                     to=None,
                     query_ns='vcard-temp',
                     query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    # join the muc
    call_async(
        q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: '*****@*****.**'
        })

    q.expect_many(
        EventPattern(
            'dbus-signal',
            signal='MembersChangedDetailed',
            predicate=lambda e: e.args[0] == [] and  # added
            e.args[1] == [] and  # removed
            e.args[2] == [] and  # local pending
            len(e.args[3]) == 1 and  # remote pending
            e.args[4].get('actor', 0) == 0 and e.args[4].get(
                'change-reason', 0) == 0 and e.args[4]['contact-ids'][e.args[
                    3][0]] == '[email protected]/test'),
        EventPattern('stream-presence', to='[email protected]/test'))

    # Send presence for other member of room.
    stream.send(
        make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob'))

    # Send presence for own membership of room.
    stream.send(
        make_muc_presence('none', 'participant', '*****@*****.**',
                          'test'))

    event = q.expect(
        'dbus-signal',
        signal='MembersChangedDetailed',
        predicate=lambda e: len(e.args[0]) == 2 and  # added
        e.args[1] == [] and  # removed
        e.args[2] == [] and  # local pending
        e.args[3] == [] and  # remote pending
        e.args[4].get('actor', 0) == 0 and e.args[4].get('change-reason', 0) ==
        0 and set([e.args[4]['contact-ids'][h] for h in e.args[0]]) == set(
            ['[email protected]/test', '[email protected]/bob']))

    for h in event.args[0]:
        if event.args[4]['contact-ids'][h] == '[email protected]/bob':
            bob_handle = h

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

    # Bob offers a stream tube
    stream_tube_id = 666
    presence = make_muc_presence('owner', 'moderator', '*****@*****.**',
                                 'bob')
    tubes = presence.addElement((ns.TUBES, 'tubes'))
    tube = tubes.addElement((None, 'tube'))
    tube['type'] = 'stream'
    tube['service'] = 'echo'
    tube['id'] = str(stream_tube_id)
    parameters = tube.addElement((None, 'parameters'))
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 's'
    parameter['type'] = 'str'
    parameter.addContent('hello')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'ay'
    parameter['type'] = 'bytes'
    parameter.addContent('aGVsbG8=')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'u'
    parameter['type'] = 'uint'
    parameter.addContent('123')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'i'
    parameter['type'] = 'int'
    parameter.addContent('-123')

    stream.send(presence)

    # text channel
    new_event = q.expect('dbus-signal', signal='NewChannels')

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT

    def new_chan_predicate(e):
        path, props = e.args[0][0]
        return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE

    # tube channel is announced
    new_event = q.expect('dbus-signal',
                         signal='NewChannels',
                         predicate=new_chan_predicate)

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert props[cs.INITIATOR_HANDLE] == bob_handle
    assert props[cs.INITIATOR_ID] == '[email protected]/bob'
    assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE],
                   props[cs.INTERFACES])
    assert props[cs.REQUESTED] == False
    assert props[cs.TARGET_ID] == '*****@*****.**'
    assert props[cs.STREAM_TUBE_SERVICE] == 'echo'
    assert props[cs.TUBE_PARAMETERS] == {
        's': 'hello',
        'ay': b'hello',
        'u': 123,
        'i': -123
    }
    assert access_control in \
            props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type]

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE,
                                  dbus_interface=cs.PROPERTIES_IFACE,
                                  byte_arrays=True)
    tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
    assert tube_props['Parameters'] == sample_parameters
    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING

    # Accept the tube
    call_async(q,
               tube_iface,
               'Accept',
               address_type,
               access_control,
               access_control_param,
               byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='Accept'),
        EventPattern('dbus-signal', signal='TubeChannelStateChanged',
                     args=[2]))

    address = accept_return_event.value[0]
    if isinstance(address, bytes):
        address = address.decode()

    socket_event, si_event, conn_id = t.connect_to_cm_socket(
        q, '[email protected]/bob', address_type, address, access_control,
        access_control_param)

    protocol = socket_event.protocol
    protocol.sendData(b"hello initiator")

    def accept_tube_si_connection():
        bytestream, profile = create_from_si_offer(stream, q, bytestream_cls,
                                                   si_event.stanza,
                                                   '[email protected]/test')

        assert profile == ns.TUBES

        muc_stream_node = xpath.queryForNodes(
            '/iq/si/muc-stream[@xmlns="%s"]' % ns.TUBES, si_event.stanza)[0]
        assert muc_stream_node is not None
        assert muc_stream_node['tube'] == str(stream_tube_id)

        # set the real jid of the target as 'to' because the XMPP server changes
        # it when delivering the IQ
        result, si = bytestream.create_si_reply(si_event.stanza,
                                                'test@localhost/Resource')
        si.addElement((ns.TUBES, 'tube'))
        stream.send(result)

        bytestream.wait_bytestream_open()
        return bytestream

    bytestream = accept_tube_si_connection()

    binary = bytestream.get_data()
    assert binary == b'hello initiator'

    # reply on the socket
    bytestream.send_data(b'hi joiner!')

    q.expect('socket-data', protocol=protocol, data=b"hi joiner!")

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(
        q, '[email protected]/bob', address_type, address, access_control,
        access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(
        q, '[email protected]/bob', address_type, address, access_control,
        access_control_param)

    protocol = socket_event.protocol
    bytestream = accept_tube_si_connection()

    # disconnect local socket
    protocol.transport.loseConnection()
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CANCELLED, e.args[1])

    # OK, we're done
    disconnect_conn(q, conn, stream)
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control,
         access_control_param):
    if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS:
        print "Skip Socket_Access_Control_Credentials (fdo #45445)"
        return

    vcard_event, roster_event, disco_event = q.expect_many(
        EventPattern('stream-iq',
                     to=None,
                     query_ns='vcard-temp',
                     query_name='vCard'),
        EventPattern('stream-iq', query_ns=ns.ROSTER),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, vcard_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    roster = roster_event.stanza
    roster['type'] = 'result'
    item = roster_event.query.addElement('item')
    item['jid'] = 'bob@localhost'  # Bob can do tubes
    item['subscription'] = 'both'
    stream.send(roster)

    # Send Bob presence and his caps
    presence = domish.Element(('jabber:client', 'presence'))
    presence['from'] = 'bob@localhost/Bob'
    presence['to'] = 'test@localhost/Resource'
    c = presence.addElement('c')
    c['xmlns'] = 'http://jabber.org/protocol/caps'
    c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy'
    c['ver'] = '1.2.3'
    stream.send(presence)

    event = q.expect('stream-iq',
                     iq_type='get',
                     query_ns='http://jabber.org/protocol/disco#info',
                     to='bob@localhost/Bob')
    assert event.query['node'] == \
        'http://example.com/ICantBelieveItsNotTelepathy#1.2.3'
    result = make_result_iq(stream, event.stanza)
    query = result.firstChildElement()
    feature = query.addElement('feature')
    feature['var'] = ns.TUBES
    stream.send(result)

    sync_dbus(bus, q, conn)

    # Receive a tube offer from Bob
    (new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)

    # Try bad parameters on the new iface
    call_async(q, new_tube_iface, 'Accept', 20, 0, '', byte_arrays=True)
    q.expect('dbus-error', method='Accept')
    call_async(q, new_tube_iface, 'Accept', 0, 1, '', byte_arrays=True)
    q.expect('dbus-error', method='Accept')

    # Receive a tube offer from Bob
    (new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)

    # Accept the tube with new iface, and use UNIX sockets
    call_async(q,
               new_tube_iface,
               'Accept',
               address_type,
               access_control,
               access_control_param,
               byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='Accept'),
        EventPattern('dbus-signal', signal='TubeChannelStateChanged',
                     args=[2]))

    socket_address = accept_return_event.value[0]

    bytestream, conn_id = expect_tube_activity(q, bus, conn, stream,
                                               bytestream_cls, address_type,
                                               socket_address, access_control,
                                               access_control_param)

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    event_socket, si_event, conn_id = t.connect_to_cm_socket(
        q, bob_jid, address_type, socket_address, access_control,
        access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    new_tube_chan.Close()

    # Receive a tube offer from Bob
    (new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)
    # Just close the tube
    new_tube_chan.Close()

    q.expect_many(EventPattern('dbus-signal', signal='Closed'),
                  EventPattern('dbus-signal', signal='ChannelClosed'))
Esempio n. 37
0
    lat = xpath.queryForNodes('/geoloc/accuracy', geoloc)[0]
    assertEquals(float(str(lat)), 1.4)

    acknowledge_iq(stream, event.stanza)
    q.expect('dbus-return', method='SetLocation')

    # Server refuses to set Location
    call_async(q, conn.Location, 'SetLocation', {'lat': 0.0, 'lon': 0.0})

    geoloc_iq_set_event = EventPattern(
        'stream-iq',
        predicate=lambda x: xpath.queryForNodes(
            "/iq/pubsub/publish/item/geoloc", x.stanza))
    event = q.expect_many(geoloc_iq_set_event)[0]

    send_error_reply(stream, event.stanza)
    q.expect('dbus-error', method='SetLocation')

    # Request Bob's location
    bob_handle = conn.get_contact_handle_sync('*****@*****.**')

    # Gabble should not send a pubsub query. The point of PEP is that we don't
    # have to do this.
    pubsub_get_pattern = EventPattern('stream-iq',
                                      iq_type='get',
                                      query_ns=ns.PUBSUB)
    q.forbid_events([pubsub_get_pattern])

    location = get_location(conn, bob_handle)
    # Location isn't known yet
    assertEquals(None, location)
Esempio n. 38
0
def test(q, bus, conn, stream):
    iq_event = q.expect('stream-iq',
                        to=None,
                        query_ns='vcard-temp',
                        query_name='vCard')

    # When we start, there is no avatar
    acknowledge_iq(stream, iq_event.stanza)
    self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")

    # Another resource confirms we have no avatar. We don't request our vCard
    # because we already know there is no avatar
    presence_stanza = make_presence('test@localhost/noavatar',
                                    to='test@localhost/Resource',
                                    show='away',
                                    status='At the pub',
                                    photo="")
    q.forbid_events([avatar_request_event, avatar_retrieved_event])
    # Gabble must resist temptation to send vCard requests even with several
    # presence stanza sent!
    stream.send(presence_stanza)
    stream.send(presence_stanza)
    sync_stream(q, stream)  # Twice because the vCard request is done in
    sync_stream(q, stream)  # g_idle_add
    q.unforbid_events([avatar_request_event, avatar_retrieved_event])

    # Request on the first contact. Test the cache.
    handle = conn.get_contact_handle_sync('*****@*****.**')
    test_get_avatar(q,
                    bus,
                    conn,
                    stream,
                    '*****@*****.**',
                    handle,
                    in_cache=False)
    test_get_avatar(q, bus, conn, stream, '*****@*****.**', handle, in_cache=True)

    # Request another vCard and get resource-constraint
    busy_contact = '*****@*****.**'
    busy_handle = conn.get_contact_handle_sync(busy_contact)
    conn.Avatars.RequestAvatars([busy_handle])

    iq_event = q.expect('stream-iq',
                        to=busy_contact,
                        query_ns='vcard-temp',
                        query_name='vCard')
    iq = iq_event.stanza
    error = domish.Element((None, 'error'))
    error['code'] = '500'
    error['type'] = 'wait'
    error.addElement((ns.STANZA, 'resource-constraint'))

    q.forbid_events([avatar_retrieved_event, avatar_request_event])
    send_error_reply(stream, iq, error)

    # Request the same vCard again during the suspended delay
    # We should not get the avatar
    conn.Avatars.RequestAvatars([busy_handle])
    sync_stream(q, stream)
    sync_dbus(bus, q, conn)
    q.unforbid_events([avatar_retrieved_event, avatar_request_event])

    # Request on a different contact, on another server
    # We should get the avatar
    handle = conn.get_contact_handle_sync('*****@*****.**')
    test_get_avatar(q, bus, conn, stream, '*****@*****.**', handle)

    # Try again the contact on the busy server.
    # We should not get the avatar
    # Note: the timeout is 3 seconds for the test suites. We assume that
    # a few stanza with be processed fast enough to avoid the race.
    q.forbid_events([avatar_retrieved_event, avatar_request_event])
    conn.Avatars.RequestAvatars([busy_handle])
    sync_stream(q, stream)
    sync_dbus(bus, q, conn)
    q.unforbid_events([avatar_retrieved_event, avatar_request_event])

    # After 3 seconds, we receive a new vCard request on the busy server
    iq_event = q.expect('stream-iq',
                        to=busy_contact,
                        query_ns='vcard-temp',
                        query_name='vCard')
    iq = make_result_iq(stream, iq_event.stanza)
    vcard = iq.firstChildElement()
    photo = vcard.addElement('PHOTO')
    photo.addElement('TYPE', content='image/png')
    photo.addElement('BINVAL', content=base64.b64encode(b'hello').decode())
    stream.send(iq)

    event = q.expect('dbus-signal', signal='AvatarRetrieved')
    assertEquals(busy_handle, event.args[0])
    assertEquals(hashlib.sha1(b'hello').hexdigest(), event.args[1])
    assertEquals(b'hello', event.args[2])
    assertEquals('image/png', event.args[3])

    # Test with our own avatar test@localhost/Resource2
    presence_stanza = make_presence('test@localhost/Resource2',
                                    to='test@localhost/Resource',
                                    show='away',
                                    status='At the pub',
                                    photo=hashlib.sha1(b':-D').hexdigest())
    stream.send(presence_stanza)
    iq_event = q.expect('stream-iq',
                        to=None,
                        query_ns='vcard-temp',
                        query_name='vCard')
    iq = make_result_iq(stream, iq_event.stanza)
    vcard = iq.firstChildElement()
    photo = vcard.addElement('PHOTO')
    photo.addElement('TYPE', content='image/png')
    photo.addElement('BINVAL', content=base64.b64encode(b':-D').decode())

    # do not send the vCard reply now. First, send another presence.
    q.forbid_events([avatar_request_event])
    stream.send(presence_stanza)
    sync_stream(q, stream)

    # Now send the reply.
    stream.send(iq)

    # Which results in an AvatarUpdated signal
    event = q.expect('dbus-signal', signal='AvatarUpdated')
    assertEquals(self_handle, event.args[0])
    assertEquals(hashlib.sha1(b':-D').hexdigest(), event.args[1])

    # So Gabble has the right hash, and no need to ask the vCard again
    stream.send(presence_stanza)
    sync_stream(q, stream)
    q.unforbid_events([avatar_request_event])

    # But if the hash is different, the vCard is asked again
    presence_stanza = make_presence('test@localhost/Resource2',
                                    to='test@localhost/Resource',
                                    show='away',
                                    status='At the pub',
                                    photo=hashlib.sha1(b'\o/').hexdigest())
    stream.send(presence_stanza)
    iq_event = q.expect('stream-iq',
                        to=None,
                        query_ns='vcard-temp',
                        query_name='vCard')
    iq = make_result_iq(stream, iq_event.stanza)
    vcard = iq.firstChildElement()
    photo = vcard.addElement('PHOTO')
    photo.addElement('TYPE', content='image/png')
    photo.addElement('BINVAL', content=base64.b64encode(b'\o/').decode())
    stream.send(iq)

    event = q.expect('dbus-signal', signal='AvatarUpdated')
    assertEquals(self_handle, event.args[0])
    assertEquals(hashlib.sha1(b'\o/').hexdigest(), event.args[1])

    # Gabble must reply without asking the vCard to the server because the
    # avatar must be in the cache
    q.forbid_events([avatar_request_event])
    conn.Avatars.RequestAvatars([self_handle])
    e = q.expect('dbus-signal', signal='AvatarRetrieved')
    assertEquals(b'\o/', e.args[2])
    conn.Avatars.RequestAvatars([handle])
    e = q.expect('dbus-signal', signal='AvatarRetrieved')
    assertEquals(b'hello', e.args[2])
    q.unforbid_events([avatar_request_event])

    # First, ensure the pipeline is full
    contacts = ['*****@*****.**' % i for i in range(1, 100)]
    handles = conn.get_contact_handles_sync(contacts)
    conn.Avatars.RequestAvatars(handles)
    # Then, request yet another avatar. The request will time out before
    # the IQ is sent, which used to trigger a crash in Gabble
    # (LP#445847).
    conn.Avatars.RequestAvatars([handles[-1]])
    sync_dbus(bus, q, conn)
Esempio n. 39
0
def test(q, bus, conn, stream):
    # Request a sidecar thate we support before we're connected; it should just
    # wait around until we're connected.
    call_async(q, conn.Sidecars1, 'EnsureSidecar', TEST_PLUGIN_IFACE)

    if PLUGINS_ENABLED:
        # Now we're connected, the call we made earlier should return.
        path, props = q.expect('dbus-return', method='EnsureSidecar').value
        # This sidecar doesn't even implement get_immutable_properties; it
        # should just get the empty dict filled in for it.
        assertEquals({}, props)

        # We should get the same sidecar if we request it again
        path2, props2 = conn.Sidecars1.EnsureSidecar(TEST_PLUGIN_IFACE)
        assertEquals((path, props), (path2, props2))
    else:
        # Only now does it fail.
        q.expect('dbus-error', method='EnsureSidecar')

    # This is not a valid interface name
    call_async(q, conn.Sidecars1, 'EnsureSidecar', 'not an interface')
    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)

    # The test plugin makes no reference to this interface.
    call_async(q, conn.Sidecars1, 'EnsureSidecar', 'unsupported.sidecar')
    q.expect('dbus-error', name=cs.NOT_IMPLEMENTED)

    if PLUGINS_ENABLED:
        # This sidecar does have some properties:
        path, props = conn.Sidecars1.EnsureSidecar(TEST_PLUGIN_IFACE + ".Props")
        assertContains(TEST_PLUGIN_IFACE + ".Props.Greeting", props)

        # The plugin claims it implements this sidecar, but actually doesn't.
        # Check that we don't blow up (although this is no different from
        # Gabble's perspective to creating a sidecar failing because a network
        # service wasn't there, for instance).
        call_async(q, conn.Sidecars1, 'EnsureSidecar',
            TEST_PLUGIN_IFACE + ".Buggy")
        q.expect('dbus-error', name=cs.NOT_IMPLEMENTED)

        # This sidecar sends a stanza, and waits for a reply, before being
        # created.
        pattern = EventPattern('stream-iq', to='sidecar.example.com',
            query_ns='http://example.com/sidecar')
        call_async(q, conn.Sidecars1, 'EnsureSidecar', TEST_PLUGIN_IFACE + ".IQ")
        e = q.expect_many(pattern)[0]

        sync_dbus(bus, q, conn)

        # If the server says no, EnsureSidecar should fail.
        send_error_reply(stream, e.stanza)
        q.expect('dbus-error', method='EnsureSidecar', name=cs.NOT_AVAILABLE)

        # Let's try again. The plugin should get a chance to ping the server
        # again.
        call_async(q, conn.Sidecars1, 'EnsureSidecar', TEST_PLUGIN_IFACE + ".IQ")
        e = q.expect_many(pattern)[0]

        # The server said yes, so we should get a sidecar back!
        acknowledge_iq(stream, e.stanza)
        q.expect('dbus-return', method='EnsureSidecar')

        # If we ask again once the plugin has been created, it should return at
        # once without any more network traffic.
        q.forbid_events([pattern])
        conn.Sidecars1.EnsureSidecar(TEST_PLUGIN_IFACE + ".IQ")
        sync_stream(q, stream)

        # TODO: test ensuring a sidecar that waits for something from the
        # network, disconnecting while it's waiting, and ensuring that nothing
        # breaks regardless of whether the network replies before
        # </stream:stream> or not.

    call_async(q, conn, 'Disconnect')

    q.expect_many(
        EventPattern('dbus-signal', signal='StatusChanged',
            args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]),
        EventPattern('stream-closed'),
        )

    call_async(q, conn.Sidecars1, 'EnsureSidecar', 'zomg.what')
    # With older telepathy-glib this would be DISCONNECTED;
    # with newer telepathy-glib the Connection disappears from the bus
    # sooner, and you get UnknownMethod or something from dbus-glib.
    q.expect('dbus-error')

    stream.sendFooter()
    q.expect('dbus-return', method='Disconnect')
Esempio n. 40
0
def test(q, bus, conn, stream):
    iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard')

    # When we start, there is no avatar
    acknowledge_iq(stream, iq_event.stanza)
    self_handle = conn.GetSelfHandle()

    # Another resource confirms we have no avatar. We don't request our vCard
    # because we already know there is no avatar
    presence_stanza = make_presence('test@localhost/noavatar',
                                    to='test@localhost/Resource',
                                    show='away', status='At the pub',
                                    photo="")
    q.forbid_events([avatar_request_event, avatar_retrieved_event])
    # Gabble must resist temptation to send vCard requests even with several
    # presence stanza sent!
    stream.send(presence_stanza)
    stream.send(presence_stanza)
    sync_stream(q, stream) # Twice because the vCard request is done in
    sync_stream(q, stream) # g_idle_add
    q.unforbid_events([avatar_request_event, avatar_retrieved_event])

    # Request on the first contact. Test the cache.
    handle = conn.RequestHandles(cs.HT_CONTACT, ['*****@*****.**'])[0]
    test_get_avatar(q, bus, conn, stream, '*****@*****.**', handle,
            in_cache=False)
    test_get_avatar(q, bus, conn, stream, '*****@*****.**', handle,
            in_cache=True)

    # Request another vCard and get resource-constraint
    busy_contact = '*****@*****.**'
    busy_handle = conn.RequestHandles(cs.HT_CONTACT, [busy_contact])[0]
    conn.Avatars.RequestAvatars([busy_handle])

    iq_event = q.expect('stream-iq', to=busy_contact, query_ns='vcard-temp',
        query_name='vCard')
    iq = iq_event.stanza
    error = domish.Element((None, 'error'))
    error['code'] = '500'
    error['type'] = 'wait'
    error.addElement((ns.STANZA, 'resource-constraint'))

    q.forbid_events([avatar_retrieved_event, avatar_request_event])
    send_error_reply(stream, iq, error)

    # Request the same vCard again during the suspended delay
    # We should not get the avatar
    conn.Avatars.RequestAvatars([busy_handle])
    sync_stream(q, stream)
    sync_dbus(bus, q, conn)
    q.unforbid_events([avatar_retrieved_event, avatar_request_event])
    
    # Request on a different contact, on another server
    # We should get the avatar
    handle = conn.RequestHandles(cs.HT_CONTACT, ['*****@*****.**'])[0]
    test_get_avatar(q, bus, conn, stream, '*****@*****.**', handle)

    # Try again the contact on the busy server.
    # We should not get the avatar
    # Note: the timeout is 3 seconds for the test suites. We assume that
    # a few stanza with be processed fast enough to avoid the race.
    q.forbid_events([avatar_retrieved_event, avatar_request_event])
    conn.Avatars.RequestAvatars([busy_handle])
    sync_stream(q, stream)
    sync_dbus(bus, q, conn)
    q.unforbid_events([avatar_retrieved_event, avatar_request_event])

    # After 3 seconds, we receive a new vCard request on the busy server
    iq_event = q.expect('stream-iq', to=busy_contact, query_ns='vcard-temp',
        query_name='vCard')
    iq = make_result_iq(stream, iq_event.stanza)
    vcard = iq.firstChildElement()
    photo = vcard.addElement('PHOTO')
    photo.addElement('TYPE', content='image/png')
    photo.addElement('BINVAL', content=base64.b64encode('hello'))
    stream.send(iq)

    event = q.expect('dbus-signal', signal='AvatarRetrieved')
    assertEquals(busy_handle, event.args[0])
    assertEquals(hashlib.sha1('hello').hexdigest(), event.args[1])
    assertEquals('hello', event.args[2])
    assertEquals('image/png', event.args[3])

    # Test with our own avatar test@localhost/Resource2
    presence_stanza = make_presence('test@localhost/Resource2',
                                    to='test@localhost/Resource',
                                    show='away', status='At the pub',
                                    photo=hashlib.sha1(':-D').hexdigest())
    stream.send(presence_stanza)
    iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
        query_name='vCard')
    iq = make_result_iq(stream, iq_event.stanza)
    vcard = iq.firstChildElement()
    photo = vcard.addElement('PHOTO')
    photo.addElement('TYPE', content='image/png')
    photo.addElement('BINVAL', content=base64.b64encode(':-D'))

    # do not send the vCard reply now. First, send another presence.
    q.forbid_events([avatar_request_event])
    stream.send(presence_stanza)
    sync_stream(q, stream)

    # Now send the reply.
    stream.send(iq)

    # Which results in an AvatarUpdated signal
    event = q.expect('dbus-signal', signal='AvatarUpdated')
    assertEquals(self_handle, event.args[0])
    assertEquals(hashlib.sha1(':-D').hexdigest(), event.args[1])

    # So Gabble has the right hash, and no need to ask the vCard again
    stream.send(presence_stanza)
    sync_stream(q, stream)
    q.unforbid_events([avatar_request_event])

    # But if the hash is different, the vCard is asked again
    presence_stanza = make_presence('test@localhost/Resource2',
                                    to='test@localhost/Resource',
                                    show='away', status='At the pub',
                                    photo=hashlib.sha1('\o/').hexdigest())
    stream.send(presence_stanza)
    iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp',
        query_name='vCard')
    iq = make_result_iq(stream, iq_event.stanza)
    vcard = iq.firstChildElement()
    photo = vcard.addElement('PHOTO')
    photo.addElement('TYPE', content='image/png')
    photo.addElement('BINVAL', content=base64.b64encode('\o/'))
    stream.send(iq)

    event = q.expect('dbus-signal', signal='AvatarUpdated')
    assertEquals(self_handle, event.args[0])
    assertEquals(hashlib.sha1('\o/').hexdigest(), event.args[1])

    # Gabble must reply without asking the vCard to the server because the
    # avatar must be in the cache
    q.forbid_events([avatar_request_event])
    data, mime = conn.Avatars.RequestAvatar(self_handle, byte_arrays=True)
    assertEquals('\o/', data)
    data, mime = conn.Avatars.RequestAvatar(handle, byte_arrays=True)
    assertEquals('hello', data)
    q.unforbid_events([avatar_request_event])

    # First, ensure the pipeline is full
    contacts = ['*****@*****.**' % i for i in range(1, 100) ]
    handles = conn.RequestHandles(cs.HT_CONTACT, contacts)
    conn.Avatars.RequestAvatars(handles)
    # Then, request yet another avatar. The request will time out before
    # the IQ is sent, which used to trigger a crash in Gabble
    # (LP#445847). So, we assert that the error is NotAvailable (rather
    # than the error returned when the service crashes).
    try:
        conn.Avatars.RequestAvatar(handles[-1])
    except dbus.DBusException, e:
        assertEquals(cs.NOT_AVAILABLE, e.get_dbus_name())
def test(q, bus, conn, stream, bytestream_cls,
        address_type, access_control, access_control_param):
    if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]:
        # disable SOCKS5 relay tests because proxy can't be used with muc
        # contacts atm
        return

    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    call_async(q, conn, 'RequestHandles', 2,
        ['*****@*****.**'])

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

    # join the muc
    call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM,
        room_handle, True)

    _, stream_event = q.expect_many(
        EventPattern('dbus-signal', signal='MembersChanged',
            args=[u'', [], [], [], [2], 0, 0]),
        EventPattern('stream-presence', to='[email protected]/test'))

    # Send presence for other member of room.
    stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob'))

    # Send presence for own membership of room.
    stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test'))

    q.expect('dbus-signal', signal='MembersChanged',
            args=[u'', [2, 3], [], [], [], 0, 0])

    assert conn.InspectHandles(1, [2]) == ['[email protected]/test']
    assert conn.InspectHandles(1, [3]) == ['[email protected]/bob']
    bob_handle = 3

    event = q.expect('dbus-return', method='RequestChannel')

    # Bob offers a stream tube
    stream_tube_id = 666
    presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')
    tubes = presence.addElement((ns.TUBES, 'tubes'))
    tube = tubes.addElement((None, 'tube'))
    tube['type'] = 'stream'
    tube['service'] = 'echo'
    tube['id'] = str(stream_tube_id)
    parameters = tube.addElement((None, 'parameters'))
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 's'
    parameter['type'] = 'str'
    parameter.addContent('hello')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'ay'
    parameter['type'] = 'bytes'
    parameter.addContent('aGVsbG8=')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'u'
    parameter['type'] = 'uint'
    parameter.addContent('123')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'i'
    parameter['type'] = 'int'
    parameter.addContent('-123')

    stream.send(presence)

    # text channel
    event, new_event = q.expect_many(
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'))

    assert event.args[1] == cs.CHANNEL_TYPE_TEXT, event.args

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT

    # tubes channel is automatically created
    event, new_event = q.expect_many(
        EventPattern('dbus-signal', signal='NewChannel'),
        EventPattern('dbus-signal', signal='NewChannels'))

    assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args
    assert event.args[2] == cs.HT_ROOM
    assert event.args[3] == room_handle

    tubes_chan = bus.get_object(conn.bus_name, event.args[0])
    tubes_iface = dbus.Interface(tubes_chan, event.args[1])

    channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE)
    assert channel_props['TargetID'] == '*****@*****.**', channel_props
    assert channel_props['Requested'] == False
    assert channel_props['InitiatorID'] == ''
    assert channel_props['InitiatorHandle'] == 0

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES

    tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP)

    q.expect('dbus-signal', signal='NewTube',
        args=[stream_tube_id, bob_handle, 1, 'echo', sample_parameters, 0])

    expected_tube = (stream_tube_id, bob_handle, cs.TUBE_TYPE_STREAM, 'echo',
        sample_parameters, cs.TUBE_STATE_LOCAL_PENDING)
    tubes = tubes_iface.ListTubes(byte_arrays=True)
    assert tubes == [(
        stream_tube_id,
        bob_handle,
        1,      # Stream
        'echo',
        sample_parameters,
        cs.TUBE_CHANNEL_STATE_LOCAL_PENDING
        )]

    assert len(tubes) == 1, unwrap(tubes)
    t.check_tube_in_tubes(expected_tube, tubes)

    # tube channel is also announced (new API)
    new_event = q.expect('dbus-signal', signal='NewChannels')

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert props[cs.INITIATOR_HANDLE] == bob_handle
    assert props[cs.INITIATOR_ID] == '[email protected]/bob'
    assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE]
    assert props[cs.REQUESTED] == False
    assert props[cs.TARGET_HANDLE] == room_handle
    assert props[cs.TARGET_ID] == '*****@*****.**'
    assert props[cs.STREAM_TUBE_SERVICE] == 'echo'
    assert props[cs.TUBE_PARAMETERS] == {'s': 'hello', 'ay': 'hello', 'u': 123, 'i': -123}
    assert access_control in \
            props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type]

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE,
        byte_arrays=True)
    assert tube_props['Parameters'] == sample_parameters
    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING

    # Accept the tube
    call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id,
        address_type, access_control, access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='AcceptStreamTube'),
        EventPattern('dbus-signal', signal='TubeStateChanged',
            args=[stream_tube_id, 2]))

    address = accept_return_event.value[0]

    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    protocol.sendData("hello initiator")

    def accept_tube_si_connection():
        bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, si_event.stanza,
                '[email protected]/test')

        assert profile == ns.TUBES

        muc_stream_node = xpath.queryForNodes('/iq/si/muc-stream[@xmlns="%s"]' %
            ns.TUBES, si_event.stanza)[0]
        assert muc_stream_node is not None
        assert muc_stream_node['tube'] == str(stream_tube_id)

        # set the real jid of the target as 'to' because the XMPP server changes
        # it when delivering the IQ
        result, si = bytestream.create_si_reply(si_event.stanza, 'test@localhost/Resource')
        si.addElement((ns.TUBES, 'tube'))
        stream.send(result)

        bytestream.wait_bytestream_open()
        return bytestream

    bytestream = accept_tube_si_connection()

    binary = bytestream.get_data()
    assert binary == 'hello initiator'

    # reply on the socket
    bytestream.send_data('hi joiner!')

    q.expect('socket-data', protocol=protocol, data="hi joiner!")

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    bytestream = accept_tube_si_connection()

    # disconnect local socket
    protocol.transport.loseConnection()
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CANCELLED, e.args[1])

    # OK, we're done
    disconnect_conn(q, conn, stream,
        [EventPattern('dbus-signal', signal='TubeClosed', args=[stream_tube_id])])
def test(q, bus, conn, stream, bytestream_cls,
        address_type, access_control, access_control_param):

    vcard_event, roster_event, disco_event = q.expect_many(
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'),
        EventPattern('stream-iq', query_ns=ns.ROSTER),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, vcard_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    roster = roster_event.stanza
    roster['type'] = 'result'
    item = roster_event.query.addElement('item')
    item['jid'] = 'bob@localhost' # Bob can do tubes
    item['subscription'] = 'both'
    stream.send(roster)

    # Send Bob presence and his caps
    presence = domish.Element(('jabber:client', 'presence'))
    presence['from'] = 'bob@localhost/Bob'
    presence['to'] = 'test@localhost/Resource'
    c = presence.addElement('c')
    c['xmlns'] = 'http://jabber.org/protocol/caps'
    c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy'
    c['ver'] = '1.2.3'
    stream.send(presence)

    event = q.expect('stream-iq', iq_type='get',
        query_ns='http://jabber.org/protocol/disco#info',
        to='bob@localhost/Bob')
    assert event.query['node'] == \
        'http://example.com/ICantBelieveItsNotTelepathy#1.2.3'
    result = make_result_iq(stream, event.stanza)
    query = result.firstChildElement()
    feature = query.addElement('feature')
    feature['var'] = ns.TUBES
    stream.send(result)

    sync_dbus(bus, q, conn)

    # Receive a tube offer from Bob
    (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)

    # Try bad parameters on the old iface
    call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id+1, 2, 0, '',
            byte_arrays=True)
    q.expect('dbus-error', method='AcceptStreamTube')
    call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 2, 1, '',
            byte_arrays=True)
    q.expect('dbus-error', method='AcceptStreamTube')
    call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, 20, 0, '',
            byte_arrays=True)
    q.expect('dbus-error', method='AcceptStreamTube')

    # Try bad parameters on the new iface
    call_async(q, new_tube_iface, 'Accept', 20, 0, '',
            byte_arrays=True)
    q.expect('dbus-error', method='Accept')
    call_async(q, new_tube_iface, 'Accept', 0, 1, '',
            byte_arrays=True)
    q.expect('dbus-error', method='Accept')

    # Accept the tube with old iface
    call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, address_type,
        access_control, access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='AcceptStreamTube'),
        EventPattern('dbus-signal', signal='TubeStateChanged',
            args=[stream_tube_id, 2]))

    socket_address = accept_return_event.value[0]

    bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls,
        address_type, socket_address, access_control, access_control_param)

    tubes_chan.Close()
    bytestream.wait_bytestream_closed()

    # Receive a tube offer from Bob
    (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)

    # Accept the tube with old iface, and use UNIX sockets
    call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id,
        address_type, access_control, access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='AcceptStreamTube'),
        EventPattern('dbus-signal', signal='TubeStateChanged',
            args=[stream_tube_id, 2]))

    socket_address = accept_return_event.value[0]

    bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls,
        address_type, socket_address, access_control, access_control_param)
    tubes_chan.Close()
    bytestream.wait_bytestream_closed()

    # Receive a tube offer from Bob
    (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)

    # Accept the tube with new iface, and use IPv4
    call_async(q, new_tube_iface, 'Accept', address_type,
        access_control, access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='Accept'),
        EventPattern('dbus-signal', signal='TubeStateChanged',
            args=[stream_tube_id, 2]))

    socket_address = accept_return_event.value[0]

    bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls,
        address_type, socket_address, access_control, access_control_param)
    tubes_chan.Close()
    e, _ = bytestream.wait_bytestream_closed([
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected')])
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CANCELLED, e.args[1])

    # Receive a tube offer from Bob
    (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)

    # Accept the tube with new iface, and use UNIX sockets
    call_async(q, new_tube_iface, 'Accept', address_type, access_control,
        access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='Accept'),
        EventPattern('dbus-signal', signal='TubeStateChanged',
            args=[stream_tube_id, 2]))

    socket_address = accept_return_event.value[0]

    bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls,
        address_type, socket_address, access_control, access_control_param)

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    event_socket, si_event, conn_id = t.connect_to_cm_socket(q, bob_jid,
    address_type, socket_address, access_control, access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    tubes_chan.Close()

    # Receive a tube offer from Bob
    (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)
    # Just close the tube
    tubes_chan.Close()

    # Receive a tube offer from Bob
    (tubes_chan, tubes_iface, new_tube_chan, new_tube_iface) = \
        receive_tube_offer(q, bus, conn, stream)
    # Just close the tube
    new_tube_chan.Close()

    q.expect_many(
        EventPattern('dbus-signal', signal='Closed'),
        EventPattern('dbus-signal', signal='ChannelClosed'))
def test(q, bus, conn, stream, bytestream_cls,
        address_type, access_control, access_control_param):
    if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]:
        # disable SOCKS5 relay tests because proxy can't be used with muc
        # contacts atm
        return

    if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS:
        print "Skip Socket_Access_Control_Credentials (fdo #45445)"
        return

    iq_event, disco_event = q.expect_many(
        EventPattern('stream-iq', to=None, query_ns='vcard-temp',
            query_name='vCard'),
        EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS))

    acknowledge_iq(stream, iq_event.stanza)

    announce_socks5_proxy(q, stream, disco_event.stanza)

    # join the muc
    call_async(q, conn.Requests, 'CreateChannel', {
            cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.TARGET_ID: '*****@*****.**'})

    q.expect_many(
        EventPattern('dbus-signal', signal='MembersChangedDetailed',
            predicate=lambda e:
                e.args[0] == [] and         # added
                e.args[1] == [] and         # removed
                e.args[2] == [] and         # local pending
                len(e.args[3]) == 1 and     # remote pending
                e.args[4].get('actor', 0) == 0 and
                e.args[4].get('change-reason', 0) == 0 and
                e.args[4]['contact-ids'][e.args[3][0]] == '[email protected]/test'),
        EventPattern('stream-presence', to='[email protected]/test'))

    # Send presence for other member of room.
    stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob'))

    # Send presence for own membership of room.
    stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test'))

    event = q.expect('dbus-signal', signal='MembersChangedDetailed',
            predicate=lambda e:
                len(e.args[0]) == 2 and     # added
                e.args[1] == [] and         # removed
                e.args[2] == [] and         # local pending
                e.args[3] == [] and         # remote pending
                e.args[4].get('actor', 0) == 0 and
                e.args[4].get('change-reason', 0) == 0 and
                set([e.args[4]['contact-ids'][h] for h in e.args[0]]) ==
                set(['[email protected]/test', '[email protected]/bob']))

    for h in event.args[0]:
        if event.args[4]['contact-ids'][h] == '[email protected]/bob':
            bob_handle = h

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

    # Bob offers a stream tube
    stream_tube_id = 666
    presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')
    tubes = presence.addElement((ns.TUBES, 'tubes'))
    tube = tubes.addElement((None, 'tube'))
    tube['type'] = 'stream'
    tube['service'] = 'echo'
    tube['id'] = str(stream_tube_id)
    parameters = tube.addElement((None, 'parameters'))
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 's'
    parameter['type'] = 'str'
    parameter.addContent('hello')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'ay'
    parameter['type'] = 'bytes'
    parameter.addContent('aGVsbG8=')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'u'
    parameter['type'] = 'uint'
    parameter.addContent('123')
    parameter = parameters.addElement((None, 'parameter'))
    parameter['name'] = 'i'
    parameter['type'] = 'int'
    parameter.addContent('-123')

    stream.send(presence)

    # text channel
    new_event = q.expect('dbus-signal', signal='NewChannels')

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT

    def new_chan_predicate(e):
        path, props = e.args[0][0]
        return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE

    # tube channel is announced
    new_event = q.expect('dbus-signal', signal='NewChannels',
                         predicate=new_chan_predicate)

    channels = new_event.args[0]
    assert len(channels) == 1
    path, props = channels[0]
    assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
    assert props[cs.INITIATOR_HANDLE] == bob_handle
    assert props[cs.INITIATOR_ID] == '[email protected]/bob'
    assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE],
            props[cs.INTERFACES])
    assert props[cs.REQUESTED] == False
    assert props[cs.TARGET_ID] == '*****@*****.**'
    assert props[cs.STREAM_TUBE_SERVICE] == 'echo'
    assert props[cs.TUBE_PARAMETERS] == {'s': 'hello', 'ay': 'hello', 'u': 123, 'i': -123}
    assert access_control in \
            props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type]

    tube_chan = bus.get_object(conn.bus_name, path)
    tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE,
        byte_arrays=True)
    tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE)
    assert tube_props['Parameters'] == sample_parameters
    assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING

    # Accept the tube
    call_async(q, tube_iface, 'Accept',
        address_type, access_control, access_control_param, byte_arrays=True)

    accept_return_event, _ = q.expect_many(
        EventPattern('dbus-return', method='Accept'),
        EventPattern('dbus-signal', signal='TubeChannelStateChanged',
            args=[2]))

    address = accept_return_event.value[0]

    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    protocol.sendData("hello initiator")

    def accept_tube_si_connection():
        bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, si_event.stanza,
                '[email protected]/test')

        assert profile == ns.TUBES

        muc_stream_node = xpath.queryForNodes('/iq/si/muc-stream[@xmlns="%s"]' %
            ns.TUBES, si_event.stanza)[0]
        assert muc_stream_node is not None
        assert muc_stream_node['tube'] == str(stream_tube_id)

        # set the real jid of the target as 'to' because the XMPP server changes
        # it when delivering the IQ
        result, si = bytestream.create_si_reply(si_event.stanza, 'test@localhost/Resource')
        si.addElement((ns.TUBES, 'tube'))
        stream.send(result)

        bytestream.wait_bytestream_open()
        return bytestream

    bytestream = accept_tube_si_connection()

    binary = bytestream.get_data()
    assert binary == 'hello initiator'

    # reply on the socket
    bytestream.send_data('hi joiner!')

    q.expect('socket-data', protocol=protocol, data="hi joiner!")

    # peer closes the bytestream
    bytestream.close()
    e = q.expect('dbus-signal', signal='ConnectionClosed')
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_LOST, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    # bytestream is refused
    send_error_reply(stream, si_event.stanza)
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CONNECTION_REFUSED, e.args[1])

    # establish another tube connection
    socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob',
        address_type, address, access_control, access_control_param)

    protocol = socket_event.protocol
    bytestream = accept_tube_si_connection()

    # disconnect local socket
    protocol.transport.loseConnection()
    e, _ = q.expect_many(
        EventPattern('dbus-signal', signal='ConnectionClosed'),
        EventPattern('socket-disconnected'))
    assertEquals(conn_id, e.args[0])
    assertEquals(cs.CANCELLED, e.args[1])

    # OK, we're done
    disconnect_conn(q, conn, stream)
def test(q, bus, conn, stream):
    # Request a sidecar thate we support before we're connected; it should just
    # wait around until we're connected.
    call_async(q, conn.Sidecars1, 'EnsureSidecar', TEST_PLUGIN_IFACE)

    if PLUGINS_ENABLED:
        # Now we're connected, the call we made earlier should return.
        path, props = q.expect('dbus-return', method='EnsureSidecar').value
        # This sidecar doesn't even implement get_immutable_properties; it
        # should just get the empty dict filled in for it.
        assertEquals({}, props)

        # We should get the same sidecar if we request it again
        path2, props2 = conn.Sidecars1.EnsureSidecar(TEST_PLUGIN_IFACE)
        assertEquals((path, props), (path2, props2))
    else:
        # Only now does it fail.
        q.expect('dbus-error', method='EnsureSidecar')

    # This is not a valid interface name
    call_async(q, conn.Sidecars1, 'EnsureSidecar', 'not an interface')
    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)

    # The test plugin makes no reference to this interface.
    call_async(q, conn.Sidecars1, 'EnsureSidecar', 'unsupported.sidecar')
    q.expect('dbus-error', name=cs.NOT_IMPLEMENTED)

    if PLUGINS_ENABLED:
        # This sidecar does have some properties:
        path, props = conn.Sidecars1.EnsureSidecar(TEST_PLUGIN_IFACE +
                                                   ".Props")
        assertContains(TEST_PLUGIN_IFACE + ".Props.Greeting", props)

        # The plugin claims it implements this sidecar, but actually doesn't.
        # Check that we don't blow up (although this is no different from
        # Gabble's perspective to creating a sidecar failing because a network
        # service wasn't there, for instance).
        call_async(q, conn.Sidecars1, 'EnsureSidecar',
                   TEST_PLUGIN_IFACE + ".Buggy")
        q.expect('dbus-error', name=cs.NOT_IMPLEMENTED)

        # This sidecar sends a stanza, and waits for a reply, before being
        # created.
        pattern = EventPattern('stream-iq',
                               to='sidecar.example.com',
                               query_ns='http://example.com/sidecar')
        call_async(q, conn.Sidecars1, 'EnsureSidecar',
                   TEST_PLUGIN_IFACE + ".IQ")
        e = q.expect_many(pattern)[0]

        sync_dbus(bus, q, conn)

        # If the server says no, EnsureSidecar should fail.
        send_error_reply(stream, e.stanza)
        q.expect('dbus-error', method='EnsureSidecar', name=cs.NOT_AVAILABLE)

        # Let's try again. The plugin should get a chance to ping the server
        # again.
        call_async(q, conn.Sidecars1, 'EnsureSidecar',
                   TEST_PLUGIN_IFACE + ".IQ")
        e = q.expect_many(pattern)[0]

        # The server said yes, so we should get a sidecar back!
        acknowledge_iq(stream, e.stanza)
        q.expect('dbus-return', method='EnsureSidecar')

        # If we ask again once the plugin has been created, it should return at
        # once without any more network traffic.
        q.forbid_events([pattern])
        conn.Sidecars1.EnsureSidecar(TEST_PLUGIN_IFACE + ".IQ")
        sync_stream(q, stream)

        # TODO: test ensuring a sidecar that waits for something from the
        # network, disconnecting while it's waiting, and ensuring that nothing
        # breaks regardless of whether the network replies before
        # </stream:stream> or not.

    call_async(q, conn, 'Disconnect')

    q.expect_many(
        EventPattern('dbus-signal',
                     signal='StatusChanged',
                     args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]),
        EventPattern('stream-closed'),
    )

    call_async(q, conn.Sidecars1, 'EnsureSidecar', 'zomg.what')
    # With older telepathy-glib this would be DISCONNECTED;
    # with newer telepathy-glib the Connection disappears from the bus
    # sooner, and you get UnknownMethod or something from dbus-glib.
    q.expect('dbus-error')

    stream.sendFooter()
    q.expect('dbus-return', method='Disconnect')
Esempio n. 45
0
def test(q, bus, conn, stream):
    # we don't yet know we have PEP
    assertEquals(
        0,
        conn.Get(cs.CONN_IFACE_LOCATION,
                 "SupportedLocationFeatures",
                 dbus_interface=cs.PROPERTIES_IFACE))

    conn.Connect()

    # discard activities request and status change
    q.expect_many(
        EventPattern('stream-iq', iq_type='set', query_ns=ns.PUBSUB),
        EventPattern('dbus-signal',
                     signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]),
    )

    # we now know we have PEP
    assertEquals(
        cs.LOCATION_FEATURE_CAN_SET,
        conn.Get(cs.CONN_IFACE_LOCATION,
                 "SupportedLocationFeatures",
                 dbus_interface=cs.PROPERTIES_IFACE))

    # check location properties

    access_control_types = conn.Get(cs.CONN_IFACE_LOCATION,
                                    "LocationAccessControlTypes",
                                    dbus_interface=cs.PROPERTIES_IFACE)
    # only one access control is implemented in Gabble at the moment:
    assert len(access_control_types) == 1, access_control_types
    assert access_control_types[0] == \
        Rich_Presence_Access_Control_Type_Publish_List

    access_control = conn.Get(cs.CONN_IFACE_LOCATION,
                              "LocationAccessControl",
                              dbus_interface=cs.PROPERTIES_IFACE)
    assert len(access_control) == 2, access_control
    assert access_control[0] == \
        Rich_Presence_Access_Control_Type_Publish_List

    properties = conn.GetAll(cs.CONN_IFACE_LOCATION,
                             dbus_interface=cs.PROPERTIES_IFACE)

    assert properties.get('LocationAccessControlTypes') == access_control_types
    assert properties.get('LocationAccessControl') == access_control

    # Test setting the properties

    # Enum out of range
    bad_access_control = dbus.Struct(
        [dbus.UInt32(99), dbus.UInt32(0, variant_level=1)],
        signature=dbus.Signature('uv'))
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControl',
                 bad_access_control,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        pass
    else:
        assert False, "Should have had an error!"

    # Bad type
    bad_access_control = dbus.String("This should not be a string")
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControl',
                 bad_access_control,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        assert e.get_dbus_name() == cs.INVALID_ARGUMENT, e.get_dbus_name()
    else:
        assert False, "Should have had an error!"

    # Bad type
    bad_access_control = dbus.Struct([
        dbus.String("bad"),
        dbus.String("!"),
        dbus.UInt32(0, variant_level=1)
    ],
                                     signature=dbus.Signature('ssv'))
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControl',
                 bad_access_control,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        assert e.get_dbus_name() == cs.INVALID_ARGUMENT, e.get_dbus_name()
    else:
        assert False, "Should have had an error!"

    # Correct
    conn.Set(cs.CONN_IFACE_LOCATION,
             'LocationAccessControl',
             access_control,
             dbus_interface=cs.PROPERTIES_IFACE)

    # LocationAccessControlTypes is read-only, check Gabble return the
    # PermissionDenied error
    try:
        conn.Set(cs.CONN_IFACE_LOCATION,
                 'LocationAccessControlTypes',
                 access_control_types,
                 dbus_interface=cs.PROPERTIES_IFACE)
    except dbus.DBusException as e:
        assert e.get_dbus_name() == cs.PERMISSION_DENIED, e.get_dbus_name()
    else:
        assert False, "Should have had an error!"

    date = dbus.Int64(time.time())
    date_str = datetime.datetime.utcfromtimestamp(date).strftime(
        '%FT%H:%M:%SZ')

    # set a Location
    call_async(
        q,
        conn.Location,
        'SetLocation',
        {
            'lat': dbus.Double(0.0, variant_level=1),
            'lon': 0.0,
            'language': 'en',
            'timestamp': date,
            'country': 'Congo',
            'accuracy': 1.4,
            # Gabble silently ignores unknown keys
            'badger': 'mushroom'
        })

    geoloc_iq_set_event = EventPattern(
        'stream-iq',
        predicate=lambda x: xpath.queryForNodes(
            "/iq/pubsub/publish/item/geoloc", x.stanza))

    event = q.expect_many(geoloc_iq_set_event)[0]
    geoloc = xpath.queryForNodes("/iq/pubsub/publish/item/geoloc",
                                 event.stanza)[0]
    assertEquals(geoloc.getAttribute((ns.XML, 'lang')), 'en')
    lon = xpath.queryForNodes('/geoloc/lon', geoloc)[0]
    assertEquals(float(str(lon)), 0.0)
    lat = xpath.queryForNodes('/geoloc/lat', geoloc)[0]
    assertEquals(float(str(lat)), 0.0)
    timestamp = xpath.queryForNodes('/geoloc/timestamp', geoloc)[0]
    assertEquals(str(timestamp), date_str)
    country = xpath.queryForNodes('/geoloc/country', geoloc)[0]
    assertEquals(str(country), 'Congo')
    lat = xpath.queryForNodes('/geoloc/accuracy', geoloc)[0]
    assertEquals(float(str(lat)), 1.4)

    acknowledge_iq(stream, event.stanza)
    q.expect('dbus-return', method='SetLocation')

    # Server refuses to set Location
    call_async(q, conn.Location, 'SetLocation', {'lat': 0.0, 'lon': 0.0})

    geoloc_iq_set_event = EventPattern(
        'stream-iq',
        predicate=lambda x: xpath.queryForNodes(
            "/iq/pubsub/publish/item/geoloc", x.stanza))
    event = q.expect_many(geoloc_iq_set_event)[0]

    send_error_reply(stream, event.stanza)
    q.expect('dbus-error', method='SetLocation')

    # Request Bob's location
    bob_handle = conn.get_contact_handle_sync('*****@*****.**')

    # Gabble should not send a pubsub query. The point of PEP is that we don't
    # have to do this.
    pubsub_get_pattern = EventPattern('stream-iq',
                                      iq_type='get',
                                      query_ns=ns.PUBSUB)
    q.forbid_events([pubsub_get_pattern])

    location = get_location(conn, bob_handle)
    # Location isn't known yet
    assertEquals(None, location)

    # Sync the XMPP stream to ensure Gabble hasn't sent a query.
    sync_stream(q, stream)

    # Bob updates his location
    message = elem('message', from_='*****@*****.**')(
        elem((ns.PUBSUB_EVENT), 'event')(
            elem('items', node=ns.GEOLOC)(
                elem('item', id='12345')(
                    elem(ns.GEOLOC, 'geoloc', attrs={'xml:lang': 'en'})(
                        elem('lat')(u'1.25'),
                        elem('lon')(u'5.5'),
                        elem('country')(u'Belgium'),
                        elem('accuracy')(u'2.3'),
                        elem('timestamp')(date_str),
                        # invalid element, will be ignored by Gabble
                        elem('badger')(u'mushroom'),
                    )))))
    stream.send(message)

    update_event = q.expect('dbus-signal', signal='LocationUpdated')

    handle, location = update_event.args
    assertEquals(bob_handle, handle)

    assertLength(6, location)
    assertEquals(location['language'], 'en')
    assertEquals(location['lat'], 1.25)
    assertEquals(location['lon'], 5.5)
    assertEquals(location['country'], 'Belgium')
    assertEquals(location['accuracy'], 2.3)
    assertEquals(location['timestamp'], date)

    # Get location again; Gabble should return the cached location
    loc = get_location(conn, bob_handle)
    assertEquals(loc, location)

    charles_handle = conn.get_contact_handle_sync('*****@*****.**')

    # check that Contacts interface supports location
    attributes = conn.Contacts.GetContactAttributes(
        [bob_handle, charles_handle], [cs.CONN_IFACE_LOCATION], False)
    assertLength(2, attributes)
    assertContains(bob_handle, attributes)
    assertContains(charles_handle, attributes)

    assertEquals(
        {
            cs.CONN_IFACE_LOCATION + '/location': location,
            cs.CONN + '/contact-id': '*****@*****.**'
        }, attributes[bob_handle])

    assertEquals({cs.CONN + '/contact-id': '*****@*****.**'},
                 attributes[charles_handle])

    # Try to set our location by passing a valid with an invalid type (lat is
    # supposed to be a double)

    q.forbid_events([geoloc_iq_set_event])

    try:
        conn.Location.SetLocation({'lat': 'pony'})
    except dbus.DBusException as e:
        assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
    else:
        assert False

    # Bob updates his location again
    message = elem('message', from_='*****@*****.**')(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)

    update_event = q.expect('dbus-signal', signal='LocationUpdated')
    handle, location = update_event.args
    assertEquals(handle, bob_handle)
    assertLength(1, location)
    assertEquals(location['country'], 'France')

    # Now we test explicitly retrieving Bob's location, so we should not forbid
    # such queries. :)
    q.unforbid_events([pubsub_get_pattern])

    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq',
                 iq_type='get',
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')

    # Hey, while we weren't looking Bob moved abroad!
    result = make_result_iq(stream, e.stanza)
    result['from'] = '*****@*****.**'
    pubsub_node = result.firstChildElement()
    pubsub_node.addChild(
        elem('items', node=ns.GEOLOC)(elem('item', id='12345')(elem(
            ns.GEOLOC, 'geoloc')(elem('country')(u'Chad')))))
    stream.send(result)

    ret = q.expect('dbus-return', method='RequestLocation')
    location, = ret.value
    assertLength(1, location)
    assertEquals(location['country'], 'Chad')

    # Let's ask again; this time Bob's server hates us for some reason.
    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq',
                 iq_type='get',
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')
    send_error_reply(stream, e.stanza,
                     elem('error', type='auth')(elem(ns.STANZA, 'forbidden')))
    e = q.expect('dbus-error', method='RequestLocation')
    assertEquals(cs.PERMISSION_DENIED, e.name)

    # FIXME: maybe we should check that the cache gets invalidated in this
    # case? We should also test whether or not the cache is invalidated
    # properly if the contact clears their PEP node.

    # Let's ask a final time, and disconnect while we're doing so, to make sure
    # this doesn't break Gabble or Wocky.
    call_async(q, conn.Location, 'RequestLocation', bob_handle)
    e = q.expect('stream-iq',
                 iq_type='get',
                 query_ns=ns.PUBSUB,
                 to='*****@*****.**')
    # Tasty argument unpacking. disconnect_conn returns two lists, one for
    # expeced_before=[] and one for expected_after=[...]
    _, (e, ) = disconnect_conn(
        q,
        conn,
        stream,
        expected_after=[EventPattern('dbus-error', method='RequestLocation')])
    assertEquals(cs.CANCELLED, e.name)
Esempio n. 46
0
    lat = xpath.queryForNodes('/geoloc/accuracy', geoloc)[0]
    assertEquals(float(str(lat)), 1.4)

    acknowledge_iq(stream, event.stanza)
    q.expect('dbus-return', method='SetLocation')

    # Server refuses to set Location
    call_async(q, conn.Location, 'SetLocation', {
        'lat': 0.0,
        'lon': 0.0})

    geoloc_iq_set_event = EventPattern('stream-iq', predicate=lambda x:
        xpath.queryForNodes("/iq/pubsub/publish/item/geoloc", x.stanza))
    event = q.expect_many(geoloc_iq_set_event)[0]

    send_error_reply(stream, event.stanza)
    q.expect('dbus-error', method='SetLocation')

    # Request Bob's location
    bob_handle = conn.RequestHandles(1, ['*****@*****.**'])[0]
    call_async(q, conn.Location, 'GetLocations', [bob_handle])

    # Gabble should not send a pubsub query. The point of PEP is that we don't
    # have to do this.
    pubsub_get_pattern = EventPattern('stream-iq', iq_type='get',
        query_ns=ns.PUBSUB)
    q.forbid_events([ pubsub_get_pattern ])

    # GetLocations returns immediately.
    get_locations = q.expect('dbus-return', method='GetLocations')
    locations = get_locations.value[0]