2 Replies Last post: Aug 23, 2008 10:21 PM by Guest  
Guest

Aug 22, 2008 9:03 AM

[OpenSIPStack] pdif Parser

Hi Joegen,

here are my pdif parser classes ready for reviewing.

I'm ready for critique. ;)

Matthias
/*
*
* RFC3863XMLHandler.cxx
*
* Open SIP Stack ( OSS )
*
*/
#define XML_UNICODE

#include "RFC3863XMLHandler.h"

using namespace RFC3863;

RFC3863XMLHandler::RFC3863XMLHandler()
{
}

RFC3863XMLHandler::~RFC3863XMLHandler()
{
}

RFC3863Document *
RFC3863XMLHandler::Parse(PXML &xml)
{
// check if root node is node presence
PXMLElement * root = xml.GetRootElement();
if (root == NULL || root->GetName().Find("presence") == P_MAX_INDEX) {
return NULL;
} else {
return OnPresenceNodeFound(root);
}
}

RFC3863Document *
RFC3863XMLHandler::OnPresenceNodeFound(PXMLElement * presenceNode)
{
BOOL validNamespace = FALSE;
RFC3863Document * pdifDoc;

// check for namespaces and entity
if (presenceNode->HasAttributes()) {
for (PINDEX i = 0; iGetNumAttributes(); ++i) {
if (presenceNode->GetKeyAttribute(i) == "entity") {
PString entity = presenceNode->GetDataAttribute(i);
pdifDoc = new RFC3863Document(entity);
} else {
PString xmlns = presenceNode->GetKeyAttribute(i);
if (presenceNode->GetDataAttribute(i) == "urn:ietf:params:xml:ns:pidf") {
validNamespace = TRUE;
m_RFC3863NamespaceTag = ExtractNamespaceTag(xmlns);
} else {
m_namespaceTags.AppendString(ExtractNamespaceTag(xmlns));
}
}
}
}

PString entity = pdifDoc->GetEntity();
if (entity.IsEmpty() || !validNamespace) {
// no valid RFC3863Document because of missing entity
return NULL;
}

// parse subnodes of presence node
if (presenceNode->HasSubObjects()) {
PString currentNode;
for (int i = 0; i GetSize(); i++) {
PXMLElement * subNode = (PXMLElement*) presenceNode->GetElement(i);
if (subNode->IsElement()) {
currentNode = subNode->GetName();
if (currentNode == m_RFC3863NamespaceTag + "tuple") {
Tuple * tuple = OnTupleNodeFound(subNode);
if (tuple) {
pdifDoc->AddTuple(tuple);
}
} else if (currentNode == m_RFC3863NamespaceTag + "note") {
Note * note = OnNoteNodeFound(subNode);
if (note) {
pdifDoc->AddNote(note);
}
} else {
OnUnknownPresenceNodeFound(pdifDoc, subNode);
}
}
}
}
return pdifDoc;
}

Tuple *
RFC3863XMLHandler::OnTupleNodeFound(PXMLElement * tupleNode)
{
Tuple * tuple = NULL;

// check for attribute 'id' MUST be present
PString id;
if (tupleNode->HasAttributes()) {
// look for id
for (int i = 0; i GetNumAttributes(); i++) {
if (tupleNode->GetKeyAttribute(i) == "id") {
id = tupleNode->GetDataAttribute(i);
break;
}
}
if (id.IsEmpty()) {
// id is required!
return NULL;
}
}

// parse subnodes of tuple node
if (tupleNode->HasSubObjects()) {
PString currentNode;
PXMLElement * subNode;
for (int i = 0; i GetSize(); i++) {
subNode = (PXMLElement*)tupleNode->GetElement(i);
if (subNode->IsElement()) {
currentNode = subNode->GetName();
// status node has to be first see xml schema of RFC-3863
if (currentNode == m_RFC3863NamespaceTag + "status") {
Tuple::Status status;
if (OnStatusNodeFound(status, subNode)) {
tuple = new Tuple(id, status);
} else {
// tuple MUST have an id and status is mandatory!
return NULL;
}
} else if ((currentNode == m_RFC3863NamespaceTag + "contact") && tuple) {
Contact contact;
if (OnContactNodeFound(contact, subNode)) {
tuple->SetContact(contact);
}
} else if ((currentNode == m_RFC3863NamespaceTag + "note") && tuple) {
Note * note = OnNoteNodeFound(subNode);
if (note) {
tuple->AddNote(note);
}
} else if ((currentNode == m_RFC3863NamespaceTag + "timestamp") && tuple) {
PString timestamp;
if (OnTimestampNodeFound(timestamp, subNode)) {
tuple->SetTimeStamp(timestamp);
}
} else {
OnUnknownTupleNodeFound(tuple, subNode);
}
}
}
}
return tuple;
}

Note *
RFC3863XMLHandler::OnNoteNodeFound(PXMLElement * noteNode)
{
PString lang;
PString noteText = noteNode->GetData();

// check for attributes
if (noteNode->HasAttributes()) {
// look for xml:lang attribute SHOULD be present
for (int i = 0; i GetNumAttributes(); i++) {
if (noteNode->GetKeyAttribute(i) == "xml:lang") {
lang = noteNode->GetDataAttribute(i);
break;
}
}
}
// only add note if a note text exists
if (!noteText.IsEmpty()) {
return new Note(noteText, lang);
}
return NULL;
}

BOOL
RFC3863XMLHandler::OnStatusNodeFound(Tuple::Status & status, PXMLElement * statusNode)
{
// check for subnodes
if (statusNode->HasSubObjects()) {
PString currentNode;
PXMLElement * subNode;
for (int i = 0; i GetSize(); i++) {
subNode = (PXMLElement*)statusNode->GetElement(i);
if (subNode->IsElement()) {
currentNode = subNode->GetName();
// check if tuple is 'open' or 'closed'
if (currentNode == m_RFC3863NamespaceTag + "basic") {
PString stat = subNode->GetData();
status = (stat == "open") ? Tuple::Open : Tuple::Closed;
return TRUE;
} else {
OnUnknownStatusNodeFound(status, subNode);
}
}
}
}
return FALSE;
}

BOOL
RFC3863XMLHandler::OnContactNodeFound(Contact & contact, PXMLElement * contactNode)
{
// check for attributes
PString priority;
if (contactNode->HasAttributes()) {
// look for priority of this contact
for (int i = 0; i GetNumAttributes(); i++) {
if (contactNode->GetKeyAttribute(i) == "priority") {
priority = contactNode->GetDataAttribute(i);
break;
}
}
}
// set contact data
contact.SetContact(contactNode->GetData());
contact.SetPriority(priority.AsReal());

if (!contact.GetURIAsString().IsEmpty()) {
return TRUE;
}
return FALSE;
}

BOOL
RFC3863XMLHandler::OnTimestampNodeFound(PString & timestamp, PXMLElement * timestampNode)
{
timestamp = timestampNode->GetData();
return TRUE;
}

void
RFC3863XMLHandler::OnUnknownPresenceNodeFound(RFC3863Document * doc, PXMLElement * unknownNode)
{

}

void
RFC3863XMLHandler::OnUnknownTupleNodeFound(Tuple * tupel, PXMLElement * unknownNode)
{

}

void
RFC3863XMLHandler::OnUnknownStatusNodeFound(Tuple::Status & status, PXMLElement * unknownNode)
{

}

PString
RFC3863XMLHandler::ExtractNamespaceTag(PString &namespaceAttribute)
{
PStringArray namespaceParts = namespaceAttribute.Tokenise(':', FALSE);

// returns tag after xmlns:
if (namespaceParts.GetSize() == 1) {
return PString();
} else {
return namespaceParts[1] + ":";
}
}
/*
*
* RFC3863XMLHandler.h
*
* Open SIP Stack ( OSS )
*
*/

#ifndef RFC3863_XML_HANDLER_H
#define RFC3863_XML_HANDLER_H

#include

#if P_EXPAT

#include <ptclib/pxml.h>

#include "RFC3863Document.h"

namespace RFC3863
{
class RFC3863XMLHandler : public PObject
{
PCLASSINFO( RFC3863XMLHandler, PObject );

public:
RFC3863XMLHandler();
virtual ~RFC3863XMLHandler();

virtual RFC3863Document * Parse(PXML &xml);

protected:
virtual RFC3863Document * OnPresenceNodeFound(PXMLElement * presenceNode);
virtual Tuple * OnTupleNodeFound(PXMLElement * tupleNode);
virtual Note * OnNoteNodeFound(PXMLElement * noteNode);
virtual BOOL OnStatusNodeFound(Tuple::Status & status, PXMLElement * statusNode);
virtual BOOL OnContactNodeFound(Contact & contact, PXMLElement * contactNode);
virtual BOOL OnTimestampNodeFound(PString & timestamp, PXMLElement * timestampNode);

virtual void OnUnknownPresenceNodeFound(RFC3863Document * doc, PXMLElement * unknownNode);
virtual void OnUnknownTupleNodeFound(Tuple * tuple, PXMLElement * unknownNode);
virtual void OnUnknownStatusNodeFound(Tuple::Status & status, PXMLElement* unknownNode);

virtual PString ExtractNamespaceTag(PString &namespaceAttribute);

PString m_RFC3863NamespaceTag;
PStringArray m_namespaceTags;
};
};
#endif // P_EXPAT

#endif // RFC3863_XML_HANDLER_H


/*
*
* RFC3863Document.h
*
* Open SIP Stack ( OSS )
*
*/

#ifndef RFC3863DOCUMENT_H
#define RFC3863DOCUMENT_H

#include "ptlib.h"

namespace RFC3863
{
class Note : public PObject
{
PCLASSINFO( Note, PObject );

public:

Note(PString note, PString lang = PString()): m_note(note), m_language(lang) {}
virtual ~Note() {}

virtual inline PString & GetNote() { return m_note; }
virtual inline PString & GetLanguage() { return m_language; }
virtual inline BOOL HasLanguage() { return !m_language.IsEmpty(); }

virtual inline void SetNote(PString note) { m_note = note; }
virtual inline void SetLanguage(PString lang) { m_language = lang; }

private:
PString m_note;
PString m_language; // like en, de, fr, ...
};

///////////////////////////////////////////////////////////////////////

class Contact : public PObject
{
PCLASSINFO( Contact, PObject );

public:
Contact() : m_priority(0) {}
Contact(PString contact, double prio = 0) : m_contactURI(contact), m_priority(prio) {}
virtual ~Contact() {}

virtual inline PString & GetURIAsString() { return m_contactURI; }
virtual inline double GetPriority() { return m_priority; }
virtual inline BOOL HasPriority() { return m_priority != 0; }

virtual inline void SetContact(PString contact) { m_contactURI = contact; }
virtual inline void SetPriority(double prio) { m_priority = prio; }

private:
PString m_contactURI; /// SIPURI ???
double m_priority; /// values from 0.000 to 1.000
};

///////////////////////////////////////////////////////////////////////

class Tuple : public PObject
{
PCLASSINFO( Tuple, PObject );

public:
enum Status {
Open,
Closed
};

PLIST( Notes, Note );

Tuple(PString id, Status status) : m_id(id), m_status(status) {}
virtual ~Tuple() {}

virtual inline void AddNote(Note *note) { m_listOfNotes.Append(note); }
virtual inline void AddNote(PString note){ m_listOfNotes.Append(new Note(note)); }
virtual inline Notes GetListOfNotes() const { return m_listOfNotes; }
virtual inline PINDEX GetNumNotes() const { return m_listOfNotes.GetSize(); }
virtual inline Note GetNote(PINDEX idx = 0) const { return m_listOfNotesidx; }

virtual inline void SetContact(Contact contact) { m_contact = contact; }
virtual inline void SetContact(PString contact) { m_contact = Contact(contact); }
virtual inline void SetTimeStamp(PString time) { m_timestamp = time; }

virtual inline PString &GetId() { return m_id; }
virtual inline Status & GetStatus() { return m_status; }
virtual inline BOOL IsOnline() { return m_status == Open; }
virtual inline Contact & GetContact() { return m_contact; }
virtual inline PString & GetTimeStamp() { return m_timestamp; }

private:
PString m_id;
Status m_status;
Contact m_contact;
PString m_timestamp;
Notes m_listOfNotes;
};

///////////////////////////////////////////////////////////////////////

class RFC3863Document : public PObject
{
PCLASSINFO( RFC3863Document, PObject );

public:
PLIST( Tuples, Tuple );
PLIST( Notes, Note );

RFC3863Document(PString &entity) : m_entity(entity) {}
virtual ~RFC3863Document() {}

virtual inline PString & GetEntity() { return m_entity; }

virtual void AddTuple(Tuple *tuple) { m_listOfTuples.Append(tuple); }
virtual void AddTuple(PString id, Tuple::Status status) { m_listOfTuples.Append(new Tuple(id, status)); }
virtual inline Tuple & GetTuple(PINDEX idx) { return m_listOfTuplesidx; }
virtual inline Tuples & GetListOfTuples() { return m_listOfTuples; }
virtual inline PINDEX GetNumTuples() const { return m_listOfTuples.GetSize(); }

virtual void AddNote(Note *note) { m_listOfNotes.Append(note); }
virtual void AddNote(PString text) { m_listOfNotes.Append(new Note(text)); }
virtual inline Note & GetNote(PINDEX idx) { return m_listOfNotesidx; }
virtual inline Notes & GetListOfNotes() { return m_listOfNotes; }
virtual inline PINDEX GetNumNotes() const { return m_listOfNotes.GetSize(); }

protected:
Tuples m_listOfTuples;
Notes m_listOfNotes;
PString m_entity;
};
};

#endif /*RFC3863DOCUMENT_H*/


This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
opensipstack-devel mailing list
opensipstack-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensipstack-devel
Guest
1. Aug 22, 2008 9:06 AM in response to: Guest
Re: [OpenSIPStack] pdif Parser
Remark: The line with #define XML_UNICODE should be removed.

Matthias Dreißig schrieb:
Hi Joegen,

here are my pdif parser classes ready for reviewing.

I'm ready for critique. ;)

Matthias


This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
opensipstack-devel mailing list
opensipstack-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensipstack-devel
Guest
2. Aug 23, 2008 10:21 PM in response to: Guest
Re: [OpenSIPStack] pdif Parser
Mathias,

This is looking great! I can see that you have only implemented
handling of incoming PIDF from NOTIFY. We will also need the ability to
encode XML for PUBLISH when the UA initially announces it's presence
status to the presence server. When you get this done, we can have the
music start playing.

Joegen

Matthias Dreißig wrote:
Hi Joegen,

here are my pdif parser classes ready for reviewing.

I'm ready for critique. ;)

Matthias

No virus found in this incoming message.
Checked by AVG - http://www.avg.com Version: 8.0.138 / Virus Database:
270.6.7/1628 - Release Date: 8/22/2008 6:32 PM



This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/


_______________________________________________
opensipstack-devel mailing list
opensipstack-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensipstack-devel



This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
opensipstack-devel mailing list
opensipstack-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensipstack-devel