QXmppStanza.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /*
  2. * Copyright (C) 2008-2012 The QXmpp developers
  3. *
  4. * Authors:
  5. * Manjeet Dahiya
  6. * Jeremy Lainé
  7. * Georg Rudoy
  8. *
  9. * Source:
  10. * http://code.google.com/p/qxmpp
  11. *
  12. * This file is a part of QXmpp library.
  13. *
  14. * This library is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU Lesser General Public
  16. * License as published by the Free Software Foundation; either
  17. * version 2.1 of the License, or (at your option) any later version.
  18. *
  19. * This library is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22. * Lesser General Public License for more details.
  23. *
  24. */
  25. #include "QXmppStanza.h"
  26. #include "QXmppUtils.h"
  27. #include "QXmppConstants.h"
  28. #include <QDomElement>
  29. #include <QXmlStreamWriter>
  30. uint QXmppStanza::s_uniqeIdNo = 0;
  31. class QXmppExtendedAddressPrivate : public QSharedData
  32. {
  33. public:
  34. bool delivered;
  35. QString description;
  36. QString jid;
  37. QString type;
  38. };
  39. /// Constructs an empty extended address.
  40. QXmppExtendedAddress::QXmppExtendedAddress()
  41. : d(new QXmppExtendedAddressPrivate())
  42. {
  43. d->delivered = false;
  44. }
  45. /// Constructs a copy of other.
  46. ///
  47. /// \param other
  48. ///
  49. QXmppExtendedAddress::QXmppExtendedAddress(const QXmppExtendedAddress &other)
  50. : d(other.d)
  51. {
  52. }
  53. QXmppExtendedAddress::~QXmppExtendedAddress()
  54. {
  55. }
  56. /// Assigns the other address to this one.
  57. ///
  58. /// \param other
  59. ///
  60. QXmppExtendedAddress& QXmppExtendedAddress::operator=(const QXmppExtendedAddress& other)
  61. {
  62. d = other.d;
  63. return *this;
  64. }
  65. /// Returns the human-readable description of the address.
  66. QString QXmppExtendedAddress::description() const
  67. {
  68. return d->description;
  69. }
  70. /// Sets the human-readable \a description of the address.
  71. void QXmppExtendedAddress::setDescription(const QString &description)
  72. {
  73. d->description = description;
  74. }
  75. /// Returns the JID of the address.
  76. QString QXmppExtendedAddress::jid() const
  77. {
  78. return d->jid;
  79. }
  80. /// Sets the JID of the address.
  81. void QXmppExtendedAddress::setJid(const QString &jid)
  82. {
  83. d->jid = jid;
  84. }
  85. /// Returns the type of the address.
  86. QString QXmppExtendedAddress::type() const
  87. {
  88. return d->type;
  89. }
  90. /// Sets the \a type of the address.
  91. void QXmppExtendedAddress::setType(const QString &type)
  92. {
  93. d->type = type;
  94. }
  95. /// Returns whether the stanza has been delivered to this address.
  96. bool QXmppExtendedAddress::isDelivered() const
  97. {
  98. return d->delivered;
  99. }
  100. /// Sets whether the stanza has been \a delivered to this address.
  101. void QXmppExtendedAddress::setDelivered(bool delivered)
  102. {
  103. d->delivered = delivered;
  104. }
  105. /// Checks whether this address is valid. The extended address is considered
  106. /// to be valid if at least type and JID fields are non-empty.
  107. bool QXmppExtendedAddress::isValid() const
  108. {
  109. return !d->type.isEmpty() && !d->jid.isEmpty();
  110. }
  111. /// \cond
  112. void QXmppExtendedAddress::parse(const QDomElement &element)
  113. {
  114. d->delivered = element.attribute("delivered") == "true";
  115. d->description = element.attribute("desc");
  116. d->jid = element.attribute("jid");
  117. d->type = element.attribute("type");
  118. }
  119. void QXmppExtendedAddress::toXml(QXmlStreamWriter *xmlWriter) const
  120. {
  121. xmlWriter->writeStartElement("address");
  122. if (d->delivered)
  123. xmlWriter->writeAttribute("delivered", "true");
  124. if (!d->description.isEmpty())
  125. xmlWriter->writeAttribute("desc", d->description);
  126. xmlWriter->writeAttribute("jid", d->jid);
  127. xmlWriter->writeAttribute("type", d->type);
  128. xmlWriter->writeEndElement();
  129. }
  130. /// \endcond
  131. QXmppStanza::Error::Error():
  132. m_code(0),
  133. m_type(static_cast<QXmppStanza::Error::Type>(-1)),
  134. m_condition(static_cast<QXmppStanza::Error::Condition>(-1))
  135. {
  136. }
  137. QXmppStanza::Error::Error(Type type, Condition cond, const QString& text):
  138. m_code(0),
  139. m_type(type),
  140. m_condition(cond),
  141. m_text(text)
  142. {
  143. }
  144. QXmppStanza::Error::Error(const QString& type, const QString& cond,
  145. const QString& text):
  146. m_code(0),
  147. m_text(text)
  148. {
  149. setTypeFromStr(type);
  150. setConditionFromStr(cond);
  151. }
  152. QString QXmppStanza::Error::text() const
  153. {
  154. return m_text;
  155. }
  156. void QXmppStanza::Error::setText(const QString& text)
  157. {
  158. m_text = text;
  159. }
  160. int QXmppStanza::Error::code() const
  161. {
  162. return m_code;
  163. }
  164. void QXmppStanza::Error::setCode(int code)
  165. {
  166. m_code = code;
  167. }
  168. QXmppStanza::Error::Condition QXmppStanza::Error::condition() const
  169. {
  170. return m_condition;
  171. }
  172. void QXmppStanza::Error::setCondition(QXmppStanza::Error::Condition cond)
  173. {
  174. m_condition = cond;
  175. }
  176. QXmppStanza::Error::Type QXmppStanza::Error::type() const
  177. {
  178. return m_type;
  179. }
  180. void QXmppStanza::Error::setType(QXmppStanza::Error::Type type)
  181. {
  182. m_type = type;
  183. }
  184. /// \cond
  185. QString QXmppStanza::Error::getTypeStr() const
  186. {
  187. switch(m_type)
  188. {
  189. case Cancel:
  190. return "cancel";
  191. case Continue:
  192. return "continue";
  193. case Modify:
  194. return "modify";
  195. case Auth:
  196. return "auth";
  197. case Wait:
  198. return "wait";
  199. default:
  200. return "";
  201. }
  202. }
  203. QString QXmppStanza::Error::getConditionStr() const
  204. {
  205. switch(m_condition)
  206. {
  207. case BadRequest:
  208. return "bad-request";
  209. case Conflict:
  210. return "conflict";
  211. case FeatureNotImplemented:
  212. return "feature-not-implemented";
  213. case Forbidden:
  214. return "forbidden";
  215. case Gone:
  216. return "gone";
  217. case InternalServerError:
  218. return "internal-server-error";
  219. case ItemNotFound:
  220. return "item-not-found";
  221. case JidMalformed:
  222. return "jid-malformed";
  223. case NotAcceptable:
  224. return "not-acceptable";
  225. case NotAllowed:
  226. return "not-allowed";
  227. case NotAuthorized:
  228. return "not-authorized";
  229. case PaymentRequired:
  230. return "payment-required";
  231. case RecipientUnavailable:
  232. return "recipient-unavailable";
  233. case Redirect:
  234. return "redirect";
  235. case RegistrationRequired:
  236. return "registration-required";
  237. case RemoteServerNotFound:
  238. return "remote-server-not-found";
  239. case RemoteServerTimeout:
  240. return "remote-server-timeout";
  241. case ResourceConstraint:
  242. return "resource-constraint";
  243. case ServiceUnavailable:
  244. return "service-unavailable";
  245. case SubscriptionRequired:
  246. return "subscription-required";
  247. case UndefinedCondition:
  248. return "undefined-condition";
  249. case UnexpectedRequest:
  250. return "unexpected-request";
  251. default:
  252. return "";
  253. }
  254. }
  255. void QXmppStanza::Error::setTypeFromStr(const QString& type)
  256. {
  257. if(type == "cancel")
  258. setType(Cancel);
  259. else if(type == "continue")
  260. setType(Continue);
  261. else if(type == "modify")
  262. setType(Modify);
  263. else if(type == "auth")
  264. setType(Auth);
  265. else if(type == "wait")
  266. setType(Wait);
  267. else
  268. setType(static_cast<QXmppStanza::Error::Type>(-1));
  269. }
  270. void QXmppStanza::Error::setConditionFromStr(const QString& type)
  271. {
  272. if(type == "bad-request")
  273. setCondition(BadRequest);
  274. else if(type == "conflict")
  275. setCondition(Conflict);
  276. else if(type == "feature-not-implemented")
  277. setCondition(FeatureNotImplemented);
  278. else if(type == "forbidden")
  279. setCondition(Forbidden);
  280. else if(type == "gone")
  281. setCondition(Gone);
  282. else if(type == "internal-server-error")
  283. setCondition(InternalServerError);
  284. else if(type == "item-not-found")
  285. setCondition(ItemNotFound);
  286. else if(type == "jid-malformed")
  287. setCondition(JidMalformed);
  288. else if(type == "not-acceptable")
  289. setCondition(NotAcceptable);
  290. else if(type == "not-allowed")
  291. setCondition(NotAllowed);
  292. else if(type == "not-authorized")
  293. setCondition(NotAuthorized);
  294. else if(type == "payment-required")
  295. setCondition(PaymentRequired);
  296. else if(type == "recipient-unavailable")
  297. setCondition(RecipientUnavailable);
  298. else if(type == "redirect")
  299. setCondition(Redirect);
  300. else if(type == "registration-required")
  301. setCondition(RegistrationRequired);
  302. else if(type == "remote-server-not-found")
  303. setCondition(RemoteServerNotFound);
  304. else if(type == "remote-server-timeout")
  305. setCondition(RemoteServerTimeout);
  306. else if(type == "resource-constraint")
  307. setCondition(ResourceConstraint);
  308. else if(type == "service-unavailable")
  309. setCondition(ServiceUnavailable);
  310. else if(type == "subscription-required")
  311. setCondition(SubscriptionRequired);
  312. else if(type == "undefined-condition")
  313. setCondition(UndefinedCondition);
  314. else if(type == "unexpected-request")
  315. setCondition(UnexpectedRequest);
  316. else
  317. setCondition(static_cast<QXmppStanza::Error::Condition>(-1));
  318. }
  319. void QXmppStanza::Error::parse(const QDomElement &errorElement)
  320. {
  321. setCode(errorElement.attribute("code").toInt());
  322. setTypeFromStr(errorElement.attribute("type"));
  323. QString text;
  324. QString cond;
  325. QDomElement element = errorElement.firstChildElement();
  326. while(!element.isNull())
  327. {
  328. if(element.tagName() == "text")
  329. text = element.text();
  330. else if(element.namespaceURI() == ns_stanza)
  331. {
  332. cond = element.tagName();
  333. }
  334. element = element.nextSiblingElement();
  335. }
  336. setConditionFromStr(cond);
  337. setText(text);
  338. }
  339. void QXmppStanza::Error::toXml( QXmlStreamWriter *writer ) const
  340. {
  341. QString cond = getConditionStr();
  342. QString type = getTypeStr();
  343. if(cond.isEmpty() && type.isEmpty())
  344. return;
  345. writer->writeStartElement("error");
  346. helperToXmlAddAttribute(writer, "type", type);
  347. if (m_code > 0)
  348. helperToXmlAddAttribute(writer, "code", QString::number(m_code));
  349. if(!cond.isEmpty())
  350. {
  351. writer->writeStartElement(cond);
  352. writer->writeAttribute("xmlns", ns_stanza);
  353. writer->writeEndElement();
  354. }
  355. if(!m_text.isEmpty())
  356. {
  357. writer->writeStartElement("text");
  358. writer->writeAttribute("xml:lang", "en");
  359. writer->writeAttribute("xmlns", ns_stanza);
  360. writer->writeCharacters(m_text);
  361. writer->writeEndElement();
  362. }
  363. writer->writeEndElement();
  364. }
  365. /// \endcond
  366. class QXmppStanzaPrivate : public QSharedData
  367. {
  368. public:
  369. QString to;
  370. QString from;
  371. QString id;
  372. QString lang;
  373. QXmppStanza::Error error;
  374. QXmppElementList extensions;
  375. QList<QXmppExtendedAddress> extendedAddresses;
  376. };
  377. /// Constructs a QXmppStanza with the specified sender and recipient.
  378. ///
  379. /// \param from
  380. /// \param to
  381. QXmppStanza::QXmppStanza(const QString& from, const QString& to)
  382. : d(new QXmppStanzaPrivate)
  383. {
  384. d->to = to;
  385. d->from = from;
  386. }
  387. /// Constructs a copy of \a other.
  388. QXmppStanza::QXmppStanza(const QXmppStanza &other)
  389. : d(other.d)
  390. {
  391. }
  392. /// Destroys a QXmppStanza.
  393. QXmppStanza::~QXmppStanza()
  394. {
  395. }
  396. /// Assigns \a other to this stanza.
  397. QXmppStanza& QXmppStanza::operator=(const QXmppStanza &other)
  398. {
  399. d = other.d;
  400. return *this;
  401. }
  402. /// Returns the stanza's recipient JID.
  403. ///
  404. QString QXmppStanza::to() const
  405. {
  406. return d->to;
  407. }
  408. /// Sets the stanza's recipient JID.
  409. ///
  410. /// \param to
  411. void QXmppStanza::setTo(const QString& to)
  412. {
  413. d->to = to;
  414. }
  415. /// Returns the stanza's sender JID.
  416. QString QXmppStanza::from() const
  417. {
  418. return d->from;
  419. }
  420. /// Sets the stanza's sender JID.
  421. ///
  422. /// \param from
  423. void QXmppStanza::setFrom(const QString& from)
  424. {
  425. d->from = from;
  426. }
  427. /// Returns the stanza's identifier.
  428. QString QXmppStanza::id() const
  429. {
  430. return d->id;
  431. }
  432. /// Sets the stanza's identifier.
  433. ///
  434. /// \param id
  435. void QXmppStanza::setId(const QString& id)
  436. {
  437. d->id = id;
  438. }
  439. /// Returns the stanza's language.
  440. QString QXmppStanza::lang() const
  441. {
  442. return d->lang;
  443. }
  444. /// Sets the stanza's language.
  445. ///
  446. /// \param lang
  447. void QXmppStanza::setLang(const QString& lang)
  448. {
  449. d->lang = lang;
  450. }
  451. /// Returns the stanza's error.
  452. QXmppStanza::Error QXmppStanza::error() const
  453. {
  454. return d->error;
  455. }
  456. /// Sets the stanza's error.
  457. ///
  458. /// \param error
  459. void QXmppStanza::setError(const QXmppStanza::Error& error)
  460. {
  461. d->error = error;
  462. }
  463. /// Returns the stanza's "extensions".
  464. ///
  465. /// Extensions are XML elements which are not handled internally by QXmpp.
  466. QXmppElementList QXmppStanza::extensions() const
  467. {
  468. return d->extensions;
  469. }
  470. /// Sets the stanza's "extensions".
  471. ///
  472. /// \param extensions
  473. void QXmppStanza::setExtensions(const QXmppElementList &extensions)
  474. {
  475. d->extensions = extensions;
  476. }
  477. /// Returns the stanza's extended addresses as defined by
  478. /// XEP-0033: Extended Stanza Addressing.
  479. QList<QXmppExtendedAddress> QXmppStanza::extendedAddresses() const
  480. {
  481. return d->extendedAddresses;
  482. }
  483. /// Sets the stanza's extended addresses as defined by
  484. /// XEP-0033: Extended Stanza Addressing.
  485. void QXmppStanza::setExtendedAddresses(const QList<QXmppExtendedAddress> &addresses)
  486. {
  487. d->extendedAddresses = addresses;
  488. }
  489. /// \cond
  490. void QXmppStanza::generateAndSetNextId()
  491. {
  492. // get back
  493. ++s_uniqeIdNo;
  494. d->id = "qxmpp" + QString::number(s_uniqeIdNo);
  495. }
  496. void QXmppStanza::parse(const QDomElement &element)
  497. {
  498. d->from = element.attribute("from");
  499. d->to = element.attribute("to");
  500. d->id = element.attribute("id");
  501. d->lang = element.attribute("lang");
  502. QDomElement errorElement = element.firstChildElement("error");
  503. if(!errorElement.isNull())
  504. d->error.parse(errorElement);
  505. // XEP-0033: Extended Stanza Addressing
  506. QDomElement addressElement = element.firstChildElement("addresses").firstChildElement("address");
  507. while (!addressElement.isNull()) {
  508. QXmppExtendedAddress address;
  509. address.parse(addressElement);
  510. if (address.isValid())
  511. d->extendedAddresses << address;
  512. addressElement = addressElement.nextSiblingElement("address");
  513. }
  514. }
  515. void QXmppStanza::extensionsToXml(QXmlStreamWriter *xmlWriter) const
  516. {
  517. // XEP-0033: Extended Stanza Addressing
  518. if (!d->extendedAddresses.isEmpty()) {
  519. xmlWriter->writeStartElement("addresses");
  520. xmlWriter->writeAttribute("xmlns", ns_extended_addressing);
  521. foreach (const QXmppExtendedAddress &address, d->extendedAddresses)
  522. address.toXml(xmlWriter);
  523. xmlWriter->writeEndElement();
  524. }
  525. // other extensions
  526. foreach (const QXmppElement &extension, d->extensions)
  527. extension.toXml(xmlWriter);
  528. }
  529. /// \endcond