More implementation of XMPP, thanks a lot to Federico Pinna & Reitek S.p.A.
[pwlib.git] / src / ptclib / xmpp.cxx
blobd826c0960f5fb8ed63fc2e3a057d20b734264363
1 /*
2 * xmpp.cxx
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
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Post Increment
24 * Contributor(s): ______________________________________.
26 * $Log$
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.
37 #ifdef __GNUC__
38 #pragma implementation "xmpp.h"
39 #endif
41 #include <ptlib.h>
42 #include <ptclib/xmpp.h>
44 #if P_EXPAT
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)
59 ParseJID(jid);
63 XMPP::JID::JID(const PString& jid)
65 ParseJID(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)
72 BuildJID();
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)
90 ParseJID(jid);
91 return m_JID;
95 XMPP::JID::operator const PString&() const
97 if (m_IsDirty)
98 BuildJID();
100 return m_JID;
104 void XMPP::JID::SetUser(const PString& user)
106 m_IsDirty = TRUE;
107 m_User = user;
111 void XMPP::JID::SetServer(const PString& server)
113 m_IsDirty = TRUE;
114 m_Server = server;
118 void XMPP::JID::SetResource(const PString& resource)
120 m_IsDirty = TRUE;
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))
132 return;
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)
140 return;
142 m_Resource = m_Server.Mid(i + 1);
143 m_Server = m_Server.Left(i);
144 BuildJID();
148 void XMPP::JID::BuildJID() const
150 m_JID = m_User + "@" + m_Server;
152 if (!m_Resource.IsEmpty())
153 m_JID += "/" + m_Resource;
155 m_IsDirty = FALSE;
158 ///////////////////////////////////////////////////////
160 XMPP::Stream::Stream(XMPP::Transport * transport)
161 : m_Parser(new PXMLStreamParser)
163 if (transport)
164 Open(transport);
168 XMPP::Stream::~Stream()
170 delete m_Parser;
171 Close();
175 BOOL XMPP::Stream::Close()
177 if (IsOpen()) {
178 OnClose();
179 return PIndirectChannel::Close();
182 return FALSE;
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();
203 if (root == NULL)
204 return FALSE;
206 PStringStream os;
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()
220 delete m_Parser;
221 m_Parser = new PXMLStreamParser;
224 ///////////////////////////////////////////////////////
226 XMPP::BaseStreamHandler::BaseStreamHandler()
227 : PThread(0x1000),
228 m_Stream(NULL),
229 m_AutoReconnect(TRUE),
230 m_ReconnectTimeout(1000)
235 XMPP::BaseStreamHandler::~BaseStreamHandler()
237 Stop();
241 BOOL XMPP::BaseStreamHandler::Start(XMPP::Transport * transport)
243 if (m_Stream != NULL)
244 Stop();
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())
251 return FALSE;
253 if (m_Stream->Open(transport))
255 if (IsSuspended())
256 Resume();
257 else
258 Restart();
259 return TRUE;
262 return FALSE;
266 BOOL XMPP::BaseStreamHandler::Stop(const PString& _error)
268 if (m_Stream == NULL)
269 return FALSE;
271 if (!_error.IsEmpty())
273 PString error = "<stream:error><";
274 error += _error;
275 error += " xmlns='urn:ietf:params:xml:ns:xmpp-streams'/></stream:error>";
276 m_Stream->Write((const char *)error, error.GetLength());
279 m_Stream->Close();
281 if (PThread::Current() != this)
282 WaitForTermination(10000);
284 return FALSE;
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)
300 m_AutoReconnect = b;
301 m_ReconnectTimeout = t;
305 BOOL XMPP::BaseStreamHandler::Write(const void * buf, PINDEX len)
307 if (m_Stream == NULL)
308 return FALSE;
310 return m_Stream->Write(buf, len);
314 BOOL XMPP::BaseStreamHandler::Write(const PString& data)
316 if (m_Stream == NULL)
317 return FALSE;
319 return m_Stream->Write(data);
323 BOOL XMPP::BaseStreamHandler::Write(const PXML& pdu)
325 if (m_Stream == NULL)
326 return FALSE;
328 return m_Stream->Write(pdu);
332 void XMPP::BaseStreamHandler::OnElement(PXML& pdu)
334 m_ElementHandlers.Fire(pdu);
338 void XMPP::BaseStreamHandler::Main()
340 PXML * pdu;
342 for (;;)
344 if (!m_Stream || !m_Stream->IsOpen())
345 break;
347 pdu = m_Stream->Read();
349 if (pdu != NULL)
351 if (PTrace::CanTrace(5)) {
352 ostream& os = PTrace::Begin(5, __FILE__, __LINE__);
353 pdu->GetRootElement()->Output(os, *pdu, 0);
354 os << PTrace::End;
357 OnElement(*pdu);
360 delete pdu;
363 delete m_Stream;
364 m_Stream = NULL;
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)
375 if (!id.IsEmpty())
376 PAssertNULL(rootElement)->SetAttribute(XMPP::Stanza::ID, id);
379 void XMPP::Stanza::SetFrom(const PString& from)
381 if (!from.IsEmpty())
382 PAssertNULL(rootElement)->SetAttribute(XMPP::Stanza::From, from);
385 void XMPP::Stanza::SetTo(const PString& to)
387 if (!to.IsEmpty())
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();
420 if (elem != NULL)
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();
432 if (elem != NULL)
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)
456 *typeName = t;
458 if (t *= "normal")
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;
468 else
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;
484 PINDEX i = 0;
485 PXMLElement * subj;
486 PString l;
488 while ((subj = rootElement->GetElement(XMPP::Message::Subject, i)) != NULL) {
489 i = rootElement->FindObject(subj) + 1;
490 l = subj->GetAttribute(XMPP::Language);
492 if (l == lang)
493 return subj;
494 else if (l.IsEmpty() && dfltSubj == NULL)
495 dfltSubj = subj;
498 return dfltSubj;
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;
514 PINDEX i = 0;
515 PXMLElement * body;
516 PString l;
518 while ((body = rootElement->GetElement(XMPP::Message::Body, i)) != NULL) {
519 i = rootElement->FindObject(body) + 1;
520 l = body->GetAttribute(XMPP::Language);
522 if (l == lang)
523 return body;
524 else if (l.IsEmpty() && dfltBody == NULL)
525 dfltBody = body;
528 return dfltBody;
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)
548 switch (type) {
549 case XMPP::Message::Normal:
550 SetType("normal");
551 break;
552 case XMPP::Message::Chat:
553 SetType("chat");
554 break;
555 case XMPP::Message::Error:
556 SetType("error");
557 break;
558 case XMPP::Message::GroupChat:
559 SetType("groupchat");
560 break;
561 case XMPP::Message::HeadLine:
562 SetType("headline");
563 break;
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);
584 if (elem == NULL) {
585 elem = PAssertNULL(rootElement)->AddChild(new PXMLElement(rootElement, XMPP::Message::Subject));
587 if (!lang.IsEmpty())
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);
598 if (elem == NULL) {
599 elem = PAssertNULL(rootElement)->AddChild(new PXMLElement(rootElement, XMPP::Message::Body));
601 if (!lang.IsEmpty())
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);
613 if (elem == NULL)
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();
637 if (elem != NULL)
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();
648 if (elem != NULL)
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)
672 *typeName = t;
674 if (t.IsEmpty())
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;
690 else
691 return XMPP::Presence::Unknown;
695 XMPP::Presence::ShowType XMPP::Presence::GetShow(PString * showName) const
697 PXMLElement * elem = PAssertNULL(rootElement)->GetElement(XMPP::Presence::Show);
699 if (elem == NULL)
700 return XMPP::Presence::Online;
702 PString s = elem->GetData();
704 if (showName != NULL)
705 *showName = s;
707 if (s.IsEmpty())
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;
713 else if (s *= "dnd")
714 return XMPP::Presence::DND;
715 else if (s *= "xa")
716 return XMPP::Presence::XA;
717 else
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;
734 PINDEX i = 0;
735 PXMLElement * status;
736 PString l;
738 while ((status = rootElement->GetElement(XMPP::Presence::Status, i)) != NULL) {
739 i = rootElement->FindObject(status) + 1;
740 l = status->GetAttribute(XMPP::Language);
742 if (l == lang)
743 return status;
744 else if (l.IsEmpty() && dfltStatus == NULL)
745 dfltStatus = status;
748 return dfltStatus;
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)
761 switch (type) {
762 case XMPP::Presence::Available:
763 PAssertNULL(rootElement)->SetAttribute(XMPP::Presence::Type, PString::Empty());
764 break;
765 case XMPP::Presence::Unavailable:
766 SetType("unavailable");
767 break;
768 case XMPP::Presence::Subscribe:
769 SetType("subscribe");
770 break;
771 case XMPP::Presence::Subscribed:
772 SetType("subscribed");
773 break;
774 case XMPP::Presence::Unsubscribe:
775 SetType("unsubscribe");
776 break;
777 case XMPP::Presence::Unsubscribed:
778 SetType("unsubscribed");
779 break;
780 case XMPP::Presence::Probe:
781 SetType("probe");
782 break;
783 case XMPP::Presence::Error:
784 SetType("error");
785 break;
790 void XMPP::Presence::SetType(const PString& type)
792 PAssertNULL(rootElement)->SetAttribute(XMPP::Presence::Type, type);
796 void XMPP::Presence::SetShow(ShowType show)
798 switch (show) {
799 case XMPP::Presence::Online:
801 PXMLElement * elem = PAssertNULL(rootElement)->GetElement(XMPP::Presence::Show);
802 if (elem)
803 rootElement->RemoveElement(rootElement->FindObject(elem));
805 break;
806 case XMPP::Presence::Away:
807 SetType("away");
808 break;
809 case XMPP::Presence::Chat:
810 SetType("chat");
811 break;
812 case XMPP::Presence::DND:
813 SetType("dnd");
814 break;
815 case XMPP::Presence::XA:
816 SetType("xa");
817 break;
822 void XMPP::Presence::SetShow(const PString& show)
824 PXMLElement * elem = PAssertNULL(rootElement)->GetElement(XMPP::Presence::Show);
826 if (elem == NULL)
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);
837 if (elem == NULL)
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);
848 if (elem == NULL) {
849 elem = PAssertNULL(rootElement)->AddChild(new PXMLElement(rootElement, XMPP::Presence::Status));
851 if (!lang.IsEmpty())
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),
864 m_OriginalIQ(NULL)
866 SetRootElement(new PXMLElement(NULL, XMPP::IQStanza));
867 SetType(type);
868 SetID(GenerateID());
869 SetBody(body);
870 rootElement->SetAttribute(XMPP::Namespace, "jabber:client");
874 XMPP::IQ::IQ(PXML& pdu)
875 : m_Processed(FALSE),
876 m_OriginalIQ(NULL)
878 if (XMPP::IQ::IsValid(&pdu)) {
879 PWaitAndSignal m(pdu.GetMutex());
880 PXMLElement * elem = pdu.GetRootElement();
881 if (elem != NULL)
882 SetRootElement((PXMLElement *)elem->Clone(0));
887 XMPP::IQ::IQ(PXML * pdu)
888 : m_Processed(FALSE),
889 m_OriginalIQ(NULL)
891 if (XMPP::IQ::IsValid(pdu)) {
892 PWaitAndSignal m(PAssertNULL(pdu)->GetMutex());
893 PXMLElement * elem = pdu->GetRootElement();
894 if (elem != NULL)
895 SetRootElement((PXMLElement *)elem->Clone(0));
900 XMPP::IQ::~IQ()
902 delete m_OriginalIQ;
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)
917 return FALSE;
919 PString s = elem->GetAttribute(XMPP::IQ::Type);
921 if (s.IsEmpty() || (s != "get" && s != "set" && s != "result" && s != "error"))
922 return FALSE;
924 /* Appartently when a server sends a set to us there's no id...
925 s = elem->GetAttribute(XMPP::IQ::ID);
926 return !s.IsEmpty();
928 return TRUE;
932 XMPP::IQ::IQType XMPP::IQ::GetType(PString * typeName) const
934 PString t = PAssertNULL(rootElement)->GetAttribute(XMPP::IQ::Type);
936 if (typeName != NULL)
937 *typeName = t;
939 if (t *= "get")
940 return XMPP::IQ::Get;
941 else if (t *= "set")
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;
947 else
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)
961 switch (type) {
962 case XMPP::IQ::Get:
963 SetType("get");
964 break;
965 case XMPP::IQ::Set:
966 SetType("set");
967 break;
968 case XMPP::IQ::Result:
969 SetType("result");
970 break;
971 case XMPP::IQ::Error:
972 SetType("error");
973 break;
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);
991 if (body != NULL) {
992 body->SetParent(rootElement);
993 rootElement->AddChild(body);
998 void XMPP::IQ::SetOriginalMessage(IQ * iq)
1000 delete m_OriginalIQ;
1001 m_OriginalIQ = iq;
1005 XMPP::IQ * XMPP::IQ::BuildResult() const
1007 IQType iq_type = GetType();
1009 if (iq_type != XMPP::IQ::Get && iq_type != XMPP::IQ::Set)
1010 return NULL;
1012 IQ * result = new IQ(XMPP::IQ::Result);
1013 result->SetID(GetID());
1014 result->SetTo(GetFrom());
1015 return result;
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)
1024 return NULL;
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()));
1039 return error;
1043 PString XMPP::IQ::GenerateID()
1045 static PAtomicInteger s_id;
1047 return PString(PString::Printf, "iq%d", (int)++s_id);
1051 #endif // P_EXPAT
1053 // End of File ///////////////////////////////////////////////////////////////