< Previous by Date Date Index Next by Date >
  Thread Index  

[reSIProcate] NOTIFY requeset: Presence parsing: support for XML namespace prefix (patch attached)


Hi everybody,

I am using resprocate library to develop a SIP client. I had problems when parsing presence information from the other users. I've also tried limpc and found out that limpc has the same problem. The problem was one way: from the other client to limpc. The other clients had no problem with limpc's status recognition.

I've investigated the sources and I've found out that Pidf::parse() fails to parse the body of the NOTIFY request. The other SIP client uses XML namespace associated with a namespace prefix to scope the Pidf element names.

Example:
<pr:presence xmlns:pr="urn:ietf:params:xml:ns:pidf">
    <pr:tuple>
       <pr:status>
            <pr:basic>open</pr:basic>
        <pr:status>
    </pr:tuple>
</pr:presence>

But the Pidf parser works only when the global namespace is used. In this case we have no namespace prefix.

Example:
<presence xmlns="urn:ietf:params:xml:ns:pidf">
    <tuple>
       <status>
            <basic>open</basic>
       </status>
    <tuple>
</presence>

I made some corrections to be able to parse presence elements that are prefixed by a namespace prefix. I am attaching the patch. Maybe someone is interested.
The patch was made against the main trunk of the repository, revision 6387

Best Regards,
Orlin Jechev

Index: resip/stack/Pidf.cxx
===================================================================
--- resip/stack/Pidf.cxx	(revision 6387)
+++ resip/stack/Pidf.cxx	(working copy)
@@ -146,18 +146,38 @@
       str << "  </tuple>" << Symbols::CRLF;
    }
    str << "</presence>" << Symbols::CRLF;
-
+
    return str;
 }

-void
+void
 Pidf::parse(ParseBuffer& pb)
 {
    DebugLog(<< "Pidf::parse(" << Data(pb.start(), int(pb.end()-pb.start())) << ") ");

+	std::string pidf_namespace;
+
    XMLCursor xml(pb);

-   if (xml.getTag() == "presence")
+	XMLCursor::AttributeMap attr = xml.getAttributes();
+	XMLCursor::AttributeMap::const_iterator it =
+			std::find_if(attr.begin(), attr.end(), XMLCursor::AttributeValueEqual("urn:ietf:params:xml:ns:pidf"));
+
+	if ( it != attr.end() ) {
+
+		std::string key(it->first.data(), it->first.size());
+
+		size_t pos = key.find(':');
+
+		if ( pos != string::npos) {
+			pidf_namespace.assign(key, pos+1, key.size()-pos-1);
+			pidf_namespace.append(1, ':');
+		}
+	}
+
+	const std::string presence = pidf_namespace + "presence";
+
+	if (xml.getTag() == presence.c_str())
    {
       XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("entity");
       if (i != xml.getAttributes().end())
@@ -168,12 +188,13 @@
       {
          DebugLog(<< "no entity!");
       }
-
+
       if (xml.firstChild())
       {
          do
          {
-            if (xml.getTag() == "tuple")
+				const std::string tuple = pidf_namespace + "tuple";
+				if (xml.getTag() == tuple.c_str())
             {
                Tuple t;
                t.attributes = xml.getAttributes();
@@ -183,20 +204,25 @@
                   t.id = i->second;
                   t.attributes.erase("id");
                }
-
+
                // look for status, contacts, notes -- take last of each for now
                if (xml.firstChild())
                {
                   do
                   {
-                     if (xml.getTag() == "status")
+							const std::string status = pidf_namespace + "status";
+							const std::string contact = pidf_namespace + "contact";
+							const std::string note = pidf_namespace + "note";
+							const std::string timestamp = pidf_namespace + "timestamp";
+                     if (xml.getTag() == status.c_str())
                      {
                         // look for basic
                         if (xml.firstChild())
                         {
                            do
                            {
-                              if (xml.getTag() == "basic")
+										std::string basic = pidf_namespace + "basic";
+                              if (xml.getTag() == basic.c_str())
                               {
                                  if (xml.firstChild())
                                  {
@@ -208,7 +234,7 @@
                            xml.parent();
                         }
                      }
-                     else if (xml.getTag() == "contact")
+							else if (xml.getTag() == contact.c_str())
                      {
                         XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("priority");
                         if (i != xml.getAttributes().end())
@@ -221,7 +247,7 @@
                            xml.parent();
                         }
                      }
-                     else if (xml.getTag() == "note")
+							else if (xml.getTag() == note.c_str())
                      {
                         if (xml.firstChild())
                         {
@@ -229,7 +255,7 @@
                            xml.parent();
                         }
                      }
-                     else if (xml.getTag() == "timestamp")
+							else if (xml.getTag() == timestamp.c_str())
                      {
                         if (xml.firstChild())
                         {
Index: resip/stack/XMLCursor.hxx
===================================================================
--- resip/stack/XMLCursor.hxx	(revision 6387)
+++ resip/stack/XMLCursor.hxx	(working copy)
@@ -119,6 +119,13 @@
       static std::ostream& encode(std::ostream& strm, const AttributeMap& attrs);
       class Node;

+		class AttributeValueEqual {
+			Data data_;
+			public:
+				AttributeValueEqual(const Data& data) : data_(data) {};
+				bool operator()(const std::pair<Data, Data>& data) { return data.second == data_; }
+		};
+
    private:
       static void skipProlog(ParseBuffer& pb);
       static void decode(Data&);