# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.
from mixbox import entities
from mixbox import fields
from mixbox import idgen
import cybox
import cybox.utils
import cybox.bindings.cybox_core as core_binding
from cybox.common.object_properties import ObjectPropertiesFactory, ObjectProperties
from cybox.common.vocabs import VocabField
from cybox.common.vocabs import ObjectRelationship as Relationship
_EXTERNAL_CLASSES = {} # Maps xsi:type values to binding
[docs]def add_external_class(klass, xsi_type):
"""Adds a class implementation to this binding's globals() dict.
These classes can be used to implement Properties,
Domain_Specific_Object_Properties, or Defined_Effect fields on an Object.
Args:
klass (class): Python class that implements the new type
xsi_type (str): An xsi:type value corresponding to the `klass`.
"""
_EXTERNAL_CLASSES[xsi_type] = klass
class ExternalTypeFactory(entities.EntityFactory):
def entity_class(cls, key):
return _EXTERNAL_CLASSES[key]
def _modify_properties_parent(instance, value=None):
if isinstance(instance, RelatedObject) and not instance._inline:
return
if instance.properties:
instance.properties.parent = instance
def _cache_object(instance, value=None):
if instance.id_:
cybox.utils.cache_put(instance)
[docs]class Object(entities.Entity):
"""The CybOX Object element.
Currently only supports the following data members:
- id\_
- idref
- properties
- related_objects
- domain specific object properties
"""
_binding = core_binding
_binding_class = _binding.ObjectType
_namespace = 'http://cybox.mitre.org/cybox-2'
id_ = fields.IdField("id", postset_hook=_cache_object)
idref = fields.IdrefField("idref")
properties = fields.TypedField("Properties", ObjectProperties, factory=ObjectPropertiesFactory, postset_hook=_modify_properties_parent)
related_objects = fields.TypedField("Related_Objects", "cybox.core.object.RelatedObjects")
domain_specific_object_properties = fields.TypedField("Domain_Specific_Object_Properties", "cybox.core.DomainSpecificObjectProperties", factory=ExternalTypeFactory)
def __init__(self, properties=None, type_=None, id_=None, idref=None):
super(Object, self).__init__()
if properties:
prefix = str(properties.__class__.__name__)
else:
prefix = "Object"
self.id_ = id_ or idgen.create_id(prefix=prefix)
self.idref = idref
self.properties = properties
self.related_objects = RelatedObjects()
def __str__(self):
if self.id_ is not None:
return self.id_
elif self.idref is not None:
return self.idref
else:
return super(Object, self).__repr__()
[docs]class DomainSpecificObjectProperties(entities.Entity):
"""The Cybox DomainSpecificObjectProperties base class."""
_binding = core_binding
_binding_class = _binding.DomainSpecificObjectPropertiesType
# Override in subclass
_XSI_TYPE = None
_XSI_NS = None
[docs] def to_obj(self, ns_info=None):
obj = super(DomainSpecificObjectProperties, self).to_obj(ns_info=ns_info)
obj.xsi_type = "%s:%s" % (self._XSI_NS, self._XSI_TYPE)
[docs] def to_dict(self):
d = super(DomainSpecificObjectProperties, self).to_dict()
d['xsi:type'] = self._XSI_TYPE
return d