From 98d4daa7d6cf62fe4d82b513a788ed3f7cc0da67 Mon Sep 17 00:00:00 2001 From: pk910 Date: Sun, 11 Sep 2011 00:50:00 +0200 Subject: [PATCH] started writing cmd_chanservsync --- bot_NeonServ.c | 5 ++ cmd_neonserv_chanservsync.c | 160 ++++++++++++++++++++++++++++++++++++ cmd_neonserv_topic.c | 2 + tools.c | 5 ++ 4 files changed, 172 insertions(+) create mode 100644 cmd_neonserv_chanservsync.c diff --git a/bot_NeonServ.c b/bot_NeonServ.c index 6092e17..16422f7 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -151,6 +151,9 @@ static const struct default_language_entry msgtab[] = { {"NS_EXTTOPIC_INVALID_ID", "ADVANCEDTOPIC is enabled and \002%s\002 is an invalid TOPIC ID. Valid topic id's are: 1-9"}, {"NS_EXTTOPIC_TOPICID", "Topic %d: %s"}, {"NS_TOPIC_DONE", "Topic is now '%s'."}, + {"NS_CHANSERVSYNC_UNSUPPORTED", "\0034WARNING\003: the user list style of %s is not known. %s can try to synchronize the userlist, but there is no guarantee that it is successful!"}, + {"NS_CHANSERVSYNC_KEY", "If you really want to synchronize the %s userlist with %s use: chanservsync %s %s"}, + {"NS_CHANSERVSYNC_INUSE", "\002chanservsync\002 is already in use by someone else. Please try again in a few seconds..."}, {NULL, NULL} }; @@ -206,6 +209,7 @@ INCLUDE ALL CMD's HERE //#include "cmd_neonserv_resync.c" //#include "cmd_neonserv_help.c" //#include "cmd_neonserv_version.c" +#include "cmd_neonserv_chanservsync.c" //OPER CMD's //#include "cmd_neonserv_bind.c" @@ -334,6 +338,7 @@ void init_NeonServ() { register_command(BOTID, "delban", neonserv_cmd_delban, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_staticban", 0); register_command(BOTID, "netinfo", neonserv_cmd_netinfo, 0, 0, NULL, 0); register_command(BOTID, "topic", neonserv_cmd_topic, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_changetopic", 0); + register_command(BOTID, "chanservsync", neonserv_cmd_chanservsync, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "500", 0); register_command(BOTID, "trace", neonserv_cmd_trace, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, NULL, 400); diff --git a/cmd_neonserv_chanservsync.c b/cmd_neonserv_chanservsync.c new file mode 100644 index 0000000..d95f95f --- /dev/null +++ b/cmd_neonserv_chanservsync.c @@ -0,0 +1,160 @@ + +/* +* argv[0] - botnick +* argv[1] - key +*/ +#define CHANSERVSYNC_END_TIMEOUT 5 + +static void neonserv_cmd_chanservsync_notice_listener(struct UserNode *user, struct UserNode *target, char *message); +static void neonserv_cmd_chanservsync_free_cache(); + +struct neonserv_cmd_chanservsync_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + char *botnick; + time_t last_response; +}; + +struct neonserv_cmd_chanservsync_cache *neonserv_cmd_chanservsync_used = NULL; +const char* neonserv_cmd_chanservsync_supported[] = {"ChanServ", NULL}; + +static CMD_BIND(neonserv_cmd_chanservsync) { + if(neonserv_cmd_chanservsync_used && time(0) - neonserv_cmd_chanservsync_used->last_response < CHANSERVSYNC_END_TIMEOUT) { + reply(getTextBot(), user, "NS_CHANSERVSYNC_INUSE"); + return; + } + if(neonserv_cmd_chanservsync_used) { + neonserv_cmd_chanservsync_free_cache(); + } + char *botnick = "ChanServ"; + char *key = ""; + if(argc) { + if(argv[0][0] == '!') { + key = argv[0]; + } else { + botnick = argv[0]; + if(argc > 1) + key = argv[1]; + } + } + int seed = 0; + char *tmp; + char synckey[18]; + for(tmp = user->auth; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = chan->name; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = botnick; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + sprintf(synckey, "!%08x!", seed); + if(strcmp(synckey, key)) { + int f = 0; + const char **supp = neonserv_cmd_chanservsync_supported; + while(*supp) { + if(!stricmp(*supp, botnick)) { + f = 1; + break; + } + supp++; + } + if(!f) { + reply(getTextBot(), user, "NS_CHANSERVSYNC_UNSUPPORTED", botnick, client->user->nick); + } + reply(getTextBot(), user, "NS_CHANSERVSYNC_KEY", client->user->nick, botnick, botnick, synckey); + return; + } + struct neonserv_cmd_chanservsync_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->botnick = strdup(botnick); + cache->last_response = time(0); + neonserv_cmd_chanservsync_used = cache; + putsock(client, "PRIVMSG %s :users %s", botnick, chan->name); + bind_privnotice(neonserv_cmd_chanservsync_notice_listener); +} + +static void neonserv_cmd_chanservsync_notice_listener(struct UserNode *user, struct UserNode *target, char *message) { + if(neonserv_cmd_chanservsync_used && neonserv_cmd_chanservsync_used->client->user == target && !stricmp(user->nick, neonserv_cmd_chanservsync_used->botnick)) { + //we've got a notice from our bot... + //let's try parsing it.... + char *p = message; + char *tokens[MAXLEN]; + int tokensPos = 0; + while(*p == ' ') //skip leading spaces (airb0t) + p++; + message = p; + char *q = p; + while(*q) { + if(*q < 32) *q = ' '; + q++; + } + while((q = strstr(p, " "))) { + *q = '\0'; + do { + q++; + } while(*q == ' '); + if(*p) { + tokens[tokensPos++] = p; + } + p = q; + } + if(*p) { + tokens[tokensPos++] = p; + } + if(tokensPos < 2) return; + int caccess = atoi(tokens[0]); + if(caccess < 1 || caccess > 500) return; + char *username = tokens[1]; + int flags = 0; + time_t now = time(0); + time_t seen_time = now; //now - now = 0 (never) + neonserv_cmd_chanservsync_used->last_response = now; + if(strlen(username) < 3) return; + //ok we have access and username... maybe there is something else we can parse??? + char *seen = NULL; + char *status = NULL; + if(tokensPos > 2) { + if(!stricmp("normal", tokens[2]) || !stricmp("suspended", tokens[2]) || !stricmp("bot", tokens[2])) { + status = tokens[2]; + if (tokensPos > 3) { + seen = merge_argv(tokens, 3, tokensPos); + } + } else if (tokensPos > 3) { + if(!stricmp("normal", tokens[tokensPos-1]) || !stricmp("suspended", tokens[tokensPos-1]) || !stricmp("bot", tokens[tokensPos-1])) { + status = tokens[tokensPos-1]; + seen = merge_argv(tokens, 2, tokensPos-1); + } else { + seen = merge_argv(tokens, 2, tokensPos); + } + } else { + seen = merge_argv(tokens, 2, tokensPos); + } + } + if(status && !stricmp(status, "suspended")) { + flags |= DB_CHANUSER_SUSPENDED; + } + if(seen) { + if(!stricmp(seen, "here")) + seen_time = 0; + else if(stricmp(seen, "never")) + seen_time = strToTime(user, seen); + } + seen_time = now - seen_time; + reply(neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, "\002PARSED LINE!\002 Access: %d User: %s Seen: %lu State: %d", caccess, username, (unsigned long) seen_time, flags); + } +} + +static void neonserv_cmd_chanservsync_free_cache() { + free(neonserv_cmd_chanservsync_used->botnick); + free(neonserv_cmd_chanservsync_used); + unbind_privnotice(neonserv_cmd_chanservsync_notice_listener); + neonserv_cmd_chanservsync_used = NULL; +} + diff --git a/cmd_neonserv_topic.c b/cmd_neonserv_topic.c index c530de4..ab214b0 100644 --- a/cmd_neonserv_topic.c +++ b/cmd_neonserv_topic.c @@ -73,6 +73,8 @@ static CMD_BIND(neonserv_cmd_topic) { return; } newtopic = merge_argv(argv, 1, argc); + if(!strcmp(newtopic, "*")) + newtopic = ""; advtopics[topic_id-1] = newtopic; char topiclist[MAXLEN*2]; topiclist[0] = '\0'; diff --git a/tools.c b/tools.c index 1fc4be9..fb74d5b 100644 --- a/tools.c +++ b/tools.c @@ -279,12 +279,17 @@ int strToTime(struct UserNode *user, char *str) { int unit_multiplikator; while(*str) { p = str; + while(*p && !isdigit(*p)) //skip leading chars + p++; + str = p; while(*p && isdigit(*p)) //get the value p++; tmpchar = *p; *p = '\0'; cvalue = isdigit(*str) ? atoi(str) : 0; *p = tmpchar; + while(*p == ' ') //skip spaces + p++; str = p; while(*p && !isdigit(*p)) //get the unit p++; -- 2.20.1