Пример #1
0
        def _on_message(_con, _stanza, properties):

            data = [
                BookmarkData(
                    jid=JID.from_string('*****@*****.**'),
                    name='The Play\'s the Thing',
                    autojoin=True,
                    password='******',
                    nick='JC'),
                BookmarkData(
                    jid=JID.from_string('*****@*****.**'),
                    name='Second room',
                    autojoin=False,
                    password=None,
                    nick=None)
            ]

            pubsub_event = PubSubEventData(node='storage:bookmarks',
                                           id='current',
                                           item=None,
                                           data=data,
                                           deleted=False,
                                           retracted=False,
                                           purged=False)

            # We cant compare Node objects
            pubsub_event_ = properties.pubsub_event._replace(item=None)
            self.assertEqual(pubsub_event, pubsub_event_)
Пример #2
0
    def test_ip_literals(self):
        tests = [
            ('juliet@[2002:4559:1FE2::4559:1FE2]/res'),
            ('[email protected]/res'),
        ]

        for jid in tests:
            JID.from_string(jid)
Пример #3
0
    def test_jid_equality(self):
        tests = [
            '*****@*****.**',
            '[email protected]/foo',
            'example.com',
        ]

        for jid in tests:
            self.assertTrue(JID.from_string(jid) == JID.from_string(jid))
    def test_error_parsing(self):
        stanza = '''
        <iq from='upload.montague.tld'
            id='step_03'
            to='[email protected]/garden'
            type='error'>
          <error type='modify'>
            <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' />
            <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>File too large. The maximum file size is 20000 bytes</text>
            <text xml:lang='de' xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>File zu groß. Erlaubt sind 20000 bytes</text>
            <file-too-large xmlns='urn:xmpp:http:upload:0'>
              <max-file-size>20000</max-file-size>
            </file-too-large>
          </error>
        </iq>'''

        error = error_factory(Iq(node=stanza))
        self.assertEqual(error.condition, 'not-acceptable')
        self.assertEqual(error.app_condition, 'file-too-large')
        self.assertEqual(
            error.get_text(),
            'File too large. The maximum file size is 20000 bytes')
        self.assertEqual(error.get_text('de'),
                         'File zu groß. Erlaubt sind 20000 bytes')
        self.assertEqual(error.type, 'modify')
        self.assertEqual(error.id, 'step_03')
        self.assertEqual(error.jid, JID.from_string('upload.montague.tld'))
Пример #5
0
    def get_affiliation(self, jid, affiliation):
        _task = yield

        response = yield make_affiliation_request(jid, affiliation)
        if response.isError():
            raise StanzaError(response)

        room_jid = response.getFrom()
        query = response.getTag('query', namespace=Namespace.MUC_ADMIN)
        items = query.getTags('item')
        users_dict = {}
        for item in items:
            try:
                jid = JID.from_string(item.getAttr('jid'))
            except Exception as error:
                self._log.warning('Invalid JID: %s, %s', item.getAttr('jid'),
                                  error)
                continue

            users_dict[jid] = {}
            if item.has_attr('nick'):
                users_dict[jid]['nick'] = item.getAttr('nick')
            if item.has_attr('role'):
                users_dict[jid]['role'] = item.getAttr('role')
            reason = item.getTagData('reason')
            if reason:
                users_dict[jid]['reason'] = reason

        self._log.info('Affiliations received from %s: %s', room_jid,
                       users_dict)

        yield AffiliationResult(jid=room_jid, users=users_dict)
Пример #6
0
def parse_storage_node(storage, log):
    bookmarks = []
    confs = storage.getTags('conference')
    for conf in confs:
        try:
            jid = JID.from_string(conf.getAttr('jid'))
        except Exception:
            log.warning('invalid jid: %s', conf)
            continue

        if jid.localpart is None or jid.resource is not None:
            log.warning('invalid jid: %s', conf)
            continue

        autojoin = parse_autojoin(conf.getAttr('autojoin'))
        nick = parse_nickname(conf.getTagData('nick'))
        name = conf.getAttr('name') or None
        password = conf.getTagData('password') or None

        bookmark = BookmarkData(jid=jid,
                                name=name,
                                autojoin=autojoin,
                                password=password,
                                nick=nick)
        bookmarks.append(bookmark)

    return bookmarks
Пример #7
0
    def _process_voice_request(self, _client, stanza, properties):
        data_form = stanza.getTag('x', namespace=Namespace.DATA)
        if data_form is None:
            return

        data_form = extend_form(data_form)
        try:
            if data_form['FORM_TYPE'].value != Namespace.MUC_REQUEST:
                return
        except KeyError:
            return

        nick = data_form['muc#roomnick'].value

        try:
            jid = JID.from_string(data_form['muc#jid'].value)
        except Exception:
            self._log.warning('Invalid JID on voice request')
            self._log.warning(stanza)
            raise NodeProcessed

        properties.voice_request = VoiceRequest(jid=jid,
                                                nick=nick,
                                                form=data_form)
        properties.from_muc = True
        properties.muc_jid = properties.jid.new_as_bare()
Пример #8
0
def _parse_push(node):
    items = node.getTags('item')
    if not items:
        return BlockingPush(block=set(), unblock=set(), unblock_all=True)

    jids = set()
    for item in items:
        jid = item.getAttr('jid')
        if not jid:
            continue

        try:
            jid = JID.from_string(jid)
        except Exception:
            continue

        jids.add(jid)

    block, unblock = set(), set()
    if node.getName() == 'block':
        block = jids
    else:
        unblock = jids

    return BlockingPush(block=block, unblock=unblock, unblock_all=False)
Пример #9
0
    def test_invalid_jids(self):
        tests = [
            ('"juliet"@example.com', LocalpartNotAllowedChar),
            ('foo [email protected]', LocalpartNotAllowedChar),
            ('henry\[email protected]', LocalpartNotAllowedChar),
            ('@example.com', LocalpartByteLimit),
            ('[email protected]/', ResourcepartByteLimit),
            ('[email protected]/\U00000001', ResourcepartNotAllowedChar),
            ('\[email protected]', LocalpartNotAllowedChar),
            ('user@[email protected]', DomainpartNotAllowedChar),
            ('juliet@', DomainpartByteLimit),
            ('/foobar', DomainpartByteLimit),
        ]

        for jid, exception in tests:
            with self.assertRaises(exception):
                JID.from_string(jid)
Пример #10
0
 def __init__(self, room_jid, nick, password, config=None):
     self._room_jid = JID.from_string(room_jid)
     self._config = config
     self.nick = nick
     self.password = password
     self.state = MUCJoinedState.NOT_JOINED
     # Message id of the captcha challenge
     self.captcha_id = None
Пример #11
0
    def setUp(self):
        # Setup mock client
        self.client = Mock()
        self.client.is_websocket = False
        self.dispatcher = StanzaDispatcher(self.client)

        self.client.get_bound_jid.return_value = JID.from_string(
            '*****@*****.**')

        self.dispatcher.reset_parser()
        self.dispatcher.process_data(STREAM_START)
Пример #12
0
    def test_valid_jids(self):
        tests = [
            '*****@*****.**',
            '[email protected]/foo',
            '[email protected]/foo bar',
            '[email protected]/foo@bar',
            'foo\\[email protected]',
            '*****@*****.**',
            'fu\[email protected]',
            '\[email protected]',
            '\[email protected]/foo',
            '\[email protected]/foo',
            '\[email protected]/foo',
            '[email protected]/\U0000265A',
            'example.com',
            'example.com/foobar',
            'a.example.com/[email protected]',
        ]

        for jid in tests:
            JID.from_string(jid)
Пример #13
0
    def from_node(cls, node):
        attrs = node.getAttrs(copy=True)
        jid = attrs.get('jid')
        if jid is None:
            raise Exception('jid attribute missing')

        jid = JID.from_string(jid)
        attrs['jid'] = jid

        groups = {group.getData() for group in node.getTags('group')}
        attrs['groups'] = groups

        return cls(**attrs)
Пример #14
0
def _get_preference_jids(node):
    jids = []
    for item in node.getTags('jid'):
        jid = item.getData()
        if not jid:
            continue

        try:
            jid = JID.from_string(jid)
        except Exception:
            continue

        jids.append(jid)
    return jids
Пример #15
0
    def _process_mediated_invite(_client, stanza, properties):
        muc_user = stanza.getTag('x', namespace=Namespace.MUC_USER)
        if muc_user is None:
            return

        if properties.type != MessageType.NORMAL:
            return

        properties.from_muc = True
        properties.muc_jid = properties.jid.new_as_bare()

        data = {}

        invite = muc_user.getTag('invite')
        if invite is not None:
            data['muc'] = properties.jid.new_as_bare()
            data['from_'] = JID.from_string(invite.getAttr('from'))
            data['reason'] = invite.getTagData('reason')
            data['password'] = muc_user.getTagData('password')
            data['type'] = InviteType.MEDIATED

            data['continued'] = False
            data['thread'] = None
            continue_ = invite.getTag('continue')
            if continue_ is not None:
                data['continued'] = True
                data['thread'] = continue_.getAttr('thread')
            properties.muc_invite = InviteData(**data)
            return

        decline = muc_user.getTag('decline')
        if decline is not None:
            data['muc'] = properties.jid.new_as_bare()
            data['from_'] = JID.from_string(decline.getAttr('from'))
            data['reason'] = decline.getTagData('reason')
            properties.muc_decline = DeclineData(**data)
            return
Пример #16
0
    def _test_credentials(self, ignore_all_errors=False):
        self._show_progress_page(_('Connecting...'),
                                 _('Connecting to server...'))
        address, password = self.get_page('login').get_credentials()
        jid = JID.from_string(address)
        advanced = self.get_page('login').is_advanced()

        self._client = self._get_base_client(jid.domain, jid.localpart,
                                             Mode.LOGIN_TEST, advanced,
                                             ignore_all_errors)

        self._client.set_password(password)
        self._client.subscribe('login-successful', self._on_login_successful)

        self._client.connect()
Пример #17
0
def validate_jid(jid, type_=None):
    try:
        jid = JID.from_string(str(jid))
    except InvalidJid as error:
        raise ValueError(error)

    if type_ is None:
        return jid
    if type_ == 'bare' and jid.is_bare:
        return jid
    if type_ == 'full' and jid.is_full:
        return jid
    if type_ == 'domain' and jid.is_domain:
        return jid

    raise ValueError('Not a %s JID' % type_)
Пример #18
0
    def _on_apply_clicked(self, _button):
        bookmarks = []
        for row in self._ui.bookmarks_store:
            if not row[Column.ADDRESS]:
                continue

            bookmark = BookmarkData(jid=JID.from_string(row[Column.ADDRESS]),
                                    name=row[Column.NAME],
                                    autojoin=row[Column.AUTOJOIN],
                                    password=row[Column.PASSWORD],
                                    nick=row[Column.NICK])
            bookmarks.append(bookmark)

        con = app.connections[self.account]
        con.get_module('Bookmarks').store_difference(bookmarks)
        self.destroy()
Пример #19
0
def parse_muc_user(muc_user, is_presence=True):
    item = muc_user.getTag('item')
    if item is None:
        return None

    item_dict = item.getAttrs()

    role = item_dict.get('role')
    if role is not None:
        try:
            role = Role(role)
        except ValueError:
            raise StanzaMalformed('invalid role %s' % role)

    elif is_presence:
        # role attr MUST be included in all presence broadcasts
        raise StanzaMalformed('role attr missing')

    affiliation = item_dict.get('affiliation')
    if affiliation is not None:
        try:
            affiliation = Affiliation(affiliation)
        except ValueError:
            raise StanzaMalformed('invalid affiliation %s' % affiliation)

    elif is_presence:
        # affiliation attr MUST be included in all presence broadcasts
        raise StanzaMalformed('affiliation attr missing')

    jid = item_dict.get('jid')
    if jid is not None:
        try:
            jid = JID.from_string(jid)
        except InvalidJid as error:
            raise StanzaMalformed('invalid jid %s, %s' % (jid, error))

    return MucUserData(affiliation=affiliation,
                       jid=jid,
                       nick=item.getAttr('nick'),
                       role=role,
                       actor=item.getTagAttr('actor', 'nick'),
                       reason=item.getTagData('reason'))
Пример #20
0
    def _process_groupchat_message(self, _client, stanza, properties):
        properties.from_muc = True
        properties.muc_jid = properties.jid.new_as_bare()
        properties.muc_nickname = properties.jid.resource

        muc_user = stanza.getTag('x', namespace=Namespace.MUC_USER)
        if muc_user is not None:
            try:
                properties.muc_user = parse_muc_user(muc_user,
                                                     is_presence=False)
            except StanzaMalformed as error:
                self._log.warning(error)
                self._log.warning(stanza)
                raise NodeProcessed

        addresses = stanza.getTag('addresses', namespace=Namespace.ADDRESS)
        if addresses is not None:
            address = addresses.getTag('address', attrs={'type': 'ofrom'})
            if address is not None:
                properties.muc_ofrom = JID.from_string(address.getAttr('jid'))
Пример #21
0
    def _process_direct_invite(_client, stanza, properties):
        direct = stanza.getTag('x', namespace=Namespace.CONFERENCE)
        if direct is None:
            return

        if stanza.getTag('x', namespace=Namespace.MUC_USER) is not None:
            # not a direct invite
            # See https://xmpp.org/extensions/xep-0045.html#example-57
            # read implementation notes
            return

        data = {}
        data['muc'] = JID.from_string(direct.getAttr('jid'))
        data['from_'] = properties.jid
        data['reason'] = direct.getAttr('reason')
        data['password'] = direct.getAttr('password')
        data['continued'] = direct.getAttr('continue') == 'true'
        data['thread'] = direct.getAttr('thread')
        data['type'] = InviteType.DIRECT
        properties.muc_invite = InviteData(**data)
Пример #22
0
def parse_signcrypt(stanza):
    '''
    <signcrypt xmlns='urn:xmpp:openpgp:0'>
      <to jid='*****@*****.**'/>
      <time stamp='2014-07-10T17:06:00+02:00'/>
      <rpad>
        f0rm1l4n4-mT8y33j!Y%fRSrcd^ZE4Q7VDt1L%WEgR!kv
      </rpad>
      <payload>
        <body xmlns='jabber:client'>
          This is a secret message.
        </body>
      </payload>
    </signcrypt>
    '''
    if (stanza.getName() != 'signcrypt'
            or stanza.getNamespace() != Namespace.OPENPGP):
        raise StanzaMalformed('Invalid signcrypt node')

    to_nodes = stanza.getTags('to')
    if not to_nodes:
        raise StanzaMalformed('missing to nodes')

    recipients = []
    for to_node in to_nodes:
        jid = to_node.getAttr('jid')
        try:
            recipients.append(JID.from_string(jid))
        except Exception as error:
            raise StanzaMalformed('Invalid jid: %s %s' % (jid, error))

    timestamp = stanza.getTagAttr('time', 'stamp')
    if timestamp is None:
        raise StanzaMalformed('Invalid timestamp')

    payload = stanza.getTag('payload')
    if payload is None or payload.getChildren() is None:
        raise StanzaMalformed('Invalid payload node')
    return payload.getChildren(), recipients, timestamp
Пример #23
0
    def set_os_info(self, task):
        error = False
        try:
            result = task.finish()
        except StanzaError:
            error = True

        jid = task.get_user_data()

        if self.xml.get_object('information_notebook').get_n_pages() < 5:
            return

        i = 0
        client = ''
        os_info = ''
        while i in self.os_info:
            if self.os_info[i]['resource'] == JID.from_string(jid).resource:
                if not error:
                    self.os_info[i]['client'] = '%s %s' % (result.name,
                                                           result.version)
                else:
                    self.os_info[i]['client'] = Q_('?Client:Unknown')

                if not error and result.os is not None:
                    self.os_info[i]['os'] = result.os
                else:
                    self.os_info[i]['os'] = Q_('?OS:Unknown')

            if i > 0:
                client += '\n'
                os_info += '\n'
            client += self.os_info[i]['client']
            os_info += self.os_info[i]['os']
            i += 1

        self.xml.get_object('client_name_version_label').set_text(client)
        self.xml.get_object('os_label').set_text(os_info)
        self.os_info_arrived = True
Пример #24
0
    def request_blocking_list(self):
        _task = yield

        result = yield _make_blocking_list_request()
        if result.isError():
            raise StanzaError(result)

        blocklist = result.getTag('blocklist', namespace=Namespace.BLOCKING)
        if blocklist is None:
            raise MalformedStanzaError('blocklist node missing', result)

        blocked = set()
        for item in blocklist.getTags('item'):
            try:
                jid = JID.from_string(item.getAttr('jid'))
            except Exception:
                self._log.info('Invalid JID: %s', item.getAttr('jid'))
                continue

            blocked.add(jid)

        self._log.info('Received blocking list: %s', blocked)
        yield blocked
Пример #25
0
def parse_bookmark(item):
    conference = item.getTag('conference', namespace=Namespace.BOOKMARKS_1)
    if conference is None:
        raise MalformedStanzaError('conference node missing', item)

    try:
        jid = JID.from_string(item.getAttr('id'))
    except Exception as error:
        raise MalformedStanzaError('invalid jid: %s' % error, item)

    if jid.localpart is None or jid.resource is not None:
        raise MalformedStanzaError('invalid jid', item)

    autojoin = parse_autojoin(conference.getAttr('autojoin'))
    nick = parse_nickname(conference.getTagData('nick'))
    name = conference.getAttr('name') or None
    password = conference.getTagData('password') or None

    return BookmarkData(jid=jid,
                        name=name,
                        autojoin=autojoin,
                        password=password,
                        nick=nick)
Пример #26
0
def _jid_converter(jid):
    return JID.from_string(jid.decode())
Пример #27
0
 def address(self):
     return JID.from_string(self._builder.address.get_text())
Пример #28
0
    def test_jid_escaping(self):
        # (user input, escaped)
        tests = [
            (r'space [email protected]',
             r'space\[email protected]'),

            (r'call me "ishmael"@example.com',
             r'call\20me\20\22ishmael\[email protected]'),

            (r'at&t [email protected]',
             r'at\26t\[email protected]'),

            ('d\'*****@*****.**',
             r'd\[email protected]'),

            (r'/[email protected]',
             r'\[email protected]'),

            (r'::foo::@example.com',
             r'\3a\3afoo\3a\[email protected]'),

            (r'<foo>@example.com',
             r'\3cfoo\[email protected]'),

            (r'user@[email protected]',
             r'user\[email protected]'),

            (r'c:\[email protected]',
             r'c\3a\[email protected]'),

            (r'c:\\[email protected]',
             r'c\3a\\[email protected]'),

            (r'c:\cool [email protected]',
             r'c\3a\cool\[email protected]'),

            (r'c:\[email protected]',
             r'c\3a\[email protected]'),

            (r'call me\[email protected]',
             r'call\20me\[email protected]'),
        ]

        tests2 = [
            '*****@*****.**',
            '*****@*****.**',
            '*****@*****.**',
            '*****@*****.**',
            '*****@*****.**',
            'fu\[email protected]',
            '\[email protected]',
            '\[email protected]',
            '\[email protected]',
            '\[email protected]',
            'example.com',
        ]

        test3 = [
            '\\20callme\\[email protected]',
            '\\[email protected]',
            'callme\\[email protected]',
        ]

        test4 = [
            ('call\\[email protected]', 'call [email protected]',)
        ]

        fail_tests = [
            r'c:\[email protected]/asd',
            r'[email protected]/test'
        ]

        for user_input, escaped in tests:
            # Parse user input and escape it
            jid = JID.from_user_input(user_input)

            self.assertTrue(jid.domain == 'example.com')
            self.assertTrue(str(jid) == escaped)
            self.assertTrue(jid.to_user_string() == user_input)

            # We must fail on invalid JIDs
            with self.assertRaises(Exception):
                JID.from_string(user_input)

            # Parse escaped JIDs
            jid = JID.from_string(escaped)
            self.assertTrue(str(jid) == escaped)
            self.assertTrue(jid.domain == 'example.com')

        for jid in tests2:
            # show that from_string() and from_user_input() produce the same
            # result for valid bare JIDs
            self.assertTrue(JID.from_string(jid) == JID.from_user_input(jid))

        for jid in test3:
            # JIDs starting or ending with \20 are not escaped
            self.assertTrue(JID.from_string(jid).to_user_string() == jid)

        for user_input, user_string in test4:
            # Test escaped keyword argument
            self.assertTrue(JID.from_user_input(user_input, escaped=True) != JID.from_user_input(user_input))
            self.assertTrue(JID.from_user_input(user_input, escaped=True).to_user_string() == user_string)

        for user_input in fail_tests:
            # from_user_input does only support bare jids
            with self.assertRaises(Exception):
                JID.from_user_input(user_input)
Пример #29
0
    def _process_muc_user_presence(self, _client, stanza, properties):
        muc_user = stanza.getTag('x', namespace=Namespace.MUC_USER)
        if muc_user is None:
            return
        properties.from_muc = True
        properties.muc_jid = properties.jid.new_as_bare()

        destroy = muc_user.getTag('destroy')
        if destroy is not None:
            alternate = destroy.getAttr('jid')
            if alternate is not None:
                try:
                    alternate = JID.from_string(alternate)
                except Exception as error:
                    self._log.warning('Invalid alternate JID provided: %s',
                                      error)
                    self._log.warning(stanza)
                    alternate = None
            properties.muc_destroyed = MucDestroyed(
                alternate=alternate,
                reason=muc_user.getTagData('reason'),
                password=muc_user.getTagData('password'))
            return

        properties.muc_nickname = properties.jid.resource

        # https://xmpp.org/extensions/xep-0045.html#registrar-statuscodes
        message_status_codes = [
            StatusCode.NON_ANONYMOUS,
            StatusCode.SELF,
            StatusCode.CONFIG_ROOM_LOGGING,
            StatusCode.CREATED,
            StatusCode.NICKNAME_MODIFIED,
            StatusCode.REMOVED_BANNED,
            StatusCode.NICKNAME_CHANGE,
            StatusCode.REMOVED_KICKED,
            StatusCode.REMOVED_AFFILIATION_CHANGE,
            StatusCode.REMOVED_NONMEMBER_IN_MEMBERS_ONLY,
            StatusCode.REMOVED_SERVICE_SHUTDOWN,
            StatusCode.REMOVED_ERROR,
        ]

        codes = set()
        for status in muc_user.getTags('status'):
            try:
                code = StatusCode(status.getAttr('code'))
            except ValueError:
                self._log.warning('Received invalid status code: %s',
                                  status.getAttr('code'))
                self._log.warning(stanza)
                continue
            if code in message_status_codes:
                codes.add(code)

        if codes:
            properties.muc_status_codes = codes

        try:
            properties.muc_user = parse_muc_user(muc_user)
        except StanzaMalformed as error:
            self._log.warning(error)
            self._log.warning(stanza)
            raise NodeProcessed

        if (properties.muc_user is not None
                and properties.muc_user.role.is_none
                and not properties.type.is_unavailable):
            self._log.warning('Malformed Stanza')
            self._log.warning(stanza)
            raise NodeProcessed