stanza.cpp

00001 /*
00002   Copyright (c) 2005-2006 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 
00014 #include "stanza.h"
00015 #include "jid.h"
00016 
00017 namespace gloox
00018 {
00019 
00020   Stanza::Stanza( const std::string& name, const std::string& cdata, const std::string& xmllang, bool incoming )
00021     : Tag( name, cdata, incoming ), m_subtype( StanzaSubUndefined ), m_show( PresenceUnknown ),
00022       m_stanzaError( StanzaErrorUndefined ), m_stanzaErrorType( StanzaErrorTypeUndefined ),
00023       m_stanzaErrorAppCondition( 0 ), m_xmllang( xmllang ), m_priority( -300 )
00024   {
00025   }
00026 
00027   Stanza::Stanza( Tag *tag )
00028     : Tag( tag->name(), tag->cdata(), false ), m_show( PresenceUnknown ),
00029       m_stanzaError( StanzaErrorUndefined ), m_stanzaErrorType( StanzaErrorTypeUndefined ),
00030       m_stanzaErrorAppCondition( 0 ), m_xmllang( "default" )
00031   {
00032     m_attribs = tag->attributes();
00033     Tag::TagList l = tag->children();
00034     Tag::TagList::const_iterator it = l.begin();
00035     for( ; it != l.end(); ++it )
00036     {
00037       addChild( (*it)->clone() );
00038     }
00039 
00040     init();
00041   }
00042 
00043   void Stanza::init()
00044   {
00045     m_from.setJID( findAttribute( "from" ) );
00046     m_to.setJID( findAttribute( "to" ) );
00047     m_id = findAttribute( "id" );
00048 
00049     if( m_name == "iq" )
00050     {
00051       m_type = StanzaIq;
00052       if( hasAttribute( "type", "get" ) )
00053         m_subtype = StanzaIqGet;
00054       else if( hasAttribute( "type", "set" ) )
00055         m_subtype = StanzaIqSet;
00056       else if( hasAttribute( "type", "result" ) )
00057         m_subtype = StanzaIqResult;
00058       else if( hasAttribute( "type", "error" ) )
00059         m_subtype = StanzaIqError;
00060       else
00061         m_subtype = StanzaSubUndefined;
00062 
00063       Tag *t = findChildWithAttrib( "xmlns" );
00064       if( t )
00065         m_xmlns = t->findAttribute( "xmlns" );
00066     }
00067     else if( m_name == "message" )
00068     {
00069       m_type = StanzaMessage;
00070       if( hasAttribute( "type", "chat" ) )
00071         m_subtype = StanzaMessageChat;
00072       else if( hasAttribute( "type", "error" ) )
00073         m_subtype = StanzaMessageError;
00074       else if( hasAttribute( "type", "headline" ) )
00075         m_subtype = StanzaMessageHeadline;
00076       else if( hasAttribute( "type", "groupchat" ) )
00077         m_subtype = StanzaMessageGroupchat;
00078       else
00079         m_subtype = StanzaMessageNormal;
00080 
00081       TagList& c = children();
00082       TagList::const_iterator it = c.begin();
00083       for( ; it != c.end(); ++it )
00084       {
00085         if( (*it)->name() == "body" )
00086         {
00087           const std::string lang = (*it)->findAttribute( "xml:lang" );
00088           if( !lang.empty() )
00089             m_body[lang] = (*it)->cdata();
00090           else
00091             m_body["default"] = (*it)->cdata();
00092         }
00093         else if( (*it)->name() == "subject" )
00094         {
00095           const std::string lang = (*it)->findAttribute( "xml:lang" );
00096           if( !lang.empty() )
00097             m_subject[lang] = (*it)->cdata();
00098           else
00099             m_subject["default"] = (*it)->cdata();
00100         }
00101         else if( (*it)->name() == "thread" )
00102           m_thread = (*it)->cdata();
00103       }
00104     }
00105     else if( m_name == "presence" )
00106     {
00107       if( hasAttribute( "type", "subscribe" ) )
00108       {
00109         m_type = StanzaS10n;
00110         m_subtype = StanzaS10nSubscribe;
00111       }
00112       else if( hasAttribute( "type", "subscribed" ) )
00113       {
00114         m_type = StanzaS10n;
00115         m_subtype = StanzaS10nSubscribed;
00116       }
00117       else if( hasAttribute( "type", "unsubscribe" ) )
00118       {
00119         m_type = StanzaS10n;
00120         m_subtype = StanzaS10nUnsubscribe;
00121       }
00122       else if( hasAttribute( "type", "unsubscribed" ) )
00123       {
00124         m_type = StanzaS10n;
00125         m_subtype = StanzaS10nUnsubscribed;
00126       }
00127       else if( hasAttribute( "type", "unavailable" ) )
00128       {
00129         m_type = StanzaPresence;
00130         m_subtype = StanzaPresenceUnavailable;
00131       }
00132       else if( hasAttribute( "type", "probe" ) )
00133       {
00134         m_type = StanzaPresence;
00135         m_subtype = StanzaPresenceProbe;
00136       }
00137       else if( hasAttribute( "type", "error" ) )
00138       {
00139         m_type = StanzaPresence;
00140         m_subtype = StanzaPresenceError;
00141       }
00142       else if( !hasAttribute( "type" ) )
00143       {
00144         m_type = StanzaPresence;
00145         m_subtype = StanzaPresenceAvailable;
00146       }
00147       else
00148       {
00149         m_type = StanzaPresence;
00150         m_subtype = StanzaSubUndefined;
00151       }
00152     }
00153     else
00154     {
00155       m_type = StanzaUndefined;
00156       m_subtype = StanzaSubUndefined;
00157     }
00158 
00159     if( m_type == StanzaPresence )
00160     {
00161       if( !hasAttribute( "type" ) )
00162         m_show = PresenceAvailable;
00163 
00164       if( hasChildWithCData( "show", "chat" ) )
00165         m_show = PresenceChat;
00166       else if( hasChildWithCData( "show", "away" ) )
00167         m_show = PresenceAway;
00168       else if( hasChildWithCData( "show", "dnd" ) )
00169         m_show = PresenceDnd;
00170       else if( hasChildWithCData( "show", "xa" ) )
00171         m_show = PresenceXa;
00172       else if( hasAttribute( "type", "unavailable" ) )
00173         m_show = PresenceUnavailable;
00174 
00175       if( hasChild( "priority" ) )
00176         m_priority = atoi( findChild( "priority" )->cdata().c_str() );
00177     }
00178 
00179     if( m_type == StanzaPresence || m_type == StanzaS10n )
00180     {
00181       TagList& c = children();
00182       TagList::const_iterator it = c.begin();
00183       for( ; it != c.end(); ++it )
00184       {
00185         if( (*it)->name() == "status" )
00186         {
00187           const std::string lang = (*it)->findAttribute( "xml:lang" );
00188           if( !lang.empty() )
00189             m_status[lang] = (*it)->cdata();
00190           else
00191             m_status["default"] = (*it)->cdata();
00192         }
00193       }
00194     }
00195 
00196     m_xmllang = findAttribute( "xml:lang" );
00197 
00198     if( hasAttribute( "type", "error" ) && hasChild( "error" ) )
00199     {
00200       Tag *e = findChild( "error" );
00201 
00202       if( e->hasAttribute( "type", "cancel" ) )
00203         m_stanzaErrorType = StanzaErrorTypeCancel;
00204       else if( e->hasAttribute( "type", "continue" ) )
00205         m_stanzaErrorType = StanzaErrorTypeContinue;
00206       else if( e->hasAttribute( "type", "modify" ) )
00207         m_stanzaErrorType = StanzaErrorTypeModify;
00208       else if( e->hasAttribute( "type", "auth" ) )
00209         m_stanzaErrorType = StanzaErrorTypeAuth;
00210       else if( e->hasAttribute( "type", "wait" ) )
00211         m_stanzaErrorType = StanzaErrorTypeWait;
00212 
00213       TagList& c = e->children();
00214       TagList::const_iterator it = c.begin();
00215       for( ; it != c.end(); ++it )
00216       {
00217         if( (*it)->name() == "bad-request" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00218           m_stanzaError = StanzaErrorBadRequest;
00219         else if( (*it)->name() == "conflict"
00220                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00221           m_stanzaError = StanzaErrorConflict;
00222         else if( (*it)->name() == "feature-not-implemented"
00223                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00224           m_stanzaError = StanzaErrorFeatureNotImplemented;
00225         else if( (*it)->name() == "forbidden"
00226                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00227           m_stanzaError = StanzaErrorForbidden;
00228         else if( (*it)->name() == "gone"
00229                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00230           m_stanzaError = StanzaErrorGone;
00231         else if( (*it)->name() == "internal-server-error"
00232                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00233           m_stanzaError = StanzaErrorInternalServerError;
00234         else if( (*it)->name() == "item-not-found"
00235                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00236           m_stanzaError = StanzaErrorItemNotFound;
00237         else if( (*it)->name() == "jid-malformed"
00238                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00239           m_stanzaError = StanzaErrorJidMalformed;
00240         else if( (*it)->name() == "not-acceptable"
00241                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00242           m_stanzaError = StanzaErrorNotAcceptable;
00243         else if( (*it)->name() == "not-allowed"
00244                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00245           m_stanzaError = StanzaErrorNotAllowed;
00246         else if( (*it)->name() == "not-authorized"
00247                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00248           m_stanzaError = StanzaErrorNotAuthorized;
00249         else if( (*it)->name() == "recipient-unavailable"
00250                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00251           m_stanzaError = StanzaErrorRecipientUnavailable;
00252         else if( (*it)->name() == "redirect"
00253                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00254           m_stanzaError = StanzaErrorRedirect;
00255         else if( (*it)->name() == "registration-required"
00256                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00257           m_stanzaError = StanzaErrorRegistrationRequired;
00258         else if( (*it)->name() == "remote-server-not-found"
00259                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00260           m_stanzaError = StanzaErrorRemoteServerNotFound;
00261         else if( (*it)->name() == "remote-server-timeout"
00262                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00263           m_stanzaError = StanzaErrorRemoteServerTimeout;
00264         else if( (*it)->name() == "resource-constraint"
00265                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00266           m_stanzaError = StanzaErrorResourceConstraint;
00267         else if( (*it)->name() == "service-unavailable"
00268                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00269           m_stanzaError = StanzaErrorServiceUnavailable;
00270         else if( (*it)->name() == "subscription-required"
00271                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00272           m_stanzaError = StanzaErrorSubscribtionRequired;
00273         else if( (*it)->name() == "undefined-condition"
00274                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00275           m_stanzaError = StanzaErrorUndefinedCondition;
00276         else if( (*it)->name() == "unexpected-request"
00277                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00278           m_stanzaError = StanzaErrorUnexpectedRequest;
00279         else if( (*it)->name() == "text" )
00280         {
00281           const std::string lang = (*it)->findAttribute( "xml:lang" );
00282           if( !lang.empty() )
00283             m_errorText[lang] = (*it)->cdata();
00284           else
00285             m_errorText["default"] = (*it)->cdata();
00286         }
00287         else
00288           m_stanzaErrorAppCondition = (*it);
00289       }
00290     }
00291   }
00292 
00293   const std::string Stanza::body( const std::string& lang ) const
00294   {
00295     StringMap::const_iterator it = m_body.find( lang );
00296     if( it != m_body.end() )
00297       return (*it).second;
00298     else
00299       return "";
00300   }
00301 
00302   const std::string Stanza::subject( const std::string& lang ) const
00303   {
00304     StringMap::const_iterator it = m_subject.find( lang );
00305     if( it != m_subject.end() )
00306       return (*it).second;
00307     else
00308       return "";
00309   }
00310 
00311   const std::string Stanza::status( const std::string& lang ) const
00312   {
00313     StringMap::const_iterator it = m_status.find( lang );
00314     if( it != m_status.end() )
00315       return (*it).second;
00316     else
00317       return "";
00318   }
00319 
00320   const std::string Stanza::errorText( const std::string& lang ) const
00321   {
00322     StringMap::const_iterator it = m_errorText.find( lang );
00323     if( it != m_errorText.end() )
00324       return (*it).second;
00325     else
00326       return "";
00327   }
00328 
00329   Stanza* Stanza::clone()
00330   {
00331     Stanza *s = new Stanza( this );
00332     return s;
00333   }
00334 
00335   Stanza* Stanza::createIqStanza( const JID& to, const std::string& id,
00336                                   StanzaSubType subtype, const std::string& xmlns, Tag* tag )
00337   {
00338     Stanza *s = new Stanza( "iq" );
00339     switch( subtype )
00340     {
00341       case StanzaIqError:
00342         s->addAttribute( "type", "error" );
00343         break;
00344       case StanzaIqSet:
00345         s->addAttribute( "type", "set" );
00346         break;
00347       case StanzaIqResult:
00348         s->addAttribute( "type", "result" );
00349         break;
00350       case StanzaIqGet:
00351       default:
00352         s->addAttribute( "type", "get" );
00353         break;
00354     }
00355 
00356     if( !xmlns.empty() )
00357     {
00358       Tag *q = new Tag( s, "query" );
00359       q->addAttribute( "xmlns", xmlns );
00360       if( tag )
00361         q->addChild( tag );
00362     }
00363     s->addAttribute( "to", to.full() );
00364     s->addAttribute( "id", id );
00365 
00366     s->finalize();
00367 
00368     return s;
00369   }
00370 
00371   Stanza* Stanza::createPresenceStanza( const JID& to, const std::string& msg,
00372                                         Presence status, const std::string& xmllang )
00373   {
00374     Stanza *s = new Stanza( "presence" );
00375     switch( status )
00376     {
00377       case PresenceUnavailable:
00378         s->addAttribute( "type", "unavailable" );
00379         break;
00380       case PresenceChat:
00381         new Tag( s, "show", "chat" );
00382         break;
00383       case PresenceAway:
00384         new Tag( s, "show", "away" );
00385         break;
00386       case PresenceDnd:
00387         new Tag( s, "show", "dnd" );
00388         break;
00389       case PresenceXa:
00390         new Tag( s, "show", "xa" );
00391         break;
00392       default:
00393         break;
00394     }
00395 
00396     if( !to.empty() )
00397       s->addAttribute( "to", to.full() );
00398 
00399     if( !msg.empty() )
00400     {
00401       Tag *t = new Tag( s, "status", msg );
00402       t->addAttribute( "xml:lang", xmllang );
00403     }
00404 
00405     s->finalize();
00406 
00407     return s;
00408   }
00409 
00410   Stanza* Stanza::createMessageStanza( const JID& to, const std::string& body,
00411                                        StanzaSubType subtype, const std::string& subject,
00412                                        const std::string& thread, const std::string& xmllang )
00413   {
00414     Stanza *s = new Stanza( "message" );
00415     switch( subtype )
00416     {
00417       case StanzaMessageError:
00418         s->addAttribute( "type", "error" );
00419         break;
00420       case StanzaMessageNormal:
00421         s->addAttribute( "type", "normal" );
00422         break;
00423       case StanzaMessageHeadline:
00424         s->addAttribute( "type", "headline" );
00425         break;
00426       case StanzaMessageGroupchat:
00427         s->addAttribute( "type", "groupchat" );
00428         break;
00429       case StanzaMessageChat:
00430       default:
00431         s->addAttribute( "type", "chat" );
00432         break;
00433     }
00434 
00435     s->addAttribute( "to", to.full() );
00436 
00437     if( !body.empty() )
00438     {
00439       Tag *b = new Tag( s, "body", body );
00440       b->addAttribute( "xml:lang", xmllang );
00441     }
00442     if( !subject.empty() )
00443     {
00444       Tag *su = new Tag( s, "subject", subject );
00445       su->addAttribute( "xml:lang", xmllang );
00446     }
00447     if( !thread.empty() )
00448       new Tag( s, "thread", thread );
00449 
00450     s->finalize();
00451 
00452     return s;
00453   }
00454 
00455   Stanza* Stanza::createSubscriptionStanza( const JID& to, const std::string& msg,
00456                                             StanzaSubType subtype, const std::string& xmllang )
00457   {
00458     Stanza *s = new Stanza( "presence" );
00459     switch( subtype )
00460     {
00461       case StanzaS10nSubscribed:
00462         s->addAttribute( "type", "subscribed" );
00463         break;
00464       case StanzaS10nUnsubscribe:
00465         s->addAttribute( "type", "unsubscribe" );
00466         break;
00467       case StanzaS10nUnsubscribed:
00468         s->addAttribute( "type", "unsubscribed" );
00469         break;
00470       case StanzaS10nSubscribe:
00471       default:
00472         s->addAttribute( "type", "subscribe" );
00473         break;
00474     }
00475 
00476     s->addAttribute( "to", to.full() );
00477     if( !msg.empty() )
00478     {
00479       Tag *t = new Tag( s, "status", msg );
00480       t->addAttribute( "xml:lang", xmllang );
00481     }
00482 
00483     s->finalize();
00484 
00485     return s;
00486   }
00487 
00488 }

Generated on Wed Dec 20 18:25:29 2006 for gloox by  doxygen 1.5.1