asn1-types 0.1.3 → 0.2.0
raw patch · 3 files changed
+152/−22 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.ASN1.Types: instance Eq ASN1StringEncoding
- Data.ASN1.Types: instance Ord ASN1StringEncoding
- Data.ASN1.Types: instance Show ASN1StringEncoding
+ Data.ASN1.Types: ASN1CharacterString :: ASN1StringEncoding -> ByteString -> ASN1CharacterString
+ Data.ASN1.Types: asn1CharacterString :: ASN1StringEncoding -> String -> ASN1CharacterString
+ Data.ASN1.Types: asn1CharacterToString :: ASN1CharacterString -> Maybe String
+ Data.ASN1.Types: characterEncoding :: ASN1CharacterString -> ASN1StringEncoding
+ Data.ASN1.Types: data ASN1CharacterString
+ Data.ASN1.Types: getCharacterStringRawData :: ASN1CharacterString -> ByteString
+ Data.ASN1.Types.String: ASN1CharacterString :: ASN1StringEncoding -> ByteString -> ASN1CharacterString
+ Data.ASN1.Types.String: BMP :: ASN1StringEncoding
+ Data.ASN1.Types.String: Character :: ASN1StringEncoding
+ Data.ASN1.Types.String: General :: ASN1StringEncoding
+ Data.ASN1.Types.String: Graphic :: ASN1StringEncoding
+ Data.ASN1.Types.String: IA5 :: ASN1StringEncoding
+ Data.ASN1.Types.String: Numeric :: ASN1StringEncoding
+ Data.ASN1.Types.String: Printable :: ASN1StringEncoding
+ Data.ASN1.Types.String: T61 :: ASN1StringEncoding
+ Data.ASN1.Types.String: UTF32 :: ASN1StringEncoding
+ Data.ASN1.Types.String: UTF8 :: ASN1StringEncoding
+ Data.ASN1.Types.String: VideoTex :: ASN1StringEncoding
+ Data.ASN1.Types.String: Visible :: ASN1StringEncoding
+ Data.ASN1.Types.String: asn1CharacterString :: ASN1StringEncoding -> String -> ASN1CharacterString
+ Data.ASN1.Types.String: asn1CharacterToString :: ASN1CharacterString -> Maybe String
+ Data.ASN1.Types.String: characterEncoding :: ASN1CharacterString -> ASN1StringEncoding
+ Data.ASN1.Types.String: data ASN1CharacterString
+ Data.ASN1.Types.String: data ASN1StringEncoding
+ Data.ASN1.Types.String: getCharacterStringRawData :: ASN1CharacterString -> ByteString
+ Data.ASN1.Types.String: instance Eq ASN1CharacterString
+ Data.ASN1.Types.String: instance Eq ASN1StringEncoding
+ Data.ASN1.Types.String: instance IsString ASN1CharacterString
+ Data.ASN1.Types.String: instance Ord ASN1CharacterString
+ Data.ASN1.Types.String: instance Ord ASN1StringEncoding
+ Data.ASN1.Types.String: instance Show ASN1CharacterString
+ Data.ASN1.Types.String: instance Show ASN1StringEncoding
- Data.ASN1.Types: ASN1String :: ASN1StringEncoding -> ByteString -> ASN1
+ Data.ASN1.Types: ASN1String :: ASN1CharacterString -> ASN1
Files
- Data/ASN1/Types.hs +9/−21
- Data/ASN1/Types/String.hs +141/−0
- asn1-types.cabal +2/−1
Data/ASN1/Types.hs view
@@ -1,5 +1,5 @@ -- |--- Module : Data.ASN1.Stream+-- Module : Data.ASN1.Types -- License : BSD-style -- Maintainer : Vincent Hanquez <vincent@snarc.org> -- Stability : experimental@@ -14,6 +14,9 @@ , ASN1StringEncoding(..) , ASN1TimeType(..) , ASN1Object(..)+ , ASN1CharacterString(..)+ , asn1CharacterString+ , asn1CharacterToString , module Data.ASN1.OID ) where @@ -22,6 +25,7 @@ import Data.ASN1.BitArray import Data.ASN1.OID import Data.ASN1.Types.Lowlevel+import Data.ASN1.Types.String import Data.ByteString (ByteString) -- | Define the type of container@@ -30,25 +34,9 @@ | Container ASN1Class ASN1Tag deriving (Show,Eq) --- T61 encoding : http://www.mail-archive.com/asn1@asn1.org/msg00460.html---- | Define all possible ASN1 String encoding.-data ASN1StringEncoding =- IA5 -- ^ 128 characters equivalent to the ASCII alphabet- | UTF8 -- ^ UTF8- | General -- ^ all registered graphic and character sets (see ISO 2375) plus SPACE and DELETE.- | Graphic -- ^ all registered G sets and SPACE- | Numeric -- ^ encoding containing numeric [0-9] and space- | Printable -- ^ printable [a-z] [A-Z] [()+,-.?:/=] and space.- | VideoTex -- ^ CCITT's T.100 and T.101 character sets- | Visible -- ^ International ASCII printing character sets- | T61 -- ^ teletext- | UTF32 -- ^ UTF32- | Character -- ^ Character- | BMP -- ^ UCS2- deriving (Show,Eq,Ord)--data ASN1TimeType = TimeUTC | TimeGeneralized+-- | Different ASN1 time representation+data ASN1TimeType = TimeUTC -- ^ ASN1 UTCTime Type: limited between 1950-2050+ | TimeGeneralized -- ^ ASN1 GeneralizedTime Type deriving (Show,Eq,Ord) -- | Define high level ASN1 object.@@ -61,7 +49,7 @@ | OID OID | Real Double | Enumerated Int- | ASN1String ASN1StringEncoding ByteString+ | ASN1String ASN1CharacterString | ASN1Time ASN1TimeType UTCTime (Maybe TimeZone) | Other ASN1Class ASN1Tag ByteString | Start ASN1ConstructionType
+ Data/ASN1/Types/String.hs view
@@ -0,0 +1,141 @@+-- |+-- Module : Data.ASN1.Types.String+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : unknown+--+-- Different String types available in ASN1+--+module Data.ASN1.Types.String+ ( ASN1StringEncoding(..)+ , ASN1CharacterString(..)+ , asn1CharacterString+ , asn1CharacterToString+ ) where++import Data.String+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import Data.Bits++-- a note on T61 encodings. The actual specification of a T61 character set seems+-- to be lost in time, as such it will be considered an ascii like encoding.+--+-- <http://www.mail-archive.com/asn1@asn1.org/msg00460.html>+-- "sizable volume of software in the world treats TeletexString (T61String)+-- as a simple 8-bit string with mostly Windows Latin 1"++-- | Define all possible ASN1 String encoding.+data ASN1StringEncoding =+ IA5 -- ^ 128 characters equivalent to the ASCII alphabet+ | UTF8 -- ^ UTF8+ | General -- ^ all registered graphic and character sets (see ISO 2375) plus SPACE and DELETE.+ | Graphic -- ^ all registered G sets and SPACE+ | Numeric -- ^ encoding containing numeric [0-9] and space+ | Printable -- ^ printable [a-z] [A-Z] [()+,-.?:/=] and space.+ | VideoTex -- ^ CCITT's T.100 and T.101 character sets+ | Visible -- ^ International ASCII printing character sets+ | T61 -- ^ teletext+ | UTF32 -- ^ UTF32+ | Character -- ^ Character+ | BMP -- ^ UCS2+ deriving (Show,Eq,Ord)++-- | provide a way to possibly encode or decode character string based on character encoding+stringEncodingFunctions :: ASN1StringEncoding+ -> Maybe (ByteString -> String, String -> ByteString)+stringEncodingFunctions encoding+ | encoding == UTF8 = Just (decodeUTF8, encodeUTF8)+ | encoding == BMP = Just (decodeBMP, encodeBMP)+ | encoding == UTF32 = Just (decodeUTF32, encodeUTF32)+ | encoding `elem` asciiLikeEncodings = Just (decodeASCII, encodeASCII)+ | otherwise = Nothing+ where asciiLikeEncodings = [IA5,Numeric,Printable,Visible,General,Graphic,T61]++-- | encode a string into a character string+asn1CharacterString :: ASN1StringEncoding -> String -> ASN1CharacterString+asn1CharacterString encoding s =+ case stringEncodingFunctions encoding of+ Just (_, e) -> ASN1CharacterString encoding (e s)+ Nothing -> error ("cannot encode ASN1 Character String " ++ show encoding ++ " from string")++-- | try to decode an 'ASN1CharacterString' to a String+asn1CharacterToString :: ASN1CharacterString -> Maybe String+asn1CharacterToString (ASN1CharacterString encoding bs) =+ case stringEncodingFunctions encoding of+ Just (d, _) -> Just (d bs)+ Nothing -> Nothing++-- | ASN1 Character String with encoding+data ASN1CharacterString = ASN1CharacterString+ { characterEncoding :: ASN1StringEncoding+ , getCharacterStringRawData :: ByteString+ } deriving (Show,Eq,Ord)++instance IsString ASN1CharacterString where+ fromString s = ASN1CharacterString UTF8 (encodeUTF8 s)++decodeUTF8 :: ByteString -> String+decodeUTF8 b+ | B.null b = []+ | otherwise =+ case B.index b 0 of+ v | v `isClear` 7 -> toEnum (fromIntegral v) : decodeUTF8 (B.drop 1 b)+ | v `isClear` 6 -> error "continuation byte"+ | v `isClear` 5 -> uncont 1 (v .&. 0x1f)+ | v `isClear` 4 -> uncont 2 (v .&. 0xf)+ | v `isClear` 3 -> uncont 3 (v .&. 0x7)+ | otherwise -> error "too many byte"+ where uncont n iniV+ | B.length b < (n+1) = error "cannot decode"+ | otherwise = let z = flip map [1..n] $ \i ->+ case B.index b (i+1) of+ v | v `testBit` 7 && v `isClear` 6 -> v .&. 0x3f+ | otherwise -> error "not a continuation byte"+ in (toEnum $ fromIntegral $ foldl (\acc v -> (acc `shiftL` 6) + v) iniV z) : decodeUTF8 (B.drop (1+n) b)+ isClear v i = not (v `testBit` i)++encodeUTF8 :: String -> ByteString+encodeUTF8 s = B.pack $ concatMap (toUTF8 . fromEnum) s+ where toUTF8 e+ | e < 0x80 = [fromIntegral e]+ | e < 0x800 = [fromIntegral (0xc0 .|. (e `shiftR` 6)), toCont e]+ | e < 0x10000 = [fromIntegral (0xe0 .|. (e `shiftR` 12))+ ,toCont (e `shiftR` 6)+ ,toCont e]+ | e < 0x200000 = [fromIntegral (0xf0 .|. (e `shiftR` 18))+ , toCont (e `shiftR` 12)+ , toCont (e `shiftR` 6)+ , toCont e]+ | otherwise = error "not a valid value"+ toCont v = fromIntegral (0xc0 .&. (v .&. 0x3f))++decodeASCII :: ByteString -> String+decodeASCII = BC.unpack++encodeASCII :: String -> ByteString+encodeASCII = BC.pack++decodeBMP :: ByteString -> String+decodeBMP b+ | odd (B.length b) = error "not a valid BMP string"+ | otherwise = undefined+encodeBMP :: String -> ByteString+encodeBMP s = B.pack $ concatMap (toUCS2 . fromEnum) s+ where toUCS2 v = [b0,b1]+ where b0 = fromIntegral (v `shiftR` 8)+ b1 = fromIntegral (v .&. 0xff)++decodeUTF32 :: ByteString -> String+decodeUTF32 b+ | (B.length b `mod` 4) /= 0 = error "not a valid UTF32 string"+ | otherwise = undefined+encodeUTF32 :: String -> ByteString+encodeUTF32 s = B.pack $ concatMap (toUTF32 . fromEnum) s+ where toUTF32 v = [b0,b1,b2,b3]+ where b0 = fromIntegral (v `shiftR` 24)+ b1 = fromIntegral ((v `shiftR` 16) .&. 0xff)+ b2 = fromIntegral ((v `shiftR` 8) .&. 0xff)+ b3 = fromIntegral (v .&. 0xff)
asn1-types.cabal view
@@ -1,5 +1,5 @@ Name: asn1-types-Version: 0.1.3+Version: 0.2.0 Description: ASN.1 standard types License: BSD3 License-file: LICENSE@@ -21,6 +21,7 @@ Exposed-modules: Data.ASN1.BitArray Data.ASN1.OID Data.ASN1.Types+ Data.ASN1.Types.String Data.ASN1.Types.Lowlevel ghc-options: -Wall