Skip to content

Commit

Permalink
Update to use TypedFields from mixbox.
Browse files Browse the repository at this point in the history
  • Loading branch information
gtback committed Jun 18, 2015
1 parent 53283fb commit f134069
Show file tree
Hide file tree
Showing 101 changed files with 1,714 additions and 1,663 deletions.
119 changes: 5 additions & 114 deletions cybox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
import json

from mixbox.binding_utils import save_encoding
from mixbox import fields
from mixbox.vendor import six

import cybox.utils.idgen
from cybox.utils import Namespace, META, is_sequence
from cybox.utils import Namespace, META

from .version import __version__ # noqa

Expand Down Expand Up @@ -76,7 +77,7 @@ def __init__(self):
def _get_vars(cls):
var_list = []
for (name, obj) in inspect.getmembers(cls, inspect.isdatadescriptor):
if isinstance(obj, TypedField):
if isinstance(obj, fields.TypedField):
var_list.append(obj)

return var_list
Expand Down Expand Up @@ -139,7 +140,7 @@ def to_obj(self, return_obj=None, ns_info=None):
members.update(vars(klass))

for field in six.itervalues(members):
if isinstance(field, TypedField):
if isinstance(field, fields.TypedField):
val = getattr(self, field.attr_name)

if field.multiple:
Expand Down Expand Up @@ -178,7 +179,7 @@ def to_dict(self):
members.update(vars(klass))

for field in six.itervalues(members):
if isinstance(field, TypedField):
if isinstance(field, fields.TypedField):
val = getattr(self, field.attr_name)

if field.multiple:
Expand Down Expand Up @@ -592,113 +593,3 @@ class ReferenceList(EntityList):
def _fix_value(self, value):
if isinstance(value, six.string_types):
return self._contained_type(value)


class TypedField(object):

def __init__(self, name, type_=None, callback_hook=None, key_name=None,
comparable=True, multiple=False):
"""
Create a new field.
- `name` is the name of the field in the Binding class
- `type_` is the type that objects assigned to this field must be.
If `None`, no type checking is performed.
- `key_name` is only needed if the desired key for the dictionary
representation is differen than the lower-case version of `name`
- `comparable` (boolean) - whether this field should be considered
when checking Entities for equality. Default is True. If false, this
field is not considered
- `multiple` (boolean) - Whether multiple instances of this field can
exist on the Entity.
"""
self.name = name
self.type_ = type_
self.callback_hook = callback_hook
self._key_name = key_name
self.comparable = comparable
self.multiple = multiple

def __get__(self, instance, owner):
# If we are calling this on a class, we want the actual Field, not its
# value
if not instance:
return self

return instance._fields.get(self.name, [] if self.multiple else None)

def _handle_value(self, value):
"""Handles the processing of the __set__ value.
"""
if value is None:
return None
elif self.type_ is None:
return value
elif self.type_.istypeof(value):
return value
elif self.type_._try_cast: # noqa
return self.type_(value)

error_fmt = "%s must be a %s, not a %s"
error = error_fmt % (self.name, self.type_, type(value))
raise ValueError(error)

def __set__(self, instance, value):
"""Sets the field value on `instance` for this TypedField.
If the TypedField has a `type_` and `value` is not an instance of
``type_``, an attempt may be made to convert `value` into an instance
of ``type_``.
If the field is ``multiple``, an attempt is made to convert `value`
into a list if it is not an iterable type.
"""
if self.multiple:
if value is None:
processed = []
elif not is_sequence(value):
processed = [self._handle_value(value)]
else:
processed = [self._handle_value(x) for x in value if x is not None]
else:
processed = self._handle_value(value)

instance._fields[self.name] = processed

if self.callback_hook:
self.callback_hook(instance)

def __str__(self):
return self.attr_name

@property
def key_name(self):
if self._key_name:
return self._key_name
else:
return self.name.lower()

@property
def attr_name(self):
"""The name of this field as an attribute name.
This is identical to the key_name, unless the key name conflicts with
a builtin Python keyword, in which case a single underscore is
appended.
This should match the name given to the TypedField class variable (see
examples below), but this is not enforced.
Examples:
data = cybox.TypedField("Data", String)
from_ = cybox.TypedField("From", String)
"""

attr = self.key_name
# TODO: expand list with other Python keywords
if attr in ('from', 'class', 'type', 'with', 'for', 'id', 'type',
'range'):
attr = attr + "_"
return attr
16 changes: 9 additions & 7 deletions cybox/common/byterun.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import HashList, Integer, String
Expand All @@ -11,13 +13,13 @@ class ByteRun(cybox.Entity):
_binding_class = common_binding.ByteRunType
_namespace = 'http://cybox.mitre.org/common-2'

offset = cybox.TypedField("Offset", Integer)
byte_order = cybox.TypedField("Byte_Order", String)
file_system_offset = cybox.TypedField("File_System_Offset", Integer)
image_offset = cybox.TypedField("Image_Offset", Integer)
length = cybox.TypedField("Length", Integer)
hashes = cybox.TypedField("Hashes", HashList)
byte_run_data = cybox.TypedField("Byte_Run_Data")
offset = fields.TypedField("Offset", Integer)
byte_order = fields.TypedField("Byte_Order", String)
file_system_offset = fields.TypedField("File_System_Offset", Integer)
image_offset = fields.TypedField("Image_Offset", Integer)
length = fields.TypedField("Length", Integer)
hashes = fields.TypedField("Hashes", HashList)
byte_run_data = fields.TypedField("Byte_Run_Data")


class ByteRuns(cybox.EntityList):
Expand Down
16 changes: 9 additions & 7 deletions cybox/common/contributor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import DateRange
Expand All @@ -11,13 +13,13 @@ class Contributor(cybox.Entity):
_binding_class = common_binding.ContributorType
_namespace = 'http://cybox.mitre.org/common-2'

role = cybox.TypedField("Role")
name = cybox.TypedField("Name")
email = cybox.TypedField("Email")
phone = cybox.TypedField("Phone")
organization = cybox.TypedField("Organization")
date = cybox.TypedField("Date", DateRange)
contribution_location = cybox.TypedField("Contribution_Location")
role = fields.TypedField("Role")
name = fields.TypedField("Name")
email = fields.TypedField("Email")
phone = fields.TypedField("Phone")
organization = fields.TypedField("Organization")
date = fields.TypedField("Date", DateRange)
contribution_location = fields.TypedField("Contribution_Location")


class Personnel(cybox.EntityList):
Expand Down
18 changes: 10 additions & 8 deletions cybox/common/data_segment.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import Integer, String
Expand Down Expand Up @@ -58,11 +60,11 @@ class DataSegment(cybox.Entity):
_binding_class = common_binding.DataSegmentType
_namespace = 'http://cybox.mitre.org/common-2'

id_ = cybox.TypedField("id")
data_format = cybox.TypedField("Data_Format")
data_size = cybox.TypedField("Data_Size", DataSize)
byte_order = cybox.TypedField("Byte_Order", String)
data_segment = cybox.TypedField("Data_Segment", String)
offset = cybox.TypedField("Offset", Integer)
search_distance = cybox.TypedField("Search_Distance", Integer)
search_within = cybox.TypedField("Search_Within", Integer)
id_ = fields.TypedField("id")
data_format = fields.TypedField("Data_Format")
data_size = fields.TypedField("Data_Size", DataSize)
byte_order = fields.TypedField("Byte_Order", String)
data_segment = fields.TypedField("Data_Segment", String)
offset = fields.TypedField("Offset", Integer)
search_distance = fields.TypedField("Search_Distance", Integer)
search_within = fields.TypedField("Search_Within", Integer)
6 changes: 4 additions & 2 deletions cybox/common/daterange.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import DateWithPrecision
Expand All @@ -11,5 +13,5 @@ class DateRange(cybox.Entity):
_binding_class = common_binding.DateRangeType
_namespace = 'http://cybox.mitre.org/common-2'

start_date = cybox.TypedField("Start_Date", DateWithPrecision)
end_date = cybox.TypedField("End_Date", DateWithPrecision)
start_date = fields.TypedField("Start_Date", DateWithPrecision)
end_date = fields.TypedField("End_Date", DateWithPrecision)
12 changes: 7 additions & 5 deletions cybox/common/digitalsignature.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import String
Expand All @@ -11,11 +13,11 @@ class DigitalSignature(cybox.Entity):
_binding_class = common_binding.DigitalSignatureInfoType
_namespace = 'http://cybox.mitre.org/common-2'

signature_exists = cybox.TypedField("signature_exists")
signature_verified = cybox.TypedField("signature_verified")
certificate_issuer = cybox.TypedField("Certificate_Issuer", String)
certificate_subject = cybox.TypedField("Certificate_Subject", String)
signature_description = cybox.TypedField("Signature_Description", String)
signature_exists = fields.TypedField("signature_exists")
signature_verified = fields.TypedField("signature_verified")
certificate_issuer = fields.TypedField("Certificate_Issuer", String)
certificate_subject = fields.TypedField("Certificate_Subject", String)
signature_description = fields.TypedField("Signature_Description", String)


class DigitalSignatureList(cybox.EntityList):
Expand Down
10 changes: 6 additions & 4 deletions cybox/common/extracted_features.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import ExtractedStrings, ObjectProperties, String
Expand Down Expand Up @@ -35,7 +37,7 @@ class ExtractedFeatures(cybox.Entity):
_binding_class = common_binding.ExtractedFeaturesType
_namespace = 'http://cybox.mitre.org/common-2'

strings = cybox.TypedField("Strings", ExtractedStrings)
imports = cybox.TypedField("Imports", Imports)
functions = cybox.TypedField("Functions", Functions)
code_snippets = cybox.TypedField("Code_Snippets", CodeSnippets)
strings = fields.TypedField("Strings", ExtractedStrings)
imports = fields.TypedField("Imports", Imports)
functions = fields.TypedField("Functions", Functions)
code_snippets = fields.TypedField("Code_Snippets", CodeSnippets)
16 changes: 9 additions & 7 deletions cybox/common/extracted_string.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import (
Expand All @@ -15,13 +17,13 @@ class ExtractedString(cybox.Entity):
_namespace = 'http://cybox.mitre.org/common-2'

encoding = vocabs.VocabField("Encoding", CharacterEncoding)
string_value = cybox.TypedField("String_Value", String)
byte_string_value = cybox.TypedField("Byte_String_Value", String)
hashes = cybox.TypedField("Hashes", HashList)
address = cybox.TypedField("Address", HexBinary)
length = cybox.TypedField("Length", PositiveInteger)
language = cybox.TypedField("Language", String)
english_translation = cybox.TypedField("English_Translation", String)
string_value = fields.TypedField("String_Value", String)
byte_string_value = fields.TypedField("Byte_String_Value", String)
hashes = fields.TypedField("Hashes", HashList)
address = fields.TypedField("Address", HexBinary)
length = fields.TypedField("Length", PositiveInteger)
language = fields.TypedField("Language", String)
english_translation = fields.TypedField("English_Translation", String)

def __init__(self, string_value=None):
super(ExtractedString, self).__init__()
Expand Down
5 changes: 3 additions & 2 deletions cybox/common/hashes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields
from mixbox.vendor import six
from mixbox.vendor.six import u

Expand Down Expand Up @@ -38,9 +39,9 @@ def _auto_type(self):
self.type_ = Hash.TYPE_OTHER

type_ = vocabs.VocabField("Type", HashName)
simple_hash_value = cybox.TypedField("Simple_Hash_Value", HexBinary,
simple_hash_value = fields.TypedField("Simple_Hash_Value", HexBinary,
callback_hook=_auto_type)
fuzzy_hash_value = cybox.TypedField("Fuzzy_Hash_Value", String)
fuzzy_hash_value = fields.TypedField("Fuzzy_Hash_Value", String)

TYPE_MD5 = u("MD5")
TYPE_MD6 = u("MD6")
Expand Down
24 changes: 13 additions & 11 deletions cybox/common/measuresource.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2015, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

from mixbox import fields

import cybox
import cybox.bindings.cybox_common as common_binding
from cybox.common import (vocabs, ObjectProperties, Personnel,
Expand All @@ -14,17 +16,17 @@ class MeasureSource(cybox.Entity):
_binding_class = common_binding.MeasureSourceType
_namespace = 'http://cybox.mitre.org/common-2'

class_ = cybox.TypedField("classxx", key_name="class")
source_type = cybox.TypedField("source_type")
name = cybox.TypedField("name")
sighting_count = cybox.TypedField("sighting_count")
class_ = fields.TypedField("classxx", key_name="class")
source_type = fields.TypedField("source_type")
name = fields.TypedField("name")
sighting_count = fields.TypedField("sighting_count")
information_source_type = vocabs.VocabField("Information_Source_Type",
InformationSourceType)
tool_type = vocabs.VocabField("Tool_Type", ToolType)
description = cybox.TypedField("Description", StructuredText)
contributors = cybox.TypedField("Contributors", Personnel)
time = cybox.TypedField("Time", Time)
tools = cybox.TypedField("Tools", ToolInformationList)
platform = cybox.TypedField("Platform", PlatformSpecification)
system = cybox.TypedField("System", ObjectProperties)
instance = cybox.TypedField("Instance", ObjectProperties)
description = fields.TypedField("Description", StructuredText)
contributors = fields.TypedField("Contributors", Personnel)
time = fields.TypedField("Time", Time)
tools = fields.TypedField("Tools", ToolInformationList)
platform = fields.TypedField("Platform", PlatformSpecification)
system = fields.TypedField("System", ObjectProperties)
instance = fields.TypedField("Instance", ObjectProperties)

0 comments on commit f134069

Please sign in to comment.