/* * xmpp.h * * Extensible Messaging and Presence Protocol (XMPP) Core * * 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: xmpp.h,v $ * Revision 1.5 2005/11/30 12:47:37 csoutheren * Removed tabs, reformatted some code, and changed tags for Doxygen * * Revision 1.4 2004/11/11 07:34:50 csoutheren * Added #include * * Revision 1.3 2004/05/09 07:23:46 rjongbloed * More work on XMPP, thanks Federico Pinna and Reitek S.p.A. * * 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. * * */ #ifndef _XMPP #define _XMPP #ifdef P_USE_PRAGMA #pragma interface #endif #include #if P_EXPAT #include #include /////////////////////////////////////////////////////// namespace XMPP { /** 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; JID& operator=( const PString & jid ///< New JID to assign. ); operator const PString&() const; virtual PObject * Clone() const { return new JID(m_JID); } PString GetUser() const { return m_User; } PString GetServer() const { return m_Server; } virtual PString GetResource() const { return m_Resource; } virtual void SetUser(const PString& user); virtual void SetServer(const PString& server); virtual void SetResource(const PString& resource); virtual BOOL IsBare() const { return m_Resource.IsEmpty(); } virtual void PrintOn(ostream & strm) const; protected: virtual void ParseJID(const PString& jid); virtual void BuildJID() const; PString m_User; PString m_Server; PString m_Resource; mutable PString m_JID; mutable BOOL m_IsDirty; }; // A bare jid is a jid with no resource class BareJID : public JID { PCLASSINFO(BareJID, JID); public: BareJID(const char * jid = 0) : JID(jid) { } BareJID(const PString& jid) : JID(jid) { } BareJID(const PString& user, const PString& server, const PString& resource = PString::Empty()) : JID(user, server, resource) { } virtual Comparison Compare( const PObject & obj ///< Object to compare against. ) const; BareJID& operator=( const PString & jid ///< New JID to assign. ); virtual PObject * Clone() const { return new BareJID(m_JID); } virtual PString GetResource() const { return PString::Empty(); } virtual void SetResource(const PString&) { } virtual BOOL IsBare() const { return TRUE; } }; /** 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; }; /** This class represents a XMPP stream, i.e. a XML message exchange between XMPP entities */ 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); virtual PXMLElement * GetElement(const PString& name, PINDEX i = 0); virtual void AddElement(PXMLElement * elem); static PString GenerateID(); }; PLIST(StanzaList, Stanza); class Message : public Stanza { PCLASSINFO(Message, Stanza) public: 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; /** 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 IsValid() const; static BOOL IsValid(const PXML * pdu); virtual MessageType GetType(PString * typeName = 0) const; virtual PString GetLanguage() const; /** 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 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); }; 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 */ static const PString Type; static const PString Show; static const PString Status; static const PString Priority; /** Construct a new empty presence */ Presence(); /** 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); 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; /** 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()); }; class IQ : public Stanza { PCLASSINFO(IQ, Stanza) public: enum IQType { Get, Set, Result, Error, Unknown = 999 }; /** Various constant strings */ static const PString Type; IQ(IQType type, PXMLElement * body = 0); IQ(PXML& pdu); IQ(PXML * pdu); ~IQ(); virtual BOOL IsValid() const; static BOOL IsValid(const PXML * pdu); /** 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 SetType(IQType type); virtual void SetType(const PString& type); // custom, possibly non standard, type virtual void SetBody(PXMLElement * body); // 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; } protected: BOOL m_Processed; IQ * m_OriginalIQ; PNotifierList m_ResponseHandlers; }; /** JEP-0030 Service Discovery classes */ namespace Disco { class Item : public PObject { PCLASSINFO(Item, PObject); public: Item(PXMLElement * item); Item(const PString& jid, const PString& node = PString::Empty()); const JID& GetJID() const { return m_JID; } const PString& GetNode() const { return m_Node; } PXMLElement * AsXML(PXMLElement * parent) const; protected: const JID m_JID; const PString m_Node; }; PDECLARE_LIST(ItemList, Item) public: ItemList(PXMLElement * list); PXMLElement * AsXML(PXMLElement * parent) const; }; class Identity : public PObject { PCLASSINFO(Identity, PObject); public: Identity(PXMLElement * identity); Identity(const PString& category, const PString& type, const PString& name); const PString& GetCategory() const { return m_Category; } const PString& GetType() const { return m_Type; } const PString& GetName() const { return m_Name; } PXMLElement * AsXML(PXMLElement * parent) const; protected: const PString m_Category; const PString m_Type; const PString m_Name; }; PDECLARE_LIST(IdentityList, Identity) public: IdentityList(PXMLElement * list); PXMLElement * AsXML(PXMLElement * parent) const; }; class Info : public PObject { PCLASSINFO(Info, PObject); public: Info(PXMLElement * info); IdentityList& GetIdentities() { return m_Identities; } PStringSet& GetFeatures() { return m_Features; } PXMLElement * AsXML(PXMLElement * parent) const; protected: IdentityList m_Identities; PStringSet m_Features; }; } // namespace Disco }; // class XMPP #endif // P_EXPAT #endif // _XMPP // End of File ///////////////////////////////////////////////////////////////