1 /*
2  * Copyright (C) 2001, 2002  Justin Karneges
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  */
19 
20 #include <QDomElement>
21 #include <QString>
22 #include <QTimer>
23 
24 #include "xmpp_task.h"
25 #include "xmpp/jid/jid.h"
26 #include "xmpp_discoitem.h"
27 #include "xmpp_discoinfotask.h"
28 #include "xmpp_xmlcommon.h"
29 #include "xmpp_client.h"
30 #include "xmpp_caps.h"
31 
32 using namespace XMPP;
33 
34 class DiscoInfoTask::Private
35 {
36 public:
Private()37 	Private() : allowCache(true) { }
38 
39 	bool allowCache;
40 	Jid jid;
41 	QString node;
42 	DiscoItem::Identity ident;
43 	DiscoItem item;
44 };
45 
DiscoInfoTask(Task * parent)46 DiscoInfoTask::DiscoInfoTask(Task *parent)
47 : Task(parent)
48 {
49 	d = new Private;
50 }
51 
~DiscoInfoTask()52 DiscoInfoTask::~DiscoInfoTask()
53 {
54 	delete d;
55 }
56 
setAllowCache(bool allow)57 void DiscoInfoTask::setAllowCache(bool allow)
58 {
59 	d->allowCache = allow;
60 }
61 
get(const DiscoItem & item)62 void DiscoInfoTask::get(const DiscoItem &item)
63 {
64 	DiscoItem::Identity id;
65 	if ( item.identities().count() == 1 )
66 		id = item.identities().first();
67 	get(item.jid(), item.node(), id);
68 }
69 
get(const Jid & j,const QString & node,DiscoItem::Identity ident)70 void DiscoInfoTask::get (const Jid &j, const QString &node, DiscoItem::Identity ident)
71 {
72 	d->item = DiscoItem(); // clear item
73 
74 	d->jid = j;
75 	d->node = node;
76 	d->ident = ident;
77 }
78 
79 
80 /**
81  * Original requested jid.
82  * Is here because sometimes the responder does not include this information
83  * in the reply.
84  */
jid() const85 const Jid& DiscoInfoTask::jid() const
86 {
87 	return d->jid;
88 }
89 
90 /**
91  * Original requested node.
92  * Is here because sometimes the responder does not include this information
93  * in the reply.
94  */
node() const95 const QString& DiscoInfoTask::node() const
96 {
97 	return d->node;
98 }
99 
item() const100 const DiscoItem &DiscoInfoTask::item() const
101 {
102 	return d->item;
103 }
104 
onGo()105 void DiscoInfoTask::onGo ()
106 {
107 	if (d->allowCache && client()->capsManager()->isEnabled()) {
108 		d->item = client()->capsManager()->disco(d->jid);
109 		if (!d->item.features().isEmpty() || d->item.identities().count()) {
110 			QTimer::singleShot(0, this, SLOT(cachedReady())); // to be consistent with network requests
111 			return;
112 		}
113 	}
114 
115 	QDomElement iq = createIQ(doc(), "get", d->jid.full(), id());
116 	QDomElement query = doc()->createElement("query");
117 	query.setAttribute("xmlns", "http://jabber.org/protocol/disco#info");
118 
119 	if ( !d->node.isEmpty() )
120 		query.setAttribute("node", d->node);
121 
122 	if ( !d->ident.category.isEmpty() && !d->ident.type.isEmpty() ) {
123 		QDomElement i = doc()->createElement("item");
124 
125 		i.setAttribute("category", d->ident.category);
126 		i.setAttribute("type", d->ident.type);
127 		if ( !d->ident.name.isEmpty() )
128 			i.setAttribute("name", d->ident.name);
129 
130 		query.appendChild( i );
131 
132 	}
133 
134 	iq.appendChild(query);
135 	send(iq);
136 }
137 
cachedReady()138 void DiscoInfoTask::cachedReady()
139 {
140 	d->item.setJid( d->jid );
141 	setSuccess();
142 }
143 
take(const QDomElement & x)144 bool DiscoInfoTask::take(const QDomElement &x)
145 {
146 	if(!iqVerify(x, d->jid, id()))
147 		return false;
148 
149 	if(x.attribute("type") == "result") {
150 		d->item = DiscoItem::fromDiscoInfoResult(queryTag(x));
151 		d->item.setJid( d->jid );
152 		if (d->allowCache && client()->capsManager()->isEnabled()) {
153 			client()->capsManager()->updateDisco(d->jid, d->item);
154 		}
155 
156 		setSuccess();
157 	}
158 	else {
159 		setError(x);
160 	}
161 
162 	return true;
163 }
164 
165 
166