comparison src/protocols/oscar/oscar.c @ 2246:933346315b9b

[gaim-migrate @ 2256] heh. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sun, 09 Sep 2001 10:07:14 +0000
parents 5d8b6100a9cc
children cef6d4e81aec
comparison
equal deleted inserted replaced
2245:31157c54fe6e 2246:933346315b9b
58 static int gaim_caps = AIM_CAPS_CHAT | 58 static int gaim_caps = AIM_CAPS_CHAT |
59 AIM_CAPS_BUDDYICON | 59 AIM_CAPS_BUDDYICON |
60 AIM_CAPS_IMIMAGE; 60 AIM_CAPS_IMIMAGE;
61 61
62 struct oscar_data { 62 struct oscar_data {
63 struct aim_session_t *sess; 63 aim_session_t *sess;
64 struct aim_conn_t *conn; 64 aim_conn_t *conn;
65 65
66 guint cnpa; 66 guint cnpa;
67 guint paspa; 67 guint paspa;
68 68
69 int create_exchange; 69 int create_exchange;
83 }; 83 };
84 84
85 struct chat_connection { 85 struct chat_connection {
86 char *name; 86 char *name;
87 char *show; /* AOL did something funny to us */ 87 char *show; /* AOL did something funny to us */
88 int exchange; 88 fu16_t exchange; /* XXX should have instance here too */
89 int fd; /* this is redundant since we have the conn below */ 89 int fd; /* this is redundant since we have the conn below */
90 struct aim_conn_t *conn; 90 aim_conn_t *conn;
91 int inpa; 91 int inpa;
92 int id; 92 int id;
93 struct gaim_connection *gc; /* i hate this. */ 93 struct gaim_connection *gc; /* i hate this. */
94 struct conversation *cnv; /* bah. */ 94 struct conversation *cnv; /* bah. */
95 int maxlen; 95 int maxlen;
98 98
99 struct direct_im { 99 struct direct_im {
100 struct gaim_connection *gc; 100 struct gaim_connection *gc;
101 char name[80]; 101 char name[80];
102 int watcher; 102 int watcher;
103 struct aim_conn_t *conn; 103 aim_conn_t *conn;
104 }; 104 };
105 105
106 struct ask_direct { 106 struct ask_direct {
107 struct gaim_connection *gc; 107 struct gaim_connection *gc;
108 char *sn; 108 char *sn;
109 struct aim_directim_priv *priv; 109 char ip[64];
110 fu8_t cookie[8];
110 }; 111 };
111 112
112 struct icon_req { 113 struct icon_req {
113 char *user; 114 char *user;
114 time_t timestamp; 115 time_t timestamp;
115 unsigned long length; 116 unsigned long length;
116 unsigned long checksum; 117 unsigned long checksum;
117 gboolean request; 118 gboolean request;
118 }; 119 };
119 120
120 static struct direct_im *find_direct_im(struct oscar_data *od, char *who) { 121 static struct direct_im *find_direct_im(struct oscar_data *od, const char *who) {
121 GSList *d = od->direct_ims; 122 GSList *d = od->direct_ims;
122 char *n = g_strdup(normalize(who)); 123 char *n = g_strdup(normalize(who));
123 struct direct_im *m = NULL; 124 struct direct_im *m = NULL;
124 125
125 while (d) { 126 while (d) {
174 175
175 return c; 176 return c;
176 } 177 }
177 178
178 static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc, 179 static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc,
179 struct aim_conn_t *conn) { 180 aim_conn_t *conn) {
180 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats; 181 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats;
181 struct chat_connection *c = NULL; 182 struct chat_connection *c = NULL;
182 183
183 while (g) { 184 while (g) {
184 c = (struct chat_connection *)g->data; 185 c = (struct chat_connection *)g->data;
189 } 190 }
190 191
191 return c; 192 return c;
192 } 193 }
193 194
194 static int gaim_parse_auth_resp (struct aim_session_t *, struct command_rx_struct *, ...); 195 static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...);
195 static int gaim_parse_login (struct aim_session_t *, struct command_rx_struct *, ...); 196 static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...);
196 static int gaim_server_ready (struct aim_session_t *, struct command_rx_struct *, ...); 197 static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...);
197 static int gaim_handle_redirect (struct aim_session_t *, struct command_rx_struct *, ...); 198 static int gaim_info_change (aim_session_t *, aim_frame_t *, ...);
198 static int gaim_info_change (struct aim_session_t *, struct command_rx_struct *, ...); 199 static int gaim_account_confirm (aim_session_t *, aim_frame_t *, ...);
199 static int gaim_account_confirm (struct aim_session_t *, struct command_rx_struct *, ...); 200 static int gaim_parse_oncoming (aim_session_t *, aim_frame_t *, ...);
200 static int gaim_parse_oncoming (struct aim_session_t *, struct command_rx_struct *, ...); 201 static int gaim_parse_offgoing (aim_session_t *, aim_frame_t *, ...);
201 static int gaim_parse_offgoing (struct aim_session_t *, struct command_rx_struct *, ...); 202 static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...);
202 static int gaim_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *, ...); 203 static int gaim_parse_misses (aim_session_t *, aim_frame_t *, ...);
203 static int gaim_parse_misses (struct aim_session_t *, struct command_rx_struct *, ...); 204 static int gaim_parse_user_info (aim_session_t *, aim_frame_t *, ...);
204 static int gaim_parse_user_info (struct aim_session_t *, struct command_rx_struct *, ...); 205 static int gaim_parse_motd (aim_session_t *, aim_frame_t *, ...);
205 static int gaim_parse_motd (struct aim_session_t *, struct command_rx_struct *, ...); 206 static int gaim_chatnav_info (aim_session_t *, aim_frame_t *, ...);
206 static int gaim_chatnav_info (struct aim_session_t *, struct command_rx_struct *, ...); 207 static int gaim_chat_join (aim_session_t *, aim_frame_t *, ...);
207 static int gaim_chat_join (struct aim_session_t *, struct command_rx_struct *, ...); 208 static int gaim_chat_leave (aim_session_t *, aim_frame_t *, ...);
208 static int gaim_chat_leave (struct aim_session_t *, struct command_rx_struct *, ...); 209 static int gaim_chat_info_update (aim_session_t *, aim_frame_t *, ...);
209 static int gaim_chat_info_update (struct aim_session_t *, struct command_rx_struct *, ...); 210 static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...);
210 static int gaim_chat_incoming_msg(struct aim_session_t *, struct command_rx_struct *, ...); 211 static int gaim_parse_msgack (aim_session_t *, aim_frame_t *, ...);
211 static int gaim_parse_msgack (struct aim_session_t *, struct command_rx_struct *, ...); 212 static int gaim_parse_ratechange (aim_session_t *, aim_frame_t *, ...);
212 static int gaim_parse_ratechange (struct aim_session_t *, struct command_rx_struct *, ...); 213 static int gaim_parse_evilnotify (aim_session_t *, aim_frame_t *, ...);
213 static int gaim_parse_evilnotify (struct aim_session_t *, struct command_rx_struct *, ...); 214 static int gaim_parse_searcherror(aim_session_t *, aim_frame_t *, ...);
214 static int gaim_parse_searcherror(struct aim_session_t *, struct command_rx_struct *, ...); 215 static int gaim_parse_searchreply(aim_session_t *, aim_frame_t *, ...);
215 static int gaim_parse_searchreply(struct aim_session_t *, struct command_rx_struct *, ...); 216 static int gaim_bosrights (aim_session_t *, aim_frame_t *, ...);
216 static int gaim_bosrights (struct aim_session_t *, struct command_rx_struct *, ...); 217 static int rateresp_bos (aim_session_t *, aim_frame_t *, ...);
217 static int gaim_rateresp (struct aim_session_t *, struct command_rx_struct *, ...); 218 static int rateresp_auth (aim_session_t *, aim_frame_t *, ...);
218 static int gaim_reportinterval (struct aim_session_t *, struct command_rx_struct *, ...); 219 static int gaim_parse_msgerr (aim_session_t *, aim_frame_t *, ...);
219 static int gaim_parse_msgerr (struct aim_session_t *, struct command_rx_struct *, ...); 220 static int gaim_parse_buddyrights(aim_session_t *, aim_frame_t *, ...);
220 static int gaim_parse_buddyrights(struct aim_session_t *, struct command_rx_struct *, ...); 221 static int gaim_parse_locerr (aim_session_t *, aim_frame_t *, ...);
221 static int gaim_parse_locerr (struct aim_session_t *, struct command_rx_struct *, ...); 222 static int gaim_icbm_param_info (aim_session_t *, aim_frame_t *, ...);
222 static int gaim_icbm_param_info (struct aim_session_t *, struct command_rx_struct *, ...); 223 static int gaim_parse_genericerr (aim_session_t *, aim_frame_t *, ...);
223 static int gaim_parse_genericerr (struct aim_session_t *, struct command_rx_struct *, ...); 224 static int gaim_memrequest (aim_session_t *, aim_frame_t*, ...);
224 static int gaim_memrequest (struct aim_session_t *, struct command_rx_struct *, ...); 225 static int server_ready_bos (aim_session_t *, aim_frame_t*, ...);
225 226
226 static int gaim_directim_initiate (struct aim_session_t *, struct command_rx_struct *, ...); 227 static int gaim_directim_initiate (aim_session_t *, aim_frame_t *, ...);
227 static int gaim_directim_incoming (struct aim_session_t *, struct command_rx_struct *, ...); 228 static int gaim_directim_incoming (aim_session_t *, aim_frame_t *, ...);
228 static int gaim_directim_disconnect(struct aim_session_t *, struct command_rx_struct *, ...); 229 static int gaim_directim_typing (aim_session_t *, aim_frame_t *, ...);
229 static int gaim_directim_typing (struct aim_session_t *, struct command_rx_struct *, ...);
230 230
231 static char *msgerrreason[] = { 231 static char *msgerrreason[] = {
232 "Invalid error", 232 "Invalid error",
233 "Invalid SNAC", 233 "Invalid SNAC",
234 "Rate to host", 234 "Rate to host",
255 "Queue full", 255 "Queue full",
256 "Not while on AOL" 256 "Not while on AOL"
257 }; 257 };
258 static int msgerrreasonlen = 25; 258 static int msgerrreasonlen = 25;
259 259
260 static void gaim_directim_disconnect(aim_session_t *sess, aim_conn_t *conn) {
261 struct gaim_connection *gc = sess->aux_data;
262 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
263 struct conversation *cnv;
264 struct direct_im *dim;
265 char *sn;
266 char buf[256];
267
268 sn = g_strdup(aim_directim_getsn(conn));
269
270 debug_printf("%s disconnected Direct IM.\n", sn);
271
272 dim = find_direct_im(od, sn);
273 od->direct_ims = g_slist_remove(od->direct_ims, dim);
274 gaim_input_remove(dim->watcher);
275
276 g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), sn);
277 if ((cnv = find_conversation(sn)))
278 write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL));
279
280 g_free(dim); /* I guess? I don't see it anywhere else... -- mid */
281 g_free(sn);
282
283 return;
284 }
285
260 static void oscar_callback(gpointer data, gint source, 286 static void oscar_callback(gpointer data, gint source,
261 GaimInputCondition condition) { 287 GaimInputCondition condition) {
262 struct aim_conn_t *conn = (struct aim_conn_t *)data; 288 aim_conn_t *conn = (aim_conn_t *)data;
263 struct aim_session_t *sess = aim_conn_getsess(conn); 289 aim_session_t *sess = aim_conn_getsess(conn);
264 struct gaim_connection *gc = sess ? sess->aux_data : NULL; 290 struct gaim_connection *gc = sess ? sess->aux_data : NULL;
265 struct oscar_data *odata; 291 struct oscar_data *odata;
266 292
267 if (!gc) { 293 if (!gc) {
268 /* gc is null. we return, else we seg SIGSEG on next line. */ 294 /* gc is null. we return, else we seg SIGSEG on next line. */
282 if (condition & GAIM_INPUT_READ) { 308 if (condition & GAIM_INPUT_READ) {
283 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) { 309 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
284 debug_printf("got information on rendezvous\n"); 310 debug_printf("got information on rendezvous\n");
285 if (aim_handlerendconnect(odata->sess, conn) < 0) { 311 if (aim_handlerendconnect(odata->sess, conn) < 0) {
286 debug_printf(_("connection error (rend)\n")); 312 debug_printf(_("connection error (rend)\n"));
313 aim_conn_kill(odata->sess, &conn);
287 } 314 }
288 } else { 315 } else {
289 if (aim_get_command(odata->sess, conn) >= 0) { 316 if (aim_get_command(odata->sess, conn) >= 0) {
290 aim_rxdispatch(odata->sess); 317 aim_rxdispatch(odata->sess);
291 if (odata->killme) 318 if (odata->killme)
326 gaim_input_remove(odata->paspa); 353 gaim_input_remove(odata->paspa);
327 odata->paspa = 0; 354 odata->paspa = 0;
328 debug_printf("removing authconn input watcher\n"); 355 debug_printf("removing authconn input watcher\n");
329 aim_conn_kill(odata->sess, &conn); 356 aim_conn_kill(odata->sess, &conn);
330 } else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) { 357 } else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
331 debug_printf("No handler for rendezvous disconnect (%d).\n", 358 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)
332 source); 359 gaim_directim_disconnect(odata->sess, conn);
360 else {
361 debug_printf("No handler for rendezvous disconnect (%d).\n",
362 source);
363 }
333 aim_conn_kill(odata->sess, &conn); 364 aim_conn_kill(odata->sess, &conn);
334 } else { 365 } else {
335 debug_printf("holy crap! generic connection error! %d\n", 366 debug_printf("holy crap! generic connection error! %d\n",
336 conn->type); 367 conn->type);
337 aim_conn_kill(odata->sess, &conn); 368 aim_conn_kill(odata->sess, &conn);
339 } 370 }
340 } 371 }
341 } 372 }
342 } 373 }
343 374
344 static void oscar_debug(struct aim_session_t *sess, int level, const char *format, va_list va) { 375 static void oscar_debug(aim_session_t *sess, int level, const char *format, va_list va) {
345 char *s = g_strdup_vprintf(format, va); 376 char *s = g_strdup_vprintf(format, va);
346 char buf[256]; 377 char buf[256];
347 char *t; 378 char *t;
348 struct gaim_connection *gc = sess->aux_data; 379 struct gaim_connection *gc = sess->aux_data;
349 380
358 389
359 static void oscar_login_connect(gpointer data, gint source, GaimInputCondition cond) 390 static void oscar_login_connect(gpointer data, gint source, GaimInputCondition cond)
360 { 391 {
361 struct gaim_connection *gc = data; 392 struct gaim_connection *gc = data;
362 struct oscar_data *odata; 393 struct oscar_data *odata;
363 struct aim_session_t *sess; 394 aim_session_t *sess;
364 struct aim_conn_t *conn; 395 aim_conn_t *conn;
365 396
366 if (!g_slist_find(connections, gc)) { 397 if (!g_slist_find(connections, gc)) {
367 close(source); 398 close(source);
368 return; 399 return;
369 } 400 }
383 oscar_callback, conn); 414 oscar_callback, conn);
384 debug_printf(_("Password sent, waiting for response\n")); 415 debug_printf(_("Password sent, waiting for response\n"));
385 } 416 }
386 417
387 static void oscar_login(struct aim_user *user) { 418 static void oscar_login(struct aim_user *user) {
388 struct aim_session_t *sess; 419 aim_session_t *sess;
389 struct aim_conn_t *conn; 420 aim_conn_t *conn;
390 char buf[256]; 421 char buf[256];
391 struct gaim_connection *gc = new_gaim_conn(user); 422 struct gaim_connection *gc = new_gaim_conn(user);
392 struct oscar_data *odata = gc->proto_data = g_new0(struct oscar_data, 1); 423 struct oscar_data *odata = gc->proto_data = g_new0(struct oscar_data, 1);
393 odata->create_exchange = 0; 424 odata->create_exchange = 0;
394 425
395 debug_printf(_("Logging in %s\n"), user->username); 426 debug_printf(_("Logging in %s\n"), user->username);
396 427
397 sess = g_new0(struct aim_session_t, 1); 428 sess = g_new0(aim_session_t, 1);
398 429
399 aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0); 430 aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
400 aim_setdebuggingcb(sess, oscar_debug); 431 aim_setdebuggingcb(sess, oscar_debug);
401 432
402 /* we need an immediate queue because we don't use a while-loop to 433 /* we need an immediate queue because we don't use a while-loop to
474 } 505 }
475 506
476 static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) { 507 static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) {
477 struct gaim_connection *gc = data; 508 struct gaim_connection *gc = data;
478 struct oscar_data *odata; 509 struct oscar_data *odata;
479 struct aim_session_t *sess; 510 aim_session_t *sess;
480 struct aim_conn_t *bosconn; 511 aim_conn_t *bosconn;
481 512
482 if (!g_slist_find(connections, gc)) { 513 if (!g_slist_find(connections, gc)) {
483 close(source); 514 close(source);
484 return; 515 return;
485 } 516 }
498 gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ, 529 gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ,
499 oscar_callback, bosconn); 530 oscar_callback, bosconn);
500 set_login_progress(gc, 4, _("Connection established, cookie sent")); 531 set_login_progress(gc, 4, _("Connection established, cookie sent"));
501 } 532 }
502 533
503 int gaim_parse_auth_resp(struct aim_session_t *sess, 534 static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) {
504 struct command_rx_struct *command, ...) { 535 va_list ap;
505 va_list ap; 536 aim_conn_t *bosconn = NULL;
506 struct aim_conn_t *bosconn = NULL;
507 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL; 537 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
508 unsigned char *cookie = NULL; 538 fu8_t *cookie = NULL;
509 int errorcode = 0, regstatus = 0; 539 int errorcode = 0, regstatus = 0;
510 int latestbuild = 0, latestbetabuild = 0; 540 int latestbuild = 0, latestbetabuild = 0;
511 char *latestrelease = NULL, *latestbeta = NULL; 541 char *latestrelease = NULL, *latestbeta = NULL;
512 char *latestreleaseurl = NULL, *latestbetaurl = NULL; 542 char *latestreleaseurl = NULL, *latestbetaurl = NULL;
513 char *latestreleaseinfo = NULL, *latestbetainfo = NULL; 543 char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
518 struct oscar_data *od = gc->proto_data; 548 struct oscar_data *od = gc->proto_data;
519 user = gc->user; 549 user = gc->user;
520 port = user->proto_opt[USEROPT_AUTHPORT][0] ? 550 port = user->proto_opt[USEROPT_AUTHPORT][0] ?
521 atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT, 551 atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT,
522 552
523 va_start(ap, command); 553 va_start(ap, fr);
524 sn = va_arg(ap, char *); 554 sn = va_arg(ap, char *);
525 errorcode = va_arg(ap, int); 555 errorcode = va_arg(ap, int);
526 errurl = va_arg(ap, char *); 556 errurl = va_arg(ap, char *);
527 regstatus = va_arg(ap, int); 557 regstatus = va_arg(ap, int);
528 email = va_arg(ap, char *); 558 email = va_arg(ap, char *);
587 latestbeta, latestbetabuild, latestbetaurl, latestbetainfo); 617 latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
588 if (latestrelease) 618 if (latestrelease)
589 debug_printf("Latest WinAIM released version %s, build %d, at %s (%s)\n", 619 debug_printf("Latest WinAIM released version %s, build %d, at %s (%s)\n",
590 latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo); 620 latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
591 debug_printf("Closing auth connection...\n"); 621 debug_printf("Closing auth connection...\n");
592 aim_conn_kill(sess, &command->conn); 622 aim_conn_kill(sess, &fr->conn);
593 623
594 bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL); 624 bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL);
595 if (bosconn == NULL) { 625 if (bosconn == NULL) {
596 hide_login_progress(gc, _("Internal Error")); 626 hide_login_progress(gc, _("Internal Error"));
597 od->killme = TRUE; 627 od->killme = TRUE;
598 return 0; 628 return 0;
599 } 629 }
600 630
601 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0); 631 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0);
602 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, gaim_rateresp, 0); /* rate info */ 632 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, rateresp_bos, 0); /* rate info */
603 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0); 633 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
604 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, gaim_server_ready, 0); 634 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, server_ready_bos, 0);
605 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0); 635 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
606 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0); 636 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0);
607 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, gaim_reportinterval, 0);
608 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0); 637 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0);
609 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0); 638 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0);
610 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0); 639 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0);
611 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0); 640 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0);
612 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0); 641 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0);
650 struct gaim_connection *gc; 679 struct gaim_connection *gc;
651 unsigned long offset; 680 unsigned long offset;
652 unsigned long len; 681 unsigned long len;
653 char *modname; 682 char *modname;
654 int fd; 683 int fd;
655 struct aim_conn_t *conn; 684 aim_conn_t *conn;
656 unsigned int inpa; 685 unsigned int inpa;
657 }; 686 };
658 687
659 static void damn_you(gpointer data, gint source, GaimInputCondition c) 688 static void damn_you(gpointer data, gint source, GaimInputCondition c)
660 { 689 {
717 } 746 }
718 747
719 /* size of icbmui.ocm, the largest module in AIM 3.5 */ 748 /* size of icbmui.ocm, the largest module in AIM 3.5 */
720 #define AIM_MAX_FILE_SIZE 98304 749 #define AIM_MAX_FILE_SIZE 98304
721 750
722 int gaim_memrequest(struct aim_session_t *sess, 751 int gaim_memrequest(aim_session_t *sess, aim_frame_t *fr, ...) {
723 struct command_rx_struct *command, ...) {
724 va_list ap; 752 va_list ap;
725 struct pieceofcrap *pos; 753 struct pieceofcrap *pos;
726 unsigned long offset, len; 754 fu32_t offset, len;
727 char *modname; 755 char *modname;
728 int fd; 756 int fd;
729 757
730 va_start(ap, command); 758 va_start(ap, fr);
731 offset = va_arg(ap, unsigned long); 759 offset = (fu32_t)va_arg(ap, unsigned long);
732 len = va_arg(ap, unsigned long); 760 len = (fu32_t)va_arg(ap, unsigned long);
733 modname = va_arg(ap, char *); 761 modname = va_arg(ap, char *);
734 va_end(ap); 762 va_end(ap);
735 763
736 debug_printf("offset: %d, len: %d, file: %s\n", offset, len, modname ? modname : "aim.exe"); 764 debug_printf("offset: %d, len: %d, file: %s\n", offset, len, modname ? modname : "aim.exe");
737 if (len == 0) { 765 if (len == 0) {
738 debug_printf("len is 0, hashing NULL\n"); 766 debug_printf("len is 0, hashing NULL\n");
739 aim_sendmemblock(sess, command->conn, offset, len, NULL, 767 aim_sendmemblock(sess, fr->conn, offset, len, NULL,
740 AIM_SENDMEMBLOCK_FLAG_ISREQUEST); 768 AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
741 return 1; 769 return 1;
742 } 770 }
743 /* uncomment this when you're convinced it's right. remember, it's been wrong before. 771 /* uncomment this when you're convinced it's right. remember, it's been wrong before.
744 if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) { 772 if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) {
767 } 795 }
768 */ 796 */
769 797
770 pos = g_new0(struct pieceofcrap, 1); 798 pos = g_new0(struct pieceofcrap, 1);
771 pos->gc = sess->aux_data; 799 pos->gc = sess->aux_data;
772 pos->conn = command->conn; 800 pos->conn = fr->conn;
773 801
774 pos->offset = offset; 802 pos->offset = offset;
775 pos->len = len; 803 pos->len = len;
776 pos->modname = modname ? g_strdup(modname) : NULL; 804 pos->modname = modname ? g_strdup(modname) : NULL;
777 805
786 pos->fd = fd; 814 pos->fd = fd;
787 815
788 return 1; 816 return 1;
789 } 817 }
790 818
791 int gaim_parse_login(struct aim_session_t *sess, 819 static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) {
792 struct command_rx_struct *command, ...) {
793 #if 0 820 #if 0
794 struct client_info_s info = {"gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b}; 821 struct client_info_s info = {"gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b};
795 #else 822 #else
796 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD; 823 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
797 #endif 824 #endif
798 char *key; 825 char *key;
799 va_list ap; 826 va_list ap;
800 struct gaim_connection *gc = sess->aux_data; 827 struct gaim_connection *gc = sess->aux_data;
801 828
802 va_start(ap, command); 829 va_start(ap, fr);
803 key = va_arg(ap, char *); 830 key = va_arg(ap, char *);
804 va_end(ap); 831 va_end(ap);
805 832
806 aim_send_login(sess, command->conn, gc->username, gc->password, &info, key); 833 aim_send_login(sess, fr->conn, gc->username, gc->password, &info, key);
807 return 1; 834
808 } 835 return 1;
809 836 }
810 int gaim_server_ready(struct aim_session_t *sess, 837
811 struct command_rx_struct *command, ...) { 838 static int server_ready_auth(aim_session_t *sess, aim_frame_t *fr, ...) {
812 static int id = 1;
813 struct gaim_connection *gc = sess->aux_data; 839 struct gaim_connection *gc = sess->aux_data;
814 struct oscar_data *od = gc->proto_data; 840 struct oscar_data *od = gc->proto_data;
841
842 aim_auth_setversions(sess, fr->conn);
843 aim_bos_reqrate(sess, fr->conn);
844 debug_printf("done with AUTH ServerReady\n");
845 if (od->chpass) {
846 debug_printf("changing password\n");
847 aim_auth_changepasswd(sess, fr->conn, od->newp, od->oldp);
848 g_free(od->oldp);
849 g_free(od->newp);
850 od->chpass = FALSE;
851 }
852 if (od->conf) {
853 debug_printf("confirming account\n");
854 aim_auth_reqconfirm(sess, fr->conn);
855 od->conf = FALSE;
856 }
857 if (od->reqemail) {
858 debug_printf("requesting email\n");
859 aim_auth_getinfo(sess, fr->conn, 0x0011);
860 od->reqemail = FALSE;
861 }
862
863 return 1;
864 }
865
866 static int server_ready_bos(aim_session_t *sess, aim_frame_t *fr, ...) {
867 aim_setversions(sess, fr->conn);
868 aim_bos_reqrate(sess, fr->conn); /* request rate info */
869 debug_printf("done with BOS ServerReady\n");
870
871 return 1;
872 }
873
874 static int server_ready_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) {
875 debug_printf("chatnav: got server ready\n");
876 aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0);
877 aim_bos_reqrate(sess, fr->conn);
878 aim_bos_ackrateresp(sess, fr->conn);
879 aim_chatnav_clientready(sess, fr->conn);
880 aim_chatnav_reqrights(sess, fr->conn);
881
882 return 1;
883 }
884
885 static int server_ready_chat(aim_session_t *sess, aim_frame_t *fr, ...) {
886 struct gaim_connection *gc = sess->aux_data;
815 struct chat_connection *chatcon; 887 struct chat_connection *chatcon;
816 switch (command->conn->type) { 888 static int id = 1;
817 case AIM_CONN_TYPE_AUTH: 889
818 aim_auth_setversions(sess, command->conn); 890 debug_printf("chat: got server ready\n");
819 aim_bos_reqrate(sess, command->conn); 891 aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0);
820 debug_printf("done with AUTH ServerReady\n"); 892 aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0);
821 if (od->chpass) { 893 aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0);
822 debug_printf("changing password\n"); 894 aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0);
823 aim_auth_changepasswd(sess, command->conn, od->newp, od->oldp); 895 aim_bos_reqrate(sess, fr->conn);
824 g_free(od->oldp); 896 aim_bos_ackrateresp(sess, fr->conn);
825 g_free(od->newp); 897 aim_chat_clientready(sess, fr->conn);
826 od->chpass = FALSE; 898 chatcon = find_oscar_chat_by_conn(gc, fr->conn);
827 } 899 chatcon->id = id;
828 if (od->conf) { 900 chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
829 debug_printf("confirming account\n"); 901
830 aim_auth_reqconfirm(sess, command->conn); 902 return 1;
831 od->conf = FALSE; 903 }
832 } 904
833 if (od->reqemail) { 905 static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) {
834 debug_printf("requesting email\n");
835 aim_auth_getinfo(sess, command->conn, 0x0011);
836 od->reqemail = FALSE;
837 }
838 break;
839 case AIM_CONN_TYPE_BOS:
840 aim_setversions(sess, command->conn);
841 aim_bos_reqrate(sess, command->conn); /* request rate info */
842 debug_printf("done with BOS ServerReady\n");
843 break;
844 case AIM_CONN_TYPE_CHATNAV:
845 debug_printf("chatnav: got server ready\n");
846 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0);
847 aim_bos_reqrate(sess, command->conn);
848 aim_bos_ackrateresp(sess, command->conn);
849 aim_chatnav_clientready(sess, command->conn);
850 aim_chatnav_reqrights(sess, command->conn);
851 break;
852 case AIM_CONN_TYPE_CHAT:
853 debug_printf("chat: got server ready\n");
854 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0);
855 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0);
856 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0);
857 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0);
858 aim_bos_reqrate(sess, command->conn);
859 aim_bos_ackrateresp(sess, command->conn);
860 aim_chat_clientready(sess, command->conn);
861 chatcon = find_oscar_chat_by_conn(gc, command->conn);
862 chatcon->id = id;
863 chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
864 break;
865 case AIM_CONN_TYPE_RENDEZVOUS:
866 break;
867 default: /* huh? */
868 debug_printf("server ready: got unexpected connection type %04x\n", command->conn->type);
869 break;
870 }
871 return 1;
872 }
873
874 static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond)
875 {
876 struct gaim_connection *gc = data; 906 struct gaim_connection *gc = data;
877 struct oscar_data *odata; 907 struct oscar_data *odata;
878 struct aim_session_t *sess; 908 aim_session_t *sess;
879 struct aim_conn_t *tstconn; 909 aim_conn_t *tstconn;
880 910
881 if (!g_slist_find(connections, gc)) { 911 if (!g_slist_find(connections, gc)) {
882 close(source); 912 close(source);
883 return; 913 return;
884 } 914 }
893 return; 923 return;
894 } 924 }
895 925
896 aim_conn_completeconnect(sess, tstconn); 926 aim_conn_completeconnect(sess, tstconn);
897 odata->cnpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ, 927 odata->cnpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ,
898 oscar_callback, tstconn); 928 oscar_callback, tstconn);
899 debug_printf("chatnav: connected\n"); 929 debug_printf("chatnav: connected\n");
900 } 930 }
901 931
902 static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition cond) 932 static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition cond)
903 { 933 {
904 struct gaim_connection *gc = data; 934 struct gaim_connection *gc = data;
905 struct oscar_data *odata; 935 struct oscar_data *odata;
906 struct aim_session_t *sess; 936 aim_session_t *sess;
907 struct aim_conn_t *tstconn; 937 aim_conn_t *tstconn;
908 938
909 if (!g_slist_find(connections, gc)) { 939 if (!g_slist_find(connections, gc)) {
910 close(source); 940 close(source);
911 return; 941 return;
912 } 942 }
930 static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition cond) 960 static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition cond)
931 { 961 {
932 struct chat_connection *ccon = data; 962 struct chat_connection *ccon = data;
933 struct gaim_connection *gc = ccon->gc; 963 struct gaim_connection *gc = ccon->gc;
934 struct oscar_data *odata; 964 struct oscar_data *odata;
935 struct aim_session_t *sess; 965 aim_session_t *sess;
936 struct aim_conn_t *tstconn; 966 aim_conn_t *tstconn;
937 967
938 if (!g_slist_find(connections, gc)) { 968 if (!g_slist_find(connections, gc)) {
939 close(source); 969 close(source);
940 g_free(ccon->show); 970 g_free(ccon->show);
941 g_free(ccon->name); 971 g_free(ccon->name);
961 oscar_callback, tstconn); 991 oscar_callback, tstconn);
962 odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon); 992 odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon);
963 aim_chat_attachname(tstconn, ccon->name); 993 aim_chat_attachname(tstconn, ccon->name);
964 } 994 }
965 995
966 int gaim_handle_redirect(struct aim_session_t *sess, 996 /* Hrmph. I don't know how to make this look better. --mid */
967 struct command_rx_struct *command, ...) { 997 static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) {
968 va_list ap; 998 va_list ap;
969 int serviceid; 999 fu16_t serviceid;
970 char *ip; 1000 char *ip;
971 unsigned char *cookie; 1001 fu8_t *cookie;
972 struct gaim_connection *gc = sess->aux_data; 1002 struct gaim_connection *gc = sess->aux_data;
973 struct aim_user *user = gc->user; 1003 struct aim_user *user = gc->user;
974 struct aim_conn_t *tstconn; 1004 aim_conn_t *tstconn;
975 int i; 1005 int i;
976 char *host; 1006 char *host;
977 int port; 1007 int port;
978 1008
979 port = user->proto_opt[USEROPT_AUTHPORT][0] ? 1009 port = user->proto_opt[USEROPT_AUTHPORT][0] ?
980 atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT, 1010 atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT,
981 1011
982 va_start(ap, command); 1012 va_start(ap, fr);
983 serviceid = va_arg(ap, int); 1013 serviceid = (fu16_t)va_arg(ap, unsigned int);
984 ip = va_arg(ap, char *); 1014 ip = va_arg(ap, char *);
985 cookie = va_arg(ap, unsigned char *); 1015 cookie = (fu8_t *)va_arg(ap, unsigned char *);
986 1016
987 for (i = 0; i < (int)strlen(ip); i++) { 1017 for (i = 0; i < (int)strlen(ip); i++) {
988 if (ip[i] == ':') { 1018 if (ip[i] == ':') {
989 port = atoi(&(ip[i+1])); 1019 port = atoi(&(ip[i+1]));
990 break; 1020 break;
999 if (tstconn == NULL) { 1029 if (tstconn == NULL) {
1000 debug_printf("unable to reconnect with authorizer\n"); 1030 debug_printf("unable to reconnect with authorizer\n");
1001 g_free(host); 1031 g_free(host);
1002 return 1; 1032 return 1;
1003 } 1033 }
1004 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); 1034 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, server_ready_auth, 0);
1005 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, gaim_rateresp, 0); 1035 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, rateresp_auth, 0);
1006 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, gaim_info_change, 0); 1036 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, gaim_info_change, 0);
1007 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, gaim_info_change, 0); 1037 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, gaim_info_change, 0);
1008 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0); 1038 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0);
1009 1039
1010 tstconn->status |= AIM_CONN_STATUS_INPROGRESS; 1040 tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
1022 if (tstconn == NULL) { 1052 if (tstconn == NULL) {
1023 debug_printf("unable to connect to chatnav server\n"); 1053 debug_printf("unable to connect to chatnav server\n");
1024 g_free(host); 1054 g_free(host);
1025 return 1; 1055 return 1;
1026 } 1056 }
1027 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); 1057 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, server_ready_chatnav, 0);
1028 1058
1029 tstconn->status |= AIM_CONN_STATUS_INPROGRESS; 1059 tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
1030 tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, gc); 1060 tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, gc);
1031 if (tstconn->fd < 0) { 1061 if (tstconn->fd < 0) {
1032 aim_conn_kill(sess, &tstconn); 1062 aim_conn_kill(sess, &tstconn);
1036 } 1066 }
1037 aim_auth_sendcookie(sess, tstconn, cookie); 1067 aim_auth_sendcookie(sess, tstconn, cookie);
1038 break; 1068 break;
1039 case 0xe: /* Chat */ 1069 case 0xe: /* Chat */
1040 { 1070 {
1041 char *roomname = va_arg(ap, char *); 1071 char *roomname;
1042 int exchange = va_arg(ap, int); 1072 fu16_t exchange;
1043 struct chat_connection *ccon; 1073 struct chat_connection *ccon;
1074
1075 roomname = va_arg(ap, char *);
1076 exchange = (fu16_t)va_arg(ap, unsigned int);
1077
1044 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, NULL); 1078 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, NULL);
1045 if (tstconn == NULL) { 1079 if (tstconn == NULL) {
1046 debug_printf("unable to connect to chat server\n"); 1080 debug_printf("unable to connect to chat server\n");
1047 g_free(host); 1081 g_free(host);
1048 return 1; 1082 return 1;
1049 } 1083 }
1050 1084
1051 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); 1085 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, server_ready_chat, 0);
1052 ccon = g_new0(struct chat_connection, 1); 1086 ccon = g_new0(struct chat_connection, 1);
1053 ccon->conn = tstconn; 1087 ccon->conn = tstconn;
1054 ccon->gc = gc; 1088 ccon->gc = gc;
1055 ccon->fd = -1; 1089 ccon->fd = -1;
1056 ccon->name = g_strdup(roomname); 1090 ccon->name = g_strdup(roomname);
1081 1115
1082 g_free(host); 1116 g_free(host);
1083 return 1; 1117 return 1;
1084 } 1118 }
1085 1119
1086 int gaim_parse_oncoming(struct aim_session_t *sess, 1120 static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
1087 struct command_rx_struct *command, ...) {
1088 struct aim_userinfo_s *info; 1121 struct aim_userinfo_s *info;
1089 time_t time_idle; 1122 time_t time_idle;
1090 int type = 0; 1123 int type = 0;
1091 struct gaim_connection *gc = sess->aux_data; 1124 struct gaim_connection *gc = sess->aux_data;
1092 1125
1093 va_list ap; 1126 va_list ap;
1094 va_start(ap, command); 1127 va_start(ap, fr);
1095 info = va_arg(ap, struct aim_userinfo_s *); 1128 info = va_arg(ap, struct aim_userinfo_s *);
1096 va_end(ap); 1129 va_end(ap);
1097 1130
1098 if (info->flags & AIM_FLAG_UNCONFIRMED) 1131 if (info->flags & AIM_FLAG_UNCONFIRMED)
1099 type |= UC_UNCONFIRMED; 1132 type |= UC_UNCONFIRMED;
1116 time_idle, type, info->capabilities); 1149 time_idle, type, info->capabilities);
1117 1150
1118 return 1; 1151 return 1;
1119 } 1152 }
1120 1153
1121 int gaim_parse_offgoing(struct aim_session_t *sess, 1154 static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) {
1122 struct command_rx_struct *command, ...) {
1123 struct aim_userinfo_s *info; 1155 struct aim_userinfo_s *info;
1124 va_list ap; 1156 va_list ap;
1125 struct gaim_connection *gc = sess->aux_data; 1157 struct gaim_connection *gc = sess->aux_data;
1126 1158
1127 va_start(ap, command); 1159 va_start(ap, fr);
1128 info = va_arg(ap, struct aim_userinfo_s *); 1160 info = va_arg(ap, struct aim_userinfo_s *);
1129 va_end(ap); 1161 va_end(ap);
1130 1162
1131 serv_got_update(gc, info->sn, 0, 0, 0, 0, 0, 0); 1163 serv_got_update(gc, info->sn, 0, 0, 0, 0, 0, 0);
1132 1164
1155 if (source < 0) { 1187 if (source < 0) {
1156 g_free(dim); 1188 g_free(dim);
1157 return; 1189 return;
1158 } 1190 }
1159 1191
1192 if (dim->conn->fd != source)
1193 dim->conn->fd = source;
1194
1160 aim_conn_completeconnect(od->sess, dim->conn); 1195 aim_conn_completeconnect(od->sess, dim->conn);
1161 if (!(cnv = find_conversation(dim->name))) cnv = new_conversation(dim->name); 1196 if (!(cnv = find_conversation(dim->name)))
1197 cnv = new_conversation(dim->name);
1162 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name); 1198 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name);
1163 write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); 1199 write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL));
1164 1200
1165 od->direct_ims = g_slist_append(od->direct_ims, dim); 1201 od->direct_ims = g_slist_append(od->direct_ims, dim);
1166 1202
1184 } 1220 }
1185 dim = g_new0(struct direct_im, 1); 1221 dim = g_new0(struct direct_im, 1);
1186 dim->gc = d->gc; 1222 dim->gc = d->gc;
1187 g_snprintf(dim->name, sizeof dim->name, "%s", d->sn); 1223 g_snprintf(dim->name, sizeof dim->name, "%s", d->sn);
1188 1224
1189 if ((dim->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL)) == NULL) { 1225 dim->conn = aim_directim_connect(od->sess, d->sn, NULL, d->cookie);
1226 if (!dim->conn) {
1190 g_free(dim); 1227 g_free(dim);
1191 cancel_direct_im(w, d); 1228 cancel_direct_im(w, d);
1192 return TRUE; 1229 return TRUE;
1193 } 1230 }
1194 dim->conn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM; 1231
1195 dim->conn->priv = d->priv;
1196 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, 1232 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING,
1197 gaim_directim_incoming, 0); 1233 gaim_directim_incoming, 0);
1198 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT,
1199 gaim_directim_disconnect, 0);
1200 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, 1234 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING,
1201 gaim_directim_typing, 0); 1235 gaim_directim_typing, 0);
1202 1236
1203 for (i = 0; i < (int)strlen(d->priv->ip); i++) { 1237 for (i = 0; i < (int)strlen(d->ip); i++) {
1204 if (d->priv->ip[i] == ':') { 1238 if (d->ip[i] == ':') {
1205 port = atoi(&(d->priv->ip[i+1])); 1239 port = atoi(&(d->ip[i+1]));
1206 break; 1240 break;
1207 } 1241 }
1208 } 1242 }
1209 host = g_strndup(d->priv->ip, i); 1243 host = g_strndup(d->ip, i);
1210 dim->conn->status |= AIM_CONN_STATUS_INPROGRESS; 1244 dim->conn->status |= AIM_CONN_STATUS_INPROGRESS;
1211 dim->conn->fd = proxy_connect(host, port, oscar_directim_callback, dim); 1245 dim->conn->fd = proxy_connect(host, port, oscar_directim_callback, dim);
1212 g_free(host); 1246 g_free(host);
1213 if (dim->conn->fd < 0) { 1247 if (dim->conn->fd < 0) {
1214 aim_conn_kill(od->sess, &dim->conn); 1248 aim_conn_kill(od->sess, &dim->conn);
1220 cancel_direct_im(w, d); 1254 cancel_direct_im(w, d);
1221 1255
1222 return TRUE; 1256 return TRUE;
1223 } 1257 }
1224 1258
1225 int gaim_parse_incoming_im(struct aim_session_t *sess, 1259 static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch1_args *args) {
1226 struct command_rx_struct *command, ...) { 1260 char *tmp = g_malloc(BUF_LONG);
1227 int channel; 1261 struct gaim_connection *gc = sess->aux_data;
1262
1263 if (args->icbmflags & AIM_IMFLAGS_HASICON) {
1264 struct oscar_data *od = gc->proto_data;
1265 struct icon_req *ir = NULL;
1266 GSList *h = od->hasicons;
1267 char *who = normalize(userinfo->sn);
1268 debug_printf("%s has an icon\n", userinfo->sn);
1269 while (h) {
1270 ir = h->data;
1271 if (!strcmp(ir->user, who))
1272 break;
1273 h = h->next;
1274 }
1275 if (!h) {
1276 ir = g_new0(struct icon_req, 1);
1277 ir->user = g_strdup(who);
1278 od->hasicons = g_slist_append(od->hasicons, ir);
1279 }
1280 if ((args->iconlen != ir->length) ||
1281 (args->iconsum != ir->checksum) ||
1282 (args->iconstamp != ir->timestamp))
1283 ir->request = TRUE;
1284 ir->length = args->iconlen;
1285 ir->checksum = args->iconsum;
1286 ir->timestamp = args->iconstamp;
1287 }
1288
1289 if (gc->iconfile && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
1290 FILE *file;
1291 struct stat st;
1292
1293 if (!stat(gc->iconfile, &st)) {
1294 char *buf = g_malloc(st.st_size);
1295 file = fopen(gc->iconfile, "r");
1296 if (file) {
1297 fread(buf, 1, st.st_size, file);
1298 aim_send_icon(sess, conn, userinfo->sn, buf, st.st_size,
1299 st.st_mtime, aim_iconsum(buf, st.st_size));
1300 fclose(file);
1301 }
1302 g_free(buf);
1303 }
1304 }
1305
1306 /*
1307 * Quickly convert it to eight bit format, replacing
1308 * non-ASCII UNICODE characters with their equivelent
1309 * HTML entity.
1310 */
1311 if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1312 int i;
1313
1314 for (i = 0, tmp[0] = '\0'; i < args->msglen; i += 2) {
1315 unsigned short uni;
1316
1317 uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
1318
1319 if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
1320
1321 g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "%c", uni);
1322
1323 } else { /* something else, do UNICODE entity */
1324 g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "&#%04x;", uni);
1325 }
1326 }
1327 } else
1328 g_snprintf(tmp, BUF_LONG, "%s", args->msg);
1329
1330 serv_got_im(gc, userinfo->sn, tmp, args->icbmflags & AIM_IMFLAGS_AWAY, time(NULL));
1331 g_free(tmp);
1332
1333 return 1;
1334 }
1335
1336 static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args) {
1337 struct gaim_connection *gc = sess->aux_data;
1338
1339 if (args->reqclass & AIM_CAPS_CHAT) {
1340 char *name = extract_name(args->info.chat.roominfo.name);
1341 int *exch = g_new0(int, 1);
1342 GList *m = NULL;
1343 m = g_list_append(m, g_strdup(name ? name : args->info.chat.roominfo.name));
1344 *exch = args->info.chat.roominfo.exchange;
1345 m = g_list_append(m, exch);
1346 serv_got_chat_invite(gc,
1347 name ? name : args->info.chat.roominfo.name,
1348 userinfo->sn,
1349 args->info.chat.msg,
1350 m);
1351 if (name)
1352 g_free(name);
1353 } else if (args->reqclass & AIM_CAPS_SENDFILE) {
1354 } else if (args->reqclass & AIM_CAPS_GETFILE) {
1355 } else if (args->reqclass & AIM_CAPS_VOICE) {
1356 } else if (args->reqclass & AIM_CAPS_BUDDYICON) {
1357 set_icon_data(gc, normalize(userinfo->sn), args->info.icon.icon,
1358 args->info.icon.length);
1359 } else if (args->reqclass & AIM_CAPS_IMIMAGE) {
1360 struct ask_direct *d = g_new0(struct ask_direct, 1);
1361 char buf[256];
1362
1363 debug_printf("%s received direct im request from %s (%s)\n",
1364 gc->username, userinfo->sn, args->info.imimage.ip);
1365
1366 d->gc = gc;
1367 d->sn = g_strdup(userinfo->sn);
1368 strncpy(d->ip, args->info.imimage.ip, sizeof(d->ip));
1369 memcpy(d->cookie, args->cookie, 8);
1370 g_snprintf(buf, sizeof buf, "%s has just asked to directly connect to %s.",
1371 userinfo->sn, gc->username);
1372 do_ask_dialog(buf, d, accept_direct_im, cancel_direct_im);
1373 } else {
1374 debug_printf("Unknown reqclass %d\n", args->reqclass);
1375 }
1376
1377 return 1;
1378 }
1379
1380
1381 static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) {
1382 int channel, ret = 0;
1228 struct aim_userinfo_s *userinfo; 1383 struct aim_userinfo_s *userinfo;
1229 va_list ap; 1384 va_list ap;
1230 struct gaim_connection *gc = sess->aux_data; 1385
1231 1386 va_start(ap, fr);
1232 va_start(ap, command);
1233 channel = va_arg(ap, int); 1387 channel = va_arg(ap, int);
1234 userinfo = va_arg(ap, struct aim_userinfo_s *); 1388 userinfo = va_arg(ap, struct aim_userinfo_s *);
1235 1389
1236 /* channel 1: standard message */ 1390 /* channel 1: standard message */
1237 if (channel == 1) { 1391 if (channel == 1) {
1238 char *tmp = g_malloc(BUF_LONG);
1239 struct aim_incomingim_ch1_args *args; 1392 struct aim_incomingim_ch1_args *args;
1240 1393
1241 args = va_arg(ap, struct aim_incomingim_ch1_args *); 1394 args = va_arg(ap, struct aim_incomingim_ch1_args *);
1242 va_end(ap); 1395
1243 1396 ret = incomingim_chan1(sess, fr->conn, userinfo, args);
1244 if (args->icbmflags & AIM_IMFLAGS_HASICON) { 1397
1245 struct oscar_data *od = gc->proto_data;
1246 struct icon_req *ir = NULL;
1247 GSList *h = od->hasicons;
1248 char *who = normalize(userinfo->sn);
1249 debug_printf("%s has an icon\n", userinfo->sn);
1250 while (h) {
1251 ir = h->data;
1252 if (!strcmp(ir->user, who))
1253 break;
1254 h = h->next;
1255 }
1256 if (!h) {
1257 ir = g_new0(struct icon_req, 1);
1258 ir->user = g_strdup(who);
1259 od->hasicons = g_slist_append(od->hasicons, ir);
1260 }
1261 if ((args->iconlength != ir->length) ||
1262 (args->iconchecksum != ir->checksum) ||
1263 (args->iconstamp != ir->timestamp))
1264 ir->request = TRUE;
1265 ir->length = args->iconlength;
1266 ir->checksum = args->iconchecksum;
1267 ir->timestamp = args->iconstamp;
1268 }
1269
1270 if (gc->iconfile && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
1271 FILE *file;
1272 struct stat st;
1273
1274 if (!stat(gc->iconfile, &st)) {
1275 char *buf = g_malloc(st.st_size);
1276 file = fopen(gc->iconfile, "r");
1277 if (file) {
1278 fread(buf, 1, st.st_size, file);
1279 aim_send_icon(sess, command->conn, userinfo->sn, buf, st.st_size,
1280 st.st_mtime, aim_iconsum(buf, st.st_size));
1281 fclose(file);
1282 }
1283 g_free(buf);
1284 }
1285 }
1286
1287 /*
1288 * Quickly convert it to eight bit format, replacing
1289 * non-ASCII UNICODE characters with their equivelent
1290 * HTML entity.
1291 */
1292 if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1293 int i;
1294
1295 for (i = 0, tmp[0] = '\0'; i < args->msglen; i += 2) {
1296 unsigned short uni;
1297
1298 uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
1299
1300 if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
1301
1302 g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "%c", uni);
1303
1304 } else { /* something else, do UNICODE entity */
1305 g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "&#%04x;", uni);
1306 }
1307 }
1308 } else
1309 g_snprintf(tmp, BUF_LONG, "%s", args->msg);
1310
1311 serv_got_im(gc, userinfo->sn, tmp, args->icbmflags & AIM_IMFLAGS_AWAY, time(NULL));
1312 g_free(tmp);
1313 } else if (channel == 2) { 1398 } else if (channel == 2) {
1314 struct aim_incomingim_ch2_args *args; 1399 struct aim_incomingim_ch2_args *args;
1400
1315 args = va_arg(ap, struct aim_incomingim_ch2_args *); 1401 args = va_arg(ap, struct aim_incomingim_ch2_args *);
1316 va_end(ap); 1402
1317 if (args->reqclass & AIM_CAPS_CHAT) { 1403 ret = incomingim_chan2(sess, fr->conn, userinfo, args);
1318 char *name = extract_name(args->info.chat.roominfo.name); 1404 }
1319 int *exch = g_new0(int, 1); 1405
1320 GList *m = NULL; 1406 va_end(ap);
1321 m = g_list_append(m, g_strdup(name ? name : args->info.chat.roominfo.name)); 1407
1322 *exch = args->info.chat.roominfo.exchange; 1408 return ret;
1323 m = g_list_append(m, exch); 1409 }
1324 serv_got_chat_invite(gc, 1410
1325 name ? name : args->info.chat.roominfo.name, 1411 static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) {
1326 userinfo->sn, 1412 va_list ap;
1327 args->info.chat.msg, 1413 fu16_t chan, nummissed, reason;
1328 m);
1329 if (name)
1330 g_free(name);
1331 } else if (args->reqclass & AIM_CAPS_SENDFILE) {
1332 } else if (args->reqclass & AIM_CAPS_GETFILE) {
1333 } else if (args->reqclass & AIM_CAPS_VOICE) {
1334 } else if (args->reqclass & AIM_CAPS_BUDDYICON) {
1335 set_icon_data(gc, normalize(userinfo->sn), args->info.icon.icon,
1336 args->info.icon.length);
1337 } else if (args->reqclass & AIM_CAPS_IMIMAGE) {
1338 struct ask_direct *d = g_new0(struct ask_direct, 1);
1339 char buf[256];
1340
1341 debug_printf("%s received direct im request from %s (%s)\n",
1342 gc->username, userinfo->sn, args->info.directim->ip);
1343
1344 d->gc = gc;
1345 d->sn = g_strdup(userinfo->sn);
1346 d->priv = args->info.directim;
1347 g_snprintf(buf, sizeof buf, "%s has just asked to directly connect to %s.",
1348 userinfo->sn, gc->username);
1349 do_ask_dialog(buf, d, accept_direct_im, cancel_direct_im);
1350 } else {
1351 debug_printf("Unknown reqclass %d\n", args->reqclass);
1352 }
1353 }
1354
1355 return 1;
1356 }
1357
1358 int gaim_parse_misses(struct aim_session_t *sess,
1359 struct command_rx_struct *command, ...) {
1360 va_list ap;
1361 unsigned short chan, nummissed, reason;
1362 struct aim_userinfo_s *userinfo; 1414 struct aim_userinfo_s *userinfo;
1363 char buf[1024]; 1415 char buf[1024];
1364 1416
1365 va_start(ap, command); 1417 va_start(ap, fr);
1366 chan = (unsigned short)va_arg(ap, unsigned int); 1418 chan = (fu16_t)va_arg(ap, unsigned int);
1367 userinfo = va_arg(ap, struct aim_userinfo_s *); 1419 userinfo = va_arg(ap, struct aim_userinfo_s *);
1368 nummissed = (unsigned short)va_arg(ap, unsigned int); 1420 nummissed = (fu16_t)va_arg(ap, unsigned int);
1369 reason = (unsigned short)va_arg(ap, unsigned int); 1421 reason = (fu16_t)va_arg(ap, unsigned int);
1370 va_end(ap); 1422 va_end(ap);
1371 1423
1372 switch(reason) { 1424 switch(reason) {
1373 case 0: 1425 case 0:
1374 /* Invalid (0) */ 1426 /* Invalid (0) */
1429 do_error_dialog(buf, _("Gaim - Error")); 1481 do_error_dialog(buf, _("Gaim - Error"));
1430 1482
1431 return 1; 1483 return 1;
1432 } 1484 }
1433 1485
1434 int gaim_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1486 static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) {
1435 va_list ap; 1487 va_list ap;
1436 unsigned short reason; 1488 fu16_t reason;
1437 1489
1438 va_start(ap, command); 1490 va_start(ap, fr);
1439 reason = va_arg(ap, int); 1491 reason = (fu16_t)va_arg(ap, unsigned int);
1440 va_end(ap); 1492 va_end(ap);
1441 1493
1442 debug_printf("snac threw error (reason 0x%04x: %s\n", reason, 1494 debug_printf("snac threw error (reason 0x%04x: %s\n", reason,
1443 (reason < msgerrreasonlen) ? msgerrreason[reason] : "unknown"); 1495 (reason < msgerrreasonlen) ? msgerrreason[reason] : "unknown");
1444 1496
1445 return 1; 1497 return 1;
1446 } 1498 }
1447 1499
1448 int gaim_parse_msgerr(struct aim_session_t *sess, 1500 static int gaim_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...) {
1449 struct command_rx_struct *command, ...) {
1450 va_list ap; 1501 va_list ap;
1451 char *destn; 1502 char *destn;
1452 unsigned short reason; 1503 fu16_t reason;
1453 char buf[1024]; 1504 char buf[1024];
1454 1505
1455 va_start(ap, command); 1506 va_start(ap, fr);
1456 reason = (unsigned short)va_arg(ap, unsigned int); 1507 reason = (fu16_t)va_arg(ap, unsigned int);
1457 destn = va_arg(ap, char *); 1508 destn = va_arg(ap, char *);
1458 va_end(ap); 1509 va_end(ap);
1459 1510
1460 sprintf(buf, _("Your message to %s did not get sent: %s"), destn, 1511 sprintf(buf, _("Your message to %s did not get sent: %s"), destn,
1461 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); 1512 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown"));
1462 do_error_dialog(buf, _("Gaim - Error")); 1513 do_error_dialog(buf, _("Gaim - Error"));
1463 1514
1464 return 1; 1515 return 1;
1465 } 1516 }
1466 1517
1467 int gaim_parse_locerr(struct aim_session_t *sess, 1518 static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) {
1468 struct command_rx_struct *command, ...) {
1469 va_list ap; 1519 va_list ap;
1470 char *destn; 1520 char *destn;
1471 unsigned short reason; 1521 fu16_t reason;
1472 char buf[1024]; 1522 char buf[1024];
1473 1523
1474 va_start(ap, command); 1524 va_start(ap, fr);
1475 reason = (unsigned short)va_arg(ap, unsigned int); 1525 reason = (fu16_t)va_arg(ap, unsigned int);
1476 destn = va_arg(ap, char *); 1526 destn = va_arg(ap, char *);
1477 va_end(ap); 1527 va_end(ap);
1478 1528
1479 sprintf(buf, _("User information for %s unavailable: %s"), destn, 1529 sprintf(buf, _("User information for %s unavailable: %s"), destn,
1480 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); 1530 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown"));
1491 (flags & AIM_FLAG_ADMINISTRATOR) ? "<IMG SRC=\"admin_icon.gif\">" : "", 1541 (flags & AIM_FLAG_ADMINISTRATOR) ? "<IMG SRC=\"admin_icon.gif\">" : "",
1492 (flags & AIM_FLAG_FREE) ? "<IMG SRC=\"free_icon.gif\">" : ""); 1542 (flags & AIM_FLAG_FREE) ? "<IMG SRC=\"free_icon.gif\">" : "");
1493 return buf; 1543 return buf;
1494 } 1544 }
1495 1545
1496 int gaim_parse_user_info(struct aim_session_t *sess, 1546 static int gaim_parse_user_info(aim_session_t *sess, aim_frame_t *fr, ...) {
1497 struct command_rx_struct *command, ...) {
1498 struct aim_userinfo_s *info; 1547 struct aim_userinfo_s *info;
1499 char *prof_enc = NULL, *prof = NULL; 1548 char *prof_enc = NULL, *prof = NULL;
1500 unsigned short infotype; 1549 fu16_t infotype;
1501 char buf[BUF_LONG]; 1550 char buf[BUF_LONG];
1502 char legend[BUF_LONG]; 1551 char legend[BUF_LONG];
1503 struct gaim_connection *gc = sess->aux_data; 1552 struct gaim_connection *gc = sess->aux_data;
1504 va_list ap; 1553 va_list ap;
1505 char *asc; 1554 char *asc;
1506 1555
1507 va_start(ap, command); 1556 va_start(ap, fr);
1508 info = va_arg(ap, struct aim_userinfo_s *); 1557 info = va_arg(ap, struct aim_userinfo_s *);
1509 prof_enc = va_arg(ap, char *); 1558 prof_enc = va_arg(ap, char *);
1510 prof = va_arg(ap, char *); 1559 prof = va_arg(ap, char *);
1511 infotype = (unsigned short)va_arg(ap, unsigned int); 1560 infotype = (fu16_t)va_arg(ap, unsigned int);
1512 va_end(ap); 1561 va_end(ap);
1513 1562
1514 if (info->membersince) 1563 if (info->membersince)
1515 asc = g_strdup_printf("Member Since : <B>%s</B><BR>\n", 1564 asc = g_strdup_printf("Member Since : <B>%s</B><BR>\n",
1516 asctime(localtime(&info->membersince))); 1565 asctime(localtime(&info->membersince)));
1547 g_free(asc); 1596 g_free(asc);
1548 1597
1549 return 1; 1598 return 1;
1550 } 1599 }
1551 1600
1552 int gaim_parse_motd(struct aim_session_t *sess, 1601 static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) {
1553 struct command_rx_struct *command, ...) {
1554 char *msg; 1602 char *msg;
1555 unsigned short id; 1603 fu16_t id;
1556 va_list ap; 1604 va_list ap;
1557 char buildbuf[150]; 1605 char buildbuf[150];
1558 1606
1559 va_start(ap, command); 1607 va_start(ap, fr);
1560 id = (unsigned short)va_arg(ap, unsigned int); 1608 id = (fu16_t)va_arg(ap, unsigned int);
1561 msg = va_arg(ap, char *); 1609 msg = va_arg(ap, char *);
1562 va_end(ap); 1610 va_end(ap);
1563 1611
1564 aim_getbuildstring(buildbuf, sizeof(buildbuf)); 1612 aim_getbuildstring(buildbuf, sizeof(buildbuf));
1565 1613
1566 debug_printf("MOTD: %s (%d)\n", msg ? msg : "Unknown", id); 1614 debug_printf("MOTD: %s (%d)\n", msg ? msg : "Unknown", id);
1567 debug_printf("Gaim %s / Libfaim %s\n", VERSION, buildbuf); 1615 debug_printf("Gaim %s / libfaim %s\n", VERSION, buildbuf);
1568 if (id < 4) 1616 if (id < 4)
1569 do_error_dialog(_("Your connection may be lost."), 1617 do_error_dialog(_("Your connection may be lost."),
1570 _("AOL error")); 1618 _("AOL error"));
1571 1619
1572 return 1; 1620 return 1;
1573 } 1621 }
1574 1622
1575 int gaim_chatnav_info(struct aim_session_t *sess, 1623 static int gaim_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...) {
1576 struct command_rx_struct *command, ...) { 1624 va_list ap;
1577 va_list ap; 1625 fu16_t type;
1578 unsigned short type;
1579 struct gaim_connection *gc = sess->aux_data; 1626 struct gaim_connection *gc = sess->aux_data;
1580 struct oscar_data *odata = (struct oscar_data *)gc->proto_data; 1627 struct oscar_data *odata = (struct oscar_data *)gc->proto_data;
1581 1628
1582 va_start(ap, command); 1629 va_start(ap, fr);
1583 type = (unsigned short)va_arg(ap, unsigned int); 1630 type = (fu16_t)va_arg(ap, unsigned int);
1584 1631
1585 switch(type) { 1632 switch(type) {
1586 case 0x0002: { 1633 case 0x0002: {
1587 int maxrooms; 1634 fu8_t maxrooms;
1588 struct aim_chat_exchangeinfo *exchanges; 1635 struct aim_chat_exchangeinfo *exchanges;
1589 int exchangecount, i = 0; 1636 int exchangecount, i;
1590 1637
1591 maxrooms = (unsigned char)va_arg(ap, unsigned int); 1638 maxrooms = (fu8_t)va_arg(ap, unsigned int);
1592 exchangecount = va_arg(ap, int); 1639 exchangecount = va_arg(ap, int);
1593 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *); 1640 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
1594 va_end(ap); 1641 va_end(ap);
1595 1642
1596 debug_printf("chat info: Chat Rights:\n"); 1643 debug_printf("chat info: Chat Rights:\n");
1597 debug_printf("chat info: \tMax Concurrent Rooms: %d\n", maxrooms); 1644 debug_printf("chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
1598 debug_printf("chat info: \tExchange List: (%d total)\n", exchangecount); 1645 debug_printf("chat info: \tExchange List: (%d total)\n", exchangecount);
1599 while (i < exchangecount) 1646 for (i = 0; i < exchangecount; i++)
1600 debug_printf("chat info: \t\t%d\n", exchanges[i++].number); 1647 debug_printf("chat info: \t\t%d\n", exchanges[i].number);
1601 if (odata->create_exchange) { 1648 if (odata->create_exchange) {
1602 debug_printf("creating room %s\n", odata->create_name); 1649 debug_printf("creating room %s\n", odata->create_name);
1603 aim_chatnav_createroom(sess, command->conn, odata->create_name, 1650 aim_chatnav_createroom(sess, fr->conn, odata->create_name,
1604 odata->create_exchange); 1651 odata->create_exchange);
1605 odata->create_exchange = 0; 1652 odata->create_exchange = 0;
1606 g_free(odata->create_name); 1653 g_free(odata->create_name);
1607 odata->create_name = NULL; 1654 odata->create_name = NULL;
1608 } 1655 }
1609 } 1656 }
1610 break; 1657 break;
1611 case 0x0008: { 1658 case 0x0008: {
1612 char *fqcn, *name, *ck; 1659 char *fqcn, *name, *ck;
1613 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange; 1660 fu16_t instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
1614 unsigned char createperms; 1661 fu8_t createperms;
1615 unsigned long createtime; 1662 fu32_t createtime;
1616 1663
1617 fqcn = va_arg(ap, char *); 1664 fqcn = va_arg(ap, char *);
1618 instance = (unsigned short)va_arg(ap, unsigned int); 1665 instance = (fu16_t)va_arg(ap, unsigned int);
1619 exchange = (unsigned short)va_arg(ap, unsigned int); 1666 exchange = (fu16_t)va_arg(ap, unsigned int);
1620 flags = (unsigned short)va_arg(ap, unsigned int); 1667 flags = (fu16_t)va_arg(ap, unsigned int);
1621 createtime = va_arg(ap, unsigned long); 1668 createtime = va_arg(ap, fu32_t);
1622 maxmsglen = (unsigned short)va_arg(ap, unsigned int); 1669 maxmsglen = (fu16_t)va_arg(ap, unsigned int);
1623 maxoccupancy = (unsigned short)va_arg(ap, unsigned int); 1670 maxoccupancy = (fu16_t)va_arg(ap, unsigned int);
1624 createperms = (unsigned char)va_arg(ap, int); 1671 createperms = (fu8_t)va_arg(ap, int);
1625 unknown = (unsigned short)va_arg(ap, unsigned int); 1672 unknown = (fu16_t)va_arg(ap, unsigned int);
1626 name = va_arg(ap, char *); 1673 name = va_arg(ap, char *);
1627 ck = va_arg(ap, char *); 1674 ck = va_arg(ap, char *);
1628 va_end(ap); 1675 va_end(ap);
1629 1676
1630 debug_printf("created room: %s %d %d %d %lu %d %d %d %d %s %s\n", 1677 debug_printf("created room: %s %d %d %d %lu %d %d %d %d %s %s\n",
1631 fqcn, 1678 fqcn,
1632 exchange, instance, flags, 1679 exchange, instance, flags,
1633 createtime, 1680 createtime,
1634 maxmsglen, maxoccupancy, createperms, unknown, 1681 maxmsglen, maxoccupancy, createperms, unknown,
1635 name, ck); 1682 name, ck);
1636 aim_chat_join(odata->sess, odata->conn, exchange, ck); 1683 aim_chat_join(odata->sess, odata->conn, exchange, ck, instance);
1637 } 1684 }
1638 break; 1685 break;
1639 default: 1686 default:
1640 va_end(ap); 1687 va_end(ap);
1641 debug_printf("chatnav info: unknown type (%04x)\n", type); 1688 debug_printf("chatnav info: unknown type (%04x)\n", type);
1642 break; 1689 break;
1643 } 1690 }
1644 return 1; 1691 return 1;
1645 } 1692 }
1646 1693
1647 int gaim_chat_join(struct aim_session_t *sess, 1694 static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) {
1648 struct command_rx_struct *command, ...) { 1695 va_list ap;
1649 va_list ap; 1696 int count, i;
1650 int count, i = 0;
1651 struct aim_userinfo_s *info; 1697 struct aim_userinfo_s *info;
1652 struct gaim_connection *g = sess->aux_data; 1698 struct gaim_connection *g = sess->aux_data;
1653 1699
1654 struct chat_connection *c = NULL; 1700 struct chat_connection *c = NULL;
1655 1701
1656 va_start(ap, command); 1702 va_start(ap, fr);
1657 count = va_arg(ap, int); 1703 count = va_arg(ap, int);
1658 info = va_arg(ap, struct aim_userinfo_s *); 1704 info = va_arg(ap, struct aim_userinfo_s *);
1659 va_end(ap); 1705 va_end(ap);
1660 1706
1661 c = find_oscar_chat_by_conn(g, command->conn); 1707 c = find_oscar_chat_by_conn(g, fr->conn);
1662 if (!c) 1708 if (!c)
1663 return 1; 1709 return 1;
1664 1710
1665 while (i < count) 1711 for (i = 0; i < count; i++)
1666 add_chat_buddy(c->cnv, info[i++].sn); 1712 add_chat_buddy(c->cnv, info[i].sn);
1667 1713
1668 return 1; 1714 return 1;
1669 } 1715 }
1670 1716
1671 int gaim_chat_leave(struct aim_session_t *sess, 1717 static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) {
1672 struct command_rx_struct *command, ...) { 1718 va_list ap;
1673 va_list ap; 1719 int count, i;
1674 int count, i = 0;
1675 struct aim_userinfo_s *info; 1720 struct aim_userinfo_s *info;
1676 struct gaim_connection *g = sess->aux_data; 1721 struct gaim_connection *g = sess->aux_data;
1677 1722
1678 struct chat_connection *c = NULL; 1723 struct chat_connection *c = NULL;
1679 1724
1680 va_start(ap, command); 1725 va_start(ap, fr);
1681 count = va_arg(ap, int); 1726 count = va_arg(ap, int);
1682 info = va_arg(ap, struct aim_userinfo_s *); 1727 info = va_arg(ap, struct aim_userinfo_s *);
1683 va_end(ap); 1728 va_end(ap);
1684 1729
1685 c = find_oscar_chat_by_conn(g, command->conn); 1730 c = find_oscar_chat_by_conn(g, fr->conn);
1686 if (!c) 1731 if (!c)
1687 return 1; 1732 return 1;
1688 1733
1689 while (i < count) 1734 for (i = 0; i < count; i++)
1690 remove_chat_buddy(c->cnv, info[i++].sn); 1735 remove_chat_buddy(c->cnv, info[i].sn);
1691 1736
1692 return 1; 1737 return 1;
1693 } 1738 }
1694 1739
1695 int gaim_chat_info_update(struct aim_session_t *sess, 1740 static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) {
1696 struct command_rx_struct *command, ...) {
1697 va_list ap; 1741 va_list ap;
1698 struct aim_userinfo_s *userinfo; 1742 struct aim_userinfo_s *userinfo;
1699 struct aim_chat_roominfo *roominfo; 1743 struct aim_chat_roominfo *roominfo;
1700 char *roomname; 1744 char *roomname;
1701 int usercount; 1745 int usercount;
1702 char *roomdesc; 1746 char *roomdesc;
1703 unsigned short unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen; 1747 fu16_t unknown_c9, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
1704 unsigned long creationtime; 1748 fu32_t creationtime;
1705 struct gaim_connection *gc = sess->aux_data; 1749 struct gaim_connection *gc = sess->aux_data;
1706 struct chat_connection *ccon = find_oscar_chat_by_conn(gc, command->conn); 1750 struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn);
1707 1751
1708 va_start(ap, command); 1752 va_start(ap, fr);
1709 roominfo = va_arg(ap, struct aim_chat_roominfo *); 1753 roominfo = va_arg(ap, struct aim_chat_roominfo *);
1710 roomname = va_arg(ap, char *); 1754 roomname = va_arg(ap, char *);
1711 usercount= va_arg(ap, int); 1755 usercount= va_arg(ap, int);
1712 userinfo = va_arg(ap, struct aim_userinfo_s *); 1756 userinfo = va_arg(ap, struct aim_userinfo_s *);
1713 roomdesc = va_arg(ap, char *); 1757 roomdesc = va_arg(ap, char *);
1714 unknown_c9 = va_arg(ap, int); 1758 unknown_c9 = (fu16_t)va_arg(ap, int);
1715 creationtime = va_arg(ap, unsigned long); 1759 creationtime = (fu32_t)va_arg(ap, unsigned long);
1716 maxmsglen = va_arg(ap, int); 1760 maxmsglen = (fu16_t)va_arg(ap, int);
1717 unknown_d2 = va_arg(ap, int); 1761 unknown_d2 = (fu16_t)va_arg(ap, int);
1718 unknown_d5 = va_arg(ap, int); 1762 unknown_d5 = (fu16_t)va_arg(ap, int);
1719 maxvisiblemsglen = va_arg(ap, int); 1763 maxvisiblemsglen = (fu16_t)va_arg(ap, int);
1720 va_end(ap); 1764 va_end(ap);
1721 1765
1722 debug_printf("inside chat_info_update (maxmsglen = %d, maxvislen = %d)\n", 1766 debug_printf("inside chat_info_update (maxmsglen = %d, maxvislen = %d)\n",
1723 maxmsglen, maxvisiblemsglen); 1767 maxmsglen, maxvisiblemsglen);
1724 1768
1726 ccon->maxvis = maxvisiblemsglen; 1770 ccon->maxvis = maxvisiblemsglen;
1727 1771
1728 return 1; 1772 return 1;
1729 } 1773 }
1730 1774
1731 int gaim_chat_incoming_msg(struct aim_session_t *sess, 1775 static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) {
1732 struct command_rx_struct *command, ...) {
1733 va_list ap; 1776 va_list ap;
1734 struct aim_userinfo_s *info; 1777 struct aim_userinfo_s *info;
1735 char *msg; 1778 char *msg;
1736 struct gaim_connection *gc = sess->aux_data; 1779 struct gaim_connection *gc = sess->aux_data;
1737 struct chat_connection *ccon = find_oscar_chat_by_conn(gc, command->conn); 1780 struct chat_connection *ccon = find_oscar_chat_by_conn(gc, fr->conn);
1738 char *tmp; 1781 char *tmp;
1739 1782
1740 va_start(ap, command); 1783 va_start(ap, fr);
1741 info = va_arg(ap, struct aim_userinfo_s *); 1784 info = va_arg(ap, struct aim_userinfo_s *);
1742 msg = va_arg(ap, char *); 1785 msg = va_arg(ap, char *);
1743 1786
1744 tmp = g_malloc(BUF_LONG); 1787 tmp = g_malloc(BUF_LONG);
1745 g_snprintf(tmp, BUF_LONG, "%s", msg); 1788 g_snprintf(tmp, BUF_LONG, "%s", msg);
1747 g_free(tmp); 1790 g_free(tmp);
1748 1791
1749 return 1; 1792 return 1;
1750 } 1793 }
1751 1794
1752 /* 1795 /*
1753 * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option. 1796 * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
1754 */ 1797 */
1755 int gaim_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1798 static int gaim_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...) {
1756 va_list ap; 1799 va_list ap;
1757 unsigned short type; 1800 fu16_t type;
1758 char *sn = NULL; 1801 char *sn;
1759 1802
1760 va_start(ap, command); 1803 va_start(ap, fr);
1761 type = (unsigned short)va_arg(ap, unsigned int); 1804 type = (fu16_t)va_arg(ap, unsigned int);
1762 sn = va_arg(ap, char *); 1805 sn = va_arg(ap, char *);
1763 va_end(ap); 1806 va_end(ap);
1764 1807
1765 debug_printf("Sent message to %s.\n", sn); 1808 debug_printf("Sent message to %s.\n", sn);
1766 1809
1767 return 1; 1810 return 1;
1768 } 1811 }
1769 1812
1770 int gaim_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1813 static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) {
1771 static char *codes[5] = {"invalid", 1814 static const char *codes[5] = {
1772 "change", 1815 "invalid",
1773 "warning", 1816 "change",
1774 "limit", 1817 "warning",
1775 "limit cleared"}; 1818 "limit",
1776 va_list ap; 1819 "limit cleared",
1777 int code; 1820 };
1778 unsigned long rateclass, windowsize, clear, alert, limit, disconnect; 1821 va_list ap;
1779 unsigned long currentavg, maxavg; 1822 fu16_t code, rateclass;
1780 1823 fu32_t windowsize, clear, alert, limit, disconnect, currentavg, maxavg;
1781 va_start(ap, command); 1824
1782 code = va_arg(ap, int); 1825 va_start(ap, fr);
1783 rateclass= va_arg(ap, int); 1826 code = (fu16_t)va_arg(ap, unsigned int);
1784 windowsize = va_arg(ap, unsigned long); 1827 rateclass= (fu16_t)va_arg(ap, unsigned int);
1785 clear = va_arg(ap, unsigned long); 1828 windowsize = (fu32_t)va_arg(ap, unsigned long);
1786 alert = va_arg(ap, unsigned long); 1829 clear = (fu32_t)va_arg(ap, unsigned long);
1787 limit = va_arg(ap, unsigned long); 1830 alert = (fu32_t)va_arg(ap, unsigned long);
1788 disconnect = va_arg(ap, unsigned long); 1831 limit = (fu32_t)va_arg(ap, unsigned long);
1789 currentavg = va_arg(ap, unsigned long); 1832 disconnect = (fu32_t)va_arg(ap, unsigned long);
1790 maxavg = va_arg(ap, unsigned long); 1833 currentavg = (fu32_t)va_arg(ap, unsigned long);
1834 maxavg = (fu32_t)va_arg(ap, unsigned long);
1791 va_end(ap); 1835 va_end(ap);
1792 1836
1793 debug_printf("rate %s (paramid 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, " 1837 debug_printf("rate %s (paramid 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, "
1794 "clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n", 1838 "clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
1795 (code < 5) ? codes[code] : codes[0], 1839 (code < 5) ? codes[code] : codes[0],
1797 currentavg, maxavg, 1841 currentavg, maxavg,
1798 alert, clear, 1842 alert, clear,
1799 limit, disconnect, 1843 limit, disconnect,
1800 windowsize); 1844 windowsize);
1801 1845
1846 /* XXX fix these values */
1802 if (code == AIM_RATE_CODE_CHANGE) { 1847 if (code == AIM_RATE_CODE_CHANGE) {
1803 if (currentavg >= clear) 1848 if (currentavg >= clear)
1804 aim_conn_setlatency(command->conn, 0); 1849 aim_conn_setlatency(fr->conn, 0);
1805 } else if (code == AIM_RATE_CODE_WARNING) { 1850 } else if (code == AIM_RATE_CODE_WARNING) {
1806 aim_conn_setlatency(command->conn, windowsize/4); 1851 aim_conn_setlatency(fr->conn, windowsize/4);
1807 } else if (code == AIM_RATE_CODE_LIMIT) { 1852 } else if (code == AIM_RATE_CODE_LIMIT) {
1808 aim_conn_setlatency(command->conn, windowsize/2); 1853 aim_conn_setlatency(fr->conn, windowsize/2);
1809 } else if (code == AIM_RATE_CODE_CLEARLIMIT) { 1854 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
1810 aim_conn_setlatency(command->conn, 0); 1855 aim_conn_setlatency(fr->conn, 0);
1811 } 1856 }
1812 1857
1813 return 1; 1858 return 1;
1814 } 1859 }
1815 1860
1816 int gaim_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1861 static int gaim_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...) {
1817 va_list ap; 1862 va_list ap;
1818 int newevil; 1863 fu16_t newevil;
1819 struct aim_userinfo_s *userinfo; 1864 struct aim_userinfo_s *userinfo;
1820 struct gaim_connection *gc = sess->aux_data; 1865 struct gaim_connection *gc = sess->aux_data;
1821 1866
1822 va_start(ap, command); 1867 va_start(ap, fr);
1823 newevil = va_arg(ap, int); 1868 newevil = (fu16_t)va_arg(ap, unsigned int);
1824 userinfo = va_arg(ap, struct aim_userinfo_s *); 1869 userinfo = va_arg(ap, struct aim_userinfo_s *);
1825 va_end(ap); 1870 va_end(ap);
1826 1871
1827 serv_got_eviled(gc, (userinfo && userinfo->sn[0]) ? userinfo->sn : NULL, newevil / 10); 1872 serv_got_eviled(gc, (userinfo && userinfo->sn[0]) ? userinfo->sn : NULL, newevil / 10);
1828 1873
1829 return 1; 1874 return 1;
1830 } 1875 }
1831 1876
1832 int gaim_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1877 static int rateresp_bos(aim_session_t *sess, aim_frame_t *fr, ...) {
1833 struct gaim_connection *gc = sess->aux_data; 1878 struct gaim_connection *gc = sess->aux_data;
1834 switch (command->conn->type) { 1879
1835 case AIM_CONN_TYPE_BOS: 1880 aim_bos_ackrateresp(sess, fr->conn);
1836 aim_bos_ackrateresp(sess, command->conn); 1881 aim_bos_reqpersonalinfo(sess, fr->conn);
1837 aim_bos_reqpersonalinfo(sess, command->conn); 1882 aim_bos_reqlocaterights(sess, fr->conn);
1838 aim_bos_reqlocaterights(sess, command->conn); 1883 aim_bos_setprofile(sess, fr->conn, gc->user->user_info, NULL, gaim_caps);
1839 aim_bos_setprofile(sess, command->conn, gc->user->user_info, NULL, gaim_caps); 1884 aim_bos_reqbuddyrights(sess, fr->conn);
1840 aim_bos_reqbuddyrights(sess, command->conn); 1885
1841 1886 account_online(gc);
1842 account_online(gc); 1887 serv_finish_login(gc);
1843 serv_finish_login(gc); 1888
1844 1889 if (bud_list_cache_exists(gc))
1845 if (bud_list_cache_exists(gc)) 1890 do_import(NULL, gc);
1846 do_import(NULL, gc); 1891
1847 1892 debug_printf("buddy list loaded\n");
1848 debug_printf("buddy list loaded\n"); 1893
1849 1894 aim_reqicbmparams(sess, fr->conn);
1850 aim_reqicbmparams(sess, command->conn); 1895
1851 1896 aim_bos_reqrights(sess, fr->conn);
1852 aim_bos_reqrights(sess, command->conn); 1897 aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
1853 aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS); 1898 aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE |
1854 aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE | 1899 AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
1855 AIM_PRIVFLAGS_ALLOWMEMBERSINCE); 1900
1856 1901 return 1;
1857 break; 1902 }
1858 case AIM_CONN_TYPE_AUTH: 1903
1859 aim_bos_ackrateresp(sess, command->conn); 1904 static int rateresp_auth(aim_session_t *sess, aim_frame_t *fr, ...) {
1860 aim_auth_clientready(sess, command->conn); 1905 aim_bos_ackrateresp(sess, fr->conn);
1861 debug_printf("connected to auth (admin)\n"); 1906 aim_auth_clientready(sess, fr->conn);
1862 break; 1907 debug_printf("connected to auth (admin)\n");
1863 default: 1908
1864 debug_printf("got rate response for unhandled connection type %04x\n", 1909 return 1;
1865 command->conn->type); 1910 }
1866 break; 1911
1867 } 1912 static int gaim_icbm_param_info(aim_session_t *sess, aim_frame_t *fr, ...) {
1868
1869 return 1;
1870 }
1871
1872 int gaim_icbm_param_info(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
1873 struct aim_icbmparameters *params; 1913 struct aim_icbmparameters *params;
1874 va_list ap; 1914 va_list ap;
1875 1915
1876 va_start(ap, command); 1916 va_start(ap, fr);
1877 params = va_arg(ap, struct aim_icbmparameters *); 1917 params = va_arg(ap, struct aim_icbmparameters *);
1878 va_end(ap); 1918 va_end(ap);
1879 1919
1880 debug_printf("ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, " 1920 debug_printf("ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, "
1881 "max sender evil = %f, max receiver evil = %f, min msg interval = %ld\n", 1921 "max sender evil = %f, max receiver evil = %f, min msg interval = %ld\n",
1882 params->maxchan, params->flags, params->maxmsglen, 1922 params->maxchan, params->flags, params->maxmsglen,
1883 ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, 1923 ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0,
1884 params->minmsginterval); 1924 params->minmsginterval);
1885 1925
1926 /* Maybe senderwarn and recverwarn should be user preferences... */
1886 params->maxmsglen = 8000; 1927 params->maxmsglen = 8000;
1887 params->minmsginterval = 0; 1928 params->minmsginterval = 0;
1888 1929
1889 aim_seticbmparam(sess, command->conn, params); 1930 aim_seticbmparam(sess, fr->conn, params);
1890 1931
1891 return 1; 1932 return 1;
1892 } 1933 }
1893 1934
1894 int gaim_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1935 /* XXX this is frivelous... do you really want to know this info? */
1895 va_list ap; 1936 static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...) {
1896 unsigned short interval = 0; 1937 va_list ap;
1897 1938 fu16_t maxbuddies, maxwatchers;
1898 va_start(ap, command); 1939
1899 interval = va_arg(ap, int); 1940 va_start(ap, fr);
1900 va_end(ap); 1941 maxbuddies = (fu16_t)va_arg(ap, unsigned int);
1901 1942 maxwatchers = (fu16_t)va_arg(ap, unsigned int);
1902 debug_printf("minimum report interval: %d (seconds?)\n", interval);
1903
1904 aim_reqicbmparams(sess, command->conn);
1905
1906 return 1;
1907 }
1908
1909 int gaim_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
1910 va_list ap;
1911 unsigned short maxbuddies, maxwatchers;
1912
1913 va_start(ap, command);
1914 maxbuddies = (unsigned short)va_arg(ap, unsigned int);
1915 maxwatchers = (unsigned short)va_arg(ap, unsigned int);
1916 va_end(ap); 1943 va_end(ap);
1917 1944
1918 debug_printf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers); 1945 debug_printf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
1919 1946
1920 return 1; 1947 return 1;
1921 } 1948 }
1922 1949
1923 int gaim_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1950 static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) {
1924 unsigned short maxpermits, maxdenies; 1951 fu16_t maxpermits, maxdenies;
1925 va_list ap; 1952 va_list ap;
1926 1953
1927 va_start(ap, command); 1954 va_start(ap, fr);
1928 maxpermits = (unsigned short)va_arg(ap, unsigned int); 1955 maxpermits = (fu16_t)va_arg(ap, unsigned int);
1929 maxdenies = (unsigned short)va_arg(ap, unsigned int); 1956 maxdenies = (fu16_t)va_arg(ap, unsigned int);
1930 va_end(ap); 1957 va_end(ap);
1931 1958
1932 debug_printf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies); 1959 debug_printf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
1933 1960
1934 aim_bos_clientready(sess, command->conn); 1961 aim_bos_clientready(sess, fr->conn);
1935 1962
1936 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); 1963 aim_bos_reqservice(sess, fr->conn, AIM_CONN_TYPE_CHATNAV);
1937 1964
1938 return 1; 1965 return 1;
1939 } 1966 }
1940 1967
1941 int gaim_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1968 static int gaim_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...) {
1942 va_list ap; 1969 va_list ap;
1943 char *address, *SNs; 1970 char *address, *SNs;
1944 int i, num; 1971 int i, num;
1945 char *buf; 1972 char *buf;
1946 int at = 0, len; 1973 int at = 0, len;
1947 1974
1948 va_start(ap, command); 1975 va_start(ap, fr);
1949 address = va_arg(ap, char *); 1976 address = va_arg(ap, char *);
1950 num = va_arg(ap, int); 1977 num = va_arg(ap, int);
1951 SNs = va_arg(ap, char *); 1978 SNs = va_arg(ap, char *);
1952 va_end(ap); 1979 va_end(ap);
1953 1980
1960 g_free(buf); 1987 g_free(buf);
1961 1988
1962 return 1; 1989 return 1;
1963 } 1990 }
1964 1991
1965 int gaim_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 1992 static int gaim_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...) {
1966 va_list ap; 1993 va_list ap;
1967 char *address; 1994 char *address;
1968 char buf[BUF_LONG]; 1995 char buf[BUF_LONG];
1969 1996
1970 va_start(ap, command); 1997 va_start(ap, fr);
1971 address = va_arg(ap, char *); 1998 address = va_arg(ap, char *);
1972 va_end(ap); 1999 va_end(ap);
1973 2000
1974 g_snprintf(buf, sizeof(buf), "No results found for email address %s", address); 2001 g_snprintf(buf, sizeof(buf), "No results found for email address %s", address);
1975 do_error_dialog(buf, _("Error")); 2002 do_error_dialog(buf, _("Error"));
1976 2003
1977 return 1; 2004 return 1;
1978 } 2005 }
1979 2006
1980 int gaim_account_confirm(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 2007 static int gaim_account_confirm(aim_session_t *sess, aim_frame_t *fr, ...) {
1981 int status; 2008 fu16_t status;
1982 va_list ap; 2009 va_list ap;
1983 char msg[256]; 2010 char msg[256];
1984 struct gaim_connection *gc = sess->aux_data; 2011 struct gaim_connection *gc = sess->aux_data;
1985 2012
1986 va_start(ap, command); 2013 va_start(ap, fr);
1987 status = va_arg(ap, int); /* status code of confirmation request */ 2014 status = (fu16_t)va_arg(ap, unsigned int); /* status code of confirmation request */
1988 va_end(ap); 2015 va_end(ap);
1989 2016
1990 debug_printf("account confirmation returned status 0x%04x (%s)\n", status, 2017 debug_printf("account confirmation returned status 0x%04x (%s)\n", status,
1991 status ? "email sent" : "unknown"); 2018 status ? "email sent" : "unknown");
1992 if (status) { 2019 if (status) {
1996 } 2023 }
1997 2024
1998 return 1; 2025 return 1;
1999 } 2026 }
2000 2027
2001 int gaim_info_change(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 2028 static int gaim_info_change(aim_session_t *sess, aim_frame_t *fr, ...) {
2002 unsigned short change = 0; 2029 int change, str;
2003 int perms, type, length, str; 2030 fu16_t perms, type, length;
2004 char *val; 2031 char *val;
2005 va_list ap; 2032 va_list ap;
2006 char buf[BUF_LONG]; 2033 char buf[BUF_LONG];
2007 struct gaim_connection *gc = sess->aux_data; 2034 struct gaim_connection *gc = sess->aux_data;
2008 2035
2009 va_start(ap, command); 2036 va_start(ap, fr);
2010 perms = va_arg(ap, int); 2037 change = va_arg(ap, int);
2011 type = va_arg(ap, int); 2038 perms = (fu16_t)va_arg(ap, unsigned int);
2012 length = va_arg(ap, int); 2039 type = (fu16_t)va_arg(ap, unsigned int);
2040 length = (fu16_t)va_arg(ap, unsigned int);
2013 val = va_arg(ap, char *); 2041 val = va_arg(ap, char *);
2014 str = va_arg(ap, int); 2042 str = va_arg(ap, int);
2015 va_end(ap); 2043 va_end(ap);
2016
2017 if (aimutil_get16(command->data+2) == 0x0005)
2018 change = 1;
2019 2044
2020 debug_printf("info%s: perms = %d, type = %x, length = %d, val = %s\n", 2045 debug_printf("info%s: perms = %d, type = %x, length = %d, val = %s\n",
2021 change ? " change" : "", perms, type, length, str ? val : "(not string)"); 2046 change ? " change" : "", perms, type, length, str ? val : "(not string)");
2022 2047
2023 if ((type == 0x0011) && str) { 2048 if ((type == 0x0011) && str) {
2045 } else { 2070 } else {
2046 if (imflags & IM_FLAG_AWAY) 2071 if (imflags & IM_FLAG_AWAY)
2047 return aim_send_im(odata->sess, odata->conn, name, AIM_IMFLAGS_AWAY, message); 2072 return aim_send_im(odata->sess, odata->conn, name, AIM_IMFLAGS_AWAY, message);
2048 else { 2073 else {
2049 struct aim_sendimext_args args; 2074 struct aim_sendimext_args args;
2050
2051 int flags = AIM_IMFLAGS_ACK;
2052
2053 GSList *h = odata->hasicons; 2075 GSList *h = odata->hasicons;
2054 struct icon_req *ir = NULL; 2076 struct icon_req *ir = NULL;
2055 char *who = normalize(name); 2077 char *who = normalize(name);
2056
2057 struct stat st; 2078 struct stat st;
2079
2080 args.flags = AIM_IMFLAGS_ACK;
2058 2081
2059 while (h) { 2082 while (h) {
2060 ir = h->data; 2083 ir = h->data;
2061 if (ir->request && !strcmp(who, ir->user)) 2084 if (ir->request && !strcmp(who, ir->user))
2062 break; 2085 break;
2063 h = h->next; 2086 h = h->next;
2064 } 2087 }
2065 if (h) { 2088 if (h) {
2066 ir->request = FALSE; 2089 ir->request = FALSE;
2067 flags |= AIM_IMFLAGS_BUDDYREQ; 2090 args.flags |= AIM_IMFLAGS_BUDDYREQ;
2068 debug_printf("sending buddy icon request with message\n"); 2091 debug_printf("sending buddy icon request with message\n");
2069 } 2092 }
2070 2093
2071 if (gc->iconfile && !stat(gc->iconfile, &st)) { 2094 if (gc->iconfile && !stat(gc->iconfile, &st)) {
2072 FILE *file = fopen(gc->iconfile, "r"); 2095 FILE *file = fopen(gc->iconfile, "r");
2076 2099
2077 args.iconlen = st.st_size; 2100 args.iconlen = st.st_size;
2078 args.iconsum = aim_iconsum(buf, st.st_size); 2101 args.iconsum = aim_iconsum(buf, st.st_size);
2079 args.iconstamp = st.st_mtime; 2102 args.iconstamp = st.st_mtime;
2080 2103
2081 flags |= AIM_IMFLAGS_HASICON; 2104 args.flags |= AIM_IMFLAGS_HASICON;
2082 2105
2083 fclose(file); 2106 fclose(file);
2084 g_free(buf); 2107 g_free(buf);
2085 } 2108 }
2086 } 2109 }
2087 2110
2088 args.destsn = name; 2111 args.destsn = name;
2089 args.msg = message; 2112 args.msg = message;
2090 args.msglen = strlen(message); 2113 args.msglen = strlen(message);
2091 args.flags = flags;
2092 2114
2093 return aim_send_im_ext(odata->sess, odata->conn, &args); 2115 return aim_send_im_ext(odata->sess, odata->conn, &args);
2094 } 2116 }
2095 } 2117 }
2096 } 2118 }
2203 return m; 2225 return m;
2204 } 2226 }
2205 2227
2206 static void oscar_join_chat(struct gaim_connection *g, GList *data) { 2228 static void oscar_join_chat(struct gaim_connection *g, GList *data) {
2207 struct oscar_data *odata = (struct oscar_data *)g->proto_data; 2229 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
2208 struct aim_conn_t *cur = NULL; 2230 aim_conn_t *cur;
2209 char *name; 2231 char *name;
2210 int *exchange; 2232 int *exchange;
2211 2233
2212 if (!data || !data->next) 2234 if (!data || !data->next)
2213 return; 2235 return;
2345 if (uc & UC_UNCONFIRMED) 2367 if (uc & UC_UNCONFIRMED)
2346 return (char **)dt_icon_xpm; 2368 return (char **)dt_icon_xpm;
2347 return NULL; 2369 return NULL;
2348 } 2370 }
2349 2371
2350 static int gaim_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 2372 static int gaim_directim_initiate(aim_session_t *sess, aim_frame_t *fr, ...) {
2351 va_list ap; 2373 va_list ap;
2352 struct gaim_connection *gc = sess->aux_data; 2374 struct gaim_connection *gc = sess->aux_data;
2353 struct oscar_data *od = (struct oscar_data *)gc->proto_data; 2375 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
2354 struct aim_directim_priv *priv; 2376 aim_conn_t *newconn, *listenerconn;
2355 struct aim_conn_t *newconn;
2356 struct conversation *cnv; 2377 struct conversation *cnv;
2357 struct direct_im *dim; 2378 struct direct_im *dim;
2358 char buf[256]; 2379 char buf[256];
2359 2380 char *sn;
2360 va_start(ap, command); 2381
2361 newconn = va_arg(ap, struct aim_conn_t *); 2382 va_start(ap, fr);
2362 va_end(ap); 2383 newconn = va_arg(ap, aim_conn_t *);
2363 2384 listenerconn = va_arg(ap, aim_conn_t *);
2364 priv = (struct aim_directim_priv *)newconn->priv; 2385 va_end(ap);
2365 2386
2366 debug_printf("DirectIM: initiate success to %s\n", priv->sn); 2387 aim_conn_close(listenerconn);
2367 dim = find_direct_im(od, priv->sn); 2388 aim_conn_kill(sess, &listenerconn);
2368 2389
2369 if (!(cnv = find_conversation(priv->sn))) 2390 sn = g_strdup(aim_directim_getsn(newconn));
2370 cnv = new_conversation(priv->sn); 2391
2392 debug_printf("DirectIM: initiate success to %s\n", sn);
2393 dim = find_direct_im(od, sn);
2394
2395 if (!(cnv = find_conversation(sn)))
2396 cnv = new_conversation(sn);
2371 gaim_input_remove(dim->watcher); 2397 gaim_input_remove(dim->watcher);
2372 dim->conn = newconn; 2398 dim->conn = newconn;
2373 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, 2399 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,
2374 oscar_callback, dim->conn); 2400 oscar_callback, dim->conn);
2375 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), priv->sn); 2401 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), sn);
2402 g_free(sn);
2376 write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL)); 2403 write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL));
2377 2404
2378 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, 2405 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING,
2379 gaim_directim_incoming, 0); 2406 gaim_directim_incoming, 0);
2380 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT,
2381 gaim_directim_disconnect, 0);
2382 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, 2407 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING,
2383 gaim_directim_typing, 0); 2408 gaim_directim_typing, 0);
2384 2409
2385 return 1; 2410 return 1;
2386 } 2411 }
2387 2412
2388 static int gaim_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...) { 2413 static int gaim_directim_incoming(aim_session_t *sess, aim_frame_t *fr, ...) {
2389 va_list ap; 2414 va_list ap;
2390 char *msg = NULL; 2415 char *msg, *sn;
2391 struct aim_conn_t *conn;
2392 struct aim_directim_priv *priv;
2393 struct gaim_connection *gc = sess->aux_data; 2416 struct gaim_connection *gc = sess->aux_data;
2394 2417
2395 va_start(ap, command); 2418 va_start(ap, fr);
2396 conn = va_arg(ap, struct aim_conn_t *); 2419 sn = va_arg(ap, char *);
2397 msg = va_arg(ap, char *); 2420 msg = va_arg(ap, char *);
2398 va_end(ap); 2421 va_end(ap);
2399 2422
2400 if (!(priv = conn->priv)) { 2423 debug_printf("Got DirectIM message from %s\n", sn);
2401 return -1; 2424
2402 } 2425 serv_got_im(gc, sn, msg, 0, time((time_t)NULL));
2403 2426
2404 debug_printf("Got DirectIM message from %s\n", priv->sn); 2427 return 1;
2405 2428 }
2406 serv_got_im(gc, priv->sn, msg, 0, time((time_t)NULL)); 2429
2407 2430 static int gaim_directim_typing(aim_session_t *sess, aim_frame_t *fr, ...) {
2408 return 1; 2431 va_list ap;
2409 }
2410
2411 static int gaim_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
2412 va_list ap;
2413 struct aim_conn_t *conn;
2414 char *sn; 2432 char *sn;
2415 struct gaim_connection *gc = sess->aux_data; 2433
2416 struct oscar_data *od = (struct oscar_data *)gc->proto_data; 2434 va_start(ap, fr);
2417 struct conversation *cnv;
2418 struct direct_im *dim;
2419 char buf[256];
2420
2421 va_start(ap, command);
2422 conn = va_arg(ap, struct aim_conn_t *);
2423 sn = va_arg(ap, char *); 2435 sn = va_arg(ap, char *);
2424 va_end(ap); 2436 va_end(ap);
2425 2437
2426 debug_printf("%s disconnected Direct IM.\n", sn);
2427
2428 dim = find_direct_im(od, sn);
2429 od->direct_ims = g_slist_remove(od->direct_ims, dim);
2430 gaim_input_remove(dim->watcher);
2431
2432 g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), sn);
2433 if ((cnv = find_conversation(sn)) != NULL)
2434 write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL));
2435
2436 aim_conn_kill(sess, &conn);
2437
2438 return 1;
2439 }
2440
2441 static int gaim_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
2442 va_list ap;
2443 struct aim_conn_t *conn;
2444 struct aim_directim_priv *priv;
2445
2446 va_start(ap, command);
2447 conn = va_arg(ap, struct aim_conn_t *);
2448 va_end(ap);
2449
2450 if (!(priv = conn->priv)) {
2451 return -1;
2452 }
2453
2454 /* I had to leave this. It's just too funny. It reminds me of my sister. */ 2438 /* I had to leave this. It's just too funny. It reminds me of my sister. */
2455 debug_printf("ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn); 2439 debug_printf("ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn);
2456 2440
2457 return 1; 2441 return 1;
2458 } 2442 }
2459 2443
2460 struct ask_do_dir_im { 2444 struct ask_do_dir_im {
2478 } 2462 }
2479 dim = g_new0(struct direct_im, 1); 2463 dim = g_new0(struct direct_im, 1);
2480 dim->gc = gc; 2464 dim->gc = gc;
2481 g_snprintf(dim->name, sizeof dim->name, "%s", data->who); 2465 g_snprintf(dim->name, sizeof dim->name, "%s", data->who);
2482 2466
2483 dim->conn = aim_directim_initiate(od->sess, od->conn, NULL, data->who); 2467 dim->conn = aim_directim_initiate(od->sess, od->conn, data->who);
2484 if (dim->conn != NULL) { 2468 if (dim->conn != NULL) {
2485 od->direct_ims = g_slist_append(od->direct_ims, dim); 2469 od->direct_ims = g_slist_append(od->direct_ims, dim);
2486 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, 2470 dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,
2487 oscar_callback, dim->conn); 2471 oscar_callback, dim->conn);
2488 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, 2472 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE,
2615 } 2599 }
2616 2600
2617 static void oscar_do_action(struct gaim_connection *gc, char *act) 2601 static void oscar_do_action(struct gaim_connection *gc, char *act)
2618 { 2602 {
2619 struct oscar_data *od = gc->proto_data; 2603 struct oscar_data *od = gc->proto_data;
2620 struct aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH); 2604 aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
2621 2605
2622 if (!strcmp(act, "Set User Info")) { 2606 if (!strcmp(act, "Set User Info")) {
2623 show_set_info(gc); 2607 show_set_info(gc);
2624 } else if (!strcmp(act, "Change Password")) { 2608 } else if (!strcmp(act, "Change Password")) {
2625 show_change_passwd(gc); 2609 show_change_passwd(gc);
2669 aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH); 2653 aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
2670 } else { 2654 } else {
2671 aim_auth_changepasswd(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH), 2655 aim_auth_changepasswd(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH),
2672 new, old); 2656 new, old);
2673 } 2657 }
2658 }
2659
2660 static void oscar_convo_closed(struct gaim_connection *gc, char *who)
2661 {
2662 struct oscar_data *od = gc->proto_data;
2663 struct direct_im *dim = find_direct_im(od, who);
2664
2665 if (!dim)
2666 return;
2667
2668 od->direct_ims = g_slist_remove(od->direct_ims, dim);
2669 gaim_input_remove(dim->watcher);
2670 aim_conn_kill(od->sess, &dim->conn);
2671 g_free(dim);
2674 } 2672 }
2675 2673
2676 static struct prpl *my_protocol = NULL; 2674 static struct prpl *my_protocol = NULL;
2677 2675
2678 void oscar_init(struct prpl *ret) { 2676 void oscar_init(struct prpl *ret) {
2711 ret->chat_invite = oscar_chat_invite; 2709 ret->chat_invite = oscar_chat_invite;
2712 ret->chat_leave = oscar_chat_leave; 2710 ret->chat_leave = oscar_chat_leave;
2713 ret->chat_whisper = NULL; 2711 ret->chat_whisper = NULL;
2714 ret->chat_send = oscar_chat_send; 2712 ret->chat_send = oscar_chat_send;
2715 ret->keepalive = oscar_keepalive; 2713 ret->keepalive = oscar_keepalive;
2714 ret->convo_closed = oscar_convo_closed;
2716 2715
2717 my_protocol = ret; 2716 my_protocol = ret;
2718 } 2717 }
2719 2718
2720 #ifndef STATIC 2719 #ifndef STATIC