From cb37b54dc15e78b3155e96f75ed3ec04533de617 Mon Sep 17 00:00:00 2001 From: rjongbloed Date: Mon, 26 Apr 2004 01:51:57 +0000 Subject: [PATCH] More implementation of XMPP, thanks a lot to Federico Pinna & Reitek S.p.A. --- include/ptclib/xmpp.h | 392 ++++++++++++++++++++++++++++++++++++------ include/ptclib/xmpp_c2s.h | 365 ++++++++++++++++++++++----------------- include/ptclib/xmpp_roster.h | 136 +++++++++++++++ pwlib.sln | 10 ++ samples/xmpptest/xmpptest.dsp | 127 ++++++++++++++ 5 files changed, 820 insertions(+), 210 deletions(-) rewrite include/ptclib/xmpp_c2s.h (63%) create mode 100644 include/ptclib/xmpp_roster.h create mode 100644 samples/xmpptest/xmpptest.dsp diff --git a/include/ptclib/xmpp.h b/include/ptclib/xmpp.h index 1f06fcdb..9ba17ab3 100644 --- a/include/ptclib/xmpp.h +++ b/include/ptclib/xmpp.h @@ -24,6 +24,9 @@ * Contributor(s): ______________________________________. * * $Log$ + * Revision 1.2 2004/04/26 01:51:57 rjongbloed + * More implementation of XMPP, thanks a lot to Federico Pinna & Reitek S.p.A. + * * Revision 1.1 2004/04/22 12:31:00 rjongbloed * Added PNotifier extensions and XMPP (Jabber) support, * thanks to Federico Pinna and Reitek S.p.A. @@ -38,103 +41,382 @@ #pragma interface #endif +#include + #if P_EXPAT #include -#include #include /////////////////////////////////////////////////////// -/** This interface is the base class of each XMPP transport class - - Derived classes might include an XMPP TCP transport as well as - classes to handle XMPP incapsulated in SIP messages. - */ -class XMPPTransport : public PIndirectChannel +namespace XMPP { - PCLASSINFO(XMPPTransport, PIndirectChannel); + /** Various constant strings + */ + extern const PString Language; + extern const PString Namespace; + extern const PString MessageStanza; + extern const PString PresenceStanza; + extern const PString IQStanza; + extern const PString IQQuery; + + class JID : public PObject + { + PCLASSINFO(JID, PObject); + + public: + JID(const char * jid = 0); + JID(const PString& jid); + JID(const PString& user, const PString& server, const PString& resource = PString::Empty()); + + virtual Comparison Compare( + const PObject & obj // Object to compare against. + ) const; + + PString & operator=( + const PString & jid /// New JID to assign. + ); + + operator const PString&() const; + + PString GetUser() const { return m_User; } + PString GetServer() const { return m_Server; } + PString GetResource() const { return m_Resource; } + PString GetShortFormat() const { return m_User + "@" + m_Server; } + + void SetUser(const PString& user); + void SetServer(const PString& server); + void SetResource(const PString& resource); + + protected: + void ParseJID(const PString& jid); + void BuildJID() const; + + PString m_User; + PString m_Server; + PString m_Resource; + + mutable PString m_JID; + mutable BOOL m_IsDirty; + }; + + /** This interface is the base class of each XMPP transport class + + Derived classes might include an XMPP TCP transport as well as + classes to handle XMPP incapsulated in SIP messages. + */ + class Transport : public PIndirectChannel + { + PCLASSINFO(Transport, PIndirectChannel); - public: - virtual BOOL Open() = 0; - virtual BOOL Close() = 0; -}; + public: + virtual BOOL Open() = 0; + virtual BOOL Close() = 0; + }; -/////////////////////////////////////////////////////// /** This class represents a XMPP stream, i.e. a XML message exchange between XMPP entities */ -class XMPPStream : public PIndirectChannel -{ - PCLASSINFO(XMPPStream, PIndirectChannel); + class Stream : public PIndirectChannel + { + PCLASSINFO(Stream, PIndirectChannel); + + public: + Stream(Transport * transport = 0); + ~Stream(); + + virtual BOOL OnOpen() { return m_OpenHandlers.Fire(*this); } + PNotifierList& OpenHandlers() { return m_OpenHandlers; } + + virtual BOOL Close(); + virtual void OnClose() { m_CloseHandlers.Fire(*this); } + PNotifierList& CloseHandlers() { return m_CloseHandlers; } + + virtual BOOL Write(const void * buf, PINDEX len); + virtual BOOL Write(const PString& data); + virtual BOOL Write(const PXML& pdu); + + /** Read a XMPP stanza from the stream + */ + virtual PXML * Read(); + + /** Reset the parser. The will delete and re-instantiate the + XML stream parser. + */ + virtual void Reset(); + PXMLStreamParser * GetParser() { return m_Parser; } + + protected: + PXMLStreamParser * m_Parser; + PNotifierList m_OpenHandlers; + PNotifierList m_CloseHandlers; + }; + + + class BaseStreamHandler : public PThread + { + PCLASSINFO(BaseStreamHandler, PThread); + + public: + BaseStreamHandler(); + ~BaseStreamHandler(); + + virtual BOOL Start(Transport * transport = 0); + virtual BOOL Stop(const PString& error = PString::Empty()); + + void SetAutoReconnect(BOOL b = TRUE, long timeout = 1000); + + PNotifierList& ElementHandlers() { return m_ElementHandlers; } + Stream * GetStream() { return m_Stream; } + + virtual BOOL Write(const void * buf, PINDEX len); + virtual BOOL Write(const PString& data); + virtual BOOL Write(const PXML& pdu); + virtual void OnElement(PXML& pdu); + + virtual void Main(); + + protected: + PDECLARE_NOTIFIER(Stream, BaseStreamHandler, OnOpen); + PDECLARE_NOTIFIER(Stream, BaseStreamHandler, OnClose); + + Stream * m_Stream; + BOOL m_AutoReconnect; + PTimeInterval m_ReconnectTimeout; + + PNotifierList m_ElementHandlers; + }; + + + /** XMPP stanzas: the following classes represent the three + stanzas (PDUs) defined by the xmpp protocol + */ + + class Stanza : public PXML + { + PCLASSINFO(Stanza, PXML) + + public: + /** Various constant strings + */ + static const PString ID; + static const PString From; + static const PString To; + + virtual BOOL IsValid() const = 0; + + virtual PString GetID() const; + virtual PString GetFrom() const; + virtual PString GetTo() const; + + virtual void SetID(const PString& id); + virtual void SetFrom(const PString& from); + virtual void SetTo(const PString& to); + }; + + PLIST(StanzaList, Stanza); - protected: - PXMLStreamParser * m_Parser; - PNotifierList m_OpenHandlers; - PNotifierList m_CloseHandlers; + + class Message : public Stanza + { + PCLASSINFO(Message, Stanza) public: - XMPPStream(XMPPTransport * transport = 0); - ~XMPPStream(); + enum MessageType { + Normal, + Chat, + Error, + GroupChat, + HeadLine, + Unknown = 999 + }; + + /** Various constant strings + */ + static const PString Type; + static const PString Subject; + static const PString Body; + static const PString Thread; - virtual BOOL OnOpen() { return m_OpenHandlers.Fire(*this); } - PNotifierList& OpenHandlers() { return m_OpenHandlers; } + /** Construct a new empty message + */ + Message(); + + /** Construct a message from a (received) xml PDU. + The root of the pdu MUST be a message stanza. + NOTE: the root of the pdu is cloned. + */ + Message(PXML& pdu); + Message(PXML * pdu); - virtual BOOL Close(); - virtual void OnClose() { m_CloseHandlers.Fire(*this); } - PNotifierList& CloseHandlers() { return m_CloseHandlers; } + virtual BOOL IsValid() const; + static BOOL IsValid(const PXML * pdu); - virtual BOOL Write(const void * buf, PINDEX len); + virtual MessageType GetType(PString * typeName = 0) const; + virtual PString GetLanguage() const; - /** Read a XMPP stanza from the stream + /** Get the subject for the specified language. The default subject (if any) + is returned in case no language is specified or a matching one cannot be + found */ - virtual PXML * Read(); + virtual PString GetSubject(const PString& lang = PString::Empty()); + virtual PString GetBody(const PString& lang = PString::Empty()); + virtual PString GetThread(); + + virtual PXMLElement * GetSubjectElement(const PString& lang = PString::Empty()); + virtual PXMLElement * GetBodyElement(const PString& lang = PString::Empty()); + + virtual void SetType(MessageType type); + virtual void SetType(const PString& type); // custom, possibly non standard, type + virtual void SetLanguage(const PString& lang); + + virtual void SetSubject(const PString& subj, const PString& lang = PString::Empty()); + virtual void SetBody(const PString& body, const PString& lang = PString::Empty()); + virtual void SetThread(const PString& thrd); + }; + - /** Reset the parser. The will delete and re-instantiate the - XML stream parser. + class Presence : public Stanza + { + PCLASSINFO(Presence, Stanza) + + public: + enum PresenceType { + Available, + Unavailable, + Subscribe, + Subscribed, + Unsubscribe, + Unsubscribed, + Probe, + Error, + Unknown = 999 + }; + + enum ShowType { + Online, + Away, + Chat, + DND, + XA, + Other = 999 + }; + + /** Various constant strings */ - virtual void Reset(); -}; + static const PString Type; + static const PString Show; + static const PString Status; + static const PString Priority; -/////////////////////////////////////////////////////// + /** Construct a new empty presence + */ + Presence(); -class XMPPStreamHandler : public PThread -{ - PCLASSINFO(XMPPStreamHandler, PThread); + /** Construct a presence from a (received) xml PDU. + The root of the pdu MUST be a presence stanza. + NOTE: the root of the pdu is cloned. + */ + Presence(PXML& pdu); + Presence(PXML * pdu); - protected: - XMPPStream * m_Stream; - BOOL m_AutoReconnect; - PTimeInterval m_ReconnectTimeout; + virtual BOOL IsValid() const; + static BOOL IsValid(const PXML * pdu); + + virtual PresenceType GetType(PString * typeName = 0) const; + virtual ShowType GetShow(PString * showName = 0) const; + virtual BYTE GetPriority() const; - PNotifierList m_ElementHandlers; + /** Get the status for the specified language. The default status (if any) + is returned in case no language is specified or a matching one cannot be + found + */ + virtual PString GetStatus(const PString& lang = PString::Empty()); + virtual PXMLElement * GetStatusElement(const PString& lang = PString::Empty()); + + virtual void SetType(PresenceType type); + virtual void SetType(const PString& type); // custom, possibly non standard, type + virtual void SetShow(ShowType show); + virtual void SetShow(const PString& show); // custom, possibly non standard, type + virtual void SetPriority(BYTE priority); + + virtual void SetStatus(const PString& status, const PString& lang = PString::Empty()); + }; - PDECLARE_NOTIFIER(XMPPStream, XMPPStreamHandler, OnOpen); - PDECLARE_NOTIFIER(XMPPStream, XMPPStreamHandler, OnClose); + + class IQ : public Stanza + { + PCLASSINFO(IQ, Stanza) public: - XMPPStreamHandler(); - ~XMPPStreamHandler(); + enum IQType { + Get, + Set, + Result, + Error, + Unknown = 999 + }; + + /** Various constant strings + */ + static const PString Type; - virtual BOOL Start(XMPPTransport * transport); - virtual BOOL Stop(const PString& error = PString::Empty()); + IQ(IQType type, PXMLElement * body = 0); + IQ(PXML& pdu); + IQ(PXML * pdu); + ~IQ(); - void SetAutoReconnect(BOOL b = TRUE, long timeout = 1000); + virtual BOOL IsValid() const; + static BOOL IsValid(const PXML * pdu); - PNotifierList& ElementHandlers() { return m_ElementHandlers; } + /** This method signals that the message was taken care of + If the stream handler, after firing all the notifiers finds + that an iq set/get pdu has not being processed, it returns + an error to the sender + */ + void SetProcessed() { m_Processed = TRUE; } + BOOL HasBeenProcessed() const { return m_Processed; } + + virtual IQType GetType(PString * typeName = 0) const; + virtual PXMLElement * GetBody(); - virtual void OnElement(PXML& pdu); + virtual void SetType(IQType type); + virtual void SetType(const PString& type); // custom, possibly non standard, type + virtual void SetBody(PXMLElement * body); - virtual void Main(); -}; + // If the this message is response, returns a pointer to the + // original set/get message + virtual IQ * GetOriginalMessage() const { return m_OriginalIQ; } + virtual void SetOriginalMessage(IQ * iq); + + /** Creates a new response iq for this message (that must + be of the set/get type!) + */ + virtual IQ * BuildResult() const; + + /** Creates an error response for this message + */ + virtual IQ * BuildError(const PString& type, const PString& code) const; + + virtual PNotifierList GetResponseHandlers() { return m_ResponseHandlers; } + + static PString GenerateID(); + + protected: + BOOL m_Processed; + IQ * m_OriginalIQ; + PNotifierList m_ResponseHandlers; + }; + +}; // class XMPP #endif // P_EXPAT #endif // _XMPP - // End of File /////////////////////////////////////////////////////////////// diff --git a/include/ptclib/xmpp_c2s.h b/include/ptclib/xmpp_c2s.h dissimilarity index 63% index a2465aa2..56c11a51 100644 --- a/include/ptclib/xmpp_c2s.h +++ b/include/ptclib/xmpp_c2s.h @@ -1,155 +1,210 @@ -/* - * xmpp_c2s.h - * - * Extensible Messaging and Presence Protocol (XMPP) Core - * Client to Server communication classes - * - * Portable Windows Library - * - * Copyright (c) 2004 Reitek S.p.A. - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. - * - * The Original Code is Portable Windows Library. - * - * The Initial Developer of the Original Code is Post Increment - * - * Contributor(s): ______________________________________. - * - * $Log$ - * Revision 1.2 2004/04/23 06:07:24 csoutheren - * Added #if P_SASL to allow operation without SASL - * - * Revision 1.1 2004/04/22 12:31:00 rjongbloed - * Added PNotifier extensions and XMPP (Jabber) support, - * thanks to Federico Pinna and Reitek S.p.A. - * - * - */ - -#if P_EXPAT -#ifndef _XMPP_C2S -#define _XMPP_C2S - -#ifdef P_USE_PRAGMA -#pragma interface -#endif - -#include -#include - -/////////////////////////////////////////////////////// - -/** XMPP client to server TCP transport - */ -class XMPP_C2S_TCPTransport : public XMPPTransport -{ - PCLASSINFO(XMPP_C2S_TCPTransport, XMPPTransport); - - public: - XMPP_C2S_TCPTransport(const PString& hostname, WORD port = 5222); - ~XMPP_C2S_TCPTransport(); - - const PString& GetServerHost() const { return m_Hostname; } - WORD GetServerPort() const { return m_Port; } - - virtual BOOL Open(); - virtual BOOL Close(); - - protected: - const PString& m_Hostname; - const WORD m_Port; - PTCPSocket * m_Socket; -}; - -/////////////////////////////////////////////////////// - -/** This class handles the client side of a C2S (Client to Server) - XMPP stream. - */ -class XMPP_C2S : public XMPPStreamHandler -{ - PCLASSINFO(XMPP_C2S, XMPPStreamHandler); - - public: - XMPP_C2S(const PString& uid, - const PString& server, - const PString& resource, - const PString& pwd); - - ~XMPP_C2S(); - - /** These notifier lists are fired when a XMPP stanza or a - stream error is received. For the notifier lists to be fired - the stream must be already in the established state (i.e. - after the bind and the session state) - */ - PNotifierList& ErrorHandlers() { return m_ErrorHandlers; } - PNotifierList& MessageHandlers() { return m_MessageHandlers; } - PNotifierList& PresenceHandlers() { return m_PresenceHandlers; } - PNotifierList& IQHandlers() { return m_IQHandlers; } - - protected: - const PString m_UserID; - const PString m_Server; - PString m_Resource; // the resource can change: the server can force one - const PString m_Password; -#if P_SASL - PSASLClient m_SASL; -#endif - PString m_Mechanism; - BOOL m_HasBind; - BOOL m_HasSession; - - PNotifierList m_ErrorHandlers; - PNotifierList m_MessageHandlers; - PNotifierList m_PresenceHandlers; - PNotifierList m_IQHandlers; - - enum C2S_StreamState - { - Null, - TLSStarted, - SASLStarted, - StreamSent, - BindSent, - SessionSent, - Established - }; - - C2S_StreamState m_State; - - virtual void OnOpen(XMPPStream& stream, INT); - virtual void OnClose(XMPPStream& stream, INT); - - virtual void OnElement(PXML& pdu); - virtual void OnError(PXML& pdu); - virtual void OnMessage(PXML& pdu); - virtual void OnPresence(PXML& pdu); - virtual void OnIQ(PXML& pdu); - - // State handlers - virtual void HandleNullState(PXML& pdu); - virtual void HandleTLSStartedState(PXML& pdu); -#if P_SASL - virtual void HandleSASLStartedState(PXML& pdu); -#endif - virtual void HandleStreamSentState(PXML& pdu); - virtual void HandleBindSentState(PXML& pdu); - virtual void HandleSessionSentState(PXML& pdu); - virtual void HandleEstablishedState(PXML& pdu); - }; - - #endif // _XMPP_C2S -#endif // P_EXPAT - -// End of File /////////////////////////////////////////////////////////////// - +/* + * xmpp_c2s.h + * + * Extensible Messaging and Presence Protocol (XMPP) Core + * Client to Server communication classes + * + * Portable Windows Library + * + * Copyright (c) 2004 Reitek S.p.A. + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Portable Windows Library. + * + * The Initial Developer of the Original Code is Post Increment + * + * Contributor(s): ______________________________________. + * + * $Log$ + * Revision 1.3 2004/04/26 01:51:57 rjongbloed + * More implementation of XMPP, thanks a lot to Federico Pinna & Reitek S.p.A. + * + * Revision 1.2 2004/04/23 06:07:24 csoutheren + * Added #if P_SASL to allow operation without SASL + * + * Revision 1.1 2004/04/22 12:31:00 rjongbloed + * Added PNotifier extensions and XMPP (Jabber) support, + * thanks to Federico Pinna and Reitek S.p.A. + * + * + */ + +#ifndef _XMPP_C2S +#define _XMPP_C2S + +#ifdef P_USE_PRAGMA +#pragma interface +#endif + +#include + +#if P_EXPAT + +#include +#include + + +/////////////////////////////////////////////////////// + +namespace XMPP +{ + namespace C2S + { + + /** XMPP client to server TCP transport + */ + class TCPTransport : public Transport + { + PCLASSINFO(TCPTransport, Transport); + + public: + TCPTransport(const PString& hostname); + TCPTransport(const PString& hostname, WORD port); + ~TCPTransport(); + + const PString& GetServerHost() const { return m_Hostname; } + WORD GetServerPort() const { return m_Port; } + + virtual BOOL Open(); + virtual BOOL Close(); + + protected: + PString m_Hostname; + WORD m_Port; + PTCPSocket * m_Socket; + }; + + +/** This class handles the client side of a C2S (Client to Server) + XMPP stream. + */ + class StreamHandler : public BaseStreamHandler + { + PCLASSINFO(StreamHandler, BaseStreamHandler); + + public: + StreamHandler(const JID& jid, const PString& pwd); + ~StreamHandler(); + + virtual BOOL Start(Transport * transport = 0); + + /** Request the delivery of the specified stanza + NOTE: the StreamHandler takes ownership of the stanza + and will take care of deleting it. + BIG NOTE: use this method and not Write() if you want to + get a notification when an answer to an iq arrives + */ + BOOL Send(Stanza * stanza); + + void SetVersion(WORD major, WORD minor); + void GetVersion(WORD& major, WORD& minor) const; + + /** These notifier lists after when a client session is + established (i.e. after the handshake and authentication + steps are completed) or is released. The parameter passed + to the notifiers is a reference to the stream handler + */ + PNotifierList& SessionEstablishedHandlers() { return m_SessionEstablishedHandlers; } + PNotifierList& SessionReleasedHandlers() { return m_SessionReleasedHandlers; } + + /** These notifier lists are fired when a XMPP stanza or a + stream error is received. For the notifier lists to be fired + the stream must be already in the established state (i.e. + after the bind and the session state). The parameter passed + to the notifiers is a reference to the received pdu + */ + PNotifierList& ErrorHandlers() { return m_ErrorHandlers; } + PNotifierList& MessageHandlers() { return m_MessageHandlers; } + PNotifierList& PresenceHandlers() { return m_PresenceHandlers; } + PNotifierList& IQHandlers() { return m_IQHandlers; } + + /** A notifier list for a specific namespace. The list will + be fired only upon receiving an IQ with a child element + of type "query" (just like a lot of JEPs) and the specified + namespace + */ + PNotifierList& IQQueryHandlers(const PString& xml_namespace); + + protected: + virtual void OnOpen(Stream& stream, INT); + virtual void OnClose(Stream& stream, INT); + virtual void StartAuthNegotiation(); + + virtual void OnSessionEstablished(); + virtual void OnSessionReleased(); + virtual void OnElement(PXML& pdu); + virtual void OnError(PXML& pdu); + + virtual void OnMessage(XMPP::Message& pdu); + virtual void OnPresence(XMPP::Presence& pdu); + virtual void OnIQ(XMPP::IQ& pdu); + + // State handlers + virtual void HandleNullState(PXML& pdu); + virtual void HandleTLSStartedState(PXML& pdu); + virtual void HandleSASLStartedState(PXML& pdu); + virtual void HandleNonSASLStartedState(PXML& pdu); + virtual void HandleStreamSentState(PXML& pdu); + virtual void HandleBindSentState(PXML& pdu); + virtual void HandleSessionSentState(PXML& pdu); + virtual void HandleEstablishedState(PXML& pdu); + + WORD m_VersionMajor; + WORD m_VersionMinor; + JID m_JID; + const PString m_Password; +#if P_SASL + PSASLClient m_SASL; + PString m_Mechanism; +#endif + BOOL m_HasBind; + BOOL m_HasSession; + + PNotifierList m_SessionEstablishedHandlers; + PNotifierList m_SessionReleasedHandlers; + PNotifierList m_ErrorHandlers; + PNotifierList m_MessageHandlers; + PNotifierList m_PresenceHandlers; + PNotifierList m_IQHandlers; + PDictionary m_IQQueryHandlers; + + PMutex m_PendingIQsLock; + StanzaList m_PendingIQs; + + enum StreamState + { + Null, + TLSStarted, + SASLStarted, + NonSASLStarted, // non SASL authentication (JEP-0078) + StreamSent, + BindSent, + SessionSent, + Established + }; + + virtual void SetState(StreamState s); + + StreamState m_State; + }; + + } // namespace C2S +} // namespace XMPP + + +#endif // P_EXPAT + +#endif // _XMPP_C2S + +// End of File /////////////////////////////////////////////////////////////// + + diff --git a/include/ptclib/xmpp_roster.h b/include/ptclib/xmpp_roster.h new file mode 100644 index 00000000..719ba7a1 --- /dev/null +++ b/include/ptclib/xmpp_roster.h @@ -0,0 +1,136 @@ +/* + * xmpp_roster.h + * + * Extensible Messaging and Presence Protocol (XMPP) IM + * Roster management classes + * + * Portable Windows Library + * + * Copyright (c) 2004 Reitek S.p.A. + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Portable Windows Library. + * + * The Initial Developer of the Original Code is Post Increment + * + * Contributor(s): ______________________________________. + * + * $Log$ + * Revision 1.1 2004/04/26 01:51:57 rjongbloed + * More implementation of XMPP, thanks a lot to Federico Pinna & Reitek S.p.A. + * + * + */ + +#ifndef _XMPP_ROSTER +#define _XMPP_ROSTER + +#ifdef P_USE_PRAGMA +#pragma interface +#endif + +#include + +#if P_EXPAT + +/////////////////////////////////////////////////////// + +namespace XMPP +{ + class Roster : public PObject + { + PCLASSINFO(Roster, PObject); + public: + + enum ItemType { // Subscription type + None, + To, + From, + Both, + Unknown = 999 + }; + + class Item : public PObject + { + PCLASSINFO(Item, PObject); + public: + Item(PXMLElement * item = 0); + Item(PXMLElement& item); + Item(const JID& jid, ItemType type, const PString& group, const PString& name = PString::Empty()); + + const JID& GetJID() const { return m_JID; } + ItemType GetType() const { return m_Type; } + const PString& GetName() const { return m_Name; } + const PStringSet& GetGroups() const { return m_Groups; } + + virtual void SetJID(const JID& jid, BOOL dirty = TRUE) + { m_JID = jid; if (dirty) SetDirty(); } + virtual void SetType(ItemType type, BOOL dirty = TRUE) + { m_Type = type; if (dirty) SetDirty(); } + virtual void SetName(const PString& name, BOOL dirty = TRUE) + { m_Name = name; if (dirty) SetDirty(); } + + virtual void AddGroup(const PString& group, BOOL dirty = TRUE); + virtual void RemoveGroup(const PString& group, BOOL dirty = TRUE); + + void SetDirty(BOOL b = TRUE) { m_IsDirty = b; } + + /** This operator will set the dirty flag + */ + Item & operator=( + const PXMLElement& item + ); + + virtual PXMLElement * AsXML(PXMLElement * parent) const; + + protected: + JID m_JID; + ItemType m_Type; + PString m_Name; + PStringSet m_Groups; + + BOOL m_IsDirty; // item modified locally, server needs to be updated + }; + PLIST(ItemList, Item); + + public: + Roster(XMPP::C2S::StreamHandler * handler = 0); + ~Roster(); + + const ItemList& GetItems() const { return m_Items; } + + virtual Item * FindItem(const PString& jid); + + virtual BOOL SetItem(Item * item, BOOL localOnly = FALSE); + virtual BOOL RemoveItem(const PString& jid, BOOL localOnly = FALSE); + virtual BOOL RemoveItem(Item * item, BOOL localOnly = FALSE); + + virtual void Attach(XMPP::C2S::StreamHandler * handler); + virtual void Detach(); + + protected: + PDECLARE_NOTIFIER(XMPP::C2S::StreamHandler, Roster, OnSessionEstablished); + PDECLARE_NOTIFIER(XMPP::C2S::StreamHandler, Roster, OnSessionReleased); + PDECLARE_NOTIFIER(XMPP::IQ, Roster, OnIQ); + + ItemList m_Items; + XMPP::C2S::StreamHandler * m_Handler; + }; + +} // namespace XMPP + + +#endif // P_EXPAT + +#endif // _XMPP_ROSTER + +// End of File /////////////////////////////////////////////////////////////// diff --git a/pwlib.sln b/pwlib.sln index 432c059f..465a9ad7 100644 --- a/pwlib.sln +++ b/pwlib.sln @@ -68,6 +68,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stunclient", "samples\stunc {85F4F26A-1A5D-4685-A48A-448102C5C5BC} = {85F4F26A-1A5D-4685-A48A-448102C5C5BC} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmpptest", "samples\xmpptest\xmpptest.vcproj", "{F338AFB2-AA33-444E-994C-4D6C0B107983}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -134,6 +138,12 @@ Global {D0C00ADD-544B-4922-AB52-14415894D684}.Pseudo-Debug.Build.0 = Debug|Win32 {D0C00ADD-544B-4922-AB52-14415894D684}.Release.ActiveCfg = Release|Win32 {D0C00ADD-544B-4922-AB52-14415894D684}.Release.Build.0 = Release|Win32 + {F338AFB2-AA33-444E-994C-4D6C0B107983}.Debug.ActiveCfg = Debug|Win32 + {F338AFB2-AA33-444E-994C-4D6C0B107983}.Debug.Build.0 = Debug|Win32 + {F338AFB2-AA33-444E-994C-4D6C0B107983}.Pseudo-Debug.ActiveCfg = Debug|Win32 + {F338AFB2-AA33-444E-994C-4D6C0B107983}.Pseudo-Debug.Build.0 = Debug|Win32 + {F338AFB2-AA33-444E-994C-4D6C0B107983}.Release.ActiveCfg = Release|Win32 + {F338AFB2-AA33-444E-994C-4D6C0B107983}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/samples/xmpptest/xmpptest.dsp b/samples/xmpptest/xmpptest.dsp new file mode 100644 index 00000000..0899e6c2 --- /dev/null +++ b/samples/xmpptest/xmpptest.dsp @@ -0,0 +1,127 @@ +# Microsoft Developer Studio Project File - Name="xmpptest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=xmpptest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "xmpptest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "xmpptest.mak" CFG="xmpptest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "xmpptest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "xmpptest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "xmpptest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W4 /GR /GX /O2 /D "NDEBUG" /D "PTRACING" /Yu"ptlib.h" /FD /c +# ADD BASE RSC /l 0x410 /d "NDEBUG" +# ADD RSC /l 0x410 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 ptclib.lib ptlib.lib comdlg32.lib winspool.lib wsock32.lib mpr.lib kernel32.lib user32.lib gdi32.lib shell32.lib advapi32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "xmpptest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "PTRACING" /FR /Yu"ptlib.h" /FD /GZ /c +# ADD BASE RSC /l 0x410 /d "_DEBUG" +# ADD RSC /l 0x410 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ptclibd.lib ptlibd.lib comdlg32.lib winspool.lib wsock32.lib mpr.lib kernel32.lib user32.lib gdi32.lib shell32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "xmpptest - Win32 Release" +# Name "xmpptest - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\main.cxx +# End Source File +# Begin Source File + +SOURCE=.\precompile.cxx + +!IF "$(CFG)" == "xmpptest - Win32 Release" + +!ELSEIF "$(CFG)" == "xmpptest - Win32 Debug" + +# ADD CPP /Yc"ptlib.h" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\main.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=".\draft-ietf-xmpp-core-22.txt" +# End Source File +# Begin Source File + +SOURCE=".\draft-ietf-xmpp-im-21.txt" +# End Source File +# End Target +# End Project -- 2.11.4.GIT