Mercurial > pidgin
annotate src/protocols/jabber/jabber.c @ 6623:156e6643f9db
[gaim-migrate @ 7147]
Bjoern Voigt writes:
"i18n23.patch contains:
- Updated German translation
- removed some (around 15-30) strings:
The patch reduces the work of the translators a bit and makes the
Gaim UI more consistent for all users (also for the native English
users).
I sorted the translatable strings with:
$ cd po
$ xgettext -s --default-domain=gaim --directory=.. --add-comments \
--keyword=_ --keyword=N_ --files-from=./POTFILES.in
# -> look at gaim.po
A lot of strings look very similar, for instance
"Age" and "Age:"
"Last Name" and "Lastname"
"An error message" and "An error message."
I tried to eliminate one string for each pair. This is possible, if
string concatination functions like g_strconcat() or g_snprintf()
are used. I also changed some uppercase letters to lowercase
letters. But I changed very few strings, because this can be better
done by a native speaker.
THERE IS STILL SOME WORK TO DO:
Most of the error messages have dots (".") at the end, some not.
There are still some spellings of same words, for instance
"screenname" and "screen name". If you are interested, please sort
the strings (see above) and look at the sorted file gaim.po."
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Mon, 25 Aug 2003 15:42:39 +0000 |
parents | a4622f1fb5a1 |
children | dbc3bdcc8861 |
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, |
6623 | 988 _("Unable to change password."), |
5436
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 { |
6502 | 1024 struct jabber_data *jd; |
3311 | 1025 gpointer val; |
1026 char *realwho; | |
1027 | |
6502 | 1028 if (gc == NULL) |
1029 return NULL; | |
1030 | |
1031 jd = gc->proto_data; | |
3311 | 1032 if((realwho = get_realwho(jd->gjc, buddy, FALSE, NULL)) == NULL) |
1033 return NULL; | |
1034 | |
1035 val = g_hash_table_lookup(jd->buddies, realwho); | |
1036 if(val) { | |
1037 g_free(realwho); | |
1038 return (struct jabber_buddy_data *)val; | |
1039 | |
5135 | 1040 } else if (create) { |
3311 | 1041 struct jabber_buddy_data *jbd = g_new0(struct jabber_buddy_data, 1); |
3340 | 1042 jbd->invisible = JABBER_NOT_INVIS; |
3311 | 1043 g_hash_table_insert(jd->buddies, g_strdup(realwho), jbd); |
1044 g_free(realwho); | |
1045 return jbd; | |
5135 | 1046 } else { |
5940 | 1047 g_free(realwho); |
5135 | 1048 return NULL; |
3311 | 1049 } |
1050 } | |
3770 | 1051 |
3236 | 1052 /* |
3311 | 1053 * find a resource by name, or if no name given, return the "default" resource |
3770 | 1054 * default being the highest priority one. |
3311 | 1055 */ |
1056 | |
5572 | 1057 static jab_res_info jabber_find_resource(GaimConnection *gc, const char *who) |
3311 | 1058 { |
1059 GSList *resources; | |
5135 | 1060 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, who, FALSE); |
3311 | 1061 jab_res_info jri = NULL; |
1062 char *res = strstr(who, "/"); | |
1063 | |
1064 if(res) | |
1065 res++; | |
1066 | |
1067 if(jbd) | |
1068 { | |
1069 resources = jbd->resources; | |
1070 while(resources) | |
1071 { | |
1072 if(!jri && !res) { | |
1073 jri = (jab_res_info) resources->data; | |
1074 } else if(!res) { /* we're looking for the default priority, so... */ | |
1075 if(((jab_res_info) resources->data)->priority >= jri->priority) | |
1076 jri = (jab_res_info) resources->data; | |
3337 | 1077 } else if(((jab_res_info)resources->data)->name) { |
3311 | 1078 if(!strcasecmp(((jab_res_info) resources->data)->name, res)) { |
1079 jri = (jab_res_info) resources->data; | |
1080 break; | |
1081 } | |
1082 } | |
1083 resources = resources->next; | |
1084 } | |
1085 } | |
1086 | |
1087 return jri; | |
1088 } | |
1089 | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
1090 #if 0 |
5572 | 1091 static gboolean jabber_is_default_resource(GaimConnection *gc, const char *who) |
5291 | 1092 { |
1093 jab_res_info jri = jabber_find_resource(gc, who); | |
1094 char *buddy = g_strdup(who); | |
1095 char *resource = strrchr(buddy, '/'); | |
1096 | |
1097 if(!resource || !strcmp(resource+1, jri->name)) { | |
1098 g_free(buddy); | |
1099 return TRUE; | |
1100 } | |
1101 | |
1102 g_free(buddy); | |
1103 return FALSE; | |
1104 } | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
1105 #endif |
5291 | 1106 |
3311 | 1107 /* |
1108 * if the resource doesn't exist, create it. otherwise, just update the priority | |
2956 | 1109 */ |
5572 | 1110 static void jabber_track_resource(GaimConnection *gc, |
3311 | 1111 char *buddy, |
1112 char *res, | |
1113 int priority, | |
1114 int state) | |
1115 { | |
5135 | 1116 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, TRUE); |
3311 | 1117 |
3337 | 1118 if(jbd) { |
1119 char *who; | |
1120 jab_res_info jri; | |
1121 if(res) | |
1122 who = g_strdup_printf("%s/%s", buddy, res); | |
1123 else | |
1124 who = g_strdup(buddy); | |
1125 jri = jabber_find_resource(gc, who); | |
3311 | 1126 g_free(who); |
1127 if(!jri) { | |
1128 jri = g_new0(struct jabber_resource_info, 1); | |
1129 jri->name = g_strdup(res); | |
1130 jri->away_msg = NULL; | |
5093 | 1131 jri->has_xhtml = TRUE; |
3311 | 1132 jbd->resources = g_slist_append(jbd->resources, jri); |
1133 } | |
1134 jri->priority = priority; | |
1135 jri->state = state; | |
1136 } | |
1137 } | |
1138 | |
1139 /* | |
1140 * remove the resource, if it exists | |
1141 */ | |
5572 | 1142 static void jabber_remove_resource(GaimConnection *gc, char *buddy, char *res) |
2956 | 1143 { |
5135 | 1144 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, FALSE); |
3337 | 1145 if(jbd) { |
1146 char *who; | |
1147 jab_res_info jri; | |
1148 if(res) | |
1149 who = g_strdup_printf("%s/%s", buddy, res); | |
1150 else | |
1151 who = g_strdup(buddy); | |
1152 jri = jabber_find_resource(gc, who); | |
3311 | 1153 g_free(who); |
1154 if(jri) { | |
3337 | 1155 if(jri->name) |
1156 g_free(jri->name); | |
3311 | 1157 if(jri->away_msg) |
1158 g_free(jri->away_msg); | |
1159 jbd->resources = g_slist_remove(jbd->resources, jri); | |
1160 g_free(jri); | |
1161 } | |
1162 } | |
1163 } | |
1164 | |
1165 /* | |
1166 * grab the away message for the default resource | |
1167 */ | |
1168 static char *jabber_lookup_away(gjconn gjc, char *name) | |
1169 { | |
1170 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); | |
1171 | |
4745 | 1172 if(!jri) |
3311 | 1173 return _("Unknown"); |
1174 | |
1175 return jri->away_msg; | |
1176 } | |
4745 | 1177 static const char *jabber_get_state_string(int s) { |
1178 switch(s) { | |
1179 case UC_AWAY: | |
1180 return _("Away"); | |
1181 case UC_CHAT: | |
1182 return _("Chatty"); | |
1183 case UC_XA: | |
1184 return _("Extended Away"); | |
1185 case UC_DND: | |
1186 return _("Do Not Disturb"); | |
1187 default: | |
1188 return _("Available"); | |
1189 } | |
1190 } | |
3311 | 1191 |
1192 static void jabber_track_away(gjconn gjc, jpacket p, char *type) | |
1193 { | |
1194 jab_res_info jri = NULL; | |
1195 | |
3337 | 1196 if(!p || !p->from || !p->from->user) |
3311 | 1197 return; |
1198 | |
1199 jri = jabber_find_resource(GJ_GC(gjc), jid_full(p->from)); | |
1200 | |
1201 if(!jri) | |
1202 return; | |
3770 | 1203 |
3311 | 1204 if(jri->away_msg) |
1205 g_free(jri->away_msg); | |
1206 | |
4745 | 1207 jri->away_msg = g_strdup(xmlnode_get_tag_data(p->x, "status")); |
3311 | 1208 } |
1209 | |
6059 | 1210 static void jabber_convo_closed(GaimConnection *gc, const char *name) |
3311 | 1211 { |
1212 jab_res_info jri = jabber_find_resource(gc, name); | |
1213 | |
1214 if(jri) { | |
1215 if(jri->thread_id) | |
1216 g_free(jri->thread_id); | |
1217 | |
1218 jri->thread_id = NULL; | |
2956 | 1219 } |
1220 } | |
1221 | |
3311 | 1222 static void jabber_track_convo_thread(gjconn gjc, char *name, char *thread_id) |
1223 { | |
1224 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); | |
1225 | |
1226 if(jri) { | |
1227 if(jri->thread_id) | |
1228 g_free(jri->thread_id); | |
1229 | |
1230 jri->thread_id = g_strdup(thread_id); | |
1231 } | |
1232 } | |
1233 | |
5136 | 1234 static char *jabber_get_convo_thread(gjconn gjc, const char *name) |
3311 | 1235 { |
1236 char *ct = NULL; | |
1237 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), name); | |
1238 | |
1239 if(jri) { | |
1240 if(jri->thread_id) | |
1241 ct = g_strdup(jri->thread_id); | |
1242 } | |
5135 | 1243 |
3311 | 1244 return ct; |
1245 } | |
1246 | |
1247 | |
5426 | 1248 static time_t str_to_time(char *timestamp) |
3159 | 1249 { |
5426 | 1250 struct tm t; |
1251 time_t retval = 0; | |
1252 char buf[32]; | |
1253 char *c; | |
1254 int tzoff = 0; | |
1255 | |
1256 time(&retval); | |
1257 localtime_r(&retval, &t); | |
1258 | |
1259 snprintf(buf, sizeof(buf), "%s", timestamp); | |
1260 c = buf; | |
1261 | |
1262 /* 4 digit year */ | |
1263 if(!sscanf(c, "%04d", &t.tm_year)) return 0; | |
1264 c+=4; | |
1265 if(*c == '-') | |
1266 c++; | |
1267 | |
1268 t.tm_year -= 1900; | |
1269 | |
1270 /* 2 digit month */ | |
1271 if(!sscanf(c, "%02d", &t.tm_mon)) return 0; | |
1272 c+=2; | |
1273 if(*c == '-') | |
1274 c++; | |
1275 | |
1276 t.tm_mon -= 1; | |
1277 | |
1278 /* 2 digit day */ | |
1279 if(!sscanf(c, "%02d", &t.tm_mday)) return 0; | |
1280 c+=2; | |
1281 | |
1282 if(*c == 'T') { /* we have more than a date, keep going */ | |
1283 c++; /* skip the "T" */ | |
1284 | |
1285 /* 2 digit hour */ | |
1286 if(sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec)) { | |
1287 int tzhrs, tzmins; | |
1288 c+=8; | |
1289 if(*c == '.') /* dealing with precision we don't care about */ | |
1290 c += 4; | |
1291 | |
1292 if((*c == '+' || *c == '-') && | |
1293 sscanf(c+1, "%02d:%02d", &tzhrs, &tzmins)) { | |
1294 tzoff = tzhrs*60*60 + tzmins*60; | |
1295 if(*c == '+') | |
1296 tzoff *= -1; | |
5279 | 1297 } |
5426 | 1298 |
1299 #ifdef HAVE_TM_GMTOFF | |
1300 tzoff += t.tm_gmtoff; | |
1301 #else | |
1302 # ifdef HAVE_TIMEZONE | |
1303 tzset(); /* making sure */ | |
1304 tzoff -= timezone; | |
1305 # endif | |
1306 #endif | |
5279 | 1307 } |
3229 | 1308 } |
5426 | 1309 retval = mktime(&t); |
1310 | |
1311 retval += tzoff; | |
1312 | |
1313 return retval; | |
3159 | 1314 } |
1315 | |
2956 | 1316 static void jabber_handlemessage(gjconn gjc, jpacket p) |
2086 | 1317 { |
3311 | 1318 xmlnode y, subj; |
3159 | 1319 time_t time_sent = time(NULL); |
3311 | 1320 gboolean typing = FALSE; |
5093 | 1321 gboolean has_xhtml = TRUE; |
2086 | 1322 |
1323 char *from = NULL, *msg = NULL, *type = NULL, *topic = NULL; | |
3311 | 1324 char *thread_id = NULL; |
1325 char *conference_room = NULL; | |
2086 | 1326 char m[BUF_LONG * 2]; |
1327 | |
1328 type = xmlnode_get_attrib(p->x, "type"); | |
3769 | 1329 |
3311 | 1330 if ((y = xmlnode_get_tag(p->x, "thread"))) |
1331 thread_id = xmlnode_get_data(y); | |
1332 | |
1333 y = xmlnode_get_firstchild(p->x); | |
1334 | |
1335 while(y) { | |
1336 if(NSCHECK(y, NS_DELAY)) { | |
1337 char *timestamp = xmlnode_get_attrib(y, "stamp"); | |
5426 | 1338 if(timestamp) |
1339 time_sent = str_to_time(timestamp); | |
3311 | 1340 } else if(NSCHECK(y, "jabber:x:event")) { |
1341 if(xmlnode_get_tag(y, "composing")) | |
1342 typing = TRUE; | |
1343 } else if(NSCHECK(y, "jabber:x:conference")) { | |
1344 conference_room = xmlnode_get_attrib(y, "jid"); | |
1345 } | |
1346 y = xmlnode_get_nextsibling(y); | |
3159 | 1347 } |
1348 | |
2086 | 1349 if (!type || !strcasecmp(type, "normal") || !strcasecmp(type, "chat")) { |
1350 | |
1351 from = jid_full(p->from); | |
1352 if ((y = xmlnode_get_tag(p->x, "html"))) { | |
5093 | 1353 msg = xmlnode2str(y); |
1354 } else if ((y = xmlnode_get_tag(p->x, "body"))) { | |
2086 | 1355 msg = xmlnode_get_data(y); |
5093 | 1356 has_xhtml = FALSE; |
2086 | 1357 } |
1358 | |
1359 if (!from) | |
1360 return; | |
1361 | |
3311 | 1362 if (conference_room) { |
5234 | 1363 GHashTable *components = g_hash_table_new_full(g_str_hash, |
1364 g_str_equal, g_free, g_free); | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1365 char **data; |
2086 | 1366 |
3311 | 1367 data = g_strsplit(conference_room, "@", 2); |
5234 | 1368 g_hash_table_replace(components, g_strdup("room"), |
1369 g_strdup(data[0])); | |
1370 g_hash_table_replace(components, g_strdup("server"), | |
1371 g_strdup(data[1])); | |
1372 g_hash_table_replace(components, g_strdup("handle"), | |
1373 g_strdup(gjc->user->user)); | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1374 g_strfreev(data); |
2086 | 1375 |
5234 | 1376 serv_got_chat_invite(GJ_GC(gjc), conference_room, from, msg, components); |
2086 | 1377 } else if (msg) { /* whisper */ |
1378 struct jabber_chat *jc; | |
1379 g_snprintf(m, sizeof(m), "%s", msg); | |
2956 | 1380 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
|
1381 serv_got_chat_in(GJ_GC(gjc), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1382 gaim_chat_get_id(GAIM_CHAT(jc->b)), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1383 p->from->resource, 1, m, time_sent); |
2086 | 1384 else { |
2278
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
1385 int flags = 0; |
3769 | 1386 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), from); |
5093 | 1387 if(jri) { |
1388 if(typing) | |
1389 jri->has_composing = TRUE; | |
1390 jri->has_xhtml = has_xhtml; | |
1391 } | |
3769 | 1392 jabber_track_convo_thread(gjc, from, thread_id); |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1393 if (gaim_find_conversation(from)) |
3769 | 1394 serv_got_im(GJ_GC(gjc), from, m, flags, |
3311 | 1395 time_sent, -1); |
2086 | 1396 else { |
2956 | 1397 if(p->from->user) { |
3311 | 1398 from = g_strdup_printf("%s@%s", p->from->user, |
1399 p->from->server); | |
2956 | 1400 } else { |
3311 | 1401 /* server message? */ |
1402 from = g_strdup(p->from->server); | |
2956 | 1403 } |
3159 | 1404 serv_got_im(GJ_GC(gjc), from, m, flags, time_sent, -1); |
2086 | 1405 g_free(from); |
1406 } | |
1407 } | |
3311 | 1408 } else { |
1409 /* a non-message message! */ | |
1410 from = g_strdup_printf("%s@%s", p->from->user, p->from->server); | |
1411 if(typing) | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
1412 serv_got_typing(GJ_GC(gjc), from, 0, GAIM_TYPING); |
3311 | 1413 else |
1414 serv_got_typing_stopped(GJ_GC(gjc), from); | |
1415 g_free(from); | |
2086 | 1416 } |
1417 | |
1418 } else if (!strcasecmp(type, "error")) { | |
1419 if ((y = xmlnode_get_tag(p->x, "error"))) { | |
1420 type = xmlnode_get_attrib(y, "code"); | |
1421 msg = xmlnode_get_data(y); | |
1422 } | |
1423 | |
1424 if (msg) { | |
3427 | 1425 from = g_strdup_printf(_("Jabber Error %s"), type ? type : ""); |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
1426 gaim_notify_error(GJ_GC(gjc), NULL, from, msg); |
2086 | 1427 g_free(from); |
1428 } | |
1429 } else if (!strcasecmp(type, "groupchat")) { | |
1430 struct jabber_chat *jc; | |
1431 static int i = 0; | |
1432 | |
1433 if ((y = xmlnode_get_tag(p->x, "html"))) { | |
5093 | 1434 msg = xmlnode2str(y); |
1435 } else if ((y = xmlnode_get_tag(p->x, "body"))) { | |
2086 | 1436 msg = xmlnode_get_data(y); |
1437 } | |
1438 | |
1439 if ((subj = xmlnode_get_tag(p->x, "subject"))) { | |
3770 | 1440 topic = xmlnode_get_data(subj); |
1441 } | |
2086 | 1442 |
2956 | 1443 jc = find_existing_chat(GJ_GC(gjc), p->from); |
2086 | 1444 if (!jc) { |
1445 /* we're not in this chat. are we supposed to be? */ | |
2956 | 1446 if ((jc = find_pending_chat(GJ_GC(gjc), p->from)) != NULL) { |
2086 | 1447 /* yes, we're supposed to be. so now we are. */ |
2956 | 1448 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
|
1449 jc->id = gaim_chat_get_id(GAIM_CHAT(jc->b)); |
2956 | 1450 jc->state = JCS_ACTIVE; |
2086 | 1451 } else { |
1452 /* no, we're not supposed to be. */ | |
1453 g_free(msg); | |
1454 return; | |
1455 } | |
1456 } | |
1457 if (p->from->resource) { | |
1458 if (!y) { | |
2956 | 1459 if (!find_chat_buddy(jc->b, p->from->resource)) { |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1460 gaim_chat_add_user(GAIM_CHAT(jc->b), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1461 p->from->resource, NULL); |
2956 | 1462 } else if ((y = xmlnode_get_tag(p->x, "status"))) { |
3311 | 1463 jabber_track_away(gjc, p, NULL); |
2086 | 1464 } |
1465 } else if (jc->b && msg) { | |
1466 char buf[8192]; | |
1467 | |
1468 if (topic) { | |
1469 char tbuf[8192]; | |
1470 g_snprintf(tbuf, sizeof(tbuf), "%s", topic); | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1471 gaim_chat_set_topic(GAIM_CHAT(jc->b), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1472 p->from->resource, tbuf); |
2086 | 1473 } |
1474 | |
1475 g_snprintf(buf, sizeof(buf), "%s", msg); | |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1476 serv_got_chat_in(GJ_GC(gjc), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1477 gaim_chat_get_id(GAIM_CHAT(jc->b)), |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1478 p->from->resource, 0, buf, time_sent); |
2086 | 1479 } |
1480 } else { /* message from the server */ | |
3770 | 1481 if(jc->b && topic) { |
1482 char tbuf[8192]; | |
2086 | 1483 g_snprintf(tbuf, sizeof(tbuf), "%s", topic); |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1484 gaim_chat_set_topic(GAIM_CHAT(jc->b), "", tbuf); |
2086 | 1485 } |
1486 } | |
1487 | |
1488 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1489 gaim_debug(GAIM_DEBUG_WARNING, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1490 "unhandled message %s\n", type); |
2086 | 1491 } |
1492 } | |
3770 | 1493 |
2956 | 1494 static void jabber_handlepresence(gjconn gjc, jpacket p) |
2086 | 1495 { |
1496 char *to, *from, *type; | |
1497 struct buddy *b = NULL; | |
3311 | 1498 gaim_jid gjid; |
2086 | 1499 char *buddy; |
3194 | 1500 xmlnode y; |
2086 | 1501 char *show; |
2501
227cc42ffa6e
[gaim-migrate @ 2514]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2382
diff
changeset
|
1502 int state = 0; |
5679 | 1503 GaimConversation *cnv = NULL; |
2086 | 1504 struct jabber_chat *jc = NULL; |
3311 | 1505 int priority = 0; |
1506 struct jabber_buddy_data *jbd; | |
3770 | 1507 |
2086 | 1508 to = xmlnode_get_attrib(p->x, "to"); |
1509 from = xmlnode_get_attrib(p->x, "from"); | |
1510 type = xmlnode_get_attrib(p->x, "type"); | |
3770 | 1511 |
3311 | 1512 if((buddy = get_realwho(gjc, from, FALSE, &gjid)) == NULL) |
1513 return; | |
1514 | |
1515 if (gjid->user == NULL) { | |
1516 /* FIXME: transport */ | |
1517 g_free(buddy); | |
1518 gaim_jid_free(gjid); | |
1519 return; | |
1520 } | |
1521 | |
5135 | 1522 jbd = jabber_find_buddy(GJ_GC(gjc), buddy, TRUE); |
3311 | 1523 |
1524 if(jbd->error_msg) { | |
1525 g_free(jbd->error_msg); | |
1526 jbd->error_msg = NULL; | |
1527 } | |
1528 | |
3259 | 1529 if(type && !strcasecmp(type, "error")) { |
1530 state = UC_ERROR; | |
3311 | 1531 if((y = xmlnode_get_tag(p->x, "error")) != NULL) { |
1532 jbd->error_msg = g_strdup_printf(_("Error %s: %s"), | |
1533 xmlnode_get_attrib(y, "code"), xmlnode_get_data(y)); | |
1534 } else { | |
1535 jbd->error_msg = g_strdup(_("Unknown Error in presence")); | |
1536 } | |
3259 | 1537 } else { |
1538 if ((y = xmlnode_get_tag(p->x, "show"))) { | |
1539 show = xmlnode_get_data(y); | |
1540 if (!show) { | |
1541 state = 0; | |
1542 } else if (!strcasecmp(show, "away")) { | |
1543 state = UC_AWAY; | |
1544 } else if (!strcasecmp(show, "chat")) { | |
1545 state = UC_CHAT; | |
1546 } else if (!strcasecmp(show, "xa")) { | |
1547 state = UC_XA; | |
1548 } else if (!strcasecmp(show, "dnd")) { | |
1549 state = UC_DND; | |
1550 } | |
1551 } else { | |
2501
227cc42ffa6e
[gaim-migrate @ 2514]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2382
diff
changeset
|
1552 state = 0; |
2086 | 1553 } |
1554 } | |
1555 | |
5291 | 1556 if ((y = xmlnode_get_tag(p->x, "priority"))) |
1557 priority = atoi(xmlnode_get_data(y)); | |
1558 | |
2086 | 1559 /* um. we're going to check if it's a chat. if it isn't, and there are pending |
2956 | 1560 * chats, create the chat. if there aren't pending chats and we don't have the |
1561 * buddy on our list, simply bail out. */ | |
3311 | 1562 if ((cnv = find_chat(GJ_GC(gjc), gjid->user)) == NULL) { |
2086 | 1563 static int i = 0x70; |
3311 | 1564 if ((jc = find_pending_chat(GJ_GC(gjc), gjid)) != NULL) { |
1565 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
|
1566 jc->id = gaim_chat_get_id(GAIM_CHAT(jc->b)); |
2956 | 1567 jc->state = JCS_ACTIVE; |
4687 | 1568 } else if ((b = gaim_find_buddy(GJ_GC(gjc)->account, buddy)) == NULL) { |
2956 | 1569 g_free(buddy); |
3311 | 1570 gaim_jid_free(gjid); |
2956 | 1571 return; |
2086 | 1572 } |
1573 } | |
1574 | |
4732 | 1575 if (state == UC_ERROR || (type && (strcasecmp(type, "unavailable") == 0))) |
3311 | 1576 jabber_remove_resource(GJ_GC(gjc), buddy, gjid->resource); |
1577 else { | |
1578 jabber_track_resource(GJ_GC(gjc), buddy, gjid->resource, priority, state); | |
1579 | |
1580 /* keep track of away msg somewhat the same as the yahoo plugin */ | |
1581 jabber_track_away(gjc, p, type); | |
1582 } | |
3770 | 1583 |
2086 | 1584 if (!cnv) { |
3311 | 1585 /* this is where we handle presence information for "regular" buddies */ |
1586 jab_res_info jri = jabber_find_resource(GJ_GC(gjc), buddy); | |
1587 if(jri) { | |
4732 | 1588 serv_got_update(GJ_GC(gjc), buddy, 1, 0, b->signon, b->idle, jri->state); |
3311 | 1589 } else |
4732 | 1590 serv_got_update(GJ_GC(gjc), buddy, 0, 0, 0, 0, 0); |
3311 | 1591 |
2086 | 1592 } else { |
3311 | 1593 if (gjid->resource) { |
3259 | 1594 if (type && (!strcasecmp(type, "unavailable"))) { |
2086 | 1595 struct jabber_data *jd; |
3311 | 1596 if (!jc && !(jc = find_existing_chat(GJ_GC(gjc), gjid))) { |
2086 | 1597 g_free(buddy); |
3311 | 1598 gaim_jid_free(gjid); |
2086 | 1599 return; |
1600 } | |
1601 jd = jc->gc->proto_data; | |
2956 | 1602 /* if it's not ourselves...*/ |
3311 | 1603 if (strcmp(gjid->resource, jc->gjid->resource) && jc->b) { |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1604 gaim_chat_remove_user(GAIM_CHAT(jc->b), gjid->resource, |
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1605 NULL); |
2086 | 1606 g_free(buddy); |
3311 | 1607 gaim_jid_free(gjid); |
2086 | 1608 return; |
1609 } | |
2956 | 1610 |
1611 jc->state = JCS_CLOSED; | |
1612 serv_got_chat_left(GJ_GC(gjc), jc->id); | |
1613 /* | |
1614 * TBD: put back some day? | |
1615 jd->chats = g_slist_remove(jd->chats, jc); | |
1616 g_free(jc); | |
1617 */ | |
1618 } else { | |
3311 | 1619 if ((!jc && !(jc = find_existing_chat(GJ_GC(gjc), gjid))) || !jc->b) { |
2956 | 1620 g_free(buddy); |
3311 | 1621 gaim_jid_free(gjid); |
2956 | 1622 return; |
1623 } | |
3311 | 1624 if (!find_chat_buddy(jc->b, gjid->resource)) { |
4359
5fb47ec9bfe4
[gaim-migrate @ 4625]
Christian Hammond <chipx86@chipx86.com>
parents:
4357
diff
changeset
|
1625 gaim_chat_add_user(GAIM_CHAT(jc->b), gjid->resource, NULL); |
2086 | 1626 } |
1627 } | |
1628 } | |
1629 } | |
1630 | |
1631 g_free(buddy); | |
3311 | 1632 gaim_jid_free(gjid); |
2086 | 1633 |
1634 return; | |
1635 } | |
1636 | |
3229 | 1637 /* |
1638 * Used only by Jabber accept/deny add stuff just below | |
1639 */ | |
1640 struct jabber_add_permit { | |
5572 | 1641 GaimConnection *gc; |
3229 | 1642 gchar *user; |
1643 }; | |
1644 | |
1645 /* | |
1646 * Common part for Jabber accept/deny adds | |
1647 * | |
1648 * "type" says whether we'll permit/deny the subscribe request | |
1649 */ | |
1650 static void jabber_accept_deny_add(struct jabber_add_permit *jap, const char *type) | |
1651 { | |
1652 xmlnode g = xmlnode_new_tag("presence"); | |
1653 | |
1654 xmlnode_put_attrib(g, "to", jap->user); | |
1655 xmlnode_put_attrib(g, "type", type); | |
4249 | 1656 gjab_send(GC_GJ(jap->gc), g); |
3229 | 1657 |
1658 xmlnode_free(g); | |
1659 } | |
1660 | |
1661 /* | |
5498
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1662 * Callback from "accept" in gaim_request_action() invoked |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1663 * by jabber_handles10n() |
3229 | 1664 */ |
3730 | 1665 static void jabber_accept_add(struct jabber_add_permit *jap) |
3229 | 1666 { |
5578
847ad796326d
[gaim-migrate @ 5982]
Christian Hammond <chipx86@chipx86.com>
parents:
5572
diff
changeset
|
1667 if(g_list_find(gaim_connections_get_all(), jap->gc)) { |
4249 | 1668 jabber_accept_deny_add(jap, "subscribed"); |
1669 /* | |
1670 * If we don't already have the buddy on *our* buddylist, | |
1671 * ask if we want him or her added. | |
1672 */ | |
4687 | 1673 if(gaim_find_buddy(jap->gc->account, jap->user) == NULL) { |
4249 | 1674 show_got_added(jap->gc, NULL, jap->user, NULL, NULL); |
1675 } | |
3229 | 1676 } |
4249 | 1677 |
3229 | 1678 g_free(jap->user); |
1679 g_free(jap); | |
1680 } | |
1681 | |
1682 /* | |
5498
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1683 * Callback from "deny/cancel" in gaim_request_action() invoked |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1684 * by jabber_handles10n() |
3229 | 1685 */ |
3730 | 1686 static void jabber_deny_add(struct jabber_add_permit *jap) |
3229 | 1687 { |
5578
847ad796326d
[gaim-migrate @ 5982]
Christian Hammond <chipx86@chipx86.com>
parents:
5572
diff
changeset
|
1688 if(g_list_find(gaim_connections_get_all(), jap->gc)) { |
4249 | 1689 jabber_accept_deny_add(jap, "unsubscribed"); |
1690 } | |
1691 | |
3229 | 1692 g_free(jap->user); |
1693 g_free(jap); | |
1694 } | |
1695 | |
1696 /* | |
1697 * Handle subscription requests | |
1698 */ | |
2956 | 1699 static void jabber_handles10n(gjconn gjc, jpacket p) |
2086 | 1700 { |
1701 xmlnode g; | |
1702 char *Jid = xmlnode_get_attrib(p->x, "from"); | |
3136 | 1703 char *type = xmlnode_get_attrib(p->x, "type"); |
2086 | 1704 |
1705 g = xmlnode_new_tag("presence"); | |
1706 xmlnode_put_attrib(g, "to", Jid); | |
3229 | 1707 |
1708 if (!strcmp(type, "subscribe")) { | |
1709 /* | |
1710 * A "subscribe to us" request was received - put up the approval dialog | |
1711 */ | |
1712 struct jabber_add_permit *jap = g_new0(struct jabber_add_permit, 1); | |
1713 gchar *msg = g_strdup_printf(_("The user %s wants to add you to their buddy list."), | |
1714 Jid); | |
1715 | |
4249 | 1716 jap->gc = GJ_GC(gjc); |
3229 | 1717 jap->user = g_strdup(Jid); |
5498
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1718 |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1719 gaim_request_action(jap->gc, NULL, msg, NULL, 0, jap, 2, |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1720 _("Authorize"), G_CALLBACK(jabber_accept_add), |
cce2d7868c78
[gaim-migrate @ 5894]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
1721 _("Deny"), G_CALLBACK(jabber_deny_add)); |
3229 | 1722 |
1723 g_free(msg); | |
1724 xmlnode_free(g); /* Never needed it here anyway */ | |
1725 return; | |
1726 | |
1727 } else if (!strcmp(type, "unsubscribe")) { | |
1728 /* | |
1729 * An "unsubscribe to us" was received - simply "approve" it | |
1730 */ | |
2086 | 1731 xmlnode_put_attrib(g, "type", "unsubscribed"); |
3229 | 1732 } else { |
1733 /* | |
1734 * Did we attempt to subscribe to somebody and they do not exist? | |
1735 */ | |
3136 | 1736 if (!strcmp(type, "unsubscribed")) { |
1737 xmlnode y; | |
1738 char *status; | |
1739 if((y = xmlnode_get_tag(p->x, "status")) && (status = xmlnode_get_data(y)) && | |
1740 !strcmp(status, "Not Found")) { | |
3427 | 1741 char *msg = g_strdup_printf(_("The Jabber user %s does not exist and was therefore " |
1742 "not added to your roster."), | |
1743 xmlnode_get_attrib(p->x, "from")); | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
1744 gaim_notify_error(GJ_GC(gjc), NULL, _("No such user."), msg); |
3136 | 1745 g_free(msg); |
1746 } | |
1747 } | |
1748 | |
2956 | 1749 xmlnode_free(g); |
2086 | 1750 return; |
2956 | 1751 } |
1752 | |
1753 gjab_send(gjc, g); | |
1754 xmlnode_free(g); | |
2086 | 1755 } |
1756 | |
2956 | 1757 /* |
1758 * Pending subscription to a buddy? | |
1759 */ | |
1760 #define BUD_SUB_TO_PEND(sub, ask) ((!strcasecmp((sub), "none") || !strcasecmp((sub), "from")) && \ | |
3770 | 1761 (ask) != NULL && !strcasecmp((ask), "subscribe")) |
2956 | 1762 |
1763 /* | |
1764 * Subscribed to a buddy? | |
1765 */ | |
1766 #define BUD_SUBD_TO(sub, ask) ((!strcasecmp((sub), "to") || !strcasecmp((sub), "both")) && \ | |
1767 ((ask) == NULL || !strcasecmp((ask), "subscribe"))) | |
1768 | |
1769 /* | |
1770 * Pending unsubscription to a buddy? | |
1771 */ | |
1772 #define BUD_USUB_TO_PEND(sub, ask) ((!strcasecmp((sub), "to") || !strcasecmp((sub), "both")) && \ | |
1773 (ask) != NULL && !strcasecmp((ask), "unsubscribe")) | |
1774 | |
1775 /* | |
1776 * Unsubscribed to a buddy? | |
1777 */ | |
1778 #define BUD_USUBD_TO(sub, ask) ((!strcasecmp((sub), "none") || !strcasecmp((sub), "from")) && \ | |
1779 ((ask) == NULL || !strcasecmp((ask), "unsubscribe"))) | |
1780 | |
1781 /* | |
1782 * If a buddy is added or removed from the roster on another resource | |
1783 * jabber_handlebuddy is called | |
1784 * | |
1785 * Called with roster item node. | |
1786 */ | |
1787 static void jabber_handlebuddy(gjconn gjc, xmlnode x) | |
1788 { | |
1789 xmlnode g; | |
3311 | 1790 char *who, *name, *sub, *ask; |
1791 gaim_jid gjid; | |
2956 | 1792 struct buddy *b = NULL; |
4927 | 1793 struct jabber_buddy_data *jbd = NULL; |
3136 | 1794 char *buddyname, *groupname = NULL; |
2956 | 1795 |
3311 | 1796 who = xmlnode_get_attrib(x, "jid"); |
2956 | 1797 name = xmlnode_get_attrib(x, "name"); |
1798 sub = xmlnode_get_attrib(x, "subscription"); | |
1799 ask = xmlnode_get_attrib(x, "ask"); | |
3311 | 1800 |
1801 if((buddyname = get_realwho(gjc, who, FALSE, &gjid)) == NULL) | |
1802 return; | |
2956 | 1803 |
4705 | 1804 |
2956 | 1805 /* JFIXME: jabber_handleroster() had a "FIXME: transport" at this |
1806 * equivilent point. So... | |
1807 * | |
3311 | 1808 * We haven't done anything interesting to this point, so we'll |
1809 * violate Good Coding Structure here by simply bailing out. | |
2956 | 1810 */ |
3311 | 1811 if(!gjid->user) { |
1812 g_free(buddyname); | |
1813 gaim_jid_free(gjid); | |
2956 | 1814 return; |
1815 } | |
3311 | 1816 gaim_jid_free(gjid); |
2956 | 1817 |
3236 | 1818 if((g = xmlnode_get_tag(x, "group")) != NULL) { |
3136 | 1819 groupname = xmlnode_get_data(g); |
2956 | 1820 } |
1821 | |
3059 | 1822 /* |
3136 | 1823 * Add or remove a buddy? Change buddy's alias or group? |
3059 | 1824 */ |
2956 | 1825 if (BUD_SUB_TO_PEND(sub, ask) || BUD_SUBD_TO(sub, ask)) { |
4687 | 1826 if ((b = gaim_find_buddy(GJ_GC(gjc)->account, buddyname)) == NULL) { |
4932 | 1827 struct group *g; |
4927 | 1828 b = gaim_buddy_new(GJ_GC(gjc)->account, buddyname, name); |
4687 | 1829 if (groupname) { |
4775 | 1830 if (!(g = gaim_find_group(groupname))) { |
4687 | 1831 g = gaim_group_new(groupname); |
4775 | 1832 gaim_blist_add_group(g, NULL); |
1833 } | |
1834 } else { | |
4687 | 1835 g = gaim_group_new(_("Buddies")); |
4775 | 1836 gaim_blist_add_group(g, NULL); |
1837 } | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1838 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1839 "adding buddy [4]: %s\n", buddyname); |
4687 | 1840 gaim_blist_add_buddy(b, g, NULL); |
4349 | 1841 gaim_blist_save(); |
3136 | 1842 } else { |
5264 | 1843 gboolean save = FALSE; |
4687 | 1844 struct group *c_grp = gaim_find_buddys_group(b); |
3136 | 1845 |
3770 | 1846 /* |
3136 | 1847 * If the buddy's in a new group or his/her alias is changed... |
1848 */ | |
1849 if(groupname && c_grp && strcmp(c_grp->name, groupname)) { | |
5264 | 1850 struct group *g = gaim_find_group(groupname); |
1851 if(!g) { | |
1852 g = gaim_group_new(groupname); | |
1853 gaim_blist_add_group(g, NULL); | |
1854 } | |
1855 | |
1856 gaim_blist_add_buddy(b, g, NULL); | |
1857 save = TRUE; | |
1858 } | |
1859 | |
1860 if(name && (!b->alias || strcmp(b->alias, name))) { | |
1861 gaim_blist_alias_buddy(b, name); | |
1862 save = TRUE; | |
1863 } | |
1864 | |
1865 if(save) | |
4349 | 1866 gaim_blist_save(); |
2956 | 1867 } |
1868 } else if (BUD_USUB_TO_PEND(sub, ask) || BUD_USUBD_TO(sub, ask) || !strcasecmp(sub, "remove")) { | |
3236 | 1869 jabber_remove_gaim_buddy(GJ_GC(gjc), buddyname); |
2956 | 1870 } |
5135 | 1871 if(b && (jbd = jabber_find_buddy(b->account->gc, buddyname, TRUE)) != NULL) { |
4927 | 1872 jbd->subscription = JABBER_SUB_NONE; |
1873 if(!strcasecmp(sub, "to")) | |
1874 jbd->subscription |= JABBER_SUB_TO; | |
1875 else if(!strcasecmp(sub, "from")) | |
1876 jbd->subscription |= JABBER_SUB_FROM; | |
1877 else if(!strcasecmp(sub, "both")) | |
1878 jbd->subscription |= JABBER_SUB_BOTH; | |
1879 | |
1880 if(ask && !strcasecmp(ask, "subscribe")) | |
1881 jbd->subscription |= JABBER_SUB_PENDING; | |
1882 } | |
3328 | 1883 |
2956 | 1884 g_free(buddyname); |
1885 | |
1886 } | |
1887 | |
1888 static void jabber_handleroster(gjconn gjc, xmlnode querynode) | |
2086 | 1889 { |
1890 xmlnode x; | |
1891 | |
1892 x = xmlnode_get_firstchild(querynode); | |
1893 while (x) { | |
2956 | 1894 jabber_handlebuddy(gjc, x); |
2086 | 1895 x = xmlnode_get_nextsibling(x); |
1896 } | |
1897 | |
5426 | 1898 x = xmlnode_new_tag("presence"); |
2956 | 1899 gjab_send(gjc, x); |
2086 | 1900 xmlnode_free(x); |
1901 } | |
1902 | |
2956 | 1903 static void jabber_handleauthresp(gjconn gjc, jpacket p) |
2086 | 1904 { |
1905 if (jpacket_subtype(p) == JPACKET__RESULT) { | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1906 if (xmlnode_has_children(p->x)) { |
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1907 xmlnode query = xmlnode_get_tag(p->x, "query"); |
5572 | 1908 gaim_connection_update_progress(GJ_GC(gjc), _("Authenticating"), |
1909 4, JABBER_CONNECT_STEPS); | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1910 if (!xmlnode_get_tag(query, "digest")) { |
2956 | 1911 g_free(gjc->sid); |
1912 gjc->sid = NULL; | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1913 } |
2956 | 1914 gjab_auth(gjc); |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1915 } else { |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1916 gaim_debug(GAIM_DEBUG_INFO, "jabber", "auth success\n"); |
2086 | 1917 |
5572 | 1918 gaim_connection_set_state(GJ_GC(gjc), GAIM_CONNECTED); |
2956 | 1919 serv_finish_login(GJ_GC(gjc)); |
1920 | |
1921 ((struct jabber_data *)GJ_GC(gjc)->proto_data)->did_import = TRUE; | |
1922 | |
1923 gjab_reqroster(gjc); | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
1924 } |
2086 | 1925 } else { |
1926 xmlnode xerr; | |
1927 char *errmsg = NULL; | |
1928 int errcode = 0; | |
1929 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1930 gaim_debug(GAIM_DEBUG_ERROR, "jabber", "auth failed\n"); |
2086 | 1931 xerr = xmlnode_get_tag(p->x, "error"); |
1932 if (xerr) { | |
1933 char msg[BUF_LONG]; | |
1934 errmsg = xmlnode_get_data(xerr); | |
1935 if (xmlnode_get_attrib(xerr, "code")) { | |
1936 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
1937 g_snprintf(msg, sizeof(msg), "Error %d: %s", errcode, errmsg); | |
1938 } else | |
1939 g_snprintf(msg, sizeof(msg), "%s", errmsg); | |
5572 | 1940 gaim_connection_error(GJ_GC(gjc), msg); |
2086 | 1941 } else { |
5572 | 1942 gaim_connection_error(GJ_GC(gjc), _("Unknown login error")); |
2086 | 1943 } |
1944 } | |
1945 } | |
1946 | |
2956 | 1947 static void jabber_handleversion(gjconn gjc, xmlnode iqnode) { |
2086 | 1948 xmlnode querynode, x; |
1949 char *id, *from; | |
1950 char os[1024]; | |
1951 struct utsname osinfo; | |
1952 | |
1953 uname(&osinfo); | |
1954 g_snprintf(os, sizeof os, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine); | |
1955 | |
1956 id = xmlnode_get_attrib(iqnode, "id"); | |
1957 from = xmlnode_get_attrib(iqnode, "from"); | |
1958 | |
1959 x = jutil_iqnew(JPACKET__RESULT, NS_VERSION); | |
1960 | |
1961 xmlnode_put_attrib(x, "to", from); | |
1962 xmlnode_put_attrib(x, "id", id); | |
1963 querynode = xmlnode_get_tag(x, "query"); | |
1964 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "name"), PACKAGE, -1); | |
1965 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "version"), VERSION, -1); | |
1966 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "os"), os, -1); | |
1967 | |
2956 | 1968 gjab_send(gjc, x); |
2086 | 1969 |
1970 xmlnode_free(x); | |
1971 } | |
1972 | |
2956 | 1973 static void jabber_handletime(gjconn gjc, xmlnode iqnode) { |
2086 | 1974 xmlnode querynode, x; |
1975 char *id, *from; | |
3770 | 1976 time_t now_t; |
2086 | 1977 struct tm *now; |
1978 char buf[1024]; | |
1979 | |
1980 time(&now_t); | |
1981 now = localtime(&now_t); | |
1982 | |
1983 id = xmlnode_get_attrib(iqnode, "id"); | |
1984 from = xmlnode_get_attrib(iqnode, "from"); | |
1985 | |
1986 x = jutil_iqnew(JPACKET__RESULT, NS_TIME); | |
1987 | |
1988 xmlnode_put_attrib(x, "to", from); | |
1989 xmlnode_put_attrib(x, "id", id); | |
1990 querynode = xmlnode_get_tag(x, "query"); | |
1991 | |
1992 strftime(buf, 1024, "%Y%m%dT%T", now); | |
1993 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "utc"), buf, -1); | |
1994 strftime(buf, 1024, "%Z", now); | |
1995 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "tz"), buf, -1); | |
1996 strftime(buf, 1024, "%d %b %Y %T", now); | |
1997 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "display"), buf, -1); | |
3770 | 1998 |
2956 | 1999 gjab_send(gjc, x); |
2086 | 2000 |
2001 xmlnode_free(x); | |
2002 } | |
2003 | |
4538 | 2004 struct jabber_xfer_data { |
3630 | 2005 struct g_url *url; |
2006 GString *headers; | |
2007 gboolean newline; | |
4538 | 2008 |
2009 char *iq_id; | |
2010 | |
2011 struct jabber_data *jd; | |
3630 | 2012 }; |
2013 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2014 static void jabber_xfer_init(GaimXfer *xfer) |
4538 | 2015 { |
2016 struct jabber_xfer_data *data = xfer->data; | |
2017 gaim_xfer_start(xfer, -1, data->url->address, data->url->port); | |
2018 } | |
2019 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2020 static void jabber_xfer_free(GaimXfer *xfer) |
4538 | 2021 { |
2022 struct jabber_xfer_data *data = xfer->data; | |
2023 data->jd->file_transfers = g_slist_remove(data->jd->file_transfers, xfer); | |
2024 | |
2025 g_string_free(data->headers, TRUE); | |
2026 g_free(data->url); | |
2027 g_free(data->iq_id); | |
2028 g_free(data); | |
2029 | |
2030 xfer->data = NULL; | |
3630 | 2031 } |
2032 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2033 static void jabber_xfer_end(GaimXfer *xfer) |
4538 | 2034 { |
2035 struct jabber_xfer_data *data = xfer->data; | |
2036 xmlnode x; | |
2037 | |
2038 x = xmlnode_new_tag("iq"); | |
2039 xmlnode_put_attrib(x, "type", "result"); | |
2040 xmlnode_put_attrib(x, "to", xfer->who); | |
2041 xmlnode_put_attrib(x, "id", data->iq_id); | |
2042 | |
2043 gjab_send(data->jd->gjc, x); | |
2044 | |
2045 xmlnode_free(x); | |
2046 | |
2047 jabber_xfer_free(xfer); | |
2048 } | |
2049 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2050 static void jabber_xfer_start(GaimXfer *xfer) |
4538 | 2051 { |
2052 struct jabber_xfer_data *data = xfer->data; | |
2053 char *buf = g_strdup_printf("GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", | |
2054 data->url->page, data->url->address); | |
2055 write(xfer->fd, buf, strlen(buf)); | |
2056 g_free(buf); | |
2057 } | |
2058 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2059 static size_t jabber_xfer_read(char **buffer, GaimXfer *xfer) { |
4538 | 2060 struct jabber_xfer_data *data = xfer->data; |
3630 | 2061 char test; |
5435 | 2062 int size; |
4538 | 2063 |
2064 if(read(xfer->fd, &test, sizeof(test)) > 0) { | |
2065 data->headers = g_string_append_c(data->headers, test); | |
2066 if(test == '\r') | |
2067 return 0; | |
2068 if(test == '\n') { | |
2069 if(data->newline) { | |
2070 gchar *lenstr = strstr(data->headers->str, "Content-Length: "); | |
2071 if(lenstr) { | |
5435 | 2072 sscanf(lenstr, "Content-Length: %d", &size); |
4538 | 2073 gaim_xfer_set_size(xfer, size); |
2074 } | |
2075 gaim_xfer_set_read_fnc(xfer, NULL); | |
2076 return 0; | |
2077 } else | |
2078 data->newline = TRUE; | |
2079 return 0; | |
3630 | 2080 } |
4538 | 2081 data->newline = FALSE; |
2082 return 0; | |
3630 | 2083 } |
4538 | 2084 return 0; |
3630 | 2085 } |
2086 | |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2087 static void jabber_xfer_cancel_send(GaimXfer *xfer) { |
4675
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2088 } |
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2089 |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2090 static void jabber_xfer_cancel_recv(GaimXfer *xfer) { |
4538 | 2091 struct jabber_xfer_data *data = xfer->data; |
3630 | 2092 xmlnode x,y; |
2093 | |
2094 x = xmlnode_new_tag("iq"); | |
2095 xmlnode_put_attrib(x, "type", "error"); | |
4538 | 2096 xmlnode_put_attrib(x, "to", xfer->who); |
2097 xmlnode_put_attrib(x, "id", data->iq_id); | |
3630 | 2098 y = xmlnode_insert_tag(x, "error"); |
2099 /* FIXME: need to handle other kinds of errors here */ | |
2100 xmlnode_put_attrib(y, "code", "406"); | |
2101 xmlnode_insert_cdata(y, "File Transfer Refused", -1); | |
2102 | |
4538 | 2103 gjab_send(data->jd->gjc, x); |
3630 | 2104 |
2105 xmlnode_free(x); | |
2106 | |
4538 | 2107 jabber_xfer_free(xfer); |
3630 | 2108 } |
2109 | |
2110 static void jabber_handleoob(gjconn gjc, xmlnode iqnode) { | |
4538 | 2111 struct jabber_xfer_data *xfer_data; |
3630 | 2112 struct jabber_data *jd = GJ_GC(gjc)->proto_data; |
6240
ac191233b816
[gaim-migrate @ 6734]
Christian Hammond <chipx86@chipx86.com>
parents:
6115
diff
changeset
|
2113 GaimXfer *xfer; |
3630 | 2114 char *msg = NULL; |
4538 | 2115 char *filename; |
3630 | 2116 xmlnode querynode = xmlnode_get_tag(iqnode, "query"); |
2117 xmlnode urlnode,descnode; | |
2118 | |
2119 if(!querynode) | |
2120 return; | |
2121 urlnode = xmlnode_get_tag(querynode, "url"); | |
2122 if(!urlnode) | |
2123 return; | |
2124 descnode = xmlnode_get_tag(querynode, "desc"); | |
2125 if(descnode) | |
2126 msg = xmlnode_get_data(descnode); | |
2127 | |
4538 | 2128 xfer_data = g_new0(struct jabber_xfer_data, 1); |
2129 xfer_data->url = parse_url(xmlnode_get_data(urlnode)); | |
2130 xfer_data->jd = jd; | |
2131 xfer_data->headers = g_string_new(""); | |
2132 xfer_data->iq_id = g_strdup(xmlnode_get_attrib(iqnode, "id")); | |
2133 | |
2134 xfer = gaim_xfer_new(GJ_GC(gjc)->account, GAIM_XFER_RECEIVE, | |
2135 xmlnode_get_attrib(iqnode, "from")); | |
2136 xfer->data = xfer_data; | |
2137 | |
2138 filename = g_strdup(g_strrstr(xfer_data->url->page, "/")); | |
2139 if(!filename) | |
2140 filename = g_strdup(xfer_data->url->page); | |
2141 | |
2142 gaim_xfer_set_filename(xfer, filename); | |
2143 | |
2144 g_free(filename); | |
2145 | |
2146 gaim_xfer_set_init_fnc(xfer, jabber_xfer_init); | |
2147 gaim_xfer_set_end_fnc(xfer, jabber_xfer_end); | |
4675
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2148 gaim_xfer_set_cancel_send_fnc(xfer, jabber_xfer_cancel_send); |
3145c5c45877
[gaim-migrate @ 4986]
Christian Hammond <chipx86@chipx86.com>
parents:
4634
diff
changeset
|
2149 gaim_xfer_set_cancel_recv_fnc(xfer, jabber_xfer_cancel_recv); |
4538 | 2150 gaim_xfer_set_read_fnc(xfer, jabber_xfer_read); |
2151 gaim_xfer_set_start_fnc(xfer, jabber_xfer_start); | |
2152 | |
2153 jd->file_transfers = g_slist_append(jd->file_transfers, xfer); | |
2154 | |
2155 gaim_xfer_request(xfer); | |
3630 | 2156 } |
2157 | |
2956 | 2158 static void jabber_handlelast(gjconn gjc, xmlnode iqnode) { |
3630 | 2159 xmlnode x, querytag; |
2086 | 2160 char *id, *from; |
2956 | 2161 struct jabber_data *jd = GJ_GC(gjc)->proto_data; |
2086 | 2162 char idle_time[32]; |
3630 | 2163 |
2086 | 2164 id = xmlnode_get_attrib(iqnode, "id"); |
2165 from = xmlnode_get_attrib(iqnode, "from"); | |
2166 | |
2167 x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last"); | |
2168 | |
2169 xmlnode_put_attrib(x, "to", from); | |
2170 xmlnode_put_attrib(x, "id", id); | |
2171 querytag = xmlnode_get_tag(x, "query"); | |
2172 g_snprintf(idle_time, sizeof idle_time, "%ld", jd->idle ? time(NULL) - jd->idle : 0); | |
2173 xmlnode_put_attrib(querytag, "seconds", idle_time); | |
2174 | |
2956 | 2175 gjab_send(gjc, x); |
2086 | 2176 xmlnode_free(x); |
2177 } | |
2178 | |
2956 | 2179 /* |
2180 * delete == TRUE: delete found entry | |
2181 * | |
2182 * returns pointer to (local) copy of value if found, NULL otherwise | |
2183 * | |
2184 * Note: non-reentrant! Local static storage re-used on subsequent calls. | |
2185 * If you're going to need to keep the returned value, make a copy! | |
2186 */ | |
2187 static gchar *jabber_track_queries(GHashTable *queries, gchar *key, gboolean delete) | |
2188 { | |
2189 gpointer my_key, my_val; | |
2190 static gchar *ret_val = NULL; | |
2191 | |
2192 if(ret_val != NULL) { | |
2193 g_free(ret_val); | |
2194 ret_val = NULL; | |
2195 } | |
2196 | |
2197 /* self-protection */ | |
2198 if(queries != NULL && key != NULL) { | |
2199 if(g_hash_table_lookup_extended(queries, key, &my_key, &my_val)) { | |
2200 ret_val = g_strdup((gchar *) my_val); | |
2201 if(delete) { | |
2202 g_hash_table_remove(queries, key); | |
2203 g_free(my_key); | |
2204 g_free(my_val); | |
2205 } | |
2206 } | |
2207 } | |
2208 | |
2209 return(ret_val); | |
2210 } | |
2211 | |
2212 static void jabber_handlepacket(gjconn gjc, jpacket p) | |
2086 | 2213 { |
5994 | 2214 char *id, *from, *to; |
2086 | 2215 switch (p->type) { |
2216 case JPACKET_MESSAGE: | |
2956 | 2217 jabber_handlemessage(gjc, p); |
2086 | 2218 break; |
2219 case JPACKET_PRESENCE: | |
2956 | 2220 jabber_handlepresence(gjc, p); |
2086 | 2221 break; |
2222 case JPACKET_IQ: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2223 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2224 "jpacket_subtype: %d\n", jpacket_subtype(p)); |
2086 | 2225 |
2956 | 2226 id = xmlnode_get_attrib(p->x, "id"); |
2227 if (id != NULL && !strcmp(id, IQID_AUTH)) { | |
2228 jabber_handleauthresp(gjc, p); | |
2814
f4f9e5a01890
[gaim-migrate @ 2827]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2800
diff
changeset
|
2229 break; |
2086 | 2230 } |
2231 | |
2232 if (jpacket_subtype(p) == JPACKET__SET) { | |
2956 | 2233 xmlnode querynode; |
2234 querynode = xmlnode_get_tag(p->x, "query"); | |
5994 | 2235 from = xmlnode_get_attrib(p->x, "from"); |
2236 to = xmlnode_get_attrib(p->x, "to"); | |
6004 | 2237 if (NSCHECK(querynode, "jabber:iq:roster") && (!from || !strcmp(from, to))) { |
2956 | 2238 jabber_handlebuddy(gjc, xmlnode_get_firstchild(querynode)); |
3630 | 2239 } else if(NSCHECK(querynode, "jabber:iq:oob")) { |
2240 jabber_handleoob(gjc, p->x); | |
2956 | 2241 } |
2086 | 2242 } else if (jpacket_subtype(p) == JPACKET__GET) { |
3770 | 2243 xmlnode querynode; |
2086 | 2244 querynode = xmlnode_get_tag(p->x, "query"); |
3770 | 2245 if (NSCHECK(querynode, NS_VERSION)) { |
2246 jabber_handleversion(gjc, p->x); | |
2086 | 2247 } else if (NSCHECK(querynode, NS_TIME)) { |
3770 | 2248 jabber_handletime(gjc, p->x); |
2086 | 2249 } else if (NSCHECK(querynode, "jabber:iq:last")) { |
3770 | 2250 jabber_handlelast(gjc, p->x); |
2086 | 2251 } |
2252 } else if (jpacket_subtype(p) == JPACKET__RESULT) { | |
2253 xmlnode querynode, vcard; | |
2254 char *xmlns, *from; | |
2255 | |
2956 | 2256 /* |
2257 * TBD: ISTM maybe this part could use a serious re-work? | |
2258 */ | |
2086 | 2259 from = xmlnode_get_attrib(p->x, "from"); |
2260 querynode = xmlnode_get_tag(p->x, "query"); | |
2261 vcard = xmlnode_get_tag(p->x, "vCard"); | |
2316
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
2262 if (!vcard) |
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
2263 vcard = xmlnode_get_tag(p->x, "VCARD"); |
2086 | 2264 |
2265 if (NSCHECK(querynode, NS_ROSTER)) { | |
2956 | 2266 jabber_handleroster(gjc, querynode); |
2086 | 2267 } else if (NSCHECK(querynode, NS_VCARD)) { |
2956 | 2268 jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ |
3770 | 2269 jabber_handlevcard(gjc, querynode, from); |
2316
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
2270 } else if (vcard) { |
2956 | 2271 jabber_track_queries(gjc->queries, id, TRUE); /* delete query track */ |
2272 jabber_handlevcard(gjc, vcard, from); | |
2273 } else if((xmlns = xmlnode_get_attrib(querynode, "xmlns")) != NULL) { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2274 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2275 "jabber:iq:query: %s\n", xmlns); |
2086 | 2276 } else { |
2956 | 2277 char *val; |
2278 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2279 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2280 "jabber:iq: %s\n", xmlnode2str(p->x)); |
2956 | 2281 |
2282 /* handle "null" query results */ | |
2283 if((val = jabber_track_queries(gjc->queries, id, TRUE)) != NULL) { | |
2284 if(strcmp((char *) val, "vCard") == 0) { | |
2285 /* | |
2286 * No actual vCard, but there's other stuff. This | |
2287 * way the user always gets some kind of response. | |
2288 */ | |
2289 jabber_handlevcard(gjc, NULL, from); | |
3257 | 2290 } else if(!strcmp((char *) val, "change_password")) { |
2291 char buf[BUF_LONG]; | |
3311 | 2292 sprintf(buf, _("Password successfully changed.")); |
3257 | 2293 |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2294 gaim_notify_info(GJ_GC(gjc), NULL, buf, NULL); |
2956 | 2295 } |
2296 } | |
2086 | 2297 } |
2298 | |
2299 } else if (jpacket_subtype(p) == JPACKET__ERROR) { | |
2300 xmlnode xerr; | |
2301 char *from, *errmsg = NULL; | |
2302 int errcode = 0; | |
2303 | |
2304 from = xmlnode_get_attrib(p->x, "from"); | |
2305 xerr = xmlnode_get_tag(p->x, "error"); | |
2306 if (xerr) { | |
2307 errmsg = xmlnode_get_data(xerr); | |
2308 if (xmlnode_get_attrib(xerr, "code")) | |
2309 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
2310 } | |
2311 | |
3427 | 2312 from = g_strdup_printf("Jabber Error %d (%s)", errcode, from); |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2313 gaim_notify_error(GJ_GC(gjc), NULL, from, errmsg); |
2086 | 2314 g_free(from); |
2315 | |
2316 } | |
2317 | |
2318 break; | |
2319 case JPACKET_S10N: | |
2956 | 2320 jabber_handles10n(gjc, p); |
2086 | 2321 break; |
2322 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2323 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2324 "jabber: packet type %d (%s)\n", p->type, xmlnode2str(p->x)); |
2086 | 2325 } |
2326 | |
2327 xmlnode_free(p->x); | |
2328 | |
2329 return; | |
2330 } | |
2331 | |
2956 | 2332 static void jabber_handlestate(gjconn gjc, int state) |
2086 | 2333 { |
2334 switch (state) { | |
2335 case JCONN_STATE_OFF: | |
3074 | 2336 if(gjc->was_connected) { |
5572 | 2337 gaim_connection_error(GJ_GC(gjc), _("Connection lost")); |
3074 | 2338 } else { |
5572 | 2339 gaim_connection_error(GJ_GC(gjc), _("Unable to connect")); |
3074 | 2340 } |
2086 | 2341 break; |
2342 case JCONN_STATE_CONNECTED: | |
3074 | 2343 gjc->was_connected = 1; |
5572 | 2344 gaim_connection_update_progress(GJ_GC(gjc), _("Connected"), 2, JABBER_CONNECT_STEPS); |
2086 | 2345 break; |
2346 case JCONN_STATE_ON: | |
5572 | 2347 gaim_connection_update_progress(GJ_GC(gjc), _("Requesting Authentication Method"), 3, JABBER_CONNECT_STEPS); |
2956 | 2348 gjab_reqauth(gjc); |
2086 | 2349 break; |
2350 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2351 gaim_debug(GAIM_DEBUG_MISC, "jabber", "state change: %d\n", state); |
2086 | 2352 } |
2353 return; | |
2354 } | |
2355 | |
5572 | 2356 static void jabber_login(GaimAccount *account) |
2086 | 2357 { |
5572 | 2358 GaimConnection *gc = gaim_account_get_connection(account); |
2086 | 2359 struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); |
4917 | 2360 char *loginname = create_valid_jid(account->username, DEFAULT_SERVER, "Gaim"); |
2086 | 2361 |
6622 | 2362 gc->flags |= GAIM_CONNECTION_HTML; |
5174 | 2363 |
3311 | 2364 jd->buddies = g_hash_table_new(g_str_hash, g_str_equal); |
2956 | 2365 jd->chats = NULL; /* we have no chats yet */ |
2086 | 2366 |
5572 | 2367 gaim_connection_update_progress(gc, _("Connecting"), 1, JABBER_CONNECT_STEPS); |
2086 | 2368 |
4491 | 2369 if (!(jd->gjc = gjab_new(loginname, account->password, gc))) { |
2086 | 2370 g_free(loginname); |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2371 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2372 "unable to connect (jab_new failed)\n"); |
5572 | 2373 gaim_connection_error(gc, _("Unable to connect")); |
2086 | 2374 return; |
2375 } | |
2376 | |
2377 g_free(loginname); | |
2956 | 2378 gjab_state_handler(jd->gjc, jabber_handlestate); |
2379 gjab_packet_handler(jd->gjc, jabber_handlepacket); | |
2380 jd->gjc->queries = g_hash_table_new(g_str_hash, g_str_equal); | |
2381 gjab_start(jd->gjc); | |
2086 | 2382 } |
2383 | |
2384 static gboolean jabber_destroy_hash(gpointer key, gpointer val, gpointer data) { | |
3770 | 2385 g_free(key); |
2086 | 2386 g_free(val); |
2387 return TRUE; | |
2388 } | |
2389 | |
3311 | 2390 static gboolean jabber_destroy_buddy_hash(gpointer key, gpointer val, gpointer data) { |
2391 struct jabber_buddy_data *jbd = val; | |
2392 while (jbd->resources) { | |
2393 g_free(((jab_res_info) ((GSList *)jbd->resources)->data)->name); | |
2394 if(((jab_res_info) ((GSList *)jbd->resources)->data)->away_msg) | |
2395 g_free(((jab_res_info) ((GSList *)jbd->resources)->data)->away_msg); | |
2396 g_free(((GSList *)jbd->resources)->data); | |
2397 jbd->resources = g_slist_remove(jbd->resources, ((GSList *)jbd->resources)->data); | |
2398 | |
2399 } | |
2400 if(jbd->error_msg) | |
2401 g_free(jbd->error_msg); | |
2402 g_free(key); | |
2403 g_free(jbd); | |
2404 return TRUE; | |
2405 } | |
2406 | |
2407 | |
2086 | 2408 static gboolean jabber_free(gpointer data) |
2409 { | |
2956 | 2410 struct jabber_data *jd = data; |
2411 | |
3236 | 2412 if(jd->gjc != NULL) { |
3486 | 2413 g_free(jd->gjc->sid); |
3236 | 2414 gjab_delete(jd->gjc); |
2415 jd->gjc = NULL; | |
2416 } | |
2956 | 2417 g_free(jd); |
2418 | |
2086 | 2419 return FALSE; |
2420 } | |
2421 | |
5572 | 2422 static void jabber_close(GaimConnection *gc) |
2086 | 2423 { |
2424 struct jabber_data *jd = gc->proto_data; | |
2956 | 2425 |
2426 if(jd) { | |
2427 GSList *jcs = jd->chats; | |
2428 | |
2429 /* Free-up the jabber_chat struct allocs and the list */ | |
2430 while (jcs) { | |
3311 | 2431 gaim_jid_free(((struct jabber_chat *)jcs->data)->gjid); |
2956 | 2432 g_free(jcs->data); |
2433 jcs = jcs->next; | |
2434 } | |
2435 g_slist_free(jd->chats); | |
2436 | |
3311 | 2437 /* Free-up the buddy data hash */ |
2438 if(jd->buddies != NULL) | |
2439 { | |
2440 g_hash_table_foreach_remove(jd->buddies, jabber_destroy_buddy_hash, NULL); | |
2441 g_hash_table_destroy(jd->buddies); | |
2442 jd->buddies = NULL; | |
2956 | 2443 } |
2444 | |
2445 /* Free-up the pending queries memories and the list */ | |
3236 | 2446 if(jd->gjc != NULL && jd->gjc->queries != NULL) { |
2956 | 2447 g_hash_table_foreach_remove(jd->gjc->queries, jabber_destroy_hash, NULL); |
2448 g_hash_table_destroy(jd->gjc->queries); | |
2449 jd->gjc->queries = NULL; | |
2450 } | |
2451 } | |
2300
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
2452 if (gc->inpa) |
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
2453 gaim_input_remove(gc->inpa); |
2956 | 2454 |
2455 if(jd) { | |
3613 | 2456 g_timeout_add(0, jabber_free, jd); |
3236 | 2457 if(jd->gjc != NULL) |
2458 xmlnode_free(jd->gjc->current); | |
2956 | 2459 } |
2086 | 2460 gc->proto_data = NULL; |
2461 } | |
2462 | |
6059 | 2463 static int jabber_send_typing(GaimConnection *gc, const char *who, int typing) |
3311 | 2464 { |
2465 xmlnode x, y; | |
2466 char *realwho; | |
2467 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; | |
2468 jab_res_info jri = jabber_find_resource(gc, who); | |
2469 | |
2470 if(!jri || !jri->has_composing) | |
2471 return 0; | |
2472 | |
2473 if((realwho = get_realwho(gjc, who, FALSE, NULL)) == NULL) | |
2474 return 0; | |
3596 | 2475 |
3311 | 2476 x = xmlnode_new_tag("message"); |
2477 xmlnode_put_attrib(x, "to", realwho); | |
2478 | |
2479 y = xmlnode_insert_tag(x, "x"); | |
2480 xmlnode_put_attrib(y, "xmlns", "jabber:x:event"); | |
2481 | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5685
diff
changeset
|
2482 if(typing == GAIM_TYPING) |
3311 | 2483 xmlnode_insert_tag(y, "composing"); |
3596 | 2484 |
3311 | 2485 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2486 xmlnode_free(x); | |
2487 g_free(realwho); | |
2488 return JABBER_TYPING_NOTIFY_INT; | |
2489 } | |
2490 | |
5093 | 2491 static void insert_message(xmlnode x, const char *message, gboolean use_xhtml) { |
2492 xmlnode y; | |
5110 | 2493 char *buf = g_strdup_printf("<html xmlns='http://jabber.org/protocol/xhtml-im'><body>%s</body></html>", message); |
2494 char *xhtml, *plain; | |
2495 | |
2496 html_to_xhtml(buf, &xhtml, &plain); | |
2497 g_free(buf); | |
2498 | |
5093 | 2499 y = xmlnode_insert_tag(x, "body"); |
5110 | 2500 xmlnode_insert_cdata(y, plain, -1); |
2501 g_free(plain); | |
5093 | 2502 |
2503 if(use_xhtml) { | |
5110 | 2504 y = xmlnode_str(xhtml, strlen(xhtml)); |
5093 | 2505 if(y) { |
2506 xmlnode_insert_tag_node(x, y); | |
2507 xmlnode_free(y); | |
2508 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2509 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2510 "holy cow, html_to_xhtml didn't work right!\n"); |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2511 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
2512 "the invalid XML: %s\n", xhtml); |
5093 | 2513 } |
2514 } | |
5110 | 2515 g_free(xhtml); |
5093 | 2516 } |
2517 | |
6622 | 2518 static int jabber_send_im(GaimConnection *gc, const char *who, const char *message, int len, GaimImFlags flags) |
2086 | 2519 { |
2520 xmlnode x, y; | |
3311 | 2521 char *thread_id = NULL; |
2956 | 2522 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
5093 | 2523 jab_res_info jri = jabber_find_resource(gc, who); |
2086 | 2524 |
2525 if (!who || !message) | |
2123
56c4382f2909
[gaim-migrate @ 2133]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2112
diff
changeset
|
2526 return 0; |
2086 | 2527 |
2528 x = xmlnode_new_tag("message"); | |
4927 | 2529 xmlnode_put_attrib(x, "to", who); |
2530 | |
2531 thread_id = jabber_get_convo_thread(gjc, who); | |
3311 | 2532 if(thread_id) |
2533 { | |
3769 | 2534 if(strcmp(thread_id, "")) { |
2535 y = xmlnode_insert_tag(x, "thread"); | |
2536 xmlnode_insert_cdata(y, thread_id, -1); | |
2537 } | |
3311 | 2538 g_free(thread_id); |
2539 } | |
2540 | |
2086 | 2541 xmlnode_put_attrib(x, "type", "chat"); |
2542 | |
3311 | 2543 /* let other clients know we support typing notification */ |
2544 y = xmlnode_insert_tag(x, "x"); | |
2545 xmlnode_put_attrib(y, "xmlns", "jabber:x:event"); | |
2546 xmlnode_insert_tag(y, "composing"); | |
2547 | |
2086 | 2548 if (message && strlen(message)) { |
5093 | 2549 insert_message(x, message, jri ? jri->has_xhtml : TRUE); |
2086 | 2550 } |
2551 | |
2956 | 2552 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 2553 xmlnode_free(x); |
2303
f5bf315e6104
[gaim-migrate @ 2313]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2300
diff
changeset
|
2554 return 1; |
2086 | 2555 } |
2556 | |
3105 | 2557 /* |
2558 * Add/update buddy's roster entry on server | |
3349 | 2559 * |
2560 * If "alias" or "group" are NULL, gets them from Gaim's current buddylist values | |
2561 * for the buddy. | |
3105 | 2562 */ |
5572 | 2563 static void jabber_roster_update(GaimConnection *gc, const char *name, const char *alias, const char *group) |
3105 | 2564 { |
2565 xmlnode x, y; | |
2566 char *realwho; | |
2567 gjconn gjc; | |
2568 struct buddy *buddy = NULL; | |
2569 struct group *buddy_group = NULL; | |
3867 | 2570 const char *my_alias = NULL; |
2571 const char *my_group = NULL; | |
3770 | 2572 |
3105 | 2573 if(gc && gc->proto_data && ((struct jabber_data *)gc->proto_data)->gjc && name) { |
3311 | 2574 gaim_jid gjid; |
3105 | 2575 gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2576 | |
3311 | 2577 if((realwho = get_realwho(gjc, name, FALSE, &gjid)) == NULL) |
2578 return; | |
2579 | |
2580 /* FIXME: transport */ | |
2581 if(gjid->user == NULL) { | |
2582 g_free(realwho); | |
2583 gaim_jid_free(gjid); | |
2584 return; | |
3105 | 2585 } |
3311 | 2586 gaim_jid_free(gjid); |
3105 | 2587 |
2588 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
2589 y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); | |
2590 xmlnode_put_attrib(y, "jid", realwho); | |
2591 | |
4687 | 2592 buddy = gaim_find_buddy(gc->account, realwho); |
4349 | 2593 |
3349 | 2594 /* |
2595 * See if there's an explict (new?) alias for the buddy or we can pull | |
2596 * one out of current Gaim buddylist data for him. | |
2597 */ | |
2598 if(alias && alias[0] != '\0') { | |
2599 my_alias = alias; | |
4705 | 2600 } else if(buddy && buddy->alias) { |
4227 | 2601 my_alias = buddy->alias; |
3349 | 2602 } |
2603 | |
2604 /* If there's an alias for the buddy, it's not 0-length | |
3105 | 2605 * and it doesn't match his JID, add the "name" attribute. |
2606 */ | |
3349 | 2607 if(my_alias != NULL && my_alias[0] != '\0' && strcmp(realwho, my_alias)) |
3311 | 2608 { |
3642 | 2609 xmlnode_put_attrib(y, "name", my_alias); |
3105 | 2610 } |
2611 | |
2612 /* | |
3349 | 2613 * See if there's an explict (new?) group for the buddy or pull |
2614 * one out of current Gaim buddylist data for him. | |
3105 | 2615 */ |
3349 | 2616 if(group && group[0] != '\0') { |
2617 my_group = group; | |
4687 | 2618 } else if((buddy_group = gaim_find_buddys_group(buddy)) != NULL) { |
3349 | 2619 my_group = buddy_group->name; |
2620 } | |
2621 | |
2622 /* | |
2623 * Send what group the buddy's in along with the roster item. | |
2624 */ | |
2625 if(my_group != NULL && my_group[0] != '\0') { | |
2626 xmlnode z = xmlnode_insert_tag(y, "group"); | |
2627 xmlnode_insert_cdata(z, my_group, -1); | |
3105 | 2628 } |
2629 | |
2630 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); | |
2631 | |
2632 xmlnode_free(x); | |
2633 g_free(realwho); | |
2634 } | |
2635 } | |
2636 | |
3136 | 2637 /* |
3349 | 2638 * Add/update buddy's alias on server |
2639 * | |
2640 * This is just a roster update using existing, local buddylist data | |
2641 */ | |
5572 | 2642 static void jabber_alias_buddy(GaimConnection *gc, const char *name, const char *alias) |
3349 | 2643 { |
4269 | 2644 jabber_roster_update(gc, name, alias, NULL); |
3349 | 2645 } |
2646 | |
2647 /* | |
3136 | 2648 * Change buddy's group on server roster |
2649 */ | |
5572 | 2650 static void jabber_group_change(GaimConnection *gc, const char *name, const char *old_group, const char *new_group) |
3136 | 2651 { |
3349 | 2652 if(old_group && new_group && strcmp(old_group, new_group)) |
2653 jabber_roster_update(gc, name, NULL, new_group); | |
2654 } | |
2655 | |
2656 /* | |
2657 * Group rename | |
2658 * | |
2659 * Jabber doesn't have "groups," per se. "Group" is simply a JID attribute. | |
2660 * So we iterate through the list of buddies that are in the group and change | |
2661 * the group attribute for each of them. | |
2662 */ | |
5572 | 2663 static void jabber_rename_group(GaimConnection *gc, |
3867 | 2664 const char *old_group, |
2665 const char *new_group, | |
3349 | 2666 GList *members) |
2667 { | |
2668 if(old_group && new_group && strcmp(old_group, new_group)) | |
2669 while(members) { | |
2670 jabber_group_change(gc, (char *)(members->data), old_group, new_group); | |
2671 members = members->next; | |
2672 } | |
3136 | 2673 } |
2674 | |
5572 | 2675 static void jabber_add_buddy(GaimConnection *gc, const char *name) |
2086 | 2676 { |
3136 | 2677 xmlnode x; |
2086 | 2678 char *realwho; |
2956 | 2679 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3311 | 2680 gaim_jid gjid; |
5572 | 2681 GaimAccount *account = gaim_connection_get_account(gc); |
2086 | 2682 |
2683 if (!((struct jabber_data *)gc->proto_data)->did_import) | |
2684 return; | |
2685 | |
3311 | 2686 /* |
2687 * If there's no name or the name is ourself | |
2688 */ | |
5572 | 2689 if(!name || !strcmp(gaim_account_get_username(account), name)) |
2086 | 2690 return; |
2691 | |
3311 | 2692 if((realwho = get_realwho(gjc, name, FALSE, &gjid)) == NULL) { |
3427 | 2693 char *msg = g_strdup_printf(_("The user %s is an invalid Jabber I.D. and was " |
2694 "therefore not added."), name); | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2695 gaim_notify_error(gc, NULL, _("Unable to add buddy."), |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5435
diff
changeset
|
2696 _("Jabber Error")); |
3311 | 2697 g_free(msg); |
2698 jabber_remove_gaim_buddy(gc, name); | |
2699 return; | |
2086 | 2700 } |
2701 | |
3311 | 2702 /* FIXME: transport */ |
2703 if(gjid->user == NULL) { | |
2704 g_free(realwho); | |
2705 gaim_jid_free(gjid); | |
2706 return; | |
2707 } | |
2708 gaim_jid_free(gjid); | |
2709 | |
2086 | 2710 x = xmlnode_new_tag("presence"); |
2711 xmlnode_put_attrib(x, "to", realwho); | |
2712 xmlnode_put_attrib(x, "type", "subscribe"); | |
2956 | 2713 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2714 xmlnode_free(x); | |
2086 | 2715 |
3349 | 2716 jabber_roster_update(gc, realwho, NULL, NULL); |
3105 | 2717 |
2086 | 2718 g_free(realwho); |
2719 } | |
2720 | |
6059 | 2721 static void jabber_remove_buddy(GaimConnection *gc, const char *name, const char *group) |
2086 | 2722 { |
3048 | 2723 xmlnode x; |
2086 | 2724 char *realwho; |
2956 | 2725 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2086 | 2726 |
3311 | 2727 if(!name || (realwho = get_realwho(gjc, name, FALSE, NULL)) == NULL) |
2086 | 2728 return; |
2729 | |
2956 | 2730 x = xmlnode_new_tag("presence"); |
2731 xmlnode_put_attrib(x, "to", realwho); | |
2732 xmlnode_put_attrib(x, "type", "unsubscribe"); | |
2733 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); | |
2086 | 2734 g_free(realwho); |
2735 xmlnode_free(x); | |
2736 } | |
2737 | |
4916 | 2738 #if 0 /* Faceprint! Look here! */ |
3314 | 2739 /* |
2740 * Remove a buddy item from the roster entirely | |
2741 */ | |
5572 | 2742 static void jabber_remove_buddy_roster_item(GaimConnection *gc, char *name) |
3314 | 2743 { |
3340 | 2744 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3314 | 2745 char *realwho; |
3340 | 2746 |
2747 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { | |
2748 xmlnode x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
2749 xmlnode y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); | |
2750 xmlnode_put_attrib(y, "jid", realwho); | |
2751 xmlnode_put_attrib(y, "subscription", "remove"); | |
2752 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); | |
2753 g_free(realwho); | |
2754 xmlnode_free(x); | |
2755 } | |
2756 } | |
4916 | 2757 #endif |
3340 | 2758 |
2759 /* | |
2760 * Unsubscribe a buddy from our presence | |
2761 */ | |
5572 | 2762 static void jabber_unsubscribe_buddy_from_us(GaimConnection *gc, const char *name) |
3340 | 2763 { |
2764 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; | |
2765 char *realwho; | |
2766 | |
2767 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { | |
2768 xmlnode g = xmlnode_new_tag("presence"); | |
2769 xmlnode_put_attrib(g, "to", realwho); | |
2770 xmlnode_put_attrib(g, "type", "unsubscribed"); | |
2771 gjab_send(gjc, g); | |
2772 xmlnode_free(g); | |
2773 } | |
2774 } | |
2775 | |
2776 /* | |
2777 * Common code for setting ourselves invisible/visible to buddy | |
2778 */ | |
5572 | 2779 static void jabber_invisible_to_buddy_common(GaimConnection *gc, const char *name, gboolean invisible) |
3340 | 2780 { |
3314 | 2781 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3340 | 2782 char *realwho; |
2783 | |
2784 if((realwho = get_realwho(gjc, name, FALSE, NULL)) != NULL) { | |
5135 | 2785 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho, TRUE); |
3340 | 2786 xmlnode g = xmlnode_new_tag("presence"); |
2787 | |
2788 xmlnode_put_attrib(g, "to", realwho); | |
2789 | |
2790 if(invisible) | |
2791 xmlnode_put_attrib(g, "type", "invisible"); | |
2792 | |
2793 gjab_send(gjc, g); | |
2794 | |
2795 g_free(realwho); | |
2796 xmlnode_free(g); | |
2797 | |
2798 if(jbd) { | |
2799 if(invisible) { | |
2800 jbd->invisible |= JABBER_BUD_INVIS; | |
2801 } else { | |
2802 jbd->invisible &= ~JABBER_BUD_INVIS; | |
2803 } | |
2804 } | |
2805 } | |
2806 } | |
2807 | |
2808 /* | |
2809 * Make ourselves temporarily invisible to a buddy | |
2810 */ | |
5572 | 2811 static void jabber_invisible_to_buddy(GaimConnection *gc, const char *name) |
3340 | 2812 { |
2813 jabber_invisible_to_buddy_common(gc, name, TRUE); | |
2814 } | |
2815 | |
2816 /* | |
2817 * Make ourselves visible to a buddy | |
2818 */ | |
5572 | 2819 static void jabber_visible_to_buddy(GaimConnection *gc, const char *name) |
3340 | 2820 { |
2821 jabber_invisible_to_buddy_common(gc, name, FALSE); | |
2822 } | |
2823 | |
2824 /* | |
2825 * Function used by the g_hash_table_foreach() in invisible_to_all_buddies() to | |
2826 * actually set the status. | |
2827 * | |
2828 * key is unused | |
2829 * value is the pointer to the jabber_buddy_data struct | |
2830 * data is gboolean: TRUE (invisible) or FALSE (not invisible) | |
2831 */ | |
2832 static void set_invisible_to_buddy_status(gpointer key, gpointer val, gpointer data) { | |
2833 struct jabber_buddy_data *jbd = val; | |
6478
338147ea6896
[gaim-migrate @ 6991]
Christian Hammond <chipx86@chipx86.com>
parents:
6371
diff
changeset
|
2834 gboolean invisible = GPOINTER_TO_INT(data); |
3340 | 2835 |
2836 if(jbd) { | |
2837 if(invisible) { | |
2838 jbd->invisible = JABBER_SERV_INVIS | JABBER_BUD_INVIS; | |
2839 } else { | |
2840 /* | |
2841 * If we've asserted server-level invisibility, cancelling | |
2842 * it removes explicit buddy invisibility settings too. | |
2843 */ | |
2844 if(jbd->invisible & JABBER_SERV_INVIS) | |
2845 jbd->invisible = JABBER_NOT_INVIS; | |
2846 } | |
2847 } | |
2848 } | |
2849 | |
2850 /* | |
2851 * Show we've set ourselves invisible/visible to all buddies on the server | |
2852 * | |
2853 * Used when we set server-wide invisibility so that individual buddy menu | |
2854 * entries show the proper option. | |
2855 */ | |
5572 | 2856 static void invisible_to_all_buddies(GaimConnection *gc, gboolean invisible) |
3340 | 2857 { |
2858 struct jabber_data *jd = gc->proto_data; | |
2859 | |
2860 if(jd->buddies != NULL) | |
6478
338147ea6896
[gaim-migrate @ 6991]
Christian Hammond <chipx86@chipx86.com>
parents:
6371
diff
changeset
|
2861 g_hash_table_foreach(jd->buddies, set_invisible_to_buddy_status, GINT_TO_POINTER(invisible)); |
3314 | 2862 } |
2863 | |
5572 | 2864 static const char *jabber_list_icon(GaimAccount *a, struct buddy *b) |
2086 | 2865 { |
4687 | 2866 return "jabber"; |
2867 } | |
4916 | 2868 |
2869 static void jabber_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne) | |
2870 { | |
5135 | 2871 struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); |
2872 | |
2873 if(!GAIM_BUDDY_IS_ONLINE(b)) { | |
2874 if (jbd && jbd->error_msg) | |
4927 | 2875 *nw = "error"; |
5135 | 2876 |
2877 if(jbd && (jbd->subscription & JABBER_SUB_PENDING || | |
2878 !(jbd->subscription & JABBER_SUB_TO))) | |
2879 *se = "notauthorized"; | |
2880 else | |
2881 *se = "offline"; | |
2882 | |
4916 | 2883 } else { |
2884 switch (b->uc) { | |
2885 case UC_AWAY: | |
2886 *se = "away"; | |
2887 break; | |
2888 case UC_CHAT: | |
2889 *se = "chat"; | |
2890 break; | |
2891 case UC_XA: | |
2892 *se = "extendedaway"; | |
2893 break; | |
2894 case UC_DND: | |
2895 *se = "dnd"; | |
2896 break; | |
2897 case UC_ERROR: | |
2898 *se = "error"; | |
2899 break; | |
2900 } | |
2086 | 2901 } |
4916 | 2902 } |
2086 | 2903 |
5572 | 2904 static GList *jabber_chat_info(GaimConnection *gc) |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2905 { |
2956 | 2906 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2907 | |
2908 static char *confserv = NULL; /* this pointer must be persistent */ | |
2909 gchar *server; | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2910 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2911 GList *m = NULL; |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2912 struct proto_chat_entry *pce; |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2913 |
2956 | 2914 /* This is a scientific wild-ass guess... |
2915 * | |
2916 * If there are more than two "components" to the current server name, | |
2917 * lop-off the left-most component and replace with "conference." | |
2918 */ | |
2919 if(confserv != NULL) { | |
2920 g_free(confserv); /* dispose of the old value */ | |
2921 } | |
2922 | |
2923 if((server = g_strdup(gjc->user->server)) == NULL) { | |
2924 confserv = g_strdup(DEFAULT_GROUPCHAT); | |
2925 } else { | |
2926 gchar **splits, **index; | |
2927 gchar *tmp; | |
2928 int cnt = 0; | |
2929 | |
2930 | |
2931 index = splits = g_strsplit(server, ".", -1); /* split the connected server */ | |
2932 | |
2933 while(*(index++)) /* index to the end--counting the parts */ | |
2934 ++cnt; | |
2935 | |
2936 /* | |
2937 * If we've more than two parts, point to the second part. Else point | |
2938 * to the start. | |
2939 */ | |
2940 if(cnt > 2) { | |
2941 index -= cnt; | |
2942 } else { | |
2943 index = splits; | |
2944 } | |
2945 | |
2946 /* Put it together */ | |
2947 confserv = g_strjoin(".", "conference", (tmp = g_strjoinv(".", index)), NULL); | |
2948 | |
2949 g_free(server); /* we don't need this stuff no more */ | |
2950 g_free(tmp); | |
2951 g_strfreev(splits); | |
2952 } | |
2953 | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2954 pce = g_new0(struct proto_chat_entry, 1); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2955 pce->label = _("Room:"); |
5234 | 2956 pce->identifier = "room"; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2957 m = g_list_append(m, pce); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2958 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2959 pce = g_new0(struct proto_chat_entry, 1); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2960 pce->label = _("Server:"); |
5234 | 2961 pce->identifier = "server"; |
2956 | 2962 pce->def = confserv; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2963 m = g_list_append(m, pce); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2964 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2965 pce = g_new0(struct proto_chat_entry, 1); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2966 pce->label = _("Handle:"); |
5234 | 2967 pce->identifier = "handle"; |
2956 | 2968 pce->def = gjc->user->user; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2969 m = g_list_append(m, pce); |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2970 |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2971 return m; |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2972 } |
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
2973 |
5572 | 2974 static void jabber_join_chat(GaimConnection *gc, GHashTable *data) |
2086 | 2975 { |
2976 xmlnode x; | |
5234 | 2977 char *room, *server, *handle; |
2086 | 2978 char *realwho; |
2956 | 2979 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
2980 GSList *jcs = ((struct jabber_data *)gc->proto_data)->chats; | |
2086 | 2981 struct jabber_chat *jc; |
3311 | 2982 gaim_jid gjid; |
2086 | 2983 |
5234 | 2984 room = g_hash_table_lookup(data, "room"); |
2985 server = g_hash_table_lookup(data, "server"); | |
2986 handle = g_hash_table_lookup(data, "handle"); | |
2987 | |
2988 if (!room || !server || !handle) | |
2086 | 2989 return; |
2990 | |
5234 | 2991 realwho = create_valid_jid(room, server, handle); |
2992 gaim_debug(GAIM_DEBUG_INFO, "jabber", "%s\n", realwho); | |
2086 | 2993 |
3311 | 2994 if((gjid = gaim_jid_new(realwho)) == NULL) { |
3427 | 2995 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
|
2996 gaim_notify_error(gc, NULL, _("Unable to join chat"), msg); |
3236 | 2997 g_free(msg); |
3311 | 2998 g_free(realwho); |
3236 | 2999 return; |
3000 } | |
2956 | 3001 |
3311 | 3002 if((jc = find_any_chat(gc, gjid)) != NULL) { |
2956 | 3003 switch(jc->state) { |
3004 case JCS_PENDING: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3005 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3006 "attempt to re-join already pending Jabber chat! (ignoring)\n"); |
2956 | 3007 g_free(realwho); /* yuck! */ |
3311 | 3008 gaim_jid_free(gjid); |
2956 | 3009 return; |
3010 case JCS_ACTIVE: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3011 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3012 "attempt to re-join already active Jabber chat! (ignoring)\n"); |
2956 | 3013 g_free(realwho); /* yuck! */ |
3311 | 3014 gaim_jid_free(gjid); |
2956 | 3015 return; |
3016 case JCS_CLOSED: | |
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 "rejoining previously closed Jabber chat\n"); |
2956 | 3019 break; |
3020 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3021 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3022 "found Jabber chat in unknown state! (ignoring)\n"); |
2956 | 3023 g_free(realwho); /* yuck! */ |
3311 | 3024 gaim_jid_free(gjid); |
2956 | 3025 return; |
3026 } | |
3027 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3028 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3029 "joining completely new Jabber chat\n"); |
2956 | 3030 jc = g_new0(struct jabber_chat, 1); |
3311 | 3031 jc->gjid = gjid; |
2956 | 3032 jc->gc = gc; |
3033 ((struct jabber_data *)gc->proto_data)->chats = g_slist_append(jcs, jc); | |
4687 | 3034 // add_buddy(gc->account, _("Chats"), realwho, realwho); |
2956 | 3035 } |
3036 | |
3037 jc->state = JCS_PENDING; | |
3038 | |
2086 | 3039 x = jutil_presnew(0, realwho, NULL); |
2956 | 3040 gjab_send(gjc, x); |
2086 | 3041 xmlnode_free(x); |
3042 g_free(realwho); | |
3043 } | |
3044 | |
5572 | 3045 static void jabber_chat_invite(GaimConnection *gc, int id, const char *message, const char *name) |
2086 | 3046 { |
3047 xmlnode x, y; | |
3048 struct jabber_data *jd = gc->proto_data; | |
2956 | 3049 gjconn gjc = jd->gjc; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3050 struct jabber_chat *jc = NULL; |
2086 | 3051 char *realwho, *subject; |
3052 | |
3311 | 3053 if(!name || (realwho = get_realwho(gjc, name, FALSE, NULL)) == NULL) |
2086 | 3054 return; |
3055 | |
3056 /* find which chat we're inviting to */ | |
2956 | 3057 if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) |
2086 | 3058 return; |
3059 | |
3060 x = xmlnode_new_tag("message"); | |
3061 xmlnode_put_attrib(x, "to", realwho); | |
3311 | 3062 |
2086 | 3063 g_free(realwho); |
3064 | |
3065 y = xmlnode_insert_tag(x, "x"); | |
3066 xmlnode_put_attrib(y, "xmlns", "jabber:x:conference"); | |
3311 | 3067 subject = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); |
2086 | 3068 xmlnode_put_attrib(y, "jid", subject); |
3069 g_free(subject); | |
3070 | |
3071 if (message && strlen(message)) { | |
5093 | 3072 insert_message(x, message, FALSE); |
2086 | 3073 } |
3074 | |
2956 | 3075 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 3076 xmlnode_free(x); |
3077 } | |
3078 | |
5572 | 3079 static void jabber_chat_leave(GaimConnection *gc, int id) |
2086 | 3080 { |
3081 struct jabber_data *jd = gc->proto_data; | |
2956 | 3082 gjconn gjc = jd->gjc; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3083 struct jabber_chat *jc = NULL; |
3311 | 3084 char *chatname; |
2086 | 3085 xmlnode x; |
3086 | |
2956 | 3087 /* Find out which chat we're leaving */ |
3088 if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) | |
2086 | 3089 return; |
3090 | |
3311 | 3091 chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); |
3092 x = jutil_presnew(0, chatname, NULL); | |
3093 g_free(chatname); | |
2086 | 3094 xmlnode_put_attrib(x, "type", "unavailable"); |
2956 | 3095 gjab_send(gjc, x); |
2086 | 3096 xmlnode_free(x); |
3097 jc->b = NULL; | |
3098 } | |
3099 | |
6059 | 3100 static int jabber_chat_send(GaimConnection *gc, int id, const char *message) |
2086 | 3101 { |
3102 xmlnode x, y; | |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3103 struct jabber_chat *jc = NULL; |
2086 | 3104 char *chatname; |
2956 | 3105 int retval = 0; |
3106 | |
3107 /* Find out which chat we're sending to */ | |
3108 if((retval = jabber_find_chat_by_convo_id(gc, id, &jc)) != 0) | |
3109 return(retval); | |
2086 | 3110 |
3111 x = xmlnode_new_tag("message"); | |
3311 | 3112 xmlnode_put_attrib(x, "from", jc->gjid->full); |
3113 chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); | |
2086 | 3114 xmlnode_put_attrib(x, "to", chatname); |
3115 g_free(chatname); | |
3116 xmlnode_put_attrib(x, "type", "groupchat"); | |
3117 | |
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3118 if (message && strlen(message) > strlen("/topic ") && |
4793 | 3119 !g_ascii_strncasecmp(message, "/topic ", strlen("/topic "))) { |
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3120 char buf[8192]; |
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3121 y = xmlnode_insert_tag(x, "subject"); |
3642 | 3122 xmlnode_insert_cdata(y, message + strlen("/topic "), -1); |
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3123 y = xmlnode_insert_tag(x, "body"); |
3642 | 3124 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
|
3125 xmlnode_insert_cdata(y, buf, -1); |
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
3126 } else if (message && strlen(message)) { |
5093 | 3127 insert_message(x, message, FALSE); |
2086 | 3128 } |
3129 | |
2956 | 3130 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 3131 xmlnode_free(x); |
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
3132 return 0; |
2086 | 3133 } |
3134 | |
6059 | 3135 static void jabber_chat_whisper(GaimConnection *gc, int id, const char *who, const char *message) |
2086 | 3136 { |
5093 | 3137 xmlnode x; |
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
3138 struct jabber_chat *jc = NULL; |
2086 | 3139 char *chatname; |
3140 | |
2956 | 3141 /* Find out which chat we're whispering to */ |
3142 if(jabber_find_chat_by_convo_id(gc, id, &jc) != 0) | |
2086 | 3143 return; |
3144 | |
3145 x = xmlnode_new_tag("message"); | |
3311 | 3146 xmlnode_put_attrib(x, "from", jc->gjid->full); |
3147 chatname = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); | |
2086 | 3148 xmlnode_put_attrib(x, "to", chatname); |
3149 g_free(chatname); | |
3150 xmlnode_put_attrib(x, "type", "normal"); | |
3151 | |
3152 if (message && strlen(message)) { | |
5093 | 3153 insert_message(x, message, FALSE); |
2086 | 3154 } |
3155 | |
2956 | 3156 gjab_send(((struct jabber_data *)gc->proto_data)->gjc, x); |
2086 | 3157 xmlnode_free(x); |
3158 } | |
3159 | |
3160 static char *jabber_normalize(const char *s) | |
3161 { | |
3162 static char buf[BUF_LEN]; | |
3163 char *t, *u; | |
3164 int x = 0; | |
3165 | |
3166 g_return_val_if_fail((s != NULL), NULL); | |
3167 | |
2956 | 3168 /* Somebody called us with s == NULL once... */ |
3169 if(s == NULL) { | |
3170 return(NULL); | |
3171 } else { | |
4793 | 3172 u = t = g_utf8_strdown(s, -1); |
2956 | 3173 |
3174 while (*t && (x < BUF_LEN - 1)) { | |
3175 if (*t != ' ') | |
3176 buf[x++] = *t; | |
3177 t++; | |
3178 } | |
3179 buf[x] = '\0'; | |
3180 g_free(u); | |
3181 | |
3182 if (!strchr(buf, '@')) { | |
4927 | 3183 strcat(buf, "@" DEFAULT_SERVER); /* this isn't always right, but eh */ |
2956 | 3184 } else if ((u = strchr(strchr(buf, '@'), '/')) != NULL) { |
3185 *u = '\0'; | |
3186 } | |
3187 | |
3188 return buf; | |
2086 | 3189 } |
3190 } | |
3191 | |
5572 | 3192 static void jabber_get_info(GaimConnection *gc, const char *who) { |
2086 | 3193 xmlnode x; |
3194 char *id; | |
2956 | 3195 char *realwho; |
2086 | 3196 struct jabber_data *jd = gc->proto_data; |
2956 | 3197 gjconn gjc = jd->gjc; |
2086 | 3198 |
3311 | 3199 if((realwho = get_realwho(gjc, who, TRUE, NULL)) == NULL) |
3200 return; | |
3201 | |
2086 | 3202 x = jutil_iqnew(JPACKET__GET, NS_VCARD); |
2956 | 3203 xmlnode_put_attrib(x, "to", realwho); |
3311 | 3204 |
2956 | 3205 g_free(realwho); |
3206 | |
3207 id = gjab_getid(gjc); | |
2086 | 3208 xmlnode_put_attrib(x, "id", id); |
3209 | |
2956 | 3210 g_hash_table_insert(jd->gjc->queries, g_strdup(id), g_strdup("vCard")); |
3211 | |
3212 gjab_send(gjc, x); | |
2086 | 3213 |
3214 xmlnode_free(x); | |
3311 | 3215 } |
3216 | |
5572 | 3217 static void jabber_get_error_msg(GaimConnection *gc, const char *who) { |
3311 | 3218 struct jabber_data *jd = gc->proto_data; |
3219 gjconn gjc = jd->gjc; | |
3220 gchar **str_arr = (gchar **) g_new(gpointer, 3); | |
3221 gchar **ap = str_arr; | |
3222 gchar *realwho, *final; | |
3223 struct jabber_buddy_data *jbd; | |
3224 | |
3225 if((realwho = get_realwho(gjc, who, FALSE, NULL)) == NULL) { | |
3226 g_strfreev(str_arr); | |
3227 return; | |
3228 } | |
3229 | |
5135 | 3230 jbd = jabber_find_buddy(gc, realwho, TRUE); |
3311 | 3231 |
5236 | 3232 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), realwho); |
3233 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Error"), jbd->error_msg); | |
3311 | 3234 *ap = NULL; |
3770 | 3235 |
3311 | 3236 final= g_strjoinv(NULL, str_arr); |
3770 | 3237 |
3311 | 3238 g_strfreev(str_arr); |
3239 | |
3240 g_show_info_text(gc, realwho, 2, final, NULL); | |
3241 g_free(realwho); | |
3242 g_free(final); | |
2086 | 3243 } |
3244 | |
5572 | 3245 static void jabber_get_away_msg(GaimConnection *gc, const char *who) { |
2956 | 3246 struct jabber_data *jd = gc->proto_data; |
3247 gjconn gjc = jd->gjc; | |
3311 | 3248 int num_resources; |
3249 gaim_jid gjid; | |
3250 char *buddy = get_realwho(gjc, who, FALSE, &gjid); | |
5135 | 3251 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, buddy, TRUE); |
3311 | 3252 gchar **str_arr; |
3253 gchar **ap; | |
3254 gchar *realwho, *final; | |
3255 GSList *resources; | |
3256 int i; | |
3257 | |
3258 if(!buddy) | |
3259 return; | |
3260 | |
3261 if(!gjid->resource) { | |
3262 num_resources = g_slist_length(jbd->resources); | |
3263 resources = jbd->resources; | |
3264 } else { | |
3265 num_resources = 1; | |
3266 resources = jbd->resources; | |
3267 while(strcasecmp(((jab_res_info)resources->data)->name, gjid->resource)) | |
3268 resources = resources->next; | |
3269 } | |
3270 | |
3271 gaim_jid_free(gjid); | |
2956 | 3272 |
3273 /* space for all elements: Jabber I.D. + "status" + NULL (list terminator) */ | |
3311 | 3274 str_arr = (gchar **) g_new(gpointer, num_resources*2 + 1); |
3275 ap = str_arr; | |
3276 | |
3277 for(i=0; i<num_resources; i++) | |
3278 { | |
3279 jab_res_info jri = resources->data; | |
4450 | 3280 char *status; |
3311 | 3281 realwho = g_strdup_printf("%s/%s", buddy, jri->name); |
4450 | 3282 status = strdup_withhtml(jabber_lookup_away(gjc, realwho)); |
5236 | 3283 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), realwho); |
3284 *ap++ = g_strdup_printf("<B>%s:</B> %s%s%s<BR>\n", _("Status"), jabber_get_state_string(jri->state), status ? ": " : "", status ? status : ""); | |
4450 | 3285 g_free(status); |
3311 | 3286 g_free(realwho); |
3287 resources = resources->next; | |
2956 | 3288 } |
3289 | |
3290 *ap = NULL; | |
3770 | 3291 |
3311 | 3292 g_free(buddy); |
2956 | 3293 |
3294 final= g_strjoinv(NULL, str_arr); | |
3295 g_strfreev(str_arr); | |
3296 | |
3311 | 3297 g_show_info_text(gc, who, 2, final, NULL); |
2956 | 3298 g_free(final); |
3770 | 3299 |
2956 | 3300 } |
3301 | |
6059 | 3302 static void jabber_get_cb_info(GaimConnection *gc, int cid, const char *who) { |
2956 | 3303 struct jabber_chat *jc = NULL; |
3304 char *realwho; | |
3305 | |
3306 /* Find out which chat */ | |
3307 if(jabber_find_chat_by_convo_id(gc, cid, &jc) != 0) | |
3308 return; | |
3309 | |
3311 | 3310 realwho = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); |
2956 | 3311 |
3312 jabber_get_info(gc, realwho); | |
3313 g_free(realwho); | |
3314 } | |
3315 | |
6059 | 3316 static void jabber_get_cb_away_msg(GaimConnection *gc, int cid, const char *who) { |
2956 | 3317 struct jabber_chat *jc = NULL; |
3318 char *realwho; | |
3319 | |
3320 /* Find out which chat */ | |
3321 if(jabber_find_chat_by_convo_id(gc, cid, &jc) != 0) | |
3322 return; | |
3323 | |
3311 | 3324 realwho = g_strdup_printf("%s@%s/%s", jc->gjid->user, jc->gjid->server, who); |
2956 | 3325 |
3326 jabber_get_away_msg(gc, realwho); | |
3327 g_free(realwho); | |
3328 | |
3329 } | |
3330 | |
4744 | 3331 static char *jabber_tooltip_text(struct buddy *b) |
3332 { | |
5135 | 3333 struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); |
4745 | 3334 jab_res_info jri = jabber_find_resource(b->account->gc, b->name); |
5135 | 3335 char *ret = NULL; |
4745 | 3336 if(jri) { |
4777 | 3337 char *stripped = strip_html(jabber_lookup_away(GC_GJ(b->account->gc), |
4745 | 3338 b->name)); |
4777 | 3339 char *text = NULL; |
3340 if(stripped) | |
3341 text = g_markup_escape_text(stripped, strlen(stripped)); | |
5236 | 3342 ret = g_strdup_printf("<b>%s:</b> %s%s%s", |
3343 _("Status"), | |
4745 | 3344 jabber_get_state_string(jri->state), text ? ": " : "", |
3345 text ? text : ""); | |
3346 | |
4777 | 3347 if(stripped) { |
3348 g_free(stripped); | |
4745 | 3349 g_free(text); |
4777 | 3350 } |
5136 | 3351 } else if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && |
3352 (jbd->subscription & JABBER_SUB_PENDING || | |
5135 | 3353 !(jbd->subscription & JABBER_SUB_TO))) { |
5236 | 3354 ret = g_strdup_printf("<b>%s:</b> %s", _("Status"), _("Not Authorized")); |
4745 | 3355 } |
5135 | 3356 return ret; |
4744 | 3357 } |
3358 | |
4732 | 3359 static char *jabber_status_text(struct buddy *b) |
3360 { | |
5135 | 3361 struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE); |
3362 char *ret = NULL; | |
4732 | 3363 if (b->uc & UC_UNAVAILABLE) { |
4777 | 3364 char *stripped = strip_html(jabber_lookup_away(GC_GJ(b->account->gc), |
4745 | 3365 b->name)); |
4777 | 3366 if(!stripped) { |
4745 | 3367 jab_res_info jri = jabber_find_resource(b->account->gc, b->name); |
3368 if(jri) | |
4777 | 3369 stripped = g_strdup(jabber_get_state_string(jri->state)); |
4745 | 3370 } |
4777 | 3371 ret = g_markup_escape_text(stripped, strlen(stripped)); |
3372 g_free(stripped); | |
5136 | 3373 } else if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && |
3374 (jbd->subscription & JABBER_SUB_PENDING || | |
5135 | 3375 !(jbd->subscription & JABBER_SUB_TO))) { |
3376 ret = g_strdup(_("Not Authorized")); | |
4732 | 3377 } |
5135 | 3378 return ret; |
4732 | 3379 } |
3380 | |
5572 | 3381 static GList *jabber_buddy_menu(GaimConnection *gc, const char *who) { |
2170
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3382 GList *m = NULL; |
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3383 struct proto_buddy_menu *pbm; |
4687 | 3384 struct buddy *b = gaim_find_buddy(gc->account, who); |
3311 | 3385 |
3386 if(b->uc == UC_ERROR) | |
3387 { | |
3388 pbm = g_new0(struct proto_buddy_menu, 1); | |
3389 pbm->label = _("View Error Msg"); | |
3390 pbm->callback = jabber_get_error_msg; | |
3391 pbm->gc = gc; | |
3392 m = g_list_append(m, pbm); | |
3393 } else { | |
3340 | 3394 gjconn gjc = ((struct jabber_data *)gc->proto_data)->gjc; |
3395 char *realwho = get_realwho(gjc, who, FALSE, NULL); | |
5135 | 3396 struct jabber_buddy_data *jbd = jabber_find_buddy(gc, realwho, FALSE); |
3340 | 3397 |
3398 g_free(realwho); | |
3399 | |
3311 | 3400 pbm = g_new0(struct proto_buddy_menu, 1); |
3401 pbm->label = _("Get Away Msg"); | |
3402 pbm->callback = jabber_get_away_msg; | |
3403 pbm->gc = gc; | |
3404 m = g_list_append(m, pbm); | |
3340 | 3405 |
3406 pbm = g_new0(struct proto_buddy_menu, 1); | |
3407 if(jbd && (jbd->invisible & JABBER_BUD_INVIS)) { | |
3408 pbm->label = _("Un-hide From"); | |
3409 pbm->callback = jabber_visible_to_buddy; | |
3410 } else { | |
3411 pbm->label = _("Temporarily Hide From"); | |
3412 pbm->callback = jabber_invisible_to_buddy; | |
3413 } | |
4916 | 3414 |
3415 pbm->gc = gc; | |
3416 m = g_list_append(m, pbm); | |
3417 pbm = g_new0(struct proto_buddy_menu, 1); | |
3418 pbm->label = _("Cancel Presence Notification"); | |
3419 pbm->callback = jabber_unsubscribe_buddy_from_us; | |
3340 | 3420 pbm->gc = gc; |
3421 m = g_list_append(m, pbm); | |
5136 | 3422 |
3423 if(jbd && !GAIM_BUDDY_IS_ONLINE(b) && | |
3424 !(jbd->subscription & JABBER_SUB_TO)) { | |
3425 pbm = g_new0(struct proto_buddy_menu, 1); | |
3426 pbm->label = _("Re-request authorization"); | |
3427 pbm->callback = jabber_add_buddy; | |
3428 pbm->gc = gc; | |
3429 m = g_list_append(m, pbm); | |
3430 } | |
3311 | 3431 } |
2170
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3432 |
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
3433 return m; |
2086 | 3434 } |
3435 | |
5572 | 3436 static GList *jabber_away_states(GaimConnection *gc) { |
2086 | 3437 GList *m = NULL; |
3438 | |
4982 | 3439 m = g_list_append(m, _("Online")); |
3440 m = g_list_append(m, _("Chatty")); | |
3441 m = g_list_append(m, _("Away")); | |
3442 m = g_list_append(m, _("Extended Away")); | |
3443 m = g_list_append(m, _("Do Not Disturb")); | |
3444 m = g_list_append(m, _("Invisible")); | |
4110 | 3445 m = g_list_append(m, GAIM_AWAY_CUSTOM); |
2086 | 3446 |
3447 return m; | |
3448 } | |
3449 | |
6059 | 3450 static void jabber_set_away(GaimConnection *gc, const char *state, const char *message) |
2086 | 3451 { |
3452 xmlnode x, y; | |
3453 struct jabber_data *jd = gc->proto_data; | |
2956 | 3454 gjconn gjc = jd->gjc; |
3311 | 3455 GSList *jcs; |
3456 struct jabber_chat *jc; | |
3457 char *chatname; | |
3340 | 3458 gboolean invisible = FALSE; |
2086 | 3459 |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3460 if (gc->away) { |
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3461 g_free(gc->away); |
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3462 gc->away = NULL; |
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3463 } |
2086 | 3464 |
3465 x = xmlnode_new_tag("presence"); | |
3466 | |
3467 if (!strcmp(state, GAIM_AWAY_CUSTOM)) { | |
3468 /* oh goody. Gaim is telling us what to do. */ | |
3469 if (message) { | |
3470 /* Gaim wants us to be away */ | |
5174 | 3471 char *stripped; |
3472 | |
3473 /* Jabber supports XHTML in IMs, but not in away messages. */ | |
3474 html_to_xhtml(message, NULL, &stripped); | |
3475 | |
2086 | 3476 y = xmlnode_insert_tag(x, "show"); |
3477 xmlnode_insert_cdata(y, "away", -1); | |
3478 y = xmlnode_insert_tag(x, "status"); | |
5174 | 3479 xmlnode_insert_cdata(y, stripped, -1); |
3480 | |
3481 gc->away = g_strdup(stripped); | |
3482 g_free(stripped); | |
2086 | 3483 } else { |
3484 /* Gaim wants us to not be away */ | |
3485 /* but for Jabber, we can just send presence with no other information. */ | |
3486 } | |
3487 } else { | |
3488 /* state is one of our own strings. it won't be NULL. */ | |
4982 | 3489 if (!strcmp(state, _("Online"))) { |
2086 | 3490 /* once again, we don't have to put anything here */ |
4982 | 3491 } else if (!strcmp(state, _("Chatty"))) { |
2086 | 3492 y = xmlnode_insert_tag(x, "show"); |
3493 xmlnode_insert_cdata(y, "chat", -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, _("Away"))) { |
2086 | 3496 y = xmlnode_insert_tag(x, "show"); |
3497 xmlnode_insert_cdata(y, "away", -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, _("Extended Away"))) { |
2086 | 3500 y = xmlnode_insert_tag(x, "show"); |
3501 xmlnode_insert_cdata(y, "xa", -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, _("Do Not Disturb"))) { |
2086 | 3504 y = xmlnode_insert_tag(x, "show"); |
3505 xmlnode_insert_cdata(y, "dnd", -1); | |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3506 gc->away = g_strdup(""); |
4982 | 3507 } else if (!strcmp(state, _("Invisible"))) { |
3340 | 3508 xmlnode_put_attrib(x, "type", "invisible"); |
4111
ee884f1d7ae3
[gaim-migrate @ 4326]
Christian Hammond <chipx86@chipx86.com>
parents:
4110
diff
changeset
|
3509 gc->away = g_strdup(""); |
3340 | 3510 invisible = TRUE; |
2086 | 3511 } |
3512 } | |
3513 | |
3311 | 3514 gjab_send(gjc, x); /* Notify "individuals" */ |
3515 | |
3516 /* | |
3517 * As of jabberd-1.4.2: simply sending presence to the server doesn't result in | |
3518 * it being propagated to conference rooms. So we wade thru the list of chats, | |
3519 * sending our new presence status to each and every one. | |
3520 */ | |
3521 for(jcs = jd->chats; jcs; jcs = jcs->next) { | |
3522 jc = jcs->data; | |
3523 if(jc->state == JCS_ACTIVE) { | |
3524 xmlnode_put_attrib(x, "from", jc->gjid->full); | |
3525 chatname = g_strdup_printf("%s@%s", jc->gjid->user, jc->gjid->server); | |
3526 xmlnode_put_attrib(x, "to", chatname); | |
3527 gjab_send(gjc, x); | |
3528 g_free(chatname); | |
3529 } | |
3530 } | |
3531 | |
2086 | 3532 xmlnode_free(x); |
3340 | 3533 |
3534 invisible_to_all_buddies(gc, invisible); | |
2086 | 3535 } |
3536 | |
5572 | 3537 static void jabber_set_idle(GaimConnection *gc, int idle) { |
2086 | 3538 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3539 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3540 "jabber_set_idle: setting idle %i\n", idle); |
3770 | 3541 jd->idle = idle ? time(NULL) - idle : idle; |
2086 | 3542 } |
3543 | |
5572 | 3544 static void jabber_keepalive(GaimConnection *gc) { |
2086 | 3545 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; |
4450 | 3546 gjab_send_raw(jd->gjc, JABBER_KEEPALIVE_STRING); |
2086 | 3547 } |
3548 | |
2956 | 3549 /*---------------------------------------*/ |
3550 /* Jabber "set info" (vCard) support */ | |
3551 /*---------------------------------------*/ | |
3552 | |
3553 /* | |
3554 * V-Card format: | |
3555 * | |
3556 * <vCard prodid='' version='' xmlns=''> | |
3557 * <FN></FN> | |
3558 * <N> | |
3559 * <FAMILY/> | |
3560 * <GIVEN/> | |
3561 * </N> | |
3562 * <NICKNAME/> | |
3563 * <URL/> | |
3564 * <ADR> | |
3565 * <STREET/> | |
3566 * <EXTADD/> | |
3567 * <LOCALITY/> | |
3568 * <REGION/> | |
3569 * <PCODE/> | |
3570 * <COUNTRY/> | |
3571 * </ADR> | |
3572 * <TEL/> | |
3573 * <EMAIL/> | |
3574 * <ORG> | |
3575 * <ORGNAME/> | |
3576 * <ORGUNIT/> | |
3577 * </ORG> | |
3578 * <TITLE/> | |
3579 * <ROLE/> | |
3580 * <DESC/> | |
3581 * <BDAY/> | |
3582 * </vCard> | |
3583 * | |
3584 * See also: | |
3585 * | |
3586 * http://docs.jabber.org/proto/html/vcard-temp.html | |
3587 * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd | |
3588 */ | |
3589 | |
3590 /* | |
3591 * Cross-reference user-friendly V-Card entry labels to vCard XML tags | |
3592 * and attributes. | |
3593 * | |
3594 * Order is (or should be) unimportant. For example: we have no way of | |
3595 * knowing in what order real data will arrive. | |
3596 * | |
3597 * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag | |
3598 * name, XML tag's parent tag "path" (relative to vCard node). | |
3599 * | |
3600 * List is terminated by a NULL label pointer. | |
3601 * | |
3602 * Entries with no label text, but with XML tag and parent tag | |
3603 * entries, are used by V-Card XML construction routines to | |
3604 * "automagically" construct the appropriate XML node tree. | |
3605 * | |
3606 * Thoughts on future direction/expansion | |
3607 * | |
3608 * This is a "simple" vCard. | |
3609 * | |
3610 * It is possible for nodes other than the "vCard" node to have | |
3611 * attributes. Should that prove necessary/desirable, add an | |
3612 * "attributes" pointer to the vcard_template struct, create the | |
3613 * necessary tag_attr structs, and add 'em to the vcard_dflt_data | |
3614 * array. | |
3615 * | |
3616 * The above changes will (obviously) require changes to the vCard | |
3617 * construction routines. | |
3618 */ | |
3619 | |
3620 struct vcard_template { | |
3621 char *label; /* label text pointer */ | |
3622 char *text; /* entry text pointer */ | |
3623 int visible; /* should entry field be "visible?" */ | |
3624 int editable; /* should entry field be editable? */ | |
3625 char *tag; /* tag text */ | |
3626 char *ptag; /* parent tag "path" text */ | |
3627 char *url; /* vCard display format if URL */ | |
3628 } vcard_template_data[] = { | |
2975 | 3629 {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, |
3630 {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, | |
3631 {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, | |
3632 {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, | |
3633 {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, | |
3634 {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, | |
3635 {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, | |
3636 {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, | |
3637 {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, | |
3638 {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, | |
3639 {N_("Country"), NULL, TRUE, TRUE, "COUNTRY", "ADR", NULL}, | |
3640 {N_("Telephone"), NULL, TRUE, TRUE, "TELEPHONE", NULL, NULL}, | |
3641 {N_("Email"), NULL, TRUE, TRUE, "EMAIL", NULL, "<A HREF=\"mailto:%s\">%s</A>"}, | |
3642 {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, | |
3643 {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, | |
3644 {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, | |
3645 {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, | |
3646 {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, | |
3647 {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, | |
2956 | 3648 {"", NULL, TRUE, TRUE, "N", NULL, NULL}, |
3649 {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, | |
3650 {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, | |
3651 {NULL, NULL, 0, 0, NULL, NULL, NULL} | |
3652 }; | |
3653 | |
3654 /* | |
3655 * The "vCard" tag's attibute list... | |
3656 */ | |
3657 struct tag_attr { | |
3658 char *attr; | |
3659 char *value; | |
3660 } vcard_tag_attr_list[] = { | |
3661 {"prodid", "-//HandGen//NONSGML vGen v1.0//EN"}, | |
3662 {"version", "2.0", }, | |
3663 {"xmlns", "vcard-temp", }, | |
3664 {NULL, NULL}, | |
3665 }; | |
3666 | |
3667 | |
3668 /* | |
3669 * Used by routines to parse an XML-encoded string into an xmlnode tree | |
3670 */ | |
3671 typedef struct { | |
3672 XML_Parser parser; | |
3673 xmlnode current; | |
3674 } *xmlstr2xmlnode_parser, xmlstr2xmlnode_parser_struct; | |
3675 | |
3676 | |
3677 /* | |
3678 * Display a Jabber vCard | |
3679 */ | |
3680 static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from) | |
3681 { | |
5572 | 3682 GaimConnection *gc = GJ_GC(gjc); |
2956 | 3683 char *cdata, *status; |
3684 struct vcard_template *vc_tp = vcard_template_data; | |
3685 | |
3686 /* space for all vCard elements + Jabber I.D. + "status" + NULL (list terminator) */ | |
3687 gchar **str_arr = (gchar **) g_new(gpointer, | |
3688 (sizeof(vcard_template_data)/sizeof(struct vcard_template)) + 3); | |
3689 gchar **ap = str_arr; | |
3690 gchar *buddy, *final; | |
3691 | |
4745 | 3692 jab_res_info jri; |
3693 | |
3311 | 3694 if((buddy = get_realwho(gjc, from, TRUE, NULL)) == NULL) { |
3695 g_strfreev(str_arr); | |
3696 return; | |
2956 | 3697 } |
3311 | 3698 |
4745 | 3699 jri = jabber_find_resource(GJ_GC(gjc), buddy); |
3700 | |
5236 | 3701 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _("Jabber ID"), buddy); |
2956 | 3702 |
3703 for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { | |
3704 if(strcmp(vc_tp->tag, "DESC") == 0) | |
3705 continue; /* special handling later */ | |
3706 if(vc_tp->ptag == NULL) { | |
3707 cdata = xmlnode_get_tag_data(querynode, vc_tp->tag); | |
3708 } else { | |
3709 gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); | |
3710 cdata = xmlnode_get_tag_data(querynode, tag); | |
3711 g_free(tag); | |
3712 } | |
3713 if(cdata != NULL) { | |
3714 if(vc_tp->url == NULL) { | |
5236 | 3715 *ap++ = g_strdup_printf("<B>%s:</B> %s<BR>\n", _(vc_tp->label), cdata); |
2956 | 3716 } else { |
3717 gchar *fmt = g_strdup_printf("<B>%%s:</B> %s<BR>\n", vc_tp->url); | |
5236 | 3718 *ap++ = g_strdup_printf(fmt, _(vc_tp->label), cdata, cdata); |
2956 | 3719 g_free(fmt); |
3720 } | |
3721 } | |
3722 } | |
3723 | |
4745 | 3724 |
4450 | 3725 status = strdup_withhtml(jabber_lookup_away(gjc, buddy)); |
5236 | 3726 *ap++ = g_strdup_printf("<B>%s:</B> %s%s%s<BR>\n", |
3727 _("Status"), | |
4745 | 3728 jri ? jabber_get_state_string(jri->state) : "", |
3729 jri && status ? ": " : "", status ? status : ""); | |
4450 | 3730 g_free(status); |
2956 | 3731 |
3732 /* | |
3733 * "Description" handled as a special case: get a copy of the | |
3734 * string and HTML-ize. | |
3735 */ | |
3736 if((cdata = xmlnode_get_tag_data(querynode, "DESC")) != NULL) { | |
3737 gchar *tmp = g_strdup_printf("<HR>%s<BR>", cdata); | |
3738 *ap++ = strdup_withhtml(tmp); | |
3739 g_free(tmp); | |
3740 } | |
3741 | |
3742 *ap = NULL; | |
3743 | |
3744 final= g_strjoinv(NULL, str_arr); | |
3745 g_strfreev(str_arr); | |
3746 | |
3747 g_show_info_text(gc, buddy, 2, final, NULL); | |
3748 g_free(buddy); | |
3749 g_free(final); | |
3750 } | |
3751 | |
3752 /* | |
3753 * Used by XML_Parse on parsing CDATA | |
3754 */ | |
3755 static void xmlstr2xmlnode_charData(void *userdata, const char *s, int slen) | |
3756 { | |
3757 xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; | |
3758 | |
3759 if (xmlp->current) | |
3760 xmlnode_insert_cdata(xmlp->current, s, slen); | |
3761 } | |
3762 | |
3763 /* | |
3764 * Used by XML_Parse to start or append to an xmlnode | |
3765 */ | |
3766 static void xmlstr2xmlnode_startElement(void *userdata, const char *name, const char **attribs) | |
3767 { | |
3768 xmlnode x; | |
3769 xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; | |
3770 | |
3771 if (xmlp->current) { | |
3772 /* Append the node to the current one */ | |
3773 x = xmlnode_insert_tag(xmlp->current, name); | |
3774 xmlnode_put_expat_attribs(x, attribs); | |
3775 | |
3776 xmlp->current = x; | |
3777 } else { | |
3778 x = xmlnode_new_tag(name); | |
3779 xmlnode_put_expat_attribs(x, attribs); | |
3780 xmlp->current = x; | |
3781 } | |
3782 } | |
3783 | |
3784 /* | |
3785 * Used by XML_Parse to end an xmlnode | |
3786 */ | |
3787 static void xmlstr2xmlnode_endElement(void *userdata, const char *name) | |
3788 { | |
3789 xmlstr2xmlnode_parser xmlp = (xmlstr2xmlnode_parser) userdata; | |
3790 xmlnode x; | |
3791 | |
3792 if (xmlp->current != NULL && (x = xmlnode_get_parent(xmlp->current)) != NULL) { | |
3793 xmlp->current = x; | |
3794 } | |
3795 } | |
3796 | |
3797 /* | |
3798 * Parse an XML-encoded string into an xmlnode tree | |
3799 * | |
3800 * Caller is responsible for freeing the returned xmlnode | |
3801 */ | |
3802 static xmlnode xmlstr2xmlnode(char *xmlstring) | |
3803 { | |
3804 xmlstr2xmlnode_parser my_parser = g_new(xmlstr2xmlnode_parser_struct, 1); | |
3805 xmlnode x = NULL; | |
3806 | |
3807 my_parser->parser = XML_ParserCreate(NULL); | |
3808 my_parser->current = NULL; | |
3809 | |
3810 XML_SetUserData(my_parser->parser, (void *)my_parser); | |
3811 XML_SetElementHandler(my_parser->parser, xmlstr2xmlnode_startElement, xmlstr2xmlnode_endElement); | |
3812 XML_SetCharacterDataHandler(my_parser->parser, xmlstr2xmlnode_charData); | |
3813 XML_Parse(my_parser->parser, xmlstring, strlen(xmlstring), 0); | |
3814 | |
3815 x = my_parser->current; | |
3816 | |
3817 XML_ParserFree(my_parser->parser); | |
3818 g_free(my_parser); | |
3819 | |
3820 return(x); | |
3821 } | |
3822 | |
3823 /* | |
3824 * Insert a tag node into an xmlnode tree, recursively inserting parent tag | |
3825 * nodes as necessary | |
3826 * | |
3827 * Returns pointer to inserted node | |
3828 * | |
3829 * Note to hackers: this code is designed to be re-entrant (it's recursive--it | |
3830 * calls itself), so don't put any "static"s in here! | |
3831 */ | |
3832 static xmlnode insert_tag_to_parent_tag(xmlnode start, const char *parent_tag, const char *new_tag) | |
3833 { | |
3834 xmlnode x = NULL; | |
3835 | |
3836 /* | |
3837 * If the parent tag wasn't specified, see if we can get it | |
3838 * from the vCard template struct. | |
3839 */ | |
3840 if(parent_tag == NULL) { | |
3841 struct vcard_template *vc_tp = vcard_template_data; | |
3842 | |
3843 while(vc_tp->label != NULL) { | |
3844 if(strcmp(vc_tp->tag, new_tag) == 0) { | |
3845 parent_tag = vc_tp->ptag; | |
3846 break; | |
3847 } | |
3848 ++vc_tp; | |
3849 } | |
3850 } | |
3851 | |
3852 /* | |
3853 * If we have a parent tag... | |
3854 */ | |
3855 if(parent_tag != NULL ) { | |
3856 /* | |
3857 * Try to get the parent node for a tag | |
3858 */ | |
3859 if((x = xmlnode_get_tag(start, parent_tag)) == NULL) { | |
3860 /* | |
3861 * Descend? | |
3862 */ | |
3863 char *grand_parent = strcpy(g_malloc(strlen(parent_tag) + 1), parent_tag); | |
3864 char *parent; | |
3865 | |
3866 if((parent = strrchr(grand_parent, '/')) != NULL) { | |
3867 *(parent++) = '\0'; | |
3868 x = insert_tag_to_parent_tag(start, grand_parent, parent); | |
3869 } else { | |
3870 x = xmlnode_insert_tag(start, grand_parent); | |
3871 } | |
3872 g_free(grand_parent); | |
3873 } else { | |
3874 /* | |
3875 * We found *something* to be the parent node. | |
3876 * Note: may be the "root" node! | |
3877 */ | |
3878 xmlnode y; | |
3879 if((y = xmlnode_get_tag(x, new_tag)) != NULL) { | |
3880 return(y); | |
3881 } | |
3882 } | |
3883 } | |
3884 | |
3885 /* | |
3886 * insert the new tag into its parent node | |
3887 */ | |
3888 return(xmlnode_insert_tag((x == NULL? start : x), new_tag)); | |
3889 } | |
3890 | |
3891 /* | |
3892 * Send vCard info to Jabber server | |
3893 */ | |
5954 | 3894 static void jabber_set_info(GaimConnection *gc, const char *info) |
2956 | 3895 { |
3896 xmlnode x, vc_node; | |
3897 char *id; | |
3898 struct jabber_data *jd = gc->proto_data; | |
3899 gjconn gjc = jd->gjc; | |
5954 | 3900 gchar *info2; |
2956 | 3901 |
3902 x = xmlnode_new_tag("iq"); | |
3311 | 3903 xmlnode_put_attrib(x, "type", "set"); |
2956 | 3904 |
3905 id = gjab_getid(gjc); | |
3770 | 3906 |
2956 | 3907 xmlnode_put_attrib(x, "id", id); |
3908 | |
3909 /* | |
3910 * Send only if there's actually any *information* to send | |
3911 */ | |
5954 | 3912 info2 = g_strdup(info); |
3913 vc_node = xmlstr2xmlnode(info2); | |
4874 | 3914 |
3915 if(vc_node) { | |
3916 if (xmlnode_get_name(vc_node) && | |
3917 !g_ascii_strncasecmp(xmlnode_get_name(vc_node), "vcard", 5)) { | |
3918 xmlnode_insert_tag_node(x, vc_node); | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3919 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
3920 "jabber: vCard packet: %s\n", xmlnode2str(x)); |
4874 | 3921 gjab_send(gjc, x); |
3922 } | |
3923 xmlnode_free(vc_node); | |
2956 | 3924 } |
3925 | |
3926 xmlnode_free(x); | |
5954 | 3927 g_free(info2); |
2956 | 3928 } |
3929 | |
3930 /* | |
3931 * This is the callback from the "ok clicked" for "set vCard" | |
3932 * | |
3933 * Formats GSList data into XML-encoded string and returns a pointer | |
3934 * to said string. | |
3935 * | |
3936 * g_free()'ing the returned string space is the responsibility of | |
3937 * the caller. | |
3938 */ | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3939 static void |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3940 jabber_format_info(GaimConnection *gc, GaimRequestFields *fields) |
2956 | 3941 { |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3942 GaimAccount *account; |
2956 | 3943 xmlnode vc_node; |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3944 GaimRequestField *field; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3945 const char *text; |
2956 | 3946 char *p; |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3947 const struct vcard_template *vc_tp; |
2956 | 3948 struct tag_attr *tag_attr; |
3949 | |
3950 vc_node = xmlnode_new_tag("vCard"); | |
3951 | |
3952 for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) | |
3953 xmlnode_put_attrib(vc_node, tag_attr->attr, tag_attr->value); | |
3954 | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3955 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
|
3956 if (*vc_tp->label == '\0') |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3957 continue; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3958 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3959 field = gaim_request_fields_get_field(fields, vc_tp->tag); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3960 text = gaim_request_field_string_get_value(field); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3961 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3962 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3963 "Setting %s to '%s'\n", vc_tp->tag, text); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3964 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3965 if (text != NULL && *text != '\0') { |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3966 xmlnode xp; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3967 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3968 if ((xp = insert_tag_to_parent_tag(vc_node, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3969 NULL, vc_tp->tag)) != NULL) { |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3970 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3971 xmlnode_insert_cdata(xp, text, -1); |
2956 | 3972 } |
3973 } | |
3974 } | |
3975 | |
3976 p = g_strdup(xmlnode2str(vc_node)); | |
3977 xmlnode_free(vc_node); | |
3978 | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3979 account = gaim_connection_get_account(gc); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3980 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3981 if (account != NULL) { |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3982 gaim_account_set_user_info(account, p); |
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 if (gc != NULL) |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3985 serv_set_info(gc, p); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3986 } |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3987 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3988 g_free(p); |
2956 | 3989 } |
3990 | |
3991 /* | |
3992 * This gets executed by the proto action | |
3993 * | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
3994 * Creates a new GaimRequestFields struct, gets the XML-formatted user_info |
2956 | 3995 * string (if any) into GSLists for the (multi-entry) edit dialog and |
3996 * calls the set_vcard dialog. | |
3997 */ | |
5572 | 3998 static void jabber_setup_set_info(GaimConnection *gc) |
2956 | 3999 { |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4000 GaimRequestFields *fields; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4001 GaimRequestFieldGroup *group; |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4002 GaimRequestField *field; |
2956 | 4003 const struct vcard_template *vc_tp; |
4004 char *user_info; | |
4005 char *cdata; | |
4006 xmlnode x_vc_data = NULL; | |
6294 | 4007 |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4008 fields = gaim_request_fields_new(); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4009 group = gaim_request_field_group_new(NULL); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4010 gaim_request_fields_add_group(fields, group); |
2956 | 4011 |
4012 /* | |
4013 * Get existing, XML-formatted, user info | |
4014 */ | |
6294 | 4015 if((user_info = g_strdup(gaim_account_get_user_info(gc->account))) != NULL) |
2956 | 4016 x_vc_data = xmlstr2xmlnode(user_info); |
6294 | 4017 else |
4018 user_info = g_strdup(""); | |
2956 | 4019 |
4020 /* | |
4021 * Set up GSLists for edit with labels from "template," data from user info | |
4022 */ | |
4023 for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { | |
4024 if((vc_tp->label)[0] == '\0') | |
4025 continue; | |
4026 if(vc_tp->ptag == NULL) { | |
4027 cdata = xmlnode_get_tag_data(x_vc_data, vc_tp->tag); | |
4028 } else { | |
4029 gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); | |
4030 cdata = xmlnode_get_tag_data(x_vc_data, tag); | |
4031 g_free(tag); | |
4032 } | |
4033 if(strcmp(vc_tp->tag, "DESC") == 0) { | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4034 field = gaim_request_field_string_new(vc_tp->tag, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4035 _(vc_tp->label), cdata, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4036 TRUE); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4037 #if 0 |
2956 | 4038 multi_text_list_update(&(b->multi_text_items), |
4039 vc_tp->label, cdata, TRUE); | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4040 #endif |
2956 | 4041 } else { |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4042 field = gaim_request_field_string_new(vc_tp->tag, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4043 _(vc_tp->label), cdata, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4044 FALSE); |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4045 #if 0 |
2956 | 4046 data = multi_entry_list_update(&(b->multi_entry_items), |
4047 vc_tp->label, cdata, TRUE); | |
4048 data->visible = vc_tp->visible; | |
4049 data->editable = vc_tp->editable; | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4050 #endif |
2956 | 4051 } |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4052 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4053 gaim_request_field_group_add_field(group, field); |
2956 | 4054 } |
4055 | |
4056 if(x_vc_data != NULL) { | |
4057 xmlnode_free(x_vc_data); | |
4058 } else { | |
4059 /* | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4060 * 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
|
4061 * 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
|
4062 * 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
|
4063 * 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
|
4064 * manually going to have to search through all fields for the |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4065 * label and update. |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4066 * |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4067 * -- ChipX86 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4068 */ |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4069 #if 0 |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4070 /* |
2956 | 4071 * Early Beta versions had a different user_info storage format--let's |
4072 * see if that works. | |
4073 * | |
4074 * This goes away RSN. | |
4075 */ | |
4076 const char *record_separator = "<BR>"; | |
4077 const char *field_separator = ": "; | |
4078 gchar **str_list, **str_list_ptr, **str_list2; | |
4079 | |
4080 if((str_list = g_strsplit(user_info, record_separator, 0)) != NULL) { | |
4081 for(str_list_ptr = str_list; *str_list_ptr != NULL; ++str_list_ptr) { | |
4082 str_list2 = g_strsplit(*str_list_ptr, field_separator, 2); | |
4083 if(str_list2[0] != NULL && str_list2[1] != NULL) { | |
4084 g_strstrip(str_list2[0]); | |
4085 g_strstrip(str_list2[1]); | |
4086 /* this is ugly--so far */ | |
4087 if(strcmp(str_list2[0], "Description") == 0) { | |
4088 multi_text_list_update(&(b->multi_text_items), | |
4089 str_list2[0], str_list2[1], FALSE); | |
4090 } else { | |
4091 multi_entry_list_update(&(b->multi_entry_items), | |
4092 str_list2[0], str_list2[1], FALSE); | |
4093 } | |
4094 } | |
4095 g_strfreev(str_list2); | |
4096 } | |
4097 g_strfreev(str_list); | |
4098 } | |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4099 #endif |
2956 | 4100 } |
4101 | |
6294 | 4102 g_free(user_info); |
2956 | 4103 |
6339
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4104 gaim_request_fields(gc, _("Edit Jabber vCard"), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4105 _("Edit Jabber vCard"), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4106 _("All items below are optional. Enter only the " |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4107 "information with which you feel comfortable."), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4108 fields, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4109 _("Save"), G_CALLBACK(jabber_format_info), |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4110 _("Cancel"), NULL, |
cc527f9ba197
[gaim-migrate @ 6838]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
4111 gc); |
2956 | 4112 } |
4113 | |
4114 /*---------------------------------------*/ | |
4115 /* End Jabber "set info" (vCard) support */ | |
4116 /*---------------------------------------*/ | |
4117 | |
4118 /*----------------------------------------*/ | |
4119 /* Jabber "user registration" support */ | |
4120 /*----------------------------------------*/ | |
4121 | |
4122 /* | |
4123 * Three of the following four functions duplicate much of what | |
4124 * exists elsewhere: | |
4125 * | |
4126 * jabber_handleregresp() | |
4127 * gjab_reqreg() | |
4128 * jabber_handle_registration_state() | |
4129 * | |
4130 * It may be that an additional flag could be added to one of | |
4131 * the "local" structs and the duplicated code modified to | |
4132 * account for it--thus eliminating the duplication. Then again: | |
4133 * doing it the way it is may be much cleaner. | |
4134 * | |
4135 * TBD: Code to support requesting additional information server | |
4136 * wants at registration--incl. dialog. | |
4137 */ | |
4138 | |
4139 /* | |
4140 * Like jabber_handlepacket(), only different | |
4141 */ | |
4142 static void jabber_handleregresp(gjconn gjc, jpacket p) | |
4143 { | |
4144 if (jpacket_subtype(p) == JPACKET__RESULT) { | |
4145 xmlnode querynode; | |
4146 | |
4147 if((querynode = xmlnode_get_tag(p->x, "query")) != NULL) { | |
4148 char *xmlns; | |
4149 | |
4150 /* we damn well *better* have this! */ | |
4151 if((xmlns = xmlnode_get_attrib(querynode, "xmlns")) != NULL && | |
4152 strcmp(xmlns, NS_REGISTER) == 0) { | |
4153 | |
4154 char *tag; | |
4155 xmlnode child = xmlnode_get_firstchild(querynode); | |
4156 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4157 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4158 "got registration requirments response!\n"); |
2956 | 4159 |
4160 while(child != NULL) { | |
4161 if((tag = xmlnode_get_name(child)) != NULL) { | |
4162 char *data; | |
4163 | |
4164 fprintf(stderr, "DBG: got node: \"%s\"\n", tag); | |
4165 fflush(stderr); | |
4166 | |
4167 if((data = xmlnode_get_data(child)) != NULL) { | |
4168 fprintf(stderr, "DBG: got data: \"%s\"\n", data); | |
4169 fflush(stderr); | |
4170 } | |
4171 } | |
4172 child = xmlnode_get_nextsibling(child); | |
4173 } | |
4174 } | |
4175 } else { | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4176 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4177 "registration successful!\n"); |
2956 | 4178 |
5572 | 4179 gaim_connection_notice(GJ_GC(gjc), _("Server Registration successful!")); |
5578
847ad796326d
[gaim-migrate @ 5982]
Christian Hammond <chipx86@chipx86.com>
parents:
5572
diff
changeset
|
4180 gaim_connection_destroy(GJ_GC(gjc)); |
2956 | 4181 } |
4182 | |
4183 } else { | |
4184 xmlnode xerr; | |
4185 char *errmsg = NULL; | |
4186 int errcode = 0; | |
4187 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4188 gaim_debug(GAIM_DEBUG_ERROR, "jabber", "registration failed\n"); |
2956 | 4189 xerr = xmlnode_get_tag(p->x, "error"); |
4190 if (xerr) { | |
4191 char msg[BUF_LONG]; | |
4192 errmsg = xmlnode_get_data(xerr); | |
4193 if (xmlnode_get_attrib(xerr, "code")) { | |
4194 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
6321 | 4195 g_snprintf(msg, sizeof(msg), _("Error %d: %s"), errcode, errmsg); |
2956 | 4196 } else |
4197 g_snprintf(msg, sizeof(msg), "%s", errmsg); | |
5572 | 4198 gaim_connection_error(GJ_GC(gjc), msg); |
2956 | 4199 } else { |
5572 | 4200 gaim_connection_error(GJ_GC(gjc), _("Unknown registration error")); |
2956 | 4201 } |
4202 } | |
4203 } | |
4204 | |
4205 /* | |
4206 * Like gjab_reqauth(), only different | |
4207 */ | |
4208 static void gjab_reqreg(gjconn gjc) | |
4209 { | |
4210 xmlnode x, y, z; | |
4211 char *user; | |
4212 | |
4213 if (!gjc) | |
4214 return; | |
4215 | |
4216 x = jutil_iqnew(JPACKET__SET, NS_REGISTER); | |
4217 y = xmlnode_get_tag(x, "query"); | |
4218 | |
4219 user = gjc->user->user; | |
4220 | |
4221 if (user) { | |
4222 z = xmlnode_insert_tag(y, "username"); | |
4223 xmlnode_insert_cdata(z, user, -1); | |
4224 } | |
4225 z = xmlnode_insert_tag(y, "password"); | |
4226 xmlnode_insert_cdata(z, gjc->pass, -1); | |
4227 | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4228 gaim_debug(GAIM_DEBUG_MISC, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4229 "jabber: registration packet: %s\n", xmlnode2str(x)); |
2956 | 4230 gjab_send(gjc, x); |
4231 xmlnode_free(x); | |
4232 } | |
4233 | |
4234 /* | |
4235 * Like jabber_handlestate(), only different | |
4236 */ | |
4237 static void jabber_handle_registration_state(gjconn gjc, int state) | |
4238 { | |
4239 switch (state) { | |
4240 case JCONN_STATE_OFF: | |
3074 | 4241 if(gjc->was_connected) { |
5572 | 4242 gaim_connection_error(GJ_GC(gjc), _("Connection lost")); |
3074 | 4243 } else { |
5572 | 4244 gaim_connection_error(GJ_GC(gjc), _("Unable to connect")); |
3074 | 4245 } |
2956 | 4246 break; |
4247 case JCONN_STATE_CONNECTED: | |
3074 | 4248 gjc->was_connected = 1; |
2956 | 4249 /* |
4250 * TBD? | |
6106 | 4251 gaim_connection_update_progress(GJ_GC(gjc), _("Connected"), |
4252 2, JABBER_CONNECT_STEPS); | |
2956 | 4253 */ |
4254 break; | |
4255 case JCONN_STATE_ON: | |
4256 /* | |
4257 * TBD? | |
6106 | 4258 gaim_connection_update_progress(GJ_GC(gjc), _("Authenticating"), |
4259 _("Requesting Authentication Method"), 3, | |
4260 JABBER_CONNECT_STEPS); | |
2956 | 4261 */ |
4262 gjab_reqreg(gjc); | |
4263 /* | |
4264 * TBD: A work-in-progress | |
4265 gjab_reqregreqs(gjc); | |
4266 */ | |
4267 break; | |
4268 default: | |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4269 gaim_debug(GAIM_DEBUG_MISC, "jabber", "state change: %d\n", state); |
2956 | 4270 } |
4271 return; | |
4272 } | |
4273 | |
4274 /* | |
4275 * Like jabber_login(), only different | |
4276 */ | |
5572 | 4277 void jabber_register_user(GaimAccount *account) |
2956 | 4278 { |
6581 | 4279 GaimConnection *gc = gaim_account_get_connection(account); |
2956 | 4280 struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); |
4917 | 4281 char *loginname = create_valid_jid(account->username, DEFAULT_SERVER, "Gaim"); |
2956 | 4282 |
4283 /* | |
4284 * These do nothing during registration | |
4285 */ | |
3311 | 4286 jd->buddies = NULL; |
2956 | 4287 jd->chats = NULL; |
4288 | |
4491 | 4289 if ((jd->gjc = gjab_new(loginname, account->password, gc)) == NULL) { |
2956 | 4290 g_free(loginname); |
5223
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4291 gaim_debug(GAIM_DEBUG_ERROR, "jabber", |
e2e5bc3ca705
[gaim-migrate @ 5593]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
4292 "unable to connect (jab_new failed)\n"); |
5572 | 4293 gaim_connection_error(gc, _("Unable to connect")); |
2956 | 4294 } else { |
4295 gjab_state_handler(jd->gjc, jabber_handle_registration_state); | |
4296 gjab_packet_handler(jd->gjc, jabber_handleregresp); | |
4297 jd->gjc->queries = NULL; | |
4298 gjab_start(jd->gjc); | |
4299 } | |
4300 | |
4301 g_free(loginname); | |
4302 } | |
4303 | |
4304 /*----------------------------------------*/ | |
4305 /* End Jabber "user registration" support */ | |
4306 /*----------------------------------------*/ | |
4307 | |
5572 | 4308 static GList *jabber_actions(GaimConnection *gc) |
2956 | 4309 { |
4310 GList *m = NULL; | |
4333 | 4311 struct proto_actions_menu *pam; |
4312 | |
4313 pam = g_new0(struct proto_actions_menu, 1); | |
4314 pam->label = _("Set User Info"); | |
4315 pam->callback = jabber_setup_set_info; | |
4316 pam->gc = gc; | |
4317 m = g_list_append(m, pam); | |
4318 | |
2956 | 4319 /* |
4333 | 4320 pam = g_new0(struct proto_actions_menu, 1); |
4321 pam->label = _("Set Dir Info"); | |
4322 pam->callback = show_set_dir; | |
4323 pam->gc = gc; | |
4324 m = g_list_append(m, pam); | |
3257 | 4325 */ |
4333 | 4326 |
4327 pam = g_new0(struct proto_actions_menu, 1); | |
4328 pam->label = _("Change Password"); | |
4329 pam->callback = show_change_passwd; | |
4330 pam->gc = gc; | |
4331 m = g_list_append(m, pam); | |
2956 | 4332 |
4333 return m; | |
4334 } | |
4335 | |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4336 static GaimPluginProtocolInfo prpl_info = |
2086 | 4337 { |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4338 GAIM_PROTO_JABBER, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4339 OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_CHAT_TOPIC, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4340 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4341 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4342 jabber_list_icon, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4343 jabber_list_emblems, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4344 jabber_status_text, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4345 jabber_tooltip_text, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4346 jabber_away_states, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4347 jabber_actions, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4348 jabber_buddy_menu, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4349 jabber_chat_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4350 jabber_login, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4351 jabber_close, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4352 jabber_send_im, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4353 jabber_set_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4354 jabber_send_typing, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4355 jabber_get_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4356 jabber_set_away, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4357 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4358 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4359 NULL, |
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_set_idle, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4362 jabber_change_passwd, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4363 jabber_add_buddy, |
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 jabber_remove_buddy, |
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 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4370 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4371 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4372 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4373 jabber_join_chat, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4374 jabber_chat_invite, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4375 jabber_chat_leave, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4376 jabber_chat_whisper, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4377 jabber_chat_send, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4378 jabber_keepalive, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4379 jabber_register_user, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4380 jabber_get_cb_info, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4381 jabber_get_cb_away_msg, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4382 jabber_alias_buddy, |
5957 | 4383 jabber_group_change, |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4384 jabber_rename_group, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4385 NULL, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4386 jabber_convo_closed, |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4387 jabber_normalize |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4388 }; |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4389 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4390 static GaimPluginInfo info = |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4391 { |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4392 2, /**< api_version */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4393 GAIM_PLUGIN_PROTOCOL, /**< type */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4394 NULL, /**< ui_requirement */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4395 0, /**< flags */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4396 NULL, /**< dependencies */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4397 GAIM_PRIORITY_DEFAULT, /**< priority */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4398 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4399 "prpl-jabber", /**< id */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4400 "Jabber", /**< name */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4401 VERSION, /**< version */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4402 /** summary */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4403 N_("Jabber Protocol Plugin"), |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4404 /** description */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4405 N_("Jabber Protocol Plugin"), |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4406 NULL, /**< author */ |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6357
diff
changeset
|
4407 GAIM_WEBSITE, /**< homepage */ |
5205
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, /**< load */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4410 NULL, /**< unload */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4411 NULL, /**< destroy */ |
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 NULL, /**< ui_info */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4414 &prpl_info /**< extra_info */ |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4415 }; |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4416 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4417 static void |
5920
7d385de2f9cd
[gaim-migrate @ 6360]
Christian Hammond <chipx86@chipx86.com>
parents:
5894
diff
changeset
|
4418 init_plugin(GaimPlugin *plugin) |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4419 { |
5638
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4420 GaimAccountUserSplit *split; |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4421 GaimAccountOption *option; |
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 /* Splits */ |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4424 split = gaim_account_user_split_new(_("Server"), "jabber.org", '@'); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4425 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
|
4426 |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4427 split = gaim_account_user_split_new(_("Resource"), "Gaim", '/'); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4428 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
|
4429 |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4430 /* Account Options */ |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4431 option = gaim_account_option_int_new(_("Port"), "port", DEFAULT_PORT); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4432 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4433 option); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4434 |
5685
43ea75092684
[gaim-migrate @ 6106]
Christian Hammond <chipx86@chipx86.com>
parents:
5681
diff
changeset
|
4435 option = gaim_account_option_string_new(_("Connect server"), |
5638
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4436 "connect_server", NULL); |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4437 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, |
0bdfa28c678e
[gaim-migrate @ 6047]
Christian Hammond <chipx86@chipx86.com>
parents:
5613
diff
changeset
|
4438 option); |
5205
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4439 |
fefad67de2c7
[gaim-migrate @ 5573]
Christian Hammond <chipx86@chipx86.com>
parents:
5174
diff
changeset
|
4440 my_protocol = plugin; |
2086 | 4441 } |
4442 | |
5920
7d385de2f9cd
[gaim-migrate @ 6360]
Christian Hammond <chipx86@chipx86.com>
parents:
5894
diff
changeset
|
4443 GAIM_INIT_PLUGIN(jabber, init_plugin, info); |