|
|
|
|
@ -1,5 +1,11 @@
@@ -1,5 +1,11 @@
|
|
|
|
|
-- Picklers and unpicklers convert Haskell data to XML and XML to Haskell data, |
|
|
|
|
-- respectively. By convensions, pickler/unpickler ("PU") function names start |
|
|
|
|
-- out with "xp". |
|
|
|
|
|
|
|
|
|
{-# Language OverloadedStrings, ViewPatterns, NoMonomorphismRestriction #-} |
|
|
|
|
|
|
|
|
|
{-# OPTIONS_HADDOCK hide #-} |
|
|
|
|
|
|
|
|
|
module Network.XMPP.Marshal where |
|
|
|
|
|
|
|
|
|
import Data.XML.Pickle |
|
|
|
|
@ -11,15 +17,6 @@ import Network.XMPP.Types
@@ -11,15 +17,6 @@ import Network.XMPP.Types
|
|
|
|
|
xpStreamEntity :: PU [Node] (Either XmppStreamError Stanza) |
|
|
|
|
xpStreamEntity = xpEither xpStreamError xpStanza |
|
|
|
|
|
|
|
|
|
stanzaSel :: Stanza -> Int |
|
|
|
|
stanzaSel (IQRequestS _) = 0 |
|
|
|
|
stanzaSel (IQResultS _) = 1 |
|
|
|
|
stanzaSel (IQErrorS _) = 2 |
|
|
|
|
stanzaSel (MessageS _) = 3 |
|
|
|
|
stanzaSel (MessageErrorS _) = 4 |
|
|
|
|
stanzaSel (PresenceS _) = 5 |
|
|
|
|
stanzaSel (PresenceErrorS _) = 6 |
|
|
|
|
|
|
|
|
|
xpStanza :: PU [Node] Stanza |
|
|
|
|
xpStanza = xpAlt stanzaSel |
|
|
|
|
[ xpWrap IQRequestS (\(IQRequestS x) -> x) xpIQRequest |
|
|
|
|
@ -30,14 +27,22 @@ xpStanza = xpAlt stanzaSel
@@ -30,14 +27,22 @@ xpStanza = xpAlt stanzaSel
|
|
|
|
|
, xpWrap PresenceS (\(PresenceS x) -> x) xpPresence |
|
|
|
|
, xpWrap PresenceErrorS (\(PresenceErrorS x) -> x) xpPresenceError |
|
|
|
|
] |
|
|
|
|
where |
|
|
|
|
-- Selector for which pickler to execute above. |
|
|
|
|
stanzaSel :: Stanza -> Int |
|
|
|
|
stanzaSel (IQRequestS _) = 0 |
|
|
|
|
stanzaSel (IQResultS _) = 1 |
|
|
|
|
stanzaSel (IQErrorS _) = 2 |
|
|
|
|
stanzaSel (MessageS _) = 3 |
|
|
|
|
stanzaSel (MessageErrorS _) = 4 |
|
|
|
|
stanzaSel (PresenceS _) = 5 |
|
|
|
|
stanzaSel (PresenceErrorS _) = 6 |
|
|
|
|
|
|
|
|
|
xpMessage :: PU [Node] (Message) |
|
|
|
|
xpMessage = xpWrap (\((tp, qid, from, to, lang), (sub, body, thr, ext)) |
|
|
|
|
-> Message qid from to lang tp sub thr body ext) |
|
|
|
|
(\(Message qid from to lang tp sub thr body ext) |
|
|
|
|
-> ((tp, qid, from, to, lang), (sub, body, thr, ext))) |
|
|
|
|
$ |
|
|
|
|
xpElem "{jabber:client}message" |
|
|
|
|
xpMessage = xpWrap |
|
|
|
|
(\((tp, qid, from, to, lang), ext) -> Message qid from to lang tp ext) |
|
|
|
|
(\(Message qid from to lang tp ext) -> ((tp, qid, from, to, lang), ext)) |
|
|
|
|
(xpElem "{jabber:client}message" |
|
|
|
|
(xp5Tuple |
|
|
|
|
(xpDefault Normal $ xpAttr "type" xpPrim) |
|
|
|
|
(xpAttrImplied "id" xpPrim) |
|
|
|
|
@ -46,21 +51,14 @@ xpMessage = xpWrap (\((tp, qid, from, to, lang), (sub, body, thr, ext))
@@ -46,21 +51,14 @@ xpMessage = xpWrap (\((tp, qid, from, to, lang), (sub, body, thr, ext))
|
|
|
|
|
(xpAttrImplied xmlLang xpPrim) |
|
|
|
|
-- TODO: NS? |
|
|
|
|
) |
|
|
|
|
(xp4Tuple |
|
|
|
|
(xpOption . xpElemNodes "{jabber:client}subject" $ xpContent xpId) |
|
|
|
|
(xpOption . xpElemNodes "{jabber:client}body" $ xpContent xpId) |
|
|
|
|
(xpOption . xpElemNodes "{jabber:client}thread" $ xpContent xpId) |
|
|
|
|
(xpAll xpElemVerbatim) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
xpPresence :: PU [Node] Presence |
|
|
|
|
xpPresence = xpWrap (\((qid, from, to, lang, tp),(shw, stat, prio, ext)) |
|
|
|
|
-> Presence qid from to lang tp shw stat prio ext) |
|
|
|
|
(\(Presence qid from to lang tp shw stat prio ext) |
|
|
|
|
-> ((qid, from, to, lang, tp), (shw, stat, prio, ext))) |
|
|
|
|
$ |
|
|
|
|
xpElem "{jabber:client}presence" |
|
|
|
|
xpPresence = xpWrap |
|
|
|
|
(\((qid, from, to, lang, tp), ext) -> Presence qid from to lang tp ext) |
|
|
|
|
(\(Presence qid from to lang tp ext) -> ((qid, from, to, lang, tp), ext)) |
|
|
|
|
(xpElem "{jabber:client}presence" |
|
|
|
|
(xp5Tuple |
|
|
|
|
(xpAttrImplied "id" xpPrim) |
|
|
|
|
(xpAttrImplied "from" xpPrim) |
|
|
|
|
@ -68,20 +66,14 @@ xpPresence = xpWrap (\((qid, from, to, lang, tp),(shw, stat, prio, ext))
@@ -68,20 +66,14 @@ xpPresence = xpWrap (\((qid, from, to, lang, tp),(shw, stat, prio, ext))
|
|
|
|
|
xpLangTag |
|
|
|
|
(xpAttrImplied "type" xpPrim) |
|
|
|
|
) |
|
|
|
|
(xp4Tuple |
|
|
|
|
(xpOption . xpElemNodes "{jabber:client}show" $ xpContent xpPrim) |
|
|
|
|
(xpOption . xpElemNodes "{jabber:client}status" $ xpContent xpId) |
|
|
|
|
(xpOption . xpElemNodes "{jabber:client}priority" $ xpContent xpPrim) |
|
|
|
|
(xpAll xpElemVerbatim) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
xpIQRequest :: PU [Node] IQRequest |
|
|
|
|
xpIQRequest = xpWrap (\((qid, from, to, lang, tp),body) |
|
|
|
|
-> IQRequest qid from to lang tp body) |
|
|
|
|
(\(IQRequest qid from to lang tp body) |
|
|
|
|
-> ((qid, from, to, lang, tp), body)) |
|
|
|
|
$ |
|
|
|
|
xpElem "{jabber:client}iq" |
|
|
|
|
xpIQRequest = xpWrap |
|
|
|
|
(\((qid, from, to, lang, tp),body) -> IQRequest qid from to lang tp body) |
|
|
|
|
(\(IQRequest qid from to lang tp body) -> ((qid, from, to, lang, tp), body)) |
|
|
|
|
(xpElem "{jabber:client}iq" |
|
|
|
|
(xp5Tuple |
|
|
|
|
(xpAttr "id" xpPrim) |
|
|
|
|
(xpAttrImplied "from" xpPrim) |
|
|
|
|
@ -89,15 +81,14 @@ xpIQRequest = xpWrap (\((qid, from, to, lang, tp),body)
@@ -89,15 +81,14 @@ xpIQRequest = xpWrap (\((qid, from, to, lang, tp),body)
|
|
|
|
|
xpLangTag |
|
|
|
|
((xpAttr "type" xpPrim)) |
|
|
|
|
) |
|
|
|
|
(xpElemVerbatim) |
|
|
|
|
xpElemVerbatim |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
xpIQResult :: PU [Node] IQResult |
|
|
|
|
xpIQResult = xpWrap (\((qid, from, to, lang, _tp),body) |
|
|
|
|
-> IQResult qid from to lang body) |
|
|
|
|
(\(IQResult qid from to lang body) |
|
|
|
|
-> ((qid, from, to, lang, ()), body)) |
|
|
|
|
$ |
|
|
|
|
xpElem "{jabber:client}iq" |
|
|
|
|
xpIQResult = xpWrap |
|
|
|
|
(\((qid, from, to, lang, _tp),body) -> IQResult qid from to lang body) |
|
|
|
|
(\(IQResult qid from to lang body) -> ((qid, from, to, lang, ()), body)) |
|
|
|
|
(xpElem "{jabber:client}iq" |
|
|
|
|
(xp5Tuple |
|
|
|
|
(xpAttr "id" xpPrim) |
|
|
|
|
(xpAttrImplied "from" xpPrim) |
|
|
|
|
@ -106,23 +97,28 @@ xpIQResult = xpWrap (\((qid, from, to, lang, _tp),body)
@@ -106,23 +97,28 @@ xpIQResult = xpWrap (\((qid, from, to, lang, _tp),body)
|
|
|
|
|
((xpAttrFixed "type" "result")) |
|
|
|
|
) |
|
|
|
|
(xpOption xpElemVerbatim) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
---------------------------------------------------------- |
|
|
|
|
-- Errors |
|
|
|
|
---------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
xpErrorCondition :: PU [Node] StanzaErrorCondition |
|
|
|
|
xpErrorCondition = xpWrap (\(cond, (), ()) -> cond) (\cond -> (cond, (), ())) $ |
|
|
|
|
xpElemByNamespace |
|
|
|
|
"urn:ietf:params:xml:ns:xmpp-stanzas" xpPrim |
|
|
|
|
xpErrorCondition = xpWrap |
|
|
|
|
(\(cond, (), ()) -> cond) |
|
|
|
|
(\cond -> (cond, (), ())) |
|
|
|
|
(xpElemByNamespace |
|
|
|
|
"urn:ietf:params:xml:ns:xmpp-stanzas" |
|
|
|
|
xpPrim |
|
|
|
|
xpUnit |
|
|
|
|
xpUnit |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
xpStanzaError :: PU [Node] StanzaError |
|
|
|
|
xpStanzaError = xpWrap |
|
|
|
|
(\(tp, (cond, txt, ext)) -> StanzaError tp cond txt ext) |
|
|
|
|
(\(StanzaError tp cond txt ext) -> (tp, (cond, txt, ext))) $ |
|
|
|
|
xpElem "{jabber:client}error" |
|
|
|
|
(\(StanzaError tp cond txt ext) -> (tp, (cond, txt, ext))) |
|
|
|
|
(xpElem "{jabber:client}error" |
|
|
|
|
(xpAttr "type" xpPrim) |
|
|
|
|
(xp3Tuple |
|
|
|
|
xpErrorCondition |
|
|
|
|
@ -132,14 +128,15 @@ xpStanzaError = xpWrap
@@ -132,14 +128,15 @@ xpStanzaError = xpWrap
|
|
|
|
|
) |
|
|
|
|
(xpOption xpElemVerbatim) |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
xpMessageError :: PU [Node] (MessageError) |
|
|
|
|
xpMessageError = xpWrap (\((_, qid, from, to, lang), (err, ext)) |
|
|
|
|
-> MessageError qid from to lang err ext) |
|
|
|
|
(\(MessageError qid from to lang err ext) |
|
|
|
|
-> (((), qid, from, to, lang), (err, ext))) |
|
|
|
|
$ |
|
|
|
|
xpElem "{jabber:client}message" |
|
|
|
|
xpMessageError = xpWrap |
|
|
|
|
(\((_, qid, from, to, lang), (err, ext)) -> |
|
|
|
|
MessageError qid from to lang err ext) |
|
|
|
|
(\(MessageError qid from to lang err ext) -> |
|
|
|
|
(((), qid, from, to, lang), (err, ext))) |
|
|
|
|
(xpElem "{jabber:client}message" |
|
|
|
|
(xp5Tuple |
|
|
|
|
(xpAttrFixed "type" "error") |
|
|
|
|
(xpAttrImplied "id" xpPrim) |
|
|
|
|
@ -148,18 +145,16 @@ xpMessageError = xpWrap (\((_, qid, from, to, lang), (err, ext))
@@ -148,18 +145,16 @@ xpMessageError = xpWrap (\((_, qid, from, to, lang), (err, ext))
|
|
|
|
|
(xpAttrImplied xmlLang xpPrim) |
|
|
|
|
-- TODO: NS? |
|
|
|
|
) |
|
|
|
|
(xp2Tuple |
|
|
|
|
xpStanzaError |
|
|
|
|
(xpAll xpElemVerbatim) |
|
|
|
|
(xp2Tuple xpStanzaError (xpAll xpElemVerbatim)) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
xpPresenceError :: PU [Node] PresenceError |
|
|
|
|
xpPresenceError = xpWrap (\((qid, from, to, lang, _),(err, ext)) |
|
|
|
|
-> PresenceError qid from to lang err ext) |
|
|
|
|
(\(PresenceError qid from to lang err ext) |
|
|
|
|
-> ((qid, from, to, lang, ()), (err, ext))) |
|
|
|
|
$ |
|
|
|
|
xpElem "{jabber:client}presence" |
|
|
|
|
xpPresenceError = xpWrap |
|
|
|
|
(\((qid, from, to, lang, _),(err, ext)) -> |
|
|
|
|
PresenceError qid from to lang err ext) |
|
|
|
|
(\(PresenceError qid from to lang err ext) -> |
|
|
|
|
((qid, from, to, lang, ()), (err, ext))) |
|
|
|
|
(xpElem "{jabber:client}presence" |
|
|
|
|
(xp5Tuple |
|
|
|
|
(xpAttrImplied "id" xpPrim) |
|
|
|
|
(xpAttrImplied "from" xpPrim) |
|
|
|
|
@ -167,18 +162,16 @@ xpPresenceError = xpWrap (\((qid, from, to, lang, _),(err, ext))
@@ -167,18 +162,16 @@ xpPresenceError = xpWrap (\((qid, from, to, lang, _),(err, ext))
|
|
|
|
|
xpLangTag |
|
|
|
|
(xpAttrFixed "type" "error") |
|
|
|
|
) |
|
|
|
|
(xp2Tuple |
|
|
|
|
xpStanzaError |
|
|
|
|
(xpAll xpElemVerbatim) |
|
|
|
|
(xp2Tuple xpStanzaError (xpAll xpElemVerbatim)) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
xpIQError :: PU [Node] IQError |
|
|
|
|
xpIQError = xpWrap (\((qid, from, to, lang, _tp),(err, body)) |
|
|
|
|
-> IQError qid from to lang err body) |
|
|
|
|
(\(IQError qid from to lang err body) |
|
|
|
|
-> ((qid, from, to, lang, ()), (err, body))) |
|
|
|
|
$ |
|
|
|
|
xpElem "{jabber:client}iq" |
|
|
|
|
xpIQError = xpWrap |
|
|
|
|
(\((qid, from, to, lang, _tp),(err, body)) -> |
|
|
|
|
IQError qid from to lang err body) |
|
|
|
|
(\(IQError qid from to lang err body) -> |
|
|
|
|
((qid, from, to, lang, ()), (err, body))) |
|
|
|
|
(xpElem "{jabber:client}iq" |
|
|
|
|
(xp5Tuple |
|
|
|
|
(xpAttr "id" xpPrim) |
|
|
|
|
(xpAttrImplied "from" xpPrim) |
|
|
|
|
@ -186,9 +179,7 @@ xpIQError = xpWrap (\((qid, from, to, lang, _tp),(err, body))
@@ -186,9 +179,7 @@ xpIQError = xpWrap (\((qid, from, to, lang, _tp),(err, body))
|
|
|
|
|
xpLangTag |
|
|
|
|
((xpAttrFixed "type" "error")) |
|
|
|
|
) |
|
|
|
|
(xp2Tuple |
|
|
|
|
xpStanzaError |
|
|
|
|
(xpOption xpElemVerbatim) |
|
|
|
|
(xp2Tuple xpStanzaError (xpOption xpElemVerbatim)) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
xpStreamError :: PU [Node] XmppStreamError |
|
|
|
|
@ -196,22 +187,23 @@ xpStreamError = xpWrap
@@ -196,22 +187,23 @@ xpStreamError = xpWrap
|
|
|
|
|
(\((cond,() ,()), txt, el) -> XmppStreamError cond txt el) |
|
|
|
|
(\(XmppStreamError cond txt el) ->((cond,() ,()), txt, el)) |
|
|
|
|
(xpElemNodes |
|
|
|
|
(Name "error" |
|
|
|
|
(Name |
|
|
|
|
"error" |
|
|
|
|
(Just "http://etherx.jabber.org/streams") |
|
|
|
|
(Just "stream") |
|
|
|
|
) $ xp3Tuple |
|
|
|
|
) |
|
|
|
|
(xp3Tuple |
|
|
|
|
(xpElemByNamespace |
|
|
|
|
"urn:ietf:params:xml:ns:xmpp-streams" xpPrim |
|
|
|
|
"urn:ietf:params:xml:ns:xmpp-streams" |
|
|
|
|
xpPrim |
|
|
|
|
xpUnit |
|
|
|
|
xpUnit |
|
|
|
|
) |
|
|
|
|
(xpOption $ xpElem |
|
|
|
|
"{urn:ietf:params:xml:ns:xmpp-streams}text" |
|
|
|
|
xpLangTag |
|
|
|
|
(xpContent xpId)) |
|
|
|
|
( xpOption xpElemVerbatim |
|
|
|
|
-- application specific error conditions |
|
|
|
|
(xpContent xpId) |
|
|
|
|
) |
|
|
|
|
(xpOption xpElemVerbatim) -- Application specific error conditions |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|