+
+ }
+ break;
+ case 0x0008: {
+ char *fqcn, *name, *ck;
+ unsigned short instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
+ unsigned char createperms;
+ unsigned long createtime;
+
+ fqcn = va_arg(ap, char *);
+ instance = va_arg(ap, int);
+ exchange = va_arg(ap, int);
+ flags = va_arg(ap, int);
+ createtime = va_arg(ap, unsigned long);
+ maxmsglen = va_arg(ap, int);
+ maxoccupancy = va_arg(ap, int);
+ createperms = va_arg(ap, int);
+ unknown = va_arg(ap, int);
+ name = va_arg(ap, char *);
+ ck = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: recieved room create reply for %s/0x%04x\n", fqcn, exchange);
+ }
+ break;
+ default:
+ va_end(ap);
+ printf("faimtest: chatnav info: unknown type (%04x)\n", type);
+ }
+ return 1;
+}
+
+int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ unsigned short code;
+ char *msg = NULL;
+
+ va_start(ap, command);
+ code = va_arg(ap, int);
+ msg = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: connerr: Code 0x%04x: %s\n", code, msg);
+ aim_conn_kill(sess, &command->conn); /* this will break the main loop */
+
+ return 1;
+}
+
+int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ printf("faimtest: connecting to an aimdebugd!\n");
+
+ /* convert the authorizer connection to a BOS connection */
+ command->conn->type = AIM_CONN_TYPE_BOS;
+
+ aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
+
+ /* tell the aimddebugd we're ready */
+ aim_debugconn_sendconnect(sess, command->conn);
+
+ /* go right into main loop (don't open a BOS connection, etc) */
+ return 1;
+}
+
+/*
+ * Recieved in response to an IM sent with the AIM_IMFLAGS_ACK option.
+ */
+int faimtest_parse_msgack(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ unsigned short type;
+ char *sn = NULL;
+
+ va_start(ap, command);
+ type = va_arg(ap, int);
+ sn = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: msgack: 0x%04x / %s\n", type, sn);
+
+ return 1;
+}
+
+#ifdef FILESUPPORT
+int faimtest_getfile_filereq(struct aim_session_t *ses, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_conn_t *oftconn;
+ struct aim_fileheader_t *fh;
+ char *cookie;
+
+ va_start(ap, command);
+ oftconn = va_arg(ap, struct aim_conn_t *);
+ fh = va_arg(ap, struct aim_fileheader_t *);
+ cookie = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: request for file %s.\n", fh->name);
+
+ return 1;
+}
+
+
+int faimtest_getfile_filesend(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_conn_t *oftconn;
+ struct aim_fileheader_t *fh;
+ char *path, *cookie;
+
+ FILE *file;
+
+ va_start(ap, command);
+ oftconn = va_arg(ap, struct aim_conn_t *);
+ fh = va_arg(ap, struct aim_fileheader_t *);
+ cookie = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: sending file %s.\n", fh->name);
+
+ if( (path = (char *)calloc(1, strlen(sess->oft.listingdir) +strlen(fh->name)+2)) == NULL) {
+ perror("calloc:");
+ printf("faimtest: error in calloc of path\n");
+ return 0; /* XXX: no idea what winaim expects here =) */
+ }
+
+ snprintf(path, strlen(sess->oft.listingdir)+strlen(fh->name)+2, "%s/%s", sess->oft.listingdir, fh->name);
+
+
+ if( (file = fopen(path, "r")) == NULL) {
+ printf("faimtest: getfile_send fopen failed for %s. damn.\n", path);
+ return 0;
+ }
+
+ if (aim_getfile_send(oftconn, file, fh) == -1) {
+ printf("faimtest: getfile_send failed. damn.\n");
+ } else {
+ printf("faimtest: looks like getfile went clean\n");
+ }
+
+ free(fh);
+ return 1;
+}
+
+int faimtest_getfile_complete(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_conn_t *conn;
+ struct aim_fileheader_t *fh;
+
+ va_start(ap, command);
+ conn = va_arg(ap, struct aim_conn_t *);
+ fh = va_arg(ap, struct aim_fileheader_t *);
+ va_end(ap);
+
+ printf("faimtest: completed file transfer for %s.\n", fh->name);
+
+ /* aim_conn_kill(sess, &conn); */ /* we'll let winaim close the conn */
+ return 1;
+}
+
+int faimtest_getfile_disconnect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ struct aim_conn_t *conn;
+ char *sn;
+
+ va_start(ap, command);
+ conn = va_arg(ap, struct aim_conn_t *);
+ sn = va_arg(ap, char *);
+ va_end(ap);
+
+ aim_conn_kill(sess, &conn);
+
+ printf("faimtest: getfile: disconnected from %s\n", sn);
+ return 1;
+}
+#endif
+
+int faimtest_parse_ratechange(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ static char *codes[5] = {"invalid",
+ "change",
+ "warning",
+ "limit",
+ "limit cleared"};
+ va_list ap;
+ int code;
+ unsigned long parmid, windowsize, clear, alert, limit, disconnect;
+ unsigned long currentavg, maxavg;
+
+ va_start(ap, command);
+
+ /* See code explanations below */
+ code = va_arg(ap, int);
+
+ /*
+ * Known parameter ID's...
+ * 0x0003 BOS (normal ICBMs, userinfo requests, etc)
+ * 0x0005 Chat messages
+ */
+ parmid = va_arg(ap, unsigned long);
+
+ /*
+ * Not sure what this is exactly. I think its the temporal
+ * relation factor (ie, how to make the rest of the numbers
+ * make sense in the real world).
+ */
+ windowsize = va_arg(ap, unsigned long);
+
+ /* Explained below */
+ clear = va_arg(ap, unsigned long);
+ alert = va_arg(ap, unsigned long);
+ limit = va_arg(ap, unsigned long);
+ disconnect = va_arg(ap, unsigned long);
+ currentavg = va_arg(ap, unsigned long);
+ maxavg = va_arg(ap, unsigned long);
+
+ va_end(ap);
+
+
+ printf("faimtest: rate %s (paramid 0x%04lx): curavg = %ld, maxavg = %ld, alert at %ld, clear warning at %ld, limit at %ld, disconnect at %ld (window size = %ld)\n",
+ (code < 5)?codes[code]:"invalid",
+ parmid,
+ currentavg, maxavg,
+ alert, clear,
+ limit, disconnect,
+ windowsize);
+
+ if (code == AIM_RATE_CODE_CHANGE) {
+ /*
+ * Not real sure when these get sent.
+ */
+ if (currentavg >= clear)
+ aim_conn_setlatency(command->conn, 0);
+
+ } else if (code == AIM_RATE_CODE_WARNING) {
+ /*
+ * We start getting WARNINGs the first time we go below the 'alert'
+ * limit (currentavg < alert) and they stop when either we pause
+ * long enough for currentavg to go above 'clear', or until we
+ * flood it bad enough to go below 'limit' (and start getting
+ * LIMITs instead) or even further and go below 'disconnect' and
+ * get disconnected completely (and won't be able to login right
+ * away either).
+ */
+ aim_conn_setlatency(command->conn, windowsize/4); /* XXX this is bogus! */
+
+ } else if (code == AIM_RATE_CODE_LIMIT) {
+ /*
+ * When we hit LIMIT, messages will start getting dropped.
+ */
+ aim_conn_setlatency(command->conn, windowsize/2); /* XXX this is bogus! */
+
+ } else if (code == AIM_RATE_CODE_CLEARLIMIT) {
+ /*
+ * The limit is cleared when curavg goes above 'clear'.
+ */
+ aim_conn_setlatency(command->conn, 0);
+ }
+
+ return 1;
+}
+
+int faimtest_parse_evilnotify(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+ va_list ap;
+ char *sn;
+
+ va_start(ap, command);
+ sn = va_arg(ap, char *);
+ va_end(ap);
+
+ printf("faimtest: warning from: %s\n", sn);
+