+++ /dev/null
-/* cmd_neonserv_chanservsync.c - NeonServ v5.3
- * Copyright (C) 2011-2012 Philipp Kreil (pk910)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "cmd_neonserv.h"
-
-/*
-* 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();
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_chanservsync_auth_lookup);
-static void neonserv_cmd_chanservsync_synchronize_user(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *username, int userid, int caccess, time_t seen, int flags, int new);
-
-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_auth_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- int caccess;
- time_t seen;
- int flags;
-};
-
-struct neonserv_cmd_chanservsync_cache *neonserv_cmd_chanservsync_used = NULL;
-const char* neonserv_cmd_chanservsync_supported[] = {"ChanServ", NULL};
-
-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);
- reply(getTextBot(), user, "NS_CHANSERVSYNC_SYNCHRONIZING", chan->name, botnick);
- logEvent(event);
-}
-
-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 == ' ' || *q == '-');
- if(*p) {
- tokens[tokensPos++] = p;
- }
- p = q;
- }
- if(*p) {
- tokens[tokensPos++] = p;
- }
- int caccess;
- char *username;
- if(tokensPos == 1) {
- //maybe a chip-like userlist
- if(tokens[0][0] == '@') {
- caccess = 200;
- username = &tokens[0][1];
- } else if(tokens[0][0] == '+') {
- caccess = 100;
- username = &tokens[0][1];
- } else
- return;
- } else if(tokensPos >= 2) {
- if(atoi(tokens[0]) > 0) {
- caccess = atoi(tokens[0]);
- username = tokens[1];
- } else {
- caccess = atoi(tokens[1]);
- username = tokens[0];
- }
- } else
- return;
- if(caccess < 1 || caccess > 500) return;
- 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;
- //we've collected all information now. synchronize the user (use the higher access if the user is already added)
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(username));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- neonserv_cmd_chanservsync_synchronize_user(neonserv_cmd_chanservsync_used->client, neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, neonserv_cmd_chanservsync_used->chan, username, userid, caccess, seen_time, flags, 0);
- } else if(!stricmp(user->nick, "chanserv")) {
- printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(username));
- userid = (int) mysql_insert_id(get_mysql_conn());
- neonserv_cmd_chanservsync_synchronize_user(neonserv_cmd_chanservsync_used->client, neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, neonserv_cmd_chanservsync_used->chan, username, userid, caccess, seen_time, flags, 1);
- } else {
- //lookup auth
- struct neonserv_cmd_chanservsync_auth_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = neonserv_cmd_chanservsync_used->client;
- cache->textclient = neonserv_cmd_chanservsync_used->textclient;
- cache->user = neonserv_cmd_chanservsync_used->user;
- cache->chan = neonserv_cmd_chanservsync_used->chan;
- cache->caccess = caccess;
- cache->seen = seen_time;
- cache->flags = flags;
- lookup_authname(username, neonserv_cmd_chanservsync_auth_lookup, cache);
- }
- }
-}
-
-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;
-}
-
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_chanservsync_auth_lookup) {
- struct neonserv_cmd_chanservsync_auth_cache *cache = data;
- if(exists) {
- printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth));
- int userid = (int) mysql_insert_id(get_mysql_conn());
- neonserv_cmd_chanservsync_synchronize_user(cache->client, cache->textclient, cache->user, cache->chan, auth, userid, cache->caccess, cache->seen, cache->flags, 1);
- }
- free(cache);
-}
-
-static void neonserv_cmd_chanservsync_synchronize_user(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *username, int userid, int caccess, time_t seen, int flags, int new) {
- //just sync the user with the given userid with the providet information
- if(caccess == 500) caccess = 499;
- if(new) {
- //just add
- printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`, `chanuser_seen`, `chanuser_flags`) VALUES ('%d', '%d', '%d', '%lu', '%d')", chan->channel_id, userid, caccess, (unsigned long) seen, flags);
- } else {
- MYSQL_RES *res;
- MYSQL_ROW row;
- //check if already added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- //clvl
- if(atoi(row[0]) >= caccess) return;
- if(atol(row[2]) > seen) seen = atol(row[2]);
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d', `chanuser_seen` = '%lu' WHERE `chanuser_id` = '%s'", caccess, (unsigned long) seen, row[1]);
- } else
- printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`, `chanuser_seen`, `chanuser_flags`) VALUES ('%d', '%d', '%d', '%lu', '%d')", chan->channel_id, userid, caccess, (unsigned long) seen, flags);
- }
- reply(textclient, user, "NS_CHANSERVSYNC_SYNCHRONIZED", username, caccess);
-}