source: aim.c @ c8735aa

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