| |
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 } |