QXmppPresence.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * Copyright (C) 2008-2012 The QXmpp developers
  3. *
  4. * Author:
  5. * Manjeet Dahiya
  6. *
  7. * Source:
  8. * http://code.google.com/p/qxmpp
  9. *
  10. * This file is a part of QXmpp library.
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation; either
  15. * version 2.1 of the License, or (at your option) any later version.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. */
  23. #include "QXmppPresence.h"
  24. #include "QXmppUtils.h"
  25. #include <QtDebug>
  26. #include <QDomElement>
  27. #include <QXmlStreamWriter>
  28. #include "QXmppConstants.h"
  29. static const char* presence_types[] = {
  30. "error",
  31. "",
  32. "unavailable",
  33. "subscribe",
  34. "subscribed",
  35. "unsubscribe",
  36. "unsubscribed",
  37. "probe"
  38. };
  39. static const char* presence_shows[] = {
  40. "",
  41. "away",
  42. "xa",
  43. "dnd",
  44. "chat",
  45. "invisible"
  46. };
  47. class QXmppPresencePrivate : public QSharedData
  48. {
  49. public:
  50. QXmppPresence::AvailableStatusType availableStatusType;
  51. QXmppPresence::Type type;
  52. QXmppPresence::Status status;
  53. /// XEP-0153: vCard-Based Avatars
  54. /// photoHash: the SHA1 hash of the avatar image data itself (not the base64-encoded version)
  55. /// in accordance with RFC 3174
  56. QByteArray photoHash;
  57. QXmppPresence::VCardUpdateType vCardUpdateType;
  58. // XEP-0115: Entity Capabilities
  59. QString capabilityHash;
  60. QString capabilityNode;
  61. QByteArray capabilityVer;
  62. // Legacy XEP-0115: Entity Capabilities
  63. QStringList capabilityExt;
  64. // XEP-0045: Multi-User Chat
  65. QXmppMucItem mucItem;
  66. QString mucPassword;
  67. QList<int> mucStatusCodes;
  68. bool mucSupported;
  69. };
  70. /// Constructs a QXmppPresence.
  71. ///
  72. /// \param type
  73. QXmppPresence::QXmppPresence(QXmppPresence::Type type)
  74. : d(new QXmppPresencePrivate)
  75. {
  76. d->type = type;
  77. d->mucSupported = false;
  78. d->vCardUpdateType = VCardUpdateNone;
  79. }
  80. /// Constructs a copy of \a other.
  81. QXmppPresence::QXmppPresence(const QXmppPresence &other)
  82. : QXmppStanza(other)
  83. , d(other.d)
  84. {
  85. }
  86. /// Destroys a QXmppPresence.
  87. QXmppPresence::~QXmppPresence()
  88. {
  89. }
  90. /// Assigns \a other to this presence.
  91. QXmppPresence &QXmppPresence::operator=(const QXmppPresence &other)
  92. {
  93. QXmppStanza::operator=(other);
  94. d = other.d;
  95. return *this;
  96. }
  97. /// Returns the availability status type, for instance busy or away.
  98. ///
  99. /// This will not tell you whether a contact is connected, check whether
  100. /// type() is QXmppPresence::Available instead.
  101. QXmppPresence::AvailableStatusType QXmppPresence::availableStatusType() const
  102. {
  103. return static_cast<QXmppPresence::AvailableStatusType>(d->status.type());
  104. }
  105. /// Sets the availability status type, for instance busy or away.
  106. void QXmppPresence::setAvailableStatusType(AvailableStatusType type)
  107. {
  108. d->status.setType(static_cast<QXmppPresence::Status::Type>(type));
  109. }
  110. /// Returns the priority level of the resource.
  111. int QXmppPresence::priority() const
  112. {
  113. return d->status.priority();
  114. }
  115. /// Sets the \a priority level of the resource.
  116. void QXmppPresence::setPriority(int priority)
  117. {
  118. d->status.setPriority(priority);
  119. }
  120. /// Returns the status text, a textual description of the user's status.
  121. QString QXmppPresence::statusText() const
  122. {
  123. return d->status.statusText();
  124. }
  125. /// Sets the status text, a textual description of the user's status.
  126. ///
  127. /// \param statusText The status text, for example "Gone fishing".
  128. void QXmppPresence::setStatusText(const QString& statusText)
  129. {
  130. d->status.setStatusText(statusText);
  131. }
  132. /// Returns the presence type.
  133. ///
  134. /// You can use this method to determine the action which needs to be
  135. /// taken in response to receiving the presence. For instance, if the type is
  136. /// QXmppPresence::Available or QXmppPresence::Unavailable, you could update
  137. /// the icon representing a contact's availability.
  138. QXmppPresence::Type QXmppPresence::type() const
  139. {
  140. return d->type;
  141. }
  142. /// Sets the presence type.
  143. ///
  144. /// \param type
  145. void QXmppPresence::setType(QXmppPresence::Type type)
  146. {
  147. d->type = type;
  148. }
  149. /// \cond
  150. void QXmppPresence::parse(const QDomElement &element)
  151. {
  152. QXmppStanza::parse(element);
  153. const QString type = element.attribute("type");
  154. for (int i = Error; i <= Probe; i++) {
  155. if (type == presence_types[i]) {
  156. d->type = static_cast<Type>(i);
  157. break;
  158. }
  159. }
  160. d->status.parse(element);
  161. QXmppElementList extensions;
  162. QDomElement xElement = element.firstChildElement();
  163. d->vCardUpdateType = VCardUpdateNone;
  164. while(!xElement.isNull())
  165. {
  166. // XEP-0045: Multi-User Chat
  167. if(xElement.namespaceURI() == ns_muc) {
  168. d->mucSupported = true;
  169. d->mucPassword = xElement.firstChildElement("password").text();
  170. }
  171. else if(xElement.namespaceURI() == ns_muc_user)
  172. {
  173. QDomElement itemElement = xElement.firstChildElement("item");
  174. d->mucItem.parse(itemElement);
  175. QDomElement statusElement = xElement.firstChildElement("status");
  176. d->mucStatusCodes.clear();
  177. while (!statusElement.isNull()) {
  178. d->mucStatusCodes << statusElement.attribute("code").toInt();
  179. statusElement = statusElement.nextSiblingElement("status");
  180. }
  181. }
  182. // XEP-0153: vCard-Based Avatars
  183. else if(xElement.namespaceURI() == ns_vcard_update)
  184. {
  185. QDomElement photoElement = xElement.firstChildElement("photo");
  186. if(!photoElement.isNull())
  187. {
  188. d->photoHash = QByteArray::fromHex(photoElement.text().toAscii());
  189. if(d->photoHash.isEmpty())
  190. d->vCardUpdateType = VCardUpdateNoPhoto;
  191. else
  192. d->vCardUpdateType = VCardUpdateValidPhoto;
  193. }
  194. else
  195. {
  196. d->photoHash = QByteArray();
  197. d->vCardUpdateType = VCardUpdateNotReady;
  198. }
  199. }
  200. // XEP-0115: Entity Capabilities
  201. else if(xElement.tagName() == "c" && xElement.namespaceURI() == ns_capabilities)
  202. {
  203. d->capabilityNode = xElement.attribute("node");
  204. d->capabilityVer = QByteArray::fromBase64(xElement.attribute("ver").toAscii());
  205. d->capabilityHash = xElement.attribute("hash");
  206. d->capabilityExt = xElement.attribute("ext").split(" ", QString::SkipEmptyParts);
  207. }
  208. else if (xElement.tagName() == "addresses")
  209. {
  210. }
  211. else if (xElement.tagName() == "error")
  212. {
  213. }
  214. else if (xElement.tagName() == "show")
  215. {
  216. }
  217. else if (xElement.tagName() == "status")
  218. {
  219. }
  220. else if (xElement.tagName() == "priority")
  221. {
  222. }
  223. else
  224. {
  225. // other extensions
  226. extensions << QXmppElement(xElement);
  227. }
  228. xElement = xElement.nextSiblingElement();
  229. }
  230. setExtensions(extensions);
  231. }
  232. void QXmppPresence::toXml(QXmlStreamWriter *xmlWriter) const
  233. {
  234. xmlWriter->writeStartElement("presence");
  235. helperToXmlAddAttribute(xmlWriter,"xml:lang", lang());
  236. helperToXmlAddAttribute(xmlWriter,"id", id());
  237. helperToXmlAddAttribute(xmlWriter,"to", to());
  238. helperToXmlAddAttribute(xmlWriter,"from", from());
  239. helperToXmlAddAttribute(xmlWriter,"type", presence_types[d->type]);
  240. d->status.toXml(xmlWriter);
  241. error().toXml(xmlWriter);
  242. // XEP-0045: Multi-User Chat
  243. if(d->mucSupported) {
  244. xmlWriter->writeStartElement("x");
  245. xmlWriter->writeAttribute("xmlns", ns_muc);
  246. if (!d->mucPassword.isEmpty())
  247. xmlWriter->writeTextElement("password", d->mucPassword);
  248. xmlWriter->writeEndElement();
  249. }
  250. if(!d->mucItem.isNull() || !d->mucStatusCodes.isEmpty())
  251. {
  252. xmlWriter->writeStartElement("x");
  253. xmlWriter->writeAttribute("xmlns", ns_muc_user);
  254. if (!d->mucItem.isNull())
  255. d->mucItem.toXml(xmlWriter);
  256. foreach (int code, d->mucStatusCodes) {
  257. xmlWriter->writeStartElement("status");
  258. xmlWriter->writeAttribute("code", QString::number(code));
  259. xmlWriter->writeEndElement();
  260. }
  261. xmlWriter->writeEndElement();
  262. }
  263. // XEP-0153: vCard-Based Avatars
  264. if(d->vCardUpdateType != VCardUpdateNone)
  265. {
  266. xmlWriter->writeStartElement("x");
  267. xmlWriter->writeAttribute("xmlns", ns_vcard_update);
  268. switch(d->vCardUpdateType)
  269. {
  270. case VCardUpdateNoPhoto:
  271. helperToXmlAddTextElement(xmlWriter, "photo", "");
  272. break;
  273. case VCardUpdateValidPhoto:
  274. helperToXmlAddTextElement(xmlWriter, "photo", d->photoHash.toHex());
  275. break;
  276. case VCardUpdateNotReady:
  277. break;
  278. default:
  279. break;
  280. }
  281. xmlWriter->writeEndElement();
  282. }
  283. if(!d->capabilityNode.isEmpty() && !d->capabilityVer.isEmpty()
  284. && !d->capabilityHash.isEmpty())
  285. {
  286. xmlWriter->writeStartElement("c");
  287. xmlWriter->writeAttribute("xmlns", ns_capabilities);
  288. helperToXmlAddAttribute(xmlWriter, "hash", d->capabilityHash);
  289. helperToXmlAddAttribute(xmlWriter, "node", d->capabilityNode);
  290. helperToXmlAddAttribute(xmlWriter, "ver", d->capabilityVer.toBase64());
  291. xmlWriter->writeEndElement();
  292. }
  293. // other extensions
  294. QXmppStanza::extensionsToXml(xmlWriter);
  295. xmlWriter->writeEndElement();
  296. }
  297. /// \endcond
  298. /// Returns the photo-hash of the VCardUpdate.
  299. ///
  300. /// \return QByteArray
  301. QByteArray QXmppPresence::photoHash() const
  302. {
  303. return d->photoHash;
  304. }
  305. /// Sets the photo-hash of the VCardUpdate.
  306. ///
  307. /// \param photoHash as QByteArray
  308. void QXmppPresence::setPhotoHash(const QByteArray& photoHash)
  309. {
  310. d->photoHash = photoHash;
  311. }
  312. /// Returns the type of VCardUpdate
  313. ///
  314. /// \return VCardUpdateType
  315. QXmppPresence::VCardUpdateType QXmppPresence::vCardUpdateType() const
  316. {
  317. return d->vCardUpdateType;
  318. }
  319. /// Sets the type of VCardUpdate
  320. ///
  321. /// \param type VCardUpdateType
  322. void QXmppPresence::setVCardUpdateType(VCardUpdateType type)
  323. {
  324. d->vCardUpdateType = type;
  325. }
  326. /// XEP-0115: Entity Capabilities
  327. QString QXmppPresence::capabilityHash() const
  328. {
  329. return d->capabilityHash;
  330. }
  331. /// XEP-0115: Entity Capabilities
  332. void QXmppPresence::setCapabilityHash(const QString& hash)
  333. {
  334. d->capabilityHash = hash;
  335. }
  336. /// XEP-0115: Entity Capabilities
  337. QString QXmppPresence::capabilityNode() const
  338. {
  339. return d->capabilityNode;
  340. }
  341. /// XEP-0115: Entity Capabilities
  342. void QXmppPresence::setCapabilityNode(const QString& node)
  343. {
  344. d->capabilityNode = node;
  345. }
  346. /// XEP-0115: Entity Capabilities
  347. QByteArray QXmppPresence::capabilityVer() const
  348. {
  349. return d->capabilityVer;
  350. }
  351. /// XEP-0115: Entity Capabilities
  352. void QXmppPresence::setCapabilityVer(const QByteArray& ver)
  353. {
  354. d->capabilityVer = ver;
  355. }
  356. /// Legacy XEP-0115: Entity Capabilities
  357. QStringList QXmppPresence::capabilityExt() const
  358. {
  359. return d->capabilityExt;
  360. }
  361. /// Returns the MUC item.
  362. QXmppMucItem QXmppPresence::mucItem() const
  363. {
  364. return d->mucItem;
  365. }
  366. /// Sets the MUC item.
  367. ///
  368. /// \param item
  369. void QXmppPresence::setMucItem(const QXmppMucItem &item)
  370. {
  371. d->mucItem = item;
  372. }
  373. /// Returns the password used to join a MUC room.
  374. QString QXmppPresence::mucPassword() const
  375. {
  376. return d->mucPassword;
  377. }
  378. /// Sets the password used to join a MUC room.
  379. void QXmppPresence::setMucPassword(const QString &password)
  380. {
  381. d->mucPassword = password;
  382. }
  383. /// Returns the MUC status codes.
  384. QList<int> QXmppPresence::mucStatusCodes() const
  385. {
  386. return d->mucStatusCodes;
  387. }
  388. /// Sets the MUC status codes.
  389. ///
  390. /// \param codes
  391. void QXmppPresence::setMucStatusCodes(const QList<int> &codes)
  392. {
  393. d->mucStatusCodes = codes;
  394. }
  395. /// Returns true if the sender has indicated MUC support.
  396. bool QXmppPresence::isMucSupported() const
  397. {
  398. return d->mucSupported;
  399. }
  400. /// Sets whether MUC is \a supported.
  401. void QXmppPresence::setMucSupported(bool supported)
  402. {
  403. d->mucSupported = supported;
  404. }
  405. /// \cond
  406. const QXmppPresence::Status& QXmppPresence::status() const
  407. {
  408. return d->status;
  409. }
  410. QXmppPresence::Status& QXmppPresence::status()
  411. {
  412. return d->status;
  413. }
  414. void QXmppPresence::setStatus(const QXmppPresence::Status& status)
  415. {
  416. d->status = status;
  417. }
  418. QXmppPresence::Status::Status(QXmppPresence::Status::Type type,
  419. const QString statusText, int priority) :
  420. m_type(type),
  421. m_statusText(statusText), m_priority(priority)
  422. {
  423. }
  424. QXmppPresence::Status::Type QXmppPresence::Status::type() const
  425. {
  426. return m_type;
  427. }
  428. void QXmppPresence::Status::setType(QXmppPresence::Status::Type type)
  429. {
  430. m_type = type;
  431. }
  432. QString QXmppPresence::Status::statusText() const
  433. {
  434. return m_statusText;
  435. }
  436. void QXmppPresence::Status::setStatusText(const QString& str)
  437. {
  438. m_statusText = str;
  439. }
  440. int QXmppPresence::Status::priority() const
  441. {
  442. return m_priority;
  443. }
  444. void QXmppPresence::Status::setPriority(int priority)
  445. {
  446. m_priority = priority;
  447. }
  448. void QXmppPresence::Status::parse(const QDomElement &element)
  449. {
  450. const QString show = element.firstChildElement("show").text();
  451. for (int i = Online; i <= Invisible; i++) {
  452. if (show == presence_shows[i]) {
  453. m_type = static_cast<Type>(i);
  454. break;
  455. }
  456. }
  457. m_statusText = element.firstChildElement("status").text();
  458. m_priority = element.firstChildElement("priority").text().toInt();
  459. }
  460. void QXmppPresence::Status::toXml(QXmlStreamWriter *xmlWriter) const
  461. {
  462. const QString show = presence_shows[m_type];
  463. if (!show.isEmpty())
  464. helperToXmlAddTextElement(xmlWriter, "show", show);
  465. if (!m_statusText.isEmpty())
  466. helperToXmlAddTextElement(xmlWriter, "status", m_statusText);
  467. if (m_priority != 0)
  468. helperToXmlAddTextElement(xmlWriter, "priority", QString::number(m_priority));
  469. }
  470. /// \endcond