2006-10-19 20:33:15 +00:00
|
|
|
/**
|
|
|
|
* xmlparser.h
|
|
|
|
* Yet Another XMPP 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 __XMLPARSER_H
|
|
|
|
#define __XMLPARSER_H
|
|
|
|
|
|
|
|
#include <yateclass.h>
|
|
|
|
#include <tinyxml.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 {
|
|
|
|
|
|
|
|
#define XMLPARSER_MAXDATABUFFER 8192 // Default max data buffer
|
|
|
|
|
|
|
|
class XMLElement;
|
|
|
|
class XMLParser;
|
|
|
|
class XMLElementOut;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class holds an XML element.
|
|
|
|
* @short An XML element.
|
|
|
|
*/
|
|
|
|
class YJINGLE_API XMLElement
|
|
|
|
{
|
|
|
|
friend class XMLParser;
|
|
|
|
public:
|
|
|
|
enum Type {
|
|
|
|
// *** Stream related elements
|
|
|
|
StreamStart, // stream:stream
|
|
|
|
StreamEnd, // /stream:stream
|
|
|
|
StreamError, // stream::error
|
|
|
|
Handshake, // handshake
|
|
|
|
// *** Stanzas
|
|
|
|
Iq, // iq
|
|
|
|
Message, // message
|
|
|
|
Presence, // presence
|
|
|
|
// *** Stanza children
|
|
|
|
Error, // error
|
|
|
|
Query, // query
|
|
|
|
Jingle, // session
|
|
|
|
// Description
|
|
|
|
Description, // description
|
|
|
|
PayloadType, // payload-type
|
|
|
|
// Transport
|
|
|
|
Transport, // transport
|
|
|
|
Candidate, // candidate
|
|
|
|
// Message
|
|
|
|
Body, // body
|
|
|
|
// Resources
|
|
|
|
Feature, // feature
|
|
|
|
Bind, // bind
|
|
|
|
Resource, // resource
|
|
|
|
// Miscellanous
|
2006-11-17 14:05:53 +00:00
|
|
|
Dtmf, // dtmf
|
|
|
|
DtmfMethod, // dtmf-method
|
2006-12-17 18:09:25 +00:00
|
|
|
Command, // command
|
2006-10-19 20:33:15 +00:00
|
|
|
Unknown, // Any text
|
|
|
|
Invalid, // m_element is 0
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* Constructs an StreamEnd element.
|
|
|
|
*/
|
|
|
|
XMLElement();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* Constructs an XML element with a TiXmlElement element with the given name.
|
|
|
|
* Used for outgoing elements.
|
|
|
|
* @param name The element's name.
|
2007-04-12 08:16:42 +00:00
|
|
|
* @param attributes Optional list of attributes.
|
2006-10-19 20:33:15 +00:00
|
|
|
* @param text Optional text for the XML element.
|
|
|
|
*/
|
|
|
|
XMLElement(const char* name, NamedList* attributes = 0, const char* text = 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* Constructs an XML element with a TiXmlElement element with the given type's name.
|
|
|
|
* Used for outgoing elements.
|
2007-04-12 08:16:42 +00:00
|
|
|
* @param type The element's type.
|
|
|
|
* @param attributes Optional list of attributes.
|
2006-10-19 20:33:15 +00:00
|
|
|
* @param text Optional text for the XML element.
|
|
|
|
*/
|
|
|
|
XMLElement(Type type, NamedList* attributes = 0, const char* text = 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor. Deletes the underlying TiXmlElement if owned.
|
|
|
|
*/
|
|
|
|
virtual ~XMLElement();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the type of this object.
|
|
|
|
* @return The type of this object as enumeration.
|
|
|
|
*/
|
|
|
|
inline Type type() const
|
|
|
|
{ return m_type; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the TiXmlElement's name.
|
|
|
|
* @return The name of the TiXmlElement object or 0.
|
|
|
|
*/
|
|
|
|
inline const char* name() const
|
|
|
|
{ return valid() ? m_element->Value() : 0; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the TiXmlElement's name is the given text.
|
|
|
|
* @param text Text to compare with.
|
|
|
|
* @return False if text is 0 or not equal to name.
|
|
|
|
*/
|
|
|
|
inline bool nameIs(const char* text) const
|
|
|
|
{ return (text && name() && (0 == ::strcmp(name(),text))); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the validity of this object.
|
|
|
|
* @return True if m_element is non null.
|
|
|
|
*/
|
|
|
|
inline bool valid() const
|
|
|
|
{ return m_element != 0; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Put the element in a buffer.
|
|
|
|
* @param dest Destination string.
|
|
|
|
* @param unclose True to leave the tag unclosed.
|
|
|
|
*/
|
|
|
|
void toString(String& dest, bool unclose = false) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the value of an existing attribute or adds a new one.
|
|
|
|
* @param name Attribute's name.
|
|
|
|
* @param value Attribute's value.
|
|
|
|
*/
|
|
|
|
void setAttribute(const char* name, const char* value);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the value of an existing attribute or adds a new one if the value's length is not 0.
|
|
|
|
* @param name Attribute's name.
|
|
|
|
* @param value Attribute's value.
|
|
|
|
*/
|
|
|
|
inline void setAttributeValid(const char* name, const String& value) {
|
|
|
|
if (value)
|
|
|
|
setAttribute(name,value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the value of an existing attribute or adds a new one from an integer.
|
|
|
|
* @param name Attribute's name.
|
|
|
|
* @param value Attribute's value.
|
|
|
|
*/
|
|
|
|
inline void setAttribute(const char* name, int value) {
|
|
|
|
String s(value);
|
|
|
|
setAttribute(name,s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the value of an attribute.
|
|
|
|
* @param name Attribute's name.
|
|
|
|
* @return Attribute's value. May be 0 if doesn't exists or empty.
|
|
|
|
*/
|
|
|
|
const char* getAttribute(const char* name);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the value of an attribute.
|
|
|
|
* @param name Attribute's name.
|
|
|
|
* @param value Destination string.
|
|
|
|
* @return True if attribute with the given name exists and is not empty.
|
|
|
|
*/
|
|
|
|
inline bool getAttribute(const char* name, String& value) {
|
|
|
|
value = getAttribute(name);
|
|
|
|
return 0 != value.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if an attribute with the given name and value exists.
|
|
|
|
* @param name Attribute's name.
|
|
|
|
* @param value Attribute's value.
|
|
|
|
* @return True/False.
|
|
|
|
*/
|
|
|
|
bool hasAttribute(const char* name, const char* value);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the text of this XML element.
|
|
|
|
* @return Pointer to the text of this XML element or 0.
|
|
|
|
*/
|
|
|
|
const char* getText();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a child to this object. Release the received element.
|
|
|
|
* On exit 'element' will be invalid if the operation succeedded.
|
|
|
|
* To succeed, 'element' MUST own his 'm_element'.
|
|
|
|
* @param element XMLElement to add.
|
|
|
|
*/
|
|
|
|
void addChild(XMLElement* element);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the first child element.
|
|
|
|
* @param name Optional name of the child.
|
|
|
|
* @return Pointer to an XMLElement or 0 if not found.
|
|
|
|
*/
|
|
|
|
XMLElement* findFirstChild(const char* name = 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the first child element of the given type.
|
|
|
|
* @param type Child's type to find.
|
|
|
|
* @return Pointer to an XMLElement or 0 if not found.
|
|
|
|
*/
|
|
|
|
inline XMLElement* findFirstChild(Type type)
|
|
|
|
{ return findFirstChild(typeName(type)); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the next child element.
|
|
|
|
* @param element Starting XMLElement. O to find from the beginning.
|
|
|
|
* @param name Optional name of the child.
|
|
|
|
* @return Pointer to an XMLElement or 0 if not found.
|
|
|
|
*/
|
|
|
|
XMLElement* findNextChild(const XMLElement* element, const char* name = 0);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the next child element of the given type.
|
|
|
|
* @param element Starting XMLElement. O to find from the beginning.
|
|
|
|
* @param type Child's type to find.
|
|
|
|
* @return Pointer to an XMLElement or 0 if not found.
|
|
|
|
*/
|
|
|
|
inline XMLElement* findNextChild(const XMLElement* element, Type type)
|
|
|
|
{ return findNextChild(element,typeName(type)); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the first attribute.
|
|
|
|
* @return Pointer to the first attribute or 0.
|
|
|
|
*/
|
|
|
|
inline const TiXmlAttribute* firstAttribute() const
|
|
|
|
{ return valid() ? m_element->FirstAttribute() : 0; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the name associated with the given type.
|
|
|
|
* @param type Element type as enumeration.
|
|
|
|
* @return Pointer to the name or 0.
|
|
|
|
*/
|
|
|
|
static inline const char* typeName(Type type)
|
|
|
|
{ return lookup(type,s_names); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* check if the given text is equal to the one associated with the given type.
|
|
|
|
* @param txt Text to compare.
|
|
|
|
* @param type Element type as enumeration.
|
|
|
|
* @return True if txt equals the text associated with the given type.
|
|
|
|
*/
|
|
|
|
static inline bool isType(const char* txt, Type type) {
|
|
|
|
const char* s = typeName(type);
|
|
|
|
return (txt && s && (0 == ::strcmp(txt,s)));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* Constructs an XML element from a TiXmlElement.
|
|
|
|
* Used to extract elements from parser and access the children.
|
|
|
|
* When extracting elements from parser the object will own the TiXmlElement.
|
|
|
|
* When accessing the children, the object will not own the TiXmlElement.
|
|
|
|
* @param element Pointer to a valid TiXmlElement.
|
|
|
|
* @param owner Owner flag.
|
|
|
|
*/
|
|
|
|
XMLElement(TiXmlElement* element, bool owner);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the underlying TiXmlElement.
|
|
|
|
* @return The underlying TiXmlElement object or 0.
|
|
|
|
*/
|
|
|
|
inline TiXmlElement* get() const
|
|
|
|
{ return m_element; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Release the ownership of the underlying TiXmlElement
|
|
|
|
* and returns it if the object owns it.
|
|
|
|
* @return The underlying TiXmlElement object or 0 if not owned or 0.
|
|
|
|
*/
|
|
|
|
TiXmlElement* releaseOwnership();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Associations between XML element name and type.
|
|
|
|
*/
|
|
|
|
static TokenDict s_names[];
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Set this object's type from m_element's name
|
|
|
|
inline void setType()
|
|
|
|
{ m_type = (Type)lookup(name(),s_names,Unknown); }
|
|
|
|
|
|
|
|
Type m_type; // Element's type
|
|
|
|
bool m_owner; // Owner flag. If true, this object owns the XML element
|
|
|
|
TiXmlElement* m_element; // The underlying XML element
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class is responsable of parsing incoming data.
|
|
|
|
* Keeps the resulting XML elements and the input buffer.
|
|
|
|
* @short An XML parser.
|
|
|
|
*/
|
|
|
|
class YJINGLE_API XMLParser : public TiXmlDocument, public Mutex
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* Constructs an XML parser.
|
|
|
|
*/
|
|
|
|
inline XMLParser()
|
|
|
|
: TiXmlDocument(), Mutex(true), m_findstart(true)
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor.
|
|
|
|
*/
|
|
|
|
virtual ~XMLParser()
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add data to buffer. Parse the buffer.
|
|
|
|
* On success, the already parsed data is removed from buffer.
|
|
|
|
* This method is thread safe.
|
|
|
|
* @param data Pointer to the data to consume.
|
|
|
|
* @param len Data length.
|
|
|
|
* @return True on successfully parsed.
|
|
|
|
*/
|
|
|
|
bool consume(const char* data, u_int32_t len);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extract the first XML element from document.
|
|
|
|
* Remove non-element children of the document (e.g. declaration).
|
|
|
|
* This method is thread safe.
|
|
|
|
* @return Pointer to an XMLElement or 0 if the document is empty.
|
|
|
|
*/
|
|
|
|
XMLElement* extract();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a copy of the parser's buffer.
|
|
|
|
* @param dest Destination string.
|
|
|
|
*/
|
|
|
|
inline void getBuffer(String& dest) const
|
|
|
|
{ dest = m_buffer; }
|
|
|
|
|
|
|
|
/**
|
2006-10-26 12:58:23 +00:00
|
|
|
* Clear the parser's input buffer and already parsed elements. Reset data.
|
2006-10-19 20:33:15 +00:00
|
|
|
*/
|
2006-10-26 12:58:23 +00:00
|
|
|
void reset();
|
2006-10-19 20:33:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The maximum allowed buffer length.
|
|
|
|
*/
|
|
|
|
static u_int32_t s_maxDataBuffer;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The XML encoding.
|
|
|
|
*/
|
|
|
|
static TiXmlEncoding s_xmlEncoding;
|
|
|
|
|
|
|
|
private:
|
|
|
|
String m_buffer; // Input data buffer
|
|
|
|
bool m_findstart; // Search for stream start tag or not
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class holds an XML element to be sent through a stream.
|
|
|
|
* @short An outgoing XML element.
|
|
|
|
*/
|
|
|
|
class YJINGLE_API XMLElementOut : public RefObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
* @param element The XML element.
|
|
|
|
* @param senderID Optional sender id.
|
|
|
|
*/
|
|
|
|
inline XMLElementOut(XMLElement* element, const char* senderID = 0)
|
|
|
|
: m_element(element), m_offset(0), m_id(senderID)
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor.
|
|
|
|
* Delete m_element if not 0.
|
|
|
|
*/
|
|
|
|
virtual ~XMLElementOut() {
|
|
|
|
if (m_element)
|
|
|
|
delete m_element;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the underlying element.
|
|
|
|
* @return The underlying element.
|
|
|
|
*/
|
|
|
|
inline XMLElement* element() const
|
|
|
|
{ return m_element; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the data buffer.
|
|
|
|
* @return The data buffer.
|
|
|
|
*/
|
|
|
|
inline String& buffer()
|
|
|
|
{ return m_buffer; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the id member.
|
|
|
|
* @return The id member.
|
|
|
|
*/
|
|
|
|
inline const String& id() const
|
|
|
|
{ return m_id; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the remainig byte count to send.
|
|
|
|
* @return The unsent number of bytes.
|
|
|
|
*/
|
|
|
|
inline u_int32_t dataCount()
|
|
|
|
{ return m_buffer.length() - m_offset; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the remainig data to send. Set the buffer if not already set.
|
|
|
|
* @param nCount The number of unsent bytes.
|
|
|
|
* @return Pointer to the remaining data or 0.
|
|
|
|
*/
|
|
|
|
inline const char* getData(u_int32_t& nCount) {
|
|
|
|
if (!m_buffer)
|
|
|
|
prepareToSend();
|
|
|
|
nCount = dataCount();
|
|
|
|
return m_buffer.c_str() + m_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Increase the offset with nCount bytes.
|
|
|
|
* @param nCount The number of bytes sent.
|
|
|
|
*/
|
|
|
|
inline void dataSent(u_int32_t nCount) {
|
|
|
|
m_offset += nCount;
|
|
|
|
if (m_offset > m_buffer.length())
|
|
|
|
m_offset = m_buffer.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Release the ownership of m_element.
|
|
|
|
* The caller is responsable of returned pointer.
|
|
|
|
* @return XMLElement pointer or 0.
|
|
|
|
*/
|
|
|
|
inline XMLElement* release() {
|
|
|
|
XMLElement* e = m_element;
|
|
|
|
m_element = 0;
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fill a buffer with the XML element to send.
|
|
|
|
* @param buffer The buffer to fill.
|
|
|
|
*/
|
|
|
|
inline void toBuffer(String& buffer)
|
|
|
|
{ if (m_element) m_element->toString(buffer); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fill the buffer with the XML element to send.
|
|
|
|
*/
|
|
|
|
inline void prepareToSend()
|
|
|
|
{ toBuffer(m_buffer); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
XMLElement* m_element; // The XML element
|
|
|
|
String m_buffer; // Data to send
|
|
|
|
u_int32_t m_offset; // Offset to send
|
|
|
|
String m_id; // Sender's id
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* __XMLPARSER_H */
|
|
|
|
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|