source: aim.c @ fa00c5c

owl
Last change on this file since fa00c5c was fa00c5c, checked in by James M. Kretchmar <kretch@mit.edu>, 15 years ago
Correct license.
  • Property mode set to 100644
File size: 92.8 KB
Line 
1/* Copyright (c) 2002,2003,2004,2009 James M. Kretchmar
2 *
3 * This file is part of Owl.
4 *
5 * Owl is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Owl is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Owl.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 * ---------------------------------------------------------------
19 *
20 * As of Owl version 2.1.12 there are patches contributed by
21 * developers of the branched BarnOwl project, Copyright (c)
22 * 2006-2009 The BarnOwl Developers. All rights reserved.
23 */
24
25#include <stdio.h>
26#include <stdio.h>
27#include <sys/stat.h>
28#include "owl.h"
29
30/**********************************************************************/
31
32struct owlfaim_priv {
33  char *aimbinarypath;
34  char *screenname;
35  char *password;
36  char *server;
37  char *proxy;
38  char *proxyusername;
39  char *proxypass;
40  char *ohcaptainmycaptain;
41  int connected;
42
43  FILE *listingfile;
44  char *listingpath;
45
46  fu8_t *buddyicon;
47  int buddyiconlen;
48  time_t buddyiconstamp;
49  fu16_t buddyiconsum;
50};
51
52static char *msgerrreasons[] = {
53        "Invalid error",
54        "Invalid SNAC",
55        "Rate to host",
56        "Rate to client",
57        "Not logged on",
58        "Service unavailable",
59        "Service not defined",
60        "Obsolete SNAC",
61        "Not supported by host",
62        "Not supported by client",
63        "Refused by client",
64        "Reply too big",
65        "Responses lost",
66        "Request denied",
67        "Busted SNAC payload",
68        "Insufficient rights",
69        "In local permit/deny",
70        "Too evil (sender)",
71        "Too evil (receiver)",
72        "User temporarily unavailable",
73        "No match",
74        "List overflow",
75        "Request ambiguous",
76        "Queue full",
77        "Not while on AOL",
78};
79static int msgerrreasonslen = 25;
80
81static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
82static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...);
83static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...);
84int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...);
85int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...);
86void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn);
87static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...);
88static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...);
89static int conninitdone_chatnav  (aim_session_t *, aim_frame_t *, ...);
90static int conninitdone_chat     (aim_session_t *, aim_frame_t *, ...);
91int logout(aim_session_t *sess);
92
93static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...);
94static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...);
95static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...);
96static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...);
97static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...);
98static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...);
99static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...);
100static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...);
101static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...);
102/* static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs); */
103static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...);
104static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname);
105static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...);
106/* static void printuserflags(fu16_t flags); */
107static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...);
108static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, const char *tmpstr);
109static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args);
110static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args);
111static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...);
112static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...);
113static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...);
114int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...);
115static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...);
116static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...);
117static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...);
118static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...);
119static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...);
120static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...);
121static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...);
122static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...);
123static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...);
124static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...);
125static int migrate(aim_session_t *sess, aim_frame_t *fr, ...);
126static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...);
127static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...);
128static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...);
129static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...);
130static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...);
131/*
132static int faimtest_ssi_parseerr     (aim_session_t *, aim_frame_t *, ...);
133static int faimtest_ssi_parserights  (aim_session_t *, aim_frame_t *, ...);
134static int faimtest_ssi_parselist    (aim_session_t *, aim_frame_t *, ...);
135static int faimtest_ssi_parseack     (aim_session_t *, aim_frame_t *, ...);
136static int faimtest_ssi_authgiven    (aim_session_t *, aim_frame_t *, ...);
137static int faimtest_ssi_authrequest  (aim_session_t *, aim_frame_t *, ...);
138static int faimtest_ssi_authreply    (aim_session_t *, aim_frame_t *, ...);
139static int faimtest_ssi_gotadded     (aim_session_t *, aim_frame_t *, ...);
140*/
141
142void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
143void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
144
145/*****************************************************************/
146
147void owl_aim_init(void)
148{
149  /* this has all been moved to owl_aim_login, but we'll leave the
150   * function here, in case there's stuff we want to init in the
151   * future.  It's still called by Owl.
152   */
153     
154}
155
156
157int owl_aim_login(char *screenname, char *password)
158{
159  struct owlfaim_priv *priv;
160  aim_conn_t *conn;
161  aim_session_t *sess;
162
163  sess=owl_global_get_aimsess(&g);
164
165  aim_session_init(sess, TRUE, 0);
166  aim_setdebuggingcb(sess, faimtest_debugcb);
167  aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
168 
169  /* this will leak, I know and just don't care right now */
170  priv=owl_malloc(sizeof(struct owlfaim_priv));
171  memset(priv, 0, sizeof(struct owlfaim_priv));
172
173  priv->screenname = owl_strdup(screenname);
174  priv->password = owl_strdup(password);
175  priv->server = owl_strdup(FAIM_LOGIN_SERVER);
176  sess->aux_data = priv;
177
178  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, priv->server ? priv->server : FAIM_LOGIN_SERVER);
179  /*  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); */
180  if (!conn) {
181    owl_function_error("owl_aim_login: connection error during AIM login\n");
182    owl_global_set_aimnologgedin(&g);
183    owl_global_set_no_doaimevents(&g);
184    return (-1);
185  }
186
187  /*
188  else if (conn->fd == -1) {
189    if (conn->status & AIM_CONN_STATUS_RESOLVERR) {
190      owl_function_error("owl_aim_login: could not resolve authorize name");
191    } else if (conn->status & AIM_CONN_STATUS_CONNERR) {
192      owl_function_error("owl_aim_login: could not connect to authorizer");
193    } else {
194      owl_function_error("owl_aim_login: unknown connection error");
195    }
196    owl_global_set_aimnologgedin(&g);
197    owl_global_set_no_doaimevents(&g);
198    aim_conn_kill(sess, &conn);
199    return(-1);
200  }
201  */
202
203   
204  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
205  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
206
207  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_AUTHRESPONSE, faimtest_parse_login, 0);
208  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_LOGINRESPONSE, faimtest_parse_authresp, 0);
209  /* aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); */
210  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); */
211  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); */
212   
213  /* start processing AIM events */
214  owl_global_set_doaimevents(&g);
215  /* conn->status |= AIM_CONN_STATUS_INPROGRESS; */
216  owl_function_debugmsg("owl_aim_login: sending login request for %s", screenname);
217  aim_request_login(sess, conn, screenname);
218  owl_function_debugmsg("owl_aim_login: connecting");
219
220  return(0);
221}
222
223/* stuff to run once login has been successful */
224void owl_aim_successful_login(char *screenname)
225{
226  char *buff;
227  owl_function_debugmsg("doing owl_aim_successful_login");
228  owl_global_set_aimloggedin(&g, screenname);
229  owl_global_set_doaimevents(&g); /* this should already be on */
230  owl_function_makemsg("%s logged in", screenname);
231  buff=owl_sprintf("Logged in to AIM as %s", screenname);
232  owl_function_adminmsg("", buff);
233  owl_free(buff);
234
235  owl_function_debugmsg("Successful AIM login for %s", screenname);
236
237  /* start the ingorelogin timer */
238  owl_timer_reset_newstart(owl_global_get_aim_login_timer(&g),
239                           owl_global_get_aim_ignorelogin_timer(&g));
240
241 
242  /* aim_ssi_setpresence(owl_global_get_aimsess(&g), 0x00000400); */
243  /* aim_bos_setidle(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), 5000); */
244}
245
246void owl_aim_logout(void)
247{
248  /* need to check if it's connected first, I think */
249  logout(owl_global_get_aimsess(&g));
250
251  if (owl_global_is_aimloggedin(&g)) owl_function_adminmsg("", "Logged out of AIM");
252  owl_global_set_aimnologgedin(&g);
253  owl_global_set_no_doaimevents(&g);
254}
255
256void owl_aim_logged_out()
257{
258  if (owl_global_is_aimloggedin(&g)) owl_function_adminmsg("", "Logged out of AIM");
259  owl_aim_logout();
260}
261
262void owl_aim_login_error(char *message)
263{
264  if (message) {
265    owl_function_error("%s", message);
266  } else {
267    owl_function_error("Authentication error on login");
268  }
269  owl_function_beep();
270  owl_global_set_aimnologgedin(&g);
271  owl_global_set_no_doaimevents(&g);
272}
273
274int owl_aim_send_im(char *to, char *msg)
275{
276  int ret;
277
278  ret=aim_im_sendch1(owl_global_get_aimsess(&g), to, NULL, msg);
279   
280  /* I don't know how to check for an error yet */
281  return(ret);
282}
283
284int owl_aim_send_awaymsg(char *to, char *msg)
285{
286  int ret;
287
288  ret=aim_im_sendch1(owl_global_get_aimsess(&g), to, AIM_IMFLAGS_AWAY, msg);
289
290  /* I don't know how to check for an error yet */
291  return(ret);
292}
293
294void owl_aim_addbuddy(char *name)
295{
296
297  aim_ssi_addbuddy(owl_global_get_aimsess(&g), name, "Buddies", NULL, NULL, NULL, 0);
298
299  /*
300  aim_ssi_addbuddy(owl_global_get_aimsess(&g),
301                   name,
302                   "Buddies",
303                   NULL, NULL, NULL,
304                   aim_ssi_waitingforauth(owl_global_get_aimsess(&g)->ssi.local, "Buddies", name));
305  */
306}
307
308void owl_aim_delbuddy(char *name)
309{
310  aim_ssi_delbuddy(owl_global_get_aimsess(&g), name, "Buddies");
311  owl_buddylist_offgoing(owl_global_get_buddylist(&g), name);
312}
313
314void owl_aim_search(char *email)
315{
316  int ret;
317
318  owl_function_debugmsg("owl_aim_search: doing search for %s", email);
319  ret=aim_search_address(owl_global_get_aimsess(&g), 
320                         aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_BOS),
321                         email);
322
323  if (ret) owl_function_error("owl_aim_search: aim_search_address returned %i", ret);
324}
325
326
327int owl_aim_set_awaymsg(char *msg)
328{
329  int len;
330  char *foo;
331  /* there is a max away message lentgh we should check against */
332
333  foo=owl_strdup(msg);
334  len=strlen(foo);
335  if (len>500) {
336    foo[500]='\0';
337    len=499;
338  }
339   
340  aim_locate_setprofile(owl_global_get_aimsess(&g),
341                        NULL, NULL, 0,
342                        "us-ascii", foo, len);
343  owl_free(foo);
344
345  /*
346  aim_bos_setprofile(owl_global_get_aimsess(&g),
347                     owl_global_get_bosconn(&g),
348                     NULL, NULL, 0, "us-ascii", msg,
349                     strlen(msg), 0);
350  */
351  return(0);
352}
353
354void owl_aim_chat_join(char *name, int exchange)
355{
356  int ret;
357  aim_conn_t *cur;
358  /*
359  OscarData *od = (OscarData *)g->proto_data;
360  char *name, *exchange;
361  */
362
363  owl_function_debugmsg("Attempting to join chatroom %s exchange %i", name, exchange);
364
365  /*
366  name = g_hash_table_lookup(data, "room");
367  exchange = g_hash_table_lookup(data, "exchange");
368  */
369  if ((cur = aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV))) {
370    owl_function_debugmsg("owl_aim_chat_join: chatnav exists, creating room");
371    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
372  } else {
373    /*    struct create_room *cr = g_new0(struct create_room, 1); */
374    owl_function_debugmsg("owl_aim_chat_join: chatnav does not exist, opening chatnav");
375    /*
376    cr->exchange = atoi(exchange);
377    cr->name = g_strdup(name);
378    od->create_rooms = g_slist_append(od->create_rooms, cr);
379    */
380    aim_reqservice(owl_global_get_aimsess(&g),
381                   aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV),
382                   AIM_CONN_TYPE_CHATNAV);
383    aim_reqservice(owl_global_get_aimsess(&g), NULL, AIM_CONN_TYPE_CHATNAV);
384    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
385    ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
386
387  }
388  return;
389  /******/
390
391
392  /* ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, chatroom, 0x0000); */
393  /*
394  ret=aim_chat_join(owl_global_get_aimsess(&g),
395                    aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), exchange, chatroom, 0x0000);
396  */
397
398  aim_reqservice(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), AIM_CONN_TYPE_CHATNAV);
399  ret = aim_chatnav_createroom(owl_global_get_aimsess(&g),
400                               aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), name, exchange);
401   ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
402 
403}
404
405void owl_aim_chat_leave(char *chatroom)
406{
407}
408
409int owl_aim_chat_sendmsg(char *chatroom, char *msg)
410{
411  return(0);
412}
413
414/* caller must free the return */
415char *owl_aim_normalize_screenname(char *in)
416{
417  char *out;
418  int i, j, k;
419
420  j=strlen(in);
421  out=owl_malloc(j+30);
422  k=0;
423  for (i=0; i<j; i++) {
424    if (in[i]!=' ') {
425      out[k]=in[i];
426      k++;
427    }
428  }
429  out[k]='\0';
430  return(out);
431}
432
433int owl_aim_process_events()
434{
435  aim_session_t *aimsess;
436  aim_conn_t *waitingconn = NULL;
437  struct timeval tv;
438  int selstat = 0;
439  struct owlfaim_priv *priv;
440
441  aimsess=owl_global_get_aimsess(&g);
442  priv = (struct owlfaim_priv *) &(aimsess->aux_data);
443
444  /* do a select without blocking */
445  tv.tv_sec = 0;
446  tv.tv_usec = 0;
447  waitingconn = aim_select(aimsess, &tv, &selstat);
448
449  if (owl_global_is_aimnop_time(&g)) {
450    aim_flap_nop(aimsess, aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS));
451    owl_global_aimnop_sent(&g);
452  }
453
454  if (selstat == -1) {
455    owl_aim_logged_out();
456  } else if (selstat == 0) { 
457    /* no events pending */
458  } else if (selstat == 1) { /* outgoing data pending */
459    aim_tx_flushqueue(aimsess);
460  } else if (selstat == 2) { /* incoming data pending */
461    /* printf("selstat == 2\n"); */
462   
463    if (aim_get_command(aimsess, waitingconn) >= 0) {
464      aim_rxdispatch(aimsess);
465    } else {
466      /* printf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype); */
467      /* we should have callbacks for all these, else the library will do the conn_kill for us. */
468      if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
469        if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
470          /* printf("disconnected from %s\n", aim_directim_getsn(waitingconn)); */
471          aim_conn_kill(aimsess, &waitingconn);
472          owl_aim_logged_out();
473        }
474      } else {
475        aim_conn_kill(aimsess, &waitingconn);
476        owl_aim_logged_out();
477      }
478      if (!aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS)) {
479        /* printf("major connection error\n"); */
480        owl_aim_logged_out();
481        /* break; */
482      }
483    }
484  }
485  /* free(priv->buddyicon); */
486  /* exit(0); */
487  return(0);
488}
489
490static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
491{
492  return;
493}
494
495static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...)
496{
497  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
498  struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
499   
500  char *key;
501  va_list ap;
502
503  va_start(ap, fr);
504  key = va_arg(ap, char *);
505  va_end(ap);
506
507  owl_function_debugmsg("faimtest_parse_login: %s %s %s", priv->screenname, priv->password, key);
508
509  aim_send_login(sess, fr->conn, priv->screenname, priv->password, &info, key);
510 
511  return(1);
512}
513
514
515static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...)
516{
517  va_list ap;
518  struct aim_authresp_info *info;
519  aim_conn_t *bosconn;
520
521  va_start(ap, fr);
522  info = va_arg(ap, struct aim_authresp_info *);
523  va_end(ap);
524
525  /* printf("Screen name: %s\n", info->sn); */
526  owl_function_debugmsg("doing faimtest_parse_authresp");
527  owl_function_debugmsg("faimtest_parse_authresp: %s", info->sn);
528
529  /*
530   * Check for error.
531   */
532  if (info->errorcode || !info->bosip || !info->cookie) {
533    /*
534    printf("Login Error Code 0x%04x\n", info->errorcode);
535    printf("Error URL: %s\n", info->errorurl);
536    */
537    if (info->errorcode==0x05) {
538      owl_aim_login_error("Incorrect nickname or password.");
539    } else if (info->errorcode==0x11) {
540      owl_aim_login_error("Your account is currently suspended.");
541    } else if (info->errorcode==0x14) {
542      owl_aim_login_error("The AOL Instant Messenger service is temporarily unavailable.");
543    } else if (info->errorcode==0x18) {
544      owl_aim_login_error("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.");
545    } else if (info->errorcode==0x1c) {
546      owl_aim_login_error("The client version you are using is too old.");
547    } else {
548      owl_aim_login_error(NULL);
549    }
550    aim_conn_kill(sess, &fr->conn);
551    return(1);
552  }
553
554  /*
555  printf("Reg status: %d\n", info->regstatus);
556  printf("Email: %s\n", info->email);
557  printf("BOS IP: %s\n", info->bosip);
558  */
559
560  /* printf("Closing auth connection...\n"); */
561  aim_conn_kill(sess, &fr->conn);
562  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, info->bosip))) {
563    /* printf("could not connect to BOS: internal error\n"); */
564    return(1);
565  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
566    /* printf("could not connect to BOS\n"); */
567    aim_conn_kill(sess, &bosconn);
568    return(1);
569  }
570  owl_global_set_bossconn(&g, bosconn);
571  owl_aim_successful_login(info->sn);
572  addcb_bos(sess, bosconn);
573  aim_sendcookie(sess, bosconn, info->cookielen, info->cookie);
574  return(1);
575}
576
577int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...)
578{
579  owl_function_debugmsg("doing faimtest_flapversion");
580
581#if 0
582  /* XXX fix libfaim to support this */
583  printf("using FLAP version 0x%08x\n", /* aimutil_get32(fr->data)*/ 0xffffffff);
584
585  /*
586   * This is an alternate location for starting the login process.
587   */
588  /* XXX should do more checking to make sure its really the right AUTH conn */
589  if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
590    /* do NOT send a flapversion, request_login will send it if needed */
591    aim_request_login(sess, fr->conn, priv->screenname);
592    /* printf("faimtest: login request sent\n"); */
593  }
594#endif
595
596  return 1;
597}
598
599
600int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
601{
602  owl_function_debugmsg("doing faimtest_conncomplete");
603  /* owl_aim_successful_login(info->sn); */
604  return 1;
605}
606
607void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
608{
609  owl_function_debugmsg("doing addcb_bos");
610  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
611  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0);
612
613  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0003,                        ssirights, 0);
614  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0006,                        ssidata, 0);
615  aim_conn_addhandler(sess, bosconn, 0x0013,         0x000f,                        ssidatanochange, 0);
616  aim_conn_addhandler(sess, bosconn, 0x0008,         0x0002,                        handlepopup, 0);
617  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0003,                        faimtest_bosrights, 0);
618  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT,           faimtest_handleredirect, 0);
619  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL,  faimtest_reportinterval, 0);
620  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO,         faimtest_parse_buddyrights, 0);
621  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD,               faimtest_parse_motd, 0);
622  aim_conn_addhandler(sess, bosconn, 0x0004,         0x0005,                        faimtest_icbmparaminfo, 0);
623  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,    faimtest_parse_connerr, 0);
624  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO,         faimtest_locrights, 0);
625  aim_conn_addhandler(sess, bosconn, 0x0001,         0x001f,                        faimtest_memrequest, 0);
626  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING,           faimtest_parse_oncoming, 0);
627  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING,           faimtest_parse_offgoing, 0);
628  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING,           faimtest_parse_incoming_im, 0);
629  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR,              faimtest_parse_locerr, 0);
630  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL,         faimtest_parse_misses, 0);
631  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE,         faimtest_parse_ratechange, 0);
632  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL,               faimtest_parse_evilnotify, 0);
633
634  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0001,                        faimtest_parse_searcherror, 0);
635  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0003,                        faimtest_parse_searchreply, 0);
636
637  /*
638  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, faimtest_parse_searcherror, 0);
639  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, faimtest_parse_searchreply, 0);
640  */
641 
642  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR,              faimtest_parse_msgerr, 0);
643  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO,           faimtest_parse_userinfo, 0);
644  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK,                faimtest_parse_msgack, 0);
645
646  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0001,                        faimtest_parse_genericerr, 0);
647  aim_conn_addhandler(sess, bosconn, 0x0003,         0x0001,                        faimtest_parse_genericerr, 0);
648  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0001,                        faimtest_parse_genericerr, 0);
649  aim_conn_addhandler(sess, bosconn, 0x0001,         0x000b,                        serverpause, 0);
650  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0012,                        migrate, 0);
651  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG,         offlinemsg, 0);
652  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE, offlinemsgdone, 0);
653
654  /*
655  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,     gaim_connerr, 0);
656  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0);
657  */
658
659  /*
660  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ERROR,              faimtest_ssi_parseerr, 0);
661  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RIGHTSINFO,         faimtest_ssi_parserights, 0);
662  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_LIST,               faimtest_ssi_parselist, 0);
663  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_NOLIST,             faimtest_ssi_parselist, 0);
664  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_SRVACK,             faimtest_ssi_parseack, 0);
665  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTH,           faimtest_ssi_authgiven, 0);
666  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREQ,        faimtest_ssi_authrequest, 0);
667  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREP,        faimtest_ssi_authreply, 0);
668  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ADDED,              faimtest_ssi_gotadded, 0);
669  */
670
671  return;
672}
673
674static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...)
675{
676  owl_function_debugmsg("doing coninitdone_bos");
677
678
679  aim_reqpersonalinfo(sess, fr->conn);
680  aim_ssi_reqrights(sess);
681  aim_ssi_reqdata(sess);
682  aim_locate_reqrights(sess);
683  aim_buddylist_reqrights(sess, fr->conn);
684
685  aim_im_reqparams(sess);
686  /* aim_bos_reqrights(sess, fr->conn); */ /* XXX - Don't call this with ssi */
687
688  owl_function_debugmsg("conninitdone_bos: requesting rights");
689  aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */
690  aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
691  aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
692
693  return(1);
694}
695
696static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...)
697{
698  aim_clientready(sess, fr->conn);
699  owl_function_debugmsg("conninitdone_admin: initializtion done for admin connection");
700  return(1);
701}
702
703int logout(aim_session_t *sess)
704{
705  aim_session_kill(sess);
706  owl_aim_init();
707
708  owl_function_debugmsg("libfaim logout called");
709  /*
710  if (faimtest_init() == -1)
711    printf("faimtest_init failed\n");
712  */
713
714  return(0);
715}
716
717/**************************************************************************************************/
718
719static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
720{
721  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
722  va_list ap;
723  fu16_t code;
724  char *msg;
725 
726  va_start(ap, fr);
727  code = va_arg(ap, int);
728  msg = va_arg(ap, char *);
729  va_end(ap);
730 
731  owl_function_error("faimtest_parse_connerr: Code 0x%04x: %s\n", code, msg);
732  aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
733 
734  priv->connected = 0;
735 
736  return 1;
737}
738
739static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...)
740{
741  int status;
742  va_list ap;
743 
744  va_start(ap, fr);
745  status = va_arg(ap, int); /* status code of confirmation request */
746  va_end(ap);
747
748  /* owl_function_debugmsg("faimtest_accountconfirm: Code 0x%04x: %s\n", code, msg); */
749  owl_function_debugmsg("faimtest_accountconfirm: account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
750 
751  return 1;
752}
753
754static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
755{
756  fu16_t change = 0, perms, type;
757  int length, str;
758  char *val;
759  va_list ap;
760 
761  va_start(ap, fr);
762  change = va_arg(ap, int);
763  perms = (fu16_t)va_arg(ap, unsigned int);
764  type = (fu16_t)va_arg(ap, unsigned int);
765  length = va_arg(ap, int);
766  val = va_arg(ap, char *);
767  str = va_arg(ap, int);
768  va_end(ap);
769 
770  owl_function_debugmsg("faimtest_infochange: info%s: perms = %d, type = %x, length = %d, val = %s", change?" change":"", perms, type, length, str?val:"(not string)");
771 
772  return(1);
773}
774
775
776static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...)
777{
778  va_list ap;
779  struct aim_redirect_data *redir;
780
781  owl_function_debugmsg("faimtest_handledirect:");
782 
783  va_start(ap, fr);
784  redir = va_arg(ap, struct aim_redirect_data *);
785 
786  if (redir->group == 0x0005) {  /* Adverts */
787   
788  } else if (redir->group == 0x0007) {  /* Authorizer */
789    aim_conn_t *tstconn;
790
791    owl_function_debugmsg("faimtest_handledirect: autorizer");
792   
793    tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, redir->ip);
794    if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
795      owl_function_error("faimtest_handleredirect: unable to reconnect with authorizer");
796    } else {
797      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
798      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
799      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0);
800      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
801      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
802      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
803      /* Send the cookie to the Auth */
804      aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
805      owl_function_debugmsg("faimtest_handleredirect: sent cookie to authorizer host");
806    }
807  } else if (redir->group == 0x000d) {  /* ChatNav */
808    owl_function_debugmsg("faimtest_handledirect: chatnav");
809    chatnav_redirect(sess, redir);
810  } else if (redir->group == 0x000e) { /* Chat */
811    owl_function_debugmsg("faimtest_handledirect: chat");
812    chat_redirect(sess, redir);
813  } else {
814    owl_function_debugmsg("faimtest_handleredirect: uh oh... got redirect for unknown service 0x%04x!!", redir->group);
815  }
816  va_end(ap);
817  return 1;
818}
819
820static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
821{
822  struct aim_icbmparameters *params;
823  va_list ap;
824 
825  va_start(ap, fr);
826  params = va_arg(ap, struct aim_icbmparameters *);
827  va_end(ap);
828 
829  owl_function_debugmsg("faimtest_icbmparaminfo: ICBM Parameters: maxchannel = %d, default flags = 0x%08lx, max msg len = %d, max sender evil = %f, max reciever evil = %f, min msg interval = %ld",
830                       params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, params->minmsginterval);
831     
832  /*
833  * Set these to your taste, or client medium.  Setting minmsginterval
834  * higher is good for keeping yourself from getting flooded (esp
835  * if you're on a slow connection or something where that would be
836  * useful).
837  */
838  params->maxmsglen = 8000;
839  params->minmsginterval = 0; /* in milliseconds */
840  /* aim_seticbmparam(sess, params); */
841  aim_im_setparams(sess, params);
842 
843  return 1;
844}
845
846static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
847{
848  va_list ap;
849  fu16_t maxbuddies, maxwatchers;
850 
851  va_start(ap, fr);
852  maxbuddies = va_arg(ap, int);
853  maxwatchers = va_arg(ap, int);
854  va_end(ap);
855 
856  owl_function_debugmsg("faimtest_parse_buddyrights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
857 
858  /* aim_ssi_reqrights(sess, fr->conn); */
859  aim_ssi_reqrights(sess);
860 
861  return 1;
862}
863
864static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
865{
866  va_list ap;
867  fu16_t maxpermits, maxdenies;
868 
869  va_start(ap, fr);
870  maxpermits = va_arg(ap, int);
871  maxdenies = va_arg(ap, int);
872  va_end(ap);
873 
874  owl_function_debugmsg("faimtest_bosrights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
875  aim_clientready(sess, fr->conn);
876  owl_function_debugmsg("officially connected to BOS.");
877  aim_icq_reqofflinemsgs(sess);
878  return 1;
879}
880
881static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
882{
883  va_list ap;
884  fu16_t maxsiglen;
885 
886  va_start(ap, fr);
887  maxsiglen = va_arg(ap, int);
888  va_end(ap);
889
890  owl_function_debugmsg("faimtest_locrights: rights: max signature length = %d\n", maxsiglen);
891 
892  return(1);
893}
894
895static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
896{
897  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
898  va_list ap;
899  fu16_t interval;
900
901  va_start(ap, fr);
902  interval = va_arg(ap, int);
903  va_end(ap);
904
905  owl_function_debugmsg("faimtest_reportinterval: %d (seconds?)\n", interval);
906
907  if (!priv->connected) {
908    priv->connected++;
909  }
910  /* aim_reqicbmparams(sess); */
911  aim_im_reqparams(sess);
912  /* kretch */
913  return 1;
914}
915
916static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
917{
918  char *msg;
919  fu16_t id;
920  va_list ap;
921  static int codeslen = 5;
922  static char *codes[] = {
923    "Unknown",
924    "Mandatory upgrade",
925    "Advisory upgrade",
926    "System bulletin",
927    "Top o' the world!"
928  };
929
930  va_start(ap, fr);
931  id = va_arg(ap, int);
932  msg = va_arg(ap, char *);
933  va_end(ap);
934
935  owl_function_debugmsg("faimtest_parse_motd: %s (%d / %s)\n", msg?msg:"nomsg", id, (id < codeslen)?codes[id]:"unknown");
936 
937  return 1;
938}
939
940/*
941 * This is a little more complicated than it looks.  The module
942 * name (proto, boscore, etc) may or may not be given.  If it is
943 * not given, then use aim.exe.  If it is given, put ".ocm" on the
944 * end of it.
945 *
946 * Now, if the offset or length requested would cause a read past
947 * the end of the file, then the request is considered invalid.  Invalid
948 * requests are processed specially.  The value hashed is the
949 * the request, put into little-endian (eight bytes: offset followed
950 * by length). 
951 *
952 * Additionally, if the request is valid, the length is mod 4096.  It is
953 * important that the length is checked for validity first before doing
954 * the mod.
955 *
956 * Note to Bosco's Brigade: if you'd like to break this, put the
957 * module name on an invalid request.
958 *
959 */
960static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
961{
962  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
963  FILE *f;
964  static const char defaultmod[] = "aim.exe";
965  char *filename = NULL;
966  struct stat st;
967  unsigned char *buf;
968  int invalid = 0;
969 
970  if (!bufret || !buflenret)
971    return -1;
972 
973  if (modname) {
974    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
975      /* perror("memrequest: malloc"); */
976      return -1;
977    }
978    sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
979  } else {
980    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
981      /* perror("memrequest: malloc"); */
982      return -1;
983    }
984    sprintf(filename, "%s/%s", priv->aimbinarypath, defaultmod);
985  }
986 
987  if (stat(filename, &st) == -1) {
988    if (!modname) {
989      /* perror("memrequest: stat"); */
990      owl_free(filename);
991      return -1;
992    }
993    invalid = 1;
994  }
995 
996  if (!invalid) {
997    if ((offset > st.st_size) || (len > st.st_size))
998      invalid = 1;
999    else if ((st.st_size - offset) < len)
1000      len = st.st_size - offset;
1001    else if ((st.st_size - len) < len)
1002      len = st.st_size - len;
1003  }
1004 
1005  if (!invalid && len) {
1006    len %= 4096;
1007  }
1008 
1009  if (invalid) {
1010    int i;
1011   
1012    owl_free(filename); /* not needed */
1013    owl_function_error("getaimdata memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
1014    i = 8;
1015    if (modname) {
1016      i+=strlen(modname);
1017    }
1018   
1019    if (!(buf = owl_malloc(i))) {
1020      return -1;
1021    }
1022   
1023    i=0;
1024   
1025    if (modname) {
1026      memcpy(buf, modname, strlen(modname));
1027      i+=strlen(modname);
1028    }
1029   
1030    /* Damn endianness. This must be little (LSB first) endian. */
1031    buf[i++] = offset & 0xff;
1032    buf[i++] = (offset >> 8) & 0xff;
1033    buf[i++] = (offset >> 16) & 0xff;
1034    buf[i++] = (offset >> 24) & 0xff;
1035    buf[i++] = len & 0xff;
1036    buf[i++] = (len >> 8) & 0xff;
1037    buf[i++] = (len >> 16) & 0xff;
1038    buf[i++] = (len >> 24) & 0xff;
1039   
1040    *bufret = buf;
1041    *buflenret = i;
1042  } else {
1043    if (!(buf = owl_malloc(len))) {
1044      owl_free(filename);
1045      return -1;
1046    }
1047    /* printf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename); */
1048    if (!(f = fopen(filename, "r"))) {
1049      /* perror("memrequest: fopen"); */
1050      owl_free(filename);
1051      owl_free(buf);
1052      return -1;
1053    }
1054   
1055    owl_free(filename);
1056   
1057    if (fseek(f, offset, SEEK_SET) == -1) {
1058      /* perror("memrequest: fseek"); */
1059      fclose(f);
1060      owl_free(buf);
1061      return -1;
1062    }
1063   
1064    if (fread(buf, len, 1, f) != 1) {
1065      /* perror("memrequest: fread"); */
1066      fclose(f);
1067      owl_free(buf);
1068      return -1;
1069    }
1070   
1071    fclose(f);
1072    *bufret = buf;
1073    *buflenret = len;
1074  }
1075  return 0; /* success! */
1076}
1077
1078/*
1079 * This will get an offset and a length.  The client should read this
1080 * data out of whatever AIM.EXE binary the user has provided (hopefully
1081 * it matches the client information thats sent at login) and pass a
1082 * buffer back to libfaim so it can hash the data and send it to AOL for
1083 * inspection by the client police.
1084 */
1085static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...)
1086{
1087  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
1088  va_list ap;
1089  fu32_t offset, len;
1090  char *modname;
1091  unsigned char *buf;
1092  int buflen;
1093 
1094  va_start(ap, fr);
1095  offset = va_arg(ap, fu32_t);
1096  len = va_arg(ap, fu32_t);
1097  modname = va_arg(ap, char *);
1098  va_end(ap);
1099 
1100  if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
1101    aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
1102    owl_free(buf);
1103  } else {
1104    owl_function_debugmsg("faimtest_memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname);
1105    aim_sendmemblock(sess, fr->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
1106  }
1107  return 1;
1108}
1109
1110/*
1111static void printuserflags(fu16_t flags)
1112{
1113  if (flags & AIM_FLAG_UNCONFIRMED) printf("UNCONFIRMED ");
1114  if (flags & AIM_FLAG_ADMINISTRATOR) printf("ADMINISTRATOR ");
1115  if (flags & AIM_FLAG_AOL) printf("AOL ");
1116  if (flags & AIM_FLAG_OSCAR_PAY) printf("OSCAR_PAY ");
1117  if (flags & AIM_FLAG_FREE) printf("FREE ");
1118  if (flags & AIM_FLAG_AWAY) printf("AWAY ");
1119  if (flags & AIM_FLAG_ICQ) printf("ICQ ");
1120  if (flags & AIM_FLAG_WIRELESS) printf("WIRELESS ");
1121  if (flags & AIM_FLAG_ACTIVEBUDDY) printf("ACTIVEBUDDY ");
1122 
1123  return;
1124}
1125*/
1126
1127static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...)
1128{
1129  aim_userinfo_t *userinfo;
1130  char *prof_encoding = NULL;
1131  char *prof = NULL;
1132  fu16_t inforeq = 0;
1133  owl_buddy *b;
1134  va_list ap;
1135  va_start(ap, fr);
1136  userinfo = va_arg(ap, aim_userinfo_t *);
1137  inforeq = (fu16_t)va_arg(ap, unsigned int);
1138  prof_encoding = va_arg(ap, char *);
1139  prof = va_arg(ap, char *);
1140  va_end(ap);
1141
1142  /* right now the only reason we call this is for idle times */
1143  owl_function_debugmsg("parse_userinfo sn: %s idle: %i", userinfo->sn, userinfo->idletime);
1144  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g),
1145                                userinfo->sn);
1146  if (!b) return(1);
1147  owl_buddy_set_idle_since(b, userinfo->idletime);
1148  return(1);
1149
1150  /*
1151  printf("userinfo: sn: %s\n", userinfo->sn);
1152  printf("userinfo: warnlevel: %f\n", aim_userinfo_warnlevel(userinfo));
1153  printf("userinfo: flags: 0x%04x = ", userinfo->flags);
1154  printuserflags(userinfo->flags);
1155  printf("\n");
1156  */
1157
1158  /*
1159  printf("userinfo: membersince: %lu\n", userinfo->membersince);
1160  printf("userinfo: onlinesince: %lu\n", userinfo->onlinesince);
1161  printf("userinfo: idletime: 0x%04x\n", userinfo->idletime);
1162  printf("userinfo: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
1163  */
1164
1165  /*
1166  if (inforeq == AIM_GETINFO_GENERALINFO) {
1167    owl_function_debugmsg("userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1168    owl_function_debugmsg("userinfo: prof: %s\n", prof ? prof : "[none]");
1169  } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
1170    owl_function_debugmsg("userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1171    owl_function_debugmsg("userinfo: awaymsg: %s\n", prof ? prof : "[none]");
1172  } else if (inforeq == AIM_GETINFO_CAPABILITIES) {
1173    owl_function_debugmsg("userinfo: capabilities: see above\n");
1174  } else {
1175    owl_function_debugmsg("userinfo: unknown info request\n");
1176  }
1177  */
1178  return(1);
1179}
1180
1181#if 0
1182static int faimtest_handlecmd(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, const char *tmpstr)
1183{
1184  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
1185 
1186  if (!strncmp(tmpstr, "disconnect", 10)) {
1187    logout(sess);
1188  } else if (strstr(tmpstr, "goodday")) {
1189    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK, "Good day to you too."); */
1190  } else if (strstr(tmpstr, "haveicon") && priv->buddyicon) {
1191    struct aim_sendimext_args args;
1192    /* static const char iconmsg[] = {"I have an icon"}; */
1193    static const char iconmsg[] = {""};
1194   
1195    args.destsn = userinfo->sn;
1196    args.flags = AIM_IMFLAGS_HASICON;
1197    args.msg = iconmsg;
1198    args.msglen = strlen(iconmsg);
1199    args.iconlen = priv->buddyiconlen;
1200    args.iconstamp = priv->buddyiconstamp;
1201    args.iconsum = priv->buddyiconsum;
1202   
1203    /* aim_send_im_ext(sess, &args); */
1204   
1205  } else if (strstr(tmpstr, "sendbin")) {
1206    struct aim_sendimext_args args;
1207    static const unsigned char data[] = {
1208      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1209      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1210      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1211      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1212      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1213      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1214    };
1215   
1216    /*
1217     * I put this here as a demonstration of how to send
1218     * arbitrary binary data via OSCAR ICBM's without the need
1219     * for escape or baseN encoding of any sort. 
1220     *
1221     * Apparently if you set the charset to something WinAIM
1222     * doesn't recognize, it will completly ignore the message.
1223     * That is, it will not display anything in the conversation
1224     * window for the user that recieved it.
1225     *
1226     * HOWEVER, if they do not have a conversation window open
1227     * for you, a new one will be created, but it will not have
1228     * any messages in it.  Therefore sending these things could
1229     * be a great way to seemingly subliminally convince people
1230     * to talk to you...
1231     *
1232     */
1233    args.destsn = userinfo->sn;
1234    /* args.flags = AIM_IMFLAGS_CUSTOMCHARSET; */
1235    args.charset = args.charsubset = 0x4242;
1236    args.msg = data;
1237    args.msglen = sizeof(data);
1238    /* aim_send_im_ext(sess, &args); */
1239   } else if (strstr(tmpstr, "sendmulti")) {
1240    struct aim_sendimext_args args;
1241    aim_mpmsg_t mpm;
1242    static const fu16_t unidata[] = { /* "UNICODE." */
1243      0x0055, 0x004e, 0x0049, 0x0043,
1244      0x004f, 0x0044, 0x0045, 0x002e,
1245    };
1246    static const int unidatalen = 8;
1247   
1248    /*
1249     * This is how multipart messages should be sent.
1250     *
1251     * This should render as:
1252     *        "Part 1, ASCII.  UNICODE.Part 3, ASCII.  "
1253     */
1254   
1255    aim_mpmsg_init(sess, &mpm);
1256    aim_mpmsg_addascii(sess, &mpm, "Part 1, ASCII.  ");
1257    aim_mpmsg_addunicode(sess, &mpm, unidata, unidatalen);
1258    aim_mpmsg_addascii(sess, &mpm, "Part 3, ASCII.  ");
1259   
1260    args.destsn = userinfo->sn;
1261    args.flags = AIM_IMFLAGS_MULTIPART;
1262    args.mpmsg = &mpm;
1263   
1264    /* aim_send_im_ext(sess, &args); */
1265   
1266    aim_mpmsg_free(sess, &mpm);
1267   
1268  } else if (strstr(tmpstr, "sendprebin")) {
1269    static const unsigned char data[] = {
1270      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1271      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1272      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1273      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1274      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1275      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
1276    };
1277    struct aim_sendimext_args args;
1278    aim_mpmsg_t mpm;
1279   
1280    /*
1281     * This demonstrates sending a human-readable preamble,
1282     * and then arbitrary binary data.
1283     *
1284     * This means that you can very inconspicuously send binary
1285     * attachments to other users.  In WinAIM, this appears as
1286     * though it only had the ASCII portion.
1287     *
1288     */
1289   
1290    aim_mpmsg_init(sess, &mpm);
1291    aim_mpmsg_addascii(sess, &mpm, "This message has binary data.");
1292    aim_mpmsg_addraw(sess, &mpm, 0x4242, 0x4242, data, sizeof(data));
1293   
1294    args.destsn = userinfo->sn;
1295    args.flags = AIM_IMFLAGS_MULTIPART;
1296    args.mpmsg = &mpm;
1297   
1298    /* aim_send_im_ext(sess, &args); */
1299    aim_mpmsg_free(sess, &mpm);
1300   
1301  } else if (strstr(tmpstr, "havefeat")) {
1302    struct aim_sendimext_args args;
1303    static const char featmsg[] = {"I have nifty features."};
1304    fu8_t features[] = {0x01, 0x01, 0x01, 0x02, 0x42, 0x43, 0x44, 0x45};
1305   
1306    args.destsn = userinfo->sn;
1307    args.flags = AIM_IMFLAGS_CUSTOMFEATURES;
1308    args.msg = featmsg;
1309    args.msglen = strlen(featmsg);
1310    args.features = features;
1311    args.featureslen = sizeof(features);
1312   
1313    /* aim_send_im_ext(sess, &args); */
1314  } else if (strstr(tmpstr, "sendicon") && priv->buddyicon) {
1315    /* aim_send_icon(sess, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum); */
1316  } else if (strstr(tmpstr, "warnme")) {
1317    /* printf("icbm: sending non-anon warning\n"); */
1318    /* aim_send_warning(sess, conn, userinfo->sn, 0); */
1319  } else if (strstr(tmpstr, "anonwarn")) {
1320    /* printf("icbm: sending anon warning\n"); */
1321    /* aim_send_warning(sess, conn, userinfo->sn, AIM_WARN_ANON); */
1322  } else if (strstr(tmpstr, "setdirectoryinfo")) {
1323    /* printf("icbm: sending backwards profile data\n"); */
1324    aim_setdirectoryinfo(sess, conn, "tsrif", "elddim", "tsal", "nediam", "emankcin", "teerts", "ytic", "etats", "piz", 0, 1);
1325  } else if (strstr(tmpstr, "setinterests")) {
1326    /* printf("icbm: setting fun interests\n"); */
1327    aim_setuserinterests(sess, conn, "interest1", "interest2", "interest3", "interest4", "interest5", 1);
1328  } else if (!strncmp(tmpstr, "open chatnav", 12)) {
1329    aim_reqservice(sess, conn, AIM_CONN_TYPE_CHATNAV);
1330  } else if (!strncmp(tmpstr, "create", 6)) {
1331    aim_chatnav_createroom(sess,aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV), (strlen(tmpstr) < 7)?"WorldDomination":tmpstr+7, 0x0004);
1332  } else if (!strncmp(tmpstr, "close chatnav", 13)) {
1333    aim_conn_t *chatnavconn;
1334    if ((chatnavconn = aim_getconn_type(sess, AIM_CONN_TYPE_CHATNAV)))
1335      aim_conn_kill(sess, &chatnavconn);
1336  } else if (!strncmp(tmpstr, "join", 4)) {
1337    aim_chat_join(sess, conn, 0x0004, "worlddomination", 0x0000);
1338  } else if (!strncmp(tmpstr, "leave", 5)) {
1339    aim_chat_leaveroom(sess, "worlddomination");
1340  } else if (!strncmp(tmpstr, "getinfo", 7)) {
1341    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_GENERALINFO);
1342    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_AWAYMESSAGE);
1343    aim_getinfo(sess, conn, "midendian", AIM_GETINFO_CAPABILITIES);
1344  } else if(strstr(tmpstr, "lookup")) {
1345    /* aim_usersearch_address(sess, conn, "mid@auk.cx"); */
1346  } else if (!strncmp(tmpstr, "reqsendmsg", 10)) {
1347    /* aim_send_im(sess, priv->ohcaptainmycaptain, 0, "sendmsg 7900"); */
1348  } else if (!strncmp(tmpstr, "reqadmin", 8)) {
1349    aim_reqservice(sess, conn, AIM_CONN_TYPE_AUTH);
1350  } else if (!strncmp(tmpstr, "changenick", 10)) {
1351    aim_admin_setnick(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "diputs8  1");
1352  } else if (!strncmp(tmpstr, "reqconfirm", 10)) {
1353    aim_admin_reqconfirm(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH));
1354  } else if (!strncmp(tmpstr, "reqemail", 8)) {
1355    aim_admin_getinfo(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), 0x0011);
1356  } else if (!strncmp(tmpstr, "changepass", 8)) {
1357    aim_admin_changepasswd(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWPASSWORD", "OLDPASSWORD");
1358  } else if (!strncmp(tmpstr, "setemail", 8)) {
1359    aim_admin_setemail(sess, aim_getconn_type(sess, AIM_CONN_TYPE_AUTH), "NEWEMAILADDRESS");
1360  } else if (!strncmp(tmpstr, "sendmsg", 7)) {
1361    int i;
1362   
1363    i = atoi(tmpstr+8);
1364    if (i < 10000) {
1365      char *newbuf;
1366      int z;
1367     
1368      newbuf = owl_malloc(i+1);
1369      for (z = 0; z < i; z++)
1370        newbuf[z] = (z % 10)+0x30;
1371      newbuf[i] = '\0';
1372      /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_ACK | AIM_IMFLAGS_AWAY, newbuf); */
1373      owl_free(newbuf);
1374    }
1375  } else if (strstr(tmpstr, "seticqstatus")) {
1376    aim_setextstatus(sess, AIM_ICQ_STATE_DND);
1377  } else if (strstr(tmpstr, "rtfmsg")) {
1378    static const char rtfmsg[] = {"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}{\\f1\\froman\\fprq2\\fcharset0 Georgia;}{\\f2\\fmodern\\fprq1\\fcharset0 MS Mincho;}{\\f3\\froman\\fprq2\\fcharset2 Symbol;}}\\viewkind4\\uc1\\pard\\f0\\fs20 Test\\f1 test\\f2\fs44 test\\f3\\fs20 test\\f0\\par}"};
1379    struct aim_sendrtfmsg_args rtfargs;
1380   
1381    memset(&rtfargs, 0, sizeof(rtfargs));
1382    rtfargs.destsn = userinfo->sn;
1383    rtfargs.fgcolor = 0xffffffff;
1384    rtfargs.bgcolor = 0x00000000;
1385    rtfargs.rtfmsg = rtfmsg;
1386    /* aim_send_rtfmsg(sess, &rtfargs); */
1387  } else {
1388    /* printf("unknown command.\n"); */
1389    aim_add_buddy(sess, conn, userinfo->sn);
1390  } 
1391 
1392  return 0;
1393}
1394#endif
1395
1396/*
1397 * Channel 1: Standard Message
1398 */
1399static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args)
1400{
1401  struct owlfaim_priv *priv = (struct owlfaim_priv *)sess->aux_data;
1402  owl_message *m;
1403  char *stripmsg, *nz_screenname, *wrapmsg;
1404  char realmsg[8192+1] = {""};
1405  /* int clienttype = AIM_CLIENTTYPE_UNKNOWN; */
1406
1407  /* clienttype = aim_fingerprintclient(args->features, args->featureslen); */
1408
1409  /*
1410  printf("icbm: sn = \"%s\"\n", userinfo->sn);
1411  printf("icbm: probable client type: %d\n", clienttype);
1412  printf("icbm: warnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
1413  printf("icbm: flags = 0x%04x = ", userinfo->flags);
1414  printuserflags(userinfo->flags);
1415  printf("\n");
1416  */
1417
1418  /*
1419  printf("icbm: membersince = %lu\n", userinfo->membersince);
1420  printf("icbm: onlinesince = %lu\n", userinfo->onlinesince);
1421  printf("icbm: idletime = 0x%04x\n", userinfo->idletime);
1422  printf("icbm: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
1423  */
1424
1425  /*
1426  printf("icbm: icbmflags = ");
1427  if (args->icbmflags & AIM_IMFLAGS_AWAY) printf("away ");
1428  if (args->icbmflags & AIM_IMFLAGS_ACK) printf("ackrequest ");
1429  if (args->icbmflags & AIM_IMFLAGS_OFFLINE) printf("offline ");
1430  if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) printf("buddyreq ");
1431  if (args->icbmflags & AIM_IMFLAGS_HASICON) printf("hasicon ");
1432  printf("\n");
1433  */
1434
1435  /*
1436  if (args->icbmflags & AIM_IMFLAGS_CUSTOMCHARSET) {
1437  printf("icbm: encoding flags = {%04x, %04x}\n", args->charset, args->charsubset);
1438  }
1439  */
1440 
1441  /*
1442   * Quickly convert it to eight bit format, replacing non-ASCII UNICODE
1443   * characters with their equivelent HTML entity.
1444   */
1445  if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1446    int i;
1447   
1448    for (i=0; i<args->msglen; i+=2) {
1449      fu16_t uni;
1450
1451      uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
1452      if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
1453        snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
1454      } else { /* something else, do UNICODE entity */
1455        snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
1456      }
1457    }
1458  } else {
1459    /*
1460     * For non-UNICODE encodings (ASCII and ISO 8859-1), there is
1461     * no need to do anything special here.  Most
1462     * terminals/whatever will be able to display such characters
1463     * unmodified.
1464     *
1465     * Beware that PC-ASCII 128 through 159 are _not_ actually
1466     * defined in ASCII or ISO 8859-1, and you should send them as
1467     * UNICODE.  WinAIM will send these characters in a UNICODE
1468     * message, so you need to do so as well.
1469     *
1470     * You may not think it necessary to handle UNICODE messages. 
1471     * You're probably wrong.  For one thing, Microsoft "Smart
1472     * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
1473     * but real UNICODE). If you don't parse UNICODE at all, your
1474     * users will get a blank message instead of the message
1475     * containing Smart Quotes.
1476     *
1477     */
1478    if (!args->msg) {
1479      if (args->mpmsg.parts->data) {
1480        strncpy(realmsg,args->mpmsg.parts->data, sizeof(realmsg));
1481      } else {
1482        strncpy(realmsg,"",1);
1483      }
1484    } else {
1485      strncpy(realmsg, args->msg, sizeof(realmsg));
1486    }
1487  }
1488
1489  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: message from: %s", userinfo->sn?userinfo->sn:"");
1490  /* create a message, and put it on the message queue */
1491  stripmsg=owl_text_htmlstrip(realmsg);
1492  wrapmsg=owl_text_wordwrap(stripmsg, 70);
1493  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1494  m=owl_malloc(sizeof(owl_message));
1495  owl_message_create_aim(m,
1496                         nz_screenname,
1497                         owl_global_get_aim_screenname(&g),
1498                         wrapmsg,
1499                         OWL_MESSAGE_DIRECTION_IN,
1500                         0);
1501  if (args->icbmflags & AIM_IMFLAGS_AWAY) owl_message_set_attribute(m, "isauto", "");
1502  owl_global_messagequeue_addmsg(&g, m);
1503  owl_free(stripmsg);
1504  owl_free(wrapmsg);
1505  owl_free(nz_screenname);
1506
1507  return(1);
1508
1509  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: message: %s\n", realmsg);
1510 
1511  if (args->icbmflags & AIM_IMFLAGS_MULTIPART) {
1512    aim_mpmsg_section_t *sec;
1513    int z;
1514
1515    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart: this message has %d parts\n", args->mpmsg.numparts);
1516   
1517    for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++) {
1518      if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff)) {
1519        owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart:   part %d: charset 0x%04x, subset 0x%04x, msg = %s\n", z, sec->charset, sec->charsubset, sec->data);
1520      } else {
1521        owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart:   part %d: charset 0x%04x, subset 0x%04x, binary or UNICODE data\n", z, sec->charset, sec->charsubset);
1522      }
1523    }
1524  }
1525 
1526  if (args->icbmflags & AIM_IMFLAGS_HASICON) {
1527    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon"); */
1528    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: their icon: iconstamp = %ld, iconlen = 0x%08lx, iconsum = 0x%04x\n", args->iconstamp, args->iconlen, args->iconsum);
1529  }
1530
1531  /*
1532  if (realmsg) {
1533    int i = 0;
1534    while (realmsg[i] == '<') {
1535      if (realmsg[i] == '<') {
1536        while (realmsg[i] != '>')
1537          i++;
1538        i++;
1539      }
1540    }
1541    tmpstr = realmsg+i;
1542    faimtest_handlecmd(sess, conn, userinfo, tmpstr);
1543  }
1544  */
1545 
1546  if (priv->buddyicon && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
1547    /* aim_send_icon(sess, userinfo->sn, priv->buddyicon, priv->buddyiconlen, priv->buddyiconstamp, priv->buddyiconsum); */
1548  }
1549 
1550  return(1);
1551}
1552
1553/*
1554 * Channel 2: Rendevous Request
1555 */
1556static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args)
1557{
1558  /*
1559  printf("rendezvous: source sn = %s\n", userinfo->sn);
1560  printf("rendezvous: \twarnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
1561  printf("rendezvous: \tclass = 0x%04x = ", userinfo->flags);
1562  printuserflags(userinfo->flags);
1563  printf("\n");
1564 
1565  printf("rendezvous: \tonlinesince = %lu\n", userinfo->onlinesince);
1566  printf("rendezvous: \tidletime = 0x%04x\n", userinfo->idletime);
1567 
1568  printf("rendezvous: message/description = %s\n", args->msg);
1569  printf("rendezvous: encoding = %s\n", args->encoding);
1570  printf("rendezvous: language = %s\n", args->language);
1571  */
1572 
1573  if (args->reqclass == AIM_CAPS_SENDFILE) {
1574    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: send file!");
1575  } else if (args->reqclass == AIM_CAPS_CHAT) {
1576    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: chat invite: %s, %i, %i", args->info.chat.roominfo.name, args->info.chat.roominfo.exchange, args->info.chat.roominfo.instance);
1577    /*
1578    printf("chat invitation: room name = %s\n", args->info.chat.roominfo.name);
1579    printf("chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
1580    printf("chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
1581    */
1582    /* Automatically join room... */
1583    /* printf("chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name); */
1584
1585    /* aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance); */
1586  } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
1587    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: Buddy Icon from %s, length = %lu\n",
1588                          userinfo->sn, args->info.icon.length);
1589  } else if (args->reqclass == AIM_CAPS_ICQRTF) {
1590    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: RTF message from %s: (fgcolor = 0x%08lx, bgcolor = 0x%08lx) %s\n",
1591                          userinfo->sn, args->info.rtfmsg.fgcolor, args->info.rtfmsg.bgcolor, args->info.rtfmsg.rtfmsg);
1592  } else {
1593    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: icbm: unknown reqclass (%d)\n", args->reqclass);
1594  }
1595  return 1;
1596}
1597
1598static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
1599{
1600  fu16_t channel;
1601  aim_userinfo_t *userinfo;
1602  va_list ap;
1603  int ret = 0;
1604 
1605  va_start(ap, fr);
1606  channel = (fu16_t)va_arg(ap, unsigned int);
1607  userinfo = va_arg(ap, aim_userinfo_t *);
1608 
1609  if (channel == 1) {
1610    struct aim_incomingim_ch1_args *args;
1611    args = va_arg(ap, struct aim_incomingim_ch1_args *);
1612    ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
1613  } else if (channel == 2) {
1614    struct aim_incomingim_ch2_args *args;
1615    args = va_arg(ap, struct aim_incomingim_ch2_args *);
1616    ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
1617  } else {
1618    owl_function_debugmsg("faimtest_parse_incoming_im: unsupported channel 0x%04x\n", channel);
1619  }
1620  va_end(ap);
1621  owl_function_debugmsg("faimtest_parse_incoming_im: done with ICBM handling (ret = %d)\n", ret);
1622  return 1;
1623}
1624
1625static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
1626{
1627  aim_userinfo_t *userinfo;
1628  char *nz_screenname;
1629  owl_buddy *b;
1630  owl_buddylist *bl;
1631  va_list ap;
1632  va_start(ap, fr);
1633  userinfo = va_arg(ap, aim_userinfo_t *);
1634  va_end(ap);
1635
1636  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1637  bl=owl_global_get_buddylist(&g);
1638 
1639  owl_buddylist_oncoming(owl_global_get_buddylist(&g), nz_screenname);
1640
1641  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1642    owl_function_debugmsg("faimtest_parseoncoming: in empty part of userinfo present and present idle");
1643  }
1644
1645  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g), nz_screenname);
1646  if (!b) {
1647    owl_function_debugmsg("Error: parse_oncoming setting idle time with no buddy present.");
1648    return(1);
1649  }
1650  if (userinfo->idletime==0) {
1651    owl_buddy_set_unidle(b);
1652  } else {
1653    owl_buddy_set_idle(b);
1654    owl_buddy_set_idle_since(b, userinfo->idletime);
1655  }
1656
1657  if (userinfo->flags & AIM_FLAG_AWAY) {
1658    owl_function_debugmsg("parse_oncoming sn: %s away flag!", userinfo->sn);
1659  }
1660 
1661  owl_function_debugmsg("parse_oncoming sn: %s idle: %i", userinfo->sn, userinfo->idletime);
1662   
1663  owl_free(nz_screenname);
1664 
1665  /*
1666    printf("%ld  %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1667    time(NULL),
1668    userinfo->sn, userinfo->flags,
1669    (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1670    (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1671    (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1672    (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1673    (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1674    (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1675    (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1676    (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1677    (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1678    userinfo->capabilities);
1679  */
1680  return(1);
1681}
1682
1683static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
1684{
1685  aim_userinfo_t *userinfo;
1686  char *nz_screenname;
1687  va_list ap;
1688 
1689  va_start(ap, fr);
1690  userinfo = va_arg(ap, aim_userinfo_t *);
1691  va_end(ap);
1692
1693  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1694  owl_buddylist_offgoing(owl_global_get_buddylist(&g), nz_screenname);
1695  owl_free(nz_screenname);
1696
1697  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1698    owl_function_debugmsg("parse_offgoing sn: %s idle time %i", userinfo->sn, userinfo->idletime);
1699  }
1700
1701  /*
1702  printf("%ld  %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1703         time(NULL),
1704         userinfo->sn, userinfo->flags,
1705         (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1706         (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1707         (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1708         (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1709         (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1710         (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1711         (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1712         (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1713         (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1714         userinfo->capabilities);
1715  */
1716 
1717  return 1;
1718}
1719
1720/* Used by chat as well. */
1721int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
1722{
1723  va_list ap;
1724  fu16_t reason;
1725 
1726  va_start(ap, fr);
1727  reason = (fu16_t)va_arg(ap, unsigned int);
1728  va_end(ap);
1729 
1730  /* printf("snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1731  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1732 
1733  return 1;
1734}
1735
1736static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
1737{
1738  va_list ap;
1739  char *destsn;
1740  fu16_t reason;
1741 
1742  va_start(ap, fr);
1743  reason = (fu16_t)va_arg(ap, unsigned int);
1744  destsn = va_arg(ap, char *);
1745  va_end(ap);
1746 
1747  /* printf("message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1748  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1749
1750  if (reason==4) {
1751    owl_function_adminmsg("", "Could not send AIM message, user not logged on");
1752  }
1753 
1754  return 1;
1755}
1756
1757static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
1758{
1759  va_list ap;
1760  char *destsn;
1761  fu16_t reason;
1762 
1763  va_start(ap, fr);
1764  reason = (fu16_t)va_arg(ap, unsigned int);
1765  destsn = va_arg(ap, char *);
1766  va_end(ap);
1767 
1768  /* printf("user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1769  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1770 
1771  return 1;
1772}
1773
1774static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
1775{
1776  static char *missedreasons[] = {
1777    "Invalid (0)",
1778    "Message too large",
1779    "Rate exceeded",
1780    "Evil Sender",
1781    "Evil Receiver"
1782  };
1783  static int missedreasonslen = 5;
1784 
1785  va_list ap;
1786  fu16_t chan, nummissed, reason;
1787  aim_userinfo_t *userinfo;
1788 
1789  va_start(ap, fr);
1790  chan = (fu16_t)va_arg(ap, unsigned int);
1791  userinfo = va_arg(ap, aim_userinfo_t *);
1792  nummissed = (fu16_t)va_arg(ap, unsigned int);
1793  reason = (fu16_t)va_arg(ap, unsigned int);
1794  va_end(ap);
1795 
1796  owl_function_debugmsg("faimtest_parse_misses: missed %d messages from %s on channel %d (reason %d: %s)\n", nummissed, userinfo->sn, chan, reason, (reason<missedreasonslen)?missedreasons[reason]:"unknown");
1797 
1798  return 1;
1799}
1800
1801/*
1802 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1803 */
1804static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
1805{
1806  va_list ap;
1807  fu16_t type;
1808  char *sn = NULL;
1809 
1810  va_start(ap, fr);
1811  type = (fu16_t)va_arg(ap, unsigned int);
1812  sn = va_arg(ap, char *);
1813  va_end(ap);
1814 
1815  owl_function_debugmsg("faimtest_parse_msgack: 0x%04x / %s\n", type, sn);
1816 
1817  return 1;
1818}
1819
1820static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
1821{
1822  static char *codes[5] = {
1823    "invalid",
1824    "change",
1825    "warning",
1826    "limit",
1827    "limit cleared"
1828  };
1829  va_list ap;
1830  fu16_t code, rateclass;
1831  fu32_t windowsize, clear, alert, limit, disconnect;
1832  fu32_t currentavg, maxavg;
1833 
1834  va_start(ap, fr); 
1835 
1836  /* See code explanations below */
1837  code = (fu16_t)va_arg(ap, unsigned int);
1838 
1839  /*
1840   * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1841   */
1842  rateclass = (fu16_t)va_arg(ap, unsigned int);
1843 
1844  /*
1845   * Not sure what this is exactly.  I think its the temporal
1846   * relation factor (ie, how to make the rest of the numbers
1847   * make sense in the real world).
1848   */
1849  windowsize = va_arg(ap, fu32_t);
1850 
1851  /* Explained below */
1852  clear = va_arg(ap, fu32_t);
1853  alert = va_arg(ap, fu32_t);
1854  limit = va_arg(ap, fu32_t);
1855  disconnect = va_arg(ap, fu32_t);
1856  currentavg = va_arg(ap, fu32_t);
1857  maxavg = va_arg(ap, fu32_t);
1858 
1859  va_end(ap);
1860 
1861  owl_function_debugmsg("faimtest_parse_ratechange: rate %s (rate class 0x%04x): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)",
1862                        (code < 5)?codes[code]:"invalid",
1863                        rateclass,
1864                        currentavg, maxavg,
1865                        alert, clear,
1866                        limit, disconnect,
1867                        windowsize);
1868  return 1;
1869}
1870
1871static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
1872{
1873  va_list ap;
1874  fu16_t newevil;
1875  aim_userinfo_t *userinfo;
1876 
1877  va_start(ap, fr);
1878  newevil = (fu16_t)va_arg(ap, unsigned int);
1879  userinfo = va_arg(ap, aim_userinfo_t *);
1880  va_end(ap);
1881 
1882  /*
1883   * Evil Notifications that are lacking userinfo->sn are anon-warns
1884   * if they are an evil increases, but are not warnings at all if its
1885   * a decrease (its the natural backoff happening).
1886   *
1887   * newevil is passed as an int representing the new evil value times
1888   * ten.
1889   */
1890  owl_function_debugmsg("faimtest_parse_evilnotify: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
1891 
1892  return 1;
1893}
1894
1895static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
1896{
1897  va_list ap;
1898  char *address, *SNs;
1899  int num, i;
1900  owl_list list;
1901 
1902  va_start(ap, fr);
1903  address = va_arg(ap, char *);
1904  num = va_arg(ap, int);
1905  SNs = va_arg(ap, char *);
1906  va_end(ap);
1907
1908  owl_list_create(&list);
1909 
1910  owl_function_debugmsg("faimtest_parse_searchreply: E-Mail Search Results for %s: ", address);
1911  for (i=0; i<num; i++) {
1912    owl_function_debugmsg("  %s", &SNs[i*(MAXSNLEN+1)]);
1913    owl_list_append_element(&list, &SNs[i*(MAXSNLEN+1)]);
1914  }
1915  owl_function_aimsearch_results(address, &list);
1916  owl_list_free_simple(&list);
1917  return(1);
1918}
1919
1920static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
1921{
1922  va_list ap;
1923  char *address;
1924 
1925  va_start(ap, fr);
1926  address = va_arg(ap, char *);
1927  va_end(ap);
1928
1929  owl_function_error("No results searching for %s", address);
1930  owl_function_debugmsg("faimtest_parse_searcherror: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
1931 
1932  return(1);
1933}
1934
1935static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...)
1936{
1937  va_list ap;
1938  char *msg, *url;
1939  fu16_t width, height, delay;
1940 
1941  va_start(ap, fr);
1942  msg = va_arg(ap, char *);
1943  url = va_arg(ap, char *);
1944  width = va_arg(ap, unsigned int);
1945  height = va_arg(ap, unsigned int);
1946  delay = va_arg(ap, unsigned int);
1947  va_end(ap);
1948 
1949  owl_function_debugmsg("handlepopup: (%dx%x:%d) %s (%s)\n", width, height, delay, msg, url);
1950 
1951  return 1;
1952}
1953
1954static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...)
1955{
1956  aim_sendpauseack(sess, fr->conn);
1957  return 1;
1958}
1959
1960static int migrate(aim_session_t *sess, aim_frame_t *fr, ...)
1961{
1962  va_list ap;
1963  aim_conn_t *bosconn;
1964  char *bosip;
1965  fu8_t *cookie;
1966 
1967  va_start(ap, fr);
1968  bosip = va_arg(ap, char *);
1969  cookie = va_arg(ap, fu8_t *);
1970  va_end(ap);
1971 
1972  owl_function_debugmsg("migrate: migration in progress -- new BOS is %s -- disconnecting", bosip);
1973  aim_conn_kill(sess, &fr->conn);
1974 
1975  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
1976    owl_function_debugmsg("migrate: could not connect to BOS: internal error");
1977    return 1;
1978  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {       
1979    owl_function_debugmsg("migrate: could not connect to BOS");
1980    aim_conn_kill(sess, &bosconn);
1981    return 1;
1982  }
1983 
1984  /* Login will happen all over again. */
1985  addcb_bos(sess, bosconn);
1986  /* aim_sendcookie(sess, bosconn, cookie); */ /********/
1987  return 1;
1988}
1989
1990static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...)
1991{
1992  owl_function_debugmsg("ssirights: got SSI rights, requesting data\n");
1993  /* aim_ssi_reqdata(sess, fr->conn, 0, 0x0000); */
1994  aim_ssi_reqdata(sess);
1995 
1996  return(1);
1997}
1998
1999static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...)
2000{
2001  va_list ap;
2002  fu8_t fmtver;
2003  fu16_t itemcount;
2004  fu32_t stamp;
2005  struct aim_ssi_item *list;
2006  /*
2007  struct aim_ssi_item *curitem;
2008  struct aim_ssi_item *l;
2009  */
2010 
2011  va_start(ap, fr);
2012  fmtver = va_arg(ap, unsigned int);
2013  itemcount = va_arg(ap, unsigned int);
2014  stamp = va_arg(ap, fu32_t);
2015  list = va_arg(ap, struct aim_ssi_item *);
2016  va_end(ap);
2017 
2018  owl_function_debugmsg("ssiddata: got SSI data (0x%02x, %d items, %ld)", fmtver, itemcount, stamp);
2019  /*
2020  for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
2021    for (l = list; l; l = l->next) {
2022      owl_function_debugmsg("\t0x%04x (%s) - 0x%04x/0x%04x", l->type, l->name, l->gid, l->bid);
2023    }
2024  }
2025  */
2026  aim_ssi_enable(sess);
2027 
2028  return 1;
2029}
2030
2031static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...)
2032{
2033  owl_function_debugmsg("ssidatanochange: server says we have the latest SSI data already");
2034  /* aim_ssi_enable(sess, fr->conn); */
2035  aim_ssi_enable(sess);
2036  return 1;
2037}
2038
2039static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...)
2040{
2041  va_list ap;
2042  struct aim_icq_offlinemsg *msg;
2043 
2044  va_start(ap, fr);
2045  msg = va_arg(ap, struct aim_icq_offlinemsg *);
2046  va_end(ap);
2047 
2048  if (msg->type == 0x0001) {
2049    owl_function_debugmsg("offlinemsg: from %ld at %d/%d/%d %02d:%02d : %s", msg->sender, msg->year, msg->month, msg->day, msg->hour, msg->minute, msg->msg);
2050  } else {
2051    owl_function_debugmsg("unknown offline message type 0x%04x", msg->type);
2052  }
2053  return 1;
2054}
2055
2056static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...)
2057{
2058  /* Tell the server to delete them. */
2059  owl_function_debugmsg("offlinemsg done: ");
2060  aim_icq_ackofflinemsgs(sess);
2061  return 1;
2062}
2063
2064
2065/******************** chat.c **************************/
2066
2067static int faimtest_chat_join(aim_session_t *sess, aim_frame_t *fr, ...)
2068{
2069  va_list ap;
2070  aim_userinfo_t *userinfo;
2071  int count;
2072  /* int i; */
2073 
2074  va_start(ap, fr);
2075  count = va_arg(ap, int);
2076  userinfo = va_arg(ap, aim_userinfo_t *);
2077  va_end(ap);
2078
2079  owl_function_debugmsg("In faimtest_chat_join");
2080  /*
2081  printf("chat: %s:  New occupants have joined:\n", aim_chat_getname(fr->conn));
2082  for (i = 0; i < count; i++)
2083    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
2084  */
2085  return 1;
2086}
2087
2088static int faimtest_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...)
2089{
2090  aim_userinfo_t *userinfo;
2091  va_list ap;
2092  int count;
2093  /* int i; */
2094
2095 
2096  va_start(ap, fr);
2097  count = va_arg(ap, int);
2098  userinfo = va_arg(ap, aim_userinfo_t *);
2099  va_end(ap);
2100 
2101  /*
2102    printf("chat: %s:  Some occupants have left:\n", aim_chat_getname(fr->conn));
2103   
2104    for (i = 0; i < count; i++)
2105    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
2106  */
2107  return 1;
2108}
2109
2110static int faimtest_chat_infoupdate(aim_session_t *sess, aim_frame_t *fr, ...)
2111{
2112  va_list ap;
2113  aim_userinfo_t *userinfo;
2114  struct aim_chat_roominfo *roominfo;
2115  char *roomname;
2116  int usercount;
2117  char *roomdesc;
2118  fu16_t flags, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
2119  fu32_t creationtime;
2120  const char *croomname;
2121  /* int i; */
2122 
2123  croomname = aim_chat_getname(fr->conn);
2124 
2125  va_start(ap, fr);
2126  roominfo = va_arg(ap, struct aim_chat_roominfo *);
2127  roomname = va_arg(ap, char *);
2128  usercount = va_arg(ap, int);
2129  userinfo = va_arg(ap, aim_userinfo_t *);
2130  roomdesc = va_arg(ap, char *);
2131  flags = (fu16_t)va_arg(ap, unsigned int);
2132  creationtime = va_arg(ap, fu32_t);
2133  maxmsglen = (fu16_t)va_arg(ap, unsigned int);
2134  unknown_d2 = (fu16_t)va_arg(ap, unsigned int);
2135  unknown_d5 = (fu16_t)va_arg(ap, unsigned int);
2136  maxvisiblemsglen = (fu16_t)va_arg(ap, unsigned int);
2137  va_end(ap);
2138
2139  owl_function_debugmsg("In faimtest_chat_infoupdate");
2140  /*
2141  printf("chat: %s:  info update:\n", croomname);
2142  printf("chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", croomname, roominfo->exchange, roominfo->name, roominfo->instance);
2143  printf("chat: %s:  \tRoomname: %s\n", croomname, roomname);
2144  printf("chat: %s:  \tRoomdesc: %s\n", croomname, roomdesc);
2145  printf("chat: %s:  \tOccupants: (%d)\n", croomname, usercount);
2146
2147  for (i = 0; i < usercount; i++)
2148    printf("chat: %s:  \t\t%s\n", croomname, userinfo[i].sn);
2149 
2150  owl_function_debugmsg("chat: %s:  \tRoom flags: 0x%04x (%s%s%s%s)\n",
2151         croomname, flags,
2152         (flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
2153         (flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
2154         (flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
2155         (flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
2156  printf("chat: %s:  \tCreation time: %lu (time_t)\n", croomname, creationtime);
2157  printf("chat: %s:  \tUnknown_d2: 0x%04x\n", croomname, unknown_d2);
2158  printf("chat: %s:  \tUnknown_d5: 0x%02x\n", croomname, unknown_d5);
2159  printf("chat: %s:  \tMax message length: %d bytes\n", croomname, maxmsglen);
2160  printf("chat: %s:  \tMax visible message length: %d bytes\n", croomname, maxvisiblemsglen);
2161  */
2162 
2163  return(1);
2164}
2165
2166static int faimtest_chat_incomingmsg(aim_session_t *sess, aim_frame_t *fr, ...)
2167{
2168  va_list ap;
2169  aim_userinfo_t *userinfo;
2170  char *msg;
2171  char tmpbuf[1152];
2172 
2173  va_start(ap, fr);
2174  userinfo = va_arg(ap, aim_userinfo_t *);     
2175  msg = va_arg(ap, char *);
2176  va_end(ap);
2177
2178  owl_function_debugmsg("in faimtest_chat_incomingmsg");
2179
2180  /*
2181  printf("chat: %s: incoming msg from %s: %s\n", aim_chat_getname(fr->conn), userinfo->sn, msg);
2182  */
2183 
2184  /*
2185   * Do an echo for testing purposes.  But not for ourselves ("oops!")
2186   */
2187  if (strcmp(userinfo->sn, sess->sn) != 0) {
2188    /* sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg); */
2189    aim_chat_send_im(sess, fr->conn, 0, tmpbuf, strlen(tmpbuf));
2190  }
2191 
2192  return 1;
2193}
2194
2195static int faimtest_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...)
2196{
2197  fu16_t type;
2198  va_list ap;
2199 
2200  va_start(ap, fr);
2201  type = (fu16_t)va_arg(ap, unsigned int);
2202
2203  owl_function_debugmsg("in faimtest_chatnav_info");
2204 
2205  if (type == 0x0002) {
2206    int maxrooms;
2207    struct aim_chat_exchangeinfo *exchanges;
2208    int exchangecount;
2209    /* int i; */
2210   
2211    maxrooms = va_arg(ap, int);
2212    exchangecount = va_arg(ap, int);
2213    exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
2214    va_end(ap);
2215
2216    /*
2217    printf("chat info: Chat Rights:\n");
2218    printf("chat info: \tMax Concurrent Rooms: %d\n", maxrooms);
2219    printf("chat info: \tExchange List: (%d total)\n", exchangecount);
2220    for (i = 0; i < exchangecount; i++) {
2221      printf("chat info: \t\t%x: %s (%s/%s) (0x%04x = %s%s%s%s)\n",
2222             exchanges[i].number,
2223             exchanges[i].name,
2224             exchanges[i].charset1,
2225             exchanges[i].lang1,
2226             exchanges[i].flags,
2227             (exchanges[i].flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
2228             (exchanges[i].flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
2229             (exchanges[i].flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
2230             (exchanges[i].flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
2231    }
2232    */
2233  } else if (type == 0x0008) {
2234    char *fqcn, *name, *ck;
2235    fu16_t instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
2236    fu8_t createperms;
2237    fu32_t createtime;
2238   
2239    fqcn = va_arg(ap, char *);
2240    instance = (fu16_t)va_arg(ap, unsigned int);
2241    exchange = (fu16_t)va_arg(ap, unsigned int);
2242    flags = (fu16_t)va_arg(ap, unsigned int);
2243    createtime = va_arg(ap, fu32_t);
2244    maxmsglen = (fu16_t)va_arg(ap, unsigned int);
2245    maxoccupancy = (fu16_t)va_arg(ap, unsigned int);
2246    createperms = (fu8_t)va_arg(ap, unsigned int);
2247    unknown = (fu16_t)va_arg(ap, unsigned int);
2248    name = va_arg(ap, char *);
2249    ck = va_arg(ap, char *);
2250    va_end(ap);
2251   
2252    /* printf("received room create reply for %s/0x%04x\n", fqcn, exchange); */
2253   
2254  } else {
2255    va_end(ap);
2256    /* printf("chatnav info: unknown type (%04x)\n", type); */
2257  }
2258 
2259  return 1;
2260}
2261
2262static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...)
2263{
2264  owl_function_debugmsg("faimtest_conninitdone_chat:");
2265
2266  aim_conn_addhandler(sess, fr->conn, 0x000e, 0x0001, faimtest_parse_genericerr, 0);
2267  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
2268  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
2269  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
2270  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
2271 
2272  aim_clientready(sess, fr->conn);
2273 
2274  owl_function_debugmsg("Chat ready");
2275
2276  /*
2277    chatcon = find_oscar_chat_by_conn(gc, fr->conn);
2278    chatcon->id = id;
2279    chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
2280  */
2281  return(1);
2282}
2283
2284static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...)
2285{
2286  owl_function_debugmsg("faimtest_conninitdone_chatnav:");
2287
2288  /* aim_conn_addhandler(sess, fr->conn, 0x000d, 0x0001, gaim_parse_genericerr, 0); */
2289  /* aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0); */
2290
2291  aim_clientready(sess, fr->conn);
2292
2293  aim_chatnav_reqrights(sess, fr->conn);
2294
2295  return(1);
2296}
2297
2298void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
2299{
2300  aim_conn_t *tstconn;
2301
2302  owl_function_debugmsg("in faimtest_chatnav_redirect");
2303 
2304  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, redir->ip);
2305  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
2306    /* printf("unable to connect to chat(nav) server\n"); */
2307    if (tstconn)
2308      aim_conn_kill(sess, &tstconn);
2309    return;
2310  }
2311 
2312  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
2313  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
2314  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
2315  /* printf("chatnav: connected\n"); */
2316  return;
2317}
2318
2319/* XXX this needs instance too */
2320void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
2321{
2322  aim_conn_t *tstconn;
2323
2324  owl_function_debugmsg("in chat_redirect");
2325 
2326  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, redir->ip);
2327  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
2328    /* printf("unable to connect to chat server\n"); */
2329    if (tstconn) aim_conn_kill(sess, &tstconn);
2330    return; 
2331  }             
2332  /* printf("chat: connected to %s instance %d on exchange %d\n", redir->chat.room, redir->chat.instance, redir->chat.exchange); */
2333 
2334  /*
2335   * We must do this to attach the stored name to the connection!
2336   */
2337  aim_chat_attachname(tstconn, redir->chat.exchange, redir->chat.room, redir->chat.instance);
2338  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
2339  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
2340  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
2341  return;       
2342}
2343
2344void owl_process_aim()
2345{
2346  if (owl_global_is_doaimevents(&g)) {
2347    owl_aim_process_events();
2348  }
2349}
2350
2351/**********************************************************************************/
2352
2353#if 0
2354static int faimtest_ssi_rerequestdata(aim_session_t *sess, aim_frame_t *fr, ...)
2355{
2356  aim_ssi_reqdata(sess);
2357  return(0);
2358}
2359
2360static int faimtest_ssi_parseerr(aim_session_t *sess, aim_frame_t *fr, ...)
2361{
2362  /* GaimConnection *gc = sess->aux_data; */
2363  /*    OscarData *od = gc->proto_data; */
2364  va_list ap;
2365  fu16_t reason;
2366
2367  va_start(ap, fr);
2368  reason = (fu16_t)va_arg(ap, unsigned int);
2369  va_end(ap);
2370
2371  owl_function_debugmsg("faimtest_ssi_parseerr: ssi: SNAC error %hu", reason);
2372
2373  if (reason == 0x0005) {
2374    owl_function_error("faimtest_ssi_parseerr: unable to retrieve buddy list");
2375  }
2376
2377  /* Activate SSI */
2378  /* Sending the enable causes other people to be able to see you, and you to see them */
2379  /* Make sure your privacy setting/invisibility is set how you want it before this! */
2380  owl_function_debugmsg("faimtest_ssi_parseerr: ssi: activating server-stored buddy list");
2381  aim_ssi_enable(sess);
2382 
2383  return(1);
2384}
2385
2386static int faimtest_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...)
2387{
2388  /* GaimConnection *gc = sess->aux_data; */
2389  /* OscarData *od = (OscarData *)gc->proto_data; */
2390  int numtypes, i;
2391  fu16_t *maxitems;
2392  va_list ap;
2393
2394  va_start(ap, fr);
2395  numtypes = va_arg(ap, int);
2396  maxitems = va_arg(ap, fu16_t *);
2397  va_end(ap);
2398
2399  owl_function_debugmsg("faimtest_ssi_parserights: ");
2400  for (i=0; i<numtypes; i++) {
2401    owl_function_debugmsg(" max type 0x%04x=%hd,", i, maxitems[i]);
2402  }
2403
2404  /*
2405  if (numtypes >= 0) od->rights.maxbuddies = maxitems[0];
2406  if (numtypes >= 1) od->rights.maxgroups = maxitems[1];
2407  if (numtypes >= 2) od->rights.maxpermits = maxitems[2];
2408  if (numtypes >= 3) od->rights.maxdenies = maxitems[3];
2409  */
2410 
2411  return(1);
2412}
2413
2414static int faimtest_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...)
2415{
2416  /* GaimConnection *gc = sess->aux_data; */
2417  /* GaimAccount *account = gaim_connection_get_account(gc); */
2418  /* OscarData *od = (OscarData *)gc->proto_data; */
2419  struct aim_ssi_item *curitem;
2420  int tmp;
2421  int export = FALSE;
2422  /* XXX - use these?
2423     va_list ap;
2424     
2425     va_start(ap, fr);
2426     fmtver = (fu16_t)va_arg(ap, int);
2427     numitems = (fu16_t)va_arg(ap, int);
2428     items = va_arg(ap, struct aim_ssi_item);
2429     timestamp = va_arg(ap, fu32_t);
2430     va_end(ap); */
2431 
2432  owl_function_debugmsg("faimtest_ssi_parselist: syncing local list and server list");
2433
2434  /* Clean the buddy list */
2435  aim_ssi_cleanlist(sess);
2436
2437  /* Add from server list to local list */
2438  for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
2439    if ((curitem->name == NULL) || (g_utf8_validate(curitem->name, -1, NULL)))
2440      switch (curitem->type) {
2441      case 0x0000: { /* Buddy */
2442        if (curitem->name) {
2443          char *gname = aim_ssi_itemlist_findparentname(sess->ssi.local, curitem->name);
2444          char *gname_utf8 = gname ? gaim_utf8_try_convert(gname) : NULL;
2445          char *alias = aim_ssi_getalias(sess->ssi.local, gname, curitem->name);
2446          char *alias_utf8 = alias ? gaim_utf8_try_convert(alias) : NULL;
2447          GaimBuddy *buddy = gaim_find_buddy(gc->account, curitem->name);
2448          /* Should gname be freed here? -- elb */
2449          /* Not with the current code, but that might be cleaner -- med */
2450          free(alias);
2451          if (buddy) {
2452            /* Get server stored alias */
2453            if (alias_utf8) {
2454              g_free(buddy->alias);
2455              buddy->alias = g_strdup(alias_utf8);
2456            }
2457          } else {
2458            GaimGroup *g;
2459            buddy = gaim_buddy_new(gc->account, curitem->name, alias_utf8);
2460           
2461            if (!(g = gaim_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
2462              g = gaim_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
2463              gaim_blist_add_group(g, NULL);
2464            }
2465           
2466            gaim_debug(GAIM_DEBUG_INFO, "oscar",
2467                       "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans"));
2468            gaim_blist_add_buddy(buddy, NULL, g, NULL);
2469            export = TRUE;
2470          }
2471          g_free(gname_utf8);
2472          g_free(alias_utf8);
2473        }
2474      } break;
2475     
2476      case 0x0001: { /* Group */
2477        /* Shouldn't add empty groups */
2478      } break;
2479     
2480      case 0x0002: { /* Permit buddy */
2481        if (curitem->name) {
2482          /* if (!find_permdeny_by_name(gc->permit, curitem->name)) { AAA */
2483          GSList *list;
2484          for (list=account->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
2485          if (!list) {
2486            gaim_debug(GAIM_DEBUG_INFO, "oscar",
2487                       "ssi: adding permit buddy %s to local list\n", curitem->name);
2488            gaim_privacy_permit_add(account, curitem->name, TRUE);
2489            export = TRUE;
2490          }
2491        }
2492      } break;
2493     
2494      case 0x0003: { /* Deny buddy */
2495        if (curitem->name) {
2496          GSList *list;
2497          for (list=account->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next);
2498          if (!list) {
2499            gaim_debug(GAIM_DEBUG_INFO, "oscar",
2500                       "ssi: adding deny buddy %s to local list\n", curitem->name);
2501            gaim_privacy_deny_add(account, curitem->name, TRUE);
2502            export = TRUE;
2503          }
2504        }
2505      } break;
2506     
2507      case 0x0004: { /* Permit/deny setting */
2508        if (curitem->data) {
2509          fu8_t permdeny;
2510          if ((permdeny = aim_ssi_getpermdeny(sess->ssi.local)) && (permdeny != account->perm_deny)) {
2511            gaim_debug(GAIM_DEBUG_INFO, "oscar",
2512                       "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, permdeny);
2513            account->perm_deny = permdeny;
2514            if (od->icq && account->perm_deny == 0x03) {
2515              serv_set_away(gc, "Invisible", "");
2516            }
2517            export = TRUE;
2518          }
2519        }
2520      } break;
2521     
2522      case 0x0005: { /* Presence setting */
2523        /* We don't want to change Gaim's setting because it applies to all accounts */
2524      } break;
2525      } /* End of switch on curitem->type */
2526  } /* End of for loop */
2527 
2528  /* If changes were made, then flush buddy list to file */
2529  if (export)
2530    gaim_blist_save();
2531 
2532  { /* Add from local list to server list */
2533    GaimBlistNode *gnode, *cnode, *bnode;
2534    GaimGroup *group;
2535    GaimBuddy *buddy;
2536    GaimBuddyList *blist;
2537    GSList *cur;
2538   
2539    /* Buddies */
2540    if ((blist = gaim_get_blist()))
2541      for (gnode = blist->root; gnode; gnode = gnode->next) {
2542        if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
2543          continue;
2544        group = (GaimGroup *)gnode;
2545        for (cnode = gnode->child; cnode; cnode = cnode->next) {
2546          if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
2547            continue;
2548          for (bnode = cnode->child; bnode; bnode = bnode->next) {
2549            if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
2550              continue;
2551            buddy = (GaimBuddy *)bnode;
2552            if (buddy->account == gc->account) {
2553              const char *servernick = gaim_buddy_get_setting(buddy, "servernick");
2554              if (servernick)
2555                serv_got_alias(gc, buddy->name, servernick);
2556             
2557              if (aim_ssi_itemlist_exists(sess->ssi.local, buddy->name)) {
2558                /* Store local alias on server */
2559                char *alias = aim_ssi_getalias(sess->ssi.local, group->name, buddy->name);
2560                if (!alias && buddy->alias && strlen(buddy->alias))
2561                  aim_ssi_aliasbuddy(sess, group->name, buddy->name, buddy->alias);
2562                free(alias);
2563              } else {
2564                gaim_debug(GAIM_DEBUG_INFO, "oscar",
2565                           "ssi: adding buddy %s from local list to server list\n", buddy->name);
2566                aim_ssi_addbuddy(sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
2567              }
2568            }
2569          }
2570        }
2571      }
2572   
2573    /* Permit list */
2574    if (gc->account->permit) {
2575      for (cur=gc->account->permit; cur; cur=cur->next)
2576        if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
2577          gaim_debug(GAIM_DEBUG_INFO, "oscar",
2578                     "ssi: adding permit %s from local list to server list\n", (char *)cur->data);
2579          aim_ssi_addpermit(sess, cur->data);
2580        }
2581    }
2582   
2583    /* Deny list */
2584    if (gc->account->deny) {
2585      for (cur=gc->account->deny; cur; cur=cur->next)
2586        if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) {
2587          gaim_debug(GAIM_DEBUG_INFO, "oscar",
2588                     "ssi: adding deny %s from local list to server list\n", (char *)cur->data);
2589          aim_ssi_adddeny(sess, cur->data);
2590        }
2591    }
2592    /* Presence settings (idle time visibility) */
2593    if ((tmp = aim_ssi_getpresence(sess->ssi.local)) != 0xFFFFFFFF)
2594      if (!(tmp & 0x400))
2595        aim_ssi_setpresence(sess, tmp | 0x400);
2596  } /* end adding buddies from local list to server list */
2597 
2598  /* Set our ICQ status */
2599  if  (od->icq && !gc->away) {
2600    aim_setextstatus(sess, AIM_ICQ_STATE_NORMAL);
2601  }
2602 
2603  /* Activate SSI */
2604  /* Sending the enable causes other people to be able to see you, and you to see them */
2605  /* Make sure your privacy setting/invisibility is set how you want it before this! */
2606  gaim_debug(GAIM_DEBUG_INFO, "oscar", "ssi: activating server-stored buddy list\n");
2607  aim_ssi_enable(sess);
2608 
2609  return 1;
2610}
2611
2612static int gaim_ssi_parseack(aim_session_t *sess, aim_frame_t *fr, ...)
2613{
2614  GaimConnection *gc = sess->aux_data;
2615  va_list ap;
2616  struct aim_ssi_tmp *retval;
2617 
2618  va_start(ap, fr);
2619  retval = va_arg(ap, struct aim_ssi_tmp *);
2620  va_end(ap);
2621 
2622  while (retval) {
2623    gaim_debug(GAIM_DEBUG_MISC, "oscar",
2624               "ssi: status is 0x%04hx for a 0x%04hx action with name %s\n", retval->ack,  retval->action, retval->item ? (retval->item->name ? retval->item->name : "no name") : "no item");
2625   
2626    if (retval->ack != 0xffff)
2627      switch (retval->ack) {
2628      case 0x0000: { /* added successfully */
2629      } break;
2630     
2631      case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */
2632        gchar *buf;
2633        buf = g_strdup_printf(_("Could not add the buddy %s because you have too many buddies in your buddy list.  Please remove one and try again."), (retval->name ? retval->name : _("(no name)")));
2634        gaim_notify_error(gc, NULL, _("Unable To Add"), buf);
2635        g_free(buf);
2636      }
2637       
2638      case 0x000e: { /* buddy requires authorization */
2639        if ((retval->action == AIM_CB_SSI_ADD) && (retval->name))
2640          gaim_auth_sendrequest(gc, retval->name);
2641      } break;
2642     
2643      default: { /* La la la */
2644        gchar *buf;
2645        gaim_debug(GAIM_DEBUG_ERROR, "oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack);
2646        buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason.  The most common reason for this is that you have the maximum number of allowed buddies in your buddy list."), (retval->name ? retval->name : _("(no name)")));
2647        gaim_notify_error(gc, NULL, _("Unable To Add"), buf);
2648        g_free(buf);
2649        /* XXX - Should remove buddy from local list */
2650      } break;
2651      }
2652   
2653    retval = retval->next;
2654  }
2655 
2656  return 1;
2657}
2658
2659static int gaim_ssi_authgiven(aim_session_t *sess, aim_frame_t *fr, ...)
2660{
2661  GaimConnection *gc = sess->aux_data;
2662  va_list ap;
2663  char *sn, *msg;
2664  gchar *dialog_msg, *nombre;
2665  struct name_data *data;
2666  GaimBuddy *buddy;
2667 
2668  va_start(ap, fr);
2669  sn = va_arg(ap, char *);
2670  msg = va_arg(ap, char *);
2671  va_end(ap);
2672 
2673  gaim_debug(GAIM_DEBUG_INFO, "oscar",
2674             "ssi: %s has given you permission to add him to your buddy list\n", sn);
2675 
2676  buddy = gaim_find_buddy(gc->account, sn);
2677  if (buddy && (gaim_get_buddy_alias_only(buddy)))
2678    nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
2679  else
2680    nombre = g_strdup(sn);
2681 
2682  dialog_msg = g_strdup_printf(_("The user %s has given you permission to add you to their buddy list.  Do you want to add them?"), nombre);
2683  data = g_new(struct name_data, 1);
2684  data->gc = gc;
2685  data->name = g_strdup(sn);
2686  data->nick = NULL;
2687 
2688  gaim_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg,
2689                      0, data,
2690                      G_CALLBACK(gaim_icq_buddyadd),
2691                      G_CALLBACK(oscar_free_name_data));
2692 
2693  g_free(dialog_msg);
2694  g_free(nombre);
2695 
2696  return 1;
2697}
2698
2699static int gaim_ssi_authrequest(aim_session_t *sess, aim_frame_t *fr, ...)
2700{
2701  GaimConnection *gc = sess->aux_data;
2702  va_list ap;
2703  char *sn, *msg;
2704  gchar *dialog_msg, *nombre;
2705  struct name_data *data;
2706  GaimBuddy *buddy;
2707 
2708  va_start(ap, fr);
2709  sn = va_arg(ap, char *);
2710  msg = va_arg(ap, char *);
2711  va_end(ap);
2712 
2713  gaim_debug(GAIM_DEBUG_INFO, "oscar",
2714             "ssi: received authorization request from %s\n", sn);
2715 
2716  buddy = gaim_find_buddy(gc->account, sn);
2717  if (buddy && (gaim_get_buddy_alias_only(buddy)))
2718    nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
2719  else
2720    nombre = g_strdup(sn);
2721 
2722  dialog_msg = g_strdup_printf(_("The user %s wants to add you to their buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
2723  data = g_new(struct name_data, 1);
2724  data->gc = gc;
2725  data->name = g_strdup(sn);
2726  data->nick = NULL;
2727 
2728  gaim_request_action(gc, NULL, _("Authorization Request"), dialog_msg,
2729                      0, data, 2,
2730                      _("Authorize"), G_CALLBACK(gaim_auth_grant),
2731                      _("Deny"), G_CALLBACK(gaim_auth_dontgrant_msgprompt));
2732 
2733  g_free(dialog_msg);
2734  g_free(nombre);
2735 
2736  return 1;
2737}
2738
2739static int gaim_ssi_authreply(aim_session_t *sess, aim_frame_t *fr, ...)
2740{
2741  GaimConnection *gc = sess->aux_data;
2742  va_list ap;
2743  char *sn, *msg;
2744  gchar *dialog_msg, *nombre;
2745  fu8_t reply;
2746  GaimBuddy *buddy;
2747 
2748  va_start(ap, fr);
2749  sn = va_arg(ap, char *);
2750  reply = (fu8_t)va_arg(ap, int);
2751  msg = va_arg(ap, char *);
2752  va_end(ap);
2753 
2754  gaim_debug(GAIM_DEBUG_INFO, "oscar",
2755             "ssi: received authorization reply from %s.  Reply is 0x%04hhx\n", sn, reply);
2756 
2757  buddy = gaim_find_buddy(gc->account, sn);
2758  if (buddy && (gaim_get_buddy_alias_only(buddy)))
2759    nombre = g_strdup_printf("%s (%s)", sn, gaim_get_buddy_alias_only(buddy));
2760  else
2761    nombre = g_strdup(sn);
2762 
2763  if (reply) {
2764    /* Granted */
2765    dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre);
2766    gaim_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg);
2767  } else {
2768    /* Denied */
2769    dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
2770    gaim_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg);
2771  }
2772  g_free(dialog_msg);
2773  g_free(nombre);
2774 
2775  return 1;
2776}
2777
2778static int gaim_ssi_gotadded(aim_session_t *sess, aim_frame_t *fr, ...)
2779{
2780  GaimConnection *gc = sess->aux_data;
2781  va_list ap;
2782  char *sn;
2783  GaimBuddy *buddy;
2784 
2785  va_start(ap, fr);
2786  sn = va_arg(ap, char *);
2787  va_end(ap);
2788 
2789  buddy = gaim_find_buddy(gc->account, sn);
2790  gaim_debug(GAIM_DEBUG_INFO, "oscar",
2791             "ssi: %s added you to their buddy list\n", sn);
2792  gaim_account_notify_added(gc->account, NULL, sn, (buddy ? gaim_get_buddy_alias_only(buddy) : NULL), NULL);
2793 
2794  return 1;
2795}
2796#endif
Note: See TracBrowser for help on using the repository browser.