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, 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 }