1215 lines
45 KiB
Python
1215 lines
45 KiB
Python
# -*- coding: UTF-8 -*-
|
|
#/**
|
|
# * Software Name : pycrate
|
|
# * Version : 0.3
|
|
# *
|
|
# * Copyright 2017. Benoit Michau. ANSSI.
|
|
# *
|
|
# * This library is free software; you can redistribute it and/or
|
|
# * modify it under the terms of the GNU Lesser General Public
|
|
# * License as published by the Free Software Foundation; either
|
|
# * version 2.1 of the License, or (at your option) any later version.
|
|
# *
|
|
# * This library is distributed in the hope that it will be useful,
|
|
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# * Lesser General Public License for more details.
|
|
# *
|
|
# * You should have received a copy of the GNU Lesser General Public
|
|
# * License along with this library; if not, write to the Free Software
|
|
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
# * MA 02110-1301 USA
|
|
# *
|
|
# *--------------------------------------------------------
|
|
# * File Name : pycrate_asn1rt/asnobj.py
|
|
# * Created : 2017-01-31
|
|
# * Authors : Benoit Michau
|
|
# *--------------------------------------------------------
|
|
#*/
|
|
|
|
from .utils import *
|
|
from .err import *
|
|
from .refobj import *
|
|
from .dictobj import *
|
|
from .setobj import *
|
|
from .codecs import *
|
|
|
|
|
|
ASN1Obj_docstring = """
|
|
Common object attributes:
|
|
|
|
- name: str, the identifier of the object
|
|
|
|
- mode: str (MODE_*), the mode of the object after compilation.
|
|
- MODE_TYPE : ASN.1 subtype or subclass
|
|
- MODE_VALUE: ASN.1 value
|
|
- MODE_SET : ASN.1 set of values
|
|
|
|
- param: bool, True in case the object is a parameterized one.
|
|
Parameterized objects are "empty" and mainly useless for encoding / decoding.
|
|
They are still required to keep track of object references and tag chain.
|
|
|
|
- tag: None or tuple, contains the tagging of the ASN.1 type.
|
|
If defined, it has the following format:
|
|
(tag value (int),
|
|
tag class (str in TAG_CONTEXT_SPEC / TAG_PRIVATE / TAG_APPLICATION / TAG_UNIVERSAL),
|
|
tag mode (str in TAG_IMPLICIT / TAG_EXPLICIT))
|
|
|
|
- typeref: None or ASN1Ref, provides the reference to the subtype of the object
|
|
in case it derives from another user-defined one (and not a native one).
|
|
|
|
- tr: None or ASN1Obj, provides the actual subtype object
|
|
|
|
- cont: type-dependent.
|
|
|
|
- root: None or list of str, provides the identifiers of the root content if
|
|
defined.
|
|
|
|
- ext: None or list of str, provides the identifiers of the extended content if
|
|
defined.
|
|
|
|
- val: None for MODE_TYPE,
|
|
single_value (type-dependent) for MODE_VALUE,
|
|
ASN1Set for MODE_SET.
|
|
|
|
Attributes for object generic constraints:
|
|
|
|
- const_val: None or ASN1Set, provides the set of values that constraints the type
|
|
|
|
- const_tab: None or ASN1Obj (MODE_SET), provides the CLASS set for table lookup
|
|
|
|
- const_tab_id: None or str, only set if const_tab is set,
|
|
provides the identifier that corresponds to self in const_tab
|
|
|
|
- const_tab_at: None or tuple of str, only set if const_tab is set,
|
|
provides the path of identifiers to which self must refer for the table lookup in const_tab
|
|
|
|
Attributes defined for components of a constructed or CLASS type:
|
|
|
|
- parent: None or ASN1Obj, indicates the parent ASN.1 object container
|
|
|
|
- opt: bool, indicates if the component is OPTIONAL
|
|
|
|
- def: None or single value, indicates the DEFAULT value
|
|
|
|
- uniq: bool, indicates if the component is UNIQUE
|
|
|
|
- group: None or int, indicates the extension group index for grouped extended components
|
|
|
|
Special attributes that exists only for some objects:
|
|
|
|
- root_mand (for SEQUENCE, SET, CLASS)
|
|
- root_opt (for SEQUENCE, SET, CLASS)
|
|
- cont_rev (for ENUM)
|
|
- cont_tags (for CHOICE, SEQUENCE, SET)
|
|
- ext_ident (for CHOICE, SEQUENCE, SET)
|
|
- ext_group (for CHOICE, SEQUENCE, SET)
|
|
- ext_group_obj (for SEQUENCE, SET)
|
|
- ext_nest (for SEQUENCE, SET)
|
|
- defby (for ANY)
|
|
|
|
Attributes for object specific constraints:
|
|
|
|
- const_sz (for BIT STRING, OCTET STRING, *String, SEQUENCE OF, SET OF)
|
|
- const_ind (for ENUM and CHOICE)
|
|
- const_cont (for BIT STRING, OCTET STRING)
|
|
- const_cont_enc (for BIT STRING, OCTET STRING)
|
|
- const_alpha (for *String)
|
|
|
|
Attributes used at run-time:
|
|
|
|
- struct: None or pycrate.elt.Element instance, provides the complete
|
|
structure of the transfer syntax with, generated when encoding and
|
|
decoding the object when using from_*_ws() and to_*_ws() methods.
|
|
"""
|
|
|
|
class ASN1Obj(Element):
|
|
|
|
# in order to disable any asnlog() during the runtime
|
|
_SILENT = False
|
|
|
|
# this enables object verification during Python module initialization
|
|
_SAFE_INIT = True
|
|
# this enables object value verification when using set_val()
|
|
_SAFE_VAL = True
|
|
# this enables object's constraints verification when using set_val() or
|
|
# set_val_unsafe()
|
|
_SAFE_BND = True
|
|
# this enables object's table constraint verification when using set_val()
|
|
# or set_val_unsafe()
|
|
_SAFE_BNDTAB = True
|
|
|
|
#--------------------------------------------------------------------------#
|
|
# class attributes, initialization and safe checking methods
|
|
#--------------------------------------------------------------------------#
|
|
|
|
_name = ''
|
|
_mode = MODE_TYPE
|
|
_tag = None
|
|
_typeref = None
|
|
_tr = None
|
|
_param = False
|
|
_parent = None
|
|
_opt = False
|
|
_def = None
|
|
_uniq = False
|
|
_group = None
|
|
_cont = None
|
|
_root = None
|
|
_ext = None
|
|
_val = None
|
|
|
|
_const_val = None
|
|
# _const_sz is only defined for types which can have a SIZE constraint
|
|
#_const_sz = None
|
|
# _const_alpha is only defined for _String subtypes
|
|
#_const_alpha = None
|
|
# _const_cont is only defined for BIT STRING and OCTET STRING
|
|
#_const_cont = None
|
|
#_const_cont_enc = None
|
|
_const_tab = None
|
|
# _const_tab_id and _const_tab_at are only defined if _const_tab is not None
|
|
#_const_tab_id = None
|
|
#_const_tab_at = None
|
|
|
|
|
|
TYPE = None
|
|
TAG = None
|
|
|
|
def __init__(self, **kwargs):
|
|
if 'name' in kwargs: self._name = kwargs['name']
|
|
if 'mode' in kwargs: self._mode = kwargs['mode']
|
|
if 'tag' in kwargs: self._tag = kwargs['tag']
|
|
if 'typeref' in kwargs: self._typeref = kwargs['typeref']
|
|
if 'param' in kwargs: self._param = kwargs['param']
|
|
if 'opt' in kwargs: self._opt = kwargs['opt']
|
|
elif 'default' in kwargs: self._def = kwargs['default']
|
|
if 'defby' in kwargs: self._defby = kwargs['defby']
|
|
if 'uniq' in kwargs: self._uniq = kwargs['uniq']
|
|
if 'group' in kwargs: self._group = kwargs['group']
|
|
|
|
def _safechk_obj(self):
|
|
"""
|
|
ensures all internal attributes at initialization have the correct format
|
|
"""
|
|
# name
|
|
if not isinstance(self._name, str_types):
|
|
raise(ASN1ObjErr('invalid name, {0!r}'.format(self._name)))
|
|
# mode
|
|
if self._mode not in (MODE_TYPE, MODE_SET, MODE_VALUE):
|
|
raise(ASN1ObjErr('{0}: invalid mode, {1!r}'\
|
|
.format(self.fullname(), self._mode)))
|
|
# tag
|
|
if not isinstance(self._tag, (NoneType, tuple)):
|
|
raise(ASN1ObjErr('{0}: invalid tag, {1!r}'\
|
|
.format(self.fullname(), self._tag)))
|
|
elif isinstance(self._tag, tuple) and ( \
|
|
len(self._tag) != 3 or \
|
|
not isinstance(self._tag[0], integer_types) or \
|
|
self._tag[1] not in (TAG_CONTEXT_SPEC, TAG_PRIVATE, TAG_APPLICATION, TAG_UNIVERSAL) or \
|
|
self._tag[2] not in (TAG_IMPLICIT, TAG_EXPLICIT)):
|
|
raise(ASN1ObjErr('{0}: invalid tag, {1!r}'\
|
|
.format(self.fullname(), self._tag)))
|
|
# typeref
|
|
if not isinstance(self._typeref, (NoneType, ASN1Ref)):
|
|
raise(ASN1ObjErr('{0}: invalid typeref, {1!r}'\
|
|
.format(self.fullname(), self._typeref)))
|
|
# param
|
|
if not isinstance(self._param, bool):
|
|
raise(ASN1ObjErr('{0}: invalid param, {1!r}'\
|
|
.format(self.fullname(), self._param)))
|
|
# parent
|
|
if not isinstance(self._parent, (NoneType, ASN1Obj)):
|
|
raise(ASN1ObjErr('{0}: invalid parent, {1!r}'\
|
|
.format(self.fullname(), self._parent)))
|
|
# opt
|
|
if not isinstance(self._opt, bool):
|
|
raise(ASN1ObjErr('{0}: invalid opt, {1!r}'\
|
|
.format(self.fullname(), self._opt)))
|
|
# default
|
|
if not isinstance(self._def, NoneType):
|
|
if self._mode == MODE_SET:
|
|
self._safechk_set(self._def)
|
|
else:
|
|
self._safechk_val(self._def)
|
|
# uniq
|
|
if not isinstance(self._uniq, bool):
|
|
raise(ASN1ObjErr('{0}: invalid uniq, {1!r}'\
|
|
.format(self.fullname(), self._uniq)))
|
|
# group
|
|
if not isinstance(self._group, (NoneType, integer_types)):
|
|
raise(ASN1ObjErr('{0}: invalid group, {1!r}'\
|
|
.format(self.fullname(), self._group)))
|
|
|
|
def _safechk_val(self, val):
|
|
"""
|
|
ensures the value val has the correct format according to self
|
|
"""
|
|
# check val format, implemented for each specific object
|
|
pass
|
|
|
|
def _safechk_val_int(self, val):
|
|
if not isinstance(val, integer_types):
|
|
raise(ASN1ObjErr('{0}: invalid INTEGER value, {1!r}'\
|
|
.format(self.fullname(), val)))
|
|
|
|
def _safechk_val_real(self, val):
|
|
if not isinstance(val, tuple) or len(val) != 3 or \
|
|
not isinstance(val[0], integer_types) or \
|
|
val[1] not in (2, 10) or \
|
|
not isinstance(val[2], integer_types):
|
|
raise(ASN1ObjErr('{0}: invalid REAL value, {1!r}'\
|
|
.format(self.fullname(), val)))
|
|
|
|
def _safechk_val_str(self, val):
|
|
if not isinstance(val, str_types):
|
|
raise(ASN1ObjErr('{0}: invalid _String value, {1!r}'\
|
|
.format(self.fullname(), val)))
|
|
|
|
def _safechk_set(self, s):
|
|
"""
|
|
ensures the set of values s has the correct format according to self
|
|
"""
|
|
if not isinstance(s, ASN1Set):
|
|
raise(ASN1ObjErr('{0}: invalid set, {1!r}'.format(self.fullname(), s)))
|
|
for v in s._rv:
|
|
self._safechk_val(v)
|
|
if s._ev is not None:
|
|
for v in s._ev:
|
|
self._safechk_val(v)
|
|
|
|
def _safechk_set_int(self, si):
|
|
if not isinstance(s, ASN1Set):
|
|
raise(ASN1ObjErr('{0}: invalid set, {1!r}'.format(self.fullname(), s)))
|
|
for v in s._rv:
|
|
self._safechk_val(v)
|
|
for vr in s._rr:
|
|
if not isinstance(vr, ASN1RangeInt):
|
|
raise(ASN1ObjErr('{0}: invalid INTEGER range, {1!r}'\
|
|
.format(self.fullname(), vr)))
|
|
if s._ev is not None:
|
|
for v in s._ev:
|
|
self._safechk_val(v)
|
|
for vr in s._er:
|
|
if not isinstance(vr, ASN1RangeInt):
|
|
raise(ASN1ObjErr('{0}: invalid INTEGER range, {1!r}'\
|
|
.format(self.fullname(), vr)))
|
|
|
|
def _safechk_set_real(self, sr):
|
|
if not isinstance(s, ASN1Set):
|
|
raise(ASN1ObjErr('{0}: invalid set, {1!r}'.format(self.fullname(), s)))
|
|
for v in s._rv:
|
|
self._safechk_val(v)
|
|
for vr in s._rr:
|
|
if not isinstance(vr, ASN1RangeReal):
|
|
raise(ASN1ObjErr('{0}: invalid REAL range, {1!r}'\
|
|
.format(self.fullname(), vr)))
|
|
if s._ev is not None:
|
|
for v in s._evt:
|
|
self._safechk_val(v)
|
|
for vr in s._er:
|
|
if not isinstance(vr, ASN1RangeReal):
|
|
raise(ASN1ObjErr('{0}: invalid REAL range, {1!r}'\
|
|
.format(self.fullname(), vr)))
|
|
|
|
def _safechk_set_str(self, ss):
|
|
if not isinstance(s, ASN1Set):
|
|
raise(ASN1ObjErr('{0}: invalid set, {1!r}'.format(self.fullname(), s)))
|
|
for v in s._rv:
|
|
self._safechk_val(v)
|
|
for vr in s._rr:
|
|
if not isinstance(vr, ASN1RangeStr):
|
|
raise(ASN1ObjErr('{0}: invalid _String range, {1!r}'\
|
|
.format(self.fullname(), vr)))
|
|
if s._ev is not None:
|
|
for v in s._ev:
|
|
self._safechk_val(v)
|
|
for vr in s._er:
|
|
if not isinstance(vr, ASN1RangeStr):
|
|
raise(ASN1ObjErr('{0}: invalid _String range, {1!r}'\
|
|
.format(self.fullname(), vr)))
|
|
|
|
def _safechk_bnd(self, val):
|
|
"""
|
|
ensures the value val is within potential constraints defined for self
|
|
"""
|
|
# check val against potential constraints
|
|
if self._const_val and \
|
|
self._const_val.ext is None and \
|
|
val not in self._const_val:
|
|
raise(ASN1ObjErr('{0}: value out of constraint, {1!r}'\
|
|
.format(self.fullname(), val)))
|
|
if self._SAFE_BNDTAB and self._const_tab and self._const_tab_at:
|
|
# check val against a constraint defined within the table constraint
|
|
try:
|
|
const_val = self._get_tab_obj()
|
|
except Exception as err:
|
|
if not self._SILENT:
|
|
asnlog('%s._from_per_ws: %s, unable to retrieve a defined object, %s'\
|
|
% (self.__class__.__name__, self._name, err))
|
|
else:
|
|
if self._mode == MODE_VALUE and val != const_val or \
|
|
self._mode == MODE_SET and val not in const_val:
|
|
raise(ASN1ObjErr('{0}: value out of table constraint, {1!r}'\
|
|
.format(self.fullname(), val)))
|
|
|
|
def _get_tab_obj(self):
|
|
try:
|
|
IndIdent = self._get_obj_by_path(self._const_tab_at)._const_tab_id
|
|
IndVal = self._get_val_by_path(self._const_tab_at)
|
|
except:
|
|
raise(ASN1ObjErr('{0}: invalid table constraint @ path, {1!r}'\
|
|
.format(self.fullname(), self._const_tab_at)))
|
|
try:
|
|
claval = self._const_tab(IndIdent, IndVal)
|
|
except:
|
|
raise(ASN1ObjErr('{0}: invalid identifier {1} for the table constraint'\
|
|
.format(self.fullname(), IndIdent)))
|
|
if claval is None:
|
|
raise(ASN1ObjErr('{0}: non-existent value {1} for identifier {2} in the table constraint'\
|
|
.format(self.fullname(), IndVal, IndIdent)))
|
|
else:
|
|
try:
|
|
return claval[self._const_tab_id]
|
|
except:
|
|
raise(ASN1ObjErr('{0}: non-existent ident {1} within table constraint value'\
|
|
.format(self.fullname(), self._const_tab_id)))
|
|
|
|
#--------------------------------------------------------------------------#
|
|
# user-friendly generic representation
|
|
#--------------------------------------------------------------------------#
|
|
|
|
def fullname(self):
|
|
name = [self._name]
|
|
obj = self
|
|
while obj._parent is not None:
|
|
obj = obj._parent
|
|
name.append(obj._name)
|
|
return '.'.join(reversed(name))
|
|
|
|
def __repr__(self):
|
|
if self._typeref is not None:
|
|
if isinstance(self._typeref, (ASN1RefType, ASN1RefInstOf)):
|
|
try:
|
|
typeref = self._typeref.called[1]
|
|
except AttributeError:
|
|
# .called is ASN1RefParam
|
|
typeref = repr(self._typeref.called)
|
|
elif isinstance(self._typeref, ASN1RefChoiceComp):
|
|
try:
|
|
typeref = '%s<' % self._typeref.called[1] + \
|
|
'<'.join(self._typeref.ced_path)
|
|
except AttributeError:
|
|
# .called is ASN1RefParam
|
|
typeref = '%s<' % repr(self._typeref.called) + \
|
|
'<'.join(self._typeref.ced_path)
|
|
elif isinstance(self._typeref, ASN1RefClassField):
|
|
try:
|
|
typeref = '%s.&' % self._typeref.called[1] + \
|
|
'.&'.join(self._typeref.ced_path)
|
|
except AttributeError:
|
|
# .called is ASN1RefParam
|
|
typeref = '%s.&' % repr(self._typeref.called) + \
|
|
'.&'.join(self._typeref.ced_path)
|
|
elif isinstance(self._typeref, ASN1RefClassIntern):
|
|
typeref = '&%s' % '.&'.join(self._typeref.ced_path)
|
|
elif isinstance(self._typeref, ASN1RefClassValField):
|
|
try:
|
|
typeref = '%s.&%s' % (self._typeref.called[1],
|
|
'.&'.join(self._typeref.ced_path))
|
|
except AttributeError:
|
|
# .called is ASN1RefParam
|
|
typeref = '%s.&%s' % (repr(self._typeref.called),
|
|
'.&'.join(self._typeref.ced_path))
|
|
else:
|
|
assert()
|
|
else:
|
|
typeref = None
|
|
#
|
|
if self._mode == MODE_TYPE:
|
|
if typeref is not None:
|
|
return '<%s ([%s] %s)>' % (self._name,
|
|
typeref,
|
|
self.TYPE)
|
|
else:
|
|
return '<%s (%s)>' % (self._name,
|
|
self.TYPE)
|
|
elif self._mode == MODE_VALUE:
|
|
if self._val is not None:
|
|
val = self._val
|
|
else:
|
|
val = ' '
|
|
if typeref is not None:
|
|
return '<%s ([%s] %s): %s>' % (self._name,
|
|
typeref,
|
|
self.TYPE,
|
|
val)
|
|
else:
|
|
return '<%s (%s): %s>' % (self._name,
|
|
self.TYPE,
|
|
val)
|
|
elif self._mode == MODE_SET:
|
|
if self._val is not None:
|
|
val = repr(self._val)
|
|
else:
|
|
val = ' '
|
|
if typeref is not None:
|
|
return '<%s ([%s] %s): %s>' % (self._name,
|
|
typeref,
|
|
self.TYPE,
|
|
val)
|
|
else:
|
|
return '<%s (%s): %s>' % (self._name,
|
|
self.TYPE,
|
|
val)
|
|
|
|
# TODO: make repr() and show() similar to those from pycrate_core.elt.Envelope
|
|
|
|
#--------------------------------------------------------------------------#
|
|
# internal attributes access method
|
|
#--------------------------------------------------------------------------#
|
|
|
|
def get_internals(self):
|
|
"""
|
|
returns all internal attributes within a dict
|
|
"""
|
|
internals = {
|
|
'name' : self._name,
|
|
'mode' : self._mode,
|
|
'tag' : self._tag,
|
|
'typeref': self._typeref,
|
|
'tr' : self._tr,
|
|
'param' : self._param,
|
|
'parent' : self._parent,
|
|
'opt' : self._opt,
|
|
'def' : self._def,
|
|
'uniq' : self._uniq,
|
|
'group' : self._group,
|
|
'cont' : self._cont,
|
|
'root' : self._root,
|
|
'ext' : self._ext,
|
|
'val' : self._val,
|
|
'const_val': self._const_val,
|
|
'const_tab': self._const_tab
|
|
}
|
|
if hasattr(self, 'cont_tags'):
|
|
internals['cont_tags'] = self._cont_tags
|
|
if hasattr(self, '_root_mand'):
|
|
internals['root_mand'] = self._root_mand
|
|
if hasattr(self, '_root_ext'):
|
|
internals['root_ext'] = self._root_ext
|
|
if hasattr(self, '_ext_group'):
|
|
internals['ext_group'] = self._ext_group
|
|
if hasattr(self, '_ext_group_obj'):
|
|
internals['ext_group_obj'] = self._ext_group_obj
|
|
if hasattr(self, '_ext_ident'):
|
|
internals['ext_ident'] = self._ext_ident
|
|
if hasattr(self, '_const_sz'):
|
|
internals['const_sz'] = self._const_sz
|
|
if hasattr(self, '_const_alpha'):
|
|
internals['const_alpha'] = self._const_alpha
|
|
if hasattr(self, '_const_cont'):
|
|
internals['const_cont'] = self._const_cont
|
|
if hasattr(self, '_const_cont_enc'):
|
|
internals['const_cont_enc'] = self._const_cont_enc
|
|
if hasattr(self, '_const_tab_id'):
|
|
internals['const_tab_id'] = self._const_tab_id
|
|
if hasattr(self, '_const_tab_at'):
|
|
internals['const_tab_at'] = self._const_tab_at
|
|
return internals
|
|
|
|
def get_proto(self):
|
|
"""
|
|
returns the prototype of the object
|
|
"""
|
|
# TODO: in case of recursive object, this will break Python
|
|
# TODO: add information on OPTIONAL / DEFAULT components
|
|
if self.TYPE in TYPES_BASIC + TYPES_EXT:
|
|
return self.TYPE
|
|
elif self.TYPE in (TYPE_SEQ_OF, TYPE_SET_OF):
|
|
return [self._cont.get_proto()]
|
|
elif self.TYPE in (TYPE_CHOICE, TYPE_SEQ, TYPE_SET, TYPE_CLASS):
|
|
return ASN1Dict([(ident, Comp.get_proto()) for (ident, Comp) in self._cont.items()])
|
|
else:
|
|
assert()
|
|
|
|
def get_complexity(self):
|
|
"""
|
|
returns the number of basic types referenced from self,
|
|
and the maximum depth possible within self
|
|
"""
|
|
ref, depth = 0, 0
|
|
if self.TYPE in TYPES_BASIC + TYPES_EXT:
|
|
ref += 1
|
|
elif self.TYPE in (TYPE_SEQ_OF, TYPE_SET_OF):
|
|
comp_ref, comp_depth = self._cont.get_complexity()
|
|
ref += comp_ref
|
|
depth += 1 + comp_depth
|
|
elif self.TYPE in (TYPE_CHOICE, TYPE_SEQ, TYPE_SET, TYPE_CLASS):
|
|
loc_depth = []
|
|
for (ident, Comp) in self._cont.items():
|
|
comp_ref, comp_depth = Comp.get_complexity()
|
|
ref += comp_ref
|
|
loc_depth.append(comp_depth)
|
|
if loc_depth:
|
|
depth += 1 + max(loc_depth)
|
|
else:
|
|
assert()
|
|
return ref, depth
|
|
|
|
def _get_obj_by_path(self, path):
|
|
# this is used for solving table constraint lookups
|
|
obj = self
|
|
for p in path:
|
|
if p == '..':
|
|
obj = obj._parent
|
|
else:
|
|
obj = obj._cont[p]
|
|
return obj
|
|
|
|
def _get_val_by_path(self, path):
|
|
# this is used for solving table constraint lookups
|
|
obj = self
|
|
for p in path:
|
|
if p == '..':
|
|
obj = obj._parent
|
|
else:
|
|
obj = obj._cont[p]
|
|
return obj._val
|
|
|
|
def get_root(self):
|
|
"""
|
|
returns the root object containing self in case self is within a
|
|
constructed or CLASS object
|
|
"""
|
|
# WNG: in case an object from a CLASS has been inserted after a table
|
|
# constraint lookup, the parent will be incorrect
|
|
par = self._parent
|
|
while par is not None:
|
|
par = self._parent
|
|
return par
|
|
|
|
def get_root_chain(self):
|
|
"""
|
|
returns the list of successive objects containing self up to the root one
|
|
in case self is within a constructed or CLASS object
|
|
"""
|
|
# WNG: in case an object from a CLASS has been inserted after a table
|
|
# constraint lookup, the parent will be incorrect
|
|
par = self._parent
|
|
chain = []
|
|
while par is not None:
|
|
chain.append(par)
|
|
par = par._parent
|
|
return chain
|
|
|
|
def in_class(self):
|
|
"""
|
|
returns True in case self is a field of a CLASS, False otherwise
|
|
"""
|
|
par = self._parent
|
|
while par is not None:
|
|
if par.TYPE == TYPE_CLASS:
|
|
return True
|
|
else:
|
|
par = par._parent
|
|
return False
|
|
|
|
#--------------------------------------------------------------------------#
|
|
# internal value access methods
|
|
#--------------------------------------------------------------------------#
|
|
|
|
def __call__(self):
|
|
return self._val
|
|
|
|
def get_val(self):
|
|
return self._val
|
|
|
|
def set_val(self, val):
|
|
self._val = val
|
|
if self._SAFE_VAL:
|
|
self._safechk_val(self._val)
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
def set_val_unsafe(self, val):
|
|
self._val = val
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
#--------------------------------------------------------------------------#
|
|
# encoding / decoding methods
|
|
#--------------------------------------------------------------------------#
|
|
|
|
###
|
|
# conversion between internal value and ASN.1 syntax
|
|
###
|
|
|
|
def _from_asn1(self, txt):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
def _to_asn1(self):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
def from_asn1(self, txt):
|
|
txt = clean_text(txt)
|
|
ret = self._from_asn1(txt)
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
return ret
|
|
|
|
def to_asn1(self, val=None):
|
|
if val is not None:
|
|
self.set_val(val)
|
|
if self._val is not None:
|
|
return self._to_asn1()
|
|
else:
|
|
return None
|
|
|
|
def show(self):
|
|
return '<~ASN1~: %s>' % self.to_asn1()
|
|
|
|
###
|
|
# conversion between internal value and ASN.1 PER encoding
|
|
###
|
|
|
|
def _from_per(self, char):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
def _to_per(self):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
def from_uper(self, buf):
|
|
ASN1CodecPER.ALIGNED = False
|
|
if isinstance(buf, bytes_types):
|
|
char = Charpy(buf)
|
|
else:
|
|
char = buf
|
|
#assert( char.len_bit() % 8 == 0 )
|
|
off0 = char._cur
|
|
self._from_per(char)
|
|
off1 = char._cur
|
|
if off1 == off0:
|
|
# char was not consumed at all (all decoded values were implicit)
|
|
# hence a null byte must be consumed for outer decoding
|
|
null = char.get_bytes(8)
|
|
assert( null == b'\0' )
|
|
elif (off1 - off0) % 8:
|
|
# realignement required for outer decoding
|
|
char.forward(8 - ((off1 - off0)%8))
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
def to_uper(self, val=None):
|
|
ASN1CodecPER.ALIGNED = False
|
|
if val is not None:
|
|
self.set_val(val)
|
|
if self._val is not None:
|
|
ret = pack_val(*self._to_per())[0]
|
|
if ret:
|
|
return ret
|
|
else:
|
|
return b'\0'
|
|
else:
|
|
return None
|
|
|
|
def from_aper(self, buf):
|
|
ASN1CodecPER.ALIGNED = True
|
|
ASN1CodecPER._off.append(0)
|
|
if isinstance(buf, bytes_types):
|
|
char = Charpy(buf)
|
|
else:
|
|
char = buf
|
|
assert( char.len_bit() % 8 == 0 )
|
|
self._from_per(char)
|
|
if ASN1CodecPER._off[-1] == 0:
|
|
# char was not consumed at all (all decoded values were implicit)
|
|
# hence a null byte must be consumed
|
|
null = char.get_bytes(8)
|
|
assert( null == b'\0' )
|
|
elif ASN1CodecPER._off[-1] % 8:
|
|
# realignement required for outer decoding
|
|
char.forward(8 - (ASN1CodecPER._off[-1]%8))
|
|
del ASN1CodecPER._off[-1]
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
def to_aper(self, val=None):
|
|
ASN1CodecPER.ALIGNED = True
|
|
if val is not None:
|
|
self.set_val(val)
|
|
if self._val is not None:
|
|
ASN1CodecPER._off.append(0)
|
|
ret = pack_val(*self._to_per())[0]
|
|
if not ret:
|
|
ret = b'\0'
|
|
del ASN1CodecPER._off[-1]
|
|
return ret
|
|
else:
|
|
return None
|
|
|
|
# methods generating complete transfer structure in _struct attributes
|
|
|
|
def _from_per_ws(self, char):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
def _to_per_ws(self):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
def from_uper_ws(self, buf):
|
|
ASN1CodecPER.ALIGNED = False
|
|
if isinstance(buf, bytes_types):
|
|
char = Charpy(buf)
|
|
else:
|
|
char = buf
|
|
#assert( char.len_bit() % 8 == 0 )
|
|
off0 = char._cur
|
|
self._from_per_ws(char)
|
|
off1 = char._cur
|
|
pad = None
|
|
if off1 == off0:
|
|
# char was not consumed at all (all decoded values were implicit)
|
|
# hence a null byte must be consumed
|
|
pad = Uint('P', val=0, bl=8, rep=REPR_BIN)
|
|
pad._from_char(char)
|
|
self._struct.append(pad)
|
|
assert( pad() == 0 )
|
|
elif (off1 - off0) % 8:
|
|
# realignment required for outer decoding
|
|
pad = Uint('P', val=0, bl=(8-((off1 - off0)%8)), rep=REPR_BIN)
|
|
pad._from_char(char)
|
|
self._struct.append(pad)
|
|
assert( pad() == 0 )
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
def to_uper_ws(self, val=None):
|
|
ASN1CodecPER.ALIGNED = False
|
|
if val is not None:
|
|
self.set_val(val)
|
|
if self._val is not None:
|
|
_struct = self._to_per_ws()
|
|
bl = _struct.get_bl()
|
|
if bl == 0:
|
|
_struct.append( Uint('P', val=0, bl=8, rep=REPR_BIN) )
|
|
elif bl % 8:
|
|
_struct.append( Uint('P', val=0, bl=(8-(bl%8)), rep=REPR_BIN) )
|
|
return _struct.to_bytes()
|
|
else:
|
|
return None
|
|
|
|
def from_aper_ws(self, buf):
|
|
ASN1CodecPER.ALIGNED = True
|
|
ASN1CodecPER._off.append(0)
|
|
if isinstance(buf, bytes_types):
|
|
char = Charpy(buf)
|
|
else:
|
|
char = buf
|
|
assert( char.len_bit() % 8 == 0 )
|
|
self._from_per_ws(char)
|
|
if ASN1CodecPER._off[-1] == 0:
|
|
# char was not consumed at all (all decoded values were implicit)
|
|
# hence a null byte must be consumed
|
|
pad = Uint('P', val=0, bl=8, rep=REPR_BIN)
|
|
pad._from_char(char)
|
|
self._struct.append(pad)
|
|
assert( pad() == 0 )
|
|
elif ASN1CodecPER._off[-1] % 8:
|
|
# realignement required for outer decoding
|
|
pad = Uint('P', val=0, bl=(8 - (ASN1CodecPER._off[-1]%8)), rep=REPR_BIN)
|
|
pad._from_char(char)
|
|
self._struct.append(pad)
|
|
assert( pad() == 0 )
|
|
del ASN1CodecPER._off[-1]
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
def to_aper_ws(self, val=None):
|
|
ASN1CodecPER.ALIGNED = True
|
|
if val is not None:
|
|
self.set_val(val)
|
|
if self._val is not None:
|
|
ASN1CodecPER._off.append(0)
|
|
_struct = self._to_per_ws()
|
|
if ASN1CodecPER._off[-1] == 0:
|
|
_struct.append( Uint('P', val=0, bl=8, rep=REPR_BIN) )
|
|
elif ASN1CodecPER._off[-1] % 8:
|
|
_struct.append( Uint('P', val=0, bl=(8-(ASN1CodecPER._off[-1]%8)), rep=REPR_BIN) )
|
|
del ASN1CodecPER._off[-1]
|
|
return _struct.to_bytes()
|
|
else:
|
|
return None
|
|
|
|
###
|
|
# conversion between internal value and ASN.1 BER encoding
|
|
###
|
|
|
|
def _from_ber(self, char, TLV):
|
|
# 1) decode the tag chain
|
|
tlv, pc = TLV, 1
|
|
for t in self._tagc:
|
|
tlv = tlv[0]
|
|
cl, pc, tval, lval = tlv[0:4]
|
|
if (cl, tval) != t or (t != self._tagc[-1] and pc == 0):
|
|
raise(ASN1BERDecodeErr('{0}: invalid tag class / pc / value, {1!r}'\
|
|
.format(self.fullname(), (cl, pc, tval))))
|
|
tlv = tlv[4]
|
|
if pc == 0:
|
|
# 2a) decode primitive content value
|
|
# here, tlv is actually a 2-tuple with the value boundaries
|
|
assert( isinstance(tlv, tuple) )
|
|
else:
|
|
# 2b) decode constructed content
|
|
assert( isinstance(tlv, list) )
|
|
self._decode_ber_cont(char, tlv)
|
|
|
|
def from_ber(self, buf, single=True):
|
|
if isinstance(buf, bytes_types):
|
|
char = Charpy(buf)
|
|
else:
|
|
char = buf
|
|
# decode the whole char buffer into tag, length and value boundary
|
|
if single:
|
|
TLV = [ASN1CodecBER.decode_single(char)[0]]
|
|
else:
|
|
TLV = ASN1CodecBER.decode_all(char)
|
|
char_cur, char_lb = char._cur, char._len_bit
|
|
# decode all value content
|
|
self._from_ber(char, TLV)
|
|
char._cur, char._len_bit = char_cur, char_lb
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
def _to_ber(self):
|
|
# 1) encode the most inner TLV part
|
|
pc, lval, V = self._encode_ber_cont()
|
|
if not self._tagc:
|
|
# in case no tag is associated to the object (CHOICE, OPEN / ANY)
|
|
# we only have the inner encoding
|
|
return V
|
|
TLV = ASN1CodecBER.encode_tag(self._tagc[-1][0], pc, self._tagc[-1][1])
|
|
TLV.extend( ASN1CodecBER.encode_len(lval) )
|
|
TLV.extend( V )
|
|
if lval == -1:
|
|
TLV.append( (T_BYTES, b'\0\0', 16) )
|
|
# 2) encode the outer part of the object, i.e. the rest of the tag chain
|
|
if len(self._tagc) > 1:
|
|
GEN = [TLV]
|
|
if ASN1CodecBER.ENC_LUNDEF:
|
|
for t in reversed(self._tagc[:-1]):
|
|
TL = ASN1CodecBER.encode_tag(t[0], 1, t[1])
|
|
TL.extend( ASN1CodecBER.encode_len(-1) )
|
|
# append an EOC marker after the value
|
|
TLV.append( (T_BYTES, b'\0\0', 16) )
|
|
GEN.append(TL)
|
|
else:
|
|
lval = sum([f[2] for f in TLV]) >> 3
|
|
for t in reversed(self._tagc[:-1]):
|
|
TL = ASN1CodecBER.encode_tag(t[0], 1, t[1])
|
|
TL.extend( ASN1CodecBER.encode_len(lval) )
|
|
lval += sum([f[2] for f in TL]) >> 3
|
|
GEN.append(TL)
|
|
# revert and flatten GEN
|
|
return [i for j in reversed(GEN) for i in j]
|
|
else:
|
|
return TLV
|
|
|
|
def to_ber(self, val=None):
|
|
if val is not None:
|
|
self.set_val(val)
|
|
if self._val is not None:
|
|
return pack_val(*self._to_ber())[0]
|
|
else:
|
|
return None
|
|
|
|
# methods generating complete transfer structure in _struct attributes
|
|
|
|
def _from_ber_ws(self, char, TLV):
|
|
# 1) decode the tag chain
|
|
tlv, TL, pc = TLV, [], 1
|
|
for t in self._tagc:
|
|
tlv = tlv[0]
|
|
Tag, cl, pc, tval, Len, lval = tlv[0:6]
|
|
if (cl, tval) != t or (t != self._tagc[-1] and pc == 0):
|
|
raise(ASN1BERDecodeErr('{0}: invalid tag class / pc / value, {1!r}'\
|
|
.format(self.fullname(), (cl, pc, tval))))
|
|
# select the value as a new inner tlv
|
|
tlv = tlv[6]
|
|
if lval == -1:
|
|
# keep track of the End-Of-Content marker
|
|
TL.append( (Tag, Len, tlv[-1][0], tlv[-1][4]) )
|
|
else:
|
|
TL.append( (Tag, Len) )
|
|
#
|
|
if pc == 0:
|
|
# 2a) decode primitive content value
|
|
# here, tlv is actually a 2-tuple with the value boundaries
|
|
assert( isinstance(tlv, tuple) )
|
|
else:
|
|
# 2b) decode constructed content
|
|
assert( isinstance(tlv, list) )
|
|
V = self._decode_ber_cont_ws(char, tlv)
|
|
#
|
|
# 3) generate the complete TLV structure
|
|
if TL:
|
|
TL.reverse()
|
|
for tl in TL:
|
|
if len(tl) == 4:
|
|
# EOC marker
|
|
TLV = Envelope('TLV', GEN=(tl[0], tl[1], V, tl[2], tl[3]))
|
|
else:
|
|
TLV = Envelope('TLV', GEN=(tl[0], tl[1], V))
|
|
V = TLV
|
|
V._name = 'V'
|
|
else:
|
|
# in case no tag is associated to the object (CHOICE, OPEN / ANY)
|
|
# we only have the inner encoding
|
|
TLV = V
|
|
# set object name and final struct
|
|
TLV._name = self._name
|
|
self._struct = TLV
|
|
|
|
def from_ber_ws(self, buf, single=True):
|
|
if isinstance(buf, bytes_types):
|
|
char = Charpy(buf)
|
|
else:
|
|
char = buf
|
|
# decode the whole char buffer into tag, length and value boundary
|
|
if single:
|
|
TLV = [ASN1CodecBER.decode_single_ws(char)[0]]
|
|
else:
|
|
TLV = ASN1CodecBER.decode_all_ws(char)
|
|
char_cur, char_lb = char._cur, char._len_bit
|
|
# decode all value content
|
|
self._from_ber_ws(char, TLV)
|
|
char._cur, char._len_bit = char_cur, char_lb
|
|
if self._SAFE_BND:
|
|
self._safechk_bnd(self._val)
|
|
|
|
def _to_ber_ws(self):
|
|
# 1) encode the most inner TLV part
|
|
pc, lval, V = self._encode_ber_cont_ws()
|
|
if not self._tagc:
|
|
# in case no tag is associated to the object (CHOICE, OPEN / ANY)
|
|
# we only have the inner encoding
|
|
TLV = V
|
|
else:
|
|
if pc == 1 and ASN1CodecBER.ENC_LUNDEF:
|
|
TLV = Envelope('TLV', GEN=(
|
|
ASN1CodecBER.encode_tag_ws(self._tagc[-1][0], pc, self._tagc[-1][1]),
|
|
ASN1CodecBER.encode_len_ws(-1),
|
|
V,
|
|
ASN1CodecBER.encode_tag_ws(0, 0, 0),
|
|
ASN1CodecBER.encode_len_ws(0)))
|
|
else:
|
|
TLV = Envelope('TLV', GEN=(
|
|
ASN1CodecBER.encode_tag_ws(self._tagc[-1][0], pc, self._tagc[-1][1]),
|
|
ASN1CodecBER.encode_len_ws(lval),
|
|
V))
|
|
# 2) encode the outer part of the object, i.e. the rest of the tag chain
|
|
if len(self._tagc) > 1:
|
|
if ASN1CodecBER.ENC_LUNDEF:
|
|
for t in reversed(self._tagc[:-1]):
|
|
TLV._name = 'V'
|
|
TLV = Envelope('TLV', GEN=(ASN1CodecBER.encode_tag_ws(t[0], 1, t[1]),
|
|
ASN1CodecBER.encode_len_ws(-1),
|
|
TLV,
|
|
ASN1CodecBER.encode_tag_ws(0, 0, 0),
|
|
ASN1CodecBER.encode_len_ws(0)))
|
|
else:
|
|
lval += (TLV[0].get_bl() + TLV[1].get_bl()) >> 3
|
|
for t in reversed(self._tagc[:-1]):
|
|
TLV._name = 'V'
|
|
TLV = Envelope('TLV', GEN=(ASN1CodecBER.encode_tag_ws(t[0], 1, t[1]),
|
|
ASN1CodecBER.encode_len_ws(lval),
|
|
TLV))
|
|
lval += (TLV[0].get_bl() + TLV[1].get_bl()) >> 3
|
|
# set object name and final struct
|
|
TLV._name = self._name
|
|
self._struct = TLV
|
|
return TLV
|
|
|
|
def to_ber_ws(self, val=None):
|
|
if val is not None:
|
|
self.set_val(val)
|
|
if self._val is not None:
|
|
return self._to_ber_ws().to_bytes()
|
|
else:
|
|
return None
|
|
|
|
###
|
|
# conversion between internal value and ASN.1 CER encoding
|
|
# reusing the BER encoder
|
|
###
|
|
|
|
def from_cer(self, buf):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = True
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.from_ber(buf)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
def to_cer(self, val=None):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = True
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.to_ber(val)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
# methods generating complete transfer structure in _struct attributes
|
|
|
|
def from_cer_ws(self, buf):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = True
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.from_ber_ws(buf)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
def to_cer_ws(self, val=None):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = True
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 1000
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.to_ber_ws(val)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
###
|
|
# conversion between internal value and ASN.1 DER encoding
|
|
# reusing the BER encoder
|
|
###
|
|
|
|
def from_der(self, buf):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = False
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.from_ber(buf)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
def to_der(self, val=None):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = False
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.to_ber(val)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
# methods generating complete transfer structure in _struct attributes
|
|
|
|
def from_der_ws(self, buf):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = False
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.from_ber_ws(buf)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
def to_der_ws(self, val=None):
|
|
_save_ber_params()
|
|
ASN1CodecBER.ENC_LLONG = 0
|
|
ASN1CodecBER.ENC_LUNDEF = False
|
|
ASN1CodecBER.ENC_BOOLTRUE = 0xff
|
|
ASN1CodecBER.ENC_REALNR = 3
|
|
ASN1CodecBER.ENC_BSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_OSTR_FRAG = 0
|
|
ASN1CodecBER.ENC_TIME_CANON = True
|
|
ASN1CodecBER.ENC_DEF_CANON = True
|
|
ret = self.to_ber_ws(val)
|
|
_restore_ber_params()
|
|
return ret
|
|
|
|
###
|
|
# convert internal value to ASN.1 GSER encoding
|
|
###
|
|
# TODO
|
|
|
|
def from_gser(self, char):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
def to_gser(self, buf, val=None):
|
|
raise(ASN1NotSuppErr(self.fullname()))
|
|
|
|
|
|
|
|
def _save_ber_params():
|
|
global __ber_enc_llong
|
|
global __ber_enc_lundef
|
|
global __ber_enc_booltrue
|
|
global __ber_enc_realnr
|
|
global __ber_enc_bstr_frag
|
|
global __ber_enc_ostr_frag
|
|
global __ber_enc_time_canon
|
|
global __ber_enc_def_canon
|
|
__ber_enc_llong = ASN1CodecBER.ENC_LLONG
|
|
__ber_enc_lundef = ASN1CodecBER.ENC_LUNDEF
|
|
__ber_enc_booltrue = ASN1CodecBER.ENC_BOOLTRUE
|
|
__ber_enc_realnr = ASN1CodecBER.ENC_REALNR
|
|
__ber_enc_bstr_frag = ASN1CodecBER.ENC_BSTR_FRAG
|
|
__ber_enc_ostr_frag = ASN1CodecBER.ENC_OSTR_FRAG
|
|
__ber_enc_time_canon = ASN1CodecBER.ENC_TIME_CANON
|
|
__ber_enc_def_canon = ASN1CodecBER.ENC_DEF_CANON
|
|
|
|
def _restore_ber_params():
|
|
global __ber_enc_llong
|
|
global __ber_enc_lundef
|
|
global __ber_enc_booltrue
|
|
global __ber_enc_realnr
|
|
global __ber_enc_bstr_frag
|
|
global __ber_enc_ostr_frag
|
|
global __ber_enc_time_canon
|
|
global __ber_enc_def_canon
|
|
ASN1CodecBER.ENC_LLONG = __ber_enc_llong
|
|
ASN1CodecBER.ENC_LUNDEF = __ber_enc_lundef
|
|
ASN1CodecBER.ENC_BOOLTRUE = __ber_enc_booltrue
|
|
ASN1CodecBER.ENC_REALNR = __ber_enc_realnr
|
|
ASN1CodecBER.ENC_BSTR_FRAG = __ber_enc_bstr_frag
|
|
ASN1CodecBER.ENC_OSTR_FRAG = __ber_enc_ostr_frag
|
|
ASN1CodecBER.ENC_TIME_CANON = __ber_enc_time_canon
|
|
ASN1CodecBER.ENC_DEF_CANON = __ber_enc_def_canon
|
|
|