packages feed

gnuidn 0.1.1.2 → 0.2

raw patch · 6 files changed

+453/−135 lines, 6 filesdep ~basedep ~bytestringdep ~textPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, bytestring, text

API changes (from Hackage documentation)

- Data.Text.IDN.StringPrep: ErrorBidiBothLAndRAL :: Error
- Data.Text.IDN.StringPrep: ErrorBidiContainsProhibited :: Error
- Data.Text.IDN.StringPrep: ErrorBidiLeadTrailNotRAL :: Error
- Data.Text.IDN.StringPrep: ErrorContainsProhibited :: Error
- Data.Text.IDN.StringPrep: ErrorContainsUnassigned :: Error
- Data.Text.IDN.StringPrep: ErrorInconsistentProfile :: Error
- Data.Text.IDN.StringPrep: ErrorInvalidFlag :: Error
- Data.Text.IDN.StringPrep: ErrorNormalisationFailed :: Error
- Data.Text.IDN.StringPrep: ErrorUnknown :: Integer -> Error
- Data.Text.IDN.StringPrep: instance Eq Error
- Data.Text.IDN.StringPrep: instance Show Error
- Data.Text.IDN.StringPrep: profileISCSI :: Profile
- Data.Text.IDN.StringPrep: profileKerberos5 :: Profile
- Data.Text.IDN.StringPrep: profileNameprep :: Profile
- Data.Text.IDN.StringPrep: profileNodeprep :: Profile
- Data.Text.IDN.StringPrep: profilePlain :: Profile
- Data.Text.IDN.StringPrep: profileResourceprep :: Profile
- Data.Text.IDN.StringPrep: profileSaslPrep :: Profile
- Data.Text.IDN.StringPrep: profileTrace :: Profile
+ Data.Text.IDN.IDNA: Flags :: Bool -> Bool -> Flags
+ Data.Text.IDN.IDNA: allowUnassigned :: Flags -> Bool
+ Data.Text.IDN.IDNA: data Error
+ Data.Text.IDN.IDNA: data Flags
+ Data.Text.IDN.IDNA: defaultFlags :: Flags
+ Data.Text.IDN.IDNA: instance Enum Idna_flags
+ Data.Text.IDN.IDNA: instance Enum Idna_rc
+ Data.Text.IDN.IDNA: instance Eq Flags
+ Data.Text.IDN.IDNA: instance Show Flags
+ Data.Text.IDN.IDNA: toASCII :: Flags -> Text -> Either Error ByteString
+ Data.Text.IDN.IDNA: toUnicode :: Flags -> ByteString -> Text
+ Data.Text.IDN.IDNA: verifySTD3 :: Flags -> Bool
+ Data.Text.IDN.Punycode: decode :: ByteString -> Maybe (Text, Integer -> Bool)
+ Data.Text.IDN.Punycode: encode :: Text -> Maybe (Integer -> Bool) -> ByteString
+ Data.Text.IDN.Punycode: instance Enum Punycode_status
+ Data.Text.IDN.StringPrep: instance Enum Stringprep_profile_flags
+ Data.Text.IDN.StringPrep: instance Enum Stringprep_rc
+ Data.Text.IDN.StringPrep: instance Eq Flags
+ Data.Text.IDN.StringPrep: instance Show Flags
+ Data.Text.IDN.StringPrep: iscsi :: Profile
+ Data.Text.IDN.StringPrep: kerberos5 :: Profile
+ Data.Text.IDN.StringPrep: nameprep :: Profile
+ Data.Text.IDN.StringPrep: sasl :: Profile
+ Data.Text.IDN.StringPrep: saslAnonymous :: Profile
+ Data.Text.IDN.StringPrep: trace :: Profile
+ Data.Text.IDN.StringPrep: xmppNode :: Profile
+ Data.Text.IDN.StringPrep: xmppResource :: Profile

Files

+ Data/Text/IDN/IDNA.chs view
@@ -0,0 +1,117 @@+{-# LANGUAGE ForeignFunctionInterface #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+-- +-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- 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 General Public License for more details.+-- +-- You should have received a copy of the GNU General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++module Data.Text.IDN.IDNA+	( Flags (..)+	, Error+	, defaultFlags+	, toASCII+	, toUnicode+	) where++import Control.Exception (ErrorCall(..), throwIO)+import qualified Data.ByteString as B+import qualified Data.Text as T++import Foreign+import Foreign.C++import Data.Text.IDN.Internal++#include <idna.h>+#include <idn-free.h>++{# enum Idna_rc {} with prefix = "IDNA_" #}++{# enum Idna_flags {} with prefix = "IDNA_" #}++data Flags = Flags+	{ verifySTD3 :: Bool+	-- ^ Check output to make sure it is a STD3-conforming host name+	+	, allowUnassigned :: Bool+	-- ^ Allow unassigned Unicode code points+	}+	deriving (Show, Eq)++-- | @defaultFlags = Flags True False@+defaultFlags :: Flags+defaultFlags = Flags True False++-- | Convert a Unicode domain name to an ASCII 'B.ByteString'. The domain+-- name may contain several labels, separated by periods.+--+-- @toASCII@ never alters a sequence of code points that are all in the+-- ASCII range to begin with (although it could fail). Applying @toASCII@+-- multiple times gives the same result as applying it once.+toASCII :: Flags -> T.Text -> Either Error B.ByteString+toASCII flags input =+	unsafePerformIO $+	withArray0 0 (toUCS4 input) $ \buf ->+	let c_flags = encodeFlags flags in+	alloca $ \outBufPtr -> do+		c_rc <- {# call idna_to_ascii_4z #}+			(castPtr buf) outBufPtr c_flags+		+		let rc = fromIntegral c_rc+		if rc /= fromEnum SUCCESS+			then return (Left (cToError c_rc))+			else do+				outBuf <- peek outBufPtr+				bytes <- B.packCString outBuf+				{# call idn_free #} (castPtr outBuf)+				return (Right bytes)++-- | Convert a possibly ACE-encoded domain name to Unicode. The domain+-- name may contain several labels, separated by dots.+--+-- Aside from memory allocation failure, @toUnicode@ always succeeds.+-- If the input cannot be decoded, it is returned unchanged.+toUnicode :: Flags -> B.ByteString -> T.Text+toUnicode flags input =+	unsafePerformIO $+	B.useAsCString input $ \buf ->+	let c_flags = encodeFlags flags in+	alloca $ \outBufPtr -> do+		c_rc <- {# call idna_to_unicode_8z4z #}+			(castPtr buf) outBufPtr c_flags+		+		let rc = fromIntegral c_rc+		if rc == fromEnum MALLOC_ERROR+			then throwError c_rc+			else do+				outBuf <- peek outBufPtr+				ucs4 <- peekArray0 0 (castPtr outBuf)+				{# call idn_free #} (castPtr outBuf)+				return (fromUCS4 ucs4)++encodeFlags :: Flags -> CInt+encodeFlags flags = foldr (.|.) 0 bits where+	bitAt f e = if f flags then 0 else fromIntegral (fromEnum e)+	bits = [ bitAt verifySTD3 USE_STD3_ASCII_RULES+	       , bitAt allowUnassigned ALLOW_UNASSIGNED+	       ]++cToError :: CInt -> Error+cToError rc = IDNAError (T.pack str) where+	c_strerror = {# call idna_strerror #}+	str = unsafePerformIO (c_strerror rc >>= peekCString)++throwError :: CInt -> IO a+throwError rc = do+	str <- peekCString =<< {# call idna_strerror #} rc+	throwIO (ErrorCall str)
+ Data/Text/IDN/Internal.hs view
@@ -0,0 +1,35 @@+-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+-- +-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- 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 General Public License for more details.+-- +-- You should have received a copy of the GNU General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++module Data.Text.IDN.Internal+	( Error (..)+	, toUCS4+	, fromUCS4+	) where++import qualified Data.Text as T+import Data.Char (chr, ord)++import qualified Foreign as F++data Error = IDNAError T.Text+           | StringPrepError T.Text+	deriving (Show, Eq)++toUCS4 :: T.Text -> [F.Word32]+toUCS4 = map (fromIntegral . ord) . T.unpack++fromUCS4 :: [F.Word32] -> T.Text+fromUCS4 = T.pack . map (chr . fromIntegral)
+ Data/Text/IDN/Punycode.chs view
@@ -0,0 +1,143 @@+{-# LANGUAGE ForeignFunctionInterface #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+-- +-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- 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 General Public License for more details.+-- +-- You should have received a copy of the GNU General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++-- | Punycode is a simple and efficient transfer encoding syntax designed+-- for use with Internationalized Domain Names in Applications (IDNA). It+-- uniquely and reversibly transforms a Unicode string into ASCII. ASCII+-- characters in the Unicode string are represented literally, and non-ASCII+-- characters are represented by ASCII characters that are allowed in host+-- name labels (letters, digits, and hyphens).+module Data.Text.IDN.Punycode+	( encode+	, decode+	) where++import Control.Exception (ErrorCall(..), throwIO)+import Control.Monad (unless)+import Data.List (unfoldr)+import qualified Data.ByteString as B+import qualified Data.Text as T++import Foreign+import Foreign.C++import Data.Text.IDN.Internal (toUCS4, fromUCS4)++#include <punycode.h>++-- | Encode unicode into an ASCII-only 'B.ByteString'. If provided, the+-- case predicate indicates whether to uppercase the corresponding character+-- after decoding.+encode :: T.Text+       -> Maybe (Integer -> Bool)+       -> B.ByteString+encode input maybeIsCase = unsafePerformIO io where+	inSize = T.length input+	+	flags = flip fmap maybeIsCase $ \isCase -> let+		step idx = Just (fromBool (isCase idx), idx + 1)+		in unfoldr step 0+	+	io = maybeWith (withArray . take inSize) flags impl+	+	impl caseBuf = withArray (toUCS4 input) (loop caseBuf inSize . castPtr)+	+	loop caseBuf outMax inBuf = do+		res <- tryEnc caseBuf outMax inBuf+		case res of+			Nothing -> loop caseBuf (outMax + 50) inBuf+			Just (Right bytes) -> return bytes+			Just (Left rc) -> cToError rc+	+	tryEnc caseBuf outMax inBuf =+		allocaBytes outMax $ \outBuf ->+		alloca $ \outSizeBuf -> do+			poke outSizeBuf (fromIntegral outMax)+			c_rc <- {# call punycode_encode #}+				(fromIntegral inSize)+				inBuf+				caseBuf+				outSizeBuf+				outBuf+			+			let rc = fromIntegral c_rc+			if rc == fromEnum OVERFLOW+				then return Nothing+				else if rc == fromEnum SUCCESS+					then do+						outSize <- peek outSizeBuf+						bytes <- peekOut outBuf outSize+						return (Just (Right bytes))+					else return (Just (Left c_rc))+	+	peekOut outBuf outSize = B.packCStringLen cstr where+		cstr = (outBuf, fromIntegral outSize)++-- | Decode a 'B.ByteString' into unicode. The second component of the+-- result is a case predicate; it indicates whether a particular character+-- position of the result string should be upper-cased.+--+-- Returns 'Nothing' if the input is invalid.+decode :: B.ByteString+       -> Maybe (T.Text, (Integer -> Bool))+decode input = unsafePerformIO $+	let outMax = B.length input in+	B.useAsCStringLen input $ \(inBuf, inSize) ->+	alloca $ \outSizeBuf ->+	allocaArray outMax $ \outBuf -> do+	+	flagForeign <- mallocForeignPtrArray outMax+	poke outSizeBuf (fromIntegral outMax)+	+	c_rc <- withForeignPtr flagForeign $ \flagBuf ->+		{# call punycode_decode #}+			(fromIntegral inSize)+			inBuf+			outSizeBuf+			outBuf+			flagBuf+	+	let rc = fromIntegral c_rc+	if rc == fromEnum BAD_INPUT+		then return Nothing+		else do+			unless (rc == fromEnum SUCCESS) (cToError c_rc)+			+			outSize <- peek outSizeBuf+			ucs4 <- peekArray (fromIntegral outSize) (castPtr outBuf)+			let text = fromUCS4 ucs4+			return (Just (text, checkCaseFlag flagForeign outSize))++type SizeT = {# type size_t #}++{# enum Punycode_status {} with prefix = "PUNYCODE_" #}++checkCaseFlag :: ForeignPtr CUChar -> SizeT -> Integer -> Bool+checkCaseFlag ptr csize = checkIdx where+	intsize = toInteger csize+	checkIdx idx | idx < 0        = False+	checkIdx idx | idx >= intsize = False+	checkIdx idx =+		unsafePerformIO $+		withForeignPtr ptr $ \buf -> do+			cuchar <- peekElemOff buf (fromInteger idx)+			return (toBool cuchar)++cToError :: CInt -> IO a+cToError rc = do+	str <- peekCString =<< {# call punycode_strerror #} rc+	throwIO (ErrorCall str)
+ Data/Text/IDN/StringPrep.chs view
@@ -0,0 +1,147 @@+{-# LANGUAGE ForeignFunctionInterface #-}++-- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>+-- +-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- 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 General Public License for more details.+-- +-- You should have received a copy of the GNU General Public License+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.++module Data.Text.IDN.StringPrep+	(+	-- * Stringprep+	  Flags (..)+	, Error+	, defaultFlags+	, stringprep+	+	-- * Profiles+	, Profile+	, iscsi+	, kerberos5+	, nameprep+	, sasl+	, saslAnonymous+	, trace+	, xmppNode+	, xmppResource+	) where++import qualified Data.ByteString as B+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE++import Foreign+import Foreign.C++import Data.Text.IDN.Internal++#include <stringprep.h>++{# pointer *Stringprep_profile as Profile newtype #}++{# enum Stringprep_rc {} with prefix = "STRINGPREP_" #}++{# enum Stringprep_profile_flags {} with prefix = "STRINGPREP_" #}++data Flags = Flags+	{ enableNFKC :: Bool+	-- ^ Enable the NFKC normalization, as well as selecting the NFKC+	-- case folding tables. Usually the profile specifies BIDI and NFKC+	-- settings, and applications should not override it unless in+	-- special situations.+	+	, enableBidi :: Bool+	-- ^ Enable the BIDI step. Usually the profile specifies BIDI and+	-- NFKC settings, and applications should not override it unless in+	-- special situations.+	+	, allowUnassigned :: Bool+	-- ^ If false, 'stringprep' will return an error if the input+	-- contains characters not assigned to the profile.+	}+	deriving (Show, Eq)++-- | @defaultFlags = Flags True True False@+defaultFlags :: Flags+defaultFlags = Flags True True False++stringprep :: Profile -> Flags -> T.Text -> Either Error T.Text+stringprep profile flags input = unsafePerformIO io where+	io = B.useAsCString utf8 (loop inSize)+	+	utf8 = TE.encodeUtf8 input+	c_flags = encodeFlags flags+	inSize = B.length utf8 + 1 -- + 1 for NUL+	+	loop outSize inBuf = do+		res <- tryPrep outSize inBuf+		case res of+			Nothing -> loop (outSize + 50) inBuf+			Just (Right bytes) -> return (Right (TE.decodeUtf8 bytes))+			Just (Left rc) -> return (Left (cToError rc))+	+	tryPrep outSize inBuf = allocaBytes outSize $ \outBuf -> do+		copyArray outBuf inBuf inSize+		let csize = fromIntegral outSize+		c_rc <- {# call stringprep as c_stringprep #}+			outBuf csize c_flags profile+		+		let rc = fromIntegral c_rc+		if rc == fromEnum TOO_SMALL_BUFFER+			then return Nothing+			else if rc == fromEnum OK+				then fmap (Just . Right) (B.packCString outBuf)+				else return (Just (Left c_rc))++encodeFlags :: Flags -> CInt+encodeFlags flags = foldr (.|.) 0 bits where+	bitAt f e = if f flags then 0 else fromIntegral (fromEnum e)+	bits = [ bitAt enableNFKC NO_NFKC+	       , bitAt enableBidi NO_BIDI+	       , bitAt allowUnassigned NO_UNASSIGNED+	       ]++cToError :: CInt -> Error+cToError rc = StringPrepError (T.pack str) where+	c_strerror = {# call stringprep_strerror #}+	str = unsafePerformIO (c_strerror rc >>= peekCString)++-- | iSCSI (RFC 3722)+foreign import ccall "&stringprep_iscsi"+	iscsi :: Profile++-- | Kerberos 5+foreign import ccall "&stringprep_kerberos5"+	kerberos5 :: Profile++-- | Nameprep (RFC 3491)+foreign import ccall "&stringprep_nameprep"+	nameprep :: Profile++-- | SASLprep (RFC 4013)+foreign import ccall "&stringprep_saslprep"+	sasl :: Profile++-- | Draft SASL ANONYMOUS+foreign import ccall "&stringprep_plain"+	saslAnonymous :: Profile++foreign import ccall "&stringprep_trace"+	trace :: Profile++-- | XMPP node (RFC 3920)+foreign import ccall "&stringprep_xmpp_nodeprep"+	xmppNode :: Profile++-- | XMPP resource (RFC 3920)+foreign import ccall "&stringprep_xmpp_resourceprep"+	xmppResource :: Profile
− Data/Text/IDN/StringPrep.hs
@@ -1,132 +0,0 @@--- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>--- --- This program is free software: you can redistribute it and/or modify--- it under the terms of the GNU General Public License as published by--- the Free Software Foundation, either version 3 of the License, or--- 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 General Public License for more details.--- --- You should have received a copy of the GNU General Public License--- along with this program.  If not, see <http://www.gnu.org/licenses/>.--{-# LANGUAGE ForeignFunctionInterface #-}-module Data.Text.IDN.StringPrep-	(-	-- * Stringprep-	  Flags (..)-	, Error (..)-	, defaultFlags-	, stringprep-	-	-- * Profiles-	, Profile-	, profileNameprep-	, profileSaslPrep-	, profilePlain-	, profileTrace-	, profileKerberos5-	, profileNodeprep-	, profileResourceprep-	, profileISCSI-	) where-import Data.Bits ((.|.))-import qualified Data.ByteString as B-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Encoding as TE-import qualified Foreign as F-import qualified Foreign.C as F-import System.IO.Unsafe (unsafePerformIO)--data Error-	= ErrorContainsUnassigned-	| ErrorContainsProhibited-	| ErrorBidiBothLAndRAL-	| ErrorBidiLeadTrailNotRAL-	| ErrorBidiContainsProhibited-	| ErrorInconsistentProfile-	| ErrorInvalidFlag-	| ErrorNormalisationFailed-	| ErrorUnknown Integer-	deriving (Show, Eq)--data Flags = Flags-	{ enableNFKC :: Bool-	, enableBidi :: Bool-	, allowUnassigned :: Bool-	}--newtype Profile = Profile (F.Ptr Profile)--defaultFlags :: Flags-defaultFlags = Flags True True False--stringprep :: Profile -> Flags -> TL.Text -> Either Error TL.Text-stringprep profile flags input = unsafePerformIO io where-	utf8 = TE.encodeUtf8 $ T.concat $ TL.toChunks input-	cflags = encodeFlags flags-	len = B.length utf8 + 1 -- + 1 for NUL-	io = B.useAsCString utf8 (loop len)-	loop bufsize pIn = F.allocaBytes bufsize $ \buf -> do-		F.copyArray buf pIn len-		let csize = fromIntegral bufsize-		rc <- c_stringprep buf csize cflags profile-		case rc of-			-- TOO_SMALL_BUFFER-			100 -> loop (bufsize + 50) pIn-			-			0 -> do-				bytes <- B.packCString buf-				return $ Right $ TL.fromChunks [TE.decodeUtf8 bytes]-			_ -> return $ Left $ cToError rc--encodeFlags :: Flags -> F.CInt-encodeFlags flags = foldr (.|.) 0 bits where-	bit f x y = if f flags then x else y-	bits = [ bit enableNFKC 0 1-	       , bit enableBidi 0 2-	       , bit allowUnassigned 0 4-	       ]--cToError :: F.CInt -> Error-cToError x = case x of-	1 -> ErrorContainsUnassigned-	2 -> ErrorContainsProhibited-	3 -> ErrorBidiBothLAndRAL-	4 -> ErrorBidiLeadTrailNotRAL-	5 -> ErrorBidiContainsProhibited-	101 -> ErrorInconsistentProfile-	102 -> ErrorInvalidFlag-	200 -> ErrorNormalisationFailed-	_ -> ErrorUnknown $ toInteger x--foreign import ccall "stringprep"-	c_stringprep :: F.CString -> F.CSize -> F.CInt -> Profile -> IO F.CInt--foreign import ccall "&stringprep_nameprep"-	profileNameprep :: Profile--foreign import ccall "&stringprep_saslprep"-	profileSaslPrep :: Profile--foreign import ccall "&stringprep_plain"-	profilePlain :: Profile--foreign import ccall "&stringprep_trace"-	profileTrace :: Profile--foreign import ccall "&stringprep_kerberos5"-	profileKerberos5 :: Profile--foreign import ccall "&stringprep_xmpp_nodeprep"-	profileNodeprep :: Profile--foreign import ccall "&stringprep_xmpp_resourceprep"-	profileResourceprep :: Profile--foreign import ccall "&stringprep_iscsi"-	profileISCSI :: Profile
gnuidn.cabal view
@@ -1,5 +1,5 @@ name: gnuidn-version: 0.1.1.2+version: 0.2 stability: experimental synopsis: Bindings for GNU IDN license: GPL-3@@ -22,11 +22,19 @@    build-depends:       base >= 3 && < 5-    , text >= 0.2 && < 0.11-    , bytestring >= 0.9 && < 0.10+    , text+    , bytestring    extra-libraries: idn   pkgconfig-depends: libidn +  build-tools:+    c2hs+   exposed-modules:+    Data.Text.IDN.IDNA+    Data.Text.IDN.Punycode     Data.Text.IDN.StringPrep++  other-modules:+    Data.Text.IDN.Internal