Mercurial > pidgin
annotate src/protocols/jabber/iq.c @ 8519:f8ab826e11ad
[gaim-migrate @ 9258]
" this patch will return the text for the smileys instead
of skipping them. This patch also gets rid of two
members in the gtkimhtml stuct that weren't being used
anywhere. They were gboolean smileys, comments; which
got replace with show_smileys, and show_comments. Also
an fixes the gtk_imhtml_class_init so that if it's
being compiled in c++, it will compile..." --Gary Kramlich
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Mon, 29 Mar 2004 16:20:30 +0000 |
parents | 52ea0ab31caa |
children | 4d05b6e9e9cd |
rev | line source |
---|---|
7014 | 1 /* |
2 * gaim - Jabber Protocol Plugin | |
3 * | |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 #include "internal.h" | |
22 #include "debug.h" | |
23 #include "prefs.h" | |
24 | |
7395 | 25 #include "buddy.h" |
8312 | 26 #include "disco.h" |
7014 | 27 #include "iq.h" |
7170 | 28 #include "oob.h" |
7014 | 29 #include "roster.h" |
7395 | 30 #include "si.h" |
7014 | 31 |
7058
06e7697f3fae
[gaim-migrate @ 7621]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7014
diff
changeset
|
32 #ifdef _WIN32 |
06e7697f3fae
[gaim-migrate @ 7621]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7014
diff
changeset
|
33 #include "utsname.h" |
06e7697f3fae
[gaim-migrate @ 7621]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
7014
diff
changeset
|
34 #endif |
7014 | 35 |
36 JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type) | |
37 { | |
38 JabberIq *iq; | |
39 | |
40 iq = g_new0(JabberIq, 1); | |
41 | |
42 iq->type = type; | |
43 | |
44 iq->node = xmlnode_new("iq"); | |
45 switch(iq->type) { | |
46 case JABBER_IQ_SET: | |
47 xmlnode_set_attrib(iq->node, "type", "set"); | |
48 break; | |
49 case JABBER_IQ_GET: | |
50 xmlnode_set_attrib(iq->node, "type", "get"); | |
51 break; | |
52 case JABBER_IQ_ERROR: | |
53 xmlnode_set_attrib(iq->node, "type", "error"); | |
54 break; | |
55 case JABBER_IQ_RESULT: | |
56 xmlnode_set_attrib(iq->node, "type", "result"); | |
57 break; | |
58 case JABBER_IQ_NONE: | |
59 /* this shouldn't ever happen */ | |
60 break; | |
61 } | |
62 | |
63 iq->js = js; | |
64 | |
65 if(type == JABBER_IQ_GET || type == JABBER_IQ_SET) { | |
66 iq->id = jabber_get_next_id(js); | |
67 xmlnode_set_attrib(iq->node, "id", iq->id); | |
68 } | |
69 | |
70 return iq; | |
71 } | |
72 | |
73 JabberIq *jabber_iq_new_query(JabberStream *js, JabberIqType type, | |
74 const char *xmlns) | |
75 { | |
76 JabberIq *iq = jabber_iq_new(js, type); | |
77 xmlnode *query; | |
78 | |
79 query = xmlnode_new_child(iq->node, "query"); | |
80 xmlnode_set_attrib(query, "xmlns", xmlns); | |
81 | |
82 return iq; | |
83 } | |
84 | |
7395 | 85 typedef struct _JabberCallbackData { |
86 JabberIqCallback *callback; | |
87 gpointer data; | |
88 } JabberCallbackData; | |
89 | |
90 void | |
91 jabber_iq_set_callback(JabberIq *iq, JabberIqCallback *callback, gpointer data) | |
7014 | 92 { |
93 iq->callback = callback; | |
7395 | 94 iq->callback_data = data; |
7014 | 95 } |
96 | |
97 void jabber_iq_set_id(JabberIq *iq, const char *id) | |
98 { | |
99 if(iq->id) | |
100 g_free(iq->id); | |
101 | |
102 if(id) { | |
103 xmlnode_set_attrib(iq->node, "id", id); | |
104 iq->id = g_strdup(id); | |
105 } else { | |
106 xmlnode_remove_attrib(iq->node, "id"); | |
107 iq->id = NULL; | |
108 } | |
109 } | |
110 | |
111 void jabber_iq_send(JabberIq *iq) | |
112 { | |
7395 | 113 JabberCallbackData *jcd; |
7014 | 114 g_return_if_fail(iq != NULL); |
115 | |
116 jabber_send(iq->js, iq->node); | |
117 | |
7395 | 118 if(iq->id && iq->callback) { |
119 jcd = g_new0(JabberCallbackData, 1); | |
120 jcd->callback = iq->callback; | |
121 jcd->data = iq->callback_data; | |
8312 | 122 g_hash_table_insert(iq->js->iq_callbacks, g_strdup(iq->id), jcd); |
7395 | 123 } |
7014 | 124 |
125 jabber_iq_free(iq); | |
126 } | |
127 | |
128 void jabber_iq_free(JabberIq *iq) | |
129 { | |
130 g_return_if_fail(iq != NULL); | |
131 | |
132 g_free(iq->id); | |
133 xmlnode_free(iq->node); | |
134 g_free(iq); | |
135 } | |
136 | |
8312 | 137 static void jabber_iq_last_parse(JabberStream *js, xmlnode *packet) |
7014 | 138 { |
139 JabberIq *iq; | |
8006 | 140 const char *type; |
7014 | 141 const char *from; |
142 const char *id; | |
143 xmlnode *query; | |
144 char *idle_time; | |
145 | |
8006 | 146 type = xmlnode_get_attrib(packet, "type"); |
7014 | 147 from = xmlnode_get_attrib(packet, "from"); |
148 id = xmlnode_get_attrib(packet, "id"); | |
149 | |
8006 | 150 if(type && !strcmp(type, "get")) { |
151 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:last"); | |
152 jabber_iq_set_id(iq, id); | |
153 xmlnode_set_attrib(iq->node, "to", from); | |
7014 | 154 |
8006 | 155 query = xmlnode_get_child(iq->node, "query"); |
7014 | 156 |
8006 | 157 idle_time = g_strdup_printf("%ld", js->idle ? time(NULL) - js->idle : 0); |
158 xmlnode_set_attrib(query, "seconds", idle_time); | |
159 g_free(idle_time); | |
7401 | 160 |
8006 | 161 jabber_iq_send(iq); |
162 } | |
7014 | 163 } |
164 | |
8312 | 165 static void jabber_iq_time_parse(JabberStream *js, xmlnode *packet) |
7014 | 166 { |
8006 | 167 const char *type, *from, *id; |
7014 | 168 JabberIq *iq; |
169 char buf[1024]; | |
170 xmlnode *query; | |
171 time_t now_t; | |
172 struct tm now; | |
173 time(&now_t); | |
174 localtime_r(&now_t, &now); | |
175 | |
8006 | 176 type = xmlnode_get_attrib(packet, "type"); |
7014 | 177 from = xmlnode_get_attrib(packet, "from"); |
178 id = xmlnode_get_attrib(packet, "id"); | |
179 | |
8006 | 180 if(type && !strcmp(type, "get")) { |
7014 | 181 |
8006 | 182 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:time"); |
183 jabber_iq_set_id(iq, id); | |
184 xmlnode_set_attrib(iq->node, "to", from); | |
185 | |
186 query = xmlnode_get_child(iq->node, "query"); | |
7014 | 187 |
8006 | 188 strftime(buf, sizeof(buf), "%Y%m%dT%T", &now); |
189 xmlnode_insert_data(xmlnode_new_child(query, "utc"), buf, -1); | |
190 strftime(buf, sizeof(buf), "%Z", &now); | |
191 xmlnode_insert_data(xmlnode_new_child(query, "tz"), buf, -1); | |
192 strftime(buf, sizeof(buf), "%d %b %Y %T", &now); | |
193 xmlnode_insert_data(xmlnode_new_child(query, "display"), buf, -1); | |
7014 | 194 |
8006 | 195 jabber_iq_send(iq); |
196 } | |
7014 | 197 } |
198 | |
8312 | 199 static void jabber_iq_version_parse(JabberStream *js, xmlnode *packet) |
7014 | 200 { |
201 JabberIq *iq; | |
8006 | 202 const char *type, *from, *id; |
7014 | 203 xmlnode *query; |
204 char *os = NULL; | |
205 | |
8006 | 206 type = xmlnode_get_attrib(packet, "type"); |
207 | |
208 if(type && !strcmp(type, "get")) { | |
209 | |
210 if(!gaim_prefs_get_bool("/plugins/prpl/jabber/hide_os")) { | |
211 struct utsname osinfo; | |
7014 | 212 |
8006 | 213 uname(&osinfo); |
214 os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release, | |
215 osinfo.machine); | |
216 } | |
7014 | 217 |
8006 | 218 from = xmlnode_get_attrib(packet, "from"); |
219 id = xmlnode_get_attrib(packet, "id"); | |
7014 | 220 |
8006 | 221 iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version"); |
222 xmlnode_set_attrib(iq->node, "to", from); | |
223 jabber_iq_set_id(iq, id); | |
7014 | 224 |
8006 | 225 query = xmlnode_get_child(iq->node, "query"); |
7014 | 226 |
8006 | 227 xmlnode_insert_data(xmlnode_new_child(query, "name"), PACKAGE, -1); |
228 xmlnode_insert_data(xmlnode_new_child(query, "version"), VERSION, -1); | |
229 if(os) { | |
230 xmlnode_insert_data(xmlnode_new_child(query, "os"), os, -1); | |
231 g_free(os); | |
232 } | |
233 | |
234 jabber_iq_send(iq); | |
7014 | 235 } |
236 } | |
237 | |
238 void jabber_iq_parse(JabberStream *js, xmlnode *packet) | |
239 { | |
7395 | 240 JabberCallbackData *jcd; |
8169 | 241 xmlnode *query, *error, *x; |
7014 | 242 const char *xmlns; |
8135 | 243 const char *type, *id, *from; |
7014 | 244 |
245 query = xmlnode_get_child(packet, "query"); | |
8043 | 246 type = xmlnode_get_attrib(packet, "type"); |
8135 | 247 from = xmlnode_get_attrib(packet, "from"); |
8312 | 248 id = xmlnode_get_attrib(packet, "id"); |
249 | |
250 /* First, lets see if a special callback got registered */ | |
251 | |
252 if(type && (!strcmp(type, "result") || !strcmp(type, "error"))) { | |
253 if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) { | |
254 jcd->callback(js, packet, jcd->data); | |
255 g_hash_table_remove(js->iq_callbacks, id); | |
8314 | 256 return; |
8312 | 257 } |
258 } | |
259 | |
260 /* Apparently not, so lets see if we have a pre-defined handler */ | |
7014 | 261 |
8043 | 262 if(type && query && (xmlns = xmlnode_get_attrib(query, "xmlns"))) { |
263 if(!strcmp(type, "set")) { | |
264 if(!strcmp(xmlns, "jabber:iq:roster")) { | |
265 jabber_roster_parse(js, packet); | |
266 return; | |
267 } else if(!strcmp(xmlns, "jabber:iq:oob")) { | |
268 jabber_oob_parse(js, packet); | |
269 return; | |
8262 | 270 } else if(!strcmp(xmlns, "http://jabber.org/protocol/bytestreams")) { |
271 jabber_bytestreams_parse(js, packet); | |
272 return; | |
8043 | 273 } |
274 } else if(!strcmp(type, "get")) { | |
275 if(!strcmp(xmlns, "jabber:iq:last")) { | |
8312 | 276 jabber_iq_last_parse(js, packet); |
8043 | 277 return; |
278 } else if(!strcmp(xmlns, "jabber:iq:time")) { | |
8312 | 279 jabber_iq_time_parse(js, packet); |
8043 | 280 return; |
281 } else if(!strcmp(xmlns, "jabber:iq:version")) { | |
8312 | 282 jabber_iq_version_parse(js, packet); |
8043 | 283 return; |
284 } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#info")) { | |
285 jabber_disco_info_parse(js, packet); | |
286 return; | |
287 } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#items")) { | |
288 jabber_disco_items_parse(js, packet); | |
289 return; | |
290 } | |
291 } else if(!strcmp(type, "result")) { | |
292 if(!strcmp(xmlns, "jabber:iq:roster")) { | |
293 jabber_roster_parse(js, packet); | |
294 return; | |
295 } else if(!strcmp(xmlns, "jabber:iq:register")) { | |
296 jabber_register_parse(js, packet); | |
297 return; | |
298 } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#info")) { | |
299 jabber_disco_info_parse(js, packet); | |
300 return; | |
301 } | |
7395 | 302 } |
8262 | 303 } else { |
8312 | 304 if(xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si")) { |
8262 | 305 jabber_si_parse(js, packet); |
306 return; | |
307 } | |
7395 | 308 } |
309 | |
310 | |
8312 | 311 /* If we get here, send the default error reply mandated by XMPP-CORE */ |
8135 | 312 |
8315 | 313 if(type && (!strcmp(type, "set") || !strcmp(type, "get"))) { |
314 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); | |
8135 | 315 |
8315 | 316 xmlnode_free(iq->node); |
317 iq->node = xmlnode_copy(packet); | |
318 xmlnode_set_attrib(iq->node, "to", from); | |
319 xmlnode_set_attrib(iq->node, "type", "error"); | |
320 error = xmlnode_new_child(iq->node, "error"); | |
321 xmlnode_set_attrib(error, "type", "cancel"); | |
322 xmlnode_set_attrib(error, "code", "501"); | |
323 x = xmlnode_new_child(error, "feature-not-implemented"); | |
324 xmlnode_set_attrib(x, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); | |
8169 | 325 |
8315 | 326 jabber_iq_send(iq); |
327 } | |
7014 | 328 } |
329 |