00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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 }