You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
4.6 KiB
127 lines
4.6 KiB
{-# LANGUAGE OverloadedStrings #-} |
|
{-# LANGUAGE RecordWildCards #-} |
|
|
|
{-# OPTIONS_HADDOCK hide #-} |
|
|
|
module Network.Xmpp.Utilities (presTo, message, answerMessage, openElementToEvents, renderOpenElement, renderElement) where |
|
|
|
import Network.Xmpp.Types |
|
|
|
import Control.Monad.STM |
|
import Control.Concurrent.STM.TVar |
|
import Prelude |
|
|
|
import Data.XML.Types |
|
|
|
import qualified Data.Attoparsec.Text as AP |
|
import qualified Data.Text as Text |
|
|
|
import qualified Data.ByteString as BS |
|
import qualified Data.Text as Text |
|
import qualified Data.Text.Encoding as Text |
|
import System.IO.Unsafe(unsafePerformIO) |
|
import Data.Conduit.List as CL |
|
-- import Data.Typeable |
|
import Control.Applicative ((<$>)) |
|
import Control.Exception |
|
import Control.Monad.Trans.Class |
|
|
|
import Data.Conduit as C |
|
import Data.XML.Types |
|
|
|
import qualified Text.XML.Stream.Render as TXSR |
|
import Text.XML.Unresolved as TXU |
|
|
|
|
|
-- TODO: Not used, and should probably be removed. |
|
-- | Creates a new @IdGenerator@. Internally, it will maintain an infinite list |
|
-- of IDs ('[\'a\', \'b\', \'c\'...]'). The argument is a prefix to prepend the |
|
-- IDs with. Calling the function will extract an ID and update the generator's |
|
-- internal state so that the same ID will not be generated again. |
|
idGenerator :: Text.Text -> IO IdGenerator |
|
idGenerator prefix = atomically $ do |
|
tvar <- newTVar $ ids prefix |
|
return $ IdGenerator $ next tvar |
|
where |
|
-- Transactionally extract the next ID from the infinite list of IDs. |
|
next :: TVar [Text.Text] -> IO Text.Text |
|
next tvar = atomically $ do |
|
list <- readTVar tvar |
|
case list of |
|
[] -> error "empty list in Utilities.hs" |
|
(x:xs) -> do |
|
writeTVar tvar xs |
|
return x |
|
|
|
-- Generates an infinite and predictable list of IDs, all beginning with the |
|
-- provided prefix. Adds the prefix to all combinations of IDs (ids'). |
|
ids :: Text.Text -> [Text.Text] |
|
ids p = Prelude.map (\ id -> Text.append p id) ids' |
|
where |
|
-- Generate all combinations of IDs, with increasing length. |
|
ids' :: [Text.Text] |
|
ids' = Prelude.map Text.pack $ Prelude.concatMap ids'' [1..] |
|
-- Generates all combinations of IDs with the given length. |
|
ids'' :: Integer -> [String] |
|
ids'' 0 = [""] |
|
ids'' l = [x:xs | x <- repertoire, xs <- ids'' (l - 1)] |
|
-- Characters allowed in IDs. |
|
repertoire :: String |
|
repertoire = ['a'..'z'] |
|
|
|
-- Constructs a "Version" based on the major and minor version numbers. |
|
versionFromNumbers :: Integer -> Integer -> Version |
|
versionFromNumbers major minor = Version major minor |
|
|
|
-- | Add a recipient to a presence notification. |
|
presTo :: Presence -> Jid -> Presence |
|
presTo pres to = pres{presenceTo = Just to} |
|
|
|
-- | An empty message. |
|
message :: Message |
|
message = Message { messageID = Nothing |
|
, messageFrom = Nothing |
|
, messageTo = Nothing |
|
, messageLangTag = Nothing |
|
, messageType = Normal |
|
, messagePayload = [] |
|
} |
|
|
|
-- | Produce an answer message with the given payload, switching the "from" and |
|
-- "to" attributes in the original message. Produces a 'Nothing' value of the |
|
-- provided message message has no from attribute. |
|
answerMessage :: Message -> [Element] -> Maybe Message |
|
answerMessage Message{messageFrom = Just frm, ..} payload = |
|
Just Message{ messageFrom = messageTo |
|
, messageID = Nothing |
|
, messageTo = Just frm |
|
, messagePayload = payload |
|
, .. |
|
} |
|
answerMessage _ _ = Nothing |
|
|
|
openElementToEvents :: Element -> [Event] |
|
openElementToEvents (Element name as ns) = EventBeginElement name as : goN ns [] |
|
where |
|
goE (Element name' as' ns') = |
|
(EventBeginElement name' as' :) |
|
. goN ns' |
|
. (EventEndElement name' :) |
|
goN [] = id |
|
goN [x] = goN' x |
|
goN (x:xs) = goN' x . goN xs |
|
goN' (NodeElement e) = goE e |
|
goN' (NodeInstruction i) = (EventInstruction i :) |
|
goN' (NodeContent c) = (EventContent c :) |
|
goN' (NodeComment t) = (EventComment t :) |
|
|
|
renderOpenElement :: Element -> BS.ByteString |
|
renderOpenElement e = Text.encodeUtf8 . Text.concat . unsafePerformIO |
|
$ CL.sourceList (openElementToEvents e) $$ TXSR.renderText def =$ CL.consume |
|
|
|
renderElement :: Element -> BS.ByteString |
|
renderElement e = Text.encodeUtf8 . Text.concat . unsafePerformIO |
|
$ CL.sourceList (elementToEvents e) $$ TXSR.renderText def =$ CL.consume |
|
where |
|
elementToEvents :: Element -> [Event] |
|
elementToEvents e@(Element name _ _) = openElementToEvents e ++ [EventEndElement name]
|
|
|