1 /*
2  * xmpp.h
3  *
4  * Extensible Messaging and Presence Protocol (XMPP) Core
5  *
6  * Portable Windows Library
7  *
8  * Copyright (c) 2004 Reitek S.p.A.
9  *
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/
14  *
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.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Post Increment
23  *
24  * Contributor(s): ______________________________________.
25  *
26  * $Revision: 25387 $
27  * $Author: rjongbloed $
28  * $Date: 2011-03-22 22:51:09 -0500 (Tue, 22 Mar 2011) $
29  */
30 
31 #ifndef PTLIB_XMPP_H
32 #define PTLIB_XMPP_H
33 
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37 
38 #include <ptlib.h>
39 
40 #if P_EXPAT
41 
42 #include <ptclib/pxml.h>
43 #include <ptlib/notifier_ext.h>
44 
45 
46 ///////////////////////////////////////////////////////
47 
48 namespace XMPP
49 {
50   /** Various constant strings
51    */
52   extern const PCaselessString & LanguageTag();
53   extern const PCaselessString & NamespaceTag();
54   extern const PCaselessString & MessageStanzaTag();
55   extern const PCaselessString & PresenceStanzaTag();
56   extern const PCaselessString & IQStanzaTag();
57   extern const PCaselessString & IQQueryTag();
58 
59   class JID : public PObject
60   {
61     PCLASSINFO(JID, PObject);
62 
63   public:
64     JID(const char * jid = 0);
65     JID(const PString& jid);
66     JID(const PString& user, const PString& server, const PString& resource = PString::Empty());
67 
68     virtual Comparison Compare(
69       const PObject & obj   ///< Object to compare against.
70       ) const;
71 
72     JID& operator=(
73       const PString & jid  ///< New JID to assign.
74       );
75 
76     operator const PString&() const;
77 
Clone()78     virtual PObject * Clone() const { return new JID(m_JID); }
79 
GetUser()80     PString   GetUser() const         { return m_User; }
GetServer()81     PString   GetServer() const       { return m_Server; }
82 
GetResource()83     virtual PString GetResource() const { return m_Resource; }
84 
85     virtual void SetUser(const PString& user);
86     virtual void SetServer(const PString& server);
87     virtual void SetResource(const PString& resource);
88 
IsBare()89     virtual PBoolean IsBare() const       { return m_Resource.IsEmpty(); }
90     virtual void PrintOn(ostream & strm) const;
91 
92   protected:
93     virtual void ParseJID(const PString& jid);
94     virtual void BuildJID() const;
95 
96     PString   m_User;
97     PString   m_Server;
98     PString   m_Resource;
99 
100     mutable PString m_JID;
101     mutable PBoolean    m_IsDirty;
102   };
103 
104   // A bare jid is a jid with no resource
105   class BareJID : public JID
106   {
107     PCLASSINFO(BareJID, JID);
108 
109   public:
JID(jid)110     BareJID(const char * jid = 0) : JID(jid) { }
BareJID(const PString & jid)111     BareJID(const PString& jid) : JID(jid) { }
112     BareJID(const PString& user, const PString& server, const PString& resource = PString::Empty())
JID(user,server,resource)113       : JID(user, server, resource) { }
114 
115     virtual Comparison Compare(
116       const PObject & obj   ///< Object to compare against.
117       ) const;
118 
119     BareJID& operator=(
120       const PString & jid  ///< New JID to assign.
121       );
122 
Clone()123     virtual PObject * Clone() const { return new BareJID(m_JID); }
GetResource()124     virtual PString GetResource() const { return PString::Empty(); }
SetResource(const PString &)125     virtual void SetResource(const PString&) { }
IsBare()126     virtual PBoolean IsBare() const { return true; }
127   };
128 
129   /** This interface is the base class of each XMPP transport class
130 
131   Derived classes might include an XMPP TCP transport as well as
132   classes to handle XMPP incapsulated in SIP messages.
133   */
134   class Transport : public PIndirectChannel
135   {
136     PCLASSINFO(Transport, PIndirectChannel);
137 
138   public:
139     virtual PBoolean Open() = 0;
140     virtual PBoolean Close() = 0;
141   };
142 
143 
144 /** This class represents a XMPP stream, i.e. a XML message exchange
145     between XMPP entities
146  */
147   class Stream : public PIndirectChannel
148   {
149     PCLASSINFO(Stream, PIndirectChannel);
150 
151   public:
152     Stream(Transport * transport = 0);
153     ~Stream();
154 
OnOpen()155     virtual PBoolean        OnOpen()            { return m_OpenHandlers.Fire(*this); }
OpenHandlers()156     PNotifierList&      OpenHandlers()      { return m_OpenHandlers; }
157 
158     virtual PBoolean        Close();
OnClose()159     virtual void        OnClose()           { m_CloseHandlers.Fire(*this); }
CloseHandlers()160     PNotifierList&      CloseHandlers()     { return m_CloseHandlers; }
161 
162     virtual PBoolean        Write(const void * buf, PINDEX len);
163     virtual PBoolean        Write(const PString& data);
164     virtual PBoolean        Write(const PXML& pdu);
165 
166     /** Read a XMPP stanza from the stream
167     */
168     virtual PXML *      Read();
169 
170     /** Reset the parser. The will delete and re-instantiate the
171     XML stream parser.
172     */
173     virtual void        Reset();
GetParser()174     PXMLStreamParser *  GetParser()     { return m_Parser; }
175 
176   protected:
177     PXMLStreamParser *  m_Parser;
178     PNotifierList       m_OpenHandlers;
179     PNotifierList       m_CloseHandlers;
180   };
181 
182 
183   class BaseStreamHandler : public PThread
184   {
185     PCLASSINFO(BaseStreamHandler, PThread);
186 
187   public:
188     BaseStreamHandler();
189     ~BaseStreamHandler();
190 
191     virtual PBoolean        Start(Transport * transport = 0);
192     virtual PBoolean        Stop(const PString& error = PString::Empty());
193 
194     void                SetAutoReconnect(PBoolean b = true, long timeout = 1000);
195 
ElementHandlers()196     PNotifierList&      ElementHandlers()   { return m_ElementHandlers; }
GetStream()197     Stream *            GetStream()         { return m_Stream; }
198 
199     virtual PBoolean        Write(const void * buf, PINDEX len);
200     virtual PBoolean        Write(const PString& data);
201     virtual PBoolean        Write(const PXML& pdu);
202     virtual void        OnElement(PXML& pdu);
203 
204     virtual void        Main();
205 
206   protected:
207     PDECLARE_NOTIFIER(Stream, BaseStreamHandler, OnOpen);
208     PDECLARE_NOTIFIER(Stream, BaseStreamHandler, OnClose);
209 
210     Stream *        m_Stream;
211     PBoolean            m_AutoReconnect;
212     PTimeInterval   m_ReconnectTimeout;
213 
214     PNotifierList   m_ElementHandlers;
215   };
216 
217 
218   /** XMPP stanzas: the following classes represent the three
219     stanzas (PDUs) defined by the xmpp protocol
220    */
221 
222   class Stanza : public PXML
223   {
224     PCLASSINFO(Stanza, PXML)
225 
226   public:
227     /** Various constant strings
228     */
229     static const PCaselessString & IDTag();
230     static const PCaselessString & FromTag();
231     static const PCaselessString & ToTag();
232 
233     virtual PBoolean IsValid() const = 0;
234 
235     virtual PString GetID() const;
236     virtual PString GetFrom() const;
237     virtual PString GetTo() const;
238 
239     virtual void SetID(const PString& id);
240     virtual void SetFrom(const PString& from);
241     virtual void SetTo(const PString& to);
242 
243     virtual PXMLElement * GetElement(const PString& name, PINDEX i = 0);
244     virtual void AddElement(PXMLElement * elem);
245 
246     static PString GenerateID();
247   };
248 
249   PLIST(StanzaList, Stanza);
250 
251 
252   class Message : public Stanza
253   {
254     PCLASSINFO(Message, Stanza)
255 
256   public:
257     enum MessageType {
258       Normal,
259       Chat,
260       Error,
261       GroupChat,
262       HeadLine,
263       Unknown = 999
264     };
265 
266     /** Various constant strings
267     */
268     static const PCaselessString & TypeTag();
269     static const PCaselessString & SubjectTag();
270     static const PCaselessString & BodyTag();
271     static const PCaselessString & ThreadTag();
272 
273     /** Construct a new empty message
274     */
275     Message();
276 
277     /** Construct a message from a (received) xml PDU.
278     The root of the pdu MUST be a message stanza.
279     NOTE: the root of the pdu is cloned.
280     */
281     Message(PXML& pdu);
282     Message(PXML * pdu);
283 
284     virtual PBoolean IsValid() const;
285     static PBoolean IsValid(const PXML * pdu);
286 
287     virtual MessageType GetType(PString * typeName = 0) const;
288     virtual PString     GetLanguage() const;
289 
290     /** Get the subject for the specified language. The default subject (if any)
291     is returned in case no language is specified or a matching one cannot be
292     found
293     */
294     virtual PString GetSubject(const PString& lang = PString::Empty());
295     virtual PString GetBody(const PString& lang = PString::Empty());
296     virtual PString GetThread();
297 
298     virtual PXMLElement * GetSubjectElement(const PString& lang = PString::Empty());
299     virtual PXMLElement * GetBodyElement(const PString& lang = PString::Empty());
300 
301     virtual void SetType(MessageType type);
302     virtual void SetType(const PString& type); // custom, possibly non standard, type
303     virtual void SetLanguage(const PString& lang);
304 
305     virtual void SetSubject(const PString& subj, const PString& lang = PString::Empty());
306     virtual void SetBody(const PString& body, const PString& lang = PString::Empty());
307     virtual void SetThread(const PString& thrd);
308   };
309 
310 
311   class Presence : public Stanza
312   {
313     PCLASSINFO(Presence, Stanza)
314 
315   public:
316     enum PresenceType {
317       Available,
318       Unavailable,
319       Subscribe,
320       Subscribed,
321       Unsubscribe,
322       Unsubscribed,
323       Probe,
324       Error,
325       Unknown = 999
326     };
327 
328     enum ShowType {
329       Online,
330       Away,
331       Chat,
332       DND,
333       XA,
334       Other = 999
335     };
336 
337     /** Various constant strings
338     */
339     static const PCaselessString & TypeTag();
340     static const PCaselessString & ShowTag();
341     static const PCaselessString & StatusTag();
342     static const PCaselessString & PriorityTag();
343 
344     /** Construct a new empty presence
345     */
346     Presence();
347 
348     /** Construct a presence from a (received) xml PDU.
349     The root of the pdu MUST be a presence stanza.
350     NOTE: the root of the pdu is cloned.
351     */
352     Presence(PXML& pdu);
353     Presence(PXML * pdu);
354 
355     virtual PBoolean IsValid() const;
356     static PBoolean IsValid(const PXML * pdu);
357 
358     virtual PresenceType GetType(PString * typeName = 0) const;
359     virtual ShowType     GetShow(PString * showName = 0) const;
360     virtual BYTE         GetPriority() const;
361 
362     /** Get the status for the specified language. The default status (if any)
363     is returned in case no language is specified or a matching one cannot be
364     found
365     */
366     virtual PString GetStatus(const PString& lang = PString::Empty());
367     virtual PXMLElement * GetStatusElement(const PString& lang = PString::Empty());
368 
369     virtual void SetType(PresenceType type);
370     virtual void SetType(const PString& type); // custom, possibly non standard, type
371     virtual void SetShow(ShowType show);
372     virtual void SetShow(const PString& show); // custom, possibly non standard, type
373     virtual void SetPriority(BYTE priority);
374 
375     virtual void SetStatus(const PString& status, const PString& lang = PString::Empty());
376   };
377 
378 
379   class IQ : public Stanza
380   {
381     PCLASSINFO(IQ, Stanza)
382 
383   public:
384     enum IQType {
385       Get,
386       Set,
387       Result,
388       Error,
389       Unknown = 999
390     };
391 
392     /** Various constant strings
393     */
394     static const PCaselessString & TypeTag();
395 
396     IQ(IQType type, PXMLElement * body = 0);
397     IQ(PXML& pdu);
398     IQ(PXML * pdu);
399     ~IQ();
400 
401     virtual PBoolean IsValid() const;
402     static PBoolean IsValid(const PXML * pdu);
403 
404     /** This method signals that the message was taken care of
405     If the stream handler, after firing all the notifiers finds
406     that an iq set/get pdu has not being processed, it returns
407     an error to the sender
408     */
SetProcessed()409     void SetProcessed()             { m_Processed = true; }
HasBeenProcessed()410     PBoolean HasBeenProcessed() const   { return m_Processed; }
411 
412     virtual IQType        GetType(PString * typeName = 0) const;
413     virtual PXMLElement * GetBody();
414 
415     virtual void SetType(IQType type);
416     virtual void SetType(const PString& type); // custom, possibly non standard, type
417     virtual void SetBody(PXMLElement * body);
418 
419     // If the this message is response, returns a pointer to the
420     // original set/get message
GetOriginalMessage()421     virtual IQ *  GetOriginalMessage() const      { return m_OriginalIQ; }
422     virtual void  SetOriginalMessage(IQ * iq);
423 
424     /** Creates a new response iq for this message (that must
425     be of the set/get type!)
426     */
427     virtual IQ *  BuildResult() const;
428 
429     /** Creates an error response for this message
430     */
431     virtual IQ *  BuildError(const PString& type, const PString& code) const;
432 
GetResponseHandlers()433     virtual PNotifierList GetResponseHandlers()   { return m_ResponseHandlers; }
434 
435   protected:
436     PBoolean            m_Processed;
437     IQ *            m_OriginalIQ;
438     PNotifierList   m_ResponseHandlers;
439   };
440   /** JEP-0030 Service Discovery classes
441    */
442   namespace Disco
443   {
444     class Item : public PObject
445     {
446       PCLASSINFO(Item, PObject);
447     public:
448       Item(PXMLElement * item);
449       Item(const PString& jid, const PString& node = PString::Empty());
450 
GetJID()451       const JID&      GetJID() const    { return m_JID; }
GetNode()452       const PString&  GetNode() const   { return m_Node; }
453 
454       PXMLElement *   AsXML(PXMLElement * parent) const;
455 
456     protected:
457       const JID     m_JID;
458       const PString m_Node;
459     };
460 
461     PDECLARE_LIST(ItemList, Item)
462     public:
463       ItemList(PXMLElement * list);
464       PXMLElement * AsXML(PXMLElement * parent) const;
465     };
466 
467     class Identity : public PObject
468     {
469       PCLASSINFO(Identity, PObject);
470     public:
471       Identity(PXMLElement * identity);
472       Identity(const PString& category, const PString& type, const PString& name);
473 
GetCategory()474       const PString&  GetCategory() const   { return m_Category; }
GetType()475       const PString&  GetType() const       { return m_Type; }
GetName()476       const PString&  GetName() const       { return m_Name; }
477 
478       PXMLElement *   AsXML(PXMLElement * parent) const;
479 
480     protected:
481       const PString m_Category;
482       const PString m_Type;
483       const PString m_Name;
484     };
485 
486     PDECLARE_LIST(IdentityList, Identity)
487     public:
488       IdentityList(PXMLElement * list);
489       PXMLElement * AsXML(PXMLElement * parent) const;
490     };
491 
492     class Info : public PObject
493     {
494       PCLASSINFO(Info, PObject);
495     public:
496       Info(PXMLElement * info);
497 
GetIdentities()498       IdentityList&   GetIdentities() { return m_Identities; }
GetFeatures()499       PStringSet&     GetFeatures()   { return m_Features; }
500 
501       PXMLElement *   AsXML(PXMLElement * parent) const;
502 
503     protected:
504       IdentityList  m_Identities;
505       PStringSet    m_Features;
506     };
507   } // namespace Disco
508 
509 }; // class XMPP
510 
511 
512 #endif  // P_EXPAT
513 
514 #endif  // PTLIB_XMPP_H
515 
516 // End of File ///////////////////////////////////////////////////////////////
517