Browse Source

fixed JID parsing, moved JID to JID.hs

master
Philipp Balzarek 14 years ago
parent
commit
2f13935c0b
  1. 73
      src/Network/XMPP/JID.hs
  2. 34
      src/Network/XMPP/Types.hs

73
src/Network/XMPP/JID.hs

@ -15,28 +15,64 @@ @@ -15,28 +15,64 @@
--
-- This module does not internationalize hostnames.
module Network.XMPP.JID (fromString, fromStrings, isBare, isFull) where
module Network.XMPP.JID
( JID(..)
, fromText
, fromStrings
, isBare
, isFull) where
import Control.Applicative ((<$>),(<|>))
import Control.Monad(guard)
import qualified Data.Attoparsec.Text as AP
import Data.Maybe(fromJust)
import qualified Data.Set as Set
import Data.String (IsString(..))
import Data.Text (Text)
import qualified Data.Text as Text
-- import Network.URI (isIPv4address, isIPv6address)
import Network.XMPP.Types
import qualified Text.NamePrep as SP
import qualified Text.StringPrep as SP
-- |
-- @From@ is a readability type synonym for @Address@.
-- | Jabber ID (JID) datatype
data JID = JID { localpart :: !(Maybe Text)
-- ^ Account name
, domainpart :: !Text
-- ^ Server adress
, resourcepart :: !(Maybe Text)
-- ^ Resource name
}
instance Show JID where
show (JID nd dmn res) =
maybe "" ((++ "@") . Text.unpack) nd ++
(Text.unpack dmn) ++
maybe "" (('/' :) . Text.unpack) res
instance Read JID where
readsPrec _ x = case fromText (Text.pack x) of
Nothing -> []
Just j -> [(j,"")]
instance IsString JID where
fromString = fromJust . fromText . Text.pack
-- |
-- Converts a string to a JID.
fromString :: String -> Maybe JID
fromString s = fromStrings l d r
fromText :: Text -> Maybe JID
fromText t = do
(l, d, r) <- eitherToMaybe $ AP.parseOnly jidParts t
fromStrings l d r
where
Right (l, d, r) =
AP.parseOnly jidParts (Text.pack s)
eitherToMaybe = either (const Nothing) Just
-- |
-- Converts localpart, domainpart, and resourcepart strings to a JID.
@ -48,6 +84,8 @@ fromStrings l d r = do @@ -48,6 +84,8 @@ fromStrings l d r = do
Just l'-> do
l'' <- SP.runStringPrep nodeprepProfile l'
guard $ validPartLength l''
let prohibMap = Set.fromList nodeprepExtraProhibitedCharacters
guard $ Text.all (`Set.notMember` prohibMap) l''
return $ Just l''
domainPart <- SP.runStringPrep (SP.namePrepProfile False) d
guard $ validDomainPart domainPart
@ -93,21 +131,24 @@ jidParts = do @@ -93,21 +131,24 @@ jidParts = do
(x, Nothing, z) -> return (Nothing, x, z)
-- When we do have an "@", x is the localpart
(x, Just y, z) -> return (Just x, y, z)
where
firstPartP = AP.takeWhile1 (AP.notInClass ['@', '/'])
domainPartP = do
firstPartP = AP.takeWhile1 (AP.notInClass ['@', '/'])
domainPartP = do
_ <- AP.char '@'
AP.takeWhile1 (/= '/')
resourcePartP = do
resourcePartP = do
_ <- AP.char '/'
AP.takeText
nodeprepProfile :: SP.StringPrepProfile
nodeprepProfile = SP.Profile
{ SP.maps = [SP.b1, SP.b2]
, SP.shouldNormalize = True
, SP.prohibited = [SP.a1
, SP.c11
, SP.c12
, SP.c21
, SP.c22
, SP.c3
, SP.c4
, SP.c5
@ -115,10 +156,6 @@ nodeprepProfile = SP.Profile @@ -115,10 +156,6 @@ nodeprepProfile = SP.Profile
, SP.c7
, SP.c8
, SP.c9
, SP.c11
, SP.c12
, SP.c21
, SP.c22
]
, SP.shouldCheckBidi = True
}
@ -136,6 +173,9 @@ resourceprepProfile = SP.Profile @@ -136,6 +173,9 @@ resourceprepProfile = SP.Profile
{ SP.maps = [SP.b1]
, SP.shouldNormalize = True
, SP.prohibited = [ SP.a1
, SP.c12
, SP.c21
, SP.c22
, SP.c3
, SP.c4
, SP.c5
@ -143,9 +183,6 @@ resourceprepProfile = SP.Profile @@ -143,9 +183,6 @@ resourceprepProfile = SP.Profile
, SP.c7
, SP.c8
, SP.c9
, SP.c12
, SP.c21
, SP.c22
]
, SP.shouldCheckBidi = True
}

34
src/Network/XMPP/Types.hs

@ -33,6 +33,8 @@ import Data.XML.Types @@ -33,6 +33,8 @@ import Data.XML.Types
import qualified Network as N
import Network.XMPP.JID
import System.IO
@ -74,38 +76,6 @@ instance Read StanzaId where @@ -74,38 +76,6 @@ instance Read StanzaId where
instance IsString StanzaId where
fromString = SI . Text.pack
-- |
-- @From@ is a readability type synonym for @Address@.
-- | Jabber ID (JID) datatype
data JID = JID { localpart :: !(Maybe Text)
-- ^ Account name
, domainpart :: !Text
-- ^ Server adress
, resourcepart :: !(Maybe Text)
-- ^ Resource name
}
instance Show JID where
show (JID nd dmn res) =
maybe "" ((++ "@") . Text.unpack) nd ++
(Text.unpack dmn) ++
maybe "" (('/' :) . Text.unpack) res
parseJID :: [Char] -> [JID]
parseJID jid = do
(jid', rst) <- case L.splitOn "@" jid of
[rest] -> [(JID Nothing, rest)]
[nd,rest] -> [(JID (Just (Text.pack nd)), rest)]
_ -> []
case L.splitOn "/" rst of
[dmn] -> [jid' (Text.pack dmn) Nothing]
[dmn, rsrc] -> [jid' (Text.pack dmn) (Just (Text.pack rsrc))]
_ -> []
instance Read JID where
readsPrec _ x = (,"") <$> parseJID x
-- An Info/Query (IQ) stanza is either of the type "request" ("get" or
-- "set") or "response" ("result" or "error"). The @IQ@ type wraps
-- these two sub-types.

Loading…
Cancel
Save