|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include "resip/stack/Pidf.hxx" 00006 #include "resip/stack/SipMessage.hxx" 00007 #include "resip/stack/Symbols.hxx" 00008 #include "rutil/XMLCursor.hxx" 00009 #include "rutil/Logger.hxx" 00010 #include "rutil/Inserter.hxx" 00011 #include "rutil/WinLeakCheck.hxx" 00012 00013 using namespace resip; 00014 using namespace std; 00015 00016 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP 00017 00018 bool 00019 Pidf::init() 00020 { 00021 static ContentsFactory<Pidf> factory; 00022 (void)factory; 00023 return true; 00024 } 00025 00026 const Pidf Pidf::Empty; 00027 00028 Pidf::Pidf() 00029 : Contents(getStaticType()), 00030 mNote() 00031 { 00032 } 00033 00034 Pidf::Pidf(const Data& txt) 00035 : Contents(getStaticType()), 00036 mNote(txt) 00037 { 00038 } 00039 00040 Pidf::Pidf(const Mime& contentType) 00041 : Contents(getStaticType()), 00042 mNote() 00043 { 00044 } 00045 00046 Pidf::Pidf(const HeaderFieldValue& hfv, const Mime& contentsType) 00047 : Contents(hfv, contentsType), 00048 mNote() 00049 { 00050 } 00051 00052 Pidf::Pidf(const Data& txt, const Mime& contentType) 00053 : Contents(contentType), 00054 mNote(txt) 00055 { 00056 } 00057 00058 Pidf& 00059 Pidf::operator=(const Pidf& rhs) 00060 { 00061 if (this != &rhs) 00062 { 00063 Contents::operator=(rhs); 00064 mNote = rhs.mNote; 00065 mEntity = rhs.mEntity; 00066 mTuples = rhs.mTuples; 00067 } 00068 return *this; 00069 } 00070 00071 Pidf::Pidf(const Pidf& rhs) 00072 : Contents(rhs), 00073 mNote(rhs.mNote), 00074 mEntity(rhs.mEntity), 00075 mTuples(rhs.mTuples) 00076 { 00077 } 00078 00079 Pidf::Pidf(const Uri& entity) 00080 : Contents(getStaticType()), 00081 mEntity(entity) 00082 { 00083 } 00084 00085 Pidf::~Pidf() 00086 { 00087 } 00088 00089 void 00090 Pidf::setEntity(const Uri& entity) 00091 { 00092 checkParsed(); 00093 mEntity = entity; 00094 } 00095 00096 const Uri& 00097 Pidf::getEntity() const 00098 { 00099 checkParsed(); 00100 return mEntity; 00101 }; 00102 00103 std::vector<Pidf::Tuple>& 00104 Pidf::getTuples() 00105 { 00106 checkParsed(); 00107 return mTuples; 00108 } 00109 00110 const std::vector<Pidf::Tuple>& 00111 Pidf::getTuples() const 00112 { 00113 checkParsed(); 00114 return mTuples; 00115 } 00116 00117 int 00118 Pidf::getNumTuples() const 00119 { 00120 checkParsed(); 00121 return (int)mTuples.size(); 00122 } 00123 00124 Contents* 00125 Pidf::clone() const 00126 { 00127 return new Pidf(*this); 00128 } 00129 00130 const Mime& 00131 Pidf::getStaticType() 00132 { 00133 static Mime type("application","pidf+xml"); 00134 return type; 00135 } 00136 00137 EncodeStream& 00138 Pidf::encodeParsed(EncodeStream& str) const 00139 { 00140 str << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << Symbols::CRLF; 00141 str << "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"" << Symbols::CRLF; 00142 str << " entity=\"" << mEntity << "\">" << Symbols::CRLF; 00143 for (vector<Tuple>::const_iterator i = mTuples.begin(); i != mTuples.end(); ++i) 00144 { 00145 Data status( (char*)( (i->status) ? "open" : "closed" ) ); 00146 str << " <tuple id=\"" << i->id << "\" "; 00147 00148 XMLCursor::encode(str, i->attributes); 00149 str << ">" << Symbols::CRLF; 00150 str << " <status><basic>" << status << "</basic></status>" << Symbols::CRLF; 00151 if ( !i->contact.empty() ) 00152 { 00153 str << " <contact priority=\"" << i->contactPriority << "\">" << i->contact << "</contact>" << Symbols::CRLF; 00154 } 00155 if ( !i->timeStamp.empty() ) 00156 { 00157 str << " <timestamp>" << i->timeStamp << "</timestamp>" << Symbols::CRLF; 00158 } 00159 if ( !i->note.empty() ) 00160 { 00161 str << " <note>" << i->note << "</note>" << Symbols::CRLF; 00162 } 00163 str << " </tuple>" << Symbols::CRLF; 00164 } 00165 str << "</presence>" << Symbols::CRLF; 00166 00167 return str; 00168 } 00169 00170 void 00171 Pidf::parse(ParseBuffer& pb) 00172 { 00173 /* 00174 REVISIT WHY THE BELOW WAS REMOVED 00175 REMOVING IT SCREWS UP WHAT GOES OUT IN THE PUBLISH 00176 */ 00177 DebugLog(<< "Pidf::parse(" << Data(pb.start(), int(pb.end()-pb.start())) << ") "); 00178 00179 std::string pidf_namespace; 00180 00181 XMLCursor xml(pb); 00182 00183 XMLCursor::AttributeMap attr = xml.getAttributes(); 00184 XMLCursor::AttributeMap::const_iterator it = 00185 std::find_if(attr.begin(), attr.end(), XMLCursor::AttributeValueEqual("urn:ietf:params:xml:ns:pidf")); 00186 00187 if ( it != attr.end() ) { 00188 00189 std::string key(it->first.data(), it->first.size()); 00190 00191 size_t pos = key.find(':'); 00192 00193 if ( pos != string::npos) { 00194 pidf_namespace.assign(key, pos+1, key.size()-pos-1); 00195 pidf_namespace.append(1, ':'); 00196 } 00197 } 00198 00199 const std::string presence = pidf_namespace + "presence"; 00200 00201 if (xml.getTag() == presence.c_str()) 00202 { 00203 XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("entity"); 00204 if (i != xml.getAttributes().end()) 00205 { 00206 mEntity = Uri(i->second); 00207 } 00208 else 00209 { 00210 DebugLog(<< "no entity!"); 00211 } 00212 00213 if (xml.firstChild()) 00214 { 00215 do 00216 { 00217 const std::string tuple = pidf_namespace + "tuple"; 00218 if (xml.getTag() == tuple.c_str()) 00219 { 00220 Tuple t; 00221 t.attributes = xml.getAttributes(); 00222 XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("id"); 00223 if (i != xml.getAttributes().end()) 00224 { 00225 t.id = i->second; 00226 t.attributes.erase("id"); 00227 } 00228 00229 // look for status, contacts, notes -- take last of each for now 00230 if (xml.firstChild()) 00231 { 00232 do 00233 { 00234 const std::string status = pidf_namespace + "status"; 00235 const std::string contact = pidf_namespace + "contact"; 00236 const std::string note = pidf_namespace + "note"; 00237 const std::string timestamp = pidf_namespace + "timestamp"; 00238 if (xml.getTag() == status.c_str()) 00239 { 00240 // look for basic 00241 if (xml.firstChild()) 00242 { 00243 do 00244 { 00245 std::string basic = pidf_namespace + "basic"; 00246 if (xml.getTag() == basic.c_str()) 00247 { 00248 if (xml.firstChild()) 00249 { 00250 t.status = (xml.getValue() == "open"); 00251 xml.parent(); 00252 } 00253 } 00254 } while (xml.nextSibling()); 00255 xml.parent(); 00256 } 00257 } 00258 else if (xml.getTag() == contact.c_str()) 00259 { 00260 XMLCursor::AttributeMap::const_iterator i = xml.getAttributes().find("priority"); 00261 if (i != xml.getAttributes().end()) 00262 { 00263 t.contactPriority.setValue(i->second); 00264 } 00265 if (xml.firstChild()) 00266 { 00267 t.contact = xml.getValue(); 00268 xml.parent(); 00269 } 00270 } 00271 else if (xml.getTag() == note.c_str()) 00272 { 00273 if (xml.firstChild()) 00274 { 00275 t.note = xml.getValue(); 00276 xml.parent(); 00277 } 00278 } 00279 else if (xml.getTag() == timestamp.c_str()) 00280 { 00281 if (xml.firstChild()) 00282 { 00283 t.timeStamp = xml.getValue(); 00284 xml.parent(); 00285 } 00286 } 00287 } while (xml.nextSibling()); 00288 xml.parent(); 00289 } 00290 00291 mTuples.push_back(t); 00292 } 00293 } while (xml.nextSibling()); 00294 xml.parent(); 00295 } 00296 } 00297 else 00298 { 00299 DebugLog(<< "no presence tag!"); 00300 } 00301 /* 00302 REVISIT WHY THE ABOVE WAS REMOVED 00303 */ 00304 00305 // THIS HERE IS THE ESSENCE OF WHAT IS USED. 00306 // const char* anchor = pb.position(); 00307 const char* anchor = pb.start(); 00308 pb.skipToEnd(); 00309 pb.data(mNote, anchor); 00310 DebugLog(<< "mNote is : " << mNote ); 00311 // END OF - ESSENCE 00312 } 00313 00314 void 00315 Pidf::setSimpleId(const Data& id) 00316 { 00317 checkParsed(); 00318 if (mTuples.empty()) 00319 { 00320 Tuple t; 00321 mTuples.push_back(t); 00322 } 00323 mTuples[0].id = id; 00324 } 00325 00326 void 00327 Pidf::setSimpleStatus( bool online, const Data& note, const Data& contact ) 00328 { 00329 checkParsed(); 00330 if (mTuples.empty()) 00331 { 00332 Tuple t; 00333 mTuples.push_back(t); 00334 } 00335 00336 mTuples[0].status = online; 00337 mTuples[0].contact = contact; 00338 mTuples[0].contactPriority = 1000; // 1.0 00339 mTuples[0].note = note; 00340 mTuples[0].timeStamp = Data::Empty; 00341 } 00342 00343 bool 00344 Pidf::getSimpleStatus(Data* note) const 00345 { 00346 checkParsed(); 00347 00348 if (!mTuples.empty()) 00349 { 00350 if (note) 00351 { 00352 *note = mTuples[0].note; 00353 } 00354 00355 return mTuples[0].status; 00356 } 00357 return false; 00358 } 00359 00360 void 00361 Pidf::merge(const Pidf& other) 00362 { 00363 vector<Tuple>& tuples = getTuples(); 00364 tuples.reserve(tuples.size() + other.getTuples().size()); 00365 00366 setEntity(other.mEntity); 00367 00368 for (vector<Tuple>::const_iterator i = other.getTuples().begin(); 00369 i != other.getTuples().end(); ++i) 00370 { 00371 bool found = false; 00372 for (vector<Tuple>::iterator j = getTuples().begin(); 00373 j != getTuples().end(); ++j) 00374 { 00375 if (i->id == j->id) 00376 { 00377 found = true; 00378 *j = *i; 00379 break; 00380 } 00381 } 00382 if (!found) 00383 { 00384 tuples.push_back(*i); 00385 } 00386 } 00387 } 00388 00389 EncodeStream& 00390 resip::operator<<(EncodeStream& strm, const Pidf::Tuple& tuple) 00391 { 00392 strm << "Tuple [" 00393 << " status=" << tuple.status 00394 << " id=" << tuple.id 00395 << " contact=" << tuple.contact 00396 << " attributes=" << Inserter(tuple.attributes); 00397 return strm; 00398 } 00399 00400 /* ==================================================================== 00401 * The Vovida Software License, Version 1.0 00402 * 00403 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00404 * 00405 * Redistribution and use in source and binary forms, with or without 00406 * modification, are permitted provided that the following conditions 00407 * are met: 00408 * 00409 * 1. Redistributions of source code must retain the above copyright 00410 * notice, this list of conditions and the following disclaimer. 00411 * 00412 * 2. Redistributions in binary form must reproduce the above copyright 00413 * notice, this list of conditions and the following disclaimer in 00414 * the documentation and/or other materials provided with the 00415 * distribution. 00416 * 00417 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00418 * and "Vovida Open Communication Application Library (VOCAL)" must 00419 * not be used to endorse or promote products derived from this 00420 * software without prior written permission. For written 00421 * permission, please contact vocal@vovida.org. 00422 * 00423 * 4. Products derived from this software may not be called "VOCAL", nor 00424 * may "VOCAL" appear in their name, without prior written 00425 * permission of Vovida Networks, Inc. 00426 * 00427 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00428 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00429 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00430 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00431 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00432 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00433 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00434 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00435 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00436 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00437 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00438 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00439 * DAMAGE. 00440 * 00441 * ==================================================================== 00442 * 00443 * This software consists of voluntary contributions made by Vovida 00444 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00445 * Inc. For more information on Vovida Networks, Inc., please see 00446 * <http://www.vovida.org/>. 00447 * 00448 */
1.7.5.1