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

Generated on Tue May 1 14:20:20 2007 for gloox by  doxygen 1.5.1