source: aim.c @ 27f6487

release-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 27f6487 was 2646676, checked in by Anders Kaseorg <andersk@mit.edu>, 15 years ago
faimtest_parse_incoming_im_chan1: Fix realmsg initializer. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 66.3 KB
Line 
1#include <stdio.h>
2#include <stdio.h>
3#include <sys/stat.h>
4#include "owl.h"
5
6/**********************************************************************/
7
8struct owlfaim_priv {
9  char *aimbinarypath;
10  char *screenname;
11  char *password;
12  char *server;
13  int connected;
14};
15
16static const char *msgerrreasons[] = {
17        "Invalid error",
18        "Invalid SNAC",
19        "Rate to host",
20        "Rate to client",
21        "Not logged on",
22        "Service unavailable",
23        "Service not defined",
24        "Obsolete SNAC",
25        "Not supported by host",
26        "Not supported by client",
27        "Refused by client",
28        "Reply too big",
29        "Responses lost",
30        "Request denied",
31        "Busted SNAC payload",
32        "Insufficient rights",
33        "In local permit/deny",
34        "Too evil (sender)",
35        "Too evil (receiver)",
36        "User temporarily unavailable",
37        "No match",
38        "List overflow",
39        "Request ambiguous",
40        "Queue full",
41        "Not while on AOL",
42};
43static int msgerrreasonslen = 25;
44
45static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
46static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...);
47static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...);
48int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...);
49int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...);
50void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn);
51static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...);
52static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...);
53static int conninitdone_chat     (aim_session_t *, aim_frame_t *, ...);
54int logout(aim_session_t *sess);
55
56static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...);
57static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...);
58static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...);
59static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...);
60static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...);
61static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...);
62static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...);
63static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...);
64static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...);
65/* static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs); */
66static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...);
67static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname);
68static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...);
69/* static void printuserflags(fu16_t flags); */
70static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...);
71static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args);
72static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args);
73static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...);
74static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...);
75static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...);
76int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...);
77static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...);
78static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...);
79static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...);
80static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...);
81static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...);
82static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...);
83static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...);
84static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...);
85static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...);
86static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...);
87static int migrate(aim_session_t *sess, aim_frame_t *fr, ...);
88static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...);
89static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...);
90static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...);
91static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...);
92static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...);
93/*
94static int faimtest_ssi_parseerr     (aim_session_t *, aim_frame_t *, ...);
95static int faimtest_ssi_parserights  (aim_session_t *, aim_frame_t *, ...);
96static int faimtest_ssi_parselist    (aim_session_t *, aim_frame_t *, ...);
97static int faimtest_ssi_parseack     (aim_session_t *, aim_frame_t *, ...);
98static int faimtest_ssi_authgiven    (aim_session_t *, aim_frame_t *, ...);
99static int faimtest_ssi_authrequest  (aim_session_t *, aim_frame_t *, ...);
100static int faimtest_ssi_authreply    (aim_session_t *, aim_frame_t *, ...);
101static int faimtest_ssi_gotadded     (aim_session_t *, aim_frame_t *, ...);
102*/
103
104void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
105void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir);
106
107/*****************************************************************/
108
109void owl_aim_init(void)
110{
111  /* this has all been moved to owl_aim_login, but we'll leave the
112   * function here, in case there's stuff we want to init in the
113   * future.  It's still called by Owl.
114   */
115     
116}
117
118void owl_aim_send_nop(owl_timer *t, void *data) {
119    if(owl_global_is_doaimevents(&g)) {
120        aim_session_t *sess = owl_global_get_aimsess(&g);
121        aim_flap_nop(sess, aim_getconn_type(sess, AIM_CONN_TYPE_BOS));
122    }
123}
124
125
126int owl_aim_login(const char *screenname, const char *password)
127{
128  struct owlfaim_priv *priv;
129  aim_conn_t *conn;
130  aim_session_t *sess;
131
132  sess=owl_global_get_aimsess(&g);
133
134  aim_session_init(sess, TRUE, 0);
135  aim_setdebuggingcb(sess, faimtest_debugcb);
136  aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
137 
138  /* this will leak, I know and just don't care right now */
139  priv=owl_malloc(sizeof(struct owlfaim_priv));
140  memset(priv, 0, sizeof(struct owlfaim_priv));
141
142  priv->screenname = owl_strdup(screenname);
143  priv->password = owl_strdup(password);
144  priv->server = owl_strdup(FAIM_LOGIN_SERVER);
145  sess->aux_data = priv;
146
147  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, priv->server ? priv->server : FAIM_LOGIN_SERVER);
148  /*  conn=aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); */
149  if (!conn) {
150    owl_function_error("owl_aim_login: connection error during AIM login\n");
151    owl_global_set_aimnologgedin(&g);
152    owl_global_set_no_doaimevents(&g);
153    return (-1);
154  }
155
156  /*
157  else if (conn->fd == -1) {
158    if (conn->status & AIM_CONN_STATUS_RESOLVERR) {
159      owl_function_error("owl_aim_login: could not resolve authorize name");
160    } else if (conn->status & AIM_CONN_STATUS_CONNERR) {
161      owl_function_error("owl_aim_login: could not connect to authorizer");
162    } else {
163      owl_function_error("owl_aim_login: unknown connection error");
164    }
165    owl_global_set_aimnologgedin(&g);
166    owl_global_set_no_doaimevents(&g);
167    aim_conn_kill(sess, &conn);
168    return(-1);
169  }
170  */
171
172   
173  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
174  aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
175
176  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_AUTHRESPONSE, faimtest_parse_login, 0);
177  aim_conn_addhandler(sess, conn, AIM_CB_FAM_ATH, AIM_CB_ATH_LOGINRESPONSE, faimtest_parse_authresp, 0);
178  /* aim_conn_addhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_connerr, 0); */
179  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); */
180  /* aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0); */
181   
182  /* start processing AIM events */
183  owl_global_set_doaimevents(&g);
184  /* conn->status |= AIM_CONN_STATUS_INPROGRESS; */
185  owl_function_debugmsg("owl_aim_login: sending login request for %s", screenname);
186  aim_request_login(sess, conn, screenname);
187  owl_function_debugmsg("owl_aim_login: connecting");
188
189  g.aim_nop_timer = owl_select_add_timer(30, 30, owl_aim_send_nop, NULL, NULL);
190
191  return(0);
192}
193
194void owl_aim_unset_ignorelogin(owl_timer *t, void *data) {      /* noproto */
195    owl_global_unset_ignore_aimlogin(&g);
196}
197
198/* stuff to run once login has been successful */
199void owl_aim_successful_login(const char *screenname)
200{
201  char *buff;
202  owl_function_debugmsg("doing owl_aim_successful_login");
203  owl_global_set_aimloggedin(&g, screenname);
204  owl_global_set_doaimevents(&g); /* this should already be on */
205  owl_function_makemsg("%s logged in", screenname);
206  buff=owl_sprintf("Logged in to AIM as %s", screenname);
207  owl_function_adminmsg("", buff);
208  owl_free(buff);
209
210  owl_function_debugmsg("Successful AIM login for %s", screenname);
211
212  /* start the ingorelogin timer */
213  owl_global_set_ignore_aimlogin(&g);
214  owl_select_add_timer(owl_global_get_aim_ignorelogin_timer(&g),
215                       0, owl_aim_unset_ignorelogin, NULL, NULL);
216
217  /* aim_ssi_setpresence(owl_global_get_aimsess(&g), 0x00000400); */
218  /* aim_bos_setidle(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), 5000); */
219}
220
221void owl_aim_logout(void)
222{
223  /* need to check if it's connected first, I think */
224  logout(owl_global_get_aimsess(&g));
225
226  if (owl_global_is_aimloggedin(&g)) owl_function_adminmsg("", "Logged out of AIM");
227  owl_global_set_aimnologgedin(&g);
228  owl_global_set_no_doaimevents(&g);
229  owl_select_remove_timer(g.aim_nop_timer);
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(const char *message)
239{
240  if (message) {
241    owl_function_error("%s", 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  owl_select_remove_timer(g.aim_nop_timer);
249}
250
251int owl_aim_send_im(const char *to, const char *msg)
252{
253  int ret;
254
255  ret=aim_im_sendch1(owl_global_get_aimsess(&g), to, 0, msg);
256   
257  /* I don't know how to check for an error yet */
258  return(ret);
259}
260
261int owl_aim_send_awaymsg(const char *to, const char *msg)
262{
263  int ret;
264
265  ret=aim_im_sendch1(owl_global_get_aimsess(&g), to, AIM_IMFLAGS_AWAY, msg);
266
267  /* I don't know how to check for an error yet */
268  return(ret);
269}
270
271void owl_aim_addbuddy(const char *name)
272{
273
274  aim_ssi_addbuddy(owl_global_get_aimsess(&g), name, "Buddies", NULL, NULL, NULL, 0);
275
276  /*
277  aim_ssi_addbuddy(owl_global_get_aimsess(&g),
278                   name,
279                   "Buddies",
280                   NULL, NULL, NULL,
281                   aim_ssi_waitingforauth(owl_global_get_aimsess(&g)->ssi.local, "Buddies", name));
282  */
283}
284
285void owl_aim_delbuddy(const char *name)
286{
287  aim_ssi_delbuddy(owl_global_get_aimsess(&g), name, "Buddies");
288  owl_buddylist_offgoing(owl_global_get_buddylist(&g), name);
289}
290
291void owl_aim_search(const char *email)
292{
293  int ret;
294
295  owl_function_debugmsg("owl_aim_search: doing search for %s", email);
296  ret=aim_search_address(owl_global_get_aimsess(&g), 
297                         aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_BOS),
298                         email);
299
300  if (ret) owl_function_error("owl_aim_search: aim_search_address returned %i", ret);
301}
302
303
304int owl_aim_set_awaymsg(const char *msg)
305{
306  int len;
307  char *foo;
308  /* there is a max away message lentgh we should check against */
309
310  foo=owl_strdup(msg);
311  len=strlen(foo);
312  if (len>500) {
313    foo[500]='\0';
314    len=499;
315  }
316   
317  aim_locate_setprofile(owl_global_get_aimsess(&g),
318                        NULL, NULL, 0,
319                        "us-ascii", foo, len);
320  owl_free(foo);
321
322  /*
323  aim_bos_setprofile(owl_global_get_aimsess(&g),
324                     owl_global_get_bosconn(&g),
325                     NULL, NULL, 0, "us-ascii", msg,
326                     strlen(msg), 0);
327  */
328  return(0);
329}
330
331void owl_aim_chat_join(const char *name, int exchange)
332{
333  int ret;
334  aim_conn_t *cur;
335  /*
336  OscarData *od = g->proto_data;
337  const char *name, *exchange;
338  */
339
340  owl_function_debugmsg("Attempting to join chatroom %s exchange %i", name, exchange);
341
342  /*
343  name = g_hash_table_lookup(data, "room");
344  exchange = g_hash_table_lookup(data, "exchange");
345  */
346  if ((cur = aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV))) {
347    owl_function_debugmsg("owl_aim_chat_join: chatnav exists, creating room");
348    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
349  } else {
350    /*    struct create_room *cr = g_new0(struct create_room, 1); */
351    owl_function_debugmsg("owl_aim_chat_join: chatnav does not exist, opening chatnav");
352    /*
353    cr->exchange = atoi(exchange);
354    cr->name = g_strdup(name);
355    od->create_rooms = g_slist_append(od->create_rooms, cr);
356    */
357    aim_reqservice(owl_global_get_aimsess(&g),
358                   aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV),
359                   AIM_CONN_TYPE_CHATNAV);
360    aim_reqservice(owl_global_get_aimsess(&g), NULL, AIM_CONN_TYPE_CHATNAV);
361    aim_chatnav_createroom(owl_global_get_aimsess(&g), cur, name, exchange);
362    ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
363
364  }
365  return;
366  /******/
367
368
369  /* ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, chatroom, 0x0000); */
370  /*
371  ret=aim_chat_join(owl_global_get_aimsess(&g),
372                    aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), exchange, chatroom, 0x0000);
373  */
374
375  aim_reqservice(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), AIM_CONN_TYPE_CHATNAV);
376  ret = aim_chatnav_createroom(owl_global_get_aimsess(&g),
377                               aim_getconn_type(owl_global_get_aimsess(&g), AIM_CONN_TYPE_CHATNAV), name, exchange);
378   ret=aim_chat_join(owl_global_get_aimsess(&g), owl_global_get_bosconn(&g), exchange, name, 0x0000);
379 
380}
381
382void owl_aim_chat_leave(const char *chatroom)
383{
384}
385
386int owl_aim_chat_sendmsg(const char *chatroom, const char *msg)
387{
388  return(0);
389}
390
391/* caller must free the return */
392char *owl_aim_normalize_screenname(const char *in)
393{
394  char *out;
395  int i, j, k;
396
397  j=strlen(in);
398  out=owl_malloc(j+30);
399  k=0;
400  for (i=0; i<j; i++) {
401    if (in[i]!=' ') {
402      out[k]=in[i];
403      k++;
404    }
405  }
406  out[k]='\0';
407  return(out);
408}
409
410int owl_aim_process_events()
411{
412  aim_session_t *aimsess;
413  aim_conn_t *waitingconn = NULL;
414  struct timeval tv;
415  int selstat = 0;
416  struct owlfaim_priv *priv;
417
418  aimsess=owl_global_get_aimsess(&g);
419  priv = aimsess->aux_data;
420
421  /* do a select without blocking */
422  tv.tv_sec = 0;
423  tv.tv_usec = 0;
424  waitingconn = aim_select(aimsess, &tv, &selstat);
425
426  if (selstat == -1) {
427    owl_aim_logged_out();
428  } else if (selstat == 0) { 
429    /* no events pending */
430  } else if (selstat == 1) { /* outgoing data pending */
431    aim_tx_flushqueue(aimsess);
432  } else if (selstat == 2) { /* incoming data pending */
433    /* printf("selstat == 2\n"); */
434   
435    if (aim_get_command(aimsess, waitingconn) >= 0) {
436      aim_rxdispatch(aimsess);
437    } else {
438      /* printf("connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype); */
439      /* we should have callbacks for all these, else the library will do the conn_kill for us. */
440      if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS) {
441        if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
442          /* printf("disconnected from %s\n", aim_directim_getsn(waitingconn)); */
443          aim_conn_kill(aimsess, &waitingconn);
444          owl_aim_logged_out();
445        }
446      } else {
447        aim_conn_kill(aimsess, &waitingconn);
448        owl_aim_logged_out();
449      }
450      if (!aim_getconn_type(aimsess, AIM_CONN_TYPE_BOS)) {
451        /* printf("major connection error\n"); */
452        owl_aim_logged_out();
453        /* break; */
454      }
455    }
456  }
457  /* exit(0); */
458  return(0);
459}
460
461static void faimtest_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
462{
463  return;
464}
465
466static int faimtest_parse_login(aim_session_t *sess, aim_frame_t *fr, ...)
467{
468  struct owlfaim_priv *priv = sess->aux_data;
469  struct client_info_s info = CLIENTINFO_AIM_KNOWNGOOD;
470   
471  const char *key;
472  va_list ap;
473
474  va_start(ap, fr);
475  key = va_arg(ap, const char *);
476  va_end(ap);
477
478  owl_function_debugmsg("faimtest_parse_login: %s %s %s", priv->screenname, priv->password, key);
479
480  aim_send_login(sess, fr->conn, priv->screenname, priv->password, &info, key);
481 
482  return(1);
483}
484
485
486static int faimtest_parse_authresp(aim_session_t *sess, aim_frame_t *fr, ...)
487{
488  va_list ap;
489  struct aim_authresp_info *info;
490  aim_conn_t *bosconn;
491
492  va_start(ap, fr);
493  info = va_arg(ap, struct aim_authresp_info *);
494  va_end(ap);
495
496  /* printf("Screen name: %s\n", info->sn); */
497  owl_function_debugmsg("doing faimtest_parse_authresp");
498  owl_function_debugmsg("faimtest_parse_authresp: %s", info->sn);
499
500  /*
501   * Check for error.
502   */
503  if (info->errorcode || !info->bosip || !info->cookie) {
504    /*
505    printf("Login Error Code 0x%04x\n", info->errorcode);
506    printf("Error URL: %s\n", info->errorurl);
507    */
508    if (info->errorcode==0x05) {
509      owl_aim_login_error("Incorrect nickname or password.");
510    } else if (info->errorcode==0x11) {
511      owl_aim_login_error("Your account is currently suspended.");
512    } else if (info->errorcode==0x14) {
513      owl_aim_login_error("The AOL Instant Messenger service is temporarily unavailable.");
514    } else if (info->errorcode==0x18) {
515      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.");
516    } else if (info->errorcode==0x1c) {
517      owl_aim_login_error("The client version you are using is too old.");
518    } else {
519      owl_aim_login_error(NULL);
520    }
521    aim_conn_kill(sess, &fr->conn);
522    return(1);
523  }
524
525  /*
526  printf("Reg status: %d\n", info->regstatus);
527  printf("Email: %s\n", info->email);
528  printf("BOS IP: %s\n", info->bosip);
529  */
530
531  /* printf("Closing auth connection...\n"); */
532  aim_conn_kill(sess, &fr->conn);
533  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, info->bosip))) {
534    /* printf("could not connect to BOS: internal error\n"); */
535    return(1);
536  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {
537    /* printf("could not connect to BOS\n"); */
538    aim_conn_kill(sess, &bosconn);
539    return(1);
540  }
541  owl_global_set_bossconn(&g, bosconn);
542  owl_aim_successful_login(info->sn);
543  addcb_bos(sess, bosconn);
544  aim_sendcookie(sess, bosconn, info->cookielen, info->cookie);
545  return(1);
546}
547
548int faimtest_flapversion(aim_session_t *sess, aim_frame_t *fr, ...)
549{
550  owl_function_debugmsg("doing faimtest_flapversion");
551
552#if 0
553  /* XXX fix libfaim to support this */
554  printf("using FLAP version 0x%08x\n", /* aimutil_get32(fr->data)*/ 0xffffffff);
555
556  /*
557   * This is an alternate location for starting the login process.
558   */
559  /* XXX should do more checking to make sure its really the right AUTH conn */
560  if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
561    /* do NOT send a flapversion, request_login will send it if needed */
562    aim_request_login(sess, fr->conn, priv->screenname);
563    /* printf("faimtest: login request sent\n"); */
564  }
565#endif
566
567  return 1;
568}
569
570
571int faimtest_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
572{
573  owl_function_debugmsg("doing faimtest_conncomplete");
574  /* owl_aim_successful_login(info->sn); */
575  return 1;
576}
577
578void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
579{
580  owl_function_debugmsg("doing addcb_bos");
581  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
582  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0);
583
584  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0003,                        ssirights, 0);
585  aim_conn_addhandler(sess, bosconn, 0x0013,         0x0006,                        ssidata, 0);
586  aim_conn_addhandler(sess, bosconn, 0x0013,         0x000f,                        ssidatanochange, 0);
587  aim_conn_addhandler(sess, bosconn, 0x0008,         0x0002,                        handlepopup, 0);
588  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0003,                        faimtest_bosrights, 0);
589  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT,           faimtest_handleredirect, 0);
590  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL,  faimtest_reportinterval, 0);
591  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO,         faimtest_parse_buddyrights, 0);
592  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD,               faimtest_parse_motd, 0);
593  aim_conn_addhandler(sess, bosconn, 0x0004,         0x0005,                        faimtest_icbmparaminfo, 0);
594  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,    faimtest_parse_connerr, 0);
595  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO,         faimtest_locrights, 0);
596  aim_conn_addhandler(sess, bosconn, 0x0001,         0x001f,                        faimtest_memrequest, 0);
597  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING,           faimtest_parse_oncoming, 0);
598  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING,           faimtest_parse_offgoing, 0);
599  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING,           faimtest_parse_incoming_im, 0);
600  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR,              faimtest_parse_locerr, 0);
601  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL,         faimtest_parse_misses, 0);
602  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE,         faimtest_parse_ratechange, 0);
603  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_EVIL,               faimtest_parse_evilnotify, 0);
604
605  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0001,                        faimtest_parse_searcherror, 0);
606  aim_conn_addhandler(sess, bosconn, 0x000a,         0x0003,                        faimtest_parse_searchreply, 0);
607
608  /*
609  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, AIM_CB_LOK_ERROR, faimtest_parse_searcherror, 0);
610  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOK, 0x0003, faimtest_parse_searchreply, 0);
611  */
612 
613  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR,              faimtest_parse_msgerr, 0);
614  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO,           faimtest_parse_userinfo, 0);
615  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK,                faimtest_parse_msgack, 0);
616
617  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0001,                        faimtest_parse_genericerr, 0);
618  aim_conn_addhandler(sess, bosconn, 0x0003,         0x0001,                        faimtest_parse_genericerr, 0);
619  aim_conn_addhandler(sess, bosconn, 0x0009,         0x0001,                        faimtest_parse_genericerr, 0);
620  aim_conn_addhandler(sess, bosconn, 0x0001,         0x000b,                        serverpause, 0);
621  aim_conn_addhandler(sess, bosconn, 0x0001,         0x0012,                        migrate, 0);
622  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG,         offlinemsg, 0);
623  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE, offlinemsgdone, 0);
624
625  /*
626  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR,     gaim_connerr, 0);
627  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0);
628  */
629
630  /*
631  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ERROR,              faimtest_ssi_parseerr, 0);
632  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RIGHTSINFO,         faimtest_ssi_parserights, 0);
633  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_LIST,               faimtest_ssi_parselist, 0);
634  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_NOLIST,             faimtest_ssi_parselist, 0);
635  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_SRVACK,             faimtest_ssi_parseack, 0);
636  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTH,           faimtest_ssi_authgiven, 0);
637  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREQ,        faimtest_ssi_authrequest, 0);
638  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RECVAUTHREP,        faimtest_ssi_authreply, 0);
639  aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_ADDED,              faimtest_ssi_gotadded, 0);
640  */
641
642  return;
643}
644
645static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...)
646{
647  owl_function_debugmsg("doing coninitdone_bos");
648
649
650  aim_reqpersonalinfo(sess, fr->conn);
651  aim_ssi_reqrights(sess);
652  aim_ssi_reqdata(sess);
653  aim_locate_reqrights(sess);
654  aim_buddylist_reqrights(sess, fr->conn);
655
656  aim_im_reqparams(sess);
657  /* aim_bos_reqrights(sess, fr->conn); */ /* XXX - Don't call this with ssi */
658
659  owl_function_debugmsg("conninitdone_bos: requesting rights");
660  aim_bos_reqrights(sess, fr->conn); /* XXX - Don't call this with ssi */
661  aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
662  aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
663
664  return(1);
665}
666
667static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...)
668{
669  aim_clientready(sess, fr->conn);
670  owl_function_debugmsg("conninitdone_admin: initializtion done for admin connection");
671  return(1);
672}
673
674int logout(aim_session_t *sess)
675{
676  aim_session_kill(sess);
677  owl_aim_init();
678
679  owl_function_debugmsg("libfaim logout called");
680  /*
681  if (faimtest_init() == -1)
682    printf("faimtest_init failed\n");
683  */
684
685  return(0);
686}
687
688/**************************************************************************************************/
689
690static int faimtest_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
691{
692  struct owlfaim_priv *priv = sess->aux_data;
693  va_list ap;
694  fu16_t code;
695  const char *msg;
696 
697  va_start(ap, fr);
698  code = va_arg(ap, int);
699  msg = va_arg(ap, const char *);
700  va_end(ap);
701 
702  owl_function_error("faimtest_parse_connerr: Code 0x%04x: %s\n", code, msg);
703  aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
704 
705  priv->connected = 0;
706 
707  return 1;
708}
709
710static int faimtest_accountconfirm(aim_session_t *sess, aim_frame_t *fr, ...)
711{
712  int status;
713  va_list ap;
714 
715  va_start(ap, fr);
716  status = va_arg(ap, int); /* status code of confirmation request */
717  va_end(ap);
718
719  /* owl_function_debugmsg("faimtest_accountconfirm: Code 0x%04x: %s\n", code, msg); */
720  owl_function_debugmsg("faimtest_accountconfirm: account confirmation returned status 0x%04x (%s)\n", status, (status==0x0000)?"email sent":"unknown");
721 
722  return 1;
723}
724
725static int faimtest_infochange(aim_session_t *sess, aim_frame_t *fr, ...)
726{
727  fu16_t change = 0, perms, type;
728  int length, str;
729  const char *val;
730  va_list ap;
731 
732  va_start(ap, fr);
733  change = va_arg(ap, int);
734  perms = (fu16_t)va_arg(ap, unsigned int);
735  type = (fu16_t)va_arg(ap, unsigned int);
736  length = va_arg(ap, int);
737  val = va_arg(ap, const char *);
738  str = va_arg(ap, int);
739  va_end(ap);
740 
741  owl_function_debugmsg("faimtest_infochange: info%s: perms = %d, type = %x, length = %d, val = %s", change?" change":"", perms, type, length, str?val:"(not string)");
742 
743  return(1);
744}
745
746
747static int faimtest_handleredirect(aim_session_t *sess, aim_frame_t *fr, ...)
748{
749  va_list ap;
750  struct aim_redirect_data *redir;
751
752  owl_function_debugmsg("faimtest_handledirect:");
753 
754  va_start(ap, fr);
755  redir = va_arg(ap, struct aim_redirect_data *);
756 
757  if (redir->group == 0x0005) {  /* Adverts */
758   
759  } else if (redir->group == 0x0007) {  /* Authorizer */
760    aim_conn_t *tstconn;
761
762    owl_function_debugmsg("faimtest_handledirect: autorizer");
763   
764    tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, redir->ip);
765    if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
766      owl_function_error("faimtest_handleredirect: unable to reconnect with authorizer");
767    } else {
768      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, faimtest_flapversion, 0);
769      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
770      aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0);
771      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, faimtest_accountconfirm, 0);
772      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, faimtest_infochange, 0);
773      aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, faimtest_infochange, 0);
774      /* Send the cookie to the Auth */
775      aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
776      owl_function_debugmsg("faimtest_handleredirect: sent cookie to authorizer host");
777    }
778  } else if (redir->group == 0x000d) {  /* ChatNav */
779    owl_function_debugmsg("faimtest_handledirect: chatnav");
780    chatnav_redirect(sess, redir);
781  } else if (redir->group == 0x000e) { /* Chat */
782    owl_function_debugmsg("faimtest_handledirect: chat");
783    chat_redirect(sess, redir);
784  } else {
785    owl_function_debugmsg("faimtest_handleredirect: uh oh... got redirect for unknown service 0x%04x!!", redir->group);
786  }
787  va_end(ap);
788  return 1;
789}
790
791static int faimtest_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
792{
793  struct aim_icbmparameters *params;
794  va_list ap;
795 
796  va_start(ap, fr);
797  params = va_arg(ap, struct aim_icbmparameters *);
798  va_end(ap);
799 
800  owl_function_debugmsg("faimtest_icbmparaminfo: ICBM Parameters: maxchannel = %d, default flags = 0x%08x, max msg len = %d, max sender evil = %f, max reciever evil = %f, min msg interval = %u",
801                       params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn)/10.0, ((float)params->maxrecverwarn)/10.0, params->minmsginterval);
802     
803  /*
804  * Set these to your taste, or client medium.  Setting minmsginterval
805  * higher is good for keeping yourself from getting flooded (esp
806  * if you're on a slow connection or something where that would be
807  * useful).
808  */
809  params->maxmsglen = 8000;
810  params->minmsginterval = 0; /* in milliseconds */
811  /* aim_seticbmparam(sess, params); */
812  aim_im_setparams(sess, params);
813 
814  return 1;
815}
816
817static int faimtest_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
818{
819  va_list ap;
820  fu16_t maxbuddies, maxwatchers;
821 
822  va_start(ap, fr);
823  maxbuddies = va_arg(ap, int);
824  maxwatchers = va_arg(ap, int);
825  va_end(ap);
826 
827  owl_function_debugmsg("faimtest_parse_buddyrights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers);
828 
829  /* aim_ssi_reqrights(sess, fr->conn); */
830  aim_ssi_reqrights(sess);
831 
832  return 1;
833}
834
835static int faimtest_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
836{
837  va_list ap;
838  fu16_t maxpermits, maxdenies;
839 
840  va_start(ap, fr);
841  maxpermits = va_arg(ap, int);
842  maxdenies = va_arg(ap, int);
843  va_end(ap);
844 
845  owl_function_debugmsg("faimtest_bosrights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies);
846  aim_clientready(sess, fr->conn);
847  owl_function_debugmsg("officially connected to BOS.");
848  aim_icq_reqofflinemsgs(sess);
849  return 1;
850}
851
852static int faimtest_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
853{
854  va_list ap;
855  fu16_t maxsiglen;
856 
857  va_start(ap, fr);
858  maxsiglen = va_arg(ap, int);
859  va_end(ap);
860
861  owl_function_debugmsg("faimtest_locrights: rights: max signature length = %d\n", maxsiglen);
862 
863  return(1);
864}
865
866static int faimtest_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
867{
868  struct owlfaim_priv *priv = sess->aux_data;
869  va_list ap;
870  fu16_t interval;
871
872  va_start(ap, fr);
873  interval = va_arg(ap, int);
874  va_end(ap);
875
876  owl_function_debugmsg("faimtest_reportinterval: %d (seconds?)\n", interval);
877
878  if (!priv->connected) {
879    priv->connected++;
880  }
881  /* aim_reqicbmparams(sess); */
882  aim_im_reqparams(sess);
883  /* kretch */
884  return 1;
885}
886
887static int faimtest_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
888{
889  const char *msg;
890  fu16_t id;
891  va_list ap;
892  static int codeslen = 5;
893  static const char *codes[] = {
894    "Unknown",
895    "Mandatory upgrade",
896    "Advisory upgrade",
897    "System bulletin",
898    "Top o' the world!"
899  };
900
901  va_start(ap, fr);
902  id = va_arg(ap, int);
903  msg = va_arg(ap, const char *);
904  va_end(ap);
905
906  owl_function_debugmsg("faimtest_parse_motd: %s (%d / %s)\n", msg?msg:"nomsg", id, (id < codeslen)?codes[id]:"unknown");
907 
908  return 1;
909}
910
911/*
912 * This is a little more complicated than it looks.  The module
913 * name (proto, boscore, etc) may or may not be given.  If it is
914 * not given, then use aim.exe.  If it is given, put ".ocm" on the
915 * end of it.
916 *
917 * Now, if the offset or length requested would cause a read past
918 * the end of the file, then the request is considered invalid.  Invalid
919 * requests are processed specially.  The value hashed is the
920 * the request, put into little-endian (eight bytes: offset followed
921 * by length). 
922 *
923 * Additionally, if the request is valid, the length is mod 4096.  It is
924 * important that the length is checked for validity first before doing
925 * the mod.
926 *
927 * Note to Bosco's Brigade: if you'd like to break this, put the
928 * module name on an invalid request.
929 *
930 */
931static int getaimdata(aim_session_t *sess, unsigned char **bufret, int *buflenret, unsigned long offset, unsigned long len, const char *modname)
932{
933  struct owlfaim_priv *priv = sess->aux_data;
934  FILE *f;
935  static const char defaultmod[] = "aim.exe";
936  char *filename = NULL;
937  struct stat st;
938  unsigned char *buf;
939  int invalid = 0;
940 
941  if (!bufret || !buflenret)
942    return -1;
943 
944  if (modname) {
945    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(modname)+4+1))) {
946      /* perror("memrequest: malloc"); */
947      return -1;
948    }
949    sprintf(filename, "%s/%s.ocm", priv->aimbinarypath, modname);
950  } else {
951    if (!(filename = owl_malloc(strlen(priv->aimbinarypath)+1+strlen(defaultmod)+1))) {
952      /* perror("memrequest: malloc"); */
953      return -1;
954    }
955    sprintf(filename, "%s/%s", priv->aimbinarypath, defaultmod);
956  }
957 
958  if (stat(filename, &st) == -1) {
959    if (!modname) {
960      /* perror("memrequest: stat"); */
961      owl_free(filename);
962      return -1;
963    }
964    invalid = 1;
965  }
966 
967  if (!invalid) {
968    if ((offset > st.st_size) || (len > st.st_size))
969      invalid = 1;
970    else if ((st.st_size - offset) < len)
971      len = st.st_size - offset;
972    else if ((st.st_size - len) < len)
973      len = st.st_size - len;
974  }
975 
976  if (!invalid && len) {
977    len %= 4096;
978  }
979 
980  if (invalid) {
981    int i;
982   
983    owl_free(filename); /* not needed */
984    owl_function_error("getaimdata memrequest: recieved invalid request for 0x%08lx bytes at 0x%08lx (file %s)\n", len, offset, modname);
985    i = 8;
986    if (modname) {
987      i+=strlen(modname);
988    }
989   
990    if (!(buf = owl_malloc(i))) {
991      return -1;
992    }
993   
994    i=0;
995   
996    if (modname) {
997      memcpy(buf, modname, strlen(modname));
998      i+=strlen(modname);
999    }
1000   
1001    /* Damn endianness. This must be little (LSB first) endian. */
1002    buf[i++] = offset & 0xff;
1003    buf[i++] = (offset >> 8) & 0xff;
1004    buf[i++] = (offset >> 16) & 0xff;
1005    buf[i++] = (offset >> 24) & 0xff;
1006    buf[i++] = len & 0xff;
1007    buf[i++] = (len >> 8) & 0xff;
1008    buf[i++] = (len >> 16) & 0xff;
1009    buf[i++] = (len >> 24) & 0xff;
1010   
1011    *bufret = buf;
1012    *buflenret = i;
1013  } else {
1014    if (!(buf = owl_malloc(len))) {
1015      owl_free(filename);
1016      return -1;
1017    }
1018    /* printf("memrequest: loading %ld bytes from 0x%08lx in \"%s\"...\n", len, offset, filename); */
1019    if (!(f = fopen(filename, "r"))) {
1020      /* perror("memrequest: fopen"); */
1021      owl_free(filename);
1022      owl_free(buf);
1023      return -1;
1024    }
1025   
1026    owl_free(filename);
1027   
1028    if (fseek(f, offset, SEEK_SET) == -1) {
1029      /* perror("memrequest: fseek"); */
1030      fclose(f);
1031      owl_free(buf);
1032      return -1;
1033    }
1034   
1035    if (fread(buf, len, 1, f) != 1) {
1036      /* perror("memrequest: fread"); */
1037      fclose(f);
1038      owl_free(buf);
1039      return -1;
1040    }
1041   
1042    fclose(f);
1043    *bufret = buf;
1044    *buflenret = len;
1045  }
1046  return 0; /* success! */
1047}
1048
1049/*
1050 * This will get an offset and a length.  The client should read this
1051 * data out of whatever AIM.EXE binary the user has provided (hopefully
1052 * it matches the client information thats sent at login) and pass a
1053 * buffer back to libfaim so it can hash the data and send it to AOL for
1054 * inspection by the client police.
1055 */
1056static int faimtest_memrequest(aim_session_t *sess, aim_frame_t *fr, ...)
1057{
1058  struct owlfaim_priv *priv = sess->aux_data;
1059  va_list ap;
1060  fu32_t offset, len;
1061  const char *modname;
1062  unsigned char *buf;
1063  int buflen;
1064 
1065  va_start(ap, fr);
1066  offset = va_arg(ap, fu32_t);
1067  len = va_arg(ap, fu32_t);
1068  modname = va_arg(ap, const char *);
1069  va_end(ap);
1070 
1071  if (priv->aimbinarypath && (getaimdata(sess, &buf, &buflen, offset, len, modname) == 0)) {
1072    aim_sendmemblock(sess, fr->conn, offset, buflen, buf, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
1073    owl_free(buf);
1074  } else {
1075    owl_function_debugmsg("faimtest_memrequest: unable to use AIM binary (\"%s/%s\"), sending defaults...\n", priv->aimbinarypath, modname);
1076    aim_sendmemblock(sess, fr->conn, offset, len, NULL, AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
1077  }
1078  return 1;
1079}
1080
1081/*
1082static void printuserflags(fu16_t flags)
1083{
1084  if (flags & AIM_FLAG_UNCONFIRMED) printf("UNCONFIRMED ");
1085  if (flags & AIM_FLAG_ADMINISTRATOR) printf("ADMINISTRATOR ");
1086  if (flags & AIM_FLAG_AOL) printf("AOL ");
1087  if (flags & AIM_FLAG_OSCAR_PAY) printf("OSCAR_PAY ");
1088  if (flags & AIM_FLAG_FREE) printf("FREE ");
1089  if (flags & AIM_FLAG_AWAY) printf("AWAY ");
1090  if (flags & AIM_FLAG_ICQ) printf("ICQ ");
1091  if (flags & AIM_FLAG_WIRELESS) printf("WIRELESS ");
1092  if (flags & AIM_FLAG_ACTIVEBUDDY) printf("ACTIVEBUDDY ");
1093 
1094  return;
1095}
1096*/
1097
1098static int faimtest_parse_userinfo(aim_session_t *sess, aim_frame_t *fr, ...)
1099{
1100  aim_userinfo_t *userinfo;
1101  const char *prof_encoding = NULL;
1102  const char *prof = NULL;
1103  fu16_t inforeq = 0;
1104  owl_buddy *b;
1105  va_list ap;
1106  va_start(ap, fr);
1107  userinfo = va_arg(ap, aim_userinfo_t *);
1108  inforeq = (fu16_t)va_arg(ap, unsigned int);
1109  prof_encoding = va_arg(ap, const char *);
1110  prof = va_arg(ap, const char *);
1111  va_end(ap);
1112
1113  /* right now the only reason we call this is for idle times */
1114  owl_function_debugmsg("parse_userinfo sn: %s idle: %i", userinfo->sn, userinfo->idletime);
1115  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g),
1116                                userinfo->sn);
1117  if (!b) return(1);
1118  owl_buddy_set_idle_since(b, userinfo->idletime);
1119  return(1);
1120
1121  /*
1122  printf("userinfo: sn: %s\n", userinfo->sn);
1123  printf("userinfo: warnlevel: %f\n", aim_userinfo_warnlevel(userinfo));
1124  printf("userinfo: flags: 0x%04x = ", userinfo->flags);
1125  printuserflags(userinfo->flags);
1126  printf("\n");
1127  */
1128
1129  /*
1130  printf("userinfo: membersince: %lu\n", userinfo->membersince);
1131  printf("userinfo: onlinesince: %lu\n", userinfo->onlinesince);
1132  printf("userinfo: idletime: 0x%04x\n", userinfo->idletime);
1133  printf("userinfo: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
1134  */
1135
1136  /*
1137  if (inforeq == AIM_GETINFO_GENERALINFO) {
1138    owl_function_debugmsg("userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1139    owl_function_debugmsg("userinfo: prof: %s\n", prof ? prof : "[none]");
1140  } else if (inforeq == AIM_GETINFO_AWAYMESSAGE) {
1141    owl_function_debugmsg("userinfo: awaymsg_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
1142    owl_function_debugmsg("userinfo: awaymsg: %s\n", prof ? prof : "[none]");
1143  } else if (inforeq == AIM_GETINFO_CAPABILITIES) {
1144    owl_function_debugmsg("userinfo: capabilities: see above\n");
1145  } else {
1146    owl_function_debugmsg("userinfo: unknown info request\n");
1147  }
1148  */
1149  return(1);
1150}
1151
1152/*
1153 * Channel 1: Standard Message
1154 */
1155static int faimtest_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args)
1156{
1157  owl_message *m;
1158  char *stripmsg, *nz_screenname, *wrapmsg;
1159  char realmsg[8192+1] = "";
1160  /* int clienttype = AIM_CLIENTTYPE_UNKNOWN; */
1161
1162  /* clienttype = aim_fingerprintclient(args->features, args->featureslen); */
1163
1164  /*
1165  printf("icbm: sn = \"%s\"\n", userinfo->sn);
1166  printf("icbm: probable client type: %d\n", clienttype);
1167  printf("icbm: warnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
1168  printf("icbm: flags = 0x%04x = ", userinfo->flags);
1169  printuserflags(userinfo->flags);
1170  printf("\n");
1171  */
1172
1173  /*
1174  printf("icbm: membersince = %lu\n", userinfo->membersince);
1175  printf("icbm: onlinesince = %lu\n", userinfo->onlinesince);
1176  printf("icbm: idletime = 0x%04x\n", userinfo->idletime);
1177  printf("icbm: capabilities = %s = 0x%08lx\n", (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present", userinfo->capabilities);
1178  */
1179
1180  /*
1181  printf("icbm: icbmflags = ");
1182  if (args->icbmflags & AIM_IMFLAGS_AWAY) printf("away ");
1183  if (args->icbmflags & AIM_IMFLAGS_ACK) printf("ackrequest ");
1184  if (args->icbmflags & AIM_IMFLAGS_OFFLINE) printf("offline ");
1185  if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) printf("buddyreq ");
1186  if (args->icbmflags & AIM_IMFLAGS_HASICON) printf("hasicon ");
1187  printf("\n");
1188  */
1189
1190  /*
1191  if (args->icbmflags & AIM_IMFLAGS_CUSTOMCHARSET) {
1192  printf("icbm: encoding flags = {%04x, %04x}\n", args->charset, args->charsubset);
1193  }
1194  */
1195 
1196  /*
1197   * Quickly convert it to eight bit format, replacing non-ASCII UNICODE
1198   * characters with their equivelent HTML entity.
1199   */
1200  if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
1201    int i;
1202   
1203    for (i=0; i<args->msglen; i+=2) {
1204      fu16_t uni;
1205
1206      uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
1207      if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
1208        snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
1209      } else { /* something else, do UNICODE entity */
1210        snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
1211      }
1212    }
1213  } else {
1214    /*
1215     * For non-UNICODE encodings (ASCII and ISO 8859-1), there is
1216     * no need to do anything special here.  Most
1217     * terminals/whatever will be able to display such characters
1218     * unmodified.
1219     *
1220     * Beware that PC-ASCII 128 through 159 are _not_ actually
1221     * defined in ASCII or ISO 8859-1, and you should send them as
1222     * UNICODE.  WinAIM will send these characters in a UNICODE
1223     * message, so you need to do so as well.
1224     *
1225     * You may not think it necessary to handle UNICODE messages. 
1226     * You're probably wrong.  For one thing, Microsoft "Smart
1227     * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
1228     * but real UNICODE). If you don't parse UNICODE at all, your
1229     * users will get a blank message instead of the message
1230     * containing Smart Quotes.
1231     *
1232     */
1233    if (args->msg && args->msglen)
1234      strncpy(realmsg, args->msg, sizeof(realmsg));
1235  }
1236
1237  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: message from: %s", userinfo->sn?userinfo->sn:"");
1238  /* create a message, and put it on the message queue */
1239  stripmsg=owl_text_htmlstrip(realmsg);
1240  wrapmsg=owl_text_wordwrap(stripmsg, 70);
1241  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1242  m=owl_malloc(sizeof(owl_message));
1243  owl_message_create_aim(m,
1244                         nz_screenname,
1245                         owl_global_get_aim_screenname(&g),
1246                         wrapmsg,
1247                         OWL_MESSAGE_DIRECTION_IN,
1248                         0);
1249  if (args->icbmflags & AIM_IMFLAGS_AWAY) owl_message_set_attribute(m, "isauto", "");
1250  owl_global_messagequeue_addmsg(&g, m);
1251  owl_free(stripmsg);
1252  owl_free(wrapmsg);
1253  owl_free(nz_screenname);
1254
1255  return(1);
1256
1257  owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: message: %s\n", realmsg);
1258 
1259  if (args->icbmflags & AIM_IMFLAGS_MULTIPART) {
1260    aim_mpmsg_section_t *sec;
1261    int z;
1262
1263    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: multipart: this message has %d parts\n", args->mpmsg.numparts);
1264   
1265    for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++) {
1266      if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff)) {
1267        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);
1268      } else {
1269        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);
1270      }
1271    }
1272  }
1273 
1274  if (args->icbmflags & AIM_IMFLAGS_HASICON) {
1275    /* aim_send_im(sess, userinfo->sn, AIM_IMFLAGS_BUDDYREQ, "You have an icon"); */
1276    owl_function_debugmsg("faimtest_parse_incoming_im_chan1: icbm: their icon: iconstamp = %ld, iconlen = 0x%08x, iconsum = 0x%04x\n", args->iconstamp, args->iconlen, args->iconsum);
1277  }
1278
1279  /*
1280  if (realmsg) {
1281    int i = 0;
1282    while (realmsg[i] == '<') {
1283      if (realmsg[i] == '<') {
1284        while (realmsg[i] != '>')
1285          i++;
1286        i++;
1287      }
1288    }
1289    tmpstr = realmsg+i;
1290    faimtest_handlecmd(sess, conn, userinfo, tmpstr);
1291  }
1292  */
1293 
1294  return(1);
1295}
1296
1297/*
1298 * Channel 2: Rendevous Request
1299 */
1300static int faimtest_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args)
1301{
1302  /*
1303  printf("rendezvous: source sn = %s\n", userinfo->sn);
1304  printf("rendezvous: \twarnlevel = %f\n", aim_userinfo_warnlevel(userinfo));
1305  printf("rendezvous: \tclass = 0x%04x = ", userinfo->flags);
1306  printuserflags(userinfo->flags);
1307  printf("\n");
1308 
1309  printf("rendezvous: \tonlinesince = %lu\n", userinfo->onlinesince);
1310  printf("rendezvous: \tidletime = 0x%04x\n", userinfo->idletime);
1311 
1312  printf("rendezvous: message/description = %s\n", args->msg);
1313  printf("rendezvous: encoding = %s\n", args->encoding);
1314  printf("rendezvous: language = %s\n", args->language);
1315  */
1316 
1317  if (args->reqclass == AIM_CAPS_SENDFILE) {
1318    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: send file!");
1319  } else if (args->reqclass == AIM_CAPS_CHAT) {
1320    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);
1321    /*
1322    printf("chat invitation: room name = %s\n", args->info.chat.roominfo.name);
1323    printf("chat invitation: exchange = 0x%04x\n", args->info.chat.roominfo.exchange);
1324    printf("chat invitation: instance = 0x%04x\n", args->info.chat.roominfo.instance);
1325    */
1326    /* Automatically join room... */
1327    /* printf("chat invitiation: autojoining %s...\n", args->info.chat.roominfo.name); */
1328
1329    /* aim_chat_join(sess, conn, args->info.chat.roominfo.exchange, args->info.chat.roominfo.name, args->info.chat.roominfo.instance); */
1330  } else if (args->reqclass == AIM_CAPS_BUDDYICON) {
1331    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: Buddy Icon from %s, length = %u\n",
1332                          userinfo->sn, args->info.icon.length);
1333  } else if (args->reqclass == AIM_CAPS_ICQRTF) {
1334    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: RTF message from %s: (fgcolor = 0x%08x, bgcolor = 0x%08x) %s\n",
1335                          userinfo->sn, args->info.rtfmsg.fgcolor, args->info.rtfmsg.bgcolor, args->info.rtfmsg.rtfmsg);
1336  } else {
1337    owl_function_debugmsg("faimtest_parse_incoming_im_chan2: icbm: unknown reqclass (%d)\n", args->reqclass);
1338  }
1339  return 1;
1340}
1341
1342static int faimtest_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
1343{
1344  fu16_t channel;
1345  aim_userinfo_t *userinfo;
1346  va_list ap;
1347  int ret = 0;
1348 
1349  va_start(ap, fr);
1350  channel = (fu16_t)va_arg(ap, unsigned int);
1351  userinfo = va_arg(ap, aim_userinfo_t *);
1352 
1353  if (channel == 1) {
1354    struct aim_incomingim_ch1_args *args;
1355    args = va_arg(ap, struct aim_incomingim_ch1_args *);
1356    ret = faimtest_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
1357  } else if (channel == 2) {
1358    struct aim_incomingim_ch2_args *args;
1359    args = va_arg(ap, struct aim_incomingim_ch2_args *);
1360    ret = faimtest_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
1361  } else {
1362    owl_function_debugmsg("faimtest_parse_incoming_im: unsupported channel 0x%04x\n", channel);
1363  }
1364  va_end(ap);
1365  owl_function_debugmsg("faimtest_parse_incoming_im: done with ICBM handling (ret = %d)\n", ret);
1366  return 1;
1367}
1368
1369static int faimtest_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
1370{
1371  aim_userinfo_t *userinfo;
1372  char *nz_screenname;
1373  owl_buddy *b;
1374  va_list ap;
1375  va_start(ap, fr);
1376  userinfo = va_arg(ap, aim_userinfo_t *);
1377  va_end(ap);
1378
1379  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1380 
1381  owl_buddylist_oncoming(owl_global_get_buddylist(&g), nz_screenname);
1382
1383  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1384    owl_function_debugmsg("faimtest_parseoncoming: in empty part of userinfo present and present idle");
1385  }
1386
1387  b=owl_buddylist_get_aim_buddy(owl_global_get_buddylist(&g), nz_screenname);
1388  if (!b) {
1389    owl_function_debugmsg("Error: parse_oncoming setting idle time with no buddy present.");
1390    return(1);
1391  }
1392  if (userinfo->idletime==0) {
1393    owl_buddy_set_unidle(b);
1394  } else {
1395    owl_buddy_set_idle(b);
1396    owl_buddy_set_idle_since(b, userinfo->idletime);
1397  }
1398
1399  if (userinfo->flags & AIM_FLAG_AWAY) {
1400    owl_function_debugmsg("parse_oncoming sn: %s away flag!", userinfo->sn);
1401  }
1402 
1403  owl_function_debugmsg("parse_oncoming sn: %s idle: %i", userinfo->sn, userinfo->idletime);
1404   
1405  owl_free(nz_screenname);
1406 
1407  /*
1408    printf("%ld  %s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1409    time(NULL),
1410    userinfo->sn, userinfo->flags,
1411    (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1412    (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1413    (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1414    (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1415    (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1416    (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1417    (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1418    (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1419    (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1420    userinfo->capabilities);
1421  */
1422  return(1);
1423}
1424
1425static int faimtest_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
1426{
1427  aim_userinfo_t *userinfo;
1428  char *nz_screenname;
1429  va_list ap;
1430 
1431  va_start(ap, fr);
1432  userinfo = va_arg(ap, aim_userinfo_t *);
1433  va_end(ap);
1434
1435  nz_screenname=owl_aim_normalize_screenname(userinfo->sn);
1436  owl_buddylist_offgoing(owl_global_get_buddylist(&g), nz_screenname);
1437  owl_free(nz_screenname);
1438
1439  if (userinfo->present & AIM_USERINFO_PRESENT_IDLE) {
1440    owl_function_debugmsg("parse_offgoing sn: %s idle time %i", userinfo->sn, userinfo->idletime);
1441  }
1442
1443  /*
1444  printf("%ld  %s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = %s = 0x%08lx)\n",
1445         time(NULL),
1446         userinfo->sn, userinfo->flags,
1447         (userinfo->flags&AIM_FLAG_UNCONFIRMED)?" UNCONFIRMED":"",
1448         (userinfo->flags&AIM_FLAG_ADMINISTRATOR)?" ADMINISTRATOR":"",
1449         (userinfo->flags&AIM_FLAG_AOL)?" AOL":"",
1450         (userinfo->flags&AIM_FLAG_OSCAR_PAY)?" OSCAR_PAY":"",
1451         (userinfo->flags&AIM_FLAG_FREE)?" FREE":"",
1452         (userinfo->flags&AIM_FLAG_AWAY)?" AWAY":"",
1453         (userinfo->flags&AIM_FLAG_ICQ)?" ICQ":"",
1454         (userinfo->flags&AIM_FLAG_WIRELESS)?" WIRELESS":"",
1455         (userinfo->present & AIM_USERINFO_PRESENT_CAPABILITIES) ? "present" : "not present",
1456         userinfo->capabilities);
1457  */
1458 
1459  return 1;
1460}
1461
1462/* Used by chat as well. */
1463int faimtest_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
1464{
1465  va_list ap;
1466  fu16_t reason;
1467 
1468  va_start(ap, fr);
1469  reason = (fu16_t)va_arg(ap, unsigned int);
1470  va_end(ap);
1471 
1472  /* printf("snac threw error (reason 0x%04x: %s)\n", reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1473  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1474 
1475  return 1;
1476}
1477
1478static int faimtest_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
1479{
1480  va_list ap;
1481  const char *destsn;
1482  fu16_t reason;
1483 
1484  va_start(ap, fr);
1485  reason = (fu16_t)va_arg(ap, unsigned int);
1486  destsn = va_arg(ap, const char *);
1487  va_end(ap);
1488 
1489  /* printf("message to %s bounced (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1490  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1491
1492  if (reason==4) {
1493    owl_function_adminmsg("", "Could not send AIM message, user not logged on");
1494  }
1495 
1496  return 1;
1497}
1498
1499static int faimtest_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
1500{
1501  va_list ap;
1502  const char *destsn;
1503  fu16_t reason;
1504 
1505  va_start(ap, fr);
1506  reason = (fu16_t)va_arg(ap, unsigned int);
1507  destsn = va_arg(ap, const char *);
1508  va_end(ap);
1509 
1510  /* printf("user information for %s unavailable (reason 0x%04x: %s)\n", destsn, reason, (reason<msgerrreasonslen)?msgerrreasons[reason]:"unknown"); */
1511  if (reason<msgerrreasonslen) owl_function_error("%s", msgerrreasons[reason]);
1512 
1513  return 1;
1514}
1515
1516static int faimtest_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
1517{
1518  static const char *missedreasons[] = {
1519    "Invalid (0)",
1520    "Message too large",
1521    "Rate exceeded",
1522    "Evil Sender",
1523    "Evil Receiver"
1524  };
1525  static int missedreasonslen = 5;
1526 
1527  va_list ap;
1528  fu16_t chan, nummissed, reason;
1529  aim_userinfo_t *userinfo;
1530 
1531  va_start(ap, fr);
1532  chan = (fu16_t)va_arg(ap, unsigned int);
1533  userinfo = va_arg(ap, aim_userinfo_t *);
1534  nummissed = (fu16_t)va_arg(ap, unsigned int);
1535  reason = (fu16_t)va_arg(ap, unsigned int);
1536  va_end(ap);
1537 
1538  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");
1539 
1540  return 1;
1541}
1542
1543/*
1544 * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
1545 */
1546static int faimtest_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
1547{
1548  va_list ap;
1549  fu16_t type;
1550  const char *sn = NULL;
1551 
1552  va_start(ap, fr);
1553  type = (fu16_t)va_arg(ap, unsigned int);
1554  sn = va_arg(ap, const char *);
1555  va_end(ap);
1556 
1557  owl_function_debugmsg("faimtest_parse_msgack: 0x%04x / %s\n", type, sn);
1558 
1559  return 1;
1560}
1561
1562static int faimtest_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
1563{
1564  static const char *codes[5] = {
1565    "invalid",
1566    "change",
1567    "warning",
1568    "limit",
1569    "limit cleared"
1570  };
1571  va_list ap;
1572  fu16_t code, rateclass;
1573  fu32_t windowsize, clear, alert, limit, disconnect;
1574  fu32_t currentavg, maxavg;
1575 
1576  va_start(ap, fr); 
1577 
1578  /* See code explanations below */
1579  code = (fu16_t)va_arg(ap, unsigned int);
1580 
1581  /*
1582   * See comments above aim_parse_ratechange_middle() in aim_rxhandlers.c.
1583   */
1584  rateclass = (fu16_t)va_arg(ap, unsigned int);
1585 
1586  /*
1587   * Not sure what this is exactly.  I think its the temporal
1588   * relation factor (ie, how to make the rest of the numbers
1589   * make sense in the real world).
1590   */
1591  windowsize = va_arg(ap, fu32_t);
1592 
1593  /* Explained below */
1594  clear = va_arg(ap, fu32_t);
1595  alert = va_arg(ap, fu32_t);
1596  limit = va_arg(ap, fu32_t);
1597  disconnect = va_arg(ap, fu32_t);
1598  currentavg = va_arg(ap, fu32_t);
1599  maxavg = va_arg(ap, fu32_t);
1600 
1601  va_end(ap);
1602 
1603  owl_function_debugmsg("faimtest_parse_ratechange: rate %s (rate class 0x%04x): curavg = %u, maxavg = %u, alert at %u, clear warning at %u, limit at %u, disconnect at %u (window size = %u)",
1604                        (code < 5)?codes[code]:"invalid",
1605                        rateclass,
1606                        currentavg, maxavg,
1607                        alert, clear,
1608                        limit, disconnect,
1609                        windowsize);
1610  return 1;
1611}
1612
1613static int faimtest_parse_evilnotify(aim_session_t *sess, aim_frame_t *fr, ...)
1614{
1615  va_list ap;
1616  fu16_t newevil;
1617  aim_userinfo_t *userinfo;
1618 
1619  va_start(ap, fr);
1620  newevil = (fu16_t)va_arg(ap, unsigned int);
1621  userinfo = va_arg(ap, aim_userinfo_t *);
1622  va_end(ap);
1623 
1624  /*
1625   * Evil Notifications that are lacking userinfo->sn are anon-warns
1626   * if they are an evil increases, but are not warnings at all if its
1627   * a decrease (its the natural backoff happening).
1628   *
1629   * newevil is passed as an int representing the new evil value times
1630   * ten.
1631   */
1632  owl_function_debugmsg("faimtest_parse_evilnotify: new value = %2.1f%% (caused by %s)\n", ((float)newevil)/10, (userinfo && strlen(userinfo->sn))?userinfo->sn:"anonymous");
1633 
1634  return 1;
1635}
1636
1637static int faimtest_parse_searchreply(aim_session_t *sess, aim_frame_t *fr, ...)
1638{
1639  va_list ap;
1640  const char *address, *SNs;
1641  int num, i;
1642  owl_list list;
1643 
1644  va_start(ap, fr);
1645  address = va_arg(ap, const char *);
1646  num = va_arg(ap, int);
1647  SNs = va_arg(ap, const char *);
1648  va_end(ap);
1649
1650  owl_list_create(&list);
1651 
1652  owl_function_debugmsg("faimtest_parse_searchreply: E-Mail Search Results for %s: ", address);
1653  for (i=0; i<num; i++) {
1654    owl_function_debugmsg("  %s", &SNs[i*(MAXSNLEN+1)]);
1655    owl_list_append_element(&list, (void *)&SNs[i*(MAXSNLEN+1)]);
1656  }
1657  owl_function_aimsearch_results(address, &list);
1658  owl_list_free_simple(&list);
1659  return(1);
1660}
1661
1662static int faimtest_parse_searcherror(aim_session_t *sess, aim_frame_t *fr, ...)
1663{
1664  va_list ap;
1665  const char *address;
1666 
1667  va_start(ap, fr);
1668  address = va_arg(ap, const char *);
1669  va_end(ap);
1670
1671  owl_function_error("No results searching for %s", address);
1672  owl_function_debugmsg("faimtest_parse_searcherror: E-Mail Search Results for %s: No Results or Invalid Email\n", address);
1673 
1674  return(1);
1675}
1676
1677static int handlepopup(aim_session_t *sess, aim_frame_t *fr, ...)
1678{
1679  va_list ap;
1680  const char *msg, *url;
1681  fu16_t width, height, delay;
1682 
1683  va_start(ap, fr);
1684  msg = va_arg(ap, const char *);
1685  url = va_arg(ap, const char *);
1686  width = va_arg(ap, unsigned int);
1687  height = va_arg(ap, unsigned int);
1688  delay = va_arg(ap, unsigned int);
1689  va_end(ap);
1690 
1691  owl_function_debugmsg("handlepopup: (%dx%x:%d) %s (%s)\n", width, height, delay, msg, url);
1692 
1693  return 1;
1694}
1695
1696static int serverpause(aim_session_t *sess, aim_frame_t *fr, ...)
1697{
1698  aim_sendpauseack(sess, fr->conn);
1699  return 1;
1700}
1701
1702static int migrate(aim_session_t *sess, aim_frame_t *fr, ...)
1703{
1704  va_list ap;
1705  aim_conn_t *bosconn;
1706  const char *bosip;
1707  fu8_t *cookie;
1708 
1709  va_start(ap, fr);
1710  bosip = va_arg(ap, const char *);
1711  cookie = va_arg(ap, fu8_t *);
1712  va_end(ap);
1713 
1714  owl_function_debugmsg("migrate: migration in progress -- new BOS is %s -- disconnecting", bosip);
1715  aim_conn_kill(sess, &fr->conn);
1716 
1717  if (!(bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, bosip))) {
1718    owl_function_debugmsg("migrate: could not connect to BOS: internal error");
1719    return 1;
1720  } else if (bosconn->status & AIM_CONN_STATUS_CONNERR) {       
1721    owl_function_debugmsg("migrate: could not connect to BOS");
1722    aim_conn_kill(sess, &bosconn);
1723    return 1;
1724  }
1725 
1726  /* Login will happen all over again. */
1727  addcb_bos(sess, bosconn);
1728  /* aim_sendcookie(sess, bosconn, cookie); */ /********/
1729  return 1;
1730}
1731
1732static int ssirights(aim_session_t *sess, aim_frame_t *fr, ...)
1733{
1734  owl_function_debugmsg("ssirights: got SSI rights, requesting data\n");
1735  /* aim_ssi_reqdata(sess, fr->conn, 0, 0x0000); */
1736  aim_ssi_reqdata(sess);
1737 
1738  return(1);
1739}
1740
1741static int ssidata(aim_session_t *sess, aim_frame_t *fr, ...)
1742{
1743  va_list ap;
1744  fu8_t fmtver;
1745  fu16_t itemcount;
1746  fu32_t stamp;
1747  struct aim_ssi_item *list;
1748  /*
1749  struct aim_ssi_item *curitem;
1750  struct aim_ssi_item *l;
1751  */
1752 
1753  va_start(ap, fr);
1754  fmtver = va_arg(ap, unsigned int);
1755  itemcount = va_arg(ap, unsigned int);
1756  stamp = va_arg(ap, fu32_t);
1757  list = va_arg(ap, struct aim_ssi_item *);
1758  va_end(ap);
1759 
1760  owl_function_debugmsg("ssiddata: got SSI data (0x%02x, %d items, %u)", fmtver, itemcount, stamp);
1761  /*
1762  for (curitem=sess->ssi.local; curitem; curitem=curitem->next) {
1763    for (l = list; l; l = l->next) {
1764      owl_function_debugmsg("\t0x%04x (%s) - 0x%04x/0x%04x", l->type, l->name, l->gid, l->bid);
1765    }
1766  }
1767  */
1768  aim_ssi_enable(sess);
1769 
1770  return 1;
1771}
1772
1773static int ssidatanochange(aim_session_t *sess, aim_frame_t *fr, ...)
1774{
1775  owl_function_debugmsg("ssidatanochange: server says we have the latest SSI data already");
1776  /* aim_ssi_enable(sess, fr->conn); */
1777  aim_ssi_enable(sess);
1778  return 1;
1779}
1780
1781static int offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...)
1782{
1783  va_list ap;
1784  struct aim_icq_offlinemsg *msg;
1785 
1786  va_start(ap, fr);
1787  msg = va_arg(ap, struct aim_icq_offlinemsg *);
1788  va_end(ap);
1789 
1790  if (msg->type == 0x0001) {
1791    owl_function_debugmsg("offlinemsg: from %u at %d/%d/%d %02d:%02d : %s", msg->sender, msg->year, msg->month, msg->day, msg->hour, msg->minute, msg->msg);
1792  } else {
1793    owl_function_debugmsg("unknown offline message type 0x%04x", msg->type);
1794  }
1795  return 1;
1796}
1797
1798static int offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...)
1799{
1800  /* Tell the server to delete them. */
1801  owl_function_debugmsg("offlinemsg done: ");
1802  aim_icq_ackofflinemsgs(sess);
1803  return 1;
1804}
1805
1806
1807/******************** chat.c **************************/
1808
1809static int faimtest_chat_join(aim_session_t *sess, aim_frame_t *fr, ...)
1810{
1811  va_list ap;
1812  aim_userinfo_t *userinfo;
1813  int count;
1814  /* int i; */
1815 
1816  va_start(ap, fr);
1817  count = va_arg(ap, int);
1818  userinfo = va_arg(ap, aim_userinfo_t *);
1819  va_end(ap);
1820
1821  owl_function_debugmsg("In faimtest_chat_join");
1822  /*
1823  printf("chat: %s:  New occupants have joined:\n", aim_chat_getname(fr->conn));
1824  for (i = 0; i < count; i++)
1825    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
1826  */
1827  return 1;
1828}
1829
1830static int faimtest_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...)
1831{
1832  aim_userinfo_t *userinfo;
1833  va_list ap;
1834  int count;
1835  /* int i; */
1836
1837 
1838  va_start(ap, fr);
1839  count = va_arg(ap, int);
1840  userinfo = va_arg(ap, aim_userinfo_t *);
1841  va_end(ap);
1842 
1843  /*
1844    printf("chat: %s:  Some occupants have left:\n", aim_chat_getname(fr->conn));
1845   
1846    for (i = 0; i < count; i++)
1847    printf("chat: %s: \t%s\n", aim_chat_getname(fr->conn), userinfo[i].sn);
1848  */
1849  return 1;
1850}
1851
1852static int faimtest_chat_infoupdate(aim_session_t *sess, aim_frame_t *fr, ...)
1853{
1854  va_list ap;
1855  aim_userinfo_t *userinfo;
1856  struct aim_chat_roominfo *roominfo;
1857  const char *roomname;
1858  int usercount;
1859  const char *roomdesc;
1860  fu16_t flags, unknown_d2, unknown_d5, maxmsglen, maxvisiblemsglen;
1861  fu32_t creationtime;
1862  const char *croomname;
1863  /* int i; */
1864 
1865  croomname = aim_chat_getname(fr->conn);
1866 
1867  va_start(ap, fr);
1868  roominfo = va_arg(ap, struct aim_chat_roominfo *);
1869  roomname = va_arg(ap, const char *);
1870  usercount = va_arg(ap, int);
1871  userinfo = va_arg(ap, aim_userinfo_t *);
1872  roomdesc = va_arg(ap, const char *);
1873  flags = (fu16_t)va_arg(ap, unsigned int);
1874  creationtime = va_arg(ap, fu32_t);
1875  maxmsglen = (fu16_t)va_arg(ap, unsigned int);
1876  unknown_d2 = (fu16_t)va_arg(ap, unsigned int);
1877  unknown_d5 = (fu16_t)va_arg(ap, unsigned int);
1878  maxvisiblemsglen = (fu16_t)va_arg(ap, unsigned int);
1879  va_end(ap);
1880
1881  owl_function_debugmsg("In faimtest_chat_infoupdate");
1882  /*
1883  printf("chat: %s:  info update:\n", croomname);
1884  printf("chat: %s:  \tRoominfo: {%04x, %s, %04x}\n", croomname, roominfo->exchange, roominfo->name, roominfo->instance);
1885  printf("chat: %s:  \tRoomname: %s\n", croomname, roomname);
1886  printf("chat: %s:  \tRoomdesc: %s\n", croomname, roomdesc);
1887  printf("chat: %s:  \tOccupants: (%d)\n", croomname, usercount);
1888
1889  for (i = 0; i < usercount; i++)
1890    printf("chat: %s:  \t\t%s\n", croomname, userinfo[i].sn);
1891 
1892  owl_function_debugmsg("chat: %s:  \tRoom flags: 0x%04x (%s%s%s%s)\n",
1893         croomname, flags,
1894         (flags & AIM_CHATROOM_FLAG_EVILABLE) ? "Evilable, " : "",
1895         (flags & AIM_CHATROOM_FLAG_NAV_ONLY) ? "Nav Only, " : "",
1896         (flags & AIM_CHATROOM_FLAG_INSTANCING_ALLOWED) ? "Instancing allowed, " : "",
1897         (flags & AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED) ? "Occupant peek allowed, " : "");
1898  printf("chat: %s:  \tCreation time: %lu (time_t)\n", croomname, creationtime);
1899  printf("chat: %s:  \tUnknown_d2: 0x%04x\n", croomname, unknown_d2);
1900  printf("chat: %s:  \tUnknown_d5: 0x%02x\n", croomname, unknown_d5);
1901  printf("chat: %s:  \tMax message length: %d bytes\n", croomname, maxmsglen);
1902  printf("chat: %s:  \tMax visible message length: %d bytes\n", croomname, maxvisiblemsglen);
1903  */
1904 
1905  return(1);
1906}
1907
1908static int faimtest_chat_incomingmsg(aim_session_t *sess, aim_frame_t *fr, ...)
1909{
1910  va_list ap;
1911  aim_userinfo_t *userinfo;
1912  const char *msg;
1913  char tmpbuf[1152];
1914 
1915  va_start(ap, fr);
1916  userinfo = va_arg(ap, aim_userinfo_t *);     
1917  msg = va_arg(ap, const char *);
1918  va_end(ap);
1919
1920  owl_function_debugmsg("in faimtest_chat_incomingmsg");
1921
1922  /*
1923  printf("chat: %s: incoming msg from %s: %s\n", aim_chat_getname(fr->conn), userinfo->sn, msg);
1924  */
1925 
1926  /*
1927   * Do an echo for testing purposes.  But not for ourselves ("oops!")
1928   */
1929  if (strcmp(userinfo->sn, sess->sn) != 0) {
1930    /* sprintf(tmpbuf, "(%s said \"%s\")", userinfo->sn, msg); */
1931    aim_chat_send_im(sess, fr->conn, 0, tmpbuf, strlen(tmpbuf));
1932  }
1933 
1934  return 1;
1935}
1936
1937static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...)
1938{
1939  owl_function_debugmsg("faimtest_conninitdone_chat:");
1940
1941  aim_conn_addhandler(sess, fr->conn, 0x000e, 0x0001, faimtest_parse_genericerr, 0);
1942  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, faimtest_chat_join, 0);
1943  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, faimtest_chat_leave, 0);
1944  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, faimtest_chat_infoupdate, 0);
1945  aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, faimtest_chat_incomingmsg, 0);
1946 
1947  aim_clientready(sess, fr->conn);
1948 
1949  owl_function_debugmsg("Chat ready");
1950
1951  /*
1952    chatcon = find_oscar_chat_by_conn(gc, fr->conn);
1953    chatcon->id = id;
1954    chatcon->cnv = serv_got_joined_chat(gc, id++, chatcon->show);
1955  */
1956  return(1);
1957}
1958
1959void chatnav_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
1960{
1961  aim_conn_t *tstconn;
1962
1963  owl_function_debugmsg("in faimtest_chatnav_redirect");
1964 
1965  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, redir->ip);
1966  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
1967    /* printf("unable to connect to chat(nav) server\n"); */
1968    if (tstconn)
1969      aim_conn_kill(sess, &tstconn);
1970    return;
1971  }
1972 
1973  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
1974  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
1975  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
1976  /* printf("chatnav: connected\n"); */
1977  return;
1978}
1979
1980/* XXX this needs instance too */
1981void chat_redirect(aim_session_t *sess, struct aim_redirect_data *redir)
1982{
1983  aim_conn_t *tstconn;
1984
1985  owl_function_debugmsg("in chat_redirect");
1986 
1987  tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, redir->ip);
1988  if (!tstconn || (tstconn->status & AIM_CONN_STATUS_RESOLVERR)) {
1989    /* printf("unable to connect to chat server\n"); */
1990    if (tstconn) aim_conn_kill(sess, &tstconn);
1991    return; 
1992  }             
1993  /* printf("chat: connected to %s instance %d on exchange %d\n", redir->chat.room, redir->chat.instance, redir->chat.exchange); */
1994 
1995  /*
1996   * We must do this to attach the stored name to the connection!
1997   */
1998  aim_chat_attachname(tstconn, redir->chat.exchange, redir->chat.room, redir->chat.instance);
1999  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, faimtest_conncomplete, 0);
2000  aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0);
2001  aim_sendcookie(sess, tstconn, redir->cookielen, redir->cookie);
2002  return;       
2003}
2004
2005void owl_process_aim()
2006{
2007  if (owl_global_is_doaimevents(&g)) {
2008    owl_aim_process_events();
2009  }
2010}
Note: See TracBrowser for help on using the repository browser.