Added file share namespaces and tags to known list. Add utility methods used to build file share and result set management elements.

git-svn-id: http://yate.null.ro/svn/yate/trunk@5475 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2013-04-23 07:30:30 +00:00
parent a345ff2216
commit d2be7683e8
4 changed files with 289 additions and 17 deletions

View File

@ -2562,7 +2562,7 @@ bool JBEntityCapsList::processCaps(String& capsId, XmlElement* xml, JBStream* st
void JBEntityCapsList::addCaps(NamedList& list, JBEntityCaps& caps)
{
#define CHECK_NS(ns,param) \
if (caps.m_features.get(ns)) { \
if (caps.hasFeature(ns)) { \
params->append(param,","); \
list.addParam(param,String::boolText(true)); \
}
@ -2590,6 +2590,8 @@ void JBEntityCapsList::addCaps(NamedList& list, JBEntityCaps& caps)
case 0:
break;
}
CHECK_NS(XMPPNamespace::FileInfoShare,"caps.fileinfoshare");
CHECK_NS(XMPPNamespace::ResultSetMngt,"caps.resultsetmngt");
}
CHECK_NS(XMPPNamespace::Muc,"caps.muc");
#undef CHECK_NS

View File

@ -107,6 +107,9 @@ const String XMPPNamespace::s_array[Count] = {
"http://jabber.org/protocol/chatstates", // ChatStates
"http://yate.null.ro/yate/cluster", // YateCluster
"http://www.google.com/transport/raw-udp", // JingleTransportGoogleRawUdp
"urn:xmpp:hashes:1", // Hash
"http://jabber.org/protocol/rsm", // ResultSetMngt
"urn:xmpp.mam", // FileInfoShare
};
const String XMPPError::s_array[Count] = {
@ -249,6 +252,23 @@ const String XmlTag::s_array[Count] = {
"compressed", // Compressed
"compression", // Compression
"x", // X
"hash", // Hash
"algo", // Algo
"size", // Size
"date", // Date
"desc", // Desc
"set", // Set
"after", // After
"before", // Before
"count", // CountTag
"first", // First
"index", // Index
"last", // Last
"max", // Max
"match", // Match
"directory", // Directory
"name", // Name
"changed", // Changed
};
XMPPNamespace XMPPUtils::s_ns;
@ -342,13 +362,7 @@ void JabberID::set(const char* node, const char* domain, const char* resource)
m_node = node;
m_domain = domain;
m_resource = resource;
String::clear();
if (m_node)
*this << m_node << "@";
*this << m_domain;
m_bare = *this;
if (m_node && m_resource)
*this << "/" << m_resource;
normalize();
}
bool JabberID::valid(const String& value)
@ -383,11 +397,20 @@ void JabberID::parse()
m_domain = tmp.substr(0,i);
m_resource = tmp.substr(i+1,tmp.length()-i-1);
}
// Set bare JID
m_bare = "";
normalize();
}
void JabberID::normalize()
{
m_node.toLower();
m_domain.toLower();
m_bare.clear();
if (m_node)
m_bare << m_node << "@";
m_bare << m_domain;
assign(m_bare);
if (m_resource)
*this << "/" << m_resource;
}
// Get an empty JabberID
@ -730,6 +753,17 @@ void XMPPFeatureList::updateEntityCaps()
/*
* XMPPUtils
*/
// Find an xml tag in an array terminated with XmlTag::Count
int XMPPUtils::findTag(const String& tag, int* tags)
{
if (!(tag && tags))
return XmlTag::Count;
for (; *tags != XmlTag::Count; tags++)
if (tag == s_tag[*tags])
return *tags;
return XmlTag::Count;
}
// Partially build an XML element from another one.
XmlElement* XMPPUtils::createElement(const XmlElement& src, bool response, bool result)
{
@ -1037,6 +1071,76 @@ XmlElement* XMPPUtils::createDelay(unsigned int timeSec, const char* from,
return x;
}
// Create a 'file' element in file transfer namespace, add the name child if not empty
XmlElement* XMPPUtils::createFileNsTransfer(const char* name)
{
XmlElement* x = createElement(XmlTag::File,XMPPNamespace::JingleAppsFileTransfer);
if (!TelEngine::null(name))
x->addChildSafe(createElement(XmlTag::Name,name));
return x;
}
// Create a 'hash' element as defined in XEP-0300
XmlElement* XMPPUtils::createHash(const char* name, const char* value)
{
XmlElement* x = createElement(XmlTag::Hash,XMPPNamespace::Hash,value);
x->setAttribute(s_tag[XmlTag::Algo],name);
return x;
}
// Decode a 'hash' element as defined in XEP-0300
void XMPPUtils::decodeHash(XmlElement& xml, const char*& name, const char*& value)
{
name = xml.attribute(s_tag[XmlTag::Algo]);
value = xml.getText();
}
// Build a Result Set Management (XEP-0059) set element from a parameter list
XmlElement* XMPPUtils::createRSM(const NamedList& params, const String& prefix)
{
static int s_rsmTags[] = {XmlTag::After,XmlTag::Before,XmlTag::CountTag,XmlTag::First,
XmlTag::Index,XmlTag::Last,XmlTag::Max,XmlTag::Count};
XmlElement* rsm = 0;
NamedIterator iter(params);
for (const NamedString* ns = 0; 0 != (ns = iter.get());) {
if (!ns->name().startsWith(prefix))
continue;
String tmp = ns->name().substr(prefix.length());
int tag = findTag(tmp,s_rsmTags);
if (tag == XmlTag::Count)
continue;
XmlElement* x = createElement(tmp,*ns);
if (tag == XmlTag::First) {
String* index = params.getParam(ns->name() + ".index");
if (!TelEngine::null(index))
x->setAttribute(s_tag[XmlTag::Index],*index);
}
if (!rsm)
rsm = createElement(XmlTag::Set,XMPPNamespace::ResultSetMngt);
rsm->addChildSafe(x);
}
return rsm;
}
// Add Result Set Management (XEP-0059) set element child data to a parameter list
void XMPPUtils::addRSM(XmlElement* rsm, NamedList& params, const String& prefix)
{
if (!rsm)
return;
for (XmlElement* c = 0; 0 != (c = rsm->findNextChild(c));) {
int tag = XmlTag::Count;
int ns = XMPPNamespace::Count;
getTag(*c,tag,ns);
String p = prefix + c->unprefixedTag();
params.addParam(p,c->getText());
if (tag == XmlTag::First && ns == XMPPNamespace::ResultSetMngt) {
const char* index = c->attribute(s_ns[XmlTag::Index]);
if (index)
params.addParam(p + ".index",index);
}
}
}
// Check if an element has a child with 'priority' tag
int XMPPUtils::priority(XmlElement& xml, int defVal)
{
@ -1524,13 +1628,13 @@ const String& XMPPUtils::body(XmlElement& xml, int ns)
}
// Retrieve an xml element from a NamedPointer. Release its ownership
XmlElement* XMPPUtils::getXml(GenObject* gen)
XmlElement* XMPPUtils::getXml(GenObject* gen, bool takeOwnerShip)
{
if (!gen)
return 0;
NamedPointer* np = static_cast<NamedPointer*>(gen->getObject(YATOM("NamedPointer")));
XmlElement* xml = np ? static_cast<XmlElement*>(np->userObject(YATOM("XmlElement"))) : 0;
if (xml)
if (xml && takeOwnerShip)
np->takeData();
return xml;
}

View File

@ -191,6 +191,9 @@ public:
ChatStates, // http://jabber.org/protocol/chatstates
YateCluster, // http://yate.null.ro/yate/cluster
JingleTransportGoogleRawUdp, // http://www.google.com/transport/raw-udp
Hash, // urn:xmpp:hashes:1
ResultSetMngt, // http://jabber.org/protocol/rsm
FileInfoShare, // urn:xmpp:mam
// This value MUST be the last one: it's used as array bound
Count,
};
@ -388,6 +391,23 @@ public:
Compressed, // compressed
Compression, // compression
X, // x
Hash, // hash
Algo, // algo
Size, // size
Date, // date
Desc, // desc
Set, // set
After, // after
Before, // before
CountTag, // count
First, // first
Index, // index
Last, // last
Max, // max
Match, // match
Directory, // directory
Name, // name
Changed, // changed
// This value MUST be the last one: it's used as array bound
Count
};
@ -620,6 +640,7 @@ public:
private:
void parse(); // Parse the string. Set the data
void normalize(); // Lowercase node and domain. Set bare jid and jid
String m_node; // The node part
String m_domain; // The domain part
@ -1108,6 +1129,14 @@ public:
AuthDialback = 0x08, // Dialback authentication
};
/**
* Find an xml tag in an array terminated with XmlTag::Count
* @param tag Tag to find
* @param tags Tags list
* @return XmlTag value, XmlTag::Count if not found
*/
static int findTag(const String& tag, int* tags);
/**
* Check if an xml element has type 'result' or 'error'
* @param xml The element to check
@ -1118,6 +1147,28 @@ public:
return tmp && (*tmp == "result" || *tmp == "error");
}
/**
* Retrieve a JID from 'to' and 'to_instance' parameters
* @param params Parameter list
* @param jid Destination to be set
*/
static inline void getJIDTo(const NamedList& params, JabberID& jid) {
jid = params[YSTRING("to")];
if (jid && !jid.resource())
jid.resource(params[YSTRING("to_instance")]);
}
/**
* Retrieve a JID from 'from' and 'from_instance' parameters
* @param params Parameter list
* @param jid Destination to be set
*/
static inline void getJIDFrom(const NamedList& params, JabberID& jid) {
jid = params[YSTRING("from")];
if (jid && !jid.resource())
jid.resource(params[YSTRING("from_instance")]);
}
/**
* Create an XML element
* @param name Element's name
@ -1178,6 +1229,21 @@ public:
*/
static XmlElement* createElement(const XmlElement& src, bool response, bool result);
/**
* Create an element with an attribute
* @param tag Element tag
* @param attrName Attribute name
* @param attrValue Attribute value
* @param ns Optional 'xmlns' attribute as enumeration
* @return A valid XmlElement pointer
*/
static inline XmlElement* createElementAttr(int tag, const String& attrName,
const char* attrValue, int ns = XMPPNamespace::Count) {
XmlElement* x = createElement(tag,ns);
x->setAttributeValid(attrName,attrValue);
return x;
}
/**
* Create an 'iq' element
* @param type Iq type as enumeration
@ -1410,6 +1476,57 @@ public:
static XmlElement* createDelay(unsigned int timeSec, const char* from = 0,
unsigned int fractions = 0, const char* text = 0);
/**
* Create a 'file' element in file transfer namespace, add the name child if not empty
* @param name Optional file name
* @return XmlElement pointer
*/
static XmlElement* createFileNsTransfer(const char* name = 0);
/**
* Create a 'hash' element as defined in XEP-0300
* @param name Hash name
* @param value Hash value
* @return XmlElement pointer
*/
static XmlElement* createHash(const char* name, const char* value);
/**
* Decode a 'hash' element as defined in XEP-0300
* @param xml XML element to handle
* @param name Hash name
* @param value Hash value
*/
static void decodeHash(XmlElement& xml, const char*& name, const char*& value);
/**
* Create a 'match' element in FileInfoShare namespace
* @param child Optional child
* @return XmlElement pointer
*/
static inline XmlElement* createFileInfoShareMatch(XmlElement* child = 0) {
XmlElement* m = createElement(XmlTag::Match,XMPPNamespace::FileInfoShare);
if (child)
m->addChildSafe(child);
return m;
}
/**
* Build a Result Set Management (XEP-0059) set element from a parameter list
* @param params List of parameters containing the RSM
* @param prefix Prefix for RSM parameters
* @return XmlElement pointer or 0
*/
static XmlElement* createRSM(const NamedList& params, const String& prefix = "rsm_");
/**
* Add Result Set Management (XEP-0059) set element child data to a parameter list
* @param rsn The element in RSM namespace
* @param params List of parameters to add the RSM data
* @param prefix Prefix for RSM parameters
*/
static void addRSM(XmlElement* rsm, NamedList& params, const String& prefix = "rsm_");
/**
* Check if an element has a child with 'remove' tag
* @param xml The element to check
@ -1525,6 +1642,38 @@ public:
static XmlElement* findNextChild(const XmlElement& xml, XmlElement* start,
int t = XmlTag::Count, int ns = XMPPNamespace::Count);
/**
* Retrieve a child's text
* @param xml The xml
* @param tag Child tag
* @param ns Optional child namespace
* @return Pointer to child's text, 0 if the child was not found
*/
static inline const String* childText(XmlElement& xml, int tag, int ns = XMPPNamespace::Count) {
XmlElement* c = findFirstChild(xml,tag,ns);
return c ? &(c->getText()) : 0;
}
/**
* Retrieve a child's text converted to integer
* @param xml The xml
* @param tag Child tag
* @param ns Optional child namespace
* @param defVal Default to return if not found or the string is not a number
* @param base Numeration base, 0 to autodetect
* @param minvalue Minimum value allowed
* @param maxvalue Maximum value allowed
* @param clamp Control the out of bound values: true to adjust to the nearest
* bound, false to return the default value
* @return Integer value
*/
static inline int childTextInt(XmlElement& xml, int tag, int ns = XMPPNamespace::Count,
int defVal = 0, int base = 0, int minvalue = INT_MIN, int maxvalue = INT_MAX,
bool clamp = true) {
const String* tmp = childText(xml,tag,ns);
return tmp ? tmp->toInteger(defVal,base,minvalue,maxvalue,clamp) : defVal;
}
/**
* Find an error child of a given element and decode it
* @param xml The element
@ -1856,11 +2005,12 @@ public:
/**
* Retrieve an xml element from a NamedPointer.
* Release NamedPointer ownership if found
* Release NamedPointer ownership if found and requested
* @param gen The object to be processed
* @param takeOwnerShip Take ownership (defaults to true)
* @return XmlElement pointer or 0
*/
static XmlElement* getXml(GenObject* gen);
static XmlElement* getXml(GenObject* gen, bool takeOwnerShip = true);
/**
* Parse a string to an XmlElement
@ -2052,6 +2202,14 @@ public:
: m_value(0)
{ replace(flags); }
/**
* Copy constructor
* @param other Source to copy
*/
inline XMPPDirVal(const XMPPDirVal& other)
: m_value(other.m_value)
{}
/**
* Replace all flags
* @param flag The new value of the flags

View File

@ -2791,14 +2791,22 @@ public:
m_version(version), m_node(node), m_data(data)
{}
/**
* Check if a given feature is found in the list
* @param ns The feature to check
* @return True if the feature was found in the list
*/
inline bool hasFeature(int ns)
{ return 0 != m_features.get(ns); }
/**
* Check if an audio capability is present
* @return True if an audio capability is present
*/
inline bool hasAudio() {
return m_features.get(XMPPNamespace::JingleAppsRtpAudio) ||
m_features.get(XMPPNamespace::JingleAudio) ||
m_features.get(XMPPNamespace::JingleVoiceV1);
return hasFeature(XMPPNamespace::JingleAppsRtpAudio) ||
hasFeature(XMPPNamespace::JingleAudio) ||
hasFeature(XMPPNamespace::JingleVoiceV1);
}
/**