reSIProcate/stack  9694
Pidf.cxx
Go to the documentation of this file.
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  */