Source: libs/yjingle/xmpputils.h


Annotated List
Files
Globals
Hierarchy
Index
/**
 * 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 
#include 

#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: */

Generated by: paulc on bussard on Wed Oct 21 01:57:30 2009, using kdoc 2.0a54.