" (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]. ] ]