Mercurial > pidgin
comparison plugins/oscar.c @ 981:7e231bc0018a
[gaim-migrate @ 991]
I think I need a Pepsi.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Fri, 13 Oct 2000 07:24:40 +0000 |
parents | |
children | 0b5db8cdd30f |
comparison
equal
deleted
inserted
replaced
980:82c5865f7cfe | 981:7e231bc0018a |
---|---|
1 /* | |
2 * gaim | |
3 * | |
4 * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
5 * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx> | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 * | |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include "../config.h" | |
25 #endif | |
26 | |
27 | |
28 #include <netdb.h> | |
29 #include <gtk/gtk.h> | |
30 #include <unistd.h> | |
31 #include <errno.h> | |
32 #include <netinet/in.h> | |
33 #include <arpa/inet.h> | |
34 #include <string.h> | |
35 #include <stdlib.h> | |
36 #include <stdio.h> | |
37 #include <time.h> | |
38 #include <sys/socket.h> | |
39 #include <sys/stat.h> | |
40 #include "multi.h" | |
41 #include "prpl.h" | |
42 #include "gaim.h" | |
43 #include "aim.h" | |
44 #include "gnome_applet_mgr.h" | |
45 | |
46 #include "pixmaps/cancel.xpm" | |
47 #include "pixmaps/ok.xpm" | |
48 | |
49 int gaim_caps = AIM_CAPS_CHAT | AIM_CAPS_SENDFILE | AIM_CAPS_GETFILE | | |
50 AIM_CAPS_VOICE | AIM_CAPS_IMIMAGE | AIM_CAPS_BUDDYICON; | |
51 int keepalv = -1; | |
52 | |
53 struct chat_connection *find_oscar_chat(struct gaim_connection *gc, char *name) { | |
54 GSList *g = gc->oscar_chats; | |
55 struct chat_connection *c = NULL; | |
56 if (gc->protocol != PROTO_OSCAR) return NULL; | |
57 | |
58 while (g) { | |
59 c = (struct chat_connection *)g->data; | |
60 if (!strcmp(name, c->name)) | |
61 break; | |
62 g = g->next; | |
63 c = NULL; | |
64 } | |
65 | |
66 return c; | |
67 } | |
68 | |
69 static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc, | |
70 struct aim_conn_t *conn) { | |
71 GSList *g = gc->oscar_chats; | |
72 struct chat_connection *c = NULL; | |
73 | |
74 while (g) { | |
75 c = (struct chat_connection *)g->data; | |
76 if (c->conn == conn) | |
77 break; | |
78 g = g->next; | |
79 c = NULL; | |
80 } | |
81 | |
82 return c; | |
83 } | |
84 | |
85 static struct gaim_connection *find_gaim_conn_by_aim_sess(struct aim_session_t *sess) { | |
86 GSList *g = connections; | |
87 struct gaim_connection *gc = NULL; | |
88 | |
89 while (g) { | |
90 gc = (struct gaim_connection *)g->data; | |
91 if (sess == gc->oscar_sess) | |
92 break; | |
93 g = g->next; | |
94 gc = NULL; | |
95 } | |
96 | |
97 return gc; | |
98 } | |
99 | |
100 static struct gaim_connection *find_gaim_conn_by_oscar_conn(struct aim_conn_t *conn) { | |
101 GSList *g = connections; | |
102 struct gaim_connection *c = NULL; | |
103 struct aim_conn_t *s; | |
104 while (g) { | |
105 c = (struct gaim_connection *)g->data; | |
106 if (c->protocol != PROTO_OSCAR) { | |
107 c = NULL; | |
108 g = g->next; | |
109 continue; | |
110 } | |
111 s = c->oscar_sess->connlist; | |
112 while (s) { | |
113 if (conn == s) | |
114 break; | |
115 s = s->next; | |
116 } | |
117 if (s) break; | |
118 g = g->next; | |
119 c = NULL; | |
120 } | |
121 | |
122 return c; | |
123 } | |
124 | |
125 static int gaim_parse_auth_resp (struct aim_session_t *, struct command_rx_struct *, ...); | |
126 static int gaim_parse_login (struct aim_session_t *, struct command_rx_struct *, ...); | |
127 static int gaim_server_ready (struct aim_session_t *, struct command_rx_struct *, ...); | |
128 static int gaim_handle_redirect (struct aim_session_t *, struct command_rx_struct *, ...); | |
129 static int gaim_parse_oncoming (struct aim_session_t *, struct command_rx_struct *, ...); | |
130 static int gaim_parse_offgoing (struct aim_session_t *, struct command_rx_struct *, ...); | |
131 static int gaim_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *, ...); | |
132 static int gaim_parse_misses (struct aim_session_t *, struct command_rx_struct *, ...); | |
133 static int gaim_parse_user_info (struct aim_session_t *, struct command_rx_struct *, ...); | |
134 static int gaim_parse_motd (struct aim_session_t *, struct command_rx_struct *, ...); | |
135 static int gaim_chatnav_info (struct aim_session_t *, struct command_rx_struct *, ...); | |
136 static int gaim_chat_join (struct aim_session_t *, struct command_rx_struct *, ...); | |
137 static int gaim_chat_leave (struct aim_session_t *, struct command_rx_struct *, ...); | |
138 static int gaim_chat_info_update (struct aim_session_t *, struct command_rx_struct *, ...); | |
139 static int gaim_chat_incoming_msg(struct aim_session_t *, struct command_rx_struct *, ...); | |
140 static int gaim_parse_msgack (struct aim_session_t *, struct command_rx_struct *, ...); | |
141 static int gaim_parse_ratechange (struct aim_session_t *, struct command_rx_struct *, ...); | |
142 static int gaim_parse_evilnotify (struct aim_session_t *, struct command_rx_struct *, ...); | |
143 static int gaim_bosrights (struct aim_session_t *, struct command_rx_struct *, ...); | |
144 static int gaim_rateresp (struct aim_session_t *, struct command_rx_struct *, ...); | |
145 static int gaim_reportinterval (struct aim_session_t *, struct command_rx_struct *, ...); | |
146 static int gaim_parse_msgerr (struct aim_session_t *, struct command_rx_struct *, ...); | |
147 static int gaim_parse_buddyrights(struct aim_session_t *, struct command_rx_struct *, ...); | |
148 static int gaim_parse_locerr (struct aim_session_t *, struct command_rx_struct *, ...); | |
149 | |
150 static int gaim_directim_incoming(struct aim_session_t *, struct command_rx_struct *, ...); | |
151 static int gaim_directim_typing (struct aim_session_t *, struct command_rx_struct *, ...); | |
152 static int gaim_directim_initiate(struct aim_session_t *, struct command_rx_struct *, ...); | |
153 | |
154 static char *msgerrreason[] = { | |
155 "Invalid error", | |
156 "Invalid SNAC", | |
157 "Rate to host", | |
158 "Rate to client", | |
159 "Not logged in", | |
160 "Service unavailable", | |
161 "Service not defined", | |
162 "Obsolete SNAC", | |
163 "Not supported by host", | |
164 "Not supported by client", | |
165 "Refused by client", | |
166 "Reply too big", | |
167 "Responses lost", | |
168 "Request denied", | |
169 "Busted SNAC payload", | |
170 "Insufficient rights", | |
171 "In local permit/deny", | |
172 "Too evil (sender)", | |
173 "Too evil (receiver)", | |
174 "User temporarily unavailable", | |
175 "No match", | |
176 "List overflow", | |
177 "Request ambiguous", | |
178 "Queue full", | |
179 "Not while on AOL" | |
180 }; | |
181 static int msgerrreasonlen = 25; | |
182 | |
183 static void oscar_callback(gpointer data, gint source, | |
184 GdkInputCondition condition) { | |
185 struct aim_conn_t *conn = (struct aim_conn_t *)data; | |
186 struct gaim_connection *gc = find_gaim_conn_by_oscar_conn(conn); | |
187 if (!gc) { | |
188 /* oh boy. this is probably bad. i guess the only thing we can really do | |
189 * is return? */ | |
190 debug_print("oscar callback for closed connection.\n"); | |
191 return; | |
192 } | |
193 | |
194 if (condition & GDK_INPUT_EXCEPTION) { | |
195 hide_login_progress(gc->username, _("Disconnected.")); | |
196 signoff(gc); | |
197 return; | |
198 } | |
199 if (condition & GDK_INPUT_READ) { | |
200 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) { | |
201 debug_print("got information on rendezvous\n"); | |
202 if (aim_handlerendconnect(gc->oscar_sess, conn) < 0) { | |
203 debug_print(_("connection error (rend)\n")); | |
204 } | |
205 } else { | |
206 if (aim_get_command(gc->oscar_sess, conn) >= 0) { | |
207 aim_rxdispatch(gc->oscar_sess); | |
208 } else { | |
209 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS && | |
210 conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { | |
211 struct conversation *cnv = | |
212 find_conversation(((struct aim_directim_priv *)conn->priv)->sn); | |
213 debug_print("connection error for directim\n"); | |
214 if (cnv) { | |
215 make_direct(cnv, FALSE, NULL, 0); | |
216 } | |
217 aim_conn_kill(gc->oscar_sess, &conn); | |
218 } else if ((conn->type == AIM_CONN_TYPE_BOS) || | |
219 !(aim_getconn_type(gc->oscar_sess, AIM_CONN_TYPE_BOS))) { | |
220 debug_print(_("major connection error\n")); | |
221 hide_login_progress(gc->username, _("Disconnected.")); | |
222 signoff(gc); | |
223 } else if (conn->type == AIM_CONN_TYPE_CHAT) { | |
224 struct chat_connection *c = find_oscar_chat_by_conn(gc, conn); | |
225 char buf[BUF_LONG]; | |
226 sprintf(debug_buff, "disconnected from chat room %s\n", c->name); | |
227 debug_print(debug_buff); | |
228 c->conn = NULL; | |
229 if (c->inpa > -1) | |
230 gdk_input_remove(c->inpa); | |
231 c->inpa = -1; | |
232 c->fd = -1; | |
233 aim_conn_kill(gc->oscar_sess, &conn); | |
234 sprintf(buf, _("You have been disconnected from chat room %s."), c->name); | |
235 do_error_dialog(buf, _("Chat Error!")); | |
236 } else if (conn->type == AIM_CONN_TYPE_CHATNAV) { | |
237 if (gc->cnpa > -1) | |
238 gdk_input_remove(gc->cnpa); | |
239 gc->cnpa = -1; | |
240 debug_print("removing chatnav input watcher\n"); | |
241 aim_conn_kill(gc->oscar_sess, &conn); | |
242 } else { | |
243 sprintf(debug_buff, "holy crap! generic connection error! %d\n", | |
244 conn->type); | |
245 debug_print(debug_buff); | |
246 aim_conn_kill(gc->oscar_sess, &conn); | |
247 } | |
248 } | |
249 } | |
250 } | |
251 } | |
252 | |
253 void oscar_login(struct aim_user *user) { | |
254 struct aim_session_t *sess; | |
255 struct aim_conn_t *conn; | |
256 char buf[256]; | |
257 struct gaim_connection *gc; | |
258 | |
259 sprintf(debug_buff, _("Logging in %s\n"), user->username); | |
260 debug_print(debug_buff); | |
261 | |
262 gc = new_gaim_conn(PROTO_OSCAR, user->username, user->password); | |
263 sess = g_new0(struct aim_session_t, 1); | |
264 aim_session_init(sess); | |
265 /* we need an immediate queue because we don't use a while-loop to | |
266 * see if things need to be sent. */ | |
267 sess->tx_enqueue = &aim_tx_enqueue__immediate; | |
268 gc->oscar_sess = sess; | |
269 | |
270 sprintf(buf, _("Looking up %s"), FAIM_LOGIN_SERVER); | |
271 conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, FAIM_LOGIN_SERVER); | |
272 | |
273 if (conn == NULL) { | |
274 debug_print(_("internal connection error\n")); | |
275 hide_login_progress(gc->username, _("Unable to login to AIM")); | |
276 destroy_gaim_conn(gc); | |
277 return; | |
278 } else if (conn->fd == -1) { | |
279 if (conn->status & AIM_CONN_STATUS_RESOLVERR) { | |
280 sprintf(debug_buff, _("couldn't resolve host")); | |
281 debug_print(debug_buff); debug_print("\n"); | |
282 hide_login_progress(gc->username, debug_buff); | |
283 } else if (conn->status & AIM_CONN_STATUS_CONNERR) { | |
284 sprintf(debug_buff, _("couldn't connect to host")); | |
285 debug_print(debug_buff); debug_print("\n"); | |
286 hide_login_progress(gc->username, debug_buff); | |
287 } | |
288 destroy_gaim_conn(gc); | |
289 return; | |
290 } | |
291 g_snprintf(buf, sizeof(buf), _("Signon: %s"), gc->username); | |
292 | |
293 aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); | |
294 aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); | |
295 aim_sendconnack(sess, conn); | |
296 aim_request_login(sess, conn, gc->username); | |
297 | |
298 gc->inpa = gdk_input_add(conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, | |
299 oscar_callback, conn); | |
300 | |
301 sprintf(gc->user_info, "%s", user->user_info); | |
302 gc->options = user->options; | |
303 save_prefs(); /* is this necessary anymore? */ | |
304 | |
305 debug_print(_("Password sent, waiting for response\n")); | |
306 } | |
307 | |
308 void oscar_close(struct gaim_connection *gc) { | |
309 if (gc->protocol != PROTO_OSCAR) return; | |
310 if (gc->inpa > 0) | |
311 gdk_input_remove(gc->inpa); | |
312 gc->inpa = -1; | |
313 if (gc->cnpa > 0) | |
314 gdk_input_remove(gc->cnpa); | |
315 gc->cnpa = -1; | |
316 if (gc->paspa > 0) | |
317 gdk_input_remove(gc->paspa); | |
318 gc->paspa = -1; | |
319 aim_logoff(gc->oscar_sess); | |
320 g_free(gc->oscar_sess); | |
321 debug_print(_("Signed off.\n")); | |
322 } | |
323 | |
324 int gaim_parse_auth_resp(struct aim_session_t *sess, | |
325 struct command_rx_struct *command, ...) { | |
326 struct aim_conn_t *bosconn = NULL; | |
327 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
328 sprintf(debug_buff, "inside auth_resp (Screen name: %s)\n", | |
329 sess->logininfo.screen_name); | |
330 debug_print(debug_buff); | |
331 | |
332 if (sess->logininfo.errorcode) { | |
333 switch (sess->logininfo.errorcode) { | |
334 case 0x18: | |
335 /* connecting too frequently */ | |
336 do_error_dialog(_("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."), _("Gaim - Error")); | |
337 plugin_event(event_error, (void *)983, 0, 0); | |
338 break; | |
339 case 0x05: | |
340 /* Incorrect nick/password */ | |
341 do_error_dialog(_("Incorrect nickname or password."), _("Gaim - Error")); | |
342 plugin_event(event_error, (void *)980, 0, 0); | |
343 break; | |
344 case 0x1c: | |
345 /* client too old */ | |
346 do_error_dialog(_("The client version you are using is too old. Please upgrade at http://www.marko.net/gaim/"), _("Gaim - Error")); | |
347 plugin_event(event_error, (void *)989, 0, 0); | |
348 break; | |
349 } | |
350 sprintf(debug_buff, "Login Error Code 0x%04x\n", | |
351 sess->logininfo.errorcode); | |
352 debug_print(debug_buff); | |
353 sprintf(debug_buff, "Error URL: %s\n", | |
354 sess->logininfo.errorurl); | |
355 debug_print(debug_buff); | |
356 #ifdef USE_APPLET | |
357 set_user_state(offline); | |
358 #endif | |
359 gdk_input_remove(gc->inpa); | |
360 hide_login_progress(gc->username, _("Authentication Failed")); | |
361 signoff(gc); | |
362 return 0; | |
363 } | |
364 | |
365 | |
366 if (sess->logininfo.email) { | |
367 sprintf(debug_buff, "Email: %s\n", sess->logininfo.email); | |
368 debug_print(debug_buff); | |
369 } else { | |
370 debug_print("Email is NULL\n"); | |
371 } | |
372 sprintf(debug_buff, "Closing auth connection...\n"); | |
373 debug_print(debug_buff); | |
374 gdk_input_remove(gc->inpa); | |
375 aim_conn_kill(sess, &command->conn); | |
376 | |
377 bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, sess->logininfo.BOSIP); | |
378 if (bosconn == NULL) { | |
379 #ifdef USE_APPLET | |
380 set_user_state(offline); | |
381 #endif | |
382 hide_login_progress(gc->username, _("Internal Error")); | |
383 destroy_gaim_conn(gc); | |
384 return -1; | |
385 } else if (bosconn->status != 0) { | |
386 #ifdef USE_APPLET | |
387 set_user_state(offline); | |
388 #endif | |
389 hide_login_progress(gc->username, _("Could Not Connect")); | |
390 destroy_gaim_conn(gc); | |
391 return -1; | |
392 } | |
393 | |
394 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0); | |
395 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, gaim_rateresp, 0); /* rate info */ | |
396 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0); | |
397 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, gaim_server_ready, 0); | |
398 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0); | |
399 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0); | |
400 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, gaim_reportinterval, 0); | |
401 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0); | |
402 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0); | |
403 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0); | |
404 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0); | |
405 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0); | |
406 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, gaim_parse_misses, 0); | |
407 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, gaim_parse_ratechange, 0); | |
408 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, gaim_parse_evilnotify, 0); | |
409 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0); | |
410 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_user_info, 0); | |
411 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, gaim_parse_msgack, 0); | |
412 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0); | |
413 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0); | |
414 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0); | |
415 | |
416 aim_auth_sendcookie(sess, bosconn, sess->logininfo.cookie); | |
417 gc->oscar_conn = bosconn; | |
418 gc->inpa = gdk_input_add(bosconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, | |
419 oscar_callback, bosconn); | |
420 return 1; | |
421 } | |
422 | |
423 int gaim_parse_login(struct aim_session_t *sess, | |
424 struct command_rx_struct *command, ...) { | |
425 struct client_info_s info = {"AOL Instant Messenger (SM), version 4.1.2010/WIN32", 4, 30, 3141, "us", "en", 0x0004, 0x0001, 0x055}; | |
426 char *key; | |
427 va_list ap; | |
428 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
429 | |
430 va_start(ap, command); | |
431 key = va_arg(ap, char *); | |
432 va_end(ap); | |
433 | |
434 aim_send_login(sess, command->conn, gc->username, gc->password, &info, key); | |
435 return 1; | |
436 } | |
437 | |
438 int gaim_server_ready(struct aim_session_t *sess, | |
439 struct command_rx_struct *command, ...) { | |
440 static int id = 1; | |
441 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
442 switch (command->conn->type) { | |
443 case AIM_CONN_TYPE_BOS: | |
444 aim_setversions(sess, command->conn); | |
445 aim_bos_reqrate(sess, command->conn); /* request rate info */ | |
446 debug_print("done with BOS ServerReady\n"); | |
447 break; | |
448 case AIM_CONN_TYPE_CHATNAV: | |
449 debug_print("chatnav: got server ready\n"); | |
450 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0); | |
451 aim_bos_reqrate(sess, command->conn); | |
452 aim_bos_ackrateresp(sess, command->conn); | |
453 aim_chatnav_clientready(sess, command->conn); | |
454 aim_chatnav_reqrights(sess, command->conn); | |
455 break; | |
456 case AIM_CONN_TYPE_CHAT: | |
457 debug_print("chat: got server ready\n"); | |
458 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0); | |
459 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0); | |
460 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0); | |
461 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0); | |
462 aim_bos_reqrate(sess, command->conn); | |
463 aim_bos_ackrateresp(sess, command->conn); | |
464 aim_chat_clientready(sess, command->conn); | |
465 serv_got_joined_chat(gc, id++, aim_chat_getname(command->conn)); | |
466 break; | |
467 case AIM_CONN_TYPE_RENDEZVOUS: | |
468 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, gaim_directim_incoming, 0); | |
469 break; | |
470 default: /* huh? */ | |
471 sprintf(debug_buff, "server ready: got unexpected connection type %04x\n", command->conn->type); | |
472 debug_print(debug_buff); | |
473 break; | |
474 } | |
475 return 1; | |
476 } | |
477 | |
478 int gaim_handle_redirect(struct aim_session_t *sess, | |
479 struct command_rx_struct *command, ...) { | |
480 va_list ap; | |
481 int serviceid; | |
482 char *ip; | |
483 unsigned char *cookie; | |
484 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
485 | |
486 va_start(ap, command); | |
487 serviceid = va_arg(ap, int); | |
488 ip = va_arg(ap, char *); | |
489 cookie = va_arg(ap, unsigned char *); | |
490 | |
491 switch(serviceid) { | |
492 case 0x7: /* Authorizer */ | |
493 debug_print("Reconnecting with authorizor...\n"); | |
494 { | |
495 struct aim_conn_t *tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, ip); | |
496 if (tstconn == NULL || tstconn->status >= AIM_CONN_STATUS_RESOLVERR) | |
497 debug_print("unable to reconnect with authorizer\n"); | |
498 else { | |
499 gc->paspa = gdk_input_add(tstconn->fd, | |
500 GDK_INPUT_READ | GDK_INPUT_EXCEPTION, | |
501 oscar_callback, tstconn); | |
502 aim_auth_sendcookie(sess, tstconn, cookie); | |
503 } | |
504 } | |
505 break; | |
506 case 0xd: /* ChatNav */ | |
507 { | |
508 struct aim_conn_t *tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, ip); | |
509 if (tstconn == NULL || tstconn->status >= AIM_CONN_STATUS_RESOLVERR) { | |
510 debug_print("unable to connect to chatnav server\n"); | |
511 return 1; | |
512 } | |
513 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); | |
514 aim_auth_sendcookie(sess, tstconn, cookie); | |
515 gc->cnpa = gdk_input_add(tstconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, | |
516 oscar_callback, tstconn); | |
517 } | |
518 debug_print("chatnav: connected\n"); | |
519 break; | |
520 case 0xe: /* Chat */ | |
521 { | |
522 struct aim_conn_t *tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, ip); | |
523 char *roomname = va_arg(ap, char *); | |
524 struct chat_connection *ccon; | |
525 if (tstconn == NULL || tstconn->status >= AIM_CONN_STATUS_RESOLVERR) { | |
526 debug_print("unable to connect to chat server\n"); | |
527 return 1; | |
528 } | |
529 sprintf(debug_buff, "Connected to chat room %s\n", roomname); | |
530 debug_print(debug_buff); | |
531 | |
532 ccon = g_new0(struct chat_connection, 1); | |
533 ccon->conn = tstconn; | |
534 ccon->fd = tstconn->fd; | |
535 ccon->name = g_strdup(roomname); | |
536 | |
537 ccon->inpa = gdk_input_add(tstconn->fd, | |
538 GDK_INPUT_READ | GDK_INPUT_EXCEPTION, | |
539 oscar_callback, tstconn); | |
540 | |
541 gc->oscar_chats = g_slist_append(gc->oscar_chats, ccon); | |
542 | |
543 aim_chat_attachname(tstconn, roomname); | |
544 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0); | |
545 aim_auth_sendcookie(sess, tstconn, cookie); | |
546 } | |
547 break; | |
548 default: /* huh? */ | |
549 sprintf(debug_buff, "got redirect for unknown service 0x%04x\n", | |
550 serviceid); | |
551 debug_print(debug_buff); | |
552 break; | |
553 } | |
554 | |
555 va_end(ap); | |
556 | |
557 return 1; | |
558 } | |
559 | |
560 int gaim_parse_oncoming(struct aim_session_t *sess, | |
561 struct command_rx_struct *command, ...) { | |
562 struct aim_userinfo_s *info; | |
563 time_t time_idle; | |
564 int type = 0; | |
565 | |
566 va_list ap; | |
567 va_start(ap, command); | |
568 info = va_arg(ap, struct aim_userinfo_s *); | |
569 va_end(ap); | |
570 | |
571 if (info->flags & AIM_FLAG_UNCONFIRMED) | |
572 type |= UC_UNCONFIRMED; | |
573 else if (info->flags & AIM_FLAG_ADMINISTRATOR) | |
574 type |= UC_ADMIN; | |
575 else if (info->flags & AIM_FLAG_AOL) | |
576 type |= UC_AOL; | |
577 else if (info->flags & AIM_FLAG_FREE) | |
578 type |= UC_NORMAL; | |
579 if (info->flags & AIM_FLAG_AWAY) | |
580 type |= UC_UNAVAILABLE; | |
581 | |
582 if (info->idletime) { | |
583 time(&time_idle); | |
584 time_idle -= info->idletime*60; | |
585 } else | |
586 time_idle = 0; | |
587 | |
588 serv_got_update(info->sn, 1, info->warnlevel/10, info->onlinesince, | |
589 time_idle, type, info->capabilities); | |
590 | |
591 return 1; | |
592 } | |
593 | |
594 int gaim_parse_offgoing(struct aim_session_t *sess, | |
595 struct command_rx_struct *command, ...) { | |
596 char *sn; | |
597 va_list ap; | |
598 | |
599 va_start(ap, command); | |
600 sn = va_arg(ap, char *); | |
601 va_end(ap); | |
602 | |
603 serv_got_update(sn, 0, 0, 0, 0, 0, 0); | |
604 | |
605 return 1; | |
606 } | |
607 | |
608 static void accept_directim(GtkWidget *w, GtkWidget *m) | |
609 { | |
610 struct aim_conn_t *newconn; | |
611 struct aim_directim_priv *priv; | |
612 struct gaim_connection *gc; | |
613 int watcher; | |
614 | |
615 priv = (struct aim_directim_priv *)gtk_object_get_user_data(GTK_OBJECT(m)); | |
616 gc = (struct gaim_connection *)gtk_object_get_user_data(GTK_OBJECT(w)); | |
617 gtk_widget_destroy(m); | |
618 | |
619 if (!(newconn = aim_directim_connect(gc->oscar_sess, gc->oscar_conn, priv))) { | |
620 debug_print("imimage: could not connect\n"); | |
621 return; | |
622 } | |
623 | |
624 aim_conn_addhandler(gc->oscar_sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, gaim_directim_incoming, 0); | |
625 aim_conn_addhandler(gc->oscar_sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_directim_typing, 0); | |
626 | |
627 watcher = gdk_input_add(newconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, | |
628 oscar_callback, newconn); | |
629 | |
630 sprintf(debug_buff, "DirectIM: connected to %s\n", priv->sn); | |
631 debug_print(debug_buff); | |
632 | |
633 serv_got_imimage(gc, priv->sn, priv->cookie, priv->ip, newconn, watcher); | |
634 | |
635 g_free(priv); | |
636 } | |
637 | |
638 static void cancel_directim(GtkWidget *w, GtkWidget *m) | |
639 { | |
640 gtk_widget_destroy(m); | |
641 } | |
642 | |
643 static void directim_dialog(struct gaim_connection *gc, struct aim_directim_priv *priv) | |
644 { | |
645 GtkWidget *window; | |
646 GtkWidget *vbox; | |
647 GtkWidget *hbox; | |
648 GtkWidget *label; | |
649 GtkWidget *yes; | |
650 GtkWidget *no; | |
651 char buf[BUF_LONG]; | |
652 | |
653 window = gtk_window_new(GTK_WINDOW_DIALOG); | |
654 gtk_window_set_title(GTK_WINDOW(window), _("Accept Direct IM?")); | |
655 gtk_window_set_wmclass(GTK_WINDOW(window), "directim", "Gaim"); | |
656 gtk_widget_realize(window); | |
657 aol_icon(window->window); | |
658 gtk_object_set_user_data(GTK_OBJECT(window), (void *)priv); | |
659 | |
660 vbox = gtk_vbox_new(TRUE, 5); | |
661 gtk_container_add(GTK_CONTAINER(window), vbox); | |
662 gtk_widget_show(vbox); | |
663 | |
664 sprintf(buf, _("%s has requested to directly connect to your computer. " | |
665 "Do you accept?"), priv->sn); | |
666 label = gtk_label_new(buf); | |
667 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 5); | |
668 gtk_widget_show(label); | |
669 | |
670 hbox = gtk_hbox_new(TRUE, 10); | |
671 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5); | |
672 gtk_widget_show(hbox); | |
673 | |
674 yes = picture_button(window, _("Accept"), ok_xpm); | |
675 gtk_box_pack_start(GTK_BOX(hbox), yes, FALSE, FALSE, 5); | |
676 gtk_object_set_user_data(GTK_OBJECT(yes), gc); | |
677 | |
678 no = picture_button(window, _("Cancel"), cancel_xpm); | |
679 gtk_box_pack_end(GTK_BOX(hbox), no, FALSE, FALSE, 5); | |
680 | |
681 gtk_signal_connect(GTK_OBJECT(yes), "clicked", | |
682 GTK_SIGNAL_FUNC(accept_directim), window); | |
683 gtk_signal_connect(GTK_OBJECT(no), "clicked", | |
684 GTK_SIGNAL_FUNC(cancel_directim), window); | |
685 | |
686 gtk_widget_show(window); | |
687 } | |
688 | |
689 int gaim_parse_incoming_im(struct aim_session_t *sess, | |
690 struct command_rx_struct *command, ...) { | |
691 int channel; | |
692 va_list ap; | |
693 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
694 | |
695 va_start(ap, command); | |
696 channel = va_arg(ap, int); | |
697 | |
698 /* channel 1: standard message */ | |
699 if (channel == 1) { | |
700 struct aim_userinfo_s *userinfo; | |
701 char *msg = NULL; | |
702 char *tmp = g_malloc(BUF_LONG); | |
703 u_int icbmflags = 0; | |
704 u_short flag1, flag2; | |
705 | |
706 userinfo = va_arg(ap, struct aim_userinfo_s *); | |
707 msg = va_arg(ap, char *); | |
708 icbmflags = va_arg(ap, u_int); | |
709 flag1 = (u_short)va_arg(ap, u_int); | |
710 flag2 = (u_short)va_arg(ap, u_int); | |
711 va_end(ap); | |
712 | |
713 g_snprintf(tmp, BUF_LONG, "%s", msg); | |
714 serv_got_im(gc, userinfo->sn, tmp, icbmflags & AIM_IMFLAGS_AWAY); | |
715 g_free(tmp); | |
716 } else if (channel == 2) { | |
717 struct aim_userinfo_s *userinfo; | |
718 int rendtype = va_arg(ap, int); | |
719 if (rendtype & AIM_CAPS_CHAT) { | |
720 char *msg, *encoding, *lang; | |
721 struct aim_chat_roominfo *roominfo; | |
722 | |
723 userinfo = va_arg(ap, struct aim_userinfo_s *); | |
724 roominfo = va_arg(ap, struct aim_chat_roominfo *); | |
725 msg = va_arg(ap, char *); | |
726 encoding = va_arg(ap, char *); | |
727 lang = va_arg(ap, char *); | |
728 va_end(ap); | |
729 | |
730 serv_got_chat_invite(gc, | |
731 roominfo->name, | |
732 roominfo->exchange, | |
733 userinfo->sn, | |
734 msg); | |
735 } else if (rendtype & AIM_CAPS_SENDFILE) { | |
736 /* libfaim won't tell us that we got this just yet */ | |
737 } else if (rendtype & AIM_CAPS_GETFILE) { | |
738 /* nor will it tell us this. but it's still there */ | |
739 } else if (rendtype & AIM_CAPS_VOICE) { | |
740 /* this one libfaim tells us unuseful info about */ | |
741 } else if (rendtype & AIM_CAPS_BUDDYICON) { | |
742 /* bah */ | |
743 } else if (rendtype & AIM_CAPS_IMIMAGE) { | |
744 /* DirectIM stuff */ | |
745 struct aim_directim_priv *priv, *priv2; | |
746 | |
747 userinfo = va_arg(ap, struct aim_userinfo_s *); | |
748 priv = va_arg(ap, struct aim_directim_priv *); | |
749 va_end(ap); | |
750 | |
751 sprintf(debug_buff, "DirectIM request from %s (%s)\n", userinfo->sn, priv->ip); | |
752 debug_print(debug_buff); | |
753 | |
754 priv2 = g_new0(struct aim_directim_priv, 1); | |
755 strcpy(priv2->cookie, priv->cookie); | |
756 strcpy(priv2->sn, priv->sn); | |
757 strcpy(priv2->ip, priv->ip); | |
758 directim_dialog(gc, priv2); | |
759 } else { | |
760 sprintf(debug_buff, "Unknown rendtype %d\n", rendtype); | |
761 debug_print(debug_buff); | |
762 } | |
763 } | |
764 | |
765 return 1; | |
766 } | |
767 | |
768 int gaim_parse_misses(struct aim_session_t *sess, | |
769 struct command_rx_struct *command, ...) { | |
770 va_list ap; | |
771 u_short chan, nummissed, reason; | |
772 struct aim_userinfo_s *userinfo; | |
773 char buf[1024]; | |
774 | |
775 va_start(ap, command); | |
776 chan = (u_short)va_arg(ap, u_int); | |
777 userinfo = va_arg(ap, struct aim_userinfo_s *); | |
778 nummissed = (u_short)va_arg(ap, u_int); | |
779 reason = (u_short)va_arg(ap, u_int); | |
780 va_end(ap); | |
781 | |
782 switch(reason) { | |
783 case 1: | |
784 /* message too large */ | |
785 sprintf(buf, _("You missed a message from %s because it was too large."), userinfo->sn); | |
786 do_error_dialog(buf, _("Gaim - Error")); | |
787 plugin_event(event_error, (void *)961, 0, 0); | |
788 break; | |
789 default: | |
790 sprintf(buf, _("You missed a message from %s for unknown reasons."), userinfo->sn); | |
791 do_error_dialog(buf, _("Gaim - Error")); | |
792 plugin_event(event_error, (void *)970, 0, 0); | |
793 break; | |
794 } | |
795 | |
796 return 1; | |
797 } | |
798 | |
799 int gaim_parse_msgerr(struct aim_session_t *sess, | |
800 struct command_rx_struct *command, ...) { | |
801 va_list ap; | |
802 char *destn; | |
803 u_short reason; | |
804 char buf[1024]; | |
805 | |
806 va_start(ap, command); | |
807 destn = va_arg(ap, char *); | |
808 reason = (u_short)va_arg(ap, u_int); | |
809 va_end(ap); | |
810 | |
811 sprintf(buf, _("Your message to %s did not get sent: %s"), destn, | |
812 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); | |
813 do_error_dialog(buf, _("Gaim - Error")); | |
814 | |
815 return 1; | |
816 } | |
817 | |
818 int gaim_parse_locerr(struct aim_session_t *sess, | |
819 struct command_rx_struct *command, ...) { | |
820 va_list ap; | |
821 char *destn; | |
822 u_short reason; | |
823 char buf[1024]; | |
824 | |
825 va_start(ap, command); | |
826 destn = va_arg(ap, char *); | |
827 reason = (u_short)va_arg(ap, u_int); | |
828 va_end(ap); | |
829 | |
830 sprintf(buf, _("User information for %s unavailable: %s"), destn, | |
831 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); | |
832 do_error_dialog(buf, _("Gaim - Error")); | |
833 | |
834 return 1; | |
835 } | |
836 | |
837 int gaim_parse_user_info(struct aim_session_t *sess, | |
838 struct command_rx_struct *command, ...) { | |
839 struct aim_userinfo_s *info; | |
840 char *prof_enc = NULL, *prof = NULL; | |
841 u_short infotype; | |
842 char buf[BUF_LONG]; | |
843 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
844 va_list ap; | |
845 | |
846 va_start(ap, command); | |
847 info = va_arg(ap, struct aim_userinfo_s *); | |
848 prof_enc = va_arg(ap, char *); | |
849 prof = va_arg(ap, char *); | |
850 infotype = (u_short)va_arg(ap, u_int); | |
851 va_end(ap); | |
852 | |
853 if (prof == NULL || !strlen(prof)) { | |
854 /* no info/away message */ | |
855 char buf[1024]; | |
856 sprintf(buf, _("%s has no info/away message."), info->sn); | |
857 do_error_dialog(buf, _("Gaim - Error")); | |
858 plugin_event(event_error, (void *)977, 0, 0); | |
859 return 1; | |
860 } | |
861 | |
862 snprintf(buf, sizeof buf, _("Username : <B>%s</B>\n<BR>" | |
863 "Warning Level : <B>%d %%</B>\n<BR>" | |
864 "Online Since : <B>%s</B><BR>" | |
865 "Idle Minutes : <B>%d</B>\n<BR><HR><BR>" | |
866 "%s\n"), | |
867 info->sn, | |
868 info->warnlevel/10, | |
869 asctime(localtime(&info->onlinesince)), | |
870 info->idletime, | |
871 infotype == AIM_GETINFO_GENERALINFO ? prof : | |
872 away_subs(prof, gc->username)); | |
873 g_show_info_text(away_subs(buf, gc->username)); | |
874 | |
875 return 1; | |
876 } | |
877 | |
878 int gaim_parse_motd(struct aim_session_t *sess, | |
879 struct command_rx_struct *command, ...) { | |
880 char *msg; | |
881 u_short id; | |
882 va_list ap; | |
883 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
884 | |
885 va_start(ap, command); | |
886 id = (u_short)va_arg(ap, u_int); | |
887 msg = va_arg(ap, char *); | |
888 va_end(ap); | |
889 | |
890 sprintf(debug_buff, "MOTD: %s (%d)\n", msg, id); | |
891 debug_print(debug_buff); | |
892 sprintf(debug_buff, "Gaim %s / Libfaim %s\n", | |
893 VERSION, aim_getbuildstring()); | |
894 debug_print(debug_buff); | |
895 if (id != 4) | |
896 do_error_dialog(_("Your connection may be lost."), | |
897 _("AOL error")); | |
898 | |
899 if (gc->keepalive < 0) | |
900 update_keepalive(gc, gc->keepalive); | |
901 | |
902 return 1; | |
903 } | |
904 | |
905 int gaim_chatnav_info(struct aim_session_t *sess, | |
906 struct command_rx_struct *command, ...) { | |
907 va_list ap; | |
908 u_short type; | |
909 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
910 | |
911 va_start(ap, command); | |
912 type = (u_short)va_arg(ap, u_int); | |
913 | |
914 switch(type) { | |
915 case 0x0002: { | |
916 int maxrooms; | |
917 struct aim_chat_exchangeinfo *exchanges; | |
918 int exchangecount, i = 0; | |
919 | |
920 maxrooms = (u_char)va_arg(ap, u_int); | |
921 exchangecount = va_arg(ap, int); | |
922 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *); | |
923 va_end(ap); | |
924 | |
925 debug_print("chat info: Chat Rights:\n"); | |
926 sprintf(debug_buff, "chat info: \tMax Concurrent Rooms: %d\n", maxrooms); | |
927 debug_print(debug_buff); | |
928 sprintf(debug_buff, "chat info: \tExchange List: (%d total)\n", exchangecount); | |
929 debug_print(debug_buff); | |
930 while (i < exchangecount) { | |
931 sprintf(debug_buff, "chat info: \t\t%x: %s (%s/%s)\n", | |
932 exchanges[i].number, | |
933 exchanges[i].name, | |
934 exchanges[i].charset1, | |
935 exchanges[i].lang1); | |
936 debug_print(debug_buff); | |
937 i++; | |
938 } | |
939 if (gc->create_exchange) { | |
940 sprintf(debug_buff, "creating room %s\n", | |
941 gc->create_name); | |
942 debug_print(debug_buff); | |
943 aim_chatnav_createroom(sess, command->conn, gc->create_name, gc->create_exchange); | |
944 gc->create_exchange = 0; | |
945 g_free(gc->create_name); | |
946 gc->create_name = NULL; | |
947 } | |
948 } | |
949 break; | |
950 case 0x0008: { | |
951 char *fqcn, *name, *ck; | |
952 u_short instance, flags, maxmsglen, maxoccupancy, unknown; | |
953 unsigned char createperms; | |
954 unsigned long createtime; | |
955 | |
956 fqcn = va_arg(ap, char *); | |
957 instance = (u_short)va_arg(ap, u_int); | |
958 flags = (u_short)va_arg(ap, u_int); | |
959 createtime = va_arg(ap, unsigned long); | |
960 maxmsglen = (u_short)va_arg(ap, u_int); | |
961 maxoccupancy = (u_short)va_arg(ap, u_int); | |
962 createperms = (unsigned char)va_arg(ap, int); | |
963 unknown = (u_short)va_arg(ap, u_int); | |
964 name = va_arg(ap, char *); | |
965 ck = va_arg(ap, char *); | |
966 va_end(ap); | |
967 | |
968 sprintf(debug_buff, "created room: %s %d %d %lu %d %d %d %d %s %s\n", fqcn, instance, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck); | |
969 debug_print(debug_buff); | |
970 if (flags & 0x4) { | |
971 sprintf(debug_buff, "joining %s on exchange 5\n", name); | |
972 debug_print(debug_buff); | |
973 aim_chat_join(gc->oscar_sess, gc->oscar_conn, 5, ck); | |
974 } else | |
975 sprintf(debug_buff, "joining %s on exchange 4\n", name);{ | |
976 debug_print(debug_buff); | |
977 aim_chat_join(gc->oscar_sess, gc->oscar_conn, 4, ck); | |
978 } | |
979 } | |
980 break; | |
981 default: | |
982 va_end(ap); | |
983 sprintf(debug_buff, "chatnav info: unknown type (%04x)\n", type); | |
984 debug_print(debug_buff); | |
985 break; | |
986 } | |
987 return 1; | |
988 } | |
989 | |
990 int gaim_chat_join(struct aim_session_t *sess, | |
991 struct command_rx_struct *command, ...) { | |
992 va_list ap; | |
993 int count, i = 0; | |
994 struct aim_userinfo_s *info; | |
995 struct gaim_connection *g = find_gaim_conn_by_aim_sess(sess); | |
996 | |
997 GSList *bcs = g->buddy_chats; | |
998 struct conversation *b = NULL; | |
999 | |
1000 va_start(ap, command); | |
1001 count = va_arg(ap, int); | |
1002 info = va_arg(ap, struct aim_userinfo_s *); | |
1003 va_end(ap); | |
1004 | |
1005 while(bcs) { | |
1006 b = (struct conversation *)bcs->data; | |
1007 if (!strcasecmp(b->name, (char *)command->conn->priv)) | |
1008 break; | |
1009 bcs = bcs->next; | |
1010 b = NULL; | |
1011 } | |
1012 if (!b) | |
1013 return 1; | |
1014 | |
1015 while (i < count) | |
1016 add_chat_buddy(b, info[i++].sn); | |
1017 | |
1018 return 1; | |
1019 } | |
1020 | |
1021 int gaim_chat_leave(struct aim_session_t *sess, | |
1022 struct command_rx_struct *command, ...) { | |
1023 va_list ap; | |
1024 int count, i = 0; | |
1025 struct aim_userinfo_s *info; | |
1026 struct gaim_connection *g = find_gaim_conn_by_aim_sess(sess); | |
1027 | |
1028 GSList *bcs = g->buddy_chats; | |
1029 struct conversation *b = NULL; | |
1030 | |
1031 va_start(ap, command); | |
1032 count = va_arg(ap, int); | |
1033 info = va_arg(ap, struct aim_userinfo_s *); | |
1034 va_end(ap); | |
1035 | |
1036 while(bcs) { | |
1037 b = (struct conversation *)bcs->data; | |
1038 if (!strcasecmp(b->name, (char *)command->conn->priv)) | |
1039 break; | |
1040 bcs = bcs->next; | |
1041 b = NULL; | |
1042 } | |
1043 if (!b) | |
1044 return 1; | |
1045 | |
1046 while (i < count) | |
1047 remove_chat_buddy(b, info[i++].sn); | |
1048 | |
1049 return 1; | |
1050 } | |
1051 | |
1052 int gaim_chat_info_update(struct aim_session_t *sess, | |
1053 struct command_rx_struct *command, ...) { | |
1054 debug_print("inside chat_info_update\n"); | |
1055 return 1; | |
1056 } | |
1057 | |
1058 int gaim_chat_incoming_msg(struct aim_session_t *sess, | |
1059 struct command_rx_struct *command, ...) { | |
1060 va_list ap; | |
1061 struct aim_userinfo_s *info; | |
1062 char *msg; | |
1063 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
1064 | |
1065 GSList *bcs = gc->buddy_chats; | |
1066 struct conversation *b = NULL; | |
1067 | |
1068 va_start(ap, command); | |
1069 info = va_arg(ap, struct aim_userinfo_s *); | |
1070 msg = va_arg(ap, char *); | |
1071 | |
1072 while(bcs) { | |
1073 b = (struct conversation *)bcs->data; | |
1074 if (!strcasecmp(b->name, (char *)command->conn->priv)) | |
1075 break; | |
1076 bcs = bcs->next; | |
1077 b = NULL; | |
1078 } | |
1079 if (!b) | |
1080 return 0; | |
1081 | |
1082 serv_got_chat_in(gc, b->id, info->sn, 0, msg); | |
1083 | |
1084 return 1; | |
1085 } | |
1086 | |
1087 /* | |
1088 * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option. | |
1089 */ | |
1090 int gaim_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1091 va_list ap; | |
1092 u_short type; | |
1093 char *sn = NULL; | |
1094 | |
1095 va_start(ap, command); | |
1096 type = (u_short)va_arg(ap, u_int); | |
1097 sn = va_arg(ap, char *); | |
1098 va_end(ap); | |
1099 | |
1100 sprintf(debug_buff, "Sent message to %s.\n", sn); | |
1101 debug_print(debug_buff); | |
1102 | |
1103 return 1; | |
1104 } | |
1105 | |
1106 int gaim_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1107 va_list ap; | |
1108 unsigned long newrate; | |
1109 | |
1110 va_start(ap, command); | |
1111 newrate = va_arg(ap, unsigned long); | |
1112 va_end(ap); | |
1113 | |
1114 sprintf(debug_buff, "ratechange: %lu\n", newrate); | |
1115 debug_print(debug_buff); | |
1116 | |
1117 return 1; | |
1118 } | |
1119 | |
1120 int gaim_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1121 va_list ap; | |
1122 char *sn; | |
1123 | |
1124 va_start(ap, command); | |
1125 sn = va_arg(ap, char *); | |
1126 va_end(ap); | |
1127 | |
1128 serv_got_eviled(sn, 0); | |
1129 | |
1130 return 1; | |
1131 } | |
1132 | |
1133 int gaim_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1134 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
1135 switch (command->conn->type) { | |
1136 case AIM_CONN_TYPE_BOS: | |
1137 aim_bos_ackrateresp(sess, command->conn); | |
1138 aim_bos_reqpersonalinfo(sess, command->conn); | |
1139 aim_bos_reqlocaterights(sess, command->conn); | |
1140 aim_bos_setprofile(sess, command->conn, gc->user_info, NULL, gaim_caps); | |
1141 aim_bos_reqbuddyrights(sess, command->conn); | |
1142 | |
1143 if (mainwindow) | |
1144 gtk_widget_hide(mainwindow); | |
1145 show_buddy_list(); | |
1146 | |
1147 #ifdef USE_APPLET | |
1148 if (general_options & OPT_GEN_APP_BUDDY_SHOW) { | |
1149 refresh_buddy_window(); | |
1150 createOnlinePopup(); | |
1151 applet_buddy_show = TRUE; | |
1152 } else { | |
1153 gtk_widget_hide(blist); | |
1154 applet_buddy_show = FALSE; | |
1155 } | |
1156 set_user_state(online); | |
1157 #else | |
1158 refresh_buddy_window(); | |
1159 #endif | |
1160 | |
1161 serv_finish_login(gc); | |
1162 gaim_setup(gc); | |
1163 | |
1164 if (bud_list_cache_exists(gc)) | |
1165 do_import(NULL, gc); | |
1166 | |
1167 debug_print("buddy list loaded\n"); | |
1168 | |
1169 setup_buddy_chats(); | |
1170 | |
1171 aim_addicbmparam(sess, command->conn); | |
1172 aim_bos_reqicbmparaminfo(sess, command->conn); | |
1173 | |
1174 aim_bos_reqrights(sess, command->conn); | |
1175 aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS); | |
1176 aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE | | |
1177 AIM_PRIVFLAGS_ALLOWMEMBERSINCE); | |
1178 | |
1179 break; | |
1180 default: | |
1181 sprintf(debug_buff, "got rate response for unhandled connection type %04x\n", | |
1182 command->conn->type); | |
1183 debug_print(debug_buff); | |
1184 break; | |
1185 } | |
1186 | |
1187 return 1; | |
1188 } | |
1189 | |
1190 int gaim_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1191 if (command->data) { | |
1192 sprintf(debug_buff, "minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10)); | |
1193 debug_print(debug_buff); | |
1194 } else | |
1195 debug_print("NULL minimum report interval!\n"); | |
1196 return 1; | |
1197 } | |
1198 | |
1199 int gaim_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1200 va_list ap; | |
1201 u_short maxbuddies, maxwatchers; | |
1202 | |
1203 va_start(ap, command); | |
1204 maxbuddies = (u_short)va_arg(ap, u_int); | |
1205 maxwatchers = (u_short)va_arg(ap, u_int); | |
1206 va_end(ap); | |
1207 | |
1208 sprintf(debug_buff, "buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers); | |
1209 debug_print(debug_buff); | |
1210 | |
1211 return 1; | |
1212 } | |
1213 | |
1214 int gaim_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1215 u_short maxpermits, maxdenies; | |
1216 va_list ap; | |
1217 | |
1218 va_start(ap, command); | |
1219 maxpermits = (u_short)va_arg(ap, u_int); | |
1220 maxdenies = (u_short)va_arg(ap, u_int); | |
1221 va_end(ap); | |
1222 | |
1223 sprintf(debug_buff, "BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies); | |
1224 debug_print(debug_buff); | |
1225 | |
1226 aim_bos_clientready(sess, command->conn); | |
1227 | |
1228 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV); | |
1229 | |
1230 return 1; | |
1231 } | |
1232 | |
1233 int gaim_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1234 va_list ap; | |
1235 char *sn = NULL, *msg = NULL; | |
1236 struct aim_conn_t *conn; | |
1237 struct gaim_connection *gc = find_gaim_conn_by_aim_sess(sess); | |
1238 | |
1239 va_start(ap, command); | |
1240 conn = va_arg(ap, struct aim_conn_t *); | |
1241 sn = va_arg(ap, char *); | |
1242 msg = va_arg(ap, char *); | |
1243 va_end(ap); | |
1244 | |
1245 sprintf(debug_buff, "Got DirectIM message from %s\n", sn); | |
1246 debug_print(debug_buff); | |
1247 | |
1248 serv_got_im(gc, sn, msg, 0); | |
1249 | |
1250 return 1; | |
1251 } | |
1252 | |
1253 /* this is such a f*cked up function */ | |
1254 int gaim_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1255 va_list ap; | |
1256 struct aim_directim_priv *priv; | |
1257 struct aim_conn_t *newconn; | |
1258 struct conversation *cnv; | |
1259 int watcher; | |
1260 | |
1261 va_start(ap, command); | |
1262 newconn = va_arg(ap, struct aim_conn_t *); | |
1263 va_end(ap); | |
1264 | |
1265 priv = (struct aim_directim_priv *)newconn->priv; | |
1266 | |
1267 sprintf(debug_buff, "DirectIM: initiate success to %s\n", priv->sn); | |
1268 debug_print(debug_buff); | |
1269 | |
1270 cnv = find_conversation(priv->sn); | |
1271 gdk_input_remove(cnv->watcher); | |
1272 watcher = gdk_input_add(newconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, | |
1273 oscar_callback, newconn); | |
1274 make_direct(cnv, TRUE, newconn, watcher); | |
1275 | |
1276 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, gaim_directim_incoming, 0); | |
1277 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_directim_typing, 0); | |
1278 | |
1279 return 1; | |
1280 } | |
1281 | |
1282 int gaim_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...) { | |
1283 va_list ap; | |
1284 char *sn; | |
1285 | |
1286 va_start(ap, command); | |
1287 sn = va_arg(ap, char *); | |
1288 va_end(ap); | |
1289 | |
1290 /* I had to leave this. It's just too funny. It reminds me of my sister. */ | |
1291 sprintf(debug_buff, "ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn); | |
1292 debug_print(debug_buff); | |
1293 | |
1294 return 1; | |
1295 } | |
1296 | |
1297 void oscar_do_directim(struct gaim_connection *gc, char *name) { | |
1298 struct aim_conn_t *newconn = aim_directim_initiate(gc->oscar_sess, gc->oscar_conn, NULL, name); | |
1299 struct conversation *cnv = find_conversation(name); /* this will never be null because it just got set up */ | |
1300 cnv->conn = newconn; | |
1301 cnv->watcher = gdk_input_add(newconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, oscar_callback, newconn); | |
1302 aim_conn_addhandler(gc->oscar_sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE, gaim_directim_initiate, 0); | |
1303 } | |
1304 | |
1305 static void oscar_keepalive(struct gaim_connection *gc) { | |
1306 aim_flap_nop(gc->oscar_sess, gc->oscar_conn); | |
1307 } | |
1308 | |
1309 static char *oscar_name() { | |
1310 return "Oscar"; | |
1311 } | |
1312 | |
1313 char *name() { | |
1314 return "Oscar"; | |
1315 } | |
1316 | |
1317 char *description() { | |
1318 return "Allows gaim to use the Oscar protocol"; | |
1319 } | |
1320 | |
1321 static void oscar_send_im(struct gaim_connection *gc, char *name, char *message, int away) { | |
1322 struct conversation *cnv = find_conversation(name); | |
1323 if (cnv && cnv->is_direct) { | |
1324 debug_printf("Sending DirectIM to %s\n", name); | |
1325 aim_send_im_direct(gc->oscar_sess, cnv->conn, message); | |
1326 } else { | |
1327 if (away) | |
1328 aim_send_im(gc->oscar_sess, gc->oscar_conn, name, AIM_IMFLAGS_AWAY, message); | |
1329 else | |
1330 aim_send_im(gc->oscar_sess, gc->oscar_conn, name, AIM_IMFLAGS_ACK, message); | |
1331 } | |
1332 } | |
1333 | |
1334 static void oscar_get_info(struct gaim_connection *g, char *name) { | |
1335 aim_getinfo(g->oscar_sess, g->oscar_conn, name, AIM_GETINFO_GENERALINFO); | |
1336 } | |
1337 | |
1338 static void oscar_get_away_msg(struct gaim_connection *g, char *name) { | |
1339 aim_getinfo(g->oscar_sess, g->oscar_conn, name, AIM_GETINFO_AWAYMESSAGE); | |
1340 } | |
1341 | |
1342 static void oscar_set_dir(struct gaim_connection *g, char *first, char *middle, char *last, | |
1343 char *maiden, char *city, char *state, char *country, int web) { | |
1344 /* FIXME : some of these things are wrong, but i'm lazy */ | |
1345 aim_setdirectoryinfo(g->oscar_sess, g->oscar_conn, first, middle, last, | |
1346 maiden, NULL, NULL, city, state, NULL, 0, web); | |
1347 } | |
1348 | |
1349 | |
1350 static void oscar_set_idle(struct gaim_connection *g, int time) { | |
1351 aim_bos_setidle(g->oscar_sess, g->oscar_conn, time); | |
1352 } | |
1353 | |
1354 static void oscar_set_info(struct gaim_connection *g, char *info) { | |
1355 if (awaymessage) | |
1356 aim_bos_setprofile(g->oscar_sess, g->oscar_conn, info, | |
1357 awaymessage->message, gaim_caps); | |
1358 else | |
1359 aim_bos_setprofile(g->oscar_sess, g->oscar_conn, info, | |
1360 NULL, gaim_caps); | |
1361 } | |
1362 | |
1363 static void oscar_set_away(struct gaim_connection *g, char *message) { | |
1364 aim_bos_setprofile(g->oscar_sess, g->oscar_conn, g->user_info, message, gaim_caps); | |
1365 } | |
1366 | |
1367 static void oscar_warn(struct gaim_connection *g, char *name, int anon) { | |
1368 aim_send_warning(g->oscar_sess, g->oscar_conn, name, anon); | |
1369 } | |
1370 | |
1371 static void oscar_dir_search(struct gaim_connection *g, char *first, char *middle, char *last, | |
1372 char *maiden, char *city, char *state, char *country, char *email) { | |
1373 if (strlen(email)) | |
1374 aim_usersearch_address(g->oscar_sess, g->oscar_conn, email); | |
1375 } | |
1376 | |
1377 static void oscar_add_buddy(struct gaim_connection *g, char *name) { | |
1378 aim_add_buddy(g->oscar_sess, g->oscar_conn, name); | |
1379 } | |
1380 | |
1381 static void oscar_add_buddies(struct gaim_connection *g, GList *buddies) { | |
1382 char buf[MSG_LEN]; | |
1383 int n = 0; | |
1384 while (buddies) { | |
1385 if (n > MSG_LEN - 18) { | |
1386 aim_bos_setbuddylist(g->oscar_sess, g->oscar_conn, buf); | |
1387 n = 0; | |
1388 } | |
1389 n += g_snprintf(buf + n, sizeof(buf) - n, "%s&", (char *)buddies->data); | |
1390 buddies = buddies->next; | |
1391 } | |
1392 aim_bos_setbuddylist(g->oscar_sess, g->oscar_conn, buf); | |
1393 } | |
1394 | |
1395 static void oscar_remove_buddy(struct gaim_connection *g, char *name) { | |
1396 aim_remove_buddy(g->oscar_sess, g->oscar_conn, name); | |
1397 } | |
1398 | |
1399 static void oscar_join_chat(struct gaim_connection *g, int exchange, char *name) { | |
1400 struct aim_conn_t *cur = NULL; | |
1401 sprintf(debug_buff, "Attempting to join chat room %s.\n", name); | |
1402 debug_print(debug_buff); | |
1403 if ((cur = aim_getconn_type(g->oscar_sess, AIM_CONN_TYPE_CHATNAV))) { | |
1404 debug_print("chatnav exists, creating room\n"); | |
1405 aim_chatnav_createroom(g->oscar_sess, cur, name, exchange); | |
1406 } else { | |
1407 /* this gets tricky */ | |
1408 debug_print("chatnav does not exist, opening chatnav\n"); | |
1409 g->create_exchange = exchange; | |
1410 g->create_name = g_strdup(name); | |
1411 aim_bos_reqservice(g->oscar_sess, g->oscar_conn, AIM_CONN_TYPE_CHATNAV); | |
1412 } | |
1413 } | |
1414 | |
1415 static void oscar_chat_invite(struct gaim_connection *g, int id, char *message, char *name) { | |
1416 GSList *bcs = g->buddy_chats; | |
1417 struct conversation *b = NULL; | |
1418 | |
1419 while (bcs) { | |
1420 b = (struct conversation *)bcs->data; | |
1421 if (id == b->id) | |
1422 break; | |
1423 bcs = bcs->next; | |
1424 b = NULL; | |
1425 } | |
1426 | |
1427 if (!b) | |
1428 return; | |
1429 | |
1430 aim_chat_invite(g->oscar_sess, g->oscar_conn, name, | |
1431 message ? message : "", 0x4, b->name, 0x0); | |
1432 } | |
1433 | |
1434 static void oscar_chat_leave(struct gaim_connection *g, int id) { | |
1435 GSList *bcs = g->buddy_chats; | |
1436 struct conversation *b = NULL; | |
1437 struct chat_connection *c = NULL; | |
1438 int count = 0; | |
1439 | |
1440 while (bcs) { | |
1441 count++; | |
1442 b = (struct conversation *)bcs->data; | |
1443 if (id == b->id) | |
1444 break; | |
1445 bcs = bcs->next; | |
1446 b = NULL; | |
1447 } | |
1448 | |
1449 if (!b) | |
1450 return; | |
1451 | |
1452 sprintf(debug_buff, "Attempting to leave room %s (currently in %d rooms)\n", | |
1453 b->name, count); | |
1454 debug_print(debug_buff); | |
1455 | |
1456 c = find_oscar_chat(g, b->name); | |
1457 if (c != NULL) { | |
1458 g->oscar_chats = g_slist_remove(g->oscar_chats, c); | |
1459 gdk_input_remove(c->inpa); | |
1460 if (g && g->oscar_sess) | |
1461 aim_conn_kill(g->oscar_sess, &c->conn); | |
1462 g_free(c->name); | |
1463 g_free(c); | |
1464 } | |
1465 /* we do this because with Oscar it doesn't tell us we left */ | |
1466 serv_got_chat_left(g, b->id); | |
1467 } | |
1468 | |
1469 static void oscar_chat_whisper(struct gaim_connection *g, int id, char *who, char *message) { | |
1470 do_error_dialog("Sorry, Oscar doesn't whisper. Send an IM. (The last message was not received.)", | |
1471 "Gaim - Chat"); | |
1472 } | |
1473 | |
1474 static void oscar_chat_send(struct gaim_connection *g, int id, char *message) { | |
1475 struct aim_conn_t *cn; | |
1476 GSList *bcs = g->buddy_chats; | |
1477 struct conversation *b = NULL; | |
1478 | |
1479 while (bcs) { | |
1480 b = (struct conversation *)bcs->data; | |
1481 if (id == b->id) | |
1482 break; | |
1483 bcs = bcs->next; | |
1484 b = NULL; | |
1485 } | |
1486 if (!b) | |
1487 return; | |
1488 | |
1489 cn = aim_chat_getconn(g->oscar_sess, b->name); | |
1490 aim_chat_send_im(g->oscar_sess, cn, message); | |
1491 } | |
1492 | |
1493 struct prpl *oscar_init() { | |
1494 struct prpl *ret = g_new0(struct prpl, 1); | |
1495 | |
1496 ret->protocol = PROTO_OSCAR; | |
1497 ret->name = oscar_name; | |
1498 ret->login = oscar_login; | |
1499 ret->close = oscar_close; | |
1500 ret->send_im = oscar_send_im; | |
1501 ret->set_info = oscar_set_info; | |
1502 ret->get_info = oscar_get_info; | |
1503 ret->set_away = oscar_set_away; | |
1504 ret->get_away_msg = oscar_get_away_msg; | |
1505 ret->set_dir = oscar_set_dir; | |
1506 ret->get_dir = NULL; /* Oscar really doesn't have this */ | |
1507 ret->dir_search = oscar_dir_search; | |
1508 ret->set_idle = oscar_set_idle; | |
1509 ret->change_passwd = NULL; /* Oscar doesn't have this either */ | |
1510 ret->add_buddy = oscar_add_buddy; | |
1511 ret->add_buddies = oscar_add_buddies; | |
1512 ret->remove_buddy = oscar_remove_buddy; | |
1513 ret->add_permit = NULL; /* Oscar's permit/deny stuff is messed up */ | |
1514 ret->add_deny = NULL; /* at least, i can't figure it out :-P */ | |
1515 ret->warn = oscar_warn; | |
1516 ret->accept_chat = NULL; /* oscar doesn't have accept, it just joins */ | |
1517 ret->join_chat = oscar_join_chat; | |
1518 ret->chat_invite = oscar_chat_invite; | |
1519 ret->chat_leave = oscar_chat_leave; | |
1520 ret->chat_whisper = oscar_chat_whisper; | |
1521 ret->chat_send = oscar_chat_send; | |
1522 ret->keepalive = oscar_keepalive; | |
1523 | |
1524 return ret; | |
1525 } | |
1526 | |
1527 int gaim_plugin_init(void *handle) { | |
1528 protocols = g_slist_append(protocols, oscar_init()); | |
1529 return 0; | |
1530 } |