[cvslog] (2007-08-18 22:32:35 UTC) Module eggdrop1.9: Change committed!

cvslog cvs at tsss.org
Sat Aug 18 16:32:37 CST 2007


CVSROOT    : /usr/local/cvsroot
Module     : eggdrop1.9
Commit time: 2007-08-18 22:32:34 UTC
Commited by: sven

Modified files:
     lib/eggdrop/Makefile.am lib/eggdrop/base64.c lib/eggdrop/base64.h
     lib/eggdrop/botnet.c lib/eggdrop/botnet.h lib/eggdrop/partyline.c
     lib/eggdrop/partymember.c lib/eggdrop/partymember.h
     lib/eggdrop/xml.c modules/botnet/botnet.c modules/botnet/botnet.h
     modules/botnet/events.c modules/dccparty/events.c
     modules/oldbotnet/events.c modules/oldbotnet/oldbotnet.c

Log message:

Due to some time without internet access this commit is kinda random stuff
thrown together:

 * Moved the int <-> base64 functions to base64.c
 * Added botnet event on_login. This is triggered every time someone logs
   into a bot.
 * Documented some of xml functions.
 * Fixed a xml memory leak. (perhaps. That suff still confuses me.)
 * Fixed a xml bug that crashed the bot if there were comments in an xml file.
 * Wrote about half of the new botnet module. (The easy part.)
 * The version of linked bots is now actually saved and transmitted in the
   oldbotnet module.

 * Added a xml node to the botnet_bot_t struct. This can be used to save any
   kind of information a module or scriptwriter might want to keep for this
   bot. This information has the same lifetime as the bot it refers to and
   is never saved. If the bot leaves the botnet, the information is gone
   unless someone copies it somewhere else befor that happens.
   Depending on how this works out, this xml node might be removed again or
   added to some more data structs like users, partymembers, channels, and
   so on.

---------------------- diff included ----------------------
Index: eggdrop1.9/lib/eggdrop/Makefile.am
diff -u eggdrop1.9/lib/eggdrop/Makefile.am:1.41 eggdrop1.9/lib/eggdrop/Makefile.am:1.42
--- eggdrop1.9/lib/eggdrop/Makefile.am:1.41	Sun Jun  3 18:43:45 2007
+++ eggdrop1.9/lib/eggdrop/Makefile.am	Sat Aug 18 17:32:23 2007
@@ -1,4 +1,4 @@
-# $Id: Makefile.am,v 1.41 2007-06-03 23:43:45 sven Exp $
+# $Id: Makefile.am,v 1.42 2007-08-18 22:32:23 sven Exp $
 
 MAINTAINERCLEANFILES	= Makefile.in
 
@@ -37,7 +37,6 @@
 			ircmasks.c ircmasks.h \
 			ircparse.c ircparse.h \
 			linemode.c linemode.h \
-			netstring.c netstring.h \
 			logging.c logging.h \
 			match.c match.h \
 			md5.c md5.h \
Index: eggdrop1.9/lib/eggdrop/base64.c
diff -u eggdrop1.9/lib/eggdrop/base64.c:1.3 eggdrop1.9/lib/eggdrop/base64.c:1.4
--- eggdrop1.9/lib/eggdrop/base64.c:1.3	Fri Jun 25 12:44:03 2004
+++ eggdrop1.9/lib/eggdrop/base64.c	Sat Aug 18 17:32:23 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: base64.c,v 1.3 2004-06-25 17:44:03 darko Exp $";
+static const char rcsid[] = "$Id: base64.c,v 1.4 2007-08-18 22:32:23 sven Exp $";
 #endif
 
 #include <stdlib.h>
@@ -117,3 +117,76 @@
 	dest[i] = 0;
 	return(i);
 }
+static char base64to[256] = {
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,	 0,  0,  0,  0,  0,  0,  0,  0,
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0,  0,  0,  0,
+	 0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62,  0, 63,  0,  0,
+	 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+};
+
+static int tobase64[64] = {
+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+	'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[', ']'
+};
+
+/*!
+ * \brief Decodes a base64 string into an int.
+ *
+ * \note Uses the non-standard eggdrop1.6 style algorithm.
+ *
+ * \param b A base64 string.
+ *
+ * \return The decoded int value.
+ */
+
+int b64dec_int(const char *b)
+{
+	int i = 0;
+
+	while (*b) i = (i << 6) + base64to[(unsigned char) *b++];
+	return i;
+}
+
+/*!
+ * \brief Calculate the base64 value of an int.
+ *
+ * \note Uses the non-standard eggdrop1.6 style algotithm.
+ *
+ * \param i The number to convert.
+ *
+ * \return A string containing the base64 value of \e i.
+ *
+ * \warning This function returns a pointer to a static buffer. Calling it
+ *          again will overwrite it. \b Always \b remember!
+ */
+
+const char *b64enc_int(int i)
+{
+	char *pos;
+	static char ret[12];
+
+	pos = ret + 11;
+	*pos = 0;
+
+	do {
+		--pos;
+		*pos = tobase64[i & 0x3F];
+		i >>= 6;
+	} while (i);
+
+	return pos;
+}
Index: eggdrop1.9/lib/eggdrop/base64.h
diff -u eggdrop1.9/lib/eggdrop/base64.h:1.2 eggdrop1.9/lib/eggdrop/base64.h:1.3
--- eggdrop1.9/lib/eggdrop/base64.h:1.2	Wed Dec 17 01:39:14 2003
+++ eggdrop1.9/lib/eggdrop/base64.h	Sat Aug 18 17:32:23 2007
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Id: base64.h,v 1.2 2003-12-17 07:39:14 wcc Exp $
+ * $Id: base64.h,v 1.3 2007-08-18 22:32:23 sven Exp $
  */
 
 #ifndef _EGG_BASE64_H_
@@ -28,4 +28,9 @@
 char *b64dec(const unsigned char *data, int len);
 int b64dec_buf(const unsigned char *data, int len, char *dest);
 
+const char *b64enc_int(int i);
+char *b64enc_int_buf(int i, char *dest);
+
+int b64dec_int(const char *b);
+
 #endif /* !_EGG_BASE64_H_ */
Index: eggdrop1.9/lib/eggdrop/botnet.c
diff -u eggdrop1.9/lib/eggdrop/botnet.c:1.10 eggdrop1.9/lib/eggdrop/botnet.c:1.11
--- eggdrop1.9/lib/eggdrop/botnet.c:1.10	Wed May  9 19:25:07 2007
+++ eggdrop1.9/lib/eggdrop/botnet.c	Sat Aug 18 17:32:23 2007
@@ -28,7 +28,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: botnet.c,v 1.10 2007-05-10 00:25:07 sven Exp $";
+static const char rcsid[] = "$Id: botnet.c,v 1.11 2007-08-18 22:32:23 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -295,6 +295,7 @@
 	bot->handler = handler;
 	bot->client_data = client_data;
 	bot->owner = owner;
+	bot->info = xml_node_new();
 
 	hash_table_insert(bot_ht, bot->name, bot);
 	
@@ -379,7 +380,7 @@
 		return 0;
 	}
 
-	snprintf(obuf, sizeof(obuf), "%s (%s)", reason, from->full_name);
+	snprintf(obuf, sizeof(obuf), "%s (%s)", reason, entity_full_name(from));
 
 	if (bot->handler && bot->handler->on_lost_bot) bot->handler->on_lost_bot(bot->client_data, bot, obuf);
 	if (from->what == ENTITY_PARTYMEMBER) partymember_msgf(from->user, &me, _("Unlinked from %s."), bot->name);
@@ -417,6 +418,7 @@
 	}
 	hash_table_remove(bot_ht, bot->name, NULL);
 
+	xml_node_delete(bot->info);
 	free(bot->name);
 	free(bot);
 }
@@ -570,7 +572,7 @@
  * \warning Don't call this unless you're botnet_replay_net().
  */
 
-static void botnet_recursive_replay_net(botnet_bot_t *dst, botnet_bot_t *start, partymember_t *members)
+static void botnet_recursive_replay_net(botnet_bot_t *dst, botnet_bot_t *start)
 {
 	int i;
 	botnet_bot_t *tmp;
@@ -578,19 +580,17 @@
 
 	if (start && dst->handler->on_new_bot) dst->handler->on_new_bot(dst->client_data, start, 1);
 	
-	if (dst->handler->on_join) {
-		for (p = members; p; p = p->next) {
-			if (p->flags & PARTY_DELETED) continue;
-			if (p->bot != start) continue;
-			for (i = 0; i < p->nchannels; ++i) {
-				dst->handler->on_join(dst->client_data, p->channels[i], p, 1);
-			}
+	for (p = start->partys; p; p = p->next_on_bot) {
+		if (p->flags & PARTY_DELETED) continue;
+		if (dst->handler->on_login) dst->handler->on_login(dst->client_data, p, 1);
+		for (i = 0; i < p->nchannels; ++i) {
+			if (dst->handler->on_join) dst->handler->on_join(dst->client_data, p->channels[i], p, 1);
 		}
 	}
 
 	for (tmp = bot_head; tmp; tmp = tmp->next) {
 		if (tmp->flags & BOT_DELETED || tmp == dst) continue;
-		if (tmp->uplink == start) botnet_recursive_replay_net(dst, tmp, members);
+		if (tmp->uplink == start) botnet_recursive_replay_net(dst, tmp);
 	}
 }
 
@@ -606,7 +606,7 @@
 
 void botnet_replay_net(botnet_bot_t *dst)
 {
-	botnet_recursive_replay_net(dst, NULL, partymember_get_head());
+	botnet_recursive_replay_net(dst, NULL);
 }
 
 /*!
@@ -796,13 +796,10 @@
 		if (src->what == ENTITY_PARTYMEMBER) partymember_msg(src->user, &entity_me, _("Can't link there: Already linked."), -1);
 		return -2;
 	}
-	if (user_get_setting(user, NULL, "bot.type", &type)) {
-		if (src->what == ENTITY_PARTYMEMBER) partymember_msg(src->user, &entity_me, _("Can't link there: Unknown bot type."), -1);
-		return -3;
-	}
+	if (user_get_setting(user, NULL, "bot.type", &type)) type = "eggdrop";
 	if (!user_get_setting(user, NULL, "bot.link-priority", &priority) && atoi(priority) < 0) {
 		if (src->what == ENTITY_PARTYMEMBER) partymember_msg(src->user, &entity_me, _("Won't link there: Negative link priority."), -1);
-		return -4;
+		return -3;
 	}
 
 	user->flags |= USER_LINKING_BOT;
@@ -817,6 +814,24 @@
 	return 0;
 }
 
+const char *botnet_get_info(botnet_bot_t *bot, const char *name)
+{
+	char *ret;
+
+	xml_node_get_str(&ret, bot->info, name, (void *) 0);
+	return ret;
+}
+
+void botnet_set_info(botnet_bot_t *bot, const char *name, const char *value)
+{
+	xml_node_set_str(value, bot->info, name, (void *) 0);
+}
+
+void botnet_set_info_int(botnet_bot_t *bot, const char *name, int value)
+{
+	xml_node_set_int(value, bot->info, name, (void *) 0);
+}
+
 /*!
  * \brief Sends a partyline channel join out to the botnet
  *
Index: eggdrop1.9/lib/eggdrop/botnet.h
diff -u eggdrop1.9/lib/eggdrop/botnet.h:1.6 eggdrop1.9/lib/eggdrop/botnet.h:1.7
--- eggdrop1.9/lib/eggdrop/botnet.h:1.6	Tue May  8 20:32:31 2007
+++ eggdrop1.9/lib/eggdrop/botnet.h	Sat Aug 18 17:32:23 2007
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Id: botnet.h,v 1.6 2007-05-09 01:32:31 sven Exp $
+ * $Id: botnet.h,v 1.7 2007-08-18 22:32:23 sven Exp $
  */
 
 #ifndef _EGG_BOTNET_H_
@@ -34,6 +34,7 @@
 
 typedef struct {
 	/* Events that don't depend on a single chan. */
+	int (*on_login)(void *client_data, partymember_t *new, int netburst);
 	int (*on_bcast)(void *client_data, botnet_entity_t *src, const char *text, int len);
 	int (*on_privmsg)(void *client_data, botnet_entity_t *src, partymember_t *dst, const char *text, int len);
 	int (*on_nick)(void *client_data, partymember_t *src, const char *newnick);
@@ -74,6 +75,7 @@
 	void *client_data;                 //!< Some data passed back to every callback function.
 	event_owner_t *owner;              //!< The owner of this bot.
 	partymember_t *partys;             //!< Start of the list of partymembers on this bot.
+	xml_node_t *info;                  //!< Save anything you want here.
 	struct botnet_bot *prev;           //!< Previous bot in the list.
 	struct botnet_bot *next;           //!< Next bot in the list.
 	struct botnet_bot *prev_local;     //!< Previous bot in the list of local bots. NULL if this bot isn't local.
@@ -95,7 +97,7 @@
  * \endcode
  */
 
-#define user_entity(user) {ENTITY_PARTYMEMBER, (user), 0, (user)->full_id_name, (user)->full_name, (user)->common_name}
+#define user_entity(user) {ENTITY_PARTYMEMBER, (user), 0}
 
 /*!
  * \brief Creates an entity from a bot.
@@ -106,35 +108,33 @@
  * Example:
  * \code
  * botnet_entity_t other = bot_entity(some_bot);
- * botnet_entity_t me = bot_entity(0);
+ * botnet_entity_t me = bot_entity((botnet_bot *) 0);
  * \endcode
  */
 
-#define bot_entity(bot) {ENTITY_BOT, 0, (bot), (bot) ? (bot)->name : botnet_get_name(), (bot) ? (bot)->name : botnet_get_name(), (bot) ? (bot)->name : botnet_get_name()}
+#define bot_entity(bot) {ENTITY_BOT, 0, (bot)}
 
 #define set_user_entity(e, u) do {\
 	(e)->what = ENTITY_PARTYMEMBER;\
 	(e)->user = (u);\
-	(e)->full_id_name = (u)->full_id_name;\
-	(e)->full_name = (u)->full_name;\
-	(e)->common_name = (u)->common_name;\
 } while (0)
 
 #define set_bot_entity(e, b) do {\
 	(e)->what = ENTITY_BOT;\
 	(e)->bot = (b);\
-	(e)->full_id_name = (e)->full_name = (e)->common_name = (b) ? (b)->name : botnet_get_name();\
 } while (0)
 
 struct botnet_entity {
 	int what;                          //!< ::ENTITY_PARTYMEMBER or ::ENTITY_BOT
 	partymember_t *user;
 	botnet_bot_t *bot;
-	const char *full_id_name;
-	const char *full_name;
-	const char *common_name;
 };
 
+#define entity_full_id_name(e) ((e)->what == ENTITY_BOT ? (e)->bot ? (e)->bot->name : botnet_get_name() : (e)->user->full_id_name)
+#define entity_full_name(e) ((e)->what == ENTITY_BOT ? (e)->bot ? (e)->bot->name : botnet_get_name() : (e)->user->full_name)
+#define entity_common_name(e) ((e)->what == ENTITY_BOT ? (e)->bot ? (e)->bot->name : botnet_get_name() : (e)->user->bot ? (e)->user->full_name : (e)->user->nick)
+#define entity_net_name(e) ((e)->what == ENTITY_BOT ? (e)->bot ? (e)->bot->name : botnet_get_name() : (e)->user->net_name)
+
 int botnet_init(void);
 int botnet_shutdown(void);
 
@@ -153,6 +153,10 @@
 int botnet_unlink(botnet_entity_t *from, botnet_bot_t *bot, const char *reason);
 int botnet_link(botnet_entity_t *src, botnet_bot_t *dst, const char *target);
 
+const char *botnet_get_info(botnet_bot_t *bot, const char *name);
+void botnet_set_info(botnet_bot_t *bot, const char *name, const char *value);
+void botnet_set_info_int(botnet_bot_t *bot, const char *name, int value);
+
 void botnet_replay_net(botnet_bot_t *bot);
 int botnet_check_direction(botnet_bot_t *direction, botnet_bot_t *src);
 
Index: eggdrop1.9/lib/eggdrop/partyline.c
diff -u eggdrop1.9/lib/eggdrop/partyline.c:1.28 eggdrop1.9/lib/eggdrop/partyline.c:1.29
--- eggdrop1.9/lib/eggdrop/partyline.c:1.28	Sat Apr 14 10:21:11 2007
+++ eggdrop1.9/lib/eggdrop/partyline.c	Sat Aug 18 17:32:23 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: partyline.c,v 1.28 2007-04-14 15:21:11 sven Exp $";
+static const char rcsid[] = "$Id: partyline.c,v 1.29 2007-08-18 22:32:23 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -239,9 +239,9 @@
 
 	if (src) {
 		if (len >= 9 && !strncasecmp(text, "\1ACTION ", 8) && text[len - 1] == 1) {
-			egg_iprintf(idx, "%s* %s %.*s\r\n", ts, src->common_name, len - 9, text + 8);
+			egg_iprintf(idx, "%s* %s %.*s\r\n", ts, entity_common_name(src), len - 9, text + 8);
 		} else {
-			egg_iprintf(idx, "%s[%s] %s\r\n", ts, src->common_name, text);
+			egg_iprintf(idx, "%s[%s] %s\r\n", ts, entity_common_name(src), text);
 		}
 	} else {
 		egg_iprintf(idx, "%s\r\n", text);
@@ -270,9 +270,9 @@
 
 	if (src) {
 		if (len >= 9 && !strncasecmp(text, "\1ACTION ", 8) && text[len - 1] == 1) {
-			egg_iprintf(idx, "%s %s* %s %.*s\r\n", chan->name, ts, src->common_name, len - 9, text + 8);
+			egg_iprintf(idx, "%s %s* %s %.*s\r\n", chan->name, ts, entity_common_name(src), len - 9, text + 8);
 		} else {
-			egg_iprintf(idx, "%s %s<%s> %s\r\n", chan->name, ts, src->common_name, text);
+			egg_iprintf(idx, "%s %s<%s> %s\r\n", chan->name, ts, entity_common_name(src), text);
 		}
 	} else {
 		egg_iprintf(idx, "%s %s%s\r\n", chan->name, ts, text);
Index: eggdrop1.9/lib/eggdrop/partymember.c
diff -u eggdrop1.9/lib/eggdrop/partymember.c:1.28 eggdrop1.9/lib/eggdrop/partymember.c:1.29
--- eggdrop1.9/lib/eggdrop/partymember.c:1.28	Tue May  8 20:32:31 2007
+++ eggdrop1.9/lib/eggdrop/partymember.c	Sat Aug 18 17:32:23 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: partymember.c,v 1.28 2007-05-09 01:32:31 sven Exp $";
+static const char rcsid[] = "$Id: partymember.c,v 1.29 2007-08-18 22:32:23 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -75,10 +75,11 @@
 	if (p->next_on_bot) p->next_on_bot->prev_on_bot = p->prev_on_bot;
 
 	/* Free! */
-	if (p->nick) free(p->nick);
+	free(p->nick);
 	if (p->ident) free(p->ident);
 	if (p->host) free(p->host);
-	if (p->full_id_name) free(p->full_id_name);
+	free(p->net_name);
+	free(p->full_id_name);
 	if (p->channels) free(p->channels);
 
 	/* Zero it out in case anybody has kept a reference (bad!). */
@@ -126,6 +127,7 @@
 	mem->nick = strdup(nick);
 	mem->ident = strdup(ident);
 	mem->host = strdup(host);
+	mem->net_name = egg_mprintf("%s@%s", b64enc_int(id), bot ? bot->name : botnet_get_name());
 	mem->full_id_name = egg_mprintf("%d:%s@%s", id, nick, bot ? bot->name : botnet_get_name());
 	mem->full_name = strchr(mem->full_id_name, ':') + 1;
 	mem->common_name = bot ? mem->full_name : mem->nick;
Index: eggdrop1.9/lib/eggdrop/partymember.h
diff -u eggdrop1.9/lib/eggdrop/partymember.h:1.7 eggdrop1.9/lib/eggdrop/partymember.h:1.8
--- eggdrop1.9/lib/eggdrop/partymember.h:1.7	Sat Apr 14 10:21:12 2007
+++ eggdrop1.9/lib/eggdrop/partymember.h	Sat Aug 18 17:32:23 2007
@@ -16,7 +16,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Id: partymember.h,v 1.7 2007-04-14 15:21:12 sven Exp $
+ * $Id: partymember.h,v 1.8 2007-08-18 22:32:23 sven Exp $
  */
 
 #ifndef _EGG_PARTYMEMBER_H
@@ -34,6 +34,7 @@
 	struct botnet_bot *bot;
 	int flags;
 
+	char *net_name;
 	char *full_id_name;
 	const char *full_name;
 	const char *common_name;
Index: eggdrop1.9/lib/eggdrop/xml.c
diff -u eggdrop1.9/lib/eggdrop/xml.c:1.25 eggdrop1.9/lib/eggdrop/xml.c:1.26
--- eggdrop1.9/lib/eggdrop/xml.c:1.25	Thu Mar  3 12:44:47 2005
+++ eggdrop1.9/lib/eggdrop/xml.c	Sat Aug 18 17:32:23 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: xml.c,v 1.25 2005-03-03 18:44:47 stdarg Exp $";
+static const char rcsid[] = "$Id: xml.c,v 1.26 2007-08-18 22:32:23 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -35,7 +35,12 @@
 	str_redup(&last_error, err);
 }
 
-/* Get a new, blank node. */
+/*!
+ * \brief Get a new, blank node.
+ *
+ * \return The new, empty node.
+ */
+
 xml_node_t *xml_node_new()
 {
 	xml_node_t *node;
@@ -45,7 +50,14 @@
 	return node;
 }
 
-/* Get a new, named node. */
+/*!
+ * \brief Get a new, named node.
+ *
+ * \param name The name of the node.
+ *
+ * \return The new, empty node.
+ */
+
 xml_node_t *xml_node_new_named(const char *name)
 {
 	xml_node_t *node = xml_node_new();
@@ -53,7 +65,12 @@
 	return(node);
 }
 
-/* Free all memory associated with a node. */
+/*!
+ * \brief Free all memory associated with a node.
+ *
+ * \param node The node to be free'd.
+ */
+
 void xml_node_free(xml_node_t *node)
 {
 	xml_attr_t *attr;
@@ -66,8 +83,18 @@
 		xml_attr_free(attr);
 	}
 	if (node->attributes) free(node->attributes);
+	free(node);
 }
 
+/*!
+ * \brief Unlinks a XML node from a tree.
+ *
+ * Removes a node from a tree. Unlinks the node from its parent and siblings,
+ * but all nodes descending from this one will still be attached.
+ *
+ * \param node The node to unlink.
+ */
+
 void xml_node_unlink(xml_node_t *node)
 {
 	xml_node_t *parent = node->parent;
@@ -90,11 +117,32 @@
 	if (node->next_sibling) node->next_sibling->prev_sibling = node->prev_sibling;
 }
 
+/*!
+ * \brief Deletes a node.
+ *
+ * This function is a wrapper for xml_node_delete_callbacked() without a
+ * callback.
+ *
+ * \todo Might be better as a macro.
+ *
+ * \param node The node to delete.
+ */
+
 void xml_node_delete(xml_node_t *node)
 {
 	xml_node_delete_callbacked(node, NULL);
 }
 
+/*!
+ * \brief Deletes a node and executes a callback function.
+ *
+ * This function deletes a node and all of its children and attributes. For
+ * every deleted node the callback function is executed.
+ *
+ * \param node The node to delete.
+ * \param callback The callback function to execute. May be NULL.
+ */
+
 void xml_node_delete_callbacked(xml_node_t *node, void (*callback)(void *))
 {
 	xml_node_t *child;
@@ -113,6 +161,15 @@
 	xml_node_free(node);
 }
 
+/*!
+ * \brief Deletes an entire tree.
+ *
+ * This function will delete the entire tree a node is in. The node does not
+ * have to be the root of that tree, any node of the tree will do.
+ *
+ * \param root Any node in the tree that will be deleted. Does not really have to be the root node.
+ */
+
 void xml_doc_delete(xml_node_t *root)
 {
 	while (root->parent) root = root->parent;
@@ -144,6 +201,23 @@
 	return(node);
 }
 
+/*!
+ * \brief Get a child of a node by its name.
+ *
+ * This function searches a tree beginning with a given node and its children
+ * for a child by a given name.
+ *
+ * This name can be very complex with serveral layers of the tree seperated by
+ * '.' and an index with "[x]. Example: "layer1.layer2[3].layer3".
+ *
+ * \param root The node to start searching from.
+ * \param path The name or path of the child to search for.
+ * \param index Added to the index of every layer. Best used for a simple query without multiple layers.
+ * \param create If this is non-zero and the node was not found it will be created.
+ *
+ * \return The node searched for or, if it was not found and \e create was zero, NULL.
+ */
+
 xml_node_t *xml_node_path_lookup(xml_node_t *root, const char *path, int index, int create)
 {
 	int thisindex, len;
@@ -255,6 +329,19 @@
 	return(-1);
 }
 
+/*!
+ * \brief Get an int or the default value from a node.
+ *
+ * Will convert the text of a given node to an int and return the value. If
+ * no node was given or the node does not contain text, a default value will
+ * be returned.
+ *
+ * \param node The node to extract the int from.
+ * \param def The default value to return in case the node does not contain text.
+ *
+ * \return Either the value from the node or the default value.
+ */
+
 int xml_node_int(xml_node_t *node, int def)
 {
 	int value;
@@ -281,6 +368,18 @@
 	return(-1);
 }
 
+/*!
+ * \brief Get a string or the default value from a node.
+ *
+ * Will return the text of a given node as a string. If no node was given or
+ * the node does not contain text, a default value will be returned.
+ *
+ * \param node The node to return the string from.
+ * \param def The default value to return in case the node does not contain text.
+ *
+ * \return Either the value from the node or the default value.
+ */
+
 char *xml_node_str(xml_node_t *node, char *def)
 {
 	if (!node || !node->text) return(def);
@@ -385,6 +484,16 @@
 	 return node;
 }
 
+/*!
+ * \brief Attaches a node to a parent.
+ *
+ * Sets a node as a child of a parent node. This node must not have a parent!
+ * If it does, use xml_node_unlink() first!
+ *
+ * \param parent The node that will be the parent.
+ * \param child The node that will be attached to the parent.
+ */
+
 void xml_node_append(xml_node_t *parent, xml_node_t *child)
 {	
 	xml_node_t *node;
@@ -402,8 +511,9 @@
 
 	parent->last_child = child;
 
+	if (!child->name) return;
 	for (node = child->prev; node; node = node->prev) {
-		if (!strcasecmp(node->name, child->name)) {
+		if (node->name && !strcasecmp(node->name, child->name)) {
 			node->next_sibling = child;
 			child->prev_sibling = node;
 			break;
@@ -411,6 +521,19 @@
 	}
 }
 
+/*!
+ * \brief Create a new attribute.
+ *
+ * Creates a new attribute and fills its fields. The strings used as
+ * parameters to this function will not be dup'd but used as is. The
+ * parameters must not be NULL.
+ *
+ * \param name The name of the attribute.
+ * \param value The value of the attribute. An empty string is fine, NULL is not.
+ *
+ * \return The new attribute.
+ */
+
 xml_attr_t *xml_attr_new(char *name, char *value)
 {
 	xml_attr_t *attr;
@@ -422,6 +545,14 @@
 	return(attr);
 }
 
+/*!
+ * \brief Frees a node's attribute.
+ *
+ * This will delete an attribute and free all it's memory.
+ *
+ * \param attr The attribute to free.
+ */
+
 void xml_attr_free(xml_attr_t *attr)
 {
 	if (attr->name) free(attr->name);
@@ -429,6 +560,15 @@
 	free(attr);
 }
 
+/*!
+ * \brief Append an attribute to a node.
+ *
+ * \param node The node to appand the attribute to.
+ * \param attr The attribute to append.
+ *
+ * \return Always 0.
+ */
+
 int xml_node_append_attr(xml_node_t *node, xml_attr_t *attr)
 {
 	node->attributes = realloc(node->attributes, sizeof(*node->attributes) * (node->nattributes+1));
@@ -436,6 +576,18 @@
 	return(0);
 }
 
+/*!
+ * \brief Searches for an attribute with a given name.
+ *
+ * Searches all attributes of a node for a given name. If an attribute with
+ * that name is found, it's returned.
+ *
+ * \param node The node to search.
+ * \param name The name of the attribute to search for.
+ *
+ * \return The attribute if found, otherwise NULL.
+ */
+
 xml_attr_t *xml_attr_lookup(xml_node_t *node, const char *name)
 {
 	int i;
@@ -446,6 +598,20 @@
 	return(NULL);
 }
 
+/*!
+ * \brief Get an int or the default value from an attribute of a node.
+ *
+ * Will return the int value of the text of a given attribute of a node. If
+ * the node does not have an attribute of the given name or the attribute does
+ * not contain text, a default value will be returned.
+ *
+ * \param node The node to return the int from.
+ * \param name The name of the attribute.
+ * \param def The default value to return in case no text is available.
+ *
+ * \return Either the value of the attribute or the default value.
+ */
+
 int xml_attr_int(xml_node_t *node, const char *name, int def)
 {
 	xml_attr_t *attr = xml_attr_lookup(node, name);
@@ -453,6 +619,20 @@
 	else return(def);
 }
 
+/*!
+ * \brief Get a string or the default value from an attribute of a node.
+ *
+ * Will return the text of a given attribute of a node as a string. If the
+ * node does not have an attribute of the given name or the attribute does
+ * not contain text, a default value will be returned.
+ *
+ * \param node The node to return the string from.
+ * \param name The name of the attribute.
+ * \param def The default value to return in case no text is available.
+ *
+ * \return Either the value of the attribute or the default value.
+ */
+
 char *xml_attr_str(xml_node_t *node, const char *name, char *def)
 {
 	xml_attr_t *attr = xml_attr_lookup(node, name);
Index: eggdrop1.9/modules/botnet/botnet.c
diff -u eggdrop1.9/modules/botnet/botnet.c:1.1 eggdrop1.9/modules/botnet/botnet.c:1.2
--- eggdrop1.9/modules/botnet/botnet.c:1.1	Sun Jun  3 18:43:45 2007
+++ eggdrop1.9/modules/botnet/botnet.c	Sat Aug 18 17:32:24 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: botnet.c,v 1.1 2007-06-03 23:43:45 sven Exp $";
+static const char rcsid[] = "$Id: botnet.c,v 1.2 2007-08-18 22:32:24 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -49,6 +49,18 @@
 static int idx_on_eof(void *client_data, int idx, int err, const char *errmsg);
 static int idx_on_delete(void *client_data, int idx);
 
+static int got_newbot(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
+
+static struct {
+	char *cmd;
+	int source;
+	int (*function)(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len);
+} cmd_mapping[] = {
+	{"newbot", ENTITY_BOT, got_newbot}
+};
+
+static int cmd_num = sizeof(cmd_mapping) / sizeof(cmd_mapping[0]);
+
 static int listen_idx;
 
 static botnet_config_t botnet_config;
@@ -156,6 +168,31 @@
 	return(BIND_RET_LOG);
 }
 
+static int get_entity(botnet_entity_t *ent, const char *text)
+{
+	char *p;
+	int id = -1;
+	botnet_bot_t *bot;
+	partymember_t *pm;
+
+	p = strchr(text, '@');
+	if (p) {
+		*p = 0;
+		id = b64dec_int(text);
+		text = p + 1;
+	}
+	bot = botnet_lookup(text);
+	if (!bot && strcmp(text, botnet_get_name())) return 1;
+	if (id == -1) {
+		set_bot_entity(ent, bot);
+		return 0;
+	}
+	pm = partymember_lookup(NULL, bot, id);
+	if (!pm) return 1;
+	set_user_entity(ent, pm);
+	return 0;
+}
+
 static int do_link(user_t *user, const char *type)
 {
 	char *host = NULL, *portstr = NULL, *password = NULL;
@@ -167,7 +204,7 @@
 	user_get_setting(user, NULL, "bot.password", &password);
 
 	if (portstr) port = atoi(portstr);
-	if (!host || !portstr || port < 0 || port > 65535) {
+	if (!host || !portstr || port <= 0 || port > 65535) {
 		putlog(LOG_MISC, "*", _("Error linking %s: Invalid telnet address:port stored."), user->handle);
 		return BIND_RET_BREAK;
 	}
@@ -176,11 +213,11 @@
 	data->bot = NULL;
 	data->user = user;
 	data->idx = egg_connect(host, port, -1);
-	if (password) data->password = strdup(password);
-	else data->password = NULL;
+	data->proto = NULL;
+	if (password) data->pass = strdup(password);
+	else data->pass = NULL;
 	data->incoming = 0;
 	data->linking = 1;
-	data->version = 0;
 	data->idle = 0;
 
 	sockbuf_set_handler(data->idx, &client_handler, data);
@@ -190,6 +227,28 @@
 	return BIND_RET_BREAK;
 }
 
+/* newbot uplink name type version fullversion linking */
+
+static int got_newbot(bot_t *bot, botnet_entity_t *src, char *cmd, int argc, char *argv[21], int len)
+{
+	int flags;
+	botnet_bot_t *new;
+
+	if (argc < 5) return 0;
+	
+	flags = b64dec_int(argv[4]);
+	new = botnet_new(argv[0], NULL, src->bot, bot->bot, NULL, NULL, &generic_owner, flags & 1);
+	if (!new) {
+		botnet_delete(bot->bot, _("Couldn't create introduced bot"));
+		return 0;
+	}
+	botnet_set_info(new, "type", argv[1]);
+	botnet_set_info_int(new, "numversion", b64dec_int(argv[2]));
+	botnet_set_info(new, "version", argv[3]);
+
+	return 0;
+}
+
 static int idx_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port)
 {
 	bot_t *session;
@@ -198,10 +257,10 @@
 	session->bot = NULL;
 	session->user = NULL;
 	session->idx = newidx;
-	session->password = NULL;
+	session->proto = NULL;
+	session->pass = NULL;
 	session->incoming = 1;
 	session->linking = 1;
-	session->version = 0;
 	session->idle = 0;
 
 	sockbuf_set_handler(newidx, &client_handler, session);
@@ -212,15 +271,229 @@
 
 static int idx_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
 {
-	sockbuf_write(idx, "p", 1);
+	egg_iprintf(idx, ":%s proto", botnet_get_name());
+
+	return 0;
+}
+
+/*!
+ * \brief Handles the login for incomming links.
+ *
+ * \param bot The ::bot_t struct for this link.
+ * \param src The source of this message. This is a string!
+ * \param cmd The command.
+ * \param argc The number of parameters.
+ * \param argv Up to 20 parameters. NULL terminated.
+ * \param len The length of the last parameter.
+ *
+ * \return Always 0.
+ */
+
+static int recving_login(bot_t *bot, char *src, char *cmd, int argc, char *argv[], int len) {
+	if (!bot->user) {
+		if (!src) {
+			sockbuf_delete(bot->idx);
+			return 0;
+		} else {
+			bot->user = user_lookup_by_handle(src);
+			if (!bot->user || !(bot->user->flags & USER_BOT) || !strcmp(src, botnet_get_name())) {
+				sockbuf_delete(bot->idx);
+				return 0;
+			}
+			if (botnet_lookup(src) || bot->user->flags & (USER_LINKING_BOT | USER_LINKED_BOT)) {
+				sockbuf_delete(bot->idx);
+				return 0;
+			}
+		}
+	}
+	if (src && strcmp(src, bot->user->handle)) {
+		sockbuf_delete(bot->idx);
+		return 0;
+	}
+	if (!strcasecmp(cmd, "PROTO")) {
+		if (bot->proto) {
+			sockbuf_delete(bot->idx);
+			return 0;
+		}
+		bot->proto = malloc(sizeof(*bot->proto));
+		bot->proto->dummy = 0;
+		egg_iprintf(bot->idx, "PROTO");
+	} else if (!strcasecmp(cmd, "HELLO")) {
+		int i;
+		char salt[33], *pass = NULL;
+		unsigned char hash[16];
+		MD5_CTX md5;
+
+		if (bot->pass || argc != 1 || strcmp(argv[0], botnet_get_name())) {
+			sockbuf_delete(bot->idx);
+			return 0;
+		}
+		user_get_setting(bot->user, NULL, "bot.password", &pass);
+		if (!pass || !*pass) {
+			egg_iprintf(bot->idx, "thisbot eggdrop %s %s %s :%s", botnet_get_name(), "1090000", "eggdrop1.9.0+cvs", "some informative stuff");
+			bot->pass = calloc(1, 1);
+			return 0;
+		}
+		for (i = 0; i < 32; ++i) {
+			salt[i] = random() % 62;
+			if (salt[i] < 26) salt[i] += 'A';
+			else if (salt[i] < 52) salt[i] += 'a';
+			else salt[i] += '0';
+		}
+		salt[32] = 0;
+		MD5_Init(&md5);
+		MD5_Update(&md5, salt, 32);
+		MD5_Update(&md5, pass, strlen(pass));
+		MD5_Final(hash, &md5);
+		bot->pass = malloc(33);
+		MD5_Hex(hash, bot->pass);
+		egg_iprintf(bot->idx, "passreq %s", salt);
+	} else if (!strcasecmp(cmd, "PASS")) {
+		if (!bot->pass || argc != 1 || strcmp(argv[0], bot->pass)) {
+			sockbuf_delete(bot->idx);
+			return 0;
+		}
+		*bot->pass = 0;
+		egg_iprintf(bot->idx, "thisbot %s eggdrop %s %s :%s", botnet_get_name(), "1090000", "eggdrop1.9.0+cvs", "some informative stuff");
+	} else if (!strcasecmp(cmd, "THISBOT")) {
+		if (!bot->pass || *bot->pass || argc != 5 || strcmp(bot->user->handle, argv[0])) {
+			sockbuf_delete(bot->idx);
+			return 0;
+		}
+		free(bot->pass);
+		bot->pass = NULL;
+		bot->linking = 0;
+		bot->bot = botnet_new(bot->user->handle, bot->user, NULL, NULL, &bothandler, bot, &bot_owner, 0);
+		botnet_set_info(bot->bot, "type", argv[0]);
+		botnet_set_info_int(bot->bot, "numversion", b64dec_int(argv[2]));
+		botnet_set_info(bot->bot, "version", argv[3]);
+		botnet_replay_net(bot->bot);
+		egg_iprintf(bot->idx, "el");
+	} else {
+		sockbuf_delete(bot->idx);
+	}
+	return 0;
+}
 
+static int sending_login(bot_t *bot, char *src, char *cmd, int argc, char *argv[], int len)
+{
+	if (src && strcmp(src, bot->user->handle)) {
+		egg_iprintf(bot->idx, "error :Wrong bot.");
+		sockbuf_delete(bot->idx);
+		return 0;
+	}
+	if (!strcasecmp(cmd, "PROTO")) {
+		if (bot->proto) {
+			egg_iprintf(bot->idx, "error :Been there, done that.");
+			sockbuf_delete(bot->idx);
+			return 0;
+		}
+		bot->proto = malloc(sizeof(*bot->proto));
+		bot->proto->dummy = 0;
+		egg_iprintf(bot->idx, "hello %s", bot->user->handle);
+	} else if (!strcasecmp(cmd, "PASSREQ")) {
+		char buf[33];
+		unsigned char hash[16];
+		MD5_CTX md5;
+		if (argc != 1 || !bot->proto || !bot->pass || !*bot->pass) {
+			if (!bot->pass) putlog(LOG_MISC, "*", "botnet error: password on %s needs to be reset.", bot->user->handle);
+			egg_iprintf(bot->idx, "error :Expected something else.");
+			sockbuf_delete(bot->idx);
+			return 0;
+		}
+		MD5_Init(&md5);
+		MD5_Update(&md5, argv[0], len);
+		MD5_Update(&md5, bot->pass, strlen(bot->pass));
+		MD5_Final(hash, &md5);
+		MD5_Hex(hash, buf);
+		egg_iprintf(bot->idx, "pass %s", buf);
+		*bot->pass = 0;
+	} else if (!strcasecmp(cmd, "THISBOT")) {
+		if (argc != 5 || strcmp(bot->user->handle, argv[0])) {
+			sockbuf_delete(bot->idx);
+			return 0;
+		}
+		egg_iprintf(bot->idx, "thisbot eggdrop %s %s %s :%s", botnet_get_name(), "1090000", "eggdrop1.9.0+cvs", "some informative stuff");
+		free(bot->pass);
+		bot->pass = NULL;
+		bot->linking = 0;
+		bot->bot = botnet_new(bot->user->handle, bot->user, NULL, NULL, &bothandler, bot, &bot_owner, 0);
+		botnet_set_info(bot->bot, "type", argv[0]);
+		botnet_set_info_int(bot->bot, "numversion", b64dec_int(argv[2]));
+		botnet_set_info(bot->bot, "version", argv[3]);
+		botnet_replay_net(bot->bot);
+		egg_iprintf(bot->idx, "el");
+	} else {
+		sockbuf_delete(bot->idx);
+	}
 	return 0;
 }
 
 static int idx_on_read(void *client_data, int idx, char *data, int len)
 {
+	int argc = 0;
+	char *start = data, *p, *srcstr = NULL, *argv[22];
 	bot_t *bot = client_data;
+	botnet_entity_t src;
+
+	if (!len) return 0;
+	if (*data == ':') {
+		srcstr = data + 1;
+		p = strchr(srcstr, ' ');
+		if (!p) return 0;
+		*p = 0;
+		data = p + 1;
+		while (isspace(*data)) ++data;
+	}
 
+	while (*data) {
+		argv[argc++] = data;
+		if (*data == ':') {
+			argv[argc - 1]++;
+			break;
+		}
+		if (argc == 21) break;
+		p = strchr(data, ' ');
+		if (!p) break;
+		*p = 0;
+		data = p + 1;
+		while (isspace(*data)) ++data;
+	}
+
+	if (!argc) return 0;
+
+	len -= argv[argc - 1] - start;
+	argv[argc] = NULL;
+	if (!bot->bot) {
+		if (bot->incoming) return recving_login(bot, srcstr, argv[0], argc, argv + 1, len);
+		else return sending_login(bot, srcstr, argv[0], argc, argv + 1, len);
+	}
+
+	if (srcstr) {
+		botnet_bot_t *srcbot;
+		get_entity(&src, srcstr);
+		if (src.what == ENTITY_BOT) srcbot = src.bot;
+		else srcbot = src.user->bot;
+		if (botnet_check_direction(bot->bot, srcbot)) return 0;
+	} else {
+		set_bot_entity(&src, bot->bot);
+	}
+
+	int min = 0, max = cmd_num - 1, cur = max / 2;
+	while (min <= max) {
+		int ret = strcasecmp(argv[0], cmd_mapping[cur].cmd);
+		if (!ret) {
+			if (cmd_mapping[cur].source && cmd_mapping[cur].source != src.what) return 0;
+			return cmd_mapping[cur].function(bot, &src, argv[0], argc, argv + 1, len);
+		} else if (ret < 0) {
+			max = cur;
+		} else {
+			if (min == cur) ++min;
+			else min = cur;
+		}
+		cur = (min + max) / 2;
+	}
+	putlog(LOG_MISC, "*",  _("Botnet: Got unknown something from %s: %s"), bot->user->handle, argv[0]);
 	return 0;
 }
 
@@ -250,12 +523,24 @@
 	if (bot->bot) botnet_delete(bot->bot, _("Socket deleted."));
 	else if (!bot->incoming && bot->user && bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, "Socket deleted.");
 
-	if (bot->password) free(bot->password);
+	if (bot->pass) free(bot->pass);
 	free(bot);
 
 	return 0;
 }
 
+/*!
+ * \brief on_delete callback for ::botnet_bot_t.
+ *
+ * Gets called every time a directly linked bot created by this module is
+ * deleted. Marks it as deleted in the ::bot_t struct and deletes the
+ * ::sockbuf_t.
+ *
+ * \param owner The ::event_owner_t struct belonging to this bot. It's bot_owner.
+ * \param client_data Our callback data. The ::bot_t struct of the deleted bot.
+ * \return Always 0.
+ */
+
 static int bot_on_delete(event_owner_t *owner, void *client_data)
 {
 	bot_t *bot = client_data;
@@ -279,6 +564,8 @@
 
 	listen_idx = egg_server(botnet_config.ip, botnet_config.port, &real_port);
 	sockbuf_set_handler(listen_idx, &server_handler, NULL);
+
+	bind_add_simple(BTN_BOTNET_REQUEST_LINK, NULL, "eggdrop", do_link);
 }
 
 static int bot_close(int why)
@@ -290,6 +577,8 @@
 
 	sockbuf_delete(listen_idx);
 
+	bind_rem_simple(BTN_BOTNET_REQUEST_LINK, NULL, "eggdrop", do_link); 
+
 	return 0;
 }
 
Index: eggdrop1.9/modules/botnet/botnet.h
diff -u eggdrop1.9/modules/botnet/botnet.h:1.1 eggdrop1.9/modules/botnet/botnet.h:1.2
--- eggdrop1.9/modules/botnet/botnet.h:1.1	Sun Jun  3 18:43:45 2007
+++ eggdrop1.9/modules/botnet/botnet.h	Sat Aug 18 17:32:24 2007
@@ -16,26 +16,30 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * $Id: botnet.h,v 1.1 2007-06-03 23:43:45 sven Exp $
+ * $Id: botnet.h,v 1.2 2007-08-18 22:32:24 sven Exp $
  */
 
-#ifndef _EGG_MOD_OLDBOTNET_OLDBOTNET_H_
-#define _EGG_MOD_OLDBOTNET_OLDBOTNET_H_
+#ifndef _EGG_MOD_BOTNET_BOTNET_H_
+#define _EGG_MOD_BOTNET_BOTNET_H_
 
 #define bothandler   botnet_LTX_bothandler
 
 typedef struct {
+	int dummy;
+} bot_proto_t;
+
+typedef struct {
 	botnet_bot_t *bot;
 	user_t *user;
 	int idx;
-	char *password;
+	bot_proto_t *proto;
+	char *pass;
 	int incoming;
 	int linking;
-	int version;
 	int idle;
 } bot_t;
 
 /* From events.c */
 botnet_handler_t bothandler;
 
-#endif /* !_EGG_MOD_OLDBOTNET_OLDBOTNET_H_ */
+#endif /* !_EGG_MOD_BOTNET_BOTNET_H_ */
Index: eggdrop1.9/modules/botnet/events.c
diff -u eggdrop1.9/modules/botnet/events.c:1.1 eggdrop1.9/modules/botnet/events.c:1.2
--- eggdrop1.9/modules/botnet/events.c:1.1	Sun Jun  3 18:43:46 2007
+++ eggdrop1.9/modules/botnet/events.c	Sat Aug 18 17:32:24 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: events.c,v 1.1 2007-06-03 23:43:46 sven Exp $";
+static const char rcsid[] = "$Id: events.c,v 1.2 2007-08-18 22:32:24 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -26,6 +26,7 @@
 #include "botnet.h"
 
 /* botnet callbacks */
+static int on_login(void *client_data, partymember_t *src, int linking);
 static int on_bcast(void *client_data, botnet_entity_t *src, const char *text, int len);
 static int on_privmsg(void *client_data, botnet_entity_t *src, partymember_t *dst, const char *text, int len);
 static int on_nick(void *client_data, partymember_t *src, const char *oldnick);
@@ -42,11 +43,21 @@
 static int on_extension(void *client_data, botnet_entity_t *src, botnet_bot_t *dst, const char *cmd, const char *text, int len);
 
 botnet_handler_t bothandler = {
-	on_bcast, on_privmsg, on_nick, on_quit,
+	on_login, on_bcast, on_privmsg, on_nick, on_quit,
 	on_chanmsg, on_join, on_part,
 	on_new_bot, on_lost_bot, on_link, on_unlink, on_botmsg, on_botbroadcast, on_extension
 };
 
+static int on_login(void *client_data, partymember_t *src, int linking)
+{
+	bot_t *b = client_data;
+
+	if (src->bot) egg_iprintf(b->idx, ":%s login %s %s %s %s %d", src->bot->name, src->nick, src->ident, src->host, b64enc_int(src->id), linking);
+	else egg_iprintf(b->idx, "login %s %s %s %s %d", src->nick, src->ident, src->host, b64enc_int(src->id), linking);
+
+	return 0;
+}
+
 /*!
  * \brief Send a broadcast event out.
  *
@@ -63,70 +74,164 @@
 
 static int on_bcast(void *client_data, botnet_entity_t *src, const char *text, int len)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s broadcast :%s", entity_net_name(src), text ? text : "");
+
 	return 0;
 }
 
 static int on_privmsg(void *client_data, botnet_entity_t *src, partymember_t *dst, const char *text, int len)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s privmsg %s :%s", entity_net_name(src), dst->net_name, text);
+
 	return 0;
 }
 
 static int on_quit(void *client_data, partymember_t *src, const char *text, int len)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s quit :%s", src->net_name, text ? text : "");
+
 	return 0;
 }
 
 static int on_nick(void *client_data, partymember_t *src, const char *oldnick)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s nick %s", src->net_name, src->nick);
+
 	return 0;
 }
 
 static int on_chanmsg(void *client_data, partychan_t *chan, botnet_entity_t *src, const char *text, int len)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s chanmsg %s :%s", entity_net_name(src), chan->name, text ? text : text);
+
 	return 0;
 }
 
 static int on_join(void *client_data, partychan_t *chan, partymember_t *src, int linking)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s join %s %d", src->net_name, chan->name, linking);
+
 	return 0;
 }
 
 static int on_part(void *client_data, partychan_t *chan, partymember_t *src, const char *reason, int len)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s part %s :%s", src->net_name, chan->name, reason ? reason : "");
+
 	return 0;
 }
 
 static int on_new_bot(void *client_data, botnet_bot_t *bot, int linking)
 {
+	int version = 1090000;
+	const char *ver, *type, *fullversion;
+	bot_t *b = client_data;
+
+	type = botnet_get_info(bot, "type");
+	ver = botnet_get_info(bot, "numversion");
+	fullversion = botnet_get_info(bot, "numversion");
+	if (!type) type = "unknown";
+	if (ver) version = atoi(ver);
+	if (!fullversion) fullversion = "unknown";
+	egg_iprintf(b->idx, ":%s newbot %s %s %s %s %s", bot->uplink ? bot->uplink->name : botnet_get_name(), bot->name, type, b64enc_int(version), fullversion, linking ? "B" : "A");
+
 	return 0;
 }
 
 static int on_lost_bot(void *client_data, botnet_bot_t *bot, const char *reason)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s bquit :%s", bot->name, reason ? reason : reason);
+
 	return 0;
 }
 
 static int on_link(void *client_data, botnet_entity_t *from, struct botnet_bot *dst, const char *target)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s link %s %s", entity_net_name(from), dst->name, target);
+
 	return 0;
 }
 
 static int on_unlink(void *client_data, botnet_entity_t *from, struct botnet_bot *bot, const char *reason)
 {
+	bot_t *b = client_data;
+
+	egg_iprintf(b->idx, ":%s unlink %s :%s", entity_net_name(from), bot->name, reason);
+
 	return 0;
 }
 
 static int on_botbroadcast(void *client_data, botnet_bot_t *src, const char *command, const char *text, int len)
 {
+	int printlen, totallen;
+	char sbuf[512], *obuf;
+	bot_t *b = client_data;
+
+	if (src) totallen = 1 + strlen(src->name) + 12 + strlen(command) + 2 + len;
+	else totallen = 11 + strlen(command) + 2 + len;
+	if (totallen < 512) obuf = sbuf;
+	else obuf = malloc(totallen + 1);
+
+	if (src) printlen = sprintf(obuf, ":%s bbroadcast %s :", src->name, command);
+	else printlen = sprintf(obuf, "bbroadcast %s :", command);
+	memcpy(obuf + printlen, text, len);
+	sockbuf_write(b->idx, obuf, totallen);
+	if (obuf != sbuf) free(obuf);
+
 	return 0;
 }
 
 static int on_botmsg(void *client_data, botnet_bot_t *src, botnet_bot_t *dst, const char *command, const char *text, int len)
 {
+	int printlen, totallen;
+	char sbuf[512], *obuf;
+	bot_t *b = client_data;
+
+	if (src) totallen = 1 + strlen(src->name) + 8 + strlen(dst->name) + 1 + strlen(command) + 2 + len;
+	else totallen = 7 + strlen(dst->name) + 1 + strlen(command) + 2 + len;
+	if (totallen < 512) obuf = sbuf;
+	else obuf = malloc(totallen + 1);
+
+	if (src) printlen = sprintf(obuf, ":%s botmsg %s %s :", src->name, dst->name, command);
+	else printlen = sprintf(obuf, "botmsg %s %s :", dst->name, command);
+	memcpy(obuf + printlen, text, len);
+	sockbuf_write(b->idx, obuf, totallen);
+	if (obuf != sbuf) free(obuf);
+
 	return 0;
 }
 
 static int on_extension(void *client_data, botnet_entity_t *src, botnet_bot_t *dst, const char *cmd, const char *text, int len)
 {
+	char sbuf[512], *obuf;
+	int printlen, totallen = 1 + strlen(entity_net_name(src)) + 11 + strlen(dst->name) + 1 + strlen(cmd) + 2 + len;
+	bot_t *b = client_data;
+
+	if (totallen < 512) obuf = sbuf;
+	else obuf = malloc(totallen + 1);
+
+	printlen = sprintf(obuf, ":%s extension %s %s :", entity_net_name(src), dst->name, cmd);
+	memcpy(obuf + printlen, text, len);
+	sockbuf_write(b->idx, obuf, totallen);
+	if (obuf != sbuf) free(obuf);
+
 	return 0;
 }
Index: eggdrop1.9/modules/dccparty/events.c
diff -u eggdrop1.9/modules/dccparty/events.c:1.9 eggdrop1.9/modules/dccparty/events.c:1.10
--- eggdrop1.9/modules/dccparty/events.c:1.9	Sat Apr 14 10:21:12 2007
+++ eggdrop1.9/modules/dccparty/events.c	Sat Aug 18 17:32:24 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: events.c,v 1.9 2007-04-14 15:21:12 sven Exp $";
+static const char rcsid[] = "$Id: events.c,v 1.10 2007-08-18 22:32:24 sven Exp $";
 #endif
 
 #include <string.h>
@@ -49,9 +49,9 @@
 
 	if (src) {
 		if (len >= 9 && !strncasecmp(text, "\1ACTION ", 8) && text[len - 1] == 1) {
-			egg_iprintf(session->idx, "%s %.*s\r\n", src->common_name, len - 9, text + 8);
+			egg_iprintf(session->idx, "%s %.*s\r\n", entity_common_name(src), len - 9, text + 8);
 		} else {
-			egg_iprintf(session->idx, "[%s] %s\r\n", src->common_name, text);
+			egg_iprintf(session->idx, "[%s] %s\r\n", entity_common_name(src), text);
 		}
 	} else {
 		egg_iprintf(session->idx, "%s\r\n", text);
@@ -84,9 +84,9 @@
 
 	if (src) {
 		if (len >= 9 && !strncasecmp(text, "\1ACTION ", 8) && text[len - 1] == 1) {
-			egg_iprintf(session->idx, "%s %s %.*s\r\n", chan->name, src->common_name, len - 9, text + 8);
+			egg_iprintf(session->idx, "%s %s %.*s\r\n", chan->name, entity_common_name(src), len - 9, text + 8);
 		} else {
-			egg_iprintf(session->idx, "%s <%s> %s\r\n", chan->name, src->common_name, text);
+			egg_iprintf(session->idx, "%s <%s> %s\r\n", chan->name, entity_common_name(src), text);
 		}
 	} else {
 		egg_iprintf(session->idx, "%s %s\r\n", chan->name, text);
Index: eggdrop1.9/modules/oldbotnet/events.c
diff -u eggdrop1.9/modules/oldbotnet/events.c:1.12 eggdrop1.9/modules/oldbotnet/events.c:1.13
--- eggdrop1.9/modules/oldbotnet/events.c:1.12	Tue May  8 20:32:31 2007
+++ eggdrop1.9/modules/oldbotnet/events.c	Sat Aug 18 17:32:24 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: events.c,v 1.12 2007-05-09 01:32:31 sven Exp $";
+static const char rcsid[] = "$Id: events.c,v 1.13 2007-08-18 22:32:24 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -42,47 +42,22 @@
 static int on_extension(void *client_data, botnet_entity_t *src, botnet_bot_t *dst, const char *cmd, const char *text, int len);
 
 botnet_handler_t bothandler = {
-	on_bcast, on_privmsg, on_nick, on_quit,
+	NULL, on_bcast, on_privmsg, on_nick, on_quit,
 	on_chanmsg, on_join, on_part,
 	on_new_bot, on_lost_bot, on_link, on_unlink, on_botmsg, on_botbroadcast, on_extension
 };
 
-static int tobase64[] = {
-	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-	'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '[', ']'
-};
-
-/*!
- * \brief Calculate the base64 value of an int.
- *
- * Uses the eggdrop1.6 style base64 algotithm to convert an int to a
- * base64 string.
- *
- * \param i The number to convert.
- *
- * \return A string containing the base64 value of \e i.
- *
- * \warning This function returns a pointer to a static buffer. Calling it
- *          again will overwrite it. \b Always \b remember!
- */
-
-static const char *itob(int i)
+static const char *filter(const char *text)
 {
-	char *pos;
-	static char ret[12];
-
-	pos = ret + 11;
-	*pos = 0;
+	char *p;
+	static char buf[512] = {0};
 
-	do {
-		--pos;
-		*pos = tobase64[i & 0x3F];
-		i >>= 6;
-	} while (i);
+	if (!strchr(text, '\n')) return text;
 
-	return pos;
+	strncpy(buf, text, 511);
+	p = strchr(buf, '\n');
+	if (p) *p = 0;
+	return buf;
 }
 
 /*!
@@ -104,11 +79,11 @@
 	const char *name;
 	oldbotnet_t *obot = client_data;
 
-	if (src->what == ENTITY_BOT) name = src->full_name;
+	if (src->what == ENTITY_BOT) name = entity_full_name(src);
 	else if (src->user->bot) name = src->user->bot->name;
 	else name = botnet_get_name();
 
-	egg_iprintf(obot->idx, "ct %s %s\n", name, text);
+	egg_iprintf(obot->idx, "ct %s %s\n", name, filter(text));
 
 	return 0;
 }
@@ -117,7 +92,7 @@
 {
 	oldbotnet_t *obot = client_data;
 
-	egg_iprintf(obot->idx, "p %s %s %s\n", src->full_id_name, dst->full_id_name, text);
+	egg_iprintf(obot->idx, "p %s %s %s\n", entity_full_id_name(src), dst->full_id_name, filter(text));
 
 	return 0;
 }
@@ -126,7 +101,7 @@
 {
 	oldbotnet_t *obot = client_data;
 
-	egg_iprintf(obot->idx, "pt %s %s %s\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, itob(src->id));
+	egg_iprintf(obot->idx, "pt %s %s %s\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, b64enc_int(src->id));
 
 	return 0;
 }
@@ -135,19 +110,20 @@
 {
 	oldbotnet_t *obot = client_data;
 
-	egg_iprintf(obot->idx, "nc %s %s %s\n", src->bot ? src->bot->name : botnet_get_name(), itob(src->id), src->nick);
+	egg_iprintf(obot->idx, "nc %s %s %s\n", src->bot ? src->bot->name : botnet_get_name(), b64enc_int(src->id), src->nick);
 
 	return 0;
 }
 
-static int on_chanmsg(void *client_data, partychan_t *chan, botnet_entity_t *src, const char *text, int len)
+static int on_chanmsg(void *client_data, partychan_t *chan, botnet_entity_t *src, const char *t, int len)
 {
+	const char *text = filter(t);
 	oldbotnet_t *obot = client_data;
 
 	if (len >= 9 && !strncasecmp(text, "\1ACTION ", 8) && text[len - 1] == 1) {
-		egg_iprintf(obot->idx, "a %s %s %.*s\n", src->full_name, itob(assoc_get_id(chan->name)), len - 9, text + 8);
+		egg_iprintf(obot->idx, "a %s %s %.*s\n", entity_full_name(src), b64enc_int(assoc_get_id(chan->name)), len - 9, text + 8);
 	} else {
-		egg_iprintf(obot->idx, "c %s %s %s\n", src->full_name, itob(assoc_get_id(chan->name)), text);
+		egg_iprintf(obot->idx, "c %s %s %s\n", entity_full_name(src), b64enc_int(assoc_get_id(chan->name)), text);
 	}
 	return 0;
 }
@@ -157,8 +133,8 @@
 	char *cid;
 	oldbotnet_t *obot = client_data;
 
-	cid = strdup(itob(assoc_get_id(chan->name)));
-	egg_iprintf(obot->idx, "j %s%s %s %s %c%s %s@%s\n", linking ? "!" : "", src->bot ? src->bot->name : botnet_get_name(), src->nick, cid, '*', itob(src->id), src->ident, src->host);
+	cid = strdup(b64enc_int(assoc_get_id(chan->name)));
+	egg_iprintf(obot->idx, "j %s%s %s %s %c%s %s@%s\n", linking ? "!" : "", src->bot ? src->bot->name : botnet_get_name(), src->nick, cid, '*', b64enc_int(src->id), src->ident, src->host);
 	free(cid);
 
 	return 0;
@@ -169,13 +145,13 @@
 	oldbotnet_t *obot = client_data;
 
 	if (!src->nchannels) {
-		if (reason && *reason) egg_iprintf(obot->idx, "pt %s %s %s %s\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, itob(src->id), reason);
-		else egg_iprintf(obot->idx, "pt %s %s %d\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, itob(src->id));
+		if (reason && *reason) egg_iprintf(obot->idx, "pt %s %s %s %s\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, b64enc_int(src->id), filter(reason));
+		else egg_iprintf(obot->idx, "pt %s %s %s\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, b64enc_int(src->id));
 	} else {
 		char *cid;
 
-		cid = strdup(itob(assoc_get_id(src->channels[src->nchannels - 1]->name)));
-		egg_iprintf(obot->idx, "j %s %s %s %c%s %s@%s\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, cid, '*', itob(src->id), src->ident, src->host);
+		cid = strdup(b64enc_int(assoc_get_id(src->channels[src->nchannels - 1]->name)));
+		egg_iprintf(obot->idx, "j %s %s %s %c%s %s@%s\n", src->bot ? src->bot->name : botnet_get_name(), src->nick, cid, '*', b64enc_int(src->id), src->ident, src->host);
 		free(cid);
 	}
 
@@ -184,9 +160,13 @@
 
 static int on_new_bot(void *client_data, botnet_bot_t *bot, int linking)
 {
+	int version = 1090000;
+	const char *verstr;
 	oldbotnet_t *obot = client_data;
 
-	egg_iprintf(obot->idx, "n %s %s %cEDNI\n", bot->name, bot->uplink ? bot->uplink->name : botnet_get_name(), linking ? '-' : '!');
+	verstr = botnet_get_info(bot, "numversion");
+	if (verstr) version = atoi(verstr);
+	egg_iprintf(obot->idx, "n %s %s %c%s\n", bot->name, bot->uplink ? bot->uplink->name : botnet_get_name(), linking ? '-' : '!', b64enc_int(version));
 
 	return 0;
 }
@@ -195,8 +175,8 @@
 {
 	oldbotnet_t *obot = client_data;
 
-	if (bot == obot->bot) egg_iprintf(obot->idx, "bye %s\n", reason);
-	else egg_iprintf(obot->idx, "un %s %s\n", bot->name, reason);
+	if (bot == obot->bot) egg_iprintf(obot->idx, "bye %s\n", filter(reason));
+	else egg_iprintf(obot->idx, "un %s %s\n", bot->name, filter(reason));
 
 	return 0;
 }
@@ -205,7 +185,7 @@
 {
 	oldbotnet_t *obot = client_data;
 
-	egg_iprintf(obot->idx, "l %s %s %s\n", from->full_id_name, dst->name, target);
+	egg_iprintf(obot->idx, "l %s %s %s\n", entity_full_id_name(from), dst->name, target);
 
 	return 0;
 }
@@ -214,7 +194,7 @@
 {
 	oldbotnet_t *obot = client_data;
 
-	egg_iprintf(obot->idx, "ul %s %s %s %s\n", from->full_id_name, bot->uplink->name, bot->name, reason);
+	egg_iprintf(obot->idx, "ul %s %s %s %s\n", entity_full_id_name(from), bot->uplink->name, bot->name, filter(reason));
 
 	return 0;
 }
@@ -224,7 +204,7 @@
 	const char *srcname = src ? src->name : botnet_get_name();
 	oldbotnet_t *obot = client_data;
 
-	if (text && len > 0) egg_iprintf(obot->idx, "z %s %s %s\n", srcname, command, text);
+	if (text && len > 0) egg_iprintf(obot->idx, "z %s %s %s\n", srcname, command, filter(text));
 	else egg_iprintf(obot->idx, "z %s %s\n", srcname, command);
 
 	return 0;
@@ -235,27 +215,28 @@
 	const char *srcname = src ? src->name : botnet_get_name();
 	oldbotnet_t *obot = client_data;
 
-	if (text && len > 0) egg_iprintf(obot->idx, "zb %s %s %s %s\n", srcname, dst->name, command, text);
+	if (text && len > 0) egg_iprintf(obot->idx, "zb %s %s %s %s\n", srcname, dst->name, command, filter(text));
 	else egg_iprintf(obot->idx, "zb %s %s %s\n", srcname, dst->name, command);
 
 	return 0;
 }
 
-static int on_extension(void *client_data, botnet_entity_t *src, botnet_bot_t *dst, const char *cmd, const char *text, int len)
+static int on_extension(void *client_data, botnet_entity_t *src, botnet_bot_t *dst, const char *cmd, const char *t, int len)
 {
+	const char *text = filter(t);
 	oldbotnet_t *obot = client_data;
 
 	if (!strcmp(cmd, "note")) {
-		egg_iprintf(obot->idx, "p %s %s\n", src->full_id_name, text);
+		egg_iprintf(obot->idx, "p %s %s\n", entity_full_id_name(src), text);
 	} else if (!strcmp(cmd, "who")) {
-		egg_iprintf(obot->idx, "w %s %s %s\n", src->full_id_name, dst->name, text);
+		egg_iprintf(obot->idx, "w %s %s %s\n", entity_full_id_name(src), dst->name, text);
 	} else if (!strcmp(cmd, "motd")) {
-		egg_iprintf(obot->idx, "m %s %s\n", src->full_id_name, dst->name);
-	} else if (!strcmp(cmd, "versions")) {
+		egg_iprintf(obot->idx, "m %s %s\n", entity_full_id_name(src), dst->name);
+	} else if (!strcmp(cmd, "versions") && src->what == ENTITY_PARTYMEMBER) {
 		egg_iprintf(obot->idx, "v %s %s %d:%s\n", src->user->bot->name, dst->name, src->user->id, src->user->nick);
-	} else if (!strcmp(cmd, "away")) {
-		if (*text) egg_iprintf(obot->idx, "aw %s %s %s\n", src->user->bot ? src->user->bot->name : botnet_get_name(), itob(src->user->id), text);
-		else egg_iprintf(obot->idx, "aw %s %s\n", src->user->bot ? src->user->bot->name : botnet_get_name(), itob(src->user->id));
+	} else if (!strcmp(cmd, "away") && src->what == ENTITY_PARTYMEMBER) {
+		if (*text) egg_iprintf(obot->idx, "aw %s %s %s\n", src->user->bot ? src->user->bot->name : botnet_get_name(), b64enc_int(src->user->id), text);
+		else egg_iprintf(obot->idx, "aw %s %s\n", src->user->bot ? src->user->bot->name : botnet_get_name(), b64enc_int(src->user->id));
 	} else if (!strcmp(cmd, "ping")) {
 		if (obot->idle == -1) {
 			botnet_delete(obot->bot, _("Ping timeout"));
Index: eggdrop1.9/modules/oldbotnet/oldbotnet.c
diff -u eggdrop1.9/modules/oldbotnet/oldbotnet.c:1.21 eggdrop1.9/modules/oldbotnet/oldbotnet.c:1.22
--- eggdrop1.9/modules/oldbotnet/oldbotnet.c:1.21	Fri May 11 21:04:24 2007
+++ eggdrop1.9/modules/oldbotnet/oldbotnet.c	Sat Aug 18 17:32:24 2007
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static const char rcsid[] = "$Id: oldbotnet.c,v 1.21 2007-05-12 02:04:24 sven Exp $";
+static const char rcsid[] = "$Id: oldbotnet.c,v 1.22 2007-08-18 22:32:24 sven Exp $";
 #endif
 
 #include <eggdrop/eggdrop.h>
@@ -244,38 +244,6 @@
 	return a->id;
 }
 
-static char base64to[256] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-
-	0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
-	
-	0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-	
-	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62, 0, 63, 0, 0, 0, 26, 27, 28,
-	
-	29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	
-	49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-	
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static int btoi(const char *b)
-{
-	int i = 0;
-
-	while (*b) i = (i << 6) + base64to[(unsigned char) *b++];
-	return(i);
-}
-
 static int get_entity(botnet_bot_t *bot, botnet_entity_t *src, char *word)
 {
 	oldbotnet_t *obot = bot->client_data;
@@ -434,15 +402,13 @@
 	if (next && *next == '<') {
 		MD5_CTX md5;
 		unsigned char hash[16];
-		char hex[64];
-		int i;
+		char hex[33];
 
 		MD5_Init(&md5);
 		MD5_Update(&md5, next, strlen(next));
 		MD5_Update(&md5, bot->password, strlen(bot->password));
 		MD5_Final(hash, &md5);
-		for (i = 0; i < 16; i++) sprintf(hex+2*i, "%.2x", (unsigned char) hash[i]);
-		hex[33] = 0;
+		MD5_Hex(hash, hex);
 		putlog(LOG_MISC, "*", _("Received challenge from %s... sending response ..."), bot->user->handle);
 		egg_iprintf(bot->idx, "digest %s\n", hex);
 	} else {
@@ -488,6 +454,7 @@
 
 static void got_version(oldbotnet_t *bot, const char *next)
 {
+	char buf[32];
 	/* Get their version and handlen. */
 	sscanf(next, "%d %d", &bot->version, &bot->handlen);
 
@@ -504,6 +471,11 @@
 		sockbuf_delete(bot->idx);
 		return;
 	}
+	if (bot->version % 100) sprintf(buf, "eggdrop%d.%d.%d.%d", bot->version / 1000000, bot->version / 10000 % 100, bot->version / 100 % 100, bot->version % 100);
+	else sprintf(buf, "eggdrop%d.%d.%d", bot->version / 1000000, bot->version / 10000 % 100, bot->version / 100 % 100);
+	botnet_set_info(bot->bot, "type", "eggdrop");
+	botnet_set_info_int(bot->bot, "numversion", bot->version);
+	botnet_set_info(bot->bot, "version", buf);
 	botnet_replay_net(bot->bot);
 	egg_iprintf(bot->idx, "el\n");
 }
@@ -529,7 +501,7 @@
 
 	while (isspace(*next)) next++;
 	action = egg_msprintf(buf, sizeof(buf), &len, "\1ACTION %s\1", next);
-	partychan_msg_name(assoc_get_name(btoi(word[1])), &src, action, len);  
+	partychan_msg_name(assoc_get_name(b64dec_int(word[1])), &src, action, len);  
 	if (action != buf) free(action);
 
 	egg_free_word_array(word, 2);
@@ -680,7 +652,7 @@
 		return BIND_RET_BREAK;
 	}
 
-	id = btoi(word[1]);
+	id = b64dec_int(word[1]);
 	src = partymember_lookup(NULL, srcbot, id);
 	if (!src) {
 		egg_free_word_array(word, 3);
@@ -692,10 +664,25 @@
 	return BIND_RET_BREAK;
 }
 
+/*!
+ * \brief A new bot has linked to the botnet somewhere else.
+ *
+ * Triggered every time a new bot joins the net to introduce that bot and all
+ * the bots behind it. There might be an '!' as the first char of the version
+ * string. If that isn't there, don't announce the new bot on the partyline,
+ * it's probably from a net join. Might get spammy otherwise.
+ *
+ * \param bot The bot the msg came from.
+ * \param cmd "nlinked" or "n".
+ * \param next The parameters.
+ *
+ * \format \b nlinked newbot uplink [!]version
+ */
+
 static int got_nlinked(botnet_bot_t *bot, const char *cmd, const char *next)
 {
-	char *word[3];
-	int n, linking = 1;
+	char *word[3], buf[32];
+	int n, linking = 1, version;
 	botnet_bot_t *src, *new;
 	oldbotnet_t *obot = bot->client_data;
 
@@ -719,7 +706,12 @@
 		return BIND_RET_BREAK;
 	}
 
-	if (word[2][0] == '!') linking = 0;
+	if (word[2][0] == '!') {
+		linking = 0;
+		version = b64dec_int(word[2] + 1);
+	} else {
+		version = b64dec_int(word[2]);
+	}
 	new = botnet_new(word[0], NULL, src, bot, NULL, NULL, &generic_owner, linking);
 	if (!new) {
 		/* Invalid botname ... should probably do some really clever name mangleing here ... */
@@ -728,6 +720,11 @@
 		botnet_delete(bot, obuf);
 		/* or just be lazy and kill the bot -_- */
 	}
+	if (version % 100) sprintf(buf, "eggdrop%d.%d.%d.%d", version / 1000000, version / 10000 % 100, version / 100 % 100, version % 100);
+	else sprintf(buf, "eggdrop%d.%d.%d", version / 1000000, version / 10000 % 100, version / 100 % 100);
+	botnet_set_info(new, "type", "eggdrop");
+	botnet_set_info_int(new, "numversion", version);
+	botnet_set_info(new, "version", buf);
 	return BIND_RET_BREAK;
 }
 
@@ -828,7 +825,7 @@
 		return BIND_RET_BREAK;
 	}
 
-	p = partymember_lookup(NULL, src, btoi(word[1]));
+	p = partymember_lookup(NULL, src, b64dec_int(word[1]));
 	if (!p) {
 		egg_free_word_array(word, 2);
 		return BIND_RET_BREAK;
@@ -892,7 +889,7 @@
 		return BIND_RET_BREAK;
 	}
 
-	id = btoi(word[3] + 1);
+	id = b64dec_int(word[3] + 1);
 
 	p = partymember_lookup(NULL, frombot, id);
 	if (p) {
@@ -923,7 +920,7 @@
 
 		p = partymember_new(id, NULL, frombot, word[1], ident, host, NULL, NULL, &generic_owner);
 	}
-	partychan_join_name(assoc_get_name(btoi(word[2])), p, linking);
+	partychan_join_name(assoc_get_name(b64dec_int(word[2])), p, linking);
 	egg_free_word_array(word, 5);
 	return BIND_RET_BREAK;
 }
@@ -946,7 +943,7 @@
 	else reason = "No reason.";
 
 	src = botnet_lookup(word[0]);
-	id = btoi(word[2]);
+	id = b64dec_int(word[2]);
 	if (botnet_check_direction(bot, src)) {
 		egg_free_word_array(word, 3);
 		return BIND_RET_BREAK;
@@ -1043,7 +1040,7 @@
 	}
 
 	while (isspace(*next)) next++;
-	partychan_msg_name(assoc_get_name(btoi(word[1])), &src, next, strlen(next));
+	partychan_msg_name(assoc_get_name(b64dec_int(word[1])), &src, next, strlen(next));
 
 	egg_free_word_array(word, 2);
 	return BIND_RET_BREAK;
@@ -1292,7 +1289,7 @@
 
 	bot->idx = -1;
 	if (bot->bot) botnet_delete(bot->bot, _("Socket deleted."));
-	else if (bot->user && bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, "Socket deleted.");
+	else if (bot->user && bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, _("Socket deleted."));
 
 	if (bot->name) free(bot->name);
 	if (bot->password) free(bot->password);
----------------------- End of diff -----------------------



More information about the Changes mailing list