def test_empty_tree(self): """ Test trie ctor, and that is doesn't match on "any" prefix. """ t = StringTrie() for key in ['', 'f', 'foo', 'foobar']: with self.assertRaises(KeyError): t.longest_prefix_value(key)
def test_empty_tree(self): """ Test trie ctor, and that is doesn't match on "any" prefix. """ t = StringTrie() for key in [u'', u'f', u'foo', u'foobar']: with self.assertRaises(KeyError): t.longest_prefix_value(key)
def __init__(self, router_session_factory, config, reactor): self._router_session_factory = router_session_factory self._router_factory = router_session_factory._routerFactory self._options = config.get('options', {}) self._realm = self._options.get('realm', None) self._reactor = reactor self._payload_mapping = StringTrie() for topic, pmap in self._options.get('payload_mapping', {}).items(): self._set_payload_format(topic, pmap)
def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert (permissions is None or type(permissions) == list) if permissions: for p in permissions: assert (type(p) == dict) assert (default_permissions is None or type(default_permissions) == dict) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() self._wild_permissions = StringTrie() # for "wildcard" URIs, there will be a ".." in them somewhere, # and so we want to match on the biggest prefix # (i.e. everything to the left of the first "..") for obj in permissions or []: perms = RouterPermissions.from_dict(obj) if '..' in perms.uri: trunc = perms.uri[:perms.uri.index('..')] self._wild_permissions[trunc] = perms else: self._permissions[perms.uri] = perms
def test_longest_prefix_1(self): """ Test that keys are detected as prefix of themselfes. """ t = StringTrie() test_keys = ['f', 'foo', 'foobar', 'baz'] for key in test_keys: t[key] = key for key in test_keys: self.assertEqual(t.longest_prefix_value(key), key)
def test_longest_prefix_1(self): """ Test that keys are detected as prefix of themselfes. """ t = StringTrie() test_keys = [u'f', u'foo', u'foobar', u'baz'] for key in test_keys: t[key] = key for key in test_keys: self.assertEqual(t.longest_prefix_value(key), key)
def __init__(self, default_key=None): """ Create a new key ring to hold public and private keys mapped from an URI space. """ assert (default_key is None or isinstance(default_key, Key) or type(default_key == six.text_type)) self._uri_to_key = StringTrie() if type(default_key) == six.text_type: default_key = Key(originator_priv=default_key, responder_priv=default_key) self._default_key = default_key
def test_longest_prefix_3(self): """ Test non-matching prefix lookups. """ t = StringTrie() for key in ['x', 'fop', 'foobar']: t[key] = key for key in ['y', 'yfoo', 'fox', 'fooba']: with self.assertRaises(KeyError): t.longest_prefix_value(key)
def is_valid(valid_list, letters): # create empty trie trie = StringTrie() # traverse through list of string to insert it in trie. # Here value of key is itself key because at last we need to retun for key in valid_list: trie[key] = key # values(search) method returns list of values of keys # which contains search pattern as prefix return trie.values(letters)
def test_longest_prefix_3(self): """ Test non-matching prefix lookups. """ t = StringTrie() for key in [u'x', u'fop', u'foobar']: t[key] = key for key in [u'y', u'yfoo', u'fox', u'fooba']: with self.assertRaises(KeyError): t.longest_prefix_value(key)
def prefixSearch(arr, prefix): trie = StringTrie() # traverse through list of strings # to insert it in trie. Here value of # key is itself key because at last # we need to return for key in arr: trie[key] = key length = len(prefix) + 1 for x in range(2, length): answer = trie.values(prefix[:x]) answer.sort() print(answer)
def init(): app.meditems = StringTrie() drugs = ['advil', 'tylenol'] app.conitems = StringTrie() conditions = ['high cholesterol', 'fatness'] for d in drugs: app.meditems[d] = d for c in conditions: app.conitems[c] = c
def build_trie_and_execute(map_to_search, prefix_term): trie = StringTrie() for key in map_to_search: trie[key] = key prefix_matches = trie.values(url_id) if len(prefix_matches) > 0: first_match = prefix_matches[0] index = map_to_search[first_match][0] open_url_in_browser(links[index], get_params()) return True return False
def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert(permissions is None or isinstance(permissions, list)) if permissions: for p in permissions: assert(isinstance(p, dict)) assert(default_permissions is None or isinstance(default_permissions, dict)) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() self._wild_permissions = StringTrie() # for "wildcard" URIs, there will be a ".." in them somewhere, # and so we want to match on the biggest prefix # (i.e. everything to the left of the first "..") for obj in permissions or []: perms = RouterPermissions.from_dict(obj) if '..' in perms.uri: trunc = perms.uri[:perms.uri.index('..')] self._wild_permissions[trunc] = perms else: self._permissions[perms.uri] = perms
def init(): app.p = Predictor() app.meditems = StringTrie() drugs = app.p.get_drugs() app.conitems = StringTrie() conditions = app.p.get_conditions() for d in drugs: app.meditems[d] = d for c in conditions: app.conitems[c] = c
def prefix_search(arr, prefix): # create empty trie trie = StringTrie() # traverse through list of strings # to insert it in trie. Here value of # key is itself key because at last # we need to return for key in arr: trie[key] = key # values(search) method returns list # of values of keys which contains # search pattern as prefix return trie.values(prefix)
def test_longest_prefix_4(self): """ Test that a trie with an empty string as a key contained matches a non-empty prefix matching lookup. """ self.skip = True # stored_key = u'x' # this works (and of course it should!) stored_key = u'' # this blows up! (and it _should_ work) test_key = u'xyz' t = StringTrie() t[stored_key] = stored_key self.assertTrue(stored_key in t) self.assertTrue(test_key.startswith(stored_key)) self.assertEqual(t.longest_prefix_value(test_key), stored_key)
def test_longest_prefix_4(self): """ Test that a trie with an empty string as a key contained matches a non-empty prefix matching lookup. """ self.skip = True # stored_key = 'x' # this works (and of course it should!) stored_key = '' # this blows up! (and it _should_ work) test_key = 'xyz' t = StringTrie() t[stored_key] = stored_key self.assertTrue(stored_key in t) self.assertTrue(test_key.startswith(stored_key)) self.assertEqual(t.longest_prefix_value(test_key), stored_key)
def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert (permissions is None or type(permissions) == list) if permissions: for p in permissions: assert (type(p) == dict) assert (default_permissions is None or type(default_permissions) == dict) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() for obj in permissions or []: perms = RouterPermissions.from_dict(obj) self._permissions[perms.uri] = perms
def __init__(self, router, uri, permissions=None, default_permissions=None): """ Ctor. :param uri: The URI of the role. :type uri: str :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list """ RouterRole.__init__(self, router, uri) self.permissions = permissions or [] self._urimap = StringTrie() self._default = default_permissions or RouterPermissions('', True, False, False, False, False) for p in self.permissions: uri = p['uri'] if len(uri) > 0 and uri[-1] == '*': match_by_prefix = True uri = uri[:-1] else: match_by_prefix = False perms = RouterPermissions(uri, match_by_prefix, call=p.get('call', False), register=p.get('register', False), publish=p.get('publish', False), subscribe=p.get('subscribe', False)) if len(uri) > 0: self._urimap[uri] = perms else: self._default = perms
def __init__(self, ordered=False): # flag indicating whether observers should be maintained in a SortedSet # or a regular set (unordered) self._ordered = ordered # map: URI => ExactUriObservation self._observations_exact = {} # map: URI => PrefixUriObservation self._observations_prefix = StringTrie() # map: URI => WildcardUriObservation self._observations_wildcard = WildcardTrieMatcher() # map: observation ID => UriObservation self._observation_id_to_observation = {}
class FIB: def __init__(self): self.fib = StringTrie() self.fib["/mbandeira"] = "int1" self.fib["/cdrummond"] = "int2" def getIface(self, contentName): return self.fib.longest_prefix_value(contentName)
def __init__(self, router_session_factory, config, reactor): self._router_session_factory = router_session_factory self._router_factory = router_session_factory._routerFactory self._options = config.get(u'options', {}) self._realm = self._options.get(u'realm', None) self._reactor = reactor self._payload_mapping = StringTrie() for topic, pmap in self._options.get(u'payload_mapping', {}).items(): self._set_payload_format(topic, pmap)
def __init__(self, router, uri, permissions=None, default_permissions=None, debug=False): """ Ctor. :param uri: The URI of the role. :type uri: str :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list :param debug: Enable debug logging. :type debug: bool """ RouterRole.__init__(self, router, uri, debug) self.permissions = permissions or [] self._urimap = StringTrie() self._default = default_permissions or RouterPermissions( '', True, False, False, False, False) for p in self.permissions: uri = p['uri'] if len(uri) > 0 and uri[-1] == '*': match_by_prefix = True uri = uri[:-1] else: match_by_prefix = False perms = RouterPermissions(uri, match_by_prefix, call=p.get('call', False), register=p.get('register', False), publish=p.get('publish', False), subscribe=p.get('subscribe', False)) if len(uri) > 0: self._urimap[uri] = perms else: self._default = perms
def __init__(self, default_key=None): """ Create a new key ring to hold public and private keys mapped from an URI space. """ assert(default_key is None or isinstance(default_key, Key) or type(default_key == six.text_type)) self._uri_to_key = StringTrie() if type(default_key) == six.text_type: default_key = Key(originator_priv=default_key, responder_priv=default_key) self._default_key = default_key
def filter_argv(argv, option_strings, *blacklist): ptree = StringTrie({v: i for i, v in enumerate(blacklist)}) filtered = [] boolean_args = set(option_strings) i = -1 while i + 1 < len(argv): i += 1 arg = argv[i] has_value = arg.startswith("-") and \ not any(arg.startswith(b) for b in boolean_args) \ and '=' not in arg and arg != "-" if ptree.longest_prefix(arg, None) is None: filtered.append(arg) if has_value: i += 1 filtered.append(argv[i]) elif has_value: i += 1 return filtered
def prefixSearch(arr, modelName): # create empty trie trie = StringTrie() # traverse through list of strings # to insert it in trie. Here value of # key is itself key because at last # we need to return for key in arr: trie[key] = key save_object(trie, modelName)
class Suggester(object): def __init__(self): self.trie = None def update_trie(self, word_list): self.trie = StringTrie() for word in word_list: word = word.lower() self.trie[word] = word def search_prefix(self, prefix): return self.trie.values(prefix=prefix)
def test_longest_prefix_2(self): """ Test matching prefix lookups. """ t = StringTrie() test_keys = [u'f', u'foo', u'foobar'] for key in test_keys: t[key] = key test_keys = { u'foobarbaz': u'foobar', u'foobaz': u'foo', u'fool': u'foo', u'foo': u'foo', u'fob': u'f', u'fo': u'f', u'fx': u'f', u'f': u'f', } for key in test_keys: self.assertEqual(t.longest_prefix_value(key), test_keys[key])
def test_contains(self): """ Test the contains operator. """ t = StringTrie() test_keys = ['', 'f', 'foo', 'foobar', 'baz'] for key in test_keys: t[key] = key for key in test_keys: self.assertTrue(key in t) for key in ['x', 'fb', 'foob', 'fooba', 'bazz']: self.assertFalse(key in t)
def test_longest_prefix_2(self): """ Test matching prefix lookups. """ t = StringTrie() test_keys = ['f', 'foo', 'foobar'] for key in test_keys: t[key] = key test_keys = { 'foobarbaz': 'foobar', 'foobaz': 'foo', 'fool': 'foo', 'foo': 'foo', 'fob': 'f', 'fo': 'f', 'fx': 'f', 'f': 'f', } for key in test_keys: self.assertEqual(t.longest_prefix_value(key), test_keys[key])
def __init__(self, ordered=False): # flag indicating whether observers should be maintained in a SortedSet # or a regular set (unordered) self._ordered = ordered # map: URI => ExactUriObservation self._observations_exact = {} # map: URI => PrefixUriObservation self._observations_prefix = StringTrie() # map: URI => WildcardUriObservation if True: # use a Trie-based implementation (supposed to be faster, but # otherwise compatible to the naive implementation below) self._observations_wildcard = WildcardTrieMatcher() else: self._observations_wildcard = WildcardMatcher() # map: observation ID => UriObservation self._observation_id_to_observation = {}
class GeohashContainer(object): """ A class which can be used as a container of geohashes and corresponding items. The underlying data structure is a trie (StringTrie).""" def __init__(self, itemCollection): self.container = StringTrie() for item in itemCollection: self.container[Geohash.encode(item.Location.Latitude, item.Location.Longitude)] = item def Retrieve(self, keyPrefix): """ Returns all items which match the specified keyPrefix """ results = self.container.values(keyPrefix) return results def Add(self, key, value): """ Adds a new item to its underlying container """ self.container[key] = value
class Suggester(object): def __init__(self): self.trie = None self.trie = StringTrie() def update_trie(self, word_list): for word in word_list: # word = word.lower() # 拼音提取,首字母,全拼都改成小写,去空格 word_pinyin1 = get_every_word_first(word) word_pinyin2 = get_all_pinying(word) # 拼音建立字典树 self.trie[word] = word self.trie[word_pinyin1] = word_pinyin1 self.trie[word_pinyin2] = word_pinyin2 def search_prefix(self, prefix): return self.trie.values(prefix=prefix)
def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert(permissions is None or type(permissions) == list) if permissions: for p in permissions: assert(type(p) == dict) assert(default_permissions is None or type(default_permissions) == dict) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() for obj in permissions or []: perms = RouterPermissions.from_dict(obj) self._permissions[perms.uri] = perms
class WampMQTTServerFactory(Factory): log = make_logger() protocol = WampMQTTServerProtocol serializers = { u'json': JsonObjectSerializer(), u'msgpack': MsgPackObjectSerializer(), u'cbor': CBORObjectSerializer(), u'ubjson': UBJSONObjectSerializer(), } def __init__(self, router_session_factory, config, reactor): self._router_session_factory = router_session_factory self._router_factory = router_session_factory._routerFactory self._options = config.get(u'options', {}) self._realm = self._options.get(u'realm', None) self._reactor = reactor self._payload_mapping = StringTrie() for topic, pmap in self._options.get(u'payload_mapping', {}).items(): self._set_payload_format(topic, pmap) def buildProtocol(self, addr): protocol = self.protocol(self._reactor) protocol.factory = self return protocol def _get_payload_format(self, topic): """ Map a WAMP topic URI to MQTT payload format. :param topic: WAMP URI. :type topic: str :returns: Payload format metadata. :rtype: dict """ try: pmap = self._payload_mapping.longest_prefix_value(topic) except KeyError: return None else: return pmap def _set_payload_format(self, topic, pmap=None): if pmap is None: if topic in self._payload_mapping: del self._payload_mapping[topic] else: self._payload_mapping[topic] = pmap @inlineCallbacks def transform_wamp(self, topic, msg): # check for cached transformed payload cache_key = u'_{}_{}'.format(self.__class__.__name__, id(self)) cached = msg._serialized.get(cache_key, None) if cached: payload_format, mapped_topic, payload = cached self.log.debug('using cached payload for {cache_key} in message {msg_id}!', msg_id=id(msg), cache_key=cache_key) else: # convert WAMP URI to MQTT topic mapped_topic = _wamp_topic_to_mqtt(topic) # for WAMP->MQTT, the payload mapping is determined from the # WAMP URI (not the transformed MQTT topic) payload_format = self._get_payload_format(topic) payload_format_type = payload_format[u'type'] if payload_format_type == u'passthrough': payload = msg.payload elif payload_format_type == u'native': serializer = payload_format.get(u'serializer', None) payload = self._transform_wamp_native(serializer, msg) elif payload_format_type == u'dynamic': encoder = payload_format.get(u'encoder', None) codec_realm = payload_format.get(u'realm', self._realm) payload = yield self._transform_wamp_dynamic(encoder, codec_realm, mapped_topic, topic, msg) else: raise Exception('payload format {} not implemented'.format(payload_format)) msg._serialized[cache_key] = (payload_format, mapped_topic, payload) self.log.debug('transform_wamp({topic}, {msg}) -> payload_format={payload_format}, mapped_topic={mapped_topic}, payload={payload}', topic=topic, msg=msg, payload_format=payload_format, mapped_topic=mapped_topic, payload=payload) returnValue((payload_format, mapped_topic, payload)) @inlineCallbacks def _transform_wamp_dynamic(self, encoder, codec_realm, mapped_topic, topic, msg): codec_session = self._router_factory.get(codec_realm)._realm.session payload = yield codec_session.call(encoder, mapped_topic, topic, msg.args, msg.kwargs) returnValue(payload) def _transform_wamp_native(self, serializer, msg): obj = {} for opt in [u'args', u'kwargs', u'exclude', u'exclude_authid', u'exclude_authrole', u'eligible', u'eligible_authid', u'eligible_authrole']: attr = getattr(msg, opt, None) if attr is not None: obj[opt] = attr if serializer in self.serializers: payload = self.serializers[serializer].serialize(obj) else: raise Exception('MQTT native mode payload transform: invalid serializer {}'.format(serializer)) return payload @inlineCallbacks def transform_mqtt(self, topic, payload): # transform MQTT topic to WAMP URI mapped_topic = _mqtt_topicname_to_wamp(topic) # for MQTT->WAMP, the payload mapping is determined from the # transformed WAMP URI (not the original MQTT topic) payload_format = self._get_payload_format(mapped_topic) payload_format_type = payload_format[u'type'] if payload_format_type == u'passthrough': options = { u'payload': payload, u'enc_algo': u'mqtt' } elif payload_format_type == u'native': serializer = payload_format.get(u'serializer', None) options = self._transform_mqtt_native(serializer, payload) elif payload_format_type == u'dynamic': decoder = payload_format.get(u'decoder', None) codec_realm = payload_format.get(u'realm', self._realm) options = yield self._transform_mqtt_dynamic(decoder, codec_realm, mapped_topic, topic, payload) else: raise Exception('payload format {} not implemented'.format(payload_format)) self.log.debug('transform_mqtt({topic}, {payload}) -> payload_format={payload_format}, mapped_topic={mapped_topic}, options={options}', topic=topic, payload=payload, payload_format=payload_format, mapped_topic=mapped_topic, options=options) returnValue((payload_format, mapped_topic, options)) @inlineCallbacks def _transform_mqtt_dynamic(self, decoder, codec_realm, mapped_topic, topic, payload): codec_session = self._router_factory.get(codec_realm)._realm.session options = yield codec_session.call(decoder, mapped_topic, topic, payload) returnValue(options) def _transform_mqtt_native(self, serializer, payload): """ Transform MQTT binary payload from a MQTT Publish to keyword dict suitable for the constructor of a WAMP Publish message, that is :class:`autobahn.wamp.message.Publish`. """ options = {} if serializer in self.serializers: if serializer == u'json': if not _validator.validate(payload)[0]: # invalid UTF-8: drop the event raise Exception('invalid UTF8 in JSON encoded MQTT payload') obj = self.serializers[serializer].unserialize(payload)[0] else: raise Exception('"{}" serializer for encoded MQTT payload not implemented'.format(serializer)) if type(obj) != dict: raise Exception('invalid type {} for "{}" encoded MQTT payload'.format(type(obj), serializer)) for opt in [u'args', u'kwargs', u'exclude', u'exclude_authid', u'exclude_authrole', u'eligible', u'eligible_authid', u'eligible_authrole']: if opt in obj: options[opt] = obj[opt] return options
def __init__(self): self.fib = StringTrie() self.fib["/mbandeira"] = "int1" self.fib["/cdrummond"] = "int2"
class KeyRing(object): """ A keyring holds (cryptobox) public-private key pairs for use with WAMP-cryptobox payload encryption. The keyring can be set on a WAMP session and then transparently will get used for encrypting and decrypting WAMP message payloads. """ @public def __init__(self, default_key=None): """ Create a new key ring to hold public and private keys mapped from an URI space. """ assert (default_key is None or isinstance(default_key, Key) or type(default_key == six.text_type)) self._uri_to_key = StringTrie() if type(default_key) == six.text_type: default_key = Key(originator_priv=default_key, responder_priv=default_key) self._default_key = default_key @public def generate_key(self): """ Generate a new private key and return a pair with the base64 encodings of (priv_key, pub_key). """ key = PrivateKey.generate() priv_key = key.encode(encoder=Base64Encoder) pub_key = key.public_key.encode(encoder=Base64Encoder) return (u'{}'.format(priv_key), u'{}'.format(pub_key)) @public def set_key(self, uri, key): """ Add a key set for a given URI. """ assert (type(uri) == six.text_type) assert (key is None or isinstance(key, Key) or type(key) == six.text_type) if type(key) == six.text_type: key = Key(originator_priv=key, responder_priv=key) if uri == u'': self._default_key = key else: if key is None: if uri in self._uri_to_key: del self._uri_to_key[uri] else: self._uri_to_key[uri] = key @public def rotate_key(self, uri): assert (type(uri) == six.text_type) if uri in self._uri_to_key: self._uri_to_key[uri].rotate() else: self._uri_to_key[uri].rotate() def _get_box(self, is_originating, uri, match_exact=False): try: if match_exact: key = self._uri_to_key[uri] else: key = self._uri_to_key.longest_prefix_value(uri) except KeyError: if self._default_key: key = self._default_key else: return None if is_originating: return key.originator_box else: return key.responder_box @public def encode(self, is_originating, uri, args=None, kwargs=None): """ Encrypt the given WAMP URI, args and kwargs into an EncodedPayload instance, or None if the URI should not be encrypted. """ assert (type(is_originating) == bool) assert (type(uri) == six.text_type) assert (args is None or type(args) in (list, tuple)) assert (kwargs is None or type(kwargs) == dict) box = self._get_box(is_originating, uri) if not box: # if we didn't find a crypto box, then return None, which # signals that the payload travel unencrypted (normal) return None payload = {u'uri': uri, u'args': args, u'kwargs': kwargs} nonce = random(Box.NONCE_SIZE) payload_ser = _json_dumps(payload).encode('utf8') payload_encr = box.encrypt(payload_ser, nonce, encoder=RawEncoder) # above returns an instance of http://pynacl.readthedocs.io/en/latest/utils/#nacl.utils.EncryptedMessage # which is a bytes _subclass_! hence we apply bytes() to get at the underlying plain # bytes "scalar", which is the concatenation of `payload_encr.nonce + payload_encr.ciphertext` payload_bytes = bytes(payload_encr) payload_key = None return EncodedPayload(payload_bytes, u'cryptobox', u'json', enc_key=payload_key) @public def decode(self, is_originating, uri, encoded_payload): """ Decrypt the given WAMP URI and EncodedPayload into a tuple ``(uri, args, kwargs)``. """ assert (type(uri) == six.text_type) assert (isinstance(encoded_payload, EncodedPayload)) assert (encoded_payload.enc_algo == u'cryptobox') box = self._get_box(is_originating, uri) if not box: raise Exception( "received encrypted payload, but can't find key!") payload_ser = box.decrypt(encoded_payload.payload, encoder=RawEncoder) if encoded_payload.enc_serializer != u'json': raise Exception( "received encrypted payload, but don't know how to process serializer '{}'" .format(encoded_payload.enc_serializer)) payload = _json_loads(payload_ser.decode('utf8')) uri = payload.get(u'uri', None) args = payload.get(u'args', None) kwargs = payload.get(u'kwargs', None) return uri, args, kwargs
class KeyRing(object): """ A keyring holds (cryptobox) public-private key pairs for use with WAMP-cryptobox payload encryption. The keyring can be set on a WAMP session and then transparently will get used for encrypting and decrypting WAMP message payloads. """ @public def __init__(self, default_key=None): """ Create a new key ring to hold public and private keys mapped from an URI space. """ assert(default_key is None or isinstance(default_key, Key) or type(default_key == six.text_type)) self._uri_to_key = StringTrie() if type(default_key) == six.text_type: default_key = Key(originator_priv=default_key, responder_priv=default_key) self._default_key = default_key @public def generate_key(self): """ Generate a new private key and return a pair with the base64 encodings of (priv_key, pub_key). """ key = PrivateKey.generate() priv_key = key.encode(encoder=Base64Encoder) pub_key = key.public_key.encode(encoder=Base64Encoder) return (u'{}'.format(priv_key), u'{}'.format(pub_key)) @public def set_key(self, uri, key): """ Add a key set for a given URI. """ assert(type(uri) == six.text_type) assert(key is None or isinstance(key, Key) or type(key) == six.text_type) if type(key) == six.text_type: key = Key(originator_priv=key, responder_priv=key) if uri == u'': self._default_key = key else: if key is None: if uri in self._uri_to_key: del self._uri_to_key[uri] else: self._uri_to_key[uri] = key @public def rotate_key(self, uri): assert(type(uri) == six.text_type) if uri in self._uri_to_key: self._uri_to_key[uri].rotate() else: self._uri_to_key[uri].rotate() def _get_box(self, is_originating, uri, match_exact=False): try: if match_exact: key = self._uri_to_key[uri] else: key = self._uri_to_key.longest_prefix_value(uri) except KeyError: if self._default_key: key = self._default_key else: return None if is_originating: return key.originator_box else: return key.responder_box @public def encode(self, is_originating, uri, args=None, kwargs=None): """ Encrypt the given WAMP URI, args and kwargs into an EncodedPayload instance, or None if the URI should not be encrypted. """ assert(type(is_originating) == bool) assert(type(uri) == six.text_type) assert(args is None or type(args) in (list, tuple)) assert(kwargs is None or type(kwargs) == dict) box = self._get_box(is_originating, uri) if not box: # if we didn't find a crypto box, then return None, which # signals that the payload travel unencrypted (normal) return None payload = { u'uri': uri, u'args': args, u'kwargs': kwargs } nonce = random(Box.NONCE_SIZE) payload_ser = _json_dumps(payload).encode('utf8') payload_encr = box.encrypt(payload_ser, nonce, encoder=RawEncoder) # above returns an instance of http://pynacl.readthedocs.io/en/latest/utils/#nacl.utils.EncryptedMessage # which is a bytes _subclass_! hence we apply bytes() to get at the underlying plain # bytes "scalar", which is the concatenation of `payload_encr.nonce + payload_encr.ciphertext` payload_bytes = bytes(payload_encr) payload_key = None return EncodedPayload(payload_bytes, u'cryptobox', u'json', enc_key=payload_key) @public def decode(self, is_originating, uri, encoded_payload): """ Decrypt the given WAMP URI and EncodedPayload into a tuple ``(uri, args, kwargs)``. """ assert(type(uri) == six.text_type) assert(isinstance(encoded_payload, EncodedPayload)) assert(encoded_payload.enc_algo == u'cryptobox') box = self._get_box(is_originating, uri) if not box: raise Exception("received encrypted payload, but can't find key!") payload_ser = box.decrypt(encoded_payload.payload, encoder=RawEncoder) if encoded_payload.enc_serializer != u'json': raise Exception("received encrypted payload, but don't know how to process serializer '{}'".format(encoded_payload.enc_serializer)) payload = _json_loads(payload_ser.decode('utf8')) uri = payload.get(u'uri', None) args = payload.get(u'args', None) kwargs = payload.get(u'kwargs', None) return uri, args, kwargs
def longest_match_pytrie(search): if longest_match_pytrie.trie is None: from pytrie import StringTrie longest_match_pytrie.trie = StringTrie.fromkeys(hosts) matches = longest_match_pytrie.trie.keys(prefix=search) return max(matches, key=len) if matches else ''
class RouterRoleStaticAuth(RouterRole): """ A role on a router realm that is authorized using a static configuration. """ def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert(permissions is None or isinstance(permissions, list)) if permissions: for p in permissions: assert(isinstance(p, dict)) assert(default_permissions is None or isinstance(default_permissions, dict)) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() self._wild_permissions = StringTrie() # for "wildcard" URIs, there will be a ".." in them somewhere, # and so we want to match on the biggest prefix # (i.e. everything to the left of the first "..") for obj in permissions or []: perms = RouterPermissions.from_dict(obj) if '..' in perms.uri: trunc = perms.uri[:perms.uri.index('..')] self._wild_permissions[trunc] = perms else: self._permissions[perms.uri] = perms def authorize(self, session, uri, action, options): """ Authorize a session connected under this role to perform the given action on the given URI. :param session: The WAMP session that requests the action. :type session: Instance of :class:`autobahn.wamp.protocol.ApplicationSession` :param uri: The URI on which to perform the action. :type uri: str :param action: The action to be performed. :type action: str :return: bool -- Flag indicating whether session is authorized or not. """ self.log.debug( "CrossbarRouterRoleStaticAuth.authorize {myuri} {uri} {action}", myuri=self.uri, uri=uri, action=action) try: # longest prefix match of the URI to be authorized against our Trie # of configured URIs for permissions permissions = self._permissions.longest_prefix_value(uri) # if there is a _prefix_ matching URI, check that this is actually the # match policy on the permission (otherwise, apply default permissions)! if permissions.match != u'prefix' and uri != permissions.uri: permissions = self._default except KeyError: # workaround because of https://bitbucket.org/gsakkis/pytrie/issues/4/string-keys-of-zero-length-are-not permissions = self._permissions.get(u'', self._default) # if we found a non-"exact" match, there might be a better one in the wildcards if permissions.match != u'exact': try: wildperm = self._wild_permissions.longest_prefix_value(uri) Pattern(wildperm.uri, Pattern.URI_TARGET_ENDPOINT).match(uri) except (KeyError, Exception): # match() raises Exception on no match wildperm = None if wildperm is not None: permissions = wildperm # we now have some permissions, either from matching something # or via self._default if action == u'publish': return { u'allow': permissions.publish, u'disclose': permissions.disclose_publisher, u'cache': permissions.cache } elif action == u'subscribe': return { u'allow': permissions.subscribe, u'cache': permissions.cache } elif action == u'call': return { u'allow': permissions.call, u'disclose': permissions.disclose_caller, u'cache': permissions.cache } elif action == u'register': return { u'allow': permissions.register, u'cache': permissions.cache } else: # should not arrive here raise Exception('logic error')
class RouterRoleStaticAuth(RouterRole): """ A role on a router realm that is authorized using a static configuration. """ def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert (permissions is None or type(permissions) == list) if permissions: for p in permissions: assert (type(p) == dict) assert (default_permissions is None or type(default_permissions) == dict) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() self._wild_permissions = StringTrie() # for "wildcard" URIs, there will be a ".." in them somewhere, # and so we want to match on the biggest prefix # (i.e. everything to the left of the first "..") for obj in permissions or []: perms = RouterPermissions.from_dict(obj) if '..' in perms.uri: trunc = perms.uri[:perms.uri.index('..')] self._wild_permissions[trunc] = perms else: self._permissions[perms.uri] = perms def authorize(self, session, uri, action, options): """ Authorize a session connected under this role to perform the given action on the given URI. :param session: The WAMP session that requests the action. :type session: Instance of :class:`autobahn.wamp.protocol.ApplicationSession` :param uri: The URI on which to perform the action. :type uri: str :param action: The action to be performed. :type action: str :return: bool -- Flag indicating whether session is authorized or not. """ self.log.debug( "CrossbarRouterRoleStaticAuth.authorize {myuri} {uri} {action}", myuri=self.uri, uri=uri, action=action) try: # longest prefix match of the URI to be authorized against our Trie # of configured URIs for permissions permissions = self._permissions.longest_prefix_value(uri) # if there is a _prefix_ matching URI, check that this is actually the # match policy on the permission (otherwise, apply default permissions)! if permissions.match != u'prefix' and uri != permissions.uri: permissions = self._default except KeyError: # workaround because of https://bitbucket.org/gsakkis/pytrie/issues/4/string-keys-of-zero-length-are-not permissions = self._permissions.get(u'', self._default) # if we found a non-"exact" match, there might be a better one in the wildcards if permissions.match != u'exact': try: wildperm = self._wild_permissions.longest_prefix_value(uri) Pattern(wildperm.uri, Pattern.URI_TARGET_ENDPOINT).match(uri) except (KeyError, Exception): # match() raises Exception on no match wildperm = None if wildperm is not None: permissions = wildperm # we now have some permissions, either from matching something # or via self._default if action == u'publish': return { u'allow': permissions.publish, u'disclose': permissions.disclose_publisher, u'cache': permissions.cache } elif action == u'subscribe': return { u'allow': permissions.subscribe, u'cache': permissions.cache } elif action == u'call': return { u'allow': permissions.call, u'disclose': permissions.disclose_caller, u'cache': permissions.cache } elif action == u'register': return { u'allow': permissions.register, u'cache': permissions.cache } else: # should not arrive here raise Exception('logic error')
class KeyRing(object): """ A keyring holds (cryptobox) public-private key pairs for use with WAMP-cryptobox payload encryption. The keyring can be set on a WAMP session and then transparently will get used for encrypting and decrypting WAMP message payloads. """ def __init__(self, default_key=None): """ Create a new key ring to hold public and private keys mapped from an URI space. """ assert(default_key is None or isinstance(default_key, Key) or type(default_key == six.text_type)) self._uri_to_key = StringTrie() if type(default_key) == six.text_type: default_key = Key(originator_priv=default_key, responder_priv=default_key) self._default_key = default_key def generate_key(self): """ Generate a new private key and return a pair with the base64 encodings of (priv_key, pub_key). """ key = PrivateKey.generate() priv_key = key.encode(encoder=Base64Encoder) pub_key = key.public_key.encode(encoder=Base64Encoder) return (u'{}'.format(priv_key), u''.format(pub_key)) def set_key(self, uri, key): """ Add a key set for a given URI. """ assert(type(uri) == six.text_type) assert(key is None or isinstance(key, Key) or type(key) == six.text_type) if type(key) == six.text_type: key = Key(originator_priv=key, responder_priv=key) if uri == u'': self._default_key = key else: if key is None: if uri in self._uri_to_key: del self._uri_to_key[uri] else: self._uri_to_key[uri] = key def _get_box(self, is_originator, uri, match_exact=False): try: if match_exact: key = self._uri_to_key[uri] else: key = self._uri_to_key.longest_prefix_value(uri) except KeyError: if self._default_key: key = self._default_key else: return None if is_originator: return key.originator_box else: return key.responder_box def encrypt(self, is_originator, uri, args=None, kwargs=None): """ Encrypt the given WAMP URI, args and kwargs into an EncryptedPayload instance, or None if the URI should not be encrypted. """ assert(type(uri) == six.text_type) assert(type(is_originator) == bool) assert(args is None or type(args) in (list, tuple)) assert(kwargs is None or type(kwargs) == dict) box = self._get_box(is_originator, uri) if not box: return payload = { u'uri': uri, u'args': args, u'kwargs': kwargs } nonce = random(Box.NONCE_SIZE) payload_ser = json.dumps(payload) payload_encr = box.encrypt(payload_ser, nonce, encoder=Base64Encoder) payload_bytes = payload_encr.encode().decode('ascii') payload_key = None return EncryptedPayload(u'cryptobox', payload_key, u'json', payload_bytes) def decrypt(self, is_originator, uri, encrypted_payload): """ Decrypt the given WAMP URI and EncryptedPayload into a tuple (uri, args, kwargs). """ assert(type(uri) == six.text_type) assert(isinstance(encrypted_payload, EncryptedPayload)) box = self._get_box(is_originator, uri) if not box: raise Exception("received encrypted payload, but can't find key!") payload_ser = box.decrypt(encrypted_payload.payload, encoder=Base64Encoder) if encrypted_payload.serializer != u'json': raise Exception("received encrypted payload, but don't know how to process serializer '{}'".format(encrypted_payload.serializer)) payload = json.loads(payload_ser) uri = payload[u'uri'] args = payload.get(u'args', None) kwargs = payload.get(u'kwargs', None) return uri, args, kwargs
class RouterRoleStaticAuth(RouterRole): """ A role on a router realm that is authorized using a static configuration. """ def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert(permissions is None or type(permissions) == list) if permissions: for p in permissions: assert(type(p) == dict) assert(default_permissions is None or type(default_permissions) == dict) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() for obj in permissions or []: perms = RouterPermissions.from_dict(obj) self._permissions[perms.uri] = perms def authorize(self, session, uri, action): """ Authorize a session connected under this role to perform the given action on the given URI. :param session: The WAMP session that requests the action. :type session: Instance of :class:`autobahn.wamp.protocol.ApplicationSession` :param uri: The URI on which to perform the action. :type uri: str :param action: The action to be performed. :type action: str :return: bool -- Flag indicating whether session is authorized or not. """ self.log.debug( "CrossbarRouterRoleStaticAuth.authorize {myuri} {uri} {action}", myuri=self.uri, uri=uri, action=action) try: # longest prefix match of the URI to be authorized against our Trie # of configured URIs for permissions permissions = self._permissions.longest_prefix_value(uri) # if there is a _prefix_ matching URI, check that this is actually the # match policy on the permission (otherwise, apply default permissions)! if permissions.match != u'prefix' and uri != permissions.uri: permissions = self._default except KeyError: # workaround because of https://bitbucket.org/gsakkis/pytrie/issues/4/string-keys-of-zero-length-are-not if u'' in self._permissions: permissions = self._permissions[u''] else: permissions = self._default if action == u'publish': return { u'allow': permissions.publish, u'disclose': permissions.disclose_publisher, u'cache': permissions.cache } elif action == u'subscribe': return { u'allow': permissions.subscribe, u'cache': permissions.cache } elif action == u'call': return { u'allow': permissions.call, u'disclose': permissions.disclose_caller, u'cache': permissions.cache } elif action == u'register': return { u'allow': permissions.register, u'cache': permissions.cache } else: # should not arrive here raise Exception('logic error')
"""Script that loads a trie of French words, to be used in other scripts""" import os import logging from pytrie import StringTrie path = "French-Dictionary-master/dictionary" files = os.listdir(path) dico = StringTrie() for file in files: logging.info(f"Loading {file}") with open(path + "/" + file) as f: mots = [line.split(";")[0].strip() for line in f.readlines()] for mot in mots: dico[mot] = mot logging.info("Dico loaded")
def update_trie(self, word_list): self.trie = StringTrie() for word in word_list: word = word.lower() self.trie[word] = word
from pytrie import StringTrie as trie from bitstring import BitArray words = open('words.txt') t = trie.fromkeys(words.read().splitlines()) def evaluate(target): good = BitArray(len(target)) # all characters that are part of a meaningful word bestLength = 0 # length of the longest word bestPattern = BitArray(len(target)) # characters that form the longest word for i in range(len(target)): match = t.longest_prefix(key=target[i:], default="") if len(match)>0: temp = BitArray(len(target)) temp.set(1, range(i, i+len(match))) # set mathcing character positions to 1 good.set(1, range(i, i+len(match))) # set mathcing character positions to 1 if len(match)>bestLength: bestLength = len(match) bestPattern = temp return bestPattern, good
class UriObservationMap(object): """ Represents the current set of observations maintained by a broker/dealer. To test: trial crossbar.router.test.test_subscription """ __slots__ = ( "_ordered", "_observations_exact", "_observations_prefix", "_observations_wildcard", "_observation_id_to_observation", ) def __init__(self, ordered=False): # flag indicating whether observers should be maintained in a SortedSet # or a regular set (unordered) self._ordered = ordered # map: URI => ExactUriObservation self._observations_exact = {} # map: URI => PrefixUriObservation self._observations_prefix = StringTrie() # map: URI => WildcardUriObservation if True: # use a Trie-based implementation (supposed to be faster, but # otherwise compatible to the naive implementation below) self._observations_wildcard = WildcardTrieMatcher() else: self._observations_wildcard = WildcardMatcher() # map: observation ID => UriObservation self._observation_id_to_observation = {} def __repr__(self): return "{}(_ordered={}, _observations_exact={}, _observations_wildcard={})".format( self.__class__.__name__, self._ordered, self._observations_exact, self._observations_prefix, self._observations_wildcard, self._observation_id_to_observation, ) def add_observer(self, observer, uri, match=u"exact", extra=None): """ Adds a observer to the observation set and returns the respective observation. :param observer: The observer to add (this can be any opaque object). :type observer: obj :param uri: The URI (or URI pattern) to add the observer to add to. :type uri: unicode :param match: The matching policy for observing, one of ``u"exact"``, ``u"prefix"`` or ``u"wildcard"``. :type match: unicode :returns: A tuple ``(observation, was_already_observed, was_first_observer)``. Here, ``observation`` is an instance of one of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation``. :rtype: tuple """ if not isinstance(uri, six.text_type): raise Exception("'uri' should be unicode, not {}".format(type(uri).__name__)) if match == u"exact": # if the exact-matching URI isn't in our map, create a new observation # if uri not in self._observations_exact: self._observations_exact[uri] = ExactUriObservation(uri, ordered=self._ordered, extra=extra) is_first_observer = True else: is_first_observer = False # get the observation # observation = self._observations_exact[uri] elif match == u"prefix": # if the prefix-matching URI isn't in our map, create a new observation # if uri not in self._observations_prefix: self._observations_prefix[uri] = PrefixUriObservation(uri, ordered=self._ordered, extra=extra) is_first_observer = True else: is_first_observer = False # get the observation # observation = self._observations_prefix[uri] elif match == u"wildcard": # if the wildcard-matching URI isn't in our map, create a new observation # if uri not in self._observations_wildcard: self._observations_wildcard[uri] = WildcardUriObservation(uri, ordered=self._ordered, extra=extra) is_first_observer = True else: is_first_observer = False # get the observation # observation = self._observations_wildcard[uri] else: raise Exception("invalid match strategy '{}'".format(match)) # note observation in observation ID map # if is_first_observer: self._observation_id_to_observation[observation.id] = observation # add observer if not already in observation # if observer not in observation.observers: observation.observers.add(observer) was_already_observed = False else: was_already_observed = True return observation, was_already_observed, is_first_observer def get_observation(self, uri, match=u"exact"): """ Get a observation (if any) for given URI and match policy. :param uri: The URI (or URI pattern) to get the observation for. :type uri: unicode :param match: The matching policy for observation to retrieve, one of ``u"exact"``, ``u"prefix"`` or ``u"wildcard"``. :type match: unicode :returns: The observation (instance of one of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation``) or ``None``. :rtype: obj or None """ if not isinstance(uri, six.text_type): raise Exception("'uri' should be unicode, not {}".format(type(uri).__name__)) if match == u"exact": return self._observations_exact.get(uri, None) elif match == u"prefix": return self._observations_prefix.get(uri, None) elif match == u"wildcard": return self._observations_wildcard.get(uri, None) else: raise Exception("invalid match strategy '{}'".format(match)) def match_observations(self, uri): """ Returns the observations matching the given URI. This is the core method called by a broker to actually dispatch events. :param uri: The URI to match. :type uri: unicode :returns: A list of observations matching the URI. This is a list of instance of one of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation``. :rtype: list """ observations = [] if not isinstance(uri, six.text_type): raise Exception("'uri' should be unicode, not {}".format(type(uri).__name__)) if uri in self._observations_exact: observations.append(self._observations_exact[uri]) for observation in self._observations_prefix.iter_prefix_values(uri): observations.append(observation) for observation in self._observations_wildcard.iter_matches(uri): observations.append(observation) return observations def best_matching_observation(self, uri): """ Returns the observation that best matches the given URI. This is the core method called by a dealer to actually forward calls. :param uri: The URI to match. :type uri: unicode :returns: The observation best matching the URI. This is an instance of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation`` or ``None``. :rtype: obj or None """ if not isinstance(uri, six.text_type): raise Exception("'uri' should be unicode, not {}".format(type(uri).__name__)) # a exact matching observation is always "best", if any # if uri in self._observations_exact: return self._observations_exact[uri] # "second best" is the longest prefix-matching observation, if any # FIXME: do we want this to take precedence over _any_ wildcard (see below)? # try: return self._observations_prefix.longest_prefix_value(uri) except KeyError: pass # FIXME: for wildcard observations, when there are multiple matching, we'd # like to deterministically select the "most selective one" # We first need a definition of "most selective", and then we need to implement # this here. # for observation in self._observations_wildcard.iter_matches(uri): return observation def get_observation_by_id(self, id): """ Get a observation by ID. :param id: The ID of the observation to retrieve. :type id: int :returns: The observation for the given ID or ``None``. :rtype: obj or None """ return self._observation_id_to_observation.get(id, None) def drop_observer(self, observer, observation): """ Drop a observer from a observation. :param observer: The observer to drop from the given observation. :type observer: obj :param observation: The observation from which to drop the observer. An instance of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation`` previously created and handed out by this observation map. :type observation: obj :returns: A tuple ``(was_observed, was_last_observer)``. :rtype: tuple """ if observer in observation.observers: was_observed = True # remove observer from observation # observation.observers.discard(observer) # no more observers on this observation! # if not observation.observers: if observation.match == u"exact": del self._observations_exact[observation.uri] elif observation.match == u"prefix": del self._observations_prefix[observation.uri] elif observation.match == u"wildcard": del self._observations_wildcard[observation.uri] else: # should not arrive here raise Exception("logic error") was_last_observer = True del self._observation_id_to_observation[observation.id] else: was_last_observer = False else: # observer wasn't on this observation was_observed = False return was_observed, was_last_observer
def incrementInTrie(key,trie): if trie.has_key(key): curCount = corpus.__getitem__(key) trie.__setitem__(key,curCount+1) else: trie.__setitem__(key,1)
class RouterRoleStaticAuth(RouterRole): """ A role on a router realm that is authorized using a static configuration. """ def __init__(self, router, uri, permissions=None, default_permissions=None): """ :param router: The router this role is defined on. :type router: obj :param uri: The URI of the role. :type uri: unicode :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list of dict :param default_permissions: The default permissions to apply when no other configured permission matches. The default permissions when not explicitly set is to deny all actions on all URIs! :type default_permissions: dict """ RouterRole.__init__(self, router, uri) assert (permissions is None or type(permissions) == list) if permissions: for p in permissions: assert (type(p) == dict) assert (default_permissions is None or type(default_permissions) == dict) # default permissions (used when nothing else is matching) # note: default permissions have their matching URI and match policy set to None! if default_permissions: self._default = RouterPermissions.from_dict(default_permissions) else: self._default = RouterPermissions(None, None, call=False, register=False, publish=False, subscribe=False, disclose_caller=False, disclose_publisher=False, cache=True) # Trie of explicitly configured permissions self._permissions = StringTrie() for obj in permissions or []: perms = RouterPermissions.from_dict(obj) self._permissions[perms.uri] = perms def authorize(self, session, uri, action): """ Authorize a session connected under this role to perform the given action on the given URI. :param session: The WAMP session that requests the action. :type session: Instance of :class:`autobahn.wamp.protocol.ApplicationSession` :param uri: The URI on which to perform the action. :type uri: str :param action: The action to be performed. :type action: str :return: bool -- Flag indicating whether session is authorized or not. """ self.log.debug( "CrossbarRouterRoleStaticAuth.authorize {myuri} {uri} {action}", myuri=self.uri, uri=uri, action=action) try: # longest prefix match of the URI to be authorized against our Trie # of configured URIs for permissions permissions = self._permissions.longest_prefix_value(uri) # if there is a _prefix_ matching URI, check that this is actually the # match policy on the permission (otherwise, apply default permissions)! if permissions.match != u'prefix' and uri != permissions.uri: permissions = self._default except KeyError: # workaround because of https://bitbucket.org/gsakkis/pytrie/issues/4/string-keys-of-zero-length-are-not if u'' in self._permissions: permissions = self._permissions[u''] else: permissions = self._default if action == u'publish': return { u'allow': permissions.publish, u'disclose': permissions.disclose_publisher, u'cache': permissions.cache } elif action == u'subscribe': return { u'allow': permissions.subscribe, u'cache': permissions.cache } elif action == u'call': return { u'allow': permissions.call, u'disclose': permissions.disclose_caller, u'cache': permissions.cache } elif action == u'register': return { u'allow': permissions.register, u'cache': permissions.cache } else: # should not arrive here raise Exception('logic error')
class RouterRoleStaticAuth(RouterRole): """ A role on a router realm that is authorized using a static configuration. """ def __init__(self, router, uri, permissions=None, default_permissions=None, debug=False): """ Ctor. :param uri: The URI of the role. :type uri: str :param permissions: A permissions configuration, e.g. a list of permission dicts like `{'uri': 'com.example.*', 'call': True}` :type permissions: list :param debug: Enable debug logging. :type debug: bool """ RouterRole.__init__(self, router, uri, debug) self.permissions = permissions or [] self._urimap = StringTrie() self._default = default_permissions or RouterPermissions('', True, False, False, False, False) for p in self.permissions: uri = p['uri'] if len(uri) > 0 and uri[-1] == '*': match_by_prefix = True uri = uri[:-1] else: match_by_prefix = False perms = RouterPermissions(uri, match_by_prefix, call=p.get('call', False), register=p.get('register', False), publish=p.get('publish', False), subscribe=p.get('subscribe', False)) if len(uri) > 0: self._urimap[uri] = perms else: self._default = perms def authorize(self, session, uri, action): """ Authorize a session connected under this role to perform the given action on the given URI. :param session: The WAMP session that requests the action. :type session: Instance of :class:`autobahn.wamp.protocol.ApplicationSession` :param uri: The URI on which to perform the action. :type uri: str :param action: The action to be performed. :type action: str :return: bool -- Flag indicating whether session is authorized or not. """ if self.debug: log.msg("CrossbarRouterRoleStaticAuth.authorize", self.uri, uri, action) # if action == 'publish': # f = 1/0 try: permissions = self._urimap.longest_prefix_value(uri) if not permissions.match_by_prefix and uri != permissions.uri: return False return getattr(permissions, action) except KeyError: return getattr(self._default, action)
class WampMQTTServerFactory(Factory): log = make_logger() protocol = WampMQTTServerProtocol serializers = { 'json': JsonObjectSerializer(), 'msgpack': MsgPackObjectSerializer(), 'cbor': CBORObjectSerializer(), 'ubjson': UBJSONObjectSerializer(), } def __init__(self, router_session_factory, config, reactor): self._router_session_factory = router_session_factory self._router_factory = router_session_factory._routerFactory self._options = config.get('options', {}) self._realm = self._options.get('realm', None) self._reactor = reactor self._payload_mapping = StringTrie() for topic, pmap in self._options.get('payload_mapping', {}).items(): self._set_payload_format(topic, pmap) def buildProtocol(self, addr): protocol = self.protocol(self._reactor) protocol.factory = self return protocol def _get_payload_format(self, topic): """ Map a WAMP topic URI to MQTT payload format. :param topic: WAMP URI. :type topic: str :returns: Payload format metadata. :rtype: dict """ try: pmap = self._payload_mapping.longest_prefix_value(topic) except KeyError: return None else: return pmap def _set_payload_format(self, topic, pmap=None): if pmap is None: if topic in self._payload_mapping: del self._payload_mapping[topic] else: self._payload_mapping[topic] = pmap @inlineCallbacks def transform_wamp(self, topic, msg): # check for cached transformed payload cache_key = '_{}_{}'.format(self.__class__.__name__, id(self)) cached = msg._serialized.get(cache_key, None) if cached: payload_format, mapped_topic, payload = cached self.log.debug( 'using cached payload for {cache_key} in message {msg_id}!', msg_id=id(msg), cache_key=cache_key) else: # convert WAMP URI to MQTT topic mapped_topic = _wamp_topic_to_mqtt(topic) # for WAMP->MQTT, the payload mapping is determined from the # WAMP URI (not the transformed MQTT topic) payload_format = self._get_payload_format(topic) payload_format_type = payload_format['type'] if payload_format_type == 'passthrough': payload = msg.payload elif payload_format_type == 'native': serializer = payload_format.get('serializer', None) payload = self._transform_wamp_native(serializer, msg) elif payload_format_type == 'dynamic': encoder = payload_format.get('encoder', None) codec_realm = payload_format.get('realm', self._realm) payload = yield self._transform_wamp_dynamic( encoder, codec_realm, mapped_topic, topic, msg) else: raise Exception( 'payload format {} not implemented'.format(payload_format)) msg._serialized[cache_key] = (payload_format, mapped_topic, payload) self.log.debug( 'transform_wamp({topic}, {msg}) -> payload_format={payload_format}, mapped_topic={mapped_topic}, payload={payload}', topic=topic, msg=msg, payload_format=payload_format, mapped_topic=mapped_topic, payload=payload) returnValue((payload_format, mapped_topic, payload)) @inlineCallbacks def _transform_wamp_dynamic(self, encoder, codec_realm, mapped_topic, topic, msg): codec_session = self._router_factory.get(codec_realm)._realm.session payload = yield codec_session.call(encoder, mapped_topic, topic, msg.args, msg.kwargs) returnValue(payload) def _transform_wamp_native(self, serializer, msg): obj = {} for opt in [ 'args', 'kwargs', 'exclude', 'exclude_authid', 'exclude_authrole', 'eligible', 'eligible_authid', 'eligible_authrole' ]: attr = getattr(msg, opt, None) if attr is not None: obj[opt] = attr if serializer in self.serializers: payload = self.serializers[serializer].serialize(obj) else: raise Exception( 'MQTT native mode payload transform: invalid serializer {}'. format(serializer)) return payload @inlineCallbacks def transform_mqtt(self, topic, payload): # transform MQTT topic to WAMP URI mapped_topic = _mqtt_topicname_to_wamp(topic) # for MQTT->WAMP, the payload mapping is determined from the # transformed WAMP URI (not the original MQTT topic) payload_format = self._get_payload_format(mapped_topic) payload_format_type = payload_format['type'] if payload_format_type == 'passthrough': options = {'payload': payload, 'enc_algo': 'mqtt'} elif payload_format_type == 'native': serializer = payload_format.get('serializer', None) options = self._transform_mqtt_native(serializer, payload) elif payload_format_type == 'dynamic': decoder = payload_format.get('decoder', None) codec_realm = payload_format.get('realm', self._realm) options = yield self._transform_mqtt_dynamic( decoder, codec_realm, mapped_topic, topic, payload) else: raise Exception( 'payload format {} not implemented'.format(payload_format)) self.log.debug( 'transform_mqtt({topic}, {payload}) -> payload_format={payload_format}, mapped_topic={mapped_topic}, options={options}', topic=topic, payload=payload, payload_format=payload_format, mapped_topic=mapped_topic, options=options) returnValue((payload_format, mapped_topic, options)) @inlineCallbacks def _transform_mqtt_dynamic(self, decoder, codec_realm, mapped_topic, topic, payload): codec_session = self._router_factory.get(codec_realm)._realm.session options = yield codec_session.call(decoder, mapped_topic, topic, payload) returnValue(options) def _transform_mqtt_native(self, serializer, payload): """ Transform MQTT binary payload from a MQTT Publish to keyword dict suitable for the constructor of a WAMP Publish message, that is :class:`autobahn.wamp.message.Publish`. """ options = {} if serializer in self.serializers: if serializer == 'json': if not _validator.validate(payload)[0]: # invalid UTF-8: drop the event raise Exception( 'invalid UTF8 in JSON encoded MQTT payload') obj = self.serializers[serializer].unserialize(payload)[0] else: raise Exception( '"{}" serializer for encoded MQTT payload not implemented'. format(serializer)) if not isinstance(obj, dict): raise Exception( 'invalid type {} for "{}" encoded MQTT payload'.format( type(obj), serializer)) for opt in [ 'args', 'kwargs', 'exclude', 'exclude_authid', 'exclude_authrole', 'eligible', 'eligible_authid', 'eligible_authrole' ]: if opt in obj: options[opt] = obj[opt] return options
# Author: John Maheswaran import csv # used to read csv files from pytrie import StringTrie # used to match prefixes efficiently. # A trie allows you to match prefixes efficiently instead of the naive approach of looking # through all the strings and checking one by one, if we used a list instead of a trie import locale # used for formatting the currency in prices products = dict( ) # a dict is a hashmap representing the products, allows constant time lookup of product price # informaton based on the product id rungup = set( ) # this stores the products that we have rung up and allows constant insertion time trie = StringTrie( ) # a trie that allows us to look up all the strings matching a # prefix in faster than O(n) time where n is the number of strings # set the locate for currency formatting locale.setlocale(locale.LC_ALL, '') # first we will get the csv file name from the user print( "Please enter the csv product data filename or press ENTER to use the default (productdata.csv)" ) filename = input() if len(filename) == 0: filename = 'productdata.csv' # use a try block in case opening the csv file fails try:
class UriObservationMap(object): """ Represents the current set of observations maintained by a broker/dealer. To test: trial crossbar.router.test.test_subscription """ def __init__(self, ordered=False): # flag indicating whether observers should be maintained in a SortedSet # or a regular set (unordered) self._ordered = ordered # map: URI => ExactUriObservation self._observations_exact = {} # map: URI => PrefixUriObservation self._observations_prefix = StringTrie() # map: URI => WildcardUriObservation self._observations_wildcard = {} # map: pattern length => (map: pattern => pattern count) self._observations_wildcard_patterns = {} # map: observation ID => UriObservation self._observation_id_to_observation = {} def add_observer(self, observer, uri, match=u"exact", extra=None): """ Adds a observer to the observation set and returns the respective observation. :param observer: The observer to add (this can be any opaque object). :type observer: obj :param uri: The URI (or URI pattern) to add the observer to add to. :type uri: unicode :param match: The matching policy for observing, one of ``u"exact"``, ``u"prefix"`` or ``u"wildcard"``. :type match: unicode :returns: A tuple ``(observation, was_already_observed, was_first_observer)``. Here, ``observation`` is an instance of one of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation``. :rtype: tuple """ if match == u"exact": # if the exact-matching URI isn't in our map, create a new observation # if uri not in self._observations_exact: self._observations_exact[uri] = ExactUriObservation(uri, ordered=self._ordered, extra=extra) is_first_observer = True else: is_first_observer = False # get the observation # observation = self._observations_exact[uri] elif match == u"prefix": # if the prefix-matching URI isn't in our map, create a new observation # if uri not in self._observations_prefix: self._observations_prefix[uri] = PrefixUriObservation(uri, ordered=self._ordered, extra=extra) is_first_observer = True else: is_first_observer = False # get the observation # observation = self._observations_prefix[uri] elif match == u"wildcard": # if the wildcard-matching URI isn't in our map, create a new observation # if uri not in self._observations_wildcard: observation = WildcardUriObservation(uri, ordered=self._ordered, extra=extra) self._observations_wildcard[uri] = observation is_first_observer = True # setup map: pattern length -> patterns if observation.pattern_len not in self._observations_wildcard_patterns: self._observations_wildcard_patterns[observation.pattern_len] = {} # setup map: (pattern length, pattern) -> pattern count if observation.pattern not in self._observations_wildcard_patterns[observation.pattern_len]: self._observations_wildcard_patterns[observation.pattern_len][observation.pattern] = 1 else: self._observations_wildcard_patterns[observation.pattern_len][observation.pattern] += 1 else: is_first_observer = False # get the observation # observation = self._observations_wildcard[uri] else: raise Exception("invalid match strategy '{}'".format(match)) # note observation in observation ID map # if is_first_observer: self._observation_id_to_observation[observation.id] = observation # add observer if not already in observation # if observer not in observation.observers: observation.observers.add(observer) was_already_observed = False else: was_already_observed = True return observation, was_already_observed, is_first_observer def get_observation(self, uri, match=u"exact"): """ Get a observation (if any) for given URI and match policy. :param uri: The URI (or URI pattern) to get the observation for. :type uri: unicode :param match: The matching policy for observation to retrieve, one of ``u"exact"``, ``u"prefix"`` or ``u"wildcard"``. :type match: unicode :returns: The observation (instance of one of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation``) or ``None``. :rtype: obj or None """ if match == u"exact": return self._observations_exact.get(uri, None) elif match == u"prefix": return self._observations_prefix.get(uri, None) elif match == u"wildcard": return self._observations_wildcard.get(uri, None) else: raise Exception("invalid match strategy '{}'".format(match)) def match_observations(self, uri): """ Returns the observations matching the given URI. This is the core method called by a broker to actually dispatch events. :param uri: The URI to match. :type uri: unicode :returns: A list of observations matching the URI. This is a list of instance of one of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation``. :rtype: list """ observations = [] if uri in self._observations_exact: observations.append(self._observations_exact[uri]) for observation in self._observations_prefix.iter_prefix_values(uri): observations.append(observation) uri_parts = tuple(uri.split('.')) uri_parts_len = len(uri_parts) if uri_parts_len in self._observations_wildcard_patterns: for pattern in self._observations_wildcard_patterns[uri_parts_len]: patterned_uri = '.'.join(['' if pattern[i] else uri_parts[i] for i in range(uri_parts_len)]) if patterned_uri in self._observations_wildcard: observations.append(self._observations_wildcard[patterned_uri]) return observations def best_matching_observation(self, uri): """ Returns the observation that best matches the given URI. This is the core method called by a dealer to actually forward calls. :param uri: The URI to match. :type uri: unicode :returns: The observation best matching the URI. This is an instance of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation`` or ``None``. :rtype: obj or None """ # a exact matching observation is always "best", if any # if uri in self._observations_exact: return self._observations_exact[uri] # "second best" is the longest prefix-matching observation, if any # FIXME: do we want this to take precedence over _any_ wildcard (see below)? # try: return self._observations_prefix.longest_prefix_value(uri) except KeyError: pass # FIXME: for wildcard observations, when there are multiple matching, we'd # like to deterministically select the "most selective one" # We first need a definition of "most selective", and then we need to implement # this here. # uri_parts = tuple(uri.split('.')) uri_parts_len = len(uri_parts) if uri_parts_len in self._observations_wildcard_patterns: for pattern in self._observations_wildcard_patterns[uri_parts_len]: patterned_uri = '.'.join(['' if pattern[i] else uri_parts[i] for i in range(uri_parts_len)]) if patterned_uri in self._observations_wildcard: return self._observations_wildcard[patterned_uri] def get_observation_by_id(self, id): """ Get a observation by ID. :param id: The ID of the observation to retrieve. :type id: int :returns: The observation for the given ID or ``None``. :rtype: obj or None """ return self._observation_id_to_observation.get(id, None) def drop_observer(self, observer, observation): """ Drop a observer from a observation. :param observer: The observer to drop from the given observation. :type observer: obj :param observation: The observation from which to drop the observer. An instance of ``ExactUriObservation``, ``PrefixUriObservation`` or ``WildcardUriObservation`` previously created and handed out by this observation map. :type observation: obj :returns: A tuple ``(was_observed, was_last_observer)``. :rtype: tuple """ if observer in observation.observers: was_observed = True # remove observer from observation # observation.observers.discard(observer) # no more observers on this observation! # if not observation.observers: if observation.match == u"exact": del self._observations_exact[observation.uri] elif observation.match == u"prefix": del self._observations_prefix[observation.uri] elif observation.match == u"wildcard": # cleanup if this was the last observation with given pattern self._observations_wildcard_patterns[observation.pattern_len][observation.pattern] -= 1 if not self._observations_wildcard_patterns[observation.pattern_len][observation.pattern]: del self._observations_wildcard_patterns[observation.pattern_len][observation.pattern] # cleanup if this was the last observation with given pattern length if not self._observations_wildcard_patterns[observation.pattern_len]: del self._observations_wildcard_patterns[observation.pattern_len] # remove actual observation del self._observations_wildcard[observation.uri] else: # should not arrive here raise Exception("logic error") was_last_observer = True del self._observation_id_to_observation[observation.id] else: was_last_observer = False else: # observer wasn't on this observation was_observed = False return was_observed, was_last_observer
class KeyRing(object): """ A keyring holds (cryptobox) public-private key pairs for use with WAMP-cryptobox payload encryption. The keyring can be set on a WAMP session and then transparently will get used for encrypting and decrypting WAMP message payloads. """ def __init__(self, default_key=None): """ Create a new key ring to hold public and private keys mapped from an URI space. """ assert (default_key is None or isinstance(default_key, Key) or type(default_key == six.text_type)) self._uri_to_key = StringTrie() if type(default_key) == six.text_type: default_key = Key(originator_priv=default_key, responder_priv=default_key) self._default_key = default_key def generate_key(self): """ Generate a new private key and return a pair with the base64 encodings of (priv_key, pub_key). """ key = PrivateKey.generate() priv_key = key.encode(encoder=Base64Encoder) pub_key = key.public_key.encode(encoder=Base64Encoder) return (u'{}'.format(priv_key), u''.format(pub_key)) def set_key(self, uri, key): """ Add a key set for a given URI. """ assert (type(uri) == six.text_type) assert (key is None or isinstance(key, Key) or type(key) == six.text_type) if type(key) == six.text_type: key = Key(originator_priv=key, responder_priv=key) if uri == u'': self._default_key = key else: if key is None: if uri in self._uri_to_key: del self._uri_to_key[uri] else: self._uri_to_key[uri] = key def _get_box(self, is_originator, uri, match_exact=False): try: if match_exact: key = self._uri_to_key[uri] else: key = self._uri_to_key.longest_prefix_value(uri) except KeyError: if self._default_key: key = self._default_key else: return None if is_originator: return key.originator_box else: return key.responder_box def encrypt(self, is_originator, uri, args=None, kwargs=None): """ Encrypt the given WAMP URI, args and kwargs into an EncryptedPayload instance, or None if the URI should not be encrypted. """ assert (type(uri) == six.text_type) assert (type(is_originator) == bool) assert (args is None or type(args) in (list, tuple)) assert (kwargs is None or type(kwargs) == dict) box = self._get_box(is_originator, uri) if not box: return payload = {u'uri': uri, u'args': args, u'kwargs': kwargs} nonce = random(Box.NONCE_SIZE) payload_ser = json.dumps(payload) payload_encr = box.encrypt(payload_ser, nonce, encoder=Base64Encoder) payload_bytes = payload_encr.encode().decode('ascii') payload_key = None return EncryptedPayload(u'cryptobox', payload_key, u'json', payload_bytes) def decrypt(self, is_originator, uri, encrypted_payload): """ Decrypt the given WAMP URI and EncryptedPayload into a tuple (uri, args, kwargs). """ assert (type(uri) == six.text_type) assert (isinstance(encrypted_payload, EncryptedPayload)) box = self._get_box(is_originator, uri) if not box: raise Exception( "received encrypted payload, but can't find key!") payload_ser = box.decrypt(encrypted_payload.payload, encoder=Base64Encoder) if encrypted_payload.serializer != u'json': raise Exception( "received encrypted payload, but don't know how to process serializer '{}'" .format(encrypted_payload.serializer)) payload = json.loads(payload_ser) uri = payload[u'uri'] args = payload.get(u'args', None) kwargs = payload.get(u'kwargs', None) return uri, args, kwargs