Example #1
0
    def test_single_level_match(self):
        sub_ereg = MQTTUtils.convert_to_ereg("foo/+/bar")

        self.assertIsNotNone(re.match(sub_ereg, 'foo/buzz/bar'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo//bar'))

        self.assertIsNone(re.match(sub_ereg, 'foo/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/'))
        self.assertIsNone(re.match(sub_ereg, '/foo/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/one/two/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/one/bar/'))
        self.assertIsNone(re.match(sub_ereg, '/foo/one/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/+/bar'))

        ereg = MQTTUtils.convert_to_ereg('foo/bar/+')
        self.assertIsNotNone(re.match(ereg, 'foo/bar/buzz'))
        self.assertIsNotNone(re.match(ereg, 'foo/bar/'))

        self.assertIsNone(re.match(ereg, 'foo/bar/+'))
        self.assertIsNone(re.match(ereg, 'foo/bar/#'))
        self.assertIsNone(re.match(ereg, 'foo/bar/+/'))
        self.assertIsNone(re.match(ereg, 'foo/bar/+/#'))

        ereg = MQTTUtils.convert_to_ereg('+/foo/bar')
        self.assertIsNotNone(re.match(ereg, 'buzz/foo/bar'))
        self.assertIsNotNone(re.match(ereg, '/foo/bar'))

        self.assertIsNone(re.match(ereg, 'foo/bar'))
        self.assertIsNone(re.match(ereg, '//foo/bar'))
Example #2
0
    def test_single_level_match(self):
        sub_ereg = MQTTUtils.convert_to_ereg("foo/+/bar")

        self.assertIsNotNone(re.match(sub_ereg, 'foo/buzz/bar'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo//bar'))

        self.assertIsNone(re.match(sub_ereg, 'foo/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/'))
        self.assertIsNone(re.match(sub_ereg, '/foo/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/one/two/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/one/bar/'))
        self.assertIsNone(re.match(sub_ereg, '/foo/one/bar'))
        self.assertIsNone(re.match(sub_ereg, 'foo/+/bar'))

        ereg = MQTTUtils.convert_to_ereg('foo/bar/+')
        self.assertIsNotNone(re.match(ereg, 'foo/bar/buzz'))
        self.assertIsNotNone(re.match(ereg, 'foo/bar/'))

        self.assertIsNone(re.match(ereg, 'foo/bar/+'))
        self.assertIsNone(re.match(ereg, 'foo/bar/#'))
        self.assertIsNone(re.match(ereg, 'foo/bar/+/'))
        self.assertIsNone(re.match(ereg, 'foo/bar/+/#'))

        ereg = MQTTUtils.convert_to_ereg('+/foo/bar')
        self.assertIsNotNone(re.match(ereg, 'buzz/foo/bar'))
        self.assertIsNotNone(re.match(ereg, '/foo/bar'))

        self.assertIsNone(re.match(ereg, 'foo/bar'))
        self.assertIsNone(re.match(ereg, '//foo/bar'))
Example #3
0
    def _clear_authorization_entry(cls, ts, allow_wildcards=False):
        """
        Validates an authorization entry
        :param ts: authorization entry: an asterisk string `'*'` meaning
        fully authorized, or a list of strings (topics, wildcards allowed)
        :type ts: str | list[str]
        :return:
        """

        if ts == cls.ALL:
            return ts

        elif isinstance(ts, list):
            rs = []
            for t in ts:
                assert isinstance(t, str)
                ereg = MQTTUtils.convert_to_ereg(
                    t, allow_wildcards=allow_wildcards)
                assert isinstance(ereg, str)
                rs.append((t, re.compile(ereg)))

            return rs

        else:
            raise ValueError('authorization has unexpected format')
Example #4
0
    def test_single_level_mask(self):
        single_level = MQTTUtils.convert_to_ereg('foo/+/bar', allow_wildcards=True)
        self.assertIsMatch(single_level, 'foo/+/bar')
        self.assertIsMatch(single_level, 'foo/buzz/bar')
        self.assertIsMatch(single_level, 'foo//bar')

        self.assertIsNotMatch(single_level, 'foo/bar')
Example #5
0
    def _clear_authorization_entry(cls, ts, allow_wildcards=False):
        """
        Validates an authorization entry
        :param ts: authorization entry: an asterisk string `'*'` meaning
        fully authorized, or a list of strings (topics, wildcards allowed)
        :type ts: str | list[str]
        :return:
        """

        if ts == cls.ALL:
            return ts

        elif isinstance(ts, list):
            rs = []
            for t in ts:
                assert isinstance(t, str)
                ereg = MQTTUtils.convert_to_ereg(t,
                        allow_wildcards=allow_wildcards)
                assert isinstance(ereg, str)
                rs.append((t, re.compile(ereg)))

            return rs

        else:
            raise ValueError('authorization has unexpected format')
Example #6
0
    def test_single_level_mask(self):
        single_level = MQTTUtils.convert_to_ereg('foo/+/bar',
                                                 allow_wildcards=True)
        self.assertIsMatch(single_level, 'foo/+/bar')
        self.assertIsMatch(single_level, 'foo/buzz/bar')
        self.assertIsMatch(single_level, 'foo//bar')

        self.assertIsNotMatch(single_level, 'foo/bar')
Example #7
0
    def _get_regex(self, mask):
        compiled = self._re_cache.get(mask, None)

        if not compiled:
            ereg = MQTTUtils.convert_to_ereg(mask)
            compiled = re.compile(ereg)
            self._re_cache[mask] = compiled

        return compiled
Example #8
0
    def _get_regex(self, mask):
        compiled = self._re_cache.get(mask, None)

        if not compiled:
            ereg = MQTTUtils.convert_to_ereg(mask)
            compiled = re.compile(ereg)
            self._re_cache[mask] = compiled

        return compiled
Example #9
0
    def test_substring_doesnt_match(self):
        super = "/foo/bar"
        sub = "/foo/ba"

        sub_ereg = MQTTUtils.convert_to_ereg(sub)

        self.assertTrue(re.match(sub_ereg, sub) is not None)
        self.assertTrue(re.match(sub_ereg, super) is None)

        ereg = MQTTUtils.convert_to_ereg('foo/bar')
        self.assertIsNotNone(re.match(ereg, 'foo/bar'))

        self.assertIsNone(re.match(ereg, 'foo/bar/'))
        self.assertIsNone(re.match(ereg, '/foo/bar'))
        self.assertIsNone(re.match(ereg, 'foo//bar'))

        self.assertIsNone(re.match(ereg, 'foo/bar/buzz'))
        self.assertIsNone(re.match(ereg, 'buzz/foo/bar'))
        self.assertIsNone(re.match(ereg, 'foo/buzz/bar'))
Example #10
0
    def test_substring_doesnt_match(self):
        super = "/foo/bar"
        sub = "/foo/ba"

        sub_ereg = MQTTUtils.convert_to_ereg(sub)

        self.assertTrue(re.match(sub_ereg, sub) is not None)
        self.assertTrue(re.match(sub_ereg, super) is None)

        ereg = MQTTUtils.convert_to_ereg('foo/bar')
        self.assertIsNotNone(re.match(ereg, 'foo/bar'))

        self.assertIsNone(re.match(ereg, 'foo/bar/'))
        self.assertIsNone(re.match(ereg, '/foo/bar'))
        self.assertIsNone(re.match(ereg, 'foo//bar'))

        self.assertIsNone(re.match(ereg, 'foo/bar/buzz'))
        self.assertIsNone(re.match(ereg, 'buzz/foo/bar'))
        self.assertIsNone(re.match(ereg, 'foo/buzz/bar'))
Example #11
0
    def test_multilevel_match(self):
        sub = "foo/bar/#"
        sub_ereg = MQTTUtils.convert_to_ereg(sub)
        self.assertIsNone(re.match(sub_ereg, 'foo/b'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one/'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one/two'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one/two/'))

        self.assertIsNone(re.match(sub_ereg, 'foo/bar/#'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/+'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/+/'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/+/#'))
Example #12
0
    def test_multilevel_match(self):
        sub = "foo/bar/#"
        sub_ereg = MQTTUtils.convert_to_ereg(sub)
        self.assertIsNone(re.match(sub_ereg, 'foo/b'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one/'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one/two'))
        self.assertIsNotNone(re.match(sub_ereg, 'foo/bar/one/two/'))

        self.assertIsNone(re.match(sub_ereg, 'foo/bar/#'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/+'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/+/'))
        self.assertIsNone(re.match(sub_ereg, 'foo/bar/+/#'))
Example #13
0
    def test_multi_level_mask(self):
        """
        tests for access_control.Authorization.is_subscription_allowed
        """
        multi_level = MQTTUtils.convert_to_ereg('foo/bar/#', allow_wildcards=True)

        self.assertIsMatch(multi_level, 'foo/bar')
        self.assertIsMatch(multi_level, 'foo/bar/')
        self.assertIsMatch(multi_level, 'foo/bar//')
        self.assertIsMatch(multi_level, 'foo/bar/#')

        self.assertIsMatch(multi_level, 'foo/bar/+')
        self.assertIsMatch(multi_level, 'foo/bar/+/')
        self.assertIsMatch(multi_level, 'foo/bar/+/#')

        self.assertIsMatch(multi_level, 'foo/bar/buzz/+/#')
        self.assertIsMatch(multi_level, 'foo/bar/fuzz/+/buzz/#')
Example #14
0
    def test_multi_level_mask(self):
        """
        tests for access_control.Authorization.is_subscription_allowed
        """
        multi_level = MQTTUtils.convert_to_ereg('foo/bar/#',
                                                allow_wildcards=True)

        self.assertIsMatch(multi_level, 'foo/bar')
        self.assertIsMatch(multi_level, 'foo/bar/')
        self.assertIsMatch(multi_level, 'foo/bar//')
        self.assertIsMatch(multi_level, 'foo/bar/#')

        self.assertIsMatch(multi_level, 'foo/bar/+')
        self.assertIsMatch(multi_level, 'foo/bar/+/')
        self.assertIsMatch(multi_level, 'foo/bar/+/#')

        self.assertIsMatch(multi_level, 'foo/bar/buzz/+/#')
        self.assertIsMatch(multi_level, 'foo/bar/fuzz/+/buzz/#')
Example #15
0
    def test_mixed_masks(self):
        mixed = MQTTUtils.convert_to_ereg('foo/+/bar/#', allow_wildcards=True)
        self.assertIsMatch(mixed, 'foo/+/bar')
        self.assertIsMatch(mixed, 'foo/+/bar/#')
        self.assertIsMatch(mixed, 'foo/+/bar/buzz')
        self.assertIsMatch(mixed, 'foo/+/bar/buzz/')
        self.assertIsMatch(mixed, 'foo/+/bar/buzz/#')
        self.assertIsMatch(mixed, 'foo/+/bar/+/#')
        self.assertIsMatch(mixed, 'foo/+/bar/+/+/#')
        self.assertIsMatch(mixed, 'foo/buzz/bar')
        self.assertIsMatch(mixed, 'foo/buzz/bar/')
        self.assertIsMatch(mixed, 'foo/buzz/bar/+')
        self.assertIsMatch(mixed, 'foo/buzz/bar/#')
        self.assertIsMatch(mixed, 'foo/buzz/bar/+/')
        self.assertIsMatch(mixed, 'foo/buzz/bar/+/#')

        self.assertIsNotMatch(mixed, 'foo/#')
        self.assertIsNotMatch(mixed, 'foo/+/#')
        self.assertIsNotMatch(mixed, 'foo/+/+/#')
Example #16
0
    def test_mixed_masks(self):
        mixed = MQTTUtils.convert_to_ereg('foo/+/bar/#', allow_wildcards=True)
        self.assertIsMatch(mixed, 'foo/+/bar')
        self.assertIsMatch(mixed, 'foo/+/bar/#')
        self.assertIsMatch(mixed, 'foo/+/bar/buzz')
        self.assertIsMatch(mixed, 'foo/+/bar/buzz/')
        self.assertIsMatch(mixed, 'foo/+/bar/buzz/#')
        self.assertIsMatch(mixed, 'foo/+/bar/+/#')
        self.assertIsMatch(mixed, 'foo/+/bar/+/+/#')
        self.assertIsMatch(mixed, 'foo/buzz/bar')
        self.assertIsMatch(mixed, 'foo/buzz/bar/')
        self.assertIsMatch(mixed, 'foo/buzz/bar/+')
        self.assertIsMatch(mixed, 'foo/buzz/bar/#')
        self.assertIsMatch(mixed, 'foo/buzz/bar/+/')
        self.assertIsMatch(mixed, 'foo/buzz/bar/+/#')

        self.assertIsNotMatch(mixed, 'foo/#')
        self.assertIsNotMatch(mixed, 'foo/+/#')
        self.assertIsNotMatch(mixed, 'foo/+/+/#')
Example #17
0
    def subscribe(self, subscription_mask, qos):
        """
        Subscribes the client to a topic or wildcarded mask at the informed QoS
        level. Calling this method also signalizes the server to enqueue the
        matching retained messages.

        When called for a (`subscripition_mask`, `qos`) pair for which the
        client has already a subscription it will silently ignore the command
        and return a suback.

        :param string subscription_mask: A MQTT valid topic or wildcarded mask;
        :param int qos: A valid QoS level (0, 1 or 2).
        :rtype: int
        :return: The granted QoS level (0, 1 or 2) or 0x80 for failed
          subscriptions.
        """
        if qos not in [0, 1, 2]:
            self.logger.warn('client tried to subscribe with invalid qos %s' %
                             qos)
            return 0x80

        new_subscription = subscription_mask not in self.subscriptions or \
            self.subscriptions.qos(subscription_mask) != qos

        if not self.authorization.is_subscription_allowed(subscription_mask):
            self.logger.warn("[uid: %s] is not allowed to subscribe on %s" %
                             (self.uid, subscription_mask))
            del self.subscriptions[subscription_mask]
            qos = 0x80

        elif new_subscription:
            ereg = MQTTUtils.convert_to_ereg(subscription_mask)
            if ereg is not None:
                self.subscriptions.add(subscription_mask, qos,
                                       re.compile(ereg))
                self.server.enqueue_retained_message(self, subscription_mask)

            else:
                qos = 0x80
        if "#" in subscription_mask:
            print("SUBSCRIBING TO: {}".format(subscription_mask))
        return qos
Example #18
0
    def test_mixed_match(self):
        ereg = MQTTUtils.convert_to_ereg('foo/+/bar/#')
        self.assertIsNotNone(re.match(ereg, 'foo/xyz/bar'))
        self.assertIsNotNone(re.match(ereg, 'foo/xyz/bar/'))
        self.assertIsNotNone(re.match(ereg, 'foo/xyz/bar/abc'))
        self.assertIsNotNone(re.match(ereg, 'foo//bar'))
        self.assertIsNotNone(re.match(ereg, 'foo//bar/'))
        self.assertIsNotNone(re.match(ereg, 'foo//bar/abc'))

        self.assertIsNone(re.match(ereg, 'foo/bar'))
        self.assertIsNone(re.match(ereg, 'foo/#'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/#'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/abc'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/abc/'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/abc/#'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/+/#'))
        self.assertIsNone(re.match(ereg, 'foo/xyz/bar/#'))
        self.assertIsNone(re.match(ereg, 'foo/xyz/bar/+'))
        self.assertIsNone(re.match(ereg, 'foo/xyz/bar/+/#'))
Example #19
0
    def test_mixed_match(self):
        ereg = MQTTUtils.convert_to_ereg('foo/+/bar/#')
        self.assertIsNotNone(re.match(ereg, 'foo/xyz/bar'))
        self.assertIsNotNone(re.match(ereg, 'foo/xyz/bar/'))
        self.assertIsNotNone(re.match(ereg, 'foo/xyz/bar/abc'))
        self.assertIsNotNone(re.match(ereg, 'foo//bar'))
        self.assertIsNotNone(re.match(ereg, 'foo//bar/'))
        self.assertIsNotNone(re.match(ereg, 'foo//bar/abc'))

        self.assertIsNone(re.match(ereg, 'foo/bar'))
        self.assertIsNone(re.match(ereg, 'foo/#'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/#'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/abc'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/abc/'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/abc/#'))
        self.assertIsNone(re.match(ereg, 'foo/+/bar/+/#'))
        self.assertIsNone(re.match(ereg, 'foo/xyz/bar/#'))
        self.assertIsNone(re.match(ereg, 'foo/xyz/bar/+'))
        self.assertIsNone(re.match(ereg, 'foo/xyz/bar/+/#'))
Example #20
0
    def subscribe(self, subscription_mask, qos):
        """
        Subscribes the client to a topic or wildcarded mask at the informed QoS
        level. Calling this method also signalizes the server to enqueue the
        matching retained messages.

        When called for a (`subscripition_mask`, `qos`) pair for which the
        client has already a subscription it will silently ignore the command
        and return a suback.

        :param string subscription_mask: A MQTT valid topic or wildcarded mask;
        :param int qos: A valid QoS level (0, 1 or 2).
        :rtype: int
        :return: The granted QoS level (0, 1 or 2) or 0x80 for failed
          subscriptions.
        """
        if qos not in [0, 1, 2]:
            self.logger.warn('client tried to subscribe with invalid qos %s' % qos)
            return 0x80

        new_subscription = subscription_mask not in self.subscriptions or \
            self.subscriptions.qos(subscription_mask) != qos

        if not self.authorization.is_subscription_allowed(subscription_mask):
            self.logger.warn("[uid: %s] is not allowed to subscribe on %s" %
                             (self.uid, subscription_mask))
            del self.subscriptions[subscription_mask]
            qos = 0x80

        elif new_subscription:
            ereg = MQTTUtils.convert_to_ereg(subscription_mask)
            if ereg is not None:
                self.subscriptions.add(subscription_mask, qos, re.compile(ereg))
                self.server.enqueue_retained_message(self, subscription_mask)

            else:
                qos = 0x80
        if "#" in subscription_mask:
            print("SUBSCRIBING TO: {}".format(subscription_mask))
        return qos
Example #21
0
 def add(self, mask, qos, pattern=None):
     self._re_cache[mask] = pattern or re.compile(MQTTUtils.convert_to_ereg(mask))
     self._subscriptions[mask] = qos
Example #22
0
 def add(self, mask, qos, pattern=None):
     self._re_cache[mask] = pattern or re.compile(
         MQTTUtils.convert_to_ereg(mask))
     self._subscriptions[mask] = qos