]> andersk Git - libfaim.git/blame - utils/faimtest/faimtest.c
Integrated session changes needed for Jabber transport. Lots of changes.
[libfaim.git] / utils / faimtest / faimtest.c
CommitLineData
9de3ca7e 1/*
2 * -----------------------------------------------------------
3 * ProtoFAIM: v1.xx.xxplxx
4 * -----------------------------------------------------------
5 *
6 * This is ProtoFAIM v1.xx.xxplxx!!! Its nearly completely
7 * different than that ugly thing called v0. This app is
8 * compatible with the latest version of the libfaim library.
9 * Work is continuing.
10 *
11 * ProtoFAIM should only be used for two things...
12 * 1) Testing the libfaim backend.
13 * 2) For reference on the libfaim API when developing clients.
14 *
15 * Its very ugly. Probably always will be. Nothing is more
16 * ugly than the backend itself, however.
17 *
18 * -----------------------------------------------------------
19 *
20 * I'm releasing this code and all it's associated linkage
21 * under the GNU General Public License. For more information,
22 * please refer to http://www.fsf.org. For any questions,
23 * please contact me at the address below.
24 *
25 * Most everything:
26 * (c) 1998 Adam Fritzler, PST, afritz@iname.com
27 *
28 * The password algorithms
29 * (c) 1998 Brock Wilcox, awwaiid@iname.com
30 *
31 * THERE IS NO CODE FROM AOL'S AIM IN THIS CODE, NOR
32 * WAS THERE ANY DISASSEMBLAGE TO DEFINE PROTOCOL. All
33 * information was gained through painstakingly comparing
34 * TCP dumps while the AIM Java client was running. Nothing
35 * more than that, except for a lot of experimenting.
36 *
37 * -----------------------------------------------------------
38 *
39 */
40
41/*
42 Current status:
43
44
45 */
46
47#define FAIMTEST_SCREENNAME "SN"
48#define FAIMTEST_PASSWORD "PASS"
49
50#include "aim.h" /* for struct defs, global ptrs, etc */
51
52int faimtest_parse_oncoming(struct command_rx_struct *, ...);
53int faimtest_parse_offgoing(struct command_rx_struct *, ...);
54int faimtest_parse_login_phase3d_f(struct command_rx_struct *, ...);
55int faimtest_auth_error(struct command_rx_struct *, ...);
56int faimtest_auth_success(struct command_rx_struct *, ...);
57int faimtest_parse_incoming_im(struct command_rx_struct *command, ...);
58int faimtest_parse_userinfo(struct command_rx_struct *command, ...);
59int faimtest_handleredirect(struct command_rx_struct *command, ...);
60int faimtest_authsvrready(struct command_rx_struct *command, ...);
61int faimtest_pwdchngdone(struct command_rx_struct *command, ...);
62int faimtest_serverready(struct command_rx_struct *command, ...);
63int faimtest_parse_misses(struct command_rx_struct *command, ...);
49c8a2fa 64
9de3ca7e 65int main(void)
66{
67
9de3ca7e 68 struct client_info_s info = {"FAIMtest (Hi guys!)", 3, 90, 42, "us", "en"};
69 struct aim_conn_t *authconn = NULL;
70 int stayconnected = 1;
71
72 aim_connrst(); /* reset connection array -- there's a better place for this*/
73 /* register our callback array (optional) */
74 //aim_register_callbacks(faimtest_callbacks);
75
76 enter:
77 authconn = aim_newconn(AIM_CONN_TYPE_AUTH, FAIM_LOGIN_SERVER);
78
79 if (authconn == NULL)
80 {
81 fprintf(stderr, "faimtest: internal connection error while in aim_login. bailing out.\n");
82 return -1;
83 }
84 else if (authconn->fd == -1)
85 {
86 if (authconn->status & AIM_CONN_STATUS_RESOLVERR)
87 fprintf(stderr, "faimtest: could not resolve authorizer name\n");
88 else if (authconn->status & AIM_CONN_STATUS_CONNERR)
89 fprintf(stderr, "faimtest: could not connect to authorizer\n");
90 return -1;
91 }
92 else
93 {
94 aim_conn_addhandler(authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR, faimtest_auth_error, 0);
95 aim_conn_addhandler(authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_AUTHSUCCESS, faimtest_auth_success, 0);
96 aim_conn_addhandler(authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
97 aim_send_login(authconn, FAIMTEST_SCREENNAME, FAIMTEST_PASSWORD, &info);
98 }
99
100 while (aim_select(NULL) > (struct aim_conn_t *)0)
101 {
102 if (aim_queue_outgoing)
103 aim_tx_flushqueue();
104
105 if (aim_get_command() < 0)
106 {
107 printf("\afaimtest: connection error!\n");
108 }
109 else
110 aim_rxdispatch();
111 }
112
113 /* Close up */
114 printf("AIM just decided we didn't need to be here anymore, closing up.,,\n");
115
116 /* close up all connections, dead or no */
117 aim_logoff();
118
119 if (stayconnected)
120 {
121 printf("\nTrying to reconnect in 2 seconds...\n");
122 sleep(2);
123 goto enter;
124 }
125
126 /* Get out */
127 exit(0);
128}
129
130int faimtest_serverready(struct command_rx_struct *command, ...)
131{
132 switch (command->conn->type)
133 {
134 case AIM_CONN_TYPE_BOS:
135 aim_bos_reqrate(command->conn); /* request rate info */
136 aim_bos_ackrateresp(command->conn); /* ack rate info response -- can we say timing? */
137 aim_bos_setprivacyflags(command->conn, 0x00000003);
138
139#if 0
140 aim_bos_reqpersonalinfo(command->conn);
141#endif
142
143 aim_bos_reqservice(command->conn, AIM_CONN_TYPE_ADS); /* 0x05 == Advertisments */
144
145#if 0
146 aim_bos_reqrights(NULL);
147 aim_bos_reqbuddyrights(NULL);
148 aim_bos_reqlocaterights(NULL);
149 aim_bos_reqicbmparaminfo(NULL);
150#endif
151
152 /* set group permissions */
153 aim_bos_setgroupperm(NULL, 0x1f);
154 fprintf(stderr, "faimtest: done with BOS ServerReady\n");
155 break;
156 case AIM_CONN_TYPE_CHATNAV:
157 fprintf(stderr, "faimtest: chatnav: got server ready\n");
158 break;
159 default:
160 fprintf(stderr, "faimtest: unknown connection type on Server Ready\n");
161 }
162 return 1;
163}
164
165/*
166 handleredirect()...
167
168 This, of course, handles Service Redirects from OSCAR.
169
170 Should get passed in the following:
171 struct command_rx_struct *command
172 the raw command data
173 int serviceid
174 the destination service ID
175 char *serverip
176 the IP address of the service's server
177 char *cookie
178 the raw auth cookie
179 */
180int faimtest_handleredirect(struct command_rx_struct *command, ...)
181{
182 va_list ap;
183 int serviceid;
184 char *ip;
185 char *cookie;
186
187 /* this is the new buddy list */
188 char buddies[] = "Buddy1&Buddy2&";
189 /* this is the new profile */
190 char profile[] = "Hello";
191
192 va_start(ap, command);
193 serviceid = va_arg(ap, int);
194 ip = va_arg(ap, char *);
195 cookie = va_arg(ap, char *);
196 va_end(ap);
197
198 switch(serviceid)
199 {
200 case 0x0005: /* Advertisements */
201 /*
202 * The craziest explanation yet as to why we finish logging in when
203 * we get the advertisements redirect, of which we don't use anyway....
204 * IT WAS EASY!
205 */
206
207 /* send the buddy list and profile (required, even if empty) */
208 aim_bos_setbuddylist(command->conn, buddies);
209 aim_bos_setprofile(command->conn, profile);
210
211 /* send final login command (required) */
212 aim_bos_clientready(command->conn); /* tell BOS we're ready to go live */
213
214 /* you should now be ready to go */
215 printf("\nYou are now officially online. (%s)\n", ip);
216
217 break;
218 case 0x0007: /* Authorizer */
219 {
220 struct aim_conn_t *tstconn;
221 /* Open a connection to the Auth */
222 tstconn = aim_newconn(AIM_CONN_TYPE_AUTH, ip);
223 if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR) )
224 fprintf(stderr, "faimtest: unable to reconnect with authorizer\n");
225 else
226 /* Send the cookie to the Auth */
227 aim_auth_sendcookie(tstconn, cookie);
228
229 }
230 break;
231 case 0x000d: /* ChatNav */
232 {
233 struct aim_conn_t *tstconn = NULL;
234 tstconn = aim_newconn(AIM_CONN_TYPE_CHATNAV, ip);
235 if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
236 {
237 fprintf(stderr, "faimtest: unable to connect to chatnav server\n");
238 return 1;
239 }
240 aim_conn_addhandler(tstconn, AIM_CB_FAM_CTN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
241 aim_conn_addhandler(tstconn, AIM_CB_FAM_GEN, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
242 aim_auth_sendcookie(tstconn, cookie);
243 fprintf(stderr, "\achatnav: connected\n");
244 }
245 break;
246 case 0x000e: /* Chat */
247 {
248#if 0
249 struct aim_conn_t *tstconn = NULL;
250 tstconn = aim_newconn(AIM_CONN_TYPE_CHAT, ip);
251 if ( (tstconn==NULL) || (tstconn->status >= AIM_CONN_STATUS_RESOLVERR))
252 {
253 fprintf(stderr, "faimtest: unable to connect to chat server\n");
254 return 1;
255 }
256 aim_auth_sendcookie(aim_getconn_type(AIM_CONN_TYPE_CHAT), cookie);
257 fprintf(stderr, "\achat: connected\n");
258#endif
259 }
260 break;
261 default:
262 printf("uh oh... got redirect for unknown service 0x%04x!!\n", serviceid);
263 /* dunno */
264 }
265
266 return 1;
267}
268
269int faimtest_auth_error(struct command_rx_struct *command, ...)
270{
271 va_list ap;
272 struct login_phase1_struct *logininfo;
273 char *errorurl;
274 short errorcode;
275
276 va_start(ap, command);
277 logininfo = va_arg(ap, struct login_phase1_struct *);
278 printf("Screen name: %s\n", logininfo->screen_name);
279 errorurl = va_arg(ap, char *);
280 printf("Error URL: %s\n", errorurl);
281 errorcode = va_arg(ap, short);
282 printf("Error code: 0x%02x\n", errorcode);
283 va_end(ap);
284
285 aim_conn_close(aim_getconn_type(AIM_CONN_TYPE_AUTH));
286 exit(0);
287
288 return 0;
289}
290
291int faimtest_auth_success(struct command_rx_struct *command, ...)
292{
293 va_list ap;
294 struct login_phase1_struct *logininfo;
295 struct aim_conn_t *bosconn = NULL;
296
297 va_start(ap, command);
298 logininfo = va_arg(ap, struct login_phase1_struct *);
299 va_end(ap);
300
301 printf("Screen name: %s\n", logininfo->screen_name);
302 printf("Reg status: %2d\n", logininfo->regstatus);
303 printf("Email: %s\n", logininfo->email);
304 printf("Cookie len: %d\n", sizeof(logininfo->cookie));
305 printf("BOS IP: %s\n", logininfo->BOSIP);
306
307 printf("Closing auth connection...\n");
308 aim_conn_close(command->conn);
309 bosconn = aim_newconn(AIM_CONN_TYPE_BOS, logininfo->BOSIP);
310 if (bosconn == NULL)
311 {
312 fprintf(stderr, "faimtest: could not connect to BOS: internal error\n");
313 }
314 else if (bosconn->status != 0)
315 {
316 fprintf(stderr, "faimtest: could not connect to BOS\n");
317 }
318 else
319 {
320 aim_conn_addhandler(bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
321 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_serverready, 0);
322 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, NULL, 0);
323 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, faimtest_handleredirect, 0);
324 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, NULL, 0);
325 aim_conn_addhandler(bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, NULL, 0);
326 aim_conn_addhandler(bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, faimtest_parse_oncoming, 0);
327 aim_conn_addhandler(bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, faimtest_parse_offgoing, 0);
328 aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
329 aim_conn_addhandler(bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, faimtest_parse_misses, 0);
330 aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, faimtest_parse_misses, 0);
331 aim_conn_addhandler(bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, faimtest_parse_misses, 0);
332 aim_conn_addhandler(bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, faimtest_parse_misses, 0);
333 aim_conn_addhandler(bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, faimtest_parse_userinfo, 0);
334
335 aim_conn_addhandler(bosconn, AIM_CB_FAM_CTN, AIM_CB_CTN_DEFAULT, aim_parse_unknown, 0);
336 aim_conn_addhandler(bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEFAULT, aim_parse_unknown, 0);
337 aim_auth_sendcookie(bosconn, logininfo->cookie);
338 }
339 return 1;
340}
341
342int faimtest_parse_userinfo(struct command_rx_struct *command, ...)
343{
344 struct aim_userinfo_s *userinfo;
345 char *prof_encoding = NULL;
346 char *prof = NULL;
347
348 va_list ap;
349 va_start(ap, command);
350 userinfo = va_arg(ap, struct aim_userinfo_s *);
351 prof_encoding = va_arg(ap, char *);
352 prof = va_arg(ap, char *);
353 va_end(ap);
354
355 printf("faimtest: userinfo: sn: %s\n", userinfo->sn);
356 printf("faimtest: userinfo: warnlevel: 0x%04x\n", userinfo->warnlevel);
357 printf("faimtest: userinfo: class: 0x%04x = ", userinfo->class);
358
359 /*
360 * 00000000 (binary)
361 * 1 Trial
362 * 2 Unknown
363 * 3 AOL
364 * 4 Unknown
365 * 5 Free
366 *
367 * ORed together.
368 *
369 */
370
371 if (userinfo->class & 0x0001)
372 printf("TRIAL ");
373 if (userinfo->class & 0x0002)
374 printf("UNKNOWN_BIT2 ");
375 if (userinfo->class & 0x0004)
376 printf("AOL ");
377 if (userinfo->class & 0x0008)
378 printf("UNKNOWN_BIT4 ");
379 if (userinfo->class & 0x0010)
380 printf("FREE ");
381 printf("\n");
382
383 printf("faimtest: userinfo: membersince: %lu\n", userinfo->membersince);
384 printf("faimtest: userinfo: onlinesince: %lu\n", userinfo->onlinesince);
385 printf("faimtest: userinfo: idletime: 0x%04x\n", userinfo->idletime);
386
387 printf("faimtest: userinfo: profile_encoding: %s\n", prof_encoding ? prof_encoding : "[none]");
388 printf("faimtest: userinfo: prof: %s\n", prof ? prof : "[none]");
389
390 return 1;
391}
392
393/*
394 * The user-level Incoming ICBM callback.
395 *
396 * Arguments:
397 * struct command_rx_struct * command if you feel like doing it yourself
398 * char * srcsn the source name
399 * char * msg message
400 * int warnlevel warning/evil level
401 * int class user class
402 * ulong membersince time_t of date of signup
403 * ulong onsince time_t of date of singon
404 * int idletime min (sec?) idle
24286d93 405 * u_int icbmflags sets AIM_IMFLAGS_{AWAY,ACK}
9de3ca7e 406 *
407 */
408int faimtest_parse_incoming_im(struct command_rx_struct *command, ...)
409{
410 struct aim_userinfo_s *userinfo;
411 char *msg = NULL;
24286d93 412 u_int icbmflags = 0;
9de3ca7e 413 va_list ap;
414 char *tmpstr = NULL;
49c8a2fa 415 u_short flag1, flag2;
9de3ca7e 416
417 va_start(ap, command);
418 userinfo = va_arg(ap, struct aim_userinfo_s *);
419 msg = va_arg(ap, char *);
24286d93 420 icbmflags = va_arg(ap, u_int);
49c8a2fa 421 flag1 = va_arg(ap, u_short);
422 flag2 = va_arg(ap, u_short);
9de3ca7e 423 va_end(ap);
424
425 printf("faimtest: icbm: sn = \"%s\"\n", userinfo->sn);
426 printf("faimtest: icbm: warnlevel = 0x%04x\n", userinfo->warnlevel);
427 printf("faimtest: icbm: class = 0x%04x ", userinfo->class);
428 if (userinfo->class & 0x0010)
429 printf("(FREE)\n");
430 else if (userinfo->class & 0x0001)
431 printf("(TRIAL)\n");
432 else if (userinfo->class & 0x0004)
433 printf("(AOL)\n");
434 else
435 printf("(UNKNOWN)\n");
436 printf("faimtest: icbm: membersince = %lu\n", userinfo->membersince);
437 printf("faimtest: icbm: onlinesince = %lu\n", userinfo->onlinesince);
438 printf("faimtest: icbm: idletime = 0x%04x\n", userinfo->idletime);
24286d93 439
440 printf("faimtest: icbm: icbmflags = ");
441 if (icbmflags & AIM_IMFLAGS_AWAY)
442 printf("away ");
443 if (icbmflags & AIM_IMFLAGS_ACK)
444 printf("ackrequest ");
445 printf("\n");
446
49c8a2fa 447 printf("faimtest: icbm: encoding flags = {%04x, %04x}\n", flag1, flag2);
9de3ca7e 448
449 printf("faimtest: icbm: message: %s\n", msg);
450
451 if (msg)
452 {
453 tmpstr = index(msg, '>');
454 if (tmpstr != NULL)
455 tmpstr+=1;
456 else
457 tmpstr = msg;
458
459 if ( (strlen(tmpstr) >= 10) &&
460 (!strncmp(tmpstr, "disconnect", 10)) )
461 {
462 aim_send_im(command->conn, "midendian", 0, "ta ta...");
463 aim_logoff();
464 }
465 else if (strstr(tmpstr, "goodday"))
466 {
467 printf("faimtest: icbm: sending response\n");
468 aim_send_im(command->conn, userinfo->sn, 0, "Good day to you too.");
469 }
470#if 0
471 else if (!strncmp(tmpstr, "joinchat", 8))
472 {
473 aim_chat_join(command->conn, "GoodDay");
474 }
475#endif
476 else
477 {
478#if 0
479 printf("faimtest: icbm: starting chat...\n");
480 aim_bos_reqservice(command->conn, AIM_CONN_TYPE_CHATNAV);
481#else
482 aim_bos_setidle(command->conn, 0x0ffffffe);
483#endif
484 }
485
486 }
487
488 printf("faimtest: icbm: done with ICBM handling\n");
489
490 return 1;
491}
492
493int faimtest_authsvrready(struct command_rx_struct *command, ...)
494{
495 printf("faimtest_authsvrready: called (contype: %d)\n", command->conn->type);
496 sleep(10);
497 /* should just be able to tell it we're ready too... */
498 aim_auth_clientready(command->conn);
499
500#if 0
501 /*
502 * This is where you'd really begin changing your password.
503 * However, this callback may get called for reasons other
504 * than you wanting to change your password. You should
505 * probably check that before actually doing it.
506 */
507 aim_auth_changepasswd(command->conn, "PWD1", "PWD2");
508#endif
509
510 return 1;
511}
512
513int faimtest_pwdchngdone(struct command_rx_struct *command, ...)
514{
515 printf("PASSWORD CHANGE SUCCESSFUL!!!\n");
516 return 1;
517}
518
519int faimtest_parse_oncoming(struct command_rx_struct *command, ...)
520{
521 struct aim_userinfo_s *userinfo;
522
523 va_list ap;
524 va_start(ap, command);
525 userinfo = va_arg(ap, struct aim_userinfo_s *);
526 va_end(ap);
527
528 printf("\n%s is now online\n", userinfo->sn);
529
530 return 1;
531}
532
533int faimtest_parse_offgoing(struct command_rx_struct *command, ...)
534{
535
536 printf("\n%s has left\n", &(command->data[11]));
537
538 return 1;
539}
540
541
542/*
543 * Handles callbacks for: AIM_CB_RATECHANGE, AIM_CB_USERERROR,
544 * AIM_CB_MISSED_IM, and AIM_CB_MISSED_CALL.
545 */
546int faimtest_parse_misses(struct command_rx_struct *command, ...)
547{
548 u_short family;
549 u_short subtype;
550
551 family = (command->data[0] << 8) + command->data[1];
552 subtype = (command->data[2] << 8) + command->data[3];
553
554 switch (family)
555 {
556 case 0x0001:
557 if (subtype == 0x000a) /* or AIM_CB_RATECHANGE */
558 printf("\n****STOP SENDING/RECIEVING MESSAGES SO FAST!****\n\n");
559 break;
560 case 0x0002:
561 if (subtype == 0x0001) /* or AIM_CB_USERERROR */
562 {
563 u_long snacid = 0x00000000;
564
565 snacid = aimutil_get32(&command->data[6]);
566
567 printf("Received unknown error in SNAC family 0x0002 (snacid = %08lx)\n", snacid);
568 }
569 break;
570 case 0x0004:
571 if (subtype == 0x0001) /* or AIM_CB_MISSED_IM */
572 printf("\n***LAST IM DIDN\'T MAKE IT BECAUSE THE BUDDY IS NOT ONLINE***\n\n");
573 else if (subtype == 0x000a) /* or AIM_CB_MISSED_CALL */
574 printf("You missed some messages from %s because they were sent too fast\n", &(command->data[13]));
575 break;
576 }
577
578 return 0;
579}
580
581
582
583
584
This page took 0.126839 seconds and 5 git commands to generate.