+
+/*
+ * 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(command->conn, 0x0017, 0x0007)))
+ ret = userfunc(sess, command, (char *)key);
+
+ free(key);
+
+ return ret;
+}
+
+/*
+ * Generate an authorization response.
+ *
+ * You probably don't want this unless you're writing an AIM server.
+ *
+ */
+faim_export unsigned long aim_sendauthresp(struct aim_session_t *sess,
+ struct aim_conn_t *conn,
+ char *sn, char *bosip,
+ char *cookie, char *email,
+ int regstatus)
+{
+ struct command_tx_struct *tx;
+ struct aim_tlvlist_t *tlvlist = NULL;
+
+ if (!(tx = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0004, conn, 1152)))
+ return -1;
+
+ tx->lock = 1;
+
+ if (sn)
+ aim_addtlvtochain_str(&tlvlist, 0x0001, sn, strlen(sn));
+ else
+ aim_addtlvtochain_str(&tlvlist, 0x0001, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
+
+ if (sess->logininfo.errorcode) {
+ aim_addtlvtochain16(&tlvlist, 0x0008, sess->logininfo.errorcode);
+ aim_addtlvtochain_str(&tlvlist, 0x0004, sess->logininfo.errorurl, strlen(sess->logininfo.errorurl));
+ } else {
+ aim_addtlvtochain_str(&tlvlist, 0x0005, bosip, strlen(bosip));
+ aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
+ aim_addtlvtochain_str(&tlvlist, 0x0011, email, strlen(email));
+ aim_addtlvtochain16(&tlvlist, 0x0013, (unsigned short)regstatus);
+ }
+
+ tx->commandlen = aim_writetlvchain(tx->data, tx->commandlen, &tlvlist);
+ tx->lock = 0;
+ return aim_tx_enqueue(sess, tx);
+}
+
+/*
+ * Generate a random cookie. (Non-client use only)
+ */
+faim_export int aim_gencookie(unsigned char *buf)
+{
+ int i;
+
+ srand(time(NULL));
+
+ for (i=0; i < AIM_COOKIELEN; i++)
+ buf[i] = 1+(int) (256.0*rand()/(RAND_MAX+0.0));
+
+ return i;
+}
+
+/*
+ * Send Server Ready. (Non-client)
+ */
+faim_export int aim_sendserverready(struct aim_session_t *sess, struct aim_conn_t *conn)
+{
+ struct command_tx_struct *tx;
+ int i = 0;
+
+ if (!(tx = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+0x22)))
+ return -1;
+
+ tx->lock = 1;
+
+ i += aim_putsnac(tx->data, 0x0001, 0x0003, 0x0000, sess->snac_nextid++);
+
+ i += aimutil_put16(tx->data+i, 0x0001);
+ i += aimutil_put16(tx->data+i, 0x0002);
+ i += aimutil_put16(tx->data+i, 0x0003);
+ i += aimutil_put16(tx->data+i, 0x0004);
+ i += aimutil_put16(tx->data+i, 0x0006);
+ i += aimutil_put16(tx->data+i, 0x0008);
+ i += aimutil_put16(tx->data+i, 0x0009);
+ i += aimutil_put16(tx->data+i, 0x000a);
+ i += aimutil_put16(tx->data+i, 0x000b);
+ i += aimutil_put16(tx->data+i, 0x000c);
+ i += aimutil_put16(tx->data+i, 0x0013);
+ i += aimutil_put16(tx->data+i, 0x0015);
+
+ tx->commandlen = i;
+ tx->lock = 0;
+ return aim_tx_enqueue(sess, tx);
+}
+
+
+/*
+ * Send service redirect. (Non-Client)
+ */
+faim_export unsigned long aim_sendredirect(struct aim_session_t *sess,
+ struct aim_conn_t *conn,
+ unsigned short servid,
+ char *ip,
+ char *cookie)
+{
+ struct command_tx_struct *tx;
+ struct aim_tlvlist_t *tlvlist = NULL;
+ int i = 0;
+
+ if (!(tx = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152)))
+ return -1;
+
+ tx->lock = 1;
+
+ i += aim_putsnac(tx->data+i, 0x0001, 0x0005, 0x0000, 0x00000000);
+
+ aim_addtlvtochain16(&tlvlist, 0x000d, servid);
+ aim_addtlvtochain_str(&tlvlist, 0x0005, ip, strlen(ip));
+ aim_addtlvtochain_str(&tlvlist, 0x0006, cookie, AIM_COOKIELEN);
+
+ tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist)+i;
+ aim_freetlvchain(&tlvlist);
+
+ tx->lock = 0;
+ return aim_tx_enqueue(sess, tx);
+}