source: aim.c @ 952bb256

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