stanza.cpp

00001 /*
00002   Copyright (c) 2005 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 )
00021     : Tag( name, cdata ), m_show( PRESENCE_UNKNOWN ),
00022       m_stanzaError( ST_ERROR_UNDEFINED ), m_stanzaErrorAppCondition( 0 ),
00023       m_xmllang( xmllang )
00024   {
00025   }
00026 
00027   Stanza::Stanza( Tag *tag )
00028     : Tag( tag->name(), tag->cdata() ), m_show( PRESENCE_UNKNOWN ),
00029       m_stanzaError( ST_ERROR_UNDEFINED ), m_stanzaErrorAppCondition( 0 ),
00030       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 = STANZA_IQ;
00052       if( hasAttribute( "type", "get" ) )
00053         m_subtype = STANZA_IQ_GET;
00054       else if( hasAttribute( "type", "set" ) )
00055         m_subtype = STANZA_IQ_SET;
00056       else if( hasAttribute( "type", "result" ) )
00057         m_subtype = STANZA_IQ_RESULT;
00058       else if( hasAttribute( "type", "error" ) )
00059         m_subtype = STANZA_IQ_ERROR;
00060       else
00061         m_subtype = STANZA_SUB_UNDEFINED;
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 = STANZA_MESSAGE;
00070       if( hasAttribute( "type", "chat" ) )
00071         m_subtype = STANZA_MESSAGE_CHAT;
00072       else if( hasAttribute( "type", "error" ) )
00073         m_subtype = STANZA_MESSAGE_ERROR;
00074       else if( hasAttribute( "type", "headline" ) )
00075         m_subtype = STANZA_MESSAGE_HEADLINE;
00076       else if( hasAttribute( "type", "groupchat" ) )
00077         m_subtype = STANZA_MESSAGE_GROUPCHAT;
00078       else if( hasAttribute( "type", "normal" ) )
00079         m_subtype = STANZA_MESSAGE_NORMAL;
00080       else
00081         m_subtype = STANZA_SUB_UNDEFINED;
00082 
00083       TagList& c = children();
00084       TagList::const_iterator it = c.begin();
00085       for( ; it != c.end(); ++it )
00086       {
00087         if( (*it)->name() == "body" )
00088         {
00089           const std::string lang = (*it)->findAttribute( "xml:lang" );
00090           if( !lang.empty() )
00091             m_body[lang] = (*it)->cdata();
00092           else
00093             m_body["default"] = (*it)->cdata();
00094         }
00095         else if( (*it)->name() == "subject" )
00096         {
00097           const std::string lang = (*it)->findAttribute( "xml:lang" );
00098           if( !lang.empty() )
00099             m_subject[lang] = (*it)->cdata();
00100           else
00101             m_subject["default"] = (*it)->cdata();
00102         }
00103         else if( (*it)->name() == "thread" )
00104           m_thread = (*it)->cdata();
00105       }
00106     }
00107     else if( m_name == "presence" )
00108     {
00109       if( hasAttribute( "type", "subscribe" ) )
00110       {
00111         m_type = STANZA_S10N;
00112         m_subtype = STANZA_S10N_SUBSCRIBE;
00113       }
00114       else if( hasAttribute( "type", "subscribed" ) )
00115       {
00116         m_type = STANZA_S10N;
00117         m_subtype = STANZA_S10N_SUBSCRIBED;
00118       }
00119       else if( hasAttribute( "type", "unsubscribe" ) )
00120       {
00121         m_type = STANZA_S10N;
00122         m_subtype = STANZA_S10N_UNSUBSCRIBE;
00123       }
00124       else if( hasAttribute( "type", "unsubscribed" ) )
00125       {
00126         m_type = STANZA_S10N;
00127         m_subtype = STANZA_S10N_UNSUBSCRIBED;
00128       }
00129       else if( hasAttribute( "type", "unavailable" ) )
00130       {
00131         m_type = STANZA_PRESENCE;
00132         m_subtype = STANZA_PRES_UNAVAILABLE;
00133       }
00134       else if( hasAttribute( "type", "probe" ) )
00135       {
00136         m_type = STANZA_PRESENCE;
00137         m_subtype = STANZA_PRES_PROBE;
00138       }
00139       else if( hasAttribute( "type", "error" ) )
00140       {
00141         m_type = STANZA_PRESENCE;
00142         m_subtype = STANZA_PRES_ERROR;
00143       }
00144       else if( !hasAttribute( "type" ) )
00145       {
00146         m_type = STANZA_PRESENCE;
00147         m_subtype = STANZA_PRES_AVAILABLE;
00148       }
00149       else
00150       {
00151         m_type = STANZA_PRESENCE;
00152         m_subtype = STANZA_SUB_UNDEFINED;
00153       }
00154     }
00155     else
00156     {
00157       m_type = STANZA_UNDEFINED;
00158       m_subtype = STANZA_SUB_UNDEFINED;
00159     }
00160 
00161     if( m_type == STANZA_PRESENCE )
00162     {
00163       if( !hasAttribute( "type" ) )
00164         m_show = PRESENCE_AVAILABLE;
00165 
00166       if( hasChildWithCData( "show", "chat" ) )
00167         m_show = PRESENCE_CHAT;
00168       else if( hasChildWithCData( "show", "away" ) )
00169         m_show = PRESENCE_AWAY;
00170       else if( hasChildWithCData( "show", "dnd" ) )
00171         m_show = PRESENCE_DND;
00172       else if( hasChildWithCData( "show", "xa" ) )
00173         m_show = PRESENCE_XA;
00174       else if( hasAttribute( "type", "unavailable" ) )
00175         m_show = PRESENCE_UNAVAILABLE;
00176 
00177       if( hasChild( "priority" ) )
00178         m_priority = atoi( findChild( "priority" )->cdata().c_str() );
00179     }
00180 
00181     if( m_type == STANZA_PRESENCE || m_type == STANZA_S10N )
00182     {
00183       TagList& c = children();
00184       TagList::const_iterator it = c.begin();
00185       for( ; it != c.end(); ++it )
00186       {
00187         if( (*it)->name() == "status" )
00188         {
00189           const std::string lang = (*it)->findAttribute( "xml:lang" );
00190           if( !lang.empty() )
00191             m_status[lang] = (*it)->cdata();
00192           else
00193             m_status["default"] = (*it)->cdata();
00194         }
00195       }
00196     }
00197 
00198     m_xmllang = findAttribute( "xml:lang" );
00199 
00200     if( hasAttribute( "type", "error" ) && hasChild( "error" ) )
00201     {
00202       Tag *e = findChild( "error" );
00203 
00204       if( e->hasAttribute( "type", "cancel" ) )
00205         m_stanzaErrorType = ST_TYPE_CANCEL;
00206       else if( e->hasAttribute( "type", "continue" ) )
00207         m_stanzaErrorType = ST_TYPE_CONTINUE;
00208       else if( e->hasAttribute( "type", "modify" ) )
00209         m_stanzaErrorType = ST_TYPE_MODIFY;
00210       else if( e->hasAttribute( "type", "auth" ) )
00211         m_stanzaErrorType = ST_TYPE_AUTH;
00212       else if( e->hasAttribute( "type", "wait" ) )
00213         m_stanzaErrorType = ST_TYPE_WAIT;
00214 
00215       TagList& c = e->children();
00216       TagList::const_iterator it = c.begin();
00217       for( ; it != c.end(); ++it )
00218       {
00219         if( (*it)->name() == "bad-request" && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00220           m_stanzaError = ST_ERROR_BAD_REQUEST;
00221         else if( (*it)->name() == "conflict"
00222                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00223           m_stanzaError = ST_ERROR_CONFLICT;
00224         else if( (*it)->name() == "feature-not-implemented"
00225                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00226           m_stanzaError = ST_ERROR_FEATURE_NOT_IMPLEMENTED;
00227         else if( (*it)->name() == "forbidden"
00228                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00229           m_stanzaError = ST_ERROR_FORBIDDEN;
00230         else if( (*it)->name() == "gone"
00231                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00232           m_stanzaError = ST_ERROR_GONE;
00233         else if( (*it)->name() == "internal-server-error"
00234                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00235           m_stanzaError = ST_ERROR_INTERNAL_SERVER_ERROR;
00236         else if( (*it)->name() == "item-not-found"
00237                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00238           m_stanzaError = ST_ERROR_ITEM_NOT_FOUND;
00239         else if( (*it)->name() == "jid-malformed"
00240                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00241           m_stanzaError = ST_ERROR_JID_MALFORMED;
00242         else if( (*it)->name() == "not-acceptable"
00243                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00244           m_stanzaError = ST_ERROR_NOT_ACCEPTABLE;
00245         else if( (*it)->name() == "not-allowed"
00246                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00247           m_stanzaError = ST_ERROR_NOT_ALLOWED;
00248         else if( (*it)->name() == "not-authorized"
00249                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00250           m_stanzaError = ST_ERROR_NOT_AUTHORIZED;
00251         else if( (*it)->name() == "recipient-unavailable"
00252                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00253           m_stanzaError = ST_ERROR_RECIPIENT_UNAVAILABLE;
00254         else if( (*it)->name() == "redirect"
00255                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00256           m_stanzaError = ST_ERROR_REDIRECT;
00257         else if( (*it)->name() == "registration-required"
00258                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00259           m_stanzaError = ST_ERROR_REGISTRATION_REQUIRED;
00260         else if( (*it)->name() == "remote-server-not-found"
00261                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00262           m_stanzaError = ST_ERROR_REMOTE_SERVER_NOT_FOUND;
00263         else if( (*it)->name() == "remote-server-timeout"
00264                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00265           m_stanzaError = ST_ERROR_REMOTE_SERVER_TIMEOUT;
00266         else if( (*it)->name() == "resource-constraint"
00267                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00268           m_stanzaError = ST_ERROR_RESOURCE_CONSTRAINT;
00269         else if( (*it)->name() == "service-unavailable"
00270                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00271           m_stanzaError = ST_ERROR_SERVICE_UNAVAILABLE;
00272         else if( (*it)->name() == "subscription-required"
00273                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00274           m_stanzaError = ST_ERROR_SUBSCRIBTION_REQUIRED;
00275         else if( (*it)->name() == "undefined-condition"
00276                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00277           m_stanzaError = ST_ERROR_UNDEFINED_CONDITION;
00278         else if( (*it)->name() == "unexpected-request"
00279                    && (*it)->hasAttribute( "xmlns", XMLNS_XMPP_STANZAS ) )
00280           m_stanzaError = ST_ERROR_UNEXPECTED_REQUEST;
00281         else if( (*it)->name() == "text" )
00282         {
00283           const std::string lang = (*it)->findAttribute( "xml:lang" );
00284           if( !lang.empty() )
00285             m_errorText[lang] = (*it)->cdata();
00286           else
00287             m_errorText["default"] = (*it)->cdata();
00288         }
00289         else
00290           m_stanzaErrorAppCondition = (*it);
00291       }
00292     }
00293   }
00294 
00295   const std::string Stanza::body( const std::string& lang ) const
00296   {
00297     StringMap::const_iterator it = m_body.find( lang );
00298     if( it != m_body.end() )
00299       return (*it).second;
00300     else
00301       return "";
00302   }
00303 
00304   const std::string Stanza::subject( const std::string& lang ) const
00305   {
00306     StringMap::const_iterator it = m_subject.find( lang );
00307     if( it != m_subject.end() )
00308       return (*it).second;
00309     else
00310       return "";
00311   }
00312 
00313   const std::string Stanza::status( const std::string& lang ) const
00314   {
00315     StringMap::const_iterator it = m_status.find( lang );
00316     if( it != m_status.end() )
00317       return (*it).second;
00318     else
00319       return "";
00320   }
00321 
00322   const std::string Stanza::errorText( const std::string& lang ) const
00323   {
00324     StringMap::const_iterator it = m_errorText.find( lang );
00325     if( it != m_errorText.end() )
00326       return (*it).second;
00327     else
00328       return "";
00329   }
00330 
00331   Stanza* Stanza::clone( bool )
00332   {
00333     Stanza *s = new Stanza( this );
00334     return s;
00335   }
00336 
00337   Stanza* Stanza::createIqStanza( const JID& to, const std::string& id,
00338                           StanzaSubType subtype, const std::string& xmlns, Tag* tag )
00339   {
00340     Stanza *s = new Stanza( "iq" );
00341     switch( subtype )
00342     {
00343       case STANZA_IQ_ERROR:
00344         s->addAttrib( "type", "error" );
00345         break;
00346       case STANZA_IQ_SET:
00347         s->addAttrib( "type", "set" );
00348         break;
00349       case STANZA_IQ_RESULT:
00350         s->addAttrib( "type", "result" );
00351         break;
00352       case STANZA_IQ_GET:
00353       default:
00354         s->addAttrib( "type", "get" );
00355         break;
00356     }
00357 
00358     if( !xmlns.empty() )
00359     {
00360       Tag *q = new Tag( s, "query" );
00361       q->addAttrib( "xmlns", xmlns );
00362       if( tag )
00363         q->addChild( tag );
00364     }
00365     s->addAttrib( "to", to.full() );
00366     s->addAttrib( "id", id );
00367 
00368     s->finalize();
00369 
00370     return s;
00371   }
00372 
00373   Stanza* Stanza::createPresenceStanza( const JID& to, const std::string& msg,
00374                                  PresenceStatus status, const std::string& xmllang )
00375   {
00376     Stanza *s = new Stanza( "presence" );
00377     switch( status )
00378     {
00379       case PRESENCE_UNAVAILABLE:
00380         s->addAttrib( "type", "unavailable" );
00381         break;
00382       case PRESENCE_CHAT:
00383         s->addChild( new Tag( "show", "chat" ) );
00384         break;
00385       case PRESENCE_AWAY:
00386         s->addChild( new Tag( "show", "away" ) );
00387         break;
00388       case PRESENCE_DND:
00389         s->addChild( new Tag( "show", "dnd" ) );
00390         break;
00391       case PRESENCE_XA:
00392         s->addChild( new Tag( "show", "xa" ) );
00393       default:
00394         break;
00395     }
00396 
00397     if( !to.empty() )
00398       s->addAttrib( "to", to.full() );
00399 
00400     if( !msg.empty() )
00401     {
00402       Tag *t = new Tag( s, "status", msg );
00403       t->addAttrib( "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 STANZA_MESSAGE_ERROR:
00419         s->addAttrib( "type", "error" );
00420         break;
00421       case STANZA_MESSAGE_NORMAL:
00422         s->addAttrib( "type", "normal" );
00423         break;
00424       case STANZA_MESSAGE_HEADLINE:
00425         s->addAttrib( "type", "headline" );
00426         break;
00427       case STANZA_MESSAGE_GROUPCHAT:
00428         s->addAttrib( "type", "groupchat" );
00429         break;
00430       case STANZA_MESSAGE_CHAT:
00431       default:
00432         s->addAttrib( "type", "chat" );
00433         break;
00434     }
00435 
00436     s->addAttrib( "to", to.full() );
00437 
00438     if( !body.empty() )
00439     {
00440       Tag *b = new Tag( s, "body", body );
00441       b->addAttrib( "xml:lang", xmllang );
00442     }
00443     if( !subject.empty() )
00444     {
00445       Tag *su = new Tag( s, "subject", subject );
00446       su->addAttrib( "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 STANZA_S10N_SUBSCRIBED:
00463         s->addAttrib( "type", "subscribed" );
00464         break;
00465       case STANZA_S10N_UNSUBSCRIBE:
00466         s->addAttrib( "type", "unsubscribe" );
00467         break;
00468       case STANZA_S10N_UNSUBSCRIBED:
00469         s->addAttrib( "type", "unsubscribed" );
00470         break;
00471       case STANZA_S10N_SUBSCRIBE:
00472       default:
00473         s->addAttrib( "type", "subscribe" );
00474         break;
00475     }
00476 
00477     s->addAttrib( "to", to.full() );
00478     if( !msg.empty() )
00479     {
00480       Tag *t = new Tag( s, "status", msg );
00481       t->addAttrib( "xml:lang", xmllang );
00482     }
00483 
00484     s->finalize();
00485 
00486     return s;
00487   }
00488 
00489 }

Generated on Mon Jan 16 16:19:54 2006 for gloox by  doxygen 1.4.6