Skip to content

Commit 501d285

Browse files
committed
Merge branch '59-http-header-content-security-policy'
Closes: #59
2 parents 6bf9565 + fd7ebca commit 501d285

File tree

8 files changed

+1717
-74
lines changed

8 files changed

+1717
-74
lines changed

cryptoparser/common/base.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def as_markdown(self):
279279

280280

281281
@attr.s
282-
class VariantParsable(ParsableBase):
282+
class VariantParsableBase(ParsableBase):
283283
variant = attr.ib()
284284

285285
_REGISTERED_VARIANTS = OrderedDict()
@@ -324,6 +324,21 @@ def register_variant_parser(cls, variant_tag, parsable_class):
324324

325325
registered_variants[variant_tag].append(parsable_class)
326326

327+
@classmethod
328+
@abc.abstractmethod
329+
def _parse(cls, parsable):
330+
raise NotImplementedError()
331+
332+
def compose(self):
333+
return self.variant.compose()
334+
335+
336+
class VariantParsable(VariantParsableBase):
337+
@classmethod
338+
@abc.abstractmethod
339+
def _get_variants(cls):
340+
raise NotImplementedError()
341+
327342
@classmethod
328343
def _parse(cls, parsable):
329344
for variant_parser in cls._get_variant_types():
@@ -335,8 +350,23 @@ def _parse(cls, parsable):
335350

336351
raise InvalidValue(parsable, cls)
337352

338-
def compose(self):
339-
return self.variant.compose()
353+
354+
class VariantParsableExact(VariantParsableBase):
355+
@classmethod
356+
@abc.abstractmethod
357+
def _get_variants(cls):
358+
raise NotImplementedError()
359+
360+
@classmethod
361+
def _parse(cls, parsable):
362+
for variant_parser in cls._get_variant_types():
363+
try:
364+
parsed_object = variant_parser.parse_exact_size(parsable)
365+
return parsed_object, len(parsable)
366+
except (InvalidType, InvalidValue, TooMuchData):
367+
pass
368+
369+
raise InvalidValue(parsable, cls)
340370

341371

342372
@attr.s
@@ -825,7 +855,7 @@ def _parse(cls, parsable):
825855
enum_items.sort(key=lambda color: len(color.value.code), reverse=True)
826856

827857
try:
828-
code = six.ensure_text(parsable, 'ascii')
858+
code = six.ensure_text(bytes(parsable), 'ascii')
829859
except UnicodeDecodeError as e:
830860
six.raise_from(InvalidValue(parsable, cls), e)
831861

cryptoparser/common/field.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# -*- coding: utf-8 -*-
2+
# pylint: disable=too-many-lines
23

34
import abc
45
import collections
56
import datetime
7+
import enum
68
import json
79

810
import attr
@@ -791,6 +793,63 @@ def _get_header_value_list_class(cls):
791793
return NameValuePairListSemicolonSeparated
792794

793795

796+
class MimeTypeRegistry(enum.Enum):
797+
APPLICATION = 'application'
798+
AUDIO = 'audio'
799+
FONT = 'font'
800+
EXAMPLE = 'example'
801+
IMAGE = 'image'
802+
MESSAGE = 'message'
803+
MODEL = 'model'
804+
MULTIPART = 'multipart'
805+
TEXT = 'text'
806+
VIDEO = 'video'
807+
808+
809+
@attr.s
810+
class FieldValueMimeType(FieldValueComponentBase):
811+
type = attr.ib(
812+
validator=attr.validators.instance_of(six.string_types),
813+
default=None,
814+
)
815+
registry = attr.ib(
816+
validator=attr.validators.optional(attr.validators.instance_of(MimeTypeRegistry)),
817+
default=None,
818+
)
819+
820+
def __str__(self):
821+
return '{}/{}'.format(self.registry.value, self.type)
822+
823+
@property
824+
def value(self):
825+
return self
826+
827+
@classmethod
828+
def get_canonical_name(cls):
829+
return ''
830+
831+
@classmethod
832+
def _parse(cls, parsable):
833+
parser = ParserText(parsable)
834+
835+
parser.parse_string_until_separator('registry', '/', item_class=MimeTypeRegistry)
836+
parser.parse_separator('/')
837+
parser.parse_string_by_length('type', parser.unparsed_length)
838+
839+
return FieldValueMimeType(**parser), parser.parsed_length
840+
841+
def compose(self):
842+
composer = ComposerText()
843+
844+
composer.compose_string(str(self))
845+
846+
return composer.composed
847+
848+
@classmethod
849+
def _check_name(cls, name):
850+
pass
851+
852+
794853
@attr.s
795854
class FieldValueSingleBase(FieldValueBase, Serializable):
796855
value = attr.ib()
@@ -916,6 +975,32 @@ def _as_markdown(self, level):
916975
return self._markdown_result(self.value, level)
917976

918977

978+
class FieldValueStringBySeparatorBase(FieldValueSingleComplexBase):
979+
@classmethod
980+
@abc.abstractmethod
981+
def _get_separators(cls):
982+
raise NotImplementedError()
983+
984+
@classmethod
985+
def _get_value_type(cls):
986+
return six.string_types
987+
988+
@classmethod
989+
def _parse(cls, parsable):
990+
parser = ParserText(parsable)
991+
992+
parser.parse_string_until_separator_or_end('value', cls._get_separators())
993+
994+
return cls(parser['value']), parser.parsed_length
995+
996+
def compose(self):
997+
composer = ComposerText()
998+
999+
composer.compose_string(self.value)
1000+
1001+
return composer.composed
1002+
1003+
9191004
class FieldValueStringEnum(FieldValueSingleComplexBase):
9201005
@classmethod
9211006
@abc.abstractmethod

cryptoparser/common/parse.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def _check_separators( # pylint: disable=too-many-arguments
201201

202202
return actual_offset - count_offset
203203

204-
def parse_separator(self, separator, min_length=1, max_length=1):
204+
def parse_separator(self, separator, min_length=1, max_length=None):
205205
self._parsed_length += self._check_separators(
206206
'separator', self._parsed_length, separator, min_length, max_length
207207
)
@@ -405,15 +405,18 @@ def _parse_string_array(
405405
name, item_offset, separator, str, None, True, separator_spaces
406406
)
407407
if parsed_length:
408-
parsed_value = self._apply_item_class(
409-
name,
410-
item_offset,
411-
item_offset + parsed_length,
412-
separator,
413-
item_class,
414-
fallback_class,
415-
True
416-
)
408+
if isinstance(item_class, type) and issubclass(item_class, ParsableBase):
409+
parsed_value = item_class.parse_exact_size(parsed_value.encode(self._encoding))
410+
else:
411+
parsed_value = self._apply_item_class(
412+
name,
413+
item_offset,
414+
item_offset + parsed_length,
415+
separator,
416+
item_class,
417+
fallback_class,
418+
True
419+
)
417420
value.append(parsed_value)
418421
item_offset += parsed_length
419422
elif not skip_empty:

0 commit comments

Comments
 (0)