1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 from common import BERException, inflate_long, deflate_long
26 from common import UNIVERSAL, APPLICATION, CONTEXT, PRIVATE
27
28
29 _class_name = { UNIVERSAL: 'UNIVERSAL', APPLICATION: 'APPLICATION',
30 CONTEXT: 'CONTEXT', PRIVATE: 'PRIVATE' }
31
32
34 """
35 Representation of the header of an ASN.1 object. This includes the
36 class (universal, application, context, or private), the type tag (any
37 integer), and size.
38 """
39
40 - def __init__(self, tag_class=0, tag=UNIVERSAL, size=None, container=False, _bytes_read=0):
41 self._tag_class = tag_class
42 self._tag = tag
43 self._size = size
44 self._container = container
45 self._bytes_read = _bytes_read
46
48 return '<ASN.1 Tag(%s, %d, size=%r, container=%r)>' % (_class_name[self._tag_class], self._tag,
49 self._size, self._container)
50
52 if not isinstance(other, Tag):
53 raise ValueError('not comparable with %r', other)
54 x = cmp(self._tag_class, other._tag_class)
55 if x != 0:
56 return x
57 x = cmp(self._container, other._container)
58 if x != 0:
59 return x
60 return cmp(self._tag, other._tag)
61
63 n = self._tag_class
64 n *= 37
65 if self._container:
66 n += 1
67 n *= 37
68 n += self._tag
69 return n
70
71 tag_class = property(lambda self: self._tag_class, None, None)
72 tag = property(lambda self: self._tag, None, None)
73 size = property(lambda self: self._size, None, None)
74 container = property(lambda self: self._container, None, None)
75
77 """
78 Return C{True} if this tag is the special type used to terminate
79 indefinite-length sequences (type 0, length 0).
80 """
81 return (self._tag_class == UNIVERSAL) and not self._container and (self._tag == 0) and \
82 self._size == 0
83
84 @staticmethod
86 """
87 Return a tag that can be used to terminate indefinite-length sequences.
88 """
89 return Tag(Tag.UNIVERSAL, False, 0, 0)
90
91 @staticmethod
93 return Tag(t._tag_class, t._tag, size, t._container)
94
95 @staticmethod
139
141 if self._bytes_read > 0:
142 return self._bytes_read
143 n = 2
144 if self.tag > 30:
145 t = self.tag
146 while t > 0:
147 n += 1
148 t >>= 7
149 if self.size > 0x7f:
150 n += len(deflate_long(self.size))
151 return n
152
154 high_bits = (self._tag_class << 6)
155 if self._container:
156 high_bits |= 0x20
157 if self._tag <= 30:
158 fd.write(chr(self._tag | high_bits))
159 elif self._tag <= 127:
160 fd.write(chr(high_bits | 0x1f))
161 fd.write(chr(self._tag))
162 else:
163 fd.write(chr(high_bits | 0x1f))
164 tag = self._tag
165 tagstr = chr(tag & 0x7f)
166 tag >>= 7
167 while tag > 0:
168 tagstr = chr(0x80 | (tag & 0x7f)) + tagstr
169 tag >>= 7
170 fd.write(tagstr)
171
172 if self._size is None:
173 fd.write(chr(0x80))
174 elif self._size > 0x7f:
175 lenstr = deflate_long(self._size)
176 fd.write(chr(0x80 | len(lenstr)))
177 fd.write(lenstr)
178 else:
179 fd.write(chr(self._size))
180