Yate
|
00001 00024 #ifndef __XMPPUTILS_H 00025 #define __XMPPUTILS_H 00026 00027 #include <yateclass.h> 00028 #include <yatexml.h> 00029 00030 #ifdef _WINDOWS 00031 00032 #ifdef LIBYJABBER_EXPORTS 00033 #define YJABBER_API __declspec(dllexport) 00034 #else 00035 #ifndef LIBYJABBER_STATIC 00036 #define YJABBER_API __declspec(dllimport) 00037 #endif 00038 #endif 00039 00040 #endif /* _WINDOWS */ 00041 00042 #ifndef YJABBER_API 00043 #define YJABBER_API 00044 #endif 00045 00046 // Support old RFC 3920 00047 // If not defined RFC 3920bis changes will be used 00048 #define RFC3920 00049 00053 namespace TelEngine { 00054 00055 class StringArray; // A String array 00056 class XMPPNamespace; // XMPP namespaces 00057 class XMPPError; // XMPP errors 00058 class JabberID; // A Jabber ID (JID) 00059 class JIDIdentity; // A JID's identity 00060 class JIDIdentityList; // A list of JID identities 00061 class XMPPFeature; // A feature (stream or JID) 00062 class XMPPFeatureSasl; // A SASL feature 00063 class XMPPFeatureCompress; // A stream compression feature 00064 class XMPPFeatureList; // Feature list 00065 class XMPPUtils; // Utilities 00066 class XMPPDirVal; // Direction flags 00067 class XmlElementOut; // An outgoing xml element 00068 00073 class YJABBER_API StringArray 00074 { 00075 public: 00081 inline StringArray(const String* array, unsigned int len) 00082 : m_array((String*)array), m_length(len) 00083 {} 00084 00090 inline const String& at(unsigned int index) const 00091 { return index < m_length ? m_array[index] : String::empty(); } 00092 00098 inline const String& operator[](unsigned int index) const 00099 { return m_array[index]; } 00100 00106 inline int operator[](const String& token) { 00107 unsigned int i = 0; 00108 for (; i < m_length; i++) 00109 if (m_array[i] == token) 00110 return i; 00111 return m_length; 00112 } 00113 00114 protected: 00115 String* m_array; 00116 unsigned int m_length; 00117 00118 private: 00119 StringArray() {} 00120 }; 00121 00122 00127 class YJABBER_API XMPPNamespace : public StringArray 00128 { 00129 public: 00133 enum Type { 00134 Stream = 0, // http://etherx.jabber.org/streams 00135 Client, // jabber:client 00136 Server, // jabber:server 00137 Dialback, // jabber:server:dialback 00138 StreamError, // urn:ietf:params:xml:ns:xmpp-streams 00139 StanzaError, // urn:ietf:params:xml:ns:xmpp-stanzas 00140 Ping, // urn:xmpp:ping 00141 Register, // http://jabber.org/features/iq-register 00142 IqRegister, // jabber:iq:register 00143 IqPrivate, // jabber:iq:private 00144 IqAuth, // jabber:iq:auth 00145 IqAuthFeature, // http://jabber.org/features/iq-auth 00146 IqVersion, // jabber:iq:version 00147 Delay, // urn:xmpp:delay 00148 Tls, // urn:ietf:params:xml:ns:xmpp-tls 00149 Sasl, // urn:ietf:params:xml:ns:xmpp-sasl 00150 Session, // urn:ietf:params:xml:ns:xmpp-session 00151 Bind, // urn:ietf:params:xml:ns:xmpp-bind 00152 Roster, // jabber:iq:roster 00153 DynamicRoster, // jabber:iq:roster-dynamic 00154 DiscoInfo, // http://jabber.org/protocol/disco#info 00155 DiscoItems, // http://jabber.org/protocol/disco#items 00156 EntityCaps, // http://jabber.org/protocol/caps 00157 VCard, // vcard-temp 00158 SIProfileFileTransfer, // http://jabber.org/protocol/si/profile/file-transfer 00159 ByteStreams, // http://jabber.org/protocol/bytestreams 00160 Jingle, // urn:xmpp:jingle:1 00161 JingleError, // urn:xmpp:jingle:errors:1 00162 JingleAppsRtp, // urn:xmpp:jingle:apps:rtp:1 00163 JingleAppsRtpError, // urn:xmpp:jingle:apps:rtp:errors:1 00164 JingleAppsRtpInfo, // urn:xmpp:jingle:apps:rtp:info:1 00165 JingleAppsRtpAudio, // urn:xmpp:jingle:apps:rtp:audio 00166 JingleAppsFileTransfer, // urn:xmpp:jingle:apps:file-transfer:1 00167 JingleTransportIceUdp, // urn:xmpp:jingle:transports:ice-udp:1 00168 JingleTransportRawUdp, // urn:xmpp:jingle:transports:raw-udp:1 00169 JingleTransportRawUdpInfo, // urn:xmpp:jingle:transports:raw-udp:info:1 00170 JingleTransportByteStreams, // urn:xmpp:jingle:transports:bytestreams:1 00171 JingleTransfer, // urn:xmpp:jingle:transfer:0 00172 JingleDtmf, // urn:xmpp:jingle:dtmf:0 00173 JingleSession, // http://www.google.com/session 00174 JingleAudio, // http://www.google.com/session/phone 00175 JingleTransport, // http://www.google.com/transport/p2p 00176 JingleVoiceV1, // http://www.google.com/xmpp/protocol/voice/v1 00177 JingleRtpInfoOld, // urn:xmpp:jingle:apps:rtp:info 00178 DtmfOld, // http://jabber.org/protocol/jingle/info/dtmf 00179 XOob, // jabber:x:oob 00180 Command, // http://jabber.org/protocol/command 00181 MsgOffline, // msgoffline 00182 ComponentAccept, // jabber:component:accept 00183 Muc, // http://jabber.org/protocol/muc 00184 MucAdmin, // http://jabber.org/protocol/muc#admin 00185 MucOwner, // http://jabber.org/protocol/muc#owner 00186 MucUser, // http://jabber.org/protocol/muc#user 00187 DialbackFeature, // urn:xmpp:features:dialback 00188 Compress, // http://jabber.org/protocol/compress 00189 CompressFeature, // http://jabber.org/features/compress 00190 XData, // jabber:x:data 00191 ChatStates, // http://jabber.org/protocol/chatstates 00192 YateCluster, // http://yate.null.ro/yate/cluster 00193 // This value MUST be the last one: it's used as array bound 00194 Count, 00195 }; 00196 00200 inline XMPPNamespace() 00201 : StringArray(s_array,Count) 00202 {} 00203 00204 private: 00205 static const String s_array[Count]; // Namespace list 00206 }; 00207 00208 00213 class YJABBER_API XMPPError : public StringArray 00214 { 00215 public: 00219 enum Type { 00220 NoError = 0, 00221 BadFormat, // bad-format 00222 BadNamespace, // bad-namespace-prefix 00223 Conflict, // conflict 00224 ConnTimeout, // connection-timeout 00225 HostGone, // host-gone 00226 HostUnknown, // host-unknown 00227 BadAddressing, // improper-addressing 00228 Internal, // internal-server-error 00229 InvalidFrom, // invalid-from 00230 InvalidId, // invalid-id 00231 InvalidNamespace, // invalid-namespace 00232 InvalidXml, // invalid-xml 00233 NotAuth, // not-authorized 00234 Policy, // policy-violation 00235 RemoteConn, // remote-connection-failed 00236 ResConstraint, // resource-constraint 00237 RestrictedXml, // restricted-xml 00238 SeeOther, // see-other-host 00239 Shutdown, // system-shutdown 00240 UndefinedCondition, // undefined-condition 00241 UnsupportedEnc, // unsupported-encoding 00242 UnsupportedStanza, // unsupported-stanza-type 00243 UnsupportedVersion, // unsupported-version 00244 Xml, // xml-not-well-formed 00245 Aborted, // aborted 00246 AccountDisabled, // account-disabled 00247 CredentialsExpired, // credentials-expired 00248 EncryptionRequired, // encryption-required 00249 IncorrectEnc, // incorrect-encoding 00250 InvalidAuth, // invalid-authzid 00251 InvalidMechanism, // invalid-mechanism 00252 MalformedRequest, // malformed-request 00253 MechanismTooWeak, // mechanism-too-weak 00254 NotAuthorized, // not-authorized 00255 TempAuthFailure, // temporary-auth-failure 00256 TransitionNeeded, // transition-needed 00257 ResourceConstraint, // resource-constraint 00258 NotAllowed, // not-allowed 00259 BadRequest, // bad-request 00260 FeatureNotImpl, // feature-not-implemented 00261 Forbidden, // forbidden 00262 Gone, // gone 00263 ItemNotFound, // item-not-found 00264 BadJid, // jid-malformed 00265 NotAcceptable, // not-acceptable 00266 Payment, // payment-required 00267 Unavailable, // recipient-unavailable 00268 Redirect, // redirect 00269 Reg, // registration-required 00270 NoRemote, // remote-server-not-found 00271 RemoteTimeout, // remote-server-timeout 00272 ServiceUnavailable, // service-unavailable 00273 Subscription, // subscription-required 00274 Request, // unexpected-request 00275 SocketError, // Don't send any error or stream end tag to remote party 00276 UnsupportedMethod, // unsupported-method 00277 SetupFailed, // setup-failed 00278 // This value MUST be the last one: it's used as error type start 00279 TypeCount 00280 }; 00281 00285 enum ErrorType { 00286 TypeCancel = TypeCount, // do not retry (the error is unrecoverable) 00287 TypeContinue, // proceed (the condition was only a warning) 00288 TypeModify, // retry after changing the data sent 00289 TypeAuth, // retry after providing credentials 00290 TypeWait, // retry after waiting (the error is temporary) 00291 // This value MUST be the last one: it's used as array bound 00292 Count 00293 }; 00294 00298 inline XMPPError() 00299 : StringArray(s_array,Count) 00300 {} 00301 00302 private: 00303 static const String s_array[Count]; // Error list 00304 }; 00305 00310 class YJABBER_API XmlTag : public StringArray 00311 { 00312 public: 00316 enum Type { 00317 Stream = 0, // stream 00318 Error, // error 00319 Features, // features 00320 Register, // register 00321 Starttls, // starttls 00322 Auth, // auth 00323 Challenge, // challenge 00324 Abort, // abort 00325 Aborted, // aborted 00326 Response, // response 00327 Proceed, // proceed 00328 Success, // success 00329 Failure, // failure 00330 Mechanisms, // mechanisms 00331 Mechanism, // mechanism 00332 Session, // session 00333 Iq, // iq 00334 Message, // message 00335 Presence, // presence 00336 Query, // query 00337 VCard, // vCard 00338 Jingle, // jingle 00339 Description, // description 00340 PayloadType, // payload-type 00341 Transport, // transport 00342 Candidate, // candidate 00343 Body, // body 00344 Subject, // subject 00345 Feature, // feature 00346 Bind, // bind 00347 Resource, // resource 00348 Transfer, // transfer 00349 Hold, // hold 00350 Active, // active 00351 Ringing, // ringing 00352 Mute, // mute 00353 Registered, // registered 00354 Remove, // remove 00355 Jid, // jid 00356 Username, // username 00357 Password, // password 00358 Digest, // digest 00359 Required, // required 00360 Optional, // optional 00361 Dtmf, // dtmf 00362 DtmfMethod, // dtmf-method 00363 Command, // command 00364 Text, // text 00365 Item, // item 00366 Group, // group 00367 Reason, // reason 00368 Content, // content 00369 Trying, // trying 00370 Received, // received 00371 File, // file 00372 Offer, // offer 00373 Request, // request 00374 StreamHost, // streamhost 00375 StreamHostUsed, // streamhost-used 00376 Ping, // ping 00377 Encryption, // encryption 00378 Crypto, // crypto 00379 Parameter, // parameter 00380 Identity, // identity 00381 Priority, // priority 00382 EntityCapsTag, // c 00383 Handshake, // handshake 00384 Dialback, // dialback 00385 Method, // method 00386 Compress, // compress 00387 Compressed, // compressed 00388 Compression, // compression 00389 X, // x 00390 // This value MUST be the last one: it's used as array bound 00391 Count 00392 }; 00393 00397 inline XmlTag() 00398 : StringArray(s_array,Count) 00399 {} 00400 00401 private: 00402 static const String s_array[Count]; // Tag list 00403 }; 00404 00405 00410 class YJABBER_API JabberID : public String 00411 { 00412 YCLASS(JabberID,String) 00413 public: 00417 inline JabberID() {} 00418 00423 inline JabberID(const char* jid) 00424 { set(jid); } 00425 00430 inline JabberID(const String& jid) 00431 { set(jid); } 00432 00437 inline JabberID(const String* jid) 00438 { set(TelEngine::c_safe(jid)); } 00439 00446 inline JabberID(const char* node, const char* domain, const char* resource = 0) 00447 { set(node,domain,resource); } 00448 00453 inline JabberID(const JabberID& src) 00454 { *this = src; } 00455 00460 inline bool valid() const 00461 { return null() || m_domain; } 00462 00467 inline const String& node() const 00468 { return m_node; } 00469 00474 inline const String& bare() const 00475 { return m_bare; } 00476 00481 inline const String& domain() const 00482 { return m_domain; } 00483 00488 inline void domain(const char* d) 00489 { set(m_node.c_str(),d,m_resource.c_str()); } 00490 00495 inline const String& resource() const 00496 { return m_resource; } 00497 00502 inline bool isFull() const 00503 { return m_node && m_domain && m_resource; } 00504 00508 inline void clear() { 00509 String::clear(); 00510 m_node.clear(); 00511 m_domain.clear(); 00512 m_resource.clear(); 00513 m_bare.clear(); 00514 } 00515 00522 inline bool match(const JabberID& src) const 00523 { return (src.resource().null() || (resource() == src.resource())) && (bare() &= src.bare()); } 00524 00530 JabberID& operator=(const JabberID& src); 00531 00537 inline JabberID& operator=(const String& src) 00538 { set(src); return *this; } 00539 00545 inline JabberID& operator=(const String* src) 00546 { set(TelEngine::c_safe(src)); return *this; } 00547 00554 inline bool operator==(const JabberID& src) const 00555 { return (resource() == src.resource()) && (bare() &= src.bare()); } 00556 00562 inline bool operator==(const String& src) const 00563 { JabberID tmp(src); return operator==(tmp); } 00564 00570 inline bool operator!=(const JabberID& src) const 00571 { return !operator==(src); } 00572 00578 inline bool operator!=(const String& src) const 00579 { return !operator==(src); } 00580 00585 inline void resource(const char* res) 00586 { set(m_node.c_str(),m_domain.c_str(),res); } 00587 00592 void set(const char* jid); 00593 00600 void set(const char* node, const char* domain, const char* resource = 0); 00601 00606 static const JabberID& empty(); 00607 00613 static bool valid(const String& value); 00614 00618 static Regexp s_regExpValid; 00619 00620 private: 00621 void parse(); // Parse the string. Set the data 00622 00623 String m_node; // The node part 00624 String m_domain; // The domain part 00625 String m_resource; // The resource part 00626 String m_bare; // The bare JID: node@domain 00627 }; 00628 00629 00636 class YJABBER_API JIDIdentity : public GenObject 00637 { 00638 YCLASS(JIDIdentity,GenObject) 00639 public: 00646 inline JIDIdentity(const char* c, const char* t, const char* name = 0) 00647 : m_category(c), m_type(t), m_name(name) 00648 {} 00649 00654 inline JIDIdentity(XmlElement* identity) 00655 { fromXml(identity); } 00656 00661 inline XmlElement* toXml() const { 00662 if (!(m_category && m_type)) 00663 return 0; 00664 return createIdentity(m_category,m_type,m_name); 00665 } 00666 00671 void fromXml(XmlElement* identity); 00672 00680 static XmlElement* createIdentity(const char* category, 00681 const char* type, const char* name); 00682 00683 String m_category; 00684 String m_type; 00685 String m_name; 00686 }; 00687 00688 00693 class YJABBER_API JIDIdentityList : public ObjList 00694 { 00695 YCLASS(JIDIdentityList,ObjList) 00696 public: 00701 void toXml(XmlElement* parent) const; 00702 00707 void fromXml(XmlElement* parent); 00708 }; 00709 00714 class YJABBER_API XMPPFeature : public String 00715 { 00716 YCLASS(XMPPFeature,GenObject) 00717 public: 00724 inline XMPPFeature(int xml, int feature, bool required = false) 00725 : m_xml(xml), m_required(required) 00726 { setFeature(feature); } 00727 00734 inline XMPPFeature(int xml, const char* feature, bool required = false) 00735 : String(feature), m_xml(xml), m_required(required) 00736 {} 00737 00742 inline XMPPFeature(int feature) 00743 : m_xml(XmlTag::Count), m_required(false) 00744 { setFeature(feature); } 00745 00750 inline XMPPFeature(const char* feature) 00751 : String(feature), m_xml(XmlTag::Count), m_required(false) 00752 {} 00753 00757 virtual ~XMPPFeature() 00758 {} 00759 00764 inline bool required() const 00765 { return m_required; } 00766 00772 virtual XmlElement* build(bool addReq = true); 00773 00778 virtual XmlElement* buildFeature(); 00779 00784 void addReqChild(XmlElement& xml); 00785 00791 static XMPPFeature* fromStreamFeature(XmlElement& xml); 00792 00793 private: 00794 void setFeature(int feature); 00795 00796 int m_xml; // Element tag as enumeration 00797 bool m_required; // Required flag 00798 }; 00799 00800 00805 class YJABBER_API XMPPFeatureSasl : public XMPPFeature 00806 { 00807 YCLASS(XMPPFeatureSasl,XMPPFeature) 00808 public: 00814 inline XMPPFeatureSasl(int mech, bool required = false) 00815 : XMPPFeature(XmlTag::Mechanisms,XMPPNamespace::Sasl,required), 00816 m_mechanisms(mech) 00817 {} 00818 00823 inline int mechanisms() const 00824 { return m_mechanisms; } 00825 00830 inline bool mechanism(int mech) const 00831 { return 0 != (m_mechanisms & mech); } 00832 00838 virtual XmlElement* build(bool addReq = true); 00839 00840 private: 00841 int m_mechanisms; // Authentication mechanisms 00842 }; 00843 00844 00849 class YJABBER_API XMPPFeatureCompress : public XMPPFeature 00850 { 00851 YCLASS(XMPPFeatureCompress,XMPPFeature) 00852 public: 00858 inline XMPPFeatureCompress(const String& meth, bool required = false) 00859 : XMPPFeature(XmlTag::Compression,XMPPNamespace::CompressFeature,required), 00860 m_methods(meth) 00861 {} 00862 00867 inline const String& methods() const 00868 { return m_methods; } 00869 00875 bool hasMethod(const String& method) const; 00876 00882 virtual XmlElement* build(bool addReq = true); 00883 00884 private: 00885 String m_methods; // Compression methods 00886 }; 00887 00888 00893 class YJABBER_API XMPPFeatureList : public ObjList 00894 { 00895 YCLASS(XMPPFeatureList,ObjList) 00896 public: 00904 inline bool add(int xml, int feature, bool required = false) { 00905 if (get(feature)) 00906 return false; 00907 append(new XMPPFeature(xml,feature,required)); 00908 return true; 00909 } 00910 00916 inline bool add(int feature) { 00917 if (get(feature)) 00918 return false; 00919 append(new XMPPFeature(feature)); 00920 return true; 00921 } 00922 00928 inline bool add(XMPPFeature* feature) { 00929 if (!feature || get(*feature)) { 00930 TelEngine::destruct(feature); 00931 return false; 00932 } 00933 append(feature); 00934 return true; 00935 } 00936 00940 inline void reset() { 00941 clear(); 00942 m_identities.clear(); 00943 m_entityCapsHash.clear(); 00944 } 00945 00950 void add(XMPPFeatureList& list); 00951 00956 void fromStreamFeatures(XmlElement& xml); 00957 00962 void fromDiscoInfo(XmlElement& xml); 00963 00968 inline void remove(int feature) 00969 { ObjList::remove(get(feature),true); } 00970 00976 XMPPFeature* get(int feature); 00977 00983 inline XMPPFeature* get(const String& feature) { 00984 ObjList* o = find(feature); 00985 return o ? static_cast<XMPPFeature*>(o->get()) : 0; 00986 } 00987 00992 inline XMPPFeatureSasl* getSasl() 00993 { return YOBJECT(XMPPFeatureSasl,get(XMPPNamespace::Sasl)); } 00994 00999 inline XMPPFeatureCompress* getCompress() 01000 { return YOBJECT(XMPPFeatureCompress,get(XMPPNamespace::CompressFeature)); } 01001 01006 XmlElement* buildStreamFeatures(); 01007 01017 XmlElement* buildDiscoInfo(const char* from, const char* to, const char* id, 01018 const char* node = 0, const char* cap = 0); 01019 01024 void add(XmlElement& xml); 01025 01029 void updateEntityCaps(); 01030 01031 JIDIdentityList m_identities; 01032 String m_entityCapsHash; // SHA-1 entity caps as defined in XEP 0115 01033 }; 01034 01035 01040 class YJABBER_API XMPPUtils 01041 { 01042 public: 01046 enum Presence { 01047 Probe, // probe 01048 Subscribe, // subscribe request 01049 Subscribed, // subscribe accepted 01050 Unavailable, // unavailable 01051 Unsubscribe, // unsubscribe request 01052 Unsubscribed, // unsubscribe accepted 01053 PresenceError, // error 01054 PresenceNone 01055 }; 01056 01060 enum MsgType { 01061 Chat, // chat 01062 GroupChat, // groupchat 01063 HeadLine, // headline 01064 Normal, // normal 01065 MsgError, // error 01066 }; 01067 01071 enum IqType { 01072 IqSet, // set 01073 IqGet, // get 01074 IqResult, // result 01075 IqError, // error 01076 IqCount 01077 }; 01078 01082 enum CommandAction { 01083 CommExecute, 01084 CommCancel, 01085 CommPrev, 01086 CommNext, 01087 CommComplete, 01088 }; 01089 01093 enum CommandStatus { 01094 CommExecuting, 01095 CommCompleted, 01096 CommCancelled, 01097 }; 01098 01102 enum AuthMethod { 01103 AuthNone = 0x00, // No authentication mechanism 01104 AuthSHA1 = 0x01, // SHA1 digest 01105 AuthMD5 = 0x02, // MD5 digest 01106 AuthPlain = 0x04, // Plain text password 01107 AuthDialback = 0x08, // Dialback authentication 01108 }; 01109 01115 static inline bool isResponse(const XmlElement& xml) { 01116 String* tmp = xml.getAttribute("type"); 01117 return tmp && (*tmp == "result" || *tmp == "error"); 01118 } 01119 01127 static inline XmlElement* createElement(const char* name, const char* text = 0, 01128 const String& ns = String::empty()) { 01129 XmlElement* xml = new XmlElement(String(name),true); 01130 if (!TelEngine::null(text)) 01131 xml->addText(text); 01132 if (ns) 01133 xml->setXmlns(String::empty(),true,ns); 01134 return xml; 01135 } 01136 01143 static inline XmlElement* createElement(int type, const char* text = 0) 01144 { return createElement(s_tag[type],text); } 01145 01153 static inline XmlElement* createElement(const char* name, int ns, 01154 const char* text = 0) { 01155 XmlElement* xml = createElement(name,text); 01156 setXmlns(*xml,String::empty(),true,ns); 01157 return xml; 01158 } 01159 01167 static inline XmlElement* createElement(int type, int ns, const char* text = 0) 01168 { return createElement(s_tag[type],ns,text); } 01169 01178 static XmlElement* createElement(const XmlElement& src, bool response, bool result); 01179 01188 static XmlElement* createIq(IqType type, const char* from = 0, 01189 const char* to = 0, const char* id = 0); 01190 01199 static inline XmlElement* createIqResult(const char* from, const char* to, 01200 const char* id, XmlElement* child = 0) { 01201 XmlElement* xml = createIq(IqResult,from,to,id); 01202 if (child) 01203 xml->addChild(child); 01204 return xml; 01205 } 01206 01218 static XmlElement* createIqError(const char* from, const char* to, XmlElement*& xml, 01219 int type, int error, const char* text = 0); 01220 01229 static XmlElement* createVCard(bool get, const char* from, const char* to, const char* id); 01230 01238 static XmlElement* createCommand(CommandAction action, const char* node, 01239 const char* sessionId = 0); 01240 01252 static XmlElement* createIqDisco(bool info, bool req, const char* from, const char* to, 01253 const char* id, const char* node = 0, const char* cap = 0); 01254 01265 static XmlElement* createIqVersionRes(const char* from, const char* to, 01266 const char* id, const char* name, const char* version, const char* os = 0); 01267 01275 static XmlElement* createError(int type, int error, const char* text = 0); 01276 01286 static XmlElement* createError(XmlElement* xml, int type, int error, 01287 const char* text = 0); 01288 01295 static XmlElement* createStreamError(int error, const char* text = 0); 01296 01308 static XmlElement* createRegisterQuery(IqType type, const char* from, 01309 const char* to, const char* id, 01310 XmlElement* child1 = 0, XmlElement* child2 = 0, XmlElement* child3 = 0); 01311 01317 static inline XmlElement* createIqAuthGet(const char* id) { 01318 XmlElement* iq = createIq(IqGet,0,0,id); 01319 iq->addChild(createElement(XmlTag::Query,XMPPNamespace::IqAuth)); 01320 return iq; 01321 } 01322 01332 static XmlElement* createIqAuthSet(const char* id, const char* username, 01333 const char* resource, const char* authStr, bool digest); 01334 01342 static XmlElement* createIqAuthOffer(const char* id, bool digest = true, 01343 bool plain = false); 01344 01354 static inline XmlElement* createRegisterQuery(const char* from, 01355 const char* to, const char* id, 01356 const char* username, const char* password) { 01357 return createRegisterQuery(XMPPUtils::IqSet,from,to,id, 01358 createElement(XmlTag::Username,username), 01359 createElement(XmlTag::Password,password)); 01360 } 01361 01368 static inline XmlElement* createFailure(XMPPNamespace::Type ns, 01369 XMPPError::Type error = XMPPError::NoError) { 01370 XmlElement* xml = createElement(XmlTag::Failure,ns); 01371 if (error != XMPPError::NoError) 01372 xml->addChild(new XmlElement(s_error[error])); 01373 return xml; 01374 } 01375 01382 static inline XmlElement* createXOobUrl(const char* url, const char* desc = 0) { 01383 XmlElement* xml = createElement(XmlTag::X,XMPPNamespace::XOob); 01384 xml->addChild(createElement("url",url)); 01385 if (desc) 01386 xml->addChild(createElement("desc",desc)); 01387 return xml; 01388 } 01389 01398 static XmlElement* createDelay(unsigned int timeSec, const char* from = 0, 01399 unsigned int fractions = 0, const char* text = 0); 01400 01406 static inline bool remove(XmlElement& xml) 01407 { return 0 != findFirstChild(xml,XmlTag::Remove); } 01408 01414 static inline bool required(XmlElement& xml) 01415 { return 0 != findFirstChild(xml,XmlTag::Required); } 01416 01423 static int priority(XmlElement& xml, int defVal = 0); 01424 01430 static inline void setPriority(XmlElement& xml, const char* prio) 01431 { xml.addChild(createElement(XmlTag::Priority,prio)); } 01432 01438 static inline int xmlns(XmlElement& xml) { 01439 String* x = xml.xmlns(); 01440 return x ? s_ns[*x] : XMPPNamespace::Count; 01441 } 01442 01449 static inline bool hasDefaultXmlns(const XmlElement& xml, int ns) { 01450 String* s = xml.xmlnsAttribute(XmlElement::s_ns); 01451 return s && *s == s_ns[ns]; 01452 } 01453 01460 static inline bool hasXmlns(const XmlElement& xml, int ns) 01461 { return xml.hasXmlns(s_ns[ns]); } 01462 01471 static inline bool setXmlns(XmlElement& xml, const String& name = String::empty(), 01472 bool addAttr = false, int ns = XMPPNamespace::Count) { 01473 if (ns < XMPPNamespace::Count) 01474 return xml.setXmlns(name,addAttr,s_ns[ns]); 01475 return xml.setXmlns(name); 01476 } 01477 01484 static inline bool setStreamXmlns(XmlElement& xml, bool addAttr = true) 01485 { return setXmlns(xml,"stream",addAttr,XMPPNamespace::Stream); } 01486 01492 static inline bool setDbXmlns(XmlElement& xml) 01493 { return setXmlns(xml,"db",true,XMPPNamespace::Dialback); } 01494 01502 static XmlElement* findFirstChild(const XmlElement& xml, int t = XmlTag::Count, 01503 int ns = XMPPNamespace::Count); 01504 01513 static XmlElement* findNextChild(const XmlElement& xml, XmlElement* start, 01514 int t = XmlTag::Count, int ns = XMPPNamespace::Count); 01515 01524 static void decodeError(XmlElement* xml, int ns = XMPPNamespace::Count, 01525 String* error = 0, String* text = 0); 01526 01533 static void decodeError(XmlElement* xml, String& error, String& text); 01534 01542 static void encodeDateTimeSec(String& buf, unsigned int timeSec, 01543 unsigned int fractions = 0); 01544 01552 static unsigned int decodeDateTimeSec(const String& time, unsigned int* fractions = 0); 01553 01559 static unsigned int decodeDateTimeSecXDelay(const String& time); 01560 01567 static void print(String& xmlStr, XmlChild& xml, bool verbose); 01568 01575 static void toList(XmlElement& xml, NamedList& dest, const char* prefix); 01576 01586 static bool split(NamedList& dest, const char* src, const char sep, 01587 bool nameFirst); 01588 01595 static int decodeFlags(const String& src, const TokenDict* dict); 01596 01603 static void buildFlags(String& dest, int src, const TokenDict* dict); 01604 01611 static bool addChidren(XmlElement* dest, ObjList& list); 01612 01619 static XmlElement* createEntityCaps(const String& hash, const char* node); 01620 01627 static XmlElement* createEntityCapsGTalkV1(const char* node = 0, 01628 bool muc = false); 01629 01637 static XmlElement* createPresence(const char* from, 01638 const char* to, Presence type = PresenceNone); 01639 01649 static XmlElement* createMessage(const char* type, const char* from, 01650 const char* to, const char* id, const char* body); 01651 01661 static inline XmlElement* createMessage(MsgType type, const char* from, 01662 const char* to, const char* id, const char* body) 01663 { return createMessage(msgText(type),from,to,id,body); } 01664 01672 static XmlElement* createDialbackKey(const char* from, const char* to, 01673 const char* key); 01674 01683 static XmlElement* createDialbackResult(const char* from, const char* to, 01684 XMPPError::Type rsp = XMPPError::NoError); 01685 01694 static XmlElement* createDialbackVerify(const char* from, const char* to, 01695 const char* id, const char* key); 01696 01706 static XmlElement* createDialbackVerifyRsp(const char* from, const char* to, 01707 const char* id, XMPPError::Type rsp = XMPPError::NoError); 01708 01715 static int decodeDbRsp(XmlElement* xml); 01716 01722 static inline XmlElement* createSubject(const char* subject) 01723 { return createElement(XmlTag::Subject,subject); } 01724 01730 static inline const String& subject(XmlElement& xml) { 01731 XmlElement* s = findFirstChild(xml,XmlTag::Subject); 01732 return s ? s->getText() : String::empty(); 01733 } 01734 01741 static inline XmlElement* createBody(const char* body, int ns = XMPPNamespace::Count) 01742 { return createElement(XmlTag::Body,ns,body); } 01743 01750 static const String& body(XmlElement& xml, int ns = XMPPNamespace::Count); 01751 01759 static inline XmlElement* createParameter(const char* name, const char* value, 01760 const char* tag = "parameter") { 01761 XmlElement* tmp = new XmlElement(tag); 01762 tmp->setAttributeValid("name",name); 01763 tmp->setAttributeValid("value",value); 01764 return tmp; 01765 } 01766 01773 static inline XmlElement* createParameter(const NamedString& pair, 01774 const char* tag = "parameter") 01775 { return createParameter(pair.name(),pair,tag); } 01776 01782 static inline int ns(const XmlElement& xml) { 01783 String* xmlns = xml.xmlns(); 01784 return xmlns ? s_ns[*xmlns] : XMPPNamespace::Count; 01785 } 01786 01792 static inline int tag(const XmlElement& xml) 01793 { return s_tag[xml.getTag()]; } 01794 01802 static inline bool getTag(const XmlElement& xml, int& tag, int& ns) { 01803 const String* t = 0; 01804 const String* n = 0; 01805 if (!xml.getTag(t,n)) 01806 return false; 01807 tag = s_tag[*t]; 01808 ns = n ? s_ns[*n] : XMPPNamespace::Count; 01809 return tag != XmlTag::Count; 01810 } 01811 01819 static inline bool isTag(const XmlElement& xml, int tag, int ns) { 01820 int t,n; 01821 return getTag(xml,t,n) && tag == t && n == ns; 01822 } 01823 01830 static inline bool isUnprefTag(const XmlElement& xml, int tag) 01831 { return xml.unprefixedTag() == s_tag[tag]; } 01832 01838 static inline bool isStanza(const XmlElement& xml) { 01839 int t,n; 01840 return getTag(xml,t,n) && 01841 (t == XmlTag::Iq || t == XmlTag::Presence || t == XmlTag::Message); 01842 } 01843 01850 static XmlElement* getXml(GenObject* gen); 01851 01858 static XmlElement* getXml(const String& data); 01859 01869 static XmlElement* getXml(NamedList& list, const char* param = "xml", 01870 const char* extra = "data"); 01871 01884 static XmlElement* getPresenceXml(NamedList& list, const char* param = "xml", 01885 const char* extra = "data", Presence type = PresenceNone, bool build = true); 01886 01898 static XmlElement* getChatXml(NamedList& list, const char* param = "xml", 01899 const char* extra = "data", bool build = true); 01900 01908 static int cmpBytes(const String& s1, const String& s2); 01909 01915 static inline Presence presenceType(const char* text) 01916 { return (Presence)lookup(text,s_presence,PresenceNone); } 01917 01923 static inline const char* presenceText(Presence presence) 01924 { return lookup(presence,s_presence,0); } 01925 01931 static inline MsgType msgType(const char* text) 01932 { return (MsgType)lookup(text,s_msg,Normal); } 01933 01939 static inline const char* msgText(MsgType msg) 01940 { return lookup(msg,s_msg,0); } 01941 01947 static inline IqType iqType(const char* text) 01948 { return (IqType)lookup(text,s_iq,IqCount); } 01949 01956 static inline int authMeth(const char* text, int defVal = AuthNone) 01957 { return lookup(text,s_authMeth,defVal); } 01958 01962 static XMPPNamespace s_ns; 01963 01967 static XMPPError s_error; 01968 01972 static XmlTag s_tag; 01973 01977 static const TokenDict s_presence[]; 01978 01982 static const TokenDict s_msg[]; 01983 01987 static const TokenDict s_iq[]; 01988 01992 static const TokenDict s_commandAction[]; 01993 01997 static const TokenDict s_commandStatus[]; 01998 02002 static const TokenDict s_authMeth[]; 02003 }; 02004 02009 class YJABBER_API XMPPDirVal 02010 { 02011 public: 02015 enum Direction { 02016 None = 0x00, 02017 To = 0x01, 02018 From = 0x02, 02019 PendingIn = 0x10, 02020 PendingOut = 0x20, 02021 // Masks 02022 Both = 0x03, 02023 Pending = 0x30 02024 }; 02025 02030 inline XMPPDirVal(int flags = None) 02031 : m_value(flags) 02032 {} 02033 02038 inline XMPPDirVal(const String& flags) 02039 : m_value(0) 02040 { replace(flags); } 02041 02046 inline void replace(int flag) 02047 { m_value = flag; } 02048 02053 inline void replace(const String& flags) 02054 { m_value = XMPPUtils::decodeFlags(flags,s_names); } 02055 02061 void toString(String& buf, bool full) const; 02062 02067 void toSubscription(String& buf) const; 02068 02073 inline void set(int flag) 02074 { m_value |= flag; } 02075 02080 inline void reset(int flag) 02081 { m_value &= ~flag; } 02082 02088 inline bool test(int mask) const 02089 { return (m_value & mask) != 0; } 02090 02095 inline bool to() const 02096 { return test(To); } 02097 02102 inline bool from() const 02103 { return test(From); } 02104 02108 inline operator int() 02109 { return m_value; } 02110 02114 static const TokenDict s_names[]; 02115 02116 private: 02117 int m_value; // The value 02118 }; 02119 02124 class YJABBER_API XmlElementOut : public RefObject 02125 { 02126 public: 02133 inline XmlElementOut(XmlElement* element, const char* senderID = 0, 02134 bool unclose = false) 02135 : m_element(element), m_offset(0), m_id(senderID), m_unclose(unclose), 02136 m_sent(false) 02137 {} 02138 02143 virtual ~XmlElementOut() 02144 { TelEngine::destruct(m_element); } 02145 02150 inline XmlElement* element() const 02151 { return m_element; } 02152 02157 inline bool sent() const 02158 { return m_sent; } 02159 02164 inline const String& buffer() 02165 { return m_buffer; } 02166 02171 inline const String& id() const 02172 { return m_id; } 02173 02178 inline unsigned int dataCount() 02179 { return m_buffer.length() - m_offset; } 02180 02186 inline const char* getData(unsigned int& nCount) { 02187 if (!m_buffer) 02188 prepareToSend(); 02189 nCount = dataCount(); 02190 return m_buffer.c_str() + m_offset; 02191 } 02192 02197 inline void dataSent(unsigned int nCount) { 02198 m_sent = true; 02199 m_offset += nCount; 02200 if (m_offset > m_buffer.length()) 02201 m_offset = m_buffer.length(); 02202 } 02203 02209 inline XmlElement* release() { 02210 XmlElement* e = m_element; 02211 m_element = 0; 02212 return e; 02213 } 02214 02219 inline void toBuffer(String& buffer) { 02220 if (m_element) 02221 m_element->toString(buffer,true,String::empty(),String::empty(),!m_unclose); 02222 } 02223 02227 inline void prepareToSend() 02228 { toBuffer(m_buffer); } 02229 02230 private: 02231 XmlElement* m_element; // The XML element 02232 String m_buffer; // Data to send 02233 unsigned int m_offset; // Offset to send 02234 String m_id; // Sender's id 02235 bool m_unclose; // Close or not the element's tag 02236 bool m_sent; // Sent flag (true if an attempt to send was done) 02237 }; 02238 02239 }; 02240 02241 #endif /* __XMPPUTILS_H */ 02242 02243 /* vi: set ts=8 sw=4 sts=4 noet: */