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