File indexing completed on 2024-06-02 04:07:09

0001 /*
0002  * types.cpp - IM data types
0003  * Copyright (C) 2003  Justin Karneges
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * either version 2
0009    of the License, or (at your option) any later version.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library; if not, write to the Free Software
0018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0019  *
0020  */
0021 
0022 #include "im.h"
0023 #include "protocol.h"
0024 #include "xmpp_features.h"
0025 
0026 #include <QMap>
0027 #include <QApplication>
0028 //Added by qt3to4:
0029 #include <QList>
0030 
0031 #include "xmpp_xmlcommon.h"
0032 #define NS_XML     "http://www.w3.org/XML/1998/namespace"
0033 
0034 namespace XMPP
0035 {
0036 
0037 //----------------------------------------------------------------------------
0038 // Url
0039 //----------------------------------------------------------------------------
0040 class Url::Private
0041 {
0042 public:
0043     QString url;
0044     QString desc;
0045 };
0046 
0047 //! \brief Construct Url object with a given URL and Description.
0048 //!
0049 //! This function will construct a Url object.
0050 //! \param QString - url (default: empty string)
0051 //! \param QString - description of url (default: empty string)
0052 //! \sa setUrl() setDesc()
0053 Url::Url(const QString &url, const QString &desc)
0054 {
0055     d = new Private;
0056     d->url = url;
0057     d->desc = desc;
0058 }
0059 
0060 //! \brief Construct Url object.
0061 //!
0062 //! Overloaded constructor which will constructs a exact copy of the Url object that was passed to the constructor.
0063 //! \param Url - Url Object
0064 Url::Url(const Url &from)
0065 {
0066     d = new Private;
0067     *this = from;
0068 }
0069 
0070 //! \brief operator overloader needed for d pointer (Internel).
0071 Url & Url::operator=(const Url &from)
0072 {
0073     *d = *from.d;
0074     return *this;
0075 }
0076 
0077 //! \brief destroy Url object.
0078 Url::~Url()
0079 {
0080     delete d;
0081 }
0082 
0083 //! \brief Get url information.
0084 //!
0085 //! Returns url information.
0086 QString Url::url() const
0087 {
0088     return d->url;
0089 }
0090 
0091 //! \brief Get Description information.
0092 //!
0093 //! Returns desction of the URL.
0094 QString Url::desc() const
0095 {
0096     return d->desc;
0097 }
0098 
0099 //! \brief Set Url information.
0100 //!
0101 //! Set url information.
0102 //! \param url - url string (eg: http://psi.affinix.com/)
0103 void Url::setUrl(const QString &url)
0104 {
0105     d->url = url;
0106 }
0107 
0108 //! \brief Set Description information.
0109 //!
0110 //! Set description of the url.
0111 //! \param desc - description of url
0112 void Url::setDesc(const QString &desc)
0113 {
0114     d->desc = desc;
0115 }
0116 
0117  //----------------------------------------------------------------------------
0118 // Address
0119 //----------------------------------------------------------------------------
0120 
0121 //! \brief Construct Address object with a given Type and Jid.
0122 //!
0123 //! This function will construct a Address object.
0124 //! \param Type - type (default: Unknown)
0125 //! \param Jid - specify address (default: empty string)
0126 //! \sa setType() setJid()
0127 Address::Address(Type type, const Jid & jid)
0128 : v_delivered(false)
0129 {
0130     v_type = type;
0131     v_jid = jid;
0132     v_delivered = false;
0133 }
0134 
0135 Address::Address(const QDomElement& e)
0136 : v_delivered(false)
0137 {
0138     fromXml(e);
0139 }
0140 
0141 void Address::fromXml(const QDomElement& t)
0142 {
0143     setJid(t.attribute("jid"));
0144     setUri(t.attribute("uri"));
0145     setNode(t.attribute("node"));
0146     setDesc(t.attribute("desc"));
0147     setDelivered(t.attribute("delivered") == "true");
0148     QString type = t.attribute("type");
0149     if (type == "to")
0150         setType(To);
0151     else if (type == "cc")
0152         setType(Cc);
0153     else if (type == "bcc")
0154         setType(Bcc);
0155     else if (type == "replyto")
0156         setType(ReplyTo);
0157     else if (type == "replyroom")
0158         setType(ReplyRoom);
0159     else if (type == "noreply")
0160         setType(NoReply);
0161     else if (type == "ofrom")
0162         setType(OriginalFrom);
0163     else if (type == "oto")
0164         setType(OriginalTo);
0165 }
0166 
0167 QDomElement Address::toXml(Stanza& s) const
0168 {
0169     QDomElement e = s.createElement("http://jabber.org/protocol/address", "address");
0170     if(!jid().isEmpty())
0171         e.setAttribute("jid", jid().full());
0172     if(!uri().isEmpty())
0173         e.setAttribute("uri", uri());
0174     if(!node().isEmpty())
0175         e.setAttribute("node", node());
0176     if(!desc().isEmpty())
0177         e.setAttribute("desc", desc());
0178     if(delivered())
0179         e.setAttribute("delivered", "true");
0180     switch (type()) {
0181         case To:
0182             e.setAttribute("type", "to");
0183             break;
0184         case Cc:
0185             e.setAttribute("type", "cc");
0186             break;
0187         case Bcc:
0188             e.setAttribute("type", "bcc");
0189             break;
0190         case ReplyTo: 
0191             e.setAttribute("type", "replyto");
0192             break;
0193         case ReplyRoom: 
0194             e.setAttribute("type", "replyroom");
0195             break;
0196         case NoReply: 
0197             e.setAttribute("type", "noreply");
0198             break;
0199         case OriginalFrom:
0200             e.setAttribute("type", "ofrom");
0201             break;
0202         case OriginalTo: 
0203             e.setAttribute("type", "oto");
0204             break;
0205         case Unknown:
0206             // Add nothing
0207             break;
0208     }
0209     return e;
0210 }
0211 
0212 //! \brief Get Jid information.
0213 //!
0214 //! Returns jid information.
0215 const Jid& Address::jid() const
0216 {
0217     return v_jid;
0218 }
0219 
0220 //! \brief Get Uri information.
0221 //!
0222 //! Returns desction of the Address.
0223 const QString& Address::uri() const
0224 {
0225     return v_uri;
0226 }
0227 
0228 //! \brief Get Node information.
0229 //!
0230 //! Returns node of the Address.
0231 const QString& Address::node() const
0232 {
0233     return v_node;
0234 }
0235 
0236 //! \brief Get Description information.
0237 //!
0238 //! Returns desction of the Address.
0239 const QString& Address::desc() const
0240 {
0241     return v_desc;
0242 }
0243 
0244 //! \brief Get Delivered information.
0245 //!
0246 //! Returns delivered of the Address.
0247 bool Address::delivered() const
0248 {
0249     return v_delivered;
0250 }
0251 
0252 //! \brief Get Type information.
0253 //!
0254 //! Returns type of the Address.
0255 Address::Type Address::type() const
0256 {
0257     return v_type;
0258 }
0259 
0260 //! \brief Set Address information.
0261 //!
0262 //! Set jid information.
0263 //! \param jid - jid
0264 void Address::setJid(const Jid &jid)
0265 {
0266     v_jid = jid;
0267 }
0268 
0269 //! \brief Set Address information.
0270 //!
0271 //! Set uri information.
0272 //! \param uri - url string (eg: http://psi.affinix.com/)
0273 void Address::setUri(const QString &uri)
0274 {
0275     v_uri = uri;
0276 }
0277 
0278 //! \brief Set Node information.
0279 //!
0280 //! Set node information.
0281 //! \param node - node string
0282 void Address::setNode(const QString &node)
0283 {
0284     v_node = node;
0285 }
0286 
0287 //! \brief Set Description information.
0288 //!
0289 //! Set description of the url.
0290 //! \param desc - description of url
0291 void Address::setDesc(const QString &desc)
0292 {
0293     v_desc = desc;
0294 }
0295 
0296 //! \brief Set delivered information.
0297 //!
0298 //! Set delivered information.
0299 //! \param delivered - delivered flag
0300 void Address::setDelivered(bool delivered)
0301 {
0302     v_delivered = delivered;
0303 }
0304 
0305 //! \brief Set Type information.
0306 //!
0307 //! Set type information.
0308 //! \param type - type
0309 void Address::setType(Type type)
0310 {
0311     v_type = type;
0312 }
0313 
0314 //----------------------------------------------------------------------------
0315 // RosterExchangeItem
0316 //----------------------------------------------------------------------------
0317 
0318 RosterExchangeItem::RosterExchangeItem(const Jid& jid, const QString& name, const QStringList& groups, Action action) : jid_(jid), name_(name), groups_(groups), action_(action)
0319 {
0320 }
0321 
0322 RosterExchangeItem::RosterExchangeItem(const QDomElement& el) : action_(Add)
0323 {
0324     fromXml(el);
0325 }
0326 
0327 const Jid& RosterExchangeItem::jid() const
0328 {
0329     return jid_;
0330 }
0331 
0332 RosterExchangeItem::Action RosterExchangeItem::action() const
0333 {
0334     return action_;
0335 }
0336 
0337 const QString& RosterExchangeItem::name() const
0338 {
0339     return name_;
0340 }
0341 
0342 const QStringList& RosterExchangeItem::groups() const
0343 {
0344     return groups_;
0345 }
0346 
0347 bool RosterExchangeItem::isNull() const
0348 {
0349     return jid_.isEmpty();
0350 }
0351 
0352 void RosterExchangeItem::setJid(const Jid& jid)
0353 {
0354     jid_ = jid;
0355 }
0356 
0357 void RosterExchangeItem::setAction(Action action)
0358 {
0359     action_ = action;
0360 }
0361 
0362 void RosterExchangeItem::setName(const QString& name)
0363 {
0364     name_ = name;
0365 }
0366 
0367 void RosterExchangeItem::setGroups(const QStringList& groups)
0368 {
0369     groups_ = groups;
0370 }
0371 
0372 QDomElement RosterExchangeItem::toXml(Stanza& s) const
0373 {
0374     QDomElement e = s.createElement("http://jabber.org/protocol/rosterx", "item");
0375     e.setAttribute("jid", jid().full());
0376     if (!name().isEmpty())
0377         e.setAttribute("name", name());
0378     switch(action()) {
0379         case Add:
0380             e.setAttribute("action","add");
0381             break;
0382         case Delete:
0383             e.setAttribute("action","delete");
0384             break;
0385         case Modify:
0386             e.setAttribute("action","modify");
0387             break;
0388     }
0389     foreach(QString group, groups_) {
0390         e.appendChild(s.createTextElement("http://jabber.org/protocol/rosterx", "group",group));
0391     }
0392     return e;
0393 }
0394 
0395 void RosterExchangeItem::fromXml(const QDomElement& e)
0396 {
0397     setJid(e.attribute("jid"));
0398     setName(e.attribute("name"));
0399     if (e.attribute("action") == "delete") {
0400         setAction(Delete);
0401     }
0402     else if (e.attribute("action") == "modify") {
0403         setAction(Modify);
0404     }
0405     else {
0406         setAction(Add);
0407     }
0408     QDomNodeList nl = e.childNodes();
0409     for(int n = 0; n < nl.count(); ++n) {
0410         QDomElement g = nl.item(n).toElement();
0411         if (!g.isNull() && g.tagName() == "group") {
0412             groups_ += g.text();
0413         }
0414     }
0415 }
0416 
0417 
0418 //----------------------------------------------------------------------------
0419 // MUCItem
0420 //----------------------------------------------------------------------------
0421 MUCItem::MUCItem(Role r, Affiliation a) : affiliation_(a), role_(r)
0422 {
0423 }
0424 
0425 MUCItem::MUCItem(const QDomElement& el) : affiliation_(UnknownAffiliation), role_(UnknownRole)
0426 {
0427     fromXml(el);
0428 }
0429 
0430 void MUCItem::setNick(const QString& n)
0431 {
0432     nick_ = n;
0433 }
0434 
0435 void MUCItem::setJid(const Jid& j)
0436 {
0437     jid_ = j;
0438 }
0439 
0440 void MUCItem::setAffiliation(Affiliation a)
0441 {
0442     affiliation_ = a;
0443 }
0444 
0445 void MUCItem::setRole(Role r)
0446 {
0447     role_ = r;
0448 }
0449 
0450 void MUCItem::setActor(const Jid& a)
0451 {
0452     actor_ = a;
0453 }
0454 
0455 void MUCItem::setReason(const QString& r)
0456 {
0457     reason_ = r;
0458 }
0459 
0460 const QString& MUCItem::nick() const
0461 {
0462     return nick_;
0463 }
0464 
0465 const Jid& MUCItem::jid() const
0466 {
0467     return jid_;
0468 }
0469 
0470 MUCItem::Affiliation MUCItem::affiliation() const
0471 {
0472     return affiliation_;
0473 }
0474 
0475 MUCItem::Role MUCItem::role() const
0476 {
0477     return role_;
0478 }
0479 
0480 const Jid& MUCItem::actor() const
0481 {
0482     return actor_;
0483 }
0484 
0485 const QString& MUCItem::reason() const
0486 {
0487     return reason_;
0488 }
0489 
0490 void MUCItem::fromXml(const QDomElement& e)
0491 {
0492     if (e.tagName() != "item")
0493         return;
0494 
0495     jid_ = Jid(e.attribute("jid"));
0496     nick_ = e.attribute("nick");
0497     
0498     // Affiliation
0499     if (e.attribute("affiliation") == "owner") {
0500         affiliation_ = Owner;
0501     }
0502     else if (e.attribute("affiliation") == "admin") {
0503         affiliation_ = Admin;
0504     }
0505     else if (e.attribute("affiliation") == "member") {
0506         affiliation_ = Member;
0507     }
0508     else if (e.attribute("affiliation") == "outcast") {
0509         affiliation_ = Outcast;
0510     }
0511     else if (e.attribute("affiliation") == "none") {
0512         affiliation_ = NoAffiliation;
0513     }
0514     
0515     // Role
0516     if (e.attribute("role") == "moderator") {
0517         role_ = Moderator;
0518     }
0519     else if (e.attribute("role") == "participant") {
0520         role_ = Participant;
0521     }
0522     else if (e.attribute("role") == "visitor") {
0523         role_ = Visitor;
0524     }
0525     else if (e.attribute("role") == "none") {
0526         role_ = NoRole;
0527     }
0528     
0529     for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
0530         QDomElement i = n.toElement();
0531         if(i.isNull())
0532             continue;
0533 
0534         if (i.tagName() == "actor") 
0535             actor_ = Jid(i.attribute("jid"));
0536         else if (i.tagName() == "reason") 
0537             reason_ = i.text();
0538     }
0539 }
0540 
0541 QDomElement MUCItem::toXml(QDomDocument& d)
0542 {
0543     QDomElement e = d.createElement("item");
0544     
0545     if (!nick_.isEmpty())
0546         e.setAttribute("nick",nick_);
0547 
0548     if (!jid_.isEmpty())
0549         e.setAttribute("jid",jid_.full());
0550     
0551     if (!reason_.isEmpty())
0552         e.appendChild(textTag(&d,"reason",reason_));
0553     
0554     switch (affiliation_) {
0555         case NoAffiliation:
0556             e.setAttribute("affiliation","none");
0557             break;
0558         case Owner:
0559             e.setAttribute("affiliation","owner");
0560             break;
0561         case Admin:
0562             e.setAttribute("affiliation","admin");
0563             break;
0564         case Member:
0565             e.setAttribute("affiliation","member");
0566             break;
0567         case Outcast:
0568             e.setAttribute("affiliation","outcast");
0569             break;
0570         default:
0571             break;
0572     }
0573     switch (role_) {
0574         case NoRole:
0575             e.setAttribute("role","none");
0576             break;
0577         case Moderator:
0578             e.setAttribute("role","moderator");
0579             break;
0580         case Participant:
0581             e.setAttribute("role","participant");
0582             break;
0583         case Visitor:
0584             e.setAttribute("role","visitor");
0585             break;
0586         default:
0587             break;
0588     }
0589     
0590     return e;
0591 }
0592 
0593 bool MUCItem::operator==(const MUCItem& o)
0594 {
0595     return !nick_.compare(o.nick_) && ((!jid_.isValid() && !o.jid_.isValid()) || jid_.compare(o.jid_,true)) && ((!actor_.isValid() && !o.actor_.isValid()) || actor_.compare(o.actor_,true)) && affiliation_ == o.affiliation_ && role_ == o.role_ && !reason_.compare(o.reason_);
0596 }
0597 
0598 //----------------------------------------------------------------------------
0599 // MUCInvite
0600 //----------------------------------------------------------------------------
0601 
0602 MUCInvite::MUCInvite() : cont_(false)
0603 {
0604 }
0605 
0606 MUCInvite::MUCInvite(const Jid& to, const QString& reason) : to_(to), reason_(reason), cont_(false)
0607 {
0608 }
0609 
0610 MUCInvite::MUCInvite(const QDomElement& e) : cont_(false)
0611 {
0612     fromXml(e);
0613 }
0614 
0615 const Jid& MUCInvite::from() const
0616 {
0617     return from_;
0618 }
0619 
0620 void MUCInvite::setFrom(const Jid& j)
0621 {
0622     from_ = j;
0623 }
0624 
0625 const Jid& MUCInvite::to() const
0626 {
0627     return to_;
0628 }
0629 
0630 void MUCInvite::setTo(const Jid& j)
0631 {
0632     to_ = j;
0633 }
0634 
0635 const QString& MUCInvite::reason() const
0636 {
0637     return reason_;
0638 }
0639 
0640 void MUCInvite::setReason(const QString& r)
0641 {
0642     reason_ = r;
0643 }
0644 
0645 bool MUCInvite::cont() const
0646 {
0647     return cont_;
0648 }
0649 
0650 void MUCInvite::setCont(bool b)
0651 {
0652     cont_ = b;
0653 }
0654 
0655 void MUCInvite::fromXml(const QDomElement& e)
0656 {
0657     if (e.tagName() != "invite")
0658         return;
0659     
0660     from_ = e.attribute("from");
0661     to_ = e.attribute("to");
0662     for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
0663         QDomElement i = n.toElement();
0664         if(i.isNull())
0665             continue;
0666 
0667         if (i.tagName() == "continue")
0668            cont_ = true;    
0669         else if (i.tagName() == "reason") 
0670             reason_ = i.text();
0671     }
0672 }
0673 
0674 QDomElement MUCInvite::toXml(QDomDocument& d) const
0675 {
0676     QDomElement invite = d.createElement("invite");
0677     if (!to_.isEmpty()) {
0678         invite.setAttribute("to",to_.full());
0679     }
0680     if (!from_.isEmpty()) {
0681         invite.setAttribute("from",from_.full());
0682     }
0683     if (!reason_.isEmpty()) {
0684         invite.appendChild(textTag(&d, "reason", reason_));
0685     }
0686     if (cont_) {
0687         invite.appendChild(d.createElement("continue"));
0688     }
0689     return invite;
0690 }
0691 
0692 bool MUCInvite::isNull() const
0693 {
0694     return to_.isEmpty() && from_.isEmpty();
0695 }
0696 
0697 //----------------------------------------------------------------------------
0698 // MUCDecline
0699 //----------------------------------------------------------------------------
0700 
0701 MUCDecline::MUCDecline()
0702 {
0703 }
0704 
0705 MUCDecline::MUCDecline(const QDomElement& e) 
0706 {
0707     fromXml(e);
0708 }
0709 
0710 const Jid& MUCDecline::from() const
0711 {
0712     return from_;
0713 }
0714 
0715 void MUCDecline::setFrom(const Jid& j)
0716 {
0717     from_ = j;
0718 }
0719 
0720 const Jid& MUCDecline::to() const
0721 {
0722     return to_;
0723 }
0724 
0725 void MUCDecline::setTo(const Jid& j)
0726 {
0727     to_ = j;
0728 }
0729 
0730 const QString& MUCDecline::reason() const
0731 {
0732     return reason_;
0733 }
0734 
0735 void MUCDecline::setReason(const QString& r)
0736 {
0737     reason_ = r;
0738 }
0739 
0740 void MUCDecline::fromXml(const QDomElement& e)
0741 {
0742     if (e.tagName() != "decline")
0743         return;
0744     
0745     from_ = e.attribute("from");
0746     to_ = e.attribute("to");
0747     for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
0748         QDomElement i = n.toElement();
0749         if(i.isNull())
0750             continue;
0751 
0752         if (i.tagName() == "reason") 
0753             reason_ = i.text();
0754     }
0755 }
0756 
0757 QDomElement MUCDecline::toXml(QDomDocument& d) const
0758 {
0759     QDomElement decline = d.createElement("decline");
0760     if (!to_.isEmpty()) {
0761         decline.setAttribute("to",to_.full());
0762     }
0763     if (!from_.isEmpty()) {
0764         decline.setAttribute("from",from_.full());
0765     }
0766     if (!reason_.isEmpty()) {
0767         decline.appendChild(textTag(&d, "reason", reason_));
0768     }
0769     return decline;
0770 }
0771 
0772 bool MUCDecline::isNull() const
0773 {
0774     return to_.isEmpty() && from_.isEmpty();
0775 }
0776 
0777 //----------------------------------------------------------------------------
0778 // MUCDestroy
0779 //----------------------------------------------------------------------------
0780 
0781 MUCDestroy::MUCDestroy()
0782 {
0783 }
0784 
0785 MUCDestroy::MUCDestroy(const QDomElement& e) 
0786 {
0787     fromXml(e);
0788 }
0789 
0790 const Jid& MUCDestroy::jid() const
0791 {
0792     return jid_;
0793 }
0794 
0795 void MUCDestroy::setJid(const Jid& j)
0796 {
0797     jid_ = j;
0798 }
0799 
0800 const QString& MUCDestroy::reason() const
0801 {
0802     return reason_;
0803 }
0804 
0805 void MUCDestroy::setReason(const QString& r)
0806 {
0807     reason_ = r;
0808 }
0809 
0810 void MUCDestroy::fromXml(const QDomElement& e)
0811 {
0812     if (e.tagName() != "destroy")
0813         return;
0814     
0815     jid_ = e.attribute("jid");
0816     for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
0817         QDomElement i = n.toElement();
0818         if(i.isNull())
0819             continue;
0820 
0821         if (i.tagName() == "reason") 
0822             reason_ = i.text();
0823     }
0824 }
0825 
0826 QDomElement MUCDestroy::toXml(QDomDocument& d) const
0827 {
0828     QDomElement destroy = d.createElement("destroy");
0829     if (!jid_.isEmpty()) {
0830         destroy.setAttribute("jid",jid_.full());
0831     }
0832     if (!reason_.isEmpty()) {
0833         destroy.appendChild(textTag(&d, "reason", reason_));
0834     }
0835     return destroy;
0836 }
0837 
0838 //----------------------------------------------------------------------------
0839 // HTMLElement
0840 //----------------------------------------------------------------------------
0841 HTMLElement::HTMLElement() 
0842 {
0843 }
0844 
0845 HTMLElement::HTMLElement(const QDomElement &body) { setBody(body); }
0846 
0847 void HTMLElement::setBody(const QDomElement &body)
0848 {
0849     body_ = doc_.importNode(body, true).toElement();
0850 }
0851 
0852 const QDomElement& HTMLElement::body() const
0853 {
0854     return body_;
0855 }
0856 
0857 /**
0858  * Returns the string reperesentation of the HTML element.
0859  * By default, this is of the form <body ...>...</body>, but the
0860  * root tag can be modified using a parameter.
0861  *
0862  * \param rootTagName the tagname of the root element to use.
0863  */
0864 QString HTMLElement::toString(const QString &rootTagName) const
0865 {
0866     // create a copy of the body_ node,
0867     // get rid of the xmlns attribute and
0868     // change the root node name
0869     QDomElement e = body_.cloneNode().toElement();
0870     e.setTagName(rootTagName);
0871 
0872     // instead of using:
0873     //  QDomDocument msg;
0874     //  msg.appendChild(e);
0875     //  return msg.toString();
0876     // call Stream::xmlToString, to remove unwanted namespace attributes
0877     return(Stream::xmlToString(e));
0878 }
0879 
0880 QString HTMLElement::text() const
0881 {
0882     return body_.text();
0883 }
0884 
0885 
0886 //----------------------------------------------------------------------------
0887 // Message
0888 //----------------------------------------------------------------------------
0889 class Message::Private
0890 {
0891 public:
0892     Jid to, from;
0893     QString id, type, lang;
0894 
0895     StringMap subject, body, xHTMLBody;
0896 
0897     QString thread;
0898     bool threadSend;
0899     Stanza::Error error;
0900 
0901     // extensions
0902     QDateTime timeStamp;
0903     bool timeStampSend;
0904     UrlList urlList;
0905     AddressList addressList;
0906     RosterExchangeItems rosterExchangeItems;
0907     QList<MsgEvent> eventList;
0908     QString pubsubNode;
0909     QList<PubSubItem> pubsubItems;
0910     QList<PubSubRetraction> pubsubRetractions;
0911     QString eventId;
0912     QString xencrypted, invite;
0913     ChatState chatState;
0914     MessageReceipt messageReceipt;
0915     QString nick;
0916     HttpAuthRequest httpAuthRequest;
0917     XData xdata;
0918     QMap<QString,HTMLElement> htmlElements;
0919     QDomElement sxe;
0920     
0921     QList<int> mucStatuses;
0922     QList<MUCInvite> mucInvites;
0923     MUCDecline mucDecline;
0924     QString mucPassword;
0925 
0926     bool spooled, wasEncrypted;
0927 };
0928 
0929 //! \brief Constructs Message with given Jid information.
0930 //!
0931 //! This function will construct a Message container.
0932 //! \param to - specify reciver (default: empty string)
0933 Message::Message(const Jid &to)
0934 {
0935     d = new Private;
0936     d->to = to;
0937     d->spooled = false;
0938     d->threadSend = false;
0939     d->timeStampSend = false;
0940     d->wasEncrypted = false;
0941     /*d->flag = false;
0942     d->spooled = false;
0943     d->wasEncrypted = false;
0944     d->errorCode = -1;*/
0945     d->chatState = StateNone;
0946     d->messageReceipt = ReceiptNone;
0947 }
0948 
0949 //! \brief Constructs a copy of Message object
0950 //!
0951 //! Overloaded constructor which will constructs a exact copy of the Message
0952 //! object that was passed to the constructor.
0953 //! \param from - Message object you want to copy
0954 Message::Message(const Message &from)
0955 {
0956     d = new Private;
0957     *this = from;
0958 }
0959 
0960 //! \brief Required for internel use.
0961 Message & Message::operator=(const Message &from)
0962 {
0963     *d = *from.d;
0964     return *this;
0965 }
0966 
0967 //! \brief Destroy Message object.
0968 Message::~Message()
0969 {
0970     delete d;
0971 }
0972 
0973 //! \brief Return receiver's Jid information.
0974 Jid Message::to() const
0975 {
0976     return d->to;
0977 }
0978 
0979 //! \brief Return sender's Jid information.
0980 Jid Message::from() const
0981 {
0982     return d->from;
0983 }
0984 
0985 QString Message::id() const
0986 {
0987     return d->id;
0988 }
0989 
0990 //! \brief Return type information
0991 QString Message::type() const
0992 {
0993     return d->type;
0994 }
0995 
0996 QString Message::lang() const
0997 {
0998     return d->lang;
0999 }
1000 
1001 //! \brief Return subject information.
1002 QString Message::subject(const QString &lang) const
1003 {
1004     return d->subject[lang];
1005 }
1006 
1007 //! \brief Return body information.
1008 //!
1009 //! This function will return a plain text or the Richtext version if it
1010 //! it exists.
1011 //! \param rich - Returns richtext if true and plain text if false. (default: false)
1012 //! \note Richtext is in Qt's richtext format and not in xhtml.
1013 QString Message::body(const QString &lang) const
1014 {
1015     if (d->body.empty())
1016         return "";
1017     else if (d->body.contains(lang))
1018         return d->body[lang];
1019     else
1020         return d->body.begin().value();
1021 }
1022 
1023 //! \brief Return xhtml body.
1024 //!
1025 //! This function will return the richtext version of the body, if
1026 //! available.
1027 //! \param lang - body language
1028 //! \note The return string is in xhtml
1029 HTMLElement Message::html(const QString &lang) const
1030 {
1031 /*  if(containsHTML()) {
1032         if (d->htmlElements.contains(lang))
1033             return d->htmlElements[lang];
1034         else
1035             return d->htmlElements.begin().value();
1036     }
1037     else*/
1038         return HTMLElement();
1039 }
1040 QString Message::thread() const
1041 {
1042     return d->thread;
1043 }
1044 
1045 Stanza::Error Message::error() const
1046 {
1047     return d->error;
1048 }
1049 
1050 //! \brief Set receivers information
1051 //!
1052 //! \param to - Receivers Jabber id
1053 void Message::setTo(const Jid &j)
1054 {
1055     d->to = j;
1056     //d->flag = false;
1057 }
1058 
1059 void Message::setFrom(const Jid &j)
1060 {
1061     d->from = j;
1062     //d->flag = false;
1063 }
1064 
1065 void Message::setId(const QString &s)
1066 {
1067     d->id = s;
1068 }
1069 
1070 //! \brief Set Type of message
1071 //!
1072 //! \param type - type of message your going to send
1073 void Message::setType(const QString &s)
1074 {
1075     d->type = s;
1076     //d->flag = false;
1077 }
1078 
1079 void Message::setLang(const QString &s)
1080 {
1081     d->lang = s;
1082 }
1083 
1084 //! \brief Set subject
1085 //!
1086 //! \param subject - Subject information
1087 void Message::setSubject(const QString &s, const QString &lang)
1088 {
1089     d->subject[lang] = s;
1090     //d->flag = false;
1091 }
1092 
1093 //! \brief Set body
1094 //!
1095 //! \param body - body information
1096 //! \param rich - set richtext if true and set plaintext if false.
1097 //! \note Richtext support will be implemented in the future... Sorry.
1098 void Message::setBody(const QString &s, const QString &lang)
1099 {
1100     d->body[lang] = s;
1101     //d->flag = false;
1102 }
1103 
1104 void Message::setThread(const QString &s, bool send)
1105 {
1106     d->threadSend = send;
1107     d->thread = s;
1108 }
1109 
1110 void Message::setError(const Stanza::Error &err)
1111 {
1112     d->error = err;
1113 }
1114 
1115 const QString& Message::pubsubNode() const
1116 {
1117     return d->pubsubNode;
1118 }
1119 
1120 const QList<PubSubItem>& Message::pubsubItems() const
1121 {
1122     return d->pubsubItems;
1123 }
1124 
1125 const QList<PubSubRetraction>& Message::pubsubRetractions() const
1126 {
1127     return d->pubsubRetractions;
1128 }
1129 
1130 QDateTime Message::timeStamp() const
1131 {
1132     return d->timeStamp;
1133 }
1134 
1135 void Message::setTimeStamp(const QDateTime &ts, bool send)
1136 {
1137     d->timeStampSend = send;
1138     d->timeStamp = ts;
1139 }
1140 
1141 //! \brief Return list of urls attached to message.
1142 UrlList Message::urlList() const
1143 {
1144     return d->urlList;
1145 }
1146 
1147 //! \brief Add Url to the url list.
1148 //!
1149 //! \param url - url to append
1150 void Message::urlAdd(const Url &u)
1151 {
1152     d->urlList += u;
1153 }
1154 
1155 //! \brief clear out the url list.
1156 void Message::urlsClear()
1157 {
1158     d->urlList.clear();
1159 }
1160 
1161 //! \brief Set urls to send
1162 //!
1163 //! \param urlList - list of urls to send
1164 void Message::setUrlList(const UrlList &list)
1165 {
1166     d->urlList = list;
1167 }
1168 
1169 //! \brief Return list of addresses attached to message.
1170 AddressList Message::addresses() const
1171 {
1172     return d->addressList;
1173 }
1174 
1175 //! \brief Add Address to the address list.
1176 //!
1177 //! \param address - address to append
1178 void Message::addAddress(const Address &a)
1179 {
1180     d->addressList += a;
1181 }
1182 
1183 //! \brief clear out the address list.
1184 void Message::clearAddresses()
1185 {
1186     d->addressList.clear();
1187 }
1188 
1189 AddressList Message::findAddresses(Address::Type t) const
1190 {
1191     AddressList matches;
1192     foreach(Address a, d->addressList) {
1193         if (a.type() == t)
1194             matches.append(a);
1195     }
1196     return matches;
1197 }
1198 
1199 //! \brief Set addresses to send
1200 //!
1201 //! \param list - list of addresses to send
1202 void Message::setAddresses(const AddressList &list)
1203 {
1204     d->addressList = list;
1205 }
1206 
1207 const RosterExchangeItems& Message::rosterExchangeItems() const
1208 {
1209     return d->rosterExchangeItems;
1210 }
1211 
1212 void Message::setRosterExchangeItems(const RosterExchangeItems& items)
1213 {
1214     d->rosterExchangeItems = items;
1215 }
1216 
1217 QString Message::eventId() const
1218 {
1219     return d->eventId;
1220 }
1221 
1222 void Message::setEventId(const QString& id)
1223 {
1224     d->eventId = id;
1225 }
1226 
1227 bool Message::containsEvents() const
1228 {
1229     return !d->eventList.isEmpty();
1230 }
1231 
1232 bool Message::containsEvent(MsgEvent e) const
1233 {
1234     return d->eventList.contains(e);
1235 }
1236 
1237 void Message::addEvent(MsgEvent e)
1238 {
1239     if (!d->eventList.contains(e)) {
1240         if (e == CancelEvent || containsEvent(CancelEvent)) 
1241             d->eventList.clear(); // Reset list
1242         d->eventList += e;
1243     }
1244 }
1245 
1246 ChatState Message::chatState() const
1247 {
1248     return d->chatState;
1249 }
1250 
1251 void Message::setChatState(ChatState state)
1252 {
1253     d->chatState = state;
1254 }
1255 
1256 MessageReceipt Message::messageReceipt() const
1257 {
1258     return d->messageReceipt;
1259 }
1260 
1261 void Message::setMessageReceipt(MessageReceipt messageReceipt)
1262 {
1263     d->messageReceipt = messageReceipt;
1264 }
1265 
1266 QString Message::xencrypted() const
1267 {
1268     return d->xencrypted;
1269 }
1270 
1271 void Message::setXEncrypted(const QString &s)
1272 {
1273     d->xencrypted = s;
1274 }
1275 
1276 const QList<int>& Message::getMUCStatuses() const
1277 {
1278     return d->mucStatuses;
1279 }
1280 
1281 void Message::addMUCStatus(int i)
1282 {
1283     d->mucStatuses += i;
1284 }
1285 
1286 void Message::addMUCInvite(const MUCInvite& i)
1287 {
1288     d->mucInvites += i;
1289 }
1290 
1291 const QList<MUCInvite>& Message::mucInvites() const
1292 {
1293     return d->mucInvites;
1294 }
1295 
1296 void Message::setMUCDecline(const MUCDecline& de)
1297 {
1298     d->mucDecline = de;
1299 }
1300 
1301 const MUCDecline& Message::mucDecline() const
1302 {
1303     return d->mucDecline;
1304 }
1305 
1306 const QString& Message::mucPassword() const
1307 {
1308     return d->mucPassword;
1309 }
1310 
1311 void Message::setMUCPassword(const QString& p) 
1312 {
1313     d->mucPassword = p;
1314 }
1315 
1316 QString Message::invite() const
1317 {
1318     return d->invite;
1319 }
1320 
1321 void Message::setInvite(const QString &s)
1322 {
1323     d->invite = s;
1324 }
1325 
1326 const QString& Message::nick() const
1327 {
1328     return d->nick;
1329 }
1330 
1331 void Message::setNick(const QString& n)
1332 {
1333     d->nick = n;
1334 }
1335 
1336 void Message::setHttpAuthRequest(const HttpAuthRequest &req)
1337 {
1338     d->httpAuthRequest = req;
1339 }
1340 
1341 HttpAuthRequest Message::httpAuthRequest() const
1342 {
1343     return d->httpAuthRequest;
1344 }
1345 
1346 void Message::setForm(const XData &form)
1347 {
1348     d->xdata = form;
1349 }
1350 
1351 const XData& Message::getForm() const
1352 {
1353     return d->xdata;
1354 }
1355 
1356 const QDomElement& Message::sxe() const
1357 {
1358     return d->sxe;
1359 }
1360 
1361 void Message::setSxe(const QDomElement& e)
1362 {
1363     d->sxe = e;
1364 }
1365 
1366 bool Message::spooled() const
1367 {
1368     return d->spooled;
1369 }
1370 
1371 void Message::setSpooled(bool b)
1372 {
1373     d->spooled = b;
1374 }
1375 
1376 bool Message::wasEncrypted() const
1377 {
1378     return d->wasEncrypted;
1379 }
1380 
1381 void Message::setWasEncrypted(bool b)
1382 {
1383     d->wasEncrypted = b;
1384 }
1385 
1386 Stanza Message::toStanza(Stream *stream) const
1387 {
1388     Stanza s = stream->createStanza(Stanza::Message, d->to, d->type);
1389     if(!d->from.isEmpty())
1390         s.setFrom(d->from);
1391     if(!d->id.isEmpty())
1392         s.setId(d->id);
1393     if(!d->lang.isEmpty())
1394         s.setLang(d->lang);
1395 
1396     StringMap::ConstIterator it;
1397     for(it = d->subject.constBegin(); it != d->subject.constEnd(); ++it) {
1398         const QString &str = (*it);
1399         if(!str.isEmpty()) {
1400             QDomElement e = s.createTextElement(s.baseNS(), "subject", str);
1401             if(!it.key().isEmpty())
1402                 e.setAttributeNS(NS_XML, "xml:lang", it.key());
1403             s.appendChild(e);
1404         }
1405     }
1406     for(it = d->body.constBegin(); it != d->body.constEnd(); ++it) {
1407         const QString &str = (*it);
1408         if(!str.isEmpty()) {
1409             QDomElement e = s.createTextElement(s.baseNS(), "body", str);
1410             if(!it.key().isEmpty())
1411                 e.setAttributeNS(NS_XML, "xml:lang", it.key());
1412             s.appendChild(e);
1413         }
1414     }
1415     if(d->type == "error")
1416         s.setError(d->error);
1417 
1418     // thread
1419     if(d->threadSend && !d->thread.isEmpty()) {
1420         QDomElement e = s.createTextElement(s.baseNS(), "thread", d->thread);
1421         s.appendChild(e);
1422     }
1423 
1424     // timestamp
1425     if(d->timeStampSend && !d->timeStamp.isNull()) {
1426         QDomElement e = s.createElement("jabber:x:delay", "x");
1427         e.setAttribute("stamp", TS2stamp(d->timeStamp.toUTC()));
1428         s.appendChild(e);
1429     }
1430 
1431     // urls
1432     for(QList<Url>::ConstIterator uit = d->urlList.constBegin(); uit != d->urlList.constEnd(); ++uit) {
1433         QDomElement x = s.createElement("jabber:x:oob", "x");
1434         x.appendChild(s.createTextElement("jabber:x:oob", "url", (*uit).url()));
1435         if(!(*uit).desc().isEmpty())
1436             x.appendChild(s.createTextElement("jabber:x:oob", "desc", (*uit).desc()));
1437         s.appendChild(x);
1438     }
1439 
1440     // events
1441     if (!d->eventList.isEmpty()) {
1442         QDomElement x = s.createElement("jabber:x:event", "x");
1443 
1444         if (d->body.isEmpty()) {
1445             if (d->eventId.isEmpty())
1446                 x.appendChild(s.createElement("jabber:x:event","id"));
1447             else
1448                 x.appendChild(s.createTextElement("jabber:x:event","id",d->eventId));
1449         }
1450 
1451         for(QList<MsgEvent>::ConstIterator ev = d->eventList.constBegin(); ev != d->eventList.constEnd(); ++ev) {
1452             switch (*ev) {
1453                 case OfflineEvent:
1454                     x.appendChild(s.createElement("jabber:x:event", "offline"));
1455                     break;
1456                 case DeliveredEvent:
1457                     x.appendChild(s.createElement("jabber:x:event", "delivered"));
1458                     break;
1459                 case DisplayedEvent:
1460                     x.appendChild(s.createElement("jabber:x:event", "displayed"));
1461                     break;
1462                 case ComposingEvent: 
1463                     x.appendChild(s.createElement("jabber:x:event", "composing"));
1464                     break;
1465                 case CancelEvent:
1466                     // Add nothing
1467                     break;
1468             }
1469         }
1470         s.appendChild(x);
1471     } 
1472 
1473     // chat state
1474     QString chatStateNS = "http://jabber.org/protocol/chatstates";
1475     if (d->chatState != StateNone) {
1476         switch(d->chatState) {
1477             case StateActive:
1478                 s.appendChild(s.createElement(chatStateNS, "active"));
1479                 break;
1480             case StateComposing:
1481                 s.appendChild(s.createElement(chatStateNS, "composing"));
1482                 break;
1483             case StatePaused:
1484                 s.appendChild(s.createElement(chatStateNS, "paused"));
1485                 break;
1486             case StateInactive:
1487                 s.appendChild(s.createElement(chatStateNS, "inactive"));
1488                 break;
1489             case StateGone:
1490                 s.appendChild(s.createElement(chatStateNS, "gone"));
1491                 break;
1492             default: 
1493                 break;
1494         }
1495     }
1496 
1497     // message receipt
1498     QString messageReceiptNS = "urn:xmpp:receipts";
1499     if (d->messageReceipt != ReceiptNone) {
1500         switch(d->messageReceipt) {
1501             case ReceiptRequest:
1502                 s.appendChild(s.createElement(messageReceiptNS, "request"));
1503                 break;
1504             case ReceiptReceived:
1505                 s.appendChild(s.createElement(messageReceiptNS, "received"));
1506                 break;
1507             default: 
1508                 break;
1509         }
1510     }
1511 
1512     // xencrypted
1513     if(!d->xencrypted.isEmpty())
1514         s.appendChild(s.createTextElement("jabber:x:encrypted", "x", d->xencrypted));
1515 
1516     // addresses
1517     if (!d->addressList.isEmpty()) {
1518         QDomElement as = s.createElement("http://jabber.org/protocol/address","addresses");
1519         foreach(Address a, d->addressList) {
1520             as.appendChild(a.toXml(s));
1521         }
1522         s.appendChild(as);
1523     }
1524     
1525     // roster item exchange
1526     if (!d->rosterExchangeItems.isEmpty()) {
1527         QDomElement rx = s.createElement("http://jabber.org/protocol/rosterx","x");
1528         foreach(RosterExchangeItem r, d->rosterExchangeItems) {
1529             rx.appendChild(r.toXml(s));
1530         }
1531         s.appendChild(rx);
1532     }
1533 
1534     // invite
1535     if(!d->invite.isEmpty()) {
1536         QDomElement e = s.createElement("jabber:x:conference", "x");
1537         e.setAttribute("jid", d->invite);
1538         s.appendChild(e);
1539     }
1540 
1541     // nick
1542     if(!d->nick.isEmpty()) {
1543         s.appendChild(s.createTextElement("http://jabber.org/protocol/nick", "nick", d->nick));
1544     }
1545 
1546     // sxe
1547     if(!d->sxe.isNull()) {
1548         s.appendChild(d->sxe);
1549     }
1550 
1551     // muc
1552     if(!d->mucInvites.isEmpty()) {
1553         QDomElement e = s.createElement("http://jabber.org/protocol/muc#user","x");
1554         foreach(MUCInvite i, d->mucInvites) {
1555             e.appendChild(i.toXml(s.doc()));
1556         }
1557         if (!d->mucPassword.isEmpty()) {
1558             e.appendChild(s.createTextElement("http://jabber.org/protocol/muc#user","password",d->mucPassword));
1559         }
1560         s.appendChild(e);
1561     }
1562     else if(!d->mucDecline.isNull()) {
1563         QDomElement e = s.createElement("http://jabber.org/protocol/muc#user","x");
1564         e.appendChild(d->mucDecline.toXml(s.doc()));
1565         s.appendChild(e);
1566     }
1567 
1568     // http auth
1569     if(!d->httpAuthRequest.isEmpty()) {
1570         s.appendChild(d->httpAuthRequest.toXml(s.doc()));
1571     }
1572 
1573     // data form
1574     if(!d->xdata.fields().empty() || (d->xdata.type() == XData::Data_Cancel)) {
1575         bool submit = (d->xdata.type() == XData::Data_Submit) || (d->xdata.type() == XData::Data_Cancel);
1576         s.appendChild(d->xdata.toXml(&s.doc(), submit));
1577     }
1578 
1579     return s;
1580 }
1581 
1582 bool Message::fromStanza(const Stanza &s, int timeZoneOffset)
1583 {
1584     if(s.kind() != Stanza::Message)
1585         return false;
1586 
1587     setTo(s.to());
1588     setFrom(s.from());
1589     setId(s.id());
1590     setType(s.type());
1591     setLang(s.lang());
1592 
1593     d->subject.clear();
1594     d->body.clear();
1595     d->htmlElements.clear();
1596     d->thread = QString();
1597 
1598     QDomElement root = s.element();
1599 
1600     XDomNodeList nl = root.childNodes();
1601     int n;
1602     for(n = 0; n < nl.count(); ++n) {
1603         QDomNode i = nl.item(n);
1604         if(i.isElement()) {
1605             QDomElement e = i.toElement();
1606             if(e.namespaceURI() == s.baseNS()) {
1607                 if(e.tagName() == "subject") {
1608                     QString lang = e.attributeNS(NS_XML, "lang", "");
1609                     d->subject[lang] = e.text();
1610                 }
1611                 else if(e.tagName() == "body") {
1612                     QString lang = e.attributeNS(NS_XML, "lang", "");
1613                     d->body[lang] = e.text();
1614                 }
1615                 else if(e.tagName() == "thread")
1616                     d->thread = e.text();
1617             }
1618             else if(e.tagName() == "event" && e.namespaceURI() == "http://jabber.org/protocol/pubsub#event") {
1619                 for(QDomNode enode = e.firstChild(); !enode.isNull(); enode = enode.nextSibling()) {
1620                     QDomElement eel = enode.toElement();
1621                     if (eel.tagName() == "items") {
1622                         d->pubsubNode = eel.attribute("node");
1623                         for(QDomNode inode = eel.firstChild(); !inode.isNull(); inode = inode.nextSibling()) {
1624                             QDomElement o = inode.toElement();
1625                             if (o.tagName() == "item") {
1626                                 for(QDomNode j = o.firstChild(); !j.isNull(); j = j.nextSibling()) {
1627                                     QDomElement item = j.toElement();
1628                                     if (!item.isNull()) {
1629                                         d->pubsubItems += PubSubItem(o.attribute("id"),item);
1630                                     }
1631                                 }
1632                             }
1633                             if (o.tagName() == "retract") {
1634                                 d->pubsubRetractions += PubSubRetraction(o.attribute("id"));
1635                             }
1636                         }
1637                     }
1638                 }
1639             }
1640             else {
1641                 //printf("extension element: [%s]\n", e.tagName().latin1());
1642             }
1643         }
1644     }
1645 
1646     if(s.type() == "error")
1647         d->error = s.error();
1648 
1649     // xhtml-im
1650     nl = childElementsByTagNameNS(root, "http://jabber.org/protocol/xhtml-im", "html");
1651         if (!nl.isEmpty()) {
1652         nl = nl.item(0).childNodes();
1653         for(n = 0; n < nl.count(); ++n) {
1654             QDomElement e = nl.item(n).toElement();
1655             if (e.tagName() == "body" && e.namespaceURI() == "http://www.w3.org/1999/xhtml") {
1656                 QString lang = e.attributeNS(NS_XML, "lang", "");
1657                 d->htmlElements[lang] = e;
1658             }
1659         }
1660     }
1661 
1662     // timestamp
1663     QDomElement t = childElementsByTagNameNS(root, "jabber:x:delay", "x").item(0).toElement();
1664     if(!t.isNull()) {
1665         d->timeStamp = stamp2TS(t.attribute("stamp"));
1666         d->timeStamp = d->timeStamp.addSecs(timeZoneOffset * 3600);
1667         d->spooled = true;
1668     }
1669     else {
1670         d->timeStamp = QDateTime::currentDateTime();
1671         d->spooled = false;
1672     }
1673 
1674     // urls
1675     d->urlList.clear();
1676     nl = childElementsByTagNameNS(root, "jabber:x:oob", "x");
1677     for(n = 0; n < nl.count(); ++n) {
1678         QDomElement t = nl.item(n).toElement();
1679         Url u;
1680         u.setUrl(t.elementsByTagName("url").item(0).toElement().text());
1681         u.setDesc(t.elementsByTagName("desc").item(0).toElement().text());
1682         d->urlList += u;
1683     }
1684     
1685     // events
1686     d->eventList.clear();
1687     nl = childElementsByTagNameNS(root, "jabber:x:event", "x");
1688         if (!nl.isEmpty()) {
1689         nl = nl.item(0).childNodes();
1690         for(n = 0; n < nl.count(); ++n) {
1691             QString evtag = nl.item(n).toElement().tagName();
1692             if (evtag == "id") {
1693                 d->eventId =  nl.item(n).toElement().text();
1694             }
1695             else if (evtag == "displayed")
1696                 d->eventList += DisplayedEvent;
1697             else if (evtag == "composing")
1698                 d->eventList += ComposingEvent;
1699             else if (evtag == "delivered")
1700                 d->eventList += DeliveredEvent;
1701         }
1702         if (d->eventList.isEmpty())
1703             d->eventList += CancelEvent;
1704     }
1705 
1706     // Chat states
1707     QString chatStateNS = "http://jabber.org/protocol/chatstates";
1708     t = childElementsByTagNameNS(root, chatStateNS, "active").item(0).toElement();
1709     if(!t.isNull())
1710         d->chatState = StateActive;
1711     t = childElementsByTagNameNS(root, chatStateNS, "composing").item(0).toElement();
1712     if(!t.isNull())
1713         d->chatState = StateComposing;
1714     t = childElementsByTagNameNS(root, chatStateNS, "paused").item(0).toElement();
1715     if(!t.isNull())
1716         d->chatState = StatePaused;
1717     t = childElementsByTagNameNS(root, chatStateNS, "inactive").item(0).toElement();
1718     if(!t.isNull())
1719         d->chatState = StateInactive;
1720     t = childElementsByTagNameNS(root, chatStateNS, "gone").item(0).toElement();
1721     if(!t.isNull())
1722         d->chatState = StateGone;
1723 
1724     // message receipts
1725     QString messageReceiptNS = "urn:xmpp:receipts";
1726     t = childElementsByTagNameNS(root, messageReceiptNS, "request").item(0).toElement();
1727     if(!t.isNull())
1728         d->messageReceipt = ReceiptRequest;
1729     t = childElementsByTagNameNS(root, messageReceiptNS, "received").item(0).toElement();
1730     if(!t.isNull())
1731         d->messageReceipt = ReceiptReceived;
1732 
1733     // xencrypted
1734     t = childElementsByTagNameNS(root, "jabber:x:encrypted", "x").item(0).toElement();
1735     if(!t.isNull())
1736         d->xencrypted = t.text();
1737     else
1738         d->xencrypted = QString();
1739         
1740     // addresses
1741     d->addressList.clear();
1742     nl = childElementsByTagNameNS(root, "http://jabber.org/protocol/address", "addresses");
1743         if (!nl.isEmpty()) {
1744         QDomElement t = nl.item(0).toElement();
1745         nl = t.elementsByTagName("address");
1746         for(n = 0; n < nl.count(); ++n) {
1747             d->addressList += Address(nl.item(n).toElement());
1748         }
1749     }
1750     
1751     // roster item exchange
1752     d->rosterExchangeItems.clear();
1753     nl = childElementsByTagNameNS(root, "http://jabber.org/protocol/rosterx", "x");
1754         if (!nl.isEmpty()) {
1755         QDomElement t = nl.item(0).toElement();
1756         nl = t.elementsByTagName("item");
1757         for(n = 0; n < nl.count(); ++n) {
1758             RosterExchangeItem it = RosterExchangeItem(nl.item(n).toElement());
1759             if (!it.isNull())
1760                 d->rosterExchangeItems += it;
1761         }
1762     }
1763 
1764     // invite
1765     t = childElementsByTagNameNS(root, "jabber:x:conference", "x").item(0).toElement();
1766     if(!t.isNull())
1767         d->invite = t.attribute("jid");
1768     else
1769         d->invite = QString();
1770     
1771     // nick
1772     t = childElementsByTagNameNS(root, "http://jabber.org/protocol/nick", "nick").item(0).toElement();
1773     if(!t.isNull())
1774         d->nick = t.text();
1775     else
1776         d->nick = QString();
1777 
1778     // sxe
1779     t = childElementsByTagNameNS(root, "http://jabber.org/protocol/sxe", "sxe").item(0).toElement();
1780     if(!t.isNull())
1781         d->sxe = t;
1782     else
1783         d->sxe = QDomElement();
1784 
1785     t = childElementsByTagNameNS(root, "http://jabber.org/protocol/muc#user", "x").item(0).toElement();
1786     if(!t.isNull()) {
1787         for(QDomNode muc_n = t.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) {
1788             QDomElement muc_e = muc_n.toElement();
1789             if(muc_e.isNull())
1790                 continue;
1791             if (muc_e.tagName() == "status") {
1792                 addMUCStatus(muc_e.attribute("code").toInt());
1793             }
1794             else if (muc_e.tagName() == "invite") {
1795                 MUCInvite inv(muc_e);
1796                 if (!inv.isNull())
1797                     addMUCInvite(inv);
1798             }
1799             else if (muc_e.tagName() == "decline") {
1800                 setMUCDecline(MUCDecline(muc_e));
1801             }
1802             else if (muc_e.tagName() == "password") {
1803                 setMUCPassword(muc_e.text());
1804             }
1805         }
1806     }
1807 
1808     // http auth
1809     t = childElementsByTagNameNS(root, "http://jabber.org/protocol/http-auth", "confirm").item(0).toElement();
1810     if(!t.isNull()){
1811         d->httpAuthRequest = HttpAuthRequest(t);
1812     }
1813     else {
1814         d->httpAuthRequest = HttpAuthRequest();
1815     }
1816 
1817     // data form
1818     t = childElementsByTagNameNS(root, "jabber:x:data", "x").item(0).toElement();
1819     if(!t.isNull()){
1820         d->xdata.fromXml(t);
1821     }
1822 
1823     return true;
1824 }
1825 
1826 /*!
1827     Error object used to deny a request.
1828 */
1829 Stanza::Error HttpAuthRequest::denyError(Stanza::Error::Auth, Stanza::Error::NotAuthorized);
1830 
1831 /*!
1832     Constructs request of resource URL \a u, made by method \a m, with transaction id \a i.
1833 */
1834 HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u, const QString &i) : method_(m), url_(u), id_(i), hasId_(true)
1835 {
1836 }
1837 
1838 /*!
1839         Constructs request of resource URL \a u, made by method \a m, without transaction id.
1840 */
1841 HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u) : method_(m), url_(u), hasId_(false)
1842 {
1843 }
1844 
1845 /*!
1846     Constructs request object by reading XML <confirm/> element \a e.
1847 */
1848 HttpAuthRequest::HttpAuthRequest(const QDomElement &e)
1849 {
1850     fromXml(e);
1851 }
1852 
1853 /*!
1854     Returns true is object is empty (not valid).
1855 */
1856 bool HttpAuthRequest::isEmpty() const
1857 {
1858     return method_.isEmpty() && url_.isEmpty();
1859 }
1860 
1861 /*!
1862     Sets request method.
1863 */
1864 void HttpAuthRequest::setMethod(const QString& m)
1865 {
1866     method_ = m;
1867 }
1868 
1869 /*!
1870     Sets requested URL.
1871 */
1872 void HttpAuthRequest::setUrl(const QString& u)
1873 {
1874     url_ = u;
1875 }
1876 
1877 /*!
1878     Sets transaction identifier.
1879 */
1880 void HttpAuthRequest::setId(const QString& i)
1881 {
1882     id_ = i;
1883     hasId_ = true;
1884 }
1885 
1886 /*!
1887     Returns request method.
1888 */
1889 QString HttpAuthRequest::method() const
1890 {
1891     return method_;
1892 }
1893 
1894 /*!
1895     Returns requested URL.
1896 */
1897 QString HttpAuthRequest::url() const
1898 {
1899     return url_;
1900 }
1901 
1902 /*!
1903     Returns transaction identifier.
1904     Empty QString may mean both empty id or no id. Use hasId() to tell the difference.
1905 */
1906 QString HttpAuthRequest::id() const
1907 {
1908     return id_;
1909 }
1910 
1911 /*!
1912     Returns true if the request contains transaction id.
1913 */
1914 bool HttpAuthRequest::hasId() const
1915 {
1916     return hasId_;
1917 }
1918 
1919 /*!
1920     Returns XML element representing the request.
1921     If object is empty, this function returns empty element.
1922 */
1923 QDomElement HttpAuthRequest::toXml(QDomDocument &doc) const
1924 {
1925     QDomElement e;
1926     if(isEmpty())
1927         return e;
1928 
1929     e = doc.createElementNS("http://jabber.org/protocol/http-auth", "confirm");
1930     e.setAttribute("xmlns", "http://jabber.org/protocol/http-auth");
1931 
1932     if(hasId_) 
1933         e.setAttribute("id", id_);
1934     e.setAttribute("method", method_);
1935     e.setAttribute("url", url_);
1936 
1937     return e;
1938 }
1939 
1940 /*!
1941     Reads request data from XML element \a e.
1942 */
1943 bool HttpAuthRequest::fromXml(const QDomElement &e)
1944 {
1945     if(e.tagName() != "confirm")
1946         return false;
1947 
1948     hasId_ = e.hasAttribute("id");
1949     if(hasId_)
1950         id_ = e.attribute("id");
1951 
1952     method_ = e.attribute("method");
1953     url_ = e.attribute("url");
1954 
1955     return true;
1956 }
1957 
1958 //---------------------------------------------------------------------------
1959 // Subscription
1960 //---------------------------------------------------------------------------
1961 Subscription::Subscription(SubType type)
1962 {
1963     value = type;
1964 }
1965 
1966 int Subscription::type() const
1967 {
1968     return value;
1969 }
1970 
1971 QString Subscription::toString() const
1972 {
1973     switch(value) {
1974         case Remove:
1975             return "remove";
1976         case Both:
1977             return "both";
1978         case From:
1979             return "from";
1980         case To:
1981             return "to";
1982         case None:
1983         default:
1984             return "none";
1985     }
1986 }
1987 
1988 bool Subscription::fromString(const QString &s)
1989 {
1990     if(s == "remove")
1991         value = Remove;
1992     else if(s == "both")
1993         value = Both;
1994     else if(s == "from")
1995         value = From;
1996     else if(s == "to")
1997         value = To;
1998     else if(s == "none")
1999         value = None;
2000     else
2001         return false;
2002 
2003     return true;
2004 }
2005 
2006 
2007 //---------------------------------------------------------------------------
2008 // Status
2009 //---------------------------------------------------------------------------
2010 
2011 Status::Status(const QString &show, const QString &status, int priority, bool available)
2012 {
2013     v_isAvailable = available;
2014     v_show = show;
2015     v_status = status;
2016     v_priority = priority;
2017     v_timeStamp = QDateTime::currentDateTime();
2018     v_isInvisible = false;
2019     v_hasPhotoHash = false;
2020     v_isMUC = false;
2021     v_hasMUCItem = false;
2022     v_hasMUCDestroy = false;
2023     v_mucHistoryMaxChars = -1;
2024     v_mucHistoryMaxStanzas = -1;
2025     v_mucHistorySeconds = -1;
2026     ecode = -1;
2027 }
2028 
2029 Status::Status(Type type, const QString& status, int priority)
2030 {
2031     v_status = status;
2032     v_priority = priority;
2033     v_timeStamp = QDateTime::currentDateTime();
2034     v_hasPhotoHash = false;
2035     v_isMUC = false;
2036     v_hasMUCItem = false;
2037     v_hasMUCDestroy = false;
2038     v_mucHistoryMaxChars = -1;
2039     v_mucHistoryMaxStanzas = -1;
2040     v_mucHistorySeconds = -1;
2041     ecode = -1;
2042     setType(type);
2043 }
2044 
2045 Status::~Status()
2046 {
2047 }
2048 
2049 bool Status::hasError() const
2050 {
2051     return (ecode != -1);
2052 }
2053 
2054 void Status::setError(int code, const QString &str)
2055 {
2056     ecode = code;
2057     estr = str;
2058 }
2059 
2060 void Status::setIsAvailable(bool available)
2061 {
2062     v_isAvailable = available;
2063 }
2064 
2065 void Status::setIsInvisible(bool invisible)
2066 {
2067     v_isInvisible = invisible;
2068 }
2069 
2070 void Status::setPriority(int x)
2071 {
2072     v_priority = x;
2073 }
2074 
2075 void Status::setType(Status::Type _type)
2076 {
2077     bool available = true;
2078     bool invisible = false;
2079     QString show;
2080     switch(_type) {
2081         case Away:    show = "away"; break;
2082         case FFC:     show = "chat"; break;
2083         case XA:      show = "xa"; break;
2084         case DND:     show = "dnd"; break;
2085         case Offline: available = false; break;
2086         case Invisible: invisible = true; break;
2087         default: break;
2088     }
2089     setShow(show);
2090     setIsAvailable(available);
2091     setIsInvisible(invisible);
2092 }
2093 
2094 void Status::setType(QString stat)
2095 {
2096     if (stat == "offline")
2097         setType(XMPP::Status::Offline);
2098     else if (stat == "online")
2099         setType(XMPP::Status::Online);
2100     else if (stat == "away")
2101         setType(XMPP::Status::Away);
2102     else if (stat == "xa")
2103         setType(XMPP::Status::XA);
2104     else if (stat == "dnd")
2105         setType(XMPP::Status::DND);
2106     else if (stat == "invisible")
2107         setType(XMPP::Status::Invisible);
2108     else if (stat == "chat")
2109         setType(XMPP::Status::FFC);
2110     else
2111         setType(XMPP::Status::Away);
2112 }
2113 
2114 void Status::setShow(const QString & _show)
2115 {
2116     v_show = _show;
2117 }
2118 
2119 void Status::setStatus(const QString & _status)
2120 {
2121     v_status = _status;
2122 }
2123 
2124 void Status::setTimeStamp(const QDateTime & _timestamp)
2125 {
2126     v_timeStamp = _timestamp;
2127 }
2128 
2129 void Status::setKeyID(const QString &key)
2130 {
2131     v_key = key;
2132 }
2133 
2134 void Status::setXSigned(const QString &s)
2135 {
2136     v_xsigned = s;
2137 }
2138 
2139 void Status::setSongTitle(const QString & _songtitle)
2140 {
2141     v_songTitle = _songtitle;
2142 }
2143 
2144 void Status::setCapsNode(const QString & _capsNode)
2145 {
2146     v_capsNode = _capsNode;
2147 }
2148 
2149 void Status::setCapsVersion(const QString & _capsVersion)
2150 {
2151     v_capsVersion = _capsVersion;
2152 }
2153 
2154 void Status::setCapsExt(const QString & _capsExt)
2155 {
2156     v_capsExt = _capsExt;
2157 }
2158 
2159 void Status::setMUC() 
2160 {
2161     v_isMUC = true;
2162 }
2163 
2164 void Status::setMUCItem(const MUCItem& i)
2165 {
2166     v_hasMUCItem = true;
2167     v_mucItem = i;
2168 }
2169 
2170 void Status::setMUCDestroy(const MUCDestroy& i)
2171 {
2172     v_hasMUCDestroy = true;
2173     v_mucDestroy = i;
2174 }
2175 
2176 void Status::setMUCHistory(int maxchars, int maxstanzas, int seconds)
2177 {
2178     v_mucHistoryMaxChars = maxchars;
2179     v_mucHistoryMaxStanzas = maxstanzas;
2180     v_mucHistorySeconds = seconds;
2181 }
2182 
2183 
2184 const QString& Status::photoHash() const
2185 {
2186     return v_photoHash;
2187 }
2188 
2189 void Status::setPhotoHash(const QString& h)
2190 {
2191     v_photoHash = h;
2192     v_hasPhotoHash = true;
2193 }
2194 
2195 bool Status::hasPhotoHash() const
2196 {
2197     return v_hasPhotoHash;
2198 }
2199 
2200 bool Status::isAvailable() const
2201 {
2202     return v_isAvailable;
2203 }
2204 
2205 bool Status::isAway() const
2206 {
2207     return (v_show == "away" || v_show == "xa" || v_show == "dnd");
2208 }
2209 
2210 bool Status::isInvisible() const
2211 {
2212     return v_isInvisible;
2213 }
2214 
2215 int Status::priority() const
2216 {
2217     return v_priority;
2218 }
2219 
2220 Status::Type Status::type() const
2221 {
2222     Status::Type type = Status::Online;
2223     if (!isAvailable()) {
2224         type = Status::Offline;
2225     }
2226     else if (isInvisible()) {
2227         type = Status::Invisible;
2228     }
2229     else {
2230         QString s = show();
2231         if (s == "away")
2232             type = Status::Away;
2233         else if (s == "xa")
2234             type = Status::XA;
2235         else if (s == "dnd")
2236             type = Status::DND;
2237         else if (s == "chat")
2238             type = Status::FFC;
2239     }
2240     return type;
2241 }
2242 
2243 QString Status::typeString() const
2244 {
2245     QString stat;
2246     switch(type()) {
2247         case XMPP::Status::Offline: stat = "offline"; break;
2248         case XMPP::Status::Online: stat = "online"; break;
2249         case XMPP::Status::Away: stat = "away"; break;
2250         case XMPP::Status::XA: stat = "xa"; break;
2251         case XMPP::Status::DND: stat = "dnd"; break;
2252         case XMPP::Status::Invisible: stat = "invisible"; break;
2253         case XMPP::Status::FFC: stat = "chat"; break;
2254         default: stat = "away";
2255     }
2256     return stat;
2257 }
2258 
2259 const QString & Status::show() const
2260 {
2261     return v_show;
2262 }
2263 const QString & Status::status() const
2264 {
2265     return v_status;
2266 }
2267 
2268 QDateTime Status::timeStamp() const
2269 {
2270     return v_timeStamp;
2271 }
2272 
2273 const QString & Status::keyID() const
2274 {
2275     return v_key;
2276 }
2277 
2278 const QString & Status::xsigned() const
2279 {
2280     return v_xsigned;
2281 }
2282 
2283 const QString & Status::songTitle() const
2284 {
2285     return v_songTitle;
2286 }
2287 
2288 const QString & Status::capsNode() const
2289 {
2290     return v_capsNode;
2291 }
2292 
2293 const QString & Status::capsVersion() const
2294 {
2295     return v_capsVersion;
2296 }
2297 
2298 const QString & Status::capsExt() const
2299 {
2300     return v_capsExt;
2301 }
2302 
2303 bool Status::isMUC() const
2304 {
2305     return v_isMUC || !v_mucPassword.isEmpty() || hasMUCHistory();
2306 }
2307 
2308 bool Status::hasMUCItem() const
2309 {
2310     return v_hasMUCItem;
2311 }
2312 
2313 const MUCItem& Status::mucItem() const
2314 {
2315     return v_mucItem;
2316 }
2317 
2318 bool Status::hasMUCDestroy() const
2319 {
2320     return v_hasMUCDestroy;
2321 }
2322 
2323 const MUCDestroy& Status::mucDestroy() const
2324 {
2325     return v_mucDestroy;
2326 }
2327 
2328 const QList<int>& Status::getMUCStatuses() const
2329 {
2330     return v_mucStatuses;
2331 }
2332 
2333 void Status::addMUCStatus(int i)
2334 {
2335     v_mucStatuses += i;
2336 }
2337 
2338 const QString& Status::mucPassword() const
2339 {
2340     return v_mucPassword;
2341 }
2342 
2343 bool Status::hasMUCHistory() const
2344 {
2345     return v_mucHistoryMaxChars >= 0 || v_mucHistoryMaxStanzas >= 0 || v_mucHistorySeconds >= 0;
2346 }
2347 
2348 int Status::mucHistoryMaxChars() const
2349 {
2350     return v_mucHistoryMaxChars;
2351 }
2352 
2353 int Status::mucHistoryMaxStanzas() const
2354 {
2355     return v_mucHistoryMaxStanzas;
2356 }
2357 
2358 int Status::mucHistorySeconds() const
2359 {
2360     return v_mucHistorySeconds;
2361 }
2362 
2363 void Status::setMUCPassword(const QString& i)
2364 {
2365     v_mucPassword = i;
2366 }
2367 
2368 int Status::errorCode() const
2369 {
2370     return ecode;
2371 }
2372 
2373 const QString & Status::errorString() const
2374 {
2375     return estr;
2376 }
2377 
2378 
2379 //---------------------------------------------------------------------------
2380 // Resource
2381 //---------------------------------------------------------------------------
2382 Resource::Resource(const QString &name, const Status &stat)
2383 {
2384     v_name = name;
2385     v_status = stat;
2386 }
2387 
2388 Resource::~Resource()
2389 {
2390 }
2391 
2392 const QString & Resource::name() const
2393 {
2394     return v_name;
2395 }
2396 
2397 int Resource::priority() const
2398 {
2399     return v_status.priority();
2400 }
2401 
2402 const Status & Resource::status() const
2403 {
2404     return v_status;
2405 }
2406 
2407 void Resource::setName(const QString & _name)
2408 {
2409     v_name = _name;
2410 }
2411 
2412 void Resource::setStatus(const Status & _status)
2413 {
2414     v_status = _status;
2415 }
2416 
2417 
2418 //---------------------------------------------------------------------------
2419 // ResourceList
2420 //---------------------------------------------------------------------------
2421 ResourceList::ResourceList()
2422 :QList<Resource>()
2423 {
2424 }
2425 
2426 ResourceList::~ResourceList()
2427 {
2428 }
2429 
2430 ResourceList::Iterator ResourceList::find(const QString & _find)
2431 {
2432     for(ResourceList::Iterator it = begin(); it != end(); ++it) {
2433         if((*it).name() == _find)
2434             return it;
2435     }
2436 
2437     return end();
2438 }
2439 
2440 ResourceList::Iterator ResourceList::priority()
2441 {
2442     ResourceList::Iterator highest = end();
2443 
2444     for(ResourceList::Iterator it = begin(); it != end(); ++it) {
2445         if(highest == end() || (*it).priority() > (*highest).priority())
2446             highest = it;
2447     }
2448 
2449     return highest;
2450 }
2451 
2452 ResourceList::ConstIterator ResourceList::find(const QString & _find) const
2453 {
2454     for(ResourceList::ConstIterator it = constBegin(); it != constEnd(); ++it) {
2455         if((*it).name() == _find)
2456             return it;
2457     }
2458 
2459     return end();
2460 }
2461 
2462 ResourceList::ConstIterator ResourceList::priority() const
2463 {
2464     ResourceList::ConstIterator highest = end();
2465 
2466     for(ResourceList::ConstIterator it = constBegin(); it != constEnd(); ++it) {
2467         if(highest == end() || (*it).priority() > (*highest).priority())
2468             highest = it;
2469     }
2470 
2471     return highest;
2472 }
2473 
2474 
2475 //---------------------------------------------------------------------------
2476 // RosterItem
2477 //---------------------------------------------------------------------------
2478 RosterItem::RosterItem(const Jid &_jid)
2479 {
2480     v_jid = _jid;
2481     v_push = false;
2482 }
2483 
2484 RosterItem::~RosterItem()
2485 {
2486 }
2487 
2488 const Jid & RosterItem::jid() const
2489 {
2490     return v_jid;
2491 }
2492 
2493 const QString & RosterItem::name() const
2494 {
2495     return v_name;
2496 }
2497 
2498 const QStringList & RosterItem::groups() const
2499 {
2500     return v_groups;
2501 }
2502 
2503 const Subscription & RosterItem::subscription() const
2504 {
2505     return v_subscription;
2506 }
2507 
2508 const QString & RosterItem::ask() const
2509 {
2510     return v_ask;
2511 }
2512 
2513 bool RosterItem::isPush() const
2514 {
2515     return v_push;
2516 }
2517 
2518 bool RosterItem::inGroup(const QString &g) const
2519 {
2520     for(QStringList::ConstIterator it = v_groups.constBegin(); it != v_groups.constEnd(); ++it) {
2521         if(*it == g)
2522             return true;
2523     }
2524     return false;
2525 }
2526 
2527 void RosterItem::setJid(const Jid &_jid)
2528 {
2529     v_jid = _jid;
2530 }
2531 
2532 void RosterItem::setName(const QString &_name)
2533 {
2534     v_name = _name;
2535 }
2536 
2537 void RosterItem::setGroups(const QStringList &_groups)
2538 {
2539     v_groups = _groups;
2540 }
2541 
2542 void RosterItem::setSubscription(const Subscription &type)
2543 {
2544     v_subscription = type;
2545 }
2546 
2547 void RosterItem::setAsk(const QString &_ask)
2548 {
2549     v_ask = _ask;
2550 }
2551 
2552 void RosterItem::setIsPush(bool b)
2553 {
2554     v_push = b;
2555 }
2556 
2557 bool RosterItem::addGroup(const QString &g)
2558 {
2559     if(inGroup(g))
2560         return false;
2561 
2562     v_groups += g;
2563     return true;
2564 }
2565 
2566 bool RosterItem::removeGroup(const QString &g)
2567 {
2568     for(QStringList::Iterator it = v_groups.begin(); it != v_groups.end(); ++it) {
2569         if(*it == g) {
2570             v_groups.erase(it);
2571             return true;
2572         }
2573     }
2574 
2575     return false;
2576 }
2577 
2578 QDomElement RosterItem::toXml(QDomDocument *doc) const
2579 {
2580     QDomElement item = doc->createElement("item");
2581     item.setAttribute("jid", v_jid.full());
2582     item.setAttribute("name", v_name);
2583     item.setAttribute("subscription", v_subscription.toString());
2584     if(!v_ask.isEmpty())
2585         item.setAttribute("ask", v_ask);
2586     for(QStringList::ConstIterator it = v_groups.constBegin(); it != v_groups.constEnd(); ++it)
2587         item.appendChild(textTag(doc, "group", *it));
2588 
2589     return item;
2590 }
2591 
2592 bool RosterItem::fromXml(const QDomElement &item)
2593 {
2594     if(item.tagName() != "item")
2595         return false;
2596     Jid j(item.attribute("jid"));
2597     if(!j.isValid())
2598         return false;
2599     QString na = item.attribute("name");
2600     Subscription s;
2601     if(!s.fromString(item.attribute("subscription")) )
2602         return false;
2603     QStringList g;
2604     for(QDomNode n = item.firstChild(); !n.isNull(); n = n.nextSibling()) {
2605         QDomElement i = n.toElement();
2606         if(i.isNull())
2607             continue;
2608         if(i.tagName() == "group")
2609             g += tagContent(i);
2610     }
2611     QString a = item.attribute("ask");
2612 
2613     v_jid = j;
2614     v_name = na;
2615     v_subscription = s;
2616     v_groups = g;
2617     v_ask = a;
2618 
2619     return true;
2620 }
2621 
2622 
2623 //---------------------------------------------------------------------------
2624 // Roster
2625 //---------------------------------------------------------------------------
2626 Roster::Roster()
2627 :QList<RosterItem>()
2628 {
2629 }
2630 
2631 Roster::~Roster()
2632 {
2633 }
2634 
2635 Roster::Iterator Roster::find(const Jid &j)
2636 {
2637     for(Roster::Iterator it = begin(); it != end(); ++it) {
2638         if((*it).jid().compare(j))
2639             return it;
2640     }
2641 
2642     return end();
2643 }
2644 
2645 Roster::ConstIterator Roster::find(const Jid &j) const
2646 {
2647     for(Roster::ConstIterator it = begin(); it != end(); ++it) {
2648         if((*it).jid().compare(j))
2649             return it;
2650     }
2651 
2652     return end();
2653 }
2654 
2655 
2656 //---------------------------------------------------------------------------
2657 // FormField
2658 //---------------------------------------------------------------------------
2659 FormField::FormField(const QString &type, const QString &value)
2660 {
2661     v_type = misc;
2662     if(!type.isEmpty()) {
2663         int x = tagNameToType(type);
2664         if(x != -1)
2665             v_type = x;
2666     }
2667     v_value = value;
2668 }
2669 
2670 FormField::~FormField()
2671 {
2672 }
2673 
2674 int FormField::type() const
2675 {
2676     return v_type;
2677 }
2678 
2679 QString FormField::realName() const
2680 {
2681     return typeToTagName(v_type);
2682 }
2683 
2684 QString FormField::fieldName() const
2685 {
2686     switch(v_type) {
2687         case username:  return QObject::tr("Username");
2688         case nick:      return QObject::tr("Nickname");
2689         case password:  return QObject::tr("Password");
2690         case name:      return QObject::tr("Name");
2691         case first:     return QObject::tr("First Name");
2692         case last:      return QObject::tr("Last Name");
2693         case email:     return QObject::tr("E-mail");
2694         case address:   return QObject::tr("Address");
2695         case city:      return QObject::tr("City");
2696         case state:     return QObject::tr("State");
2697         case zip:       return QObject::tr("Zipcode");
2698         case phone:     return QObject::tr("Phone");
2699         case url:       return QObject::tr("URL");
2700         case date:      return QObject::tr("Date");
2701         case misc:      return QObject::tr("Misc");
2702         default:        return "";
2703     };
2704 }
2705 
2706 bool FormField::isSecret() const
2707 {
2708     return (type() == password);
2709 }
2710 
2711 const QString & FormField::value() const
2712 {
2713     return v_value;
2714 }
2715 
2716 void FormField::setType(int x)
2717 {
2718     v_type = x;
2719 }
2720 
2721 bool FormField::setType(const QString &in)
2722 {
2723     int x = tagNameToType(in);
2724     if(x == -1)
2725         return false;
2726 
2727     v_type = x;
2728     return true;
2729 }
2730 
2731 void FormField::setValue(const QString &in)
2732 {
2733     v_value = in;
2734 }
2735 
2736 int FormField::tagNameToType(const QString &in) const
2737 {
2738     if(!in.compare("username")) return username;
2739     if(!in.compare("nick"))     return nick;
2740     if(!in.compare("password")) return password;
2741     if(!in.compare("name"))     return name;
2742     if(!in.compare("first"))    return first;
2743     if(!in.compare("last"))     return last;
2744     if(!in.compare("email"))    return email;
2745     if(!in.compare("address"))  return address;
2746     if(!in.compare("city"))     return city;
2747     if(!in.compare("state"))    return state;
2748     if(!in.compare("zip"))      return zip;
2749     if(!in.compare("phone"))    return phone;
2750     if(!in.compare("url"))      return url;
2751     if(!in.compare("date"))     return date;
2752     if(!in.compare("misc"))     return misc;
2753 
2754     return -1;
2755 }
2756 
2757 QString FormField::typeToTagName(int type) const
2758 {
2759     switch(type) {
2760         case username:  return "username";
2761         case nick:      return "nick";
2762         case password:  return "password";
2763         case name:      return "name";
2764         case first:     return "first";
2765         case last:      return "last";
2766         case email:     return "email";
2767         case address:   return "address";
2768         case city:      return "city";
2769         case state:     return "state";
2770         case zip:       return "zipcode";
2771         case phone:     return "phone";
2772         case url:       return "url";
2773         case date:      return "date";
2774         case misc:      return "misc";
2775         default:        return "";
2776     };
2777 }
2778 
2779 
2780 //---------------------------------------------------------------------------
2781 // Form
2782 //---------------------------------------------------------------------------
2783 Form::Form(const Jid &j)
2784 :QList<FormField>()
2785 {
2786     setJid(j);
2787 }
2788 
2789 Form::~Form()
2790 {
2791 }
2792 
2793 Jid Form::jid() const
2794 {
2795     return v_jid;
2796 }
2797 
2798 QString Form::instructions() const
2799 {
2800     return v_instructions;
2801 }
2802 
2803 QString Form::key() const
2804 {
2805     return v_key;
2806 }
2807 
2808 void Form::setJid(const Jid &j)
2809 {
2810     v_jid = j;
2811 }
2812 
2813 void Form::setInstructions(const QString &s)
2814 {
2815     v_instructions = s;
2816 }
2817 
2818 void Form::setKey(const QString &s)
2819 {
2820     v_key = s;
2821 }
2822 
2823 
2824 //---------------------------------------------------------------------------
2825 // SearchResult
2826 //---------------------------------------------------------------------------
2827 SearchResult::SearchResult(const Jid &jid)
2828 {
2829     setJid(jid);
2830 }
2831 
2832 SearchResult::~SearchResult()
2833 {
2834 }
2835 
2836 const Jid & SearchResult::jid() const
2837 {
2838     return v_jid;
2839 }
2840 
2841 const QString & SearchResult::nick() const
2842 {
2843     return v_nick;
2844 }
2845 
2846 const QString & SearchResult::first() const
2847 {
2848     return v_first;
2849 }
2850 
2851 const QString & SearchResult::last() const
2852 {
2853     return v_last;
2854 }
2855 
2856 const QString & SearchResult::email() const
2857 {
2858     return v_email;
2859 }
2860 
2861 void SearchResult::setJid(const Jid &jid)
2862 {
2863     v_jid = jid;
2864 }
2865 
2866 void SearchResult::setNick(const QString &nick)
2867 {
2868     v_nick = nick;
2869 }
2870 
2871 void SearchResult::setFirst(const QString &first)
2872 {
2873     v_first = first;
2874 }
2875 
2876 void SearchResult::setLast(const QString &last)
2877 {
2878     v_last = last;
2879 }
2880 
2881 void SearchResult::setEmail(const QString &email)
2882 {
2883     v_email = email;
2884 }
2885 
2886 PubSubItem::PubSubItem() 
2887 {
2888 }
2889 
2890 PubSubItem::PubSubItem(const QString& id, const QDomElement& payload) : id_(id), payload_(payload) 
2891 { 
2892 }
2893 
2894 const QString& PubSubItem::id() const 
2895 { 
2896     return id_; 
2897 }
2898 
2899 const QDomElement& PubSubItem::payload() const 
2900 { 
2901     return payload_; 
2902 }
2903 
2904 
2905 PubSubRetraction::PubSubRetraction() 
2906 {
2907 }
2908 
2909 PubSubRetraction::PubSubRetraction(const QString& id) : id_(id) 
2910 { 
2911 }
2912 
2913 const QString& PubSubRetraction::id() const 
2914 { 
2915     return id_; 
2916 }
2917 
2918 
2919 }