2086
|
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 "proxy.h"
|
|
45
|
|
46 #if USE_PIXBUF
|
|
47 #include <gdk-pixbuf/gdk-pixbuf.h>
|
|
48 #include <gdk-pixbuf/gdk-pixbuf-loader.h>
|
|
49 #endif
|
|
50
|
|
51 /*#include "pixmaps/cancel.xpm"*/
|
|
52 #include "pixmaps/admin_icon.xpm"
|
|
53 #include "pixmaps/aol_icon.xpm"
|
|
54 #include "pixmaps/away_icon.xpm"
|
|
55 #include "pixmaps/dt_icon.xpm"
|
|
56 #include "pixmaps/free_icon.xpm"
|
|
57
|
|
58 /* constants to identify proto_opts */
|
|
59 #define USEROPT_AUTH 0
|
|
60 #define USEROPT_AUTHPORT 1
|
|
61
|
|
62 #define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3"
|
|
63
|
|
64 static int gaim_caps = AIM_CAPS_CHAT |
|
|
65 #if USE_PIXBUF
|
|
66 AIM_CAPS_BUDDYICON |
|
|
67 #endif
|
|
68 AIM_CAPS_GETFILE |
|
|
69 AIM_CAPS_IMIMAGE;
|
|
70
|
|
71 static GtkWidget *join_chat_spin = NULL;
|
|
72 static GtkWidget *join_chat_entry = NULL;
|
|
73
|
|
74 struct oscar_data {
|
|
75 struct aim_session_t *sess;
|
|
76 struct aim_conn_t *conn;
|
|
77
|
|
78 guint cnpa;
|
|
79 guint paspa;
|
|
80
|
|
81 int create_exchange;
|
|
82 char *create_name;
|
|
83
|
|
84 gboolean conf;
|
|
85 gboolean reqemail;
|
|
86 gboolean chpass;
|
|
87 char *oldp;
|
|
88 char *newp;
|
|
89
|
|
90 GSList *oscar_chats;
|
|
91 GSList *direct_ims;
|
|
92 GSList *getfiles;
|
|
93 GSList *hasicons;
|
|
94
|
|
95 gboolean killme;
|
|
96 };
|
|
97
|
|
98 struct chat_connection {
|
|
99 char *name;
|
|
100 char *show; /* AOL did something funny to us */
|
|
101 int exchange;
|
|
102 int fd; /* this is redundant since we have the conn below */
|
|
103 struct aim_conn_t *conn;
|
|
104 int inpa;
|
|
105 int id;
|
|
106 struct gaim_connection *gc; /* i hate this. */
|
|
107 struct conversation *cnv; /* bah. */
|
|
108 };
|
|
109
|
|
110 struct direct_im {
|
|
111 struct gaim_connection *gc;
|
|
112 char name[80];
|
|
113 struct conversation *cnv;
|
|
114 int watcher;
|
|
115 struct aim_conn_t *conn;
|
|
116 };
|
|
117
|
|
118 struct ask_direct {
|
|
119 struct gaim_connection *gc;
|
|
120 char *sn;
|
|
121 struct aim_directim_priv *priv;
|
|
122 };
|
|
123
|
|
124 struct ask_getfile {
|
|
125 struct gaim_connection *gc;
|
|
126 char *sn;
|
|
127 char *cookie;
|
|
128 char *ip;
|
|
129 };
|
|
130
|
|
131 struct getfile_transfer {
|
|
132 struct gaim_connection *gc;
|
|
133 char *receiver;
|
|
134 char *filename;
|
|
135 struct aim_conn_t *conn;
|
|
136 struct aim_fileheader_t *fh;
|
|
137 int gip;
|
|
138 int gop;
|
|
139 FILE *listing;
|
|
140 FILE *file;
|
|
141 GtkWidget *window;
|
|
142 GtkWidget *meter;
|
|
143 GtkWidget *label;
|
|
144 long pos;
|
|
145 long size;
|
|
146 };
|
|
147
|
|
148 #if USE_PIXBUF
|
|
149 struct icon_req {
|
|
150 char *user;
|
|
151 time_t timestamp;
|
|
152 unsigned long length;
|
|
153 gpointer data;
|
|
154 gboolean request;
|
|
155 GdkPixbufAnimation *anim;
|
|
156 GdkPixbuf *unanim;
|
|
157 struct conversation *cnv;
|
|
158 GtkWidget *pix;
|
|
159 int curframe;
|
|
160 int timer;
|
|
161 };
|
|
162 #endif
|
|
163
|
|
164 static struct direct_im *find_direct_im(struct oscar_data *od, char *who) {
|
|
165 GSList *d = od->direct_ims;
|
|
166 char *n = g_strdup(normalize(who));
|
|
167 struct direct_im *m = NULL;
|
|
168
|
|
169 while (d) {
|
|
170 m = (struct direct_im *)d->data;
|
|
171 if (!strcmp(n, normalize(m->name)))
|
|
172 break;
|
|
173 m = NULL;
|
|
174 d = d->next;
|
|
175 }
|
|
176
|
|
177 g_free(n);
|
|
178 return m;
|
|
179 }
|
|
180
|
|
181 /*
|
|
182 static struct getfile_transfer *find_getfile_transfer(struct oscar_data *od, struct aim_conn_t *conn) {
|
|
183 GSList *g = od->getfiles;
|
|
184 struct getfile_transfer *n = NULL;
|
|
185
|
|
186 while (g) {
|
|
187 n = (struct getfile_transfer *)g->data;
|
|
188 if (n->conn == conn)
|
|
189 return n;
|
|
190 n = NULL;
|
|
191 g = g->next;
|
|
192 }
|
|
193
|
|
194 return n;
|
|
195 }
|
|
196 */
|
|
197
|
|
198 static char *extract_name(char *name) {
|
|
199 char *tmp;
|
|
200 int i, j;
|
|
201 char *x = strchr(name, '-');
|
|
202 if (!x) return NULL;
|
|
203 x = strchr(++x, '-');
|
|
204 if (!x) return NULL;
|
|
205 tmp = g_strdup(++x);
|
|
206
|
|
207 for (i = 0, j = 0; x[i]; i++) {
|
|
208 if (x[i] != '%')
|
|
209 tmp[j++] = x[i];
|
|
210 else {
|
|
211 char hex[3];
|
|
212 hex[0] = x[++i];
|
|
213 hex[1] = x[++i];
|
|
214 hex[2] = 0;
|
|
215 sscanf(hex, "%x", (int *)&tmp[j++]);
|
|
216 }
|
|
217 }
|
|
218
|
|
219 tmp[j] = 0;
|
|
220 return tmp;
|
|
221 }
|
|
222
|
|
223 static struct chat_connection *find_oscar_chat(struct gaim_connection *gc, int id) {
|
|
224 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats;
|
|
225 struct chat_connection *c = NULL;
|
|
226 if (gc->protocol != PROTO_OSCAR) return NULL;
|
|
227
|
|
228 while (g) {
|
|
229 c = (struct chat_connection *)g->data;
|
|
230 if (c->id == id)
|
|
231 break;
|
|
232 g = g->next;
|
|
233 c = NULL;
|
|
234 }
|
|
235
|
|
236 return c;
|
|
237 }
|
|
238
|
|
239 static struct chat_connection *find_oscar_chat_by_conn(struct gaim_connection *gc,
|
|
240 struct aim_conn_t *conn) {
|
|
241 GSList *g = ((struct oscar_data *)gc->proto_data)->oscar_chats;
|
|
242 struct chat_connection *c = NULL;
|
|
243
|
|
244 while (g) {
|
|
245 c = (struct chat_connection *)g->data;
|
|
246 if (c->conn == conn)
|
|
247 break;
|
|
248 g = g->next;
|
|
249 c = NULL;
|
|
250 }
|
|
251
|
|
252 return c;
|
|
253 }
|
|
254
|
|
255 static int gaim_parse_auth_resp (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
256 static int gaim_parse_login (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
257 static int gaim_server_ready (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
258 static int gaim_handle_redirect (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
259 static int gaim_info_change (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
260 static int gaim_account_confirm (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
261 static int gaim_parse_oncoming (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
262 static int gaim_parse_offgoing (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
263 static int gaim_parse_incoming_im(struct aim_session_t *, struct command_rx_struct *, ...);
|
|
264 static int gaim_parse_misses (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
265 static int gaim_parse_user_info (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
266 static int gaim_parse_motd (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
267 static int gaim_chatnav_info (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
268 static int gaim_chat_join (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
269 static int gaim_chat_leave (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
270 static int gaim_chat_info_update (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
271 static int gaim_chat_incoming_msg(struct aim_session_t *, struct command_rx_struct *, ...);
|
|
272 static int gaim_parse_msgack (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
273 static int gaim_parse_ratechange (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
274 static int gaim_parse_evilnotify (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
275 static int gaim_parse_searcherror(struct aim_session_t *, struct command_rx_struct *, ...);
|
|
276 static int gaim_parse_searchreply(struct aim_session_t *, struct command_rx_struct *, ...);
|
|
277 static int gaim_bosrights (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
278 static int gaim_rateresp (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
279 static int gaim_reportinterval (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
280 static int gaim_parse_msgerr (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
281 static int gaim_parse_buddyrights(struct aim_session_t *, struct command_rx_struct *, ...);
|
|
282 static int gaim_parse_locerr (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
283 static int gaim_parse_genericerr (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
284 static int gaim_memrequest (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
285
|
|
286 static int gaim_directim_initiate (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
287 static int gaim_directim_incoming (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
288 static int gaim_directim_disconnect(struct aim_session_t *, struct command_rx_struct *, ...);
|
|
289 static int gaim_directim_typing (struct aim_session_t *, struct command_rx_struct *, ...);
|
|
290
|
|
291 static char *msgerrreason[] = {
|
|
292 "Invalid error",
|
|
293 "Invalid SNAC",
|
|
294 "Rate to host",
|
|
295 "Rate to client",
|
|
296 "Not logged in",
|
|
297 "Service unavailable",
|
|
298 "Service not defined",
|
|
299 "Obsolete SNAC",
|
|
300 "Not supported by host",
|
|
301 "Not supported by client",
|
|
302 "Refused by client",
|
|
303 "Reply too big",
|
|
304 "Responses lost",
|
|
305 "Request denied",
|
|
306 "Busted SNAC payload",
|
|
307 "Insufficient rights",
|
|
308 "In local permit/deny",
|
|
309 "Too evil (sender)",
|
|
310 "Too evil (receiver)",
|
|
311 "User temporarily unavailable",
|
|
312 "No match",
|
|
313 "List overflow",
|
|
314 "Request ambiguous",
|
|
315 "Queue full",
|
|
316 "Not while on AOL"
|
|
317 };
|
|
318 static int msgerrreasonlen = 25;
|
|
319
|
|
320 static void oscar_callback(gpointer data, gint source,
|
|
321 GdkInputCondition condition) {
|
|
322 struct aim_conn_t *conn = (struct aim_conn_t *)data;
|
|
323 struct aim_session_t *sess = aim_conn_getsess(conn);
|
|
324 struct gaim_connection *gc = sess ? sess->aux_data : NULL;
|
|
325 struct oscar_data *odata;
|
|
326
|
|
327 if (!gc) {
|
|
328 /* gc is null. we return, else we seg SIGSEG on next line. */
|
|
329 debug_printf("oscar callback for closed connection (1).\n");
|
|
330 return;
|
|
331 }
|
|
332
|
|
333 odata = (struct oscar_data *)gc->proto_data;
|
|
334
|
|
335 if (!g_slist_find(connections, gc)) {
|
|
336 /* oh boy. this is probably bad. i guess the only thing we
|
|
337 * can really do is return? */
|
|
338 debug_printf("oscar callback for closed connection (2).\n");
|
|
339 return;
|
|
340 }
|
|
341
|
|
342 if (condition & GDK_INPUT_EXCEPTION) {
|
|
343 hide_login_progress(gc, _("Disconnected."));
|
|
344 signoff(gc);
|
|
345 return;
|
|
346 }
|
|
347 if (condition & GDK_INPUT_READ) {
|
|
348 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
|
|
349 debug_printf("got information on rendezvous\n");
|
|
350 if (aim_handlerendconnect(odata->sess, conn) < 0) {
|
|
351 debug_printf(_("connection error (rend)\n"));
|
|
352 }
|
|
353 } else {
|
|
354 if (aim_get_command(odata->sess, conn) >= 0) {
|
|
355 aim_rxdispatch(odata->sess);
|
|
356 if (odata->killme)
|
|
357 signoff(gc);
|
|
358 } else {
|
|
359 if ((conn->type == AIM_CONN_TYPE_BOS) ||
|
|
360 !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) {
|
|
361 debug_printf(_("major connection error\n"));
|
|
362 hide_login_progress(gc, _("Disconnected."));
|
|
363 signoff(gc);
|
|
364 } else if (conn->type == AIM_CONN_TYPE_CHAT) {
|
|
365 struct chat_connection *c = find_oscar_chat_by_conn(gc, conn);
|
|
366 char buf[BUF_LONG];
|
|
367 debug_printf("disconnected from chat room %s\n", c->name);
|
|
368 c->conn = NULL;
|
|
369 if (c->inpa > 0)
|
|
370 gdk_input_remove(c->inpa);
|
|
371 c->inpa = 0;
|
|
372 c->fd = -1;
|
|
373 aim_conn_kill(odata->sess, &conn);
|
|
374 sprintf(buf, _("You have been disconnected from chat room %s."), c->name);
|
|
375 do_error_dialog(buf, _("Chat Error!"));
|
|
376 } else if (conn->type == AIM_CONN_TYPE_CHATNAV) {
|
|
377 if (odata->cnpa > 0)
|
|
378 gdk_input_remove(odata->cnpa);
|
|
379 odata->cnpa = 0;
|
|
380 debug_printf("removing chatnav input watcher\n");
|
|
381 if (odata->create_exchange) {
|
|
382 odata->create_exchange = 0;
|
|
383 g_free(odata->create_name);
|
|
384 odata->create_name = NULL;
|
|
385 do_error_dialog(_("Chat is currently unavailable"),
|
|
386 _("Gaim - Chat"));
|
|
387 }
|
|
388 aim_conn_kill(odata->sess, &conn);
|
|
389 } else if (conn->type == AIM_CONN_TYPE_AUTH) {
|
|
390 if (odata->paspa > 0)
|
|
391 gdk_input_remove(odata->paspa);
|
|
392 odata->paspa = 0;
|
|
393 debug_printf("removing authconn input watcher\n");
|
|
394 aim_conn_kill(odata->sess, &conn);
|
|
395 } else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) {
|
|
396 debug_printf("No handler for rendezvous disconnect (%d).\n",
|
|
397 source);
|
|
398 aim_conn_kill(odata->sess, &conn);
|
|
399 } else {
|
|
400 debug_printf("holy crap! generic connection error! %d\n",
|
|
401 conn->type);
|
|
402 aim_conn_kill(odata->sess, &conn);
|
|
403 }
|
|
404 }
|
|
405 }
|
|
406 }
|
|
407 }
|
|
408
|
|
409 static void oscar_debug(struct aim_session_t *sess, int level, const char *format, va_list va) {
|
|
410 char *s = g_strdup_vprintf(format, va);
|
|
411 char buf[256];
|
|
412 char *t;
|
|
413 struct gaim_connection *gc = sess->aux_data;
|
|
414
|
|
415 g_snprintf(buf, sizeof(buf), "%s %d: ", gc->username, level);
|
|
416 t = g_strconcat(buf, s, NULL);
|
|
417 debug_printf(t);
|
|
418 if (t[strlen(t)-1] != '\n')
|
|
419 debug_printf("\n");
|
|
420 g_free(t);
|
|
421 g_free(s);
|
|
422 }
|
|
423
|
|
424 static void oscar_login_connect(gpointer data, gint source, GdkInputCondition cond)
|
|
425 {
|
|
426 struct gaim_connection *gc = data;
|
|
427 struct oscar_data *odata;
|
|
428 struct aim_session_t *sess;
|
|
429 struct aim_conn_t *conn;
|
|
430
|
|
431 if (!g_slist_find(connections, gc)) {
|
|
432 close(source);
|
|
433 return;
|
|
434 }
|
|
435
|
|
436 odata = gc->proto_data;
|
|
437 sess = odata->sess;
|
|
438 conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
|
|
439
|
|
440 if (source < 0) {
|
|
441 hide_login_progress(gc, _("Couldn't connect to host"));
|
|
442 signoff(gc);
|
|
443 return;
|
|
444 }
|
|
445
|
|
446 aim_conn_completeconnect(sess, conn);
|
|
447 gc->inpa = gdk_input_add(conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
448 oscar_callback, conn);
|
|
449 debug_printf(_("Password sent, waiting for response\n"));
|
|
450 }
|
|
451
|
|
452 static void oscar_login(struct aim_user *user) {
|
|
453 struct aim_session_t *sess;
|
|
454 struct aim_conn_t *conn;
|
|
455 char buf[256];
|
|
456 struct gaim_connection *gc = new_gaim_conn(user);
|
|
457 struct oscar_data *odata = gc->proto_data = g_new0(struct oscar_data, 1);
|
|
458 odata->create_exchange = 0;
|
|
459
|
|
460 debug_printf(_("Logging in %s\n"), user->username);
|
|
461
|
|
462 sess = g_new0(struct aim_session_t, 1);
|
|
463
|
|
464 aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
|
|
465 aim_setdebuggingcb(sess, oscar_debug);
|
|
466
|
|
467 /* we need an immediate queue because we don't use a while-loop to
|
|
468 * see if things need to be sent. */
|
|
469 aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
|
|
470 odata->sess = sess;
|
|
471 sess->aux_data = gc;
|
|
472
|
|
473 conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
|
|
474 if (conn == NULL) {
|
|
475 debug_printf(_("internal connection error\n"));
|
|
476 hide_login_progress(gc, _("Unable to login to AIM"));
|
|
477 signoff(gc);
|
|
478 return;
|
|
479 }
|
|
480
|
|
481 g_snprintf(buf, sizeof(buf), _("Signon: %s"), gc->username);
|
|
482 set_login_progress(gc, 2, buf);
|
|
483
|
|
484 aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0);
|
|
485 aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0);
|
|
486
|
|
487 conn->status |= AIM_CONN_STATUS_INPROGRESS;
|
|
488 conn->fd = proxy_connect(user->proto_opt[USEROPT_AUTH][0] ?
|
|
489 user->proto_opt[USEROPT_AUTH] : FAIM_LOGIN_SERVER,
|
|
490 user->proto_opt[USEROPT_AUTHPORT][0] ?
|
|
491 atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT,
|
|
492 oscar_login_connect, gc);
|
|
493 if (conn->fd < 0) {
|
|
494 hide_login_progress(gc, _("Couldn't connect to host"));
|
|
495 signoff(gc);
|
|
496 return;
|
|
497 }
|
|
498 aim_request_login(sess, conn, gc->username);
|
|
499 }
|
|
500
|
|
501 static void oscar_close(struct gaim_connection *gc) {
|
|
502 struct oscar_data *odata = (struct oscar_data *)gc->proto_data;
|
|
503 if (gc->protocol != PROTO_OSCAR) return;
|
|
504
|
|
505 while (odata->oscar_chats) {
|
|
506 struct chat_connection *n = odata->oscar_chats->data;
|
|
507 if (n->inpa > 0)
|
|
508 gdk_input_remove(n->inpa);
|
|
509 g_free(n->name);
|
|
510 g_free(n->show);
|
|
511 odata->oscar_chats = g_slist_remove(odata->oscar_chats, n);
|
|
512 g_free(n);
|
|
513 }
|
|
514 while (odata->direct_ims) {
|
|
515 struct direct_im *n = odata->direct_ims->data;
|
|
516 if (n->watcher > 0)
|
|
517 gdk_input_remove(n->watcher);
|
|
518 odata->direct_ims = g_slist_remove(odata->direct_ims, n);
|
|
519 g_free(n);
|
|
520 }
|
|
521 #if USE_PIXBUF
|
|
522 while (odata->hasicons) {
|
|
523 struct icon_req *n = odata->hasicons->data;
|
|
524 if (n->anim)
|
|
525 gdk_pixbuf_animation_unref(n->anim);
|
|
526 if (n->unanim)
|
|
527 gdk_pixbuf_unref(n->unanim);
|
|
528 if (n->timer)
|
|
529 gtk_timeout_remove(n->timer);
|
|
530 if (n->cnv && n->pix)
|
|
531 gtk_container_remove(GTK_CONTAINER(n->cnv->bbox), n->pix);
|
|
532 g_free(n->user);
|
|
533 if (n->data)
|
|
534 g_free(n->data);
|
|
535 odata->hasicons = g_slist_remove(odata->hasicons, n);
|
|
536 g_free(n);
|
|
537 }
|
|
538 #endif
|
|
539 if (gc->inpa > 0)
|
|
540 gdk_input_remove(gc->inpa);
|
|
541 if (odata->cnpa > 0)
|
|
542 gdk_input_remove(odata->cnpa);
|
|
543 if (odata->paspa > 0)
|
|
544 gdk_input_remove(odata->paspa);
|
|
545 aim_session_kill(odata->sess);
|
|
546 g_free(odata->sess);
|
|
547 odata->sess = NULL;
|
|
548 g_free(gc->proto_data);
|
|
549 gc->proto_data = NULL;
|
|
550 debug_printf(_("Signed off.\n"));
|
|
551 }
|
|
552
|
|
553 static void oscar_bos_connect(gpointer data, gint source, GdkInputCondition cond) {
|
|
554 struct gaim_connection *gc = data;
|
|
555 struct oscar_data *odata;
|
|
556 struct aim_session_t *sess;
|
|
557 struct aim_conn_t *bosconn;
|
|
558
|
|
559 if (!g_slist_find(connections, gc)) {
|
|
560 close(source);
|
|
561 return;
|
|
562 }
|
|
563
|
|
564 odata = gc->proto_data;
|
|
565 sess = odata->sess;
|
|
566 bosconn = odata->conn;
|
|
567
|
|
568 if (source < 0) {
|
|
569 hide_login_progress(gc, _("Could Not Connect"));
|
|
570 signoff(gc);
|
|
571 return;
|
|
572 }
|
|
573
|
|
574 aim_conn_completeconnect(sess, bosconn);
|
|
575 gc->inpa = gdk_input_add(bosconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
576 oscar_callback, bosconn);
|
|
577 set_login_progress(gc, 4, _("Connection established, cookie sent"));
|
|
578 }
|
|
579
|
|
580 int gaim_parse_auth_resp(struct aim_session_t *sess,
|
|
581 struct command_rx_struct *command, ...) {
|
|
582 va_list ap;
|
|
583 struct aim_conn_t *bosconn = NULL;
|
|
584 char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
|
|
585 unsigned char *cookie = NULL;
|
|
586 int errorcode = 0, regstatus = 0;
|
|
587 int latestbuild = 0, latestbetabuild = 0;
|
|
588 char *latestrelease = NULL, *latestbeta = NULL;
|
|
589 char *latestreleaseurl = NULL, *latestbetaurl = NULL;
|
|
590 char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
|
|
591 int i; char *host; int port;
|
|
592 struct aim_user *user;
|
|
593
|
|
594 struct gaim_connection *gc = sess->aux_data;
|
|
595 struct oscar_data *od = gc->proto_data;
|
|
596 user = gc->user;
|
|
597 port = user->proto_opt[USEROPT_AUTHPORT][0] ?
|
|
598 atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT,
|
|
599
|
|
600 va_start(ap, command);
|
|
601 sn = va_arg(ap, char *);
|
|
602 errorcode = va_arg(ap, int);
|
|
603 errurl = va_arg(ap, char *);
|
|
604 regstatus = va_arg(ap, int);
|
|
605 email = va_arg(ap, char *);
|
|
606 bosip = va_arg(ap, char *);
|
|
607 cookie = va_arg(ap, unsigned char *);
|
|
608
|
|
609 latestrelease = va_arg(ap, char *);
|
|
610 latestbuild = va_arg(ap, int);
|
|
611 latestreleaseurl = va_arg(ap, char *);
|
|
612 latestreleaseinfo = va_arg(ap, char *);
|
|
613
|
|
614 latestbeta = va_arg(ap, char *);
|
|
615 latestbetabuild = va_arg(ap, int);
|
|
616 latestbetaurl = va_arg(ap, char *);
|
|
617 latestbetainfo = va_arg(ap, char *);
|
|
618
|
|
619 va_end(ap);
|
|
620
|
|
621 debug_printf("inside auth_resp (Screen name: %s)\n", sn);
|
|
622
|
|
623 if (errorcode || !bosip || !cookie) {
|
|
624 switch (errorcode) {
|
|
625 case 0x05:
|
|
626 /* Incorrect nick/password */
|
|
627 hide_login_progress(gc, _("Incorrect nickname or password."));
|
|
628 plugin_event(event_error, (void *)980, 0, 0, 0);
|
|
629 break;
|
|
630 case 0x11:
|
|
631 /* Suspended account */
|
|
632 hide_login_progress(gc, _("Your account is currently suspended."));
|
|
633 break;
|
|
634 case 0x18:
|
|
635 /* connecting too frequently */
|
|
636 hide_login_progress(gc, _("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."));
|
|
637 plugin_event(event_error, (void *)983, 0, 0, 0);
|
|
638 break;
|
|
639 case 0x1c:
|
|
640 /* client too old */
|
|
641 hide_login_progress(gc, _("The client version you are using is too old. Please upgrade at " WEBSITE));
|
|
642 plugin_event(event_error, (void *)989, 0, 0, 0);
|
|
643 break;
|
|
644 default:
|
|
645 hide_login_progress(gc, _("Authentication Failed"));
|
|
646 break;
|
|
647 }
|
|
648 debug_printf("Login Error Code 0x%04x\n", errorcode);
|
|
649 debug_printf("Error URL: %s\n", errurl);
|
|
650 od->killme = TRUE;
|
|
651 return 1;
|
|
652 }
|
|
653
|
|
654
|
|
655 debug_printf("Reg status: %2d\n", regstatus);
|
|
656 if (email) {
|
|
657 debug_printf("Email: %s\n", email);
|
|
658 } else {
|
|
659 debug_printf("Email is NULL\n");
|
|
660 }
|
|
661 debug_printf("BOSIP: %s\n", bosip);
|
|
662 if (latestbeta)
|
|
663 debug_printf("Latest WinAIM beta version %s, build %d, at %s (%s)\n",
|
|
664 latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
|
|
665 if (latestrelease)
|
|
666 debug_printf("Latest WinAIM released version %s, build %d, at %s (%s)\n",
|
|
667 latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo);
|
|
668 debug_printf("Closing auth connection...\n");
|
|
669 aim_conn_kill(sess, &command->conn);
|
|
670
|
|
671 bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL);
|
|
672 if (bosconn == NULL) {
|
|
673 hide_login_progress(gc, _("Internal Error"));
|
|
674 od->killme = TRUE;
|
|
675 return 0;
|
|
676 }
|
|
677
|
|
678 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0);
|
|
679 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0007, gaim_rateresp, 0); /* rate info */
|
|
680 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
|
|
681 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, gaim_server_ready, 0);
|
|
682 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
|
|
683 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0);
|
|
684 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, gaim_reportinterval, 0);
|
|
685 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0);
|
|
686 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0);
|
|
687 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0);
|
|
688 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0);
|
|
689 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0);
|
|
690 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, gaim_parse_misses, 0);
|
|
691 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, gaim_parse_ratechange, 0);
|
|
692 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL, gaim_parse_evilnotify, 0);
|
|
693 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, gaim_parse_searcherror, 0);
|
|
694 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, gaim_parse_searchreply, 0);
|
|
695 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0);
|
|
696 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parse_user_info, 0);
|
|
697 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, gaim_parse_msgack, 0);
|
|
698 aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0);
|
|
699 aim_conn_addhandler(sess, bosconn, 0x0001, 0x0001, gaim_parse_genericerr, 0);
|
|
700 aim_conn_addhandler(sess, bosconn, 0x0003, 0x0001, gaim_parse_genericerr, 0);
|
|
701 aim_conn_addhandler(sess, bosconn, 0x0009, 0x0001, gaim_parse_genericerr, 0);
|
|
702 aim_conn_addhandler(sess, bosconn, 0x0001, 0x001f, gaim_memrequest, 0);
|
|
703
|
|
704 ((struct oscar_data *)gc->proto_data)->conn = bosconn;
|
|
705 for (i = 0; i < (int)strlen(bosip); i++) {
|
|
706 if (bosip[i] == ':') {
|
|
707 port = atoi(&(bosip[i+1]));
|
|
708 break;
|
|
709 }
|
|
710 }
|
|
711 host = g_strndup(bosip, i);
|
|
712 bosconn->status |= AIM_CONN_STATUS_INPROGRESS;
|
|
713 bosconn->fd = proxy_connect(host, port, oscar_bos_connect, gc);
|
|
714 g_free(host);
|
|
715 if (bosconn->fd < 0) {
|
|
716 hide_login_progress(gc, _("Could Not Connect"));
|
|
717 od->killme = TRUE;
|
|
718 return 0;
|
|
719 }
|
|
720 aim_auth_sendcookie(sess, bosconn, cookie);
|
|
721 gdk_input_remove(gc->inpa);
|
|
722 return 1;
|
|
723 }
|
|
724
|
|
725 struct pieceofcrap {
|
|
726 struct gaim_connection *gc;
|
|
727 unsigned long offset;
|
|
728 unsigned long len;
|
|
729 char *modname;
|
|
730 int fd;
|
|
731 struct aim_conn_t *conn;
|
|
732 unsigned int inpa;
|
|
733 };
|
|
734
|
|
735 static void damn_you(gpointer data, gint source, GdkInputCondition c)
|
|
736 {
|
|
737 struct pieceofcrap *pos = data;
|
|
738 struct oscar_data *od = pos->gc->proto_data;
|
|
739 char in = '\0';
|
|
740 int x = 0;
|
|
741 unsigned char m[17];
|
|
742
|
|
743 while (read(pos->fd, &in, 1) == 1) {
|
|
744 if (in == '\n')
|
|
745 x++;
|
|
746 else if (in != '\r')
|
|
747 x = 0;
|
|
748 if (x == 2)
|
|
749 break;
|
|
750 in = '\0';
|
|
751 }
|
|
752 if (in != '\n') {
|
|
753 do_error_dialog("Gaim was unable to get a valid hash for logging into AIM."
|
|
754 " You may be disconnected shortly.", "Login Error");
|
|
755 gdk_input_remove(pos->inpa);
|
|
756 close(pos->fd);
|
|
757 g_free(pos);
|
|
758 return;
|
|
759 }
|
|
760 read(pos->fd, m, 16);
|
|
761 m[16] = '\0';
|
|
762 debug_printf("Sending hash: ");
|
|
763 for (x = 0; x < 16; x++)
|
|
764 debug_printf("%02x ", (unsigned char)m[x]);
|
|
765 debug_printf("\n");
|
|
766 gdk_input_remove(pos->inpa);
|
|
767 close(pos->fd);
|
|
768 aim_sendmemblock(od->sess, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH);
|
|
769 g_free(pos);
|
|
770 }
|
|
771
|
|
772 static void straight_to_hell(gpointer data, gint source, GdkInputCondition cond) {
|
|
773 struct pieceofcrap *pos = data;
|
|
774 char buf[BUF_LONG];
|
|
775
|
|
776 if (source < 0) {
|
|
777 do_error_dialog("Gaim was unable to get a valid hash for logging into AIM."
|
|
778 " You may be disconnected shortly.", "Login Error");
|
|
779 if (pos->modname)
|
|
780 g_free(pos->modname);
|
|
781 g_free(pos);
|
|
782 return;
|
|
783 }
|
|
784
|
|
785 g_snprintf(buf, sizeof(buf), "GET " AIMHASHDATA
|
|
786 "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n",
|
|
787 pos->offset, pos->len, pos->modname ? pos->modname : "");
|
|
788 write(pos->fd, buf, strlen(buf));
|
|
789 if (pos->modname)
|
|
790 g_free(pos->modname);
|
|
791 pos->inpa = gdk_input_add(pos->fd, GDK_INPUT_READ, damn_you, pos);
|
|
792 return;
|
|
793 }
|
|
794
|
|
795 /* size of icbmui.ocm, the largest module in AIM 3.5 */
|
|
796 #define AIM_MAX_FILE_SIZE 98304
|
|
797
|
|
798 int gaim_memrequest(struct aim_session_t *sess,
|
|
799 struct command_rx_struct *command, ...) {
|
|
800 va_list ap;
|
|
801 struct pieceofcrap *pos;
|
|
802 unsigned long offset, len;
|
|
803 char *modname;
|
|
804 int fd;
|
|
805
|
|
806 va_start(ap, command);
|
|
807 offset = va_arg(ap, unsigned long);
|
|
808 len = va_arg(ap, unsigned long);
|
|
809 modname = va_arg(ap, char *);
|
|
810 va_end(ap);
|
|
811
|
|
812 debug_printf("offset: %d, len: %d, file: %s\n", offset, len, modname ? modname : "aim.exe");
|
|
813 if (len == 0) {
|
|
814 debug_printf("len is 0, hashing NULL\n");
|
|
815 aim_sendmemblock(sess, command->conn, offset, len, NULL,
|
|
816 AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
|
|
817 return 1;
|
|
818 }
|
|
819 /* uncomment this when you're convinced it's right. remember, it's been wrong before.
|
|
820 if (offset > AIM_MAX_FILE_SIZE || len > AIM_MAX_FILE_SIZE) {
|
|
821 char *buf;
|
|
822 int i = 8;
|
|
823 if (modname)
|
|
824 i += strlen(modname);
|
|
825 buf = g_malloc(i);
|
|
826 i = 0;
|
|
827 if (modname) {
|
|
828 memcpy(buf, modname, strlen(modname));
|
|
829 i += strlen(modname);
|
|
830 }
|
|
831 buf[i++] = offset & 0xff;
|
|
832 buf[i++] = (offset >> 8) & 0xff;
|
|
833 buf[i++] = (offset >> 16) & 0xff;
|
|
834 buf[i++] = (offset >> 24) & 0xff;
|
|
835 buf[i++] = len & 0xff;
|
|
836 buf[i++] = (len >> 8) & 0xff;
|
|
837 buf[i++] = (len >> 16) & 0xff;
|
|
838 buf[i++] = (len >> 24) & 0xff;
|
|
839 debug_printf("len + offset is invalid, hashing request\n");
|
|
840 aim_sendmemblock(sess, command->conn, offset, i, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
|
|
841 g_free(buf);
|
|
842 return 1;
|
|
843 }
|
|
844 */
|
|
845
|
|
846 pos = g_new0(struct pieceofcrap, 1);
|
|
847 pos->gc = sess->aux_data;
|
|
848 pos->conn = command->conn;
|
|
849
|
|
850 pos->offset = offset;
|
|
851 pos->len = len;
|
|
852 pos->modname = modname ? g_strdup(modname) : NULL;
|
|
853
|
|
854 fd = proxy_connect("gaim.sourceforge.net", 80, straight_to_hell, pos);
|
|
855 if (fd < 0) {
|
|
856 if (pos->modname)
|
|
857 g_free(pos->modname);
|
|
858 g_free(pos);
|
|
859 do_error_dialog("Gaim was unable to get a valid hash for logging into AIM."
|
|
860 " You may be disconnected shortly.", "Login Error");
|
|
861 }
|
|
862 pos->fd = fd;
|
|
863
|
|
864 return 1;
|
|
865 }
|
|
866
|
|
867 int gaim_parse_login(struct aim_session_t *sess,
|
|
868 struct command_rx_struct *command, ...) {
|
|
869 #if 0
|
|
870 struct client_info_s info = {"gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b};
|
|
871 #else
|
|
872 struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
|
|
873 #endif
|
|
874 char *key;
|
|
875 va_list ap;
|
|
876 struct gaim_connection *gc = sess->aux_data;
|
|
877
|
|
878 va_start(ap, command);
|
|
879 key = va_arg(ap, char *);
|
|
880 va_end(ap);
|
|
881
|
|
882 aim_send_login(sess, command->conn, gc->username, gc->password, &info, key);
|
|
883 return 1;
|
|
884 }
|
|
885
|
|
886 int gaim_server_ready(struct aim_session_t *sess,
|
|
887 struct command_rx_struct *command, ...) {
|
|
888 static int id = 1;
|
|
889 struct gaim_connection *gc = sess->aux_data;
|
|
890 struct oscar_data *od = gc->proto_data;
|
|
891 struct chat_connection *chatcon;
|
|
892 switch (command->conn->type) {
|
|
893 case AIM_CONN_TYPE_AUTH:
|
|
894 aim_auth_setversions(sess, command->conn);
|
|
895 aim_bos_reqrate(sess, command->conn);
|
|
896 debug_printf("done with AUTH ServerReady\n");
|
|
897 if (od->chpass) {
|
|
898 debug_printf("changing password\n");
|
|
899 aim_auth_changepasswd(sess, command->conn, od->newp, od->oldp);
|
|
900 g_free(od->oldp);
|
|
901 g_free(od->newp);
|
|
902 od->chpass = FALSE;
|
|
903 }
|
|
904 if (od->conf) {
|
|
905 debug_printf("confirming account\n");
|
|
906 aim_auth_reqconfirm(sess, command->conn);
|
|
907 od->conf = FALSE;
|
|
908 }
|
|
909 if (od->reqemail) {
|
|
910 debug_printf("requesting email\n");
|
|
911 aim_auth_getinfo(sess, command->conn, 0x0011);
|
|
912 od->reqemail = FALSE;
|
|
913 }
|
|
914 break;
|
|
915 case AIM_CONN_TYPE_BOS:
|
|
916 aim_setversions(sess, command->conn);
|
|
917 aim_bos_reqrate(sess, command->conn); /* request rate info */
|
|
918 debug_printf("done with BOS ServerReady\n");
|
|
919 break;
|
|
920 case AIM_CONN_TYPE_CHATNAV:
|
|
921 debug_printf("chatnav: got server ready\n");
|
|
922 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0);
|
|
923 aim_bos_reqrate(sess, command->conn);
|
|
924 aim_bos_ackrateresp(sess, command->conn);
|
|
925 aim_chatnav_clientready(sess, command->conn);
|
|
926 aim_chatnav_reqrights(sess, command->conn);
|
|
927 break;
|
|
928 case AIM_CONN_TYPE_CHAT:
|
|
929 debug_printf("chat: got server ready\n");
|
|
930 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0);
|
|
931 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0);
|
|
932 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0);
|
|
933 aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0);
|
|
934 aim_bos_reqrate(sess, command->conn);
|
|
935 aim_bos_ackrateresp(sess, command->conn);
|
|
936 aim_chat_clientready(sess, command->conn);
|
|
937 chatcon = find_oscar_chat_by_conn(gc, command->conn);
|
|
938 chatcon->id = id;
|
|
939 chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
|
|
940 break;
|
|
941 case AIM_CONN_TYPE_RENDEZVOUS:
|
|
942 break;
|
|
943 default: /* huh? */
|
|
944 debug_printf("server ready: got unexpected connection type %04x\n", command->conn->type);
|
|
945 break;
|
|
946 }
|
|
947 return 1;
|
|
948 }
|
|
949
|
|
950 static void oscar_chatnav_connect(gpointer data, gint source, GdkInputCondition cond)
|
|
951 {
|
|
952 struct gaim_connection *gc = data;
|
|
953 struct oscar_data *odata;
|
|
954 struct aim_session_t *sess;
|
|
955 struct aim_conn_t *tstconn;
|
|
956
|
|
957 if (!g_slist_find(connections, gc)) {
|
|
958 close(source);
|
|
959 return;
|
|
960 }
|
|
961
|
|
962 odata = gc->proto_data;
|
|
963 sess = odata->sess;
|
|
964 tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_CHATNAV);
|
|
965
|
|
966 if (source < 0) {
|
|
967 aim_conn_kill(sess, &tstconn);
|
|
968 debug_printf("unable to connect to chatnav server\n");
|
|
969 return;
|
|
970 }
|
|
971
|
|
972 aim_conn_completeconnect(sess, tstconn);
|
|
973 odata->cnpa = gdk_input_add(tstconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
974 oscar_callback, tstconn);
|
|
975 debug_printf("chatnav: connected\n");
|
|
976 }
|
|
977
|
|
978 static void oscar_auth_connect(gpointer data, gint source, GdkInputCondition cond)
|
|
979 {
|
|
980 struct gaim_connection *gc = data;
|
|
981 struct oscar_data *odata;
|
|
982 struct aim_session_t *sess;
|
|
983 struct aim_conn_t *tstconn;
|
|
984
|
|
985 if (!g_slist_find(connections, gc)) {
|
|
986 close(source);
|
|
987 return;
|
|
988 }
|
|
989
|
|
990 odata = gc->proto_data;
|
|
991 sess = odata->sess;
|
|
992 tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
|
|
993
|
|
994 if (source < 0) {
|
|
995 aim_conn_kill(sess, &tstconn);
|
|
996 debug_printf("unable to connect to authorizer\n");
|
|
997 return;
|
|
998 }
|
|
999
|
|
1000 aim_conn_completeconnect(sess, tstconn);
|
|
1001 odata->paspa = gdk_input_add(tstconn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
1002 oscar_callback, tstconn);
|
|
1003 debug_printf("chatnav: connected\n");
|
|
1004 }
|
|
1005
|
|
1006 static void oscar_chat_connect(gpointer data, gint source, GdkInputCondition cond)
|
|
1007 {
|
|
1008 struct chat_connection *ccon = data;
|
|
1009 struct gaim_connection *gc = ccon->gc;
|
|
1010 struct oscar_data *odata;
|
|
1011 struct aim_session_t *sess;
|
|
1012 struct aim_conn_t *tstconn;
|
|
1013
|
|
1014 if (!g_slist_find(connections, gc)) {
|
|
1015 close(source);
|
|
1016 g_free(ccon->show);
|
|
1017 g_free(ccon->name);
|
|
1018 g_free(ccon);
|
|
1019 return;
|
|
1020 }
|
|
1021
|
|
1022 odata = gc->proto_data;
|
|
1023 sess = odata->sess;
|
|
1024 tstconn = ccon->conn;
|
|
1025
|
|
1026 if (source < 0) {
|
|
1027 aim_conn_kill(sess, &tstconn);
|
|
1028 g_free(ccon->show);
|
|
1029 g_free(ccon->name);
|
|
1030 g_free(ccon);
|
|
1031 return;
|
|
1032 }
|
|
1033
|
|
1034 aim_conn_completeconnect(sess, ccon->conn);
|
|
1035 ccon->inpa = gdk_input_add(tstconn->fd,
|
|
1036 GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
1037 oscar_callback, tstconn);
|
|
1038 odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon);
|
|
1039 aim_chat_attachname(tstconn, ccon->name);
|
|
1040 }
|
|
1041
|
|
1042 int gaim_handle_redirect(struct aim_session_t *sess,
|
|
1043 struct command_rx_struct *command, ...) {
|
|
1044 va_list ap;
|
|
1045 int serviceid;
|
|
1046 char *ip;
|
|
1047 unsigned char *cookie;
|
|
1048 struct gaim_connection *gc = sess->aux_data;
|
|
1049 struct aim_user *user = gc->user;
|
|
1050 struct aim_conn_t *tstconn;
|
|
1051 int i;
|
|
1052 char *host;
|
|
1053 int port;
|
|
1054
|
|
1055 port = user->proto_opt[USEROPT_AUTHPORT][0] ?
|
|
1056 atoi(user->proto_opt[USEROPT_AUTHPORT]) : FAIM_LOGIN_PORT,
|
|
1057
|
|
1058 va_start(ap, command);
|
|
1059 serviceid = va_arg(ap, int);
|
|
1060 ip = va_arg(ap, char *);
|
|
1061 cookie = va_arg(ap, unsigned char *);
|
|
1062
|
|
1063 for (i = 0; i < (int)strlen(ip); i++) {
|
|
1064 if (ip[i] == ':') {
|
|
1065 port = atoi(&(ip[i+1]));
|
|
1066 break;
|
|
1067 }
|
|
1068 }
|
|
1069 host = g_strndup(ip, i);
|
|
1070
|
|
1071 switch(serviceid) {
|
|
1072 case 0x7: /* Authorizer */
|
|
1073 debug_printf("Reconnecting with authorizor...\n");
|
|
1074 tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
|
|
1075 if (tstconn == NULL) {
|
|
1076 debug_printf("unable to reconnect with authorizer\n");
|
|
1077 g_free(host);
|
|
1078 return 1;
|
|
1079 }
|
|
1080 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0);
|
|
1081 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0007, gaim_rateresp, 0);
|
|
1082 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, gaim_info_change, 0);
|
|
1083 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, gaim_info_change, 0);
|
|
1084 aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0);
|
|
1085
|
|
1086 tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
|
|
1087 tstconn->fd = proxy_connect(host, port, oscar_auth_connect, gc);
|
|
1088 if (tstconn->fd < 0) {
|
|
1089 aim_conn_kill(sess, &tstconn);
|
|
1090 debug_printf("unable to reconnect with authorizer\n");
|
|
1091 g_free(host);
|
|
1092 return 1;
|
|
1093 }
|
|
1094 aim_auth_sendcookie(sess, tstconn, cookie);
|
|
1095 break;
|
|
1096 case 0xd: /* ChatNav */
|
|
1097 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, NULL);
|
|
1098 if (tstconn == NULL) {
|
|
1099 debug_printf("unable to connect to chatnav server\n");
|
|
1100 g_free(host);
|
|
1101 return 1;
|
|
1102 }
|
|
1103 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0);
|
|
1104
|
|
1105 tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
|
|
1106 tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, gc);
|
|
1107 if (tstconn->fd < 0) {
|
|
1108 aim_conn_kill(sess, &tstconn);
|
|
1109 debug_printf("unable to connect to chatnav server\n");
|
|
1110 g_free(host);
|
|
1111 return 1;
|
|
1112 }
|
|
1113 aim_auth_sendcookie(sess, tstconn, cookie);
|
|
1114 break;
|
|
1115 case 0xe: /* Chat */
|
|
1116 {
|
|
1117 char *roomname = va_arg(ap, char *);
|
|
1118 int exchange = va_arg(ap, int);
|
|
1119 struct chat_connection *ccon;
|
|
1120 tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, NULL);
|
|
1121 if (tstconn == NULL) {
|
|
1122 debug_printf("unable to connect to chat server\n");
|
|
1123 g_free(host);
|
|
1124 return 1;
|
|
1125 }
|
|
1126
|
|
1127 aim_conn_addhandler(sess, tstconn, 0x0001, 0x0003, gaim_server_ready, 0);
|
|
1128 ccon = g_new0(struct chat_connection, 1);
|
|
1129 ccon->conn = tstconn;
|
|
1130 ccon->gc = gc;
|
|
1131 ccon->fd = -1;
|
|
1132 ccon->name = g_strdup(roomname);
|
|
1133 ccon->exchange = exchange;
|
|
1134 ccon->show = extract_name(roomname);
|
|
1135
|
|
1136 ccon->conn->status |= AIM_CONN_STATUS_INPROGRESS;
|
|
1137 ccon->conn->fd = proxy_connect(host, port, oscar_chat_connect, ccon);
|
|
1138 if (ccon->conn->fd < 0) {
|
|
1139 aim_conn_kill(sess, &tstconn);
|
|
1140 debug_printf("unable to connect to chat server\n");
|
|
1141 g_free(host);
|
|
1142 g_free(ccon->show);
|
|
1143 g_free(ccon->name);
|
|
1144 g_free(ccon);
|
|
1145 return 1;
|
|
1146 }
|
|
1147 aim_auth_sendcookie(sess, tstconn, cookie);
|
|
1148 debug_printf("Connected to chat room %s exchange %d\n", roomname, exchange);
|
|
1149 }
|
|
1150 break;
|
|
1151 default: /* huh? */
|
|
1152 debug_printf("got redirect for unknown service 0x%04x\n", serviceid);
|
|
1153 break;
|
|
1154 }
|
|
1155
|
|
1156 va_end(ap);
|
|
1157
|
|
1158 g_free(host);
|
|
1159 return 1;
|
|
1160 }
|
|
1161
|
|
1162 int gaim_parse_oncoming(struct aim_session_t *sess,
|
|
1163 struct command_rx_struct *command, ...) {
|
|
1164 struct aim_userinfo_s *info;
|
|
1165 time_t time_idle;
|
|
1166 int type = 0;
|
|
1167 struct gaim_connection *gc = sess->aux_data;
|
|
1168
|
|
1169 va_list ap;
|
|
1170 va_start(ap, command);
|
|
1171 info = va_arg(ap, struct aim_userinfo_s *);
|
|
1172 va_end(ap);
|
|
1173
|
|
1174 if (info->flags & AIM_FLAG_UNCONFIRMED)
|
|
1175 type |= UC_UNCONFIRMED;
|
|
1176 else if (info->flags & AIM_FLAG_ADMINISTRATOR)
|
|
1177 type |= UC_ADMIN;
|
|
1178 else if (info->flags & AIM_FLAG_AOL)
|
|
1179 type |= UC_AOL;
|
|
1180 else if (info->flags & AIM_FLAG_FREE)
|
|
1181 type |= UC_NORMAL;
|
|
1182 if (info->flags & AIM_FLAG_AWAY)
|
|
1183 type |= UC_UNAVAILABLE;
|
|
1184
|
|
1185 if (info->idletime) {
|
|
1186 time(&time_idle);
|
|
1187 time_idle -= info->idletime*60;
|
|
1188 } else
|
|
1189 time_idle = 0;
|
|
1190
|
|
1191 serv_got_update(gc, info->sn, 1, info->warnlevel/10, info->onlinesince,
|
|
1192 time_idle, type, info->capabilities);
|
|
1193
|
|
1194 return 1;
|
|
1195 }
|
|
1196
|
|
1197 int gaim_parse_offgoing(struct aim_session_t *sess,
|
|
1198 struct command_rx_struct *command, ...) {
|
|
1199 struct aim_userinfo_s *info;
|
|
1200 va_list ap;
|
|
1201 struct gaim_connection *gc = sess->aux_data;
|
|
1202
|
|
1203 va_start(ap, command);
|
|
1204 info = va_arg(ap, struct aim_userinfo_s *);
|
|
1205 va_end(ap);
|
|
1206
|
|
1207 serv_got_update(gc, info->sn, 0, 0, 0, 0, 0, 0);
|
|
1208
|
|
1209 return 1;
|
|
1210 }
|
|
1211
|
|
1212 static void cancel_direct_im(gpointer w, struct ask_direct *d) {
|
|
1213 debug_printf("Freeing DirectIM prompts.\n");
|
|
1214
|
|
1215 g_free(d->sn);
|
|
1216 g_free(d);
|
|
1217 }
|
|
1218
|
|
1219 static void delete_direct_im(gpointer w, struct direct_im *d) {
|
|
1220 struct oscar_data *od = (struct oscar_data *)d->gc->proto_data;
|
|
1221
|
|
1222 od->direct_ims = g_slist_remove(od->direct_ims, d);
|
|
1223 gdk_input_remove(d->watcher);
|
|
1224 aim_conn_kill(od->sess, &d->conn);
|
|
1225 g_free(d);
|
|
1226 }
|
|
1227
|
|
1228 static void oscar_directim_callback(gpointer data, gint source, GdkInputCondition condition) {
|
|
1229 struct direct_im *dim = data;
|
|
1230 struct gaim_connection *gc = dim->gc;
|
|
1231 struct oscar_data *od = gc->proto_data;
|
|
1232 char buf[256];
|
|
1233
|
|
1234 if (!g_slist_find(connections, gc)) {
|
|
1235 g_free(dim);
|
|
1236 return;
|
|
1237 }
|
|
1238
|
|
1239 if (source < 0) {
|
|
1240 g_free(dim);
|
|
1241 return;
|
|
1242 }
|
|
1243
|
|
1244 aim_conn_completeconnect(od->sess, dim->conn);
|
|
1245 if (!(dim->cnv = find_conversation(dim->name))) dim->cnv = new_conversation(dim->name);
|
|
1246 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name);
|
|
1247 write_to_conv(dim->cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL));
|
|
1248
|
|
1249 od->direct_ims = g_slist_append(od->direct_ims, dim);
|
|
1250
|
|
1251 gtk_signal_connect(GTK_OBJECT(dim->cnv->window), "destroy",
|
|
1252 GTK_SIGNAL_FUNC(delete_direct_im), dim);
|
|
1253
|
|
1254 dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
1255 oscar_callback, dim->conn);
|
|
1256 }
|
|
1257
|
|
1258 static int accept_direct_im(gpointer w, struct ask_direct *d) {
|
|
1259 struct gaim_connection *gc = d->gc;
|
|
1260 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
1261 struct direct_im *dim;
|
|
1262 char *host; int port = FAIM_LOGIN_PORT;
|
|
1263 int i;
|
|
1264
|
|
1265 debug_printf("Accepted DirectIM.\n");
|
|
1266
|
|
1267 dim = find_direct_im(od, d->sn);
|
|
1268 if (dim) {
|
|
1269 cancel_direct_im(w, d); /* 40 */
|
|
1270 return TRUE;
|
|
1271 }
|
|
1272 dim = g_new0(struct direct_im, 1);
|
|
1273 dim->gc = d->gc;
|
|
1274 g_snprintf(dim->name, sizeof dim->name, "%s", d->sn);
|
|
1275
|
|
1276 if ((dim->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL)) == NULL) {
|
|
1277 g_free(dim);
|
|
1278 cancel_direct_im(w, d);
|
|
1279 return TRUE;
|
|
1280 }
|
|
1281 dim->conn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
|
|
1282 dim->conn->priv = d->priv;
|
|
1283 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING,
|
|
1284 gaim_directim_incoming, 0);
|
|
1285 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT,
|
|
1286 gaim_directim_disconnect, 0);
|
|
1287 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING,
|
|
1288 gaim_directim_typing, 0);
|
|
1289
|
|
1290 for (i = 0; i < (int)strlen(d->priv->ip); i++) {
|
|
1291 if (d->priv->ip[i] == ':') {
|
|
1292 port = atoi(&(d->priv->ip[i+1]));
|
|
1293 break;
|
|
1294 }
|
|
1295 }
|
|
1296 host = g_strndup(d->priv->ip, i);
|
|
1297 dim->conn->status |= AIM_CONN_STATUS_INPROGRESS;
|
|
1298 dim->conn->fd = proxy_connect(host, port, oscar_directim_callback, dim);
|
|
1299 g_free(host);
|
|
1300 if (dim->conn->fd < 0) {
|
|
1301 aim_conn_kill(od->sess, &dim->conn);
|
|
1302 g_free(dim);
|
|
1303 cancel_direct_im(w, d);
|
|
1304 return TRUE;
|
|
1305 }
|
|
1306
|
|
1307 cancel_direct_im(w, d);
|
|
1308
|
|
1309 return TRUE;
|
|
1310 }
|
|
1311
|
|
1312 /*
|
|
1313 static void cancel_getfile(gpointer w, struct ask_getfile *g) {
|
|
1314 g_free(g->ip);
|
|
1315 g_free(g->cookie);
|
|
1316 g_free(g->sn);
|
|
1317 g_free(g);
|
|
1318 }
|
|
1319
|
|
1320 static void cancel_getfile_file(GtkObject *obj, struct ask_getfile *g) {
|
|
1321 GtkWidget *w = gtk_object_get_user_data(obj);
|
|
1322 gtk_widget_destroy(w);
|
|
1323 cancel_getfile(w, g);
|
|
1324 }
|
|
1325
|
|
1326 static void cancel_getfile_cancel(GtkObject *obj, struct ask_getfile *g) {
|
|
1327 GtkWidget *w = gtk_object_get_user_data(obj);
|
|
1328 gtk_widget_destroy(w);
|
|
1329 }
|
|
1330
|
|
1331 static void interrupt_getfile(GtkObject *obj, struct getfile_transfer *gt) {
|
|
1332 struct gaim_connection *gc = gt->gc;
|
|
1333 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
1334
|
|
1335 gtk_widget_destroy(gt->window);
|
|
1336 gdk_input_remove(gt->gip);
|
|
1337 if (gt->gop > 0)
|
|
1338 gdk_input_remove(gt->gop);
|
|
1339 aim_conn_kill(od->sess, >->conn);
|
|
1340 od->getfiles = g_slist_remove(od->getfiles, gt);
|
|
1341 g_free(gt->receiver);
|
|
1342 g_free(gt->filename);
|
|
1343 fclose(gt->listing);
|
|
1344 g_free(gt);
|
|
1345 }
|
|
1346
|
|
1347 static int gaim_getfile_filereq(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
1348 struct gaim_connection *gc = sess->aux_data;
|
|
1349 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
1350 struct getfile_transfer *gt;
|
|
1351 char buf[2048];
|
|
1352 GtkWidget *label;
|
|
1353 GtkWidget *button;
|
|
1354
|
|
1355 va_list ap;
|
|
1356 struct aim_conn_t *oftconn;
|
|
1357 struct aim_fileheader_t *fh;
|
|
1358 char *cookie;
|
|
1359
|
|
1360 va_start(ap, command);
|
|
1361 oftconn = va_arg(ap, struct aim_conn_t *);
|
|
1362 fh = va_arg(ap, struct aim_fileheader_t *);
|
|
1363 cookie = va_arg(ap, char *);
|
|
1364 va_end(ap);
|
|
1365
|
|
1366 gt = find_getfile_transfer(od, oftconn);
|
|
1367
|
|
1368 if (gt->window)
|
|
1369 return 1;
|
|
1370
|
|
1371 gt->window = gtk_dialog_new();
|
|
1372 gtk_window_set_title(GTK_WINDOW(gt->window), _("Gaim - File Transfer"));
|
|
1373 gtk_widget_realize(gt->window);
|
|
1374 aol_icon(gt->window->window);
|
|
1375
|
|
1376 g_snprintf(buf, sizeof buf, _("Sending %s to %s"), fh->name, gt->receiver);
|
|
1377 label = gtk_label_new(buf);
|
|
1378 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->vbox), label, FALSE, FALSE, 5);
|
|
1379 gtk_widget_show(label);
|
|
1380
|
|
1381 gt->meter = gtk_progress_bar_new();
|
|
1382 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->action_area), gt->meter, FALSE, FALSE, 5);
|
|
1383 gtk_widget_show(gt->meter);
|
|
1384
|
|
1385 gt->label = gtk_label_new("0 %");
|
|
1386 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->action_area), gt->label, FALSE, FALSE, 5);
|
|
1387 gtk_widget_show(gt->label);
|
|
1388
|
|
1389 button = picture_button(gt->window, _("Cancel"), cancel_xpm);
|
|
1390 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gt->window)->action_area), button, FALSE, FALSE, 5);
|
|
1391 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(interrupt_getfile), gt);
|
|
1392
|
|
1393 gtk_widget_show(gt->window);
|
|
1394
|
|
1395 return 1;
|
|
1396 }
|
|
1397
|
|
1398 static void getfile_send_callback(gpointer data, gint source, GdkInputCondition condition) {
|
|
1399 struct getfile_transfer *gt = (struct getfile_transfer *)data;
|
|
1400 int result;
|
|
1401
|
|
1402 result = aim_getfile_send_chunk(gt->conn, gt->file, gt->fh, -1, 1024);
|
|
1403 gt->pos += result;
|
|
1404 if (result == 0) {
|
|
1405 gdk_input_remove(gt->gop); gt->gop = 0;
|
|
1406 } else if (result == -1) {
|
|
1407 do_error_dialog(_("Error in transfer"), "Gaim");
|
|
1408 gdk_input_remove(gt->gop); gt->gop = 0;
|
|
1409 interrupt_getfile(NULL, gt);
|
|
1410 }
|
|
1411 }
|
|
1412
|
|
1413 static int gaim_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
1414 struct gaim_connection *gc = sess->aux_data;
|
|
1415 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
1416 struct getfile_transfer *gt;
|
|
1417
|
|
1418 va_list ap;
|
|
1419 struct aim_conn_t *oftconn;
|
|
1420 struct aim_fileheader_t *fh;
|
|
1421 char *cookie;
|
|
1422
|
|
1423 va_start(ap, command);
|
|
1424 oftconn = va_arg(ap, struct aim_conn_t *);
|
|
1425 fh = va_arg(ap, struct aim_fileheader_t *);
|
|
1426 cookie = va_arg(ap, char *);
|
|
1427 va_end(ap);
|
|
1428
|
|
1429 gt = find_getfile_transfer(od, oftconn);
|
|
1430
|
|
1431 if (gt->gop > 0) {
|
|
1432 debug_printf("already have output watcher?\n");
|
|
1433 return 1;
|
|
1434 }
|
|
1435
|
|
1436 if ((gt->file = fopen(gt->filename, "r")) == NULL) {
|
|
1437 interrupt_getfile(NULL, gt);
|
|
1438 return 1;
|
|
1439 }
|
|
1440 gt->pos = 0;
|
|
1441 gt->fh = g_memdup(fh, sizeof(struct aim_fileheader_t));
|
|
1442 fseek(gt->file, 0, SEEK_SET);
|
|
1443
|
|
1444 gt->gop = gdk_input_add(gt->conn->fd, GDK_INPUT_WRITE, getfile_send_callback, gt);
|
|
1445
|
|
1446 return 1;
|
|
1447 }
|
|
1448
|
|
1449 static int gaim_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
1450 struct gaim_connection *gc = sess->aux_data;
|
|
1451 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
1452 struct getfile_transfer *gt;
|
|
1453
|
|
1454 va_list ap;
|
|
1455 struct aim_conn_t *conn;
|
|
1456 struct aim_fileheader_t *fh;
|
|
1457
|
|
1458 va_start(ap, command);
|
|
1459 conn = va_arg(ap, struct aim_conn_t *);
|
|
1460 fh = va_arg(ap, struct aim_fileheader_t *);
|
|
1461 va_end(ap);
|
|
1462
|
|
1463 gt = find_getfile_transfer(od, conn);
|
|
1464
|
|
1465 gtk_widget_destroy(gt->window);
|
|
1466 gt->window = NULL;
|
|
1467 do_error_dialog(_("Transfer complete."), "Gaim");
|
|
1468
|
|
1469 return 1;
|
|
1470 }
|
|
1471
|
|
1472 static int gaim_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
1473 struct gaim_connection *gc = sess->aux_data;
|
|
1474 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
1475 struct getfile_transfer *gt;
|
|
1476
|
|
1477 va_list ap;
|
|
1478 struct aim_conn_t *conn;
|
|
1479 char *sn;
|
|
1480
|
|
1481 va_start(ap, command);
|
|
1482 conn = va_arg(ap, struct aim_conn_t *);
|
|
1483 sn = va_arg(ap, char *);
|
|
1484 va_end(ap);
|
|
1485
|
|
1486 gt = find_getfile_transfer(od, conn);
|
|
1487 od->getfiles = g_slist_remove(od->getfiles, gt);
|
|
1488 gdk_input_remove(gt->gip);
|
|
1489 if (gt->gop > 0)
|
|
1490 gdk_input_remove(gt->gop);
|
|
1491 g_free(gt->receiver);
|
|
1492 g_free(gt->filename);
|
|
1493 aim_conn_kill(sess, &conn);
|
|
1494 fclose(gt->listing);
|
|
1495 g_free(gt);
|
|
1496
|
|
1497 debug_printf("getfile disconnect\n");
|
|
1498
|
|
1499 return 1;
|
|
1500 }
|
|
1501
|
|
1502 static void oscar_getfile_callback(gpointer data, gint source, GdkInputCondition condition) {
|
|
1503 struct getfile_transfer *gf = data;
|
|
1504 struct gaim_connection *gc = gf->gc;
|
|
1505 struct oscar_data *od = gc->proto_data;
|
|
1506
|
|
1507 gdk_input_remove(gf->gip);
|
|
1508 gf->gip = gdk_input_add(source, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, oscar_callback, gf->conn);
|
|
1509
|
|
1510 aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ, gaim_getfile_filereq, 0);
|
|
1511 aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND, gaim_getfile_filesend, 0);
|
|
1512 aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE, gaim_getfile_complete, 0);
|
|
1513 aim_conn_addhandler(od->sess, gf->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT, gaim_getfile_disconnect, 0);
|
|
1514 }
|
|
1515
|
|
1516 static void do_getfile(GtkObject *obj, struct ask_getfile *g) {
|
|
1517 GtkWidget *w = gtk_object_get_user_data(obj);
|
|
1518 char *filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(w));
|
|
1519 struct gaim_connection *gc = g->gc;
|
|
1520 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
1521 struct getfile_transfer *gf;
|
|
1522 struct stat st;
|
|
1523 struct tm *ft;
|
|
1524 char tmppath[256];
|
|
1525 FILE *file;
|
|
1526 static int current = 0;
|
|
1527 struct aim_conn_t *newconn;
|
|
1528
|
|
1529 if (file_is_dir(filename, w))
|
|
1530 return;
|
|
1531
|
|
1532 if (stat(filename, &st) != 0) {
|
|
1533 gtk_widget_destroy(w);
|
|
1534 do_error_dialog(_("Error examining file"), _("GetFile Error"));
|
|
1535 cancel_getfile(w, g);
|
|
1536 return;
|
|
1537 }
|
|
1538
|
|
1539 g_snprintf(tmppath, sizeof tmppath, "/%s/gaim%d%d", g_get_tmp_dir(), getpid(), current++);
|
|
1540 if ((file = fopen(tmppath, "w+")) == NULL) {
|
|
1541 gtk_widget_destroy(w);
|
|
1542 do_error_dialog(_("Could not open temporary file, aborting"), _("GetFile Error"));
|
|
1543 cancel_getfile(w, g);
|
|
1544 return;
|
|
1545 }
|
|
1546
|
|
1547 gf = g_new0(struct getfile_transfer, 1);
|
|
1548 gf->gc = gc;
|
|
1549 gf->filename = g_strdup(filename);
|
|
1550 gf->listing = file;
|
|
1551 gf->receiver = g_strdup(g->sn);
|
|
1552 gf->size = st.st_size;
|
|
1553
|
|
1554 ft = localtime(&st.st_ctime);
|
|
1555 fprintf(file, "%2d/%2d/%4d %2d:%2d %8ld ",
|
|
1556 ft->tm_mon + 1, ft->tm_mday, ft->tm_year + 1900,
|
|
1557 ft->tm_hour + 1, ft->tm_min + 1, (long)st.st_size);
|
|
1558 fprintf(file, "%s\r\n", g_basename(filename));
|
|
1559 rewind(file);
|
|
1560
|
|
1561 aim_oft_registerlisting(od->sess, file, "");
|
|
1562 if ((newconn = aim_accepttransfer(od->sess, od->conn, g->sn, g->cookie, g->ip, file, AIM_CAPS_GETFILE)) == NULL) {
|
|
1563 od->sess->flags ^= AIM_SESS_FLAGS_NONBLOCKCONNECT;
|
|
1564 do_error_dialog(_("Error connecting for transfer"), _("GetFile Error"));
|
|
1565 g_free(gf->filename);
|
|
1566 fclose(file);
|
|
1567 g_free(gf);
|
|
1568 gtk_widget_destroy(w);
|
|
1569 return;
|
|
1570 }
|
|
1571
|
|
1572 gtk_widget_destroy(w);
|
|
1573
|
|
1574 od->getfiles = g_slist_append(od->getfiles, gf);
|
|
1575 gf->conn = newconn;
|
|
1576 gf->gip = gdk_input_add(newconn->fd, GDK_INPUT_WRITE, oscar_getfile_callback, gf);
|
|
1577 }
|
|
1578
|
|
1579 static int accept_getfile(gpointer w, struct ask_getfile *g) {
|
|
1580 GtkWidget *window;
|
|
1581 window = gtk_file_selection_new(_("Gaim - Send File..."));
|
|
1582 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(window));
|
|
1583 gtk_object_set_user_data(GTK_OBJECT(window), window);
|
|
1584 gtk_signal_connect(GTK_OBJECT(window), "destroy",
|
|
1585 GTK_SIGNAL_FUNC(cancel_getfile_file), g);
|
|
1586 gtk_object_set_user_data(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), window);
|
|
1587 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked",
|
|
1588 GTK_SIGNAL_FUNC(do_getfile), g);
|
|
1589 gtk_object_set_user_data(GTK_OBJECT(GTK_FILE_SELECTION(window)->cancel_button), window);
|
|
1590 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(window)->cancel_button), "clicked",
|
|
1591 GTK_SIGNAL_FUNC(cancel_getfile_cancel), g);
|
|
1592 gtk_widget_show(window);
|
|
1593
|
|
1594 return TRUE;
|
|
1595 }
|
|
1596 */
|
|
1597
|
|
1598 #if USE_PIXBUF
|
|
1599 static gboolean redraw_anim(gpointer data)
|
|
1600 {
|
|
1601 int delay;
|
|
1602 struct icon_req *ir = data;
|
|
1603 GList *frames;
|
|
1604 GdkPixbufFrame *frame;
|
|
1605 GdkPixbuf *buf;
|
|
1606 GdkPixmap *pm; GdkBitmap *bm;
|
|
1607 GdkPixmap *src;
|
|
1608 GdkGC *gc;
|
|
1609
|
|
1610 if (!ir->cnv || !g_list_find(conversations, ir->cnv)) {
|
|
1611 debug_printf("I think this is a bug.\n");
|
|
1612 return FALSE;
|
|
1613 }
|
|
1614
|
|
1615 frames = gdk_pixbuf_animation_get_frames(ir->anim);
|
|
1616 frame = g_list_nth_data(frames, ir->curframe);
|
|
1617 buf = gdk_pixbuf_frame_get_pixbuf(frame);
|
|
1618 switch (gdk_pixbuf_frame_get_action(frame)) {
|
|
1619 case GDK_PIXBUF_FRAME_RETAIN:
|
|
1620 gdk_pixbuf_render_pixmap_and_mask(buf, &src, NULL, 0);
|
|
1621 gtk_pixmap_get(GTK_PIXMAP(ir->pix), &pm, &bm);
|
|
1622 gc = gdk_gc_new(pm);
|
|
1623 gdk_draw_pixmap(pm, gc, src, 0, 0,
|
|
1624 gdk_pixbuf_frame_get_x_offset(frame),
|
|
1625 gdk_pixbuf_frame_get_y_offset(frame),
|
|
1626 -1, -1);
|
|
1627 gdk_pixmap_unref(src);
|
|
1628 gtk_widget_queue_draw(ir->pix);
|
|
1629 gdk_gc_unref(gc);
|
|
1630 break;
|
|
1631 case GDK_PIXBUF_FRAME_DISPOSE:
|
|
1632 gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0);
|
|
1633 gtk_pixmap_set(GTK_PIXMAP(ir->pix), pm, bm);
|
|
1634 gdk_pixmap_unref(pm);
|
|
1635 if (bm)
|
|
1636 gdk_bitmap_unref(bm);
|
|
1637 break;
|
|
1638 case GDK_PIXBUF_FRAME_REVERT:
|
|
1639 frame = frames->data;
|
|
1640 buf = gdk_pixbuf_frame_get_pixbuf(frame);
|
|
1641 gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0);
|
|
1642 gtk_pixmap_set(GTK_PIXMAP(ir->pix), pm, bm);
|
|
1643 gdk_pixmap_unref(pm);
|
|
1644 if (bm)
|
|
1645 gdk_bitmap_unref(bm);
|
|
1646 break;
|
|
1647 }
|
|
1648 ir->curframe = (ir->curframe + 1) % g_list_length(frames);
|
|
1649 delay = MAX(gdk_pixbuf_frame_get_delay_time(frame), 13);
|
|
1650 ir->timer = gtk_timeout_add(delay * 10, redraw_anim, ir);
|
|
1651 return FALSE;
|
|
1652 }
|
|
1653 #endif
|
|
1654
|
|
1655 int gaim_parse_incoming_im(struct aim_session_t *sess,
|
|
1656 struct command_rx_struct *command, ...) {
|
|
1657 int channel;
|
|
1658 struct aim_userinfo_s *userinfo;
|
|
1659 va_list ap;
|
|
1660 struct gaim_connection *gc = sess->aux_data;
|
|
1661
|
|
1662 va_start(ap, command);
|
|
1663 channel = va_arg(ap, int);
|
|
1664 userinfo = va_arg(ap, struct aim_userinfo_s *);
|
|
1665
|
|
1666 /* channel 1: standard message */
|
|
1667 if (channel == 1) {
|
|
1668 char *tmp = g_malloc(BUF_LONG);
|
|
1669 struct aim_incomingim_ch1_args *args;
|
|
1670
|
|
1671 args = va_arg(ap, struct aim_incomingim_ch1_args *);
|
|
1672 va_end(ap);
|
|
1673
|
|
1674 #if USE_PIXBUF
|
|
1675 if (args->icbmflags & AIM_IMFLAGS_HASICON) {
|
|
1676 struct oscar_data *od = gc->proto_data;
|
|
1677 struct icon_req *ir;
|
|
1678 GSList *h = od->hasicons;
|
|
1679 char *who = normalize(userinfo->sn);
|
|
1680 debug_printf("%s has an icon\n", userinfo->sn);
|
|
1681 while (h) {
|
|
1682 ir = h->data;
|
|
1683 if (!strcmp(ir->user, who))
|
|
1684 break;
|
|
1685 h = h->next;
|
|
1686 }
|
|
1687 if (!h) {
|
|
1688 ir = g_new0(struct icon_req, 1);
|
|
1689 ir->user = g_strdup(who);
|
|
1690 od->hasicons = g_slist_append(od->hasicons, ir);
|
|
1691 }
|
|
1692 if (args->iconstamp > ir->timestamp)
|
|
1693 ir->request = TRUE;
|
|
1694 ir->timestamp = args->iconstamp;
|
|
1695 }
|
|
1696 #endif
|
|
1697
|
|
1698 /*
|
|
1699 * Quickly convert it to eight bit format, replacing
|
|
1700 * non-ASCII UNICODE characters with their equivelent
|
|
1701 * HTML entity.
|
|
1702 */
|
|
1703 if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
|
|
1704 int i;
|
|
1705
|
|
1706 for (i = 0, tmp[0] = '\0'; i < args->msglen; i += 2) {
|
|
1707 unsigned short uni;
|
|
1708
|
|
1709 uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
|
|
1710
|
|
1711 if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
|
|
1712
|
|
1713 g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "%c", uni);
|
|
1714
|
|
1715 } else { /* something else, do UNICODE entity */
|
|
1716 g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "&#%04x;", uni);
|
|
1717 }
|
|
1718 }
|
|
1719 } else
|
|
1720 g_snprintf(tmp, BUF_LONG, "%s", args->msg);
|
|
1721
|
|
1722 serv_got_im(gc, userinfo->sn, tmp, args->icbmflags & AIM_IMFLAGS_AWAY, time(NULL));
|
|
1723 g_free(tmp);
|
|
1724 } else if (channel == 2) {
|
|
1725 struct aim_incomingim_ch2_args *args;
|
|
1726 args = va_arg(ap, struct aim_incomingim_ch2_args *);
|
|
1727 va_end(ap);
|
|
1728 if (args->reqclass & AIM_CAPS_CHAT) {
|
|
1729 char *name = extract_name(args->info.chat.roominfo.name);
|
|
1730 serv_got_chat_invite(gc,
|
|
1731 name ? name : args->info.chat.roominfo.name,
|
|
1732 args->info.chat.roominfo.exchange,
|
|
1733 userinfo->sn,
|
|
1734 args->info.chat.msg);
|
|
1735 if (name)
|
|
1736 g_free(name);
|
|
1737 } else if (args->reqclass & AIM_CAPS_SENDFILE) {
|
|
1738 } else if (args->reqclass & AIM_CAPS_GETFILE) {
|
|
1739 /*
|
|
1740 char *ip, *cookie;
|
|
1741 struct ask_getfile *g = g_new0(struct ask_getfile, 1);
|
|
1742 char buf[256];
|
|
1743
|
|
1744 userinfo = va_arg(ap, struct aim_userinfo_s *);
|
|
1745 ip = va_arg(ap, char *);
|
|
1746 cookie = va_arg(ap, char *);
|
|
1747 va_end(ap);
|
|
1748
|
|
1749 debug_printf("%s received getfile request from %s (%s), cookie = %s\n",
|
|
1750 gc->username, userinfo->sn, ip, cookie);
|
|
1751
|
|
1752 g->gc = gc;
|
|
1753 g->sn = g_strdup(userinfo->sn);
|
|
1754 g->cookie = g_strdup(cookie);
|
|
1755 g->ip = g_strdup(ip);
|
|
1756 g_snprintf(buf, sizeof buf, "%s has just asked to get a file from %s.",
|
|
1757 userinfo->sn, gc->username);
|
|
1758 do_ask_dialog(buf, g, accept_getfile, cancel_getfile);
|
|
1759 */
|
|
1760 } else if (args->reqclass & AIM_CAPS_VOICE) {
|
|
1761 } else if (args->reqclass & AIM_CAPS_BUDDYICON) {
|
|
1762 #if USE_PIXBUF
|
|
1763 struct oscar_data *od = gc->proto_data;
|
|
1764 GSList *h = od->hasicons;
|
|
1765 struct icon_req *ir = NULL;
|
|
1766 char *who;
|
|
1767 struct conversation *c;
|
|
1768
|
|
1769 GdkPixbufLoader *load;
|
|
1770 GList *frames;
|
|
1771 GdkPixbuf *buf;
|
|
1772 GdkPixmap *pm;
|
|
1773 GdkBitmap *bm;
|
|
1774
|
|
1775 who = normalize(userinfo->sn);
|
|
1776
|
|
1777 while (h) {
|
|
1778 ir = h->data;
|
|
1779 if (!strcmp(who, ir->user))
|
|
1780 break;
|
|
1781 h = h->next;
|
|
1782
|
|
1783 }
|
|
1784
|
|
1785 if (!h || ((c = find_conversation(userinfo->sn)) == NULL) || (c->gc != gc)) {
|
|
1786 debug_printf("got buddy icon for %s but didn't want it\n", userinfo->sn);
|
|
1787 return 1;
|
|
1788 }
|
|
1789
|
|
1790 if (ir->pix && ir->cnv)
|
|
1791 gtk_container_remove(GTK_CONTAINER(ir->cnv->bbox), ir->pix);
|
|
1792 ir->pix = NULL;
|
|
1793 ir->cnv = NULL;
|
|
1794 if (ir->data)
|
|
1795 g_free(ir->data);
|
|
1796 if (ir->anim)
|
|
1797 gdk_pixbuf_animation_unref(ir->anim);
|
|
1798 ir->anim = NULL;
|
|
1799 if (ir->unanim)
|
|
1800 gdk_pixbuf_unref(ir->unanim);
|
|
1801 ir->unanim = NULL;
|
|
1802 if (ir->timer)
|
|
1803 gtk_timeout_remove(ir->timer);
|
|
1804 ir->timer = 0;
|
|
1805
|
|
1806 ir->length = args->info.icon.length;
|
|
1807
|
|
1808 if (!ir->length)
|
|
1809 return 1;
|
|
1810
|
|
1811 ir->data = g_memdup(args->info.icon.icon, args->info.icon.length);
|
|
1812
|
|
1813 load = gdk_pixbuf_loader_new();
|
|
1814 gdk_pixbuf_loader_write(load, ir->data, ir->length);
|
|
1815 ir->anim = gdk_pixbuf_loader_get_animation(load);
|
|
1816
|
|
1817 if (ir->anim) {
|
|
1818 frames = gdk_pixbuf_animation_get_frames(ir->anim);
|
|
1819 buf = gdk_pixbuf_frame_get_pixbuf(frames->data);
|
|
1820 gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0);
|
|
1821
|
|
1822 if (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1) {
|
|
1823 int delay =
|
|
1824 MAX(gdk_pixbuf_frame_get_delay_time(frames->data), 13);
|
|
1825 ir->curframe = 1;
|
|
1826 ir->timer = gtk_timeout_add(delay * 10, redraw_anim, ir);
|
|
1827 }
|
|
1828 } else {
|
|
1829 ir->unanim = gdk_pixbuf_loader_get_pixbuf(load);
|
|
1830 if (!ir->unanim) {
|
|
1831 gdk_pixbuf_loader_close(load);
|
|
1832 return 1;
|
|
1833 }
|
|
1834 gdk_pixbuf_render_pixmap_and_mask(ir->unanim, &pm, &bm, 0);
|
|
1835 }
|
|
1836
|
|
1837 ir->cnv = c;
|
|
1838 ir->pix = gtk_pixmap_new(pm, bm);
|
|
1839 gtk_box_pack_start(GTK_BOX(c->bbox), ir->pix, FALSE, FALSE, 5);
|
|
1840 if (ir->anim && (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1))
|
|
1841 gtk_widget_set_usize(ir->pix, gdk_pixbuf_animation_get_width(ir->anim),
|
|
1842 gdk_pixbuf_animation_get_height(ir->anim));
|
|
1843 gtk_widget_show(ir->pix);
|
|
1844 gdk_pixmap_unref(pm);
|
|
1845 if (bm)
|
|
1846 gdk_bitmap_unref(bm);
|
|
1847
|
|
1848 gdk_pixbuf_loader_close(load);
|
|
1849
|
|
1850 #endif
|
|
1851 } else if (args->reqclass & AIM_CAPS_IMIMAGE) {
|
|
1852 struct ask_direct *d = g_new0(struct ask_direct, 1);
|
|
1853 char buf[256];
|
|
1854
|
|
1855 debug_printf("%s received direct im request from %s (%s)\n",
|
|
1856 gc->username, userinfo->sn, args->info.directim->ip);
|
|
1857
|
|
1858 d->gc = gc;
|
|
1859 d->sn = g_strdup(userinfo->sn);
|
|
1860 d->priv = args->info.directim;
|
|
1861 g_snprintf(buf, sizeof buf, "%s has just asked to directly connect to %s.",
|
|
1862 userinfo->sn, gc->username);
|
|
1863 do_ask_dialog(buf, d, accept_direct_im, cancel_direct_im);
|
|
1864 } else {
|
|
1865 debug_printf("Unknown reqclass %d\n", args->reqclass);
|
|
1866 }
|
|
1867 }
|
|
1868
|
|
1869 return 1;
|
|
1870 }
|
|
1871
|
|
1872 int gaim_parse_misses(struct aim_session_t *sess,
|
|
1873 struct command_rx_struct *command, ...) {
|
|
1874 va_list ap;
|
|
1875 unsigned short chan, nummissed, reason;
|
|
1876 struct aim_userinfo_s *userinfo;
|
|
1877 char buf[1024];
|
|
1878
|
|
1879 va_start(ap, command);
|
|
1880 chan = (unsigned short)va_arg(ap, unsigned int);
|
|
1881 userinfo = va_arg(ap, struct aim_userinfo_s *);
|
|
1882 nummissed = (unsigned short)va_arg(ap, unsigned int);
|
|
1883 reason = (unsigned short)va_arg(ap, unsigned int);
|
|
1884 va_end(ap);
|
|
1885
|
|
1886 switch(reason) {
|
|
1887 case 1:
|
|
1888 /* message too large */
|
|
1889 sprintf(buf, _("You missed a message from %s because it was too large."), userinfo->sn);
|
|
1890 do_error_dialog(buf, _("Gaim - Error"));
|
|
1891 plugin_event(event_error, (void *)961, 0, 0, 0);
|
|
1892 break;
|
|
1893 default:
|
|
1894 sprintf(buf, _("You missed a message from %s for unknown reasons."), userinfo->sn);
|
|
1895 do_error_dialog(buf, _("Gaim - Error"));
|
|
1896 plugin_event(event_error, (void *)970, 0, 0, 0);
|
|
1897 break;
|
|
1898 }
|
|
1899
|
|
1900 return 1;
|
|
1901 }
|
|
1902
|
|
1903 int gaim_parse_genericerr(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
1904 va_list ap;
|
|
1905 unsigned short reason;
|
|
1906
|
|
1907 va_start(ap, command);
|
|
1908 reason = va_arg(ap, int);
|
|
1909 va_end(ap);
|
|
1910
|
|
1911 debug_printf("snac threw error (reason 0x%04x: %s\n", reason,
|
|
1912 (reason < msgerrreasonlen) ? msgerrreason[reason] : "unknown");
|
|
1913
|
|
1914 return 1;
|
|
1915 }
|
|
1916
|
|
1917 int gaim_parse_msgerr(struct aim_session_t *sess,
|
|
1918 struct command_rx_struct *command, ...) {
|
|
1919 va_list ap;
|
|
1920 char *destn;
|
|
1921 unsigned short reason;
|
|
1922 char buf[1024];
|
|
1923
|
|
1924 va_start(ap, command);
|
|
1925 reason = (unsigned short)va_arg(ap, unsigned int);
|
|
1926 destn = va_arg(ap, char *);
|
|
1927 va_end(ap);
|
|
1928
|
|
1929 sprintf(buf, _("Your message to %s did not get sent: %s"), destn,
|
|
1930 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown"));
|
|
1931 do_error_dialog(buf, _("Gaim - Error"));
|
|
1932
|
|
1933 return 1;
|
|
1934 }
|
|
1935
|
|
1936 int gaim_parse_locerr(struct aim_session_t *sess,
|
|
1937 struct command_rx_struct *command, ...) {
|
|
1938 va_list ap;
|
|
1939 char *destn;
|
|
1940 unsigned short reason;
|
|
1941 char buf[1024];
|
|
1942
|
|
1943 va_start(ap, command);
|
|
1944 reason = (unsigned short)va_arg(ap, unsigned int);
|
|
1945 destn = va_arg(ap, char *);
|
|
1946 va_end(ap);
|
|
1947
|
|
1948 sprintf(buf, _("User information for %s unavailable: %s"), destn,
|
|
1949 (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown"));
|
|
1950 do_error_dialog(buf, _("Gaim - Error"));
|
|
1951
|
|
1952 return 1;
|
|
1953 }
|
|
1954
|
|
1955 static char *images(int flags) {
|
|
1956 static char buf[1024];
|
|
1957 g_snprintf(buf, sizeof(buf), "%s%s%s%s",
|
|
1958 (flags & AIM_FLAG_UNCONFIRMED) ? "<IMG SRC=\"dt_icon.gif\">" : "",
|
|
1959 (flags & AIM_FLAG_AOL) ? "<IMG SRC=\"aol_icon.gif\">" : "",
|
|
1960 (flags & AIM_FLAG_ADMINISTRATOR) ? "<IMG SRC=\"admin_icon.gif\">" : "",
|
|
1961 (flags & AIM_FLAG_FREE) ? "<IMG SRC=\"free_icon.gif\">" : "");
|
|
1962 return buf;
|
|
1963 }
|
|
1964
|
|
1965 int gaim_parse_user_info(struct aim_session_t *sess,
|
|
1966 struct command_rx_struct *command, ...) {
|
|
1967 struct aim_userinfo_s *info;
|
|
1968 char *prof_enc = NULL, *prof = NULL;
|
|
1969 unsigned short infotype;
|
|
1970 char buf[BUF_LONG];
|
|
1971 struct gaim_connection *gc = sess->aux_data;
|
|
1972 va_list ap;
|
|
1973 char *asc;
|
|
1974
|
|
1975 va_start(ap, command);
|
|
1976 info = va_arg(ap, struct aim_userinfo_s *);
|
|
1977 prof_enc = va_arg(ap, char *);
|
|
1978 prof = va_arg(ap, char *);
|
|
1979 infotype = (unsigned short)va_arg(ap, unsigned int);
|
|
1980 va_end(ap);
|
|
1981
|
|
1982 if (info->membersince)
|
|
1983 asc = g_strdup_printf("Member Since : <B>%s</B><BR>\n",
|
|
1984 asctime(localtime(&info->membersince)));
|
|
1985 else
|
|
1986 asc = g_strdup("");
|
|
1987
|
|
1988 g_snprintf(buf, sizeof buf,
|
|
1989 _("Username : <B>%s</B> %s <BR>\n"
|
|
1990 "%s"
|
|
1991 "Warning Level : <B>%d %%</B><BR>\n"
|
|
1992 "Online Since : <B>%s</B><BR>\n"
|
|
1993 "Idle Minutes : <B>%d</B>\n<BR>\n<HR><BR>\n"
|
|
1994 "%s"
|
|
1995 "<br><BODY BGCOLOR=WHITE><hr><I>Legend:</I><br><br>"
|
|
1996 "<IMG SRC=\"free_icon.gif\"> : Normal AIM User<br>"
|
|
1997 "<IMG SRC=\"aol_icon.gif\"> : AOL User <br>"
|
|
1998 "<IMG SRC=\"dt_icon.gif\"> : Trial AIM User <br>"
|
|
1999 "<IMG SRC=\"admin_icon.gif\"> : Administrator"),
|
|
2000 info->sn, images(info->flags),
|
|
2001 asc,
|
|
2002 info->warnlevel/10,
|
|
2003 asctime(localtime(&info->onlinesince)),
|
|
2004 info->idletime,
|
|
2005 (prof && strlen(prof)) ?
|
|
2006 (infotype == AIM_GETINFO_GENERALINFO ?
|
|
2007 prof :
|
|
2008 away_subs(prof, gc->username))
|
|
2009 :
|
|
2010 (infotype == AIM_GETINFO_GENERALINFO ?
|
|
2011 _("<i>No Information Provided</i>") :
|
|
2012 _("<i>User has no away message</i>")));
|
|
2013
|
|
2014 g_show_info_text(away_subs(buf, gc->username));
|
|
2015
|
|
2016 g_free(asc);
|
|
2017
|
|
2018 return 1;
|
|
2019 }
|
|
2020
|
|
2021 int gaim_parse_motd(struct aim_session_t *sess,
|
|
2022 struct command_rx_struct *command, ...) {
|
|
2023 char *msg;
|
|
2024 unsigned short id;
|
|
2025 va_list ap;
|
|
2026 char buildbuf[150];
|
|
2027
|
|
2028 va_start(ap, command);
|
|
2029 id = (unsigned short)va_arg(ap, unsigned int);
|
|
2030 msg = va_arg(ap, char *);
|
|
2031 va_end(ap);
|
|
2032
|
|
2033 aim_getbuildstring(buildbuf, sizeof(buildbuf));
|
|
2034
|
|
2035 debug_printf("MOTD: %s (%d)\n", msg ? msg : "Unknown", id);
|
|
2036 debug_printf("Gaim %s / Libfaim %s\n", VERSION, buildbuf);
|
|
2037 if (id != 4)
|
|
2038 do_error_dialog(_("Your connection may be lost."),
|
|
2039 _("AOL error"));
|
|
2040
|
|
2041 return 1;
|
|
2042 }
|
|
2043
|
|
2044 int gaim_chatnav_info(struct aim_session_t *sess,
|
|
2045 struct command_rx_struct *command, ...) {
|
|
2046 va_list ap;
|
|
2047 unsigned short type;
|
|
2048 struct gaim_connection *gc = sess->aux_data;
|
|
2049 struct oscar_data *odata = (struct oscar_data *)gc->proto_data;
|
|
2050
|
|
2051 va_start(ap, command);
|
|
2052 type = (unsigned short)va_arg(ap, unsigned int);
|
|
2053
|
|
2054 switch(type) {
|
|
2055 case 0x0002: {
|
|
2056 int maxrooms;
|
|
2057 struct aim_chat_exchangeinfo *exchanges;
|
|
2058 int exchangecount, i = 0;
|
|
2059
|
|
2060 maxrooms = (unsigned char)va_arg(ap, unsigned int);
|
|
2061 exchangecount = va_arg(ap, int);
|
|
2062 exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
|
|
2063 va_end(ap);
|
|
2064
|
|
2065 debug_printf("chat info: Chat Rights:\n");
|
|
2066 debug_printf("chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
|
|
2067 debug_printf("chat info: \tExchange List: (%d total)\n", exchangecount);
|
|
2068 while (i < exchangecount)
|
|
2069 debug_printf("chat info: \t\t%d\n", exchanges[i++].number);
|
|
2070 if (odata->create_exchange) {
|
|
2071 debug_printf("creating room %s\n", odata->create_name);
|
|
2072 aim_chatnav_createroom(sess, command->conn, odata->create_name,
|
|
2073 odata->create_exchange);
|
|
2074 odata->create_exchange = 0;
|
|
2075 g_free(odata->create_name);
|
|
2076 odata->create_name = NULL;
|
|
2077 }
|
|
2078 }
|
|
2079 break;
|
|
2080 case 0x0008: {
|
|
2081 char *fqcn, *name, *ck;
|
|
2082 unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
|
|
2083 unsigned char createperms;
|
|
2084 unsigned long createtime;
|
|
2085
|
|
2086 fqcn = va_arg(ap, char *);
|
|
2087 instance = (unsigned short)va_arg(ap, unsigned int);
|
|
2088 exchange = (unsigned short)va_arg(ap, unsigned int);
|
|
2089 flags = (unsigned short)va_arg(ap, unsigned int);
|
|
2090 createtime = va_arg(ap, unsigned long);
|
|
2091 maxmsglen = (unsigned short)va_arg(ap, unsigned int);
|
|
2092 maxoccupancy = (unsigned short)va_arg(ap, unsigned int);
|
|
2093 createperms = (unsigned char)va_arg(ap, int);
|
|
2094 unknown = (unsigned short)va_arg(ap, unsigned int);
|
|
2095 name = va_arg(ap, char *);
|
|
2096 ck = va_arg(ap, char *);
|
|
2097 va_end(ap);
|
|
2098
|
|
2099 debug_printf("created room: %s %d %d %d %lu %d %d %d %d %s %s\n",
|
|
2100 fqcn,
|
|
2101 exchange, instance, flags,
|
|
2102 createtime,
|
|
2103 maxmsglen, maxoccupancy, createperms, unknown,
|
|
2104 name, ck);
|
|
2105 aim_chat_join(odata->sess, odata->conn, exchange, ck);
|
|
2106 }
|
|
2107 break;
|
|
2108 default:
|
|
2109 va_end(ap);
|
|
2110 debug_printf("chatnav info: unknown type (%04x)\n", type);
|
|
2111 break;
|
|
2112 }
|
|
2113 return 1;
|
|
2114 }
|
|
2115
|
|
2116 int gaim_chat_join(struct aim_session_t *sess,
|
|
2117 struct command_rx_struct *command, ...) {
|
|
2118 va_list ap;
|
|
2119 int count, i = 0;
|
|
2120 struct aim_userinfo_s *info;
|
|
2121 struct gaim_connection *g = sess->aux_data;
|
|
2122
|
|
2123 struct chat_connection *c = NULL;
|
|
2124
|
|
2125 va_start(ap, command);
|
|
2126 count = va_arg(ap, int);
|
|
2127 info = va_arg(ap, struct aim_userinfo_s *);
|
|
2128 va_end(ap);
|
|
2129
|
|
2130 c = find_oscar_chat_by_conn(g, command->conn);
|
|
2131 if (!c)
|
|
2132 return 1;
|
|
2133
|
|
2134 while (i < count)
|
|
2135 add_chat_buddy(c->cnv, info[i++].sn);
|
|
2136
|
|
2137 return 1;
|
|
2138 }
|
|
2139
|
|
2140 int gaim_chat_leave(struct aim_session_t *sess,
|
|
2141 struct command_rx_struct *command, ...) {
|
|
2142 va_list ap;
|
|
2143 int count, i = 0;
|
|
2144 struct aim_userinfo_s *info;
|
|
2145 struct gaim_connection *g = sess->aux_data;
|
|
2146
|
|
2147 struct chat_connection *c = NULL;
|
|
2148
|
|
2149 va_start(ap, command);
|
|
2150 count = va_arg(ap, int);
|
|
2151 info = va_arg(ap, struct aim_userinfo_s *);
|
|
2152 va_end(ap);
|
|
2153
|
|
2154 c = find_oscar_chat_by_conn(g, command->conn);
|
|
2155 if (!c)
|
|
2156 return 1;
|
|
2157
|
|
2158 while (i < count)
|
|
2159 remove_chat_buddy(c->cnv, info[i++].sn);
|
|
2160
|
|
2161 return 1;
|
|
2162 }
|
|
2163
|
|
2164 int gaim_chat_info_update(struct aim_session_t *sess,
|
|
2165 struct command_rx_struct *command, ...) {
|
|
2166 debug_printf("inside chat_info_update\n");
|
|
2167 return 1;
|
|
2168 }
|
|
2169
|
|
2170 int gaim_chat_incoming_msg(struct aim_session_t *sess,
|
|
2171 struct command_rx_struct *command, ...) {
|
|
2172 va_list ap;
|
|
2173 struct aim_userinfo_s *info;
|
|
2174 char *msg;
|
|
2175 struct gaim_connection *gc = sess->aux_data;
|
|
2176 struct chat_connection *ccon = find_oscar_chat_by_conn(gc, command->conn);
|
|
2177 char *tmp;
|
|
2178
|
|
2179 va_start(ap, command);
|
|
2180 info = va_arg(ap, struct aim_userinfo_s *);
|
|
2181 msg = va_arg(ap, char *);
|
|
2182
|
|
2183 tmp = g_malloc(BUF_LONG);
|
|
2184 g_snprintf(tmp, BUF_LONG, "%s", msg);
|
|
2185 serv_got_chat_in(gc, ccon->id, info->sn, 0, tmp, time((time_t)NULL));
|
|
2186 g_free(tmp);
|
|
2187
|
|
2188 return 1;
|
|
2189 }
|
|
2190
|
|
2191 /*
|
|
2192 * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
|
|
2193 */
|
|
2194 int gaim_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2195 va_list ap;
|
|
2196 unsigned short type;
|
|
2197 char *sn = NULL;
|
|
2198
|
|
2199 va_start(ap, command);
|
|
2200 type = (unsigned short)va_arg(ap, unsigned int);
|
|
2201 sn = va_arg(ap, char *);
|
|
2202 va_end(ap);
|
|
2203
|
|
2204 debug_printf("Sent message to %s.\n", sn);
|
|
2205
|
|
2206 return 1;
|
|
2207 }
|
|
2208
|
|
2209 int gaim_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2210 static char *codes[5] = {"invalid",
|
|
2211 "change",
|
|
2212 "warning",
|
|
2213 "limit",
|
|
2214 "limit cleared"};
|
|
2215 va_list ap;
|
|
2216 int code;
|
|
2217 unsigned long rateclass, windowsize, clear, alert, limit, disconnect;
|
|
2218 unsigned long currentavg, maxavg;
|
|
2219
|
|
2220 va_start(ap, command);
|
|
2221 code = va_arg(ap, int);
|
|
2222 rateclass= va_arg(ap, int);
|
|
2223 windowsize = va_arg(ap, unsigned long);
|
|
2224 clear = va_arg(ap, unsigned long);
|
|
2225 alert = va_arg(ap, unsigned long);
|
|
2226 limit = va_arg(ap, unsigned long);
|
|
2227 disconnect = va_arg(ap, unsigned long);
|
|
2228 currentavg = va_arg(ap, unsigned long);
|
|
2229 maxavg = va_arg(ap, unsigned long);
|
|
2230 va_end(ap);
|
|
2231
|
|
2232 debug_printf("rate %s (paramid 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, "
|
|
2233 "clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
|
|
2234 (code < 5) ? codes[code] : codes[0],
|
|
2235 rateclass,
|
|
2236 currentavg, maxavg,
|
|
2237 alert, clear,
|
|
2238 limit, disconnect,
|
|
2239 windowsize);
|
|
2240
|
|
2241 if (code == AIM_RATE_CODE_CHANGE) {
|
|
2242 if (currentavg >= clear)
|
|
2243 aim_conn_setlatency(command->conn, 0);
|
|
2244 } else if (code == AIM_RATE_CODE_WARNING) {
|
|
2245 aim_conn_setlatency(command->conn, windowsize/4);
|
|
2246 } else if (code == AIM_RATE_CODE_LIMIT) {
|
|
2247 aim_conn_setlatency(command->conn, windowsize/2);
|
|
2248 } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
|
|
2249 aim_conn_setlatency(command->conn, 0);
|
|
2250 }
|
|
2251
|
|
2252 return 1;
|
|
2253 }
|
|
2254
|
|
2255 int gaim_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2256 va_list ap;
|
|
2257 int newevil;
|
|
2258 struct aim_userinfo_s *userinfo;
|
|
2259 struct gaim_connection *gc = sess->aux_data;
|
|
2260
|
|
2261 va_start(ap, command);
|
|
2262 newevil = va_arg(ap, int);
|
|
2263 userinfo = va_arg(ap, struct aim_userinfo_s *);
|
|
2264 va_end(ap);
|
|
2265
|
|
2266 serv_got_eviled(gc, (userinfo && userinfo->sn[0]) ? userinfo->sn : NULL, newevil / 10);
|
|
2267
|
|
2268 return 1;
|
|
2269 }
|
|
2270
|
|
2271 int gaim_rateresp(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2272 struct gaim_connection *gc = sess->aux_data;
|
|
2273 switch (command->conn->type) {
|
|
2274 case AIM_CONN_TYPE_BOS:
|
|
2275 aim_bos_ackrateresp(sess, command->conn);
|
|
2276 aim_bos_reqpersonalinfo(sess, command->conn);
|
|
2277 aim_bos_reqlocaterights(sess, command->conn);
|
|
2278 aim_bos_setprofile(sess, command->conn, gc->user->user_info, NULL, gaim_caps);
|
|
2279 aim_bos_reqbuddyrights(sess, command->conn);
|
|
2280
|
|
2281 account_online(gc);
|
|
2282 serv_finish_login(gc);
|
|
2283
|
|
2284 if (bud_list_cache_exists(gc))
|
|
2285 do_import(NULL, gc);
|
|
2286
|
|
2287 debug_printf("buddy list loaded\n");
|
|
2288
|
|
2289 aim_addicbmparam(sess, command->conn);
|
|
2290 aim_bos_reqicbmparaminfo(sess, command->conn);
|
|
2291
|
|
2292 aim_bos_reqrights(sess, command->conn);
|
|
2293 aim_bos_setgroupperm(sess, command->conn, AIM_FLAG_ALLUSERS);
|
|
2294 aim_bos_setprivacyflags(sess, command->conn, AIM_PRIVFLAGS_ALLOWIDLE |
|
|
2295 AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
|
|
2296
|
|
2297 break;
|
|
2298 case AIM_CONN_TYPE_AUTH:
|
|
2299 aim_bos_ackrateresp(sess, command->conn);
|
|
2300 aim_auth_clientready(sess, command->conn);
|
|
2301 debug_printf("connected to auth (admin)\n");
|
|
2302 break;
|
|
2303 default:
|
|
2304 debug_printf("got rate response for unhandled connection type %04x\n",
|
|
2305 command->conn->type);
|
|
2306 break;
|
|
2307 }
|
|
2308
|
|
2309 return 1;
|
|
2310 }
|
|
2311
|
|
2312 int gaim_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2313 if (command->data) {
|
|
2314 debug_printf("minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10));
|
|
2315 } else
|
|
2316 debug_printf("NULL minimum report interval!\n");
|
|
2317 return 1;
|
|
2318 }
|
|
2319
|
|
2320 int gaim_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2321 va_list ap;
|
|
2322 unsigned short maxbuddies, maxwatchers;
|
|
2323
|
|
2324 va_start(ap, command);
|
|
2325 maxbuddies = (unsigned short)va_arg(ap, unsigned int);
|
|
2326 maxwatchers = (unsigned short)va_arg(ap, unsigned int);
|
|
2327 va_end(ap);
|
|
2328
|
|
2329 debug_printf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
|
|
2330
|
|
2331 return 1;
|
|
2332 }
|
|
2333
|
|
2334 int gaim_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2335 unsigned short maxpermits, maxdenies;
|
|
2336 va_list ap;
|
|
2337
|
|
2338 va_start(ap, command);
|
|
2339 maxpermits = (unsigned short)va_arg(ap, unsigned int);
|
|
2340 maxdenies = (unsigned short)va_arg(ap, unsigned int);
|
|
2341 va_end(ap);
|
|
2342
|
|
2343 debug_printf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
|
|
2344
|
|
2345 aim_bos_clientready(sess, command->conn);
|
|
2346
|
|
2347 aim_bos_reqservice(sess, command->conn, AIM_CONN_TYPE_CHATNAV);
|
|
2348
|
|
2349 return 1;
|
|
2350 }
|
|
2351
|
|
2352 int gaim_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2353 va_list ap;
|
|
2354 char *address, *SNs;
|
|
2355 int i, num;
|
|
2356 char *buf;
|
|
2357 int at = 0, len;
|
|
2358
|
|
2359 va_start(ap, command);
|
|
2360 address = va_arg(ap, char *);
|
|
2361 num = va_arg(ap, int);
|
|
2362 SNs = va_arg(ap, char *);
|
|
2363 va_end(ap);
|
|
2364
|
|
2365 len = num * (MAXSNLEN + 1) + 1024;
|
|
2366 buf = g_malloc(len);
|
|
2367 at += g_snprintf(buf + at, len - at, "<B>%s has the following screen names:</B><BR>", address);
|
|
2368 for (i = 0; i < num; i++)
|
|
2369 at += g_snprintf(buf + at, len - at, "%s<BR>", &SNs[i * (MAXSNLEN + 1)]);
|
|
2370 g_show_info_text(buf);
|
|
2371 g_free(buf);
|
|
2372
|
|
2373 return 1;
|
|
2374 }
|
|
2375
|
|
2376 int gaim_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2377 va_list ap;
|
|
2378 char *address;
|
|
2379 char buf[BUF_LONG];
|
|
2380
|
|
2381 va_start(ap, command);
|
|
2382 address = va_arg(ap, char *);
|
|
2383 va_end(ap);
|
|
2384
|
|
2385 g_snprintf(buf, sizeof(buf), "No results found for email address %s", address);
|
|
2386 do_error_dialog(buf, _("Error"));
|
|
2387
|
|
2388 return 1;
|
|
2389 }
|
|
2390
|
|
2391 int gaim_account_confirm(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2392 int status;
|
|
2393 va_list ap;
|
|
2394 char msg[256];
|
|
2395 struct gaim_connection *gc = sess->aux_data;
|
|
2396
|
|
2397 va_start(ap, command);
|
|
2398 status = va_arg(ap, int); /* status code of confirmation request */
|
|
2399 va_end(ap);
|
|
2400
|
|
2401 debug_printf("account confirmation returned status 0x%04x (%s)\n", status,
|
|
2402 status ? "email sent" : "unknown");
|
|
2403 if (status) {
|
|
2404 g_snprintf(msg, sizeof(msg), "You should receive an email asking to confirm %s.",
|
|
2405 gc->username);
|
|
2406 do_error_dialog(msg, "Confirm");
|
|
2407 }
|
|
2408
|
|
2409 return 1;
|
|
2410 }
|
|
2411
|
|
2412 int gaim_info_change(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2413 unsigned short change = 0;
|
|
2414 int perms, type, length, str;
|
|
2415 char *val;
|
|
2416 va_list ap;
|
|
2417 char buf[BUF_LONG];
|
|
2418 struct gaim_connection *gc = sess->aux_data;
|
|
2419
|
|
2420 va_start(ap, command);
|
|
2421 perms = va_arg(ap, int);
|
|
2422 type = va_arg(ap, int);
|
|
2423 length = va_arg(ap, int);
|
|
2424 val = va_arg(ap, char *);
|
|
2425 str = va_arg(ap, int);
|
|
2426 va_end(ap);
|
|
2427
|
|
2428 if (aimutil_get16(command->data+2) == 0x0005)
|
|
2429 change = 1;
|
|
2430
|
|
2431 debug_printf("info%s: perms = %d, type = %x, length = %d, val = %s\n",
|
|
2432 change ? " change" : "", perms, type, length, str ? val : "(not string)");
|
|
2433
|
|
2434 if ((type == 0x0011) && str) {
|
|
2435 g_snprintf(buf, sizeof(buf), "The email address for %s is %s", gc->username, val);
|
|
2436 do_error_dialog(buf, "Email");
|
|
2437 }
|
|
2438
|
|
2439 return 1;
|
|
2440 }
|
|
2441
|
|
2442 static void oscar_keepalive(struct gaim_connection *gc) {
|
|
2443 struct oscar_data *odata = (struct oscar_data *)gc->proto_data;
|
|
2444 aim_flap_nop(odata->sess, odata->conn);
|
|
2445 }
|
|
2446
|
|
2447 static char *oscar_name() {
|
|
2448 return "Oscar";
|
|
2449 }
|
|
2450
|
|
2451 static void oscar_send_im(struct gaim_connection *gc, char *name, char *message, int away) {
|
|
2452 struct oscar_data *odata = (struct oscar_data *)gc->proto_data;
|
|
2453 struct direct_im *dim = find_direct_im(odata, name);
|
|
2454 if (dim) {
|
|
2455 aim_send_im_direct(odata->sess, dim->conn, message);
|
|
2456 } else {
|
|
2457 if (away)
|
|
2458 aim_send_im(odata->sess, odata->conn, name, AIM_IMFLAGS_AWAY, message);
|
|
2459 else {
|
|
2460 int flags = AIM_IMFLAGS_ACK;
|
|
2461 #if USE_PIXBUF
|
|
2462 GSList *h = odata->hasicons;
|
|
2463 struct icon_req *ir;
|
|
2464 char *who = normalize(name);
|
|
2465 while (h) {
|
|
2466 ir = h->data;
|
|
2467 if (ir->request && !strcmp(who, ir->user))
|
|
2468 break;
|
|
2469 h = h->next;
|
|
2470 }
|
|
2471 if (h) {
|
|
2472 ir->request = FALSE;
|
|
2473 flags |= AIM_IMFLAGS_BUDDYREQ;
|
|
2474 debug_printf("sending buddy icon request with message\n");
|
|
2475 }
|
|
2476 #endif
|
|
2477 aim_send_im(odata->sess, odata->conn, name, flags, message);
|
|
2478 }
|
|
2479 }
|
|
2480 }
|
|
2481
|
|
2482 static void oscar_get_info(struct gaim_connection *g, char *name) {
|
|
2483 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2484 aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_GENERALINFO);
|
|
2485 }
|
|
2486
|
|
2487 static void oscar_get_away_msg(struct gaim_connection *g, char *name) {
|
|
2488 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2489 aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_AWAYMESSAGE);
|
|
2490 }
|
|
2491
|
|
2492 static void oscar_set_dir(struct gaim_connection *g, char *first, char *middle, char *last,
|
|
2493 char *maiden, char *city, char *state, char *country, int web) {
|
|
2494 /* FIXME : some of these things are wrong, but i'm lazy */
|
|
2495 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2496 aim_setdirectoryinfo(odata->sess, odata->conn, first, middle, last,
|
|
2497 maiden, NULL, NULL, city, state, NULL, 0, web);
|
|
2498 }
|
|
2499
|
|
2500
|
|
2501 static void oscar_set_idle(struct gaim_connection *g, int time) {
|
|
2502 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2503 aim_bos_setidle(odata->sess, odata->conn, time);
|
|
2504 }
|
|
2505
|
|
2506 static void oscar_set_info(struct gaim_connection *g, char *info) {
|
|
2507 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2508 char inforeal[1025], away[1025];
|
|
2509 g_snprintf(inforeal, sizeof(inforeal), "%s", info);
|
|
2510 if (g->away)
|
|
2511 g_snprintf(away, sizeof(away), "%s", g->away);
|
|
2512 if (strlen(info) > 1024)
|
|
2513 do_error_dialog("Maximum info length (1024) exceeded, truncating", "Info Too Long");
|
|
2514 aim_bos_setprofile(odata->sess, odata->conn, inforeal, g->away ? NULL : "", gaim_caps);
|
|
2515 }
|
|
2516
|
|
2517 static void oscar_set_away(struct gaim_connection *g, char *state, char *message) {
|
|
2518 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2519 char info[1025], away[1025];
|
|
2520 g_snprintf(info, sizeof(info), "%s", g->user->user_info);
|
|
2521 if (message)
|
|
2522 g_snprintf(away, sizeof(away), "%s", message);
|
|
2523 aim_bos_setprofile(odata->sess, odata->conn, NULL, message ? away : "", gaim_caps);
|
|
2524 if (g->away)
|
|
2525 g_free (g->away);
|
|
2526 g->away = NULL;
|
|
2527 if (message) {
|
|
2528 if (strlen(message) > 1024)
|
|
2529 do_error_dialog("Maximum away length (1024) exceeded, truncating",
|
|
2530 "Info Too Long");
|
|
2531 g->away = g_strdup (message);
|
|
2532 }
|
|
2533 }
|
|
2534
|
|
2535 static void oscar_warn(struct gaim_connection *g, char *name, int anon) {
|
|
2536 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2537 aim_send_warning(odata->sess, odata->conn, name, anon);
|
|
2538 }
|
|
2539
|
|
2540 static void oscar_dir_search(struct gaim_connection *g, char *first, char *middle, char *last,
|
|
2541 char *maiden, char *city, char *state, char *country, char *email) {
|
|
2542 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2543 if (strlen(email))
|
|
2544 aim_usersearch_address(odata->sess, odata->conn, email);
|
|
2545 }
|
|
2546
|
|
2547 static void oscar_add_buddy(struct gaim_connection *g, char *name) {
|
|
2548 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2549 aim_add_buddy(odata->sess, odata->conn, name);
|
|
2550 }
|
|
2551
|
|
2552 static void oscar_add_buddies(struct gaim_connection *g, GList *buddies) {
|
|
2553 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2554 char buf[MSG_LEN];
|
|
2555 int n = 0;
|
|
2556 while (buddies) {
|
|
2557 if (n > MSG_LEN - 18) {
|
|
2558 aim_bos_setbuddylist(odata->sess, odata->conn, buf);
|
|
2559 n = 0;
|
|
2560 }
|
|
2561 n += g_snprintf(buf + n, sizeof(buf) - n, "%s&", (char *)buddies->data);
|
|
2562 buddies = buddies->next;
|
|
2563 }
|
|
2564 aim_bos_setbuddylist(odata->sess, odata->conn, buf);
|
|
2565 }
|
|
2566
|
|
2567 static void oscar_remove_buddy(struct gaim_connection *g, char *name) {
|
|
2568 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2569 aim_remove_buddy(odata->sess, odata->conn, name);
|
|
2570 }
|
|
2571
|
|
2572 static void oscar_join_chat(struct gaim_connection *g, int exchange, char *name) {
|
|
2573 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2574 struct aim_conn_t *cur = NULL;
|
|
2575 if (!name) {
|
|
2576 if (!join_chat_entry || !join_chat_spin)
|
|
2577 return;
|
|
2578 name = gtk_entry_get_text(GTK_ENTRY(join_chat_entry));
|
|
2579 exchange = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(join_chat_spin));
|
|
2580 if (!name || !strlen(name))
|
|
2581 return;
|
|
2582 }
|
|
2583 debug_printf("Attempting to join chat room %s.\n", name);
|
|
2584 if ((cur = aim_getconn_type(odata->sess, AIM_CONN_TYPE_CHATNAV))) {
|
|
2585 debug_printf("chatnav exists, creating room\n");
|
|
2586 aim_chatnav_createroom(odata->sess, cur, name, exchange);
|
|
2587 } else {
|
|
2588 /* this gets tricky */
|
|
2589 debug_printf("chatnav does not exist, opening chatnav\n");
|
|
2590 odata->create_exchange = exchange;
|
|
2591 odata->create_name = g_strdup(name);
|
|
2592 aim_bos_reqservice(odata->sess, odata->conn, AIM_CONN_TYPE_CHATNAV);
|
|
2593 }
|
|
2594 }
|
|
2595
|
|
2596 static void des_jc()
|
|
2597 {
|
|
2598 join_chat_entry = NULL;
|
|
2599 join_chat_spin = NULL;
|
|
2600 }
|
|
2601
|
|
2602 static void oscar_draw_join_chat(struct gaim_connection *gc, GtkWidget *fbox) {
|
|
2603 GtkWidget *label;
|
|
2604 GtkWidget *rowbox;
|
|
2605 GtkObject *adjust;
|
|
2606
|
|
2607 rowbox = gtk_hbox_new(FALSE, 5);
|
|
2608 gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0);
|
|
2609 gtk_widget_show(rowbox);
|
|
2610
|
|
2611 label = gtk_label_new(_("Join what group:"));
|
|
2612 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
|
|
2613 gtk_signal_connect(GTK_OBJECT(label), "destroy", GTK_SIGNAL_FUNC(des_jc), NULL);
|
|
2614 gtk_widget_show(label);
|
|
2615
|
|
2616 join_chat_entry = gtk_entry_new();
|
|
2617 gtk_box_pack_start(GTK_BOX(rowbox), join_chat_entry, TRUE, TRUE, 0);
|
|
2618 gtk_widget_grab_focus(join_chat_entry);
|
|
2619 gtk_signal_connect(GTK_OBJECT(join_chat_entry), "activate", GTK_SIGNAL_FUNC(do_join_chat), NULL);
|
|
2620 gtk_widget_show(join_chat_entry);
|
|
2621
|
|
2622 rowbox = gtk_hbox_new(FALSE, 5);
|
|
2623 gtk_box_pack_start(GTK_BOX(fbox), rowbox, TRUE, TRUE, 0);
|
|
2624 gtk_widget_show(rowbox);
|
|
2625
|
|
2626 label = gtk_label_new(_("Exchange:"));
|
|
2627 gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
|
|
2628 gtk_widget_show(label);
|
|
2629
|
|
2630 adjust = gtk_adjustment_new(4, 4, 20, 1, 10, 10);
|
|
2631 join_chat_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
|
|
2632 gtk_widget_set_usize(join_chat_spin, 50, -1);
|
|
2633 gtk_box_pack_start(GTK_BOX(rowbox), join_chat_spin, FALSE, FALSE, 0);
|
|
2634 gtk_widget_show(join_chat_spin);
|
|
2635 }
|
|
2636
|
|
2637 static void oscar_chat_invite(struct gaim_connection *g, int id, char *message, char *name) {
|
|
2638 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2639 struct chat_connection *ccon = find_oscar_chat(g, id);
|
|
2640
|
|
2641 if (!ccon)
|
|
2642 return;
|
|
2643
|
|
2644 aim_chat_invite(odata->sess, odata->conn, name, message ? message : "",
|
|
2645 ccon->exchange, ccon->name, 0x0);
|
|
2646 }
|
|
2647
|
|
2648 static void oscar_chat_leave(struct gaim_connection *g, int id) {
|
|
2649 struct oscar_data *odata = g ? (struct oscar_data *)g->proto_data : NULL;
|
|
2650 GSList *bcs = g->buddy_chats;
|
|
2651 struct conversation *b = NULL;
|
|
2652 struct chat_connection *c = NULL;
|
|
2653 int count = 0;
|
|
2654
|
|
2655 while (bcs) {
|
|
2656 count++;
|
|
2657 b = (struct conversation *)bcs->data;
|
|
2658 if (id == b->id)
|
|
2659 break;
|
|
2660 bcs = bcs->next;
|
|
2661 b = NULL;
|
|
2662 }
|
|
2663
|
|
2664 if (!b)
|
|
2665 return;
|
|
2666
|
|
2667 debug_printf("Attempting to leave room %s (currently in %d rooms)\n", b->name, count);
|
|
2668
|
|
2669 c = find_oscar_chat(g, b->id);
|
|
2670 if (c != NULL) {
|
|
2671 if (odata)
|
|
2672 odata->oscar_chats = g_slist_remove(odata->oscar_chats, c);
|
|
2673 if (c->inpa > 0)
|
|
2674 gdk_input_remove(c->inpa);
|
|
2675 if (g && odata->sess)
|
|
2676 aim_conn_kill(odata->sess, &c->conn);
|
|
2677 g_free(c->name);
|
|
2678 g_free(c->show);
|
|
2679 g_free(c);
|
|
2680 }
|
|
2681 /* we do this because with Oscar it doesn't tell us we left */
|
|
2682 serv_got_chat_left(g, b->id);
|
|
2683 }
|
|
2684
|
|
2685 static void oscar_chat_send(struct gaim_connection *g, int id, char *message) {
|
|
2686 struct oscar_data *odata = (struct oscar_data *)g->proto_data;
|
|
2687 GSList *bcs = g->buddy_chats;
|
|
2688 struct conversation *b = NULL;
|
|
2689 struct chat_connection *c = NULL;
|
|
2690 char *buf;
|
|
2691 int i, j;
|
|
2692
|
|
2693 while (bcs) {
|
|
2694 b = (struct conversation *)bcs->data;
|
|
2695 if (id == b->id)
|
|
2696 break;
|
|
2697 bcs = bcs->next;
|
|
2698 b = NULL;
|
|
2699 }
|
|
2700 if (!b)
|
|
2701 return;
|
|
2702
|
|
2703 bcs = odata->oscar_chats;
|
|
2704 while (bcs) {
|
|
2705 c = (struct chat_connection *)bcs->data;
|
|
2706 if (b == c->cnv)
|
|
2707 break;
|
|
2708 bcs = bcs->next;
|
|
2709 c = NULL;
|
|
2710 }
|
|
2711 if (!c)
|
|
2712 return;
|
|
2713
|
|
2714 buf = g_malloc(strlen(message) * 4 + 1);
|
|
2715 for (i = 0, j = 0; i < strlen(message); i++) {
|
|
2716 if (message[i] == '\n') {
|
|
2717 buf[j++] = '<';
|
|
2718 buf[j++] = 'B';
|
|
2719 buf[j++] = 'R';
|
|
2720 buf[j++] = '>';
|
|
2721 } else {
|
|
2722 buf[j++] = message[i];
|
|
2723 }
|
|
2724 }
|
|
2725 buf[j] = '\0';
|
|
2726 aim_chat_send_im(odata->sess, c->conn, 0, buf, strlen(buf));
|
|
2727 g_free(buf);
|
|
2728 }
|
|
2729
|
|
2730 static char **oscar_list_icon(int uc) {
|
|
2731 if (uc & UC_UNAVAILABLE)
|
|
2732 return (char **)away_icon_xpm;
|
|
2733 if (uc & UC_AOL)
|
|
2734 return (char **)aol_icon_xpm;
|
|
2735 if (uc & UC_NORMAL)
|
|
2736 return (char **)free_icon_xpm;
|
|
2737 if (uc & UC_ADMIN)
|
|
2738 return (char **)admin_icon_xpm;
|
|
2739 if (uc & UC_UNCONFIRMED)
|
|
2740 return (char **)dt_icon_xpm;
|
|
2741 return NULL;
|
|
2742 }
|
|
2743
|
|
2744 static void oscar_info(GtkObject *obj, char *who) {
|
|
2745 struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(obj);
|
|
2746 serv_get_info(gc, who);
|
|
2747 }
|
|
2748
|
|
2749 static void oscar_away_msg(GtkObject *obj, char *who) {
|
|
2750 struct gaim_connection *gc = (struct gaim_connection *)gtk_object_get_user_data(obj);
|
|
2751 serv_get_away_msg(gc, who);
|
|
2752 }
|
|
2753
|
|
2754 static int gaim_directim_initiate(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2755 va_list ap;
|
|
2756 struct gaim_connection *gc = sess->aux_data;
|
|
2757 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
2758 struct aim_directim_priv *priv;
|
|
2759 struct aim_conn_t *newconn;
|
|
2760 struct direct_im *dim;
|
|
2761 char buf[256];
|
|
2762
|
|
2763 va_start(ap, command);
|
|
2764 newconn = va_arg(ap, struct aim_conn_t *);
|
|
2765 va_end(ap);
|
|
2766
|
|
2767 priv = (struct aim_directim_priv *)newconn->priv;
|
|
2768
|
|
2769 debug_printf("DirectIM: initiate success to %s\n", priv->sn);
|
|
2770 dim = find_direct_im(od, priv->sn);
|
|
2771
|
|
2772 dim->cnv = find_conversation(priv->sn);
|
|
2773 if (!dim->cnv) dim->cnv = new_conversation(priv->sn);
|
|
2774 gtk_signal_connect(GTK_OBJECT(dim->cnv->window), "destroy",
|
|
2775 GTK_SIGNAL_FUNC(delete_direct_im), dim);
|
|
2776 gdk_input_remove(dim->watcher);
|
|
2777 dim->conn = newconn;
|
|
2778 dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
2779 oscar_callback, dim->conn);
|
|
2780 g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), priv->sn);
|
|
2781 write_to_conv(dim->cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL));
|
|
2782
|
|
2783 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING,
|
|
2784 gaim_directim_incoming, 0);
|
|
2785 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT,
|
|
2786 gaim_directim_disconnect, 0);
|
|
2787 aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING,
|
|
2788 gaim_directim_typing, 0);
|
|
2789
|
|
2790 return 1;
|
|
2791 }
|
|
2792
|
|
2793 static int gaim_directim_incoming(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2794 va_list ap;
|
|
2795 char *msg = NULL;
|
|
2796 struct aim_conn_t *conn;
|
|
2797 struct aim_directim_priv *priv;
|
|
2798 struct gaim_connection *gc = sess->aux_data;
|
|
2799
|
|
2800 va_start(ap, command);
|
|
2801 conn = va_arg(ap, struct aim_conn_t *);
|
|
2802 msg = va_arg(ap, char *);
|
|
2803 va_end(ap);
|
|
2804
|
|
2805 if (!(priv = conn->priv)) {
|
|
2806 return -1;
|
|
2807 }
|
|
2808
|
|
2809 debug_printf("Got DirectIM message from %s\n", priv->sn);
|
|
2810
|
|
2811 serv_got_im(gc, priv->sn, msg, 0, time((time_t)NULL));
|
|
2812
|
|
2813 return 1;
|
|
2814 }
|
|
2815
|
|
2816 static int gaim_directim_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2817 va_list ap;
|
|
2818 struct aim_conn_t *conn;
|
|
2819 char *sn;
|
|
2820 struct gaim_connection *gc = sess->aux_data;
|
|
2821 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
2822 struct direct_im *dim;
|
|
2823 char buf[256];
|
|
2824
|
|
2825 va_start(ap, command);
|
|
2826 conn = va_arg(ap, struct aim_conn_t *);
|
|
2827 sn = va_arg(ap, char *);
|
|
2828 va_end(ap);
|
|
2829
|
|
2830 debug_printf("%s disconnected Direct IM.\n", sn);
|
|
2831
|
|
2832 dim = find_direct_im(od, sn);
|
|
2833 od->direct_ims = g_slist_remove(od->direct_ims, dim);
|
|
2834 gdk_input_remove(dim->watcher);
|
|
2835 gtk_signal_disconnect_by_data(GTK_OBJECT(dim->cnv->window), dim);
|
|
2836
|
|
2837 g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), sn);
|
|
2838 if (dim->cnv)
|
|
2839 write_to_conv(dim->cnv, buf, WFLAG_SYSTEM, NULL, time((time_t)NULL));
|
|
2840
|
|
2841 aim_conn_kill(sess, &conn);
|
|
2842
|
|
2843 return 1;
|
|
2844 }
|
|
2845
|
|
2846 static int gaim_directim_typing(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
|
|
2847 va_list ap;
|
|
2848 struct aim_conn_t *conn;
|
|
2849 struct aim_directim_priv *priv;
|
|
2850
|
|
2851 va_start(ap, command);
|
|
2852 conn = va_arg(ap, struct aim_conn_t *);
|
|
2853 va_end(ap);
|
|
2854
|
|
2855 if (!(priv = conn->priv)) {
|
|
2856 return -1;
|
|
2857 }
|
|
2858
|
|
2859 /* I had to leave this. It's just too funny. It reminds me of my sister. */
|
|
2860 debug_printf("ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", priv->sn);
|
|
2861
|
|
2862 return 1;
|
|
2863 }
|
|
2864
|
|
2865 struct ask_do_dir_im {
|
|
2866 char *who;
|
|
2867 struct gaim_connection *gc;
|
|
2868 };
|
|
2869
|
|
2870 static void oscar_cancel_direct_im(GtkObject *obj, struct ask_do_dir_im *data) {
|
|
2871 g_free(data);
|
|
2872 }
|
|
2873
|
|
2874 static void oscar_direct_im(GtkObject *obj, struct ask_do_dir_im *data) {
|
|
2875 struct gaim_connection *gc = data->gc;
|
|
2876 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
2877 struct direct_im *dim;
|
|
2878
|
|
2879 dim = find_direct_im(od, data->who);
|
|
2880 if (dim) {
|
|
2881 do_error_dialog("Direct IM request already pending.", "Unable");
|
|
2882 return;
|
|
2883 }
|
|
2884 dim = g_new0(struct direct_im, 1);
|
|
2885 dim->gc = gc;
|
|
2886 g_snprintf(dim->name, sizeof dim->name, "%s", data->who);
|
|
2887
|
|
2888 dim->conn = aim_directim_initiate(od->sess, od->conn, NULL, data->who);
|
|
2889 if (dim->conn != NULL) {
|
|
2890 od->direct_ims = g_slist_append(od->direct_ims, dim);
|
|
2891 dim->watcher = gdk_input_add(dim->conn->fd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
|
|
2892 oscar_callback, dim->conn);
|
|
2893 aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE,
|
|
2894 gaim_directim_initiate, 0);
|
|
2895 } else {
|
|
2896 do_error_dialog(_("Unable to open Direct IM"), _("Error"));
|
|
2897 g_free(dim);
|
|
2898 }
|
|
2899 }
|
|
2900
|
|
2901 static void oscar_ask_direct_im(GtkObject *m, gchar *who) {
|
|
2902 char buf[BUF_LONG];
|
|
2903 struct ask_do_dir_im *data = g_new0(struct ask_do_dir_im, 1);
|
|
2904 data->who = who;
|
|
2905 data->gc = gtk_object_get_user_data(m);
|
|
2906 g_snprintf(buf, sizeof(buf), _("You have selected to open a Direct IM connection with %s."
|
|
2907 " Doing this will let them see your IP address, and may be"
|
|
2908 " a security risk. Do you wish to continue?"), who);
|
|
2909 do_ask_dialog(buf, data, oscar_direct_im, oscar_cancel_direct_im);
|
|
2910 }
|
|
2911
|
|
2912 static void oscar_buddy_menu(GtkWidget *menu, struct gaim_connection *gc, char *who) {
|
|
2913 GtkWidget *button;
|
|
2914 char *n = g_strdup(normalize(gc->username));
|
|
2915
|
|
2916 button = gtk_menu_item_new_with_label(_("Get Info"));
|
|
2917 gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
2918 GTK_SIGNAL_FUNC(oscar_info), who);
|
|
2919 gtk_object_set_user_data(GTK_OBJECT(button), gc);
|
|
2920 gtk_menu_append(GTK_MENU(menu), button);
|
|
2921 gtk_widget_show(button);
|
|
2922
|
|
2923 button = gtk_menu_item_new_with_label(_("Get Away Msg"));
|
|
2924 gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
2925 GTK_SIGNAL_FUNC(oscar_away_msg), who);
|
|
2926 gtk_object_set_user_data(GTK_OBJECT(button), gc);
|
|
2927 gtk_menu_append(GTK_MENU(menu), button);
|
|
2928 gtk_widget_show(button);
|
|
2929
|
|
2930 if (strcmp(n, normalize(who))) {
|
|
2931 button = gtk_menu_item_new_with_label(_("Direct IM"));
|
|
2932 gtk_signal_connect(GTK_OBJECT(button), "activate",
|
|
2933 GTK_SIGNAL_FUNC(oscar_ask_direct_im), who);
|
|
2934 gtk_object_set_user_data(GTK_OBJECT(button), gc);
|
|
2935 gtk_menu_append(GTK_MENU(menu), button);
|
|
2936 gtk_widget_show(button);
|
|
2937 }
|
|
2938 g_free(n);
|
|
2939 }
|
|
2940
|
|
2941
|
|
2942 /* weeee */
|
|
2943 static void oscar_print_option(GtkEntry *entry, struct aim_user *user)
|
|
2944 {
|
|
2945 int entrynum;
|
|
2946
|
|
2947 entrynum = (int)gtk_object_get_user_data(GTK_OBJECT(entry));
|
|
2948
|
|
2949 if (entrynum == USEROPT_AUTH) {
|
|
2950 g_snprintf(user->proto_opt[USEROPT_AUTH],
|
|
2951 sizeof(user->proto_opt[USEROPT_AUTH]), "%s", gtk_entry_get_text(entry));
|
|
2952 } else if (entrynum == USEROPT_AUTHPORT) {
|
|
2953 g_snprintf(user->proto_opt[USEROPT_AUTHPORT],
|
|
2954 sizeof(user->proto_opt[USEROPT_AUTHPORT]), "%s", gtk_entry_get_text(entry));
|
|
2955 }
|
|
2956 }
|
|
2957
|
|
2958 static void oscar_user_opts(GtkWidget *book, struct aim_user *user)
|
|
2959 {
|
|
2960 /* so here, we create the new notebook page */
|
|
2961 GtkWidget *vbox;
|
|
2962 GtkWidget *hbox;
|
|
2963 GtkWidget *label;
|
|
2964 GtkWidget *entry;
|
|
2965
|
|
2966 vbox = gtk_vbox_new(FALSE, 5);
|
|
2967 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
|
|
2968 gtk_notebook_append_page(GTK_NOTEBOOK(book), vbox, gtk_label_new("Oscar Options"));
|
|
2969 gtk_widget_show(vbox);
|
|
2970
|
|
2971 hbox = gtk_hbox_new(FALSE, 5);
|
|
2972 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
|
|
2973 gtk_widget_show(hbox);
|
|
2974
|
|
2975 label = gtk_label_new("Auth Host:");
|
|
2976 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
|
2977 gtk_widget_show(label);
|
|
2978
|
|
2979 entry = gtk_entry_new();
|
|
2980 gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
|
|
2981 gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_AUTH);
|
|
2982 gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user);
|
|
2983 if (user->proto_opt[USEROPT_AUTH][0]) {
|
|
2984 debug_printf("setting text %s\n", user->proto_opt[USEROPT_AUTH]);
|
|
2985 gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_AUTH]);
|
|
2986 } else
|
|
2987 gtk_entry_set_text(GTK_ENTRY(entry), "login.oscar.aol.com");
|
|
2988 gtk_widget_show(entry);
|
|
2989
|
|
2990 hbox = gtk_hbox_new(FALSE, 0);
|
|
2991 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
|
|
2992 gtk_widget_show(hbox);
|
|
2993
|
|
2994 label = gtk_label_new("Auth Port:");
|
|
2995 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
|
2996 gtk_widget_show(label);
|
|
2997
|
|
2998 entry = gtk_entry_new();
|
|
2999 gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
|
|
3000 gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_AUTHPORT);
|
|
3001 gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(oscar_print_option), user);
|
|
3002 if (user->proto_opt[USEROPT_AUTHPORT][0]) {
|
|
3003 debug_printf("setting text %s\n", user->proto_opt[USEROPT_AUTHPORT]);
|
|
3004 gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_AUTHPORT]);
|
|
3005 } else
|
|
3006 gtk_entry_set_text(GTK_ENTRY(entry), "5190");
|
|
3007
|
|
3008 gtk_widget_show(entry);
|
|
3009 }
|
|
3010
|
|
3011 static void oscar_set_permit_deny(struct gaim_connection *gc) {
|
|
3012 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
|
|
3013 GSList *list;
|
|
3014 char buf[MAXMSGLEN];
|
|
3015 int at;
|
|
3016
|
|
3017 switch(gc->permdeny) {
|
|
3018 case 1:
|
|
3019 aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, gc->username);
|
|
3020 break;
|
|
3021 case 2:
|
|
3022 aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, gc->username);
|
|
3023 break;
|
|
3024 case 3:
|
|
3025 list = gc->permit;
|
|
3026 at = 0;
|
|
3027 while (list) {
|
|
3028 at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data);
|
|
3029 list = list->next;
|
|
3030 }
|
|
3031 aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_PERMITADD, buf);
|
|
3032 break;
|
|
3033 case 4:
|
|
3034 list = gc->deny;
|
|
3035 at = 0;
|
|
3036 while (list) {
|
|
3037 at += g_snprintf(buf + at, sizeof(buf) - at, "%s&", (char *)list->data);
|
|
3038 list = list->next;
|
|
3039 }
|
|
3040 aim_bos_changevisibility(od->sess, od->conn, AIM_VISIBILITYCHANGE_DENYADD, buf);
|
|
3041 break;
|
|
3042 default:
|
|
3043 break;
|
|
3044 }
|
|
3045 }
|
|
3046
|
|
3047 static void oscar_add_permit(struct gaim_connection *gc, char *who) {
|
|
3048 if (gc->permdeny != 3) return;
|
|
3049 oscar_set_permit_deny(gc);
|
|
3050 }
|
|
3051
|
|
3052 static void oscar_add_deny(struct gaim_connection *gc, char *who) {
|
|
3053 if (gc->permdeny != 4) return;
|
|
3054 oscar_set_permit_deny(gc);
|
|
3055 }
|
|
3056
|
|
3057 static void oscar_rem_permit(struct gaim_connection *gc, char *who) {
|
|
3058 if (gc->permdeny != 3) return;
|
|
3059 oscar_set_permit_deny(gc);
|
|
3060 }
|
|
3061
|
|
3062 static void oscar_rem_deny(struct gaim_connection *gc, char *who) {
|
|
3063 if (gc->permdeny != 4) return;
|
|
3064 oscar_set_permit_deny(gc);
|
|
3065 }
|
|
3066
|
|
3067 static void oscar_draw_new_user(GtkWidget *box)
|
|
3068 {
|
|
3069 GtkWidget *label;
|
|
3070
|
|
3071 label = gtk_label_new(_("Unfortunately, currently Oscar only allows new user registration by "
|
|
3072 "going to http://aim.aol.com/aimnew/Aim/register.adp?promo=106723&pageset=Aim&client=no"
|
|
3073 ". Clicking the Register button will open the URL for you."));
|
|
3074 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
|
|
3075 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 5);
|
|
3076 gtk_widget_show(label);
|
|
3077 }
|
|
3078
|
|
3079 static void oscar_do_new_user()
|
|
3080 {
|
|
3081 open_url(NULL, "http://aim.aol.com/aimnew/Aim/register.adp?promo=106723&pageset=Aim&client=no");
|
|
3082 }
|
|
3083
|
|
3084 static GList *oscar_away_states()
|
|
3085 {
|
|
3086 return g_list_append(NULL, GAIM_AWAY_CUSTOM);
|
|
3087 }
|
|
3088
|
|
3089 static void oscar_do_action(struct gaim_connection *gc, char *act)
|
|
3090 {
|
|
3091 struct oscar_data *od = gc->proto_data;
|
|
3092 struct aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
|
|
3093
|
|
3094 if (!strcmp(act, "Set User Info")) {
|
|
3095 show_set_info(gc);
|
|
3096 } else if (!strcmp(act, "Change Password")) {
|
|
3097 show_change_passwd(gc);
|
|
3098 } else if (!strcmp(act, "Confirm Account")) {
|
|
3099 if (!conn) {
|
|
3100 od->conf = TRUE;
|
|
3101 aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
|
|
3102 } else
|
|
3103 aim_auth_reqconfirm(od->sess, conn);
|
|
3104 } else if (!strcmp(act, "Change Email")) {
|
|
3105 } else if (!strcmp(act, "Display Current Registered Address")) {
|
|
3106 if (!conn) {
|
|
3107 od->reqemail = TRUE;
|
|
3108 aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
|
|
3109 } else
|
|
3110 aim_auth_getinfo(od->sess, conn, 0x11);
|
|
3111 } else if (!strcmp(act, "Search for Buddy by Email")) {
|
|
3112 show_find_email(gc);
|
|
3113 }
|
|
3114 }
|
|
3115
|
|
3116 static GList *oscar_actions()
|
|
3117 {
|
|
3118 GList *m = NULL;
|
|
3119
|
|
3120 m = g_list_append(m, "Set User Info");
|
|
3121 m = g_list_append(m, NULL);
|
|
3122 m = g_list_append(m, "Change Password");
|
|
3123 m = g_list_append(m, "Confirm Account");
|
|
3124 /*
|
|
3125 m = g_list_append(m, "Change Email");
|
|
3126 */
|
|
3127 m = g_list_append(m, "Display Current Registered Address");
|
|
3128 m = g_list_append(m, NULL);
|
|
3129 m = g_list_append(m, "Search for Buddy by Email");
|
|
3130
|
|
3131 return m;
|
|
3132 }
|
|
3133
|
|
3134 static void oscar_change_passwd(struct gaim_connection *gc, char *old, char *new)
|
|
3135 {
|
|
3136 struct oscar_data *od = gc->proto_data;
|
|
3137 if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) {
|
|
3138 od->chpass = TRUE;
|
|
3139 od->oldp = g_strdup(old);
|
|
3140 od->newp = g_strdup(new);
|
|
3141 aim_bos_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
|
|
3142 } else {
|
|
3143 aim_auth_changepasswd(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH),
|
|
3144 new, old);
|
|
3145 }
|
|
3146 }
|
|
3147
|
|
3148 static void oscar_insert_convo(struct gaim_connection *gc, struct conversation *c)
|
|
3149 {
|
|
3150 #if USE_PIXBUF
|
|
3151 struct oscar_data *od = gc->proto_data;
|
|
3152 GSList *h = od->hasicons;
|
|
3153 struct icon_req *ir = NULL;
|
|
3154 char *who = normalize(c->name);
|
|
3155
|
|
3156 GdkPixbufLoader *load;
|
|
3157 GList *frames;
|
|
3158 GdkPixbuf *buf;
|
|
3159 GdkPixmap *pm;
|
|
3160 GdkBitmap *bm;
|
|
3161
|
|
3162 while (h) {
|
|
3163 ir = h->data;
|
|
3164 if (!strcmp(who, ir->user))
|
|
3165 break;
|
|
3166 h = h->next;
|
|
3167 }
|
|
3168 if (!h || !ir->data)
|
|
3169 return;
|
|
3170
|
|
3171 ir->cnv = c;
|
|
3172
|
|
3173 load = gdk_pixbuf_loader_new();
|
|
3174 gdk_pixbuf_loader_write(load, ir->data, ir->length);
|
|
3175 ir->anim = gdk_pixbuf_loader_get_animation(load);
|
|
3176
|
|
3177 if (ir->anim) {
|
|
3178 frames = gdk_pixbuf_animation_get_frames(ir->anim);
|
|
3179 buf = gdk_pixbuf_frame_get_pixbuf(frames->data);
|
|
3180 gdk_pixbuf_render_pixmap_and_mask(buf, &pm, &bm, 0);
|
|
3181
|
|
3182 if (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1) {
|
|
3183 int delay = MAX(gdk_pixbuf_frame_get_delay_time(frames->data), 13);
|
|
3184 ir->curframe = 1;
|
|
3185 ir->timer = gtk_timeout_add(delay * 10, redraw_anim, ir);
|
|
3186 }
|
|
3187 } else {
|
|
3188 ir->unanim = gdk_pixbuf_loader_get_pixbuf(load);
|
|
3189 if (!ir->unanim) {
|
|
3190 gdk_pixbuf_loader_close(load);
|
|
3191 return;
|
|
3192 }
|
|
3193 gdk_pixbuf_render_pixmap_and_mask(ir->unanim, &pm, &bm, 0);
|
|
3194 }
|
|
3195
|
|
3196 ir->pix = gtk_pixmap_new(pm, bm);
|
|
3197 gtk_box_pack_start(GTK_BOX(c->bbox), ir->pix, FALSE, FALSE, 5);
|
|
3198 if (ir->anim && (gdk_pixbuf_animation_get_num_frames(ir->anim) > 1))
|
|
3199 gtk_widget_set_usize(ir->pix, gdk_pixbuf_animation_get_width(ir->anim),
|
|
3200 gdk_pixbuf_animation_get_height(ir->anim));
|
|
3201 gtk_widget_show(ir->pix);
|
|
3202 gdk_pixmap_unref(pm);
|
|
3203 if (bm)
|
|
3204 gdk_bitmap_unref(bm);
|
|
3205
|
|
3206 gdk_pixbuf_loader_close(load);
|
|
3207 #endif
|
|
3208 }
|
|
3209
|
|
3210 static void oscar_remove_convo(struct gaim_connection *gc, struct conversation *c)
|
|
3211 {
|
|
3212 #if USE_PIXBUF
|
|
3213 struct oscar_data *od = gc->proto_data;
|
|
3214 GSList *h = od->hasicons;
|
|
3215 struct icon_req *ir = NULL;
|
|
3216 char *who = normalize(c->name);
|
|
3217
|
|
3218 while (h) {
|
|
3219 ir = h->data;
|
|
3220 if (!strcmp(who, ir->user))
|
|
3221 break;
|
|
3222 h = h->next;
|
|
3223 }
|
|
3224 if (!h || !ir->data)
|
|
3225 return;
|
|
3226
|
|
3227 if (ir->cnv && ir->pix) {
|
|
3228 gtk_container_remove(GTK_CONTAINER(ir->cnv->bbox), ir->pix);
|
|
3229 ir->pix = NULL;
|
|
3230 ir->cnv = NULL;
|
|
3231 }
|
|
3232
|
|
3233 if (ir->anim) {
|
|
3234 gdk_pixbuf_animation_unref(ir->anim);
|
|
3235 ir->anim = NULL;
|
|
3236 } else if (ir->unanim) {
|
|
3237 gdk_pixbuf_unref(ir->unanim);
|
|
3238 ir->unanim = NULL;
|
|
3239 }
|
|
3240
|
|
3241 ir->curframe = 0;
|
|
3242
|
|
3243 if (ir->timer)
|
|
3244 gtk_timeout_remove(ir->timer);
|
|
3245 ir->timer = 0;
|
|
3246 #endif
|
|
3247 }
|
|
3248
|
|
3249 static struct prpl *my_protocol = NULL;
|
|
3250
|
|
3251 void oscar_init(struct prpl *ret) {
|
|
3252 ret->protocol = PROTO_OSCAR;
|
|
3253 ret->options = OPT_PROTO_HTML | OPT_PROTO_CORRECT_TIME;
|
|
3254 ret->name = oscar_name;
|
|
3255 ret->list_icon = oscar_list_icon;
|
|
3256 ret->away_states = oscar_away_states;
|
|
3257 ret->actions = oscar_actions;
|
|
3258 ret->do_action = oscar_do_action;
|
|
3259 ret->buddy_menu = oscar_buddy_menu;
|
|
3260 ret->user_opts = oscar_user_opts;
|
|
3261 ret->draw_new_user = oscar_draw_new_user;
|
|
3262 ret->do_new_user = oscar_do_new_user;
|
|
3263 ret->insert_convo = oscar_insert_convo;
|
|
3264 ret->remove_convo = oscar_remove_convo;
|
|
3265 ret->login = oscar_login;
|
|
3266 ret->close = oscar_close;
|
|
3267 ret->send_im = oscar_send_im;
|
|
3268 ret->set_info = oscar_set_info;
|
|
3269 ret->get_info = oscar_get_info;
|
|
3270 ret->set_away = oscar_set_away;
|
|
3271 ret->get_away_msg = oscar_get_away_msg;
|
|
3272 ret->set_dir = oscar_set_dir;
|
|
3273 ret->get_dir = NULL; /* Oscar really doesn't have this */
|
|
3274 ret->dir_search = oscar_dir_search;
|
|
3275 ret->set_idle = oscar_set_idle;
|
|
3276 ret->change_passwd = oscar_change_passwd;
|
|
3277 ret->add_buddy = oscar_add_buddy;
|
|
3278 ret->add_buddies = oscar_add_buddies;
|
|
3279 ret->remove_buddy = oscar_remove_buddy;
|
|
3280 ret->add_permit = oscar_add_permit;
|
|
3281 ret->add_deny = oscar_add_deny;
|
|
3282 ret->rem_permit = oscar_rem_permit;
|
|
3283 ret->rem_deny = oscar_rem_deny;
|
|
3284 ret->set_permit_deny = oscar_set_permit_deny;
|
|
3285 ret->warn = oscar_warn;
|
|
3286 ret->accept_chat = NULL; /* oscar doesn't have accept, it just joins */
|
|
3287 ret->join_chat = oscar_join_chat;
|
|
3288 ret->draw_join_chat = oscar_draw_join_chat;
|
|
3289 ret->chat_invite = oscar_chat_invite;
|
|
3290 ret->chat_leave = oscar_chat_leave;
|
|
3291 ret->chat_whisper = NULL;
|
|
3292 ret->chat_send = oscar_chat_send;
|
|
3293 ret->keepalive = oscar_keepalive;
|
|
3294
|
|
3295 my_protocol = ret;
|
|
3296 }
|
|
3297
|
|
3298 #ifndef STATIC
|
|
3299
|
|
3300 char *gaim_plugin_init(GModule *handle)
|
|
3301 {
|
|
3302 load_protocol(oscar_init, sizeof(struct prpl));
|
|
3303 return NULL;
|
|
3304 }
|
|
3305
|
|
3306 void gaim_plugin_remove()
|
|
3307 {
|
|
3308 struct prpl *p = find_prpl(PROTO_OSCAR);
|
|
3309 if (p == my_protocol)
|
|
3310 unload_protocol(p);
|
|
3311 }
|
|
3312
|
|
3313 char *name()
|
|
3314 {
|
|
3315 return "Oscar";
|
|
3316 }
|
|
3317
|
|
3318 char *description()
|
|
3319 {
|
|
3320 return "Allows gaim to use the Oscar protocol.";
|
|
3321 }
|
|
3322
|
|
3323 #endif
|