From VisualWorks®, 7.5 of April 3, 2007 on April 3, 2007 at 1:28:40 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>TLVStream</name> <environment>ASN1</environment> <super>Core.Stream</super> <private>false</private> none stream tagDispatchTable <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.TLVStream
TLVStream is an abstract class. It is the superclass of the marshaling streams for messages employing ASN.1 encoding rules. The implementation tacitly presupposes that lengths will never be in BER indefinite form, and is otherwise slanted toward BER and DER. A radically different encoding, like PER, might motivate a more abstract superclass. Instance Variables: stream <PositionableStream> underlying byte stream that we read/write Class Instance Variables: tagDispatchTable <Array | UndefinedObject> tag dispatch table for decoding
</comment> <class> <name>BERStreamBasic</name> <environment>ASN1</environment> <super>ASN1.TLVStream</super> <private>false</private> none encodingPolicy inImplicitTag utcSliding utcRoundMilliseconds shortTime timezone defaultEncodingPolicy defaultUTCSliding defaultUTCRoundMilliseconds defaultShortTime defaultTimezone <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.BERStreamBasic
This class is a BER encoding/decoding stream that assumes (1) that lengths will be stored in three bytes and (2) that tags will be one byte. It is expected to be a suitable superclass for an SNMP encoder/decoder. It also adds machinery for the retention and use of encodings during type-in-hand encoding and decoding. Note that said machinery is not invoked in type-agnostic marshaling. Instance Variables: encodingPolicy <EncodingPolicy> controls the stream behavior with regards to objec encodings; retention, logging, etc. inImplicitTag <Boolean> private flag, indicates if we are in the process of encoding an implicit tag utcSliding <Boolean> are the 2 digit years interpreted in a "sliding window" manner or fixed to 1950-2049 utcRoundMilliseconds <Boolean> should the timestamp milliseconds be rounded or turncated for UTCTime shortTime <Boolean> should encode timestamps omitting superfluous zero minutes/seconds if permitted timezone <TimeZone> the timezone to use for Timestamp conversions Class Instance Variables: defaultEncodingPolicy <Behavior> the default policy for streams of given class defaultUTCSliding <Boolean> are the 2 digit years interpreted in a "sliding window" manner or fixed to 1950-2049 defaultUTCRoundMilliseconds <Boolean> should the timestamp milliseconds be rounded or turncated for UTCTime defaultShortTime <Boolean> should encode timestamps omitting superfluous zero minutes/seconds if permitted defaultTimezone <TimeZone> the timezone to use for Timestamp conversions
</comment> <class> <name>BERStreamDefinite</name> <environment>ASN1</environment> <super>ASN1.BERStreamBasic</super> <private>false</private> none scratchBuffer utf8 ucs2 <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.BERStreamDefinite
This class is a BER encoding/decoding stream that assumes (1) that lengths are 'definitely' encoded in one or more bytes and (2) that tags may be more than one byte. It is intended to be a suitable superclass for a DER encoder/decoder. Instance Variables: scratchBuffer <PositionableStream> used to encode lengths utf8 <StreamEncoder> caches an encoder for UTF8, used for UTF8Strings ucs2 <StreamEncoder> caches and encoder of UCS-2, used for BMPStrings
</comment> <class> <name>EncodingPolicy</name> <environment>ASN1</environment> <super>Core.Object</super> <private>false</private> none marshaler <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.EncodingPolicy
This is the abstract superclass for all encoding policies. It enumerates all the interception points where the policies have a chance to act. Its instance can also be used as a dummy policy that takes no actions at all. Instance Variables: marshaler <Asn1Stream>
</comment> <class> <name>RetainEncodings</name> <environment>ASN1</environment> <super>ASN1.EncodingPolicy</super> <private>false</private> none currentEncoding encodingStack source <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.RetainEncodings
This encoding policy implements retention and use of encodings in type-specific manner. It is activated by sending an Asn1Type the message 'retainEncoding: true'. The retention of encodings is important is some security applications, where, for example, the encoding of a certificate should be stored, and never programatically regenerated. Retention is also a useful optimization for frequently transmitted objects. Note that the encodings of Asn1OIDs are always retained, and that Asn1OIDs are not affected by the machinery implemented in this class, which is intended for user-defined types employed in standard, uncustomized marshalers. Instance Variables: currentEncoding <Asn1Encoding> the current encoding encodingStack <OrderedCollection> a stack for managing encodings source <Collection> a copy of the entire source encoding
</comment> <class> <name>RetainAllEncodings</name> <environment>ASN1</environment> <super>ASN1.RetainEncodings</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.RetainAllEncodings
This policy retains all encodings regardless of the 'retainEncoding' setting of specific types.
</comment> <class> <name>PrettyPrinter</name> <environment>ASN1</environment> <super>ASN1.RetainEncodings</super> <private>false</private> none stream indent offsets <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.PrettyPrinter
This policy pretty-prints the decoded entities onto the 'stream' as it unmarshals them. Instance Variables: stream <WriteStream> the stream to print to indent <Integer> current indentation level offsets <Boolean> should print offsets of entities
</comment> <class> <name>MarshalingError</name> <environment>ASN1</environment> <super>ASN1.Asn1Error</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.MarshalingError
An Asn1ExcMarshaling is raised when a marshaling error is detected during encoding or decoding.
</comment> <class> <name>UTCTimeRange</name> <environment>ASN1</environment> <super>ASN1.MarshalingError</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.UTCTimeRange
This error is raised on attempt to marshal a Timestamp outside of the current UTCTime range.
</comment> <class> <name>TagUnknown</name> <environment>ASN1</environment> <super>ASN1.MarshalingError</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.TagUnknown
An Asn1ExcUnknownTag is raised when an unknown type tag is encountered.
</comment> <class> <name>TagMismatch</name> <environment>ASN1</environment> <super>ASN1.MarshalingError</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.TagMismatch
This error is raised when a tag encountered during decoding doesn't match the expected tag.
</comment> <class> <name>DERStream</name> <environment>ASN1</environment> <super>ASN1.BERStreamDefinite</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1</package> </attributes> </class> <comment> ASN1.DERStream
Asn1StreamDER is an encoder/decoder for DER encoding.
</comment> <methods> ASN1.TLVStream <category>decoding - utility</category>
peekTag | start | start := self position. ^[ self nextTag ] ensure: [ self position: start ]
raiseUnknownTagException TagUnknown raiseRequestErrorString: (#UnknownTag << #asn1 >> 'Unknown tag!')
tagDispatchWith: anInteger "... to be re-rigged with a proceedable exception." ^[ self class tagDispatchTable at: anInteger ] on: SubscriptOutOfBoundsError do: [ :ex | self raiseUnknownTagException ]
</methods> <methods> ASN1.TLVStream <category>decoding - api</category>
decodeTLV "... a recursive entry point, not to be invoked without 'local knowledge'." ^( self tagDispatchWith: self nextTag ) value: self nextLength value: self
nextLength "... the method to be directly invoked in decoding APIs. The implementation may vary depending on the length encoding in use." self subclassResponsibility
nextTag "... the method to be directly invoked in decoding APIs. The implementation may vary depending on the tag encoding in use." ^self subclassResponsibility
unmarshalObject "... the default, top-level, decoding entry point, for type-agnostic decoding." ^[ self decodeTLV ] on: Error do: [ :ex | MarshalingError raiseSignal: ex errorString ]
unmarshalObjectType: anAsn1Type "... the default, top-level, entry point for type-in-hand decoding. Sets up for encoding retention. Note that since, at this point, we do not know how much of the 'collection' is taken up by the encoding, the entire 'collection; is retained as the 'source'." ^[ anAsn1Type decodeWith: self ] on: Error do: [ :ex | MarshalingError raiseSignal: ex errorString ]
</methods> <methods> ASN1.TLVStream <category>testing</category>
canRetainEncodingWhileMarshaling ^true
requiresEncodingSort self subclassResponsibility
requiresTagSort self subclassResponsibility
</methods> <methods> ASN1.TLVStream <category>decoding - private</category>
decodeTaglessWith: aType self subclassResponsibility
decodeWith: aType self subclassResponsibility
decodeWith: aType explicitTag: aTag self subclassResponsibility
decodeWith: aType implicitTag: aTag self subclassResponsibility
</methods> <methods> ASN1.TLVStream <category>encoding - api</category>
encodeTLV: anObject "... a recursive entry point, not to be invoked without 'local knowledge'." self subclassResponsibility
marshalObject: anObject "... the top-level entry point for type-agnostic encoding." [ self encodeTLV: anObject ] on: Error do: [ :ex | MarshalingError raiseSignal: ex errorString ]
marshalObject: anObject withType: anAsn1Type "... the top-level entry point for type-in-hand encoding." [ anAsn1Type encode: anObject with: self ] on: Error do: [ :ex | MarshalingError raiseSignal: ex errorString ]
</methods> <methods> ASN1.TLVStream <category>encoding - private</category>
encode: anObject with: aType self subclassResponsibility
encode: anObject with: aType explicitTag: anInteger self subclassResponsibility
encode: anObject with: aType implicitTag: anInteger self subclassResponsibility
</methods> <methods> ASN1.TLVStream <category>initialize-release</category>
wrap: aStream stream := aStream
</methods> <methods> ASN1.TLVStream <category>private</category>
collection "used by RetainEncodings policy" ^stream collection
position ^stream position
position: anInteger ^stream position: anInteger
</methods> <methods> ASN1.TLVStream <category>accessing - stream</category>
atEnd ^stream atEnd
contents ^stream contents
next ^stream next
nextPut: aByte ^stream nextPut: aByte
reset stream reset
</methods> <methods> ASN1.TLVStream class <category>class initialization</category>
initialize "((( self initialize )))" self initializeTagDispatchTable.
initializeTagDispatchTable "Initialize the tag table used for unmarshaling or decoding." self tagDispatchTable: nil.
</methods> <methods> ASN1.TLVStream class <category>accessing</category>
tagDispatchTable ^tagDispatchTable
tagDispatchTable: anObject tagDispatchTable := anObject
</methods> <methods> ASN1.TLVStream class <category>instance creation</category>
on: aCollection ^self wrap: (ReadWriteStream on: aCollection)
with: aCollection ^self wrap: (ReadWriteStream with: aCollection)
wrap: aStream ^self basicNew wrap: aStream
</methods> <methods> ASN1.BERStreamBasic <category>decoding - tagged types</category>
decodeBOOLEAN: anInteger ^( self next == 0 ) not
decodeENUMERATED: anInteger "We elect to decode as an INTEGER unless we have a type in hand." ^self decodeINTEGER: anInteger "^Asn1ImportedEnumeration type: Asn1TypeENUMERATED default value: ( self decodeINTEGER: anInteger )"
decodeINTEGER: anInteger "Pick off the first octet. Test for a negative. Pick off the remaining octets. Finish off if negative." | oct val negative m | val := 0. oct := self next. negative := oct allMask: 2r10000000. val := oct. ( anInteger - 1 ) timesRepeat: [ oct := self next. val := ( val bitShift: 8 ) + oct ]. ( negative ) ifTrue: [ val := val - 2r00000001. m := ( 2 raisedTo: ( 8 * val digitLength ) ) - 1. val := val bitXor: m. val := val negated. ]. ^val
decodeNULL: anInteger ^nil
decodeOBJECT_IDENTIFIER: anInteger "Record the starting position, so that the encoding may be cached if necessary. Estimate the size assuming that two OID elements are encoded in the first byte and that all subsequent OID elements consume only one byte. Then read. (The first two branch identifiers are packed into the first octet. Some of the decoding logic is repetative, but I'd rather inline.) Trim the array if necessary when done. Preserve object identity. Then, always cache the encoding if we do not already have it." | ipos estimatedSize reads size array val id oct oid tpos enc | ipos := self position. estimatedSize := anInteger + 1. reads := 0. size := 0. array := Array new: estimatedSize. val := 0. [ reads := reads + 1. ( oct := self next ) > 127 ] whileTrue: [ val := ( val bitShift: 7 ) + ( oct bitAnd: 02r1111111 ) ]. val := ( val bitShift: 7 ) + oct. size := size + 1. array at: size put: val // 40. ( ( id := val rem: 40 ) ~~ 0 ) ifTrue: [ size := size + 1. array at: size put: id ]. [ anInteger > reads ] whileTrue: [ val := 0. [ reads := reads + 1. ( oct := self next ) > 127 ] whileTrue: [ val := ( val bitShift: 7 ) + ( oct bitAnd: 02r1111111 ) ]. val := ( val bitShift: 7 ) + oct. size := size + 1. array at: size put: val ]. array := self trimCollection: array ofSize: estimatedSize toSize: size. oid := ObjectIdentifier value: array. "--- creation method preserves object identity ---" ( oid encoding isNil ) ifTrue: [ tpos := self position. self position: ipos. enc := self next: ( tpos - ipos ) into: ( ByteArray new: ( tpos - ipos ) ) startingAt: 1. oid encoding: enc. self position: tpos ]. ^oid
decodeOCTET_STRING: anInteger | ba | ba := ByteArray new: anInteger. 1 to: anInteger do: [ :x | ba at: x put: self next ]. ^ba
decodeSEQUENCEorSEQUENCE_OF: anInteger "Note that we use a higher than usual default estimate for the size of the OrderedCollection." | col tpos | col := OrderedCollection new: 11. tpos := self position + anInteger. [ self position < tpos ] whileTrue: [ col add: self decodeTLV ]. ^col
decodeSETorSET_OF: anInteger "Note that we use a higher than usual default estimate for the size of the OrderedCollection." | col tpos | col := OrderedCollection new: 11. tpos := self position + anInteger. [ self position < tpos ] whileTrue: [ col add: self decodeTLV ]. ^col
decodeVisibleString: anInteger "... equals 'decodeOCTET_STRING:'." | ba | ba := ByteArray new: anInteger. 1 to: anInteger do: [ :x | ba at: x put: self next ]. ^ba asString
</methods> <methods> ASN1.BERStreamBasic <category>encoding - tagged types</category>
encodeBOOLEAN: aBoolean "... use the primitive form for 'true' that is optional for BER but required by DER." ( aBoolean ) ifTrue: [ self nextPut: 02r11111111 ] ifFalse: [ self nextPut: 02r00000000 ]
encodeENUMERATED: anInteger "Note that ENUMERATEDs may use negative integers and that 'Enumeration>>_value' is assumed to return anInteger." self encodeINTEGER: anInteger
encodeINTEGER: anInteger "Note the test using 'allMask:'. If a positive integer's high order bit is 1, an all-zero octet is written. If a negative integer's high order bit is 1, we extend the size of the mask to get the correct two's complement." "((( ( Asn1StreamBER on: ( ByteArray new: 2 ) ) encodeINTEGER: 27066 )))" "((( ( Asn1StreamBER on: ( ByteArray new: 2 ) ) encodeINTEGER: -27066 )))" | n l m | n := anInteger. l := n digitLength. ( n negative ) ifTrue: [ ( ( n digitAt: l ) allMask: 2r10000000 ) ifTrue: [ l := l + 1 ]. m := ( 2 raisedTo: ( 8 * l ) ) - 1. n := ( anInteger bitXor: m abs ) + 2r00000001. ] ifFalse: [ ( ( n digitAt: l ) allMask: 2r10000000 ) ifTrue: [ self nextPut: 0 ] ]. n digitLength to: 1 by: -1 do: [ :ndx | self nextPut: ( n digitAt: ndx ) ]
encodeNULL "Do nothing. An ASN.1 NULL is encoded solely by its tag."
encodeOBJECT_IDENTIFIER: anAsn1ImportedOID "Check for a stored encoding. ....." | enc ipos val tpos | "--- write out the stored encoding if possible ---" ( ( enc := anAsn1ImportedOID encoding ) notNil ) ifTrue: [ ^self nextPutAll: enc ]. "--- otherwise, do the work ---" ipos := self position. val := anAsn1ImportedOID value. "--- first two arcs encoded in first byte ---" self nextPut: ( ( val at: 1 ) * 40 + ( val at: 2 ) ). "--- subsequent arcs encoded one per byte ---" 3 to: val size do: [ :ndx | | int bitndx places | int := val at: ndx. bitndx := int highBit. places := bitndx - 1 // 7. places * -7 to: -7 by: 7 do: [ :i || nib | nib := int bitShift: i. nib := nib bitAnd: 02r1111111. self nextPut: ( nib bitOr: 02r10000000 ) ]. self nextPut: ( int bitAnd: 02r1111111 ) ]. "--- store encoding ---" tpos := self position. self position: ipos. enc := self next: ( tpos - ipos ) into: ( ByteArray new: ( tpos - ipos ) ) startingAt: 1. anAsn1ImportedOID encoding: enc. self position: tpos
encodeOCTET_STRING: anObject anObject asByteArray do: [ :x | self nextPut: x ]
encodeSEQUENCEorSEQUENCE_OF: aSequenceableCollection "Note that this method is used when there is no 'type-in-hand'. Marshaling without type information is dangerous and error-prone in the case of SEQUENCEs, which may contain objects of multiple types, OPTIONAL values, EXTENSION markers, and DEFAULT values that a receiver is expected to fill in if they have not been transmitted." aSequenceableCollection do: [ :o | self encodeTLV: o ].
encodeSETorSET_OF: aBag "Note that this method is used when there is no 'type-in-hand'. Marshaling without type information is dangerous and error-prone in the case of SETs, which may contain objects of multiple types transmitted in arbitrary order, OPTIONAL values, EXTENSION markers, and DEFAULT values that a receiver is expected to fill in if they have not been transmitted." aBag do: [ :o | self encodeTLV: o ].
encodeVisibleString: aByteString "... equals 'encodeOCTET_STRING:'." aByteString asByteArray do: [ :x | self nextPut: x ]
</methods> <methods> ASN1.BERStreamBasic <category>private</category>
inImplicitTag ^inImplicitTag
inImplicitTag: anObject inImplicitTag := anObject
notImplemented self error: (#NotImplemented << #asn1 >> 'This function has not been implemented in this release.')
</methods> <methods> ASN1.BERStreamBasic <category>encoding - private</category>
encode3ByteDefiniteLength: anInteger self nextPut: 02r10000010. ( anInteger digitLength == 2 ) ifTrue: [ self nextPut: ( anInteger digitAt: 2 ) ] ifFalse: [ self nextPut: 0 ]. self nextPut: ( anInteger digitAt: 1 )
encode: anObject with: aType "Called when aType doesn't have a tag. This is also called for root (default) types as those aren't tagged either." aType parent ifNil: [ aType canEncodeValue ifTrue: [ inImplicitTag ifTrue: [ inImplicitTag := false. aType encodeBody: anObject with: self ] ifFalse: [ self nextPut: anObject with: aType tag: aType tagBER ] ] ifFalse: [ self encodeTagless: anObject with: aType ] ] ifNotNil: [ :parent | parent encode: anObject with: self ]
encode: anObject with: aType explicitTag: anInteger "Called when aType has a tag." inImplicitTag := false. self nextPut: anObject with: aType tag: ( anInteger bitOr: ConstructedForm )
encode: anObject with: aType implicitTag: anInteger "Called when aType has a tag." inImplicitTag ifTrue: [ self encode: anObject with: aType ] ifFalse: [ inImplicitTag := true. self nextPut: anObject with: aType tag: (anInteger bitOr: PrimitiveForm) ]
encodeTagless: anObject with: anAsn1Type " ... for CHOICE and ANY types" encodingPolicy encodeBegin: anObject type: anAsn1Type. encodingPolicy encodeBeginBody: anObject type: anAsn1Type. anAsn1Type encodeDelegate: anObject with: self. ^encodingPolicy encodeEnd: anObject type: anAsn1Type.
nextPut: anObject with: aType tag: anInteger | end | encodingPolicy encodeBegin: anObject type: aType. self nextPutTag: anInteger. self nextPutLengthAndDo: [ encodingPolicy encodeBeginBody: anObject type: aType. (self isUniversal: anInteger) ifTrue: [ inImplicitTag := false. aType encodeBody: anObject with: self ] ifFalse: [ self encode: anObject with: aType ]. end := self position ]. self position = end ifFalse: [ encodingPolicy shiftCurrentBodyStartBy: (self position - end) ]. encodingPolicy encodeEnd: anObject type: aType.
nextPutLengthAndDo: aBlock | lpos vpos | lpos := self position. self nextPutAll: #[ 0 0 0 ]. "skip: 3" aBlock value. vpos := self position. self position: lpos. self encodeLength: vpos - lpos - 3. self position: vpos
nextPutTag: anInteger self nextPut: anInteger
</methods> <methods> ASN1.BERStreamBasic <category>testing</category>
isUniversal: anInteger ^(TagMaskClass bitAnd: anInteger) = UniversalClass
requiresEncodingSort ^false
requiresTagSort ^false
</methods> <methods> ASN1.BERStreamBasic <category>accessing</category>
encodingPolicy ^encodingPolicy
encodingPolicy: aPolicy " aPolicy <EncodingPolicy> controls the stream behavior with regards to objec encodings; retention, logging, etc. " encodingPolicy := aPolicy. aPolicy marshaler: self
shortTime " ^<Boolean> should encode timestamps omitting superfluous zero minutes/seconds if permitted " ^shortTime ifNil: [ self class defaultShortTime ]
shortTime: short " short <Boolean> should encode timestamps omitting superfluous zero minutes/seconds if permitted " shortTime := short
timezone " ^<TimeZone> the timezone to use for Timestamp conversions " ^timezone ifNil: [ self class defaultTimezone ]
timezone: tz " tz <TimeZone> the timezone to use for Timestamp conversions " timezone := tz
utcRoundMilliseconds " ^<Boolean> should the timestamp milliseconds be rounded or turncated for UTCTime " ^utcRoundMilliseconds ifNil: [ self class defaultUTCRoundMilliseconds ]
utcRoundMilliseconds: round " round <Boolean> should the timestamp milliseconds be rounded or turncated for UTCTime " utcRoundMilliseconds := round
utcSliding " ^<Boolean> are the 2 digit years of UTCTime interpreted in a 'sliding window' manner or fixed to 1950-2049 " ^utcSliding ifNil: [ self class defaultUTCSliding ]
utcSliding: slide " slide <Boolean> are the 2 digit years of UTCTime interpreted in a 'sliding window' manner or fixed to 1950-2049 " utcSliding := slide
</methods> <methods> ASN1.BERStreamBasic <category>decoding - private</category>
decodeTaglessWith: aType "... for CHOICE and ANY types only." | res | encodingPolicy decodeBeginType: aType. encodingPolicy decodeBeginBodyType: aType. res := aType decodeDelegateWith: self. ^encodingPolicy decodeEnd: res type: aType
decodeWith: aType | tag len res | aType parent ifNotNil: [ :parent | ^parent decodeWith: self ]. inImplicitTag ifTrue: [ inImplicitTag := false ] ifFalse: [ encodingPolicy decodeBeginType: aType. tag := self nextTag. tag = (self asTag: aType tagBER) ifFalse: [ self tagMismatch: tag with: aType ] ]. len := self nextLength. encodingPolicy decodeBeginBodyType: aType. res := aType decodeValue: len with: self. ^encodingPolicy decodeEnd: res type: aType
decodeWith: aType explicitTag: aTag | tag len res finishImplicitTag | finishImplicitTag := false. inImplicitTag ifTrue: [ inImplicitTag := false. finishImplicitTag := true. self nextLength. encodingPolicy decodeBeginBodyType: aType ]. encodingPolicy decodeBeginType: aType. tag := self nextTag. tag = (self asTag: aTag) ifFalse: [ self tagMismatch: tag with: aType ]. len := self nextLength. encodingPolicy decodeBeginBodyType: aType. res := aType parent ifNil: [ (self isUniversal: aTag) ifTrue: [ aType decodeValue: len with: self ] ifFalse: [ aType canEncodeValue ifTrue: [ self decodeWith: aType explicitTag: aType tagBER ] ifFalse: [ aType decodeDelegateWith: self ] ] ] ifNotNil: [ :parent | parent decodeWith: self ]. encodingPolicy decodeEnd: res type: aType. finishImplicitTag ifTrue: [ encodingPolicy decodeEnd: res type: aType ]. ^res
decodeWith: aType implicitTag: aTag | tag len res | ^inImplicitTag ifTrue: [ aType parent ifNil: [ inImplicitTag := false. len := self nextLength. encodingPolicy decodeBeginBodyType: aType. res := aType decodeValue: len with: self. encodingPolicy decodeEnd: res type: aType ] ifNotNil: [ :parent | parent decodeWith: self ] ] ifFalse: [ inImplicitTag := true. encodingPolicy decodeBeginType: aType. tag := self nextTag. tag = (self asTag: aTag) ifFalse: [ self tagMismatch: tag with: aType ]. aType parent ifNil: [ self decodeWith: aType implicitTag: aTag ] ifNotNil: [ :parent | parent decodeWith: self ] ]
next3OctetDefiniteLength "... not to be invoked directly in decoding APIs." "... reads and forgets the first octet, assumed to be '02r10000010', that is, decimal 2 with the long-form bit on, and then processes the next two octets." self next. ^( self next bitShift: 8 ) + self next
nextOctetTag "... read a single octet tag." "... not to be invoked directly in decoding APIs." ^self next
nextOctetTagMasked "... read a single octet tag and masks the first three bits." "... not to be invoked directly in decoding APIs." ^self asTag: self nextOctetTag
</methods> <methods> ASN1.BERStreamBasic <category>decoding - utility</category>
invalidLength: anInteger with:aType MarshalingError new messageText: ( #InvalidLength1p2p << #asn1 >> 'Invalid length <1p> for type <2p>!' expandMacrosWith: anInteger with: aType); parameter: aType; raise
missingElement: anElement with: aType MarshalingError new messageText: ( #MissingElement1s2p << #asn1 >> 'Missing element <1s> in type <2p>!' expandMacrosWith:anElement symbol with: aType); parameter: aType; raise
tagMismatch: aTag with: aType TagMismatch new messageText: ( #DecodingTagMismatch1p2p << #asn1 >> 'Tag <1p> does not match type <2p>!' expandMacrosWith: aTag with: aType); parameter: aTag; raise
trimCollection: aCollection ofSize: anInteger1 toSize: anInteger2 ^( anInteger1 > anInteger2 ) ifTrue: [ aCollection copyFrom: 1 to: anInteger2 ] ifFalse: [ aCollection ]
</methods> <methods> ASN1.BERStreamBasic <category>decoding - api</category>
asTag: anInteger "... a tag-related utility invoked in decoding APIs." "... if required, masks anInteger, as required by the tag matching scheme in effect." "... use constant to avoid namespace lookup." ^anInteger bitAnd: 02r00011111 "ASN1.TagMaskNumber"
nextLength "... the method to be directly invoked in decoding APIs." ^self next3OctetDefiniteLength
nextTag "... the method to be directly invoked in decoding APIs." ^self nextOctetTagMasked
unmarshalObjectType: anAsn1Type "... the default, top-level, entry point for type-in-hand decoding. Sets up for encoding retention. Note that since, at this point, we do not know how much of the 'collection' is taken up by the encoding, the entire 'collection; is retained as the 'source'." encodingPolicy unmarshalObjectType: anAsn1Type. ^super unmarshalObjectType: anAsn1Type
</methods> <methods> ASN1.BERStreamBasic <category>encoding - api</category>
encodeLength: anInteger "... the method to be directly invoked in encoding methods." self encode3ByteDefiniteLength: anInteger
encodeTLV: anObject "... a recursive entry point, not to be invoked without 'local knowledge'." "... geared for the use of 3-octet definite lengths." "... assumes anObject responds to both 'tagBER' and 'encodeASN1With:'." | lpos vpos | self nextPutTagFrom: anObject. lpos := self position. self nextPutAll: #[ 0 0 0 ]. "skip: 3" anObject encodeASN1With: self. vpos := self position. self position: lpos. self encodeLength: vpos - lpos - 3. self position: vpos
marshalObject: anObject withType: anAsn1Type "... the top-level entry point for type-in-hand encoding." encodingPolicy marshalObject: anObject withType: anAsn1Type. super marshalObject: anObject withType: anAsn1Type
</methods> <methods> ASN1.BERStreamBasic <category>encoding - utility</category>
nextPutTagFrom: anObject "... should cover both SubclassResponsibilityError and MessageNotUnderstood." "... assumes single-byte tags." [ self nextPut: anObject tagBER ] on: SubclassResponsibilityError, MessageNotUnderstood do: [ :ex | ex resignalAs: ( ( MarshalingError new ) messageText: (#TypeNotMarshalable << #asn1 >> 'The type is not marshalable under ASN.1!'); parameter: ex parameter; yourself ) ].
</methods> <methods> ASN1.BERStreamBasic <category>initialize-release</category>
wrap: aStream super wrap: aStream. encodingPolicy := self class defaultEncodingPolicy marshaler: self. inImplicitTag := false.
</methods> <methods> ASN1.BERStreamBasic <category>decoding - types - time</category>
decodeGeneralizedTime: anInteger | str date time offset seconds year month day ms | str := EncodedStream on: stream encodedBy: (StreamEncoder new: #ascii). year := ( str next: 4 ) asNumber. month := ( str next: 2 ) asNumber. day := ( str next: 2 ) asNumber. date := Date newDay: day monthNumber: month year: year. time := self decodeTimeFrom: str. ms := ( str atEnd not and: [ '.,' includes: str peek ] ) ifTrue: [ self decodeMillisecondsFrom: str ] ifFalse: [ 0 ]. (str atEnd or: [ ('Z+-' includes: str peek) not ]) ifTrue: [ ^(Timestamp fromDate: date andTime: time) addMilliseconds: ms ]. offset := self decodeTZOffsetFrom: str. seconds := date asSeconds + time asSeconds - (offset * 60). ^(self timezone convertGMT: seconds do: [ :localDate :localSeconds | Timestamp fromDate: localDate andTime: (Time fromSeconds: localSeconds) ] ) addMilliseconds: ms
decodeMillisecondsFrom: aStream | digits ms | aStream next. "drop the dot or comma" ms := 0. digits := 0. [ aStream atEnd or: [ 'Z+-' includes: aStream peek ] ] whileFalse: [ ms := ms * 10 + (aStream next asInteger - "$0 asInteger" 48). digits := digits + 1 ]. ^(ms * (10 ** ( 3 - digits ))) truncated
decodeTimeFrom: aStream | hr mn se | hr := ( aStream atEnd not and: [ aStream peek isDigit ] ) ifTrue: [ ( aStream next: 2 ) asNumber ] ifFalse: [ 0 ]. mn := ( aStream atEnd not and: [ aStream peek isDigit ] ) ifTrue: [ ( aStream next: 2 ) asNumber ] ifFalse: [ 0 ]. se := ( aStream atEnd not and: [ aStream peek isDigit ] ) ifTrue: [ ( aStream next: 2 ) asNumber ] ifFalse: [ 0 ]. ^Time new hours: hr minutes: mn seconds: se
decodeTZOffsetFrom: aStream | sign offset | sign := aStream next. sign = $Z ifTrue: [ ^0]. offset := ( aStream next: 2 ) asNumber * 60. (aStream atEnd not and: [ aStream peek isDigit ]) ifTrue: [ offset := offset + ( aStream next: 2 ) asNumber ]. ^sign = $- ifTrue: [ offset negated ] ifFalse: [ offset ]
decodeUTCTime: anInteger "Note that we go out of our way to raise an exception for a UTCTime encoding without a terminal 'Z' or offset." | str date time offset seconds year month day | str := EncodedStream on: stream encodedBy: (StreamEncoder new: #ascii). year := self fromTwoDigitYear: ( str next: 2 ) asNumber. month := ( str next: 2 ) asNumber. day := ( str next: 2 ) asNumber. date := Date newDay: day monthNumber: month year: year. time := self decodeTimeFrom: str. (str atEnd or: [ ('Z+-' includes: str peek) not ]) ifTrue: [ ^MarshalingError raiseSignal: #InvalidUTCTimeEncoding << #asn1 >> 'Invalid UTCTime encoding!' ]. offset := self decodeTZOffsetFrom: str. seconds := date asSeconds + time asSeconds - (offset * 60). ^self timezone convertGMT: seconds do: [ :localDate :localSeconds | Timestamp fromDate: localDate andTime: (Time fromSeconds: localSeconds) ]
fromTwoDigitYear: anInteger "convert a two digit year to four digit year" ^self utcSliding ifTrue: [ self fromTwoDigitYearSliding: anInteger ] ifFalse: [ self fromTwoDigitYearFixed: anInteger ]
fromTwoDigitYearFixed: anInteger "Dubuisson's 'ASN.1' on pp. 203-204, rule <6>: The ITU-T working group on the X.500 directory and the ITU-T Q22/11 question (intelligent networks protocols) propose that an application should be able to sort the UTCTime dates and interpret them in the 1950-2049 interval, which would mean, for example, that the value '0105281429Z' corresponds to the 28th of May 2001." ^anInteger < 50 ifTrue: [ 2000 + anInteger ] ifFalse: [ 1900 + anInteger ]
fromTwoDigitYearSliding: anInteger "Dubuisson's 'ASN.1' on pp. 203-204, rule <7>: The ITU-T working group on the X.400 e-mail propose that dates from 10 years backwards and 40 years ahead should be interpreted with respect to the 20th century and that the interpretation of the other years should be left to the programmer's interpretation (for example, for an application that is running in 1998, the values from 88 to 99 stand for the years from 1988 to 1999, the values from 00 to 38 are the years from 2000 to 2038, and the interpretation of the values from 39 to 87 depend on the implementation); this proposition of 'shifting window' is well-adapted for the MHS e-mail systems that manage dates in the past (dates of old messages stored or forwarded) as well as in the future (expiry date). We're forcing the interpretation of the unspecified years by extending the range from -50 to +49. " | currentYear | "We can safely assume 21st century now (UTCTime will hopefully be obsolete by the next century). That means anything from 00 all the way up to current year + 49 is 21st and the rest is 20th century." currentYear := Date today year \\ 100. ^currentYear + 49 < anInteger ifTrue: [ 1900 + anInteger ] ifFalse: [ 2000 + anInteger ]
</methods> <methods> ASN1.BERStreamBasic <category>encoding - types - time</category>
encodeGeneralizedTime: aTimestamp "We always go for the longest, most specific form. A GeneralizedTime is unlikely to exceed 23 characters." "In encoding, [1] a dot is used rather a comma, and [2] there are no meaningless zeros written for fractions of a second. These practices are optional under BER but required under DER." | str ms min sec | str := EncodedStream on: stream encodedBy: (StreamEncoder new: #ascii). aTimestamp year printOn: str base: 10 digitsToPad: 4 highDigit: 4. aTimestamp month printOn: str base: 10 digitsToPad: 2 highDigit: 2. aTimestamp day printOn: str base: 10 digitsToPad: 2 highDigit: 2. aTimestamp hour printOn: str base: 10 digitsToPad: 2 highDigit: 2. min := aTimestamp minute. sec := aTimestamp second. ms := aTimestamp millisecond. (self shortTime and: [ ((min bitOr: sec) bitOr: ms) = 0 ]) ifFalse: [ min printOn: str base: 10 digitsToPad: 2 highDigit: 2 ]. (self shortTime and: [ (sec bitOr: ms) = 0 ]) ifFalse: [ aTimestamp second printOn: str base: 10 digitsToPad: 2 highDigit: 2 ]. ms = 0 ifFalse: [ | pad | str nextPut: $.. pad := 3. [ ms \\ 10 = 0 ] whileTrue: [ pad := pad - 1. ms := ms // 10 ]. ms printOn: str base: 10 digitsToPad: pad highDigit: pad ]. self encodeTZOffsetFor: aTimestamp on: str short: self shortTime.
encodeTZOffsetFor: aTimestamp on: aStream short: short | offset local utc | local := aTimestamp asSeconds. utc := self timezone convertLocalSecondsToGMT: local. offset := (local - utc) // 60. "in minutes" offset = 0 ifTrue: [ ^aStream nextPut: $Z ]. aStream nextPut: ( offset negative ifTrue: [ $- ] ifFalse: [ $+ ] ). offset := offset abs. (offset // 60) printOn: aStream base: 10 digitsToPad: 2 highDigit: 2. offset := offset \\ 60. (short and: [offset = 0]) ifFalse: [ offset printOn: aStream base: 10 digitsToPad: 2 highDigit: 2 ].
encodeUTCTime: aTimestamp "We always go for the longest, most specific form. A UTCTime is unlikely to exceed 17 characters." | str timestamp | str := EncodedStream on: stream encodedBy: (StreamEncoder new: #ascii). timestamp := (self utcRoundMilliseconds and: [ aTimestamp millisecond > 500 ]) ifTrue: [ aTimestamp addSeconds: 1 ] ifFalse: [ aTimestamp ]. (self toTwoDigitYear: timestamp year) printOn: str base: 10 digitsToPad: 2 highDigit: 2. timestamp month printOn: str base: 10 digitsToPad: 2 highDigit: 2. timestamp day printOn: str base: 10 digitsToPad: 2 highDigit: 2. timestamp hour printOn: str base: 10 digitsToPad: 2 highDigit: 2. timestamp minute printOn: str base: 10 digitsToPad: 2 highDigit: 2. (self shortTime and: [ timestamp second = 0 ]) ifFalse: [ timestamp second printOn: str base: 10 digitsToPad: 2 highDigit: 2 ]. self encodeTZOffsetFor: timestamp on: str short: false.
toTwoDigitYear: anInteger "Convert the year to two digits." ^self utcSliding ifTrue: [ self toTwoDigitYearSliding: anInteger ] ifFalse: [ self toTwoDigitYearFixed: anInteger ]
toTwoDigitYearFixed: anInteger "Dubuisson's 'ASN.1' on pp. 203-204, rule <6>: The ITU-T working group on the X.500 directory and the ITU-T Q22/11 question (intelligent networks protocols) propose that an application should be able to sort the UTCTime dates and interpret them in the 1950-2049 interval, which would mean, for example, that the value '0105281429Z' corresponds to the 28th of May 2001." (anInteger between:1950 and: 2049) ifFalse: [ UTCTimeRange raiseRequestWith: anInteger errorString: ( #UTCTimeRangeFixed1p << #asn1 >> 'Year <1p> is out of fixed UTCTime range!' expandMacrosWith: anInteger ) ]. ^anInteger \\ 100
toTwoDigitYearSliding: anInteger "Dubuisson's 'ASN.1' on pp. 203-204, rule <7>: The ITU-T working group on the X.400 e-mail propose that dates from 10 years backwards and 40 years ahead should be interpreted with respect to the 20th century and that the interpretation of the other years should be left to the programmer's interpretation (for example, for an application that is running in 1998, the values from 88 to 99 stand for the years from 1988 to 1999, the values from 00 to 38 are the years from 2000 to 2038, and the interpretation of the values from 39 to 87 depend on the implementation); this proposition of 'shifting window' is well-adapted for the MHS e-mail systems that manage dates in the past (dates of old messages stored or forwarded) as well as in the future (expiry date). We're forcing the interpretation of the unspecified years by extending the range from -50 to +49. " | thisYear | thisYear := Date today year. (anInteger between: thisYear - 50 and: thisYear + 49) ifFalse: [ UTCTimeRange raiseRequestWith: anInteger errorString: ( #UTCTimeRange1p << #asn1 >> 'Year <1p> is out of sliding UTCTime range!' expandMacrosWith: anInteger) ]. ^anInteger \\ 100
</methods> <methods> ASN1.BERStreamBasic class <category>class initialization</category>
initialize "((( self initialize )))" super initialize
initializeTagDispatchTable "Initialize the tag table used for unmarshalling." "((( self initializeTagDispatchTable )))" self tagDispatchTable: ( Array new: 32 ). self tagDispatchTable at: 1 put: [ :len :m | m decodeBOOLEAN: len ]; at: 2 put: [ :len :m | m decodeINTEGER: len ]; at: 3 put: [ :len :m | m decodeBIT_STRING: len ]; at: 4 put: [ :len :m | m decodeOCTET_STRING: len ]; at: 5 put: [ :len :m | m decodeNULL: len ]; at: 6 put: [ :len :m | m decodeOBJECT_IDENTIFIER: len ]; at: 7 put: [ :len :m | m decodeObjectDescriptor: len ]; at: 8 put: [ :len :m | m decodeEXTERNALorINSTANCE_OF: len ]; at: 9 put: [ :len :m | m decodeREAL: len ]; at: 10 put: [ :len :m | m decodeENUMERATED: len ]; at: 11 put: [ :len :m | m decodeEMBEDDED_PDV: len ]; at: 12 put: [ :len :m | m decodeUTF8String: len ]; at: 13 put: [ :len :m | m decodeRELATIVE_OID: len ]; "14=reserved for future use" "15=reserved for future use" at: 16 put: [ :len :m | m decodeSEQUENCEorSEQUENCE_OF: len ]; at: 17 put: [ :len :m | m decodeSETorSET_OF: len ]; at: 18 put: [ :len :m | m decodeNumericString: len ]; at: 19 put: [ :len :m | m decodePrintableString: len ]; at: 20 put: [ :len :m | m decodeTeletexStringOrT61String: len ]; at: 21 put: [ :len :m | m decodeVideotexString: len ]; at: 22 put: [ :len :m | m decodeIA5String: len ]; at: 23 put: [ :len :m | m decodeUTCTime: len ]; at: 24 put: [ :len :m | m decodeGeneralizedTime: len ]; at: 25 put: [ :len :m | m decodeGraphicString: len ]; at: 26 put: [ :len :m | m decodeVisibleStringOrISO646String: len ]; at: 27 put: [ :len :m | m decodeGeneralString: len ]; at: 28 put: [ :len :m | m decodeUniversalString: len ]; at: 29 put: [ :len :m | m decodeCHARACTER_STRING: len ]; at: 30 put: [ :len :m | m decodeBMPString: len ]. "31 ... = reserved for future use"
</methods> <methods> ASN1.BERStreamBasic class <category>accessing</category>
defaultEncodingPolicy ^defaultEncodingPolicy ifNil: [ defaultEncodingPolicy := self defaultEncodingPolicyValue ]
defaultEncodingPolicy: aClass " aClass <Class> the default policy for streams of given class " defaultEncodingPolicy := aClass
defaultEncodingPolicyValue ^EncodingPolicy
defaultShortTime " ^<Boolean> should encode timestamps omitting superfluous zero minutes/seconds if permitted " ^defaultShortTime ifNil: [ self defaultShortTimeValue ]
defaultShortTime: short " short <Boolean> should encode timestamps omitting superfluous zero minutes/seconds if permitted " defaultShortTime := short
defaultShortTimeValue ^true
defaultTimezone " ^<TimeZone> the timezone to use for Timestamp conversions " ^defaultTimezone ifNil: [ self defaultTimezoneValue ]
defaultTimezone: timezone " timezone <TimeZone> the timezone to use for Timestamp conversions " defaultTimezone := timezone
defaultTimezoneValue ^TimeZone reference
defaultUTCRoundMilliseconds " ^<Boolean> should the timestamp milliseconds be rounded or turncated for UTCTime " ^defaultUTCRoundMilliseconds ifNil: [ self defaultUTCRoundMillisecondsValue ]
defaultUTCRoundMilliseconds: round " round <Boolean> should the timestamp milliseconds be rounded or turncated for UTCTime " defaultUTCRoundMilliseconds := round
defaultUTCRoundMillisecondsValue "should the timestamp milliseconds be rounded or turncated for UTCTime " ^true
defaultUTCSliding " ^<Boolean> are the 2 digit years of UTCTime interpreted in a 'sliding window' manner or fixed to 1950-2049 " ^defaultUTCSliding ifNil: [ self defaultUTCSlidingValue ]
defaultUTCSliding: slide " slide <Boolean> are the 2 digit years of UTCTime interpreted in a 'sliding window' manner or fixed to 1950-2049 " defaultUTCSliding := slide
defaultUTCSlidingValue "Are the 2 digit years of UTCTime interpreted in a 'sliding window' manner or fixed to 1950-2049. " ^true
</methods> <methods> ASN1.BERStreamDefinite <category>accessing</category>
scratchBuffer ^( scratchBuffer isNil ) ifTrue: [ scratchBuffer := ReadWriteStream on: ( ByteArray new: 64 ) ] ifFalse: [ scratchBuffer ]
ucs2 "P.Guttman's style guide says: The correct format for BMPStrings is: big-endian 16-bit characters, no Unicode byte order marks (BOMs), and no terminating null character (ISO 8825-1 section 8.20)" ^ucs2 ifNil: [ ucs2 := (StreamEncoder new: #ucs_2) initializeForMemory; bigEndian: true ]
utf8 ^utf8 ifNil: [ utf8 := (StreamEncoder new: #utf8) initializeForMemory ]
</methods> <methods> ASN1.BERStreamDefinite <category>decoding - tagged types</category>
decodeBIT_STRING: anInteger ^BitString unused: self next bytes: ( stream next: anInteger - 1 )
decodeBMPString: anInteger ^self decodeString: anInteger with: self ucs2
decodeIA5String: anInteger "... equals 'decodeOCTET_STRING:'." "... this is provisional and incorrect." | ba | ba := ByteArray new: anInteger. 1 to: anInteger do: [ :x | ba at: x put: self next ]. ^ba asString
decodeNumericString: anInteger "... equals 'decodeOCTET_STRING:'." | ba | ba := ByteArray new: anInteger. 1 to: anInteger do: [ :x | ba at: x put: self next ]. ^ba asString
decodePrintableString: anInteger "... equals 'decodeOCTET_STRING:'." | ba | ba := ByteArray new: anInteger. 1 to: anInteger do: [ :x | ba at: x put: self next ]. ^ba asString
decodeTeletexStringOrT61String: anInteger "... equals 'decodeOCTET_STRING:'." "... provisional implementation!" | ba | ba := ByteArray new: anInteger. 1 to: anInteger do: [ :x | ba at: x put: self next ]. ^ba asString
decodeUTF8String: anInteger ^self decodeString: anInteger with: self utf8
decodeVisibleStringOrISO646String: anInteger "... equals 'decodeOCTET_STRING:'." | ba | ba := ByteArray new: anInteger. 1 to: anInteger do: [ :x | ba at: x put: self next ]. ^ba asString
</methods> <methods> ASN1.BERStreamDefinite <category>decoding - private</category>
decodeString: anInteger with: encoder | start out | start := self position. out := (String new: anInteger) writeStream. [ self position - start < anInteger ] whileTrue: [ out nextPut: (encoder nextFrom: self) ]. ^out contents
nextDefiniteLength | oct val | ^( ( oct := self next ) anyMask: 2r10000000 ) ifTrue: [ val := 0. ( oct maskClear: 2r10000000 ) timesRepeat: [ val := ( val bitShift: 8 ) + self next ]. val ] ifFalse: [ oct ]
nextGenericTag "... read a single or multiple octet tag." "... not to be invoked directly in decoding APIs." "... assumes that we do not need to represent the tag class or form." | oct1 numberPart oct tag | oct1 := self next. ( ( numberPart := self asTag: oct1 ) == 31 ) "--- single-octet tag ---" ifFalse: [ ^numberPart ] "--- multi-octet tag ---" ifTrue: [ tag := 0. [ tag := tag bitShift: 7. oct := self next. tag := tag bitOr: ( oct maskClear: 2r10000000 ). ] whileTrue: [ oct anyMask: 2r10000000 ]. ^tag ]
nextShortDefiniteLength ^self next
</methods> <methods> ASN1.BERStreamDefinite <category>encoding - private</category>
encodeDefiniteLength: anInteger ( anInteger > 127 ) ifTrue: [ self halt. self nextPut: ( 2r10000000 bitOr: anInteger digitLength ). anInteger digitLength to: 1 by: -1 do: [ :idx | self nextPut: ( anInteger digitAt: idx ) ]. ] ifFalse: [ self nextPut: anInteger]
encodeDefiniteLength: anInteger on: aWriteStream ( anInteger > 127 ) ifTrue: [ aWriteStream nextPut: ( 2r10000000 bitOr: anInteger digitLength ). anInteger digitLength to: 1 by: -1 do: [ :idx | aWriteStream nextPut: ( anInteger digitAt: idx ) ]. aWriteStream contents ] ifFalse: [ aWriteStream nextPut: anInteger]. ^aWriteStream
nextPutLengthAndDo: aBlock | lpos vpos len | lpos := self position. self nextPut: 0. "skip: 1" aBlock value. vpos := self position. len := vpos - lpos - 1. ( len <= 127 ) ifTrue: [ self position: lpos. self encodeDefiniteLength: len. self position: vpos ] ifFalse: [ | inc | self scratchBuffer reset. self encodeDefiniteLength: len on: scratchBuffer. inc := scratchBuffer position - 1. self shift: inc from: lpos + 2 to: vpos. self position: lpos. ( scratchBuffer collection copyFrom: 1 to: scratchBuffer position ) do: [ :x | self nextPut: x ]. self position: vpos + inc ].
shift: increment from: start to: end stream shift: increment from: start to: end
</methods> <methods> ASN1.BERStreamDefinite <category>encoding - tagged types</category>
encodeBIT_STRING: anAsn1ImportedBitString "... only the primitive encoding." ( anAsn1ImportedBitString isEmpty ) ifTrue: [ self nextPut: 0 ] ifFalse: [ self nextPut: anAsn1ImportedBitString unused. self nextPutAll: anAsn1ImportedBitString bytes ]
encodeBMPString: anObject self encodeString: anObject with: self ucs2
encodeIA5String: aByteString "... equals 'encodeOCTET_STRING:'." "... this is provisional and incorrect." aByteString asByteArray do: [ :x | self nextPut: x ]
encodeNumericString: aByteString "... equals 'encodeOCTET_STRING:'." aByteString asByteArray do: [ :x | self nextPut: x ]
encodePrintableString: aByteString "... equals 'encodeOCTET_STRING:'." aByteString asByteArray do: [ :x | self nextPut: x ]
encodeString: string with: encoder (EncodedStream on: self encodedBy: encoder) nextPutAll: string
encodeUTF8String: anObject self encodeString: anObject with: self utf8
encodeVisibleStringOrISO646String: aByteString "... equals 'encodeOCTET_STRING:'." aByteString asByteArray do: [ :x | self nextPut: x ]
</methods> <methods> ASN1.BERStreamDefinite <category>decoding - api</category>
nextLength "... the method to be directly invoked in decoding APIs." ^self nextDefiniteLength.
nextTag "... the method to be directly invoked in decoding APIs." ^self nextGenericTag
</methods> <methods> ASN1.BERStreamDefinite <category>encoding - api</category>
encodeTLV: anObject "... a recursive entry point, not to be invoked without 'local knowledge'." "... hopes for a 1-octet definite length and plays costly copying games otherwise." "... assumes anObject responds to both 'tagBER' and 'encodeASN1With:'." | lpos vpos len | self nextPutTagFrom: anObject. lpos := self position. self nextPut: 0. "skip: 1" anObject encodeASN1With: self. vpos := self position. len := vpos - lpos - 1. ( len <= 127 ) ifTrue: [ self position: lpos. self encodeDefiniteLength: len. self position: vpos ] ifFalse: [ | inc | self scratchBuffer reset. self encodeDefiniteLength: len on: scratchBuffer. inc := scratchBuffer position - 1. self shift: inc from: lpos + 2 to: vpos. self position: lpos. scratchBuffer contents do: [ :x | self nextPut: x ]. self position: vpos + inc ]
</methods> <methods> ASN1.BERStreamDefinite <category>encoding - lengths</category>
encodeLength: anInteger "... the method to be directly invoked in encoding methods." "... intended to accord with the DER requirement that lengths be encoded in the minimum number of octets." self encodeDefiniteLength: anInteger
</methods> <methods> ASN1.BERStreamDefinite <category>encoding - unimplemented</category>
encodeCHARACTER_STRING: anObject self notImplemented
encodeEMBEDDED_PDV: anObject self notImplemented
encodeEXTERNALorINSTANCE_OF: anObject self notImplemented
encodeGeneralString: anObject self notImplemented
encodeGraphicString: anObject self notImplemented
encodeObjectDescriptor: anObject self notImplemented
encodeREAL: anObject "--- zero is encoded as a REAL of zero length ---" ( anObject = 0 ) ifTrue: [ ^nil ]. "--- fixed representations for positive and negative infinity ---" ( #{Infinity} isDefined ) ifTrue: [ ( anObject == Infinity positive ) ifTrue: [ ^self nextPut: 02r01000000 ]. ( anObject == Infinity negative ) ifTrue: [ ^self nextPut: 02r01000001 ]. ]. self notImplemented
encodeRELATIVE_OID: anObject self notImplemented
encodeUniversalString: anObject self notImplemented
</methods> <methods> ASN1.BERStreamDefinite <category>decoding - unimplemented</category>
decodeCHARACTER_STRING: anInteger self notImplemented
decodeEMBEDDED_PDV: anInteger self notImplemented
decodeEXTERNALorINSTANCE_OF: anInteger self notImplemented
decodeGeneralString: anInteger self notImplemented
decodeGraphicString: anInteger self notImplemented
decodeObjectDescriptor: anInteger self notImplemented
decodeREAL: anInteger "... going for Doubles when possible." "--- zero is encoded as a REAL of zero length ---" ( anInteger = 0 ) ifTrue: [ ^Double zero ]. self notImplemented
decodeRELATIVE_OID: anInteger self notImplemented
decodeUniversalString: anInteger self notImplemented
decodeVideotexString: anInteger self notImplemented
</methods> <methods> ASN1.BERStreamDefinite <category>testing</category>
canRetainEncodingWhileMarshaling "It seems that the length encoding shifts that can happen during marshaling for entities longer than 128 bytes can mess up retained encodings of contained elements. " ^false
</methods> <methods> ASN1.BERStreamDefinite class <category>class initialization</category>
initialize "((( self initialize )))" super initialize
</methods> <methods> ASN1.EncodingPolicy <category>decoding</category>
decodeBeginBodyType: anAsn1Type
decodeBeginType: anAsn1Type
decodeEnd: anObject type: anAsn1Type ^anObject
unmarshalObjectType: anAsn1Type
</methods> <methods> ASN1.EncodingPolicy <category>encoding</category>
encodeBegin: anObject type: anAsn1Type
encodeBeginBody: anObject type: anAsn1Type
encodeEnd: anObject type: anAsn1Type ^anObject
marshalObject: anObject withType: anAsn1Type
shiftCurrentBodyStartBy: anInteger
</methods> <methods> ASN1.EncodingPolicy <category>accessing</category>
marshaler: anAsn1Stream marshaler := anAsn1Stream
</methods> <methods> ASN1.EncodingPolicy class <category>instance creation</category>
marshaler: anAsn1Stream ^self new marshaler: anAsn1Stream; yourself
</methods> <methods> ASN1.RetainEncodings <category>private</category>
beginEncodings self pushEncoding. currentEncoding headerStart: marshaler position + 1
dropEncodingFor: anObject type: anAsn1Type self popEncoding. ^anObject
markEncodingsBodyStart currentEncoding bodyStart: marshaler position + 1
retainEncodingFor: anObject type: anAsn1Type currentEncoding bodyStop: marshaler position. ^anObject _encoding: self popEncoding type: anAsn1Type
shouldRetainEncodingFor: object type: type ^type retainEncoding
</methods> <methods> ASN1.RetainEncodings <category>encoding</category>
encodeBegin: anObject type: anAsn1Type self beginEncodings
encodeBeginBody: anObject type: anAsn1Type self markEncodingsBodyStart
encodeEnd: object type: type ^( marshaler canRetainEncodingWhileMarshaling and: [ self shouldRetainEncodingFor: object type: type] ) ifTrue: [self retainEncodingFor: object type: type] ifFalse: [self dropEncodingFor: object type: type]
marshalObject: anObject withType: anAsn1Type source := marshaler collection.
shiftCurrentBodyStartBy: anInteger currentEncoding bodyStart: currentEncoding bodyStart + anInteger
</methods> <methods> ASN1.RetainEncodings <category>stack - api</category>
clearEncoding encodingStack := OrderedCollection new: 256. currentEncoding := nil
popEncoding | res | res := self encodingStack removeLast. currentEncoding := [ self encodingStack last ] on: Error do: [ :ex | nil ]. ^res
pushEncoding | enc | enc := Encoding source: source. self encodingStack addLast: enc. ^currentEncoding := enc
</methods> <methods> ASN1.RetainEncodings <category>decoding</category>
decodeBeginBodyType: anAsn1Type self markEncodingsBodyStart
decodeBeginType: anAsn1Type self beginEncodings
decodeEnd: object type: type ^(self shouldRetainEncodingFor: object type: type) ifTrue: [self retainEncodingFor: object type: type] ifFalse: [self dropEncodingFor: object type: type]
unmarshalObjectType: anAsn1Type source := marshaler collection.
</methods> <methods> ASN1.RetainEncodings <category>accessing</category>
currentEncoding ^currentEncoding
encodingStack ^( encodingStack isNil ) ifTrue: [ encodingStack := OrderedCollection new: 256 ] ifFalse: [ encodingStack ]
</methods> <methods> ASN1.RetainAllEncodings <category>private</category>
shouldRetainEncodingFor: object type: type ^true
</methods> <methods> ASN1.PrettyPrinter <category>encoding</category>
encodeBegin: anObject type: anAsn1Type super encodeBegin: anObject type: anAsn1Type. stream cr. self offsets ifTrue: [ stream print: marshaler position ]. stream tab: indent. anAsn1Type shortPrintOn: stream. indent := indent + 1
encodeEnd: anObject type: anAsn1Type indent := indent - 1. stream cr. self offsets ifTrue: [ stream print: marshaler position - 1 ]. stream tab: indent; print: anObject. ^super encodeEnd: anObject type: anAsn1Type
</methods> <methods> ASN1.PrettyPrinter <category>accessing</category>
offsets ^offsets ifNil: [ true ]
offsets: aBoolean " aBoolean <Boolean> should print offsets of entities " offsets := aBoolean
</methods> <methods> ASN1.PrettyPrinter <category>initialize-release</category>
on: aStream stream := aStream. indent := 1
</methods> <methods> ASN1.PrettyPrinter <category>decoding</category>
decodeBeginType: anAsn1Type super decodeBeginType: anAsn1Type. stream cr. self offsets ifTrue: [ stream print: marshaler position ]. stream tab: indent. anAsn1Type shortPrintOn: stream. indent := indent + 1
decodeEnd: anObject type: anAsn1Type indent := indent - 1. stream cr. self offsets ifTrue: [ stream print: marshaler position ]. stream tab: indent; print: anObject. ^super decodeEnd: anObject type: anAsn1Type
</methods> <methods> ASN1.PrettyPrinter class <category>instance creation</category>
on: aStream ^self new on: aStream
</methods> <methods> ASN1.UTCTimeRange class <category>testing</category>
mayResume ^true
</methods> <methods> ASN1.TagUnknown class <category>testing</category>
mayResume ^true
</methods> <methods> ASN1.DERStream <category>testing</category>
requiresEncodingSort ^true
requiresTagSort ^true
</methods> <methods> ASN1.DERStream <category>encoding - tagged types</category>
encodeSETorSET_OF: aSet "Note that this method is used when there is no 'type-in-hand'. Marshaling without type information is dangerous and error-prone in the case of SETs, which may contain objects of multiple types transmitted in arbitrary order, OPTIONAL values, EXTENSION markers, and DEFAULT values that a receiver is expected to fill in if they have not been transmitted." | sc scratch | scratch := self class on: (ByteArray new: 100). sc := OrderedCollection new: aSet size. aSet do: [ :o | scratch encodeTLV: o. sc add: scratch contents. sc reset ]. "now we need to sort all entries based on the value of their encoding (pad with zeros for comparison as necessary)" (self class sortByteArrays: sc) do: [ :ba | self nextPutAll: ba ]
</methods> <methods> ASN1.DERStream <category>encoding - types - time</category>
convertToUTC: aTimestamp | ms timestamp | ms := aTimestamp millisecond. timestamp := self timezone convertToGMT: aTimestamp asSeconds do: [ :date :seconds | Timestamp fromDate: date andTime: (Time fromSeconds: seconds) ]. ^timestamp addMilliseconds: ms
encodeGeneralizedTime: aTimestamp "Timestamps are converted to universal time, as required under DER." super encodeGeneralizedTime: (self convertToUTC: aTimestamp)
encodeTZOffsetFor: aTimestamp on: aStream short: short aStream nextPut: $Z
encodeUTCTime: aTimestamp "Timestamps are converted to universal time, as required under DER." super encodeUTCTime: (self convertToUTC: aTimestamp)
</methods> <methods> ASN1.DERStream class <category>accessing</category>
defaultEncodingPolicyValue ^RetainEncodings
defaultShortTimeValue ^false
defaultUTCSlidingValue "Are the 2 digit years of UTCTime interpreted in a 'sliding window' manner or fixed to 1950-2049. Defaulting to fixed because that's what X.509 expects. " ^false
</methods> <methods> ASN1.DERStream class <category>class initialization</category>
initialize "((( self initialize )))" super initialize
</methods> <methods> ASN1.DERStream class <category>private</category>
sortByteArrays: byteArrays ^SortedCollection withAll: byteArrays sortBlock: [ :a :b | ( (1 to: (a size min: b size)) detect: [ :i | (a at: i) ~~ (b at: i) ] ifNone: [ nil ]) ifNil: [ a size <= b size ] ifNotNil: [ :i | (a at: i) < (b at: i) ] ]
</methods> <methods> ASN1.RELATIVE_OID <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00001101 "ASN1.UniversalRELATIVE_OID = 13"
</methods> <methods> ASN1.ChoiceElement <category>decoding</category>
decodeWith: aMarshaler ^type decodeWith: aMarshaler
</methods> <methods> ASN1.ChoiceElement <category>encoding</category>
encode: anObject with: aMarshaler type encode: anObject asn1ChoiceValue with: aMarshaler
key ^symbol
tagBER "Goes to the type if the tag is nil. Dubs in the context-specific and constructed tag prefixes if the tagging mode is EXPLICIT." ^self tag ifNil: [ self type tagBER ] ifNotNil: [ :t | self isExplicit ifTrue: [ t bitOr: 2r10100000 ] ifFalse: [ t ] ]
</methods> <methods> ASN1.TypeWrapper <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." "However, this implementation redispatches to the type held by this marshaling wrapper." type encodeValue: object with: aMarshaler
tagBER ^type tagBER
_encoding: anEncoding type: aType encoding := anEncoding
</methods> <methods> ASN1.Struct <category>marshaling - asn1</category>
asn1ChoiceType ^nil
asn1ChoiceValue ^self
_encoding: anEncoding type: aType encoding := anEncoding
</methods> <methods> ASN1.StructureElement <category>decoding</category>
decode: anObject with: aMarshaler | tag | aMarshaler atEnd ifTrue: [ self hasDefault ifTrue: [^self value: self default into: anObject]. self isOptional ifTrue: [^self]. ^aMarshaler missingElement: self with: type ]. tag := aMarshaler peekTag. (self matchesTag: tag) ifTrue: [ | val | val := type decodeWith: aMarshaler for: anObject. (val isNil and: [ self isOptional ]) ifTrue: [ "to be able to distinguish absence from NULL, wrap the nil in a type wrapper" val := TypeWrapper new _type: type; _value: val; yourself ]. self value: val into: anObject ] ifFalse: [ self hasDefaultOrIsOptional ifTrue: [ self hasDefault ifTrue: [ self value: self default into: anObject] ] ifFalse: [ aMarshaler missingElement: self with: type ] ]
</methods> <methods> ASN1.StructureElement <category>encoding</category>
encode: anObject with: aMarshaler [ | val | val := self valueFrom: anObject. ( (self isOptional and: [ val _isTypeWrapper not and: [ val isNil ] ]) or: [ self hasDefault and: [ val = self default ] ] ) ifFalse: [ type encode: val with: aMarshaler for: anObject ] ] on: MarshalingError do: [ :ex | self hasDefaultOrIsOptional ifFalse: [ ex pass ] ].
</methods> <methods> ASN1.StructureElement <category>decoding</category>
value: aValue into: anObject "( mapping == nil ) ifTrue: [ anObject1 add: ( anObject2 -> anObject3 ) ] ifFalse: [ anObject1 perform: ( self mutatorFrom: anObject2 ) with: anObject3 ]" anObject perform: self mutator with: aValue
</methods> <methods> ASN1.StructureElement <category>encoding</category>
valueFrom: anObject ^[ anObject perform: self accessor ] on: MessageNotUnderstood do: [ :ex | ex resignalAs: ( MarshalingError new messageText: (#MissingElementValue1s << #asn1 >> 'Missing value for element <1s>' expandMacrosWith: symbol); parameter: anObject; yourself ) ]
</methods> <methods> ASN1.TeletexString <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00010100 "ASN1.UniversalTeletexString = 20"
</methods> <methods> Core.Object <category>marshaling - asn1</category>
asn1ChoiceType ^nil
asn1ChoiceValue ^self
_encoding ^nil
_encoding: anEncoding type: aType ^ASN1.TypeWrapper new _type: aType; _value: self; _encoding: anEncoding; yourself
</methods> <methods> ASN1.MappableType <category>decoding - utility</category>
completeTarget: anObject ( mapping == nil ) ifTrue: [ anObject structName: self symbol ]. ^anObject
createTarget ^( mapping == nil ) ifTrue: [ Struct new: 11 ] ifFalse: [ mapping new ]
</methods> <methods> ASN1.MappableType <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand. Since SETs have an unconstrained transmission order, we just take what comes and push it into the target." | target end elems extension | end := aMarshaler position + anInteger. elems := (self orderedElementsFor: aMarshaler) readStream. target := self createTarget. extension := false. [ elems atEnd or: [ aMarshaler position >= end ] ] whileFalse: [ | ele | ele := elems next. ele isExtensionMarker ifTrue: [ extension := true ]. ele decode: target with: aMarshaler ]. [ extension or: [ elems atEnd ] ] whileFalse: [ | ele | ele := elems next. ele isExtensionMarker ifTrue: [ extension := true ]. ( ele isMarker or: [ ele hasDefault ifTrue: [ele value: ele default into: target]. ele hasDefaultOrIsOptional ] ) ifFalse: [ aMarshaler missingElement: ele with: self ] ]. aMarshaler position < end ifTrue: [ extension ifTrue: [ aMarshaler position: end ] ifFalse: [ aMarshaler invalidLength: anInteger with: self ] ]. ^self completeTarget: target
</methods> <methods> ASN1.MappableType <category>encoding</category>
encode: aStruct with: aMarshaler ^aStruct _encoding ifNil: [ super encode: aStruct with: aMarshaler ] ifNotNil: [ :encoding | encoding writeOn: aMarshaler ]
encodeValue: anAsn1Struct with: aMarshaler "... the method invoked when unmarshaling type-in-hand. ... branches on whether a retained encoding is present." ( self permits: anAsn1Struct ) ifFalse: [ MarshalingError new messageText: (#InvalidStructuredValue1s << #asn1 >> 'Bad object for structured type <1s>!' expandMacrosWith: symbol); parameter: anAsn1Struct; raise ]. (self orderedElementsFor: aMarshaler) do: [ :ele | ele encode: anAsn1Struct with: aMarshaler ]
orderedElementsFor: aMarshaler ^elements
</methods> <methods> ASN1.GeneralizedTime <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeGeneralizedTime: anInteger
</methods> <methods> ASN1.GeneralizedTime <category>encoding</category>
encodeValue: vaTimestamp with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeGeneralizedTime: vaTimestamp
tagBER "... avoid the namespace lookup." ^02r00011000 "ASN1.UniversalGeneralizedTime = 24"
</methods> <methods> Core.Timestamp <category>marshaling - asn1</category>
asGeneralizedTime "By default, aTimestamp is marshaled as a GeneralizedTime." ^self
asUTCTime "A Timestamp may be marshaled as a UTCTime by enclosing it in an Asn1TypeWrapper prior to marshaling." ^ASN1.TypeWrapper new _type: ASN1.UTCTime new; _value: self; yourself
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." ^aMarshaler encodeGeneralizedTime: self
tagBER "... avoid the namespace lookup." ^02r00011000 "ASN1.UniversalGeneralizedTime = 24"
</methods> <methods> Core.ByteString <category>marshaling -asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." "... this is provisional, as ByteString's range include several of the ISOReg graphical sets." "... PrintableString is chosen because it is the expected type for X509 certificates." ^aMarshaler encodePrintableString: self
tagBER "... this is provisional, as ByteString's range include several of the ISOReg graphical sets." "... PrintableString is chosen because it is the expected type for X509 certificates." "... avoid the namespace lookup." ^02r00010011 "ASN1.UniversalPrintableString = 19"
</methods> <methods> ASN1.SEQUENCE_OF <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00110000 "ASN1.ConstructedSEQUENCE = 48"
</methods> <methods> ASN1.UTF8String <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeUTF8String: anInteger
</methods> <methods> ASN1.UTF8String <category>encoding</category>
encodeValue: anObject with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeUTF8String: anObject
tagBER "... avoid the namespace lookup." ^02r00001100 "ASN1.UniversalUTF8String = 12"
</methods> <methods> ASN1.REAL <category>encoding</category>
encodeValue: aLimitedPrecisionReal with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeREAL: aLimitedPrecisionReal
tagBER "... avoid the namespace lookup." ^02r00001001 "ASN1.UniversalREAL = 9"
</methods> <methods> ASN1.GraphicString <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00011001 "ASN1.UniversalGraphicString = 25"
</methods> <methods> Core.OrderedCollection <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." ^aMarshaler encodeSEQUENCEorSEQUENCE_OF: self
tagBER "... avoid the namespace lookup." ^02r00110000 "ASN1.ConstructedSEQUENCE = 48"
</methods> <methods> ASN1.IA5String <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeIA5String: anInteger
</methods> <methods> ASN1.IA5String <category>encoding</category>
encodeValue: aByteString with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeIA5String: aByteString
tagBER "... avoid the namespace lookup." ^02r00010110 "ASN1.UniversalIA5String = 22"
</methods> <methods> ASN1.Enumeration <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." ^aMarshaler encodeENUMERATED: self
tagBER "... avoid the namespace lookup." ^02r00001010 "ASN1.UniversalENUMERATED = 10"
</methods> <methods> ASN1.INTEGER <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeINTEGER: anInteger
</methods> <methods> ASN1.INTEGER <category>encoding</category>
encodeValue: anInteger with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeINTEGER: anInteger
tagBER "... avoid the namespace lookup." ^02r00000010 "ASN1.UniversalINTEGER = 2"
</methods> <methods> ASN1.SET <category>encoding</category>
orderedElementsFor: aMarshaler ^( aMarshaler requiresTagSort ) ifTrue: [ SortedCollection withAll: elements sortBlock: [:x :y | x tagBER <= y tagBER ] ] ifFalse: [ elements ]
tagBER "... avoid the namespace lookup." ^02r00110001 "ASN1.ConstructedSET = 49"
</methods> <methods> ASN1.Choice <category>marshaling - asn1</category>
asn1ChoiceType ^choice type
asn1ChoiceValue ^self _value
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." aMarshaler encodeTLV: self _value withElement: choice
</methods> <methods> Core.UndefinedObject <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." ^aMarshaler encodeNULL
tagBER "... avoid the namespace lookup." ^02r00000101 "ASN1.UniversalNULL = 5"
</methods> <methods> ASN1.PrintableString <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodePrintableString: anInteger
</methods> <methods> ASN1.PrintableString <category>encoding</category>
encodeValue: aByteString with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodePrintableString: aByteString
tagBER "... avoid the namespace lookup." ^02r00010011 "ASN1.UniversalPrintableString = 19"
</methods> <methods> ASN1.OBJECT_IDENTIFIER <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeOBJECT_IDENTIFIER: anInteger
</methods> <methods> ASN1.OBJECT_IDENTIFIER <category>encoding</category>
encodeValue: anAsn1ImportedOID with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeOBJECT_IDENTIFIER: anAsn1ImportedOID
tagBER "... avoid the namespace lookup." ^02r00000110 "ASN1.UniversalOBJECT_IDENTIFIER = 6"
</methods> <methods> ASN1.VisibleString <category>encoding</category>
encodeValue: aByteString with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeVisibleString: aByteString
tagBER "... avoid the namespace lookup." ^02r00011010 "ASN1.UniversalVisibleString = 26"
</methods> <methods> Core.Integer <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API. This will also work if the Integer is the 'name' of an ENUMERATED." ^aMarshaler encodeINTEGER: self
tagBER "... avoid the namespace lookup." ^02r00000010 "ASN1.UniversalINTEGER = 2"
</methods> <methods> ASN1.UTCTime <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeUTCTime: anInteger
</methods> <methods> ASN1.UTCTime <category>encoding</category>
encodeValue: aTimestamp with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeUTCTime: aTimestamp
tagBER "... avoid the namespace lookup." ^02r00010111 "ASN1.UniversalUTCTime = 23"
</methods> <methods> Core.Boolean <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." ^aMarshaler encodeBOOLEAN: self
tagBER "... avoid the namespace lookup." ^02r00000001 "ASN1.UniversalBOOLEAN = 1"
</methods> <methods> ASN1.MarkerElement <category>decoding</category>
decode: anObject with: aMarshaler
</methods> <methods> ASN1.MarkerElement <category>encoding</category>
encode: anObject with: aMarshaler
</methods> <methods> ASN1.ObjectIdentifier <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." ^aMarshaler encodeOBJECT_IDENTIFIER: self
tagBER "... avoid the namespace lookup." ^02r00000110 "ASN1.UniversalOBJECT_IDENTIFIER = 6"
</methods> <methods> ASN1.NULL <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeNULL: anInteger
</methods> <methods> ASN1.NULL <category>encoding</category>
encodeValue: anUndefinedObject with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeNULL
tagBER "... avoid the namespace lookup." ^02r00000101 "ASN1.UniversalNULL = 5"
</methods> <methods> ASN1.VideotexString <category>encoding</category>
encodeValue: anObject with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." self obsoleteType
tagBER "... avoid the namespace lookup." ^02r00010101 "ASN1.UniversalVideotexString = 21"
</methods> <methods> Core.PositionableStream <category>ASN.1</category>
shift: increment from: start to: end | newEnd | newEnd := end + increment. collection growToAtLeast: newEnd. "the check for need to grow is done by #growToAtLeast:" collection replaceFrom: start + increment to: newEnd with: collection startingAt: start. readLimit := end + increment max: readLimit
</methods> <methods> ASN1.BOOLEAN <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeBOOLEAN: anInteger
</methods> <methods> ASN1.BOOLEAN <category>encoding</category>
encodeValue: aBoolean with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeBOOLEAN: aBoolean
tagBER "... avoid the namespace lookup." ^02r00000001 "ASN1.UniversalBOOLEAN = 1"
</methods> <methods> ASN1.BitString <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." "... only the primitive encoding." ^aMarshaler encodeBIT_STRING: self
tagBER "... avoid the namespace lookup." ^02r00000011 "ASN1.UniversalBIT_STRING = 3"
</methods> <methods> ASN1.NumericString <category>encoding</category>
encodeValue: aByteString with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeNumericString: aByteString
tagBER "... avoid the namespace lookup." ^02r00010010 "ASN1.UniversalNumericString = 18"
</methods> <methods> ASN1.BMPString <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeBMPString: anInteger
</methods> <methods> ASN1.BMPString <category>encoding</category>
encodeValue: anObject with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeBMPString: anObject
tagBER "... avoid the namespace lookup." ^02r00011110 "ASN1.UniversalBMPString = 30"
</methods> <methods> ASN1.OCTET_STRING <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeOCTET_STRING: anInteger
</methods> <methods> ASN1.OCTET_STRING <category>encoding</category>
encodeValue: aByteArray with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeOCTET_STRING: aByteArray
tagBER "... avoid the namespace lookup." ^02r00000100 "ASN1.UniversalOCTET_STRING = 4"
</methods> <methods> ASN1.GeneralString <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00011011 "ASN1.UniversalGeneralString = 27"
</methods> <methods> ASN1.SEQUENCE <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00110000 "ASN1.ConstructedSEQUENCE = 48"
</methods> <methods> ASN1.BIT_STRING <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeBIT_STRING: anInteger
</methods> <methods> ASN1.BIT_STRING <category>encoding</category>
encodeValue: anAsn1BitString with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeBIT_STRING: anAsn1BitString
tagBER "... avoid the namespace lookup." ^02r00000011 "ASN1.UniversalBIT_STRING = 3"
</methods> <methods> ASN1.UniversalString <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." ^aMarshaler decodeUniversalString: anInteger
</methods> <methods> ASN1.UniversalString <category>encoding</category>
encodeValue: anObject with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeUniversalString: anObject
tagBER "... avoid the namespace lookup." ^02r00011100 "ASN1.UniversalUniversalString = 28"
</methods> <methods> Core.ByteArray <category>marshaling - asn1</category>
encodeASN1With: aMarshaler "... the generic, double-dispatch encoding API." ^aMarshaler encodeOCTET_STRING: self
tagBER "... avoid the namespace lookup." ^02r00000100 "ASN1.UniversalOCTET_STRING = 4"
</methods> <methods> ASN1.UnstructuredType <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." | oc tpos | oc := OrderedCollection new: 11. tpos := aMarshaler position + anInteger. [ aMarshaler position < tpos ] whileTrue: [ oc add: ( elementType decodeWith: aMarshaler ) ]. ^oc
</methods> <methods> ASN1.UnstructuredType <category>encoding</category>
encodeValue: anOrderedCollection with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." anOrderedCollection do: [ :x | elementType encode: x with: aMarshaler ]
</methods> <methods> ASN1.ENUMERATED <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." | val | val := aMarshaler decodeENUMERATED: anInteger. ^self useEnumeration ifTrue: [ val asAsn1Enumeration: self ] ifFalse: [ val ]
</methods> <methods> ASN1.ENUMERATED <category>encoding</category>
encodeValue: aValue with: aMarshaler "... the method invoked when marshaling type wrappers or marshaling type-in-hand." aMarshaler encodeENUMERATED: (aValue asAsn1Enumeration: self) _integer
tagBER "... avoid the namespace lookup." ^02r00001010 "ASN1.UniversalENUMERATED = 10"
</methods> <methods> ASN1.CHOICE <category>testing</category>
canEncodeValue ^false
</methods> <methods> ASN1.CHOICE <category>encoding</category>
decodeDelegateWith: aMarshaler | ele eTag value | eTag := aMarshaler peekTag. ele := self elementWithTag: eTag ifNone: [ aMarshaler tagMismatch: eTag with: self ]. value := ele decodeWith: aMarshaler. ^self useChoice ifTrue: [ Choice type: self choice: ele value: value ] ifFalse: [ value ]
encodeDelegate: anObject with: aMarshaler ( elements detect: [ :e | e permits: anObject ] ifNone: [ MarshalingError new messageText: ( #InvalidChoice1p2p << #asn1 >> '<1p> is not valid choice for <2p>!' expandMacrosWith: anObject with: self); parameter: anObject; raise ] ) encode: anObject with: aMarshaler
</methods> <methods> ASN1.SET_OF <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00110001 "ASN1.ConstructedSET = 49"
</methods> <methods> ASN1.ANY <category>testing</category>
canEncodeValue ^false
</methods> <methods> ASN1.ANY <category>decoding</category>
decodeDelegateWith: aMarshaler ^aMarshaler decodeTLV "| ele eTag | eTag := aMarshaler peekTag. ele := self elementWithTag: eTag ifNone: [ aMarshaler tagMismatch: eTag with: self ]. ^Asn1Choice type: self choiceSymbol: ele symbol value: (ele decodeWith: aMarshaler)"
decodeWith: aMarshaler for: anObject "Dispatch from structured type elements." ^definedBy ifNil: [ self decodeDelegateWith: aMarshaler ] ifNotNil: [ | key type | key := definedBy valueFrom: anObject. type := typeMap at: key ifAbsent: [ self raiseUnknownDiscriminator: key ]. type decodeWith: aMarshaler for: anObject ]
</methods> <methods> ASN1.ANY <category>encoding</category>
encode: value with: marshaler for: container "Dispatch from structured type elements." definedBy ifNil: [ self encodeDelegate: value with: marshaler ] ifNotNil: [ | key type | key := definedBy valueFrom: container. type := typeMap at: key ifAbsent: [ self raiseUnknownDiscriminator: key ]. type encode: value with: marshaler for: container ]
encodeDelegate: anObject with: aMarshaler anObject _isTypeWrapper ifTrue: [ anObject _type encode: anObject _value with: aMarshaler ] ifFalse: [ aMarshaler encodeTLV: anObject ] "| ele eTag | eTag := aMarshaler peekTag. ele := self elementWithTag: eTag ifNone: [ aMarshaler tagMismatch: eTag with: self ]. ^Asn1Choice type: self choiceSymbol: ele symbol value: (ele decodeWith: aMarshaler)"
</methods> <methods> ASN1.ANY <category>decoding</category>
raiseUnknownDiscriminator: value ^MarshalingError raiseSignal: ( #UnknownANYDiscriminator << #asn1 >> 'Unknown discriminator value <1p> for <2p> in <3p>!' expandMacrosWith: value with: self with: definedBy owner)
</methods> <methods> ASN1.ANY <category>encoding</category>
tagBER ^nil
</methods> <methods> ASN1.Type <category>testing</category>
canEncodeValue ^true
</methods> <methods> ASN1.Type <category>encoding</category>
contextTagFrom: anInteger ^anInteger bitOr: ContextSpecificClass
</methods> <methods> ASN1.Type <category>decoding</category>
decodeValue: anInteger with: aMarshaler "... the method invoked when unmarshaling type-in-hand." self error: (#NotImplemented << #asn1 >> 'This function has not been implemented in this release.')
decodeWith: aMarshaler ^self tag ifNil: [ self canEncodeValue ifTrue: [ aMarshaler decodeWith: self ] ifFalse: [ aMarshaler decodeTaglessWith: self ] ] ifNotNil: [ :t || ct | ct := self contextTagFrom: t. self isImplicitlyTagged ifTrue: [ aMarshaler decodeWith: self implicitTag: ct ] ifFalse: [ aMarshaler decodeWith: self explicitTag: ct ] ]
decodeWith: aMarshaler for: anObject "Dispatch from structured type elements." ^self decodeWith: aMarshaler
</methods> <methods> ASN1.Type <category>encoding</category>
encode: anObject with: aMarshaler self tag ifNil: [ aMarshaler encode: anObject with: self ] ifNotNil: [ :t || ctag | ctag := self contextTagFrom: t. self isImplicitlyTagged ifTrue: [ aMarshaler encode: anObject with: self implicitTag: ctag ] ifFalse: [ aMarshaler encode: anObject with: self explicitTag: ctag ] ]
encode: value with: marshaler for: container "Dispatch from structured type elements." self encode: value with: marshaler
encodeBody: anObject with: aMarshaler self encodeValue: anObject with: aMarshaler
encodeValue: anObject with: aMarshaler self subclassResponsibility
</methods> <methods> ASN1.Type <category>testing</category>
matchesTag: anInteger | ttag | ttag := tag ifNil: [ self tagBER ] ifNotNil: [ tag ]. ^((ttag bitXor: anInteger) bitAnd: TagMaskNumber) isZero
</methods> <methods> ASN1.Type <category>accessing</category>
parent ^nil
</methods> <methods> ASN1.Type <category>encoding</category>
tagBER self subclassResponsibility
</methods> <methods> ASN1.ObjectDescriptor <category>encoding</category>
tagBER "... avoid the namespace lookup." ^02r00000111 "ASN1.UniversalObjectDescriptor = 7"
</methods> <initialize> ASN1.TLVStream </initialize> <initialize> ASN1.BERStreamBasic </initialize> <initialize> ASN1.BERStreamDefinite </initialize> <initialize> ASN1.DERStream </initialize> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>Object</name> <environment>Core</environment> <super></super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>UndefinedObject</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>BitString</name> <environment>ASN1</environment> <super>ASN1.Imported</super> <private>false</private> none unused <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Support</package> </attributes> </class> <class> <name>Asn1Error</name> <environment>ASN1</environment> <super>Core.Error</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Support</package> </attributes> </class> <class> <name>Integer</name> <environment>Core</environment> <super>Core.Number</super> <private>false</private> none <imports></imports> <category>Magnitude-Numbers</category> <attributes> <package>Magnitude-Numbers</package> </attributes> </class> <class> <name>Boolean</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>Type</name> <environment>ASN1</environment> <super>ASN1.Entity</super> <private>false</private> none constraint retainEncoding tag tagging defaultConstraint <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>UnstructuredType</name> <environment>ASN1</environment> <super>ASN1.ConstructedType</super> <private>false</private> none elementType <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>UniversalString</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>SEQUENCE_OF</name> <environment>ASN1</environment> <super>ASN1.UnstructuredType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>GeneralString</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>TeletexString</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>RELATIVE_OID</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>NULL</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>ObjectDescriptor</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>MarkerElement</name> <environment>ASN1</environment> <super>ASN1.AbstractElement</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>CHOICE</name> <environment>ASN1</environment> <super>ASN1.StructuredType</super> <private>false</private> none tags useChoice defaultUseChoice <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>ANY</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none definedBy typeMap <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>ENUMERATED</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none elements extensibleAt useEnumeration complete defaultUseEnumeration <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>BIT_STRING</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>OrderedCollection</name> <environment>Core</environment> <super>Core.SequenceableCollection</super> <private>false</private> objects firstIndex lastIndex <imports></imports> <category>Collections-Sequenceable</category> <attributes> <package>Collections-Sequenceable</package> </attributes> </class> <class> <name>OCTET_STRING</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>BMPString</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>BOOLEAN</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>REAL</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>VideotexString</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>UTF8String</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>ObjectIdentifier</name> <environment>ASN1</environment> <super>ASN1.Imported</super> <private>false</private> none encoding <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Support</package> </attributes> </class> <class> <name>MappableType</name> <environment>ASN1</environment> <super>ASN1.StructuredType</super> <private>false</private> none mapping <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>SEQUENCE</name> <environment>ASN1</environment> <super>ASN1.MappableType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>SET</name> <environment>ASN1</environment> <super>ASN1.MappableType</super> <private>false</private> none decodingDictionary encodingDictionary <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>Stream</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none <imports> private IOConstants.* </imports> <category>Collections-Streams</category> <attributes> <package>Collections-Streams</package> </attributes> </class> <class> <name>PositionableStream</name> <environment>Core</environment> <super>Core.PeekableStream</super> <private>false</private> none collection position readLimit writeLimit policy <imports></imports> <category>Collections-Streams</category> <attributes> <package>Collections-Streams</package> </attributes> </class> <class> <name>ByteArray</name> <environment>Core</environment> <super>Core.IntegerArray</super> <private>false</private> bytes <imports></imports> <category>Collections-Arrayed</category> <attributes> <package>Collections-Arrayed</package> </attributes> </class> <class> <name>TypeWrapper</name> <environment>ASN1</environment> <super>Protocols.MessageForwarder</super> <private>false</private> none encoding type <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>Choice</name> <environment>ASN1</environment> <super>ASN1.TypeWrapper</super> <private>false</private> none choice <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>Enumeration</name> <environment>ASN1</environment> <super>ASN1.TypeWrapper</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>ChoiceElement</name> <environment>ASN1</environment> <super>ASN1.AbstractElement</super> <private>false</private> none owner symbol type <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>StructureElement</name> <environment>ASN1</environment> <super>ASN1.ChoiceElement</super> <private>false</private> none default optional <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>OBJECT_IDENTIFIER</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>Struct</name> <environment>ASN1</environment> <super>Protocols.Struct</super> <private>false</private> objects encoding <imports></imports> <category>ASN1-Support</category> <attributes> <package>ASN1-Support</package> </attributes> </class> <class> <name>INTEGER</name> <environment>ASN1</environment> <super>ASN1.BasicType</super> <private>false</private> none identifiers <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>ByteString</name> <environment>Core</environment> <super>Core.ByteEncodedString</super> <private>false</private> bytes <imports></imports> <category>Collections-String Support</category> <attributes> <package>Collections-String Support</package> </attributes> </class> <class> <name>IA5String</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>VisibleString</name> <environment>ASN1</environment> <super>ASN1.IA5String</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>UTCTime</name> <environment>ASN1</environment> <super>ASN1.VisibleString</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>NumericString</name> <environment>ASN1</environment> <super>ASN1.IA5String</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>GeneralizedTime</name> <environment>ASN1</environment> <super>ASN1.VisibleString</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>PrintableString</name> <environment>ASN1</environment> <super>ASN1.IA5String</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>SET_OF</name> <environment>ASN1</environment> <super>ASN1.UnstructuredType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class> <class> <name>Timestamp</name> <environment>Core</environment> <super>Core.Magnitude</super> <private>false</private> none year month day hour minute second millisecond <imports></imports> <category>UIBasics-Support</category> <attributes> <package>UIBasics-Support</package> </attributes> </class> <class> <name>GraphicString</name> <environment>ASN1</environment> <super>ASN1.StringType</super> <private>false</private> none <imports></imports> <category>ASN1</category> <attributes> <package>ASN1-Types</package> </attributes> </class>