4 * Extensible Messaging and Presence Protocol (XMPP) Core
6 * Portable Windows Library
8 * Copyright (c) 2004 Reitek S.p.A.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Post Increment
24 * Contributor(s): ______________________________________.
27 * Revision 1.2 2004/04/26 01:51:58 rjongbloed
28 * More implementation of XMPP, thanks a lot to Federico Pinna & Reitek S.p.A.
30 * Revision 1.1 2004/04/22 12:31:00 rjongbloed
31 * Added PNotifier extensions and XMPP (Jabber) support,
32 * thanks to Federico Pinna and Reitek S.p.A.
38 #pragma implementation "xmpp.h"
42 #include <ptclib/xmpp.h>
46 ///////////////////////////////////////////////////////
48 const PString
XMPP::Language("xml:lang");
49 const PString
XMPP::Namespace("xmlns");
50 const PString
XMPP::MessageStanza("message");
51 const PString
XMPP::PresenceStanza("presence");
52 const PString
XMPP::IQStanza("iq");
53 const PString
XMPP::IQQuery("query");
55 ///////////////////////////////////////////////////////
57 XMPP::JID::JID(const char * jid
)
63 XMPP::JID::JID(const PString
& jid
)
69 XMPP::JID::JID(const PString
& user
, const PString
& server
, const PString
& resource
)
70 : m_User(user
), m_Server(server
), m_Resource(resource
), m_IsDirty(TRUE
)
76 PObject::Comparison
XMPP::JID::Compare(const PObject
& obj
) const
78 if (PIsDescendant(&obj
, XMPP::JID
))
79 return m_JID
.Compare((const PString
&)((const XMPP::JID
&)obj
));
80 else if (PIsDescendant(&obj
, PString
))
81 return m_JID
.Compare((const PString
&)obj
);
83 PAssertAlways(PInvalidCast
);
84 return PObject::LessThan
;
88 PString
& XMPP::JID::operator=(const PString
& jid
)
95 XMPP::JID::operator const PString
&() const
104 void XMPP::JID::SetUser(const PString
& user
)
111 void XMPP::JID::SetServer(const PString
& server
)
118 void XMPP::JID::SetResource(const PString
& resource
)
121 m_Resource
= resource
;
125 void XMPP::JID::ParseJID(const PString
& jid
)
127 m_User
[0] = m_Server
[0] = m_Resource
[0] = 0;
129 PINDEX i
= jid
.Find('@');
131 if (i
== P_MAX_INDEX
|| i
== 0 || i
== (jid
.GetLength() - 1))
134 m_User
= jid
.Left(i
);
135 m_Server
= jid
.Mid(i
+ 1);
137 i
= m_Server
.Find('/');
139 if (i
== P_MAX_INDEX
|| i
== 0)
142 m_Resource
= m_Server
.Mid(i
+ 1);
143 m_Server
= m_Server
.Left(i
);
148 void XMPP::JID::BuildJID() const
150 m_JID
= m_User
+ "@" + m_Server
;
152 if (!m_Resource
.IsEmpty())
153 m_JID
+= "/" + m_Resource
;
158 ///////////////////////////////////////////////////////
160 XMPP::Stream::Stream(XMPP::Transport
* transport
)
161 : m_Parser(new PXMLStreamParser
)
168 XMPP::Stream::~Stream()
175 BOOL
XMPP::Stream::Close()
179 return PIndirectChannel::Close();
186 BOOL
XMPP::Stream::Write(const void * buf
, PINDEX len
)
188 PTRACE(5, "XMPP\tSND: " << (const char *)buf
);
189 return PIndirectChannel::Write(buf
, len
);
193 BOOL
XMPP::Stream::Write(const PString
& data
)
195 return Write((const char *)data
, data
.GetLength());
199 BOOL
XMPP::Stream::Write(const PXML
& pdu
)
201 PXMLElement
* root
= pdu
.GetRootElement();
207 root
->Output(os
, pdu
, 0);
208 return Write(os
.GetPointer(), os
.GetLength());
212 PXML
* XMPP::Stream::Read()
214 return m_Parser
->Read(this);
218 void XMPP::Stream::Reset()
221 m_Parser
= new PXMLStreamParser
;
224 ///////////////////////////////////////////////////////
226 XMPP::BaseStreamHandler::BaseStreamHandler()
229 m_AutoReconnect(TRUE
),
230 m_ReconnectTimeout(1000)
235 XMPP::BaseStreamHandler::~BaseStreamHandler()
241 BOOL
XMPP::BaseStreamHandler::Start(XMPP::Transport
* transport
)
243 if (m_Stream
!= NULL
)
246 m_Stream
= new XMPP::Stream();
247 m_Stream
->OpenHandlers().Add(new PCREATE_NOTIFIER(OnOpen
));
248 m_Stream
->CloseHandlers().Add(new PCREATE_NOTIFIER(OnClose
));
250 if (!transport
->IsOpen() && !transport
->Open())
253 if (m_Stream
->Open(transport
))
266 BOOL
XMPP::BaseStreamHandler::Stop(const PString
& _error
)
268 if (m_Stream
== NULL
)
271 if (!_error
.IsEmpty())
273 PString error
= "<stream:error><";
275 error
+= " xmlns='urn:ietf:params:xml:ns:xmpp-streams'/></stream:error>";
276 m_Stream
->Write((const char *)error
, error
.GetLength());
281 if (PThread::Current() != this)
282 WaitForTermination(10000);
288 void XMPP::BaseStreamHandler::OnOpen(XMPP::Stream
&, INT
)
293 void XMPP::BaseStreamHandler::OnClose(XMPP::Stream
&, INT
)
298 void XMPP::BaseStreamHandler::SetAutoReconnect(BOOL b
, long t
)
301 m_ReconnectTimeout
= t
;
305 BOOL
XMPP::BaseStreamHandler::Write(const void * buf
, PINDEX len
)
307 if (m_Stream
== NULL
)
310 return m_Stream
->Write(buf
, len
);
314 BOOL
XMPP::BaseStreamHandler::Write(const PString
& data
)
316 if (m_Stream
== NULL
)
319 return m_Stream
->Write(data
);
323 BOOL
XMPP::BaseStreamHandler::Write(const PXML
& pdu
)
325 if (m_Stream
== NULL
)
328 return m_Stream
->Write(pdu
);
332 void XMPP::BaseStreamHandler::OnElement(PXML
& pdu
)
334 m_ElementHandlers
.Fire(pdu
);
338 void XMPP::BaseStreamHandler::Main()
344 if (!m_Stream
|| !m_Stream
->IsOpen())
347 pdu
= m_Stream
->Read();
351 if (PTrace::CanTrace(5)) {
352 ostream
& os
= PTrace::Begin(5, __FILE__
, __LINE__
);
353 pdu
->GetRootElement()->Output(os
, *pdu
, 0);
367 ///////////////////////////////////////////////////////
369 const PString
XMPP::Stanza::ID("id");
370 const PString
XMPP::Stanza::From("from");
371 const PString
XMPP::Stanza::To("to");
373 void XMPP::Stanza::SetID(const PString
& id
)
376 PAssertNULL(rootElement
)->SetAttribute(XMPP::Stanza::ID
, id
);
379 void XMPP::Stanza::SetFrom(const PString
& from
)
382 PAssertNULL(rootElement
)->SetAttribute(XMPP::Stanza::From
, from
);
385 void XMPP::Stanza::SetTo(const PString
& to
)
388 PAssertNULL(rootElement
)->SetAttribute(XMPP::Stanza::To
, to
);
391 PString
XMPP::Stanza::GetID() const
392 { return PAssertNULL(rootElement
)->GetAttribute(XMPP::Stanza::ID
); }
394 PString
XMPP::Stanza::GetFrom() const
395 { return PAssertNULL(rootElement
)->GetAttribute(XMPP::Stanza::From
); }
397 PString
XMPP::Stanza::GetTo() const
398 { return PAssertNULL(rootElement
)->GetAttribute(XMPP::Stanza::To
); }
400 ///////////////////////////////////////////////////////
402 const PString
XMPP::Message::Type("type");
403 const PString
XMPP::Message::Subject("subject");
404 const PString
XMPP::Message::Body("body");
405 const PString
XMPP::Message::Thread("thread");
407 XMPP::Message::Message()
409 SetRootElement(new PXMLElement(NULL
, XMPP::MessageStanza
));
410 PWaitAndSignal
m(rootMutex
);
411 rootElement
->SetAttribute(XMPP::Message::Type
, "normal");
415 XMPP::Message::Message(PXML
& pdu
)
417 if (XMPP::Message::IsValid(&pdu
)) {
418 PWaitAndSignal
m(pdu
.GetMutex());
419 PXMLElement
* elem
= pdu
.GetRootElement();
421 SetRootElement((PXMLElement
*)elem
->Clone(0));
426 XMPP::Message::Message(PXML
* pdu
)
428 if (XMPP::Message::IsValid(pdu
)) {
429 PWaitAndSignal
m(PAssertNULL(pdu
)->GetMutex());
430 PXMLElement
* elem
= pdu
->GetRootElement();
433 SetRootElement((PXMLElement
*)elem
->Clone(0));
438 BOOL
XMPP::Message::IsValid() const
440 return XMPP::Message::IsValid(this);
444 BOOL
XMPP::Message::IsValid(const PXML
* pdu
)
446 PXMLElement
* elem
= PAssertNULL(pdu
)->GetRootElement();
447 return elem
!= NULL
&& elem
->GetName() == XMPP::MessageStanza
;
451 XMPP::Message::MessageType
XMPP::Message::GetType(PString
* typeName
) const
453 PString t
= PAssertNULL(rootElement
)->GetAttribute(XMPP::Message::Type
);
455 if (typeName
!= NULL
)
459 return XMPP::Message::Normal
;
460 else if (t
*= "chat")
461 return XMPP::Message::Chat
;
462 else if (t
*= "error")
463 return XMPP::Message::Error
;
464 else if (t
*= "groupchat")
465 return XMPP::Message::GroupChat
;
466 else if (t
*= "headline")
467 return XMPP::Message::HeadLine
;
469 return XMPP::Message::Unknown
;
473 PString
XMPP::Message::GetLanguage() const
475 return PAssertNULL(rootElement
)->GetAttribute(XMPP::Language
);
479 PXMLElement
* XMPP::Message::GetSubjectElement(const PString
& lang
)
481 PAssertNULL(rootElement
);
483 PXMLElement
* dfltSubj
= NULL
;
488 while ((subj
= rootElement
->GetElement(XMPP::Message::Subject
, i
)) != NULL
) {
489 i
= rootElement
->FindObject(subj
) + 1;
490 l
= subj
->GetAttribute(XMPP::Language
);
494 else if (l
.IsEmpty() && dfltSubj
== NULL
)
502 PString
XMPP::Message::GetSubject(const PString
& lang
)
504 PXMLElement
* elem
= GetSubjectElement(lang
);
505 return elem
!= NULL
? elem
->GetData() : PString::Empty();
509 PXMLElement
* XMPP::Message::GetBodyElement(const PString
& lang
)
511 PAssertNULL(rootElement
);
513 PXMLElement
* dfltBody
= NULL
;
518 while ((body
= rootElement
->GetElement(XMPP::Message::Body
, i
)) != NULL
) {
519 i
= rootElement
->FindObject(body
) + 1;
520 l
= body
->GetAttribute(XMPP::Language
);
524 else if (l
.IsEmpty() && dfltBody
== NULL
)
532 PString
XMPP::Message::GetBody(const PString
& lang
)
534 PXMLElement
* elem
= GetBodyElement(lang
);
535 return elem
!= NULL
? elem
->GetData() : PString::Empty();
539 PString
XMPP::Message::GetThread()
541 PXMLElement
* elem
= PAssertNULL(rootElement
)->GetElement(XMPP::Message::Thread
);
542 return elem
!= NULL
? elem
->GetData() : PString::Empty();
546 void XMPP::Message::SetType(MessageType type
)
549 case XMPP::Message::Normal
:
552 case XMPP::Message::Chat
:
555 case XMPP::Message::Error
:
558 case XMPP::Message::GroupChat
:
559 SetType("groupchat");
561 case XMPP::Message::HeadLine
:
568 void XMPP::Message::SetType(const PString
& type
)
570 PAssertNULL(rootElement
)->SetAttribute(XMPP::Message::Type
, type
);
574 void XMPP::Message::SetLanguage(const PString
& lang
)
576 PAssertNULL(rootElement
)->SetAttribute(XMPP::Language
, lang
);
580 void XMPP::Message::SetSubject(const PString
& subj
, const PString
& lang
)
582 PXMLElement
* elem
= GetSubjectElement(lang
);
585 elem
= PAssertNULL(rootElement
)->AddChild(new PXMLElement(rootElement
, XMPP::Message::Subject
));
588 elem
->SetAttribute(XMPP::Language
, lang
);
590 elem
->AddChild(new PXMLData(elem
, subj
));
594 void XMPP::Message::SetBody(const PString
& body
, const PString
& lang
)
596 PXMLElement
* elem
= GetBodyElement(lang
);
599 elem
= PAssertNULL(rootElement
)->AddChild(new PXMLElement(rootElement
, XMPP::Message::Body
));
602 elem
->SetAttribute(XMPP::Language
, lang
);
605 elem
->AddChild(new PXMLData(elem
, body
));
609 void XMPP::Message::SetThread(const PString
& thrd
)
611 PXMLElement
* elem
= PAssertNULL(rootElement
)->GetElement(XMPP::Message::Thread
);
614 elem
= PAssertNULL(rootElement
)->AddChild(new PXMLElement(rootElement
, XMPP::Message::Thread
));
616 elem
->AddChild(new PXMLData(elem
, thrd
));
619 ///////////////////////////////////////////////////////
621 const PString
XMPP::Presence::Type("type");
622 const PString
XMPP::Presence::Show("show");
623 const PString
XMPP::Presence::Status("status");
624 const PString
XMPP::Presence::Priority("priority");
626 XMPP::Presence::Presence()
628 SetRootElement(new PXMLElement(0, XMPP::PresenceStanza
));
632 XMPP::Presence::Presence(PXML
& pdu
)
634 if (XMPP::Presence::IsValid(&pdu
)) {
635 PWaitAndSignal
m(pdu
.GetMutex());
636 PXMLElement
* elem
= pdu
.GetRootElement();
638 SetRootElement((PXMLElement
*)elem
->Clone(0));
643 XMPP::Presence::Presence(PXML
* pdu
)
645 if (XMPP::Presence::IsValid(pdu
)) {
646 PWaitAndSignal
m(PAssertNULL(pdu
)->GetMutex());
647 PXMLElement
* elem
= pdu
->GetRootElement();
649 SetRootElement((PXMLElement
*)elem
->Clone(0));
654 BOOL
XMPP::Presence::IsValid() const
656 return XMPP::Presence::IsValid(this);
660 BOOL
XMPP::Presence::IsValid(const PXML
* pdu
)
662 PXMLElement
* elem
= PAssertNULL(pdu
)->GetRootElement();
663 return elem
!= NULL
&& elem
->GetName() == XMPP::PresenceStanza
;
667 XMPP::Presence::PresenceType
XMPP::Presence::GetType(PString
* typeName
) const
669 PString t
= PAssertNULL(rootElement
)->GetAttribute(XMPP::Presence::Type
);
671 if (typeName
!= NULL
)
675 return XMPP::Presence::Available
;
676 else if (t
*= "unavailable")
677 return XMPP::Presence::Unavailable
;
678 else if (t
*= "subscribe")
679 return XMPP::Presence::Subscribe
;
680 else if (t
*= "subscribed")
681 return XMPP::Presence::Subscribed
;
682 else if (t
*= "unsubscribe")
683 return XMPP::Presence::Unsubscribe
;
684 else if (t
*= "unsubscribed")
685 return XMPP::Presence::Unsubscribed
;
686 else if (t
*= "probe")
687 return XMPP::Presence::Probe
;
688 else if (t
*= "error")
689 return XMPP::Presence::Error
;
691 return XMPP::Presence::Unknown
;
695 XMPP::Presence::ShowType
XMPP::Presence::GetShow(PString
* showName
) const
697 PXMLElement
* elem
= PAssertNULL(rootElement
)->GetElement(XMPP::Presence::Show
);
700 return XMPP::Presence::Online
;
702 PString s
= elem
->GetData();
704 if (showName
!= NULL
)
708 return XMPP::Presence::Online
;
709 else if (s
*= "away")
710 return XMPP::Presence::Away
;
711 else if (s
*= "chat")
712 return XMPP::Presence::Chat
;
714 return XMPP::Presence::DND
;
716 return XMPP::Presence::XA
;
718 return XMPP::Presence::Other
;
722 BYTE
XMPP::Presence::GetPriority() const
724 PXMLElement
* elem
= PAssertNULL(rootElement
)->GetElement(XMPP::Presence::Priority
);
725 return elem
== NULL
? (BYTE
)0 : (BYTE
)elem
->GetData().AsInteger();
729 PXMLElement
* XMPP::Presence::GetStatusElement(const PString
& lang
)
731 PAssertNULL(rootElement
);
733 PXMLElement
* dfltStatus
= NULL
;
735 PXMLElement
* status
;
738 while ((status
= rootElement
->GetElement(XMPP::Presence::Status
, i
)) != NULL
) {
739 i
= rootElement
->FindObject(status
) + 1;
740 l
= status
->GetAttribute(XMPP::Language
);
744 else if (l
.IsEmpty() && dfltStatus
== NULL
)
752 PString
XMPP::Presence::GetStatus(const PString
& lang
)
754 PXMLElement
* elem
= GetStatusElement(lang
);
755 return elem
!= NULL
? elem
->GetData() : PString::Empty();
759 void XMPP::Presence::SetType(PresenceType type
)
762 case XMPP::Presence::Available
:
763 PAssertNULL(rootElement
)->SetAttribute(XMPP::Presence::Type
, PString::Empty());
765 case XMPP::Presence::Unavailable
:
766 SetType("unavailable");
768 case XMPP::Presence::Subscribe
:
769 SetType("subscribe");
771 case XMPP::Presence::Subscribed
:
772 SetType("subscribed");
774 case XMPP::Presence::Unsubscribe
:
775 SetType("unsubscribe");
777 case XMPP::Presence::Unsubscribed
:
778 SetType("unsubscribed");
780 case XMPP::Presence::Probe
:
783 case XMPP::Presence::Error
:
790 void XMPP::Presence::SetType(const PString
& type
)
792 PAssertNULL(rootElement
)->SetAttribute(XMPP::Presence::Type
, type
);
796 void XMPP::Presence::SetShow(ShowType show
)
799 case XMPP::Presence::Online
:
801 PXMLElement
* elem
= PAssertNULL(rootElement
)->GetElement(XMPP::Presence::Show
);
803 rootElement
->RemoveElement(rootElement
->FindObject(elem
));
806 case XMPP::Presence::Away
:
809 case XMPP::Presence::Chat
:
812 case XMPP::Presence::DND
:
815 case XMPP::Presence::XA
:
822 void XMPP::Presence::SetShow(const PString
& show
)
824 PXMLElement
* elem
= PAssertNULL(rootElement
)->GetElement(XMPP::Presence::Show
);
827 elem
= PAssertNULL(rootElement
)->AddChild(new PXMLElement(rootElement
, XMPP::Presence::Show
));
829 elem
->AddChild(new PXMLData(elem
, show
));
833 void XMPP::Presence::SetPriority(BYTE priority
)
835 PXMLElement
* elem
= PAssertNULL(rootElement
)->GetElement(XMPP::Presence::Priority
);
838 elem
= PAssertNULL(rootElement
)->AddChild(new PXMLElement(rootElement
, XMPP::Presence::Priority
));
840 elem
->AddChild(new PXMLData(elem
, PString((PINDEX
)priority
)));
844 void XMPP::Presence::SetStatus(const PString
& status
, const PString
& lang
)
846 PXMLElement
* elem
= GetStatusElement(lang
);
849 elem
= PAssertNULL(rootElement
)->AddChild(new PXMLElement(rootElement
, XMPP::Presence::Status
));
852 elem
->SetAttribute(XMPP::Language
, lang
);
854 elem
->AddChild(new PXMLData(elem
, status
));
857 ///////////////////////////////////////////////////////
859 const PString
XMPP::IQ::Type("type");
862 XMPP::IQ::IQ(XMPP::IQ::IQType type
, PXMLElement
* body
)
863 : m_Processed(FALSE
),
866 SetRootElement(new PXMLElement(NULL
, XMPP::IQStanza
));
870 rootElement
->SetAttribute(XMPP::Namespace
, "jabber:client");
874 XMPP::IQ::IQ(PXML
& pdu
)
875 : m_Processed(FALSE
),
878 if (XMPP::IQ::IsValid(&pdu
)) {
879 PWaitAndSignal
m(pdu
.GetMutex());
880 PXMLElement
* elem
= pdu
.GetRootElement();
882 SetRootElement((PXMLElement
*)elem
->Clone(0));
887 XMPP::IQ::IQ(PXML
* pdu
)
888 : m_Processed(FALSE
),
891 if (XMPP::IQ::IsValid(pdu
)) {
892 PWaitAndSignal
m(PAssertNULL(pdu
)->GetMutex());
893 PXMLElement
* elem
= pdu
->GetRootElement();
895 SetRootElement((PXMLElement
*)elem
->Clone(0));
906 BOOL
XMPP::IQ::IsValid() const
908 return XMPP::IQ::IsValid(this);
912 BOOL
XMPP::IQ::IsValid(const PXML
* pdu
)
914 PXMLElement
* elem
= PAssertNULL(pdu
)->GetRootElement();
916 if (elem
== NULL
|| elem
->GetName() != XMPP::IQStanza
)
919 PString s
= elem
->GetAttribute(XMPP::IQ::Type
);
921 if (s
.IsEmpty() || (s
!= "get" && s
!= "set" && s
!= "result" && s
!= "error"))
924 /* Appartently when a server sends a set to us there's no id...
925 s = elem->GetAttribute(XMPP::IQ::ID);
932 XMPP::IQ::IQType
XMPP::IQ::GetType(PString
* typeName
) const
934 PString t
= PAssertNULL(rootElement
)->GetAttribute(XMPP::IQ::Type
);
936 if (typeName
!= NULL
)
940 return XMPP::IQ::Get
;
942 return XMPP::IQ::Set
;
943 else if (t
*= "result")
944 return XMPP::IQ::Result
;
945 else if (t
*= "error")
946 return XMPP::IQ::Error
;
948 return XMPP::IQ::Unknown
;
952 PXMLElement
* XMPP::IQ::GetBody()
954 PXMLObject
* elem
= PAssertNULL(rootElement
)->GetElement(0);
955 return PIsDescendant(elem
, PXMLElement
) ? (PXMLElement
*)elem
: NULL
;
959 void XMPP::IQ::SetType(XMPP::IQ::IQType type
)
968 case XMPP::IQ::Result
:
971 case XMPP::IQ::Error
:
978 void XMPP::IQ::SetType(const PString
& type
)
980 PAssertNULL(rootElement
)->SetAttribute(XMPP::IQ::Type
, type
);
984 void XMPP::IQ::SetBody(PXMLElement
* body
)
986 PAssertNULL(rootElement
);
988 while(rootElement
->HasSubObjects())
989 rootElement
->RemoveElement(0);
992 body
->SetParent(rootElement
);
993 rootElement
->AddChild(body
);
998 void XMPP::IQ::SetOriginalMessage(IQ
* iq
)
1000 delete m_OriginalIQ
;
1005 XMPP::IQ
* XMPP::IQ::BuildResult() const
1007 IQType iq_type
= GetType();
1009 if (iq_type
!= XMPP::IQ::Get
&& iq_type
!= XMPP::IQ::Set
)
1012 IQ
* result
= new IQ(XMPP::IQ::Result
);
1013 result
->SetID(GetID());
1014 result
->SetTo(GetFrom());
1019 XMPP::IQ
* XMPP::IQ::BuildError(const PString
& type
, const PString
& code
) const
1021 IQType iq_type
= GetType();
1023 if (iq_type
!= XMPP::IQ::Get
&& iq_type
!= XMPP::IQ::Set
)
1026 IQ
* error
= new IQ(XMPP::IQ::Error
);
1027 error
->SetID(GetID());
1028 error
->SetTo(GetFrom());
1030 PXMLElement
* body
= error
->GetRootElement()->AddChild(new PXMLElement(error
->GetRootElement(), "error"));
1031 body
->SetAttribute("type", type
);
1032 PXMLElement
* codeElem
= body
->AddChild(new PXMLElement(body
, code
));
1033 codeElem
->SetAttribute(XMPP::Namespace
, "urn:ietf:params:xml:ns:xmpp-stanzas");
1035 const PXMLElement
* originalBody
= (PXMLElement
*)rootElement
->GetElement(0);
1036 if (originalBody
!= NULL
)
1037 error
->GetRootElement()->AddChild((PXMLElement
*)originalBody
->Clone(error
->GetRootElement()));
1043 PString
XMPP::IQ::GenerateID()
1045 static PAtomicInteger s_id
;
1047 return PString(PString::Printf
, "iq%d", (int)++s_id
);
1053 // End of File ///////////////////////////////////////////////////////////////