"
(C) 2011 by Holger Hans Peter Freyther
All Rights Reserved
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
"
Object subclass: BERTag [
| classType tagValue constructed |
BERTag class >> classUniversal [
^ 0
]
BERTag class >> classApplication [
^ 1
]
BERTag class >> classContext [
^ 2
]
BERTag class >> classPrivate [
^ 3
]
BERTag class >> new [
^ super new initialize
]
BERTag class >> parseFrom: aStream [
^ self new
parseFrom: aStream;
yourself
]
BERTag class >> fromTuple: aTuple [
^ self new
fromTuple: aTuple;
yourself
]
BERTag class >> endOfContents [
^ self fromTuple: #(0 false 0)
]
BERTag class >> boolean [
^ self fromTuple: #(0 false 1)
]
BERTag class >> integer [
^ self fromTuple: #(0 false 2)
]
BERTag class >> octetString [
^ self fromTuple: #(0 false 4)
]
BERTag class >> null [
^ self fromTuple: #(0 false 5)
]
BERTag class >> enumerated [
^ self fromTuple: #(0 false 10)
]
BERTag class >> sequence [
^ self fromTuple: #(0 true 16)
]
BERTag class >> set [
^ self fromTuple: #(0 true 17)
]
initialize [
classType := BERTag classUniversal.
tagValue := 0.
constructed := false.
]
= aOther [
(aOther isKindOf: self class) ifTrue: [^self asTuple = aOther asTuple].
^ self asTuple = aOther.
]
parseExtendedTag: aStream [
^ self error: 'Extended tags are not implemented yet'.
]
parseFrom: aStream [
| tmp |
tmp := aStream next.
classType := (tmp bitAnd: 16rC0) bitShift: -6.
constructed := (tmp bitAnd: 16r20) > 0.
tagValue := tmp bitAnd: 16r1F.
"This is an extended tag"
(tagValue = 16r1F) ifTrue: [
self parseExtendedTag: aStream.
].
]
fromTuple: aTuple [
classType := aTuple first bitAnd: 16r3.
constructed := aTuple second.
tagValue := aTuple third.
]
writeExtendedTag: aStream [
self error: 'Cannot encode extended tag.'
]
writeOn: aStream [
tagValue >= 16r1F
ifTrue: [self writeExtendedTag: aStream.]
ifFalse: [| tag |
tag := classType bitShift: 6.
self isConstructed ifTrue: [tag := tag bitOr: 16r20].
tag := tag bitOr: self tagValue.
aStream nextPut: tag.
].
]
classType [
^ classType
]
isConstructed [
^ constructed
]
isPrimitive [
^ self isConstructed not
]
tagValue [
^ tagValue
]
asTuple [
^ Array with: self classType with: self isConstructed with: self tagValue.
]
printOn: aStream [
^ aStream nextPutAll: '%1 %2' % {self class. self asTuple.}
]
]
Object subclass: BERLength [
BERLength class >> new [
^ self error: 'Only use the class helper functions'
]
BERLength class >> parseMultiOctet: len from: aStream [
"I should handle paragraph 8.1.3.5. But I don't."
^ self error: 'Decoding multi octet length is not implemented'.
]
BERLength class >> parseFrom: aStream [
| len |
len := aStream next.
^ (len bitAnd: 16r80) > 0
ifTrue: [self parseMultiOctet: len from: aStream]
ifFalse: [len].
]
BERLength class >> writeMultiOctet: aLength on: aStream [
^ self error: 'Multi octet writing is not implemented yet'.
]
BERLength class >> writeLength: aLength on: aStream [
^ aLength > 16r7F
ifTrue: [self writeMultiOctet: aLength on: aStream]
ifFalse: [aStream nextPut: aLength].
]
]
Object subclass: BERTLVStream [
| base |
BERTLVStream class >> on: aStream [
^ self new
stream: aStream;
yourself
]
stream: aStream [
base := aStream.
]
atEnd [
^ base atEnd
]
next [
| tag len dat |
tag := BERTag parseFrom: base.
len := BERLength parseFrom: base.
dat := base next: len.
^ Array with: tag with: dat.
]
nextAll [
| ret |
ret := OrderedCollection new.
[self atEnd] whileFalse: [ret add: self next].
^ ret
]
nextAllRecursive [
| ret |
ret := OrderedCollection new.
[self atEnd] whileFalse: [| dat |
dat := self next.
dat first isConstructed
ifTrue: [|other|
other := (self class on: dat second readStream) nextAllRecursive.
ret add: (Array with: dat first with: other)]
ifFalse: [ret add: dat].
].
^ ret
]
]
BERTLVStream subclass: DERTLVStream [
nextPut: aTuple [
aTuple first writeOn: base.
aTuple first isConstructed
ifTrue: [
| stream der |
stream := WriteStream on: (base species new: 1).
(self class on: stream) nextPutAll: aTuple second.
BERLength writeLength: stream contents size on: base.
base nextPutAll: stream contents.
]
ifFalse: [
BERLength writeLength: aTuple second size on: base.
base nextPutAll: aTuple second.
].
]
nextPutAll: aTupleList [
aTupleList do: [:each | self nextPut: each].
]
]