< Previous by Date | Date Index | Next by Date > |
Thread Index |
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&);