Object subclass: #QuotedPrintableCoder instanceVariableNames: '' classVariableNames: '' poolDictionaries: ''! !QuotedPrintableCoder class publicMethods ! decode: aString | input output char outChar | input := aString readStream. output := WriteStream on: (String new: aString size). [input atEnd] whileFalse: [ char := input next. outChar := (char = $= ifTrue: [ (char := input next) = Character cr ifTrue: [ "soft line break ( see rfc 2045) - just ignore and skip the next character if it is an Lf (Windows)" input next = Character lf ifFalse: [input skip: -1]. nil] ifFalse: [ "This is an encoded character with a leading =" Character codePoint: char asUppercase digitValue * 16 + input next asUppercase digitValue]] ifFalse: [char]). outChar notNil ifTrue: [output nextPut: outChar]]. ^output contents! encode: aString | input output char charValue lineLength | input := aString readStream. output := WriteStream on: (String new: aString size). lineLength := 0. [input atEnd] whileFalse: [ lineLength >= 74 ifTrue: [ output nextPut: $=. output nextPutAll: output lineDelimiter. "This may be a Cr only or a CrLf" lineLength := 0]. char := input next. charValue := char asInteger. (charValue = 9 | (charValue between: 32 and: 60) | (charValue between: 62 and: 126)) ifTrue: [ output nextPut: char. lineLength := lineLength + 1] ifFalse: [ char = Character cr ifTrue: [ output nextPutAll: '=0D=0A'. input next = Character lf ifFalse: [input skip: -1]. "if on our platform a line end is cr+lf, ignore the lf" lineLength := 0] ifFalse: [ output nextPut: $=. output nextPutAll: (char asInteger abtHexPaddedTo: 2). lineLength := lineLength + 3]]]. ^output contents! !