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