Mercurial > pidgin
annotate src/protocols/jabber/jabber.c @ 2475:ba7ee4c1908c
[gaim-migrate @ 2488]
BMiller's fixes so gg compiles on solaris
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Wed, 10 Oct 2001 20:03:17 +0000 |
| parents | 569ae9f2bb89 |
| children | 227cc42ffa6e |
| 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 * | |
| 13 * This program is distributed in the hope that it will be useful, | |
| 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 * GNU General Public License for more details. | |
| 17 * | |
| 18 * You should have received a copy of the GNU General Public License | |
| 19 * along with this program; if not, write to the Free Software | |
| 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 21 * | |
| 22 */ | |
| 23 | |
| 24 #ifdef HAVE_CONFIG_H | |
| 25 #include "config.h" | |
| 26 #endif | |
| 27 | |
| 28 | |
| 29 #include <netdb.h> | |
| 30 #include <unistd.h> | |
| 31 #include <errno.h> | |
| 32 #include <netinet/in.h> | |
| 33 #include <arpa/inet.h> | |
| 34 #include <string.h> | |
| 35 #include <stdlib.h> | |
| 36 #include <stdio.h> | |
| 37 #include <time.h> | |
| 38 #include <sys/socket.h> | |
| 39 #include <sys/utsname.h> | |
| 40 #include <sys/stat.h> | |
| 41 #include "multi.h" | |
| 42 #include "prpl.h" | |
| 43 #include "gaim.h" | |
|
2232
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
44 #ifdef MAX |
|
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
45 #undef MAX |
|
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
46 #endif |
|
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
47 #ifdef MIN |
|
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
48 #undef MIN |
|
14e8978f86bb
[gaim-migrate @ 2242]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2231
diff
changeset
|
49 #endif |
| 2086 | 50 #include "jabber.h" |
| 51 #include "proxy.h" | |
| 52 | |
| 53 #include "pixmaps/available.xpm" | |
| 54 #include "pixmaps/available-away.xpm" | |
| 55 #include "pixmaps/available-chat.xpm" | |
| 56 #include "pixmaps/available-xa.xpm" | |
| 57 #include "pixmaps/available-dnd.xpm" | |
| 58 | |
| 59 /* The priv member of gjconn's is a gaim_connection for now. */ | |
| 60 #define GJ_GC(x) ((struct gaim_connection *)(x)->priv) | |
| 61 | |
| 62 #define IQID_AUTH "__AUTH__" | |
| 63 | |
| 64 #define IQ_NONE -1 | |
| 65 #define IQ_AUTH 0 | |
| 66 #define IQ_ROSTER 1 | |
| 67 | |
| 68 #define UC_AWAY 0x38 | |
| 69 #define UC_CHAT 0x48 | |
| 70 #define UC_XA 0x98 | |
| 71 #define UC_DND 0x118 | |
| 72 | |
| 73 #define DEFAULT_SERVER "jabber.org" | |
| 74 #define DEFAULT_GROUPCHAT "conference.jabber.org" | |
| 75 #define DEFAULT_PORT 5222 | |
| 76 | |
| 77 #define USEROPT_PORT 0 | |
| 78 | |
| 79 typedef struct gjconn_struct { | |
| 80 /* Core structure */ | |
| 81 pool p; /* Memory allocation pool */ | |
| 82 int state; /* Connection state flag */ | |
| 83 int fd; /* Connection file descriptor */ | |
| 84 jid user; /* User info */ | |
| 85 char *pass; /* User passwd */ | |
| 86 | |
| 87 /* Stream stuff */ | |
| 88 int id; /* id counter for jab_getid() function */ | |
| 89 char idbuf[9]; /* temporary storage for jab_getid() */ | |
| 90 char *sid; /* stream id from server, for digest auth */ | |
| 91 XML_Parser parser; /* Parser instance */ | |
| 92 xmlnode current; /* Current node in parsing instance.. */ | |
| 93 | |
| 94 /* Event callback ptrs */ | |
| 95 void (*on_state)(struct gjconn_struct *j, int state); | |
| 96 void (*on_packet)(struct gjconn_struct *j, jpacket p); | |
| 97 | |
| 98 void *priv; | |
| 99 | |
| 100 } *gjconn, gjconn_struct; | |
| 101 | |
| 102 typedef void (*gjconn_state_h)(gjconn j, int state); | |
| 103 typedef void (*gjconn_packet_h)(gjconn j, jpacket p); | |
| 104 | |
| 105 static gjconn gjab_new(char *user, char *pass, void *priv); | |
| 106 static void gjab_delete(gjconn j); | |
| 107 static void gjab_state_handler(gjconn j, gjconn_state_h h); | |
| 108 static void gjab_packet_handler(gjconn j, gjconn_packet_h h); | |
| 109 static void gjab_start(gjconn j); | |
| 110 static void gjab_stop(gjconn j); | |
| 111 /* | |
| 112 static int gjab_getfd(gjconn j); | |
| 113 static jid gjab_getjid(gjconn j); | |
| 114 static char *gjab_getsid(gjconn j); | |
| 115 */ | |
| 116 static char *gjab_getid(gjconn j); | |
| 117 static void gjab_send(gjconn j, xmlnode x); | |
| 118 static void gjab_send_raw(gjconn j, const char *str); | |
| 119 static void gjab_recv(gjconn j); | |
| 120 static void gjab_auth(gjconn j); | |
| 121 | |
| 122 struct jabber_data { | |
| 123 gjconn jc; | |
| 124 gboolean did_import; | |
| 125 GSList *pending_chats; | |
| 126 GSList *existing_chats; | |
| 127 GHashTable *hash; | |
| 128 time_t idle; | |
| 129 }; | |
| 130 | |
| 131 struct jabber_chat { | |
| 132 jid Jid; | |
| 133 struct gaim_connection *gc; | |
| 134 struct conversation *b; | |
| 135 int id; | |
| 136 }; | |
| 137 | |
| 138 static char *jabber_name() | |
| 139 { | |
| 140 return "Jabber"; | |
| 141 } | |
| 142 | |
| 143 #define STATE_EVT(arg) if(j->on_state) { (j->on_state)(j, (arg) ); } | |
| 144 | |
| 145 static char *create_valid_jid(const char *given, char *server, char *resource) | |
| 146 { | |
| 147 char *valid; | |
| 148 | |
| 149 if (!strchr(given, '@')) | |
| 150 valid = g_strdup_printf("%s@%s/%s", given, server, resource); | |
| 151 else if (!strchr(strchr(given, '@'), '/')) | |
| 152 valid = g_strdup_printf("%s/%s", given, resource); | |
| 153 else | |
| 154 valid = g_strdup(given); | |
| 155 | |
| 156 return valid; | |
| 157 } | |
| 158 | |
| 159 static gjconn gjab_new(char *user, char *pass, void *priv) | |
| 160 { | |
| 161 pool p; | |
| 162 gjconn j; | |
| 163 | |
| 164 if (!user) | |
| 165 return (NULL); | |
| 166 | |
| 167 p = pool_new(); | |
| 168 if (!p) | |
| 169 return (NULL); | |
| 170 j = pmalloc_x(p, sizeof(gjconn_struct), 0); | |
| 171 if (!j) | |
| 172 return (NULL); | |
| 173 j->p = p; | |
| 174 | |
| 175 j->user = jid_new(p, user); | |
| 176 j->pass = pstrdup(p, pass); | |
| 177 | |
| 178 j->state = JCONN_STATE_OFF; | |
| 179 j->id = 1; | |
| 180 j->fd = -1; | |
| 181 | |
| 182 j->priv = priv; | |
| 183 | |
| 184 return j; | |
| 185 } | |
| 186 | |
| 187 static void gjab_delete(gjconn j) | |
| 188 { | |
| 189 if (!j) | |
| 190 return; | |
| 191 | |
| 192 gjab_stop(j); | |
| 193 pool_free(j->p); | |
| 194 } | |
| 195 | |
| 196 static void gjab_state_handler(gjconn j, gjconn_state_h h) | |
| 197 { | |
| 198 if (!j) | |
| 199 return; | |
| 200 | |
| 201 j->on_state = h; | |
| 202 } | |
| 203 | |
| 204 static void gjab_packet_handler(gjconn j, gjconn_packet_h h) | |
| 205 { | |
| 206 if (!j) | |
| 207 return; | |
| 208 | |
| 209 j->on_packet = h; | |
| 210 } | |
| 211 | |
| 212 static void gjab_stop(gjconn j) | |
| 213 { | |
| 214 if (!j || j->state == JCONN_STATE_OFF) | |
| 215 return; | |
| 216 | |
| 217 j->state = JCONN_STATE_OFF; | |
| 218 gjab_send_raw(j, "</stream:stream>"); | |
| 219 close(j->fd); | |
| 220 j->fd = -1; | |
| 221 XML_ParserFree(j->parser); | |
| 222 j->parser = NULL; | |
| 223 } | |
| 224 | |
| 225 /* | |
| 226 static int gjab_getfd(gjconn j) | |
| 227 { | |
| 228 if (j) | |
| 229 return j->fd; | |
| 230 else | |
| 231 return -1; | |
| 232 } | |
| 233 | |
| 234 static jid gjab_getjid(gjconn j) | |
| 235 { | |
| 236 if (j) | |
| 237 return (j->user); | |
| 238 else | |
| 239 return NULL; | |
| 240 } | |
| 241 | |
| 242 static char *gjab_getsid(gjconn j) | |
| 243 { | |
| 244 if (j) | |
| 245 return (j->sid); | |
| 246 else | |
| 247 return NULL; | |
| 248 } | |
| 249 */ | |
| 250 | |
| 251 static char *gjab_getid(gjconn j) | |
| 252 { | |
| 253 snprintf(j->idbuf, 8, "%d", j->id++); | |
| 254 return &j->idbuf[0]; | |
| 255 } | |
| 256 | |
| 257 static void gjab_send(gjconn j, xmlnode x) | |
| 258 { | |
| 259 if (j && j->state != JCONN_STATE_OFF) { | |
| 260 char *buf = xmlnode2str(x); | |
| 261 if (buf) | |
| 262 write(j->fd, buf, strlen(buf)); | |
| 263 debug_printf("gjab_send: %s\n", buf); | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 static void gjab_send_raw(gjconn j, const char *str) | |
| 268 { | |
| 269 if (j && j->state != JCONN_STATE_OFF) { | |
| 270 write(j->fd, str, strlen(str)); | |
| 271 debug_printf("gjab_send_raw: %s\n", str); | |
| 272 } | |
| 273 } | |
| 274 | |
| 275 static void gjab_reqroster(gjconn j) | |
| 276 { | |
| 277 xmlnode x; | |
| 278 | |
| 279 x = jutil_iqnew(JPACKET__GET, NS_ROSTER); | |
| 280 xmlnode_put_attrib(x, "id", gjab_getid(j)); | |
| 281 | |
| 282 gjab_send(j, x); | |
| 283 xmlnode_free(x); | |
| 284 } | |
| 285 | |
| 286 static void gjab_auth(gjconn j) | |
| 287 { | |
| 288 xmlnode x, y, z; | |
| 289 char *hash, *user; | |
| 290 | |
| 291 if (!j) | |
| 292 return; | |
| 293 | |
| 294 x = jutil_iqnew(JPACKET__SET, NS_AUTH); | |
| 295 xmlnode_put_attrib(x, "id", IQID_AUTH); | |
| 296 y = xmlnode_get_tag(x, "query"); | |
| 297 | |
| 298 user = j->user->user; | |
| 299 | |
| 300 if (user) { | |
| 301 z = xmlnode_insert_tag(y, "username"); | |
| 302 xmlnode_insert_cdata(z, user, -1); | |
| 303 } | |
| 304 | |
| 305 z = xmlnode_insert_tag(y, "resource"); | |
| 306 xmlnode_insert_cdata(z, j->user->resource, -1); | |
| 307 | |
| 308 if (j->sid) { | |
| 309 z = xmlnode_insert_tag(y, "digest"); | |
| 310 hash = pmalloc(x->p, strlen(j->sid) + strlen(j->pass) + 1); | |
| 311 strcpy(hash, j->sid); | |
| 312 strcat(hash, j->pass); | |
| 313 hash = shahash(hash); | |
| 314 xmlnode_insert_cdata(z, hash, 40); | |
| 315 } else { | |
| 316 z = xmlnode_insert_tag(y, "password"); | |
| 317 xmlnode_insert_cdata(z, j->pass, -1); | |
| 318 } | |
| 319 | |
| 320 gjab_send(j, x); | |
| 321 xmlnode_free(x); | |
| 322 | |
| 323 return; | |
| 324 } | |
| 325 | |
| 326 static void gjab_recv(gjconn j) | |
| 327 { | |
| 328 static char buf[4096]; | |
| 329 int len; | |
| 330 | |
| 331 if (!j || j->state == JCONN_STATE_OFF) | |
| 332 return; | |
| 333 | |
| 334 if ((len = read(j->fd, buf, sizeof(buf) - 1))) { | |
| 335 buf[len] = '\0'; | |
| 336 debug_printf("input (len %d): %s\n", len, buf); | |
| 337 XML_Parse(j->parser, buf, len, 0); | |
| 338 } else if (len <= 0) { | |
| 339 STATE_EVT(JCONN_STATE_OFF) | |
| 340 } | |
| 341 } | |
| 342 | |
| 343 static void startElement(void *userdata, const char *name, const char **attribs) | |
| 344 { | |
| 345 xmlnode x; | |
| 346 gjconn j = (gjconn) userdata; | |
| 347 | |
| 348 if (j->current) { | |
| 349 /* Append the node to the current one */ | |
| 350 x = xmlnode_insert_tag(j->current, name); | |
| 351 xmlnode_put_expat_attribs(x, attribs); | |
| 352 | |
| 353 j->current = x; | |
| 354 } else { | |
| 355 x = xmlnode_new_tag(name); | |
| 356 xmlnode_put_expat_attribs(x, attribs); | |
| 357 if (strcmp(name, "stream:stream") == 0) { | |
| 358 /* special case: name == stream:stream */ | |
| 359 /* id attrib of stream is stored for digest auth */ | |
| 360 j->sid = xmlnode_get_attrib(x, "id"); | |
| 361 /* STATE_EVT(JCONN_STATE_AUTH) */ | |
| 362 } else { | |
| 363 j->current = x; | |
| 364 } | |
| 365 } | |
| 366 } | |
| 367 | |
| 368 static void endElement(void *userdata, const char *name) | |
| 369 { | |
| 370 gjconn j = (gjconn) userdata; | |
| 371 xmlnode x; | |
| 372 jpacket p; | |
| 373 | |
| 374 if (j->current == NULL) { | |
| 375 /* we got </stream:stream> */ | |
| 376 STATE_EVT(JCONN_STATE_OFF) | |
| 377 return; | |
| 378 } | |
| 379 | |
| 380 x = xmlnode_get_parent(j->current); | |
| 381 | |
| 382 if (!x) { | |
| 383 /* it is time to fire the event */ | |
| 384 p = jpacket_new(j->current); | |
| 385 | |
| 386 if (j->on_packet) | |
| 387 (j->on_packet) (j, p); | |
| 388 else | |
| 389 xmlnode_free(j->current); | |
| 390 } | |
| 391 | |
| 392 j->current = x; | |
| 393 } | |
| 394 | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
395 static void jabber_callback(gpointer data, gint source, GaimInputCondition condition) |
| 2086 | 396 { |
| 397 struct gaim_connection *gc = (struct gaim_connection *)data; | |
| 398 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; | |
| 399 | |
| 400 gjab_recv(jd->jc); | |
| 401 } | |
| 402 | |
| 403 static void charData(void *userdata, const char *s, int slen) | |
| 404 { | |
| 405 gjconn j = (gjconn) userdata; | |
| 406 | |
| 407 if (j->current) | |
| 408 xmlnode_insert_cdata(j->current, s, slen); | |
| 409 } | |
| 410 | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
411 static void gjab_connected(gpointer data, gint source, GaimInputCondition cond) |
| 2086 | 412 { |
| 413 xmlnode x; | |
| 414 char *t, *t2; | |
| 415 struct gaim_connection *gc = data; | |
| 416 struct jabber_data *jd; | |
| 417 gjconn j; | |
| 418 | |
| 419 if (!g_slist_find(connections, gc)) { | |
| 420 close(source); | |
| 421 return; | |
| 422 } | |
| 423 | |
| 424 jd = gc->proto_data; | |
| 425 j = jd->jc; | |
| 426 | |
|
2300
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
427 if (j->fd != source) |
|
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
428 j->fd = source; |
|
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
429 |
| 2086 | 430 if (source == -1) { |
| 431 STATE_EVT(JCONN_STATE_OFF) | |
| 432 return; | |
| 433 } | |
| 434 | |
| 435 j->state = JCONN_STATE_CONNECTED; | |
| 436 STATE_EVT(JCONN_STATE_CONNECTED) | |
| 437 | |
| 438 /* start stream */ | |
| 439 x = jutil_header(NS_CLIENT, j->user->server); | |
| 440 t = xmlnode2str(x); | |
| 441 /* this is ugly, we can create the string here instead of jutil_header */ | |
| 442 /* what do you think about it? -madcat */ | |
| 443 t2 = strstr(t, "/>"); | |
| 444 *t2++ = '>'; | |
| 445 *t2 = '\0'; | |
| 446 gjab_send_raw(j, "<?xml version='1.0'?>"); | |
| 447 gjab_send_raw(j, t); | |
| 448 xmlnode_free(x); | |
| 449 | |
| 450 j->state = JCONN_STATE_ON; | |
| 451 STATE_EVT(JCONN_STATE_ON); | |
| 452 | |
| 453 gc = GJ_GC(j); | |
|
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
454 gc->inpa = gaim_input_add(j->fd, GAIM_INPUT_READ, jabber_callback, gc); |
| 2086 | 455 } |
| 456 | |
| 457 static void gjab_start(gjconn j) | |
| 458 { | |
| 459 struct aim_user *user; | |
| 460 int port; | |
| 461 | |
| 462 if (!j || j->state != JCONN_STATE_OFF) | |
| 463 return; | |
| 464 | |
| 465 user = GJ_GC(j)->user; | |
| 466 port = user->proto_opt[USEROPT_PORT][0] ? atoi(user->proto_opt[USEROPT_PORT]) : DEFAULT_PORT; | |
| 467 | |
| 468 j->parser = XML_ParserCreate(NULL); | |
| 469 XML_SetUserData(j->parser, (void *)j); | |
| 470 XML_SetElementHandler(j->parser, startElement, endElement); | |
| 471 XML_SetCharacterDataHandler(j->parser, charData); | |
| 472 | |
| 473 j->fd = proxy_connect(j->user->server, port, gjab_connected, GJ_GC(j)); | |
| 474 if (!user->gc || (j->fd < 0)) { | |
| 475 STATE_EVT(JCONN_STATE_OFF) | |
| 476 return; | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 static struct conversation *find_chat(struct gaim_connection *gc, char *name) | |
| 481 { | |
| 482 GSList *bcs = gc->buddy_chats; | |
| 483 struct conversation *b = NULL; | |
| 484 char *chat = g_strdup(normalize(name)); | |
| 485 | |
| 486 while (bcs) { | |
| 487 b = bcs->data; | |
| 488 if (!strcasecmp(normalize(b->name), chat)) | |
| 489 break; | |
| 490 b = NULL; | |
| 491 bcs = bcs->next; | |
| 492 } | |
| 493 | |
| 494 g_free(chat); | |
| 495 return b; | |
| 496 } | |
| 497 | |
| 498 static struct jabber_chat *find_existing_chat(struct gaim_connection *gc, jid chat) | |
| 499 { | |
| 500 GSList *bcs = ((struct jabber_data *)gc->proto_data)->existing_chats; | |
| 501 struct jabber_chat *jc = NULL; | |
| 502 | |
| 503 while (bcs) { | |
| 504 jc = bcs->data; | |
| 505 if (!jid_cmpx(chat, jc->Jid, JID_USER | JID_SERVER)) | |
| 506 break; | |
| 507 jc = NULL; | |
| 508 bcs = bcs->next; | |
| 509 } | |
| 510 | |
| 511 return jc; | |
| 512 } | |
| 513 | |
| 514 static struct jabber_chat *find_pending_chat(struct gaim_connection *gc, jid chat) | |
| 515 { | |
| 516 GSList *bcs = ((struct jabber_data *)gc->proto_data)->pending_chats; | |
| 517 struct jabber_chat *jc = NULL; | |
| 518 | |
| 519 while (bcs) { | |
| 520 jc = bcs->data; | |
| 521 if (!jid_cmpx(chat, jc->Jid, JID_USER | JID_SERVER)) | |
| 522 break; | |
| 523 jc = NULL; | |
| 524 bcs = bcs->next; | |
| 525 } | |
| 526 | |
| 527 return jc; | |
| 528 } | |
| 529 | |
| 530 static gboolean find_chat_buddy(struct conversation *b, char *name) | |
| 531 { | |
| 532 GList *m = b->in_room; | |
| 533 | |
| 534 while (m) { | |
| 535 if (!strcmp(m->data, name)) | |
| 536 return TRUE; | |
| 537 m = m->next; | |
| 538 } | |
| 539 | |
| 540 return FALSE; | |
| 541 } | |
| 542 | |
| 543 static void jabber_handlemessage(gjconn j, jpacket p) | |
| 544 { | |
| 545 xmlnode y, xmlns, subj; | |
| 546 | |
| 547 char *from = NULL, *msg = NULL, *type = NULL, *topic = NULL; | |
| 548 char m[BUF_LONG * 2]; | |
| 549 | |
| 550 type = xmlnode_get_attrib(p->x, "type"); | |
| 551 | |
| 552 if (!type || !strcasecmp(type, "normal") || !strcasecmp(type, "chat")) { | |
| 553 | |
| 554 /* XXX namespaces could be handled better. (mid) */ | |
| 555 if ((xmlns = xmlnode_get_tag(p->x, "x"))) | |
| 556 type = xmlnode_get_attrib(xmlns, "xmlns"); | |
| 557 | |
| 558 from = jid_full(p->from); | |
| 559 /* | |
| 560 if ((y = xmlnode_get_tag(p->x, "html"))) { | |
| 561 msg = xmlnode_get_data(y); | |
| 562 } else | |
| 563 */ | |
| 564 if ((y = xmlnode_get_tag(p->x, "body"))) { | |
| 565 msg = xmlnode_get_data(y); | |
| 566 } | |
| 567 | |
| 568 msg = utf8_to_str(msg); | |
| 569 | |
| 570 if (!from) | |
| 571 return; | |
| 572 | |
| 573 if (type && !strcasecmp(type, "jabber:x:conference")) { | |
| 574 char *room; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
575 GList *m = NULL; |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
576 char **data; |
| 2086 | 577 |
| 578 room = xmlnode_get_attrib(xmlns, "jid"); | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
579 data = g_strsplit(room, "@", 2); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
580 m = g_list_append(m, g_strdup(data[0])); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
581 m = g_list_append(m, g_strdup(data[1])); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
582 m = g_list_append(m, g_strdup(j->user->user)); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
583 g_strfreev(data); |
| 2086 | 584 |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
585 serv_got_chat_invite(GJ_GC(j), room, from, msg, m); |
| 2086 | 586 } else if (msg) { /* whisper */ |
| 587 struct jabber_chat *jc; | |
| 588 g_snprintf(m, sizeof(m), "%s", msg); | |
| 589 if (((jc = find_existing_chat(GJ_GC(j), p->from)) != NULL) && jc->b) | |
| 590 serv_got_chat_in(GJ_GC(j), jc->b->id, p->from->resource, 1, m, time(NULL)); | |
| 591 else { | |
|
2278
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
592 int flags = 0; |
|
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
593 if (xmlnode_get_tag(p->x, "gaim")) |
|
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
594 flags = IM_FLAG_GAIMUSER; |
| 2086 | 595 if (find_conversation(jid_full(p->from))) |
|
2278
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
596 serv_got_im(GJ_GC(j), jid_full(p->from), m, flags, time(NULL)); |
| 2086 | 597 else { |
| 598 from = g_strdup_printf("%s@%s", p->from->user, p->from->server); | |
|
2278
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
599 serv_got_im(GJ_GC(j), from, m, flags, time(NULL)); |
| 2086 | 600 g_free(from); |
| 601 } | |
| 602 } | |
| 603 } | |
| 604 | |
| 605 if (msg) | |
| 606 g_free(msg); | |
| 607 | |
| 608 } else if (!strcasecmp(type, "error")) { | |
| 609 if ((y = xmlnode_get_tag(p->x, "error"))) { | |
| 610 type = xmlnode_get_attrib(y, "code"); | |
| 611 msg = xmlnode_get_data(y); | |
| 612 } | |
| 613 | |
| 614 if (msg) { | |
| 615 from = g_strdup_printf("Error %s", type ? type : ""); | |
| 616 do_error_dialog(msg, from); | |
| 617 g_free(from); | |
| 618 } | |
| 619 } else if (!strcasecmp(type, "groupchat")) { | |
| 620 struct jabber_chat *jc; | |
| 621 static int i = 0; | |
| 622 | |
| 623 /* | |
| 624 if ((y = xmlnode_get_tag(p->x, "html"))) { | |
| 625 msg = xmlnode_get_data(y); | |
| 626 } else | |
| 627 */ | |
| 628 if ((y = xmlnode_get_tag(p->x, "body"))) { | |
| 629 msg = xmlnode_get_data(y); | |
| 630 } | |
| 631 | |
| 632 msg = utf8_to_str(msg); | |
| 633 | |
| 634 if ((subj = xmlnode_get_tag(p->x, "subject"))) { | |
| 635 topic = xmlnode_get_data(subj); | |
| 636 } | |
| 637 topic = utf8_to_str(topic); | |
| 638 | |
| 639 jc = find_existing_chat(GJ_GC(j), p->from); | |
| 640 if (!jc) { | |
| 641 /* we're not in this chat. are we supposed to be? */ | |
| 642 struct jabber_data *jd = GJ_GC(j)->proto_data; | |
| 643 if ((jc = find_pending_chat(GJ_GC(j), p->from)) != NULL) { | |
| 644 /* yes, we're supposed to be. so now we are. */ | |
| 645 jc->b = serv_got_joined_chat(GJ_GC(j), i++, p->from->user); | |
| 646 jc->id = jc->b->id; | |
| 647 jd->existing_chats = g_slist_append(jd->existing_chats, jc); | |
| 648 jd->pending_chats = g_slist_remove(jd->pending_chats, jc); | |
| 649 } else { | |
| 650 /* no, we're not supposed to be. */ | |
| 651 g_free(msg); | |
| 652 return; | |
| 653 } | |
| 654 } | |
| 655 if (p->from->resource) { | |
| 656 if (!y) { | |
| 657 if (!find_chat_buddy(jc->b, p->from->resource)) | |
| 658 add_chat_buddy(jc->b, p->from->resource); | |
| 659 else if ((y = xmlnode_get_tag(p->x, "status"))) { | |
| 660 char buf[8192]; | |
| 661 msg = xmlnode_get_data(y); | |
| 662 g_snprintf(buf, sizeof(buf), "%s now has status: %s", | |
| 663 p->from->resource, msg); | |
| 664 write_to_conv(jc->b, buf, WFLAG_SYSTEM, NULL, time(NULL)); | |
| 665 } | |
| 666 } else if (jc->b && msg) { | |
| 667 char buf[8192]; | |
| 668 | |
| 669 if (topic) { | |
| 670 char tbuf[8192]; | |
| 671 g_snprintf(tbuf, sizeof(tbuf), "%s", topic); | |
| 672 chat_set_topic(jc->b, p->from->resource, tbuf); | |
| 673 } | |
| 674 | |
| 675 | |
| 676 g_snprintf(buf, sizeof(buf), "%s", msg); | |
| 677 serv_got_chat_in(GJ_GC(j), jc->b->id, p->from->resource, 0, buf, time(NULL)); | |
| 678 } | |
| 679 } else { /* message from the server */ | |
| 680 if(jc->b && topic) { | |
| 681 char tbuf[8192]; | |
| 682 g_snprintf(tbuf, sizeof(tbuf), "%s", topic); | |
| 683 chat_set_topic(jc->b, "", tbuf); | |
| 684 } | |
| 685 } | |
| 686 | |
| 687 g_free(msg); | |
| 688 g_free(topic); | |
| 689 | |
| 690 } else { | |
| 691 debug_printf("unhandled message %s\n", type); | |
| 692 } | |
| 693 } | |
| 694 | |
| 695 static void jabber_handlepresence(gjconn j, jpacket p) | |
| 696 { | |
| 697 char *to, *from, *type; | |
| 698 struct buddy *b = NULL; | |
| 699 jid who; | |
| 700 char *buddy; | |
| 701 xmlnode y; | |
| 702 char *show; | |
| 703 int state = UC_NORMAL; | |
| 704 GSList *resources; | |
| 705 char *res; | |
| 706 struct conversation *cnv = NULL; | |
| 707 struct jabber_chat *jc = NULL; | |
| 708 | |
| 709 to = xmlnode_get_attrib(p->x, "to"); | |
| 710 from = xmlnode_get_attrib(p->x, "from"); | |
| 711 type = xmlnode_get_attrib(p->x, "type"); | |
| 712 | |
| 713 if ((y = xmlnode_get_tag(p->x, "show"))) { | |
| 714 show = xmlnode_get_data(y); | |
| 715 if (!show) { | |
| 716 state = UC_NORMAL; | |
| 717 } else if (!strcasecmp(show, "away")) { | |
| 718 state = UC_AWAY; | |
| 719 } else if (!strcasecmp(show, "chat")) { | |
| 720 state = UC_CHAT; | |
| 721 } else if (!strcasecmp(show, "xa")) { | |
| 722 state = UC_XA; | |
| 723 } else if (!strcasecmp(show, "dnd")) { | |
| 724 state = UC_DND; | |
| 725 } | |
| 726 } else { | |
| 727 state = UC_NORMAL; | |
| 728 } | |
| 729 | |
| 730 who = jid_new(j->p, from); | |
| 731 if (who->user == NULL) { | |
| 732 /* FIXME: transport */ | |
| 733 return; | |
| 734 } | |
| 735 | |
| 736 buddy = g_strdup_printf("%s@%s", who->user, who->server); | |
| 737 | |
| 738 /* um. we're going to check if it's a chat. if it isn't, and there are pending | |
| 739 * chats, create the chat. if there aren't pending chats, add the buddy. */ | |
| 740 if ((cnv = find_chat(GJ_GC(j), who->user)) == NULL) { | |
| 741 static int i = 0x70; | |
| 742 struct jabber_data *jd = GJ_GC(j)->proto_data; | |
| 743 if ((jc = find_pending_chat(GJ_GC(j), who)) != NULL) { | |
| 744 jc->b = cnv = serv_got_joined_chat(GJ_GC(j), i++, who->user); | |
| 745 jc->id = jc->b->id; | |
| 746 jd->existing_chats = g_slist_append(jd->existing_chats, jc); | |
| 747 jd->pending_chats = g_slist_remove(jd->pending_chats, jc); | |
| 748 } else if (!(b = find_buddy(GJ_GC(j), buddy))) { | |
| 749 b = add_buddy(GJ_GC(j), "Buddies", buddy, buddy); | |
| 750 do_export(GJ_GC(j)); | |
| 751 } | |
| 752 } | |
| 753 | |
| 754 if (!cnv) { | |
| 755 resources = b->proto_data; | |
| 756 res = who->resource; | |
| 757 if (res) | |
| 758 while (resources) { | |
| 759 if (!strcmp(res, resources->data)) | |
| 760 break; | |
| 761 resources = resources->next; | |
| 762 } | |
| 763 | |
| 764 if (type && (strcasecmp(type, "unavailable") == 0)) { | |
| 765 if (resources) { | |
| 766 g_free(resources->data); | |
| 767 b->proto_data = g_slist_remove(b->proto_data, resources->data); | |
| 768 } | |
| 769 if (!b->proto_data) { | |
| 770 serv_got_update(GJ_GC(j), buddy, 0, 0, 0, 0, 0, 0); | |
| 771 } | |
| 772 } else { | |
| 773 /* keep track of away msg same as yahoo plugin */ | |
| 774 struct jabber_data *jd = GJ_GC(j)->proto_data; | |
| 775 gpointer val = g_hash_table_lookup(jd->hash, b->name); | |
| 776 if (val) | |
| 777 g_free(val); | |
| 778 g_hash_table_insert(jd->hash, g_strdup(b->name), g_strdup(xmlnode_get_tag_data(p->x, "status"))); | |
| 779 | |
| 780 | |
| 781 if (!resources) { | |
| 782 b->proto_data = g_slist_append(b->proto_data, g_strdup(res)); | |
| 783 } | |
| 784 | |
| 785 serv_got_update(GJ_GC(j), buddy, 1, 0, 0, 0, state, 0); | |
| 786 | |
| 787 } | |
| 788 } else { | |
| 789 if (who->resource) { | |
| 790 if (type && !strcasecmp(type, "unavailable")) { | |
| 791 struct jabber_data *jd; | |
| 792 if (!jc && !(jc = find_existing_chat(GJ_GC(j), who))) { | |
| 793 g_free(buddy); | |
| 794 return; | |
| 795 } | |
| 796 jd = jc->gc->proto_data; | |
| 797 if (strcmp(who->resource, jc->Jid->resource) && jc->b) { | |
| 798 remove_chat_buddy(jc->b, who->resource); | |
| 799 return; | |
| 800 } | |
| 801 | |
| 802 jd->existing_chats = g_slist_remove(jd->existing_chats, jc); | |
| 803 serv_got_chat_left(GJ_GC(j), jc->id); | |
| 804 g_free(jc); | |
| 805 } else { | |
| 806 if ((!jc && !(jc = find_existing_chat(GJ_GC(j), who))) || !jc->b) { | |
| 807 g_free(buddy); | |
| 808 return; | |
| 809 } | |
| 810 if (!find_chat_buddy(jc->b, who->resource)) | |
| 811 add_chat_buddy(jc->b, who->resource); | |
| 812 else if ((y = xmlnode_get_tag(p->x, "status"))) { | |
| 813 char buf[8192]; | |
| 814 char *msg = xmlnode_get_data(y); | |
| 815 g_snprintf(buf, sizeof(buf), "%s now has status: %s", | |
| 816 p->from->resource, msg); | |
| 817 write_to_conv(jc->b, buf, WFLAG_SYSTEM, NULL, time(NULL)); | |
| 818 } | |
| 819 } | |
| 820 } | |
| 821 } | |
| 822 | |
| 823 g_free(buddy); | |
| 824 | |
| 825 return; | |
| 826 } | |
| 827 | |
| 828 static void jabber_handles10n(gjconn j, jpacket p) | |
| 829 { | |
| 830 xmlnode g; | |
| 831 char *Jid = xmlnode_get_attrib(p->x, "from"); | |
| 832 char *ask = xmlnode_get_attrib(p->x, "type"); | |
| 833 | |
| 834 g = xmlnode_new_tag("presence"); | |
| 835 xmlnode_put_attrib(g, "to", Jid); | |
| 836 if (!strcmp(ask, "subscribe")) | |
| 837 xmlnode_put_attrib(g, "type", "subscribed"); | |
| 838 else if (!strcmp(ask, "unsubscribe")) | |
| 839 xmlnode_put_attrib(g, "type", "unsubscribed"); | |
| 840 else | |
| 841 return; | |
| 842 | |
| 843 gjab_send(j, g); | |
| 844 } | |
| 845 | |
| 846 static void jabber_handleroster(gjconn j, xmlnode querynode) | |
| 847 { | |
| 848 xmlnode x; | |
| 849 | |
| 850 x = xmlnode_get_firstchild(querynode); | |
| 851 while (x) { | |
| 852 xmlnode g; | |
| 853 char *Jid, *name, *sub, *ask; | |
| 854 jid who; | |
| 855 | |
| 856 Jid = xmlnode_get_attrib(x, "jid"); | |
| 857 name = xmlnode_get_attrib(x, "name"); | |
| 858 sub = xmlnode_get_attrib(x, "subscription"); | |
| 859 ask = xmlnode_get_attrib(x, "ask"); | |
| 860 who = jid_new(j->p, Jid); | |
| 861 | |
| 862 if ((g = xmlnode_get_firstchild(x))) { | |
| 863 while (g) { | |
|
2112
0ad5f2cf6728
[gaim-migrate @ 2122]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2111
diff
changeset
|
864 if (xmlnode_get_name(g) && |
|
0ad5f2cf6728
[gaim-migrate @ 2122]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2111
diff
changeset
|
865 g_strncasecmp(xmlnode_get_name(g), "group", 5) == 0) { |
| 2086 | 866 struct buddy *b = NULL; |
| 867 char *groupname, *buddyname; | |
| 868 | |
|
2111
109669b3887e
[gaim-migrate @ 2121]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2090
diff
changeset
|
869 if (!who || !who->user) { |
| 2086 | 870 /* FIXME: transport */ |
| 871 g = xmlnode_get_nextsibling(g); | |
| 872 continue; | |
| 873 } | |
| 874 buddyname = g_strdup_printf("%s@%s", who->user, who->server); | |
| 875 groupname = xmlnode_get_data(xmlnode_get_firstchild(g)); | |
| 876 if (groupname == NULL) | |
| 877 groupname = "Buddies"; | |
| 878 if (strcasecmp(sub, "from") && strcasecmp(sub, "none") && | |
| 879 !(b = find_buddy(GJ_GC(j), buddyname))) { | |
| 880 debug_printf("adding buddy: %s\n", buddyname); | |
| 881 b = add_buddy(GJ_GC(j), groupname, buddyname, | |
| 882 name ? name : buddyname); | |
| 883 do_export(GJ_GC(j)); | |
| 884 /* | |
| 885 } else if (b) { | |
| 886 debug_printf("updating buddy: %s/%s\n", buddyname, name); | |
| 887 g_snprintf(b->name, sizeof(b->name), "%s", buddyname); | |
| 888 g_snprintf(b->show, sizeof(b->show), "%s", | |
| 889 name ? name : buddyname); | |
| 890 */ | |
| 891 } | |
| 892 g_free(buddyname); | |
| 893 } | |
| 894 g = xmlnode_get_nextsibling(g); | |
| 895 } | |
| 896 } else { | |
| 897 struct buddy *b; | |
| 898 char *buddyname; | |
| 899 | |
|
2111
109669b3887e
[gaim-migrate @ 2121]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2090
diff
changeset
|
900 if (!who || !who->user) { |
| 2086 | 901 /* FIXME: transport */ |
| 902 x = xmlnode_get_nextsibling(x); | |
| 903 continue; | |
| 904 } | |
| 905 buddyname = g_strdup_printf("%s@%s", who->user, who->server); | |
| 906 if (strcasecmp(sub, "from") && strcasecmp(sub, "none") && | |
| 907 !(b = find_buddy(GJ_GC(j), buddyname))) { | |
| 908 debug_printf("adding buddy: %s\n", buddyname); | |
| 909 b = add_buddy(GJ_GC(j), "Buddies", buddyname, name ? name : Jid); | |
| 910 do_export(GJ_GC(j)); | |
| 911 } | |
| 912 g_free(buddyname); | |
| 913 } | |
| 914 | |
| 915 x = xmlnode_get_nextsibling(x); | |
| 916 } | |
| 917 | |
| 918 x = jutil_presnew(0, NULL, "Online"); | |
| 919 gjab_send(j, x); | |
| 920 xmlnode_free(x); | |
| 921 } | |
| 922 | |
| 923 static void jabber_handlevcard(gjconn j, xmlnode querynode, char *from) { | |
| 924 char buf[1024]; | |
| 925 char *fn, *url, *email, *nickname, *status, *desc; | |
| 926 jid who; | |
| 927 char *buddy; | |
| 928 struct jabber_data *jd = GJ_GC(j)->proto_data; | |
| 929 int at = 0; | |
| 930 | |
| 931 who = jid_new(j->p, from); | |
| 932 buddy = g_strdup_printf("%s@%s", who->user, who->server); | |
| 933 | |
| 934 fn = xmlnode_get_tag_data(querynode, "FN"); | |
| 935 url = xmlnode_get_tag_data(querynode, "URL"); | |
| 936 email = xmlnode_get_tag_data(querynode, "EMAIL"); | |
| 937 nickname = xmlnode_get_tag_data(querynode, "NICKNAME"); | |
| 938 desc = xmlnode_get_tag_data(querynode, "DESC"); | |
| 939 status = g_hash_table_lookup(jd->hash, buddy); | |
| 940 if (!status) | |
| 941 status = "Online"; | |
| 942 | |
| 943 at = g_snprintf(buf, sizeof buf, "<B>Jabber ID:</B> %s<BR>", buddy); | |
| 944 if (fn) | |
| 945 at += g_snprintf(buf + at, sizeof(buf) - at, "<B>Full Name:</B> %s<BR>", fn); | |
| 946 if (nickname) | |
| 947 at += g_snprintf(buf + at, sizeof(buf) - at, "<B>Nickname:</B> %s<BR>", nickname); | |
| 948 if (url) | |
| 949 at += g_snprintf(buf + at, sizeof(buf) - at, "<B>URL:</B> <A HREF=\"%s\">%s</A><BR>", | |
| 950 url, url); | |
| 951 if (email) | |
| 952 at += g_snprintf(buf + at, sizeof(buf) - at, | |
| 953 "<B>Email:</B> <A HREF=\"mailto:%s\">%s</A><BR>", email, email); | |
| 954 at += g_snprintf(buf + at, sizeof(buf) - at, "<B>Status:</B> %s\n", status); | |
| 955 if (desc) | |
| 956 at += g_snprintf(buf + at, sizeof(buf) - at, "<HR>%s<br>\n", desc); | |
| 957 | |
|
2137
18722ae5b882
[gaim-migrate @ 2147]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2131
diff
changeset
|
958 g_show_info_text(buf, NULL); |
| 2086 | 959 g_free(buddy); |
| 960 } | |
| 961 | |
| 962 static void jabber_handleauthresp(gjconn j, jpacket p) | |
| 963 { | |
| 964 if (jpacket_subtype(p) == JPACKET__RESULT) { | |
| 965 debug_printf("auth success\n"); | |
| 966 | |
| 967 account_online(GJ_GC(j)); | |
| 968 serv_finish_login(GJ_GC(j)); | |
| 969 | |
| 970 if (bud_list_cache_exists(GJ_GC(j))) | |
|
2382
569ae9f2bb89
[gaim-migrate @ 2395]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2316
diff
changeset
|
971 do_import(GJ_GC(j), NULL); |
| 2086 | 972 |
| 973 ((struct jabber_data *)GJ_GC(j)->proto_data)->did_import = TRUE; | |
| 974 | |
| 975 gjab_reqroster(j); | |
| 976 } else { | |
| 977 xmlnode xerr; | |
| 978 char *errmsg = NULL; | |
| 979 int errcode = 0; | |
| 980 | |
| 981 debug_printf("auth failed\n"); | |
| 982 xerr = xmlnode_get_tag(p->x, "error"); | |
| 983 if (xerr) { | |
| 984 char msg[BUF_LONG]; | |
| 985 errmsg = xmlnode_get_data(xerr); | |
| 986 if (xmlnode_get_attrib(xerr, "code")) { | |
| 987 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
| 988 g_snprintf(msg, sizeof(msg), "Error %d: %s", errcode, errmsg); | |
| 989 } else | |
| 990 g_snprintf(msg, sizeof(msg), "%s", errmsg); | |
| 991 hide_login_progress(GJ_GC(j), msg); | |
| 992 } else { | |
| 993 hide_login_progress(GJ_GC(j), "Unknown login error"); | |
| 994 } | |
| 995 | |
| 996 signoff(GJ_GC(j)); | |
| 997 } | |
| 998 } | |
| 999 | |
| 1000 static void jabber_handleversion(gjconn j, xmlnode iqnode) { | |
| 1001 xmlnode querynode, x; | |
| 1002 char *id, *from; | |
| 1003 char os[1024]; | |
| 1004 struct utsname osinfo; | |
| 1005 | |
| 1006 uname(&osinfo); | |
| 1007 g_snprintf(os, sizeof os, "%s %s %s", osinfo.sysname, osinfo.release, osinfo.machine); | |
| 1008 | |
| 1009 id = xmlnode_get_attrib(iqnode, "id"); | |
| 1010 from = xmlnode_get_attrib(iqnode, "from"); | |
| 1011 | |
| 1012 x = jutil_iqnew(JPACKET__RESULT, NS_VERSION); | |
| 1013 | |
| 1014 xmlnode_put_attrib(x, "to", from); | |
| 1015 xmlnode_put_attrib(x, "id", id); | |
| 1016 querynode = xmlnode_get_tag(x, "query"); | |
| 1017 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "name"), PACKAGE, -1); | |
| 1018 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "version"), VERSION, -1); | |
| 1019 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "os"), os, -1); | |
| 1020 | |
| 1021 gjab_send(j, x); | |
| 1022 | |
| 1023 xmlnode_free(x); | |
| 1024 } | |
| 1025 | |
| 1026 static void jabber_handletime(gjconn j, xmlnode iqnode) { | |
| 1027 xmlnode querynode, x; | |
| 1028 char *id, *from; | |
| 1029 time_t now_t; | |
| 1030 struct tm *now; | |
| 1031 char buf[1024]; | |
| 1032 | |
| 1033 time(&now_t); | |
| 1034 now = localtime(&now_t); | |
| 1035 | |
| 1036 id = xmlnode_get_attrib(iqnode, "id"); | |
| 1037 from = xmlnode_get_attrib(iqnode, "from"); | |
| 1038 | |
| 1039 x = jutil_iqnew(JPACKET__RESULT, NS_TIME); | |
| 1040 | |
| 1041 xmlnode_put_attrib(x, "to", from); | |
| 1042 xmlnode_put_attrib(x, "id", id); | |
| 1043 querynode = xmlnode_get_tag(x, "query"); | |
| 1044 | |
| 1045 strftime(buf, 1024, "%Y%m%dT%T", now); | |
| 1046 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "utc"), buf, -1); | |
| 1047 strftime(buf, 1024, "%Z", now); | |
| 1048 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "tz"), buf, -1); | |
| 1049 strftime(buf, 1024, "%d %b %Y %T", now); | |
| 1050 xmlnode_insert_cdata(xmlnode_insert_tag(querynode, "display"), buf, -1); | |
| 1051 | |
| 1052 gjab_send(j, x); | |
| 1053 | |
| 1054 xmlnode_free(x); | |
| 1055 } | |
| 1056 | |
| 1057 static void jabber_handlelast(gjconn j, xmlnode iqnode) { | |
| 1058 xmlnode x, querytag; | |
| 1059 char *id, *from; | |
| 1060 struct jabber_data *jd = GJ_GC(j)->proto_data; | |
| 1061 char idle_time[32]; | |
| 1062 | |
| 1063 id = xmlnode_get_attrib(iqnode, "id"); | |
| 1064 from = xmlnode_get_attrib(iqnode, "from"); | |
| 1065 | |
| 1066 x = jutil_iqnew(JPACKET__RESULT, "jabber:iq:last"); | |
| 1067 | |
| 1068 xmlnode_put_attrib(x, "to", from); | |
| 1069 xmlnode_put_attrib(x, "id", id); | |
| 1070 querytag = xmlnode_get_tag(x, "query"); | |
| 1071 g_snprintf(idle_time, sizeof idle_time, "%ld", jd->idle ? time(NULL) - jd->idle : 0); | |
| 1072 xmlnode_put_attrib(querytag, "seconds", idle_time); | |
| 1073 | |
| 1074 gjab_send(j, x); | |
| 1075 xmlnode_free(x); | |
| 1076 } | |
| 1077 | |
| 1078 static void jabber_handlepacket(gjconn j, jpacket p) | |
| 1079 { | |
| 1080 switch (p->type) { | |
| 1081 case JPACKET_MESSAGE: | |
| 1082 jabber_handlemessage(j, p); | |
| 1083 break; | |
| 1084 case JPACKET_PRESENCE: | |
| 1085 jabber_handlepresence(j, p); | |
| 1086 break; | |
| 1087 case JPACKET_IQ: | |
| 1088 debug_printf("jpacket_subtype: %d\n", jpacket_subtype(p)); | |
| 1089 | |
| 1090 if (xmlnode_get_attrib(p->x, "id") && (strcmp(xmlnode_get_attrib(p->x, "id"), IQID_AUTH) == 0)) { | |
| 1091 jabber_handleauthresp(j, p); | |
| 1092 break; /* I'm not sure if you like this style, Eric. */ | |
| 1093 } | |
| 1094 | |
| 1095 if (jpacket_subtype(p) == JPACKET__SET) { | |
| 1096 } else if (jpacket_subtype(p) == JPACKET__GET) { | |
| 1097 xmlnode querynode; | |
| 1098 querynode = xmlnode_get_tag(p->x, "query"); | |
| 1099 if(NSCHECK(querynode, NS_VERSION)) { | |
| 1100 jabber_handleversion(j, p->x); | |
| 1101 } else if (NSCHECK(querynode, NS_TIME)) { | |
| 1102 jabber_handletime(j, p->x); | |
| 1103 } else if (NSCHECK(querynode, "jabber:iq:last")) { | |
| 1104 jabber_handlelast(j, p->x); | |
| 1105 } | |
| 1106 } else if (jpacket_subtype(p) == JPACKET__RESULT) { | |
| 1107 xmlnode querynode, vcard; | |
| 1108 char *xmlns, *from; | |
| 1109 | |
| 1110 from = xmlnode_get_attrib(p->x, "from"); | |
| 1111 querynode = xmlnode_get_tag(p->x, "query"); | |
| 1112 xmlns = xmlnode_get_attrib(querynode, "xmlns"); | |
| 1113 vcard = xmlnode_get_tag(p->x, "vCard"); | |
|
2316
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
1114 if (!vcard) |
|
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
1115 vcard = xmlnode_get_tag(p->x, "VCARD"); |
| 2086 | 1116 |
| 1117 if (NSCHECK(querynode, NS_ROSTER)) { | |
| 1118 jabber_handleroster(j, querynode); | |
| 1119 } else if (NSCHECK(querynode, NS_VCARD)) { | |
| 1120 jabber_handlevcard(j, querynode, from); | |
|
2316
ebb5ecb2cd5b
[gaim-migrate @ 2326]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2309
diff
changeset
|
1121 } else if (vcard) { |
| 2086 | 1122 jabber_handlevcard(j, vcard, from); |
| 1123 } else { | |
| 1124 /* debug_printf("jabber:iq:query: %s\n", xmlns); */ | |
| 1125 } | |
| 1126 | |
| 1127 } else if (jpacket_subtype(p) == JPACKET__ERROR) { | |
| 1128 xmlnode xerr; | |
| 1129 char *from, *errmsg = NULL; | |
| 1130 int errcode = 0; | |
| 1131 | |
| 1132 from = xmlnode_get_attrib(p->x, "from"); | |
| 1133 xerr = xmlnode_get_tag(p->x, "error"); | |
| 1134 if (xerr) { | |
| 1135 errmsg = xmlnode_get_data(xerr); | |
| 1136 if (xmlnode_get_attrib(xerr, "code")) | |
| 1137 errcode = atoi(xmlnode_get_attrib(xerr, "code")); | |
| 1138 } | |
| 1139 | |
| 1140 from = g_strdup_printf("Error %d (%s)", errcode, from); | |
| 1141 do_error_dialog(errmsg, from); | |
| 1142 g_free(from); | |
| 1143 | |
| 1144 } | |
| 1145 | |
| 1146 break; | |
| 1147 | |
| 1148 case JPACKET_S10N: | |
| 1149 jabber_handles10n(j, p); | |
| 1150 break; | |
| 1151 default: | |
| 1152 debug_printf("jabber: packet type %d (%s)\n", p->type, xmlnode2str(p->x)); | |
| 1153 } | |
| 1154 | |
| 1155 xmlnode_free(p->x); | |
| 1156 | |
| 1157 return; | |
| 1158 } | |
| 1159 | |
| 1160 static void jabber_handlestate(gjconn j, int state) | |
| 1161 { | |
| 1162 switch (state) { | |
| 1163 case JCONN_STATE_OFF: | |
| 1164 hide_login_progress(GJ_GC(j), "Unable to connect"); | |
| 1165 signoff(GJ_GC(j)); | |
| 1166 break; | |
| 1167 case JCONN_STATE_CONNECTED: | |
| 1168 set_login_progress(GJ_GC(j), 3, "Connected"); | |
| 1169 break; | |
| 1170 case JCONN_STATE_ON: | |
| 1171 set_login_progress(GJ_GC(j), 5, "Logging in..."); | |
| 1172 gjab_auth(j); | |
| 1173 break; | |
| 1174 default: | |
| 1175 debug_printf("state change: %d\n", state); | |
| 1176 } | |
| 1177 return; | |
| 1178 } | |
| 1179 | |
| 1180 static void jabber_login(struct aim_user *user) | |
| 1181 { | |
| 1182 struct gaim_connection *gc = new_gaim_conn(user); | |
| 1183 struct jabber_data *jd = gc->proto_data = g_new0(struct jabber_data, 1); | |
| 1184 char *loginname = create_valid_jid(user->username, DEFAULT_SERVER, "GAIM"); | |
| 1185 | |
| 1186 jd->hash = g_hash_table_new(g_str_hash, g_str_equal); | |
| 1187 | |
| 1188 set_login_progress(gc, 1, "Connecting"); | |
| 1189 | |
| 1190 if (!(jd->jc = gjab_new(loginname, user->password, gc))) { | |
| 1191 g_free(loginname); | |
| 1192 debug_printf("jabber: unable to connect (jab_new failed)\n"); | |
| 1193 hide_login_progress(gc, "Unable to connect"); | |
| 1194 signoff(gc); | |
| 1195 return; | |
| 1196 } | |
| 1197 | |
| 1198 g_free(loginname); | |
| 1199 gjab_state_handler(jd->jc, jabber_handlestate); | |
| 1200 gjab_packet_handler(jd->jc, jabber_handlepacket); | |
| 1201 gjab_start(jd->jc); | |
| 1202 } | |
| 1203 | |
| 1204 static gboolean jabber_destroy_hash(gpointer key, gpointer val, gpointer data) { | |
| 1205 g_free(key); | |
| 1206 g_free(val); | |
| 1207 return TRUE; | |
| 1208 } | |
| 1209 | |
| 1210 static gboolean jabber_free(gpointer data) | |
| 1211 { | |
| 1212 gjab_delete(data); | |
| 1213 return FALSE; | |
| 1214 } | |
| 1215 | |
| 1216 static void jabber_close(struct gaim_connection *gc) | |
| 1217 { | |
| 1218 struct jabber_data *jd = gc->proto_data; | |
| 1219 g_hash_table_foreach_remove(jd->hash, jabber_destroy_hash, NULL); | |
| 1220 g_hash_table_destroy(jd->hash); | |
|
2300
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
1221 if (gc->inpa) |
|
d2686f757d6e
[gaim-migrate @ 2310]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2289
diff
changeset
|
1222 gaim_input_remove(gc->inpa); |
| 2086 | 1223 close(jd->jc->fd); |
|
2131
acc11216ec5d
[gaim-migrate @ 2141]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2123
diff
changeset
|
1224 g_timeout_add(50, jabber_free, jd->jc); |
| 2086 | 1225 jd->jc = NULL; |
| 1226 g_free(jd); | |
| 1227 gc->proto_data = NULL; | |
| 1228 } | |
| 1229 | |
|
2231
8c4ff1a368bd
[gaim-migrate @ 2241]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2205
diff
changeset
|
1230 static int jabber_send_im(struct gaim_connection *gc, char *who, char *message, int flags) |
| 2086 | 1231 { |
| 1232 xmlnode x, y; | |
| 1233 char *realwho; | |
| 1234 gjconn j = ((struct jabber_data *)gc->proto_data)->jc; | |
| 1235 | |
| 1236 if (!who || !message) | |
|
2123
56c4382f2909
[gaim-migrate @ 2133]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2112
diff
changeset
|
1237 return 0; |
| 2086 | 1238 |
| 1239 x = xmlnode_new_tag("message"); | |
| 1240 if (!strchr(who, '@')) | |
| 1241 realwho = g_strdup_printf("%s@%s", who, j->user->server); | |
| 1242 else | |
| 1243 realwho = g_strdup(who); | |
| 1244 xmlnode_put_attrib(x, "to", realwho); | |
| 1245 g_free(realwho); | |
| 1246 | |
|
2278
00a8b7bcef6c
[gaim-migrate @ 2288]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2232
diff
changeset
|
1247 xmlnode_insert_tag(x, "gaim"); |
| 2086 | 1248 xmlnode_put_attrib(x, "type", "chat"); |
| 1249 | |
| 1250 if (message && strlen(message)) { | |
| 1251 char *utf8 = str_to_utf8(message); | |
| 1252 y = xmlnode_insert_tag(x, "body"); | |
| 1253 xmlnode_insert_cdata(y, utf8, -1); | |
| 1254 g_free(utf8); | |
| 1255 } | |
| 1256 | |
| 1257 gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); | |
| 1258 xmlnode_free(x); | |
|
2303
f5bf315e6104
[gaim-migrate @ 2313]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2300
diff
changeset
|
1259 return 1; |
| 2086 | 1260 } |
| 1261 | |
| 1262 static void jabber_add_buddy(struct gaim_connection *gc, char *name) | |
| 1263 { | |
| 1264 xmlnode x, y; | |
| 1265 char *realwho; | |
| 1266 gjconn j = ((struct jabber_data *)gc->proto_data)->jc; | |
| 1267 | |
| 1268 if (!((struct jabber_data *)gc->proto_data)->did_import) | |
| 1269 return; | |
| 1270 | |
| 1271 if (!name) | |
| 1272 return; | |
| 1273 | |
| 1274 if (!strcmp(gc->username, name)) | |
| 1275 return; | |
| 1276 | |
| 1277 if (!strchr(name, '@')) | |
| 1278 realwho = g_strdup_printf("%s@%s", name, j->user->server); | |
| 1279 else { | |
| 1280 jid who = jid_new(j->p, name); | |
| 1281 if (who->user == NULL) { | |
| 1282 /* FIXME: transport */ | |
| 1283 return; | |
| 1284 } | |
| 1285 realwho = g_strdup_printf("%s@%s", who->user, who->server); | |
| 1286 } | |
| 1287 | |
| 1288 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
| 1289 y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); | |
| 1290 xmlnode_put_attrib(y, "jid", realwho); | |
| 1291 gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); | |
| 1292 xmlnode_free(x); | |
| 1293 | |
| 1294 x = xmlnode_new_tag("presence"); | |
| 1295 xmlnode_put_attrib(x, "to", realwho); | |
| 1296 xmlnode_put_attrib(x, "type", "subscribe"); | |
| 1297 gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); | |
| 1298 | |
| 1299 g_free(realwho); | |
| 1300 } | |
| 1301 | |
| 1302 static void jabber_remove_buddy(struct gaim_connection *gc, char *name) | |
| 1303 { | |
| 1304 xmlnode x, y; | |
| 1305 char *realwho; | |
| 1306 gjconn j = ((struct jabber_data *)gc->proto_data)->jc; | |
| 1307 | |
| 1308 if (!name) | |
| 1309 return; | |
| 1310 | |
| 1311 if (!strchr(name, '@')) | |
| 1312 realwho = g_strdup_printf("%s@%s", name, j->user->server); | |
| 1313 else | |
| 1314 realwho = g_strdup(name); | |
| 1315 | |
| 1316 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
| 1317 y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); | |
| 1318 xmlnode_put_attrib(y, "jid", realwho); | |
| 1319 xmlnode_put_attrib(y, "subscription", "remove"); | |
| 1320 gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); | |
| 1321 | |
| 1322 g_free(realwho); | |
| 1323 xmlnode_free(x); | |
| 1324 } | |
| 1325 | |
| 1326 static char **jabber_list_icon(int uc) | |
| 1327 { | |
| 1328 switch (uc) { | |
| 1329 case UC_AWAY: | |
| 1330 return available_away_xpm; | |
| 1331 case UC_CHAT: | |
| 1332 return available_chat_xpm; | |
| 1333 case UC_XA: | |
| 1334 return available_xa_xpm; | |
| 1335 case UC_DND: | |
| 1336 return available_dnd_xpm; | |
| 1337 default: | |
| 1338 return available_xpm; | |
| 1339 } | |
| 1340 } | |
| 1341 | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1342 static GList *jabber_chat_info(struct gaim_connection *gc) |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1343 { |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1344 gjconn j = ((struct jabber_data *)gc->proto_data)->jc; |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1345 |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1346 GList *m = NULL; |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1347 struct proto_chat_entry *pce; |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1348 |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1349 pce = g_new0(struct proto_chat_entry, 1); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1350 pce->label = _("Room:"); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1351 m = g_list_append(m, pce); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1352 |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1353 pce = g_new0(struct proto_chat_entry, 1); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1354 pce->label = _("Server:"); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1355 pce->def = DEFAULT_GROUPCHAT; |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1356 m = g_list_append(m, pce); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1357 |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1358 pce = g_new0(struct proto_chat_entry, 1); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1359 pce->label = _("Handle:"); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1360 pce->def = j->user->user; |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1361 m = g_list_append(m, pce); |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1362 |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1363 return m; |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1364 } |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1365 |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1366 static void jabber_join_chat(struct gaim_connection *gc, GList *data) |
| 2086 | 1367 { |
| 1368 xmlnode x; | |
| 1369 char *realwho; | |
| 1370 gjconn j = ((struct jabber_data *)gc->proto_data)->jc; | |
| 1371 GSList *pc = ((struct jabber_data *)gc->proto_data)->pending_chats; | |
| 1372 struct jabber_chat *jc; | |
| 1373 | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1374 if (!data || !data->next || !data->next->next) |
| 2086 | 1375 return; |
| 1376 | |
| 1377 jc = g_new0(struct jabber_chat, 1); | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1378 realwho = create_valid_jid(data->data, data->next->data, |
|
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1379 data->next->next->data); |
| 2086 | 1380 jc->Jid = jid_new(j->p, realwho); |
| 1381 jc->gc = gc; | |
| 1382 debug_printf("%s\n", realwho); | |
| 1383 | |
| 1384 x = jutil_presnew(0, realwho, NULL); | |
| 1385 gjab_send(j, x); | |
| 1386 xmlnode_free(x); | |
| 1387 g_free(realwho); | |
| 1388 | |
| 1389 ((struct jabber_data *)gc->proto_data)->pending_chats = g_slist_append(pc, jc); | |
| 1390 } | |
| 1391 | |
| 1392 static void jabber_chat_invite(struct gaim_connection *gc, int id, char *message, char *name) | |
| 1393 { | |
| 1394 xmlnode x, y; | |
| 1395 GSList *bcs = gc->buddy_chats; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1396 struct conversation *b = NULL; |
| 2086 | 1397 struct jabber_data *jd = gc->proto_data; |
| 1398 gjconn j = jd->jc; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1399 struct jabber_chat *jc = NULL; |
| 2086 | 1400 char *realwho, *subject; |
| 1401 | |
| 1402 if (!name) | |
| 1403 return; | |
| 1404 | |
| 1405 /* find which chat we're inviting to */ | |
| 1406 while (bcs) { | |
| 1407 b = bcs->data; | |
| 1408 if (id == b->id) | |
| 1409 break; | |
| 1410 bcs = bcs->next; | |
| 1411 } | |
| 1412 if (!bcs) | |
| 1413 return; | |
| 1414 | |
| 1415 bcs = jd->existing_chats; | |
| 1416 while (bcs) { | |
| 1417 jc = bcs->data; | |
| 1418 if (jc->b == b) | |
| 1419 break; | |
| 1420 bcs = bcs->next; | |
| 1421 } | |
| 1422 if (!bcs) | |
| 1423 return; | |
| 1424 | |
| 1425 x = xmlnode_new_tag("message"); | |
| 1426 if (!strchr(name, '@')) | |
| 1427 realwho = g_strdup_printf("%s@%s", name, j->user->server); | |
| 1428 else | |
| 1429 realwho = g_strdup(name); | |
| 1430 xmlnode_put_attrib(x, "to", realwho); | |
| 1431 g_free(realwho); | |
| 1432 | |
| 1433 y = xmlnode_insert_tag(x, "x"); | |
| 1434 xmlnode_put_attrib(y, "xmlns", "jabber:x:conference"); | |
| 1435 subject = g_strdup_printf("%s@%s", jc->Jid->user, jc->Jid->server); | |
| 1436 xmlnode_put_attrib(y, "jid", subject); | |
| 1437 g_free(subject); | |
| 1438 | |
| 1439 if (message && strlen(message)) { | |
| 1440 char *utf8 = str_to_utf8(message); | |
| 1441 y = xmlnode_insert_tag(x, "body"); | |
| 1442 xmlnode_insert_cdata(y, utf8, -1); | |
| 1443 g_free(utf8); | |
| 1444 } | |
| 1445 | |
| 1446 gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); | |
| 1447 xmlnode_free(x); | |
| 1448 } | |
| 1449 | |
| 1450 static void jabber_chat_leave(struct gaim_connection *gc, int id) | |
| 1451 { | |
| 1452 GSList *bcs = gc->buddy_chats; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1453 struct conversation *b = NULL; |
| 2086 | 1454 struct jabber_data *jd = gc->proto_data; |
| 1455 gjconn j = jd->jc; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1456 struct jabber_chat *jc = NULL; |
| 2086 | 1457 char *realwho; |
| 1458 xmlnode x; | |
| 1459 | |
| 1460 while (bcs) { | |
| 1461 b = bcs->data; | |
| 1462 if (id == b->id) | |
| 1463 break; | |
| 1464 bcs = bcs->next; | |
| 1465 } | |
| 1466 if (!bcs) | |
| 1467 return; | |
| 1468 | |
| 1469 bcs = jd->existing_chats; | |
| 1470 while (bcs) { | |
| 1471 jc = bcs->data; | |
| 1472 if (jc->b == b) | |
| 1473 break; | |
| 1474 bcs = bcs->next; | |
| 1475 } | |
| 1476 if (!bcs) | |
| 1477 return; | |
| 1478 | |
| 1479 realwho = g_strdup_printf("%s@%s", jc->Jid->user, jc->Jid->server); | |
| 1480 x = jutil_presnew(0, realwho, NULL); | |
| 1481 g_free(realwho); | |
| 1482 xmlnode_put_attrib(x, "type", "unavailable"); | |
| 1483 gjab_send(j, x); | |
| 1484 xmlnode_free(x); | |
| 1485 jc->b = NULL; | |
| 1486 } | |
| 1487 | |
|
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
1488 static int jabber_chat_send(struct gaim_connection *gc, int id, char *message) |
| 2086 | 1489 { |
| 1490 GSList *bcs = gc->buddy_chats; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1491 struct conversation *b = NULL; |
| 2086 | 1492 struct jabber_data *jd = gc->proto_data; |
| 1493 xmlnode x, y; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1494 struct jabber_chat *jc = NULL; |
| 2086 | 1495 char *chatname; |
| 1496 | |
| 1497 while (bcs) { | |
| 1498 b = bcs->data; | |
| 1499 if (id == b->id) | |
| 1500 break; | |
| 1501 bcs = bcs->next; | |
| 1502 } | |
| 1503 if (!bcs) | |
|
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
1504 return -EINVAL; |
| 2086 | 1505 |
| 1506 bcs = jd->existing_chats; | |
| 1507 while (bcs) { | |
| 1508 jc = bcs->data; | |
| 1509 if (jc->b == b) | |
| 1510 break; | |
| 1511 bcs = bcs->next; | |
| 1512 } | |
| 1513 if (!bcs) | |
|
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
1514 return -EINVAL; |
| 2086 | 1515 |
| 1516 x = xmlnode_new_tag("message"); | |
| 1517 xmlnode_put_attrib(x, "from", jid_full(jc->Jid)); | |
| 1518 chatname = g_strdup_printf("%s@%s", jc->Jid->user, jc->Jid->server); | |
| 1519 xmlnode_put_attrib(x, "to", chatname); | |
| 1520 g_free(chatname); | |
| 1521 xmlnode_put_attrib(x, "type", "groupchat"); | |
| 1522 | |
|
2289
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1523 if (message && strlen(message) > strlen("/topic ") && |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1524 !g_strncasecmp(message, "/topic ", strlen("/topic "))) { |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1525 char buf[8192]; |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1526 char *utf8 = str_to_utf8(message + strlen("/topic ")); |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1527 y = xmlnode_insert_tag(x, "subject"); |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1528 xmlnode_insert_cdata(y, utf8, -1); |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1529 y = xmlnode_insert_tag(x, "body"); |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1530 g_snprintf(buf, sizeof(buf), "/me has changed the subject to: %s", utf8); |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1531 xmlnode_insert_cdata(y, buf, -1); |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1532 g_free(utf8); |
|
38e156136896
[gaim-migrate @ 2299]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2278
diff
changeset
|
1533 } else if (message && strlen(message)) { |
| 2086 | 1534 char *utf8 = str_to_utf8(message); |
| 1535 y = xmlnode_insert_tag(x, "body"); | |
| 1536 xmlnode_insert_cdata(y, utf8, -1); | |
| 1537 g_free(utf8); | |
| 1538 } | |
| 1539 | |
| 1540 gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); | |
| 1541 xmlnode_free(x); | |
|
2167
edf8c5a70e5b
[gaim-migrate @ 2177]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2162
diff
changeset
|
1542 return 0; |
| 2086 | 1543 } |
| 1544 | |
| 1545 static void jabber_chat_whisper(struct gaim_connection *gc, int id, char *who, char *message) | |
| 1546 { | |
| 1547 GSList *bcs = gc->buddy_chats; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1548 struct conversation *b = NULL; |
| 2086 | 1549 struct jabber_data *jd = gc->proto_data; |
| 1550 xmlnode x, y; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1551 struct jabber_chat *jc = NULL; |
| 2086 | 1552 char *chatname; |
| 1553 | |
| 1554 while (bcs) { | |
| 1555 b = bcs->data; | |
| 1556 if (id == b->id) | |
| 1557 break; | |
| 1558 bcs = bcs->next; | |
| 1559 } | |
| 1560 if (!bcs) | |
| 1561 return; | |
| 1562 | |
| 1563 bcs = jd->existing_chats; | |
| 1564 while (bcs) { | |
| 1565 jc = bcs->data; | |
| 1566 if (jc->b == b) | |
| 1567 break; | |
| 1568 bcs = bcs->next; | |
| 1569 } | |
| 1570 if (!bcs) | |
| 1571 return; | |
| 1572 | |
| 1573 x = xmlnode_new_tag("message"); | |
| 1574 xmlnode_put_attrib(x, "from", jid_full(jc->Jid)); | |
| 1575 chatname = g_strdup_printf("%s@%s/%s", jc->Jid->user, jc->Jid->server, who); | |
| 1576 xmlnode_put_attrib(x, "to", chatname); | |
| 1577 g_free(chatname); | |
| 1578 xmlnode_put_attrib(x, "type", "normal"); | |
| 1579 | |
| 1580 if (message && strlen(message)) { | |
| 1581 char *utf8 = str_to_utf8(message); | |
| 1582 y = xmlnode_insert_tag(x, "body"); | |
| 1583 xmlnode_insert_cdata(y, utf8, -1); | |
| 1584 g_free(utf8); | |
| 1585 } | |
| 1586 | |
| 1587 gjab_send(((struct jabber_data *)gc->proto_data)->jc, x); | |
| 1588 xmlnode_free(x); | |
| 1589 } | |
| 1590 | |
| 1591 static char *jabber_normalize(const char *s) | |
| 1592 { | |
| 1593 static char buf[BUF_LEN]; | |
| 1594 char *t, *u; | |
| 1595 int x = 0; | |
| 1596 | |
| 1597 g_return_val_if_fail((s != NULL), NULL); | |
| 1598 | |
| 1599 u = t = g_strdup(s); | |
| 1600 | |
| 1601 g_strdown(t); | |
| 1602 | |
| 1603 while (*t && (x < BUF_LEN - 1)) { | |
| 1604 if (*t != ' ') | |
| 1605 buf[x++] = *t; | |
| 1606 t++; | |
| 1607 } | |
| 1608 buf[x] = '\0'; | |
| 1609 g_free(u); | |
| 1610 | |
| 1611 if (!strchr(buf, '@')) { | |
| 1612 strcat(buf, "@jabber.org"); /* this isn't always right, but eh */ | |
| 1613 } else if ((u = strchr(strchr(buf, '@'), '/')) != NULL) { | |
| 1614 *u = '\0'; | |
| 1615 } | |
| 1616 | |
| 1617 return buf; | |
| 1618 } | |
| 1619 | |
| 1620 static void jabber_get_info(struct gaim_connection *gc, char *who) { | |
| 1621 xmlnode x; | |
| 1622 char *id; | |
| 1623 struct jabber_data *jd = gc->proto_data; | |
| 1624 gjconn j = jd->jc; | |
| 1625 | |
| 1626 x = jutil_iqnew(JPACKET__GET, NS_VCARD); | |
| 1627 xmlnode_put_attrib(x, "to", who); | |
| 1628 id = gjab_getid(j); | |
| 1629 xmlnode_put_attrib(x, "id", id); | |
| 1630 | |
| 1631 gjab_send(j, x); | |
| 1632 | |
| 1633 xmlnode_free(x); | |
| 1634 | |
| 1635 } | |
| 1636 | |
|
2170
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1637 static GList *jabber_buddy_menu(struct gaim_connection *gc, char *who) { |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1638 GList *m = NULL; |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1639 struct proto_buddy_menu *pbm; |
| 2086 | 1640 |
|
2170
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1641 pbm = g_new0(struct proto_buddy_menu, 1); |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1642 pbm->label = _("Get Info"); |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1643 pbm->callback = jabber_get_info; |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1644 pbm->gc = gc; |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1645 m = g_list_append(m, pbm); |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1646 |
|
c24595d3c364
[gaim-migrate @ 2180]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2167
diff
changeset
|
1647 return m; |
| 2086 | 1648 } |
| 1649 | |
| 1650 static GList *jabber_away_states() { | |
| 1651 GList *m = NULL; | |
| 1652 | |
| 1653 m = g_list_append(m, "Online"); | |
| 1654 m = g_list_append(m, "Chatty"); | |
| 1655 m = g_list_append(m, "Away"); | |
| 1656 m = g_list_append(m, "Extended Away"); | |
| 1657 m = g_list_append(m, "Do Not Disturb"); | |
| 1658 | |
| 1659 return m; | |
| 1660 } | |
| 1661 | |
| 1662 static void jabber_set_away(struct gaim_connection *gc, char *state, char *message) | |
| 1663 { | |
| 1664 xmlnode x, y; | |
| 1665 struct jabber_data *jd = gc->proto_data; | |
| 1666 gjconn j = jd->jc; | |
| 1667 | |
| 1668 gc->away = NULL; /* never send an auto-response */ | |
| 1669 | |
| 1670 x = xmlnode_new_tag("presence"); | |
| 1671 | |
| 1672 if (!strcmp(state, GAIM_AWAY_CUSTOM)) { | |
| 1673 /* oh goody. Gaim is telling us what to do. */ | |
| 1674 if (message) { | |
| 1675 /* Gaim wants us to be away */ | |
| 1676 y = xmlnode_insert_tag(x, "show"); | |
| 1677 xmlnode_insert_cdata(y, "away", -1); | |
| 1678 y = xmlnode_insert_tag(x, "status"); | |
| 1679 xmlnode_insert_cdata(y, message, -1); | |
| 1680 gc->away = ""; | |
| 1681 } else { | |
| 1682 /* Gaim wants us to not be away */ | |
| 1683 /* but for Jabber, we can just send presence with no other information. */ | |
| 1684 } | |
| 1685 } else { | |
| 1686 /* state is one of our own strings. it won't be NULL. */ | |
| 1687 if (!strcmp(state, "Online")) { | |
| 1688 /* once again, we don't have to put anything here */ | |
| 1689 } else if (!strcmp(state, "Chatty")) { | |
| 1690 y = xmlnode_insert_tag(x, "show"); | |
| 1691 xmlnode_insert_cdata(y, "chat", -1); | |
| 1692 } else if (!strcmp(state, "Away")) { | |
| 1693 y = xmlnode_insert_tag(x, "show"); | |
| 1694 xmlnode_insert_cdata(y, "away", -1); | |
| 1695 gc->away = ""; | |
| 1696 } else if (!strcmp(state, "Extended Away")) { | |
| 1697 y = xmlnode_insert_tag(x, "show"); | |
| 1698 xmlnode_insert_cdata(y, "xa", -1); | |
| 1699 gc->away = ""; | |
| 1700 } else if (!strcmp(state, "Do Not Disturb")) { | |
| 1701 y = xmlnode_insert_tag(x, "show"); | |
| 1702 xmlnode_insert_cdata(y, "dnd", -1); | |
| 1703 gc->away = ""; | |
| 1704 } | |
| 1705 } | |
| 1706 | |
| 1707 gjab_send(j, x); | |
| 1708 xmlnode_free(x); | |
| 1709 } | |
| 1710 | |
| 1711 static void jabber_set_idle(struct gaim_connection *gc, int idle) { | |
| 1712 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; | |
| 1713 debug_printf("jabber_set_idle: setting idle %i\n", idle); | |
| 1714 jd->idle = idle ? time(NULL) - idle : idle; | |
| 1715 } | |
| 1716 | |
| 1717 static void jabber_keepalive(struct gaim_connection *gc) { | |
| 1718 struct jabber_data *jd = (struct jabber_data *)gc->proto_data; | |
| 1719 gjab_send_raw(jd->jc, " \t "); | |
| 1720 } | |
| 1721 | |
|
2154
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1722 static GList *jabber_user_opts() |
| 2086 | 1723 { |
|
2154
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1724 GList *m = NULL; |
|
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1725 struct proto_user_opt *puo; |
| 2086 | 1726 |
|
2154
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1727 puo = g_new0(struct proto_user_opt, 1); |
|
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1728 puo->label = "Port:"; |
|
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1729 puo->def = "5222"; |
|
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1730 puo->pos = USEROPT_PORT; |
|
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1731 m = g_list_append(m, puo); |
| 2086 | 1732 |
|
2154
cff133e0ec0c
[gaim-migrate @ 2164]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2137
diff
changeset
|
1733 return m; |
| 2086 | 1734 } |
| 1735 | |
| 1736 static struct prpl *my_protocol = NULL; | |
| 1737 | |
| 1738 void jabber_init(struct prpl *ret) | |
| 1739 { | |
| 1740 /* the NULL's aren't required but they're nice to have */ | |
| 1741 ret->protocol = PROTO_JABBER; | |
| 1742 ret->options = OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_CHAT_TOPIC; | |
| 1743 ret->name = jabber_name; | |
| 1744 ret->list_icon = jabber_list_icon; | |
| 1745 ret->away_states = jabber_away_states; | |
| 1746 ret->buddy_menu = jabber_buddy_menu; | |
| 1747 ret->user_opts = jabber_user_opts; | |
| 1748 ret->login = jabber_login; | |
| 1749 ret->close = jabber_close; | |
| 1750 ret->send_im = jabber_send_im; | |
| 1751 ret->set_info = NULL; | |
| 1752 ret->get_info = jabber_get_info; | |
| 1753 ret->set_away = jabber_set_away; | |
| 1754 ret->set_dir = NULL; | |
| 1755 ret->get_dir = NULL; | |
| 1756 ret->dir_search = NULL; | |
| 1757 ret->set_idle = jabber_set_idle; | |
| 1758 ret->change_passwd = NULL; | |
| 1759 ret->add_buddy = jabber_add_buddy; | |
| 1760 ret->add_buddies = NULL; | |
| 1761 ret->remove_buddy = jabber_remove_buddy; | |
| 1762 ret->add_permit = NULL; | |
| 1763 ret->add_deny = NULL; | |
| 1764 ret->rem_permit = NULL; | |
| 1765 ret->rem_deny = NULL; | |
| 1766 ret->set_permit_deny = NULL; | |
| 1767 ret->warn = NULL; | |
|
2205
cff4fbe01c7b
[gaim-migrate @ 2215]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2170
diff
changeset
|
1768 ret->chat_info = jabber_chat_info; |
| 2086 | 1769 ret->join_chat = jabber_join_chat; |
| 1770 ret->chat_invite = jabber_chat_invite; | |
| 1771 ret->chat_leave = jabber_chat_leave; | |
| 1772 ret->chat_whisper = jabber_chat_whisper; | |
| 1773 ret->chat_send = jabber_chat_send; | |
| 1774 ret->keepalive = jabber_keepalive; | |
| 1775 ret->normalize = jabber_normalize; | |
| 1776 | |
| 1777 my_protocol = ret; | |
| 1778 } | |
| 1779 | |
| 1780 #ifndef STATIC | |
| 1781 | |
| 1782 char *gaim_plugin_init(GModule *handle) | |
| 1783 { | |
| 1784 load_protocol(jabber_init, sizeof(struct prpl)); | |
| 1785 return NULL; | |
| 1786 } | |
| 1787 | |
| 1788 void gaim_plugin_remove() | |
| 1789 { | |
| 1790 struct prpl *p = find_prpl(PROTO_JABBER); | |
| 1791 if (p == my_protocol) | |
| 1792 unload_protocol(p); | |
| 1793 } | |
| 1794 | |
| 1795 char *name() | |
| 1796 { | |
| 1797 return "Jabber"; | |
| 1798 } | |
| 1799 | |
| 1800 char *description() | |
| 1801 { | |
|
2162
a464da684307
[gaim-migrate @ 2172]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2154
diff
changeset
|
1802 return PRPL_DESC("Jabber"); |
| 2086 | 1803 } |
| 1804 | |
| 1805 #endif |
