Yate
xmpputils.h
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: */