openc2lib.core.encoder

Encoder base functions and interface

This module provides base encoding functions to translate openc2lib objects into an intermediary representation.

  1""" Encoder base functions and interface
  2
  3	This module provides base encoding functions to translate openc2lib objects into an intermediary
  4	representation.
  5"""
  6
  7import copy
  8import aenum
  9import enum
 10import logging
 11
 12logger = logging.getLogger('openc2lib')
 13""" Logging features
 14
 15	Most of logging from this modules are conceived for debugging only.
 16"""
 17
 18_UNCODED = (bool, str, int, float)
 19
 20class Encoders(aenum.Enum):
 21	""" List of available Encoders
 22	
 23		This list can be used in `Transfer` protocols to select the correct class to decode an incoming OpenC2 Message
 24		based on its metadata. The list is created as enumeration, which associate the name of the encoding
 25		formats to the class that implements it.
 26	"""
 27	pass
 28
 29def register_encoder(cls):
 30	""" Register an `Encoder`
 31
 32		This function is used to register a new `Encoder`. It can be used as a decorator to the class that 
 33		defines the new `Encoder`.
 34		:param cls: The class definition that must be registered. The class internally holds its name.
 35		:return: The same class passed as argument (used to create a decoratetor).
 36	"""
 37	aenum.extend_enum(Encoders, cls.getName(), cls)
 38	return cls
 39
 40@register_encoder
 41class Encoder:
 42	""" Base `Encoder`
 43
 44		The Base `Encoder` provides a common interface that must be implemented by all implementations of
 45		Encoding mechanisms. Each new `Encoder` should be derived from this class.
 46
 47		The Base Encoder translates openc2lib data types and structures
 48		into dictionaries. This function can be used by derived class to have an intermediary representation
 49		which strictly follows the OpenC2 formatting rules. The intermediary representation must then be
 50		translated into the specific syntax used by the derived `Encoder` (e.g., json, xml, yaml).
 51
 52		Currently, this class is only designed to encode into text formats.
 53	"""
 54	encoder_type = 'dictionary'
 55
 56	@classmethod
 57	def getName(cls):
 58		""" Encoder name
 59
 60			This method MUST be implemented to return the name of the encoding format. The name should be
 61			highly representative, possible using official terminology (e.g.: json, xml).
 62
 63			:return: The class name.
 64		"""
 65		return cls.encoder_type
 66
 67	@staticmethod
 68	def encode(obj):
 69		""" Encode an OpenC2 object
 70
 71			This method encodes an openc2lib object (namely, a data structure derived from `BaseType`). 
 72			It MUST be implemented by each derived class. It could be applied to any openc2lib object,
 73			but the most common use is for `Message`, `Command`, or `Response`.
 74
 75			:param obj: An OpenC2 object derived from a `BaseType`. 
 76			:return: A string that contains the encoded object.
 77		"""
 78		return str(Encoder.todict(obj))
 79
 80	@staticmethod
 81	def decode(msgtype, msg):
 82		""" Decode into OpenC2 object
 83
 84			This method decodes a text representation into an openc2lib object. The method throws an `Exception`
 85			in case of unknown elements. 
 86
 87			This method requires to specify the openc2lib class that implements the OpenC2 object described
 88			by the text. This will commonly be either `Message`, `Command`, or `Response`. 
 89
 90			:param msgtype: The class of an openc2lib object.
 91			:param msg: Text-based representation of the OpenC2 object.
 92			:return: An instance of an openc2lib object.
 93		"""
 94		return Encoder.fromdict(msgtype, msg)
 95
 96	@staticmethod
 97	def __objtodict(obj):
 98		if isinstance(obj, list):
 99			return Encoder.__iteratelist(obj)
100
101		if isinstance(obj, dict):
102			return  Encoder.__iteratedic(obj)
103
104		# Default: return a string representation of the object
105		return str(obj)
106
107
108	# This method 
109	def __objfromdict(clstype, dic):
110		if isinstance(dic, dict):
111			return clstype(**dic)
112		if isinstance(dic, list):
113			lis = []
114			for i in dic:
115				lis.append[Encoder.fromdict(clstype, i)]
116			return lis
117		if isinstance(dic, _UNCODED):
118			return clstype(dic)
119		raise ValueError("Unmanaged obj value: ", dic)
120
121	# Convert complex types to string by interatively invoking the todict function
122	@staticmethod
123	def __iteratedic(dic):
124		newdic = {}
125		for k,v in dic.items():
126			if v is not None:
127				newdic[Encoder.todict(k)] = Encoder.todict(v)
128#			if not isinstance(v, __UNCODED):
129#				dic[k] = Encoder.todict(v)
130		return newdic
131
132	@staticmethod
133	def __iteratelist(lis):
134		objlist = []
135		for i in lis:
136#			if isinstance(i, __UNCODED):
137#				objlist.append(i)
138#			else:
139#				print("append: ", i)
140#				objlist.append( Encoder.todict(i) )
141			objlist.append( Encoder.todict(i) )
142		return objlist	
143
144#  NOT USED
145#  They Python way: "try ... except ... "
146#	@staticmethod
147#	def hasmethod(obj, method):
148#		return callable(hasattr(obj, method, None))
149
150
151	@staticmethod
152	def todict(obj):
153		""" Convert object to dictionary
154
155			This is an internal method to convert an openc2lib object into a dictionary. The dictionary is
156		  	structured according to OpenC2 syntax.
157
158			This method should only be invoked by derived classes to get the intermediary representation
159			of openc2lib objects. It will likely be used in the implementation of the `decode` method.	
160			:param obj: The openc2lib object to convert into a dictionary.
161			:return: A dictionary compliant with the OpenC2 syntax rules.
162		"""
163		try:
164			return obj.todict(Encoder)
165		except AttributeError:
166			return Encoder.__objtodict(obj)
167			
168
169	@staticmethod
170	def fromdict(clstype, dic):
171		""" Create an object from dictionary
172
173			This is an internal method to create an openc2lib object from a dictionary. The dictionary
174			must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this
175			intermediate representation and use this method in the `encode` method. It is necessary to 
176			provide the class definition of the openc2lib object to be instantiated.
177
178			:param clstype: The class definition that must be used to instantiate the object.
179			:param dic: The dictionary with the OpenC2 description.
180			:return: An instance of `clstype` initialized with the data in the `dic`.
181		"""
182		logger.debug("Decondig: %s with %s", dic, clstype)
183		try:
184			logging.debug("Trying: %s", clstype.fromdict)
185			return clstype.fromdict(dic, Encoder)
186		except AttributeError:
187			logger.debug("Falling back: Encoder.objfromdict for %s", clstype)
188			return Encoder.__objfromdict(clstype, dic)
189		
logger = <Logger openc2lib (WARNING)>

Logging features

Most of logging from this modules are conceived for debugging only.

class Encoders(aenum._enum.Enum):
21class Encoders(aenum.Enum):
22	""" List of available Encoders
23	
24		This list can be used in `Transfer` protocols to select the correct class to decode an incoming OpenC2 Message
25		based on its metadata. The list is created as enumeration, which associate the name of the encoding
26		formats to the class that implements it.
27	"""
28	pass

List of available Encoders

This list can be used in Transfer protocols to select the correct class to decode an incoming OpenC2 Message based on its metadata. The list is created as enumeration, which associate the name of the encoding formats to the class that implements it.

dictionary
json
Inherited Members
aenum._enum.Enum
name
value
values
def register_encoder(cls):
30def register_encoder(cls):
31	""" Register an `Encoder`
32
33		This function is used to register a new `Encoder`. It can be used as a decorator to the class that 
34		defines the new `Encoder`.
35		:param cls: The class definition that must be registered. The class internally holds its name.
36		:return: The same class passed as argument (used to create a decoratetor).
37	"""
38	aenum.extend_enum(Encoders, cls.getName(), cls)
39	return cls

Register an Encoder

This function is used to register a new Encoder. It can be used as a decorator to the class that defines the new Encoder.

Parameters
  • cls: The class definition that must be registered. The class internally holds its name.
Returns

The same class passed as argument (used to create a decoratetor).

@register_encoder
class Encoder:
 41@register_encoder
 42class Encoder:
 43	""" Base `Encoder`
 44
 45		The Base `Encoder` provides a common interface that must be implemented by all implementations of
 46		Encoding mechanisms. Each new `Encoder` should be derived from this class.
 47
 48		The Base Encoder translates openc2lib data types and structures
 49		into dictionaries. This function can be used by derived class to have an intermediary representation
 50		which strictly follows the OpenC2 formatting rules. The intermediary representation must then be
 51		translated into the specific syntax used by the derived `Encoder` (e.g., json, xml, yaml).
 52
 53		Currently, this class is only designed to encode into text formats.
 54	"""
 55	encoder_type = 'dictionary'
 56
 57	@classmethod
 58	def getName(cls):
 59		""" Encoder name
 60
 61			This method MUST be implemented to return the name of the encoding format. The name should be
 62			highly representative, possible using official terminology (e.g.: json, xml).
 63
 64			:return: The class name.
 65		"""
 66		return cls.encoder_type
 67
 68	@staticmethod
 69	def encode(obj):
 70		""" Encode an OpenC2 object
 71
 72			This method encodes an openc2lib object (namely, a data structure derived from `BaseType`). 
 73			It MUST be implemented by each derived class. It could be applied to any openc2lib object,
 74			but the most common use is for `Message`, `Command`, or `Response`.
 75
 76			:param obj: An OpenC2 object derived from a `BaseType`. 
 77			:return: A string that contains the encoded object.
 78		"""
 79		return str(Encoder.todict(obj))
 80
 81	@staticmethod
 82	def decode(msgtype, msg):
 83		""" Decode into OpenC2 object
 84
 85			This method decodes a text representation into an openc2lib object. The method throws an `Exception`
 86			in case of unknown elements. 
 87
 88			This method requires to specify the openc2lib class that implements the OpenC2 object described
 89			by the text. This will commonly be either `Message`, `Command`, or `Response`. 
 90
 91			:param msgtype: The class of an openc2lib object.
 92			:param msg: Text-based representation of the OpenC2 object.
 93			:return: An instance of an openc2lib object.
 94		"""
 95		return Encoder.fromdict(msgtype, msg)
 96
 97	@staticmethod
 98	def __objtodict(obj):
 99		if isinstance(obj, list):
100			return Encoder.__iteratelist(obj)
101
102		if isinstance(obj, dict):
103			return  Encoder.__iteratedic(obj)
104
105		# Default: return a string representation of the object
106		return str(obj)
107
108
109	# This method 
110	def __objfromdict(clstype, dic):
111		if isinstance(dic, dict):
112			return clstype(**dic)
113		if isinstance(dic, list):
114			lis = []
115			for i in dic:
116				lis.append[Encoder.fromdict(clstype, i)]
117			return lis
118		if isinstance(dic, _UNCODED):
119			return clstype(dic)
120		raise ValueError("Unmanaged obj value: ", dic)
121
122	# Convert complex types to string by interatively invoking the todict function
123	@staticmethod
124	def __iteratedic(dic):
125		newdic = {}
126		for k,v in dic.items():
127			if v is not None:
128				newdic[Encoder.todict(k)] = Encoder.todict(v)
129#			if not isinstance(v, __UNCODED):
130#				dic[k] = Encoder.todict(v)
131		return newdic
132
133	@staticmethod
134	def __iteratelist(lis):
135		objlist = []
136		for i in lis:
137#			if isinstance(i, __UNCODED):
138#				objlist.append(i)
139#			else:
140#				print("append: ", i)
141#				objlist.append( Encoder.todict(i) )
142			objlist.append( Encoder.todict(i) )
143		return objlist	
144
145#  NOT USED
146#  They Python way: "try ... except ... "
147#	@staticmethod
148#	def hasmethod(obj, method):
149#		return callable(hasattr(obj, method, None))
150
151
152	@staticmethod
153	def todict(obj):
154		""" Convert object to dictionary
155
156			This is an internal method to convert an openc2lib object into a dictionary. The dictionary is
157		  	structured according to OpenC2 syntax.
158
159			This method should only be invoked by derived classes to get the intermediary representation
160			of openc2lib objects. It will likely be used in the implementation of the `decode` method.	
161			:param obj: The openc2lib object to convert into a dictionary.
162			:return: A dictionary compliant with the OpenC2 syntax rules.
163		"""
164		try:
165			return obj.todict(Encoder)
166		except AttributeError:
167			return Encoder.__objtodict(obj)
168			
169
170	@staticmethod
171	def fromdict(clstype, dic):
172		""" Create an object from dictionary
173
174			This is an internal method to create an openc2lib object from a dictionary. The dictionary
175			must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this
176			intermediate representation and use this method in the `encode` method. It is necessary to 
177			provide the class definition of the openc2lib object to be instantiated.
178
179			:param clstype: The class definition that must be used to instantiate the object.
180			:param dic: The dictionary with the OpenC2 description.
181			:return: An instance of `clstype` initialized with the data in the `dic`.
182		"""
183		logger.debug("Decondig: %s with %s", dic, clstype)
184		try:
185			logging.debug("Trying: %s", clstype.fromdict)
186			return clstype.fromdict(dic, Encoder)
187		except AttributeError:
188			logger.debug("Falling back: Encoder.objfromdict for %s", clstype)
189			return Encoder.__objfromdict(clstype, dic)

Base Encoder

The Base Encoder provides a common interface that must be implemented by all implementations of Encoding mechanisms. Each new Encoder should be derived from this class.

The Base Encoder translates openc2lib data types and structures into dictionaries. This function can be used by derived class to have an intermediary representation which strictly follows the OpenC2 formatting rules. The intermediary representation must then be translated into the specific syntax used by the derived Encoder (e.g., json, xml, yaml).

Currently, this class is only designed to encode into text formats.

encoder_type = 'dictionary'
@classmethod
def getName(cls):
57	@classmethod
58	def getName(cls):
59		""" Encoder name
60
61			This method MUST be implemented to return the name of the encoding format. The name should be
62			highly representative, possible using official terminology (e.g.: json, xml).
63
64			:return: The class name.
65		"""
66		return cls.encoder_type

Encoder name

This method MUST be implemented to return the name of the encoding format. The name should be highly representative, possible using official terminology (e.g.: json, xml).

Returns

The class name.

@staticmethod
def encode(obj):
68	@staticmethod
69	def encode(obj):
70		""" Encode an OpenC2 object
71
72			This method encodes an openc2lib object (namely, a data structure derived from `BaseType`). 
73			It MUST be implemented by each derived class. It could be applied to any openc2lib object,
74			but the most common use is for `Message`, `Command`, or `Response`.
75
76			:param obj: An OpenC2 object derived from a `BaseType`. 
77			:return: A string that contains the encoded object.
78		"""
79		return str(Encoder.todict(obj))

Encode an OpenC2 object

This method encodes an openc2lib object (namely, a data structure derived from BaseType). It MUST be implemented by each derived class. It could be applied to any openc2lib object, but the most common use is for Message, Command, or Response.

Parameters
  • obj: An OpenC2 object derived from a BaseType.
Returns

A string that contains the encoded object.

@staticmethod
def decode(msgtype, msg):
81	@staticmethod
82	def decode(msgtype, msg):
83		""" Decode into OpenC2 object
84
85			This method decodes a text representation into an openc2lib object. The method throws an `Exception`
86			in case of unknown elements. 
87
88			This method requires to specify the openc2lib class that implements the OpenC2 object described
89			by the text. This will commonly be either `Message`, `Command`, or `Response`. 
90
91			:param msgtype: The class of an openc2lib object.
92			:param msg: Text-based representation of the OpenC2 object.
93			:return: An instance of an openc2lib object.
94		"""
95		return Encoder.fromdict(msgtype, msg)

Decode into OpenC2 object

This method decodes a text representation into an openc2lib object. The method throws an Exception in case of unknown elements.

This method requires to specify the openc2lib class that implements the OpenC2 object described by the text. This will commonly be either Message, Command, or Response.

Parameters
  • msgtype: The class of an openc2lib object.
  • msg: Text-based representation of the OpenC2 object.
Returns

An instance of an openc2lib object.

@staticmethod
def todict(obj):
152	@staticmethod
153	def todict(obj):
154		""" Convert object to dictionary
155
156			This is an internal method to convert an openc2lib object into a dictionary. The dictionary is
157		  	structured according to OpenC2 syntax.
158
159			This method should only be invoked by derived classes to get the intermediary representation
160			of openc2lib objects. It will likely be used in the implementation of the `decode` method.	
161			:param obj: The openc2lib object to convert into a dictionary.
162			:return: A dictionary compliant with the OpenC2 syntax rules.
163		"""
164		try:
165			return obj.todict(Encoder)
166		except AttributeError:
167			return Encoder.__objtodict(obj)

Convert object to dictionary

This is an internal method to convert an openc2lib object into a dictionary. The dictionary is structured according to OpenC2 syntax.

This method should only be invoked by derived classes to get the intermediary representation of openc2lib objects. It will likely be used in the implementation of the decode method.

Parameters
  • obj: The openc2lib object to convert into a dictionary.
Returns

A dictionary compliant with the OpenC2 syntax rules.

@staticmethod
def fromdict(clstype, dic):
170	@staticmethod
171	def fromdict(clstype, dic):
172		""" Create an object from dictionary
173
174			This is an internal method to create an openc2lib object from a dictionary. The dictionary
175			must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this
176			intermediate representation and use this method in the `encode` method. It is necessary to 
177			provide the class definition of the openc2lib object to be instantiated.
178
179			:param clstype: The class definition that must be used to instantiate the object.
180			:param dic: The dictionary with the OpenC2 description.
181			:return: An instance of `clstype` initialized with the data in the `dic`.
182		"""
183		logger.debug("Decondig: %s with %s", dic, clstype)
184		try:
185			logging.debug("Trying: %s", clstype.fromdict)
186			return clstype.fromdict(dic, Encoder)
187		except AttributeError:
188			logger.debug("Falling back: Encoder.objfromdict for %s", clstype)
189			return Encoder.__objfromdict(clstype, dic)

Create an object from dictionary

This is an internal method to create an openc2lib object from a dictionary. The dictionary must be compliant with the OpenC2 syntax rules. Derived classes are expected to create this intermediate representation and use this method in the encode method. It is necessary to provide the class definition of the openc2lib object to be instantiated.

Parameters
  • clstype: The class definition that must be used to instantiate the object.
  • dic: The dictionary with the OpenC2 description.
Returns

An instance of clstype initialized with the data in the dic.