source: aim.c @ fd93b41

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