Mercurial > pidgin
annotate src/protocols/jabber/jabber.c @ 6371:8f94cce8faa5
[gaim-migrate @ 6876]
I think I touched almost every file. Here's what happened.
I started off fixing up the Makefile.am and configure.ac files to help with
the core/UI split some. Then I got annoyed with the
build_{allow,deny}_list() functions that everything used, and decided to
core/UI split privacy. While doing that, I decided to redesign the dialog.
So now, a lot has changed, but not really so much. Just that most files
got affected.
Oh yeah, and the UI stuff was taken out of internal.h and moved to
gtkinternal.h. If you use this, please be aware of this change.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Tue, 05 Aug 2003 10:55:04 +0000 |
parents | 1fa4410d2e13 |
children | 338147ea6896 |
rev | line source |
---|---|
2086 | 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ |
2 /* | |
3 * gaim | |
4 * | |
5 * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
6 * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx> | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 * | |
21 */ | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
22 #include "internal.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
23 |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
24 #ifdef _WIN32 |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
25 # include "utsname.h" |
2086 | 26 #endif |
27 | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
28 #include "account.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
29 #include "accountopt.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
30 #include "conversation.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
31 #include "debug.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
32 #include "ft.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
33 #include "multi.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
34 #include "notify.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
35 #include "prpl.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
36 #include "request.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
37 #include "util.h" |
6115
11bedb793a44
[gaim-migrate @ 6578]
Christian Hammond <chipx86@chipx86.com>
parents:
6106
diff
changeset
|
38 #include "html.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
39 |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
40 /* XXX */ |
4608 | 41 #include "gaim.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
42 |
2232
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
43 #ifdef MAX |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
44 # undef MAX |
2232
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
45 #endif |
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
46 #ifdef MIN |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
47 # undef MIN |
2232
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
48 #endif |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
49 |
2086 | 50 #include "jabber.h" |
51 #include "proxy.h" | |
52 | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
53 static GaimPlugin *my_protocol = NULL; |
4249 | 54 |
2086 | 55 /* The priv member of gjconn's is a gaim_connection for now. */ |
5572 | 56 #define GJ_GC(x) ((GaimConnection *)(x)->priv) |
4249 | 57 /* Confused? That makes three of us. -Robot101 */ |
58 #define GC_GJ(x) ((gjconn)((struct jabber_data *)(x)->proto_data)->gjc) | |
2086 | 59 |
5894 | 60 #define JABBER_CONNECT_STEPS 5 |
5572 | 61 |
2086 | 62 #define IQID_AUTH "__AUTH__" |
63 | |
64 #define IQ_NONE -1 | |
65 #define IQ_AUTH 0 | |
66 #define IQ_ROSTER 1 | |
67 | |
3259 | 68 #define UC_AWAY (0x02 | UC_UNAVAILABLE) |
69 #define UC_CHAT 0x04 | |
70 #define UC_XA (0x08 | UC_UNAVAILABLE) | |
71 #define UC_DND (0x10 | UC_UNAVAILABLE) | |
72 #define UC_ERROR (0x20 | UC_UNAVAILABLE) | |
2086 | 73 |
4917 | 74 #define DEFAULT_SERVER "jabber.org" |
2086 | 75 #define DEFAULT_GROUPCHAT "conference.jabber.org" |
76 #define DEFAULT_PORT 5222 | |
77 | |
78 #define USEROPT_PORT 0 | |
4436 | 79 #define USEROPT_CONN_SERVER 1 |
2086 | 80 |
3311 | 81 #define JABBER_TYPING_NOTIFY_INT 15 /* Delay (in seconds) between sending typing notifications */ |
82 | |
4450 | 83 #define JABBER_KEEPALIVE_STRING " \t " |
84 | |
3074 | 85 /* |
86 * Note: "was_connected" may seem redundant, but it was needed and I | |
87 * didn't want to touch the Jabber state stuff not specific to Gaim. | |
88 */ | |
2086 | 89 typedef struct gjconn_struct { |
90 /* Core structure */ | |
91 pool p; /* Memory allocation pool */ | |
92 int state; /* Connection state flag */ | |
3074 | 93 int was_connected; /* We were once connected */ |
2086 | 94 int fd; /* Connection file descriptor */ |
95 jid user; /* User info */ | |
96 char *pass; /* User passwd */ | |
97 | |
98 /* Stream stuff */ | |
99 int id; /* id counter for jab_getid() function */ | |
100 char idbuf[9]; /* temporary storage for jab_getid() */ | |
101 char *sid; /* stream id from server, for digest auth */ | |
102 XML_Parser parser; /* Parser instance */ | |
103 xmlnode current; /* Current node in parsing instance.. */ | |
104 | |
105 /* Event callback ptrs */ | |
2956 | 106 void (*on_state)(struct gjconn_struct *gjc, int state); |
107 void (*on_packet)(struct gjconn_struct *gjc, jpacket p); | |
108 | |
109 GHashTable *queries; /* query tracker */ | |
2086 | 110 |
111 void *priv; | |
112 | |
113 } *gjconn, gjconn_struct; | |
114 | |
2956 | 115 typedef void (*gjconn_state_h)(gjconn gjc, int state); |
116 typedef void (*gjconn_packet_h)(gjconn gjc, jpacket p); | |
2086 | 117 |
118 static gjconn gjab_new(char *user, char *pass, void *priv); | |
2956 | 119 static void gjab_delete(gjconn gjc); |
120 static void gjab_state_handler(gjconn gjc, gjconn_state_h h); | |
121 static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h); | |
122 static void gjab_start(gjconn gjc); | |
123 static void gjab_stop(gjconn gjc); | |
2086 | 124 /* |
2956 | 125 static int gjab_getfd(gjconn gjc); |
126 static jid gjab_getjid(gjconn gjc); | |
127 static char *gjab_getsid(gjconn gjc); | |
2086 | 128 */ |
2956 | 129 static char *gjab_getid(gjconn gjc); |
130 static void gjab_send(gjconn gjc, xmlnode x); | |
131 static void gjab_send_raw(gjconn gjc, const char *str); | |
132 static void gjab_recv(gjconn gjc); | |
133 static void gjab_auth(gjconn gjc); | |
134 | |
135 /* | |
136 * It is *this* to which we point the gaim_connection proto_data | |
137 */ | |
2086 | 138 struct jabber_data { |
2956 | 139 gjconn gjc; |
2086 | 140 gboolean did_import; |
2956 | 141 GSList *chats; |
2086 | 142 time_t idle; |
3311 | 143 GHashTable *buddies; |
3630 | 144 GSList *file_transfers; |
2086 | 145 }; |
146 | |
2956 | 147 /* |
3340 | 148 * Used in jabber_buddy_data.invisible, below |
149 */ | |
150 #define JABBER_NOT_INVIS 0x00 | |
151 #define JABBER_SERV_INVIS 0x01 /* Invisible set on server */ | |
152 #define JABBER_BUD_INVIS 0x02 /* Invisible set on buddy */ | |
153 | |
154 /* | |
4927 | 155 * Used in jabber_buddy_data.subscription, below |
156 */ | |
157 #define JABBER_SUB_NONE 0x0 | |
158 #define JABBER_SUB_PENDING 0x1 | |
159 #define JABBER_SUB_TO 0x2 | |
160 #define JABBER_SUB_FROM 0x4 | |
161 #define JABBER_SUB_BOTH (JABBER_SUB_TO | JABBER_SUB_FROM) | |
162 | |
163 | |
164 /* | |
3311 | 165 * It is *this* to which we point the buddy proto_data |
166 */ | |
167 struct jabber_buddy_data { | |
168 GSList *resources; | |
169 char *error_msg; | |
3340 | 170 unsigned invisible; /* We've set presence type invisible for this buddy */ |
4927 | 171 unsigned subscription; /* subscription type for this buddy */ |
3311 | 172 }; |
173 | |
174 /* | |
175 * per-resource info | |
176 */ | |
177 typedef struct jabber_resource_info { | |
3770 | 178 char *name; |
3311 | 179 int priority; |
180 int state; | |
181 char *away_msg; | |
182 char *thread_id; | |
183 gboolean has_composing; | |
5093 | 184 gboolean has_xhtml; |
3311 | 185 } *jab_res_info; |
186 | |
187 /* | |
188 * For our own jid handling | |
189 * | |
190 * We do our own so we can cleanly parse buddy names | |
191 * (user@server/resource) and rid ourselves of the | |
192 * struct when we're done with it. The Jabber lib | |
193 * structs last the life of the pool--we frequently | |
194 * don't want that. | |
195 * | |
196 * We use the real jid structs so we can make use of | |
197 * jid_safe(), jid_cmp() and some others. | |
198 * | |
199 * BE CAREFUL using the Jabber lib routines. | |
200 * Many of them assume pool use and are not | |
201 * amenable to use with our own! | |
202 * | |
203 * We give them special names so we know, throughout | |
204 * the code, that they're not alloc'd out of pool | |
205 * memory and we can, and must, dispose of them when | |
206 * we're done with 'em. | |
207 */ | |
208 #define gaim_jid_struct jid_struct | |
209 typedef struct gaim_jid_struct *gaim_jid; | |
210 | |
211 /* | |
2956 | 212 * Jabber "chat group" info. Pointers to these go in jabber_data |
213 * pending and existing chats lists. | |
214 */ | |
2086 | 215 struct jabber_chat { |
3311 | 216 gaim_jid gjid; |
5572 | 217 GaimConnection *gc; |
5679 | 218 GaimConversation *b; |
2086 | 219 int id; |
2956 | 220 int state; |
2086 | 221 }; |
222 | |
2956 | 223 /* |
224 * Jabber chat states... | |
225 * | |
226 * Note: due to a bug in one version of the Jabber server, subscriptions | |
227 * to chat groups aren't (always?) properly removed at the server. The | |
228 * result is clients receive Jabber "presence" notifications for JIDs | |
229 * they no longer care about. The problem with such vestigial notifies is | |
230 * that we really have no way of telling if it's vestigial or if it's a | |
231 * valid "buddy" presence notification. So we keep jabber_chat structs | |
232 * around after leaving a chat group and simply mark them "closed." That | |
233 * way we can test for such errant presence notifications. I.e.: if we | |
234 * get a presence notfication from a JID that matches a chat group JID, | |
235 * we disregard it. | |
236 */ | |
237 #define JCS_PENDING 1 /* pending */ | |
238 #define JCS_ACTIVE 2 /* active */ | |
239 #define JCS_CLOSED 3 /* closed */ | |
240 | |
241 | |
242 #define STATE_EVT(arg) if(gjc->on_state) { (gjc->on_state)(gjc, (arg) ); } | |
243 | |
244 static void jabber_handlevcard(gjconn, xmlnode, char *); | |
2086 | 245 |
3630 | 246 static char *jabber_normalize(const char *s); |
247 | |
2086 | 248 static char *create_valid_jid(const char *given, char *server, char *resource) |
249 { | |
250 char *valid; | |
4927 | 251 char *tmp; |
252 | |
253 if (!(tmp = strchr(given, '@'))) | |
2086 | 254 valid = g_strdup_printf("%s@%s/%s", given, server, resource); |
4927 | 255 else if (!strchr(tmp, '/')) |
2086 | 256 valid = g_strdup_printf("%s/%s", given, resource); |
257 else | |
258 valid = g_strdup(given); | |
259 | |
260 return valid; | |
261 } | |
262 | |
4915 | 263 |
3311 | 264 /* |
265 * Dispose of a gaim_jid_struct | |
266 */ | |
267 static void gaim_jid_free(gaim_jid gjid) | |
268 { | |
269 if(gjid) { | |
270 if(gjid->resource) | |
271 free(gjid->resource); | |
272 if(gjid->user) | |
273 free(gjid->user); | |
274 if(gjid->server) | |
275 free(gjid->server); | |
276 if(gjid->full) | |
277 free(gjid->full); | |
278 free(gjid); | |
279 } | |
280 } | |
281 | |
282 /* | |
283 * Create a new gjid struct | |
284 * | |
285 * Unlike jid_new(), also creates "full." | |
286 * | |
287 * Shamelessly copied, in part, from jid.c: jid_new() | |
288 * | |
289 * Caller is responsible for freeing the space allocated by this via | |
290 * gaim_jid_free(). | |
291 * | |
292 * JFIXME: Has a local declaration for jid.c:jid_safe(). I've put in a | |
293 * request to have that added to libjabber's lib.h file. (JSeymour) | |
294 */ | |
295 static gaim_jid gaim_jid_new(char *name) | |
296 { | |
297 extern jid jid_safe(jid); /* *retch* */ | |
298 | |
299 gaim_jid gjid = NULL; | |
300 | |
301 if(name && strlen(name)) { | |
302 char *server, *resource, *type, *str; | |
303 int full_len = 0; | |
304 | |
305 /* user@server/resource */ | |
306 | |
307 str = strdup(name); /* we mangle a copy */ | |
308 | |
309 gjid = calloc(1, sizeof(struct gaim_jid_struct)); | |
310 | |
311 if((resource = strstr(str, "/")) != NULL) { | |
312 *resource = '\0'; | |
313 ++resource; | |
314 if((full_len = strlen(resource)) > 0) { | |
315 gjid->resource = strdup(resource); | |
316 ++full_len; /* for later "/" addition */ | |
317 } | |
318 } else { | |
319 resource = str + strlen(str); /* point to end */ | |
320 } | |
321 | |
322 type = strstr(str, ":"); | |
323 if(type != NULL && type < resource) { | |
324 *type = '\0'; | |
325 ++type; | |
326 str = type; /* ignore the type: prefix */ | |
327 } | |
328 | |
329 server = strstr(str, "@"); | |
330 | |
331 /* | |
332 * if there's no @, it's just the server address | |
333 */ | |
334 if(server == NULL || server > resource) { | |
335 gjid->server = strdup(str); | |
336 full_len += strlen(str); | |
337 } else { | |
338 *server = '\0'; | |
339 ++server; | |
340 gjid->server = strdup(server); | |
341 full_len += strlen(server) + 1; /* account for later "@" */ | |
342 if(strlen(str) > 0) { | |
343 gjid->user = strdup(str); | |
344 full_len += strlen(str); | |
345 } | |
346 } | |
347 | |
348 free(str); | |
349 | |
350 if(!jid_safe(gjid)) { | |
351 gaim_jid_free(gjid); | |
352 gjid = NULL; | |
353 } else { | |
354 if(full_len) { | |
355 char *s = gjid->full = malloc(++full_len); | |
356 | |
357 if(gjid->user) { | |
358 strcpy(s, gjid->user); | |
359 s += strlen(gjid->user); | |
360 } | |
361 if(gjid->server) { | |
362 if(s > gjid->full) | |
363 *(s++) = '@'; | |
364 strcpy(s, gjid->server); | |
365 s += strlen(gjid->server); | |
366 } | |
367 if(gjid->resource) { | |
368 *(s++) = '/'; | |
369 strcpy(s, gjid->resource); | |
370 } | |
371 } | |
372 } | |
373 } | |
374 | |
375 return gjid; | |
376 } | |
377 | |
378 /* | |
379 * Get a "username@server" from unadorned "username" | |
380 * | |
381 * If there's no "@server" part and "who" doesn't match the | |
382 * gjconn server (which would indicate that "who" *is* the | |
383 * server in case of server messages), the gjconn server is | |
384 * appended. | |
385 * | |
386 * If incl_resource is TRUE (non-0), the returned string | |
387 * includes the "/resource" part (if it exists), otherwise not. | |
388 * | |
389 * Allocates space for returned string. Caller is | |
390 * responsible for freeing it with g_free(). | |
391 * | |
392 * If "gjid" is non-null, sets that as well. Caller is | |
393 * reponsible for freeing that via gaim_jid_free() when done | |
394 * with it. | |
395 */ | |
3466 | 396 static gchar *get_realwho(gjconn gjc, const char *who, int incl_resource, gaim_jid *gjid) |
3311 | 397 { |
398 gaim_jid my_gjid; | |
399 gchar *my_who; | |
400 gchar *realwho = NULL; | |
401 | |
402 if(!(who && who[0])) { | |
403 return NULL; | |
404 } | |
405 | |
406 /* | |
407 * Bare username and "username" not the server itself? | |
408 */ | |
409 if(!strchr(who, '@') && strcasecmp(who, gjc->user->server)) { | |
410 my_who = g_strdup_printf("%s@%s", who, gjc->user->server); | |
411 } else { | |
412 my_who = g_strdup(who); | |
413 } | |
414 | |
415 if((my_gjid = gaim_jid_new(my_who)) != NULL) { | |
416 /* | |
417 * If there's no "user" part, "who" was just the server or perhaps a transport (?) | |
418 */ | |
419 if(my_gjid->user) { | |
420 /* | |
421 * Include "/resource" bit? | |
422 */ | |
423 if(incl_resource) { | |
424 realwho = g_strdup(my_gjid->full); | |
425 } else { | |
426 realwho = g_strdup_printf("%s@%s", my_gjid->user, my_gjid->server); | |
427 } | |
428 } else { | |
429 realwho = g_strdup(my_gjid->server); | |
430 } | |
431 } | |
432 | |
433 g_free(my_who); | |
434 | |
435 if(gjid) { | |
436 *gjid = my_gjid; | |
437 } else { | |
438 gaim_jid_free(my_gjid); | |
439 } | |
440 | |
441 return realwho; | |
442 } | |
443 | |
2086 | 444 static gjconn gjab_new(char *user, char *pass, void *priv) |
445 { | |
446 pool p; | |
2956 | 447 gjconn gjc; |
2086 | 448 |
449 if (!user) | |
450 return (NULL); | |
451 | |
452 p = pool_new(); | |
453 if (!p) | |
454 return (NULL); | |
2956 | 455 gjc = pmalloc_x(p, sizeof(gjconn_struct), 0); |
456 if (!gjc) { | |
457 pool_free(p); /* no need for this anymore! */ | |
2086 | 458 return (NULL); |
2956 | 459 } |
460 gjc->p = p; | |
461 | |
3236 | 462 if((gjc->user = jid_new(p, user)) == NULL) { |
463 pool_free(p); /* no need for this anymore! */ | |
464 return (NULL); | |
465 } | |
3257 | 466 |
467 gjc->pass = strdup(pass); | |
2956 | 468 |
469 gjc->state = JCONN_STATE_OFF; | |
3074 | 470 gjc->was_connected = 0; |
2956 | 471 gjc->id = 1; |
472 gjc->fd = -1; | |
473 | |
474 gjc->priv = priv; | |
475 | |
476 return gjc; | |
2086 | 477 } |
478 | |
2956 | 479 static void gjab_delete(gjconn gjc) |
2086 | 480 { |
2956 | 481 if (!gjc) |
2086 | 482 return; |
483 | |
2956 | 484 gjab_stop(gjc); |
3257 | 485 free(gjc->pass); |
2956 | 486 pool_free(gjc->p); |
2086 | 487 } |
488 | |
2956 | 489 static void gjab_state_handler(gjconn gjc, gjconn_state_h h) |
2086 | 490 { |
2956 | 491 if (!gjc) |
2086 | 492 return; |
493 | |
2956 | 494 gjc->on_state = h; |
2086 | 495 } |
496 | |
2956 | 497 static void gjab_packet_handler(gjconn gjc, gjconn_packet_h h) |
2086 | 498 { |
2956 | 499 if (!gjc) |
2086 | 500 return; |
501 | |
2956 | 502 gjc->on_packet = h; |
2086 | 503 } |
504 | |
2956 | 505 static void gjab_stop(gjconn gjc) |
2086 | 506 { |
2956 | 507 if (!gjc || gjc->state == JCONN_STATE_OFF) |
2086 | 508 return; |
509 | |
2956 | 510 gjab_send_raw(gjc, "</stream:stream>"); |
511 gjc->state = JCONN_STATE_OFF; | |
3074 | 512 gjc->was_connected = 0; |
2956 | 513 close(gjc->fd); |
514 gjc->fd = -1; | |
515 XML_ParserFree(gjc->parser); | |
516 gjc->parser = NULL; | |
2086 | 517 } |
518 | |
519 /* | |
2956 | 520 static int gjab_getfd(gjconn gjc) |
2086 | 521 { |
2956 | 522 if (gjc) |
523 return gjc->fd; | |
2086 | 524 else |
525 return -1; | |
526 } | |
527 | |
2956 | 528 static jid gjab_getjid(gjconn gjc) |
2086 | 529 { |
2956 | 530 if (gjc) |
531 return (gjc->user); | |
2086 | 532 else |
533 return NULL; | |
534 } | |
535 | |
2956 | 536 static char *gjab_getsid(gjconn gjc) |
2086 | 537 { |
2956 | 538 if (gjc) |
539 return (gjc->sid); | |
2086 | 540 else |
541 return NULL; | |
542 } | |
543 */ | |
544 | |
2956 | 545 static char *gjab_getid(gjconn gjc) |
2086 | 546 { |
2956 | 547 snprintf(gjc->idbuf, 8, "%d", gjc->id++); |
548 return &gjc->idbuf[0]; | |
2086 | 549 } |
550 | |
2956 | 551 static void gjab_send(gjconn gjc, xmlnode x) |
2086 | 552 { |
2956 | 553 if (gjc && gjc->state != JCONN_STATE_OFF) { |
2086 | 554 char *buf = xmlnode2str(x); |
6076 | 555 if (buf) { |
3630 | 556 #ifndef _WIN32 |
6076 | 557 if(write(gjc->fd, buf, strlen(buf)) < 0) { |
3630 | 558 #else |
6076 | 559 if(send(gjc->fd, buf, strlen(buf), 0) < 0) { |
3630 | 560 #endif |
6076 | 561 gaim_connection_error(GJ_GC(gjc), _("Write error")); |
562 } else { | |
563 gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send: %s\n", buf); | |
564 } | |
565 } | |
2086 | 566 } |
567 } | |
568 | |
2956 | 569 static void gjab_send_raw(gjconn gjc, const char *str) |
2086 | 570 { |
2956 | 571 if (gjc && gjc->state != JCONN_STATE_OFF) { |
572 /* | |
573 * JFIXME: No error detection?!?! | |
574 */ | |
3630 | 575 #ifndef _WIN32 |
2956 | 576 if(write(gjc->fd, str, strlen(str)) < 0) { |
3630 | 577 #else |
578 if(send(gjc->fd, str, strlen(str), 0) < 0) { | |
579 #endif | |
6076 | 580 gaim_connection_error(GJ_GC(gjc), _("Write error")); |
2956 | 581 } |
4450 | 582 /* printing keepalives to the debug window is really annoying */ |
583 if(strcmp(str, JABBER_KEEPALIVE_STRING)) | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
584 gaim_debug(GAIM_DEBUG_MISC, "jabber", "gjab_send_raw: %s\n", str); |
2086 | 585 } |
586 } | |
587 | |
2956 | 588 static void gjab_reqroster(gjconn gjc) |
2086 | 589 { |
590 xmlnode x; | |
591 | |
592 x = jutil_iqnew(JPACKET__GET, NS_ROSTER); | |
2956 | 593 xmlnode_put_attrib(x, "id", gjab_getid(gjc)); |
594 | |
595 gjab_send(gjc, x); | |
2086 | 596 xmlnode_free(x); |
597 } | |
598 | |
2956 | 599 static void gjab_reqauth(gjconn gjc) |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
600 { |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
601 xmlnode x, y, z; |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
602 char *user; |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
603 |
2956 | 604 if (!gjc) |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
605 return; |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
606 |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
607 x = jutil_iqnew(JPACKET__GET, NS_AUTH); |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
608 xmlnode_put_attrib(x, "id", IQID_AUTH); |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
609 y = xmlnode_get_tag(x, "query"); |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
610 |
2956 | 611 user = gjc->user->user; |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
612 |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
613 if (user) { |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
614 z = xmlnode_insert_tag(y, "username"); |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
615 xmlnode_insert_cdata(z, user, -1); |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
616 } |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
617 |
2956 | 618 gjab_send(gjc, x); |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
619 xmlnode_free(x); |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
620 } |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
621 |
2956 | 622 static void gjab_auth(gjconn gjc) |
2086 | 623 { |
624 xmlnode x, y, z; | |
625 char *hash, *user; | |
626 | |
2956 | 627 if (!gjc) |
2086 | 628 return; |
629 | |
630 x = jutil_iqnew(JPACKET__SET, NS_AUTH); | |
631 xmlnode_put_attrib(x, "id", IQID_AUTH); | |
632 y = xmlnode_get_tag(x, "query"); | |
633 | |
2956 | 634 user = gjc->user->user; |
2086 | 635 |
636 if (user) { | |
637 z = xmlnode_insert_tag(y, "username"); | |
638 xmlnode_insert_cdata(z, user, -1); | |
639 } | |
640 | |
641 z = xmlnode_insert_tag(y, "resource"); | |
2956 | 642 xmlnode_insert_cdata(z, gjc->user->resource, -1); |
643 | |
644 if (gjc->sid) { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
645 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
646 "digest authentication (sid %s)\n", gjc->sid); |
2086 | 647 z = xmlnode_insert_tag(y, "digest"); |
2956 | 648 hash = pmalloc(x->p, strlen(gjc->sid) + strlen(gjc->pass) + 1); |
649 strcpy(hash, gjc->sid); | |
650 strcat(hash, gjc->pass); | |
2086 | 651 hash = shahash(hash); |
652 xmlnode_insert_cdata(z, hash, 40); | |
653 } else { | |
654 z = xmlnode_insert_tag(y, "password"); | |
2956 | 655 xmlnode_insert_cdata(z, gjc->pass, -1); |
2086 | 656 } |
657 | |
2956 | 658 gjab_send(gjc, x); |
2086 | 659 xmlnode_free(x); |
660 | |
661 return; | |
662 } | |
663 | |
2956 | 664 static void gjab_recv(gjconn gjc) |
2086 | 665 { |
666 static char buf[4096]; | |
667 int len; | |
668 | |
2956 | 669 if (!gjc || gjc->state == JCONN_STATE_OFF) |
2086 | 670 return; |
3630 | 671 #ifndef _WIN32 |
3234 | 672 if ((len = read(gjc->fd, buf, sizeof(buf) - 1)) > 0) { |
3630 | 673 #else |
674 if ((len = recv(gjc->fd, buf, sizeof(buf) - 1, 0)) > 0) { | |
675 #endif | |
2086 | 676 buf[len] = '\0'; |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
677 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
678 "input (len %d): %s\n", len, buf); |
2956 | 679 XML_Parse(gjc->parser, buf, len, 0); |
3105 | 680 } else if (len < 0 || errno != EAGAIN) { |
2086 | 681 STATE_EVT(JCONN_STATE_OFF) |
682 } | |
683 } | |
684 | |
685 static void startElement(void *userdata, const char *name, const char **attribs) | |
686 { | |
687 xmlnode x; | |
2956 | 688 gjconn gjc = (gjconn) userdata; |
689 | |
690 if (gjc->current) { | |
2086 | 691 /* Append the node to the current one */ |
2956 | 692 x = xmlnode_insert_tag(gjc->current, name); |
2086 | 693 xmlnode_put_expat_attribs(x, attribs); |
694 | |
2956 | 695 gjc->current = x; |
2086 | 696 } else { |
697 x = xmlnode_new_tag(name); | |
698 xmlnode_put_expat_attribs(x, attribs); | |
699 if (strcmp(name, "stream:stream") == 0) { | |
700 /* special case: name == stream:stream */ | |
701 /* id attrib of stream is stored for digest auth */ | |
2956 | 702 gjc->sid = g_strdup(xmlnode_get_attrib(x, "id")); |
2086 | 703 /* STATE_EVT(JCONN_STATE_AUTH) */ |
2635
8c75e59e4bdf
[gaim-migrate @ 2648]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2607
diff
changeset
|
704 xmlnode_free(x); |
2086 | 705 } else { |
2956 | 706 gjc->current = x; |
2086 | 707 } |
708 } | |
709 } | |
710 | |
711 static void endElement(void *userdata, const char *name) | |
712 { | |
2956 | 713 gjconn gjc = (gjconn) userdata; |
2086 | 714 xmlnode x; |
715 jpacket p; | |
716 | |
2956 | 717 if (gjc->current == NULL) { |
2086 | 718 /* we got </stream:stream> */ |
719 STATE_EVT(JCONN_STATE_OFF) | |
720 return; | |
721 } | |
722 | |
2956 | 723 x = xmlnode_get_parent(gjc->current); |
2086 | 724 |
725 if (!x) { | |
726 /* it is time to fire the event */ | |
2956 | 727 p = jpacket_new(gjc->current); |
728 | |
729 if (gjc->on_packet) | |
730 (gjc->on_packet) (gjc, p); | |
2086 | 731 else |
2956 | 732 xmlnode_free(gjc->current); |
2086 | 733 } |
734 | |
2956 | 735 gjc->current = x; |
2086 | 736 } |
737 | |
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
738 static void jabber_callback(gpointer data, gint source, GaimInputCondition condition) |
2086 | 739 { |
5572 | 740 GaimConnection *gc = data; |
2086 | 741 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; |
742 | |
2956 | 743 gjab_recv(jd->gjc); |
2086 | 744 } |
745 | |
746 static void charData(void *userdata, const char *s, int slen) | |
747 { | |
2956 | 748 gjconn gjc = (gjconn) userdata; |
749 | |
750 if (gjc->current) | |
751 xmlnode_insert_cdata(gjc->current, s, slen); | |
2086 | 752 } |
753 | |
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
754 static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) |
2086 | 755 { |
756 xmlnode x; | |
757 char *t, *t2; | |
5572 | 758 GaimConnection *gc = data; |
2086 | 759 struct jabber_data *jd; |
2956 | 760 gjconn gjc; |
2086 | 761 |
5578
847ad796326d
[gaim-migrate @ 5982]
Christian Hammond <chipx86@chipx86.com>
parents:
5572
diff
changeset
|
762 if (!g_list_find(gaim_connections_get_all(), gc)) { |
2086 | 763 close(source); |
764 return; | |
765 } | |
766 | |
767 jd = gc->proto_data; | |
2956 | 768 gjc = jd->gjc; |
769 | |
4366 | 770 gjc->fd = source; |
2300
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
771 |
2086 | 772 if (source == -1) { |
773 STATE_EVT(JCONN_STATE_OFF) | |
774 return; | |
775 } | |
776 | |
2956 | 777 gjc->state = JCONN_STATE_CONNECTED; |
2086 | 778 STATE_EVT(JCONN_STATE_CONNECTED) |
779 | |
780 /* start stream */ | |
2956 | 781 x = jutil_header(NS_CLIENT, gjc->user->server); |
2086 | 782 t = xmlnode2str(x); |
783 /* this is ugly, we can create the string here instead of jutil_header */ | |
784 /* what do you think about it? -madcat */ | |
785 t2 = strstr(t, "/>"); | |
786 *t2++ = '>'; | |
787 *t2 = '\0'; | |
2956 | 788 gjab_send_raw(gjc, "<?xml version='1.0'?>"); |
789 gjab_send_raw(gjc, t); | |
2086 | 790 xmlnode_free(x); |
791 | |
2956 | 792 gjc->state = JCONN_STATE_ON; |
2086 | 793 STATE_EVT(JCONN_STATE_ON); |
794 | |
2956 | 795 gc = GJ_GC(gjc); |
796 gc->inpa = gaim_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc); | |
2086 | 797 } |
798 | |
2956 | 799 static void gjab_start(gjconn gjc) |
2086 | 800 { |
5572 | 801 GaimAccount *account; |
4366 | 802 int port, rc; |
5613 | 803 const char *connect_server; |
5572 | 804 const char *server; |
2086 | 805 |
2956 | 806 if (!gjc || gjc->state != JCONN_STATE_OFF) |
2086 | 807 return; |
808 | |
4491 | 809 account = GJ_GC(gjc)->account; |
5572 | 810 port = gaim_account_get_int(account, "port", DEFAULT_PORT); |
5613 | 811 connect_server = gaim_account_get_string(account, "connect_server", ""); |
812 server = connect_server[0] ? connect_server : gjc->user->server; | |
813 | |
2086 | 814 |
2956 | 815 gjc->parser = XML_ParserCreate(NULL); |
816 XML_SetUserData(gjc->parser, (void *)gjc); | |
817 XML_SetElementHandler(gjc->parser, startElement, endElement); | |
818 XML_SetCharacterDataHandler(gjc->parser, charData); | |
819 | |
5681
46d7ad0dfa26
[gaim-migrate @ 6100]
Christian Hammond <chipx86@chipx86.com>
parents:
5679
diff
changeset
|
820 rc = gaim_proxy_connect(account, server, port, gjab_connected, GJ_GC(gjc)); |
4491 | 821 if (!account->gc || (rc != 0)) { |
2086 | 822 STATE_EVT(JCONN_STATE_OFF) |
823 return; | |
824 } | |
825 } | |
826 | |
2956 | 827 /* |
828 * Find chat by chat group name | |
829 */ | |
5679 | 830 static GaimConversation *find_chat(GaimConnection *gc, char *name) |
2086 | 831 { |
832 GSList *bcs = gc->buddy_chats; | |
5679 | 833 GaimConversation *b = NULL; |
2086 | 834 char *chat = g_strdup(normalize(name)); |
835 | |
836 while (bcs) { | |
837 b = bcs->data; | |
838 if (!strcasecmp(normalize(b->name), chat)) | |
839 break; | |
840 b = NULL; | |
841 bcs = bcs->next; | |
842 } | |
843 | |
844 g_free(chat); | |
845 return b; | |
846 } | |
847 | |
2956 | 848 /* |
849 * Find chat by "chat id" | |
850 * | |
851 * Returns: 0 on success and jabber_chat pointer set | |
852 * or -EINVAL on error and jabber_chat pointer is | |
853 * undefined. | |
854 * | |
855 * TBD: Slogging through the buddy_chats list seems | |
856 * redundant since the chat i.d. is mirrored in the | |
857 * jabber_chat struct list. But that's the way it | |
858 * was, so that's the way I'm leaving it--for now. | |
859 */ | |
5572 | 860 static int jabber_find_chat_by_convo_id(GaimConnection *gc, int id, struct jabber_chat **jc) |
2086 | 861 { |
2956 | 862 GSList *bcs = gc->buddy_chats; |
5679 | 863 GaimConversation *b = NULL; |
2956 | 864 struct jabber_data *jd = gc->proto_data; |
865 | |
866 *jc = NULL; | |
867 | |
868 while(bcs != NULL) { | |
869 b = bcs->data; | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
870 if (id == gaim_chat_get_id(GAIM_CHAT(b))) |
2956 | 871 break; |
872 bcs = bcs->next; | |
873 } | |
874 | |
875 if (bcs != NULL) { | |
876 bcs = jd->chats; | |
877 while (bcs != NULL) { | |
878 *jc = bcs->data; | |
879 if ((*jc)->state == JCS_ACTIVE && (*jc)->b == b) | |
880 break; | |
881 bcs = bcs->next; | |
882 } | |
883 } | |
884 | |
885 return(bcs == NULL? -EINVAL : 0); | |
886 } | |
887 | |
888 /* | |
889 * Find any chat | |
890 */ | |
5572 | 891 static struct jabber_chat *find_any_chat(GaimConnection *gc, jid chat) |
2956 | 892 { |
893 GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; | |
2086 | 894 struct jabber_chat *jc = NULL; |
895 | |
2956 | 896 while (jcs) { |
897 jc = jcs->data; | |
3311 | 898 if (!jid_cmpx(chat, jc->gjid, JID_USER | JID_SERVER)) |
2086 | 899 break; |
900 jc = NULL; | |
2956 | 901 jcs = jcs->next; |
2086 | 902 } |
903 | |
904 return jc; | |
905 } | |
906 | |
2956 | 907 |
908 /* | |
909 * Find existing/active Jabber chat | |
910 */ | |
5572 | 911 static struct jabber_chat *find_existing_chat(GaimConnection *gc, jid chat) |
2956 | 912 { |
913 GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; | |
914 struct jabber_chat *jc = NULL; | |
915 | |
916 while (jcs) { | |
917 jc = jcs->data; | |
3311 | 918 if (jc->state == JCS_ACTIVE && !jid_cmpx(chat, jc->gjid, JID_USER | JID_SERVER)) |
2956 | 919 break; |
920 jc = NULL; | |
921 jcs = jcs->next; | |
922 } | |
923 | |
924 return jc; | |
925 } | |
926 | |
927 /* | |
928 * Find pending chat | |
929 */ | |
5572 | 930 static struct jabber_chat *find_pending_chat(GaimConnection *gc, jid chat) |
2086 | 931 { |
2956 | 932 GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; |
2086 | 933 struct jabber_chat *jc = NULL; |
934 | |
2956 | 935 while (jcs) { |
936 jc = jcs->data; | |
3311 | 937 if (jc->state == JCS_PENDING && !jid_cmpx(chat, jc->gjid, JID_USER | JID_SERVER)) |
2086 | 938 break; |
939 jc = NULL; | |
2956 | 940 jcs = jcs->next; |
2086 | 941 } |
942 | |
943 return jc; | |
944 } | |
945 | |
5679 | 946 static gboolean find_chat_buddy(GaimConversation *b, char *name) |
2086 | 947 { |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
948 GList *m = gaim_chat_get_users(GAIM_CHAT(b)); |
2086 | 949 |
950 while (m) { | |
951 if (!strcmp(m->data, name)) | |
952 return TRUE; | |
953 m = m->next; | |
954 } | |
955 | |
956 return FALSE; | |
957 } | |
958 | |
2956 | 959 /* |
3236 | 960 * Remove a buddy from the (gaim) buddylist (if he's on it) |
961 */ | |
5572 | 962 static void jabber_remove_gaim_buddy(GaimConnection *gc, const char *buddyname) |
3236 | 963 { |
964 struct buddy *b; | |
965 | |
4687 | 966 if ((b = gaim_find_buddy(gc->account, buddyname)) != NULL) { |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
967 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
968 "removing buddy [1]: %s\n", buddyname); |
4687 | 969 gaim_blist_remove_buddy(b); |
4349 | 970 gaim_blist_save(); |
3236 | 971 } |
972 } | |
973 | |
5572 | 974 static void jabber_change_passwd(GaimConnection *gc, const char *old, const char *new) |
3257 | 975 { |
976 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; | |
977 | |
978 if(strcmp(old, gjc->pass)) | |
979 { | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
980 gaim_notify_error(gc, NULL, |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
981 _("Unable to change password."), |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
982 _("The current password you entered is incorrect. " |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
983 "Your password has not been changed.")); |
3257 | 984 } |
985 else if(!strcmp(old, new)) | |
986 { | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
987 gaim_notify_error(gc, NULL, |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
988 _("Unable to change password"), |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
989 _("The new password you entered is the same as " |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
990 "your current password. " |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
991 "Your password remains the same.")); |
3257 | 992 } |
993 else | |
994 { | |
995 xmlnode x, y, z; | |
996 char *id; | |
997 | |
998 x = jutil_iqnew(JPACKET__SET, NS_REGISTER); | |
999 xmlnode_put_attrib(x, "to", gjc->user->server); | |
1000 y = xmlnode_get_tag(x, "query"); | |
1001 z = xmlnode_insert_tag(y, "username"); | |
1002 xmlnode_insert_cdata(z, gjc->user->user, -1); | |
1003 z = xmlnode_insert_tag(y, "password"); | |
1004 xmlnode_insert_cdata(z, new, -1); | |
1005 | |
1006 id = gjab_getid(gjc); | |
1007 xmlnode_put_attrib(x, "id", id); | |
1008 | |
1009 free(gjc->pass); | |
1010 gjc->pass = strdup(new); | |
1011 | |
1012 g_hash_table_insert(gjc->queries, g_strdup(id), g_strdup("change_password")); | |
1013 | |
1014 gjab_send(gjc, x); | |
1015 xmlnode_free(x); | |
1016 } | |
1017 } | |
3311 | 1018 |
3340 | 1019 /* |
1020 * Return pointer to jabber_buddy_data if buddy found. Create if necessary. | |
1021 */ | |
5572 | 1022 static struct jabber_buddy_data* jabber_find_buddy(GaimConnection *gc, const char *buddy, gboolean create) |
3311 | 1023 { |
1024 struct jabber_data *jd = gc->proto_data; | |
1025 gpointer val; | |
1026 char *realwho; | |
1027 | |
1028 if((realwho = get_realwho(jd->gjc, buddy, FALSE, NULL)) == NULL) | |
1029 return NULL; | |
1030 | |
1031 val = g_hash_table_lookup(jd->buddies, realwho); | |
1032 if(val) { | |
1033 g_free(realwho); | |
1034 return (struct jabber_buddy_data *)val; | |
1035 | |
5135 | 1036 } else if (create) { |
3311 | 1037 struct jabber_buddy_data *jbd = g_new0(struct jabber_buddy_data, 1); |
3340 | 1038 jbd->invisible = JABBER_NOT_INVIS; |
3311 | 1039 g_hash_table_insert(jd->buddies, g_strdup(realwho), jbd); |
1040 g_free(realwho); | |
1041 return jbd; | |
5135 | 1042 } else { |
5940 | 1043 g_free(realwho); |
5135 | 1044 return NULL; |
3311 | 1045 } |
1046 } | |
3770 | 1047 |
3236 | 1048 /* |
3311 | 1049 * find a resource by name, or if no name given, return the "default" resource |
3770 | 1050 * default being the highest priority one. |
3311 | 1051 */ |
1052 | |
5572 | 1053 static jab_res_info jabber_find_resource(GaimConnection *gc, const char *who) |
3311 | 1054 { |
1055 GSList *resources; | |
5135 | 1056 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, who, FALSE); |
3311 | 1057 jab_res_info jri = NULL; |
1058 char *res = strstr(who, "/"); | |
1059 | |
1060 if(res) | |
1061 res++; | |
1062 | |
1063 if(jbd) | |
1064 { | |
1065 resources = jbd->resources; | |
1066 while(resources) | |
1067 { | |
1068 if(!jri && !res) { | |
1069 jri = (jab_res_info) resources->data; | |
1070 } else if(!res) { /* we're looking for the default priority, so... */ | |
1071 if(((jab_res_info) resources->data)->priority >= jri->priority) | |
1072 jri = (jab_res_info) resources->data; | |
3337 | 1073 } else if(((jab_res_info)resources->data)->name) { |
3311 | 1074 if(!strcasecmp(((jab_res_info) resources->data)->name, res)) { |
1075 jri = (jab_res_info) resources->data; | |
1076 break; | |
1077 } | |
1078 } | |
1079 resources = resources->next; | |
1080 } | |
1081 } | |
1082 | |
1083 return jri; | |
1084 } | |
1085 | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
1086 #if 0 |
5572 | 1087 static gboolean jabber_is_default_resource(GaimConnection *gc, const char *who) |
5291 | 1088 { |
1089 jab_res_info jri = jabber_find_resource(gc, who); | |
1090 char *buddy = g_strdup(who); | |
1091 char *resource = strrchr(buddy, '/'); | |
1092 | |
1093 if(!resource || !strcmp(resource+1, jri->name)) { | |
1094 g_free(buddy); | |
1095 return TRUE; | |
1096 } | |
1097 | |
1098 g_free(buddy); | |
1099 return FALSE; | |
1100 } | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
1101 #endif |
5291 | 1102 |
3311 | 1103 /* |
1104 * if the resource doesn't exist, create it. otherwise, just update the priority | |
2956 | 1105 */ |
5572 | 1106 static void jabber_track_resource(GaimConnection *gc, |
3311 | 1107 char *buddy, |
1108 char *res, | |
1109 int priority, | |
1110 int state) | |
1111 { | |
5135 | 1112 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, TRUE); |
3311 | 1113 |
3337 | 1114 if(jbd) { |
1115 char *who; | |
1116 jab_res_info jri; | |
1117 if(res) | |
1118 who = g_strdup_printf("%s/%s", buddy, res); | |
1119 else | |
1120 who = g_strdup(buddy); | |
1121 jri = jabber_find_resource(gc, who); | |
3311 | 1122 g_free(who); |
1123 if(!jri) { | |
1124 jri = g_new0(struct jabber_resource_info, 1); | |
1125 jri->name = g_strdup(res); | |
1126 jri->away_msg = NULL; | |
5093 | 1127 jri->has_xhtml = TRUE; |
3311 | 1128 jbd->resources = g_slist_append(jbd->resources, jri); |
1129 } | |
1130 jri->priority = priority; | |
1131 jri->state = state; | |
1132 } | |
1133 } | |
1134 | |
1135 /* | |
1136 * remove the resource, if it exists | |
1137 */ | |
5572 | 1138 static void jabber_remove_resource(GaimConnection *gc, char *buddy, char *res) |
2956 | 1139 { |
5135 | 1140 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, FALSE); |
3337 | 1141 if(jbd) { |
1142 char *who; | |
1143 jab_res_info jri; | |
1144 if(res) | |
1145 who = g_strdup_printf("%s/%s", buddy, res); | |
1146 else | |
1147 who = g_strdup(buddy); | |
1148 jri = jabber_find_resource(gc, who); | |
3311 | 1149 g_free(who); |
1150 if(jri) { | |
3337 | 1151 if(jri->name) |
1152 g_free(jri->name); | |
3311 | 1153 if(jri->away_msg) |
1154 g_free(jri->away_msg); | |
1155 jbd->resources = g_slist_remove(jbd->resources, jri); | |
1156 g_free(jri); | |
1157 } | |
1158 } | |
1159 } | |
1160 | |
1161 /* | |
1162 * grab the away message for the default resource | |
1163 */ | |
1164 static char *jabber_lookup_away(gjconn gjc, char *name) | |
1165 { | |
1166 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); | |
1167 | |
4745 | 1168 if(!jri) |
3311 | 1169 return _("Unknown"); |
1170 | |
1171 return jri->away_msg; | |
1172 } | |
4745 | 1173 static const char *jabber_get_state_string(int s) { |
1174 switch(s) { | |
1175 case UC_AWAY: | |
1176 return _("Away"); | |
1177 case UC_CHAT: | |
1178 return _("Chatty"); | |
1179 case UC_XA: | |
1180 return _("Extended Away"); | |
1181 case UC_DND: | |
1182 return _("Do Not Disturb"); | |
1183 default: | |
1184 return _("Available"); | |
1185 } | |
1186 } | |
3311 | 1187 |
1188 static void jabber_track_away(gjconn gjc, jpacket p, char *type) | |
1189 { | |
1190 jab_res_info jri = NULL; | |
1191 | |
3337 | 1192 if(!p || !p->from || !p->from->user) |
3311 | 1193 return; |
1194 | |
1195 jri = jabber_find_resource(GJ_GC(gjc), jid_full(p->from)); | |
1196 | |
1197 if(!jri) | |
1198 return; | |
3770 | 1199 |
3311 | 1200 if(jri->away_msg) |
1201 g_free(jri->away_msg); | |
1202 | |
4745 | 1203 jri->away_msg = g_strdup(xmlnode_get_tag_data(p->x, "status")); |
3311 | 1204 } |
1205 | |
6059 | 1206 static void jabber_convo_closed(GaimConnection *gc, const char *name) |
3311 | 1207 { |
1208 jab_res_info jri = jabber_find_resource(gc, name); | |
1209 | |
1210 if(jri) { | |
1211 if(jri->thread_id) | |
1212 g_free(jri->thread_id); | |
1213 | |
1214 jri->thread_id = NULL; | |
2956 | 1215 } |
1216 } | |
1217 | |
3311 | 1218 static void jabber_track_convo_thread(gjconn gjc, char *name, char *thread_id) |
1219 { | |
1220 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); | |
1221 | |
1222 if(jri) { | |
1223 if(jri->thread_id) | |
1224 g_free(jri->thread_id); | |
1225 | |
1226 jri->thread_id = g_strdup(thread_id); | |
1227 } | |
1228 } | |
1229 | |
5136 | 1230 static char *jabber_get_convo_thread(gjconn gjc, const char *name) |
3311 | 1231 { |
1232 char *ct = NULL; | |
1233 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); | |
1234 | |
1235 if(jri) { | |
1236 if(jri->thread_id) | |
1237 ct = g_strdup(jri->thread_id); | |
1238 } | |
5135 | 1239 |
3311 | 1240 return ct; |
1241 } | |
1242 | |
1243 | |
5426 | 1244 static time_t str_to_time(char *timestamp) |
3159 | 1245 { |
5426 | 1246 struct tm t; |
1247 time_t retval = 0; | |
1248 char buf[32]; | |
1249 char *c; | |
1250 int tzoff = 0; | |
1251 | |
1252 time(&retval); | |
1253 localtime_r(&retval, &t); | |
1254 | |
1255 snprintf(buf, sizeof(buf), "%s", timestamp); | |
1256 c = buf; | |
1257 | |
1258 /* 4 digit year */ | |
1259 if(!sscanf(c, "%04d", &t.tm_year)) return 0; | |
1260 c+=4; | |
1261 if(*c == '-') | |
1262 c++; | |
1263 | |
1264 t.tm_year -= 1900; | |
1265 | |
1266 /* 2 digit month */ | |
1267 if(!sscanf(c, "%02d", &t.tm_mon)) return 0; | |
1268 c+=2; | |
1269 if(*c == '-') | |
1270 c++; | |
1271 | |
1272 t.tm_mon -= 1; | |
1273 | |
1274 /* 2 digit day */ | |
1275 if(!sscanf(c, "%02d", &t.tm_mday)) return 0; | |
1276 c+=2; | |
1277 | |
1278 if(*c == 'T') { /* we have more than a date, keep going */ | |
1279 c++; /* skip the "T" */ | |
1280 | |
1281 /* 2 digit hour */ | |
1282 if(sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec)) { | |
1283 int tzhrs, tzmins; | |
1284 c+=8; | |
1285 if(*c == '.') /* dealing with precision we don't care about */ | |
1286 c += 4; | |
1287 | |
1288 if((*c == '+' || *c == '-') && | |
1289 sscanf(c+1, "%02d:%02d", &tzhrs, &tzmins)) { | |
1290 tzoff = tzhrs*60*60 + tzmins*60; | |
1291 if(*c == '+') | |
1292 tzoff *= -1; | |
5279 | 1293 } |
5426 | 1294 |
1295 #ifdef HAVE_TM_GMTOFF | |
1296 tzoff += t.tm_gmtoff; | |
1297 #else | |
1298 # ifdef HAVE_TIMEZONE | |
1299 tzset(); /* making sure */ | |
1300 tzoff -= timezone; | |
1301 # endif | |
1302 #endif | |
5279 | 1303 } |
3229 | 1304 } |
5426 | 1305 retval = mktime(&t); |
1306 | |
1307 retval += tzoff; | |
1308 | |
1309 return retval; | |
3159 | 1310 } |
1311 | |
2956 | 1312 static void jabber_handlemessage(gjconn gjc, jpacket p) |
2086 | 1313 { |
3311 | 1314 xmlnode y, subj; |
3159 | 1315 time_t time_sent = time(NULL); |
3311 | 1316 gboolean typing = FALSE; |
5093 | 1317 gboolean has_xhtml = TRUE; |
2086 | 1318 |
1319 char *from = NULL, *msg = NULL, *type = NULL, *topic = NULL; | |
3311 | 1320 char *thread_id = NULL; |
1321 char *conference_room = NULL; | |
2086 | 1322 char m[BUF_LONG * 2]; |
1323 | |
1324 type = xmlnode_get_attrib(p->x, "type"); | |
3769 | 1325 |
3311 | 1326 if ((y = xmlnode_get_tag(p->x, "thread"))) |
1327 thread_id = xmlnode_get_data(y); | |
1328 | |
1329 y = xmlnode_get_firstchild(p->x); | |
1330 | |
1331 while(y) { | |
1332 if(NSCHECK(y, NS_DELAY)) { | |
1333 char *timestamp = xmlnode_get_attrib(y, "stamp"); | |
5426 | 1334 if(timestamp) |
1335 time_sent = str_to_time(timestamp); | |
3311 | 1336 } else if(NSCHECK(y, "jabber:x:event")) { |
1337 if(xmlnode_get_tag(y, "composing")) | |
1338 typing = TRUE; | |
1339 } else if(NSCHECK(y, "jabber:x:conference")) { | |
1340 conference_room = xmlnode_get_attrib(y, "jid"); | |
1341 } | |
1342 y = xmlnode_get_nextsibling(y); | |
3159 | 1343 } |
1344 | |
2086 | 1345 if (!type || !strcasecmp(type, "normal") || !strcasecmp(type, "chat")) { |
1346 | |
1347 from = jid_full(p->from); | |
1348 if ((y = xmlnode_get_tag(p->x, "html"))) { | |
5093 | 1349 msg = xmlnode2str(y); |
1350 } else if ((y = xmlnode_get_tag(p->x, "body"))) { | |
2086 | 1351 msg = xmlnode_get_data(y); |
5093 | 1352 has_xhtml = FALSE; |
2086 | 1353 } |
1354 | |
1355 if (!from) | |
1356 return; | |
1357 | |
3311 | 1358 if (conference_room) { |
5234 | 1359 GHashTable *components = g_hash_table_new_full(g_str_hash, |
1360 g_str_equal, g_free, g_free); | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1361 char **data; |
2086 | 1362 |
3311 | 1363 data = g_strsplit(conference_room, "@", 2); |
5234 | 1364 g_hash_table_replace(components, g_strdup("room"), |
1365 g_strdup(data[0])); | |
1366 g_hash_table_replace(components, g_strdup("server"), | |
1367 g_strdup(data[1])); | |
1368 g_hash_table_replace(components, g_strdup("handle"), | |
1369 g_strdup(gjc->user->user)); | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1370 g_strfreev(data); |
2086 | 1371 |
5234 | 1372 serv_got_chat_invite(GJ_GC(gjc), conference_room, from, msg, components); |
2086 | 1373 } else if (msg) { /* whisper */ |
1374 struct jabber_chat *jc; | |
1375 g_snprintf(m, sizeof(m), "%s", msg); | |
2956 | 1376 if (((jc = find_existing_chat(GJ_GC(gjc), p->from)) != NULL) && jc->b) |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1377 serv_got_chat_in(GJ_GC(gjc), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1378 gaim_chat_get_id(GAIM_CHAT(jc->b)), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1379 p->from->resource, 1, m, time_sent); |
2086 | 1380 else { |
2278
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
1381 int flags = 0; |
3769 | 1382 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), from); |
5093 | 1383 if(jri) { |
1384 if(typing) | |
1385 jri->has_composing = TRUE; | |
1386 jri->has_xhtml = has_xhtml; | |
1387 } | |
3769 | 1388 jabber_track_convo_thread(gjc, from, thread_id); |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1389 if (gaim_find_conversation(from)) |
3769 | 1390 serv_got_im(GJ_GC(gjc), from, m, flags, |
3311 | 1391 time_sent, -1); |
2086 | 1392 else { |
2956 | 1393 if(p->from->user) { |
3311 | 1394 from = g_strdup_printf("%s@%s", p->from->user, |
1395 p->from->server); | |
2956 | 1396 } else { |
3311 | 1397 /* server message? */ |
1398 from = g_strdup(p->from->server); | |
2956 | 1399 } |
3159 | 1400 serv_got_im(GJ_GC(gjc), from, m, flags, time_sent, -1); |
2086 | 1401 g_free(from); |
1402 } | |
1403 } | |
3311 | 1404 } else { |
1405 /* a non-message message! */ | |
1406 from = g_strdup_printf("%s@%s", p->from->user, p->from->server); | |
1407 if(typing) | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
1408 serv_got_typing(GJ_GC(gjc), from, 0, GAIM_TYPING); |
3311 | 1409 else |
1410 serv_got_typing_stopped(GJ_GC(gjc), from); | |
1411 g_free(from); | |
2086 | 1412 } |
1413 | |
1414 } else if (!strcasecmp(type, "error")) { | |
1415 if ((y = xmlnode_get_tag(p->x, "error"))) { | |
1416 type = xmlnode_get_attrib(y, "code"); | |
1417 msg = xmlnode_get_data(y); | |
1418 } | |
1419 | |
1420 if (msg) { | |
3427 | 1421 from = g_strdup_printf(_("Jabber Error %s"), type ? type : ""); |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
1422 gaim_notify_error(GJ_GC(gjc), NULL, from, msg); |
2086 | 1423 g_free(from); |
1424 } | |
1425 } else if (!strcasecmp(type, "groupchat")) { | |
1426 struct jabber_chat *jc; | |
1427 static int i = 0; | |
1428 | |
1429 if ((y = xmlnode_get_tag(p->x, "html"))) { | |
5093 | 1430 msg = xmlnode2str(y); |
1431 } else if ((y = xmlnode_get_tag(p->x, "body"))) { | |
2086 | 1432 msg = xmlnode_get_data(y); |
1433 } | |
1434 | |
1435 if ((subj = xmlnode_get_tag(p->x, "subject"))) { | |
3770 | 1436 topic = xmlnode_get_data(subj); |
1437 } | |
2086 | 1438 |
2956 | 1439 jc = find_existing_chat(GJ_GC(gjc), p->from); |
2086 | 1440 if (!jc) { |
1441 /* we're not in this chat. are we supposed to be? */ | |
2956 | 1442 if ((jc = find_pending_chat(GJ_GC(gjc), p->from)) != NULL) { |
2086 | 1443 /* yes, we're supposed to be. so now we are. */ |
2956 | 1444 jc->b = serv_got_joined_chat(GJ_GC(gjc), i++, p->from->user); |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1445 jc->id = gaim_chat_get_id(GAIM_CHAT(jc->b)); |
2956 | 1446 jc->state = JCS_ACTIVE; |
2086 | 1447 } else { |
1448 /* no, we're not supposed to be. */ | |
1449 g_free(msg); | |
1450 return; | |
1451 } | |
1452 } | |
1453 if (p->from->resource) { | |
1454 if (!y) { | |
2956 | 1455 if (!find_chat_buddy(jc->b, p->from->resource)) { |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1456 gaim_chat_add_user(GAIM_CHAT(jc->b), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1457 p->from->resource, NULL); |
2956 | 1458 } else if ((y = xmlnode_get_tag(p->x, "status"))) { |
3311 | 1459 jabber_track_away(gjc, p, NULL); |
2086 | 1460 } |
1461 } else if (jc->b && msg) { | |
1462 char buf[8192]; | |
1463 | |
1464 if (topic) { | |
1465 char tbuf[8192]; | |
1466 g_snprintf(tbuf, sizeof(tbuf), "%s", topic); | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1467 gaim_chat_set_topic(GAIM_CHAT(jc->b), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1468 p->from->resource, tbuf); |
2086 | 1469 } |
1470 | |
1471 g_snprintf(buf, sizeof(buf), "%s", msg); | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1472 serv_got_chat_in(GJ_GC(gjc), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1473 gaim_chat_get_id(GAIM_CHAT(jc->b)), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1474 p->from->resource, 0, buf, time_sent); |
2086 | 1475 } |
1476 } else { /* message from the server */ | |
3770 | 1477 if(jc->b && topic) { |
1478 char tbuf[8192]; | |
2086 | 1479 g_snprintf(tbuf, sizeof(tbuf), "%s", topic); |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1480 gaim_chat_set_topic(GAIM_CHAT(jc->b), "", tbuf); |
2086 | 1481 } |
1482 } | |
1483 | |
1484 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1485 gaim_debug(GAIM_DEBUG_WARNING, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1486 "unhandled message %s\n", type); |
2086 | 1487 } |
1488 } | |
3770 | 1489 |
2956 | 1490 static void jabber_handlepresence(gjconn gjc, jpacket p) |
2086 | 1491 { |
1492 char *to, *from, *type; | |
1493 struct buddy *b = NULL; | |
3311 | 1494 gaim_jid gjid; |
2086 | 1495 char *buddy; |
3194 | 1496 xmlnode y; |
2086 | 1497 char *show; |
2501
227cc42ffa6e
[gaim-migrate @ 2514]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2382
diff
changeset
|
1498 int state = 0; |
5679 | 1499 GaimConversation *cnv = NULL; |
2086 | 1500 struct jabber_chat *jc = NULL; |
3311 | 1501 int priority = 0; |
1502 struct jabber_buddy_data *jbd; | |
3770 | 1503 |
2086 | 1504 to = xmlnode_get_attrib(p->x, "to"); |
1505 from = xmlnode_get_attrib(p->x, "from"); | |
1506 type = xmlnode_get_attrib(p->x, "type"); | |
3770 | 1507 |
3311 | 1508 if((buddy = get_realwho(gjc, from, FALSE, &gjid)) == NULL) |
1509 return; | |
1510 | |
1511 if (gjid->user == NULL) { | |
1512 /* FIXME: transport */ | |
1513 g_free(buddy); | |
1514 gaim_jid_free(gjid); | |
1515 return; | |
1516 } | |
1517 | |
5135 | 1518 jbd = jabber_find_buddy(GJ_GC(gjc), buddy, TRUE); |
3311 | 1519 |
1520 if(jbd->error_msg) { | |
1521 g_free(jbd->error_msg); | |
1522 jbd->error_msg = NULL; | |
1523 } | |
1524 | |
3259 | 1525 if(type && !strcasecmp(type, "error")) { |
1526 state = UC_ERROR; | |
3311 | 1527 if((y = xmlnode_get_tag(p->x, "error")) != NULL) { |
1528 jbd->error_msg = g_strdup_printf(_("Error %s: %s"), | |
1529 xmlnode_get_attrib(y, "code"), xmlnode_get_data(y)); | |
1530 } else { | |
1531 jbd->error_msg = g_strdup(_("Unknown Error in presence")); | |
1532 } | |
3259 | 1533 } else { |
1534 if ((y = xmlnode_get_tag(p->x, "show"))) { | |
1535 show = xmlnode_get_data(y); | |
1536 if (!show) { | |
1537 state = 0; | |
1538 } else if (!strcasecmp(show, "away")) { | |
1539 state = UC_AWAY; | |
1540 } else if (!strcasecmp(show, "chat")) { | |
1541 state = UC_CHAT; | |
1542 } else if (!strcasecmp(show, "xa")) { | |
1543 state = UC_XA; | |
1544 } else if (!strcasecmp(show, "dnd")) { | |
1545 state = UC_DND; | |
1546 } | |
1547 } else { | |
2501
227cc42ffa6e
[gaim-migrate @ 2514]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2382
diff
changeset
|
1548 state = 0; |
2086 | 1549 } |
1550 } | |
1551 | |
5291 | 1552 if ((y = xmlnode_get_tag(p->x, "priority"))) |
1553 priority = atoi(xmlnode_get_data(y)); | |
1554 | |
2086 | 1555 /* um. we're going to check if it's a chat. if it isn't, and there are pending |
2956 | 1556 * chats, create the chat. if there aren't pending chats and we don't have the |
1557 * buddy on our list, simply bail out. */ | |
3311 | 1558 if ((cnv = find_chat(GJ_GC(gjc), gjid->user)) == NULL) { |
2086 | 1559 static int i = 0x70; |
3311 | 1560 if ((jc = find_pending_chat(GJ_GC(gjc), gjid)) != NULL) { |
1561 jc->b = cnv = serv_got_joined_chat(GJ_GC(gjc), i++, gjid->user); | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1562 jc->id = gaim_chat_get_id(GAIM_CHAT(jc->b)); |
2956 | 1563 jc->state = JCS_ACTIVE; |
4687 | 1564 } else if ((b = gaim_find_buddy(GJ_GC(gjc)->account, buddy)) == NULL) { |
2956 | 1565 g_free(buddy); |
3311 | 1566 gaim_jid_free(gjid); |
2956 | 1567 return; |
2086 | 1568 } |
1569 } | |
1570 | |
4732 | 1571 if (state == UC_ERROR || (type && (strcasecmp(type, "unavailable") == 0))) |
3311 | 1572 jabber_remove_resource(GJ_GC(gjc), buddy, gjid->resource); |
1573 else { | |
1574 jabber_track_resource(GJ_GC(gjc), buddy, gjid->resource, priority, state); | |
1575 | |
1576 /* keep track of away msg somewhat the same as the yahoo plugin */ | |
1577 jabber_track_away(gjc, p, type); | |
1578 } | |
3770 | 1579 |
2086 | 1580 if (!cnv) { |
3311 | 1581 /* this is where we handle presence information for "regular" buddies */ |
1582 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), buddy); | |
1583 if(jri) { | |
4732 | 1584 serv_got_update(GJ_GC(gjc), buddy, 1, 0, b->signon, b->idle, jri->state); |
3311 | 1585 } else |
4732 | 1586 serv_got_update(GJ_GC(gjc), buddy, 0, 0, 0, 0, 0); |
3311 | 1587 |
2086 | 1588 } else { |
3311 | 1589 if (gjid->resource) { |
3259 | 1590 if (type && (!strcasecmp(type, "unavailable"))) { |
2086 | 1591 struct jabber_data *jd; |
3311 | 1592 if (!jc && !(jc = find_existing_chat(GJ_GC(gjc), gjid))) { |
2086 | 1593 g_free(buddy); |
3311 | 1594 gaim_jid_free(gjid); |
2086 | 1595 return; |
1596 } | |
1597 jd = jc->gc->proto_data; | |
2956 | 1598 /* if it's not ourselves...*/ |
3311 | 1599 if (strcmp(gjid->resource, jc->gjid->resource) && jc->b) { |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1600 gaim_chat_remove_user(GAIM_CHAT(jc->b), gjid->resource, |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1601 NULL); |
2086 | 1602 g_free(buddy); |
3311 | 1603 gaim_jid_free(gjid); |
2086 | 1604 return; |
1605 } | |
2956 | 1606 |
1607 jc->state = JCS_CLOSED; | |
1608 serv_got_chat_left(GJ_GC(gjc), jc->id); | |
1609 /* | |
1610 * TBD: put back some day? | |
1611 jd->chats = g_slist_remove(jd->chats, jc); | |
1612 g_free(jc); | |
1613 */ | |
1614 } else { | |
3311 | 1615 if ((!jc && !(jc = find_existing_chat(GJ_GC(gjc), gjid))) || !jc->b) { |
2956 | 1616 g_free(buddy); |
3311 | 1617 gaim_jid_free(gjid); |
2956 | 1618 return; |
1619 } | |
3311 | 1620 if (!find_chat_buddy(jc->b, gjid->resource)) { |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1621 gaim_chat_add_user(GAIM_CHAT(jc->b), gjid->resource, NULL); |
2086 | 1622 } |
1623 } | |
1624 } | |
1625 } | |
1626 | |
1627 g_free(buddy); | |
3311 | 1628 gaim_jid_free(gjid); |
2086 | 1629 |
1630 return; | |
1631 } | |
1632 | |
3229 | 1633 /* |
1634 * Used only by Jabber accept/deny add stuff just below | |
1635 */ | |
1636 struct jabber_add_permit { | |
5572 | 1637 GaimConnection *gc; |
3229 | 1638 gchar *user; |
1639 }; | |
1640 | |
1641 /* | |
1642 * Common part for Jabber accept/deny adds | |
1643 * | |
1644 * "type" says whether we'll permit/deny the subscribe request | |
1645 */ | |
1646 static void jabber_accept_deny_add(struct jabber_add_permit *jap, const char *type) | |
1647 { | |
1648 xmlnode g = xmlnode_new_tag("presence"); | |
1649 | |
1650 xmlnode_put_attrib(g, "to", jap->user); | |
1651 xmlnode_put_attrib(g, "type", type); | |
4249 | 1652 gjab_send(GC_GJ(jap->gc), g); |
3229 | 1653 |
1654 xmlnode_free(g); | |
1655 } | |
1656 | |
1657 /* | |
5498
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1658 * Callback from "accept" in gaim_request_action() invoked |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1659 * by jabber_handles10n() |
3229 | 1660 */ |
3730 | 1661 static void jabber_accept_add(struct jabber_add_permit *jap) |
3229 | 1662 { |
5578
847ad796326d
[gaim-migrate @ 5982]
Christian Hammond <chipx86@chipx86.com>
parents:
5572
diff
changeset
|
1663 if(g_list_find(gaim_connections_get_all(), jap->gc)) { |
4249 | 1664 jabber_accept_deny_add(jap, "subscribed"); |
1665 /* | |
1666 * If we don't already have the buddy on *our* buddylist, | |
1667 * ask if we want him or her added. | |
1668 */ | |
4687 | 1669 if(gaim_find_buddy(jap->gc->account, jap->user) == NULL) { |
4249 | 1670 show_got_added(jap->gc, NULL, jap->user, NULL, NULL); |
1671 } | |
3229 | 1672 } |
4249 | 1673 |
3229 | 1674 g_free(jap->user); |
1675 g_free(jap); | |
1676 } | |
1677 | |
1678 /* | |
5498
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1679 * Callback from "deny/cancel" in gaim_request_action() invoked |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1680 * by jabber_handles10n() |
3229 | 1681 */ |
3730 | 1682 static void jabber_deny_add(struct jabber_add_permit *jap) |
3229 | 1683 { |
5578
847ad796326d
[gaim-migrate @ 5982]
Christian Hammond <chipx86@chipx86.com>
parents:
5572
diff
changeset
|
1684 if(g_list_find(gaim_connections_get_all(), jap->gc)) { |
4249 | 1685 jabber_accept_deny_add(jap, "unsubscribed"); |
1686 } | |
1687 | |
3229 | 1688 g_free(jap->user); |
1689 g_free(jap); | |
1690 } | |
1691 | |
1692 /* | |
1693 * Handle subscription requests | |
1694 */ | |
2956 | 1695 static void jabber_handles10n(gjconn gjc, jpacket p) |
2086 | 1696 { |
1697 xmlnode g; | |
1698 char *Jid = xmlnode_get_attrib(p->x, "from"); | |
3136 | 1699 char *type = xmlnode_get_attrib(p->x, "type"); |
2086 | 1700 |
1701 g = xmlnode_new_tag("presence"); | |
1702 xmlnode_put_attrib(g, "to", Jid); | |
3229 | 1703 |
1704 if (!strcmp(type, "subscribe")) { | |
1705 /* | |
1706 * A "subscribe to us" request was received - put up the approval dialog | |
1707 */ | |
1708 struct jabber_add_permit *jap = g_new0(struct jabber_add_permit, 1); | |
1709 gchar *msg = g_strdup_printf(_("The user %s wants to add you to their buddy list."), | |
1710 Jid); | |
1711 | |
4249 | 1712 jap->gc = GJ_GC(gjc); |
3229 | 1713 jap->user = g_strdup(Jid); |
5498
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1714 |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1715 gaim_request_action(jap->gc, NULL, msg, NULL, 0, jap, 2, |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1716 _("Authorize"), G_CALLBACK(jabber_accept_add), |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1717 _("Deny"), G_CALLBACK(jabber_deny_add)); |
3229 | 1718 |
1719 g_free(msg); | |
1720 xmlnode_free(g); /* Never needed it here anyway */ | |
1721 return; | |
1722 | |
1723 } else if (!strcmp(type, "unsubscribe")) { | |
1724 /* | |
1725 * An "unsubscribe to us" was received - simply "approve" it | |
1726 */ | |
2086 | 1727 xmlnode_put_attrib(g, "type", "unsubscribed"); |
3229 | 1728 } else { |
1729 /* | |
1730 * Did we attempt to subscribe to somebody and they do not exist? | |
1731 */ | |
3136 | 1732 if (!strcmp(type, "unsubscribed")) { |
1733 xmlnode y; | |
1734 char *status; | |
1735 if((y = xmlnode_get_tag(p->x, "status")) && (status = xmlnode_get_data(y)) && | |
1736 !strcmp(status, "Not Found")) { | |
3427 | 1737 char *msg = g_strdup_printf(_("The Jabber user %s does not exist and was therefore " |
1738 "not added to your roster."), | |
1739 xmlnode_get_attrib(p->x, "from")); | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
1740 gaim_notify_error(GJ_GC(gjc), NULL, _("No such user."), msg); |
3136 | 1741 g_free(msg); |
1742 } | |
1743 } | |
1744 | |
2956 | 1745 xmlnode_free(g); |
2086 | 1746 return; |
2956 | 1747 } |
1748 | |
1749 gjab_send(gjc, g); | |
1750 xmlnode_free(g); | |
2086 | 1751 } |
1752 | |
2956 | 1753 /* |
1754 * Pending subscription to a buddy? | |
1755 */ | |
1756 #define BUD_SUB_TO_PEND(sub, ask) ((!strcasecmp((sub), "none") || !strcasecmp((sub), "from")) && \ | |
3770 | 1757 (ask) != NULL && !strcasecmp((ask), "subscribe")) |
2956 | 1758 |
1759 /* | |
1760 * Subscribed to a buddy? | |
1761 */ | |
1762 #define BUD_SUBD_TO(sub, ask) ((!strcasecmp((sub), "to") || !strcasecmp((sub), "both")) && \ | |
1763 ((ask) == NULL || !strcasecmp((ask), "subscribe"))) | |
1764 | |
1765 /* | |
1766 * Pending unsubscription to a buddy? | |
1767 */ | |
1768 #define BUD_USUB_TO_PEND(sub, ask) ((!strcasecmp((sub), "to") || !strcasecmp((sub), "both")) && \ | |
1769 (ask) != NULL && !strcasecmp((ask), "unsubscribe")) | |
1770 | |
1771 /* | |
1772 * Unsubscribed to a buddy? | |
1773 */ | |
1774 #define BUD_USUBD_TO(sub, ask) ((!strcasecmp((sub), "none") || !strcasecmp((sub), "from")) && \ | |
1775 ((ask) == NULL || !strcasecmp((ask), "unsubscribe"))) | |
1776 | |
1777 /* | |
1778 * If a buddy is added or removed from the roster on another resource | |
1779 * jabber_handlebuddy is called | |
1780 * | |
1781 * Called with roster item node. | |
1782 */ | |
1783 static void jabber_handlebuddy(gjconn gjc, xmlnode x) | |
1784 { | |
1785 xmlnode g; | |
3311 | 1786 char *who, *name, *sub, *ask; |
1787 gaim_jid gjid; | |
2956 | 1788 struct buddy *b = NULL; |
4927 | 1789 struct jabber_buddy_data *jbd = NULL; |
3136 | 1790 char *buddyname, *groupname = NULL; |
2956 | 1791 |
3311 | 1792 who = xmlnode_get_attrib(x, "jid"); |
2956 | 1793 name = xmlnode_get_attrib(x, "name"); |
1794 sub = xmlnode_get_attrib(x, "subscription"); | |
1795 ask = xmlnode_get_attrib(x, "ask"); | |
3311 | 1796 |
1797 if((buddyname = get_realwho(gjc, who, FALSE, &gjid)) == NULL) | |
1798 return; | |
2956 | 1799 |
4705 | 1800 |
2956 | 1801 /* JFIXME: jabber_handleroster() had a "FIXME: transport" at this |
1802 * equivilent point. So... | |
1803 * | |
3311 | 1804 * We haven't done anything interesting to this point, so we'll |
1805 * violate Good Coding Structure here by simply bailing out. | |
2956 | 1806 */ |
3311 | 1807 if(!gjid->user) { |
1808 g_free(buddyname); | |
1809 gaim_jid_free(gjid); | |
2956 | 1810 return; |
1811 } | |
3311 | 1812 gaim_jid_free(gjid); |
2956 | 1813 |
3236 | 1814 if((g = xmlnode_get_tag(x, "group")) != NULL) { |
3136 | 1815 groupname = xmlnode_get_data(g); |
2956 | 1816 } |
1817 | |
3059 | 1818 /* |
3136 | 1819 * Add or remove a buddy? Change buddy's alias or group? |
3059 | 1820 */ |
2956 | 1821 if (BUD_SUB_TO_PEND(sub, ask) || BUD_SUBD_TO(sub, ask)) { |
4687 | 1822 if ((b = gaim_find_buddy(GJ_GC(gjc)->account, buddyname)) == NULL) { |
4932 | 1823 struct group *g; |
4927 | 1824 b = gaim_buddy_new(GJ_GC(gjc)->account, buddyname, name); |
4687 | 1825 if (groupname) { |
4775 | 1826 if (!(g = gaim_find_group(groupname))) { |
4687 | 1827 g = gaim_group_new(groupname); |
4775 | 1828 gaim_blist_add_group(g, NULL); |
1829 } | |
1830 } else { | |
4687 | 1831 g = gaim_group_new(_("Buddies")); |
4775 | 1832 gaim_blist_add_group(g, NULL); |
1833 } | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1834 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1835 "adding buddy [4]: %s\n", buddyname); |
4687 | 1836 gaim_blist_add_buddy(b, g, NULL); |
4349 | 1837 gaim_blist_save(); |
3136 | 1838 } else { |
5264 | 1839 gboolean save = FALSE; |
4687 | 1840 struct group *c_grp = gaim_find_buddys_group(b); |
3136 | 1841 |
3770 | 1842 /* |
3136 | 1843 * If the buddy's in a new group or his/her alias is changed... |
1844 */ | |
1845 if(groupname && c_grp && strcmp(c_grp->name, groupname)) { | |
5264 | 1846 struct group *g = gaim_find_group(groupname); |
1847 if(!g) { | |
1848 g = gaim_group_new(groupname); | |
1849 gaim_blist_add_group(g, NULL); | |
1850 } | |
1851 | |
1852 gaim_blist_add_buddy(b, g, NULL); | |
1853 save = TRUE; | |
1854 } | |
1855 | |
1856 if(name && (!b->alias || strcmp(b->alias, name))) { | |
1857 gaim_blist_alias_buddy(b, name); | |
1858 save = TRUE; | |
1859 } | |
1860 | |
1861 if(save) | |
4349 | 1862 gaim_blist_save(); |
2956 | 1863 } |
1864 } else if (BUD_USUB_TO_PEND(sub, ask) || BUD_USUBD_TO(sub, ask) || !strcasecmp(sub, "remove")) { | |
3236 | 1865 jabber_remove_gaim_buddy(GJ_GC(gjc), buddyname); |
2956 | 1866 } |
5135 | 1867 if(b && (jbd = jabber_find_buddy(b->account->gc, buddyname, TRUE)) != NULL) { |
4927 | 1868 jbd->subscription = JABBER_SUB_NONE; |
1869 if(!strcasecmp(sub, "to")) | |
1870 jbd->subscription |= JABBER_SUB_TO; | |
1871 else if(!strcasecmp(sub, "from")) | |
1872 jbd->subscription |= JABBER_SUB_FROM; | |
1873 else if(!strcasecmp(sub, "both")) | |
1874 jbd->subscription |= JABBER_SUB_BOTH; | |
1875 | |
1876 if(ask && !strcasecmp(ask, "subscribe")) | |
1877 jbd->subscription |= JABBER_SUB_PENDING; | |
1878 } | |
3328 | 1879 |
2956 | 1880 g_free(buddyname); |
1881 | |
1882 } | |
1883 | |
1884 static void jabber_handleroster(gjconn gjc, xmlnode querynode) | |
2086 | 1885 { |
1886 xmlnode x; | |
1887 | |
1888 x = xmlnode_get_firstchild(querynode); | |
1889 while (x) { | |
2956 | 1890 jabber_handlebuddy(gjc, x); |
2086 | 1891 x = xmlnode_get_nextsibling(x); |
1892 } | |
1893 | |
5426 | 1894 x = xmlnode_new_tag("presence"); |
2956 | 1895 gjab_send(gjc, x); |
2086 | 1896 xmlnode_free(x); |
1897 } | |
1898 | |
2956 | 1899 static void jabber_handleauthresp(gjconn gjc, jpacket p) |
2086 | 1900 { |
1901 if (jpacket_subtype(p) == JPACKET__RESULT) { | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1902 if (xmlnode_has_children(p->x)) { |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1903 xmlnode query = xmlnode_get_tag(p->x, "query"); |
5572 | 1904 gaim_connection_update_progress(GJ_GC(gjc), _("Authenticating"), |
1905 4, JABBER_CONNECT_STEPS); | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1906 if (!xmlnode_get_tag(query, "digest")) { |
2956 | 1907 g_free(gjc->sid); |
1908 gjc->sid = NULL; | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1909 } |
2956 | 1910 gjab_auth(gjc); |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1911 } else { |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1912 gaim_debug(GAIM_DEBUG_INFO, "jabber", "auth success\n"); |
2086 | 1913 |
5572 | 1914 gaim_connection_set_state(GJ_GC(gjc), GAIM_CONNECTED); |
2956 | 1915 serv_finish_login(GJ_GC(gjc)); |
1916 | |
1917 ((struct jabber_data *)GJ_GC(gjc)->proto_data)->did_import = TRUE; | |
1918 | |
1919 gjab_reqroster(gjc); | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1920 } |
2086 | 1921 } else { |
1922 xmlnode xerr; | |
1923 char *errmsg = NULL; | |
1924 int errcode = 0; | |
1925 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1926 gaim_debug(GAIM_DEBUG_ERROR, "jabber", "auth failed\n"); |
2086 | 1927 xerr = xmlnode_get_tag(p->x, "error"); |
1928 if (xerr) { | |
1929 char msg[BUF_LONG]; | |
1930 errmsg = xmlnode_get_data(xerr); | |
1931 if (xmlnode_get_attrib(xerr, "code")) { | |
1932 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
1933 g_snprintf(msg, sizeof(msg), "Error %d: %s", errcode, errmsg); | |
1934 } else | |
1935 g_snprintf(msg, sizeof(msg), "%s", errmsg); | |
5572 | 1936 gaim_connection_error(GJ_GC(gjc), msg); |
2086 | 1937 } else { |
5572 | 1938 gaim_connection_error(GJ_GC(gjc), _("Unknown login error")); |
2086 | 1939 } |
1940 } | |
1941 } | |
1942 | |
2956 | 1943 static void jabber_handleversion(gjconn gjc, xmlnode iqnode) { |
2086 | 1944 xmlnode querynode, x; |
1945 char *id, *from; | |
1946 char os[1024]; | |
1947 struct utsname osinfo; | |
1948 | |
1949 uname(&osinfo); | |
1950 g_snprintf(os, sizeof os, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine); | |
1951 | |
1952 id = xmlnode_get_attrib(iqnode, "id"); | |
1953 from = xmlnode_get_attrib(iqnode, "from"); | |
1954 | |
1955 x = jutil_iqnew(JPACKET__RESULT, NS_VERSION); | |
1956 | |
1957 xmlnode_put_attrib(x, "to", from); | |
1958 xmlnode_put_attrib(x, "id", id); | |
1959 querynode = xmlnode_get_tag(x, "query"); | |
1960 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "name"), PACKAGE, -1); | |
1961 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "version"), VERSION, -1); | |
1962 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "os"), os, -1); | |
1963 | |
2956 | 1964 gjab_send(gjc, x); |
2086 | 1965 |
1966 xmlnode_free(x); | |
1967 } | |
1968 | |
2956 | 1969 static void jabber_handletime(gjconn gjc, xmlnode iqnode) { |
2086 | 1970 xmlnode querynode, x; |
1971 char *id, *from; | |
3770 | 1972 time_t now_t; |
2086 | 1973 struct tm *now; |
1974 char buf[1024]; | |
1975 | |
1976 time(&now_t); | |
1977 now = localtime(&now_t); | |
1978 | |
1979 id = xmlnode_get_attrib(iqnode, "id"); | |
1980 from = xmlnode_get_attrib(iqnode, "from"); | |
1981 | |
1982 x = jutil_iqnew(JPACKET__RESULT, NS_TIME); | |
1983 | |
1984 xmlnode_put_attrib(x, "to", from); | |
1985 xmlnode_put_attrib(x, "id", id); | |
1986 querynode = xmlnode_get_tag(x, "query"); | |
1987 | |
1988 strftime(buf, 1024, "%Y%m%dT%T", now); | |
1989 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "utc"), buf, -1); | |
1990 strftime(buf, 1024, "%Z", now); | |
1991 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "tz"), buf, -1); | |
1992 strftime(buf, 1024, "%d %b %Y %T", now); | |
1993 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "display"), buf, -1); | |
3770 | 1994 |
2956 | 1995 gjab_send(gjc, x); |
2086 | 1996 |
1997 xmlnode_free(x); | |
1998 } | |
1999 | |
4538 | 2000 struct jabber_xfer_data { |
3630 | 2001 struct g_url *url; |
2002 GString *headers; | |
2003 gboolean newline; | |
4538 | 2004 |
2005 char *iq_id; | |
2006 | |
2007 struct jabber_data *jd; | |
3630 | 2008 }; |
2009 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2010 static void jabber_xfer_init(GaimXfer *xfer) |
4538 | 2011 { |
2012 struct jabber_xfer_data *data = xfer->data; | |
2013 gaim_xfer_start(xfer, -1, data->url->address, data->url->port); | |
2014 } | |
2015 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2016 static void jabber_xfer_free(GaimXfer *xfer) |
4538 | 2017 { |
2018 struct jabber_xfer_data *data = xfer->data; | |
2019 data->jd->file_transfers = g_slist_remove(data->jd->file_transfers, xfer); | |
2020 | |
2021 g_string_free(data->headers, TRUE); | |
2022 g_free(data->url); | |
2023 g_free(data->iq_id); | |
2024 g_free(data); | |
2025 | |
2026 xfer->data = NULL; | |
3630 | 2027 } |
2028 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2029 static void jabber_xfer_end(GaimXfer *xfer) |
4538 | 2030 { |
2031 struct jabber_xfer_data *data = xfer->data; | |
2032 xmlnode x; | |
2033 | |
2034 x = xmlnode_new_tag("iq"); | |
2035 xmlnode_put_attrib(x, "type", "result"); | |
2036 xmlnode_put_attrib(x, "to", xfer->who); | |
2037 xmlnode_put_attrib(x, "id", data->iq_id); | |
2038 | |
2039 gjab_send(data->jd->gjc, x); | |
2040 | |
2041 xmlnode_free(x); | |
2042 | |
2043 jabber_xfer_free(xfer); | |
2044 } | |
2045 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2046 static void jabber_xfer_start(GaimXfer *xfer) |
4538 | 2047 { |
2048 struct jabber_xfer_data *data = xfer->data; | |
2049 char *buf = g_strdup_printf("GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", | |
2050 data->url->page, data->url->address); | |
2051 write(xfer->fd, buf, strlen(buf)); | |
2052 g_free(buf); | |
2053 } | |
2054 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2055 static size_t jabber_xfer_read(char **buffer, GaimXfer *xfer) { |
4538 | 2056 struct jabber_xfer_data *data = xfer->data; |
3630 | 2057 char test; |
5435 | 2058 int size; |
4538 | 2059 |
2060 if(read(xfer->fd, &test, sizeof(test)) > 0) { | |
2061 data->headers = g_string_append_c(data->headers, test); | |
2062 if(test == '\r') | |
2063 return 0; | |
2064 if(test == '\n') { | |
2065 if(data->newline) { | |
2066 gchar *lenstr = strstr(data->headers->str, "Content-Length: "); | |
2067 if(lenstr) { | |
5435 | 2068 sscanf(lenstr, "Content-Length: %d", &size); |
4538 | 2069 gaim_xfer_set_size(xfer, size); |
2070 } | |
2071 gaim_xfer_set_read_fnc(xfer, NULL); | |
2072 return 0; | |
2073 } else | |
2074 data->newline = TRUE; | |
2075 return 0; | |
3630 | 2076 } |
4538 | 2077 data->newline = FALSE; |
2078 return 0; | |
3630 | 2079 } |
4538 | 2080 return 0; |
3630 | 2081 } |
2082 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2083 static void jabber_xfer_cancel_send(GaimXfer *xfer) { |
4675
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2084 } |
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2085 |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2086 static void jabber_xfer_cancel_recv(GaimXfer *xfer) { |
4538 | 2087 struct jabber_xfer_data *data = xfer->data; |
3630 | 2088 xmlnode x,y; |
2089 | |
2090 x = xmlnode_new_tag("iq"); | |
2091 xmlnode_put_attrib(x, "type", "error"); | |
4538 | 2092 xmlnode_put_attrib(x, "to", xfer->who); |
2093 xmlnode_put_attrib(x, "id", data->iq_id); | |
3630 | 2094 y = xmlnode_insert_tag(x, "error"); |
2095 /* FIXME: need to handle other kinds of errors here */ | |
2096 xmlnode_put_attrib(y, "code", "406"); | |
2097 xmlnode_insert_cdata(y, "File Transfer Refused", -1); | |
2098 | |
4538 | 2099 gjab_send(data->jd->gjc, x); |
3630 | 2100 |
2101 xmlnode_free(x); | |
2102 | |
4538 | 2103 jabber_xfer_free(xfer); |
3630 | 2104 } |
2105 | |
2106 static void jabber_handleoob(gjconn gjc, xmlnode iqnode) { | |
4538 | 2107 struct jabber_xfer_data *xfer_data; |
3630 | 2108 struct jabber_data *jd = GJ_GC(gjc)->proto_data; |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2109 GaimXfer *xfer; |
3630 | 2110 char *msg = NULL; |
4538 | 2111 char *filename; |
3630 | 2112 xmlnode querynode = xmlnode_get_tag(iqnode, "query"); |
2113 xmlnode urlnode,descnode; | |
2114 | |
2115 if(!querynode) | |
2116 return; | |
2117 urlnode = xmlnode_get_tag(querynode, "url"); | |
2118 if(!urlnode) | |
2119 return; | |
2120 descnode = xmlnode_get_tag(querynode, "desc"); | |
2121 if(descnode) | |
2122 msg = xmlnode_get_data(descnode); | |
2123 | |
4538 | 2124 xfer_data = g_new0(struct jabber_xfer_data, 1); |
2125 xfer_data->url = parse_url(xmlnode_get_data(urlnode)); | |
2126 xfer_data->jd = jd; | |
2127 xfer_data->headers = g_string_new(""); | |
2128 xfer_data->iq_id = g_strdup(xmlnode_get_attrib(iqnode, "id")); | |
2129 | |
2130 xfer = gaim_xfer_new(GJ_GC(gjc)->account, GAIM_XFER_RECEIVE, | |
2131 xmlnode_get_attrib(iqnode, "from")); | |
2132 xfer->data = xfer_data; | |
2133 | |
2134 filename = g_strdup(g_strrstr(xfer_data->url->page, "/")); | |
2135 if(!filename) | |
2136 filename = g_strdup(xfer_data->url->page); | |
2137 | |
2138 gaim_xfer_set_filename(xfer, filename); | |
2139 | |
2140 g_free(filename); | |
2141 | |
2142 gaim_xfer_set_init_fnc(xfer, jabber_xfer_init); | |
2143 gaim_xfer_set_end_fnc(xfer, jabber_xfer_end); | |
4675
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2144 gaim_xfer_set_cancel_send_fnc(xfer, jabber_xfer_cancel_send); |
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2145 gaim_xfer_set_cancel_recv_fnc(xfer, jabber_xfer_cancel_recv); |
4538 | 2146 gaim_xfer_set_read_fnc(xfer, jabber_xfer_read); |
2147 gaim_xfer_set_start_fnc(xfer, jabber_xfer_start); | |
2148 | |
2149 jd->file_transfers = g_slist_append(jd->file_transfers, xfer); | |
2150 | |
2151 gaim_xfer_request(xfer); | |
3630 | 2152 } |
2153 | |
2956 | 2154 static void jabber_handlelast(gjconn gjc, xmlnode iqnode) { |
3630 | 2155 xmlnode x, querytag; |
2086 | 2156 char *id, *from; |
2956 | 2157 struct jabber_data *jd = GJ_GC(gjc)->proto_data; |
2086 | 2158 char idle_time[32]; |
3630 | 2159 |
2086 | 2160 id = xmlnode_get_attrib(iqnode, "id"); |
2161 from = xmlnode_get_attrib(iqnode, "from"); | |
2162 | |
2163 x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last"); | |
2164 | |
2165 xmlnode_put_attrib(x, "to", from); | |
2166 xmlnode_put_attrib(x, "id", id); | |
2167 querytag = xmlnode_get_tag(x, "query"); | |
2168 g_snprintf(idle_time, sizeof idle_time, "%ld", jd->idle ? time(NULL) - jd->idle : 0); | |
2169 xmlnode_put_attrib(querytag, "seconds", idle_time); | |
2170 | |
2956 | 2171 gjab_send(gjc, x); |
2086 | 2172 xmlnode_free(x); |
2173 } | |
2174 | |
2956 | 2175 /* |
2176 * delete == TRUE: delete found entry | |
2177 * | |
2178 * returns pointer to (local) copy of value if found, NULL otherwise | |
2179 * | |
2180 * Note: non-reentrant! Local static storage re-used on subsequent calls. | |
2181 * If you're going to need to keep the returned value, make a copy! | |
2182 */ | |
2183 static gchar *jabber_track_queries(GHashTable *queries, gchar *key, gboolean delete) | |
2184 { | |
2185 gpointer my_key, my_val; | |
2186 static gchar *ret_val = NULL; | |
2187 | |
2188 if(ret_val != NULL) { | |
2189 g_free(ret_val); | |
2190 ret_val = NULL; | |
2191 } | |
2192 | |
2193 /* self-protection */ | |
2194 if(queries != NULL && key != NULL) { | |
2195 if(g_hash_table_lookup_extended(queries, key, &my_key, &my_val)) { | |
2196 ret_val = g_strdup((gchar *) my_val); | |
2197 if(delete) { | |
2198 g_hash_table_remove(queries, key); | |
2199 g_free(my_key); | |
2200 g_free(my_val); | |
2201 } | |
2202 } | |
2203 } | |
2204 | |
2205 return(ret_val); | |
2206 } | |
2207 | |
2208 static void jabber_handlepacket(gjconn gjc, jpacket p) | |
2086 | 2209 { |
5994 | 2210 char *id, *from, *to; |
2086 | 2211 switch (p->type) { |
2212 case JPACKET_MESSAGE: | |
2956 | 2213 jabber_handlemessage(gjc, p); |
2086 | 2214 break; |
2215 case JPACKET_PRESENCE: | |
2956 | 2216 jabber_handlepresence(gjc, p); |
2086 | 2217 break; |
2218 case JPACKET_IQ: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2219 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2220 "jpacket_subtype: %d\n", jpacket_subtype(p)); |
2086 | 2221 |
2956 | 2222 id = xmlnode_get_attrib(p->x, "id"); |
2223 if (id != NULL && !strcmp(id, IQID_AUTH)) { | |
2224 jabber_handleauthresp(gjc, p); | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
2225 break; |
2086 | 2226 } |
2227 | |
2228 if (jpacket_subtype(p) == JPACKET__SET) { | |
2956 | 2229 xmlnode querynode; |
2230 querynode = xmlnode_get_tag(p->x, "query"); | |
5994 | 2231 from = xmlnode_get_attrib(p->x, "from"); |
2232 to = xmlnode_get_attrib(p->x, "to"); | |
6004 | 2233 if (NSCHECK(querynode, "jabber:iq:roster") && (!from || !strcmp(from, to))) { |
2956 | 2234 jabber_handlebuddy(gjc, xmlnode_get_firstchild(querynode)); |
3630 | 2235 } else if(NSCHECK(querynode, "jabber:iq:oob")) { |
2236 jabber_handleoob(gjc, p->x); | |
2956 | 2237 } |
2086 | 2238 } else if (jpacket_subtype(p) == JPACKET__GET) { |
3770 | 2239 xmlnode querynode; |
2086 | 2240 querynode = xmlnode_get_tag(p->x, "query"); |
3770 | 2241 if (NSCHECK(querynode, NS_VERSION)) { |
2242 jabber_handleversion(gjc, p->x); | |
2086 | 2243 } else if (NSCHECK(querynode, NS_TIME)) { |
3770 | 2244 jabber_handletime(gjc, p->x); |
2086 | 2245 } else if (NSCHECK(querynode, "jabber:iq:last")) { |
3770 | 2246 jabber_handlelast(gjc, p->x); |
2086 | 2247 } |
2248 } else if (jpacket_subtype(p) == JPACKET__RESULT) { | |
2249 xmlnode querynode, vcard; | |
2250 char *xmlns, *from; | |
2251 | |
2956 | 2252 /* |
2253 * TBD: ISTM maybe this part could use a serious re-work? | |
2254 */ | |
2086 | 2255 from = xmlnode_get_attrib(p->x, "from"); |
2256 querynode = xmlnode_get_tag(p->x, "query"); | |
2257 vcard = xmlnode_get_tag(p->x, "vCard"); | |
2316
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
2258 if (!vcard) |
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
2259 vcard = xmlnode_get_tag(p->x, "VCARD"); |
2086 | 2260 |
2261 if (NSCHECK(querynode, NS_ROSTER)) { | |
2956 | 2262 jabber_handleroster(gjc, querynode); |
2086 | 2263 } else if (NSCHECK(querynode, NS_VCARD)) { |
2956 | 2264 jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ |
3770 | 2265 jabber_handlevcard(gjc, querynode, from); |
2316
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
2266 } else if (vcard) { |
2956 | 2267 jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ |
2268 jabber_handlevcard(gjc, vcard, from); | |
2269 } else if((xmlns = xmlnode_get_attrib(querynode, "xmlns")) != NULL) { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2270 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2271 "jabber:iq:query: %s\n", xmlns); |
2086 | 2272 } else { |
2956 | 2273 char *val; |
2274 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2275 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2276 "jabber:iq: %s\n", xmlnode2str(p->x)); |
2956 | 2277 |
2278 /* handle "null" query results */ | |
2279 if((val = jabber_track_queries(gjc->queries, id, TRUE)) != NULL) { | |
2280 if(strcmp((char *) val, "vCard") == 0) { | |
2281 /* | |
2282 * No actual vCard, but there's other stuff. This | |
2283 * way the user always gets some kind of response. | |
2284 */ | |
2285 jabber_handlevcard(gjc, NULL, from); | |
3257 | 2286 } else if(!strcmp((char *) val, "change_password")) { |
2287 char buf[BUF_LONG]; | |
3311 | 2288 sprintf(buf, _("Password successfully changed.")); |
3257 | 2289 |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2290 gaim_notify_info(GJ_GC(gjc), NULL, buf, NULL); |
2956 | 2291 } |
2292 } | |
2086 | 2293 } |
2294 | |
2295 } else if (jpacket_subtype(p) == JPACKET__ERROR) { | |
2296 xmlnode xerr; | |
2297 char *from, *errmsg = NULL; | |
2298 int errcode = 0; | |
2299 | |
2300 from = xmlnode_get_attrib(p->x, "from"); | |
2301 xerr = xmlnode_get_tag(p->x, "error"); | |
2302 if (xerr) { | |
2303 errmsg = xmlnode_get_data(xerr); | |
2304 if (xmlnode_get_attrib(xerr, "code")) | |
2305 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
2306 } | |
2307 | |
3427 | 2308 from = g_strdup_printf("Jabber Error %d (%s)", errcode, from); |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2309 gaim_notify_error(GJ_GC(gjc), NULL, from, errmsg); |
2086 | 2310 g_free(from); |
2311 | |
2312 } | |
2313 | |
2314 break; | |
2315 case JPACKET_S10N: | |
2956 | 2316 jabber_handles10n(gjc, p); |
2086 | 2317 break; |
2318 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2319 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2320 "jabber: packet type %d (%s)\n", p->type, xmlnode2str(p->x)); |
2086 | 2321 } |
2322 | |
2323 xmlnode_free(p->x); | |
2324 | |
2325 return; | |
2326 } | |
2327 | |
2956 | 2328 static void jabber_handlestate(gjconn gjc, int state) |
2086 | 2329 { |
2330 switch (state) { | |
2331 case JCONN_STATE_OFF: | |
3074 | 2332 if(gjc->was_connected) { |
5572 | 2333 gaim_connection_error(GJ_GC(gjc), _("Connection lost")); |
3074 | 2334 } else { |
5572 | 2335 gaim_connection_error(GJ_GC(gjc), _("Unable to connect")); |
3074 | 2336 } |
2086 | 2337 break; |
2338 case JCONN_STATE_CONNECTED: | |
3074 | 2339 gjc->was_connected = 1; |
5572 | 2340 gaim_connection_update_progress(GJ_GC(gjc), _("Connected"), 2, JABBER_CONNECT_STEPS); |
2086 | 2341 break; |
2342 case JCONN_STATE_ON: | |
5572 | 2343 gaim_connection_update_progress(GJ_GC(gjc), _("Requesting Authentication Method"), 3, JABBER_CONNECT_STEPS); |
2956 | 2344 gjab_reqauth(gjc); |
2086 | 2345 break; |
2346 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2347 gaim_debug(GAIM_DEBUG_MISC, "jabber", "state change: %d\n", state); |
2086 | 2348 } |
2349 return; | |
2350 } | |
2351 | |
5572 | 2352 static void jabber_login(GaimAccount *account) |
2086 | 2353 { |
5572 | 2354 GaimConnection *gc = gaim_account_get_connection(account); |
2086 | 2355 struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); |
4917 | 2356 char *loginname = create_valid_jid(account->username, DEFAULT_SERVER, "Gaim"); |
2086 | 2357 |
5174 | 2358 gc->flags |= OPT_CONN_HTML; |
2359 | |
3311 | 2360 jd->buddies = g_hash_table_new(g_str_hash, g_str_equal); |
2956 | 2361 jd->chats = NULL; /* we have no chats yet */ |
2086 | 2362 |
5572 | 2363 gaim_connection_update_progress(gc, _("Connecting"), 1, JABBER_CONNECT_STEPS); |
2086 | 2364 |
4491 | 2365 if (!(jd->gjc = gjab_new(loginname, account->password, gc))) { |
2086 | 2366 g_free(loginname); |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2367 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2368 "unable to connect (jab_new failed)\n"); |
5572 | 2369 gaim_connection_error(gc, _("Unable to connect")); |
2086 | 2370 return; |
2371 } | |
2372 | |
2373 g_free(loginname); | |
2956 | 2374 gjab_state_handler(jd->gjc, jabber_handlestate); |
2375 gjab_packet_handler(jd->gjc, jabber_handlepacket); | |
2376 jd->gjc->queries = g_hash_table_new(g_str_hash, g_str_equal); | |
2377 gjab_start(jd->gjc); | |
2086 | 2378 } |
2379 | |
2380 static gboolean jabber_destroy_hash(gpointer key, gpointer val, gpointer data) { | |
3770 | 2381 g_free(key); |
2086 | 2382 g_free(val); |
2383 return TRUE; | |
2384 } | |
2385 | |
3311 | 2386 static gboolean jabber_destroy_buddy_hash(gpointer key, gpointer val, gpointer data) { |
2387 struct jabber_buddy_data *jbd = val; | |
2388 while (jbd->resources) { | |
2389 g_free(((jab_res_info) ((GSList *)jbd->resources)->data)->name); | |
2390 if(((jab_res_info) ((GSList *)jbd->resources)->data)->away_msg) | |
2391 g_free(((jab_res_info) ((GSList *)jbd->resources)->data)->away_msg); | |
2392 g_free(((GSList *)jbd->resources)->data); | |
2393 jbd->resources = g_slist_remove(jbd->resources, ((GSList *)jbd->resources)->data); | |
2394 | |
2395 } | |
2396 if(jbd->error_msg) | |
2397 g_free(jbd->error_msg); | |
2398 g_free(key); | |
2399 g_free(jbd); | |
2400 return TRUE; | |
2401 } | |
2402 | |
2403 | |
2086 | 2404 static gboolean jabber_free(gpointer data) |
2405 { | |
2956 | 2406 struct jabber_data *jd = data; |
2407 | |
3236 | 2408 if(jd->gjc != NULL) { |
3486 | 2409 g_free(jd->gjc->sid); |
3236 | 2410 gjab_delete(jd->gjc); |
2411 jd->gjc = NULL; | |
2412 } | |
2956 | 2413 g_free(jd); |
2414 | |
2086 | 2415 return FALSE; |
2416 } | |
2417 | |
5572 | 2418 static void jabber_close(GaimConnection *gc) |
2086 | 2419 { |
2420 struct jabber_data *jd = gc->proto_data; | |
2956 | 2421 |
2422 if(jd) { | |
2423 GSList *jcs = jd->chats; | |
2424 | |
2425 /* Free-up the jabber_chat struct allocs and the list */ | |
2426 while (jcs) { | |
3311 | 2427 gaim_jid_free(((struct jabber_chat *)jcs->data)->gjid); |
2956 | 2428 g_free(jcs->data); |
2429 jcs = jcs->next; | |
2430 } | |
2431 g_slist_free(jd->chats); | |
2432 | |
3311 | 2433 /* Free-up the buddy data hash */ |
2434 if(jd->buddies != NULL) | |
2435 { | |
2436 g_hash_table_foreach_remove(jd->buddies, jabber_destroy_buddy_hash, NULL); | |
2437 g_hash_table_destroy(jd->buddies); | |
2438 jd->buddies = NULL; | |
2956 | 2439 } |
2440 | |
2441 /* Free-up the pending queries memories and the list */ | |
3236 | 2442 if(jd->gjc != NULL && jd->gjc->queries != NULL) { |
2956 | 2443 g_hash_table_foreach_remove(jd->gjc->queries, jabber_destroy_hash, NULL); |
2444 g_hash_table_destroy(jd->gjc->queries); | |
2445 jd->gjc->queries = NULL; | |
2446 } | |
2447 } | |
2300
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
2448 if (gc->inpa) |
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
2449 gaim_input_remove(gc->inpa); |
2956 | 2450 |
2451 if(jd) { | |
3613 | 2452 g_timeout_add(0, jabber_free, jd); |
3236 | 2453 if(jd->gjc != NULL) |
2454 xmlnode_free(jd->gjc->current); | |
2956 | 2455 } |
2086 | 2456 gc->proto_data = NULL; |
2457 } | |
2458 | |
6059 | 2459 static int jabber_send_typing(GaimConnection *gc, const char *who, int typing) |
3311 | 2460 { |
2461 xmlnode x, y; | |
2462 char *realwho; | |
2463 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; | |
2464 jab_res_info jri = jabber_find_resource(gc, who); | |
2465 | |
2466 if(!jri || !jri->has_composing) | |
2467 return 0; | |
2468 | |
2469 if((realwho = get_realwho(gjc, who, FALSE, NULL)) == NULL) | |
2470 return 0; | |
3596 | 2471 |
3311 | 2472 x = xmlnode_new_tag("message"); |
2473 xmlnode_put_attrib(x, "to", realwho); | |
2474 | |
2475 y = xmlnode_insert_tag(x, "x"); | |
2476 xmlnode_put_attrib(y, "xmlns", "jabber:x:event"); | |
2477 | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
2478 if(typing == GAIM_TYPING) |
3311 | 2479 xmlnode_insert_tag(y, "composing"); |
3596 | 2480 |
3311 | 2481 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2482 xmlnode_free(x); | |
2483 g_free(realwho); | |
2484 return JABBER_TYPING_NOTIFY_INT; | |
2485 } | |
2486 | |
5093 | 2487 static void insert_message(xmlnode x, const char *message, gboolean use_xhtml) { |
2488 xmlnode y; | |
5110 | 2489 char *buf = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body>%s</body></html>", message); |
2490 char *xhtml, *plain; | |
2491 | |
2492 html_to_xhtml(buf, &xhtml, &plain); | |
2493 g_free(buf); | |
2494 | |
5093 | 2495 y = xmlnode_insert_tag(x, "body"); |
5110 | 2496 xmlnode_insert_cdata(y, plain, -1); |
2497 g_free(plain); | |
5093 | 2498 |
2499 if(use_xhtml) { | |
5110 | 2500 y = xmlnode_str(xhtml, strlen(xhtml)); |
5093 | 2501 if(y) { |
2502 xmlnode_insert_tag_node(x, y); | |
2503 xmlnode_free(y); | |
2504 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2505 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2506 "holy cow, html_to_xhtml didn't work right!\n"); |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2507 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2508 "the invalid XML: %s\n", xhtml); |
5093 | 2509 } |
2510 } | |
5110 | 2511 g_free(xhtml); |
5093 | 2512 } |
2513 | |
5572 | 2514 static int jabber_send_im(GaimConnection *gc, const char *who, const char *message, int len, int flags) |
2086 | 2515 { |
2516 xmlnode x, y; | |
3311 | 2517 char *thread_id = NULL; |
2956 | 2518 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
5093 | 2519 jab_res_info jri = jabber_find_resource(gc, who); |
2086 | 2520 |
2521 if (!who || !message) | |
2123
56c4382f2909
[gaim-migrate @ 2133]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2112
diff
changeset
|
2522 return 0; |
2086 | 2523 |
2524 x = xmlnode_new_tag("message"); | |
4927 | 2525 xmlnode_put_attrib(x, "to", who); |
2526 | |
2527 thread_id = jabber_get_convo_thread(gjc, who); | |
3311 | 2528 if(thread_id) |
2529 { | |
3769 | 2530 if(strcmp(thread_id, "")) { |
2531 y = xmlnode_insert_tag(x, "thread"); | |
2532 xmlnode_insert_cdata(y, thread_id, -1); | |
2533 } | |
3311 | 2534 g_free(thread_id); |
2535 } | |
2536 | |
2086 | 2537 xmlnode_put_attrib(x, "type", "chat"); |
2538 | |
3311 | 2539 /* let other clients know we support typing notification */ |
2540 y = xmlnode_insert_tag(x, "x"); | |
2541 xmlnode_put_attrib(y, "xmlns", "jabber:x:event"); | |
2542 xmlnode_insert_tag(y, "composing"); | |
2543 | |
2086 | 2544 if (message && strlen(message)) { |
5093 | 2545 insert_message(x, message, jri ? jri->has_xhtml : TRUE); |
2086 | 2546 } |
2547 | |
2956 | 2548 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 2549 xmlnode_free(x); |
2303
f5bf315e6104
[gaim-migrate @ 2313]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2300
diff
changeset
|
2550 return 1; |
2086 | 2551 } |
2552 | |
3105 | 2553 /* |
2554 * Add/update buddy's roster entry on server | |
3349 | 2555 * |
2556 * If "alias" or "group" are NULL, gets them from Gaim's current buddylist values | |
2557 * for the buddy. | |
3105 | 2558 */ |
5572 | 2559 static void jabber_roster_update(GaimConnection *gc, const char *name, const char *alias, const char *group) |
3105 | 2560 { |
2561 xmlnode x, y; | |
2562 char *realwho; | |
2563 gjconn gjc; | |
2564 struct buddy *buddy = NULL; | |
2565 struct group *buddy_group = NULL; | |
3867 | 2566 const char *my_alias = NULL; |
2567 const char *my_group = NULL; | |
3770 | 2568 |
3105 | 2569 if(gc && gc->proto_data && ((struct jabber_data *)gc->proto_data)->gjc && name) { |
3311 | 2570 gaim_jid gjid; |
3105 | 2571 gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2572 | |
3311 | 2573 if((realwho = get_realwho(gjc, name, FALSE, &gjid)) == NULL) |
2574 return; | |
2575 | |
2576 /* FIXME: transport */ | |
2577 if(gjid->user == NULL) { | |
2578 g_free(realwho); | |
2579 gaim_jid_free(gjid); | |
2580 return; | |
3105 | 2581 } |
3311 | 2582 gaim_jid_free(gjid); |
3105 | 2583 |
2584 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
2585 y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); | |
2586 xmlnode_put_attrib(y, "jid", realwho); | |
2587 | |
4687 | 2588 buddy = gaim_find_buddy(gc->account, realwho); |
4349 | 2589 |
3349 | 2590 /* |
2591 * See if there's an explict (new?) alias for the buddy or we can pull | |
2592 * one out of current Gaim buddylist data for him. | |
2593 */ | |
2594 if(alias && alias[0] != '\0') { | |
2595 my_alias = alias; | |
4705 | 2596 } else if(buddy && buddy->alias) { |
4227 | 2597 my_alias = buddy->alias; |
3349 | 2598 } |
2599 | |
2600 /* If there's an alias for the buddy, it's not 0-length | |
3105 | 2601 * and it doesn't match his JID, add the "name" attribute. |
2602 */ | |
3349 | 2603 if(my_alias != NULL && my_alias[0] != '\0' && strcmp(realwho, my_alias)) |
3311 | 2604 { |
3642 | 2605 xmlnode_put_attrib(y, "name", my_alias); |
3105 | 2606 } |
2607 | |
2608 /* | |
3349 | 2609 * See if there's an explict (new?) group for the buddy or pull |
2610 * one out of current Gaim buddylist data for him. | |
3105 | 2611 */ |
3349 | 2612 if(group && group[0] != '\0') { |
2613 my_group = group; | |
4687 | 2614 } else if((buddy_group = gaim_find_buddys_group(buddy)) != NULL) { |
3349 | 2615 my_group = buddy_group->name; |
2616 } | |
2617 | |
2618 /* | |
2619 * Send what group the buddy's in along with the roster item. | |
2620 */ | |
2621 if(my_group != NULL && my_group[0] != '\0') { | |
2622 xmlnode z = xmlnode_insert_tag(y, "group"); | |
2623 xmlnode_insert_cdata(z, my_group, -1); | |
3105 | 2624 } |
2625 | |
2626 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); | |
2627 | |
2628 xmlnode_free(x); | |
2629 g_free(realwho); | |
2630 } | |
2631 } | |
2632 | |
3136 | 2633 /* |
3349 | 2634 * Add/update buddy's alias on server |
2635 * | |
2636 * This is just a roster update using existing, local buddylist data | |
2637 */ | |
5572 | 2638 static void jabber_alias_buddy(GaimConnection *gc, const char *name, const char *alias) |
3349 | 2639 { |
4269 | 2640 jabber_roster_update(gc, name, alias, NULL); |
3349 | 2641 } |
2642 | |
2643 /* | |
3136 | 2644 * Change buddy's group on server roster |
2645 */ | |
5572 | 2646 static void jabber_group_change(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) |
3136 | 2647 { |
3349 | 2648 if(old_group && new_group && strcmp(old_group, new_group)) |
2649 jabber_roster_update(gc, name, NULL, new_group); | |
2650 } | |
2651 | |
2652 /* | |
2653 * Group rename | |
2654 * | |
2655 * Jabber doesn't have "groups," per se. "Group" is simply a JID attribute. | |
2656 * So we iterate through the list of buddies that are in the group and change | |
2657 * the group attribute for each of them. | |
2658 */ | |
5572 | 2659 static void jabber_rename_group(GaimConnection *gc, |
3867 | 2660 const char *old_group, |
2661 const char *new_group, | |
3349 | 2662 GList *members) |
2663 { | |
2664 if(old_group && new_group && strcmp(old_group, new_group)) | |
2665 while(members) { | |
2666 jabber_group_change(gc, (char *)(members->data), old_group, new_group); | |
2667 members = members->next; | |
2668 } | |
3136 | 2669 } |
2670 | |
5572 | 2671 static void jabber_add_buddy(GaimConnection *gc, const char *name) |
2086 | 2672 { |
3136 | 2673 xmlnode x; |
2086 | 2674 char *realwho; |
2956 | 2675 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3311 | 2676 gaim_jid gjid; |
5572 | 2677 GaimAccount *account = gaim_connection_get_account(gc); |
2086 | 2678 |
2679 if (!((struct jabber_data *)gc->proto_data)->did_import) | |
2680 return; | |
2681 | |
3311 | 2682 /* |
2683 * If there's no name or the name is ourself | |
2684 */ | |
5572 | 2685 if(!name || !strcmp(gaim_account_get_username(account), name)) |
2086 | 2686 return; |
2687 | |
3311 | 2688 if((realwho = get_realwho(gjc, name, FALSE, &gjid)) == NULL) { |
3427 | 2689 char *msg = g_strdup_printf(_("The user %s is an invalid Jabber I.D. and was " |
2690 "therefore not added."), name); | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2691 gaim_notify_error(gc, NULL, _("Unable to add buddy."), |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2692 _("Jabber Error")); |
3311 | 2693 g_free(msg); |
2694 jabber_remove_gaim_buddy(gc, name); | |
2695 return; | |
2086 | 2696 } |
2697 | |
3311 | 2698 /* FIXME: transport */ |
2699 if(gjid->user == NULL) { | |
2700 g_free(realwho); | |
2701 gaim_jid_free(gjid); | |
2702 return; | |
2703 } | |
2704 gaim_jid_free(gjid); | |
2705 | |
2086 | 2706 x = xmlnode_new_tag("presence"); |
2707 xmlnode_put_attrib(x, "to", realwho); | |
2708 xmlnode_put_attrib(x, "type", "subscribe"); | |
2956 | 2709 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2710 xmlnode_free(x); | |
2086 | 2711 |
3349 | 2712 jabber_roster_update(gc, realwho, NULL, NULL); |
3105 | 2713 |
2086 | 2714 g_free(realwho); |
2715 } | |
2716 | |
6059 | 2717 static void jabber_remove_buddy(GaimConnection *gc, const char *name, const char *group) |
2086 | 2718 { |
3048 | 2719 xmlnode x; |
2086 | 2720 char *realwho; |
2956 | 2721 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2086 | 2722 |
3311 | 2723 if(!name || (realwho = get_realwho(gjc, name, FALSE, NULL)) == NULL) |
2086 | 2724 return; |
2725 | |
2956 | 2726 x = xmlnode_new_tag("presence"); |
2727 xmlnode_put_attrib(x, "to", realwho); | |
2728 xmlnode_put_attrib(x, "type", "unsubscribe"); | |
2729 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); | |
2086 | 2730 g_free(realwho); |
2731 xmlnode_free(x); | |
2732 } | |
2733 | |
4916 | 2734 #if 0 /* Faceprint! Look here! */ |
3314 | 2735 /* |
2736 * Remove a buddy item from the roster entirely | |
2737 */ | |
5572 | 2738 static void jabber_remove_buddy_roster_item(GaimConnection *gc, char *name) |
3314 | 2739 { |
3340 | 2740 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3314 | 2741 char *realwho; |
3340 | 2742 |
2743 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { | |
2744 xmlnode x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
2745 xmlnode y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); | |
2746 xmlnode_put_attrib(y, "jid", realwho); | |
2747 xmlnode_put_attrib(y, "subscription", "remove"); | |
2748 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); | |
2749 g_free(realwho); | |
2750 xmlnode_free(x); | |
2751 } | |
2752 } | |
4916 | 2753 #endif |
3340 | 2754 |
2755 /* | |
2756 * Unsubscribe a buddy from our presence | |
2757 */ | |
5572 | 2758 static void jabber_unsubscribe_buddy_from_us(GaimConnection *gc, const char *name) |
3340 | 2759 { |
2760 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; | |
2761 char *realwho; | |
2762 | |
2763 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { | |
2764 xmlnode g = xmlnode_new_tag("presence"); | |
2765 xmlnode_put_attrib(g, "to", realwho); | |
2766 xmlnode_put_attrib(g, "type", "unsubscribed"); | |
2767 gjab_send(gjc, g); | |
2768 xmlnode_free(g); | |
2769 } | |
2770 } | |
2771 | |
2772 /* | |
2773 * Common code for setting ourselves invisible/visible to buddy | |
2774 */ | |
5572 | 2775 static void jabber_invisible_to_buddy_common(GaimConnection *gc, const char *name, gboolean invisible) |
3340 | 2776 { |
3314 | 2777 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3340 | 2778 char *realwho; |
2779 | |
2780 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { | |
5135 | 2781 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho, TRUE); |
3340 | 2782 xmlnode g = xmlnode_new_tag("presence"); |
2783 | |
2784 xmlnode_put_attrib(g, "to", realwho); | |
2785 | |
2786 if(invisible) | |
2787 xmlnode_put_attrib(g, "type", "invisible"); | |
2788 | |
2789 gjab_send(gjc, g); | |
2790 | |
2791 g_free(realwho); | |
2792 xmlnode_free(g); | |
2793 | |
2794 if(jbd) { | |
2795 if(invisible) { | |
2796 jbd->invisible |= JABBER_BUD_INVIS; | |
2797 } else { | |
2798 jbd->invisible &= ~JABBER_BUD_INVIS; | |
2799 } | |
2800 } | |
2801 } | |
2802 } | |
2803 | |
2804 /* | |
2805 * Make ourselves temporarily invisible to a buddy | |
2806 */ | |
5572 | 2807 static void jabber_invisible_to_buddy(GaimConnection *gc, const char *name) |
3340 | 2808 { |
2809 jabber_invisible_to_buddy_common(gc, name, TRUE); | |
2810 } | |
2811 | |
2812 /* | |
2813 * Make ourselves visible to a buddy | |
2814 */ | |
5572 | 2815 static void jabber_visible_to_buddy(GaimConnection *gc, const char *name) |
3340 | 2816 { |
2817 jabber_invisible_to_buddy_common(gc, name, FALSE); | |
2818 } | |
2819 | |
2820 /* | |
2821 * Function used by the g_hash_table_foreach() in invisible_to_all_buddies() to | |
2822 * actually set the status. | |
2823 * | |
2824 * key is unused | |
2825 * value is the pointer to the jabber_buddy_data struct | |
2826 * data is gboolean: TRUE (invisible) or FALSE (not invisible) | |
2827 */ | |
2828 static void set_invisible_to_buddy_status(gpointer key, gpointer val, gpointer data) { | |
2829 struct jabber_buddy_data *jbd = val; | |
2830 gboolean invisible = (gboolean) data; | |
2831 | |
2832 if(jbd) { | |
2833 if(invisible) { | |
2834 jbd->invisible = JABBER_SERV_INVIS | JABBER_BUD_INVIS; | |
2835 } else { | |
2836 /* | |
2837 * If we've asserted server-level invisibility, cancelling | |
2838 * it removes explicit buddy invisibility settings too. | |
2839 */ | |
2840 if(jbd->invisible & JABBER_SERV_INVIS) | |
2841 jbd->invisible = JABBER_NOT_INVIS; | |
2842 } | |
2843 } | |
2844 } | |
2845 | |
2846 /* | |
2847 * Show we've set ourselves invisible/visible to all buddies on the server | |
2848 * | |
2849 * Used when we set server-wide invisibility so that individual buddy menu | |
2850 * entries show the proper option. | |
2851 */ | |
5572 | 2852 static void invisible_to_all_buddies(GaimConnection *gc, gboolean invisible) |
3340 | 2853 { |
2854 struct jabber_data *jd = gc->proto_data; | |
2855 | |
2856 if(jd->buddies != NULL) | |
2857 g_hash_table_foreach(jd->buddies, set_invisible_to_buddy_status, (gpointer) invisible); | |
3314 | 2858 } |
2859 | |
5572 | 2860 static const char *jabber_list_icon(GaimAccount *a, struct buddy *b) |
2086 | 2861 { |
4687 | 2862 return "jabber"; |
2863 } | |
4916 | 2864 |
2865 static void jabber_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne) | |
2866 { | |
5135 | 2867 struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); |
2868 | |
2869 if(!GAIM_BUDDY_IS_ONLINE(b)) { | |
2870 if (jbd && jbd->error_msg) | |
4927 | 2871 *nw = "error"; |
5135 | 2872 |
2873 if(jbd && (jbd->subscription & JABBER_SUB_PENDING || | |
2874 !(jbd->subscription & JABBER_SUB_TO))) | |
2875 *se = "notauthorized"; | |
2876 else | |
2877 *se = "offline"; | |
2878 | |
4916 | 2879 } else { |
2880 switch (b->uc) { | |
2881 case UC_AWAY: | |
2882 *se = "away"; | |
2883 break; | |
2884 case UC_CHAT: | |
2885 *se = "chat"; | |
2886 break; | |
2887 case UC_XA: | |
2888 *se = "extendedaway"; | |
2889 break; | |
2890 case UC_DND: | |
2891 *se = "dnd"; | |
2892 break; | |
2893 case UC_ERROR: | |
2894 *se = "error"; | |
2895 break; | |
2896 } | |
2086 | 2897 } |
4916 | 2898 } |
2086 | 2899 |
5572 | 2900 static GList *jabber_chat_info(GaimConnection *gc) |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2901 { |
2956 | 2902 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2903 | |
2904 static char *confserv = NULL; /* this pointer must be persistent */ | |
2905 gchar *server; | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2906 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2907 GList *m = NULL; |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2908 struct proto_chat_entry *pce; |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2909 |
2956 | 2910 /* This is a scientific wild-ass guess... |
2911 * | |
2912 * If there are more than two "components" to the current server name, | |
2913 * lop-off the left-most component and replace with "conference." | |
2914 */ | |
2915 if(confserv != NULL) { | |
2916 g_free(confserv); /* dispose of the old value */ | |
2917 } | |
2918 | |
2919 if((server = g_strdup(gjc->user->server)) == NULL) { | |
2920 confserv = g_strdup(DEFAULT_GROUPCHAT); | |
2921 } else { | |
2922 gchar **splits, **index; | |
2923 gchar *tmp; | |
2924 int cnt = 0; | |
2925 | |
2926 | |
2927 index = splits = g_strsplit(server, ".", -1); /* split the connected server */ | |
2928 | |
2929 while(*(index++)) /* index to the end--counting the parts */ | |
2930 ++cnt; | |
2931 | |
2932 /* | |
2933 * If we've more than two parts, point to the second part. Else point | |
2934 * to the start. | |
2935 */ | |
2936 if(cnt > 2) { | |
2937 index -= cnt; | |
2938 } else { | |
2939 index = splits; | |
2940 } | |
2941 | |
2942 /* Put it together */ | |
2943 confserv = g_strjoin(".", "conference", (tmp = g_strjoinv(".", index)), NULL); | |
2944 | |
2945 g_free(server); /* we don't need this stuff no more */ | |
2946 g_free(tmp); | |
2947 g_strfreev(splits); | |
2948 } | |
2949 | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2950 pce = g_new0(struct proto_chat_entry, 1); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2951 pce->label = _("Room:"); |
5234 | 2952 pce->identifier = "room"; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2953 m = g_list_append(m, pce); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2954 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2955 pce = g_new0(struct proto_chat_entry, 1); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2956 pce->label = _("Server:"); |
5234 | 2957 pce->identifier = "server"; |
2956 | 2958 pce->def = confserv; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2959 m = g_list_append(m, pce); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2960 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2961 pce = g_new0(struct proto_chat_entry, 1); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2962 pce->label = _("Handle:"); |
5234 | 2963 pce->identifier = "handle"; |
2956 | 2964 pce->def = gjc->user->user; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2965 m = g_list_append(m, pce); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2966 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2967 return m; |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2968 } |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2969 |
5572 | 2970 static void jabber_join_chat(GaimConnection *gc, GHashTable *data) |
2086 | 2971 { |
2972 xmlnode x; | |
5234 | 2973 char *room, *server, *handle; |
2086 | 2974 char *realwho; |
2956 | 2975 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2976 GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; | |
2086 | 2977 struct jabber_chat *jc; |
3311 | 2978 gaim_jid gjid; |
2086 | 2979 |
5234 | 2980 room = g_hash_table_lookup(data, "room"); |
2981 server = g_hash_table_lookup(data, "server"); | |
2982 handle = g_hash_table_lookup(data, "handle"); | |
2983 | |
2984 if (!room || !server || !handle) | |
2086 | 2985 return; |
2986 | |
5234 | 2987 realwho = create_valid_jid(room, server, handle); |
2988 gaim_debug(GAIM_DEBUG_INFO, "jabber", "%s\n", realwho); | |
2086 | 2989 |
3311 | 2990 if((gjid = gaim_jid_new(realwho)) == NULL) { |
3427 | 2991 char *msg = g_strdup_printf("The Jabber I.D. %s is invalid.", realwho); |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2992 gaim_notify_error(gc, NULL, _("Unable to join chat"), msg); |
3236 | 2993 g_free(msg); |
3311 | 2994 g_free(realwho); |
3236 | 2995 return; |
2996 } | |
2956 | 2997 |
3311 | 2998 if((jc = find_any_chat(gc, gjid)) != NULL) { |
2956 | 2999 switch(jc->state) { |
3000 case JCS_PENDING: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3001 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3002 "attempt to re-join already pending Jabber chat! (ignoring)\n"); |
2956 | 3003 g_free(realwho); /* yuck! */ |
3311 | 3004 gaim_jid_free(gjid); |
2956 | 3005 return; |
3006 case JCS_ACTIVE: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3007 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3008 "attempt to re-join already active Jabber chat! (ignoring)\n"); |
2956 | 3009 g_free(realwho); /* yuck! */ |
3311 | 3010 gaim_jid_free(gjid); |
2956 | 3011 return; |
3012 case JCS_CLOSED: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3013 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3014 "rejoining previously closed Jabber chat\n"); |
2956 | 3015 break; |
3016 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3017 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3018 "found Jabber chat in unknown state! (ignoring)\n"); |
2956 | 3019 g_free(realwho); /* yuck! */ |
3311 | 3020 gaim_jid_free(gjid); |
2956 | 3021 return; |
3022 } | |
3023 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3024 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3025 "joining completely new Jabber chat\n"); |
2956 | 3026 jc = g_new0(struct jabber_chat, 1); |
3311 | 3027 jc->gjid = gjid; |
2956 | 3028 jc->gc = gc; |
3029 ((struct jabber_data *)gc->proto_data)->chats = g_slist_append(jcs, jc); | |
4687 | 3030 // add_buddy(gc->account, _("Chats"), realwho, realwho); |
2956 | 3031 } |
3032 | |
3033 jc->state = JCS_PENDING; | |
3034 | |
2086 | 3035 x = jutil_presnew(0, realwho, NULL); |
2956 | 3036 gjab_send(gjc, x); |
2086 | 3037 xmlnode_free(x); |
3038 g_free(realwho); | |
3039 } | |
3040 | |
5572 | 3041 static void jabber_chat_invite(GaimConnection *gc, int id, const char *message, const char *name) |
2086 | 3042 { |
3043 xmlnode x, y; | |
3044 struct jabber_data *jd = gc->proto_data; | |
2956 | 3045 gjconn gjc = jd->gjc; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3046 struct jabber_chat *jc = NULL; |
2086 | 3047 char *realwho, *subject; |
3048 | |
3311 | 3049 if(!name || (realwho = get_realwho(gjc, name, FALSE, NULL)) == NULL) |
2086 | 3050 return; |
3051 | |
3052 /* find which chat we're inviting to */ | |
2956 | 3053 if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) |
2086 | 3054 return; |
3055 | |
3056 x = xmlnode_new_tag("message"); | |
3057 xmlnode_put_attrib(x, "to", realwho); | |
3311 | 3058 |
2086 | 3059 g_free(realwho); |
3060 | |
3061 y = xmlnode_insert_tag(x, "x"); | |
3062 xmlnode_put_attrib(y, "xmlns", "jabber:x:conference"); | |
3311 | 3063 subject = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); |
2086 | 3064 xmlnode_put_attrib(y, "jid", subject); |
3065 g_free(subject); | |
3066 | |
3067 if (message && strlen(message)) { | |
5093 | 3068 insert_message(x, message, FALSE); |
2086 | 3069 } |
3070 | |
2956 | 3071 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 3072 xmlnode_free(x); |
3073 } | |
3074 | |
5572 | 3075 static void jabber_chat_leave(GaimConnection *gc, int id) |
2086 | 3076 { |
3077 struct jabber_data *jd = gc->proto_data; | |
2956 | 3078 gjconn gjc = jd->gjc; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3079 struct jabber_chat *jc = NULL; |
3311 | 3080 char *chatname; |
2086 | 3081 xmlnode x; |
3082 | |
2956 | 3083 /* Find out which chat we're leaving */ |
3084 if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) | |
2086 | 3085 return; |
3086 | |
3311 | 3087 chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); |
3088 x = jutil_presnew(0, chatname, NULL); | |
3089 g_free(chatname); | |
2086 | 3090 xmlnode_put_attrib(x, "type", "unavailable"); |
2956 | 3091 gjab_send(gjc, x); |
2086 | 3092 xmlnode_free(x); |
3093 jc->b = NULL; | |
3094 } | |
3095 | |
6059 | 3096 static int jabber_chat_send(GaimConnection *gc, int id, const char *message) |
2086 | 3097 { |
3098 xmlnode x, y; | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3099 struct jabber_chat *jc = NULL; |
2086 | 3100 char *chatname; |
2956 | 3101 int retval = 0; |
3102 | |
3103 /* Find out which chat we're sending to */ | |
3104 if((retval = jabber_find_chat_by_convo_id(gc, id, &jc)) != 0) | |
3105 return(retval); | |
2086 | 3106 |
3107 x = xmlnode_new_tag("message"); | |
3311 | 3108 xmlnode_put_attrib(x, "from", jc->gjid->full); |
3109 chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); | |
2086 | 3110 xmlnode_put_attrib(x, "to", chatname); |
3111 g_free(chatname); | |
3112 xmlnode_put_attrib(x, "type", "groupchat"); | |
3113 | |
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3114 if (message && strlen(message) > strlen("/topic ") && |
4793 | 3115 !g_ascii_strncasecmp(message, "/topic ", strlen("/topic "))) { |
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3116 char buf[8192]; |
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3117 y = xmlnode_insert_tag(x, "subject"); |
3642 | 3118 xmlnode_insert_cdata(y, message + strlen("/topic "), -1); |
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3119 y = xmlnode_insert_tag(x, "body"); |
3642 | 3120 g_snprintf(buf, sizeof(buf), "/me has changed the subject to: %s", message + strlen("/topic")); |
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3121 xmlnode_insert_cdata(y, buf, -1); |
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3122 } else if (message && strlen(message)) { |
5093 | 3123 insert_message(x, message, FALSE); |
2086 | 3124 } |
3125 | |
2956 | 3126 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 3127 xmlnode_free(x); |
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
3128 return 0; |
2086 | 3129 } |
3130 | |
6059 | 3131 static void jabber_chat_whisper(GaimConnection *gc, int id, const char *who, const char *message) |
2086 | 3132 { |
5093 | 3133 xmlnode x; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3134 struct jabber_chat *jc = NULL; |
2086 | 3135 char *chatname; |
3136 | |
2956 | 3137 /* Find out which chat we're whispering to */ |
3138 if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) | |
2086 | 3139 return; |
3140 | |
3141 x = xmlnode_new_tag("message"); | |
3311 | 3142 xmlnode_put_attrib(x, "from", jc->gjid->full); |
3143 chatname = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); | |
2086 | 3144 xmlnode_put_attrib(x, "to", chatname); |
3145 g_free(chatname); | |
3146 xmlnode_put_attrib(x, "type", "normal"); | |
3147 | |
3148 if (message && strlen(message)) { | |
5093 | 3149 insert_message(x, message, FALSE); |
2086 | 3150 } |
3151 | |
2956 | 3152 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 3153 xmlnode_free(x); |
3154 } | |
3155 | |
3156 static char *jabber_normalize(const char *s) | |
3157 { | |
3158 static char buf[BUF_LEN]; | |
3159 char *t, *u; | |
3160 int x = 0; | |
3161 | |
3162 g_return_val_if_fail((s != NULL), NULL); | |
3163 | |
2956 | 3164 /* Somebody called us with s == NULL once... */ |
3165 if(s == NULL) { | |
3166 return(NULL); | |
3167 } else { | |
4793 | 3168 u = t = g_utf8_strdown(s, -1); |
2956 | 3169 |
3170 while (*t && (x < BUF_LEN - 1)) { | |
3171 if (*t != ' ') | |
3172 buf[x++] = *t; | |
3173 t++; | |
3174 } | |
3175 buf[x] = '\0'; | |
3176 g_free(u); | |
3177 | |
3178 if (!strchr(buf, '@')) { | |
4927 | 3179 strcat(buf, "@" DEFAULT_SERVER); /* this isn't always right, but eh */ |
2956 | 3180 } else if ((u = strchr(strchr(buf, '@'), '/')) != NULL) { |
3181 *u = '\0'; | |
3182 } | |
3183 | |
3184 return buf; | |
2086 | 3185 } |
3186 } | |
3187 | |
5572 | 3188 static void jabber_get_info(GaimConnection *gc, const char *who) { |
2086 | 3189 xmlnode x; |
3190 char *id; | |
2956 | 3191 char *realwho; |
2086 | 3192 struct jabber_data *jd = gc->proto_data; |
2956 | 3193 gjconn gjc = jd->gjc; |
2086 | 3194 |
3311 | 3195 if((realwho = get_realwho(gjc, who, TRUE, NULL)) == NULL) |
3196 return; | |
3197 | |
2086 | 3198 x = jutil_iqnew(JPACKET__GET, NS_VCARD); |
2956 | 3199 xmlnode_put_attrib(x, "to", realwho); |
3311 | 3200 |
2956 | 3201 g_free(realwho); |
3202 | |
3203 id = gjab_getid(gjc); | |
2086 | 3204 xmlnode_put_attrib(x, "id", id); |
3205 | |
2956 | 3206 g_hash_table_insert(jd->gjc->queries, g_strdup(id), g_strdup("vCard")); |
3207 | |
3208 gjab_send(gjc, x); | |
2086 | 3209 |
3210 xmlnode_free(x); | |
3311 | 3211 } |
3212 | |
5572 | 3213 static void jabber_get_error_msg(GaimConnection *gc, const char *who) { |
3311 | 3214 struct jabber_data *jd = gc->proto_data; |
3215 gjconn gjc = jd->gjc; | |
3216 gchar **str_arr = (gchar **) g_new(gpointer, 3); | |
3217 gchar **ap = str_arr; | |
3218 gchar *realwho, *final; | |
3219 struct jabber_buddy_data *jbd; | |
3220 | |
3221 if((realwho = get_realwho(gjc, who, FALSE, NULL)) == NULL) { | |
3222 g_strfreev(str_arr); | |
3223 return; | |
3224 } | |
3225 | |
5135 | 3226 jbd = jabber_find_buddy(gc, realwho, TRUE); |
3311 | 3227 |
5236 | 3228 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), realwho); |
3229 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Error"), jbd->error_msg); | |
3311 | 3230 *ap = NULL; |
3770 | 3231 |
3311 | 3232 final= g_strjoinv(NULL, str_arr); |
3770 | 3233 |
3311 | 3234 g_strfreev(str_arr); |
3235 | |
3236 g_show_info_text(gc, realwho, 2, final, NULL); | |
3237 g_free(realwho); | |
3238 g_free(final); | |
2086 | 3239 } |
3240 | |
5572 | 3241 static void jabber_get_away_msg(GaimConnection *gc, const char *who) { |
2956 | 3242 struct jabber_data *jd = gc->proto_data; |
3243 gjconn gjc = jd->gjc; | |
3311 | 3244 int num_resources; |
3245 gaim_jid gjid; | |
3246 char *buddy = get_realwho(gjc, who, FALSE, &gjid); | |
5135 | 3247 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, TRUE); |
3311 | 3248 gchar **str_arr; |
3249 gchar **ap; | |
3250 gchar *realwho, *final; | |
3251 GSList *resources; | |
3252 int i; | |
3253 | |
3254 if(!buddy) | |
3255 return; | |
3256 | |
3257 if(!gjid->resource) { | |
3258 num_resources = g_slist_length(jbd->resources); | |
3259 resources = jbd->resources; | |
3260 } else { | |
3261 num_resources = 1; | |
3262 resources = jbd->resources; | |
3263 while(strcasecmp(((jab_res_info)resources->data)->name, gjid->resource)) | |
3264 resources = resources->next; | |
3265 } | |
3266 | |
3267 gaim_jid_free(gjid); | |
2956 | 3268 |
3269 /* space for all elements: Jabber I.D. + "status" + NULL (list terminator) */ | |
3311 | 3270 str_arr = (gchar **) g_new(gpointer, num_resources*2 + 1); |
3271 ap = str_arr; | |
3272 | |
3273 for(i=0; i<num_resources; i++) | |
3274 { | |
3275 jab_res_info jri = resources->data; | |
4450 | 3276 char *status; |
3311 | 3277 realwho = g_strdup_printf("%s/%s", buddy, jri->name); |
4450 | 3278 status = strdup_withhtml(jabber_lookup_away(gjc, realwho)); |
5236 | 3279 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), realwho); |
3280 *ap++ = g_strdup_printf("<B>%s:</B> %s%s%s<BR>\n", _("Status"), jabber_get_state_string(jri->state), status ? ": " : "", status ? status : ""); | |
4450 | 3281 g_free(status); |
3311 | 3282 g_free(realwho); |
3283 resources = resources->next; | |
2956 | 3284 } |
3285 | |
3286 *ap = NULL; | |
3770 | 3287 |
3311 | 3288 g_free(buddy); |
2956 | 3289 |
3290 final= g_strjoinv(NULL, str_arr); | |
3291 g_strfreev(str_arr); | |
3292 | |
3311 | 3293 g_show_info_text(gc, who, 2, final, NULL); |
2956 | 3294 g_free(final); |
3770 | 3295 |
2956 | 3296 } |
3297 | |
6059 | 3298 static void jabber_get_cb_info(GaimConnection *gc, int cid, const char *who) { |
2956 | 3299 struct jabber_chat *jc = NULL; |
3300 char *realwho; | |
3301 | |
3302 /* Find out which chat */ | |
3303 if(jabber_find_chat_by_convo_id(gc, cid, &jc) != 0) | |
3304 return; | |
3305 | |
3311 | 3306 realwho = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); |
2956 | 3307 |
3308 jabber_get_info(gc, realwho); | |
3309 g_free(realwho); | |
3310 } | |
3311 | |
6059 | 3312 static void jabber_get_cb_away_msg(GaimConnection *gc, int cid, const char *who) { |
2956 | 3313 struct jabber_chat *jc = NULL; |
3314 char *realwho; | |
3315 | |
3316 /* Find out which chat */ | |
3317 if(jabber_find_chat_by_convo_id(gc, cid, &jc) != 0) | |
3318 return; | |
3319 | |
3311 | 3320 realwho = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); |
2956 | 3321 |
3322 jabber_get_away_msg(gc, realwho); | |
3323 g_free(realwho); | |
3324 | |
3325 } | |
3326 | |
4744 | 3327 static char *jabber_tooltip_text(struct buddy *b) |
3328 { | |
5135 | 3329 struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); |
4745 | 3330 jab_res_info jri = jabber_find_resource(b->account->gc, b->name); |
5135 | 3331 char *ret = NULL; |
4745 | 3332 if(jri) { |
4777 | 3333 char *stripped = strip_html(jabber_lookup_away(GC_GJ(b->account->gc), |
4745 | 3334 b->name)); |
4777 | 3335 char *text = NULL; |
3336 if(stripped) | |
3337 text = g_markup_escape_text(stripped, strlen(stripped)); | |
5236 | 3338 ret = g_strdup_printf("<b>%s:</b> %s%s%s", |
3339 _("Status"), | |
4745 | 3340 jabber_get_state_string(jri->state), text ? ": " : "", |
3341 text ? text : ""); | |
3342 | |
4777 | 3343 if(stripped) { |
3344 g_free(stripped); | |
4745 | 3345 g_free(text); |
4777 | 3346 } |
5136 | 3347 } else if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && |
3348 (jbd->subscription & JABBER_SUB_PENDING || | |
5135 | 3349 !(jbd->subscription & JABBER_SUB_TO))) { |
5236 | 3350 ret = g_strdup_printf("<b>%s:</b> %s", _("Status"), _("Not Authorized")); |
4745 | 3351 } |
5135 | 3352 return ret; |
4744 | 3353 } |
3354 | |
4732 | 3355 static char *jabber_status_text(struct buddy *b) |
3356 { | |
5135 | 3357 struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); |
3358 char *ret = NULL; | |
4732 | 3359 if (b->uc & UC_UNAVAILABLE) { |
4777 | 3360 char *stripped = strip_html(jabber_lookup_away(GC_GJ(b->account->gc), |
4745 | 3361 b->name)); |
4777 | 3362 if(!stripped) { |
4745 | 3363 jab_res_info jri = jabber_find_resource(b->account->gc, b->name); |
3364 if(jri) | |
4777 | 3365 stripped = g_strdup(jabber_get_state_string(jri->state)); |
4745 | 3366 } |
4777 | 3367 ret = g_markup_escape_text(stripped, strlen(stripped)); |
3368 g_free(stripped); | |
5136 | 3369 } else if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && |
3370 (jbd->subscription & JABBER_SUB_PENDING || | |
5135 | 3371 !(jbd->subscription & JABBER_SUB_TO))) { |
3372 ret = g_strdup(_("Not Authorized")); | |
4732 | 3373 } |
5135 | 3374 return ret; |
4732 | 3375 } |
3376 | |
5572 | 3377 static GList *jabber_buddy_menu(GaimConnection *gc, const char *who) { |
2170
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3378 GList *m = NULL; |
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3379 struct proto_buddy_menu *pbm; |
4687 | 3380 struct buddy *b = gaim_find_buddy(gc->account, who); |
3311 | 3381 |
3382 if(b->uc == UC_ERROR) | |
3383 { | |
3384 pbm = g_new0(struct proto_buddy_menu, 1); | |
3385 pbm->label = _("View Error Msg"); | |
3386 pbm->callback = jabber_get_error_msg; | |
3387 pbm->gc = gc; | |
3388 m = g_list_append(m, pbm); | |
3389 } else { | |
3340 | 3390 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3391 char *realwho = get_realwho(gjc, who, FALSE, NULL); | |
5135 | 3392 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho, FALSE); |
3340 | 3393 |
3394 g_free(realwho); | |
3395 | |
3311 | 3396 pbm = g_new0(struct proto_buddy_menu, 1); |
3397 pbm->label = _("Get Away Msg"); | |
3398 pbm->callback = jabber_get_away_msg; | |
3399 pbm->gc = gc; | |
3400 m = g_list_append(m, pbm); | |
3340 | 3401 |
3402 pbm = g_new0(struct proto_buddy_menu, 1); | |
3403 if(jbd && (jbd->invisible & JABBER_BUD_INVIS)) { | |
3404 pbm->label = _("Un-hide From"); | |
3405 pbm->callback = jabber_visible_to_buddy; | |
3406 } else { | |
3407 pbm->label = _("Temporarily Hide From"); | |
3408 pbm->callback = jabber_invisible_to_buddy; | |
3409 } | |
4916 | 3410 |
3411 pbm->gc = gc; | |
3412 m = g_list_append(m, pbm); | |
3413 pbm = g_new0(struct proto_buddy_menu, 1); | |
3414 pbm->label = _("Cancel Presence Notification"); | |
3415 pbm->callback = jabber_unsubscribe_buddy_from_us; | |
3340 | 3416 pbm->gc = gc; |
3417 m = g_list_append(m, pbm); | |
5136 | 3418 |
3419 if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && | |
3420 !(jbd->subscription & JABBER_SUB_TO)) { | |
3421 pbm = g_new0(struct proto_buddy_menu, 1); | |
3422 pbm->label = _("Re-request authorization"); | |
3423 pbm->callback = jabber_add_buddy; | |
3424 pbm->gc = gc; | |
3425 m = g_list_append(m, pbm); | |
3426 } | |
3311 | 3427 } |
2170
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3428 |
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3429 return m; |
2086 | 3430 } |
3431 | |
5572 | 3432 static GList *jabber_away_states(GaimConnection *gc) { |
2086 | 3433 GList *m = NULL; |
3434 | |
4982 | 3435 m = g_list_append(m, _("Online")); |
3436 m = g_list_append(m, _("Chatty")); | |
3437 m = g_list_append(m, _("Away")); | |
3438 m = g_list_append(m, _("Extended Away")); | |
3439 m = g_list_append(m, _("Do Not Disturb")); | |
3440 m = g_list_append(m, _("Invisible")); | |
4110 | 3441 m = g_list_append(m, GAIM_AWAY_CUSTOM); |
2086 | 3442 |
3443 return m; | |
3444 } | |
3445 | |
6059 | 3446 static void jabber_set_away(GaimConnection *gc, const char *state, const char *message) |
2086 | 3447 { |
3448 xmlnode x, y; | |
3449 struct jabber_data *jd = gc->proto_data; | |
2956 | 3450 gjconn gjc = jd->gjc; |
3311 | 3451 GSList *jcs; |
3452 struct jabber_chat *jc; | |
3453 char *chatname; | |
3340 | 3454 gboolean invisible = FALSE; |
2086 | 3455 |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3456 if (gc->away) { |
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3457 g_free(gc->away); |
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3458 gc->away = NULL; |
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3459 } |
2086 | 3460 |
3461 x = xmlnode_new_tag("presence"); | |
3462 | |
3463 if (!strcmp(state, GAIM_AWAY_CUSTOM)) { | |
3464 /* oh goody. Gaim is telling us what to do. */ | |
3465 if (message) { | |
3466 /* Gaim wants us to be away */ | |
5174 | 3467 char *stripped; |
3468 | |
3469 /* Jabber supports XHTML in IMs, but not in away messages. */ | |
3470 html_to_xhtml(message, NULL, &stripped); | |
3471 | |
2086 | 3472 y = xmlnode_insert_tag(x, "show"); |
3473 xmlnode_insert_cdata(y, "away", -1); | |
3474 y = xmlnode_insert_tag(x, "status"); | |
5174 | 3475 xmlnode_insert_cdata(y, stripped, -1); |
3476 | |
3477 gc->away = g_strdup(stripped); | |
3478 g_free(stripped); | |
2086 | 3479 } else { |
3480 /* Gaim wants us to not be away */ | |
3481 /* but for Jabber, we can just send presence with no other information. */ | |
3482 } | |
3483 } else { | |
3484 /* state is one of our own strings. it won't be NULL. */ | |
4982 | 3485 if (!strcmp(state, _("Online"))) { |
2086 | 3486 /* once again, we don't have to put anything here */ |
4982 | 3487 } else if (!strcmp(state, _("Chatty"))) { |
2086 | 3488 y = xmlnode_insert_tag(x, "show"); |
3489 xmlnode_insert_cdata(y, "chat", -1); | |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3490 gc->away = g_strdup(""); |
4982 | 3491 } else if (!strcmp(state, _("Away"))) { |
2086 | 3492 y = xmlnode_insert_tag(x, "show"); |
3493 xmlnode_insert_cdata(y, "away", -1); | |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3494 gc->away = g_strdup(""); |
4982 | 3495 } else if (!strcmp(state, _("Extended Away"))) { |
2086 | 3496 y = xmlnode_insert_tag(x, "show"); |
3497 xmlnode_insert_cdata(y, "xa", -1); | |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3498 gc->away = g_strdup(""); |
4982 | 3499 } else if (!strcmp(state, _("Do Not Disturb"))) { |
2086 | 3500 y = xmlnode_insert_tag(x, "show"); |
3501 xmlnode_insert_cdata(y, "dnd", -1); | |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3502 gc->away = g_strdup(""); |
4982 | 3503 } else if (!strcmp(state, _("Invisible"))) { |
3340 | 3504 xmlnode_put_attrib(x, "type", "invisible"); |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3505 gc->away = g_strdup(""); |
3340 | 3506 invisible = TRUE; |
2086 | 3507 } |
3508 } | |
3509 | |
3311 | 3510 gjab_send(gjc, x); /* Notify "individuals" */ |
3511 | |
3512 /* | |
3513 * As of jabberd-1.4.2: simply sending presence to the server doesn't result in | |
3514 * it being propagated to conference rooms. So we wade thru the list of chats, | |
3515 * sending our new presence status to each and every one. | |
3516 */ | |
3517 for(jcs = jd->chats; jcs; jcs = jcs->next) { | |
3518 jc = jcs->data; | |
3519 if(jc->state == JCS_ACTIVE) { | |
3520 xmlnode_put_attrib(x, "from", jc->gjid->full); | |
3521 chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); | |
3522 xmlnode_put_attrib(x, "to", chatname); | |
3523 gjab_send(gjc, x); | |
3524 g_free(chatname); | |
3525 } | |
3526 } | |
3527 | |
2086 | 3528 xmlnode_free(x); |
3340 | 3529 |
3530 invisible_to_all_buddies(gc, invisible); | |
2086 | 3531 } |
3532 | |
5572 | 3533 static void jabber_set_idle(GaimConnection *gc, int idle) { |
2086 | 3534 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3535 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3536 "jabber_set_idle: setting idle %i\n", idle); |
3770 | 3537 jd->idle = idle ? time(NULL) - idle : idle; |
2086 | 3538 } |
3539 | |
5572 | 3540 static void jabber_keepalive(GaimConnection *gc) { |
2086 | 3541 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; |
4450 | 3542 gjab_send_raw(jd->gjc, JABBER_KEEPALIVE_STRING); |
2086 | 3543 } |
3544 | |
2956 | 3545 /*---------------------------------------*/ |
3546 /* Jabber "set info" (vCard) support */ | |
3547 /*---------------------------------------*/ | |
3548 | |
3549 /* | |
3550 * V-Card format: | |
3551 * | |
3552 * <vCard prodid='' version='' xmlns=''> | |
3553 * <FN></FN> | |
3554 * <N> | |
3555 * <FAMILY/> | |
3556 * <GIVEN/> | |
3557 * </N> | |
3558 * <NICKNAME/> | |
3559 * <URL/> | |
3560 * <ADR> | |
3561 * <STREET/> | |
3562 * <EXTADD/> | |
3563 * <LOCALITY/> | |
3564 * <REGION/> | |
3565 * <PCODE/> | |
3566 * <COUNTRY/> | |
3567 * </ADR> | |
3568 * <TEL/> | |
3569 * <EMAIL/> | |
3570 * <ORG> | |
3571 * <ORGNAME/> | |
3572 * <ORGUNIT/> | |
3573 * </ORG> | |
3574 * <TITLE/> | |
3575 * <ROLE/> | |
3576 * <DESC/> | |
3577 * <BDAY/> | |
3578 * </vCard> | |
3579 * | |
3580 * See also: | |
3581 * | |
3582 * http://docs.jabber.org/proto/html/vcard-temp.html | |
3583 * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd | |
3584 */ | |
3585 | |
3586 /* | |
3587 * Cross-reference user-friendly V-Card entry labels to vCard XML tags | |
3588 * and attributes. | |
3589 * | |
3590 * Order is (or should be) unimportant. For example: we have no way of | |
3591 * knowing in what order real data will arrive. | |
3592 * | |
3593 * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag | |
3594 * name, XML tag's parent tag "path" (relative to vCard node). | |
3595 * | |
3596 * List is terminated by a NULL label pointer. | |
3597 * | |
3598 * Entries with no label text, but with XML tag and parent tag | |
3599 * entries, are used by V-Card XML construction routines to | |
3600 * "automagically" construct the appropriate XML node tree. | |
3601 * | |
3602 * Thoughts on future direction/expansion | |
3603 * | |
3604 * This is a "simple" vCard. | |
3605 * | |
3606 * It is possible for nodes other than the "vCard" node to have | |
3607 * attributes. Should that prove necessary/desirable, add an | |
3608 * "attributes" pointer to the vcard_template struct, create the | |
3609 * necessary tag_attr structs, and add 'em to the vcard_dflt_data | |
3610 * array. | |
3611 * | |
3612 * The above changes will (obviously) require changes to the vCard | |
3613 * construction routines. | |
3614 */ | |
3615 | |
3616 struct vcard_template { | |
3617 char *label; /* label text pointer */ | |
3618 char *text; /* entry text pointer */ | |
3619 int visible; /* should entry field be "visible?" */ | |
3620 int editable; /* should entry field be editable? */ | |
3621 char *tag; /* tag text */ | |
3622 char *ptag; /* parent tag "path" text */ | |
3623 char *url; /* vCard display format if URL */ | |
3624 } vcard_template_data[] = { | |
2975 | 3625 {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, |
3626 {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, | |
3627 {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, | |
3628 {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, | |
3629 {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, | |
3630 {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, | |
3631 {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, | |
3632 {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, | |
3633 {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, | |
3634 {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, | |
3635 {N_("Country"), NULL, TRUE, TRUE, "COUNTRY", "ADR", NULL}, | |
3636 {N_("Telephone"), NULL, TRUE, TRUE, "TELEPHONE", NULL, NULL}, | |
3637 {N_("Email"), NULL, TRUE, TRUE, "EMAIL", NULL, "<A HREF=\"mailto:%s\">%s</A>"}, | |
3638 {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, | |
3639 {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, | |
3640 {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, | |
3641 {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, | |
3642 {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, | |
3643 {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, | |
2956 | 3644 {"", NULL, TRUE, TRUE, "N", NULL, NULL}, |
3645 {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, | |
3646 {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, | |
3647 {NULL, NULL, 0, 0, NULL, NULL, NULL} | |
3648 }; | |
3649 | |
3650 /* | |
3651 * The "vCard" tag's attibute list... | |
3652 */ | |
3653 struct tag_attr { | |
3654 char *attr; | |
3655 char *value; | |
3656 } vcard_tag_attr_list[] = { | |
3657 {"prodid", "-//HandGen//NONSGML vGen v1.0//EN"}, | |
3658 {"version", "2.0", }, | |
3659 {"xmlns", "vcard-temp", }, | |
3660 {NULL, NULL}, | |
3661 }; | |
3662 | |
3663 | |
3664 /* | |
3665 * Used by routines to parse an XML-encoded string into an xmlnode tree | |
3666 */ | |
3667 typedef struct { | |
3668 XML_Parser parser; | |
3669 xmlnode current; | |
3670 } *xmlstr2xmlnode_parser, xmlstr2xmlnode_parser_struct; | |
3671 | |
3672 | |
3673 /* | |
3674 * Display a Jabber vCard | |
3675 */ | |
3676 static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from) | |
3677 { | |
5572 | 3678 GaimConnection *gc = GJ_GC(gjc); |
2956 | 3679 char *cdata, *status; |
3680 struct vcard_template *vc_tp = vcard_template_data; | |
3681 | |
3682 /* space for all vCard elements + Jabber I.D. + "status" + NULL (list terminator) */ | |
3683 gchar **str_arr = (gchar **) g_new(gpointer, | |
3684 (sizeof(vcard_template_data)/sizeof(struct vcard_template)) + 3); | |
3685 gchar **ap = str_arr; | |
3686 gchar *buddy, *final; | |
3687 | |
4745 | 3688 jab_res_info jri; |
3689 | |
3311 | 3690 if((buddy = get_realwho(gjc, from, TRUE, NULL)) == NULL) { |
3691 g_strfreev(str_arr); | |
3692 return; | |
2956 | 3693 } |
3311 | 3694 |
4745 | 3695 jri = jabber_find_resource(GJ_GC(gjc), buddy); |
3696 | |
5236 | 3697 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), buddy); |
2956 | 3698 |
3699 for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { | |
3700 if(strcmp(vc_tp->tag, "DESC") == 0) | |
3701 continue; /* special handling later */ | |
3702 if(vc_tp->ptag == NULL) { | |
3703 cdata = xmlnode_get_tag_data(querynode, vc_tp->tag); | |
3704 } else { | |
3705 gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); | |
3706 cdata = xmlnode_get_tag_data(querynode, tag); | |
3707 g_free(tag); | |
3708 } | |
3709 if(cdata != NULL) { | |
3710 if(vc_tp->url == NULL) { | |
5236 | 3711 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _(vc_tp->label), cdata); |
2956 | 3712 } else { |
3713 gchar *fmt = g_strdup_printf("<B>%%s:</B> %s<BR>\n", vc_tp->url); | |
5236 | 3714 *ap++ = g_strdup_printf(fmt, _(vc_tp->label), cdata, cdata); |
2956 | 3715 g_free(fmt); |
3716 } | |
3717 } | |
3718 } | |
3719 | |
4745 | 3720 |
4450 | 3721 status = strdup_withhtml(jabber_lookup_away(gjc, buddy)); |
5236 | 3722 *ap++ = g_strdup_printf("<B>%s:</B> %s%s%s<BR>\n", |
3723 _("Status"), | |
4745 | 3724 jri ? jabber_get_state_string(jri->state) : "", |
3725 jri && status ? ": " : "", status ? status : ""); | |
4450 | 3726 g_free(status); |
2956 | 3727 |
3728 /* | |
3729 * "Description" handled as a special case: get a copy of the | |
3730 * string and HTML-ize. | |
3731 */ | |
3732 if((cdata = xmlnode_get_tag_data(querynode, "DESC")) != NULL) { | |
3733 gchar *tmp = g_strdup_printf("<HR>%s<BR>", cdata); | |
3734 *ap++ = strdup_withhtml(tmp); | |
3735 g_free(tmp); | |
3736 } | |
3737 | |
3738 *ap = NULL; | |
3739 | |
3740 final= g_strjoinv(NULL, str_arr); | |
3741 g_strfreev(str_arr); | |
3742 | |
3743 g_show_info_text(gc, buddy, 2, final, NULL); | |
3744 g_free(buddy); | |
3745 g_free(final); | |
3746 } | |
3747 | |
3748 /* | |
3749 * Used by XML_Parse on parsing CDATA | |
3750 */ | |
3751 static void xmlstr2xmlnode_charData(void *userdata, const char *s, int slen) | |
3752 { | |
3753 xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; | |
3754 | |
3755 if (xmlp->current) | |
3756 xmlnode_insert_cdata(xmlp->current, s, slen); | |
3757 } | |
3758 | |
3759 /* | |
3760 * Used by XML_Parse to start or append to an xmlnode | |
3761 */ | |
3762 static void xmlstr2xmlnode_startElement(void *userdata, const char *name, const char **attribs) | |
3763 { | |
3764 xmlnode x; | |
3765 xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; | |
3766 | |
3767 if (xmlp->current) { | |
3768 /* Append the node to the current one */ | |
3769 x = xmlnode_insert_tag(xmlp->current, name); | |
3770 xmlnode_put_expat_attribs(x, attribs); | |
3771 | |
3772 xmlp->current = x; | |
3773 } else { | |
3774 x = xmlnode_new_tag(name); | |
3775 xmlnode_put_expat_attribs(x, attribs); | |
3776 xmlp->current = x; | |
3777 } | |
3778 } | |
3779 | |
3780 /* | |
3781 * Used by XML_Parse to end an xmlnode | |
3782 */ | |
3783 static void xmlstr2xmlnode_endElement(void *userdata, const char *name) | |
3784 { | |
3785 xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; | |
3786 xmlnode x; | |
3787 | |
3788 if (xmlp->current != NULL && (x = xmlnode_get_parent(xmlp->current)) != NULL) { | |
3789 xmlp->current = x; | |
3790 } | |
3791 } | |
3792 | |
3793 /* | |
3794 * Parse an XML-encoded string into an xmlnode tree | |
3795 * | |
3796 * Caller is responsible for freeing the returned xmlnode | |
3797 */ | |
3798 static xmlnode xmlstr2xmlnode(char *xmlstring) | |
3799 { | |
3800 xmlstr2xmlnode_parser my_parser = g_new(xmlstr2xmlnode_parser_struct, 1); | |
3801 xmlnode x = NULL; | |
3802 | |
3803 my_parser->parser = XML_ParserCreate(NULL); | |
3804 my_parser->current = NULL; | |
3805 | |
3806 XML_SetUserData(my_parser->parser, (void *)my_parser); | |
3807 XML_SetElementHandler(my_parser->parser, xmlstr2xmlnode_startElement, xmlstr2xmlnode_endElement); | |
3808 XML_SetCharacterDataHandler(my_parser->parser, xmlstr2xmlnode_charData); | |
3809 XML_Parse(my_parser->parser, xmlstring, strlen(xmlstring), 0); | |
3810 | |
3811 x = my_parser->current; | |
3812 | |
3813 XML_ParserFree(my_parser->parser); | |
3814 g_free(my_parser); | |
3815 | |
3816 return(x); | |
3817 } | |
3818 | |
3819 /* | |
3820 * Insert a tag node into an xmlnode tree, recursively inserting parent tag | |
3821 * nodes as necessary | |
3822 * | |
3823 * Returns pointer to inserted node | |
3824 * | |
3825 * Note to hackers: this code is designed to be re-entrant (it's recursive--it | |
3826 * calls itself), so don't put any "static"s in here! | |
3827 */ | |
3828 static xmlnode insert_tag_to_parent_tag(xmlnode start, const char *parent_tag, const char *new_tag) | |
3829 { | |
3830 xmlnode x = NULL; | |
3831 | |
3832 /* | |
3833 * If the parent tag wasn't specified, see if we can get it | |
3834 * from the vCard template struct. | |
3835 */ | |
3836 if(parent_tag == NULL) { | |
3837 struct vcard_template *vc_tp = vcard_template_data; | |
3838 | |
3839 while(vc_tp->label != NULL) { | |
3840 if(strcmp(vc_tp->tag, new_tag) == 0) { | |
3841 parent_tag = vc_tp->ptag; | |
3842 break; | |
3843 } | |
3844 ++vc_tp; | |
3845 } | |
3846 } | |
3847 | |
3848 /* | |
3849 * If we have a parent tag... | |
3850 */ | |
3851 if(parent_tag != NULL ) { | |
3852 /* | |
3853 * Try to get the parent node for a tag | |
3854 */ | |
3855 if((x = xmlnode_get_tag(start, parent_tag)) == NULL) { | |
3856 /* | |
3857 * Descend? | |
3858 */ | |
3859 char *grand_parent = strcpy(g_malloc(strlen(parent_tag) + 1), parent_tag); | |
3860 char *parent; | |
3861 | |
3862 if((parent = strrchr(grand_parent, '/')) != NULL) { | |
3863 *(parent++) = '\0'; | |
3864 x = insert_tag_to_parent_tag(start, grand_parent, parent); | |
3865 } else { | |
3866 x = xmlnode_insert_tag(start, grand_parent); | |
3867 } | |
3868 g_free(grand_parent); | |
3869 } else { | |
3870 /* | |
3871 * We found *something* to be the parent node. | |
3872 * Note: may be the "root" node! | |
3873 */ | |
3874 xmlnode y; | |
3875 if((y = xmlnode_get_tag(x, new_tag)) != NULL) { | |
3876 return(y); | |
3877 } | |
3878 } | |
3879 } | |
3880 | |
3881 /* | |
3882 * insert the new tag into its parent node | |
3883 */ | |
3884 return(xmlnode_insert_tag((x == NULL? start : x), new_tag)); | |
3885 } | |
3886 | |
3887 /* | |
3888 * Send vCard info to Jabber server | |
3889 */ | |
5954 | 3890 static void jabber_set_info(GaimConnection *gc, const char *info) |
2956 | 3891 { |
3892 xmlnode x, vc_node; | |
3893 char *id; | |
3894 struct jabber_data *jd = gc->proto_data; | |
3895 gjconn gjc = jd->gjc; | |
5954 | 3896 gchar *info2; |
2956 | 3897 |
3898 x = xmlnode_new_tag("iq"); | |
3311 | 3899 xmlnode_put_attrib(x, "type", "set"); |
2956 | 3900 |
3901 id = gjab_getid(gjc); | |
3770 | 3902 |
2956 | 3903 xmlnode_put_attrib(x, "id", id); |
3904 | |
3905 /* | |
3906 * Send only if there's actually any *information* to send | |
3907 */ | |
5954 | 3908 info2 = g_strdup(info); |
3909 vc_node = xmlstr2xmlnode(info2); | |
4874 | 3910 |
3911 if(vc_node) { | |
3912 if (xmlnode_get_name(vc_node) && | |
3913 !g_ascii_strncasecmp(xmlnode_get_name(vc_node), "vcard", 5)) { | |
3914 xmlnode_insert_tag_node(x, vc_node); | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3915 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3916 "jabber: vCard packet: %s\n", xmlnode2str(x)); |
4874 | 3917 gjab_send(gjc, x); |
3918 } | |
3919 xmlnode_free(vc_node); | |
2956 | 3920 } |
3921 | |
3922 xmlnode_free(x); | |
5954 | 3923 g_free(info2); |
2956 | 3924 } |
3925 | |
3926 /* | |
3927 * This is the callback from the "ok clicked" for "set vCard" | |
3928 * | |
3929 * Formats GSList data into XML-encoded string and returns a pointer | |
3930 * to said string. | |
3931 * | |
3932 * g_free()'ing the returned string space is the responsibility of | |
3933 * the caller. | |
3934 */ | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3935 static void |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3936 jabber_format_info(GaimConnection *gc, GaimRequestFields *fields) |
2956 | 3937 { |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3938 GaimAccount *account; |
2956 | 3939 xmlnode vc_node; |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3940 GaimRequestField *field; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3941 const char *text; |
2956 | 3942 char *p; |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3943 const struct vcard_template *vc_tp; |
2956 | 3944 struct tag_attr *tag_attr; |
3945 | |
3946 vc_node = xmlnode_new_tag("vCard"); | |
3947 | |
3948 for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) | |
3949 xmlnode_put_attrib(vc_node, tag_attr->attr, tag_attr->value); | |
3950 | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3951 for (vc_tp = vcard_template_data; vc_tp->label != NULL; vc_tp++) { |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3952 if (*vc_tp->label == '\0') |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3953 continue; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3954 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3955 field = gaim_request_fields_get_field(fields, vc_tp->tag); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3956 text = gaim_request_field_string_get_value(field); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3957 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3958 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3959 "Setting %s to '%s'\n", vc_tp->tag, text); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3960 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3961 if (text != NULL && *text != '\0') { |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3962 xmlnode xp; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3963 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3964 if ((xp = insert_tag_to_parent_tag(vc_node, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3965 NULL, vc_tp->tag)) != NULL) { |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3966 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3967 xmlnode_insert_cdata(xp, text, -1); |
2956 | 3968 } |
3969 } | |
3970 } | |
3971 | |
3972 p = g_strdup(xmlnode2str(vc_node)); | |
3973 xmlnode_free(vc_node); | |
3974 | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3975 account = gaim_connection_get_account(gc); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3976 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3977 if (account != NULL) { |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3978 gaim_account_set_user_info(account, p); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3979 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3980 if (gc != NULL) |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3981 serv_set_info(gc, p); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3982 } |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3983 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3984 g_free(p); |
2956 | 3985 } |
3986 | |
3987 /* | |
3988 * This gets executed by the proto action | |
3989 * | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3990 * Creates a new GaimRequestFields struct, gets the XML-formatted user_info |
2956 | 3991 * string (if any) into GSLists for the (multi-entry) edit dialog and |
3992 * calls the set_vcard dialog. | |
3993 */ | |
5572 | 3994 static void jabber_setup_set_info(GaimConnection *gc) |
2956 | 3995 { |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3996 GaimRequestFields *fields; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3997 GaimRequestFieldGroup *group; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3998 GaimRequestField *field; |
2956 | 3999 const struct vcard_template *vc_tp; |
4000 char *user_info; | |
4001 char *cdata; | |
4002 xmlnode x_vc_data = NULL; | |
6294 | 4003 |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4004 fields = gaim_request_fields_new(); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4005 group = gaim_request_field_group_new(NULL); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4006 gaim_request_fields_add_group(fields, group); |
2956 | 4007 |
4008 /* | |
4009 * Get existing, XML-formatted, user info | |
4010 */ | |
6294 | 4011 if((user_info = g_strdup(gaim_account_get_user_info(gc->account))) != NULL) |
2956 | 4012 x_vc_data = xmlstr2xmlnode(user_info); |
6294 | 4013 else |
4014 user_info = g_strdup(""); | |
2956 | 4015 |
4016 /* | |
4017 * Set up GSLists for edit with labels from "template," data from user info | |
4018 */ | |
4019 for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { | |
4020 if((vc_tp->label)[0] == '\0') | |
4021 continue; | |
4022 if(vc_tp->ptag == NULL) { | |
4023 cdata = xmlnode_get_tag_data(x_vc_data, vc_tp->tag); | |
4024 } else { | |
4025 gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); | |
4026 cdata = xmlnode_get_tag_data(x_vc_data, tag); | |
4027 g_free(tag); | |
4028 } | |
4029 if(strcmp(vc_tp->tag, "DESC") == 0) { | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4030 field = gaim_request_field_string_new(vc_tp->tag, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4031 _(vc_tp->label), cdata, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4032 TRUE); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4033 #if 0 |
2956 | 4034 multi_text_list_update(&(b->multi_text_items), |
4035 vc_tp->label, cdata, TRUE); | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4036 #endif |
2956 | 4037 } else { |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4038 field = gaim_request_field_string_new(vc_tp->tag, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4039 _(vc_tp->label), cdata, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4040 FALSE); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4041 #if 0 |
2956 | 4042 data = multi_entry_list_update(&(b->multi_entry_items), |
4043 vc_tp->label, cdata, TRUE); | |
4044 data->visible = vc_tp->visible; | |
4045 data->editable = vc_tp->editable; | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4046 #endif |
2956 | 4047 } |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4048 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4049 gaim_request_field_group_add_field(group, field); |
2956 | 4050 } |
4051 | |
4052 if(x_vc_data != NULL) { | |
4053 xmlnode_free(x_vc_data); | |
4054 } else { | |
4055 /* | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4056 * I'm commenting this out for now. faceprint can look at it |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4057 * later. The comment below says this is going away "real soon now," |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4058 * but it's probably been here a really long time. Getting this |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4059 * to work with the multi-field stuff won't be pretty, since we're |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4060 * manually going to have to search through all fields for the |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4061 * label and update. |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4062 * |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4063 * -- ChipX86 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4064 */ |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4065 #if 0 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4066 /* |
2956 | 4067 * Early Beta versions had a different user_info storage format--let's |
4068 * see if that works. | |
4069 * | |
4070 * This goes away RSN. | |
4071 */ | |
4072 const char *record_separator = "<BR>"; | |
4073 const char *field_separator = ": "; | |
4074 gchar **str_list, **str_list_ptr, **str_list2; | |
4075 | |
4076 if((str_list = g_strsplit(user_info, record_separator, 0)) != NULL) { | |
4077 for(str_list_ptr = str_list; *str_list_ptr != NULL; ++str_list_ptr) { | |
4078 str_list2 = g_strsplit(*str_list_ptr, field_separator, 2); | |
4079 if(str_list2[0] != NULL && str_list2[1] != NULL) { | |
4080 g_strstrip(str_list2[0]); | |
4081 g_strstrip(str_list2[1]); | |
4082 /* this is ugly--so far */ | |
4083 if(strcmp(str_list2[0], "Description") == 0) { | |
4084 multi_text_list_update(&(b->multi_text_items), | |
4085 str_list2[0], str_list2[1], FALSE); | |
4086 } else { | |
4087 multi_entry_list_update(&(b->multi_entry_items), | |
4088 str_list2[0], str_list2[1], FALSE); | |
4089 } | |
4090 } | |
4091 g_strfreev(str_list2); | |
4092 } | |
4093 g_strfreev(str_list); | |
4094 } | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4095 #endif |
2956 | 4096 } |
4097 | |
6294 | 4098 g_free(user_info); |
2956 | 4099 |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4100 gaim_request_fields(gc, _("Edit Jabber vCard"), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4101 _("Edit Jabber vCard"), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4102 _("All items below are optional. Enter only the " |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4103 "information with which you feel comfortable."), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4104 fields, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4105 _("Save"), G_CALLBACK(jabber_format_info), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4106 _("Cancel"), NULL, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4107 gc); |
2956 | 4108 } |
4109 | |
4110 /*---------------------------------------*/ | |
4111 /* End Jabber "set info" (vCard) support */ | |
4112 /*---------------------------------------*/ | |
4113 | |
4114 /*----------------------------------------*/ | |
4115 /* Jabber "user registration" support */ | |
4116 /*----------------------------------------*/ | |
4117 | |
4118 /* | |
4119 * Three of the following four functions duplicate much of what | |
4120 * exists elsewhere: | |
4121 * | |
4122 * jabber_handleregresp() | |
4123 * gjab_reqreg() | |
4124 * jabber_handle_registration_state() | |
4125 * | |
4126 * It may be that an additional flag could be added to one of | |
4127 * the "local" structs and the duplicated code modified to | |
4128 * account for it--thus eliminating the duplication. Then again: | |
4129 * doing it the way it is may be much cleaner. | |
4130 * | |
4131 * TBD: Code to support requesting additional information server | |
4132 * wants at registration--incl. dialog. | |
4133 */ | |
4134 | |
4135 /* | |
4136 * Like jabber_handlepacket(), only different | |
4137 */ | |
4138 static void jabber_handleregresp(gjconn gjc, jpacket p) | |
4139 { | |
4140 if (jpacket_subtype(p) == JPACKET__RESULT) { | |
4141 xmlnode querynode; | |
4142 | |
4143 if((querynode = xmlnode_get_tag(p->x, "query")) != NULL) { | |
4144 char *xmlns; | |
4145 | |
4146 /* we damn well *better* have this! */ | |
4147 if((xmlns = xmlnode_get_attrib(querynode, "xmlns")) != NULL && | |
4148 strcmp(xmlns, NS_REGISTER) == 0) { | |
4149 | |
4150 char *tag; | |
4151 xmlnode child = xmlnode_get_firstchild(querynode); | |
4152 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4153 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4154 "got registration requirments response!\n"); |
2956 | 4155 |
4156 while(child != NULL) { | |
4157 if((tag = xmlnode_get_name(child)) != NULL) { | |
4158 char *data; | |
4159 | |
4160 fprintf(stderr, "DBG: got node: \"%s\"\n", tag); | |
4161 fflush(stderr); | |
4162 | |
4163 if((data = xmlnode_get_data(child)) != NULL) { | |
4164 fprintf(stderr, "DBG: got data: \"%s\"\n", data); | |
4165 fflush(stderr); | |
4166 } | |
4167 } | |
4168 child = xmlnode_get_nextsibling(child); | |
4169 } | |
4170 } | |
4171 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4172 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4173 "registration successful!\n"); |
2956 | 4174 |
5572 | 4175 gaim_connection_notice(GJ_GC(gjc), _("Server Registration successful!")); |
5578
847ad796326d
[gaim-migrate @ 5982]
Christian Hammond <chipx86@chipx86.com>
parents:
5572
diff
changeset
|
4176 gaim_connection_destroy(GJ_GC(gjc)); |
2956 | 4177 } |
4178 | |
4179 } else { | |
4180 xmlnode xerr; | |
4181 char *errmsg = NULL; | |
4182 int errcode = 0; | |
4183 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4184 gaim_debug(GAIM_DEBUG_ERROR, "jabber", "registration failed\n"); |
2956 | 4185 xerr = xmlnode_get_tag(p->x, "error"); |
4186 if (xerr) { | |
4187 char msg[BUF_LONG]; | |
4188 errmsg = xmlnode_get_data(xerr); | |
4189 if (xmlnode_get_attrib(xerr, "code")) { | |
4190 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
6321 | 4191 g_snprintf(msg, sizeof(msg), _("Error %d: %s"), errcode, errmsg); |
2956 | 4192 } else |
4193 g_snprintf(msg, sizeof(msg), "%s", errmsg); | |
5572 | 4194 gaim_connection_error(GJ_GC(gjc), msg); |
2956 | 4195 } else { |
5572 | 4196 gaim_connection_error(GJ_GC(gjc), _("Unknown registration error")); |
2956 | 4197 } |
4198 } | |
4199 } | |
4200 | |
4201 /* | |
4202 * Like gjab_reqauth(), only different | |
4203 */ | |
4204 static void gjab_reqreg(gjconn gjc) | |
4205 { | |
4206 xmlnode x, y, z; | |
4207 char *user; | |
4208 | |
4209 if (!gjc) | |
4210 return; | |
4211 | |
4212 x = jutil_iqnew(JPACKET__SET, NS_REGISTER); | |
4213 y = xmlnode_get_tag(x, "query"); | |
4214 | |
4215 user = gjc->user->user; | |
4216 | |
4217 if (user) { | |
4218 z = xmlnode_insert_tag(y, "username"); | |
4219 xmlnode_insert_cdata(z, user, -1); | |
4220 } | |
4221 z = xmlnode_insert_tag(y, "password"); | |
4222 xmlnode_insert_cdata(z, gjc->pass, -1); | |
4223 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4224 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4225 "jabber: registration packet: %s\n", xmlnode2str(x)); |
2956 | 4226 gjab_send(gjc, x); |
4227 xmlnode_free(x); | |
4228 } | |
4229 | |
4230 /* | |
4231 * Like jabber_handlestate(), only different | |
4232 */ | |
4233 static void jabber_handle_registration_state(gjconn gjc, int state) | |
4234 { | |
4235 switch (state) { | |
4236 case JCONN_STATE_OFF: | |
3074 | 4237 if(gjc->was_connected) { |
5572 | 4238 gaim_connection_error(GJ_GC(gjc), _("Connection lost")); |
3074 | 4239 } else { |
5572 | 4240 gaim_connection_error(GJ_GC(gjc), _("Unable to connect")); |
3074 | 4241 } |
2956 | 4242 break; |
4243 case JCONN_STATE_CONNECTED: | |
3074 | 4244 gjc->was_connected = 1; |
2956 | 4245 /* |
4246 * TBD? | |
6106 | 4247 gaim_connection_update_progress(GJ_GC(gjc), _("Connected"), |
4248 2, JABBER_CONNECT_STEPS); | |
2956 | 4249 */ |
4250 break; | |
4251 case JCONN_STATE_ON: | |
4252 /* | |
4253 * TBD? | |
6106 | 4254 gaim_connection_update_progress(GJ_GC(gjc), _("Authenticating"), |
4255 _("Requesting Authentication Method"), 3, | |
4256 JABBER_CONNECT_STEPS); | |
2956 | 4257 */ |
4258 gjab_reqreg(gjc); | |
4259 /* | |
4260 * TBD: A work-in-progress | |
4261 gjab_reqregreqs(gjc); | |
4262 */ | |
4263 break; | |
4264 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4265 gaim_debug(GAIM_DEBUG_MISC, "jabber", "state change: %d\n", state); |
2956 | 4266 } |
4267 return; | |
4268 } | |
4269 | |
4270 /* | |
4271 * Like jabber_login(), only different | |
4272 */ | |
5572 | 4273 void jabber_register_user(GaimAccount *account) |
2956 | 4274 { |
6003 | 4275 GaimConnection *gc = gaim_connection_new(account); |
2956 | 4276 struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); |
4917 | 4277 char *loginname = create_valid_jid(account->username, DEFAULT_SERVER, "Gaim"); |
2956 | 4278 |
4279 /* | |
4280 * These do nothing during registration | |
4281 */ | |
3311 | 4282 jd->buddies = NULL; |
2956 | 4283 jd->chats = NULL; |
4284 | |
4491 | 4285 if ((jd->gjc = gjab_new(loginname, account->password, gc)) == NULL) { |
2956 | 4286 g_free(loginname); |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4287 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4288 "unable to connect (jab_new failed)\n"); |
5572 | 4289 gaim_connection_error(gc, _("Unable to connect")); |
2956 | 4290 } else { |
4291 gjab_state_handler(jd->gjc, jabber_handle_registration_state); | |
4292 gjab_packet_handler(jd->gjc, jabber_handleregresp); | |
4293 jd->gjc->queries = NULL; | |
4294 gjab_start(jd->gjc); | |
4295 } | |
4296 | |
4297 g_free(loginname); | |
4298 } | |
4299 | |
4300 /*----------------------------------------*/ | |
4301 /* End Jabber "user registration" support */ | |
4302 /*----------------------------------------*/ | |
4303 | |
5572 | 4304 static GList *jabber_actions(GaimConnection *gc) |
2956 | 4305 { |
4306 GList *m = NULL; | |
4333 | 4307 struct proto_actions_menu *pam; |
4308 | |
4309 pam = g_new0(struct proto_actions_menu, 1); | |
4310 pam->label = _("Set User Info"); | |
4311 pam->callback = jabber_setup_set_info; | |
4312 pam->gc = gc; | |
4313 m = g_list_append(m, pam); | |
4314 | |
2956 | 4315 /* |
4333 | 4316 pam = g_new0(struct proto_actions_menu, 1); |
4317 pam->label = _("Set Dir Info"); | |
4318 pam->callback = show_set_dir; | |
4319 pam->gc = gc; | |
4320 m = g_list_append(m, pam); | |
3257 | 4321 */ |
4333 | 4322 |
4323 pam = g_new0(struct proto_actions_menu, 1); | |
4324 pam->label = _("Change Password"); | |
4325 pam->callback = show_change_passwd; | |
4326 pam->gc = gc; | |
4327 m = g_list_append(m, pam); | |
2956 | 4328 |
4329 return m; | |
4330 } | |
4331 | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4332 static GaimPluginProtocolInfo prpl_info = |
2086 | 4333 { |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4334 GAIM_PROTO_JABBER, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4335 OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_CHAT_TOPIC, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4336 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4337 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4338 jabber_list_icon, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4339 jabber_list_emblems, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4340 jabber_status_text, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4341 jabber_tooltip_text, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4342 jabber_away_states, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4343 jabber_actions, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4344 jabber_buddy_menu, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4345 jabber_chat_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4346 jabber_login, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4347 jabber_close, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4348 jabber_send_im, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4349 jabber_set_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4350 jabber_send_typing, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4351 jabber_get_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4352 jabber_set_away, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4353 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4354 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4355 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4356 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4357 jabber_set_idle, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4358 jabber_change_passwd, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4359 jabber_add_buddy, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4360 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4361 jabber_remove_buddy, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4362 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4363 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4364 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4365 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4366 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4367 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4368 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4369 jabber_join_chat, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4370 jabber_chat_invite, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4371 jabber_chat_leave, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4372 jabber_chat_whisper, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4373 jabber_chat_send, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4374 jabber_keepalive, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4375 jabber_register_user, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4376 jabber_get_cb_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4377 jabber_get_cb_away_msg, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4378 jabber_alias_buddy, |
5957 | 4379 jabber_group_change, |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4380 jabber_rename_group, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4381 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4382 jabber_convo_closed, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4383 jabber_normalize |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4384 }; |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4385 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4386 static GaimPluginInfo info = |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4387 { |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4388 2, /**< api_version */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4389 GAIM_PLUGIN_PROTOCOL, /**< type */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4390 NULL, /**< ui_requirement */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4391 0, /**< flags */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4392 NULL, /**< dependencies */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4393 GAIM_PRIORITY_DEFAULT, /**< priority */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4394 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4395 "prpl-jabber", /**< id */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4396 "Jabber", /**< name */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4397 VERSION, /**< version */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4398 /** summary */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4399 N_("Jabber Protocol Plugin"), |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4400 /** description */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4401 N_("Jabber Protocol Plugin"), |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4402 NULL, /**< author */ |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6357
diff
changeset
|
4403 GAIM_WEBSITE, /**< homepage */ |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4404 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4405 NULL, /**< load */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4406 NULL, /**< unload */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4407 NULL, /**< destroy */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4408 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4409 NULL, /**< ui_info */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4410 &prpl_info /**< extra_info */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4411 }; |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4412 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4413 static void |
5920
7d385de2f9cd
[gaim-migrate @ 6360]
Christian Hammond <chipx86@chipx86.com>
parents:
5894
diff
changeset
|
4414 init_plugin(GaimPlugin *plugin) |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4415 { |
5638
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4416 GaimAccountUserSplit *split; |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4417 GaimAccountOption *option; |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4418 |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4419 /* Splits */ |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4420 split = gaim_account_user_split_new(_("Server"), "jabber.org", '@'); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4421 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4422 |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4423 split = gaim_account_user_split_new(_("Resource"), "Gaim", '/'); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4424 prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4425 |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4426 /* Account Options */ |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4427 option = gaim_account_option_int_new(_("Port"), "port", DEFAULT_PORT); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4428 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4429 option); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4430 |
5685
43ea75092684
[gaim-migrate @ 6106]
Christian Hammond <chipx86@chipx86.com>
parents:
5681
diff
changeset
|
4431 option = gaim_account_option_string_new(_("Connect server"), |
5638
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4432 "connect_server", NULL); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4433 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4434 option); |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4435 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4436 my_protocol = plugin; |
2086 | 4437 } |
4438 | |
5920
7d385de2f9cd
[gaim-migrate @ 6360]
Christian Hammond <chipx86@chipx86.com>
parents:
5894
diff
changeset
|
4439 GAIM_INIT_PLUGIN(jabber, init_plugin, info); |