{- Copyright © 2010-2011 Jon Kristensen. This file is part of Pontarius XMPP. Pontarius XMPP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Pontarius XMPP 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Pontarius XMPP. If not, see . -} -- | -- Module: $Header$ -- Description: JabberID (JID) data type and utility functions -- Copyright: Copyright © 2010-2011 Jon Kristensen -- License: LGPL-3 -- -- Maintainer: info@pontarius.org -- Stability: unstable -- Portability: portable -- -- JIDs are written in the format of `node@server/resource'. An example of a JID -- is `jonkri@jabber.org'. -- -- The node identifier is the part before the `@' character in Jabber IDs. Node -- names are optional. The server identifier is the part after the `@' character -- in Jabber IDs (and before the `/' character). The server identifier is the -- only required field of a JID. The server identifier MAY be an IP address but -- SHOULD be a fully qualified domain name. The resource identifier is the part -- after the `/' character in Jabber IDs. Like with node names, the resource -- identifier is optional. -- -- A JID without a resource identifier (i.e. a JID in the form of `node@server') -- is called `bare JID'. A JID with a resource identifier is called `full JID'. -- Node identifiers MUST be formatted in such a way so that the Nodeprep profile -- (see RFC 3920: XMPP Core, Appendix A) of RFC 3454: Preparation of -- Internationalized Strings (`stringprep') can be applied without failing. -- Servers MUST and clients SHOULD apply the Nodeprep profile to node names -- prior to comparing them. Node identifiers MUST NOT be more than 1023 bytes in -- length. -- -- If it is a domain name it MUST be an `internationalized domain name' as -- defined in RFC 3490: Internationalizing Domain Names in Applications (IDNA), -- to which RFC 3491: Nameprep: A Stringprep Profile for Internationalized -- Domain Names (IDN) can be applied without failing. Servers MUST and clients -- SHOULD first apply the Nameprep profile to the domain names prior to -- comparing them. Like with node names, server identifiers MUST NOT be more -- than 1023 bytes in length. -- -- A resource identifier has to be formatted in such a way so that the -- Resourceprep profile of RFC 3454: Preparation of Internationalized Strings -- (`stringprep') can be applied without failing. Servers MUST and clients -- SHOULD first apply the Resourceprep profile (see RFC 3920: XMPP Core, -- Appendix B) to resource names prior to comparing them. The resource -- identifier MUST MOT be more than 1023 bytes in length. -- -- Given the length of the `@' and `/' characters as well as the restrictions -- imposed on the node, server and resource identifiers, a JID will never be -- longer than 3071 bytes. -- TODO: Make the regular expression only match valid JIDs. -- TODO: Use Perl regular expressions to use non-capturing groups with "(?:"? -- TODO: Validate the input in the jid and stringToJID functions. module Network.XMPP.JID ( jid , jidIsFull , jidIsBare , stringToJID , jidToString ) where import Network.XMPP.Types import Text.Regex.Posix ((=~)) -- | Simple function to construct a JID. We will add validation to this function -- in a later release. jid :: Maybe String -> String -> Maybe String -> JID jid n s r = JID { jidNode = n, jidServer = s, jidResource = r } -- | Converts a (JID) String to a JID record. stringToJID :: String -> Maybe JID stringToJID string = matchToJID $ string =~ "^(([^@]+)@)?([^/]+)(/(.+))?$" where matchToJID [[_, _, "", server, _, ""]] = Just JID { jidNode = Nothing, jidServer = server, jidResource = Nothing } matchToJID [[_, _, node, server, _, ""]] = Just JID { jidNode = Just node , jidServer = server , jidResource = Nothing } matchToJID [[_, _, "", server, _, resource]] = Just JID { jidNode = Nothing , jidServer = server , jidResource = Just resource } matchToJID [[_, _, node, server, _, resource]] = Just JID { jidNode = Just node , jidServer = server , jidResource = Just resource } matchToJID _ = Nothing -- | Converts a JID to a String. jidToString :: JID -> String jidToString JID { jidNode = n, jidServer = s, jidResource = r } | n == Nothing && r == Nothing = s | r == Nothing = let Just n' = n in n' ++ "@" ++ s | n == Nothing = let Just r' = r in s ++ "/" ++ r' | otherwise = let Just n' = n; Just r' = r in n' ++ "@" ++ s ++ "/" ++ r' -- | JIDs are written in the format of `node@server/resource'. A JID without a -- resource identifier (i.e. a JID in the form of `server' or `node@server') -- is called a `bare JID'. A JID with a resource identifier is called `full -- JID'. This function returns True if the JID is `bare' and False otherwise. jidIsBare :: JID -> Bool jidIsBare j | jidResource j == Nothing = True | otherwise = False -- | JIDs are written in the format of `node@server/resource'. A JID without a -- resource identifier (i.e. a JID in the form of `server' or `node@server') -- is called a `bare JID'. A JID with a resource identifier is called `full -- JID'. This function returns True if the JID is `full' and False otherwise. -- This function is defined in terms of (not) jidIsBare. jidIsFull :: JID -> Bool jidIsFull jid = not $ jidIsBare jid