]> andersk Git - libfaim.git/commitdiff
- Fri Mar 23 05:42:11 UTC 2001
authormid <mid>
Fri, 23 Mar 2001 05:52:31 +0000 (05:52 +0000)
committermid <mid>
Fri, 23 Mar 2001 05:52:31 +0000 (05:52 +0000)
  - Export aim_encode_password_md5()
  - Add middle handler for 000b/0002 (min report interval)
  - Add aim_session_kill()
     - CLIENTS MUST CALL THIS either in addition to or instead of
       aim_logoff(), particularly if you keep lots of sessions open.
       (Sessions now contain dynamically allocated memory which must be freed.)
  - Oh, and some other stuff...

17 files changed:
CHANGES
include/aim.h
include/aim_internal.h
src/.cvsignore
src/Makefile.am
src/admin.c [new file with mode: 0644]
src/auth.c
src/bos.c [new file with mode: 0644]
src/buddylist.c
src/conn.c
src/info.c
src/login.c
src/misc.c
src/rxhandlers.c
src/search.c
src/stats.c [new file with mode: 0644]
utils/faimtest/faimtest.c

diff --git a/CHANGES b/CHANGES
index a0ab8aac50c63892a731488a76dd27b25717f6b6..27c976ffb00ef1442176eb8929b23f8c6127f490 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,15 @@
 
 No release numbers
 ------------------
+ - Fri Mar 23 05:42:11 UTC 2001
+  - Export aim_encode_password_md5()
+  - Add middle handler for 000b/0002 (min report interval)
+  - Add aim_session_kill()
+     - CLIENTS MUST CALL THIS either in addition to or instead of
+       aim_logoff(), particularly if you keep lots of sessions open.
+       (Sessions now contain dynamically allocated memory which must be freed.)
+  - Oh, and some other stuff...
+
  - Fri Mar 23 01:45:28 UTC 2001
   - Add AIM_CLIENTINFO_KNOWNGOOD
   - Fix a few details in aim_send_login (thanks temas)
index bad2b544d769b0093839fb1b2b05323e5bcf21a8..8d57fc20fd218c7a74f2e7a2fa0d32caca2faaf6 100644 (file)
@@ -352,6 +352,8 @@ struct aim_session_t {
   void (*debugcb)(struct aim_session_t *sess, int level, const char *format, va_list va); /* same as faim_debugging_callback_t */
 
   struct aim_msgcookie_t *msgcookies;
+
+  void *modlistv;
 };
 
 /* Values for sess->flags */
@@ -456,6 +458,7 @@ typedef int (*rxcallback_t)(struct aim_session_t *, struct command_rx_struct *,
 faim_export int aim_sendconnack(struct aim_session_t *sess, struct aim_conn_t *conn);
 faim_export int aim_request_login (struct aim_session_t *sess, struct aim_conn_t *conn, char *sn);
 faim_export int aim_send_login (struct aim_session_t *, struct aim_conn_t *, char *, char *, struct client_info_s *, char *key);
+faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest);
 faim_export unsigned long aim_sendauthresp(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn, int errorcode, char *errorurl, char *bosip, char *cookie, char *email, int regstatus);
 faim_export int aim_gencookie(unsigned char *buf);
 faim_export int aim_sendserverready(struct aim_session_t *sess, struct aim_conn_t *conn);
@@ -495,6 +498,7 @@ faim_export int aim_conn_isconnecting(struct aim_conn_t *conn);
 typedef void (*faim_debugging_callback_t)(struct aim_session_t *sess, int level, const char *format, va_list va);
 faim_export int aim_setdebuggingcb(struct aim_session_t *sess, faim_debugging_callback_t);
 faim_export void aim_session_init(struct aim_session_t *, unsigned long flags, int debuglevel);
+faim_export void aim_session_kill(struct aim_session_t *);
 faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *username, char *password);
 faim_export struct aim_conn_t *aim_getconn_type(struct aim_session_t *, int type);
 
index b8f8509e39e0069bef1472aab183e5f066c8a6c8..0682b2dac9c13bd61dfb7720a81e75e94da18de3 100644 (file)
@@ -7,11 +7,42 @@
 #ifndef __AIM_INTERNAL_H__
 #define __AIM_INTERNAL_H__ 1
 
+typedef struct {
+  unsigned short family;
+  unsigned short subtype;
+  unsigned short flags;
+  unsigned long id;
+} aim_modsnac_t;
+
+#define AIM_MODULENAME_MAXLEN 16
+#define AIM_MODFLAG_MULTIFAMILY 0x0001
+typedef struct aim_module_s {
+  unsigned short family;
+  unsigned short flags;
+  unsigned short version;
+  char name[AIM_MODULENAME_MAXLEN+1];
+  int (*snachandler)(struct aim_session_t *sess, struct aim_module_s *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen);
+  void (*shutdown)(struct aim_session_t *sess, struct aim_module_s *mod);
+  void *priv;
+  struct aim_module_s *next;
+} aim_module_t;
+
+faim_internal int aim__registermodule(struct aim_session_t *sess, int (*modfirst)(struct aim_session_t *, aim_module_t *));
+faim_internal void aim__shutdownmodules(struct aim_session_t *sess);
+
+
+faim_internal int buddylist_modfirst(struct aim_session_t *sess, aim_module_t *mod);
+faim_internal int admin_modfirst(struct aim_session_t *sess, aim_module_t *mod);
+faim_internal int bos_modfirst(struct aim_session_t *sess, aim_module_t *mod);
+faim_internal int search_modfirst(struct aim_session_t *sess, aim_module_t *mod);
+faim_internal int stats_modfirst(struct aim_session_t *sess, aim_module_t *mod);
+faim_internal int auth_modfirst(struct aim_session_t *sess, aim_module_t *mod);
+
+
 faim_internal unsigned long aim_genericreq_n(struct aim_session_t *, struct aim_conn_t *conn, u_short family, u_short subtype);
 faim_internal unsigned long aim_genericreq_l(struct aim_session_t *, struct aim_conn_t *conn, u_short family, u_short subtype, u_long *);
 faim_internal unsigned long aim_genericreq_s(struct aim_session_t *, struct aim_conn_t *conn, u_short family, u_short subtype, u_short *);
 
-faim_internal int aim_authkeyparse(struct aim_session_t *sess, struct command_rx_struct *command);
 faim_internal void aim_rxqueue_cleanbyconn(struct aim_session_t *sess, struct aim_conn_t *conn);
 faim_internal int aim_recv(int fd, void *buf, size_t count);
 
@@ -25,8 +56,6 @@ faim_internal int aim_tx_enqueue(struct aim_session_t *, struct command_tx_struc
 faim_internal int aim_tx_printqueue(struct aim_session_t *);
 faim_internal int aim_parse_hostonline(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 faim_internal int aim_parse_hostversions(struct aim_session_t *sess, struct command_rx_struct *command, ...);
-faim_internal int aim_parse_accountconfirm(struct aim_session_t *sess, struct command_rx_struct *command);
-faim_internal int aim_parse_infochange(struct aim_session_t *sess, struct command_rx_struct *command);
 faim_internal int aim_tx_cleanqueue(struct aim_session_t *, struct aim_conn_t *);
 
 faim_internal rxcallback_t aim_callhandler(struct aim_session_t *sess, struct aim_conn_t *conn, u_short family, u_short type);
@@ -58,7 +87,6 @@ faim_internal int aim_oft_buildheader(unsigned char *,struct aim_fileheader_t *)
 faim_internal int aim_listenestablish(u_short);
 faim_internal int aim_tx_destroy(struct command_tx_struct *);
 
-faim_internal int aim_authparse(struct aim_session_t *, struct command_rx_struct *);
 faim_internal int aim_handleredirect_middle(struct aim_session_t *, struct command_rx_struct *, ...);
 faim_internal int aim_parse_unknown(struct aim_session_t *, struct command_rx_struct *, ...);
 faim_internal int aim_parse_generalerrs(struct aim_session_t *, struct command_rx_struct *command, ...);
@@ -88,7 +116,6 @@ faim_internal int aim_parse_incoming_im_middle(struct aim_session_t *, struct co
 faim_internal int aim_parse_outgoing_im_middle(struct aim_session_t *, struct command_rx_struct *);
 faim_internal int aim_parse_msgerror_middle(struct aim_session_t *, struct command_rx_struct *);
 faim_internal int aim_negchan_middle(struct aim_session_t *sess, struct command_rx_struct *command);
-faim_internal int aim_parse_bosrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 faim_internal int aim_parse_missedcall(struct aim_session_t *sess, struct command_rx_struct *command);
 
 extern u_char aim_caps[8][16];
@@ -105,16 +132,9 @@ faim_internal int aim_cookie_free(struct aim_session_t *sess, struct aim_msgcook
 
 faim_internal int aim_extractuserinfo(struct aim_session_t *sess, unsigned char *, struct aim_userinfo_s *);
 faim_internal int aim_parse_userinfo_middle(struct aim_session_t *, struct command_rx_struct *);
-faim_internal int aim_parse_oncoming_middle(struct aim_session_t *, struct command_rx_struct *);
-faim_internal int aim_parse_offgoing_middle(struct aim_session_t *, struct command_rx_struct *);
 faim_internal int aim_putuserinfo(u_char *buf, int buflen, struct aim_userinfo_s *info);
 faim_internal int aim_parse_locateerr(struct aim_session_t *sess, struct command_rx_struct *command);
 
-faim_internal int aim_parse_buddyrights(struct aim_session_t *sess, struct command_rx_struct *command, ...);
-
-faim_internal unsigned long aim_parse_searcherror(struct aim_session_t *, struct command_rx_struct *);
-faim_internal unsigned long aim_parse_searchreply(struct aim_session_t *, struct command_rx_struct *);
-
 faim_internal int aim_chat_readroominfo(u_char *buf, struct aim_chat_roominfo *outinfo);
 faim_internal int aim_chat_parse_infoupdate(struct aim_session_t *sess, struct command_rx_struct *command);
 faim_internal int aim_chat_parse_joined(struct aim_session_t *sess, struct command_rx_struct *command);
index 417f3f68c4208339c7468373ccb02f02e7053363..396846a7affee46eaab88bf452b5728012b2bbd7 100644 (file)
@@ -1,8 +1,10 @@
 Makefile.in
 Makefile
 .deps
+admin.lo
 adverts.lo
 auth.lo
+bos.lo
 buddylist.lo
 chat.lo
 chatnav.lo
@@ -18,6 +20,7 @@ rxhandlers.lo
 rxqueue.lo
 search.lo
 snac.lo
+stats.lo
 tlv.lo
 txqueue.lo
 util.lo
index c6f010a867e345fb6c5edb3161d4595d65d3c49d..9b739bcbcc566971ca2a0fbcf94cbcc2f756964d 100644 (file)
@@ -1,8 +1,10 @@
 
 lib_LTLIBRARIES = libfaim.la
 
-libfaim_la_SOURCES =   adverts.c       \
+libfaim_la_SOURCES =   admin.c         \
+                       adverts.c       \
                        auth.c          \
+                       bos.c           \
                        buddylist.c     \
                        chat.c          \
                        chatnav.c       \
@@ -18,6 +20,7 @@ libfaim_la_SOURCES =  adverts.c       \
                        rxqueue.c       \
                        search.c        \
                        snac.c          \
+                       stats.c         \
                        tlv.c           \
                        txqueue.c       \
                        util.c          \
diff --git a/src/admin.c b/src/admin.c
new file mode 100644 (file)
index 0000000..22419d8
--- /dev/null
@@ -0,0 +1,254 @@
+
+#define FAIM_INTERNAL
+#include <aim.h>
+
+/* called for both reply and change-reply */
+static int infochange(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+  int i;
+
+  /*
+   * struct {
+   *    unsigned short perms;
+   *    unsigned short tlvcount;
+   *    aim_tlv_t tlvs[tlvcount];
+   *  } admin_info[n];
+   */
+  for (i = 0; i < datalen; ) {
+    int perms, tlvcount;
+
+    perms = aimutil_get16(data+i);
+    i += 2;
+
+    tlvcount = aimutil_get16(data+i);
+    i += 2;
+
+    while (tlvcount) {
+      rxcallback_t userfunc;
+      struct aim_tlv_t *tlv;
+      int str = 0;
+
+      if ((aimutil_get16(data+i) == 0x0011) ||
+         (aimutil_get16(data+i) == 0x0004))
+       str = 1;
+
+      if (str)
+       tlv = aim_grabtlvstr(data+i);
+      else
+       tlv = aim_grabtlv(data+i);
+
+      /* XXX fix so its only called once for the entire packet */
+      if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+       userfunc(sess, rx, perms, tlv->type, tlv->length, tlv->value, str);
+
+      if (tlv)
+       i += 2+2+tlv->length;
+
+      if (tlv && tlv->value)
+       free(tlv->value);
+      if (tlv)
+       free(tlv);
+
+      tlvcount--;
+    }
+  }
+
+  return 1;
+}
+
+static int accountconfirm(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+  rxcallback_t userfunc;
+  int status;
+
+  status = aimutil_get16(data);
+
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    return userfunc(sess, rx, status);
+
+  return 0;
+}
+
+static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+
+  faimdprintf(sess, 0, "%s: snachandler: got %x/%x\n", mod->name, snac->family, snac->subtype);
+
+  if (snac->family != mod->family)
+    return 0;
+
+  if (snac->subtype == 0x0001)
+    ;
+  else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005))
+    return infochange(sess, mod, rx, snac, data, datalen);
+  else if (snac->subtype == 0x0007)
+    return accountconfirm(sess, mod, rx, snac, data, datalen);
+
+  return 0;
+}
+
+faim_internal int admin_modfirst(struct aim_session_t *sess, aim_module_t *mod)
+{
+
+  mod->family = 0x0007;
+  mod->version = 0x0000;
+  mod->flags = 0;
+  strncpy(mod->name, "admin", sizeof(mod->name));
+  mod->snachandler = snachandler;
+
+  return 0;
+}
+
+faim_export unsigned long aim_auth_clientready(struct aim_session_t *sess,
+                                              struct aim_conn_t *conn)
+{
+  struct aim_tool_version tools[] = {
+    {0x0001, 0x0003,    AIM_TOOL_NEWWIN, 0x0361},
+    {0x0007, 0x0001,    AIM_TOOL_NEWWIN, 0x0361},
+  };
+  int i,j;
+  struct command_tx_struct *newpacket;
+  int toolcount = sizeof(tools)/sizeof(struct aim_tool_version);
+
+  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
+    return -1;
+
+  newpacket->lock = 1;
+
+  i = aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
+  aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
+
+  for (j = 0; j < toolcount; j++) {
+    i += aimutil_put16(newpacket->data+i, tools[j].group);
+    i += aimutil_put16(newpacket->data+i, tools[j].version);
+    i += aimutil_put16(newpacket->data+i, tools[j].tool);
+    i += aimutil_put16(newpacket->data+i, tools[j].toolversion);
+  }
+
+  newpacket->commandlen = i;
+  newpacket->lock = 0;
+
+  aim_tx_enqueue(sess, newpacket);
+
+  return sess->snac_nextid;
+}
+
+faim_export unsigned long aim_auth_changepasswd(struct aim_session_t *sess,
+                                               struct aim_conn_t *conn, 
+                                               char *new, char *current)
+{
+  struct command_tx_struct *newpacket;
+  int i;
+
+  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+4+strlen(current)+4+strlen(new))))
+    return -1;
+
+  newpacket->lock = 1;
+
+  i = aim_putsnac(newpacket->data, 0x0007, 0x0004, 0x0000, sess->snac_nextid);
+  aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
+
+  /* new password TLV t(0002) */
+  i += aim_puttlv_str(newpacket->data+i, 0x0002, strlen(new), new);
+
+  /* current password TLV t(0012) */
+  i += aim_puttlv_str(newpacket->data+i, 0x0012, strlen(current), current);
+
+  aim_tx_enqueue(sess, newpacket);
+
+  return sess->snac_nextid;
+}
+
+faim_export unsigned long aim_auth_setversions(struct aim_session_t *sess,
+                                              struct aim_conn_t *conn)
+{
+  struct command_tx_struct *newpacket;
+  int i;
+
+  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10 + (4*2))))
+    return -1;
+
+  newpacket->lock = 1;
+
+  i = aim_putsnac(newpacket->data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
+  aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0);
+
+  i += aimutil_put16(newpacket->data+i, 0x0001);
+  i += aimutil_put16(newpacket->data+i, 0x0003);
+
+  i += aimutil_put16(newpacket->data+i, 0x0007);
+  i += aimutil_put16(newpacket->data+i, 0x0001);
+
+  newpacket->commandlen = i;
+  newpacket->lock = 0;
+  aim_tx_enqueue(sess, newpacket);
+
+  return sess->snac_nextid;
+}
+
+/*
+ * Request account confirmation. 
+ *
+ * This will cause an email to be sent to the address associated with
+ * the account.  By following the instructions in the mail, you can
+ * get the TRIAL flag removed from your account.
+ *
+ */
+faim_export unsigned long aim_auth_reqconfirm(struct aim_session_t *sess,
+                                             struct aim_conn_t *conn)
+{
+  return aim_genericreq_n(sess, conn, 0x0007, 0x0006);
+}
+
+/*
+ * Request a bit of account info.
+ *
+ * The only known valid tag is 0x0011 (email address).
+ *
+ */ 
+faim_export unsigned long aim_auth_getinfo(struct aim_session_t *sess,
+                                          struct aim_conn_t *conn,
+                                          unsigned short info)
+{
+  struct command_tx_struct *newpacket;
+  int i;
+
+  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10 + 4)))
+    return -1;
+
+  newpacket->lock = 1;
+
+  i = aim_putsnac(newpacket->data, 0x0007, 0x0002, 0x0000, sess->snac_nextid);
+  aim_cachesnac(sess, 0x0002, 0x0002, 0x0000, NULL, 0);
+
+  i += aimutil_put16(newpacket->data+i, info);
+  i += aimutil_put16(newpacket->data+i, 0x0000);
+
+  newpacket->commandlen = i;
+  newpacket->lock = 0;
+  aim_tx_enqueue(sess, newpacket);
+
+  return sess->snac_nextid;
+}
+
+faim_export unsigned long aim_auth_setemail(struct aim_session_t *sess,
+                                           struct aim_conn_t *conn, 
+                                           char *newemail)
+{
+  struct command_tx_struct *newpacket;
+  int i;
+
+  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+2+strlen(newemail))))
+    return -1;
+
+  newpacket->lock = 1;
+
+  i = aim_putsnac(newpacket->data, 0x0007, 0x0004, 0x0000, sess->snac_nextid);
+  aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
+
+  i += aim_puttlv_str(newpacket->data+i, 0x0011, strlen(newemail), newemail);
+
+  aim_tx_enqueue(sess, newpacket);
+
+  return sess->snac_nextid;
+}
index 621c269c84594264f0dfc7fcd0489a9ab4686c99..629d7553ef9703fd421f04278fe63b7a397f869d 100644 (file)
@@ -30,156 +30,202 @@ faim_export int aim_auth_sendcookie(struct aim_session_t *sess,
   return aim_tx_enqueue(sess, newpacket);
 }
 
-faim_export unsigned long aim_auth_clientready(struct aim_session_t *sess,
-                                              struct aim_conn_t *conn)
+/*
+ * This is sent back as a general response to the login command.
+ * It can be either an error or a success, depending on the
+ * precense of certain TLVs.  
+ *
+ * The client should check the value passed as errorcode. If
+ * its nonzero, there was an error.
+ *
+ */
+static int parse(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  struct aim_tool_version tools[] = {
-    {0x0001, 0x0003,    AIM_TOOL_NEWWIN, 0x0361},
-    {0x0007, 0x0001,    AIM_TOOL_NEWWIN, 0x0361},
-  };
-  int i,j;
-  struct command_tx_struct *newpacket;
-  int toolcount = sizeof(tools)/sizeof(struct aim_tool_version);
-
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
-    return -1;
-
-  newpacket->lock = 1;
-
-  i = aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
-  aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
-
-  for (j = 0; j < toolcount; j++) {
-    i += aimutil_put16(newpacket->data+i, tools[j].group);
-    i += aimutil_put16(newpacket->data+i, tools[j].version);
-    i += aimutil_put16(newpacket->data+i, tools[j].tool);
-    i += aimutil_put16(newpacket->data+i, tools[j].toolversion);
+  struct aim_tlvlist_t *tlvlist;
+  int ret = 0;
+  rxcallback_t userfunc;
+  char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
+  unsigned char *cookie = NULL;
+  int errorcode = 0, regstatus = 0;
+  int latestbuild = 0, latestbetabuild = 0;
+  char *latestrelease = NULL, *latestbeta = NULL;
+  char *latestreleaseurl = NULL, *latestbetaurl = NULL;
+  char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
+
+  /*
+   * Read block of TLVs.  All further data is derived
+   * from what is parsed here.
+   *
+   */
+  tlvlist = aim_readtlvchain(data, datalen);
+
+  /*
+   * No matter what, we should have a screen name.
+   */
+  memset(sess->sn, 0, sizeof(sess->sn));
+  if (aim_gettlv(tlvlist, 0x0001, 1)) {
+    sn = aim_gettlv_str(tlvlist, 0x0001, 1);
+    strncpy(sess->sn, sn, sizeof(sess->sn));
   }
 
-  newpacket->commandlen = i;
-  newpacket->lock = 0;
-
-  aim_tx_enqueue(sess, newpacket);
-
-  return sess->snac_nextid;
-}
-
-faim_export unsigned long aim_auth_changepasswd(struct aim_session_t *sess,
-                                               struct aim_conn_t *conn, 
-                                               char *new, char *current)
-{
-  struct command_tx_struct *newpacket;
-  int i;
-
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+4+strlen(current)+4+strlen(new))))
-    return -1;
-
-  newpacket->lock = 1;
-
-  i = aim_putsnac(newpacket->data, 0x0007, 0x0004, 0x0000, sess->snac_nextid);
-  aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-
-  /* new password TLV t(0002) */
-  i += aim_puttlv_str(newpacket->data+i, 0x0002, strlen(new), new);
-
-  /* current password TLV t(0012) */
-  i += aim_puttlv_str(newpacket->data+i, 0x0012, strlen(current), current);
-
-  aim_tx_enqueue(sess, newpacket);
-
-  return sess->snac_nextid;
-}
-
-faim_export unsigned long aim_auth_setversions(struct aim_session_t *sess,
-                                              struct aim_conn_t *conn)
-{
-  struct command_tx_struct *newpacket;
-  int i;
-
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10 + (4*2))))
-    return -1;
-
-  newpacket->lock = 1;
-
-  i = aim_putsnac(newpacket->data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
-  aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0);
-
-  i += aimutil_put16(newpacket->data+i, 0x0001);
-  i += aimutil_put16(newpacket->data+i, 0x0003);
-
-  i += aimutil_put16(newpacket->data+i, 0x0007);
-  i += aimutil_put16(newpacket->data+i, 0x0001);
-
-  newpacket->commandlen = i;
-  newpacket->lock = 0;
-  aim_tx_enqueue(sess, newpacket);
+  /*
+   * Check for an error code.  If so, we should also
+   * have an error url.
+   */
+  if (aim_gettlv(tlvlist, 0x0008, 1)) 
+    errorcode = aim_gettlv16(tlvlist, 0x0008, 1);
+  if (aim_gettlv(tlvlist, 0x0004, 1))
+    errurl = aim_gettlv_str(tlvlist, 0x0004, 1);
+
+  /*
+   * BOS server address.
+   */
+  if (aim_gettlv(tlvlist, 0x0005, 1))
+    bosip = aim_gettlv_str(tlvlist, 0x0005, 1);
+
+  /*
+   * Authorization cookie.
+   */
+  if (aim_gettlv(tlvlist, 0x0006, 1)) {
+    struct aim_tlv_t *tmptlv;
+
+    tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
+
+    if ((cookie = malloc(tmptlv->length)))
+      memcpy(cookie, tmptlv->value, tmptlv->length);
+  }
 
-  return sess->snac_nextid;
+  /*
+   * The email address attached to this account
+   *   Not available for ICQ logins.
+   */
+  if (aim_gettlv(tlvlist, 0x0011, 1))
+    email = aim_gettlv_str(tlvlist, 0x0011, 1);
+
+  /*
+   * The registration status.  (Not real sure what it means.)
+   *   Not available for ICQ logins.
+   *
+   *   1 = No disclosure
+   *   2 = Limited disclosure
+   *   3 = Full disclosure
+   *
+   * This has to do with whether your email address is available
+   * to other users or not.  AFAIK, this feature is no longer used.
+   *
+   */
+  if (aim_gettlv(tlvlist, 0x0013, 1))
+    regstatus = aim_gettlv16(tlvlist, 0x0013, 1);
+
+  if (aim_gettlv(tlvlist, 0x0040, 1))
+    latestbetabuild = aim_gettlv32(tlvlist, 0x0040, 1);
+  if (aim_gettlv(tlvlist, 0x0041, 1))
+    latestbetaurl = aim_gettlv_str(tlvlist, 0x0041, 1);
+  if (aim_gettlv(tlvlist, 0x0042, 1))
+    latestbetainfo = aim_gettlv_str(tlvlist, 0x0042, 1);
+  if (aim_gettlv(tlvlist, 0x0043, 1))
+    latestbeta = aim_gettlv_str(tlvlist, 0x0043, 1);
+  if (aim_gettlv(tlvlist, 0x0048, 1))
+    ; /* no idea what this is */
+
+  if (aim_gettlv(tlvlist, 0x0044, 1))
+    latestbuild = aim_gettlv32(tlvlist, 0x0044, 1);
+  if (aim_gettlv(tlvlist, 0x0045, 1))
+    latestreleaseurl = aim_gettlv_str(tlvlist, 0x0045, 1);
+  if (aim_gettlv(tlvlist, 0x0046, 1))
+    latestreleaseinfo = aim_gettlv_str(tlvlist, 0x0046, 1);
+  if (aim_gettlv(tlvlist, 0x0047, 1))
+    latestrelease = aim_gettlv_str(tlvlist, 0x0047, 1);
+  if (aim_gettlv(tlvlist, 0x0049, 1))
+    ; /* no idea what this is */
+
+
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac?snac->family:0x0017, snac?snac->subtype:0x0003)))
+    ret = userfunc(sess, rx, sn, errorcode, errurl, regstatus, email, bosip, cookie, latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo, latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
+
+
+  if (sn)
+    free(sn);
+  if (bosip)
+    free(bosip);
+  if (errurl)
+    free(errurl);
+  if (email)
+    free(email);
+  if (cookie)
+    free(cookie);
+  if (latestrelease)
+    free(latestrelease);
+  if (latestreleaseurl)
+    free(latestreleaseurl);
+  if (latestbeta)
+    free(latestbeta);
+  if (latestbetaurl)
+    free(latestbetaurl);
+  if (latestreleaseinfo)
+    free(latestreleaseinfo);
+  if (latestbetainfo)
+    free(latestbetainfo);
+
+  aim_freetlvchain(&tlvlist);
+
+  return ret;
 }
 
 /*
- * Request account confirmation. 
+ * Middle handler for 0017/0007 SNACs.  Contains the auth key prefixed
+ * by only its length in a two byte word.
  *
- * This will cause an email to be sent to the address associated with
- * the account.  By following the instructions in the mail, you can
- * get the TRIAL flag removed from your account.
+ * Calls the client, which should then use the value to call aim_send_login.
  *
  */
-faim_export unsigned long aim_auth_reqconfirm(struct aim_session_t *sess,
-                                             struct aim_conn_t *conn)
+static int keyparse(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  return aim_genericreq_n(sess, conn, 0x0007, 0x0006);
-}
+  unsigned char *key;
+  int keylen;
+  int ret = 1;
+  rxcallback_t userfunc;
+
+  keylen = aimutil_get16(data);
+  if (!(key = malloc(keylen+1)))
+    return ret;
+  memcpy(key, data+2, keylen);
+  key[keylen] = '\0';
+  
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    ret = userfunc(sess, rx, (char *)key);
 
-/*
- * Request a bit of account info.
- *
- * The only known valid tag is 0x0011 (email address).
- *
- */ 
-faim_export unsigned long aim_auth_getinfo(struct aim_session_t *sess,
-                                          struct aim_conn_t *conn,
-                                          unsigned short info)
-{
-  struct command_tx_struct *newpacket;
-  int i;
+  free(key);  
 
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10 + 4)))
-    return -1;
+  return ret;
+}
 
-  newpacket->lock = 1;
+static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
 
-  i = aim_putsnac(newpacket->data, 0x0007, 0x0002, 0x0000, sess->snac_nextid);
-  aim_cachesnac(sess, 0x0002, 0x0002, 0x0000, NULL, 0);
+  faimdprintf(sess, 0, "%s: snachandler: got %x/%x\n", mod->name, snac->family, snac->subtype);
 
-  i += aimutil_put16(newpacket->data+i, info);
-  i += aimutil_put16(newpacket->data+i, 0x0000);
+  if (snac->family != mod->family)
+    return 0;
 
-  newpacket->commandlen = i;
-  newpacket->lock = 0;
-  aim_tx_enqueue(sess, newpacket);
+  if (snac->subtype == 0x0001)
+    ;
+  else if (snac->subtype == 0x0003)
+    return parse(sess, mod, rx, snac, data, datalen);
+  else if (snac->subtype == 0x0007)
+    return keyparse(sess, mod, rx, snac, data, datalen);
 
-  return sess->snac_nextid;
+  return 0;
 }
 
-faim_export unsigned long aim_auth_setemail(struct aim_session_t *sess,
-                                           struct aim_conn_t *conn, 
-                                           char *newemail)
+faim_internal int auth_modfirst(struct aim_session_t *sess, aim_module_t *mod)
 {
-  struct command_tx_struct *newpacket;
-  int i;
-
-  if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+2+2+strlen(newemail))))
-    return -1;
-
-  newpacket->lock = 1;
-
-  i = aim_putsnac(newpacket->data, 0x0007, 0x0004, 0x0000, sess->snac_nextid);
-  aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-
-  i += aim_puttlv_str(newpacket->data+i, 0x0011, strlen(newemail), newemail);
 
-  aim_tx_enqueue(sess, newpacket);
+  mod->family = 0x0017;
+  mod->version = 0x0000;
+  mod->flags = 0;
+  strncpy(mod->name, "auth", sizeof(mod->name));
+  mod->snachandler = snachandler;
 
-  return sess->snac_nextid;
+  return 0;
 }
diff --git a/src/bos.c b/src/bos.c
new file mode 100644 (file)
index 0000000..829788b
--- /dev/null
+++ b/src/bos.c
@@ -0,0 +1,82 @@
+
+#define FAIM_INTERNAL
+#include <aim.h>
+
+/* 
+ * aim_bos_setgroupperm(mask)
+ * 
+ * Set group permisson mask.  Normally 0x1f (all classes).
+ *
+ * The group permission mask allows you to keep users of a certain
+ * class or classes from talking to you.  The mask should be
+ * a bitwise OR of all the user classes you want to see you.
+ *
+ */
+faim_export unsigned long aim_bos_setgroupperm(struct aim_session_t *sess,
+                                              struct aim_conn_t *conn, 
+                                              u_long mask)
+{
+  return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
+}
+
+static int rights(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+  rxcallback_t userfunc;
+  int ret = 0;
+  struct aim_tlvlist_t *tlvlist;
+  unsigned short maxpermits = 0, maxdenies = 0;
+
+  /* 
+   * TLVs follow 
+   */
+  if (!(tlvlist = aim_readtlvchain(data, datalen)))
+    return 0;
+
+  /*
+   * TLV type 0x0001: Maximum number of buddies on permit list.
+   */
+  if (aim_gettlv(tlvlist, 0x0001, 1))
+    maxpermits = aim_gettlv16(tlvlist, 0x0001, 1);
+
+  /*
+   * TLV type 0x0002: Maximum number of buddies on deny list.
+   *
+   */
+  if (aim_gettlv(tlvlist, 0x0002, 1)) 
+    maxdenies = aim_gettlv16(tlvlist, 0x0002, 1);
+  
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    ret = userfunc(sess, rx, maxpermits, maxdenies);
+
+  aim_freetlvchain(&tlvlist);
+
+  return ret;  
+}
+
+static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+
+  faimdprintf(sess, 0, "%s: snachandler: got %x/%x\n", mod->name, snac->family, snac->subtype);
+
+  if (snac->family != mod->family)
+    return 0;
+
+  if (snac->subtype == 0x0001)
+    ;
+  else if (snac->subtype == 0x0003)
+    return rights(sess, mod, rx, snac, data, datalen);
+
+  return 0;
+}
+
+faim_internal int bos_modfirst(struct aim_session_t *sess, aim_module_t *mod)
+{
+
+  mod->family = 0x0009;
+  mod->version = 0x0000;
+  mod->flags = 0;
+  strncpy(mod->name, "bos", sizeof(mod->name));
+  mod->snachandler = snachandler;
+
+  return 0;
+}
index 55a3571c0b24a29026c759e98368428d92d0d3a6..28492aae465070ced1fa98ebffc18595c7f02285 100644 (file)
@@ -2,6 +2,111 @@
 #define FAIM_INTERNAL
 #include <aim.h>
 
+/*
+ * Oncoming Buddy notifications contain a subset of the
+ * user information structure.  Its close enough to run
+ * through aim_extractuserinfo() however.
+ *
+ */
+static int oncoming(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+  struct aim_userinfo_s userinfo;
+  rxcallback_t userfunc;
+
+  aim_extractuserinfo(sess, data, &userinfo);
+
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    return userfunc(sess, rx, &userinfo);
+
+  return 0;
+}
+
+/*
+ * Offgoing Buddy notifications contain no useful
+ * information other than the name it applies to.
+ *
+ */
+static int offgoing(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+  char sn[MAXSNLEN+1];
+  rxcallback_t userfunc;
+
+  strncpy(sn, (char *)data+1, (int)*data);
+
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    return userfunc(sess, rx, sn);
+
+  return 0;
+}
+
+static int rights(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+  rxcallback_t userfunc;
+  struct aim_tlvlist_t *tlvlist;
+  unsigned short maxbuddies = 0, maxwatchers = 0;
+  int ret = 0;
+
+  /* 
+   * TLVs follow 
+   */
+  if (!(tlvlist = aim_readtlvchain(data, datalen)))
+    return 0;
+
+  /*
+   * TLV type 0x0001: Maximum number of buddies.
+   */
+  if (aim_gettlv(tlvlist, 0x0001, 1))
+    maxbuddies = aim_gettlv16(tlvlist, 0x0001, 1);
+
+  /*
+   * TLV type 0x0002: Maximum number of watchers.
+   *
+   * XXX: what the hell is a watcher? 
+   *
+   */
+  if (aim_gettlv(tlvlist, 0x0002, 1))
+    maxwatchers = aim_gettlv16(tlvlist, 0x0002, 1);
+  
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    ret = userfunc(sess, rx, maxbuddies, maxwatchers);
+
+  aim_freetlvchain(&tlvlist);
+
+  return ret;  
+}
+
+static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+
+  faimdprintf(sess, 0, "%s: snachandler: got %x/%x\n", mod->name, snac->family, snac->subtype);
+
+  if (snac->family != mod->family)
+    return 0;
+
+  if (snac->subtype == 0x0001)
+    ;
+  else if (snac->subtype == 0x0003)
+    return rights(sess, mod, rx, snac, data, datalen);
+  else if (snac->subtype == 0x000b)
+    return oncoming(sess, mod, rx, snac, data, datalen);
+  else if (snac->subtype == 0x000c)
+    return offgoing(sess, mod, rx, snac, data, datalen);
+
+  return 0;
+}
+
+faim_internal int buddylist_modfirst(struct aim_session_t *sess, aim_module_t *mod)
+{
+
+  mod->family = 0x0003;
+  mod->version = 0x0000;
+  mod->flags = 0;
+  strncpy(mod->name, "buddylist", sizeof(mod->name));
+  mod->snachandler = snachandler;
+
+  return 0;
+}
+
 /*
  * aim_add_buddy()
  *
@@ -68,39 +173,3 @@ faim_export unsigned long aim_remove_buddy(struct aim_session_t *sess,
    return sess->snac_nextid;
 }
 
-faim_internal int aim_parse_buddyrights(struct aim_session_t *sess,
-                                       struct command_rx_struct *command, ...)
-{
-  rxcallback_t userfunc = NULL;
-  int ret=1;
-  struct aim_tlvlist_t *tlvlist;
-  unsigned short maxbuddies = 0, maxwatchers = 0;
-
-  /* 
-   * TLVs follow 
-   */
-  if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
-    return ret;
-
-  /*
-   * TLV type 0x0001: Maximum number of buddies.
-   */
-  if (aim_gettlv(tlvlist, 0x0001, 1))
-    maxbuddies = aim_gettlv16(tlvlist, 0x0001, 1);
-
-  /*
-   * TLV type 0x0002: Maximum number of watchers.
-   *
-   * XXX: what the hell is a watcher? 
-   *
-   */
-  if (aim_gettlv(tlvlist, 0x0002, 1))
-    maxwatchers = aim_gettlv16(tlvlist, 0x0002, 1);
-  
-  if ((userfunc = aim_callhandler(sess, command->conn, 0x0003, 0x0003)))
-    ret =  userfunc(sess, command, maxbuddies, maxwatchers);
-
-  aim_freetlvchain(&tlvlist);
-
-  return ret;  
-}
index 1482dba89952140a1d47f7c8cd8986806fa9ae8e..c64d33ae48809fdf45edf713e45138917e842ed5 100644 (file)
@@ -722,6 +722,11 @@ faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *
   return;
 }
 
+static void defaultdebugcb(struct aim_session_t *sess, int level, const char *format, va_list va)
+{
+  vfprintf(stderr, format, va);
+}
+
 /**
  * aim_session_init - Initializes a session structure
  * @sess: Session to initialize
@@ -748,7 +753,9 @@ faim_export void aim_session_init(struct aim_session_t *sess, unsigned long flag
 
   sess->flags = 0;
   sess->debug = 0;
-  sess->debugcb = NULL;
+  sess->debugcb = defaultdebugcb;
+
+  sess->modlistv = NULL;
 
   /*
    * Default to SNAC login unless XORLOGIN is explicitly set.
@@ -763,6 +770,33 @@ faim_export void aim_session_init(struct aim_session_t *sess, unsigned long flag
    */
   aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL);
 
+
+  /*
+   * Register all the modules for this session...
+   */
+  aim__registermodule(sess, buddylist_modfirst);
+  aim__registermodule(sess, admin_modfirst);
+  aim__registermodule(sess, bos_modfirst);
+  aim__registermodule(sess, search_modfirst);
+  aim__registermodule(sess, stats_modfirst);
+  aim__registermodule(sess, auth_modfirst);
+
+  return;
+}
+
+/**
+ * aim_session_kill - Deallocate a session
+ * @sess: Session to kill
+ *
+ *
+ */
+faim_export void aim_session_kill(struct aim_session_t *sess)
+{
+
+  aim_logoff(sess);
+
+  aim__shutdownmodules(sess);
+
   return;
 }
 
index de05b79118d0a8bed449b57058111610631cab1f..ee140feb91f272f06b098b66b5c388b8e00e3c1c 100644 (file)
@@ -461,51 +461,6 @@ faim_internal int aim_extractuserinfo(struct aim_session_t *sess, unsigned char
   return i;
 }
 
-/*
- * Oncoming Buddy notifications contain a subset of the
- * user information structure.  Its close enough to run
- * through aim_extractuserinfo() however.
- *
- */
-faim_internal int aim_parse_oncoming_middle(struct aim_session_t *sess,
-                                           struct command_rx_struct *command)
-{
-  struct aim_userinfo_s userinfo;
-  u_int i = 0;
-  rxcallback_t userfunc=NULL;
-
-  i = 10;
-  i += aim_extractuserinfo(sess, command->data+i, &userinfo);
-
-  userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING);
-  if (userfunc)
-    i = userfunc(sess, command, &userinfo);
-
-  return 1;
-}
-
-/*
- * Offgoing Buddy notifications contain no useful
- * information other than the name it applies to.
- *
- */
-faim_internal int aim_parse_offgoing_middle(struct aim_session_t *sess,
-                                           struct command_rx_struct *command)
-{
-  char sn[MAXSNLEN+1];
-  u_int i = 0;
-  rxcallback_t userfunc=NULL;
-
-  strncpy(sn, (char *)command->data+11, (int)command->data[10]);
-  sn[(int)command->data[10]] = '\0';
-
-  userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING);
-  if (userfunc)
-    i = userfunc(sess, command, sn);
-
-  return 1;
-}
-
 /*
  * This parses the user info stuff out all nice and pretty then calls 
  * the higher-level callback (in the user app).
index 6b06863dda35791bdf2398922919546f75c103a5..3e6e9cd2d04679d12d9eccb9bd30b464793e315d 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "md5.h"
 
-static int aim_encode_password_md5(const char *password, const char *key, md5_byte_t *digest);
 static int aim_encode_password(const char *password, unsigned char *encoded);
 
 faim_export int aim_sendconnack(struct aim_session_t *sess,
@@ -177,7 +176,7 @@ faim_export int aim_send_login (struct aim_session_t *sess,
   curbyte += aim_puttlv_str(newpacket->data+curbyte, 0x0001, strlen(sn), sn);
   
   if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN) {
-    md5_byte_t digest[16];
+    unsigned char digest[16];
 
     aim_encode_password_md5(password, key, digest);
     curbyte+= aim_puttlv_str(newpacket->data+curbyte, 0x0025, 16, (char *)digest);
@@ -231,7 +230,7 @@ faim_export int aim_send_login (struct aim_session_t *sess,
   return aim_tx_enqueue(sess, newpacket);
 }
 
-static int aim_encode_password_md5(const char *password, const char *key, md5_byte_t *digest)
+faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest)
 {
   md5_state_t state;
 
@@ -285,182 +284,6 @@ static int aim_encode_password(const char *password, unsigned char *encoded)
   return 0;
 }
 
-/*
- * This is sent back as a general response to the login command.
- * It can be either an error or a success, depending on the
- * precense of certain TLVs.  
- *
- * The client should check the value passed as errorcode. If
- * its nonzero, there was an error.
- *
- */
-faim_internal int aim_authparse(struct aim_session_t *sess, 
-                               struct command_rx_struct *command)
-{
-  struct aim_tlvlist_t *tlvlist;
-  int ret = 1;
-  rxcallback_t userfunc = NULL;
-  char *sn = NULL, *bosip = NULL, *errurl = NULL, *email = NULL;
-  unsigned char *cookie = NULL;
-  int errorcode = 0, regstatus = 0;
-  int latestbuild = 0, latestbetabuild = 0;
-  char *latestrelease = NULL, *latestbeta = NULL;
-  char *latestreleaseurl = NULL, *latestbetaurl = NULL;
-  char *latestreleaseinfo = NULL, *latestbetainfo = NULL;
-
-  /*
-   * Read block of TLVs.  All further data is derived
-   * from what is parsed here.
-   *
-   * For SNAC login, there's a 17/3 SNAC header in front.
-   *
-   */
-  if (sess->flags & AIM_SESS_FLAGS_SNACLOGIN)
-    tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10);
-  else
-    tlvlist = aim_readtlvchain(command->data, command->commandlen);
-
-  /*
-   * No matter what, we should have a screen name.
-   */
-  memset(sess->sn, 0, sizeof(sess->sn));
-  if (aim_gettlv(tlvlist, 0x0001, 1)) {
-    sn = aim_gettlv_str(tlvlist, 0x0001, 1);
-    strncpy(sess->sn, sn, sizeof(sess->sn));
-  }
-
-  /*
-   * Check for an error code.  If so, we should also
-   * have an error url.
-   */
-  if (aim_gettlv(tlvlist, 0x0008, 1)) 
-    errorcode = aim_gettlv16(tlvlist, 0x0008, 1);
-  if (aim_gettlv(tlvlist, 0x0004, 1))
-    errurl = aim_gettlv_str(tlvlist, 0x0004, 1);
-
-  /*
-   * BOS server address.
-   */
-  if (aim_gettlv(tlvlist, 0x0005, 1))
-    bosip = aim_gettlv_str(tlvlist, 0x0005, 1);
-
-  /*
-   * Authorization cookie.
-   */
-  if (aim_gettlv(tlvlist, 0x0006, 1)) {
-    struct aim_tlv_t *tmptlv;
-
-    tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
-
-    if ((cookie = malloc(tmptlv->length)))
-      memcpy(cookie, tmptlv->value, tmptlv->length);
-  }
-
-  /*
-   * The email address attached to this account
-   *   Not available for ICQ logins.
-   */
-  if (aim_gettlv(tlvlist, 0x0011, 1))
-    email = aim_gettlv_str(tlvlist, 0x0011, 1);
-
-  /*
-   * The registration status.  (Not real sure what it means.)
-   *   Not available for ICQ logins.
-   *
-   *   1 = No disclosure
-   *   2 = Limited disclosure
-   *   3 = Full disclosure
-   *
-   * This has to do with whether your email address is available
-   * to other users or not.  AFAIK, this feature is no longer used.
-   *
-   */
-  if (aim_gettlv(tlvlist, 0x0013, 1))
-    regstatus = aim_gettlv16(tlvlist, 0x0013, 1);
-
-  if (aim_gettlv(tlvlist, 0x0040, 1))
-    latestbetabuild = aim_gettlv32(tlvlist, 0x0040, 1);
-  if (aim_gettlv(tlvlist, 0x0041, 1))
-    latestbetaurl = aim_gettlv_str(tlvlist, 0x0041, 1);
-  if (aim_gettlv(tlvlist, 0x0042, 1))
-    latestbetainfo = aim_gettlv_str(tlvlist, 0x0042, 1);
-  if (aim_gettlv(tlvlist, 0x0043, 1))
-    latestbeta = aim_gettlv_str(tlvlist, 0x0043, 1);
-  if (aim_gettlv(tlvlist, 0x0048, 1))
-    ; /* no idea what this is */
-
-  if (aim_gettlv(tlvlist, 0x0044, 1))
-    latestbuild = aim_gettlv32(tlvlist, 0x0044, 1);
-  if (aim_gettlv(tlvlist, 0x0045, 1))
-    latestreleaseurl = aim_gettlv_str(tlvlist, 0x0045, 1);
-  if (aim_gettlv(tlvlist, 0x0046, 1))
-    latestreleaseinfo = aim_gettlv_str(tlvlist, 0x0046, 1);
-  if (aim_gettlv(tlvlist, 0x0047, 1))
-    latestrelease = aim_gettlv_str(tlvlist, 0x0047, 1);
-  if (aim_gettlv(tlvlist, 0x0049, 1))
-    ; /* no idea what this is */
-
-
-  if ((userfunc = aim_callhandler(sess, command->conn, 0x0017, 0x0003)))
-    ret = userfunc(sess, command, sn, errorcode, errurl, regstatus, email, bosip, cookie, latestrelease, latestbuild, latestreleaseurl, latestreleaseinfo, latestbeta, latestbetabuild, latestbetaurl, latestbetainfo);
-
-
-  if (sn)
-    free(sn);
-  if (bosip)
-    free(bosip);
-  if (errurl)
-    free(errurl);
-  if (email)
-    free(email);
-  if (cookie)
-    free(cookie);
-  if (latestrelease)
-    free(latestrelease);
-  if (latestreleaseurl)
-    free(latestreleaseurl);
-  if (latestbeta)
-    free(latestbeta);
-  if (latestbetaurl)
-    free(latestbetaurl);
-  if (latestreleaseinfo)
-    free(latestreleaseinfo);
-  if (latestbetainfo)
-    free(latestbetainfo);
-
-  aim_freetlvchain(&tlvlist);
-
-  return ret;
-}
-
-/*
- * Middle handler for 0017/0007 SNACs.  Contains the auth key prefixed
- * by only its length in a two byte word.
- *
- * Calls the client, which should then use the value to call aim_send_login.
- *
- */
-faim_internal int aim_authkeyparse(struct aim_session_t *sess, struct command_rx_struct *command)
-{
-  unsigned char *key;
-  int keylen;
-  int ret = 1;
-  rxcallback_t userfunc;
-
-  keylen = aimutil_get16(command->data+10);
-  if (!(key = malloc(keylen+1)))
-    return ret;
-  memcpy(key, command->data+12, keylen);
-  key[keylen] = '\0';
-  
-  if ((userfunc = aim_callhandler(sess, command->conn, 0x0017, 0x0007)))
-    ret = userfunc(sess, command, (char *)key);
-
-  free(key);  
-
-  return ret;
-}
-
 /*
  * Generate an authorization response.  
  *
index 252d41e899650eb5d0133cf6b30da5dd3b06063b..c8f8a80329cef8af3911424cf45a7501e33df241 100644 (file)
@@ -239,58 +239,6 @@ faim_export unsigned long aim_bos_setprofile(struct aim_session_t *sess,
   return (sess->snac_nextid++);
 }
 
-/* 
- * aim_bos_setgroupperm(mask)
- * 
- * Set group permisson mask.  Normally 0x1f (all classes).
- *
- * The group permission mask allows you to keep users of a certain
- * class or classes from talking to you.  The mask should be
- * a bitwise OR of all the user classes you want to see you.
- *
- */
-faim_export unsigned long aim_bos_setgroupperm(struct aim_session_t *sess,
-                                              struct aim_conn_t *conn, 
-                                              u_long mask)
-{
-  return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
-}
-
-faim_internal int aim_parse_bosrights(struct aim_session_t *sess,
-                                     struct command_rx_struct *command, ...)
-{
-  rxcallback_t userfunc = NULL;
-  int ret=1;
-  struct aim_tlvlist_t *tlvlist;
-  unsigned short maxpermits = 0, maxdenies = 0;
-
-  /* 
-   * TLVs follow 
-   */
-  if (!(tlvlist = aim_readtlvchain(command->data+10, command->commandlen-10)))
-    return ret;
-
-  /*
-   * TLV type 0x0001: Maximum number of buddies on permit list.
-   */
-  if (aim_gettlv(tlvlist, 0x0001, 1))
-    maxpermits = aim_gettlv16(tlvlist, 0x0001, 1);
-
-  /*
-   * TLV type 0x0002: Maximum number of buddies on deny list.
-   *
-   */
-  if (aim_gettlv(tlvlist, 0x0002, 1)) 
-    maxdenies = aim_gettlv16(tlvlist, 0x0002, 1);
-  
-  if ((userfunc = aim_callhandler(sess, command->conn, 0x0009, 0x0003)))
-    ret = userfunc(sess, command, maxpermits, maxdenies);
-
-  aim_freetlvchain(&tlvlist);
-
-  return ret;  
-}
-
 /*
  * aim_bos_clientready()
  * 
index 2241f711bd38f462d32b73e52431f69b1e7a97d7..493d040850d86ca65589c859603f346f445efca9 100644 (file)
 #define FAIM_INTERNAL
 #include <aim.h>
 
+static aim_module_t *findmodule(struct aim_session_t *sess, const char *name)
+{
+  aim_module_t *cur;
+
+  for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
+    if (strcmp(name, cur->name) == 0)
+      return cur;
+  }
+
+  return NULL;
+}
+
+faim_internal int aim__registermodule(struct aim_session_t *sess, int (*modfirst)(struct aim_session_t *, aim_module_t *))
+{
+  aim_module_t *mod;
+
+  if (!sess || !modfirst)
+    return -1;
+
+  if (!(mod = malloc(sizeof(aim_module_t))))
+    return -1;
+  memset(mod, 0, sizeof(aim_module_t));
+
+  if (modfirst(sess, mod) == -1) {
+    free(mod);
+    return -1;
+  }
+
+  if (findmodule(sess, mod->name)) {
+    if (mod->shutdown)
+      mod->shutdown(sess, mod);
+    free(mod);
+    return -1;
+  }
+
+  mod->next = (aim_module_t *)sess->modlistv;
+  (aim_module_t *)sess->modlistv = mod;
+
+  faimdprintf(sess, 0, "registered module %s (family 0x%04x)\n", mod->name, mod->family);
+
+  return 0;
+}
+
+faim_internal void aim__shutdownmodules(struct aim_session_t *sess)
+{
+  aim_module_t *cur;
+
+  for (cur = (aim_module_t *)sess->modlistv; cur; ) {
+    aim_module_t *tmp;
+
+    tmp = cur->next;
+
+    if (cur->shutdown)
+      cur->shutdown(sess, cur);
+
+    free(cur);
+
+    cur = tmp;
+  }
+
+  sess->modlistv = NULL;
+
+  return;
+}
+
+static int consumesnac(struct aim_session_t *sess, struct command_rx_struct *rx)
+{
+  aim_module_t *cur;
+  aim_modsnac_t snac;
+
+  snac.family = aimutil_get16(rx->data+0);
+  snac.subtype = aimutil_get16(rx->data+2);
+  snac.flags = aimutil_get16(rx->data+4);
+  snac.id = aimutil_get32(rx->data+6);
+
+  for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
+
+    if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && 
+       (cur->family != snac.family))
+      continue;
+
+    if (cur->snachandler(sess, cur, rx, &snac, rx->data+10, rx->commandlen-10))
+      return 1;
+
+  }
+
+  return 0;
+}
+
+static int consumenonsnac(struct aim_session_t *sess, struct command_rx_struct *rx, unsigned short family, unsigned short subtype)
+{
+  aim_module_t *cur;
+  aim_modsnac_t snac;
+
+  snac.family = family;
+  snac.subtype = subtype;
+  snac.flags = snac.id = 0;
+
+  for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {
+
+    if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && 
+       (cur->family != snac.family))
+      continue;
+
+    if (cur->snachandler(sess, cur, rx, &snac, rx->data, rx->commandlen))
+      return 1;
+
+  }
+
+  return 0;
+}
+
 /*
  * Bleck functions get called when there's no non-bleck functions
  * around to cleanup the mess...
@@ -371,10 +483,13 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
        workingPtr->handled = aim_negchan_middle(sess, workingPtr);
        continue;
       }
+
+      if ((workingPtr->handled = consumesnac(sess, workingPtr)))
+       continue;
          
       family = aimutil_get16(workingPtr->data);
       subtype = aimutil_get16(workingPtr->data+2);
-         
+
       if (family == 0x0001) {
 
        if (subtype == 0x0001)
@@ -413,14 +528,6 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
 
        if (subtype == 0x0001)
          workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
-       else if (subtype == 0x0003)
-         workingPtr->handled = aim_parse_buddyrights(sess, workingPtr);
-       else if (subtype == 0x000b)
-         workingPtr->handled = aim_parse_oncoming_middle(sess, workingPtr);
-       else if (subtype == 0x000c)
-         workingPtr->handled = aim_parse_offgoing_middle(sess, workingPtr);
-       else
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_DEFAULT, workingPtr);
 
       } else if (family == 0x0004) {
 
@@ -439,43 +546,6 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
        else
          workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_DEFAULT, workingPtr);
 
-      } else if (family == 0x0007) {
-
-       if (subtype == 0x0003)
-         workingPtr->handled = aim_parse_infochange(sess, workingPtr);
-       else if (subtype == 0x0005)
-         workingPtr->handled = aim_parse_infochange(sess, workingPtr);
-       else if (subtype == 0x0007)
-         workingPtr->handled = aim_parse_accountconfirm(sess, workingPtr);
-       break;
-
-      } else if (family == 0x0009) {
-
-       if (subtype == 0x0001)
-         workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
-       else if (subtype == 0x0003)
-         workingPtr->handled = aim_parse_bosrights(sess, workingPtr);
-       else
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_BOS, AIM_CB_BOS_DEFAULT, workingPtr);
-
-      } else if (family == 0x000a) {
-
-       if (subtype == 0x0001)
-         workingPtr->handled = aim_parse_searcherror(sess, workingPtr);
-       else if (subtype == 0x0003)
-         workingPtr->handled = aim_parse_searchreply(sess, workingPtr);
-       else
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_LOK, AIM_CB_LOK_DEFAULT, workingPtr);
-
-      } else if (family == 0x000b) {
-
-       if (subtype == 0x0001)
-         workingPtr->handled = aim_parse_generalerrs(sess, workingPtr);
-       else if (subtype == 0x0002)
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x000b, 0x0002, workingPtr);
-       else
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
-
       } else if (family == 0x000d) {
 
        if (subtype == 0x0009)
@@ -496,17 +566,6 @@ faim_export int aim_rxdispatch(struct aim_session_t *sess)
 
        faimdprintf(sess, 0, "lalala: 0x%04x/0x%04x\n", family, subtype);
 
-      } else if (family == 0x0017) {   /* New login protocol */
-
-       if (subtype == 0x0001)
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0x0001, workingPtr);
-       else if (subtype == 0x0003)
-         workingPtr->handled = aim_authparse(sess, workingPtr);
-       else if (subtype == 0x0007)
-         workingPtr->handled = aim_authkeyparse(sess, workingPtr);
-       else
-         workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0017, 0xffff, workingPtr);
-
       } else if (family == AIM_CB_FAM_SPECIAL) {
 
        workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
@@ -726,78 +785,6 @@ faim_internal int aim_parse_hostonline(struct aim_session_t *sess,
   return ret;  
 }
 
-faim_internal int aim_parse_accountconfirm(struct aim_session_t *sess,
-                                          struct command_rx_struct *command)
-{
-  rxcallback_t userfunc = NULL;
-  int ret = 1;
-  int status = -1;
-
-  status = aimutil_get16(command->data+10);
-
-  if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, 0x0007)))
-    ret = userfunc(sess, command, status);
-
-  return ret;  
-}
-
-faim_internal int aim_parse_infochange(struct aim_session_t *sess,
-                                      struct command_rx_struct *command)
-{
-  unsigned short subtype; /* called for both reply and change-reply */
-  int i;
-
-  subtype = aimutil_get16(command->data+2);
-
-  /*
-   * struct {
-   *    unsigned short perms;
-   *    unsigned short tlvcount;
-   *    aim_tlv_t tlvs[tlvcount];
-   *  } admin_info[n];
-   */
-  for (i = 10; i < command->commandlen; ) {
-    int perms, tlvcount;
-
-    perms = aimutil_get16(command->data+i);
-    i += 2;
-
-    tlvcount = aimutil_get16(command->data+i);
-    i += 2;
-
-    while (tlvcount) {
-      rxcallback_t userfunc;
-      struct aim_tlv_t *tlv;
-      int str = 0;
-
-      if ((aimutil_get16(command->data+i) == 0x0011) ||
-         (aimutil_get16(command->data+i) == 0x0004))
-       str = 1;
-
-      if (str)
-       tlv = aim_grabtlvstr(command->data+i);
-      else
-       tlv = aim_grabtlv(command->data+i);
-
-      /* XXX fix so its only called once for the entire packet */
-      if ((userfunc = aim_callhandler(sess, command->conn, 0x0007, subtype)))
-       userfunc(sess, command, perms, tlv->type, tlv->length, tlv->value, str);
-
-      if (tlv)
-       i += 2+2+tlv->length;
-
-      if (tlv && tlv->value)
-       free(tlv->value);
-      if (tlv)
-       free(tlv);
-
-      tlvcount--;
-    }
-  }
-
-  return 1;
-}
-
 faim_internal int aim_parse_hostversions(struct aim_session_t *sess,
                                         struct command_rx_struct *command, ...)
 {
@@ -896,7 +883,7 @@ faim_internal int aim_negchan_middle(struct aim_session_t *sess,
   /* Used only by the older login protocol */
   /* XXX remove this special case? */
   if (command->conn->type == AIM_CONN_TYPE_AUTH)
-    return aim_authparse(sess, command);
+    return consumenonsnac(sess, command, 0x0017, 0x0003);
 
   tlvlist = aim_readtlvchain(command->data, command->commandlen);
 
@@ -907,7 +894,7 @@ faim_internal int aim_negchan_middle(struct aim_session_t *sess,
     msg = aim_gettlv_str(tlvlist, 0x000b, 1);
 
   if ((userfunc = aim_callhandler(sess, command->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) 
-    ret =  userfunc(sess, command, code, msg);
+    ret = userfunc(sess, command, code, msg);
 
   aim_freetlvchain(&tlvlist);
 
index 649a9fce978659017a54671e8d56d42fcd0aca8b..a1024125b1b25dcdf1c3fca9d78f3641046f7333 100644 (file)
@@ -35,58 +35,46 @@ faim_export unsigned long aim_usersearch_address(struct aim_session_t *sess,
 }
 
 
-faim_internal unsigned long aim_parse_searcherror(struct aim_session_t *sess, struct command_rx_struct *command) 
+static int error(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  u_int i, ret;
-  int snacid;
+  int ret = 0;
   rxcallback_t userfunc;
-  struct aim_snac_t *snac;
+  struct aim_snac_t *snac2;
 
-  i = 6;
-
-  snacid = aimutil_get32(command->data+i);
-  i += 4;
-  
-  if(!(snac = aim_remsnac(sess, snacid))) {
-    faimdprintf(sess, 2, "faim: couldn't get a snac for %d, probably should crash.\n", snacid);
+  /* XXX the modules interface should have already retrieved this for us */
+  if(!(snac2 = aim_remsnac(sess, snac->id))) {
+    faimdprintf(sess, 2, "couldn't get a snac for 0x%08lx\n", snac->id);
     return 0;
   }
 
-  if((userfunc = aim_callhandler(sess, command->conn, 0x000a, 0x0001)))
-    ret = userfunc(sess, command, snac->data /* address */);
-  else
-    ret = 0;
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    ret = userfunc(sess, rx, snac2->data /* address */);
 
-  if(snac) {
-    if(snac->data)
-      free(snac->data);
-    free(snac);
+  /* XXX freesnac()? */
+  if (snac2) {
+    if(snac2->data)
+      free(snac2->data);
+    free(snac2);
   }
 
   return ret;
 }
-       
-  
-faim_internal unsigned long aim_parse_searchreply(struct aim_session_t *sess, struct command_rx_struct *command)
+
+static int reply(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
 {
-  u_int i, j, m, ret;
-  int snacid;
+  unsigned int j, m, ret = 0;
   struct aim_tlvlist_t *tlvlist;
   char *cur = NULL, *buf = NULL;
   rxcallback_t userfunc;
-  struct aim_snac_t *snac;
-
-  i = 6;
+  struct aim_snac_t *snac2;
 
-  snacid = aimutil_get32(command->data+i);
-  i += 4;
-
-  if(!(snac = aim_remsnac(sess, snacid))) {
-    faimdprintf(sess, 2, "faim: couldn't get a snac for %d, probably should crash.\n", snacid);
+  if (!(snac2 = aim_remsnac(sess, snac->id))) {
+    faimdprintf(sess, 2, "faim: couldn't get a snac for 0x%08lx\n", snac->id);
     return 0;
   }
 
-  tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i);
+  if (!(tlvlist = aim_readtlvchain(data, datalen)))
+    return 0;
 
   j = 0;
 
@@ -104,15 +92,14 @@ faim_internal unsigned long aim_parse_searchreply(struct aim_session_t *sess, st
 
   aim_freetlvchain(&tlvlist);
 
-  if((userfunc = aim_callhandler(sess, command->conn, 0x000a, 0x0003)))
-    ret = userfunc(sess, command, snac->data /* address */, j, buf);
-  else
-    ret = 0;
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    ret = userfunc(sess, rx, snac2->data /* address */, j, buf);
 
-  if(snac) {
-    if(snac->data)
-      free(snac->data);
-    free(snac);
+  /* XXX freesnac()? */
+  if(snac2) {
+    if(snac2->data)
+      free(snac2->data);
+    free(snac2);
   }
 
   if(buf)
@@ -120,3 +107,31 @@ faim_internal unsigned long aim_parse_searchreply(struct aim_session_t *sess, st
 
   return ret;
 }
+
+static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+
+  faimdprintf(sess, 0, "%s: snachandler: got %x/%x\n", mod->name, snac->family, snac->subtype);
+
+  if (snac->family != mod->family)
+    return 0;
+
+  if (snac->subtype == 0x0001)
+    return error(sess, mod, rx, snac, data, datalen);
+  else if (snac->subtype == 0x0003)
+    return reply(sess, mod, rx, snac, data, datalen);
+
+  return 0;
+}
+
+faim_internal int search_modfirst(struct aim_session_t *sess, aim_module_t *mod)
+{
+
+  mod->family = 0x000a;
+  mod->version = 0x0000;
+  mod->flags = 0;
+  strncpy(mod->name, "search", sizeof(mod->name));
+  mod->snachandler = snachandler;
+
+  return 0;
+}
diff --git a/src/stats.c b/src/stats.c
new file mode 100644 (file)
index 0000000..4f7f741
--- /dev/null
@@ -0,0 +1,44 @@
+
+#define FAIM_INTERNAL
+#include <aim.h>
+
+static int reportinterval(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+  unsigned short interval;
+  rxcallback_t userfunc;
+
+  interval = aimutil_get16(data);
+
+  if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+    return userfunc(sess, rx, interval);
+
+  return 0;
+}
+
+static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
+{
+
+  faimdprintf(sess, 0, "%s: snachandler: got %x/%x\n", mod->name, snac->family, snac->subtype);
+
+  if (snac->family != mod->family)
+    return 0;
+
+  if (snac->subtype == 0x0001)
+    ;
+  else if (snac->subtype == 0x0002)
+    return reportinterval(sess, mod, rx, snac, data, datalen);
+
+  return 0;
+}
+
+faim_internal int stats_modfirst(struct aim_session_t *sess, aim_module_t *mod)
+{
+
+  mod->family = 0x000b;
+  mod->version = 0x0000;
+  mod->flags = 0;
+  strncpy(mod->name, "stats", sizeof(mod->name));
+  mod->snachandler = snachandler;
+
+  return 0;
+}
index bccad2b92173fa4ba3241d19cb4a9ca7216ae949..a2976af24ce58d759582edec02f2d7f324942fe8 100644 (file)
@@ -169,10 +169,15 @@ static void faimtest_debugcb(struct aim_session_t *sess, int level, const char *
 
 int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
-  if (command->data) {
-    dvprintf("aim: minimum report interval: %d (seconds?)\n", aimutil_get16(command->data+10));
-  } else
-    dprintf("aim: NULL minimum report interval!\n");
+  va_list ap;
+  unsigned short interval = 0;
+
+  va_start(ap, command);
+  interval = va_arg(ap, int);
+  va_end(ap);
+
+  dvprintf("aim: minimum report interval: %d (seconds?)\n", interval);
+
   return 1;
 }
 
@@ -256,7 +261,7 @@ int logout(void)
   if (ohcaptainmycaptain)
     aim_send_im(&aimsess, aim_getconn_type(&aimsess, AIM_CONN_TYPE_BOS), ohcaptainmycaptain, 0, "ta ta...");
 
-  aim_logoff(&aimsess);
+  aim_session_kill(&aimsess);
 
   if (faimtest_init() == -1)
     dprintf("faimtest_init failed\n");
@@ -396,7 +401,7 @@ int main(int argc, char **argv)
     waitingconn = aim_select(&aimsess, NULL, &selstat);
 
     if (selstat == -1) { /* error */
-      keepgoing = 0; /* fall through and hit the aim_logoff() */
+      keepgoing = 0; /* fall through */
     } else if (selstat == 0) { /* no events pending */
       keepgoing = 0;
     } else if (selstat == 1) { /* outgoing data pending */
@@ -433,7 +438,7 @@ int main(int argc, char **argv)
   }
 
   /* close up all connections, dead or no */
-  aim_logoff(&aimsess); 
+  aim_session_kill(&aimsess); 
 
   if (faimtest_mode < 2) {
     printf("\n");
This page took 0.147419 seconds and 5 git commands to generate.