yate/libs/yjingle/xmpputils.h

1221 lines
36 KiB
C++

/**
* xmpputils.h
* Yet Another Jabber Component Protocol Stack
* This file is part of the YATE Project http://YATE.null.ro
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004-2006 Null Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XMPPUTILS_H
#define __XMPPUTILS_H
#include <yateclass.h>
#include <xmlparser.h>
#ifdef _WINDOWS
#ifdef LIBYJINGLE_EXPORTS
#define YJINGLE_API __declspec(dllexport)
#else
#ifndef LIBYJINGLE_STATIC
#define YJINGLE_API __declspec(dllimport)
#endif
#endif
#endif /* _WINDOWS */
#ifndef YJINGLE_API
#define YJINGLE_API
#endif
/**
* Holds all Telephony Engine related classes.
*/
namespace TelEngine {
class XMPPServerInfo; // Server info class
class XMPPNamespace; // XMPP namespaces
class XMPPError; // XMPP errors
class JabberID; // A Jabber ID (JID)
class JIDIdentity; // A JID's identity
class JIDFeature; // A JID's feature
class JIDFeatureSasl; // A JID's SASL feature
class JIDFeatureList; // Feature list
class XMPPUtils; // Utilities
class XMPPDirVal; // Direction flags
/**
* This class holds informations about a server
* @short Server info class
*/
class YJINGLE_API XMPPServerInfo : public RefObject
{
public:
/**
* Server flags
*/
enum ServerFlag {
NoAutoRestart = 0x0001, // Don't auto restart streams when down
KeepRoster = 0x0002, // Tell the presence service to keep the roster for this server
TlsRequired = 0x0004, // The server always requires connection encryption
OldStyleAuth = 0x0008, // The server doesn't support RFC 3920 TLS/SASL ...
AllowPlainAuth = 0x0020, // Allow plain password authentication
AllowUnsafeSetup = 0x0040, // Allow user account setup on unenchrypted streams
};
/**
* Constructor. Construct a full server info object
* @param name Server domain name
* @param address IP address
* @param port IP port
* @param password Component only: Password used for authentication
* @param identity Component only: The stream identity used when connecting
* @param fullidentity Component only: The user identity
* @param flags Server flags
*/
inline XMPPServerInfo(const char* name, const char* address, int port,
const char* password, const char* identity, const char* fullidentity,
int flags)
: m_name(name), m_address(address), m_port(port), m_password(password),
m_identity(identity), m_fullIdentity(fullidentity), m_flags(flags)
{}
/**
* Constructor. Construct a partial server info object
* @param name Server domain name
* @param port IP port
*/
inline XMPPServerInfo(const char* name, int port)
: m_name(name), m_port(port)
{}
/**
* Get the server's address
* @return The server's address
*/
inline const String& address() const
{ return m_address; }
/**
* Get the server's domain name
* @return The server's domain name
*/
inline const String& name() const
{ return m_name; }
/**
* Get the server's port used to connect to
* @return The server's port used to connect to
*/
inline const int port() const
{ return m_port; }
/**
* Get the server's port used to connect to
* @return The server's port used to connect to
*/
inline const String& password() const
{ return m_password; }
/**
* Get the server's identity
* @return The server's identity
*/
inline const String& identity() const
{ return m_identity; }
/**
* Get the server's full identity
* @return The server's full identity
*/
inline const String& fullIdentity() const
{ return m_fullIdentity; }
/**
* Check if a given flag (or mask) is set
* @return True if the flag is set
*/
inline bool flag(int mask) const
{ return 0 != (m_flags & mask); }
/**
* Flag names dictionary
*/
static TokenDict s_flagName[];
private:
String m_name; // Domain name
String m_address; // IP address
int m_port; // Port
String m_password; // Authentication data
String m_identity; // Identity. Used for Jabber Component protocol
String m_fullIdentity; // Full identity for this server
int m_flags; // Server flags
};
/**
* This class holds the XMPP/JabberComponent/Jingle namespace enumerations and the associated strings
* @short XMPP namespaces
*/
class YJINGLE_API XMPPNamespace
{
public:
enum Type {
Stream = 1, // http://etherx.jabber.org/streams
Client, // jabber:client
Server, // jabber:server
ComponentAccept, // jabber:component:accept
ComponentConnect, // jabber:component:connect
StreamError, // urn:ietf:params:xml:ns:xmpp-streams
StanzaError, // urn:ietf:params:xml:ns:xmpp-stanzas
Register, // http://jabber.org/features/iq-register
IqRegister, // jabber:iq:register
IqPrivate, // jabber:iq:private
IqAuth, // jabber:iq:auth
IqAuthFeature, // http://jabber.org/features/iq-auth
Starttls, // urn:ietf:params:xml:ns:xmpp-tls
Sasl, // urn:ietf:params:xml:ns:xmpp-sasl
Session, // urn:ietf:params:xml:ns:xmpp-session
Bind, // urn:ietf:params:xml:ns:xmpp-bind
Roster, // jabber:iq:roster
DynamicRoster, // jabber:iq:roster-dynamic
DiscoInfo, // http://jabber.org/protocol/disco#info
DiscoItems, // http://jabber.org/protocol/disco#items
VCard, // vcard-temp
SIProfileFileTransfer, // http://jabber.org/protocol/si/profile/file-transfer
ByteStreams, // http://jabber.org/protocol/bytestreams
Jingle, // xmlns='urn:xmpp:jingle:0
JingleError, // urn:xmpp:jingle:errors:0
JingleAppsRtp, // urn:xmpp:jingle:apps:rtp:0
JingleAppsRtpInfo, // urn:xmpp:jingle:apps:rtp:info:0
JingleAppsRtpAudio, // urn:xmpp:jingle:apps:rtp:audio
JingleAppsFileTransfer, // urn:xmpp:jingle:apps:file-transfer:0
JingleTransportIceUdp, // urn:xmpp:jingle:transports:ice-udp:0
JingleTransportRawUdp, // urn:xmpp:jingle:transports:raw-udp:0
JingleTransportRawUdpInfo, // urn:xmpp:jingle:transports:raw-udp:info:0
JingleTransportByteStreams, // urn:xmpp:jingle:transports:bytestreams:0
JingleTransfer, // urn:xmpp:jingle:transfer:0
Dtmf, // urn:xmpp:jingle:dtmf:0
JingleSession, // http://www.google.com/session
JingleAudio, // http://www.google.com/session/phone
JingleTransport, // http://www.google.com/transport/p2p
JingleRtpInfoOld, // urn:xmpp:jingle:apps:rtp:info
DtmfOld, // http://jabber.org/protocol/jingle/info/dtmf
Command, // http://jabber.org/protocol/command
CapVoiceV1, // http://www.google.com/xmpp/protocol/voice/v1
Count,
};
/**
* Get the string representation of a namespace value
*/
inline const char* operator[](Type index)
{ return lookup(index,s_value); }
/**
* Check if a text is a known namespace
*/
static bool isText(Type index, const char* txt);
/**
* Get the type associated with a given namespace text
*/
static inline Type type(const char* txt) {
int tmp = lookup(txt,s_value,Count);
return tmp ? (Type)tmp : Count;
}
private:
static TokenDict s_value[]; // Namespace list
};
/**
* This class holds the XMPP error type, error enumerations and associated strings
* @short XMPP errors.
*/
class YJINGLE_API XMPPError
{
public:
/**
* Error condition enumeration
*/
enum Type {
NoError = 0,
// Stream errors
BadFormat, // bad-format
BadNamespace, // bad-namespace-prefix
ConnTimeout, // connection-timeout
HostGone, // host-gone
HostUnknown, // host-unknown
BadAddressing, // improper-addressing
Internal, // internal-server-error
InvalidFrom, // invalid-from
InvalidId, // invalid-id
InvalidNamespace, // invalid-namespace
InvalidXml, // invalid-xml
NotAuth, // not-authorized
Policy, // policy-violation
RemoteConn, // remote-connection-failed
ResConstraint, // resource-constraint
RestrictedXml, // restricted-xml
SeeOther, // see-other-host
Shutdown, // system-shutdown
UndefinedCondition, // undefined-condition
UnsupportedEnc, // unsupported-encoding
UnsupportedStanza, // unsupported-stanza-type
UnsupportedVersion, // unsupported-version
Xml, // xml-not-well-formed
// Auth failures
Aborted, // aborted
IncorrectEnc, // incorrect-encoding
InvalidAuth, // invalid-authzid
InvalidMechanism, // invalid-mechanism
MechanismTooWeak, // mechanism-too-weak
NotAuthorized, // not-authorized
TempAuthFailure, // temporary-auth-failure
// Stanza errors
SBadRequest, // bad-request
SConflict, // conflict
SFeatureNotImpl, // feature-not-implemented
SForbidden, // forbidden
SGone, // gone
SInternal, // internal-server-error
SItemNotFound, // item-not-found
SBadJid, // jid-malformed
SNotAcceptable, // not-acceptable
SNotAllowed, // not-allowed
SPayment, // payment-required
SUnavailable, // recipient-unavailable
SRedirect, // redirect
SReg, // registration-required
SNoRemote, // remote-server-not-found
SRemoteTimeout, // remote-server-timeout
SResource, // resource-constraint
SServiceUnavailable, // service-unavailable
SSubscription, // subscription-required
SUndefinedCondition, // undefined-condition
SRequest, // unexpected-request
// Misc
DtmfNoMethod, // unsupported-dtmf-method
ItemNotFound, // item-not-found
Count,
};
/**
* Error type enumeration
*/
enum ErrorType {
TypeCancel = 1000, // do not retry (the error is unrecoverable)
TypeContinue, // proceed (the condition was only a warning)
TypeModify, // retry after changing the data sent
TypeAuth, // retry after providing credentials
TypeWait, // retry after waiting (the error is temporary)
TypeCount,
};
/**
* Get the text representation of a given error value
*/
inline const char* operator[](int index)
{ return lookup(index,s_value); }
/**
* Check if a given text is a valid error
*/
static bool isText(int index, const char* txt);
/**
* Get the type associated with a given error text
*/
static inline int type(const char* txt)
{ return lookup(txt,s_value,Count); }
private:
static TokenDict s_value[]; // Error list
};
/**
* This class holds a Jabber ID in form "node@domain/resource" or "node@domain"
* @short A Jabber ID
*/
class YJINGLE_API JabberID : public String
{
public:
/**
* Constructor
*/
inline JabberID() {}
/**
* Constructor. Constructs a JID from a given string
* @param jid The JID string
*/
inline JabberID(const char* jid)
{ set(jid); }
/**
* Constructor. Constructs a JID from user, domain, resource
* @param node The node
* @param domain The domain
* @param resource The resource
*/
JabberID(const char* node, const char* domain, const char* resource = 0)
{ set(node,domain,resource); }
/**
* Get the node part of the JID
* @return The node part of the JID
*/
inline const String& node() const
{ return m_node; }
/**
* Get the bare JID: "node@domain"
* @return The bare JID
*/
inline const String& bare() const
{ return m_bare; }
/**
* Get the domain part of the JID
* @return The domain part of the JID
*/
inline const String& domain() const
{ return m_domain; }
/**
* Set the domain part of the JID.
* @param d The new domain part of the JID.
*/
inline void domain(const char* d)
{ set(m_node.c_str(),d,m_resource.c_str()); }
/**
* Get the resource part of the JID
* @return The resource part of the JID
*/
inline const String& resource() const
{ return m_resource; }
/**
* Check if this is a full JID
* @return True if this is a full JID
*/
inline bool isFull() const
{ return m_node && m_domain && m_resource; }
/**
* Try to match another JID to this one. If src has a resource compare it too
* (case sensitive). Otherwise compare just the bare JID (case insensitive)
* @param src The JID to match
* @return True if matched
*/
inline bool match(const JabberID& src) const
{ return (src.resource().null() || (resource() == src.resource())) && (bare() &= src.bare()); }
/**
* Equality operator. Do a case senitive resource comparison and a case insensitive bare jid comparison
* @param src The JID to compare with
* @return True if equal
*/
inline bool operator==(const JabberID& src) const
{ return (resource() == src.resource()) && (bare() &= src.bare()); }
/**
* Equality operator. Build a temporary JID and compare with it
* @param src The string to compare with
* @return True if equal
*/
inline bool operator==(const String& src) const
{ JabberID tmp(src); return operator==(tmp); }
/**
* Inequality operator
* @param src The JID to compare with
* @return True if not equal
*/
inline bool operator!=(const JabberID& src) const
{ return !operator==(src); }
/**
* Inequality operator
* @param src The string to compare with
* @return True if not equal
*/
inline bool operator!=(const String& src) const
{ return !operator==(src); }
/**
* Set the resource part of the JID
* @param res The new resource part of the JID
*/
inline void resource(const char* res)
{ set(m_node.c_str(),m_domain.c_str(),res); }
/**
* Set the data
* @param jid The JID string to assign
*/
void set(const char* jid);
/**
* Set the data
* @param node The node
* @param domain The domain
* @param resource The resource
*/
void set(const char* node, const char* domain, const char* resource = 0);
/**
* Check if the given string contains valid characters
* @param value The string to check
* @return True if value is valid or 0. False if value is a non empty invalid string
*/
static bool valid(const String& value);
/**
* Keep the regexp used to check the validity of a string
*/
static Regexp s_regExpValid;
private:
void parse(); // Parse the string. Set the data
String m_node; // The node part
String m_domain; // The domain part
String m_resource; // The resource part
String m_bare; // The bare JID: node@domain
};
/**
* This class holds an identity for a JID
* @short A JID identity
*/
class YJINGLE_API JIDIdentity : public RefObject
{
public:
/**
* JID category enumeration
*/
enum Category {
Account, // account
Client, // client
Component, // component
Gateway, // gateway
CategoryUnknown
};
/**
* JID type enumeration
*/
enum Type {
AccountRegistered, // registered
ClientPhone, // phone
ComponentGeneric, // generic
ComponentPresence, // presence
GatewayGeneric, // generic
TypeUnknown
};
/**
* Constructor. Build a JID identity
* @param c The JID's category
* @param t The JID's type
* @param name The name of this identity
*/
inline JIDIdentity(Category c, Type t, const char* name = 0)
: m_name(name), m_category(c), m_type(t)
{}
/**
* Destructor
*/
virtual ~JIDIdentity()
{}
/**
* Build an XML element from this identity
* @return A valid XML element
*/
XMLElement* toXML();
/**
* Build this identity from an XML element
* @return True on succes
*/
bool fromXML(const XMLElement* element);
/**
* Get a string representation of this object
* @return This object's name
*/
virtual const String& toString() const
{ return m_name; }
/**
* Get a pointer from this object
* @param name The requested pointer's name
* @return Requested pointer or 0
*/
virtual void* getObject(const String& name) const {
if (name == "JIDIdentity")
return (void*)this;
return RefObject::getObject(name);
}
/**
* Set the name of this identity
* @param name New identity name
*/
inline void setName(const char* name)
{ if (name) m_name = name; }
/**
* Lookup for a text associated with a given category
* @return The category's name
*/
static inline const char* categoryText(Category c)
{ return lookup(c,s_category); }
/**
* Lookup for a value associated with a given category name
* @return The category's value
*/
static inline Category categoryValue(const char* c)
{ return (Category)lookup(c,s_category,CategoryUnknown); }
/**
* Lookup for a text associated with a given category type
* @return The category's type name
*/
static inline const char* typeText(Type t)
{ return lookup(t,s_type); }
/**
* Lookup for a value associated with a given category type
* @return The category's type value
*/
static inline Type typeValue(const char* t)
{ return (Type)lookup(t,s_category,TypeUnknown); }
private:
static TokenDict s_category[];
static TokenDict s_type[];
String m_name;
Category m_category; // Category
Type m_type; // Type
};
/**
* This class holds a JID feature
* @short A JID feature
*/
class YJINGLE_API JIDFeature : public RefObject
{
public:
/**
* Constructor
* @param feature The feature to add
* @param required True if this feature is required
*/
inline JIDFeature(XMPPNamespace::Type feature, bool required = false)
: m_feature(feature),
m_required(required)
{}
/**
* Destructor
*/
virtual ~JIDFeature()
{}
/**
* Check if this feature is a required one
* @return True if this feature is a required one
*/
inline bool required() const
{ return m_required; }
/**
* XMPPNamespace::Type conversion operator
*/
inline operator XMPPNamespace::Type()
{ return m_feature; }
private:
XMPPNamespace::Type m_feature; // The feature
bool m_required; // Required flag
};
/**
* This class holds a JID SASL feature (authentication methods)
* @short A JID's SASL feature
*/
class YJINGLE_API JIDFeatureSasl : public JIDFeature
{
public:
/**
* Mechanisms used to authenticate a stream
*/
enum Mechanism {
MechNone = 0x00, // No authentication mechanism
MechMD5 = 0x01, // MD5 digest
MechSHA1 = 0x02, // SHA1 digest
MechPlain = 0x04, // Plain text password
};
/**
* Constructor
* @param mech Authentication mechanisms used by the JID
* @param required Required flag
*/
inline JIDFeatureSasl(int mech, bool required = false)
: JIDFeature(XMPPNamespace::Sasl,required),
m_mechanism(mech)
{}
/**
* Get the authentication mechanisms used by the JID
* @return The authentication mechanisms used by the JID
*/
inline int mechanism() const
{ return m_mechanism; }
/**
* Check if a given mechanism is allowed
* @return True if the given mechanism is allowed
*/
inline bool mechanism(Mechanism mech) const
{ return 0 != (m_mechanism & mech); }
/**
* XMPPNamespace::Type conversion operator
*/
inline operator XMPPNamespace::Type()
{ return JIDFeature::operator XMPPNamespace::Type(); }
/**
* Authentication mechanism names
*/
static TokenDict s_authMech[];
private:
int m_mechanism; // Authentication mechanisms
};
/**
* This class holds a list of JID features
* @short JID feature list
*/
class YJINGLE_API JIDFeatureList
{
public:
/**
* Add a feature to the list
* @param feature The feature to add
* @param required True if this feature is required
* @return False if the given feature already exists
*/
inline bool add(XMPPNamespace::Type feature, bool required = false) {
if (get(feature))
return false;
m_features.append(new JIDFeature(feature,required));
return true;
}
/**
* Add a feature to the list. Destroy the received parameter if already in the list
* @param feature The feature to add
* @return False if the given feature already exists
*/
inline bool add(JIDFeature* feature) {
if (!feature || get(*feature)) {
TelEngine::destruct(feature);
return false;
}
m_features.append(feature);
return true;
}
/**
* Remove a feature from the list
* @param feature The feature to remove
*/
inline void remove(XMPPNamespace::Type feature)
{ m_features.remove(get(feature),true); }
/**
* Get a feature from the list
* @param feature The feature to get
* @return Pointer to the feature or 0 if it doesn't exists
*/
JIDFeature* get(XMPPNamespace::Type feature);
/**
* Add 'feature' children to the given element
* @param element The target XMLElement
* @return The given element
*/
XMLElement* addTo(XMLElement* element);
/**
* Update the list from 'feature' children of the given element
* @param element The source XMLElement
* @param reset True to clear the list before updating
* @return The given element
*/
void fromXml(XMLElement* element, bool reset = true);
/**
* Clear the feature list
*/
inline void clear()
{ m_features.clear(); }
private:
ObjList m_features; // The features
};
/**
* This class is a general XMPP utilities
* @short General XMPP utilities
*/
class YJINGLE_API XMPPUtils
{
public:
/**
* Iq type enumeration
*/
enum IqType {
IqSet, // set
IqGet, // get
IqResult, // result
IqError, // error
IqCount,
};
/**
* Command action enumeration
*/
enum CommandAction {
CommExecute,
CommCancel,
CommPrev,
CommNext,
CommComplete,
};
/**
* Command status enumeration
*/
enum CommandStatus {
CommExecuting,
CommCompleted,
CommCancelled,
};
/**
* Create an XML element with an 'xmlns' attribute
* @param name Element's name
* @param ns 'xmlns' attribute
* @param text Optional text for the element
* @return A valid XMLElement pointer
*/
static XMLElement* createElement(const char* name, XMPPNamespace::Type ns,
const char* text = 0);
/**
* Create an XML element with an 'xmlns' attribute
* @param type Element's type
* @param ns 'xmlns' attribute
* @param text Optional text for the element
* @return A valid XMLElement pointer
*/
static XMLElement* createElement(XMLElement::Type type, XMPPNamespace::Type ns,
const char* text = 0);
/**
* Create an 'iq' element
* @param type Iq type as enumeration
* @param from The 'from' attribute
* @param to The 'to' attribute
* @param id The 'id' attribute
* @return A valid XMLElement pointer
*/
static XMLElement* createIq(IqType type, const char* from,
const char* to, const char* id);
/**
* Create an 'iq' element with a 'bind' child containing the resources
* @param from The 'from' attribute
* @param to The 'to' attribute
* @param id The 'id' attribute
* @param resources The resources to bind (strings)
* @return A valid XMLElement pointer
*/
static XMLElement* createIqBind(const char* from,
const char* to, const char* id, const ObjList& resources);
/**
* Create an 'iq' element with a 'vcard' child
* @param get True to set the iq's type to 'get', false to set it to 'set'
* @param from The 'from' attribute
* @param to The 'to' attribute
* @param id The 'id' attribute
* @return A valid XMLElement pointer
*/
static XMLElement* createVCard(bool get, const char* from, const char* to, const char* id);
/**
* Create a 'command' element
* @param action The command action
* @param node The command
* @param sessionId Optional session ID for the command
* @return A valid XMLElement pointer
*/
static XMLElement* createCommand(CommandAction action, const char* node,
const char* sessionId = 0);
/**
* Create an 'identity' element
* @param category The 'category' attribute
* @param type The 'type' attribute
* @param name The 'name' attribute
* @return A valid XMLElement pointer
*/
static XMLElement* createIdentity(const char* category,
const char* type, const char* name);
/**
* Create an 'iq' of type 'get' element with a 'query' child
* @param from The 'from' attribute
* @param to The 'to' attribute
* @param id The 'id' attribute
* @param info True to create a query info request. False to create a query items request
* @return A valid XMLElement pointer
*/
static XMLElement* createIqDisco(const char* from, const char* to,
const char* id, bool info = true);
/**
* Create an 'iq' of type 'result' element with a 'query' child in response to
* a disco info request
* @param from The 'from' attribute
* @param to The 'to' attribute
* @param id The 'id' attribute
* @param features Features to be added to response
* @param identity The identity of the entity sending the response
* @return A valid XMLElement pointer
*/
static XMLElement* createDiscoInfoRes(const char* from, const char* to,
const char* id, JIDFeatureList* features, JIDIdentity* identity);
/**
* Create a 'error' element
* @param type Error type
* @param error The error
* @param text Optional text to add to the error element
* @return A valid XMLElement pointer
*/
static XMLElement* createError(XMPPError::ErrorType type,
XMPPError::Type error, const char* text = 0);
/**
* Create an error from a received element. Consume the received element
* Reverse 'to' and 'from' attributes
* @param xml Received element
* @param type Error type
* @param error The error
* @param text Optional text to add to the error element
* @return A valid XMLElement pointer or 0 if xml is 0
*/
static XMLElement* createError(XMLElement* xml, XMPPError::ErrorType type,
XMPPError::Type error, const char* text = 0);
/**
* Create a 'stream:error' element
* @param error The XMPP defined condition
* @param text Optional text to add to the error
* @return A valid XMLElement pointer
*/
static XMLElement* createStreamError(XMPPError::Type error,
const char* text = 0);
/**
* Build a register query element
* @param type Iq type as enumeration
* @param from The 'from' attribute
* @param to The 'to' attribute
* @param id The 'id' attribute
* @param child1 Optional child of query element
* @param child2 Optional child of query element
* @param child3 Optional child of query element
* @return Valid XMLElement pointer
*/
static XMLElement* createRegisterQuery(IqType type, const char* from,
const char* to, const char* id,
XMLElement* child1 = 0, XMLElement* child2 = 0, XMLElement* child3 = 0);
/**
* Build an register query element used to create/set username/password
* @param from The 'from' attribute
* @param to The 'to' attribute
* @param id The 'id' attribute
* @param username The username
* @param password The password
* @return Valid XMLElement pointer
*/
static inline XMLElement* createRegisterQuery(const char* from,
const char* to, const char* id,
const char* username, const char* password) {
return createRegisterQuery(XMPPUtils::IqSet,from,to,id,
new XMLElement(XMLElement::Username,0,username),
new XMLElement(XMLElement::Password,0,password));
}
/**
* Check if the given element has an attribute 'xmlns' equal to a given value
* @param element Element to check
* @param ns Namespace value to check
* @return True if the given element has the requested namespace
*/
static bool hasXmlns(XMLElement& element, XMPPNamespace::Type ns);
/**
* Decode a received stream error or stanza error
* @param element The received element
* @param error The error condition
* @param text The stanza's error or error text
*/
static void decodeError(XMLElement* element, String& error, String& text);
/**
* Encode EPOCH time given in seconds to a date/time profile as defined in
* XEP-0082 and XML Schema Part 2: Datatypes Second Edition
* @param buf Destination string
* @param timeSec The time to encode (in seconds)
* @param fractions Optional second fractions
*/
static void encodeDateTimeSec(String& buf, unsigned int timeSec,
unsigned int fractions = 0);
/**
* Decode a date/time profile as defined in XEP-0082
* and XML Schema Part 2: Datatypes Second Edition to EPOCH time
* @param time The date/time string
* @param fractions Pointer to integer to be filled with second fractions, if present
* @return The decoded time in seconds, -1 on error
*/
static unsigned int decodeDateTimeSec(const String& time, unsigned int* fractions = 0);
/**
* Print an XMLElement to a string
* @param xmlStr The destination string
* @param element The element to print
* @param indent The indent. 0 if it is the root element
*/
static void print(String& xmlStr, XMLElement& element, const char* indent = 0);
/**
* Split a string at a delimiter character and fills a named list with its parts
* Skip empty parts
* @param dest The destination NamedList
* @param src Pointer to the string
* @param sep The delimiter
* @param nameFirst True to add the parts as name and index as value.
* False to do the other way
*/
static bool split(NamedList& dest, const char* src, const char sep,
bool nameFirst);
/**
* Decode a comma separated list of flags and put them into an integer mask
* @param src Source string
* @param dict Dictionary containing flag names and values
* @return The mask of found flags
*/
static int decodeFlags(const String& src, const TokenDict* dict);
/**
* Encode a mask of flags to a comma separated list of names
* @param dest Destination string
* @param src Source mask
* @param dict Dictionary containing flag names and values
*/
static void buildFlags(String& dest, int src, const TokenDict* dict);
/**
* Add child elements from a list to a destination element
* @param dest Destination XMLElement
* @param list A list containing XML elements
* @return True if at least one child was added
*/
static bool addChidren(XMLElement* dest, ObjList& list);
/**
* Get the type of an 'iq' stanza as enumeration
* @param text The text to check
* @return Iq type as enumeration
*/
static inline IqType iqType(const char* text)
{ return (IqType)lookup(text,s_iq,IqCount); }
/**
* Keep the types of 'iq' stanzas
*/
static TokenDict s_iq[];
/**
* Keep the command actions
*/
static TokenDict s_commandAction[];
/**
* Keep the command status
*/
static TokenDict s_commandStatus[];
};
/**
* This class holds a 4-state direction value (such as subscription states)
* @short Direction flags
*/
class YJINGLE_API XMPPDirVal
{
public:
enum Direction {
None = 0,
To = 1,
From = 2,
Both = 3,
};
/**
* Constructor
* @param flags Flag(s) to set
*/
inline XMPPDirVal(int flags = None)
: m_value(flags)
{}
/**
* Constructor
* @param name The name of the flag used to initialize this object
*/
inline XMPPDirVal(const char* name)
: m_value(lookup(name,None))
{}
/**
* Replace all flags
* @param flag The new value of the flags
*/
inline void replace(int flag)
{ m_value = flag; }
/**
* Replace all flags from a value's name
* @param name The name of the flag used to replace this value
*/
inline void replace(const char* name)
{ m_value = lookup(name,None); }
/**
* Set one or more flags
* @param flag Flag(s) to set
*/
inline void set(int flag)
{ m_value |= flag; }
/**
* Reset one or more flags
* @param flag Flag(s) to reset
*/
inline void reset(int flag)
{ m_value &= ~flag; }
/**
* Check if a given bit mask is set
* @param mask Bit mask to check
* @return True if the given bit mask is set
*/
inline bool flag(int mask) const
{ return (m_value & mask) != 0; }
/**
* Check if the 'To' flag is set
* @return True if the 'To' flag is set
*/
inline bool to() const
{ return flag(To); }
/**
* Check if the 'From' flag is set
* @return True if the 'From' flag is set
*/
inline bool from() const
{ return flag(From); }
/**
* Cast operator
*/
inline operator int()
{ return m_value; }
/**
* Get the name of a flag
* @param flag The flag
* @param defVal Value to return if not found
* @return The name of the requested flag
*/
static inline const char* lookup(int flag, const char* defVal = "")
{ return TelEngine::lookup(flag,s_names,defVal); }
/**
* Get the value associated with a flag name
* @param name The flag name
* @param defVal Value to return if not found
* @return The value of the requested flag name
*/
static inline int lookup(const char* name, int defVal = None)
{ return TelEngine::lookup(name,s_names,defVal); }
/**
* Keep the flag names
*/
static TokenDict s_names[];
private:
int m_value; // The value
};
};
#endif /* __XMPPUTILS_H */
/* vi: set ts=8 sw=4 sts=4 noet: */