-config.h
-version.c
\ No newline at end of file
+mysqlConfig.h
+src/version.c
\ No newline at end of file
+++ /dev/null
-
-#include "BanNode.h"
-#include "ChanNode.h"
-#include "tools.h"
-
-struct BanNode* addChannelBan(struct ChanNode *chan, char *mask) {
- struct BanNode *ban = malloc(sizeof(*ban));
- ban->chan = chan;
- ban->mask = strdup(mask);
- ban->next = chan->bans;
- chan->bans = ban;
- return ban;
-}
-
-struct BanNode* getMatchingChannelBan(struct ChanNode *chan, char *mask) {
- struct BanNode *cban;
- for(cban = chan->bans; cban; cban = cban->next) {
- if(!match(cban->mask, mask)) {
- return cban;
- }
- }
- return NULL;
-}
-
-void removeChannelBanMask(struct ChanNode *chan, char *mask) {
- struct BanNode *cban, *last = NULL;
- for(cban = chan->bans; cban; cban = cban->next) {
- if(!strcmp(cban->mask, mask)) {
- if(last)
- last->next = cban->next;
- else
- chan->bans = cban->next;
- free(cban->mask);
- free(cban);
- break;
- } else
- last = cban;
- }
-}
-
-void removeChannelBan(struct BanNode *ban) {
- struct BanNode *cban, *last = NULL;
- struct ChanNode *chan = ban->chan;
- for(cban = chan->bans; cban; cban = cban->next) {
- if(cban == ban) {
- if(last)
- last->next = ban->next;
- else
- chan->bans = ban->next;
- free(ban->mask);
- free(ban);
- break;
- } else
- last = cban;
- }
-}
-
-void removeChannelBans(struct ChanNode *chan) {
- struct BanNode *ban, *next;
- for(ban = chan->bans; ban; ban = next) {
- next = ban->next;
- free(ban->mask);
- free(ban);
- }
- chan->bans = NULL;
-}
+++ /dev/null
-#ifndef _BanNode_h
-#define _BanNode_h
-#include "main.h"
-
-struct ChanNode;
-
-struct BanNode {
- char *mask;
- struct ChanNode *chan;
-
- struct BanNode *next;
-};
-
-struct BanNode* addChannelBan(struct ChanNode *chan, char *mask);
-struct BanNode* getMatchingChannelBan(struct ChanNode *chan, char *mask);
-void removeChannelBanMask(struct ChanNode *chan, char *mask);
-void removeChannelBan(struct BanNode *ban);
-void removeChannelBans(struct ChanNode *chan);
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "UserNode.h"
-#include "BanNode.h"
-#include "modcmd.h"
-#include "ModeNode.h"
-
-static struct ChanNode **chanList;
-
-void init_ChanNode() {
- /*
- len pos chars
- 26 0 a-z
- 10 26 0-9
- 10 36 {|}~[\]^_`
- 1 46 *everything else*
- ---------------------------
- = 47
- */
- #define CHANNEL_LIST_SIZE 47
- chanList = calloc(CHANNEL_LIST_SIZE, sizeof(*chanList));
-}
-
-void free_ChanNode() {
- //kamikaze free all channels and chanusers
- int i;
- struct ChanNode *chan, *next;
- struct ChanUser *chanuser, *next_chanuser;
- for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
- for(chan = chanList[i]; chan; chan = next) {
- next = chan->next;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next_chanuser) {
- next_chanuser = getChannelUsers(chan, chanuser);
- free(chanuser);
- }
- freeChanNode(chan);
- }
- }
- free(chanList);
-}
-
-int is_valid_chan(const char *name) {
- unsigned int ii;
- if (*name !='#')
- return 0;
- for (ii=1; name[ii]; ++ii) {
- if ((name[ii] > 0) && (name[ii] <= 32))
- return 0;
- if (name[ii] == ',')
- return 0;
- if (name[ii] == '\xa0')
- return 0;
- }
- return 1;
-}
-
-static int get_chanlist_entry(int name) {
- if((name > 0 && name <= 32) || name == ',' || name == '\xa0') return -1; //invalid name
- if(tolower(name) >= 97 && tolower(name) <= 122) {
- return (tolower(name) - 97);
- }
- if(tolower(name) >= 48 && tolower(name) <= 57) {
- return (tolower(name) - 48 + 26);
- }
- /* {|}~[\]^_` */
- if(name == '{') return 36;
- if(name == '|') return 37;
- if(name == '}') return 38;
- if(name == '~') return 39;
- if(name == '[') return 40;
- if(name == '\\') return 41;
- if(name == ']') return 42;
- if(name == '^') return 43;
- if(name == '_') return 44;
- if(name == '`') return 45;
- return 46;
-}
-
-struct ChanNode* getChanByName(const char *name) { //case insensitive
- int chanListIndex = get_chanlist_entry(name[1]);
- if(chanListIndex == -1 || chanList[chanListIndex] == NULL)
- return NULL;
- struct ChanNode *chan;
- for(chan = chanList[chanListIndex]; chan; chan = chan->next) {
- if(!stricmp(name, chan->name))
- return chan;
- }
- return NULL;
-}
-
-struct ChanNode* addChannel(const char *name) {
- int chanListIndex = get_chanlist_entry(name[1]);
- if(chanListIndex == -1 || !is_valid_chan(name))
- return NULL;
- struct ChanNode *chan = malloc(sizeof(*chan));
- if (!chan)
- {
- perror("malloc() failed");
- return NULL;
- }
- strcpy(chan->name, name);
- chan->user = NULL;
- chan->bans = NULL;
- chan->usercount = 0;
- chan->chanbot = NULL;
- chan->topic[0] = 0;
- chan->flags = 0;
- /* mode lists */
- chan->modes = createModeNode(chan);
- chan->trigger = NULL;
-
- chan->next = chanList[chanListIndex];
- chanList[chanListIndex] = chan;
- return chan;
-}
-
-int getChannelCount() {
- int i, count = 0;
- struct ChanNode *chan;
- for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
- for(chan = chanList[i]; chan; chan = chan->next) {
- count++;
- }
- }
- return count;
-}
-
-int getChanUserCount() {
- int i, count = 0;
- struct ChanNode *chan;
- for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
- for(chan = chanList[i]; chan; chan = chan->next) {
- count += chan->usercount;
- }
- }
- return count;
-}
-
-int getChanBanCount() {
- int i, count = 0;
- struct ChanNode *chan;
- struct BanNode *ban;
- for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
- for(chan = chanList[i]; chan; chan = chan->next) {
- for(ban = chan->bans; ban; ban = ban->next)
- count ++;
- }
- }
- return count;
-}
-
-void delChannel(struct ChanNode* chan, int freeChan) {
- int chanListIndex = get_chanlist_entry(chan->name[1]);
- if(chanListIndex == -1) return;
- struct ChanNode *cchan, *last_chan = NULL;
- for(cchan = chanList[chanListIndex]; cchan; cchan = cchan->next) {
- if(cchan == chan) {
- if(last_chan)
- last_chan->next = chan->next;
- else
- chanList[chanListIndex] = chan->next;
- break;
- } else
- last_chan = cchan;
- }
- if(chan->user) {
- //free all chanusers
- struct ChanUser *chanuser, *next;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
- next = getChannelUsers(chan, chanuser);
- removeChanUserFromLists(chanuser, 0, 1, 1);
- }
- }
- if(freeChan)
- freeChanNode(chan);
- else
- chan->next = NULL;
-}
-
-void freeChanNode(struct ChanNode* chan) {
- if(chan->trigger) {
- struct trigger_cache *trigger, *next_trigger;
- for(trigger = chan->trigger; trigger; trigger = next_trigger) {
- next_trigger = trigger->next;
- free(trigger->trigger);
- free(trigger);
- }
- }
- freeModeNode(chan->modes);
- if(chan->bans)
- removeChannelBans(chan);
- free(chan);
-}
-
-void checkChannelVisibility(struct ChanNode* chan) {
- struct ChanUser *chanuser, *next;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(chanuser->user->flags & USERFLAG_ISBOT) {
- chan->chanbot = chanuser->user;
- return;
- }
- }
- //free the channel...
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
- next = getChannelUsers(chan, chanuser);
- //remove the channel from the user's channel-list
- removeChanUserFromLists(chanuser, 0, 1, 0);
- if(!chanuser->user->channel) {
- //free the user (no more channels)
- delUser(chanuser->user, 1);
- }
- free(chanuser);
- }
- chan->user = NULL;
- delChannel(chan, 1);
-}
+++ /dev/null
-#ifndef _ChanNode_h
-#define _ChanNode_h
-#include "main.h"
-
-struct ChanUser;
-struct trigger_cache;
-struct ModeNode;
-
-#define CHANFLAG_RECEIVED_USERLIST 0x01
-#define CHANFLAG_REQUESTED_CHANINFO 0x02
-#define CHANFLAG_CHAN_REGISTERED 0x04
-#define CHANFLAG_HAVE_INVISIBLES 0x08
-
-struct ChanNode {
- char name[CHANNELLEN+1];
- char topic[TOPICLEN+1];
- struct ChanUser *user;
- unsigned int usercount;
- unsigned char flags;
- struct ModeNode *modes;
- struct BanNode *bans;
-
- struct UserNode *chanbot;
- struct trigger_cache *trigger;
- int channel_id;
-
- struct ChanNode *next;
-};
-
-void init_ChanNode();
-void free_ChanNode();
-int is_valid_chan(const char *name);
-struct ChanNode* getChanByName(const char *name);
-struct ChanNode* addChannel(const char *chan);
-int getChannelCount();
-int getChanUserCount();
-int getChanBanCount();
-void delChannel(struct ChanNode* chan, int freeChan);
-void freeChanNode(struct ChanNode* chan);
-void checkChannelVisibility(struct ChanNode* chan);
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "ChanUser.h"
-#include "ChanNode.h"
-#include "UserNode.h"
-
-struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user) {
- struct ChanUser *chanuser = malloc(sizeof(*chan));
- if (!chanuser)
- {
- perror("malloc() failed");
- return NULL;
- }
- chanuser->flags = 0;
- chanuser->user = user;
- chanuser->chan = chan;
-
- chanuser->changeTime = 0;
-
- chanuser->next_user = chan->user;
- chan->user = chanuser;
- chan->usercount++;
-
- chanuser->next_chan = user->channel;
- user->channel = chanuser;
-
- return chanuser;
-}
-
-struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user) {
- struct ChanUser *chanuser = malloc(sizeof(*chan));
- if (!chanuser)
- {
- perror("malloc() failed");
- return NULL;
- }
- chanuser->flags = CHANUSERFLAG_INVISIBLE;
- chanuser->user = user;
- chanuser->chan = chan;
-
- chanuser->changeTime = 0;
-
- chanuser->next_user = chan->user;
- chan->user = chanuser;
- chan->usercount++;
-
- return chanuser;
-}
-
-int isUserOnChan(struct UserNode *user, struct ChanNode *chan) {
- struct ChanUser *chanuser;
- for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
- if(chanuser->chan == chan)
- return 1;
- }
- return 0;
-}
-
-struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan) {
- struct ChanUser *chanuser;
- for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
- if(chanuser->chan == chan)
- return chanuser;
- }
- return NULL;
-}
-
-struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last) {
- if(last == NULL)
- return chan->user;
- else
- return last->next_user;
-}
-
-struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last) {
- if(last == NULL)
- return user->channel;
- else
- return last->next_chan;
-}
-
-void delChanUser(struct ChanUser *chanuser, int freeChanUser) {
- struct ChanUser *cchanuser, *last;
- //remove it from the user's channel-list
- if(!(chanuser->flags & CHANUSERFLAG_INVISIBLE)) {
- last = NULL;
- for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
- if(cchanuser == chanuser) {
- if(last)
- last->next_chan = chanuser->next_chan;
- else
- chanuser->user->channel = chanuser->next_chan;
- break;
- } else
- last = cchanuser;
- }
- }
-
- //remove it from the channel's user-list
- last = NULL;
- for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
- if(cchanuser == chanuser) {
- chanuser->chan->usercount--;
- if(last)
- last->next_user = chanuser->next_user;
- else
- chanuser->chan->user = chanuser->next_user;
- break;
- } else
- last = cchanuser;
- }
-
- if(freeChanUser)
- free(chanuser);
- else {
- chanuser->next_chan = NULL;
- chanuser->next_user = NULL;
- }
-}
-
-void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int freeChanUser) {
- struct ChanUser *cchanuser, *last;
- if(remove_from_userlist) {
- //remove it from the channel's user-list
- last = NULL;
- for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
- if(cchanuser == chanuser) {
- chanuser->chan->usercount--;
- if(last)
- last->next_user = chanuser->next_user;
- else
- chanuser->chan->user = chanuser->next_user;
- break;
- } else
- last = cchanuser;
- }
- chanuser->next_user = NULL;
- }
- if(remove_from_channellist) {
- //remove it from the user's channel-list
- last = NULL;
- for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
- if(cchanuser == chanuser) {
- if(last)
- last->next_chan = chanuser->next_chan;
- else
- chanuser->user->channel = chanuser->next_chan;
- break;
- } else
- last = cchanuser;
- }
- chanuser->next_chan = NULL;
- }
-
- if(freeChanUser)
- free(chanuser);
-}
-
+++ /dev/null
-#ifndef _ChanUser_h
-#define _ChanUser_h
-#include "main.h"
-
-#define CHANUSERFLAG_OPPED 0x01
-#define CHANUSERFLAG_VOICED 0x02
-#define CHANUSERFLAG_INVISIBLE 0x04
-
-#define CHANUSERFLAG_OPPED_OR_VOICED (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED)
-
-struct ChanNode;
-struct UserNode;
-
-struct ChanUser {
- unsigned char flags;
- struct ChanNode *chan;
- struct UserNode *user;
-
- int chageEvents;
- time_t changeTime;
-
- struct ChanUser *next_user;
- struct ChanUser *next_chan;
-};
-
-struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user);
-struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user);
-int isUserOnChan(struct UserNode *user, struct ChanNode *chan);
-struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan);
-struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last);
-struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last);
-void delChanUser(struct ChanUser *chanuser, int freeChanUser);
-void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int freeChanUser);
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "ClientSocket.h"
-#include "IRCParser.h"
-#include "UserNode.h"
-
-struct socket_list {
- struct ClientSocket *data;
- unsigned count;
-};
-
-//the magic list :P
-static struct socket_list *sockets = NULL;
-static char buffer[BUF_SIZ];
-
-static void init_sockets() {
- sockets = malloc(sizeof(*sockets));
- if (!sockets)
- {
- perror("malloc() failed");
- return;
- }
- sockets->data = NULL;
- sockets->count = 0;
-}
-
-struct ClientSocket* create_socket(char *host, int port, char *pass, struct UserNode *user) {
- if(sockets == NULL) init_sockets();
- struct ClientSocket *client = malloc(sizeof(*client));
- if (!client)
- {
- perror("malloc() failed");
- return NULL;
- }
- client->host = strdup(host);
- client->port = port;
- printf("Connect: %s:%d", client->host, client->port);
- client->pass = (pass == NULL ? NULL : strdup(pass));
- client->user = user;
- client->flags = 0;
- client->bufferpos = 0;
- client->traffic_in = 0;
- client->traffic_out = 0;
- client->connection_time = 0;
- client->botid = 0;
- client->clientid = 0;
- client->next = sockets->data;
- sockets->data = client;
- return client;
-}
-
-int connect_socket(struct ClientSocket *client) {
- if((client->flags & SOCKET_FLAG_CONNECTED)) return 1;
- struct hostent *host;
- struct sockaddr_in addr;
- int sock;
- if (!inet_aton(client->host, &addr.sin_addr))
- {
- host = gethostbyname(client->host);
- if (!host)
- {
- herror("gethostbyname() failed");
- return 0;
- }
- addr.sin_addr = *(struct in_addr*)host->h_addr;
- }
- sock = socket(PF_INET, SOCK_STREAM, 0);
- if (sock == -1)
- {
- perror("socket() failed");
- return 0;
- }
-
- addr.sin_port = htons(client->port);
- addr.sin_family = AF_INET;
-
- if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1)
- {
- perror("connect() failed");
- return 0;
- }
-
- client->sock = sock;
- client->flags |= SOCKET_FLAG_CONNECTED;
- client->connection_time = time(0);
-
- //send the IRC Headers
- char sendBuf[512];
- int len;
-
- if(client->pass) {
- len = sprintf(sendBuf, "PASS :%s\n", client->pass);
- write_socket(client, sendBuf, len);
- }
- len = sprintf(sendBuf, "USER %s 0 0 :%s\n", client->user->ident, client->user->realname);
- write_socket(client, sendBuf, len);
- len = sprintf(sendBuf, "NICK %s\n", client->user->nick);
- write_socket(client, sendBuf, len);
-
- return 1;
-}
-
-int close_socket(struct ClientSocket *client) {
- if(client == NULL) return 0;
- if((client->flags & SOCKET_FLAG_CONNECTED))
- close(client->sock);
- struct ClientSocket *sock, *last_sock = NULL;
- for (sock = sockets->data; sock; sock = sock->next) {
- if(sock == client) {
- if(last_sock)
- last_sock->next = sock->next;
- else
- sockets->data = sock->next;
- sockets->count--;
- } else
- last_sock = sock;
- }
- free(client->host);
- free(client->pass);
- free(client);
- return 1;
-}
-
-int write_socket(struct ClientSocket *client, char* msg, int len) {
- if(!(client->flags & SOCKET_FLAG_CONNECTED)) return 0;
- printf("[send %d] %s", len, msg);
- write(client->sock, msg, len);
- client->traffic_out += len;
- return 1;
-}
-
-void socket_loop(int timeout_seconds) {
- if(sockets == NULL) return;
- fd_set fds;
- struct timeval timeout;
- struct ClientSocket *sock;
- int ret = 0, bytes, i;
-
- FD_ZERO(&fds);
- for (sock = sockets->data; sock; sock = sock->next) {
- if(!(sock->flags & SOCKET_FLAG_CONNECTED)) continue; //skip disconnected sockets
- FD_SET(sock->sock, &fds);
- if(sock->sock > ret)
- ret = sock->sock;
- }
- timeout.tv_sec = timeout_seconds;
- timeout.tv_usec = 0;
- ret = select(ret + 1, &fds, NULL, NULL, &timeout);
- if(ret == 0) return;
- for (sock = sockets->data; sock; sock = sock->next) {
- if((sock->flags & SOCKET_FLAG_CONNECTED) && FD_ISSET(sock->sock, &fds)) {
- if(sock->bufferpos != 0) {
- bytes = read(sock->sock, buffer, sizeof(buffer));
- if(bytes > 0) {
- for(i = 0; i < bytes; i++) {
- if(sock->bufferpos + i == BUF_SIZ*2) break; //buffer overflow
- sock->buffer[sock->bufferpos + i] = buffer[i];
- }
- sock->bufferpos += i;
- }
- } else {
- bytes = read(sock->sock, sock->buffer, sizeof(sock->buffer));
- if(bytes > 0)
- sock->bufferpos = bytes;
- }
- if(bytes <= 0) {
- //error
- sock->flags &= ~(SOCKET_FLAG_CONNECTED | SOCKET_FLAG_READY);
- bot_disconnect(sock);
- } else {
- sock->traffic_in += bytes;
- int used = parse_lines(sock, sock->buffer, sock->bufferpos);
- if(used == sock->bufferpos + 1) {
- //used all bytes so just reset the bufferpos
- sock->bufferpos = 0;
- } else {
- for(i = 0; i < sock->bufferpos - used; i++) {
- sock->buffer[i] = sock->buffer[i+used];
- }
- sock->bufferpos -= used;
- }
- }
- }
- }
-}
-
-void
-putsock(struct ClientSocket *client, const char *text, ...)
-{
- va_list arg_list;
- char sendBuf[MAXLEN];
- int pos;
- if (!(client->flags & SOCKET_FLAG_CONNECTED)) return;
- sendBuf[0] = '\0';
- va_start(arg_list, text);
- pos = vsnprintf(sendBuf, MAXLEN - 2, text, arg_list);
- va_end(arg_list);
- if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
- sendBuf[pos] = '\n';
- sendBuf[pos+1] = '\0';
- write_socket(client, sendBuf, pos+1);
-}
-
-struct ClientSocket* getBots(int flags, struct ClientSocket* last_bot) {
- struct ClientSocket *sock = (last_bot ? last_bot->next : sockets->data);
- if(sock == NULL) return NULL;
- for (; sock; sock = sock->next) {
- if(!flags || (sock->flags & flags) == flags)
- return sock;
- }
- return NULL;
-}
-
-void free_sockets() {
- if(!sockets) return;
- struct ClientSocket *client, *next;
- for (client = sockets->data; client; client = next) {
- next = client->next;
- if((client->flags & SOCKET_FLAG_CONNECTED))
- close(client->sock);
- free(client->host);
- free(client->pass);
- free(client);
- }
- free(sockets);
- sockets = NULL;
-}
+++ /dev/null
-#ifndef _ClientSocket_h
-#define _ClientSocket_h
-
-#include "main.h"
-
-#define SOCKET_FLAG_DEAD 0x01
-#define SOCKET_FLAG_CONNECTED 0x02
-#define SOCKET_FLAG_READY 0x04
-#define SOCKET_FLAG_PREFERRED 0x08 /* prefered bot to send datas to the IRC World (NOTICE's WHO's etc pp) */
-
-#define BUF_SIZ 512
-
-struct UserNode;
-struct trigger_cache;
-
-struct ClientSocket {
- int sock;
- unsigned char flags;
- char buffer[BUF_SIZ*2]; //we need to store up to 2 full commands at once
- unsigned int bufferpos;
- char *host;
- int port;
- char *pass;
- struct UserNode *user;
- unsigned long traffic_in;
- unsigned long traffic_out;
- time_t connection_time;
-
- int botid : 16;
- int clientid : 16;
-
- struct ClientSocket *next;
-};
-
-struct ClientSocket* create_socket(char *host, int port, char *pass, struct UserNode *user);
-int connect_socket(struct ClientSocket *client);
-int close_socket(struct ClientSocket *client);
-int write_socket(struct ClientSocket *client, char* msg, int len);
-void socket_loop(int timeout_seconds);
-void putsock(struct ClientSocket *client, const char *text, ...) PRINTF_LIKE(2, 3);
-struct ClientSocket* getBots(int flags, struct ClientSocket* last_bot);
-void free_sockets();
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "DBHelper.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "mysqlConn.h"
-#include "lang.h"
-#include "tools.h"
-
-void _loadUserSettings(struct UserNode *user) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `user_lang`, `user_reply_privmsg`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- user->language = get_language_by_tag(row[0]);
- if(user->language == NULL) user->language = get_default_language();
- if(strcmp(row[1], "0"))
- user->flags |= USERFLAG_REPLY_PRIVMSG;
- if(strcmp(row[2], "0"))
- user->flags |= USERFLAG_GOD_MODE;
- } else
- user->language = get_default_language();
- user->flags |= USERFLAG_LOADED_SETTINGS;
-}
-
-int isGodMode(struct UserNode *user) {
- loadUserSettings(user);
- return (user->flags & USERFLAG_GOD_MODE);
-}
-
-int getChannelAccess(struct UserNode *user, struct ChanNode *chan, int override) {
- if(!(user->flags & USERFLAG_ISAUTHED)) return 0;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
- MYSQL_RES *res;
- MYSQL_ROW row;
- int caccess = 0;
- printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- if(strcmp(row[2], "0") && override)
- caccess = atoi(row[1]);
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id);
- //
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- int cflags = atoi(row[1]);
- if(!(cflags & DB_CHANUSER_SUSPENDED) && atoi(row[0]) > caccess)
- caccess = atoi(row[0]);
- }
- return caccess;
- }
- return 0;
-}
-
-char *getChanDefault(char *channel_setting) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_setting);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return "";
- return row[0];
-}
-
-int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_override, int allow_501) {
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
- if((user->flags & USERFLAG_ISIRCOP)) return 1;
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_setting, chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return 0;
- int require_access = atoi((row[0] ? row[0] : getChanDefault(channel_setting)));
- if(require_access == 0) return 1;
- if(!(user->flags & USERFLAG_ISAUTHED)) return 0;
- int caccess = 0;
- printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- int cflags = atoi(row[1]);
- if(!(cflags & DB_CHANUSER_SUSPENDED))
- caccess = atoi(row[0]);
- }
- }
- if(caccess >= require_access) return 1;
- if(caccess == 500 && require_access == 501 && allow_501) return 1;
- return 0;
-}
-
-void _loadChannelSettings(struct ChanNode *chan) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chan->flags |= CHANFLAG_CHAN_REGISTERED;
- chan->channel_id = atoi(row[0]);
- }
- chan->flags |= CHANFLAG_REQUESTED_CHANINFO;
-}
-
-//TODO: fix performance: we should cache the user access
-int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer) {
- /* Don't protect if someone is attacking himself, or if the aggressor is an IRC Operator. */
- if(victim == issuer || (issuer->flags & USERFLAG_ISIRCOP)) return 0;
-
- /* Don't protect if no one is to be protected. */
- MYSQL_RES *res;
- MYSQL_ROW row;
- char protection;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
- printf_mysql_query("SELECT `channel_protect` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if(!(row = mysql_fetch_row(res))) return 0;
- if(row[0]) {
- protection = (char) atoi(row[0]);
- } else {
- printf_mysql_query("SELECT `channel_protect` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- row = mysql_fetch_row(res);
- protection = (char) atoi(row[0]);
- }
- if(protection == 3) return 0;
-
- /* Don't protect if the victim isn't added to the channel, unless we are to protect non-users also. */
- int victim_access = getChannelAccess(victim, chan, 0);
- if (!victim_access && protection != 0) return 0;
-
- /* Protect if the aggressor isn't a user because at this point, the aggressor can only be less than or equal to the victim. */
- int issuer_access = getChannelAccess(issuer, chan, 0);
- if (!issuer_access) return 1;
-
- /* If the aggressor was a user, then the victim can't be helped. */
- if(!victim_access) return 0;
-
- switch(protection) {
- case 0:
- case 1:
- if(victim_access >= issuer_access) return 1;
- break;
- case 2:
- if(victim_access > issuer_access) return 1;
- break;
- }
- return 0;
-}
-
-char *getBanAffectingMask(struct ChanNode *chan, char *mask) {
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `ban_mask` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
- res = mysql_use();
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(!match(row[0], mask))
- return row[0];
- }
- return NULL;
-}
+++ /dev/null
-#ifndef _DBHelper_h
-#define _DBHelper_h
-
-#include "main.h"
-struct UserNode;
-struct ChanNode;
-
-#define DB_CHANUSER_SUSPENDED 0x01
-#define DB_CHANUSER_AUTOINVITE 0x02
-#define DB_CHANUSER_NOAUTOOP 0x04
-
-void _loadUserSettings(struct UserNode* user);
-#define loadUserSettings(USER) if((USER->flags & USERFLAG_ISAUTHED) && !(USER->flags & USERFLAG_LOADED_SETTINGS)) _loadUserSettings(USER)
-int isGodMode(struct UserNode *user);
-char *getChanDefault(char *channel_setting);
-int getChannelAccess(struct UserNode *user, struct ChanNode *chan, int override);
-int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_override, int allow_501);
-void _loadChannelSettings(struct ChanNode *chan);
-#define loadChannelSettings(CHAN) if(!(CHAN->flags & CHANFLAG_REQUESTED_CHANINFO)) _loadChannelSettings(CHAN)
-int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer);
-
-char *getBanAffectingMask(struct ChanNode *chan, char *mask); //returns bans that match a given mask eg. *!*@ab* if you pass *!*@abcdefg.*
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "EventLogger.h"
-#include "modcmd.h"
-#include "mysqlConn.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "DBHelper.h"
-
-static struct Event *first_event = NULL, *last_event = NULL;
-
-struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags) {
- struct Event *event = malloc(sizeof(*event));
- if (!event)
- {
- perror("malloc() failed");
- return NULL;
- }
- event->client = client;
- event->user = user;
- event->chan = chan;
- event->event_time = time(0);
- event->command = strdup(command);
- char arguments[MAXLEN];
- int argpos = 0;
- int i;
- for(i = 0; i < argc; i++)
- argpos += sprintf(arguments + argpos, "%s ", args[i]);
- arguments[(argpos ? argpos-1 : 0)] = '\0';
- event->arguments = strdup(arguments);
- event->flags = flags;
- event->next = NULL;
- if(last_event) {
- last_event->next = event;
- last_event = event;
- } else {
- last_event = event;
- first_event = event;
- }
- return event;
-}
-
-void logEvent(struct Event *event) {
- char fullcmd[MAXLEN];
- sprintf(fullcmd, "%s %s", event->command, event->arguments);
- if((event->flags & CMDFLAG_LOG) && event->chan) {
- char *auth = ((event->user->flags & USERFLAG_ISAUTHED) ? event->user->auth : "*");
- loadChannelSettings(event->chan);
- if((event->chan->flags & CHANFLAG_CHAN_REGISTERED))
- printf_mysql_query("INSERT INTO `events` (`cid`, `nick`, `auth`, `time`, `command`) VALUES ('%d', '%s', '%s', UNIX_TIMESTAMP(), '%s')", event->chan->channel_id, escape_string(event->user->nick), auth, escape_string(fullcmd));
- }
- if((event->flags & CMDFLAG_OPLOG)) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- char *auth = ((event->user->flags & USERFLAG_ISAUTHED) ? event->user->auth : "*");
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL)
- userid = 0;
- else
- userid = atoi(row[0]);
- loadChannelSettings(event->chan);
- if((event->chan->flags & CHANFLAG_CHAN_REGISTERED))
- printf_mysql_query("INSERT INTO `godlog` (`godlog_cid`, `godlog_uid`, `godlog_time`, `godlog_cmd`) VALUES ('%d', '%d', UNIX_TIMESTAMP(), '%s')", event->chan->channel_id, userid, escape_string(fullcmd));
- }
-}
-
-static void destroyEvent(struct Event *event) {
- if(event == first_event)
- first_event = event->next;
- if(event == last_event) {
- struct Event *last;
- for(last = first_event; last; last = last->next)
- if(last->next == NULL) break;
- last_event = last;
- }
- free(event->command);
- free(event->arguments);
- free(event);
-}
-
-void destroyEvents() {
- time_t now = time(0);
- while(first_event && now - first_event->event_time >= 60) {
- destroyEvent(first_event);
- }
-}
+++ /dev/null
-#ifndef _EventLogger_h
-#define _EventLogger_h
-
-#include "main.h"
-struct ClientSocket;
-struct UserNode;
-struct ChanNode;
-
-struct Event {
- struct ClientSocket *client;
- struct UserNode *user;
- struct ChanNode *chan;
- time_t event_time;
- char *command;
- char *arguments;
- unsigned int flags; /* defined in modcmd.h */
-
- struct Event *next;
-};
-
-struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags);
-void logEvent(struct Event *event);
-void destroyEvents();
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "HandleInfoHandler.h"
-#include "ClientSocket.h"
-#include "UserNode.h"
-#include "IRCEvents.h"
-#include "tools.h"
-
-#define AUTHSERV_NICK "AuthServ"
-
-struct HandleInfoQueueEntry {
- struct ClientSocket *client;
- void *callback;
- void *data;
-
- struct HandleInfoQueueEntry *next;
-};
-
-static struct HandleInfoQueueEntry *first_entry = NULL, *last_entry = NULL;
-
-static struct HandleInfoQueueEntry* addHandleInfoQueueEntry(struct ClientSocket *client) {
- struct HandleInfoQueueEntry *entry = malloc(sizeof(*entry));
- if (!entry)
- {
- perror("malloc() failed");
- return NULL;
- }
- entry->next = NULL;
- entry->client = client;
- if(last_entry)
- last_entry->next = entry;
- else
- last_entry = entry;
- if(!first_entry)
- first_entry = entry;
- return entry;
-}
-
-static struct HandleInfoQueueEntry* getNextHandleInfoQueueEntry(struct ClientSocket *client, int freeEntry) {
- if(!first_entry) return NULL;
- struct HandleInfoQueueEntry *entry;
- for(entry = first_entry; entry; entry = entry->next) {
- if(entry->client == client)
- break;
- }
- if(entry == NULL) return NULL;
- if(freeEntry) {
- if(entry == first_entry)
- first_entry = entry->next;
- if(entry == last_entry) {
- struct HandleInfoQueueEntry *last;
- for(last = first_entry; last; last = last->next)
- if(last->next == NULL) break;
- last_entry = last;
- }
- }
- return entry;
-}
-
-void lookup_authname(char *auth, authlookup_callback_t callback, void *data) {
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->flags & SOCKET_FLAG_PREFERRED)
- break;
- }
- if(bot == NULL) return;
- struct HandleInfoQueueEntry* entry = addHandleInfoQueueEntry(bot);
- entry->callback = callback;
- entry->data = data;
- putsock(bot, "PRIVMSG " AUTHSERV_NICK " :ACCOUNTINFO *%s", auth);
-}
-
-static void recv_notice(struct UserNode *user, struct UserNode *target, char *message) {
- if(stricmp(user->nick, AUTHSERV_NICK)) return;
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->user == target) break;
- }
- if(!bot) return;
- char *auth = NULL;
- int do_match = 0, exists = 0;
- char *tmp;
- //messages to parse:
- // Account * has not been registered.
- // Account information for Skynet:
- if(!match("Account * has not been registered.", message)) {
- do_match = 1;
- tmp = strstr(message, "\002");
- auth = tmp+1;
- tmp = strstr(auth, "\002");
- *tmp = '\0';
- }
- if(!match("Account information for *", message)) {
- do_match = 1;
- exists = 1;
- tmp = strstr(message, "\002");
- auth = tmp+1;
- tmp = strstr(auth, "\002");
- *tmp = '\0';
- }
- if(do_match) {
- struct HandleInfoQueueEntry* entry = getNextHandleInfoQueueEntry(bot, 1);
- authlookup_callback_t *callback = entry->callback;
- callback(auth, exists, entry->data);
- free(entry);
- }
-}
-
-void init_handleinfohandler() {
- bind_privnotice(recv_notice);
-}
-
-void free_handleinfohandler() {
- struct HandleInfoQueueEntry *entry, *next;
- for(entry = first_entry; entry; entry = next) {
- next = entry->next;
- free(entry);
- }
- first_entry = NULL;
- last_entry = NULL;
-}
+++ /dev/null
-#ifndef _HandleInfoHandler_h
-#define _HandleInfoHandler_h
-
-#include "main.h"
-
-struct ClientSocket;
-struct UserNode;
-
-#define AUTHLOOKUP_CALLBACK(NAME) void NAME(UNUSED_ARG(char *auth), UNUSED_ARG(int exists), UNUSED_ARG(void *data))
-typedef AUTHLOOKUP_CALLBACK(authlookup_callback_t);
-
-void lookup_authname(char *auth, authlookup_callback_t callback, void *data);
-void init_handleinfohandler();
-void free_handleinfohandler();
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "IRCEvents.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "ClientSocket.h"
-#include "mysqlConn.h"
-
-struct binding {
- void *func;
- struct binding *next;
-};
-
-static void **binds;
-#define BIND_TYPE_JOIN 0
-#define BIND_TYPE_NICK 1
-#define BIND_TYPE_PART 2
-#define BIND_TYPE_QUIT 3
-#define BIND_TYPE_KICK 4
-#define BIND_TYPE_TOPIC 5
-#define BIND_TYPE_MODE 6
-#define BIND_TYPE_CHANMSG 7
-#define BIND_TYPE_PRIVMSG 8
-#define BIND_TYPE_CHANNOTICE 9
-#define BIND_TYPE_PRIVNOTICE 10
-#define BIND_TYPE_CHANCTCP 11
-#define BIND_TYPE_PRIVCTCP 12
-#define BIND_TYPE_INVITE 13
-#define BIND_TYPE_RAW 14
-#define BIND_TYPE_BOT_READY 15
-
-#define TOTAL_BIND_TYPES 16
-
-void init_bind() {
- binds = calloc(TOTAL_BIND_TYPES, sizeof(*binds));
-}
-
-void free_bind() {
- struct binding *cbind, *next;
- int i;
- for(i = 0; i < TOTAL_BIND_TYPES; i++) {
- for(cbind = binds[i]; cbind; cbind = next) {
- next = cbind->next;
- free(cbind);
- }
- }
- free(binds);
-}
-
-static int is_bound(unsigned char type, void *func) {
- struct binding *cbind;
- for(cbind = binds[type]; cbind; cbind = cbind->next) {
- if(cbind->func == func)
- return 1;
- }
- return 0;
-}
-
-#define FUNC_BIND(NAME,FUNCTYPE,TYPE) \
-int bind_##NAME(FUNCTYPE *func) { \
- if(!is_bound(TYPE, func)) { \
- struct binding *cbind = malloc(sizeof(*cbind)); \
- if (!cbind) { \
- perror("malloc() failed"); \
- return 0; \
- } \
- cbind->func = func; \
- cbind->next = binds[TYPE]; \
- binds[TYPE] = cbind; \
- return 1; \
- } \
- return 0; \
-}
-
-#define FUNC_UNBIND(NAME,FUNCTYPE,TYPE) \
-void unbind_##NAME(FUNCTYPE *func) { \
- struct binding *cbind, *last = NULL, *next; \
- for(cbind = binds[TYPE]; cbind; cbind = next) { \
- next = cbind->next; \
- if(cbind->func == func) { \
- if(last) \
- last->next = cbind->next; \
- else \
- binds[TYPE] = cbind->next; \
- free(cbind); \
- } else \
- last = cbind; \
- } \
-}
-
-#define FUNC_EVENT(NAME,FUNCTYPE,TYPE,PDECLARATION,PLIST) \
-int event_##NAME PDECLARATION { \
- struct binding *cbind; \
- pre_event(TYPE); \
- for(cbind = binds[TYPE]; cbind; cbind = cbind->next) { \
- FUNCTYPE *func = cbind->func; \
- func PLIST; \
- } \
- post_event(TYPE); \
- return 1; \
-}
-
-void pre_event(UNUSED_ARG(int type)) {
-
-}
-
-void post_event(UNUSED_ARG(int type)) {
- mysql_free();
-}
-
-//EVENTS
-
-FUNC_BIND(join, join_func_t, BIND_TYPE_JOIN)
-FUNC_UNBIND(join, join_func_t, BIND_TYPE_JOIN)
-FUNC_EVENT(join, join_func_t, BIND_TYPE_JOIN, (struct ChanUser *chanuser), (chanuser))
-
-FUNC_BIND(nick, nick_func_t, BIND_TYPE_NICK)
-FUNC_UNBIND(nick, nick_func_t, BIND_TYPE_NICK)
-FUNC_EVENT(nick, nick_func_t, BIND_TYPE_NICK, (struct UserNode *user, char *new_nick), (user, new_nick))
-
-FUNC_BIND(part, part_func_t, BIND_TYPE_PART)
-FUNC_UNBIND(part, part_func_t, BIND_TYPE_PART)
-FUNC_EVENT(part, part_func_t, BIND_TYPE_PART, (struct ChanUser *chanuser, char *reason), (chanuser, reason))
-
-FUNC_BIND(quit, quit_func_t, BIND_TYPE_QUIT)
-FUNC_UNBIND(quit, quit_func_t, BIND_TYPE_QUIT)
-FUNC_EVENT(quit, quit_func_t, BIND_TYPE_QUIT, (struct UserNode *user, char *reason), (user, reason))
-
-FUNC_BIND(kick, kick_func_t, BIND_TYPE_KICK)
-FUNC_UNBIND(kick, kick_func_t, BIND_TYPE_KICK)
-FUNC_EVENT(kick, kick_func_t, BIND_TYPE_KICK, (struct UserNode *user, struct ChanUser *target, char *reason), (user, target, reason))
-
-FUNC_BIND(topic, topic_func_t, BIND_TYPE_TOPIC)
-FUNC_UNBIND(topic, topic_func_t, BIND_TYPE_TOPIC)
-FUNC_EVENT(topic, topic_func_t, BIND_TYPE_TOPIC, (struct UserNode *user, struct ChanNode *chan, const char *new_topic), (user, chan, new_topic))
-
-FUNC_BIND(mode, mode_func_t, BIND_TYPE_MODE)
-FUNC_UNBIND(mode, mode_func_t, BIND_TYPE_MODE)
-FUNC_EVENT(mode, mode_func_t, BIND_TYPE_MODE, (struct UserNode *user, struct ChanNode *chan, char *modes, char **args, int argc), (user, chan, modes, args, argc))
-
-FUNC_BIND(chanmsg, chanmsg_func_t, BIND_TYPE_CHANMSG)
-FUNC_UNBIND(chanmsg, chanmsg_func_t, BIND_TYPE_CHANMSG)
-FUNC_EVENT(chanmsg, chanmsg_func_t, BIND_TYPE_CHANMSG, (struct UserNode *user, struct ChanNode *chan, char *message), (user, chan, message))
-
-FUNC_BIND(privmsg, privmsg_func_t, BIND_TYPE_PRIVMSG)
-FUNC_UNBIND(privmsg, privmsg_func_t, BIND_TYPE_PRIVMSG)
-FUNC_EVENT(privmsg, privmsg_func_t, BIND_TYPE_PRIVMSG, (struct UserNode *user, struct UserNode *target, char *message), (user, target, message))
-
-FUNC_BIND(channotice, channotice_func_t, BIND_TYPE_CHANNOTICE)
-FUNC_UNBIND(channotice, channotice_func_t, BIND_TYPE_CHANNOTICE)
-FUNC_EVENT(channotice, channotice_func_t, BIND_TYPE_CHANNOTICE, (struct UserNode *user, struct ChanNode *chan, char *message), (user, chan, message))
-
-FUNC_BIND(privnotice, privnotice_func_t, BIND_TYPE_PRIVNOTICE)
-FUNC_UNBIND(privnotice, privnotice_func_t, BIND_TYPE_PRIVNOTICE)
-FUNC_EVENT(privnotice, privnotice_func_t, BIND_TYPE_PRIVNOTICE, (struct UserNode *user, struct UserNode *target, char *message), (user, target, message))
-
-FUNC_BIND(chanctcp, chanctcp_func_t, BIND_TYPE_CHANCTCP)
-FUNC_UNBIND(chanctcp, chanctcp_func_t, BIND_TYPE_CHANCTCP)
-FUNC_EVENT(chanctcp, chanctcp_func_t, BIND_TYPE_CHANCTCP, (struct UserNode *user, struct ChanNode *chan, char *command, char *text), (user, chan, command, text))
-
-FUNC_BIND(privctcp, privctcp_func_t, BIND_TYPE_PRIVCTCP)
-FUNC_UNBIND(privctcp, privctcp_func_t, BIND_TYPE_PRIVCTCP)
-FUNC_EVENT(privctcp, privctcp_func_t, BIND_TYPE_PRIVCTCP, (struct UserNode *user, struct UserNode *target, char *command, char *text), (user, target, command, text))
-
-FUNC_BIND(invite, invite_func_t, BIND_TYPE_INVITE)
-FUNC_UNBIND(invite, invite_func_t, BIND_TYPE_INVITE)
-FUNC_EVENT(invite, invite_func_t, BIND_TYPE_INVITE, (struct ClientSocket *client, struct UserNode *user, char *channel), (client, user, channel))
-
-FUNC_BIND(raw, raw_func_t, BIND_TYPE_RAW)
-FUNC_UNBIND(raw, raw_func_t, BIND_TYPE_RAW)
-FUNC_EVENT(raw, raw_func_t, BIND_TYPE_RAW, (struct ClientSocket *client, char *from, char *cmd, char **argv, int argc), (client, from, cmd, argv, argc))
-
-FUNC_BIND(bot_ready, bot_ready_func_t, BIND_TYPE_BOT_READY)
-FUNC_UNBIND(bot_ready, bot_ready_func_t, BIND_TYPE_BOT_READY)
-FUNC_EVENT(bot_ready, bot_ready_func_t, BIND_TYPE_BOT_READY, (struct ClientSocket *client), (client))
+++ /dev/null
-#ifndef _IRCEvents_h
-#define _IRCEvents_h
-
-#include "main.h"
-
-struct UserNode;
-struct ChanNode;
-struct ChanUser;
-struct ClientSocket;
-
-void init_bind();
-void free_bind();
-
-typedef void join_func_t(struct ChanUser *chanuser);
-int bind_join(join_func_t *func);
-void unbind_join(join_func_t *func);
-int event_join(struct ChanUser *chanuser);
-
-typedef void nick_func_t(struct UserNode *user, char *new_nick);
-int bind_nick(nick_func_t *func);
-void unbind_nick(nick_func_t *func);
-int event_nick(struct UserNode *user, char *new_nick);
-
-typedef void part_func_t(struct ChanUser *chanuser, char *reason);
-int bind_part(part_func_t *func);
-void unbind_part(part_func_t *func);
-int event_part(struct ChanUser *chanuser, char *reason);
-
-typedef void quit_func_t(struct UserNode *user, char *reason);
-int bind_quit(quit_func_t *func);
-void unbind_quit(quit_func_t *func);
-int event_quit(struct UserNode *user, char *reason);
-
-typedef void kick_func_t(struct UserNode *user, struct ChanUser *target, char *reason);
-int bind_kick(kick_func_t *func);
-void unbind_kick(kick_func_t *func);
-int event_kick(struct UserNode *user, struct ChanUser *target, char *reason);
-
-typedef void topic_func_t(struct UserNode *user, struct ChanNode *chan, const char *new_topic);
-int bind_topic(topic_func_t *func);
-void unbind_topic(topic_func_t *func);
-int event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic);
-
-typedef void mode_func_t(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc);
-int bind_mode(mode_func_t *func);
-void unbind_mode(mode_func_t *func);
-int event_mode(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc);
-
-typedef void chanmsg_func_t(struct UserNode *user, struct ChanNode *chan, char *message);
-int bind_chanmsg(chanmsg_func_t *func);
-void unbind_chanmsg(chanmsg_func_t *func);
-int event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message);
-
-typedef void privmsg_func_t(struct UserNode *user, struct UserNode *target, char *message);
-int bind_privmsg(privmsg_func_t *func);
-void unbind_privmsg(privmsg_func_t *func);
-int event_privmsg(struct UserNode *user, struct UserNode *target, char *message);
-
-typedef void channotice_func_t(struct UserNode *user, struct ChanNode *chan, char *message);
-int bind_channotice(channotice_func_t *func);
-void unbind_channotice(channotice_func_t *func);
-int event_channotice(struct UserNode *user, struct ChanNode *chan, char *message);
-
-typedef void privnotice_func_t(struct UserNode *user, struct UserNode *target, char *message);
-int bind_privnotice(privnotice_func_t *func);
-void unbind_privnotice(privnotice_func_t *func);
-int event_privnotice(struct UserNode *user, struct UserNode *target, char *message);
-
-typedef void chanctcp_func_t(struct UserNode *user, struct ChanNode *chan, char *command, char *text);
-int bind_chanctcp(chanctcp_func_t *func);
-void unbind_chanctcp(chanctcp_func_t *func);
-int event_chanctcp(struct UserNode *user, struct ChanNode *chan, char *command, char *text);
-
-typedef void privctcp_func_t(struct UserNode *user, struct UserNode *target, char *command, char *text);
-int bind_privctcp(privctcp_func_t *func);
-void unbind_privctcp(privctcp_func_t *func);
-int event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text);
-
-typedef void invite_func_t(struct ClientSocket *client, struct UserNode *user, char *channel);
-int bind_invite(invite_func_t *func);
-void unbind_invite(invite_func_t *func);
-int event_invite(struct ClientSocket *client, struct UserNode *user, char *channel);
-
-typedef void raw_func_t(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
-int bind_raw(raw_func_t *func);
-void unbind_raw(raw_func_t *func);
-int event_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
-
-typedef void bot_ready_func_t(struct ClientSocket *client);
-int bind_bot_ready(bot_ready_func_t *func);
-void unbind_bot_ready(bot_ready_func_t *func);
-int event_bot_ready(struct ClientSocket *client);
-
-
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "IRCParser.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "IRCEvents.h"
-#include "ClientSocket.h"
-#include "WHOHandler.h"
-#include "lang.h"
-#include "DBHelper.h"
-#include "BanNode.h"
-#include "ModeNode.h"
-
-struct irc_cmd *irc_commands = NULL;
-
-static void parse_line(struct ClientSocket *client, char *line);
-static void register_irc_function(char *command, irc_cmd_t *func);
-static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
-
-int parse_lines(struct ClientSocket *client, char *lines, int len) {
- int i, used = 0;
- char *line = lines;
- for(i = 0; i < len; i++) {
- if(lines[i] == '\r') //just zero it out :D
- lines[i] = 0;
- if(lines[i] == '\n') {
- lines[i] = 0;
- parse_line(client, line);
- line = lines+(i+1);
- used = i+1;
- }
- }
- return used;
-}
-
-static void parse_line(struct ClientSocket *client, char *line) {
- int argc = 0;
- char *argv[MAXNUMPARAMS];
- printf("[recv %lu] %s\n", (unsigned long) strlen(line), line);
- if(line[0] == ':')
- line++;
- else
- argv[argc++] = NULL;
- while(*line) {
- //skip leading spaces
- while (*line == ' ')
- *line++ = 0;
- if (*line == ':') {
- //the rest is a single parameter
- argv[argc++] = line + 1;
- break;
- }
- argv[argc++] = line;
- if (argc >= MAXNUMPARAMS)
- break;
- while (*line != ' ' && *line)
- line++;
- }
- if(argc >= 2) {
- parse_raw(client, argv[0], argv[1], argv+2, argc-2);
- }
-}
-
-static void register_irc_function(char *command, irc_cmd_t *func) {
- struct irc_cmd *irc_cmd = malloc(sizeof(*irc_cmd));
- if (!irc_cmd)
- {
- perror("malloc() failed");
- return;
- }
- irc_cmd->cmd = command;
- irc_cmd->func = func;
- irc_cmd->next = irc_commands;
- irc_commands = irc_cmd;
-}
-
-static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc) {
- struct irc_cmd *irc_cmd;
- int ret = 0;
- for(irc_cmd = irc_commands; irc_cmd; irc_cmd = irc_cmd->next) {
- if(!stricmp(irc_cmd->cmd, cmd)) {
- ret = irc_cmd->func(client, from, argv, argc);
- break;
- }
- }
- if(!irc_cmd) {
- event_raw(client, from, cmd, argv, argc);
- } else if(!ret) {
- fprintf(stderr,"PARSE ERROR: %s\n", cmd);
- }
-}
-
-static USERLIST_CALLBACK(got_channel_userlist) {
- struct ChanUser *chanuser = data;
- event_join(chanuser);
-}
-
-static IRC_CMD(raw_001) {
- client->flags |= SOCKET_FLAG_READY;
- event_bot_ready(client);
- return 1;
-}
-
-static IRC_CMD(raw_join) {
- if(from == NULL || argc < 1) return 0;
- struct UserNode *user = getUserByMask(from);
- struct ChanNode *chan = getChanByName(argv[0]);
- if(!chan && !(user->flags & USERFLAG_ISBOT)) return 0;
- if(user == NULL) {
- user = addUserMask(from);
- }
- if(chan == NULL) {
- chan = addChannel(argv[0]);
- //request member list
- chan->chanbot = user;
- struct ChanUser *chanuser = addChanUser(chan, user); //it must be a bot
- get_userlist(chan, got_channel_userlist, chanuser);
- putsock(client, "MODE %s", chan->name);
- putsock(client, "MODE %s +b", chan->name);
- } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
- struct ChanUser *chanuser = addChanUser(chan, user);
- event_join(chanuser);
- }
- return 1;
-}
-
-static IRC_CMD(raw_part) {
- if(from == NULL || argc < 1) return 0;
- struct UserNode *user = getUserByMask(from);
- if(user == NULL) return 0;
- struct ChanNode *chan = getChanByName(argv[0]);
- if(chan == NULL) return 0;
- if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
- struct ChanUser *chanuser = getChanUser(user, chan);
- delChanUser(chanuser, 0); //we need to free the chanuser manually!
- event_part(chanuser, (argc > 1 ? argv[1] : NULL));
- free(chanuser);
- if(chan->chanbot == user) {
- //check if theres another bot in the channel - otherwise free it
- checkChannelVisibility(chan);
- }
- }
- if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) {
- //remove the user
- delUser(user, 1);
- }
- return 1;
-}
-
-static IRC_CMD(raw_quit) {
- if(from == NULL || argc < 1) return 0;
- struct UserNode *user = getUserByMask(from);
- if(user == NULL) return 0;
- delUser(user, 0); //a little bit crazy, but we want to delete the user on the channel's userlists - but not the users channel list
- event_quit(user, argv[0]);
- if(user->flags & USERFLAG_ISBOT) {
- //check if there are other bots in the users channel - otherwise free them
- struct ChanUser *chanuser, *next;
- for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
- next = getUserChannels(user, chanuser);
- checkChannelVisibility(chanuser->chan);
- }
- }
- delUser(user, 1); //now we fully free the user
- return 1;
-}
-
-void bot_disconnect(struct ClientSocket *client) {
- struct UserNode *user = client->user;
- struct ChanUser *chanuser, *next;
- delUser(user, 0);
- event_quit(user, "disconnected");
- for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
- next = getUserChannels(user, chanuser);
- checkChannelVisibility(chanuser->chan);
- free(chanuser);
- }
- user->channel = NULL;
-}
-
-static IRC_CMD(raw_kick) {
- if(from == NULL || argc < 3) return 0;
- struct UserNode *user = getUserByMask(from);
- struct UserNode *target = getUserByNick(argv[1]);
- struct ChanNode *chan = getChanByName(argv[0]);
- if(chan == NULL || target == NULL) return 0;
- if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
- if(user == NULL) {
- user = createTempUser(from);
- user->flags |= USERFLAG_ISTMPUSER;
- }
- struct ChanUser *chanuser = getChanUser(target, chan);
- delChanUser(chanuser, 0); //we need to free the chanuser manually!
- event_kick(user, chanuser, argv[1]);
- free(chanuser);
- if(target->flags & USERFLAG_ISBOT) {
- //check if theres another bot in the channel - otherwise free it
- checkChannelVisibility(chan);
- }
- }
- if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) {
- //remove the user
- delUser(target, 1);
- }
- return 1;
-}
-
-static IRC_CMD(raw_topic) {
- if(from == NULL || argc < 2) return 0;
- struct UserNode *user = getUserByMask(from);
- struct ChanNode *chan = getChanByName(argv[0]);
- if(chan == NULL) return 0;
- if(chan->chanbot != client->user) return 1; //just ignore it to prevent event duplicates
- if(user == NULL) {
- user = createTempUser(from);
- user->flags |= USERFLAG_ISTMPUSER;
- }
- event_topic(user, chan, argv[1]);
- strcpy(chan->topic, argv[1]);
- return 1;
-}
-
-static IRC_CMD(raw_privmsg) {
- if(from == NULL || argc < 2) return 0;
- struct UserNode *user = getUserByMask(from);
- if(user == NULL) {
- user = createTempUser(from);
- user->flags |= USERFLAG_ISTMPUSER;
- }
- if(argv[0][0] == '#') { //Channel message
- struct ChanNode *chan = getChanByName(argv[0]);
- if(chan && chan->chanbot == client->user) {
- if(argv[1][0] == '\001') {
- char *cmd = &argv[1][1];
- char *text = strstr(cmd, " ");
- if(text) {
- *text = '\0';
- text++;
- if(strlen(text) && text[strlen(text)-1] == '\001')
- text[strlen(text)-1] = '\0';
- } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
- cmd[strlen(cmd)-1] = '\0';
- event_chanctcp(user, chan, cmd, text);
- } else
- event_chanmsg(user, chan, argv[1]);
- }
- } else {
- struct UserNode *target = getUserByNick(argv[0]);
- if(target) {
- if(argv[1][0] == '\001') {
- char *cmd = &argv[1][1];
- char *text = strstr(cmd, " ");
- if(text) {
- *text = '\0';
- text++;
- if(strlen(text) && text[strlen(text)-1] == '\001')
- text[strlen(text)-1] = '\0';
- } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
- cmd[strlen(cmd)-1] = '\0';
- event_privctcp(user, target, cmd, text);
- } else
- event_privmsg(user, target, argv[1]);
- }
- }
- return 1;
-}
-
-static IRC_CMD(raw_notice) {
- if(from == NULL || argc < 2) return 0;
- struct UserNode *user = getUserByMask(from);
- if(user == NULL) {
- user = createTempUser(from);
- user->flags |= USERFLAG_ISTMPUSER;
- }
- if(argv[0][0] == '#') { //Channel notice
- struct ChanNode *chan = getChanByName(argv[0]);
- if(chan && chan->chanbot == client->user)
- event_channotice(user, chan, argv[1]);
- } else {
- struct UserNode *target = getUserByNick(argv[0]);
- if(target)
- event_privnotice(user, target, argv[1]);
- }
- return 1;
-}
-
-static IRC_CMD(raw_nick) {
- if(from == NULL || argc == 0) return 0;
- struct UserNode *user = getUserByMask(from);
- if(user == NULL) return 0;
- event_nick(user, argv[0]);
- renameUser(user, argv[0]);
- return 1;
-}
-
-static IRC_CMD(raw_ping) {
- if(argc == 0) return 0;
- putsock(client, "PONG :%s", argv[0]);
- return 1;
-}
-
-static IRC_CMD(raw_354) {
- recv_whohandler_354(client, argv, argc);
- return 1;
-}
-
-static IRC_CMD(raw_315) {
- recv_whohandler_315(client, argv, argc);
- return 1;
-}
-
-static IRC_CMD(raw_324) { //MODE LIST
- //Watchcat #pktest +stnzN
- if(from == NULL || argc < 3) return 0;
- struct ChanNode *chan = getChanByName(argv[1]);
- if(chan == NULL) return 0;
- parseModes(chan->modes, argv[2], argv+3, argc-3);
- return 1;
-}
-
-static IRC_CMD(raw_invite) {
- if(from == NULL || argc < 2) return 0;
- struct UserNode *user = getUserByMask(from);
- if(user == NULL) {
- user = createTempUser(from);
- user->flags |= USERFLAG_ISTMPUSER;
- }
- event_invite(client, user, argv[1]);
- return 1;
-}
-
-static IRC_CMD(raw_mode) {
- if(from == NULL || argc < 2) return 0;
- struct UserNode *user = getUserByMask(from);
- if(user == NULL) {
- user = createTempUser(from);
- user->flags |= USERFLAG_ISTMPUSER;
- }
- if(argv[0][0] == '#') {
- //ChannelMode
- struct ChanNode *chan = getChanByName(argv[0]);
- if(!chan) return 0;
- if(chan->chanbot != client->user) return 1;
- event_mode(user, chan, argv[1], argv+2, argc-2);
- parseModes(chan->modes, argv[1], argv+2, argc-2);
- } else {
- //UserMode
- }
- return 1;
-}
-
-static IRC_CMD(raw_367) {
- //Watchcat #pktest pk911!*@* TestBot!~bot@pktest.user.WebGamesNet 1315863279
- struct ChanNode *chan = getChanByName(argv[1]);
- if(!chan) return 0;
- struct BanNode *ban;
- while((ban = getMatchingChannelBan(chan, argv[2]))) {
- removeChannelBan(ban);
- }
- addChannelBan(chan, argv[2]);
- return 1;
-}
-
-void init_parser() {
- //all the raws we receive...
- register_irc_function("001", raw_001);
- register_irc_function("324", raw_324);
- register_irc_function("367", raw_367);
- register_irc_function("INVITE", raw_invite);
- register_irc_function("NOTICE", raw_notice);
- register_irc_function("TOPIC", raw_topic);
- register_irc_function("KICK", raw_kick);
- register_irc_function("PART", raw_part);
- register_irc_function("QUIT", raw_quit);
- register_irc_function("JOIN", raw_join);
- register_irc_function("MODE", raw_mode);
- register_irc_function("NICK", raw_nick);
- register_irc_function("354", raw_354);
- register_irc_function("315", raw_315);
- register_irc_function("PING", raw_ping);
- register_irc_function("PRIVMSG", raw_privmsg);
-}
-
-void free_parser() {
- struct irc_cmd *cmd, *next;
- for(cmd = irc_commands; cmd; cmd = next) {
- next = cmd->next;
- free(cmd);
- }
-}
-
-void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...) {
- const char *reply_format = get_language_string(user, text);
- if(reply_format == NULL)
- reply_format = text;
- loadUserSettings(user);
- char formatBuf[MAXLEN];
- sprintf(formatBuf, "%s %s :%s", ((user->flags & USERFLAG_REPLY_PRIVMSG) ? "PRIVMSG" : "NOTICE"), user->nick, reply_format);
- va_list arg_list;
- char sendBuf[MAXLEN];
- int pos;
- if (!(client->flags & SOCKET_FLAG_CONNECTED)) return;
- sendBuf[0] = '\0';
- va_start(arg_list, text);
- pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list);
- va_end(arg_list);
- if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
- sendBuf[pos] = '\n';
- sendBuf[pos+1] = '\0';
- write_socket(client, sendBuf, pos+1);
-}
-
-char* merge_argv(char **argv, int start, int end) {
- return merge_argv_char(argv, start, end, ' ');
-}
-
-char* merge_argv_char(char **argv, int start, int end, char seperator) {
- int i;
- char *p = NULL;
- for(i = start; i < end; i++) {
- p = argv[i];
- while(*p) p++;
- *p = seperator;
- }
- if(p) *p = '\0';
- return argv[start];
-}
+++ /dev/null
-#ifndef _IRCParser_h
-#define _IRCParser_h
-
-#include "main.h"
-
-struct ClientSocket;
-struct UserNode;
-
-#define IRC_CMD(NAME) int NAME(struct ClientSocket *client, UNUSED_ARG(const char *from), UNUSED_ARG(char **argv), UNUSED_ARG(unsigned int argc))
-typedef IRC_CMD(irc_cmd_t);
-
-struct irc_cmd {
- char *cmd;
- irc_cmd_t *func;
- struct irc_cmd *next;
-};
-
-int parse_lines(struct ClientSocket *client, char *lines, int len);
-void bot_disconnect(struct ClientSocket *client);
-void init_parser();
-void free_parser();
-void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...);
-char* merge_argv(char **argv, int start, int end);
-char* merge_argv_char(char **argv, int start, int end, char seperator);
-
-#endif
\ No newline at end of file
+++ /dev/null
-CC = gcc
-SRC = EventLogger.c \
- IRCEvents.c \
- main.c \
- ChanNode.c \
- IRCParser.c \
- ClientSocket.c \
- UserNode.c \
- ChanUser.c \
- ModeNode.c \
- BanNode.c \
- WHOHandler.c \
- modcmd.c \
- mysqlConn.c \
- lang.c \
- HandleInfoHandler.c \
- tools.c \
- timeq.c \
- DBHelper.c \
- bots.c \
- bot_NeonServ.c
-CMD = cmd_neonserv_access.c \
- cmd_neonserv_addban.c \
- cmd_neonserv_addtimeban.c \
- cmd_neonserv_adduser.c \
- cmd_neonserv_ban.c \
- cmd_neonserv_bans.c \
- cmd_neonserv_bind.c \
- cmd_neonserv_chanservsync.c \
- cmd_neonserv_clvl.c \
- cmd_neonserv_command.c \
- cmd_neonserv_csuspend.c \
- cmd_neonserv_cunsuspend.c \
- cmd_neonserv_delban.c \
- cmd_neonserv_delme.c \
- cmd_neonserv_deluser.c \
- cmd_neonserv_deop.c \
- cmd_neonserv_deopall.c \
- cmd_neonserv_devoice.c \
- cmd_neonserv_devoiceall.c \
- cmd_neonserv_down.c \
- cmd_neonserv_downall.c \
- cmd_neonserv_emote.c \
- cmd_neonserv_events.c \
- cmd_neonserv_giveowner.c \
- cmd_neonserv_god.c \
- cmd_neonserv_help.c \
- cmd_neonserv_invite.c \
- cmd_neonserv_inviteme.c \
- cmd_neonserv_kick.c \
- cmd_neonserv_kickban.c \
- cmd_neonserv_mdeluser.c \
- cmd_neonserv_mode.c \
- cmd_neonserv_move.c \
- cmd_neonserv_myaccess.c \
- cmd_neonserv_netinfo.c \
- cmd_neonserv_notice.c \
- cmd_neonserv_op.c \
- cmd_neonserv_opall.c \
- cmd_neonserv_oplog.c \
- cmd_neonserv_peek.c \
- cmd_neonserv_raw.c \
- cmd_neonserv_recover.c \
- cmd_neonserv_register.c \
- cmd_neonserv_reloadlang.c \
- cmd_neonserv_resync.c \
- cmd_neonserv_say.c \
- cmd_neonserv_search.c \
- cmd_neonserv_set.c \
- cmd_neonserv_setaccess.c \
- cmd_neonserv_suspend.c \
- cmd_neonserv_topic.c \
- cmd_neonserv_trace.c \
- cmd_neonserv_trim.c \
- cmd_neonserv_unban.c \
- cmd_neonserv_unbanall.c \
- cmd_neonserv_unbanme.c \
- cmd_neonserv_unbind.c \
- cmd_neonserv_unregister.c \
- cmd_neonserv_unsuspend.c \
- cmd_neonserv_up.c \
- cmd_neonserv_upall.c \
- cmd_neonserv_users.c \
- cmd_neonserv_uset.c \
- cmd_neonserv_version.c \
- cmd_neonserv_voice.c \
- cmd_neonserv_voiceall.c \
- cmd_neonserv_wipeinfo.c
-CMD_DEPS = main.h modcmd.h IRCParser.h UserNode.h ChanNode.h ChanUser.h ModeNode.h \
- ClientSocket.h mysqlConn.h lang.h HandleInfoHandler.h WHOHandler.h DBHelper.h \
- tools.h timeq.h version.h EventLogger.h bot_NeonServ.h IRCEvents.h BanNode.h
-OBJS = ${SRC:%.c=%.o} ${CMD:%.c=%.o}
-CFLAGS=-g -O2 -Wall -Wshadow -Werror
-LIBS=-I. -I/usr/include/mysql
-LINK=-lmysqlclient
-
-all: $(OBJS)
-
-install: $(OBJS)
- chmod +x version.sh
- ./version.sh
- $(CC) $(LIBS) -c version.c $(CFLAGS)
- $(CC) $(LIBS) -o neonserv $(OBJS) version.o $(CFLAGS) $(LINK)
-
-%.o: %.c
- $(CC) $(LIBS) -c $< $(CFLAGS)
-
-clean:
- rm $(OBJS) version.o
-
-depend: $(SRC)
- mv Makefile Makefile.bak
- grep -A1 -B10000 '^# DEPENDINGS' Makefile.bak > Makefile
- $(CC) $(CFLAGS) -MM $(LIBS) $(SRC) >> Makefile
- rm Makefile.bak
-
-# DEPENDINGS -- generated by make depend
-
-
--- /dev/null
+AUTOMAKE_OPTIONS = foreign
+AM_CFLAGS = $(MYSQL_CFLAGS)
+
+CFLAGS = -g -O2 -Wall -Wshadow -Werror
+
+BUILT_SOURCES = version.c
+version.c: checkversion
+checkversion:
+ cd src && chmod +x version.sh && ./version.sh && cd ..
+
+bin_PROGRAMS = neonserv
+neonserv_SOURCES = src/version.c \
+ src/EventLogger.c \
+ src/IRCEvents.c \
+ src/main.c \
+ src/ChanNode.c \
+ src/IRCParser.c \
+ src/ClientSocket.c \
+ src/UserNode.c \
+ src/ChanUser.c \
+ src/ModeNode.c \
+ src/BanNode.c \
+ src/WHOHandler.c \
+ src/modcmd.c \
+ src/mysqlConn.c \
+ src/lang.c \
+ src/HandleInfoHandler.c \
+ src/tools.c \
+ src/timeq.c \
+ src/DBHelper.c \
+ src/bots.c \
+ src/bot_NeonServ.c \
+ src/cmd_neonserv_access.c \
+ src/cmd_neonserv_addban.c \
+ src/cmd_neonserv_addtimeban.c \
+ src/cmd_neonserv_adduser.c \
+ src/cmd_neonserv_ban.c \
+ src/cmd_neonserv_bans.c \
+ src/cmd_neonserv_bind.c \
+ src/cmd_neonserv_chanservsync.c \
+ src/cmd_neonserv_clvl.c \
+ src/cmd_neonserv_command.c \
+ src/cmd_neonserv_csuspend.c \
+ src/cmd_neonserv_cunsuspend.c \
+ src/cmd_neonserv_delban.c \
+ src/cmd_neonserv_delme.c \
+ src/cmd_neonserv_deluser.c \
+ src/cmd_neonserv_deop.c \
+ src/cmd_neonserv_deopall.c \
+ src/cmd_neonserv_devoice.c \
+ src/cmd_neonserv_devoiceall.c \
+ src/cmd_neonserv_down.c \
+ src/cmd_neonserv_downall.c \
+ src/cmd_neonserv_emote.c \
+ src/cmd_neonserv_events.c \
+ src/cmd_neonserv_giveowner.c \
+ src/cmd_neonserv_god.c \
+ src/cmd_neonserv_help.c \
+ src/cmd_neonserv_invite.c \
+ src/cmd_neonserv_inviteme.c \
+ src/cmd_neonserv_kick.c \
+ src/cmd_neonserv_kickban.c \
+ src/cmd_neonserv_mdeluser.c \
+ src/cmd_neonserv_mode.c \
+ src/cmd_neonserv_move.c \
+ src/cmd_neonserv_myaccess.c \
+ src/cmd_neonserv_netinfo.c \
+ src/cmd_neonserv_notice.c \
+ src/cmd_neonserv_op.c \
+ src/cmd_neonserv_opall.c \
+ src/cmd_neonserv_oplog.c \
+ src/cmd_neonserv_peek.c \
+ src/cmd_neonserv_raw.c \
+ src/cmd_neonserv_recover.c \
+ src/cmd_neonserv_register.c \
+ src/cmd_neonserv_reloadlang.c \
+ src/cmd_neonserv_resync.c \
+ src/cmd_neonserv_say.c \
+ src/cmd_neonserv_search.c \
+ src/cmd_neonserv_set.c \
+ src/cmd_neonserv_setaccess.c \
+ src/cmd_neonserv_suspend.c \
+ src/cmd_neonserv_topic.c \
+ src/cmd_neonserv_trace.c \
+ src/cmd_neonserv_trim.c \
+ src/cmd_neonserv_unban.c \
+ src/cmd_neonserv_unbanall.c \
+ src/cmd_neonserv_unbanme.c \
+ src/cmd_neonserv_unbind.c \
+ src/cmd_neonserv_unregister.c \
+ src/cmd_neonserv_unsuspend.c \
+ src/cmd_neonserv_up.c \
+ src/cmd_neonserv_upall.c \
+ src/cmd_neonserv_users.c \
+ src/cmd_neonserv_uset.c \
+ src/cmd_neonserv_version.c \
+ src/cmd_neonserv_voice.c \
+ src/cmd_neonserv_voiceall.c \
+ src/cmd_neonserv_wipeinfo.c
+
+neonserv_LDADD = $(MYSQL_LIBS)
\ No newline at end of file
+++ /dev/null
-#include "ModeNode.h"
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "UserNode.h"
-#include "BanNode.h"
-
-static int modes_with_strarg, modes_with_intarg, modes_count;
-
-unsigned int valid_modes[] = { /* Thats our mode list :P */
- 1, 'b', CHANNEL_MODE_TYPE_A,
- 2, 'o', CHANNEL_MODE_TYPE_A,
- 3, 'v', CHANNEL_MODE_TYPE_A,
- 4, 'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING | CHANNEL_MODE_KEY,
- 5, 'a', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
- 6, 'l', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
- 7, 'f', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
- 8, 'F', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
- 9, 'c', CHANNEL_MODE_TYPE_D,
- 10, 'C', CHANNEL_MODE_TYPE_D,
- 11, 'i', CHANNEL_MODE_TYPE_D,
- 12, 'm', CHANNEL_MODE_TYPE_D,
- 13, 'M', CHANNEL_MODE_TYPE_D,
- 14, 'n', CHANNEL_MODE_TYPE_D,
- 15, 'N', CHANNEL_MODE_TYPE_D,
- 16, 'p', CHANNEL_MODE_TYPE_D,
- 17, 'r', CHANNEL_MODE_TYPE_D,
- 18, 's', CHANNEL_MODE_TYPE_D,
- 19, 't', CHANNEL_MODE_TYPE_D,
- 20, 'u', CHANNEL_MODE_TYPE_D,
- 21, 'D', CHANNEL_MODE_TYPE_D,
- 22, 'd', CHANNEL_MODE_TYPE_D,
- 23, 'R', CHANNEL_MODE_TYPE_D,
- 24, 'z', CHANNEL_MODE_TYPE_D,
-// ^ maximum is 32!!!
- 0x00, 0x00, 0x00
-};
-
-void init_ModeNode() {
- unsigned int *mode, flag = 1;
- modes_with_strarg = 0;
- modes_with_intarg = 0;
- modes_count = 0;
- for (mode = valid_modes; mode[1]; mode += 3) {
- if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING) {
- mode[2] |= modes_with_strarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
- modes_with_strarg++;
- }
- if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
- mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
- modes_with_intarg++;
- }
- modes_count++;
- mode[0] = flag;
- flag = flag << 1;
- }
-}
-
-struct ModeNode *createModeNode(struct ChanNode *chan) {
- struct ModeNode *modes = malloc(sizeof(*modes));
- if (!modes)
- {
- perror("malloc() failed");
- return NULL;
- }
- modes->chan = chan;
- modes->modes = 0;
- modes->allmodes = 0;
- modes->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
- modes->mode_int_args = calloc(modes_with_intarg, sizeof(int));
- return modes;
-}
-
-void freeModeNode(struct ModeNode *modes) {
- int i;
- for(i = 0; i < modes_with_strarg; i++) {
- if(modes->mode_str_args[i])
- free(modes->mode_str_args[i]);
- }
- free(modes->mode_str_args);
- free(modes->mode_int_args);
- free(modes);
-}
-
-static unsigned int* getModeOptions(char mode) {
- unsigned int *cmode;
- for (cmode = valid_modes; cmode[1]; cmode += 3) {
- if(cmode[1] == mode)
- return cmode;
- }
- return NULL;
-}
-
-int isModeSet(struct ModeNode* modes, char modeChar) {
- unsigned int *modeOpt = getModeOptions(modeChar);
- return (modes->modes & modeOpt[0]);
-}
-
-int isModeAffected(struct ModeNode* modes, char modeChar) {
- unsigned int *modeOpt = getModeOptions(modeChar);
- return (modes->allmodes & modeOpt[0]);
-}
-
-void* getModeValue(struct ModeNode* modes, char modeChar) {
- #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
- unsigned int *modeOpt = getModeOptions(modeChar);
- if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING)
- return modes->mode_str_args[MODE_VALUE_INDEX];
- if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER)
- return &modes->mode_int_args[MODE_VALUE_INDEX];
- return NULL;
- #undef MODE_VALUE_INDEX
-}
-
-unsigned int getModeType(struct ModeNode* modes, char modeChar) {
- #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
- unsigned int *modeOpt = getModeOptions(modeChar);
- if(!modeOpt) return 0;
- return modeOpt[2];
- #undef MODE_VALUE_INDEX
-}
-
-static void parseModesUserPriv(struct ModeNode* modes, unsigned char flag, int add, char *nick) {
- if(modes->chan == NULL) return;
- struct UserNode *user = getUserByNick(nick);
- if(user == NULL) return;
- struct ChanUser *chanuser = getChanUser(user, modes->chan);
- if(chanuser == NULL) return;
- if(add)
- chanuser->flags |= flag;
- else
- chanuser->flags &= ~flag;
-}
-
-static void parseModesBan(struct ModeNode* modes, int add, char *mask) {
- if(modes->chan == NULL) return;
- if(add)
- addChannelBan(modes->chan, mask);
- else
- removeChannelBanMask(modes->chan, mask);
-}
-
-void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc) {
- int i, argpos = 0, add = 1;
- #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
- #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
- #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
- unsigned int *modeOpt;
- for(i = 0; i < strlen(modeStr); i++) {
- if(modeStr[i] == '+') {
- add = 1;
- continue;
- }
- if(modeStr[i] == '-') {
- add = 0;
- continue;
- }
- modeOpt = getModeOptions(modeStr[i]);
- if(!modeOpt) continue; // unknown mode?
- if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
- if(argpos == argc) continue;
- //special mode ;)
- switch(modeStr[i]) {
- case 'o':
- parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, argv[argpos]);
- break;
- case 'v':
- parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, argv[argpos]);
- break;
- case 'b':
- parseModesBan(modes, add, argv[argpos]);
- break;
- default:
- //we have an unknown TYPE_A mode???
- break;
- }
- argpos++;
- continue;
- }
- if(add) {
- if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
- if(argpos == argc) continue;
- if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
- if(modes->mode_str_args[MODE_VALUE_INDEX])
- free(modes->mode_str_args[MODE_VALUE_INDEX]);
- modes->mode_str_args[MODE_VALUE_INDEX] = strdup(argv[argpos++]);
- } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
- modes->mode_int_args[MODE_VALUE_INDEX] = atoi(argv[argpos++]);
- else
- argpos++; //we simply don't know what to do with the argument...
- }
- modes->modes |= modeOpt[0];
- modes->allmodes |= modeOpt[0];
- } else {
- modes->modes &= ~modeOpt[0];
- modes->allmodes |= modeOpt[0];
- if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
- if(argpos == argc) continue;
- if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
- free(modes->mode_str_args[MODE_VALUE_INDEX]);
- modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
- } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
- modes->mode_int_args[MODE_VALUE_INDEX] = 0;
- argpos++; //we don't need the argument when unsetting a mode...
- }
- }
- }
- #undef MODE_TYPE
- #undef MODE_VALUE
- #undef MODE_VALUE_INDEX
-}
-
-void parseModeString(struct ModeNode* modes, char *modeStr) {
- int argc = 0;
- char *args[modes_count+1];
- char *a, *b = modeStr;
- do {
- a = strstr(b, " ");
- if(a) *a = '\0';
- args[argc++] = b;
- if(a) b = a+1;
- } while(a);
- parseModes(modes, args[0], args+1, argc-1);
-}
-
-int parseMode(struct ModeNode* modes, int add, char mode, char *param) {
- #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
- #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
- #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
- unsigned int *modeOpt = getModeOptions(mode);
- if(!modeOpt) return 0;
- if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
- if(!param) return 0;
- //special mode ;)
- switch(mode) {
- case 'o':
- parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, param);
- break;
- case 'v':
- parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, param);
- break;
- case 'b':
- parseModesBan(modes, add, param);
- break;
- default:
- return 0; //we have an unknown TYPE_A mode???
- }
- }
- if(add) {
- if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
- if(!param) return 0;
- if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
- if(modes->mode_str_args[MODE_VALUE_INDEX])
- free(modes->mode_str_args[MODE_VALUE_INDEX]);
- modes->mode_str_args[MODE_VALUE_INDEX] = strdup(param);
- } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
- modes->mode_int_args[MODE_VALUE_INDEX] = atoi(param);
- }
- modes->modes |= modeOpt[0];
- modes->allmodes |= modeOpt[0];
- } else {
- modes->modes &= ~modeOpt[0];
- modes->allmodes |= modeOpt[0];
- if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
- if(!param) return 0;
- if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
- free(modes->mode_str_args[MODE_VALUE_INDEX]);
- modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
- } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
- modes->mode_int_args[MODE_VALUE_INDEX] = 0;
- }
- }
- #undef MODE_TYPE
- #undef MODE_VALUE
- #undef MODE_VALUE_INDEX
- return 1;
-}
-
-void getModeString(struct ModeNode* modes, char *modesStr) {
- #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
- #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
- #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
- char paramStr[MAXLEN];
- modesStr[0] = '+';
- unsigned int *mode;
- int modePos = 1;
- int paramPos = 0;
- for (mode = valid_modes; mode[1]; mode += 3) {
- if(modes->modes & mode[0]) {
- modesStr[modePos++] = (char) mode[1];
- if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
- if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
- paramPos += sprintf(paramStr + paramPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
- else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
- paramPos += sprintf(paramStr + paramPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
- }
- }
- }
- paramStr[paramPos] = '\0';
- strcpy(modesStr + modePos, paramStr);
- #undef MODE_TYPE
- #undef MODE_VALUE
- #undef MODE_VALUE_INDEX
-}
-
-void getFullModeString(struct ModeNode* modes, char *modesStr) {
- #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
- #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
- #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
- char addMode[modes_count+1];
- int addModePos = 0;
- char addParams[MAXLEN];
- addParams[0] = '\0';
- int addParamsPos = 0;
- char delMode[modes_count+1];
- int delModePos = 0;
- unsigned int *mode;
- for (mode = valid_modes; mode[1]; mode += 3) {
- if(modes->allmodes & mode[0]) {
- if(modes->modes & mode[0]) {
- addMode[addModePos++] = (char) mode[1];
- if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
- if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
- addParamsPos += sprintf(addParams + addParamsPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
- else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
- addParamsPos += sprintf(addParams + addParamsPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
- }
- } else {
- delMode[delModePos++] = (char) mode[1];
- }
- }
- }
- addMode[addModePos] = '\0';
- delMode[delModePos] = '\0';
- addParams[addParamsPos] = '\0';
- sprintf(modesStr, "%s%s%s%s%s", (addModePos ? "+" : ""), addMode, (delModePos ? "-" : ""), delMode, addParams);
- if(*modesStr == '\0') {
- sprintf(modesStr, "+");
- }
- #undef MODE_TYPE
- #undef MODE_VALUE
- #undef MODE_VALUE_INDEX
-}
+++ /dev/null
-#ifndef _ModeNode_h
-#define _ModeNode_h
-#include "main.h"
-
-struct ChanNode;
-
-//Types: http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
-#define CHANNEL_MODE_TYPE_A 0x01 /* ... special (addresses or users) ... */
-#define CHANNEL_MODE_TYPE_B 0x02 /* These modes always take a parameter. */
-#define CHANNEL_MODE_TYPE_C 0x03 /* These modes take a parameter only when set. */
-#define CHANNEL_MODE_TYPE_D 0x04 /* These modes never take a parameter. */
-#define CHANNEL_MODE_TYPE 0x07 /* bit mask to get the type */
-
-#define CHANNEL_MODE_VALUE_STRING 0x10
-#define CHANNEL_MODE_VALUE_INTEGER 0x20
-#define CHANNEL_MODE_VALUE 0x30 /* bit mask to get the value */
-
-#define CHANNEL_MODE_KEY 0x40 /* mode is a key - automatically add the current key as parameter on unset */
-
-#define CHANNEL_MODE_VALUE_INDEX_SHIFT 8
-#define CHANNEL_MODE_VALUE_INDEX_MASK (0xff << CHANNEL_MODE_VALUE_INDEX_SHIFT) /* this "bitrange" is reserved for storing the array indexes of the mode values */
-
-struct ModeNode {
- struct ChanNode *chan;
- unsigned int modes;
- unsigned int allmodes;
- char **mode_str_args;
- int *mode_int_args;
-};
-
-extern unsigned int valid_modes[];
-
-void init_ModeNode();
-struct ModeNode *createModeNode(struct ChanNode *chan);
-void freeModeNode(struct ModeNode *modes);
-int isModeSet(struct ModeNode* modes, char modeChar);
-int isModeAffected(struct ModeNode* modes, char modeChar);
-void* getModeValue(struct ModeNode* modes, char modeChar);
-unsigned int getModeType(struct ModeNode* modes, char modeChar);
-void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc);
-void parseModeString(struct ModeNode* modes, char *modeStr);
-int parseMode(struct ModeNode* modes, int add, char mode, char *param);
-void getModeString(struct ModeNode* modes, char *modesStr);
-void getFullModeString(struct ModeNode* modes, char *modesStr);
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include "UserNode.h"
-#include "ChanUser.h"
-#include "tools.h"
-
-static struct UserNode **userList;
-
-void init_UserNode() {
- userList = calloc(VALID_NICK_CHARS_FIRST_LEN+1, sizeof(*userList));
-}
-
-void free_UserNode() {
- //kamikaze free all users
- //chanusers will be destroyed in free_ChanNode()
- int i;
- struct UserNode *user, *next;
- for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
- for(user = userList[i]; user; user = next) {
- next = user->next;
- free(user);
- }
- }
- free(userList);
-}
-
-int is_valid_nick(const char *nick) {
- unsigned int i;
- //first char must be one of: a-zA-Z{|}~[\]^_`
- if (!strchr(VALID_NICK_CHARS_FIRST, *nick))
- return 0;
- //all other chars must be one of: a-zA-Z0-9{|}~[\]^_`
- for (i = 0; nick[i]; ++i)
- if (!strchr(VALID_NICK_CHARS, nick[i]))
- return 0;
- if (strlen(nick) > NICKLEN)
- return 0;
- return 1;
-}
-
-static int get_nicklist_entry(int nick) {
- int i;
- char *valid_chars = VALID_NICK_CHARS_FIRST;
- for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) {
- if(valid_chars[i] == nick)
- return i;
- }
- return -1; //ERROR!
-}
-
-struct UserNode* getUserByNick(const char *nick) { //case sensitive
- int userListIndex = get_nicklist_entry(*nick);
- if(userListIndex == -1 || userList[userListIndex] == NULL)
- return NULL;
- struct UserNode *user;
- for(user = userList[userListIndex]; user; user = user->next) {
- if(!stricmp(nick, user->nick))
- return user;
- }
- return NULL;
-}
-
-struct UserNode* getUserByMask(const char *mask) { //case sensitive
- char cmask[strlen(mask)+1];
- strcpy(cmask, mask);
- int i;
- struct UserNode *user = NULL;
- for(i = 0; i < strlen(mask); i++) {
- if(cmask[i] == '!') {
- cmask[i] = 0;
- user = getUserByNick(&cmask[0]);
- return user;
- } else if(cmask[i] == '.') {
- //it's a server
- return NULL;
- }
- }
- return NULL;
-}
-
-struct UserNode* searchUserByNick(const char *nick) { //case insensitive
- if(!isalpha(*nick))
- return getUserByNick(nick);
-
- int userListIndex;
- struct UserNode *user;
-
- //search in the lower case "section"
- userListIndex = get_nicklist_entry(tolower(*nick));
- if(userListIndex != -1 && userList[userListIndex] != NULL) {
- for(user = userList[userListIndex]; user; user = user->next) {
- if(!stricmp(nick, user->nick))
- return user;
- }
- }
- //search in the upper case "section"
- userListIndex = get_nicklist_entry(toupper(*nick));
- if(userListIndex != -1 && userList[userListIndex] != NULL) {
- for(user = userList[userListIndex]; user; user = user->next) {
- if(!stricmp(nick, user->nick))
- return user;
- }
- }
- return NULL;
-}
-
-int countUsersWithHost(char *host) {
- int i, count = 0;
- struct UserNode *user;
- for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
- for(user = userList[i]; user; user = user->next) {
- if(!strcmp(user->host, host)) {
- count++;
- }
- }
- }
- return count;
-}
-
-char *getAuthFakehost(char *auth) {
- int i;
- struct UserNode *user;
- for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
- for(user = userList[i]; user; user = user->next) {
- if((user->flags & USERFLAG_ISAUTHED) && !strcmp(user->auth, auth) && isFakeHost(user->host)) {
- return user->host;
- }
- }
- }
- return NULL;
-}
-
-struct UserNode* getAllUsers(struct UserNode *last) {
- if(last == NULL || last->next == NULL) {
- int cindex;
- if(last == NULL)
- cindex = 0;
- else
- cindex = get_nicklist_entry(last->nick[0]) + 1;
- while(userList[cindex] == NULL && cindex <= VALID_NICK_CHARS_FIRST_LEN)
- cindex++;
- if(cindex > VALID_NICK_CHARS_FIRST_LEN) return NULL;
- return userList[cindex];
- } else
- return last->next;
-}
-
-int getUserCount() {
- int i, count = 0;
- struct UserNode *user;
- for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
- for(user = userList[i]; user; user = user->next) {
- count++;
- }
- }
- return count;
-}
-
-struct UserNode* addUser(const char *nick) {
- int userListIndex = get_nicklist_entry(*nick);
- if(userListIndex == -1 || !is_valid_nick(nick))
- return NULL;
- struct UserNode *user = malloc(sizeof(*user));
- if (!user)
- {
- perror("malloc() failed");
- return NULL;
- }
- strcpy(user->nick, nick);
- user->created = time(0);
- user->ident[0] = 0;
- user->host[0] = 0;
- user->realname[0] = 0;
- user->flags = 0;
- user->channel = NULL;
- user->next = userList[userListIndex];
- userList[userListIndex] = user;
- return user;
-}
-
-struct UserNode* addUserMask(const char *mask) {
- char cmask[strlen(mask)+1];
- strcpy(cmask, mask);
- int i, ii = 0;
- struct UserNode *user = NULL;
- for(i = 0; i < strlen(mask)+1; i++) {
- if(cmask[i] == '!') {
- cmask[i] = 0;
- user = addUser(cmask);
- if(user == NULL) return NULL;
- ii = i+1;
- } else if(cmask[i] == '.' && !user) {
- //it's a server
- return NULL;
- } else if(cmask[i] == '@') {
- if(user == NULL) return NULL;
- cmask[i] = 0;
- strcpy(user->ident, &cmask[ii]);
- ii = i+1;
- } else if(cmask[i] == '\0') {
- if(user == NULL) return NULL;
- strcpy(user->host, &cmask[ii]);
- }
- }
- return user;
-}
-
-struct UserNode* createTempUser(const char *mask) {
- //note: it could also be a server we have to create a temponary user for...
- char cmask[strlen(mask)+1];
- strcpy(cmask, mask);
- int i, ii = 0;
- struct UserNode *user = NULL;
- for(i = 0; i < strlen(mask)+1; i++) {
- if(cmask[i] == '!') {
- cmask[i] = 0;
- user = malloc(sizeof(*user));
- if (!user)
- {
- perror("malloc() failed");
- return NULL;
- }
- strcpy(user->nick, cmask);
- user->created = time(0);
- user->ident[0] = 0;
- user->host[0] = 0;
- user->realname[0] = 0;
- user->flags = 0;
- user->channel = NULL;
- ii = i+1;
- } else if(cmask[i] == '.' && !user) {
- //it's a server
- user = malloc(sizeof(*user));
- if (!user)
- {
- perror("malloc() failed");
- return NULL;
- }
- strcpy(user->host, cmask);
- user->created = time(0);
- user->ident[0] = 0;
- user->host[0] = 0;
- user->realname[0] = 0;
- user->flags = USERFLAG_ISSERVER;
- user->channel = NULL;
- return user;
- } else if(cmask[i] == '@') {
- if(user == NULL) return NULL;
- cmask[i] = 0;
- strcpy(user->ident, &cmask[ii]);
- ii = i+1;
- } else if(cmask[i] == '\0') {
- if(user == NULL) {
- //nick only
- user = malloc(sizeof(*user));
- if (!user)
- {
- perror("malloc() failed");
- return NULL;
- }
- strcpy(user->nick, cmask);
- user->created = time(0);
- user->ident[0] = 0;
- user->host[0] = 0;
- user->realname[0] = 0;
- user->flags = 0;
- user->channel = NULL;
- return user;
- }
- strcpy(user->host, &cmask[ii]);
- }
- }
- return user;
-}
-
-int renameUser(struct UserNode* user, const char *new_nick) {
- if(!is_valid_nick(new_nick))
- return 0;
- if(user->nick[0] == *new_nick) {
- strcpy(user->nick, new_nick);
- return 1;
- }
- int userListIndex = get_nicklist_entry(*new_nick);
- delUser(user, 0);
- strcpy(user->nick, new_nick);
- user->next = userList[userListIndex];
- userList[userListIndex] = user;
- return 1;
-}
-
-void delUser(struct UserNode* user, int freeUser) {
- int userListIndex = get_nicklist_entry(user->nick[0]);
- if(userListIndex == -1) return;
- struct UserNode *cuser, *last_user = NULL;
- for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) {
- if(cuser == user) {
- if(last_user)
- last_user->next = user->next;
- else
- userList[userListIndex] = user->next;
- break;
- } else
- last_user = cuser;
- }
- if(user->channel) {
- struct ChanUser *chanUser, *next;
- for(chanUser = user->channel; chanUser; chanUser = next) {
- next = chanUser->next_chan;
- removeChanUserFromLists(chanUser, 1, 0, freeUser);
- }
- }
- if(freeUser)
- free(user);
- else
- user->next = NULL;
-}
-
-void clearTempUsers() {
- int userListIndex = TEMPUSER_LIST_INDEX;
- struct UserNode *cuser, *last_user = NULL, *next;
- time_t now = time(0);
- for(cuser = userList[userListIndex]; cuser; cuser = next) {
- next = cuser->next;
- if(cuser->flags & USERFLAG_FREETMPUSER || now - cuser->created >= 300) {
- if(last_user)
- last_user->next = cuser->next;
- else
- userList[userListIndex] = cuser->next;
- break;
- } else
- last_user = cuser;
- }
-}
+++ /dev/null
-#ifndef _UserNode_h
-#define _UserNode_h
-#include "main.h"
-
-#define USERFLAG_ISBOT 0x0001
-#define USERFLAG_ISAUTHED 0x0002
-#define USERFLAG_ISIRCOP 0x0004
-#define USERFLAG_ISTMPUSER 0x0008
-#define USERFLAG_ISSERVER 0x0010
-#define USERFLAG_FREETMPUSER 0x0020
-#define USERFLAG_LOADED_SETTINGS 0x0040
-#define USERFLAG_REPLY_PRIVMSG 0x0080
-#define USERFLAG_GOD_MODE 0x0100
-
-#define USERFLAG_SCRIPTFLAG1 0x40000000
-#define USERFLAG_SCRIPTFLAG2 0x80000000
-
-struct ChanUser;
-struct language;
-
-struct UserNode {
- char nick[NICKLEN+1];
- char ident[USERLEN+1];
- char host[HOSTLEN+1];
- char realname[REALLEN+1];
- char auth[AUTHLEN+1];
- unsigned int flags;
- time_t created;
- struct ChanUser *channel;
- struct language *language;
-
- struct UserNode *next;
-};
-
-#define isNetworkService(USER) (USER->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))
-
-void init_UserNode();
-void free_UserNode();
-int is_valid_nick(const char *nick);
-struct UserNode* getUserByNick(const char *nick);
-struct UserNode* getUserByMask(const char *mask);
-int countUsersWithHost(char *host);
-char *getAuthFakehost(char *auth);
-struct UserNode* searchUserByNick(const char *nick);
-struct UserNode* getAllUsers(struct UserNode *last);
-int getUserCount();
-struct UserNode* addUser(const char *nick);
-struct UserNode* addUserMask(const char *mask);
-struct UserNode* createTempUser(const char *mask);
-int renameUser(struct UserNode* user, const char *new_nick);
-void delUser(struct UserNode* user, int freeUser);
-void clearTempUsers();
-
-#endif
+++ /dev/null
-
-#include "WHOHandler.h"
-#include "ChanNode.h"
-#include "UserNode.h"
-#include "ChanUser.h"
-#include "ClientSocket.h"
-
-#define WHOQUEUETYPE_ISONQUEUE 0x01
-#define WHOQUEUETYPE_USERLIST 0x02
-#define WHOQUEUETYPE_USERAUTH 0x04
-#define WHOQUEUETYPE_CHECKTYPE 0x07
-#define WHOQUEUETYPE_FOUND 0x08
-
-struct WHOQueueEntry {
- char type;
- struct ClientSocket *client;
- struct ChanNode *chan;
- struct UserNode *user;
- struct WHOQueueEntry *next;
- void *callback;
- void *data;
-};
-
-static struct WHOQueueEntry *first_entry = NULL, *last_entry = NULL;
-
-static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
- struct WHOQueueEntry *entry = malloc(sizeof(*entry));
- if (!entry)
- {
- perror("malloc() failed");
- return NULL;
- }
- entry->next = NULL;
- entry->client = client;
- if(last_entry) {
- last_entry->next = entry;
- last_entry = entry;
- } else {
- last_entry = entry;
- first_entry = entry;
- }
- return entry;
-}
-
-static struct WHOQueueEntry* getNextWHOQueueEntry(struct ClientSocket *client, int freeEntry) {
- if(!first_entry) return NULL;
- struct WHOQueueEntry *entry;
- for(entry = first_entry; entry; entry = entry->next) {
- if(entry->client == client)
- break;
- }
- if(entry == NULL) return NULL;
- if(freeEntry) {
- if(entry == first_entry)
- first_entry = entry->next;
- if(entry == last_entry) {
- struct WHOQueueEntry *last;
- for(last = first_entry; last; last = last->next)
- if(last->next == NULL) break;
- last_entry = last;
- }
- }
- return entry;
-}
-
-void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data) {
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(isUserOnChan(bot->user, chan))
- break;
- }
- if(bot == NULL) return;
- struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
- entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST;
- entry->chan = chan;
- entry->callback = callback;
- entry->data = data;
- //WHO ".$channel->getName().",".$id." d%tuhnaf,".$id
- putsock(bot, "WHO %s,%d %%tuhnaf,%d", chan->name, entry->type, entry->type);
-}
-
-void get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t callback, void *data) {
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(isUserOnChan(bot->user, chan))
- break;
- }
- if(bot == NULL) return;
- struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
- entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST;
- entry->chan = chan;
- entry->callback = callback;
- entry->data = data;
- //WHO ".$channel->getName().",".$id." d%tuhnaf,".$id
- putsock(bot, "WHO %s,%d d%%tuhnaf,%d", chan->name, entry->type, entry->type);
-}
-
-void get_userauth(struct UserNode *user, userauth_callback_t callback, void *data) {
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->flags & SOCKET_FLAG_PREFERRED)
- break;
- }
- if(bot == NULL) bot = getBots(SOCKET_FLAG_READY, NULL);
- struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
- entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERAUTH;
- entry->user = user;
- entry->callback = callback;
- entry->data = data;
- //WHO ".$user->getNick().",".$id." %tuhna,".$id
- putsock(bot, "WHO %s,%d %%tuhna,%d", user->nick, entry->type, entry->type);
-}
-
-void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc) {
- int i;
- if(argc < 2) return;
- int type = atoi(argv[1]);
- if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
- struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 0);
- if(entry == NULL || (entry->type & WHOQUEUETYPE_CHECKTYPE) != (type & WHOQUEUETYPE_CHECKTYPE)) return;
- if(type & WHOQUEUETYPE_USERLIST) {
- if(argc < 7) return;
- //:OGN2.OnlineGamesNet.net 354 skynet 1 pk910 2001:41d0:2:1d3b::babe skynet H@ pk910
- struct ChanNode *chan = entry->chan;
- //add the user toe the channel if he isn't added, yet and update its user data
- //parse flags
- int userflags = 0;
- int chanuserflags = 0;
- for(i = 0; i < strlen(argv[5]); i++) {
- switch (argv[5][i]) {
- case '@':
- chanuserflags |= CHANUSERFLAG_OPPED;
- break;
- case '+':
- chanuserflags |= CHANUSERFLAG_VOICED;
- break;
- case '*':
- userflags |= USERFLAG_ISIRCOP;
- break;
- case '<':
- chanuserflags |= CHANUSERFLAG_INVISIBLE;
- break;
- default:
- break;
- }
- }
-
- struct UserNode *user;
- if(chanuserflags & CHANUSERFLAG_INVISIBLE) {
- user = createTempUser(argv[4]);
- user->flags |= USERFLAG_ISTMPUSER;
- chan->flags |= CHANFLAG_HAVE_INVISIBLES;
- struct ChanUser *chanuser = addInvisibleChanUser(chan, user);
- chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
- } else {
- user = getUserByNick(argv[4]);
- if(user == NULL) {
- user = addUser(argv[4]);
- }
- if(!isUserOnChan(user, chan)) {
- struct ChanUser *chanuser = addChanUser(chan, user);
- chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
- }
- }
- user->flags = (user->flags & ~USERFLAG_ISIRCOP) | userflags;
- if(!*user->ident)
- strcpy(user->ident, argv[2]);
- if(!*user->host)
- strcpy(user->host, argv[3]);
- if(!(user->flags & USERFLAG_ISAUTHED) && strcmp(argv[6], "0")) {
- strcpy(user->auth, argv[6]);
- user->flags |= USERFLAG_ISAUTHED;
- }
- } else if(type & WHOQUEUETYPE_USERAUTH) {
- //:OGN2.OnlineGamesNet.net 354 Skynet 1 pk910 2001:41d0:2:1d3b::babe Skynet pk910
- entry->type |= WHOQUEUETYPE_FOUND;
- if(strcmp(argv[5], "0") && !(entry->user->flags & USERFLAG_ISAUTHED)) {
- strcpy(entry->user->auth, argv[5]);
- entry->user->flags |= USERFLAG_ISAUTHED;
- }
- userauth_callback_t *callback = entry->callback;
- callback(client, entry->user->nick, entry->user, entry->data);
- }
-}
-
-void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc) {
- if(argc < 2) return;
- char *typestr = strstr(argv[1], ",") + 1;
- int type = atoi(typestr);
- if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
- struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 1);
- if(entry == NULL || (entry->type & WHOQUEUETYPE_CHECKTYPE) != (type & WHOQUEUETYPE_CHECKTYPE)) return;
- if(type & WHOQUEUETYPE_USERLIST) {
- //:OGN2.OnlineGamesNet.net 315 skynet #pk910,1 :End of /WHO list.
- entry->chan->flags |= CHANFLAG_RECEIVED_USERLIST;
- userlist_callback_t *callback = entry->callback;
- callback(client, entry->chan, entry->data);
- if(entry->chan->flags & CHANFLAG_HAVE_INVISIBLES) {
- //remove all invisible users again
- struct ChanUser *chanuser, *next;
- for(chanuser = getChannelUsers(entry->chan, NULL); chanuser; chanuser = next) {
- next = getChannelUsers(entry->chan, chanuser);
- if(chanuser->flags & CHANUSERFLAG_INVISIBLE) {
- delChanUser(chanuser, 1);
- }
- }
- }
- } else if(type & WHOQUEUETYPE_USERAUTH) {
- if(!(entry->type & WHOQUEUETYPE_FOUND)) {
- userauth_callback_t *callback = entry->callback;
- callback(client, entry->user->nick, NULL, entry->data);
- }
- }
- free(entry);
-}
-
-void free_whoqueue() {
- struct WHOQueueEntry *entry, *next;
- for(entry = first_entry; entry; entry = next) {
- next = entry->next;
- free(entry);
- }
- first_entry = NULL;
- last_entry = NULL;
-}
+++ /dev/null
-#ifndef _WHOHandler_h
-#define _WHOHandler_h
-
-#include "main.h"
-
-struct ClientSocket;
-struct ChanNode;
-struct UserNode;
-
-#define USERLIST_CALLBACK(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(struct ChanNode *chan), UNUSED_ARG(void *data))
-typedef USERLIST_CALLBACK(userlist_callback_t);
-
-#define USERAUTH_CALLBACK(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(char *user_nick), UNUSED_ARG(struct UserNode *user), UNUSED_ARG(void *data))
-typedef USERAUTH_CALLBACK(userauth_callback_t);
-
-void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc);
-void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc);
-void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data);
-void get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t callback, void *data);
-void get_userauth(struct UserNode *user, userauth_callback_t callback, void *data);
-void free_whoqueue();
-
-#endif
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+
+echo "Generating configure files... may take a while."
+
+autoreconf --install --force && \
+ echo "Preparing was successful if there was no error messages above." && \
+ echo "Now type:" && \
+ echo " ./configure && make" && \
+ echo "Run './configure --help' for more information"
+++ /dev/null
-
-#include "bot_NeonServ.h"
-#include "modcmd.h"
-#include "IRCEvents.h"
-#include "IRCParser.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "BanNode.h"
-#include "ModeNode.h"
-#include "ClientSocket.h"
-#include "mysqlConn.h"
-#include "lang.h"
-#include "HandleInfoHandler.h"
-#include "WHOHandler.h"
-#include "DBHelper.h"
-#include "tools.h"
-#include "timeq.h"
-#include "version.h"
-#include "EventLogger.h"
-#include "cmd_neonserv.h"
-
-#define BOTID 1
-
-static const struct default_language_entry msgtab[] = {
- {"NS_USER_UNKNOWN", "User with nick $b%s$b does not exist."}, /* {ARGS: "TestUser"} */
- {"NS_AUTH_UNKNOWN", "Account $b%s$b has not been registered."}, /* {ARGS: "TestAuth"} */
- {"NS_USER_NEED_AUTH", "%s must first authenticate with $bAuthServ$b."}, /* {ARGS: "TestUser"} */
- {"NS_YOU_NEED_AUTH", "You must first authenticate with $bAuthServ$b."},
- {"NS_INVALID_ACCESS", "$b%d$b is an invalid access level."}, /* {ARGS: 1337} */
- {"NS_ADDUSER_ALREADY_ADDED", "%s is already on the $b%s$b user list (with access %d)."}, /* {ARGS: "TestUser", "#TestChan", 123} */
- {"NS_ADDUSER_DONE", "Added %s to the %s user list with access %d."}, /* {ARGS: "TestUser", "#TestChan", 123} */
- {"NS_NOT_ON_USERLIST", "%s lacks access to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_NOT_ON_USERLIST_YOU", "You lack access to $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_NOT_ON_CHANNEL", "%s isn't currently in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_NOT_ON_CHANNEL_YOU", "You aren't currently in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_DELUSER_DONE", "Deleted %s (with access %d) from the %s user list."}, /* {ARGS: "TestUser", 123, "#TestChan"} */
- {"NS_ACCESS_OUTRANKED", "You cannot give users access greater than or equal to your own."},
- {"NS_USER_OUTRANKED", "$b%s$b outranks you (command has no effect)."}, /* {ARGS: "TestUser"} */
- {"NS_ACCESS_DENIED", "Access denied."},
- {"NS_NO_ACCESS", "You lack sufficient access to use this command."},
- {"NS_USER_PROTECTED", "Sorry, $b%s$b is protected."}, /* {ARGS: "TestUser"} */
- {"NS_SERVICE_IMMUNE", "$b%s$b may not be kicked, killed, banned, or deopped."}, /* {ARGS: "TestUser"} */
- {"NS_TABLE_NONE", " None"},
- {"NS_TABLE_COUNT", "Found $b%d$b matches."}, /* {ARGS: 5} */
- {"NS_BAN_ALREADY_ADDED", "$b%s$b is already banned in %s."}, /* {ARGS: "*!*@moeeep.*", "#TestChan"} */
- {"NS_INVALID_ACCESS_RANGE", "Invalid access range; minimum (%d) must be lower than maximum (%d)."}, /* {ARGS: 450, 400} */
- {"NS_CLVL_DONE", "%s now has access $b%d$b in %s."}, /* {ARGS: "TestUser", 123, "#TestChan"} */
- {"NS_A_LACKS_ACCESS_BUT_GOD_NICK", "%s lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "#TestChan"} */
- {"NS_A_LACKS_ACCESS_BUT_GOD_AUTH", "%s (%s) lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", "#TestChan"} */
- {"NS_A_ACCESS_NICK", "%s has access $b%d$b in %s."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */
- {"NS_A_ACCESS_AUTH", "%s (%s) has access $b%d$b in %s."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */
- {"NS_A_ACCESS_NICK_GOD", "%s has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */
- {"NS_A_ACCESS_AUTH_GOD", "%s (%s) has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */
- {"NS_A_SUSPENDED", "$b%s$b's access to %s has been suspended."}, /* {ARGS: "TestAuth", "#TestChan"} */
- {"NS_A_IS_IRCOP", "%s is an $bIRC operator$b."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_USERS_HEADER", "%s users from level %d to %d:"}, /* {ARGS: "#TestChan", 1, 500} */
- {"NS_USERS_HEADER_MATCH", "%s users from level %d to %d matching %s:"}, /* {ARGS: "#TestChan", 1, 500, "Test*"} */
- {"NS_USERS_HEADER_ACCESS", "Access"},
- {"NS_USERS_HEADER_ACCOUNT", "Accout"},
- {"NS_USERS_HEADER_SEEN", "Last Seen"},
- {"NS_USERS_HEADER_STATE", "Status"},
- {"NS_USERS_COUNT", "There are $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
- {"NS_USERS_COUNT_1", "There is $b%d$b user in %s."}, /* {ARGS: 1, "#TestChan"} */
- {"NS_USERS_COUNT_MATCH", "There are $b%d$b users in %s. ($b%d$b matching your request)"}, /* {ARGS: 20, "#TestChan", 5} */
- {"NS_USERS_COUNT_MATCH_1", "There is $b%d$b user in %s. ($b%d$b matching your request)"}, /* {ARGS: 1, "#TestChan", 1} */
- {"NS_USERS_SEEN_HERE", "Here"},
- {"NS_USERS_SEEN_INVISIBLE", "Here (invisible)"},
- {"NS_USERS_SEEN_NEVER", "Never"},
- {"NS_USERS_STATE_SUSPENDED", "Suspended"},
- {"NS_USERS_STATE_NORMAL", "Normal"},
- {"NS_SUSPEND_ALREADY", "$b%s$b is already suspended." }, /* {ARGS: "TestUser"} */
- {"NS_SUSPEND_NOT", "$b%s$b is not suspended." }, /* {ARGS: "TestUser"} */
- {"NS_SUSPEND_DONE", "$b%s$b's access to $b%s$b has been suspended." }, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_SUSPEND_RESTORED", "$b%s$b's access to $b%s$b has been restored." }, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_DELME_KEY", "To really remove yourself, you must use 'deleteme %s'."}, /* {ARGS: "abc123"} */
- {"NS_DELME_DONE", "Your $b%d$b access has been deleted from $b%s$b."}, /* {ARGS: 123, "#TestChan"} */
- {"NS_MYACCESS_HEADER", "Showing all channel entries for account $b%s$b:"}, /* {ARGS: "TestAuth"} */
- {"NS_MYACCESS_HEADER_MATCH", "Showing all channel entries for account $b%s$b matching %s:"}, /* {ARGS: "TestAuth", "#Test*"} */
- {"NS_MYACCESS_HEADER_NAME", "Name"},
- {"NS_MYACCESS_HEADER_ACCESS", "Access"},
- {"NS_MYACCESS_HEADER_FLAGS", "Flags"},
- {"NS_MYACCESS_HEADER_INFO", "Info"},
- {"NS_MYACCESS_COUNT", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s)."}, /* {ARGS: "TestUser", 15, 5} */
- {"NS_MYACCESS_COUNT_MATCH", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s) ($b%d$b channels matching your request)."}, /* {ARGS: "TestUser", 15, 5, 7} */
- {"NS_UP_ALREADY_OP", "You are already opped in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_UP_ALREADY_VOICE", "You are already voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_DOWN_ALREADY", "You are not opped or voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_MDELUSER_DONE", "Deleted $b%d$b account(s) matching $b%s$b with access from $b%d$b to $b%d$b from the %s user list."}, /* {ARGS: 10, "Test*", 1, 200, "#TestChan"} */
- {"NS_TRIM_DURATION_TOO_SHORT", "You must include a minimum inactivity duration of at least %d seconds to trim."},
- {"NS_TRIM_DONE", "Trimmed $b%d users$b with access from %d to %d from the %s user list who were inactive for at least %s."}, /* {ARGS: 10, 1, 100, "#TestChan", "10 days"} */
- {"NS_GIVEOWNER_SELF", "You cannot give ownership to your own account."},
- {"NS_GIVEOWNER_TIMEOUT", "You must wait %s before you can give ownership of $b%s$b to someone else."}, /* {ARGS: "5 hours", "#TestChan"} */
- {"NS_GIVEOWNER_CONFIRM", "To really give ownership to $b%1$s$b, you must use 'giveownership *%1$s %2$s'."}, /* {ARGS: "TestUser", "abc123"} */
- {"NS_GIVEOWNER_DONE", "Ownership of $b%s$b has been transferred to account $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */
- {"NS_OP_FAIL", "$b%s$b could not op some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_OP_DONE", "Opped users in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_VOICE_FAIL", "$b%s$b could not voice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_VOICE_DONE", "Voiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_DEOP_FAIL", "$b%s$b could not deop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_DEOP_DONE", "Deopped users in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_DEVOICE_FAIL", "$b%s$b could not devoice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_DEVOICE_DONE", "Devoiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_OPALL_SECURITY", "$bWARNING$b: Opping all users on a channel is very insecure! If you still want do op all users on %s use: '$bopall FORCE$b [nick mask]'"},
- {"NS_OPALL_DONE", "Opped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
- {"NS_VOICEALL_DONE", "Voiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
- {"NS_DEOPALL_DONE", "Deopped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
- {"NS_DEVOICEALL_DONE", "Devoiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
- {"NS_KICK_DONE", "Kicked $b%d$b users from %s"}, /* {ARGS: 20, "#TestChan"} */
- {"NS_KICK_FAIL", "$b%s$b could not kick some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_KICKBAN_DONE", "KickBanned $b%d$b users from %s"}, /* {ARGS: 10, "#TestChan"} */
- {"NS_KICKBAN_FAIL", "$b%s$b could not kickban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_BAN_DONE", "$b%d$b masks added to the %s ban list. (matching %d users)"}, /* {ARGS: 5, "#TestChan", 15} */
- {"NS_BAN_FAIL", "$b%s$b could not ban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_LAME_MASK", "$b%s$b is a little too general. Try making it more specific."}, /* {ARGS: "*!*@*"} */
- {"NS_SET_HEADER", "Channel Settings for %s:"}, /* {ARGS: "#TestChan"} */
- {"NS_SET_ON", "on"},
- {"NS_SET_OFF", "off"},
- {"NS_SET_UNKNOWN_SETTING", "$b%s$b is an unknown channel setting."}, /* {ARGS: "TestSetting"} */
- {"NS_SET_CANNOT_SET", "That setting is above your current level, so you cannot change it."},
- {"NS_SET_BADLEVEL", "You cannot change any setting to above your level."},
- {"NS_SET_INVALID_OPTION", "$b%d$b is not a valid choice. Choose one:"}, /* {ARGS: 5} */
- {"NS_SET_INVALID_BOOLEAN", "$b%s$b is an invalid binary value."}, /* {ARGS: 2} */
- {"NS_SET_DEFAULTS_OWNER", "You must have access 500 in %s to reset it to the default options."}, /* {ARGS: "#TestChan"} */
- {"NS_SET_DEFAULTS_CODE", "To reset %s's settings to the defaults, you must use 'set defaults %s'."}, /* {ARGS: "#TestChan", "abc123"} */
- {"NS_SET_DEFAULTS_DONE", "All settings for %s have been reset to default values."}, /* {ARGS: "#TestChan"} */
- {"NS_SET_TRIGGER_OWNER", "You must have access 500 in %s to change the channel trigger."}, /* {ARGS: "#TestChan"} */
- {"NS_SET_HELP_USERINFO","(access to set the userinfo)"},
- {"NS_SET_HELP_WIPEINFO","(access to clear the userinfo of other users)"},
- {"NS_SET_HELP_INVITEME","(access to get invited by the bot)"},
- {"NS_SET_HELP_ENFVOICE","(access to give voice to other users)"},
- {"NS_SET_HELP_ENFOPS","(access to give op to their users)"},
- {"NS_SET_HELP_GIVEOPS","(access to get op by the bot)"},
- {"NS_SET_HELP_GIVEVOICE","(access to get voice by the bot)"},
- {"NS_SET_HELP_KICK","(access to kick other users from the channel)"},
- {"NS_SET_HELP_BAN","(access to ban other users from the channel)"},
- {"NS_SET_HELP_STATICBAN","(access to add static bans to the channel banlist e.g. +addban)"},
- {"NS_SET_HELP_PUBCMD","(access to do public commands in the channel e.g. +users)"},
- {"NS_SET_HELP_ENFMODES","(access to override the modelock)"},
- {"NS_SET_HELP_ENFTOPIC","(access to override the topicmask)"},
- {"NS_SET_HELP_TOPICSNARF","(access to set the default topic by changing the topic with /TOPIC)"},
- {"NS_SET_HELP_CHANGETOPIC","(access to change the topic)"},
- {"NS_SET_HELP_SETTERS","(access to change this settings)"},
- {"NS_SET_HELP_ADDUSER","(access to add an user to the userlist)"},
- {"NS_SET_HELP_DELUSER","(access to delete an user from the userlist)"},
- {"NS_SET_HELP_CLVL","(access to change the access of an user in the userlist)"},
- {"NS_SET_HELP_RESYNC","(access to synchronize the channelrights (@,+) with the userlist)"},
- {"NS_SET_HELP_SUSPEND","(access to suspend an user on the userlist)"},
- {"NS_SET_OPTION_CTCPREACTION_0","Kick on disallowed CTCPs"},
- {"NS_SET_OPTION_CTCPREACTION_1","Kickban on disallowed CTCPs"},
- {"NS_SET_OPTION_CTCPREACTION_2","Short timed ban on disallowed CTCPs"},
- {"NS_SET_OPTION_CTCPREACTION_3","Long timed ban on disallowed CTCPs"},
- {"NS_SET_OPTION_NOTICEREACTION_0","Kick on disallowed NOTICEs"},
- {"NS_SET_OPTION_NOTICEREACTION_1","Kickban on disallowed NOTICEs"},
- {"NS_SET_OPTION_NOTICEREACTION_2","Short timed ban on disallowed NOTICEs"},
- {"NS_SET_OPTION_NOTICEREACTION_3","Long timed ban on disallowed NOTICEs"},
- {"NS_SET_OPTION_PROTECT_0","All users will be protected from users with equal or lower access."},
- {"NS_SET_OPTION_PROTECT_1","All users with access will be protected from users with equal or lower access."},
- {"NS_SET_OPTION_PROTECT_2","All users with access will be protected from user with lower access."},
- {"NS_SET_OPTION_PROTECT_3","Nobody will be protected."},
- {"NS_SET_OPTION_TOYS_0","Funcommands can't be used."},
- {"NS_SET_OPTION_TOYS_1","Funcommands are possible but the reply will be sent as a notice."},
- {"NS_SET_OPTION_TOYS_2","Funcommands are possible and the reply will be sent to the channel."},
- {"NS_SET_OPTION_DYNLIMIT_0","off"},
- {"NS_SET_OPTION_NODELETE_0","off (only bot masters)"},
- {"NS_SET_OPTION_NODELETE_1","on (only bot masters)"},
- {"NS_WIPEINFO_DONE", "Removed $b%s$b's infoline in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_TRACE_HEADER", "The following users were found:"},
- {"NS_ADDBAN_DONE", "$b%s$b permantly added to the %s ban list. (matching %d users)"}, /* {ARGS: "*!*@Test.*", "#TestChan", 4} */
- {"NS_BANS_HEADER_MASK", "Mask"},
- {"NS_BANS_HEADER_SETBY", "Set By"},
- {"NS_BANS_HEADER_TRIGGERED", "Triggered"},
- {"NS_BANS_HEADER_EXPIRES", "Expires"},
- {"NS_BANS_HEADER_REASON", "Reason"},
- {"NS_DELBAN_BANNED_BY", "%s is banned by %s."}, /* {ARGS: "*!*@bla*", "*!*@b*"} */
- {"NS_DELBAN_FAIL", "Sorry, no ban found for $b%s$b."}, /* {ARGS: "*!*@bla*"} */
- {"NS_DELBAN_DONE", "Removed $b%s$b from the %s ban list."}, /* {ARGS: "*!*@bla.*", "#TestChan"} */
- {"NS_NETINFO_HEADER", "$bNetwork information$b"},
- {"NS_NETINFO_BOTS", "Bots:"},
- {"NS_NETINFO_UPTIME", "Uptime:"},
- {"NS_NETINFO_TRAFFIC", "Traffic:"},
- {"NS_NETINFO_CACHE", "Cache:"},
- {"NS_NETINFO_DATABASE", "Database:"},
- {"NS_NETINFO_CHANNEL", " Channel:"},
- {"NS_NETINFO_CHANNEL_BAN", " Bans:"},
- {"NS_NETINFO_USER", " User:"},
- {"NS_NETINFO_CHANUSER", " Channel-User:"},
- {"NS_NETINFO_OTHER", " Other:"},
- {"NS_NETINFO_VERSION", "Version:"},
- {"NS_NETINFO_CODE", "Code:"},
- {"NS_NETINFO_CODE_VALUE", "%s lines c code (view it at http://git.pk910.de/?p=NeonServV5.git;a=summary)"}, /* {ARGS: 20} */
- {"NS_NETINFO_COMPILER", "Compiler:"},
- {"NS_NETINFO_COMPILER_VALUE", "%s (%s)"}, /* {ARGS: "GCC 4.4.5", "Sun Sep 18 2011 at 05:21:33 CEST"} */
- {"NS_EXTTOPIC_INVALID_ID", "ADVANCEDTOPIC is enabled and $b%s$b is an invalid TOPIC ID. Valid topic id's are: 1-9"}, /* {ARGS: 10} */
- {"NS_EXTTOPIC_TOPICID", "Topic %d: %s"}, /* {ARGS: 5, "topic"} */
- {"NS_TOPIC_DONE", "Topic is now '%s'."}, /* {ARGS: "i like you :D"} */
- {"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!"}, /* {ARGS: "CowBot"} */
- {"NS_CHANSERVSYNC_KEY", "If you really want to synchronize the %s userlist with %s use: chanservsync %s %s"}, /* {ARGS: "#TestChan", "CowBot", "CowBot", "abc123"} */
- {"NS_CHANSERVSYNC_INUSE", "$bchanservsync$b is already in use by someone else. Please try again in a few seconds..."},
- {"NS_CHANSERVSYNC_SYNCHRONIZING", "Synchronizing userlist in %s with $b%s$b..."}, /* {ARGS: "#TestChan", "CowBot"} */
- {"NS_CHANSERVSYNC_SYNCHRONIZED", "Synchronized user $b%s$b: access $b%d$b"}, /* {ARGS: "TestUser", 123} */
- {"NS_REGISTER_ALREADY", "%s is already registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */
- {"NS_INVALID_CHANNEL_NAME", "%s is not a valid channel name."}, /* {ARGS: "#invalid"} */
- {"NS_REGISTER_FULL", "the bot can not join more channels."},
- {"NS_REGISTER_DISCONNECTED", "%s has been registered with a Bot, that is currently NOT connected. The Bot should join the channel, when it reconnects to the IRC-Network."}, /* {ARGS: "#TestChan"} */
- {"NS_REGISTER_DONE", "$b%s$b is now registered to $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */
- {"NS_UNREGISTER_NOT_REGISTERED", "$b%s$b is not registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */
- {"NS_UNREGISTER_DONE", "$b%s$b unregistered."}, /* {ARGS: "#TestChan"} */
- {"NS_RECOVER_DONE", "$b%s$b has been recovered."}, /* {ARGS: "#TestChan"} */
- {"NS_RESYNC_DONE", "Synchronized users in $b%s$b with the userlist."}, /* {ARGS: "#TestChan"} */
- {"NS_TIMEBAN_DURATION_TOO_SHORT", "You must specify a ban duration of at least %d seconds."}, /* {ARGS: 30} */
- {"NS_TIMEBAN_DONE", "Banned $b%s$b from %s for %s. (matching %d users)"}, /* {ARGS: "*!*@bla*", "#TestChan", "2 hours", 5} */
- {"NS_MODE_INVALID", "$b%c$b is an invalid set of channel modes."}, /* {ARGS: "+xyz"} */
- {"NS_MODE_LOCKED", "Modes conflicting with $b%s$b are not allowed in %s."}, /* {ARGS: "+xyz", "#TestChan"} */
- {"NS_MODE_DONE", "Channel modes are now $b%s$b."}, /* {ARGS: "+xyz"} */
- {"NS_MODE_ENFOPS", "You may not op or deop users on $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_MODE_ENFVOICE", "You may not voice or devoice users on $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_MODE_CANBAN", "You may not ban or unban users on $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_GOD_ON", "Security override has been enabled."},
- {"NS_GOD_OFF", "Security override has been disabled."},
- {"NS_PEEK_HEADER", "$b%s$b Status:"}, /* {ARGS: "#TestChan"} */
- {"NS_PEEK_TOPIC", "Topic: %s"}, /* {ARGS: "TOPIC"} */
- {"NS_PEEK_MODES", "Modes: %s"}, /* {ARGS: "+xyz"} */
- {"NS_PEEK_USERS", "Total Users: %d (%d ops, %d voices, %d regulars, %d invisible)"}, /* {ARGS: 20, 4, 6, 8, 2} */
- {"NS_PEEK_OPS", "Ops:"},
- {"NS_USET_GLOBAL", "$b--- Global ---$b"},
- {"NS_USET_CHANNEL", "$b--- User options (channel) ---$b"},
- {"NS_USET_NO_ACCESS", "no access"},
- {"NS_USET_UNKNOWN_SETTING", "$b%s$b is an unknown uset setting."}, /* {ARGS: "TestSetting"} */
- {"NS_RELOADLANG_UNKNOWN", "$b%s$b is an unknown language tag."}, /* {ARGS: "de"} */
- {"NS_RELOADLANG_DONE", "$b%s$b (%s) reloaded."}, /* {ARGS: "Deutsch", "de"} */
- {"NS_UNBAN_DONE", "$b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */
- {"NS_UNBAN_FAIL", "$b%s$b could not unban some of the masks you provided."}, /* {ARGS: "NeonServ"} */
- {"NS_UNBANALL_DONE", "all $b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */
- {"NS_UNBANALL_FAIL", "$b%s$b could not find any bans in %s."}, /* {ARGS: "NeonServ", "#TestChan"} */
- {"NS_UNBANME_DONE", "removed $b%d$b masks from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */
- {"NS_UNBANME_FAIL", "$b%s$b could not find any bans matching %s."}, /* {ARGS: "NeonServ", "TestUser!TestIdent@TestUser.user.WebGamesNet"} */
- {"NS_INVITE_RESTRICTION", "%s doesn't want to be invited to %s."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_INVITE_TIMEOUT", "%s has already been invited to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_INVITE_ON_CHAN", "%s is already in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_INVITE_DONE_USER", "You have been invited to join $b%s$b by %s. (Do $b/msg %s %1$s uset noinvite 1$b if you don't want to be invited to %1$s anymore.)"}, /* {ARGS: "#TestChan", "TestUser", "NeonServ"} */
- {"NS_INVITE_DONE", "Invited $b%s$b to join %s."}, /* {ARGS: "TestUser", "#TestChan"} */
- {"NS_INVITEME_ON_CHAN", "You are already in $b%s$b."}, /* {ARGS: "#TestChan"} */
- {"NS_INVITEME_DONE", "You have been invited to join %s."}, /* {ARGS: "#TestChan"} */
- {"NS_HELP_TOPIC", "No help on that topic."},
- {"NS_CSUSPEND_ALREADY", "$b%s$b is already suspended."}, /* {ARGS: "#TestChan"} */
- {"NS_CSUSPEND_DONE", "Channel $b%s$b has been temporarily suspended."}, /* {ARGS: "#TestChan"} */
- {"NS_CUNSUSPEND_NOT", "$b%s$b is not suspended."}, /* {ARGS: "#TestChan"} */
- {"NS_CUNSUSPEND_DONE", "Channel $b%s$b has been restored."}, /* {ARGS: "#TestChan"} */
- {"NS_MOVE_SUSPENDED", "Moving cannot be performed if the source channel is suspended."},
- {"NS_MOVE_SELF", "Moving cannot be performed if the source and target channels are the same."},
- {"NS_MOVE_DONE", "Channel $b%s$b has been moved to $b%s$b."}, /* {ARGS: "#TestChan", "#NewTestChan"} */
- {"NS_BIND_ALREADY", "$b%s$b is already bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */
- {"NS_BIND_UNKNOWN", "$b%s$b is an undefined function."}, /* {ARGS: "TestFunction"} */
- {"NS_BIND_DONE", "New command $b%s$b bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */
- {"NS_UNBIND_NOT_FOUND", "There is no command called $b%s$b bound."}, /* {ARGS: "TestCommand"} */
- {"NS_UNBIND_DONE", "Unbound command $b%s$b."}, /* {ARGS: "TestCommand"} */
- {"NS_EVENTS_HEADER", "The following channel events were found:"},
- {"NS_OPLOG_HEADER", "The following oper events were found:"},
- {"NS_SEARCH_HEADER", "The following channels were found:"},
- {"NS_COMMAND_BINDING", "$b%s$b is a binding of %s %s"}, /* {ARGS: "TestCommand", "TestFunction", "TestParameters"} */
- {"NS_COMMAND_ACCESS", "You need at least %d channel access and %d oper access to execute this command."}, /* {ARGS: 500, 100} */
- {"NS_TOPIC_ACCESS", "You lack sufficient access in %s to change the topic."}, /* {ARGS: "#TestChan"} */
- {"NS_BOTWAR_DETECTED", "$b$k4BOTWAR DETECTED!$k Please check the channel configuration!$b"},
- {"NS_BOTWAR_REPORTED", "A supporter has been informed to help you preventing botwars in the future."},
- {"NS_BOTWAR_ALERT", "$b$k4BOTWAR ALERT:$k$b Botwar in $b%s$b detected. (opponent: $b%s$b) Please join and help them preventing Botwars."}, /* {ARGS: "#TestChan", "OtherBot"} */
- {"NS_INVITE_FAIL", "$b%s$b is not registered with %s or suspended."}, /* {ARGS: "#TestChan", "NeonServ"} */
- {"NS_SETACCESS_DONE", "$b%s$b has now %d global access."},
- {NULL, NULL}
-};
-
-/* TODO:
-trim bans
-cmd_neonserv_open.c
-cmd_neonserv_info.c
-parse, check and set modelock
-cmd_neonserv_modcmd.c
-cmd_neonserv_allowregister.c
-cmd_neonserv_noregister.c
-cmd_neonserv_expire.c
-cmd_neonserv_unvisited.c
-cmd_neonserv_merge.c
-cmd_neonserv_dnrsearch.c
-cmd_neonserv_rename.c
-cmd_neonserv_iplocate.c
-cmd_neonserv_calc.c
-*/
-//EVENTS
-#include "event_neonserv_join.c"
-#include "event_neonserv_part.c"
-#include "event_neonserv_quit.c"
-//#include "event_neonserv_kick.c"
-//#include "event_neonserv_mode.c"
-#include "event_neonserv_ctcp.c"
-#include "event_neonserv_notice.c"
-#include "event_neonserv_invite.c"
-#include "event_neonserv_topic.c"
-
-struct ClientSocket *getBotForChannel(struct ChanNode *chan) {
- struct ClientSocket *bot, *use_bot = NULL, *second_bot = NULL, *third_bot = NULL;
- struct ChanUser *chanuser;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->botid != BOTID) continue;
- if((chanuser = getChanUser(bot->user, chan)) != NULL) {
- if((chanuser->flags & CHANUSERFLAG_OPPED)) {
- use_bot = bot;
- if(bot->flags & SOCKET_FLAG_PREFERRED) break;
- } else if(bot->flags & SOCKET_FLAG_PREFERRED)
- second_bot = bot;
- else
- third_bot = bot;
- }
- }
- if(!use_bot) use_bot = second_bot;
- if(!use_bot) use_bot = third_bot;
- return use_bot;
-}
-
-static void neonserv_bot_ready(struct ClientSocket *client) {
- MYSQL_RES *res;
- MYSQL_ROW row;
-
- printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- putsock(client, "MODE %s +%s", client->user->nick, row[0]);
- }
-
- printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid);
- res = mysql_use();
-
- while ((row = mysql_fetch_row(res)) != NULL) {
- putsock(client, "JOIN %s %s", row[0], row[1]);
- }
-}
-
-static void neonserv_trigger_callback(struct ChanNode *chan, char *trigger) {
- strcpy(trigger, "+");
-}
-
-static void start_bots() {
- struct UserNode *user;
- struct ClientSocket *client;
- MYSQL_RES *res, *res2;
- MYSQL_ROW row;
-
- printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID);
- res = mysql_use();
-
- while ((row = mysql_fetch_row(res)) != NULL) {
-
- user = addUser(row[0]);
- strcpy(user->ident, row[1]);
- strcpy(user->realname, row[2]);
- user->flags |= USERFLAG_ISBOT;
- client = create_socket(row[3], atoi(row[4]), row[5], user);
- client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0);
- client->botid = BOTID;
- client->clientid = atoi(row[7]);
- connect_socket(client);
- printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botclass` = '%d'", client->botid);
- res2 = mysql_use();
- while ((row = mysql_fetch_row(res2)) != NULL) {
- if(bind_cmd_to_command(BOTID, row[0], row[1])) {
- if(row[2] && strcmp(row[2], "")) {
- bind_set_parameters(BOTID, row[0], row[2]);
- }
- if(row[3]) {
- bind_set_global_access(BOTID, row[0], atoi(row[3]));
- }
- if(row[4]) {
- bind_set_channel_access(BOTID, row[0], row[4]);
- }
- }
- }
- }
-
- //load all timed bans
- printf_mysql_query("SELECT `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_timeout` > 0");
- res = mysql_use();
- char nameBuf[20];
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(atol(row[1]) - time(0) > 0) {
- sprintf(nameBuf, "ban_%s", row[0]);
- timeq_add_name(nameBuf, atol(row[1]) - time(0), channel_ban_timeout, strdup(row[0]));
- } else {
- //timed out
- printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[0]);
- }
- }
-}
-
-TIMEQ_CALLBACK(channel_ban_timeout) {
- char *str_banid = data;
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `ban_mask`, `channel_name` FROM `bans` LEFT JOIN `channels` ON `ban_channel` = `channel_id` WHERE `ban_id` = '%s'", str_banid);
- res = mysql_use();
- struct ChanNode *chan;
- if((row = mysql_fetch_row(res)) != NULL && (chan = getChanByName(row[1])) != NULL) {
- struct ClientSocket *use_bot = getBotForChannel(chan);
- if(use_bot) {
- putsock(use_bot, "MODE %s -b %s", chan->name, row[0]);
- }
- printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", str_banid);
- }
- free(str_banid);
-}
-
-void init_NeonServ() {
-
- #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(BOTID, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS)
- // NAME FUNCTION PARAMS PRIVS FLAGS
- USER_COMMAND("adduser", neonserv_cmd_adduser, 2, "#channel_canadd", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("deluser", neonserv_cmd_deluser, 1, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("clvl", neonserv_cmd_clvl, 2, "#channel_canclvl", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("access", neonserv_cmd_access, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG);
- USER_COMMAND("users", neonserv_cmd_users, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN);
- USER_COMMAND("suspend", neonserv_cmd_suspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("unsuspend", neonserv_cmd_unsuspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("delme", neonserv_cmd_delme, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("myaccess", neonserv_cmd_myaccess, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
- USER_COMMAND("up", neonserv_cmd_up, 0, "#channel_getop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("down", neonserv_cmd_down, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG);
- USER_COMMAND("upall", neonserv_cmd_upall, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("downall", neonserv_cmd_downall, 0, NULL, CMDFLAG_LOG);
- USER_COMMAND("mdeluser", neonserv_cmd_mdeluser, 2, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("trim", neonserv_cmd_trim, 2, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("giveowner", neonserv_cmd_giveowner, 1, "500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("op", neonserv_cmd_op, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("deop", neonserv_cmd_deop, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("voice", neonserv_cmd_voice, 1, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("devoice", neonserv_cmd_devoice, 1, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("opall", neonserv_cmd_opall, 0, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("deopall", neonserv_cmd_deopall, 0, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("voiceall", neonserv_cmd_voiceall, 0, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("devoiceall", neonserv_cmd_devoiceall,0, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("set", neonserv_cmd_set, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("kick", neonserv_cmd_kick, 1, "#channel_cankick", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("kickban", neonserv_cmd_kickban, 1, "#channel_cankick,#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("ban", neonserv_cmd_ban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("wipeinfo", neonserv_cmd_wipeinfo, 1, "#channel_wipeinfo", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("addban", neonserv_cmd_addban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("bans", neonserv_cmd_bans, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
- USER_COMMAND("delban", neonserv_cmd_delban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("netinfo", neonserv_cmd_netinfo, 0, NULL, 0);
- USER_COMMAND("topic", neonserv_cmd_topic, 0, "#channel_changetopic", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("chanservsync", neonserv_cmd_chanservsync, 0,"500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("resync", neonserv_cmd_resync, 0, "#channel_canresync", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("addtimeban", neonserv_cmd_addtimeban,2, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("mode", neonserv_cmd_mode, 1, "#channel_getop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("version", neonserv_cmd_version, 0, NULL, 0);
- USER_COMMAND("peek", neonserv_cmd_peek, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN);
- USER_COMMAND("uset", neonserv_cmd_uset, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
- USER_COMMAND("unban", neonserv_cmd_unban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("unbanall", neonserv_cmd_unbanall, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("unbanme", neonserv_cmd_unbanme, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("invite", neonserv_cmd_invite, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("inviteme", neonserv_cmd_inviteme, 0, "#channel_getinvite", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
- USER_COMMAND("help", neonserv_cmd_help, 0, NULL, 0);
- USER_COMMAND("events", neonserv_cmd_events, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
- USER_COMMAND("command", neonserv_cmd_command, 1, NULL, 0);
- #undef USER_COMMAND
-
- #define OPER_COMMAND(NAME,FUNCTION,PARAMCOUNT,GACCESS,FLAGS) register_command(BOTID, NAME, FUNCTION, PARAMCOUNT, NULL, GACCESS, FLAGS)
- // NAME FUNCTION PARAMS ACCS FLAGS
- OPER_COMMAND("trace", neonserv_cmd_trace, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
- OPER_COMMAND("register", neonserv_cmd_register, 2, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("unregister", neonserv_cmd_unregister,1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("recover", neonserv_cmd_recover, 1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("say", neonserv_cmd_say, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("emote", neonserv_cmd_emote, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("notice", neonserv_cmd_notice, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("raw", neonserv_cmd_raw, 1, 800, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
- OPER_COMMAND("god", neonserv_cmd_god, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
- OPER_COMMAND("reloadlang", neonserv_cmd_reloadlang,1, 500, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
- OPER_COMMAND("csuspend", neonserv_cmd_csuspend, 1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("cunsuspend", neonserv_cmd_cunsuspend,1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("move", neonserv_cmd_move, 2, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
- OPER_COMMAND("bind", neonserv_cmd_bind, 2, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
- OPER_COMMAND("unbind", neonserv_cmd_unbind, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
- OPER_COMMAND("oplog", neonserv_cmd_oplog, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
- OPER_COMMAND("search", neonserv_cmd_search, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
- OPER_COMMAND("setaccess", neonserv_cmd_setaccess, 2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
- #undef OPER_COMMAND
-
- start_bots();
-
- //register events
- bind_bot_ready(neonserv_bot_ready);
- bind_join(neonserv_event_join);
- bind_part(neonserv_event_part);
- bind_quit(neonserv_event_quit);
- bind_chanctcp(neonserv_event_chanctcp);
- bind_privctcp(neonserv_event_privctcp);
- bind_channotice(neonserv_event_channotice);
- bind_topic(neonserv_event_topic);
- bind_invite(neonserv_event_invite);
-
- set_trigger_callback(BOTID, neonserv_trigger_callback);
-
- register_default_language_table(msgtab);
-}
-
-void loop_NeonServ() {
-
-}
-
-void free_NeonServ() {
-
-}
-
-#undef BOTID
+++ /dev/null
-#ifndef _bot_NeonServ_h
-#define _bot_NeonServ_h
-
-#include "main.h"
-#include "timeq.h"
-
-struct ChanNode;
-
-void init_NeonServ();
-void loop_NeonServ();
-void free_NeonServ();
-
-TIMEQ_CALLBACK(channel_ban_timeout);
-struct ClientSocket *getBotForChannel(struct ChanNode *chan);
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "bots.h"
-
-#include "bot_NeonServ.h"
-
-void init_bots() {
- init_NeonServ();
-}
-
-void loop_bots() {
- loop_NeonServ();
-}
-
-void free_bots() {
- free_NeonServ();
-}
+++ /dev/null
-#ifndef _bots_h
-#define _bots_h
-
-#include "main.h"
-
-void init_bots();
-void loop_bots();
-void free_bots();
-
-#endif
\ No newline at end of file
+++ /dev/null
-#ifndef _cmd_neonserv_h
-#define _cmd_neonserv_h
-#include "main.h"
-#include "modcmd.h"
-#include "IRCParser.h"
-#include "IRCEvents.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "ModeNode.h"
-#include "BanNode.h"
-#include "ClientSocket.h"
-#include "mysqlConn.h"
-#include "lang.h"
-#include "HandleInfoHandler.h"
-#include "WHOHandler.h"
-#include "DBHelper.h"
-#include "tools.h"
-#include "timeq.h"
-#include "version.h"
-#include "EventLogger.h"
-#include "bot_NeonServ.h"
-
-CMD_BIND(neonserv_cmd_access);
-CMD_BIND(neonserv_cmd_addban);
-CMD_BIND(neonserv_cmd_addtimeban);
-CMD_BIND(neonserv_cmd_adduser);
-CMD_BIND(neonserv_cmd_ban);
-CMD_BIND(neonserv_cmd_bans);
-CMD_BIND(neonserv_cmd_bind);
-CMD_BIND(neonserv_cmd_chanservsync);
-CMD_BIND(neonserv_cmd_clvl);
-CMD_BIND(neonserv_cmd_command);
-CMD_BIND(neonserv_cmd_csuspend);
-CMD_BIND(neonserv_cmd_cunsuspend);
-CMD_BIND(neonserv_cmd_delban);
-CMD_BIND(neonserv_cmd_delme);
-CMD_BIND(neonserv_cmd_deluser);
-CMD_BIND(neonserv_cmd_deop);
-CMD_BIND(neonserv_cmd_deopall);
-CMD_BIND(neonserv_cmd_devoice);
-CMD_BIND(neonserv_cmd_devoiceall);
-CMD_BIND(neonserv_cmd_down);
-CMD_BIND(neonserv_cmd_downall);
-CMD_BIND(neonserv_cmd_emote);
-CMD_BIND(neonserv_cmd_events);
-CMD_BIND(neonserv_cmd_giveowner);
-CMD_BIND(neonserv_cmd_god);
-CMD_BIND(neonserv_cmd_help);
-CMD_BIND(neonserv_cmd_invite);
-CMD_BIND(neonserv_cmd_inviteme);
-CMD_BIND(neonserv_cmd_kick);
-CMD_BIND(neonserv_cmd_kickban);
-CMD_BIND(neonserv_cmd_mdeluser);
-CMD_BIND(neonserv_cmd_mode);
-CMD_BIND(neonserv_cmd_move);
-CMD_BIND(neonserv_cmd_myaccess);
-CMD_BIND(neonserv_cmd_netinfo);
-CMD_BIND(neonserv_cmd_notice);
-CMD_BIND(neonserv_cmd_op);
-CMD_BIND(neonserv_cmd_opall);
-CMD_BIND(neonserv_cmd_oplog);
-CMD_BIND(neonserv_cmd_peek);
-CMD_BIND(neonserv_cmd_raw);
-CMD_BIND(neonserv_cmd_recover);
-CMD_BIND(neonserv_cmd_register);
-CMD_BIND(neonserv_cmd_reloadlang);
-CMD_BIND(neonserv_cmd_resync);
-CMD_BIND(neonserv_cmd_say);
-CMD_BIND(neonserv_cmd_search);
-CMD_BIND(neonserv_cmd_set);
-CMD_BIND(neonserv_cmd_setaccess);
-CMD_BIND(neonserv_cmd_suspend);
-CMD_BIND(neonserv_cmd_topic);
-CMD_BIND(neonserv_cmd_trace);
-CMD_BIND(neonserv_cmd_trim);
-CMD_BIND(neonserv_cmd_unban);
-CMD_BIND(neonserv_cmd_unbanall);
-CMD_BIND(neonserv_cmd_unbanme);
-CMD_BIND(neonserv_cmd_unbind);
-CMD_BIND(neonserv_cmd_unregister);
-CMD_BIND(neonserv_cmd_unsuspend);
-CMD_BIND(neonserv_cmd_up);
-CMD_BIND(neonserv_cmd_upall);
-CMD_BIND(neonserv_cmd_users);
-CMD_BIND(neonserv_cmd_uset);
-CMD_BIND(neonserv_cmd_version);
-CMD_BIND(neonserv_cmd_voice);
-CMD_BIND(neonserv_cmd_voiceall);
-CMD_BIND(neonserv_cmd_wipeinfo);
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup);
-static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target);
-
-struct neonserv_cmd_access_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- char *nick;
-};
-
-CMD_BIND(neonserv_cmd_access) {
- if(argc == 0) {
- if(!(user->flags & USERFLAG_ISAUTHED)) {
- struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->nick = strdup(user->nick);
- get_userauth(user, neonserv_cmd_access_nick_lookup, cache);
- } else
- neonserv_cmd_access_async1(client, getTextBot(), user, chan, user->nick, user->auth, user);
- }
- else if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- neonserv_cmd_access_async1(client, getTextBot(), user, chan, NULL, argv[0], NULL);
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_access_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, cuser);
- } else {
- struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_access_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup) {
- struct neonserv_cmd_access_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- if(!strcmp(cache->nick, cache->user->nick))
- reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH");
- else
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_access_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, user);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW user_row, chanuser_row;
- int userid;
- printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((user_row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(user_row[0]);
- //check if the user is already added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((chanuser_row = mysql_fetch_row(res)) != NULL) {
- //access output
- if(nick)
- reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_AUTH" : "NS_A_ACCESS_AUTH_GOD"), nick, auth, atoi(chanuser_row[0]), chan->name);
- else
- reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_NICK" : "NS_A_ACCESS_NICK_GOD"), auth, atoi(chanuser_row[0]), chan->name);
- int cflags = atoi(chanuser_row[1]);
- if(cflags & DB_CHANUSER_SUSPENDED)
- reply(textclient, user, "NS_A_SUSPENDED", (nick ? nick : auth), chan->name);
- if(chanuser_row[2] && strcmp(chanuser_row[2], ""))
- reply(textclient, user, "[%s] %s", (nick ? nick : auth), chanuser_row[2]);
- } else if(!strcmp(user_row[2], "1")) {
- if(nick)
- reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_AUTH", nick, auth, chan->name);
- else
- reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_NICK", auth, chan->name);
- } else
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
- } else
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
- if(target && (target->flags & USERFLAG_ISIRCOP))
- reply(textclient, user, "NS_A_IS_IRCOP", nick);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] nick|*auth|*!*@mask
-* argv[1-*] reason
-*/
-static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup);
-static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mas, char *reason);
-
-struct neonserv_cmd_addban_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *mask;
- char *reason;
-};
-
-CMD_BIND(neonserv_cmd_addban) {
- struct neonserv_cmd_addban_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->mask = strdup(argv[0]);
- if(argc > 1) {
- cache->reason = strdup(merge_argv(argv, 1, argc));
- } else
- cache->reason = NULL;
- get_userlist(chan, neonserv_cmd_addban_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup) {
- struct neonserv_cmd_addban_cache *cache = data;
- neonserv_cmd_addban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, (cache->reason ? cache->reason : "Bye."));
- free(cache->mask);
- if(cache->reason)
- free(cache->reason);
- free(cache);
-}
-
-static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, char *reason) {
- int match_count = 0;
- char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- mask = make_banmask(mask, hostmask_buffer);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(mask, usermask)) {
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- return;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- return;
- }
- match_count++;
- if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
- reply(textclient, user, "NS_LAME_MASK", mask);
- return;
- }
- }
- }
- MYSQL_RES *res;
- MYSQL_ROW row;
- //check if the provided mask is already banned by another ban
- char *ban = getBanAffectingMask(chan, mask);
- if(ban != NULL) {
- reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name);
- return;
- }
- //check if the provided mask affects any existing bans
- printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
- res = mysql_use();
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(!match(mask, row[0])) {
- //remove the ban
- printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]);
- }
- }
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- int userid;
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL)
- userid = atoi(row[0]);
- else
- return;
- //add the ban
- printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%d', '%s')", chan->channel_id, escape_string(mask), userid, escape_string(reason));
- putsock(client, "MODE %s +b %s", chan->name, mask);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(mask, usermask)) {
- putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
- }
- }
- reply(textclient, user, "NS_ADDBAN_DONE", mask, chan->name, match_count);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] nick|*auth|*!*@mask
-* argv[1] time
-* argv[2-*] reason
-*/
-static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup);
-static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason);
-
-struct neonserv_cmd_addtimeban_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *mask;
- int duration;
- char *reason;
-};
-
-CMD_BIND(neonserv_cmd_addtimeban) {
- int duration = strToTime(user, argv[1]);
- if(duration < 30) {
- reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30);
- return;
- }
- struct neonserv_cmd_addtimeban_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->mask = strdup(argv[0]);
- cache->duration = duration;
- if(argc > 2) {
- cache->reason = strdup(merge_argv(argv, 2, argc));
- } else
- cache->reason = NULL;
- get_userlist(chan, neonserv_cmd_addtimeban_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup) {
- struct neonserv_cmd_addtimeban_cache *cache = data;
- neonserv_cmd_addtimeban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, cache->duration, (cache->reason ? cache->reason : "Bye."));
- free(cache->mask);
- if(cache->reason)
- free(cache->reason);
- free(cache);
-}
-
-static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason) {
- int match_count = 0;
- char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- mask = make_banmask(mask, hostmask_buffer);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(mask, usermask)) {
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- return;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- return;
- }
- match_count++;
- if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
- reply(textclient, user, "NS_LAME_MASK", mask);
- return;
- }
- }
- }
- MYSQL_RES *res;
- MYSQL_ROW row;
- //check if the provided mask is already banned by another ban
- char *ban = getBanAffectingMask(chan, mask);
- if(ban != NULL) {
- reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name);
- return;
- }
- //check if the provided mask affects any existing bans
- printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
- res = mysql_use();
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(!match(mask, row[0])) {
- //remove the ban
- printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]);
- }
- }
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- int userid;
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL)
- userid = atoi(row[0]);
- else
- return;
- //add the ban
- printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(mask), (unsigned long) (time(0) + duration), userid, escape_string(reason));
- int banid = (int) mysql_insert_id(mysql_conn);
- putsock(client, "MODE %s +b %s", chan->name, mask);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(mask, usermask)) {
- putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
- }
- }
- char nameBuf[MAXLEN];
- char banidBuf[20];
- sprintf(nameBuf, "ban_%d", banid);
- sprintf(banidBuf, "%d", banid);
- timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
- reply(textclient, user, "NS_TIMEBAN_DONE", mask, chan->name, timeToStr(user, duration, 2, nameBuf), match_count);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-* argv[1] - chan access
-*/
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup);
-static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup);
-static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int access);
-
-struct neonserv_cmd_adduser_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- int access;
- char *nick;
-};
-
-CMD_BIND(neonserv_cmd_adduser) {
- int caccess;
- MYSQL_RES *res;
- MYSQL_ROW row;
- caccess = atoi(argv[1]);
- if(caccess <= 0 || caccess > 500) {
- reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
- return;
- }
- if(caccess >= getChannelAccess(user, chan, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_ACCESS_OUTRANKED");
- return;
- }
- }
- //check own access
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0]));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, event, argv[0], row[0], caccess);
- } else {
- //we need to create a new user...
- //but first lookup the auth to check if it really exists
- struct neonserv_cmd_adduser_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->access = caccess;
- cache->nick = strdup(argv[0]);
- lookup_authname(argv[0], neonserv_cmd_adduser_auth_lookup, cache);
- }
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, caccess);
- } else {
- struct neonserv_cmd_adduser_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->access = caccess;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_adduser_nick_lookup, cache);
- }
- }
-}
-
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup) {
- struct neonserv_cmd_adduser_cache *cache = data;
- if(!exists) {
- //AUTH_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick);
- } else
- neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->nick, auth, cache->access);
- free(cache->nick);
- free(cache);
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup) {
- struct neonserv_cmd_adduser_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->access);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is already added
- printf_mysql_query("SELECT `chanuser_access` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- reply(textclient, user, "NS_ADDUSER_ALREADY_ADDED", nick, chan->name, atoi(row[0]));
- return;
- }
- } else {
- printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth));
- userid = (int) mysql_insert_id(mysql_conn);
- }
- printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chan->channel_id, userid, caccess);
- reply(textclient, user, "NS_ADDUSER_DONE", nick, chan->name, caccess);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nick[,*auth[,*!*@mask[...]]]
-*/
-static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup);
-static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *masks);
-
-struct neonserv_cmd_ban_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *masks;
-};
-
-CMD_BIND(neonserv_cmd_ban) {
- struct neonserv_cmd_ban_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->masks = strdup(merge_argv_char(argv, 0, argc, ','));
- get_userlist_with_invisible(chan, neonserv_cmd_ban_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup) {
- struct neonserv_cmd_ban_cache *cache = data;
- neonserv_cmd_ban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->masks);
- free(cache->masks);
- free(cache);
-}
-
-static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *masks) {
- int done_masks = 0, provided_masks = 0, skip, match_count, total_match;
- char *mask, *nextmask;
- char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- nextmask = masks;
- while((mask = nextmask)) {
- nextmask = strstr(mask, ",");
- if(nextmask) {
- *nextmask = '\0';
- nextmask++;
- }
- provided_masks++;
- skip = 0;
- match_count = 0;
- mask = make_banmask(mask, hostmask_buffer);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(mask, usermask)) {
- cuser->flags |= USERFLAG_SCRIPTFLAG1; //we mark the user as 'matching'
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- skip = 1;
- break;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- skip = 1;
- break;
- }
- match_count++;
- if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
- skip = 1;
- reply(textclient, user, "NS_LAME_MASK", mask);
- break;
- }
- }
- }
- if(!skip) {
- done_masks++;
- modeBufferBan(modeBuf, mask);
- }
- }
- total_match = 0; // count all users marked as 'matching'
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- if(cuser->flags & USERFLAG_SCRIPTFLAG1) {
- cuser->flags &= ~USERFLAG_SCRIPTFLAG1;
- total_match++;
- }
- }
- freeModeBuffer(modeBuf);
- if(done_masks == provided_masks)
- reply(getTextBot(), user, "NS_BAN_DONE", done_masks, chan->name, total_match);
- else
- reply(getTextBot(), user, "NS_BAN_FAIL", client->user->nick);
- if(done_masks)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] (optional) mask
-*/
-CMD_BIND(neonserv_cmd_bans) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- //ban list
- int i, with_expire = 0, cindex = 0;
- char triggered_str[MAXLEN], expires_str[MAXLEN];
- struct Table *table;
- printf_mysql_query("SELECT `ban_mask`, `user_user`, `ban_triggered`, `ban_timeout`, `ban_reason` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d'", chan->channel_id);
- res = mysql_use();
- table = table_init(5, mysql_num_rows(res) + 1, 0);
- char *content[5];
- //add a NULL row (we add values later)
- content[0] = NULL;
- content[1] = NULL;
- content[2] = NULL;
- content[3] = NULL;
- content[4] = NULL;
- table_add(table, content);
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(argc > 0 && match(argv[0], row[0])) continue;
- content[0] = row[0];
- content[1] = row[1];
- content[2] = (strcmp(row[2], "0") ? timeToStr(user, (time(0) - atoi(row[2])), 2, triggered_str) : get_language_string(user, "NS_USERS_SEEN_NEVER"));
- if(strcmp(row[3], "0")) {
- if(!with_expire) {
- //we're using expire times now...
- for(i = 0; i < cindex; i++)
- table_change_field(table, i+1, 3, get_language_string(user, "NS_USERS_SEEN_NEVER"));
- with_expire = 1;
- }
- content[3] = timeToStr(user, (atoi(row[3]) - time(0)), 2, expires_str);
- } else
- content[3] = (with_expire ? get_language_string(user, "NS_USERS_SEEN_NEVER") : NULL);
- content[4] = row[4];
- cindex++;
- table_add(table, content);
- }
- //now we add the table header
- content[0] = get_language_string(user, "NS_BANS_HEADER_MASK");
- content[1] = get_language_string(user, "NS_BANS_HEADER_SETBY");
- content[2] = get_language_string(user, "NS_BANS_HEADER_TRIGGERED");
- content[3] = (with_expire ? get_language_string(user, "NS_BANS_HEADER_EXPIRES") : NULL);
- content[4] = get_language_string(user, "NS_BANS_HEADER_REASON");
- table_change(table, 0, content);
- char **table_lines = table_end(table);
- for(i = 0; i < table->entrys; i++) {
- reply(getTextBot(), user, table_lines[i]);
- }
- if(!cindex)
- reply(getTextBot(), user, "NS_TABLE_NONE");
- reply(getTextBot(), user, "NS_TABLE_COUNT", cindex);
- table_free(table);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] command name
-* argv[1] command function
-* argv[2-*] parameters (optional)
-*/
-
-CMD_BIND(neonserv_cmd_bind) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0]));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- reply(getTextBot(), user, "NS_BIND_ALREADY", argv[0], row[0]);
- return;
- }
- char *params;
- if(argc > 2)
- params = merge_argv(argv, 2, argc);
- else
- params = "";
- struct cmd_function *function = find_cmd_function(client->botid, argv[1]);
- if(!function) {
- reply(getTextBot(), user, "NS_BIND_UNKNOWN", argv[1]);
- return;
- }
- bind_cmd_to_function(client->botid, argv[0], function);
- if(*params)
- bind_set_parameters(client->botid, argv[0], params);
- printf_mysql_query("INSERT INTO `bot_binds` (`botclass`, `command`, `function`, `parameters`) VALUES ('%d', '%s', '%s', '%s')", client->botid, escape_string(argv[0]), escape_string(function->name), params);
- reply(getTextBot(), user, "NS_BIND_DONE", argv[0], function->name);
- logEvent(event);
-}
+++ /dev/null
-
-#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 == ' ');
- 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) {
- caccess = atoi(tokens[0]);
- username = tokens[1];
- } 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(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(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);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-* argv[1] - access
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup);
-static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess);
-
-struct neonserv_cmd_clvl_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
- int access;
-};
-
-CMD_BIND(neonserv_cmd_clvl) {
- int caccess;
- caccess = atoi(argv[1]);
- if(caccess <= 0 || caccess > 500) {
- reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
- return;
- }
- if(caccess >= getChannelAccess(user, chan, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_ACCESS_OUTRANKED");
- return;
- }
- }
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, event, argv[0], argv[0], caccess);
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, caccess);
- } else {
- struct neonserv_cmd_clvl_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[0]);
- cache->access = caccess;
- get_userauth(cuser, neonserv_cmd_clvl_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup) {
- struct neonserv_cmd_clvl_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_clvl_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->access);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is already added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` 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]) >= getChannelAccess(user, chan, 1)) {
- reply(textclient, user, "NS_USER_OUTRANKED", nick);
- return;
- }
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d' WHERE `chanuser_id` = '%s'", caccess, row[1]);
- reply(textclient, user, "NS_CLVL_DONE", nick, caccess, chan->name);
- logEvent(event);
- return;
- }
- }
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-1] command
-*/
-static int neonserv_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan);
-static int neonserv_cmd_command_operaccess(struct cmd_binding *cbind);
-
-CMD_BIND(neonserv_cmd_command) {
- char *ident;
- MYSQL_RES *res;
- MYSQL_ROW row;
- struct cmd_binding *cbind = find_cmd_binding(client->botid, argv[0]);
- if (!cbind) {
- reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]);
- return;
- }
- ident = argv[0];
- reply(getTextBot(), user, "NS_COMMAND_BINDING", cbind->cmd, cbind->func->name, (cbind->parameters ? cbind->parameters : ""));
- if(chan)
- reply(getTextBot(), user, "NS_COMMAND_ACCESS", neonserv_cmd_command_chanaccess(cbind, chan), neonserv_cmd_command_operaccess(cbind));
- printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- char *lang;
- if ((row = mysql_fetch_row(res)) != NULL)
- lang = row[0];
- else
- lang = "en";
- printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- if(stricmp(lang, "en")) {
- printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident));
- res = mysql_use();
- }
- if ((row = mysql_fetch_row(res)) == NULL) {
- printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(cbind->func->name));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- if(stricmp(lang, "en")) {
- printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(cbind->func->name));
- res = mysql_use();
- }
- if ((row = mysql_fetch_row(res)) == NULL) {
- return;
- }
- }
- }
- }
- char sendBuf[MAXLEN];
- int sendBufPos = 0;
- int i;
- for(i = 0; i < strlen(row[0]); i++) {
- switch(row[0][i]) {
- case '\n':
- if(sendBufPos) {
- sendBuf[sendBufPos] = '\0';
- reply(getTextBot(), user, "%s", sendBuf);
- sendBufPos = 0;
- }
- break;
- case '$':
- switch(row[0][i+1]) {
- case 'b':
- sendBuf[sendBufPos++] = '\002';
- i++;
- break;
- case 'k':
- sendBuf[sendBufPos++] = '\003';
- i++;
- break;
- case 'u':
- sendBuf[sendBufPos++] = '\031';
- i++;
- break;
- case 'C':
- case 'S':
- sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick);
- i++;
- break;
- default:
- sendBuf[sendBufPos++] = '$';
- break;
- }
- break;
- default:
- sendBuf[sendBufPos++] = row[0][i];
- break;
- }
- }
- if(sendBufPos) {
- sendBuf[sendBufPos] = '\0';
- reply(getTextBot(), user, "%s", sendBuf);
- sendBufPos = 0;
- }
-}
-
-static int neonserv_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan) {
- char access_list[256];
- int access_pos = 0;
- int access_count = 0;
- int minaccess = 0;
- char *str_a, *str_b = cbind->func->channel_access, *str_c;
- if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS)
- str_b = cbind->channel_access;
- access_list[0] = '\0';
- if(str_b) {
- str_c = strdup(str_b);
- str_b = str_c;
- while((str_a = str_b)) {
- str_b = strstr(str_a, ",");
- if(str_b) {
- *str_b = '\0';
- str_b++;
- }
- if(*str_a == '#') {
- str_a++;
- access_pos += sprintf(access_list+access_pos, (access_pos ? ", `%s`" : "`%s`"), str_a);
- access_count++;
- } else {
- if(atoi(str_a) > minaccess)
- minaccess = atoi(str_a);
- }
- }
- free(str_c);
- }
- if(access_count) {
- MYSQL_RES *res;
- MYSQL_ROW row, defaults = NULL;
- printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- int i, caccess;
- for(i = 0; i < access_count; i++) {
- if(!row[i] && !defaults) {
- printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list);
- defaults = mysql_fetch_row(mysql_use());
- }
- caccess = (row[i] ? atoi(row[i]) : atoi(defaults[i]));
- if(caccess > minaccess)
- minaccess = caccess;
- }
- }
- }
- return minaccess;
-}
-
-static int neonserv_cmd_command_operaccess(struct cmd_binding *cbind) {
- return ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - channel
-*/
-CMD_BIND(neonserv_cmd_csuspend) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- char *channel = argv[0];
- if(!is_valid_chan(channel)) {
- reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
- return;
- }
- int chanid;
- printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chanid = atoi(row[0]);
- } else {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- if(!strcmp(row[2], "1")) {
- reply(getTextBot(), user, "NS_CSUSPEND_ALREADY", channel);
- return;
- }
- int botid = atoi(row[0]);
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->clientid == botid)
- break;
- }
- if(bot) {
- putsock(bot, "PART %s :Channel suspended.", channel);
- }
- printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '1' WHERE `id` = '%s'", row[1]);
- reply(getTextBot(), user, "NS_CSUSPEND_DONE", channel);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - channel
-*/
-CMD_BIND(neonserv_cmd_cunsuspend) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- char *channel = argv[0];
- if(!is_valid_chan(channel)) {
- reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
- return;
- }
- int chanid;
- printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chanid = atoi(row[0]);
- } else {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- if(!strcmp(row[2], "0")) {
- reply(getTextBot(), user, "NS_CUNSUSPEND_NOT", channel);
- return;
- }
- int botid = atoi(row[0]);
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->clientid == botid)
- break;
- }
- if(bot) {
- putsock(bot, "JOIN %s", channel);
- }
- printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '0' WHERE `id` = '%s'", row[1]);
- reply(getTextBot(), user, "NS_CUNSUSPEND_DONE", channel);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] nick|*auth|*!*@mask
-*/
-
-CMD_BIND(neonserv_cmd_delban) {
- char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
- char *mask = make_banmask(argv[0], hostmask_buffer);
- int matching_bans = 0;
- MYSQL_RES *res;
- MYSQL_ROW row;
- //check if the provided mask is already banned by another ban
- char *ban = getBanAffectingMask(chan, mask);
- if(ban != NULL) {
- reply(getTextBot(), user, "NS_DELBAN_BANNED_BY", mask, ban);
- return;
- }
- //check if the provided mask affects any existing bans
- char nameBuf[20];
- printf_mysql_query("SELECT `ban_mask`, `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
- res = mysql_use();
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(!match(mask, row[0])) {
- //remove the ban
- if(strcmp(row[2], "0")) {
- sprintf(nameBuf, "ban_%s", row[1]);
- timeq_del_name(nameBuf);
- }
- printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]);
- matching_bans++;
- }
- }
- if(matching_bans) {
- putsock(client, "MODE %s -b %s", chan->name, mask);
- reply(getTextBot(), user, "NS_DELBAN_DONE", mask, chan->name);
- logEvent(event);
- } else
- reply(getTextBot(), user, "NS_DELBAN_FAIL", mask);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - key
-*/
-
-CMD_BIND(neonserv_cmd_delme) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- //check key
- int seed = 0;
- char *tmp;
- static char unregkey[16];
- 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));
- sprintf(unregkey, "%08x", seed);
- if(argc < 1 || strcmp(argv[0], unregkey)) {
- reply(getTextBot(), user, "NS_DELME_KEY", unregkey);
- return;
- } else {
- //delete
- printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]);
- reply(getTextBot(), user, "NS_DELME_DONE", atoi(row[0]), chan->name);
- logEvent(event);
- return;
- }
- }
- }
- reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup);
-static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
-
-struct neonserv_cmd_deluser_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
-};
-
-CMD_BIND(neonserv_cmd_deluser) {
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
- } else {
- struct neonserv_cmd_deluser_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_deluser_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup) {
- struct neonserv_cmd_deluser_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_deluser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is already added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(textclient, user, "NS_USER_OUTRANKED", nick);
- return;
- }
- }
- //delete
- printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]);
- reply(textclient, user, "NS_DELUSER_DONE", nick, atoi(row[0]), chan->name);
- logEvent(event);
- return;
- }
- }
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nicks
-*/
-static USERLIST_CALLBACK(neonserv_cmd_deop_userlist_lookup);
-static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc);
-
-struct neonserv_cmd_deop_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char **argv;
- int argc;
-};
-
-CMD_BIND(neonserv_cmd_deop) {
- struct neonserv_cmd_deop_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->argv = calloc(argc, sizeof(char*));
- int i;
- for(i = 0; i < argc; i++) {
- cache->argv[i] = strdup(argv[i]);
- }
- cache->argc = argc;
- get_userlist(chan, neonserv_cmd_deop_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_deop_userlist_lookup) {
- struct neonserv_cmd_deop_cache *cache = data;
- neonserv_cmd_deop_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->argv, cache->argc);
- int i;
- for(i = 0; i < cache->argc; i++) {
- free(cache->argv[i]);
- }
- free(cache);
-}
-
-static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) {
- int i, done_users = 0;
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- for(i = 0; i < argc; i++) {
- cuser = searchUserByNick(argv[i]);
- if(!cuser) continue;
- chanuser = getChanUser(cuser, chan);
- if(!chanuser) continue;
- if(isNetworkService(cuser)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
- continue;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- continue;
- }
- done_users++;
- if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue;
- modeBufferDeop(modeBuf, argv[i]);
- }
- freeModeBuffer(modeBuf);
- if(done_users == argc)
- reply(textclient, user, "NS_DEOP_DONE", chan->name);
- else
- reply(textclient, user, "NS_DEOP_FAIL", client->user->nick);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] (optional) nick mask
-*/
-static USERLIST_CALLBACK(neonserv_cmd_deopall_userlist_lookup);
-static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc);
-
-struct neonserv_cmd_deopall_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char **argv;
- int argc;
-};
-
-CMD_BIND(neonserv_cmd_deopall) {
- struct neonserv_cmd_deopall_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->argv = calloc(argc, sizeof(char*));
- int i;
- for(i = 0; i < argc; i++) {
- cache->argv[i] = strdup(argv[i]);
- }
- cache->argc = argc;
- get_userlist(chan, neonserv_cmd_deopall_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_deopall_userlist_lookup) {
- struct neonserv_cmd_deopall_cache *cache = data;
- neonserv_cmd_deopall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->argv, cache->argc);
- int i;
- for(i = 0; i < cache->argc; i++) {
- free(cache->argv[i]);
- }
- free(cache);
-}
-
-static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) {
- int issuer_access, victim_access, done_users = 0;
- char *nickmask = NULL;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- if(argc > 0)
- nickmask = argv[0];
- modeBuf = initModeBuffer(client, chan);
- issuer_access = getChannelAccess(user, chan, 0);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(nickmask && match(nickmask, chanuser->user->nick)) continue;
- victim_access = getChannelAccess(user, chan, 0);
- if(victim_access >= issuer_access) continue;
- if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue;
- modeBufferDeop(modeBuf, chanuser->user->nick);
- done_users++;
- }
- freeModeBuffer(modeBuf);
- reply(getTextBot(), user, "NS_DEOPALL_DONE", done_users, chan->name);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nicks
-*/
-
-CMD_BIND(neonserv_cmd_devoice) {
- int i, done_users = 0;
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- for(i = 0; i < argc; i++) {
- cuser = searchUserByNick(argv[i]);
- if(!cuser) continue;
- chanuser = getChanUser(cuser, chan);
- if(!chanuser) continue;
- if(isUserProtected(chan, cuser, user)) {
- reply(getTextBot(), user, "NS_USER_PROTECTED", cuser->nick);
- continue;
- }
- done_users++;
- if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue;
- modeBufferDevoice(modeBuf, argv[i]);
- }
- freeModeBuffer(modeBuf);
- if(done_users == argc)
- reply(getTextBot(), user, "NS_DEVOICE_DONE", chan->name);
- else
- reply(getTextBot(), user, "NS_DEVOICE_FAIL", client->user->nick);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] (optional) nick mask
-*/
-
-CMD_BIND(neonserv_cmd_devoiceall) {
- int issuer_access, victim_access, done_users = 0;
- char *nickmask = NULL;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- check_mysql();
- if(!checkChannelAccess(user, chan, "channel_canvoice", 1, 0)) {
- reply(getTextBot(), user, "NS_ACCESS_DENIED");
- return;
- }
- if(argc > 0)
- nickmask = argv[0];
- modeBuf = initModeBuffer(client, chan);
- issuer_access = getChannelAccess(user, chan, 0);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(nickmask && match(nickmask, chanuser->user->nick)) continue;
- victim_access = getChannelAccess(user, chan, 0);
- if(victim_access >= issuer_access) continue;
- if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue;
- modeBufferDevoice(modeBuf, chanuser->user->nick);
- done_users++;
- }
- freeModeBuffer(modeBuf);
- reply(getTextBot(), user, "NS_DEVOICEALL_DONE", done_users, chan->name);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no arguments
-*/
-
-CMD_BIND(neonserv_cmd_down) {
- struct ChanUser *chanuser = getChanUser(user, chan);
- if(!chanuser) {
- reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name);
- return;
- }
- if((chanuser->flags & CHANUSERFLAG_OPPED)) {
- putsock(client, "MODE %s -ov %s %s", chan->name, user->nick, user->nick);
- logEvent(event);
- } else if((chanuser->flags & CHANUSERFLAG_VOICED)) {
- putsock(client, "MODE %s -v %s", chan->name, user->nick);
- logEvent(event);
- } else
- reply(getTextBot(), user, "NS_DOWN_ALREADY", chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no arguments
-*/
-
-CMD_BIND(neonserv_cmd_downall) {
- struct ChanUser *chanuser;
- for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) {
- chan = chanuser->chan;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) continue;
- printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
- if (mysql_fetch_row(mysql_use()) == NULL) continue;
- int done = 0;
- if((chanuser->flags & CHANUSERFLAG_OPPED)) {
- putsock(client, "MODE %s -o %s", chan->name, user->nick);
- done = 1;
- }
- if((chanuser->flags & CHANUSERFLAG_VOICED)) {
- putsock(client, "MODE %s -v %s", chan->name, user->nick);
- done = 1;
- }
- if(done) {
- //event hack
- event->chan = chan;
- logEvent(event);
- }
- }
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] target
-* argv[1-*] message
-*/
-
-CMD_BIND(neonserv_cmd_emote) {
- char *message = merge_argv(argv, 1, argc);
- putsock(client, "PRIVMSG %s :\001ACTION %s\001", argv[0], message);
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] time
-* argv[1-*] match
-*/
-
-CMD_BIND(neonserv_cmd_events) {
- char *str_match;
- int duration = (argc ? strToTime(user, argv[0]) : 0);
- if(argc > (duration ? 1 : 0))
- str_match = merge_argv(argv, (duration ? 1 : 0), argc);
- else
- str_match = "";
- if(!duration) duration = (60*60*24);
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `time`, `auth`, `nick`, `command` FROM `events` WHERE `cid` = '%d' AND `time` > '%lu' ORDER BY `time` ASC", chan->channel_id, ((unsigned long) time(0) - duration));
- res = mysql_use();
- int skip = mysql_num_rows(res) - 100;
- int count = 0;
- char timeBuf[50];
- struct tm *timeinfo;
- time_t event_time;
- if(skip < 0) skip = 0;
- reply(getTextBot(), user, "NS_EVENTS_HEADER");
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(skip) {
- skip--;
- continue;
- }
- if(*str_match && match(str_match, row[3])) continue;
- count++;
- event_time = (time_t) atol(row[0]);
- timeinfo = localtime(&event_time);
- strftime(timeBuf, 80, "%X %x", timeinfo);
- reply(getTextBot(), user, "[%s] [%s:%s]: %s", timeBuf, row[2], row[1], row[3]);
- }
- reply(getTextBot(), user, "NS_TABLE_COUNT", count);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-* argv[1] - key
-*/
-
-#define GIVEOWNER_TIMEOUT 86400 /* 60*60*24 = 86400 */
-
-static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup);
-static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, char *key);
-
-struct neonserv_cmd_giveowner_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
- char *key;
-};
-
-CMD_BIND(neonserv_cmd_giveowner) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_lastgiveowner` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return;
- if(strcmp(row[0], "0") && (atoi(row[0]) + GIVEOWNER_TIMEOUT) > time(0)) {
- char timeBuf[MAXLEN];
- reply(getTextBot(), user, "NS_GIVEOWNER_TIMEOUT", timeToStr(user, (GIVEOWNER_TIMEOUT - (time(0) - atoi(row[0]))), 2, timeBuf), chan->name);
- return;
- }
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, event, argv[0], argv[0], (argc != 1 ? argv[1] : NULL));
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, (argc != 1 ? argv[1] : NULL));
- } else {
- struct neonserv_cmd_giveowner_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[0]);
- cache->key = (argc != 1 ? strdup(argv[1]) : NULL);
- get_userauth(cuser, neonserv_cmd_giveowner_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup) {
- struct neonserv_cmd_giveowner_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_giveowner_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->key);
- free(cache->nick);
- if(cache->key)
- free(cache->key);
- free(cache);
-}
-
-static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, char *key) {
- //we've got a valid auth now...
- if(!stricmp(user->auth, auth)) {
- reply(textclient, user, "NS_GIVEOWNER_SELF");
- return;
- }
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is already added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- int seed = 0;
- char *tmp;
- char giveownerkey[16];
- 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));
- sprintf(giveownerkey, "%08x", seed);
- if(key && !stricmp(giveownerkey, key)) {
- //give ownership
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '500' WHERE `chanuser_id` = '%s'", row[1]);
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '499' WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = (SELECT `user_id` FROM `users` WHERE `user_user` = '%s')", chan->channel_id, escape_string(user->auth));
- printf_mysql_query("INSERT INTO `owner_history` (`owner_history_cid`, `owner_history_uid`, `owner_history_time`) VALUE ('%d', '%d', UNIX_TIMESTAMP())", chan->channel_id, userid);
- reply(textclient, user, "NS_GIVEOWNER_DONE", chan->name, auth);
- logEvent(event);
- } else {
- reply(textclient, user, "NS_GIVEOWNER_CONFIRM", auth, giveownerkey);
- }
- return;
- }
- }
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] (optional) on/off
-*/
-
-CMD_BIND(neonserv_cmd_god) {
- if(argc > 0) {
- if(!strcmp(argv[0], "0") || !stricmp(argv[0], "off") || !stricmp(argv[0], get_language_string(user, "NS_SET_OFF"))) {
- if(isGodMode(user)) {
- printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth));
- user->flags &= ~USERFLAG_GOD_MODE;
- }
- reply(getTextBot(), user, "NS_GOD_OFF");
- } else if(!strcmp(argv[0], "1") || !stricmp(argv[0], "on") || !stricmp(argv[0], get_language_string(user, "NS_SET_ON"))) {
- if(!isGodMode(user)) {
- printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth));
- user->flags |= USERFLAG_GOD_MODE;
- }
- reply(getTextBot(), user, "NS_GOD_ON");
- } else {
- reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[0]);
- return;
- }
- } else {
- if(isGodMode(user)) {
- printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth));
- user->flags &= ~USERFLAG_GOD_MODE;
- reply(getTextBot(), user, "NS_GOD_OFF");
- } else {
- printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth));
- user->flags |= USERFLAG_GOD_MODE;
- reply(getTextBot(), user, "NS_GOD_ON");
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] index
-*/
-
-CMD_BIND(neonserv_cmd_help) {
- char *ident;
- if(argc)
- ident = merge_argv(argv, 0, argc);
- else
- ident = "0";
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- char *lang;
- if ((row = mysql_fetch_row(res)) != NULL)
- lang = row[0];
- else
- lang = "en";
- printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- if(stricmp(lang, "en")) {
- printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident));
- res = mysql_use();
- }
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(getTextBot(), user, "NS_HELP_TOPIC");
- return;
- }
- }
- char sendBuf[MAXLEN];
- int sendBufPos = 0;
- int i;
- for(i = 0; i < strlen(row[0]); i++) {
- switch(row[0][i]) {
- case '\n':
- if(sendBufPos) {
- sendBuf[sendBufPos] = '\0';
- reply(getTextBot(), user, "%s", sendBuf);
- sendBufPos = 0;
- }
- break;
- case '$':
- switch(row[0][i+1]) {
- case 'b':
- sendBuf[sendBufPos++] = '\002';
- i++;
- break;
- case 'k':
- sendBuf[sendBufPos++] = '\003';
- i++;
- break;
- case 'u':
- sendBuf[sendBufPos++] = '\031';
- i++;
- break;
- case 'C':
- case 'S':
- sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick);
- i++;
- break;
- default:
- sendBuf[sendBufPos++] = '$';
- break;
- }
- break;
- default:
- sendBuf[sendBufPos++] = row[0][i];
- break;
- }
- }
- if(sendBufPos) {
- sendBuf[sendBufPos] = '\0';
- reply(getTextBot(), user, "%s", sendBuf);
- sendBufPos = 0;
- }
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup);
-static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
-static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout);
-static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan);
-static int neonserv_cmd_invite_is_timeout(char *nick, char *chan);
-static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout);
-
-
-struct neonserv_cmd_invite_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
-};
-
-struct neonserv_cmd_invite_timeout {
- char *nick;
- char *chan;
-
- struct neonserv_cmd_invite_timeout *next;
-};
-
-static struct neonserv_cmd_invite_timeout *first_timeout = NULL, *last_timeout = NULL;
-
-CMD_BIND(neonserv_cmd_invite) {
- if(neonserv_cmd_invite_is_timeout(argv[0], chan->name)) {
- reply(getTextBot(), user, "NS_INVITE_TIMEOUT", argv[0], chan->name);
- return;
- }
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- } else if(getChanUser(cuser, chan)) {
- reply(getTextBot(), user, "NS_INVITE_ON_CHAN", cuser->nick, chan->name);
- /* BUG
- This check does not work if the user is invisible (CHMODE +D/+d)
- to fix this we'd need to request the full userlist...
- this is really senseless to invite a simple user so we simply mark this bug as unsolvable.
- */
- return;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_invite_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
- } else {
- struct neonserv_cmd_invite_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_invite_nick_lookup, cache);
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup) {
- struct neonserv_cmd_invite_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- } else
- neonserv_cmd_invite_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, ((user->flags & USERFLAG_ISAUTHED) ? user->auth : NULL));
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
- if(auth) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- //check if the user has set noinvite
- printf_mysql_query("SELECT `id` FROM `noinvite` WHERE `uid` = '%s' AND `cid` = '%d'", row[0], chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- reply(textclient, user, "NS_INVITE_RESTRICTION", nick, chan->name);
- return;
- }
- }
- }
- struct neonserv_cmd_invite_timeout *timeout = neonserv_cmd_invite_add_timeout(nick, chan->name);
- timeq_add(INVITE_TIMEOUT, neonserv_cmd_invite_timeout_timeout, timeout);
- putsock(client, "INVITE %s %s", nick, chan->name);
- struct UserNode *tmpu = getUserByNick(nick);
- if(!tmpu) {
- tmpu = createTempUser(nick);
- tmpu->flags |= USERFLAG_ISTMPUSER | (auth ? USERFLAG_ISAUTHED : 0);
- if(auth)
- strcpy(tmpu->auth, auth);
- }
- reply(textclient, tmpu, "NS_INVITE_DONE_USER", chan->name, user->nick, client->user->nick);
- reply(textclient, user, "NS_INVITE_DONE", nick, chan->name);
-}
-
-static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout) {
- struct neonserv_cmd_invite_timeout *entry = data;
- neonserv_cmd_invite_del_timeout(entry);
-}
-
-static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan) {
- struct neonserv_cmd_invite_timeout *entry = malloc(sizeof(*entry));
- if (!entry) {
- perror("malloc() failed");
- return NULL;
- }
- entry->next = NULL;
- entry->nick = strdup(nick);
- entry->chan = strdup(chan);
- if(last_timeout) {
- last_timeout->next = entry;
- last_timeout = entry;
- } else {
- last_timeout = entry;
- first_timeout = entry;
- }
- return entry;
-}
-
-static int neonserv_cmd_invite_is_timeout(char *nick, char *chan) {
- if(!first_timeout) return 0;
- struct neonserv_cmd_invite_timeout *entry;
- for(entry = first_timeout; entry; entry = entry->next) {
- if(!stricmp(entry->nick, nick) && !stricmp(entry->chan, chan))
- return 1;
- }
- return 0;
-}
-
-static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout) {
- struct neonserv_cmd_invite_timeout *entry, *prev = NULL;
- for(entry = first_timeout; entry; entry = entry->next) {
- if(entry == timeout) {
- if(prev)
- prev->next = entry->next;
- else
- first_timeout = entry->next;
- break;
- } else
- prev = entry;
- }
- if(last_timeout == timeout)
- last_timeout = prev;
- free(timeout->nick);
- free(timeout->chan);
- free(timeout);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no arguments
-*/
-
-CMD_BIND(neonserv_cmd_inviteme) {
- if(getChanUser(user, chan)) {
- reply(getTextBot(), user, "NS_INVITEME_ON_CHAN", chan->name);
- /* BUG
- This check does not work if the user is invisible (CHMODE +D/+d)
- to fix this we'd need to request the full userlist...
- this is really senseless to invite a simple user so we simply mark this bug as unsolvable.
- */
- return;
- }
- putsock(client, "INVITE %s %s", user->nick, chan->name);
- reply(getTextBot(), user, "NS_INVITEME_DONE", chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] nick[,*auth[,*!*@mask[...]]]
-* argv[1-*] reason
-*/
-static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup);
-static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason);
-
-struct neonserv_cmd_kick_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *nicks;
- char *reason;
-};
-
-CMD_BIND(neonserv_cmd_kick) {
- struct neonserv_cmd_kick_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->nicks = strdup(argv[0]);
- if(argc > 1) {
- cache->reason = strdup(merge_argv(argv, 1, argc));
- } else
- cache->reason = NULL;
- get_userlist_with_invisible(chan, neonserv_cmd_kick_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup) {
- struct neonserv_cmd_kick_cache *cache = data;
- neonserv_cmd_kick_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks, (cache->reason ? cache->reason : "Bye."));
- free(cache->nicks);
- if(cache->reason)
- free(cache->reason);
- free(cache);
-}
-
-static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason) {
- int i, kicked_users = 0, provided_nicks = 0;
- char *nick, *nextnick;
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- nextnick = nicks;
- while((nick = nextnick)) {
- nextnick = strstr(nick, ",");
- if(nextnick) {
- *nextnick = '\0';
- nextnick++;
- }
- if(!*nick) continue;
- if(is_ircmask(nick)) {
- //KICK HOSTMASK
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- struct ChanUser *kick_chanuser[chan->usercount];
- int kick_chanuser_pos = 0;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(nick, usermask)) {
- provided_nicks++;
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- continue;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- continue;
- }
- kick_chanuser[kick_chanuser_pos++] = chanuser;
- if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) {
- kick_chanuser_pos = 0;
- reply(textclient, user, "NS_LAME_MASK", nick);
- break;
- }
- }
- }
- for(i = 0; i < kick_chanuser_pos; i++) {
- kicked_users++;
- putsock(client, "KICK %s %s :%s", chan->name, kick_chanuser[i]->user->nick, reason);
- }
- } else if(*nick == '*') {
- //KICK AUTH
- nick++;
- cuser = NULL;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) {
- provided_nicks++;
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- continue;
- }
- if(!cuser) {
- //check if the user is protected
- if(isUserProtected(chan, chanuser->user, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick);
- break; //all other users are also protected...
- }
- cuser = chanuser->user;
- }
- kicked_users++;
- putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
- }
- }
- } else {
- provided_nicks++;
- cuser = NULL;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(!stricmp(chanuser->user->nick, nick)) {
- cuser = chanuser->user;
- }
- }
- if(!cuser) continue;
- if(isNetworkService(cuser)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
- continue;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- continue;
- }
- kicked_users++;
- putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
- }
- }
- if(kicked_users == provided_nicks)
- reply(getTextBot(), user, "NS_KICK_DONE", kicked_users, chan->name);
- else
- reply(getTextBot(), user, "NS_KICK_FAIL", client->user->nick);
- if(kicked_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] nick[,*auth[,*!*@mask[...]]]
-* argv[1-*] reason
-*/
-static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup);
-static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason);
-
-struct neonserv_cmd_kickban_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *nicks;
- char *reason;
-};
-
-CMD_BIND(neonserv_cmd_kickban) {
- struct neonserv_cmd_kickban_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->nicks = strdup(argv[0]);
- if(argc > 1) {
- cache->reason = strdup(merge_argv(argv, 1, argc));
- } else
- cache->reason = NULL;
- get_userlist_with_invisible(chan, neonserv_cmd_kickban_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup) {
- struct neonserv_cmd_kickban_cache *cache = data;
- neonserv_cmd_kickban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks, (cache->reason ? cache->reason : "Bye."));
- free(cache->nicks);
- if(cache->reason)
- free(cache->reason);
- free(cache);
-}
-
-static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason) {
- int i, kicked_users = 0, provided_nicks = 0;
- char *nick, *nextnick;
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- nextnick = nicks;
- while((nick = nextnick)) {
- nextnick = strstr(nick, ",");
- if(nextnick) {
- *nextnick = '\0';
- nextnick++;
- }
- if(!*nick) continue;
- if(is_ircmask(nick)) {
- //KICK HOSTMASK
- struct ChanUser *kickban_chanuser[chan->usercount];
- int kick_chanuser_pos = 0;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(nick, usermask)) {
- provided_nicks++;
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- continue;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- continue;
- }
- kickban_chanuser[kick_chanuser_pos++] = chanuser;
- if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) {
- kick_chanuser_pos = 0;
- reply(textclient, user, "NS_LAME_MASK", nick);
- break;
- }
- }
- }
- for(i = 0; i < kick_chanuser_pos; i++) {
- if(i == 0) {
- putsock(client, "MODE %s +b %s", chan->name, nick);
- }
- kicked_users++;
- putsock(client, "KICK %s %s :%s", chan->name, kickban_chanuser[i]->user->nick, reason);
- }
- } else if(*nick == '*') {
- //KICK AUTH
- nick++;
- cuser = NULL;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) {
- provided_nicks++;
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- continue;
- }
- if(!cuser) {
- //check if the user is protected
- if(isUserProtected(chan, chanuser->user, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick);
- break; //all other users are also protected...
- }
- cuser = chanuser->user;
- }
- kicked_users++;
- putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
- putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
- }
- }
- } else {
- provided_nicks++;
- cuser = searchUserByNick(nick);
- if(!cuser) continue;
- chanuser = getChanUser(cuser, chan);
- if(!chanuser) continue;
- if(isNetworkService(cuser)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
- continue;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- continue;
- }
- kicked_users++;
- putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
- putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
- }
- }
- if(kicked_users == provided_nicks)
- reply(getTextBot(), user, "NS_KICKBAN_DONE", kicked_users, chan->name);
- else
- reply(getTextBot(), user, "NS_KICKBAN_FAIL", client->user->nick);
- if(kicked_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] access (format: minaccess-maxaccess)
-* argv[1] pattern
-*/
-
-CMD_BIND(neonserv_cmd_mdeluser) {
- if(!checkChannelAccess(user, chan, "channel_candel", 1, 0)) {
- reply(getTextBot(), user, "NS_ACCESS_DENIED");
- return;
- }
- int min_access, max_access;
- char *seperator = strstr(argv[0], "-");
- if(seperator) {
- *seperator = '\0';
- seperator++;
- min_access = atoi(argv[0]);
- max_access = atoi(seperator);
- if(max_access > min_access) {
- reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access);
- return;
- }
- } else {
- min_access = atoi(argv[0]);
- max_access = min_access;
- }
- if(max_access >= getChannelAccess(user, chan, 1)) {
- reply(getTextBot(), user, "NS_NO_ACCESS");
- return;
- }
- MYSQL_RES *res;
- MYSQL_ROW row;
- int del_count = 0;
- printf_mysql_query("SELECT `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access);
- res = mysql_use();
- while((row = mysql_fetch_row(res)) != NULL) {
- if(!match(argv[1], row[0])) {
- del_count++;
- printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]);
- }
- }
- reply(getTextBot(), user, "NS_MDELUSER_DONE", del_count, argv[1], min_access, max_access, chan->name);
- if(del_count)
- logEvent(event);
-}
-
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - modes
-* argv[1-*] - parameters
-*/
-static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup);
-static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode);
-
-struct neonserv_cmd_mode_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *mode;
-};
-
-CMD_BIND(neonserv_cmd_mode) {
- struct neonserv_cmd_mode_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->mode = strdup(merge_argv(argv, 0, argc));
- get_userlist_with_invisible(chan, neonserv_cmd_mode_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup) {
- struct neonserv_cmd_mode_cache *cache = data;
- neonserv_cmd_mode_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mode);
- free(cache->mode);
- free(cache);
-}
-
-static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode) {
- MYSQL_ROW row, defaults = NULL;
- int i, arg, add = 1, skip = 0;
- unsigned int modetype;
- int db_canop, db_canvoice, db_canban, db_enfmodes;
- struct ModeNode *modelock = createModeNode(NULL), *changemodes = createModeNode(NULL);
- struct ModeBuffer *modeBuf;
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- modeBuf = initModeBuffer(client, chan);
- printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- row = mysql_fetch_row(mysql_use());
- if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL) {
- printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
- defaults = mysql_fetch_row(mysql_use());
- }
- db_canop = atoi((row[0] ? row[0] : defaults[0]));
- db_canvoice = atoi((row[1] ? row[1] : defaults[1]));
- db_canban = atoi((row[2] ? row[2] : defaults[2]));
- db_enfmodes = atoi((row[3] ? row[3] : defaults[3]));
- if(row[4])
- parseModeString(modelock, row[4]);
- else if(defaults[4])
- parseModeString(modelock, defaults[4]);
- int uaccess = getChannelAccess(user, chan, 0);
- char *a, *b = mode;
- char *argv[MAXNUMPARAMS];
- char *carg;
- char tmp[MAXLEN];
- int argc = 0;
- do {
- a = strstr(b, " ");
- if(a) *a = '\0';
- argv[argc++] = b;
- if(argc == MAXNUMPARAMS) break;
- if(a) b = a+1;
- } while(a);
- arg = 0;
- while(arg < argc) {
- char *modeStr = argv[arg++];
- for(i = 0; i < strlen(modeStr); i++) {
- switch(modeStr[i]) {
- case '+':
- add = 1;
- break;
- case '-':
- add = 0;
- break;
- case 'o':
- case 'v':
- if(arg == argc) {
- reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
- return;
- }
- carg = argv[arg++];
- if(modeStr[i] == 'o') {
- if(uaccess < db_canop) {
- reply(textclient, user, "NS_MODE_ENFOPS", chan->name);
- db_canop = -1;
- break;
- }
- if(db_canop == -1) break;
- } else {
- if(uaccess < db_canvoice) {
- reply(textclient, user, "NS_MODE_ENFVOICE", chan->name);
- db_canvoice = -1;
- break;
- }
- if(db_canvoice == -1) break;
- }
- cuser = searchUserByNick(carg);
- if(!cuser) {
- //check for an invisible user
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(!stricmp(chanuser->user->nick, carg)) {
- cuser = chanuser->user;
- break;
- }
- }
- if(!cuser) break;
- } else {
- chanuser = getChanUser(cuser, chan);
- if(!chanuser) break;
- }
- if(!(add ^ (chanuser->flags & (modeStr[i] == 'o' ? CHANUSERFLAG_OPPED : CHANUSERFLAG_VOICED)))) break;
- if(!add) {
- //check protection
- if(modeStr[i] == 'o' && isNetworkService(cuser)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
- break;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- break;
- }
- }
- modeBufferSet(modeBuf, add, modeStr[i], carg);
- break;
- case 'b':
- if(arg == argc) {
- reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
- return;
- }
- carg = argv[arg++];
- if(uaccess < db_canban) {
- reply(textclient, user, "NS_MODE_CANBAN", chan->name);
- db_canban = -1;
- break;
- }
- if(db_canban == -1) break;
- char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- struct BanNode *ban;
- int match_count = 0;
- carg = make_banmask(carg, hostmask_buffer);
- if(add) {
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- cuser = chanuser->user;
- sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(!match(carg, usermask)) {
- if(isNetworkService(chanuser->user)) {
- reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
- skip = 1;
- break;
- }
- if(isUserProtected(chan, cuser, user)) {
- reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
- skip = 1;
- break;
- }
- match_count++;
- if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
- skip = 1;
- reply(textclient, user, "NS_LAME_MASK", carg);
- break;
- }
- }
- }
- } else {
- skip = 1;
- for(ban = chan->bans; ban; ban = ban->next) {
- if(!match(carg, ban->mask)) {
- skip = 0;
- break;
- }
- }
- }
- if(!skip) {
- modeBufferSet(modeBuf, add, 'b', carg);
- }
- break;
- default:
- modetype = getModeType(modelock, modeStr[i]);
- if(modetype == 0) {
- reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
- return;
- }
- if(isModeAffected(modelock, modeStr[i]) && add == !isModeSet(modelock, modeStr[i]) && uaccess < db_enfmodes) {
- if(isGodMode(user))
- event->flags |= CMDFLAG_OPLOG;
- else {
- getFullModeString(modelock, tmp);
- reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
- return;
- }
- }
- if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) {
- if(arg == argc) {
- reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
- return;
- }
- carg = argv[arg++];
- if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
- char *modelock_val = getModeValue(modelock, modeStr[i]);
- if(stricmp(carg, modelock_val)) {
- if(isGodMode(user))
- event->flags |= CMDFLAG_OPLOG;
- else {
- getFullModeString(modelock, tmp);
- reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
- return;
- }
- }
- }
- if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
- int *modelock_val = getModeValue(modelock, modeStr[i]);
- if(atoi(carg) != *modelock_val) {
- if(isGodMode(user))
- event->flags |= CMDFLAG_OPLOG;
- else {
- getFullModeString(modelock, tmp);
- reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
- return;
- }
- }
- }
- } else
- carg = NULL;
- if((modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_D && isModeSet(chan->modes, modeStr[i]) == add)
- break;
- if(!isModeAffected(changemodes, modeStr[i])) {
- if(!add && (modetype & CHANNEL_MODE_KEY)) {
- if(isModeSet(chan->modes, modeStr[i])) {
- char *current_val = getModeValue(chan->modes, modeStr[i]);
- carg = current_val;
- }
- }
- if(parseMode(changemodes, add, modeStr[i], carg)) {
- if(carg) {
- if(add && (modetype & CHANNEL_MODE_KEY) && isModeSet(chan->modes, modeStr[i])) {
- char *current_val = getModeValue(chan->modes, modeStr[i]);
- modeBufferSet(modeBuf, 0, modeStr[i], current_val);
- flushModeBuffer(modeBuf);
- }
- if(!add && !isModeSet(chan->modes, modeStr[i])) break;
- modeBufferSet(modeBuf, add, modeStr[i], carg);
- } else {
- modeBufferSimpleMode(modeBuf, add, modeStr[i]);
- }
- } else {
- reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
- return;
- }
- }
- break;
- }
- }
- }
- getFullModeString(changemodes, tmp);
- freeModeBuffer(modeBuf);
- if(strcmp(tmp, "+"))
- reply(textclient, user, "NS_MODE_DONE", tmp);
-
- logEvent(event);
- freeModeNode(modelock);
- freeModeNode(changemodes);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - channel
-* argv[1] - new channel
-*/
-CMD_BIND(neonserv_cmd_move) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- char *channel = argv[0];
- char *new_channel = argv[1];
- if(!is_valid_chan(new_channel)) {
- reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", new_channel);
- return;
- }
- if(!stricmp(channel, new_channel)) {
- reply(getTextBot(), user, "NS_MOVE_SELF");
- return;
- }
- printf_mysql_query("SELECT `channel_id` FROM `bot_channels` LEFT JOIN `channels` ON `channel_id` = `chanid` WHERE `channel_name` = '%s'", escape_string(new_channel));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- reply(getTextBot(), user, "NS_REGISTER_ALREADY", new_channel, client->user->nick);
- return;
- }
- int chanid;
- printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chanid = atoi(row[0]);
- } else {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- if(!strcmp(row[2], "1")) {
- reply(getTextBot(), user, "NS_MOVE_SUSPENDED");
- return;
- }
- int botid = atoi(row[0]);
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->clientid == botid)
- break;
- }
- if(bot) {
- putsock(bot, "PART %s :Channel moved to %s.", channel, new_channel);
- putsock(bot, "JOIN %s", new_channel);
- }
- printf_mysql_query("DELETE FROM `channels` WHERE `channel_name` = '%s'", escape_string(new_channel));
- printf_mysql_query("UPDATE `channels` SET `channel_name` = '%s' WHERE `channel_id` = '%s'", escape_string(new_channel), row[1]);
- struct ChanNode *channode = getChanByName(channel);
- if(channode && channode->flags & CHANFLAG_REQUESTED_CHANINFO) {
- channode->flags &= ~CHANFLAG_CHAN_REGISTERED;
- channode->channel_id = 0;
- }
- channode = getChanByName(new_channel);
- if(channode && channode->flags & CHANFLAG_REQUESTED_CHANINFO) {
- channode->flags |= CHANFLAG_CHAN_REGISTERED;
- channode->channel_id = atoi(row[1]);
- }
- reply(getTextBot(), user, "NS_MOVE_DONE", channel, new_channel);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup);
-static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch);
-
-struct neonserv_cmd_myaccess_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- char *nick;
- char *chanmatch;
-};
-
-CMD_BIND(neonserv_cmd_myaccess) {
- char *chanmatch = NULL;
- if(argc == 0 || argv[0][0] == '#') {
- if(argc != 0) {
- chanmatch = argv[0];
- }
- if(!(user->flags & USERFLAG_ISAUTHED)) {
- struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->nick = strdup(argv[0]);
- cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL);
- get_userauth(user, neonserv_cmd_myaccess_nick_lookup, cache);
- } else
- neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, user->nick, user->auth, chanmatch);
- }
- else if(argv[0][0] == '*') {
- //we've got an auth
- if(argc > 1 && argv[1][0] == '#') {
- chanmatch = argv[1];
- }
- argv[0]++;
- neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, NULL, argv[0], chanmatch);
- } else {
- if(argc > 1 && argv[1][0] == '#') {
- chanmatch = argv[1];
- }
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, chanmatch);
- } else {
- struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->nick = strdup(argv[0]);
- cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL);
- get_userauth(cuser, neonserv_cmd_myaccess_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup) {
- struct neonserv_cmd_myaccess_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- if(!strcmp(cache->nick, cache->user->nick))
- reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH");
- else
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_myaccess_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->chanmatch);
- if(cache->chanmatch)
- free(cache->chanmatch);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch) {
- //we've got a valid auth now...
- MYSQL_RES *res, *default_res;
- MYSQL_ROW user_row, chanuser_row, default_chan = NULL;
- char flagBuf[5];
- int userid, cflags, caccess, flagPos;
- int i, total_count, match_count = 0, owner_count = 0;
- struct Table *table;
- printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- total_count = mysql_num_rows(res);
- table = table_init(4, total_count + 1, 0);
- char *content[4];
- content[0] = get_language_string(user, "NS_MYACCESS_HEADER_NAME");
- content[1] = get_language_string(user, "NS_MYACCESS_HEADER_ACCESS");
- content[2] = get_language_string(user, "NS_MYACCESS_HEADER_FLAGS");
- content[3] = get_language_string(user, "NS_MYACCESS_HEADER_INFO");
- table_add(table, content);
- if(chanmatch)
- reply(textclient, user, "NS_MYACCESS_HEADER_MATCH", auth, chanmatch);
- else
- reply(textclient, user, "NS_MYACCESS_HEADER", auth);
- if ((user_row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(user_row[0]);
- //check if the user is already added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `channel_name`, `channel_getop`, `channel_getvoice` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' ORDER BY `chanuser_access` DESC, `channel_name` ASC", userid);
- res = mysql_use();
- while ((chanuser_row = mysql_fetch_row(res)) != NULL) {
- if(!strcmp(chanuser_row[0], "500")) owner_count++;
- if(chanmatch && match(chanmatch, chanuser_row[0])) continue;
- match_count++;
- if((!chanuser_row[4] || !chanuser_row[5]) && !default_chan) {
- printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
- default_res = mysql_use();
- default_chan = mysql_fetch_row(default_res);
- }
- flagPos = 0;
- content[0] = chanuser_row[3];
- content[1] = chanuser_row[0];
- cflags = atoi(chanuser_row[1]);
- caccess = atoi(chanuser_row[0]);
- if((cflags & DB_CHANUSER_SUSPENDED))
- flagPos += sprintf(flagBuf + flagPos, "s");
- if(caccess >= (chanuser_row[4] ? atoi(chanuser_row[4]) : atoi(default_chan[0])))
- flagPos += sprintf(flagBuf + flagPos, "o");
- if(caccess >= (chanuser_row[5] ? atoi(chanuser_row[5]) : atoi(default_chan[1])))
- flagPos += sprintf(flagBuf + flagPos, "v");
- if((cflags & DB_CHANUSER_AUTOINVITE))
- flagPos += sprintf(flagBuf + flagPos, "i");
- content[2] = flagBuf;
- content[3] = chanuser_row[2];
- table_add(table, content);
- }
- }
- //send the table
- char **table_lines = table_end(table);
- for(i = 0; i < table->entrys; i++) {
- reply(textclient, user, table_lines[i]);
- }
- if(!match_count)
- reply(textclient, user, "NS_TABLE_NONE");
- if(chanmatch) {
- reply(textclient, user, "NS_MYACCESS_COUNT_MATCH", auth, total_count, owner_count, match_count, chanmatch);
- } else {
- reply(textclient, user, "NS_MYACCESS_COUNT", auth, total_count, owner_count);
- }
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no args
-*/
-
-CMD_BIND(neonserv_cmd_netinfo) {
- reply(getTextBot(), user, "NS_NETINFO_HEADER");
- char tmp[MAXLEN];
- struct Table *table;
- table = table_init(2, 18, 0);
- char *content[2];
-
- content[0] = get_language_string(user, "NS_NETINFO_UPTIME");
- content[1] = timeToStr(user, (time(0) - start_time), 3, tmp);
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_BOTS");
- struct ClientSocket *cclient;
- int bot_count = 0, connected_bot_count = 0;
- float traffic_in = 0, traffic_out = 0;
- for(cclient = getBots(0, NULL); cclient; cclient = getBots(0, cclient)) {
- bot_count++;
- if(cclient->flags & SOCKET_FLAG_READY)
- connected_bot_count++;
- traffic_in += cclient->traffic_in;
- traffic_out += cclient->traffic_out;
- }
- sprintf(tmp, "%d (%d connected)", bot_count, connected_bot_count);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_TRAFFIC");
- sprintf(tmp, "in: %.2f kb out: %.2f kb", traffic_in / 1024, traffic_out / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- int channel_count = getChannelCount();
- float channel_memory = channel_count * sizeof(struct ChanNode);
- int channel_ban_count = getChanBanCount();
- float channel_ban_memory = channel_ban_count * sizeof(struct BanNode);
- int user_count = getUserCount();
- float user_memory = user_count * sizeof(struct UserNode);
- int chanuser_count = getChanUserCount();
- float chanuser_memory = chanuser_count * sizeof(struct ChanUser);
- float total_memory = channel_memory + channel_ban_memory + user_memory + chanuser_memory;
-
- content[0] = get_language_string(user, "NS_NETINFO_CACHE");
- sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_CHANNEL");
- sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", channel_count, channel_memory / 1024, channel_count, sizeof(struct ChanNode), channel_memory / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN");
- sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", channel_ban_count, channel_ban_memory / 1024, channel_ban_count, sizeof(struct BanNode), channel_ban_memory / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_USER");
- sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", user_count, user_memory / 1024, user_count, sizeof(struct UserNode), user_memory / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_CHANUSER");
- sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", chanuser_count, chanuser_memory / 1024, chanuser_count, sizeof(struct ChanUser), chanuser_memory / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SHOW TABLE STATUS");
- res = mysql_use();
- int mysql_entrys[4];
- float mysql_length[5];
- total_memory = 0;
- mysql_entrys[0] = 0; mysql_entrys[1] = 0; mysql_entrys[2] = 0; mysql_entrys[3] = 0;
- mysql_length[0] = 0; mysql_length[1] = 0; mysql_length[2] = 0; mysql_length[3] = 0; mysql_length[4] = 0;
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(!stricmp(row[0], "channels")) {
- mysql_entrys[0] = atoi(row[4]);
- mysql_length[0] = atof(row[6]);
- total_memory += atof(row[6]);
- } else if(!stricmp(row[0], "bans")) {
- mysql_entrys[1] = atoi(row[4]);
- mysql_length[1] = atof(row[6]);
- total_memory += atof(row[6]);
- } else if(!stricmp(row[0], "users")) {
- mysql_entrys[2] = atoi(row[4]);
- mysql_length[2] = atof(row[6]);
- total_memory += atof(row[6]);
- } else if(!stricmp(row[0], "chanusers")) {
- mysql_entrys[3] = atoi(row[4]);
- mysql_length[3] = atof(row[6]);
- total_memory += atof(row[6]);
- } else {
- mysql_length[4] += atof(row[6]);
- total_memory += atof(row[6]);
- }
- }
-
- content[0] = get_language_string(user, "NS_NETINFO_DATABASE");
- sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_CHANNEL");
- sprintf(tmp, "%d %.2f kB", mysql_entrys[0], mysql_length[0] / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN");
- sprintf(tmp, "%d %.2f kB", mysql_entrys[1], mysql_length[1] / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_USER");
- sprintf(tmp, "%d %.2f kB", mysql_entrys[2], mysql_length[2] / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_CHANUSER");
- sprintf(tmp, "%d %.2f kB", mysql_entrys[3], mysql_length[3] / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_OTHER");
- sprintf(tmp, "* %.2f kB", mysql_length[4] / 1024);
- content[1] = tmp;
- table_add(table, content);
-
- if(strcmp(revision, ""))
- sprintf(tmp, "%s (%s)", NEONSERV_VERSION, revision);
- else
- strcpy(tmp, NEONSERV_VERSION);
- content[0] = get_language_string(user, "NS_NETINFO_VERSION");
- content[1] = tmp;
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_COMPILER");
- content[1] = build_language_string(user, tmp, "NS_NETINFO_COMPILER_VALUE", COMPILER, creation);
- table_add(table, content);
-
- content[0] = get_language_string(user, "NS_NETINFO_CODE");
- content[1] = build_language_string(user, tmp, "NS_NETINFO_CODE_VALUE", codelines);
- table_add(table, content);
-
- char **table_lines = table_end(table);
- int i;
- for(i = 0; i < table->entrys; i++) {
- reply(getTextBot(), user, table_lines[i]);
- }
- table_free(table);
-}
-
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] target
-* argv[1-*] message
-*/
-
-CMD_BIND(neonserv_cmd_notice) {
- char *message = merge_argv(argv, 1, argc);
- putsock(client, "NOTICE %s :%s", argv[0], message);
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nicks
-*/
-static USERLIST_CALLBACK(neonserv_cmd_op_userlist_lookup);
-static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks);
-
-struct neonserv_cmd_op_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *nicks;
-};
-
-CMD_BIND(neonserv_cmd_op) {
- struct neonserv_cmd_op_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->nicks = strdup(merge_argv(argv, 0, argc));
- get_userlist_with_invisible(chan, neonserv_cmd_op_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_op_userlist_lookup) {
- struct neonserv_cmd_op_cache *cache = data;
- neonserv_cmd_op_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks);
- free(cache->nicks);
- free(cache);
-}
-
-static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks) {
- int total_users = 0, done_users = 0;
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- char *a, *b = nicks;
- do {
- a = strstr(b, " ");
- if(a) *a = '\0';
- total_users++;
- cuser = searchUserByNick(b);
- if(!cuser) {
- //check for an invisible user
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(!stricmp(chanuser->user->nick, b)) {
- cuser = chanuser->user;
- break;
- }
- }
- if(!cuser) continue;
- } else {
- chanuser = getChanUser(cuser, chan);
- if(!chanuser) continue;
- }
- done_users++;
- if(chanuser->flags & CHANUSERFLAG_OPPED) continue;
- modeBufferOp(modeBuf, b);
- if(a) {
- b = a+1;
- }
- } while(a);
- freeModeBuffer(modeBuf);
- if(done_users == total_users)
- reply(textclient, user, "NS_OP_DONE", chan->name);
- else
- reply(textclient, user, "NS_OP_FAIL", client->user->nick);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] "force"
-* argv[1] (optional) nick mask
-*/
-static USERLIST_CALLBACK(neonserv_cmd_opall_userlist_lookup);
-static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask);
-
-struct neonserv_cmd_opall_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *nickmask;
-};
-
-CMD_BIND(neonserv_cmd_opall) {
- if(!argc || strcmp(argv[0], "FORCE")) {
- reply(getTextBot(), user, "NS_OPALL_SECURITY", chan->name);
- return;
- }
- struct neonserv_cmd_opall_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- if(argc > 1) {
- cache->nickmask = strdup(argv[1]);
- } else
- cache->nickmask = NULL;
- get_userlist_with_invisible(chan, neonserv_cmd_opall_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_opall_userlist_lookup) {
- struct neonserv_cmd_opall_cache *cache = data;
- neonserv_cmd_opall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask);
- if(cache->nickmask)
- free(cache->nickmask);
- free(cache);
-}
-
-static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask) {
- int done_users = 0;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(nickmask && match(nickmask, chanuser->user->nick)) continue;
- if(chanuser->flags & CHANUSERFLAG_OPPED) continue;
- modeBufferOp(modeBuf, chanuser->user->nick);
- done_users++;
- }
- freeModeBuffer(modeBuf);
- reply(textclient, user, "NS_OPALL_DONE", done_users, chan->name);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] time
-* argv[1-*] match
-*/
-
-CMD_BIND(neonserv_cmd_oplog) {
- char *str_match;
- int duration = (argc ? strToTime(user, argv[0]) : 0);
- if(argc > (duration ? 1 : 0))
- str_match = merge_argv(argv, (duration ? 1 : 0), argc);
- else
- str_match = "";
- if(!duration) duration = (60*60*24);
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `godlog_time`, `user_user`, `channel_name`, `godlog_cmd` FROM `godlog` LEFT JOIN `channels` ON `godlog_cid` = `channel_id` LEFT JOIN `users` ON `godlog_uid` = `user_id` WHERE `godlog_time` > '%lu' ORDER BY `godlog_time` ASC", ((unsigned long) time(0) - duration));
- res = mysql_use();
- int skip = mysql_num_rows(res) - 100;
- int count = 0;
- char timeBuf[50];
- struct tm *timeinfo;
- time_t event_time;
- if(skip < 0) skip = 0;
- reply(getTextBot(), user, "NS_EVENTS_HEADER");
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(skip) {
- skip--;
- continue;
- }
- if(*str_match && match(str_match, row[3])) continue;
- count++;
- event_time = (time_t) atol(row[0]);
- timeinfo = localtime(&event_time);
- strftime(timeBuf, 80, "%X %x", timeinfo);
- reply(getTextBot(), user, "[%s] [%s%s%s]: %s", timeBuf, row[1], (row[2] ? ":" : ""), (row[2] ? row[2] : ""), row[3]);
- }
- reply(getTextBot(), user, "NS_TABLE_COUNT", count);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no parameters
-*/
-static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup);
-static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan);
-
-struct neonserv_cmd_peek_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
-};
-
-CMD_BIND(neonserv_cmd_peek) {
- struct neonserv_cmd_peek_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- get_userlist_with_invisible(chan, neonserv_cmd_peek_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup) {
- struct neonserv_cmd_peek_cache *cache = data;
- neonserv_cmd_peek_async1(cache->client, cache->textclient, cache->user, chan);
- free(cache);
-}
-
-static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan) {
- reply(textclient, user, "NS_PEEK_HEADER", chan->name);
- reply(textclient, user, "NS_PEEK_TOPIC", chan->topic);
- char tmpStr[MAXLEN];
- getModeString(chan->modes, tmpStr);
- reply(textclient, user, "NS_PEEK_MODES", tmpStr);
- struct ChanUser *chanuser;
- int op_count = 0, voice_count = 0, normal_count = 0, invi_count = 0;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(chanuser->flags & CHANUSERFLAG_OPPED)
- op_count++;
- else if(chanuser->flags & CHANUSERFLAG_VOICED)
- voice_count++;
- else if(chanuser->flags & CHANUSERFLAG_VOICED)
- invi_count++;
- else
- normal_count++;
- }
- reply(textclient, user, "NS_PEEK_USERS", op_count+voice_count+invi_count+normal_count, op_count, voice_count, normal_count, invi_count);
- int tmpStrPos = 0;
- int headerlen = 10 + strlen(user->nick);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(chanuser->flags & CHANUSERFLAG_OPPED) {
- if(tmpStrPos + headerlen + strlen(chanuser->user->nick) + 2 >= 512) {
- //clear buffer
- reply(textclient, user, "%s", tmpStr);
- tmpStrPos = 0;
- }
- tmpStrPos += sprintf(tmpStr + tmpStrPos, (tmpStrPos ? ", %s" : "%s"), chanuser->user->nick);
- }
- }
- if(tmpStrPos) {
- reply(textclient, user, "%s", tmpStr);
- }
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] raw
-*/
-
-CMD_BIND(neonserv_cmd_raw) {
- char *raw = merge_argv(argv, 0, argc);
- putsock(client, "%s", raw);
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - channel
-*/
-CMD_BIND(neonserv_cmd_recover) {
- MYSQL_RES *res;
- MYSQL_ROW row, row2;
- char *channel = argv[0];
- if(!is_valid_chan(channel)) {
- reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
- return;
- }
- printf_mysql_query("SELECT `botid`, `bot_channels`.`id` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick);
- return;
- }
- int chanid;
- printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chanid = atoi(row[0]);
- } else {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger` FROM `bots` WHERE `botclass` = '%d' ORDER BY `register_priority` DESC", client->botid);
- res = mysql_use();
- int botid = 0;
- char *bottrigger;
- while ((row = mysql_fetch_row(res)) != NULL) {
- //check channel count
- printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]);
- row2 = mysql_fetch_row(mysql_use());
- if(atoi(row2[0]) < atoi(row[1])) {
- botid = atoi(row[0]);
- bottrigger = row[2];
- break;
- }
- }
- if(!botid) {
- reply(getTextBot(), user, "NS_REGISTER_FULL");
- return;
- }
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->clientid == botid)
- break;
- }
- if(bot) {
- putsock(bot, "JOIN %s", channel);
- } else
- reply(getTextBot(), user, "NS_REGISTER_DISCONNECTED");
- printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', '%s')", botid, chanid, bottrigger);
- reply(getTextBot(), user, "NS_RECOVER_DONE", channel);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - channel
-* argv[0/1] - nick / *auth
-*/
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup);
-static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup);
-static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth);
-
-struct neonserv_cmd_register_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
- char *channel;
-};
-
-CMD_BIND(neonserv_cmd_register) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- char *channel = argv[0];
- if(!is_valid_chan(channel)) {
- reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
- return;
- }
- printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `bot_channels`.`chanid` = `channels`.`channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick);
- return;
- }
- //check own access
- if(argv[1][0] == '*') {
- //we've got an auth
- argv[1]++;
- printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[1]));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- neonserv_cmd_register_async1(client, getTextBot(), user, chan, event, channel, row[0]);
- } else {
- //we need to create a new user...
- //but first lookup the auth to check if it really exists
- struct neonserv_cmd_register_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[1]);
- cache->channel = strdup(channel);
- lookup_authname(argv[1], neonserv_cmd_register_auth_lookup, cache);
- }
- } else {
- struct UserNode *cuser = getUserByNick(argv[1]);
- if(!cuser) {
- cuser = createTempUser(argv[1]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_register_async1(client, getTextBot(), user, chan, event, channel, cuser->auth);
- } else {
- struct neonserv_cmd_register_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[1]);
- cache->channel = strdup(channel);
- get_userauth(cuser, neonserv_cmd_register_nick_lookup, cache);
- }
- }
-}
-
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup) {
- struct neonserv_cmd_register_cache *cache = data;
- if(!exists) {
- //AUTH_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick);
- } else
- neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, auth);
- free(cache->channel);
- free(cache->nick);
- free(cache);
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup) {
- struct neonserv_cmd_register_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, user->auth);
- free(cache->channel);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row, row2;
- int userid, adminid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL)
- adminid = atoi(row[0]);
- else
- adminid = 0;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- } else {
- printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth));
- userid = (int) mysql_insert_id(mysql_conn);
- }
- printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger` FROM `bots` WHERE `botclass` = '%d' ORDER BY `register_priority` DESC", client->botid);
- res = mysql_use();
- int botid = 0;
- char *bottrigger;
- while ((row = mysql_fetch_row(res)) != NULL) {
- //check channel count
- printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]);
- row2 = mysql_fetch_row(mysql_use());
- if(atoi(row2[0]) < atoi(row[1])) {
- botid = atoi(row[0]);
- bottrigger = row[2];
- break;
- }
- }
- if(!botid) {
- reply(textclient, user, "NS_REGISTER_FULL");
- return;
- }
- int chanid;
- printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chanid = atoi(row[0]);
- printf_mysql_query("UPDATE `channels` SET `channel_registered` = UNIX_TIMESTAMP(), `channel_registrator` = '%d' WHERE `channel_id` = '%d'", adminid, chanid);
- } else {
- printf_mysql_query("INSERT INTO `channels` (`channel_name`, `channel_registered`, `channel_registrator`) VALUES ('%s', UNIX_TIMESTAMP(), '%d')", escape_string(channel), adminid);
- chanid = (int) mysql_insert_id(mysql_conn);
- }
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->clientid == botid)
- break;
- }
- if(bot) {
- putsock(bot, "JOIN %s", channel);
- } else
- reply(textclient, user, "NS_REGISTER_DISCONNECTED");
- printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', '%s')", botid, chanid, bottrigger);
- printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d'", chanid);
- printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chanid, userid, 500);
- reply(textclient, user, "NS_REGISTER_DONE", channel, auth);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] language tag
-*/
-
-CMD_BIND(neonserv_cmd_reloadlang) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `text`, `lang` FROM `language` WHERE `ident` = 'name' AND `lang` = '%s'", escape_string(argv[0]));
- res = mysql_use();
- if((row = mysql_fetch_row(res)) != NULL) {
- load_language(row[1], row[0]);
- reply(getTextBot(), user, "NS_RELOADLANG_DONE", row[0], row[1]);
- } else {
- reply(getTextBot(), user, "NS_RELOADLANG_UNKNOWN", argv[0]);
- }
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - usermask
-* argv[1] - min access
-* argv[2] - max access
-*/
-static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup);
-static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access);
-
-struct neonserv_cmd_resync_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- char *usermask;
- int min_access;
- int max_access;
-};
-
-CMD_BIND(neonserv_cmd_resync) {
- int min_access = 0, max_access = 500;
- char *usermask = NULL;
- if(argc > 0)
- usermask = argv[0];
- if(argc > 2) {
- min_access = atoi(argv[1]);
- max_access = atoi(argv[2]);
- }
- struct neonserv_cmd_resync_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->usermask = (usermask ? strdup(usermask) : NULL);
- cache->min_access = min_access;
- cache->max_access = max_access;
- get_userlist_with_invisible(chan, neonserv_cmd_resync_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup) {
- struct neonserv_cmd_resync_cache *cache = data;
- neonserv_cmd_resync_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access);
- if(cache->usermask)
- free(cache->usermask);
- free(cache);
-}
-
-static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access) {
- MYSQL_RES *res;
- MYSQL_ROW row, defaults = NULL;
- int i;
- int resync_op = 1;
- int resync_voice = 1;
- if(usermask && usermask[0] == '@') {
- resync_voice = 0;
- usermask++;
- if(!*usermask) usermask = NULL;
- } else if(usermask && usermask[0] == '+') {
- resync_op = 0;
- usermask++;
- if(!*usermask) usermask = NULL;
- }
- struct ChanUser *chanuser;
- int db_enfops, db_enfvoice;
- printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- row = mysql_fetch_row(mysql_use());
- if(row[0] == NULL || row[1] == NULL) {
- printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
- defaults = mysql_fetch_row(mysql_use());
- }
- db_enfops = atoi((row[0] ? row[0] : defaults[0]));
- db_enfvoice = atoi((row[1] ? row[1] : defaults[1]));
- printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id);
- res = mysql_use();
- char *db_users[mysql_num_rows(res)];
- int db_access[mysql_num_rows(res)];
- int db_flags[mysql_num_rows(res)];
- int db_count = 0;
- while ((row = mysql_fetch_row(res)) != NULL) {
- db_users[db_count] = row[1];
- db_access[db_count] = atoi(row[0]);
- db_flags[db_count] = atoi(row[2]);
- db_count++;
- }
- int caccess, cflags;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- caccess = 0;
- cflags = 0;
- if((chanuser->user->flags & USERFLAG_ISAUTHED)) {
- for(i = 0; i < db_count; i++) {
- if(!stricmp(db_users[i], chanuser->user->auth)) {
- caccess = db_access[i];
- cflags = db_flags[i];
- break;
- }
- }
- }
- if((usermask && *usermask && match(usermask, row[1])) || caccess < min_access || caccess > max_access) continue;
- if(caccess >= db_enfops) {
- if(!(chanuser->flags & CHANUSERFLAG_OPPED) && resync_op)
- modeBufferOp(modeBuf, chanuser->user->nick);
- } else if(caccess >= db_enfvoice) {
- if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
- modeBufferDeop(modeBuf, chanuser->user->nick);
- if(!(chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice)
- modeBufferVoice(modeBuf, chanuser->user->nick);
- } else {
- if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
- modeBufferDeop(modeBuf, chanuser->user->nick);
- if((chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
- modeBufferDevoice(modeBuf, chanuser->user->nick);
- }
-
- }
- freeModeBuffer(modeBuf);
- reply(textclient, user, "NS_RESYNC_DONE", chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] target
-* argv[1-*] message
-*/
-
-CMD_BIND(neonserv_cmd_say) {
- char *message = merge_argv(argv, 1, argc);
- putsock(client, "PRIVMSG %s :%s", argv[0], message);
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-#define CMD_SEARCH_FLAG_HAS_NODELETE 0x01
-#define CMD_SEARCH_FLAG_NOT_NODELETE 0x02
-#define CMD_SEARCH_FLAG_HAS_SUSPENDED 0x04
-#define CMD_SEARCH_FLAG_NOT_SUSPENDED 0x08
-
-struct neonserv_cmd_search_criteria {
- char *name;
- char *registrar;
- unsigned int flags : 16;
- unsigned int unvisited;
- unsigned int registered;
- unsigned int limit : 16;
-};
-
-CMD_BIND(neonserv_cmd_search) {
- //ok parse the criterias
- struct neonserv_cmd_search_criteria *criteria = malloc(sizeof(*criteria));
- if (!criteria) {
- perror("malloc() failed");
- return;
- }
- memset(criteria, 0, sizeof(*criteria));
- criteria->limit = 50;
- int i, show_chans = 0, positive;
- if(!stricmp(argv[0], "print")) {
- show_chans = 1;
- }
- for(i = 1; i < argc; i += 2) {
- if(argc <= i+1) {
- reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT");
- return;
- }
- if(!stricmp(argv[i], "name")) criteria->name = argv[i+1];
- else if(!stricmp(argv[i], "registrar")) criteria->registrar = argv[i+1];
- else if(!stricmp(argv[i], "unvisited")) criteria->unvisited = strToTime(user, argv[i+1]);
- else if(!stricmp(argv[i], "registered")) criteria->registered = strToTime(user, argv[i+1]);
- else if(!stricmp(argv[i], "flags")) {
- if(argv[i+1][0] == '+') {
- positive = 1;
- argv[i+1]++;
- } else if(argv[i+1][0] == '-') {
- positive = 0;
- argv[i+1]++;
- } else
- positive = 1;
- if(!stricmp(argv[i+1], "nodelete")) {
- if(positive)
- criteria->flags |= CMD_SEARCH_FLAG_HAS_NODELETE;
- else
- criteria->flags |= CMD_SEARCH_FLAG_NOT_NODELETE;
- } else if(!stricmp(argv[i+1], "suspended")) {
- if(positive)
- criteria->flags |= CMD_SEARCH_FLAG_HAS_SUSPENDED;
- else
- criteria->flags |= CMD_SEARCH_FLAG_NOT_SUSPENDED;
- }
- }
- else if(!stricmp(argv[i], "limit")) {
- criteria->limit = atoi(argv[i+1]);
- }
- }
- int matches = 0;
- reply(getTextBot(), user, "NS_SEARCH_HEADER");
- MYSQL_RES *res, *res2;
- MYSQL_ROW row, row2;
- printf_mysql_query("SELECT `channel_name`, `user_user`, `channel_registered`, `channel_nodelete`, `suspended`, `channel_id` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botid` = '%d'", client->botid);
- res = mysql_use();
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(show_chans && matches == criteria->limit) {
- //too many
- break;
- }
- if(criteria->name && match(criteria->name, row[0])) continue;
- if(criteria->registrar && row[1] && match(criteria->registrar, row[1])) continue;
- if(criteria->unvisited) {
- printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' ORDER BY `chanuser_seen` DESC LIMIT 1", row[5]);
- res2 = mysql_use();
- row2 = mysql_fetch_row(res);
- if(!row2) continue;
- if((time(0) - atoi(row2[0])) < criteria->unvisited) continue;
- }
- if(criteria->registered && (time(0) - atoi(row[2])) < criteria->registered) continue;
-
- if((criteria->flags & CMD_SEARCH_FLAG_HAS_NODELETE) && strcmp(row[3], "1")) continue;
- if((criteria->flags & CMD_SEARCH_FLAG_NOT_NODELETE) && strcmp(row[3], "0")) continue;
- if((criteria->flags & CMD_SEARCH_FLAG_HAS_SUSPENDED) && strcmp(row[4], "1")) continue;
- if((criteria->flags & CMD_SEARCH_FLAG_NOT_SUSPENDED) && strcmp(row[4], "0")) continue;
- matches++;
- //output
- if(show_chans) {
- reply(getTextBot(), user, "%s", row[0]);
- }
- }
- reply(getTextBot(), user, "NS_TABLE_COUNT", matches);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-typedef char* neonserv_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *argument);
-static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
-
-#define NS_VALID_FUNCTION 0x01
-#define NS_VALID_STRING 0x02
-#define NS_VALID_ACCESS 0x04
-#define NS_VALID_NO501 0x08
-#define NS_VALID_OPTIONS 0x10
-#define NS_VALID_NUMERIC 0x20
-#define NS_VALID_BOOLEAN 0x40
-
-#define NS_HAS_OPT 0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */
-#define NS_HAS_HELP 0x200 /* help (SET_HELP_{NAME}) - only shown if help is requested */
-
-static const struct {
- const char *setting;
- const char *chanfield;
- unsigned int valid;
- void *parameter;
-} channel_settings[] = {
- {"TRIGGER", NULL, NS_VALID_FUNCTION, neonserv_cmd_set_trigger},
- {"DEFAULTTOPIC", "channel_defaulttopic", NS_VALID_STRING, NULL},
- {"TOPICMASK", "channel_topicmask", NS_VALID_STRING, NULL},
- {"ADVANCEDTOPIC", "channel_exttopic", NS_VALID_BOOLEAN | NS_HAS_OPT, NULL},
- {"GREETING", "channel_greeting", NS_VALID_STRING, NULL},
- {"USERGREETING", "channel_usergreeting", NS_VALID_STRING, NULL},
- {"USERINFO", "channel_userinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"WIPEINFO", "channel_wipeinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"MODES", "channel_modes", NS_VALID_FUNCTION, neonserv_cmd_set_modes},
- {"INVITEME", "channel_getinvite", NS_VALID_ACCESS, NULL},
- {"GIVEOPS", "channel_getop", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"GIVEVOICE", "channel_getvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"ENFOPS", "channel_canop", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"ENFVOICE", "channel_canvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"KICK", "channel_cankick", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"BAN", "channel_canban", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"STATICBAN", "channel_staticban", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"PUBCMD", "channel_pubcmd", NS_VALID_ACCESS, NULL},
- {"ENFMODES", "channel_enfmodes", NS_VALID_ACCESS, NULL},
- {"ENFTOPIC", "channel_enftopic", NS_VALID_ACCESS, NULL},
- {"TOPICSNARF", "channel_topicsnarf", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"CHANGETOPIC", "channel_changetopic", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"SETTERS", "channel_setters", NS_VALID_ACCESS | NS_VALID_NO501 | NS_HAS_HELP, NULL},
- {"ADDUSER", "channel_canadd", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"DELUSER", "channel_candel", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"CLVL", "channel_canclvl", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"RESYNC", "channel_canresync", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"SUSPEND", "channel_cansuspend", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
- {"NOTICEUSERS", "channel_notice", NS_VALID_ACCESS, NULL},
- {"NOTICEREACTION", "channel_noticereaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
- {"CTCPUSERS", "channel_ctcp", NS_VALID_ACCESS, NULL},
- {"CTCPREACTION", "channel_ctcpreaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
- {"PROTECT", "channel_protect", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
- {"TOYS", "channel_toys", NS_VALID_OPTIONS | NS_HAS_OPT, "3"},
- {"DYNLIMIT", "channel_dynlimit", NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit},
- {"NODELETE", "channel_nodelete", NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete},
- {NULL, NULL, 0, NULL}
-};
-
-#define MAX_QUERY_LEN 1024
-CMD_BIND(neonserv_cmd_set) {
- int i, j;
- if(argc && !strcmp(argv[0], "defaults")) {
- //reset channel settings
- int uaccess = getChannelAccess(user, chan, 0);
- if(uaccess < 500) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name);
- return;
- }
- }
- int seed = 0;
- char *tmp;
- static char defaultskey[16];
- 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));
- sprintf(defaultskey, "%08x", seed);
- if(argc > 1 && !strcmp(argv[1], defaultskey)) {
- char query[MAX_QUERY_LEN];
- int querypos = 0;
- i = 0;
- while(channel_settings[i].setting) {
- if(channel_settings[i].chanfield)
- querypos += sprintf(query + querypos, "`%s` = NULL, ", channel_settings[i].chanfield);
- i++;
- }
- if(querypos) {
- query[querypos-2] = '\0';
- }
- printf_mysql_query("UPDATE `channels` SET %s WHERE `channel_id` = '%d'", query, chan->channel_id);
- reply(getTextBot(), user, "NS_SET_DEFAULTS_DONE", chan->name);
- logEvent(event);
- } else {
- reply(getTextBot(), user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey);
- }
- } else if(argc && strcmp(argv[0], "help")) {
- //find the correct command
- i = 0;
- j = 0;
- char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
- while(channel_settings[i].setting) {
- if(!stricmp(channel_settings[i].setting, argv[0])) {
- //setting found
- if(channel_settings[i].valid & NS_VALID_FUNCTION) {
- neonserv_cmd_set_function *func = channel_settings[i].parameter;
- func(client, user, chan, event, channel_settings[i].setting, args);
- } else {
- neonserv_cmd_set_setting(client, user, chan, event, i, args);
- }
- j = 1;
- break;
- }
- i++;
- }
- if(j == 0) {
- //unknown setting
- reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]);
- }
- } else {
- char query[MAX_QUERY_LEN], *value, *org_value, *tmp, nameBuf[64];
- int querypos = 0;
- MYSQL_RES *res, *defaults_res;
- MYSQL_ROW row, defaults;
- struct Table *table;
- char *content[2];
- i = 0;
- while(channel_settings[i].setting) {
- if(channel_settings[i].chanfield)
- querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield);
- i++;
- }
- table = table_init(2, i, 0);
- table_set_bold(table, 0, 1);
- printf_mysql_query("SELECT `channel_id` %s FROM `channels` WHERE `channel_name` = 'defaults'", query);
- defaults_res = mysql_use();
- defaults = mysql_fetch_row(defaults_res);
- printf_mysql_query("SELECT `channel_name` %s FROM `channels` WHERE `channel_id` = '%d'", query, chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- i = 0;
- j = 0;
- reply(getTextBot(), user, "NS_SET_HEADER", chan->name);
- while(channel_settings[i].setting) {
- if(channel_settings[i].chanfield) {
- j++;
- org_value = (row[j] ? row[j] : defaults[j]);
- } else if(channel_settings[i].valid & NS_VALID_FUNCTION) {
- neonserv_cmd_set_function *func = channel_settings[i].parameter;
- org_value = func(client, user, chan, event, NULL, NULL);
- } else
- org_value = "0";
- value = org_value;
- if(channel_settings[i].valid & NS_VALID_BOOLEAN) {
- if(!strcmp(value, "0"))
- value = get_language_string(user, "NS_SET_OFF");
- else
- value = get_language_string(user, "NS_SET_ON");
- }
- strcpy(query, value);
- querypos = strlen(query);
- if(channel_settings[i].valid & NS_HAS_OPT) {
- sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[i].setting, org_value);
- tmp = get_language_string(user, nameBuf);
- if(tmp) {
- querypos += sprintf(query+querypos, " - %s", tmp);
- }
- }
- if(argc && channel_settings[i].valid & NS_HAS_HELP) {
- sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[i].setting);
- tmp = get_language_string(user, nameBuf);
- if(tmp) {
- querypos += sprintf(query+querypos, " - %s", tmp);
- }
- }
- content[0] = (char*)channel_settings[i].setting;
- content[1] = query;
- table_add(table, content);
- i++;
- }
- char **table_lines = table_end(table);
- for(i = 0; i < table->entrys; i++) {
- reply(getTextBot(), user, table_lines[i]);
- }
- table_free(table);
- }
-}
-
-static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *args) {
- char *value;
- char nameBuf[64];
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_settings[setting].chanfield);
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(args) {
- //change the channel setting
- //check the new argument
- int valid = channel_settings[setting].valid;
- if(valid & NS_VALID_STRING) {
- if(!strcmp(args, "*")) {
- args = "";
- }
- }
- if(valid & NS_VALID_ACCESS) {
- int caccess = atoi(args);
- int max = ((valid & NS_VALID_NO501) ? 500 : 501);
- if(caccess < 0 || caccess > max) {
- reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
- return;
- }
- int uaccess = getChannelAccess(user, chan, 0);
- if(uaccess == 500) uaccess++;
- if(atoi(value) > uaccess) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_CANNOT_SET");
- return;
- }
- }
- if(caccess > uaccess) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_BADLEVEL");
- return;
- }
- }
- sprintf(nameBuf, "%d", caccess);
- args = nameBuf;
- }
- if(valid & NS_VALID_OPTIONS) {
- int options = atoi((char *) channel_settings[setting].parameter);
- int coption = atoi(args);
- if(coption < 0 || coption >= options) {
- reply(getTextBot(), user, "NS_SET_INVALID_OPTION", coption);
- int i;
- int nameBufPos = 0;
- if(valid & NS_HAS_OPT) {
- for(i = 0; i < options; i++) {
- sprintf(nameBuf, "NS_SET_OPTION_%s_%d", channel_settings[setting].setting, i);
- reply(getTextBot(), user, "\002%d\002 - %s", i, get_language_string(user, nameBuf));
- }
- } else {
- for(i = 0; i < options; i++) {
- nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i);
- }
- if(nameBufPos) {
- nameBuf[nameBufPos-2] = '\0';
- reply(getTextBot(), user, nameBuf);
- }
- }
- return;
- }
- }
- if(valid & NS_VALID_NUMERIC) {
- sprintf(nameBuf, "%d", atoi(args));
- args = nameBuf;
- }
- if(valid & NS_VALID_BOOLEAN) {
- if(!strcmp(args, "0") || !stricmp(args, "off") || !stricmp(args, get_language_string(user, "NS_SET_OFF"))) {
- args = "0";
- } else if(!strcmp(args, "1") || !stricmp(args, "on") || !stricmp(args, get_language_string(user, "NS_SET_ON"))) {
- args = "1";
- } else {
- reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", args);
- return;
- }
- }
- //valid - set it
- value = args;
- printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, escape_string(value), chan->channel_id);
- logEvent(event);
- }
- reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value);
- if(channel_settings[setting].valid & NS_HAS_HELP) {
- sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[setting].setting);
- reply(getTextBot(), user, " %s", get_language_string(user, nameBuf));
- }
-}
-
-static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *trigger;
- //get current trigger
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `trigger` FROM `bot_channels` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid);
- res = mysql_use();
- row = mysql_fetch_row(res);
- trigger = row[0];
- if(argument) {
- int uaccess = getChannelAccess(user, chan, 0);
- if(uaccess < 500) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_SET_TRIGGER_OWNER", chan->name);
- return NULL;
- }
- }
- if(strlen(argument) > 15)
- argument[15] = '\0';
- printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `chanid` = '%d' AND `botid` = '%d'", escape_string(argument), chan->channel_id, client->clientid);
- trigger = argument;
- changeChannelTrigger(client->botid, chan, trigger);
- logEvent(event);
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, trigger);
- }
- return trigger;
-}
-
-static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *value;
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(argument) {
- //change the channel setting
- //TODO: parse, check and set modelock
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, value);
- }
- return value;
-}
-
-static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *value;
- char tmp[64];
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(argument) {
- //change the channel setting
- sprintf(tmp, "%d", atoi(argument));
- argument = tmp;
- printf_mysql_query("UPDATE `channels` SET `channel_dynlimit` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
- if(strcmp(argument, "0"))
- putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument)));
- else if(isModeSet(chan->modes, 'l'))
- putsock(client, "MODE %s -l", chan->name);
- value = argument;
- logEvent(event);
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, value);
- }
- return value;
-}
-
-static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
- char *value;
- //get current value
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row[0] == NULL) {
- printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- row = mysql_fetch_row(res);
- }
- value = row[0];
- if(argument && isGodMode(user)) {
- //change the channel setting
- if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
- argument = "0";
- } else if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
- argument = "1";
- } else {
- reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument);
- return NULL;
- }
- printf_mysql_query("UPDATE `channels` SET `channel_nodelete` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
- event->flags |= CMDFLAG_OPLOG;
- value = argument;
- logEvent(event);
- }
- if(setting) {
- reply(getTextBot(), user, "\002%s\002 %s", setting, value);
- }
- return value;
-}
-
-#undef MAX_QUERY_LEN
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-* argv[1] - global access
-*/
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_setaccess_auth_lookup);
-static USERAUTH_CALLBACK(neonserv_cmd_setaccess_nick_lookup);
-static void neonserv_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int access);
-
-struct neonserv_cmd_setaccess_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- int access;
- char *nick;
-};
-
-CMD_BIND(neonserv_cmd_setaccess) {
- int caccess;
- MYSQL_RES *res;
- MYSQL_ROW row;
- caccess = atoi(argv[1]);
- if(caccess < 0 || caccess > 1000) {
- reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
- return;
- }
- printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL || atoi(row[0]) < caccess) {
- reply(getTextBot(), user, "NS_ACCESS_OUTRANKED");
- return;
- }
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0]));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- neonserv_cmd_setaccess_async1(client, getTextBot(), user, event, argv[0], row[0], caccess);
- } else {
- //we need to create a new user...
- //but first lookup the auth to check if it really exists
- struct neonserv_cmd_setaccess_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->access = caccess;
- cache->nick = strdup(argv[0]);
- lookup_authname(argv[0], neonserv_cmd_setaccess_auth_lookup, cache);
- }
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_setaccess_async1(client, getTextBot(), user, event, argv[0], cuser->auth, caccess);
- } else {
- struct neonserv_cmd_setaccess_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->access = caccess;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_setaccess_nick_lookup, cache);
- }
- }
-}
-
-static AUTHLOOKUP_CALLBACK(neonserv_cmd_setaccess_auth_lookup) {
- struct neonserv_cmd_setaccess_cache *cache = data;
- if(!exists) {
- //AUTH_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick);
- } else
- neonserv_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, cache->nick, auth, cache->access);
- free(cache->nick);
- free(cache);
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_setaccess_nick_lookup) {
- struct neonserv_cmd_setaccess_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, user->nick, user->auth, cache->access);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int caccess) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `user_id`, `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- if(atoi(row[1]) != caccess)
- printf_mysql_query("UPDATE `users` SET `user_access` = '%d' WHERE `user_id` = '%s'", caccess, row[0]);
- } else {
- printf_mysql_query("INSERT INTO `users` (`user_user`, `user_access`) VALUES ('%s', '%d')", escape_string(auth), caccess);
- }
- reply(textclient, user, "NS_SETACCESS_DONE", auth, caccess);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup);
-static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
-
-struct neonserv_cmd_suspend_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
-};
-
-CMD_BIND(neonserv_cmd_suspend) {
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
- } else {
- struct neonserv_cmd_suspend_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_suspend_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup) {
- struct neonserv_cmd_suspend_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_suspend_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid, cflags;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(textclient, user, "NS_USER_OUTRANKED", nick);
- return;
- }
- }
- //suspend
- cflags = atoi(row[2]);
- if(cflags & DB_CHANUSER_SUSPENDED) {
- reply(textclient, user, "NS_SUSPEND_ALREADY", nick);
- return;
- }
- cflags |= DB_CHANUSER_SUSPENDED;
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", cflags, row[1]);
- reply(textclient, user, "NS_SUSPEND_DONE", nick, chan->name);
- logEvent(event);
- return;
- }
- }
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* ADVANCEDTOPIC enabled
-* argv[0] topic id
-* argv[1-*] topic
-*
-* ADVANCEDTOPIC disabled
-* argv[0-*] topic
-*/
-
-#define ADVANCEDTOPIC_MAXID 9
-
-CMD_BIND(neonserv_cmd_topic) {
- MYSQL_RES *res;
- MYSQL_ROW row, default_row = NULL;
- int advanced_topic, i;
- char *newtopic;
- char *a,*b;
-
- printf_mysql_query("SELECT `channel_exttopic`, `channel_exttopic_topic`, `channel_topicmask`, `channel_enftopic`, `channel_topicsnarf`, `channel_defaulttopic` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(!row[0] || !row[3] || !row[4]) {
- printf_mysql_query("SELECT `channel_exttopic`, `channel_enftopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'");
- default_row = mysql_fetch_row(mysql_use());
- }
-
- if(row[0] == NULL) {
- advanced_topic = atoi(default_row[0]);
- } else
- advanced_topic = atoi(row[0]);
- if(argc == 0) {
- //default topic!
- putsock(client, "TOPIC %s :%s", chan->name, row[5]);
- reply(getTextBot(), user, "NS_TOPIC_DONE", row[5]);
- logEvent(event);
- return;
- }
- int uaccess = getChannelAccess(user, chan, 0);
- if(uaccess >= atoi((row[3] ? row[3] : default_row[1]))) {
- //just set the topic
- newtopic = merge_argv(argv, 0, argc);
- if(uaccess >= atoi((row[4] ? row[4] : default_row[2]))) {
- //set the default topic
- printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(newtopic), chan->channel_id);
- }
- putsock(client, "TOPIC %s :%s", chan->name, newtopic);
- reply(getTextBot(), user, "NS_TOPIC_DONE", newtopic);
- logEvent(event);
- return;
- }
- if(advanced_topic) {
- char *advtopics[ADVANCEDTOPIC_MAXID];
- int topic_id = 0;
- topic_id = atoi(argv[0]);
- if(!topic_id || topic_id > ADVANCEDTOPIC_MAXID) {
- reply(getTextBot(), user, "NS_EXTTOPIC_INVALID_ID", argv[0]);
- return;
- }
- //parse topics
- i = 0;
- b = row[1];
- while((a = strstr(b, "\n")) != NULL) {
- *a = '\0';
- if(i == ADVANCEDTOPIC_MAXID-1) break;
- advtopics[i++] = b;
- b = a+1;
- }
- advtopics[i++] = b;
- for(;i < ADVANCEDTOPIC_MAXID;i++)
- advtopics[i] = "";
- if(argc < 2) {
- //just show the topic with this id
- reply(getTextBot(), user, "NS_EXTTOPIC_TOPICID", topic_id, advtopics[topic_id-1]);
- return;
- }
- newtopic = merge_argv(argv, 1, argc);
- if(!strcmp(newtopic, "*"))
- newtopic = "";
- advtopics[topic_id-1] = newtopic;
- char topiclist[MAXLEN*2];
- topiclist[0] = '\0';
- int topiclistpos = 0;
- for(i = 0; i < ADVANCEDTOPIC_MAXID; i++) {
- if(topiclistpos + strlen(advtopics[i]) + 2 >= MAXLEN) break;
- topiclistpos += sprintf(topiclist+topiclistpos, (i ? "\n%s" : "%s"), advtopics[i]);
- }
- printf_mysql_query("UPDATE `channels` SET `channel_exttopic_topic` = '%s' WHERE `channel_id` = '%d'", escape_string(topiclist), chan->channel_id);
- //now build the new topic and set it...
- topiclistpos = 0;
- b = row[2];
- while((a = strstr(b, "%")) != NULL) {
- *a = '\0';
- if(isdigit(a[1]) && a[1] - 48 > 0) {
- topiclistpos += sprintf(topiclist + topiclistpos, "%s%s", b, advtopics[a[1] - 49]);
- b = a+2;
- } else {
- topiclistpos += sprintf(topiclist + topiclistpos, "%s%%", b);
- b = a+1;
- }
- }
- topiclistpos += sprintf(topiclist + topiclistpos, "%s", b);
- if(topiclistpos > MAXLEN)
- topiclist[MAXLEN] = '\0';
- putsock(client, "TOPIC %s :%s", chan->name, topiclist);
- reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist);
- logEvent(event);
- } else {
- newtopic = merge_argv(argv, 0, argc);
- char topiclist[MAXLEN*2];
- topiclist[0] = '\0';
- int topiclistpos = 0;
- b = row[2];
- while((a = strstr(b, "*")) != NULL) {
- *a = '\0';
- topiclistpos += sprintf(topiclist + topiclistpos, "%s%s", b, newtopic);
- b = a+1;
- }
- topiclistpos += sprintf(topiclist + topiclistpos, "%s", b);
- if(topiclistpos > MAXLEN)
- topiclist[MAXLEN] = '\0';
- putsock(client, "TOPIC %s :%s", chan->name, topiclist);
- reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist);
- logEvent(event);
- }
-}
-
-#undef ADVANCEDTOPIC_MAXID
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-#define NS_TRACE_CRITERIA_AUTHED 0x01
-#define NS_TRACE_CRITERIA_NUMCHAN 0x02
-
-struct neonserv_cmd_trace_criteria {
- char *mask;
- char *nick;
- char *ident;
- char *host;
- char *account;
- unsigned int flags : 4;
- unsigned int authed : 1;
- unsigned int used_channel : 5; //32 max
- char *channel[10];
- unsigned int numchannels;
- unsigned int limit : 16;
-};
-
-CMD_BIND(neonserv_cmd_trace) {
- //ok parse the criterias
- struct neonserv_cmd_trace_criteria *criteria = malloc(sizeof(*criteria));
- if (!criteria) {
- perror("malloc() failed");
- return;
- }
- memset(criteria, 0, sizeof(*criteria));
- criteria->limit = 50;
- int i, show_user = 0;
- if(!stricmp(argv[0], "print")) {
- show_user = 1;
- }
- for(i = 1; i < argc; i += 2) {
- if(argc <= i+1) {
- reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT");
- return;
- }
- if(!stricmp(argv[i], "mask")) criteria->mask = argv[i+1];
- else if(!stricmp(argv[i], "nick")) criteria->nick = argv[i+1];
- else if(!stricmp(argv[i], "ident")) criteria->ident = argv[i+1];
- else if(!stricmp(argv[i], "host")) criteria->host = argv[i+1];
- else if(!stricmp(argv[i], "account")) criteria->account = argv[i+1];
- else if(!stricmp(argv[i], "authed")) {
- if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) {
- criteria->authed = 1;
- } else if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) {
- criteria->authed = 0;
- } else {
- reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[i+1]);
- return;
- }
- criteria->flags |= NS_TRACE_CRITERIA_AUTHED;
- }
- else if(!stricmp(argv[i], "channel")) criteria->channel[criteria->used_channel++] = argv[i+1];
- else if(!stricmp(argv[i], "numchannels")) {
- criteria->numchannels = atoi(argv[i+1]);
- criteria->flags |= NS_TRACE_CRITERIA_NUMCHAN;
- }
- else if(!stricmp(argv[i], "limit")) {
- criteria->limit = atoi(argv[i+1]);
- }
- }
- char tmp[MAXLEN];
- int matches = 0;
- struct UserNode *cuser;
- reply(getTextBot(), user, "NS_TRACE_HEADER");
- for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) {
- if(show_user && matches == criteria->limit) {
- //too many
- break;
- }
- if(criteria->mask) {
- sprintf(tmp, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
- if(match(criteria->mask, tmp)) continue;
- }
- if(criteria->nick && match(criteria->nick, cuser->nick)) continue;
- if(criteria->ident && match(criteria->ident, cuser->ident)) continue;
- if(criteria->host && match(criteria->host, cuser->host)) continue;
- if(criteria->account && (!(cuser->flags & USERFLAG_ISAUTHED) || match(criteria->account, cuser->auth))) continue;
- if((criteria->flags & NS_TRACE_CRITERIA_AUTHED) && (criteria->authed ^ (cuser->flags & USERFLAG_ISAUTHED))) continue;
- if((criteria->flags & NS_TRACE_CRITERIA_NUMCHAN)) {
- int ccount = 0;
- struct ChanUser *chanuser;
- for(chanuser = getUserChannels(cuser, NULL); chanuser; chanuser = getUserChannels(cuser, chanuser))
- ccount++;
- if(ccount < criteria->numchannels)
- continue;
- }
- matches++;
- //output
- if(show_user) {
- reply(getTextBot(), user, "%s!%s@%s %s", cuser->nick, cuser->ident, cuser->host, ((cuser->flags & USERFLAG_ISAUTHED) ? cuser->auth : "*"));
- }
- }
- reply(getTextBot(), user, "NS_TABLE_COUNT", matches);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] target (format: minaccess-maxaccess/users/bans)
-* argv[1] duration
-*/
-static USERLIST_CALLBACK(neonserv_cmd_trim_userlist_lookup);
-static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int min_access, int max_access, int duration);
-
-struct neonserv_cmd_trim_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- int min_access;
- int max_access;
- int duration;
-};
-
-CMD_BIND(neonserv_cmd_trim) {
- if(stricmp(argv[0], "bans") && !checkChannelAccess(user, chan, "channel_candel", 0, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_ACCESS_DENIED");
- return;
- }
- }
- int min_access, max_access;
- if(!stricmp(argv[0], "users")) {
- min_access = 1;
- max_access = getChannelAccess(user, chan, 0) - 1;
- } else if(!stricmp(argv[0], "bans")) {
- if(!checkChannelAccess(user, chan, "channel_staticban", 0, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_ACCESS_DENIED");
- return;
- }
- }
- //TODO: TRIM BANS
- return;
- } else {
- char *seperator = strstr(argv[0], "-");
- if(seperator) {
- *seperator = '\0';
- seperator++;
- min_access = atoi(argv[0]);
- max_access = atoi(seperator);
- if(max_access < min_access) {
- reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access);
- return;
- }
- } else {
- min_access = atoi(argv[0]);
- max_access = min_access;
- }
- if(max_access >= getChannelAccess(user, chan, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(getTextBot(), user, "NS_NO_ACCESS");
- return;
- }
- }
- }
- //parse duration...
- int duration = strToTime(user, argv[1]);
- if(duration < 30) {
- reply(getTextBot(), user, "NS_TRIM_DURATION_TOO_SHORT", 30);
- return;
- }
- struct neonserv_cmd_trim_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->min_access = min_access;
- cache->max_access = max_access;
- cache->duration = duration;
- get_userlist_with_invisible(chan, neonserv_cmd_trim_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_trim_userlist_lookup) {
- struct neonserv_cmd_trim_cache *cache = data;
- //got userlist
- neonserv_cmd_trim_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->min_access, cache->max_access, cache->duration);
- free(cache);
-}
-
-static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int min_access, int max_access, int duration) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- int trim_count = 0, is_here;
- struct ChanUser *chanuser;
- printf_mysql_query("SELECT `chanuser_seen`, `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access);
- res = mysql_use();
- while ((row = mysql_fetch_row(res)) != NULL) {
- if(!strcmp(row[0], "0") || time(0) - atoi(row[0]) >= duration) {
- //check if the user is currently in the channel
- is_here = 0;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if((chanuser->user->flags & USERFLAG_ISAUTHED) && !strcmp(chanuser->user->auth, row[1])) {
- is_here = 1;
- break;
- }
- }
- if(!is_here) {
- //delete the user
- trim_count++;
- printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[2]);
- }
- }
- }
- char timeBuf[MAXLEN];
- reply(getTextBot(), user, "NS_TRIM_DONE", trim_count, min_access, max_access, chan->name, timeToStr(user, duration, 3, timeBuf));
- if(trim_count)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nick[,*auth[,*!*@mask[...]]]
-*/
-struct neonserv_cmd_unban_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- struct ModeBuffer *modeBuf;
- int provided_masks, done_masks, pending_whos, unbanned_masks;
-};
-
-static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup);
-static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user);
-static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask);
-static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache);
-
-CMD_BIND(neonserv_cmd_unban) {
- char *mask, *nextmask;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- nextmask = merge_argv_char(argv, 0, argc, ',');
- struct neonserv_cmd_unban_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->modeBuf = modeBuf;
- cache->done_masks = 0;
- cache->provided_masks = 0;
- cache->unbanned_masks = 0;
- while((mask = nextmask)) {
- nextmask = strstr(mask, ",");
- if(nextmask) {
- *nextmask = '\0';
- nextmask++;
- }
- cache->provided_masks++;
- if(is_valid_nick(mask)) {
- struct UserNode *cuser = getUserByNick(mask);
- if(!cuser) {
- cuser = createTempUser(mask);
- cuser->flags |= USERFLAG_ISTMPUSER;
- get_userauth(cuser, neonserv_cmd_unban_userauth_lookup, cache);
- cache->pending_whos++;
- } else {
- neonserv_cmd_unban_nick(cache, cuser);
- }
- } else {
- neonserv_cmd_unban_mask(cache, mask);
- }
- }
- if(!cache->pending_whos)
- neonserv_cmd_unban_finish(cache);
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup) {
- struct neonserv_cmd_unban_cache *cache = data;
- cache->pending_whos--;
- if(user)
- neonserv_cmd_unban_nick(cache, user);
- else
- neonserv_cmd_unban_mask(cache, user_nick);
- if(!cache->pending_whos)
- neonserv_cmd_unban_finish(cache);
-}
-
-static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user) {
- int matches = 0;
- struct BanNode *ban;
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
- for(ban = cache->chan->bans; ban; ban = ban->next) {
- if(!match(ban->mask, usermask)) {
- modeBufferUnban(cache->modeBuf, ban->mask);
- cache->unbanned_masks++;
- matches++;
- }
- }
- if(matches)
- cache->done_masks++;
-}
-
-static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask) {
- char banmask[NICKLEN+USERLEN+HOSTLEN+3];
- int matches = 0;
- struct BanNode *ban;
- mask = make_banmask(mask, banmask);
- for(ban = cache->chan->bans; ban; ban = ban->next) {
- if(!match(mask, ban->mask)) {
- modeBufferUnban(cache->modeBuf, ban->mask);
- cache->unbanned_masks++;
- matches++;
- }
- }
- if(matches)
- cache->done_masks++;
- else {
- for(ban = cache->chan->bans; ban; ban = ban->next) {
- if(!match(ban->mask, mask)) {
- reply(cache->textclient, cache->user, "NS_DELBAN_BANNED_BY", mask, ban->mask);
- break;
- }
- }
- }
-}
-
-static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache) {
- freeModeBuffer(cache->modeBuf);
- if(cache->done_masks == cache->provided_masks)
- reply(cache->textclient, cache->user, "NS_UNBAN_DONE", cache->unbanned_masks, cache->chan->name);
- else
- reply(cache->textclient, cache->user, "NS_UNBAN_FAIL", cache->client->user->nick);
- if(cache->done_masks)
- logEvent(cache->event);
- free(cache);
-}
-
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nothing
-*/
-
-CMD_BIND(neonserv_cmd_unbanall) {
- struct ModeBuffer *modeBuf;
- int bans = 0;
- struct BanNode *ban;
- modeBuf = initModeBuffer(client, chan);
- for(ban = chan->bans; ban; ban = ban->next) {
- modeBufferUnban(modeBuf, ban->mask);
- bans++;
- }
- freeModeBuffer(modeBuf);
- if(bans) {
- reply(getTextBot(), user, "NS_UNBANALL_DONE", bans, chan->name);
- logEvent(event);
- } else
- reply(getTextBot(), user, "NS_UNBANALL_FAIL", client->user->nick, chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nothing
-*/
-
-CMD_BIND(neonserv_cmd_unbanme) {
- struct ModeBuffer *modeBuf;
- int bans = 0;
- struct BanNode *ban;
- modeBuf = initModeBuffer(client, chan);
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
- for(ban = chan->bans; ban; ban = ban->next) {
- if(!match(ban->mask, usermask)) {
- modeBufferUnban(modeBuf, ban->mask);
- bans++;
- }
- }
- freeModeBuffer(modeBuf);
- if(bans) {
- reply(getTextBot(), user, "NS_UNBANME_DONE", bans, chan->name);
- logEvent(event);
- } else
- reply(getTextBot(), user, "NS_UNBANME_FAIL", client->user->nick, usermask);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] command name
-*/
-
-CMD_BIND(neonserv_cmd_unbind) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `id` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0]));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]);
- return;
- }
- unbind_cmd(client->botid, argv[0]);
- printf_mysql_query("DELETE FROM `bot_binds` WHERE `id` = '%s'", row[0]);
- reply(getTextBot(), user, "NS_UNBIND_DONE", argv[0]);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - channel
-*/
-CMD_BIND(neonserv_cmd_unregister) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- char *channel = argv[0];
- if(!is_valid_chan(channel)) {
- reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
- return;
- }
- int chanid;
- printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chanid = atoi(row[0]);
- } else {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
- return;
- }
- int botid = atoi(row[0]);
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->clientid == botid)
- break;
- }
- if(bot && strcmp(row[2], "1")) {
- putsock(bot, "PART %s :Channel unregistered.", channel);
- }
- printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]);
- reply(getTextBot(), user, "NS_UNREGISTER_DONE", channel);
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup);
-static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
-
-struct neonserv_cmd_unsuspend_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
-};
-
-CMD_BIND(neonserv_cmd_unsuspend) {
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
- } else {
- struct neonserv_cmd_unsuspend_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_unsuspend_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup) {
- struct neonserv_cmd_unsuspend_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_unsuspend_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid, cflags;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(textclient, user, "NS_USER_OUTRANKED", nick);
- return;
- }
- }
- //unsuspend
- cflags = atoi(row[2]);
- if(!(cflags & DB_CHANUSER_SUSPENDED)) {
- reply(textclient, user, "NS_SUSPEND_NOT", nick);
- return;
- }
- cflags &= ~DB_CHANUSER_SUSPENDED;
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", cflags, row[1]);
- reply(textclient, user, "NS_SUSPEND_RESTORED", nick, chan->name);
- logEvent(event);
- return;
- }
- }
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no arguments
-*/
-
-CMD_BIND(neonserv_cmd_up) {
- struct ChanUser *chanuser = getChanUser(user, chan);
- if(!chanuser) {
- reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name);
- return;
- }
- check_mysql();
- loadChannelSettings(chan);
- MYSQL_RES *res, *default_res;
- MYSQL_ROW row, default_row;
- int chan_getop, chan_getvoice, caccess;
- printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return;
- if(!row[0] || !row[1]) {
- printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
- default_res = mysql_use();
- if ((default_row = mysql_fetch_row(default_res)) == NULL) return;
- chan_getop = (row[0] ? atoi(row[0]) : atoi(default_row[0]));
- chan_getvoice = (row[1] ? atoi(row[1]) : atoi(default_row[1]));
- } else {
- chan_getop = atoi(row[0]);
- chan_getvoice = atoi(row[1]);
- }
- caccess = getChannelAccess(user, chan, 1);
- if(caccess >= chan_getop) {
- if(!(chanuser->flags & CHANUSERFLAG_OPPED)) {
- putsock(client, "MODE %s +o %s", chan->name, user->nick);
- logEvent(event);
- } else
- reply(getTextBot(), user, "NS_UP_ALREADY_OP", chan->name);
- } else if(caccess >= chan_getvoice) {
- if(!(chanuser->flags & CHANUSERFLAG_VOICED)) {
- putsock(client, "MODE %s +v %s", chan->name, user->nick);
- logEvent(event);
- } else
- reply(getTextBot(), user, "NS_UP_ALREADY_VOICE", chan->name);
- } else
- reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no arguments
-*/
-
-CMD_BIND(neonserv_cmd_upall) {
- MYSQL_RES *res, *default_res;
- MYSQL_ROW row, default_row;
- struct ChanUser *chanuser;
- int userid, chan_getop, chan_getvoice, caccess;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", user->auth);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL)
- return;
- userid = atoi(row[0]);
- printf_mysql_query("SELECT `chanuser_access`, `channel_getop`, `channel_getvoice`, `channel_name`, `channel_id` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d'", userid);
- res = mysql_use();
- while ((row = mysql_fetch_row(res)) != NULL) {
- chan = getChanByName(row[3]);
- if(!chan) continue;
- printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%s' AND `botclass` = '%d'", row[4], client->botid);
- if (mysql_fetch_row(mysql_use()) == NULL) continue;
- if(!(chanuser = getChanUser(user, chan))) continue;
- if(!row[1] || !row[2]) {
- printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
- default_res = mysql_use();
- if ((default_row = mysql_fetch_row(default_res)) == NULL) return;
- chan_getop = (row[1] ? atoi(row[1]) : atoi(default_row[0]));
- chan_getvoice = (row[2] ? atoi(row[2]) : atoi(default_row[1]));
- } else {
- chan_getop = atoi(row[1]);
- chan_getvoice = atoi(row[2]);
- }
- caccess = atoi(row[0]);
- int done = 0;
- if(caccess >= chan_getop) {
- if(!(chanuser->flags & CHANUSERFLAG_OPPED)) {
- putsock(client, "MODE %s +o %s", chan->name, user->nick);
- done = 1;
- }
- } else if(caccess >= chan_getvoice) {
- if(!(chanuser->flags & CHANUSERFLAG_VOICED)) {
- putsock(client, "MODE %s +v %s", chan->name, user->nick);
- done = 1;
- }
- }
- if(done) {
- event->chan = chan;
- logEvent(event);
- }
- }
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - usermask
-* argv[1] - min access
-* argv[2] - max access
-*/
-static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup);
-static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access);
-
-struct neonserv_cmd_users_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- char *usermask;
- int min_access;
- int max_access;
-};
-
-CMD_BIND(neonserv_cmd_users) {
- int min_access = 1, max_access = 500;
- char *usermask = NULL;
- if(argc > 0)
- usermask = argv[0];
- if(argc > 2) {
- min_access = atoi(argv[1]);
- max_access = atoi(argv[2]);
- }
- struct neonserv_cmd_users_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->usermask = (usermask ? strdup(usermask) : NULL);
- cache->min_access = min_access;
- cache->max_access = max_access;
- get_userlist_with_invisible(chan, neonserv_cmd_users_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup) {
- struct neonserv_cmd_users_cache *cache = data;
- neonserv_cmd_users_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access);
- if(cache->usermask)
- free(cache->usermask);
- free(cache);
-}
-
-static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- int content_count = 0, cflags, is_here, caccess, i;
- char seenstr[MAXLEN];
- struct Table *table;
- struct ChanUser *chanuser;
- printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_seen`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id);
- res = mysql_use();
- table = table_init(4, mysql_num_rows(res) + 1, 0);
- if(usermask)
- reply(textclient, user, "NS_USERS_HEADER_MATCH", chan->name, min_access, max_access, usermask);
- else
- reply(textclient, user, "NS_USERS_HEADER", chan->name, min_access, max_access);
- char *content[4];
- content[0] = get_language_string(user, "NS_USERS_HEADER_ACCESS");
- content[1] = get_language_string(user, "NS_USERS_HEADER_ACCOUNT");
- content[2] = get_language_string(user, "NS_USERS_HEADER_SEEN");
- content[3] = get_language_string(user, "NS_USERS_HEADER_STATE");
- table_add(table, content);
- while ((row = mysql_fetch_row(res)) != NULL) {
- caccess = atoi(row[0]);
- if((!usermask || !match(usermask, row[1])) && caccess >= min_access && caccess <= max_access) {
- content[0] = row[0];
- content[1] = row[1];
- is_here = 0;
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if((chanuser->user->flags & USERFLAG_ISAUTHED) && !strcmp(chanuser->user->auth, row[1])) {
- if((chanuser->flags & CHANUSERFLAG_INVISIBLE))
- is_here = 2;
- else {
- is_here = 1;
- break;
- }
- }
- }
- if(is_here) {
- content[2] = get_language_string(user, (is_here == 2 ? "NS_USERS_SEEN_INVISIBLE" : "NS_USERS_SEEN_HERE"));
- } else if(!strcmp(row[2], "0")) {
- content[2] = get_language_string(user, "NS_USERS_SEEN_NEVER");
- } else {
- timeToStr(user, (time(0) - atoi(row[2])), 2, seenstr);
- content[2] = seenstr; //generate time
- }
- cflags = atoi(row[3]);
- if(cflags & DB_CHANUSER_SUSPENDED)
- content[3] = get_language_string(user, "NS_USERS_STATE_SUSPENDED");
- else
- content[3] = get_language_string(user, "NS_USERS_STATE_NORMAL");
- content_count++;
- table_add(table, content);
- }
- }
- //send the table
- char **table_lines = table_end(table);
- for(i = 0; i < table->entrys; i++) {
- reply(textclient, user, table_lines[i]);
- }
- if(!content_count)
- reply(textclient, user, "NS_TABLE_NONE");
- if(usermask || min_access != 1 || max_access != 500)
- reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_MATCH_1" : "NS_USERS_COUNT_MATCH"), table->length - 1, chan->name, content_count);
- else
- reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_1" : "NS_USERS_COUNT"), table->length - 1, chan->name);
- table_free(table);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-CMD_BIND(neonserv_cmd_uset) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- loadUserSettings(user);
- if(argc > 0) {
- if(!stricmp(argv[0], "language")) {
- struct language* lang;
- if(argc > 1) {
- if((lang = get_language_by_tag(argv[1])) == NULL && (lang = get_language_by_name(argv[1])) == NULL) {
- lang = user->language;
- } else {
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- printf_mysql_query("UPDATE `users` SET `user_lang` = '%s' WHERE `user_id` = '%s'", escape_string(lang->langtag), row[0]);
- } else {
- printf_mysql_query("INSERT INTO `users` (`user_user`, `user_lang`) VALUES ('%s', '%s')", escape_string(user->auth), escape_string(lang->langtag));
- }
- struct UserNode *cuser;
- for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) {
- if((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))
- cuser->language = lang;
- }
- }
- } else
- lang = user->language;
- reply(getTextBot(), user, "\002Language \002%s", lang->langname);
- char tmp[MAXLEN];
- int tmppos = 0;
- lang = get_default_language();
- tmppos = sprintf(tmp, "%s (%s)", lang->langname, lang->langtag);
- printf_mysql_query("SELECT `lang`,`text` FROM `language` WHERE `ident` = 'name'");
- res = mysql_use();
- while((row = mysql_fetch_row(res)) != NULL) {
- tmppos += sprintf(tmp + tmppos, ", %s (%s)", row[1], row[0]);
- }
- reply(getTextBot(), user, " %s", tmp);
- } else if(!stricmp(argv[0], "noinvite") && chan) {
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
- reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED");
- return;
- }
- printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- row = mysql_fetch_row(res);
- int noinvite = (row ? 1 : 0);
- if(argc > 1) {
- if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) {
- if(noinvite) {
- printf_mysql_query("DELETE FROM `noinvite` WHERE `id` = '%s'", row[0]);
- noinvite = 0;
- }
- } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) {
- if(!noinvite) {
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- } else {
- printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(user->auth));
- userid = (int) mysql_insert_id(mysql_conn);
- }
- printf_mysql_query("INSERT INTO `noinvite` (`uid`, `cid`) VALUES ('%d', '%d')", userid, chan->channel_id);
- noinvite = 1;
- }
- }
- }
- reply(getTextBot(), user, "\002NoInvite \002%s", (noinvite ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
- } else if((!stricmp(argv[0], "autoinvite") || !stricmp(argv[0], "noautoop") || !stricmp(argv[0], "info")) && chan) {
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
- reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED");
- return;
- }
- printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row) {
- int flags = atoi(row[0]);
- if(!stricmp(argv[0], "autoinvite")) {
- int getInvite = 0;
- if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite")))
- getInvite = 1;
- else if(row[3] && atoi(row[2]) >= atoi(row[3]))
- getInvite = 1;
- if(getInvite && argc > 1) {
- if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) {
- if(flags & DB_CHANUSER_AUTOINVITE) {
- flags &= ~DB_CHANUSER_AUTOINVITE;
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
- }
- } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) {
- if(!(flags & DB_CHANUSER_AUTOINVITE)) {
- flags |= DB_CHANUSER_AUTOINVITE;
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
- }
- }
- }
- if(getInvite)
- reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
- else
- reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS"));
- } else if(!stricmp(argv[0], "noautoop")) {
- if(argc > 1) {
- if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) {
- if(flags & DB_CHANUSER_NOAUTOOP) {
- flags &= ~DB_CHANUSER_NOAUTOOP;
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
- }
- } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) {
- if(!(flags & DB_CHANUSER_NOAUTOOP)) {
- flags |= DB_CHANUSER_NOAUTOOP;
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
- }
- }
- }
- reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
- } else if(!stricmp(argv[0], "info")) {
- char *infoline;
- if(argc > 1) {
- infoline = merge_argv(argv, 1, argc);
- if(!strcmp(infoline, "*"))
- infoline = "";
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_infoline` = '%s' WHERE `chanuser_id` = '%s'", escape_string(infoline), row[4]);
- } else
- infoline = row[1];
- reply(getTextBot(), user, "\002Info \002%s", infoline);
- }
- } else
- reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan);
- } else
- reply(getTextBot(), user, "NS_USET_UNKNOWN_SETTING", argv[0]);
- } else {
- //view all options
- reply(getTextBot(), user, "NS_USET_GLOBAL");
- reply(getTextBot(), user, "\002Language \002%s", user->language->langname);
- if(!chan) return;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
- reply(getTextBot(), user, "NS_USET_CHANNEL");
- printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- row = mysql_fetch_row(res);
- reply(getTextBot(), user, "\002NoInvite \002%s", (row ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
- printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- row = mysql_fetch_row(res);
- if(row) {
- int flags = atoi(row[0]);
- int getInvite = 0;
- if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite")))
- getInvite = 1;
- else if(row[3] && atoi(row[2]) >= atoi(row[3]))
- getInvite = 1;
- if(getInvite)
- reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
- else
- reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS"));
- reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
- reply(getTextBot(), user, "\002Info \002%s", row[1]);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* no args
-*/
-
-CMD_BIND(neonserv_cmd_version) {
- reply(getTextBot(), user, "\002NeonServ " NEONSERV_VERSION "\002 (%s), written by pk910", (strcmp(revision, "") ? revision : "-"));
- reply(getTextBot(), user, "Build (#%s) %s (%s lines, " COMPILER ")", compilation, creation, codelines);
- reply(getTextBot(), user, "NeonServ source can be found on: http://git.pk910.de/?p=NeonServV5.git");
- //helpers :D
- reply(getTextBot(), user, "special thanks to:");
- reply(getTextBot(), user, " Zer0n, TeaTow (testing and ideas current version)");
- reply(getTextBot(), user, " Buchman, Zer0n (translating current version)");
- reply(getTextBot(), user, " Patschi95, DerGrinch, Darkfly, Zer0n, Buschman (testing and ideas older versions)");
- reply(getTextBot(), user, " Buschman, Georg, richard (translating older versions)");
- reply(getTextBot(), user, "and all the other users that reported all these nasty bugs :D");
- reply(getTextBot(), user, "\002If you found a bug or if you have a good idea report it on http://bugtrack.pk910.de/git_view.php?p=NeonServV5.git\002");
-
-}
\ No newline at end of file
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0-*] nicks
-*/
-static USERLIST_CALLBACK(neonserv_cmd_voice_userlist_lookup);
-static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks);
-
-struct neonserv_cmd_voice_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *nicks;
-};
-
-CMD_BIND(neonserv_cmd_voice) {
- struct neonserv_cmd_voice_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- cache->nicks = strdup(merge_argv(argv, 0, argc));
- get_userlist_with_invisible(chan, neonserv_cmd_voice_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_voice_userlist_lookup) {
- struct neonserv_cmd_voice_cache *cache = data;
- neonserv_cmd_voice_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks);
- free(cache->nicks);
- free(cache);
-}
-
-static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks) {
- int total_users = 0, done_users = 0;
- struct UserNode *cuser;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- char *a, *b = nicks;
- do {
- a = strstr(b, " ");
- if(a) *a = '\0';
- total_users++;
- cuser = searchUserByNick(b);
- if(!cuser) {
- //check for an invisible user
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(!stricmp(chanuser->user->nick, b)) {
- cuser = chanuser->user;
- break;
- }
- }
- if(!cuser) continue;
- } else {
- chanuser = getChanUser(cuser, chan);
- if(!chanuser) continue;
- }
- done_users++;
- if(chanuser->flags & CHANUSERFLAG_VOICED) continue;
- modeBufferVoice(modeBuf, b);
- if(a) {
- b = a+1;
- }
- } while(a);
- freeModeBuffer(modeBuf);
- if(done_users == total_users)
- reply(textclient, user, "NS_VOICE_DONE", chan->name);
- else
- reply(textclient, user, "NS_VOICE_FAIL", client->user->nick);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] (optional) nick mask
-*/
-static USERLIST_CALLBACK(neonserv_cmd_voiceall_userlist_lookup);
-static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask);
-
-struct neonserv_cmd_voiceall_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct Event *event;
- char *nickmask;
-};
-
-CMD_BIND(neonserv_cmd_voiceall) {
- struct neonserv_cmd_voiceall_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->event = event;
- if(argc > 0) {
- cache->nickmask = strdup(argv[0]);
- } else
- cache->nickmask = NULL;
- get_userlist_with_invisible(chan, neonserv_cmd_voiceall_userlist_lookup, cache);
-}
-
-static USERLIST_CALLBACK(neonserv_cmd_voiceall_userlist_lookup) {
- struct neonserv_cmd_voiceall_cache *cache = data;
- neonserv_cmd_voiceall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask);
- if(cache->nickmask)
- free(cache->nickmask);
- free(cache);
-}
-
-static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask) {
- int done_users = 0;
- struct ChanUser *chanuser;
- struct ModeBuffer *modeBuf;
- modeBuf = initModeBuffer(client, chan);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- if(nickmask && match(nickmask, chanuser->user->nick)) continue;
- if(chanuser->flags & CHANUSERFLAG_VOICED) continue;
- modeBufferVoice(modeBuf, chanuser->user->nick);
- done_users++;
- }
- freeModeBuffer(modeBuf);
- reply(textclient, user, "NS_VOICEALL_DONE", done_users, chan->name);
- if(done_users)
- logEvent(event);
-}
+++ /dev/null
-
-#include "cmd_neonserv.h"
-
-/*
-* argv[0] - nick / *auth
-*/
-static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup);
-static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
-
-struct neonserv_cmd_wipeinfo_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan;
- struct Event *event;
- char *nick;
-};
-
-CMD_BIND(neonserv_cmd_wipeinfo) {
- if(argv[0][0] == '*') {
- //we've got an auth
- argv[0]++;
- neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
- } else {
- struct UserNode *cuser = getUserByNick(argv[0]);
- if(!cuser) {
- cuser = createTempUser(argv[0]);
- cuser->flags |= USERFLAG_ISTMPUSER;
- }
- if(cuser->flags & USERFLAG_ISAUTHED) {
- neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
- } else {
- struct neonserv_cmd_wipeinfo_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->textclient = getTextBot();
- cache->user = user;
- cache->chan = chan;
- cache->event = event;
- cache->nick = strdup(argv[0]);
- get_userauth(cuser, neonserv_cmd_wipeinfo_nick_lookup, cache);
- }
- }
-}
-
-static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup) {
- struct neonserv_cmd_wipeinfo_cache *cache = data;
- if(!user) {
- //USER_DOES_NOT_EXIST
- reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
- }
- else if(!(user->flags & USERFLAG_ISAUTHED)) {
- //USER_NOT_AUTHED
- reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
- }
- else
- neonserv_cmd_wipeinfo_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
- free(cache->nick);
- free(cache);
-}
-
-static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
- //we've got a valid auth now...
- MYSQL_RES *res;
- MYSQL_ROW row;
- int userid;
- printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- userid = atoi(row[0]);
- //check if the user is already added
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
- if(isGodMode(user)) {
- event->flags |= CMDFLAG_OPLOG;
- } else {
- reply(textclient, user, "NS_USER_OUTRANKED", nick);
- return;
- }
- }
- //delete
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_infoline` = '' WHERE `chanuser_id` = '%s'", row[1]);
- reply(textclient, user, "NS_WIPEINFO_DONE", nick, chan->name);
- logEvent(event);
- return;
- }
- }
- reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
-}
+++ /dev/null
-
-#define MYSQL_HOST "127.0.0.1"
-#define MYSQL_PORT 3306
-#define MYSQL_USER "neonserv"
-#define MYSQL_PASS ""
-#define MYSQL_BASE "neonserv"
--- /dev/null
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.67])
+AC_INIT([NeonServ], [5.0], [bugs@pk910.de], [neonserv], [http://neonserv.krypton-bouncer.de])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+AC_CONFIG_HEADERS([config.h])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_AWK
+
+# Checks for libraries.
+# Get MySQL library and include locations
+AC_ARG_WITH([mysql-include-path],
+ [AS_HELP_STRING([--with-mysql-include-path],
+ [location of the MySQL headers, defaults to /usr/include/mysql])],
+ [MYSQL_CFLAGS="-I$withval"],
+ [MYSQL_CFLAGS='-I/usr/include/mysql'])
+AC_SUBST([MYSQL_CFLAGS])
+
+AC_ARG_WITH([mysql-lib-path],
+ [AS_HELP_STRING([--with-mysql-lib-path], [location of the MySQL libraries])],
+ [MYSQL_LIBS="-L$withval -lmysqlclient"],
+ [MYSQL_LIBS='-lmysqlclient'])
+AC_SUBST([MYSQL_LIBS])
+
+# Checks for header files.
+AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([gethostbyname memset select socket strchr strdup strstr])
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
\ No newline at end of file
+++ /dev/null
-
-struct neonserv_event_ctcp_cache {
- struct ClientSocket *client;
- struct UserNode *user;
- struct ChanNode *chan;
- char *command;
- char *text;
-};
-
-static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup);
-static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text);
-static int neonserv_ctcp(char *buffer, char *command, char *text);
-
-static void neonserv_event_chanctcp(struct UserNode *user, struct ChanNode *chan, char *command, char *text) {
- struct ClientSocket *client = getBotForChannel(chan);
- if(!client) return; //we can't "see" this event
- if(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) return;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
- if(!(user->flags & USERFLAG_ISAUTHED)) {
- struct neonserv_event_ctcp_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->user = user;
- cache->chan = chan;
- cache->command = strdup(command);
- cache->text = (text ? strdup(text) : NULL);
- get_userauth(user, neonserv_event_ctcp_nick_lookup, cache);
- } else
- neonserv_event_ctcp_async1(client, user, chan, command, text);
-}
-
-static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup) {
- struct neonserv_event_ctcp_cache *cache = data;
- if(user) {
- neonserv_event_ctcp_async1(cache->client, cache->user, cache->chan, cache->command, cache->text);
- }
- free(cache->command);
- if(cache->text)
- free(cache->text);
- free(cache);
-}
-
-static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text) {
- MYSQL_RES *res;
- MYSQL_ROW row, defaultrow = NULL, chanuser;
- int uaccess = 0;
- printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return;
- if(!row[0] || !row[1]) {
- printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- defaultrow = mysql_fetch_row(res);
- }
- int ctcpaccess = atoi((row[0] ? row[0] : defaultrow[0]));
- if((user->flags & USERFLAG_ISAUTHED)) {
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- chanuser = mysql_fetch_row(res);
- if(chanuser)
- uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0]));
- }
- int duration = 0;
- char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
- char *banmask = NULL;
- char *reason = "disallowed channel CTCP";
- if(uaccess < ctcpaccess) {
- switch(atoi((row[1] ? row[1] : defaultrow[1]))) {
- case 2: //TIMEBAN: 3min
- duration = 180;
- case 3: //TIMEBAN: 1h
- if(!duration)
- duration = 3600;
- banmask = generate_banmask(user, banmaskBuf);
- printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason));
- int banid = (int) mysql_insert_id(mysql_conn);
- char nameBuf[MAXLEN];
- char banidBuf[20];
- sprintf(nameBuf, "ban_%d", banid);
- sprintf(banidBuf, "%d", banid);
- timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
- case 1: //KICKBAN
- if(!banmask)
- banmask = generate_banmask(user, banmaskBuf);
- putsock(client, "MODE %s +b %s", chan->name, banmask);
- case 0: //KICK
- putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason);
- break;
- }
- }
-}
-
-static void neonserv_event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text) {
- char ctcpBuf[MAXLEN];
- if(neonserv_ctcp(ctcpBuf, command, text)) {
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->user == target) break;
- }
- if(bot)
- putsock(bot, "NOTICE %s :\001%s\001", user->nick, ctcpBuf);
- }
-}
-
-static int neonserv_ctcp(char *buffer, char *command, char *text) {
- if(!stricmp(command, "VERSION")) {
- sprintf(buffer, "VERSION NeonServ v" NEONSERV_VERSION " by pk910 (%s)", (strcmp(revision, "") ? revision : "-"));
- return 1;
- }
- if(!stricmp(command, "FINGER")) {
- sprintf(buffer, "FINGER NeonServ v" NEONSERV_VERSION " (%s) build %s lines C code using " COMPILER " (see +netinfo)", (strcmp(revision, "") ? revision : "-"), codelines);
- return 1;
- }
- if(!stricmp(command, "PING")) {
- sprintf(buffer, "PING %s", (text ? text : "0"));
- return 1;
- }
- if(!stricmp(command, "TIME")) {
- time_t rawtime;
- struct tm *timeinfo;
- char timeBuf[80];
- time(&rawtime);
- timeinfo = localtime(&rawtime);
- strftime(timeBuf, 80, "%c", timeinfo);
- sprintf(buffer, "TIME %s", timeBuf);
- return 1;
- }
- return 0;
-}
+++ /dev/null
-
-static void neonserv_event_invite(struct ClientSocket *client, struct UserNode *user, char *channel) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(client, user, "NS_INVITE_FAIL", channel, client->user->nick);
- return;
- }
- int botid = atoi(row[0]);
- struct ClientSocket *bot;
- for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
- if(bot->clientid == botid)
- break;
- }
- if(bot) {
- struct ChanNode *chan = getChanByName(channel);
- if(chan && isUserOnChan(bot->user, chan)) {
- reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name);
- } else
- putsock(bot, "JOIN %s", channel);
- }
-}
-
+++ /dev/null
-
-struct neonserv_event_join_cache {
- struct ClientSocket *client;
- struct ChanUser *chanuser;
-};
-
-static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup);
-static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser);
-static TIMEQ_CALLBACK(neonserv_event_join_dynlimit);
-
-static void neonserv_event_join(struct ChanUser *chanuser) {
- struct UserNode *user = chanuser->user;
- struct ClientSocket *client = getBotForChannel(chanuser->chan);
- if(!client) return; //we can't "see" this event
- if(user->flags & USERFLAG_ISBOT) {
- putsock(client, "MODE %s +o %s", chanuser->chan->name, chanuser->user->nick);
- return;
- }
- loadChannelSettings(chanuser->chan);
- if(!(chanuser->chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
- char *ban;
- char usermask[NICKLEN+USERLEN+HOSTLEN+3];
- sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
- if((ban = getBanAffectingMask(chanuser->chan, usermask)) != NULL && !(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `ban_reason`, `user_user` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d' AND `ban_mask` = '%s'", chanuser->chan->channel_id, escape_string(ban));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- putsock(client, "MODE %s +b %s", chanuser->chan->name, ban);
- putsock(client, "KICK %s %s :(%s) %s", chanuser->chan->name, chanuser->user->nick, (row[1] ? row[1] : client->user->nick), row[0]);
- return;
- }
- }
- if(!(user->flags & USERFLAG_ISAUTHED)) {
- struct neonserv_event_join_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->chanuser = chanuser;
- get_userauth(user, neonserv_event_join_nick_lookup, cache);
- } else
- neonserv_event_join_async1(client, chanuser);
-}
-
-static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup) {
- struct neonserv_event_join_cache *cache = data;
- if(user) {
- neonserv_event_join_async1(cache->client, cache->chanuser);
- }
- free(cache);
-}
-
-static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser) {
- struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid));
- struct ChanNode *chan = chanuser->chan;
- struct UserNode *user = chanuser->user;
- struct ModeBuffer *modeBuf;
- MYSQL_RES *res;
- MYSQL_ROW row, chanuserrow, defaultrow = NULL;
- printf_mysql_query("SELECT `channel_maxusers`, `channel_greeting`, `channel_usergreeting`, `channel_getop`, `channel_getvoice`, `channel_userinfo`, `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return;
- if(!row[3] || !row[4]) {
- printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_userinfo` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- defaultrow = mysql_fetch_row(res);
- }
- if(chan->usercount > atoi(row[0])) {
- //update maxusers
- printf_mysql_query("UPDATE `channels` SET `channel_maxusers` = '%d' WHERE `channel_id` = '%d'", chan->usercount, chan->channel_id);
- }
- if((user->flags & USERFLAG_ISAUTHED)) {
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `chanuser_seen`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- chanuserrow = mysql_fetch_row(res);
- } else
- chanuserrow = NULL;
- int userflags = (chanuserrow ? atoi(chanuserrow[1]) : 0);
- int uaccess = ((chanuserrow && !(userflags & DB_CHANUSER_SUSPENDED)) ? atoi(chanuserrow[0]) : 0);
- //GREETING
- char greeting[MAXLEN];
- int greetingPos = 0;
- char *a, *b = (chanuserrow && *row[2] ? row[2] : row[1]);
- do {
- if(!b) break;
- a = strstr(b, "$");
- if(a) *a = '\0';
- greetingPos += sprintf(greeting + greetingPos, "%s", b);
- if(!a) break;
- switch(a[1]) {
- case '\0':
- a = NULL;
- break;
- case 'A':
- greetingPos += sprintf(greeting + greetingPos, "%d", uaccess);
- break;
- case 'B':
- greetingPos += sprintf(greeting + greetingPos, "%s", client->user->nick);
- break;
- case 'N':
- greetingPos += sprintf(greeting + greetingPos, "%s", user->nick);
- break;
- case 'H':
- greetingPos += sprintf(greeting + greetingPos, "%s@%s", user->ident, user->host);
- break;
- case 'U':
- greetingPos += sprintf(greeting + greetingPos, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"));
- break;
- default:
- greeting[greetingPos++] = '$';
- greeting[greetingPos++] = a[1];
- break;
- }
- if(a)
- b = a+2;
- } while(a);
- if(greetingPos)
- reply(textclient, user, "[%s] %s", chan->name, greeting);
- //USER RIGHTS
- if(!(userflags & DB_CHANUSER_NOAUTOOP)) {
- int getop = atoi((row[3] ? row[3] : defaultrow[0]));
- int getvoice = atoi((row[4] ? row[4] : defaultrow[1]));
- modeBuf = initModeBuffer(client, chan);
- if(uaccess >= getop && uaccess != 0) { //we disallow auto op for all users
- modeBufferOp(modeBuf, user->nick);
- } else if(uaccess >= getvoice) {
- modeBufferVoice(modeBuf, user->nick);
- }
- freeModeBuffer(modeBuf);
- }
- //INFOLINE
- int userinfoaccess = atoi((row[5] ? row[5] : defaultrow[2]));
- if(chanuserrow && strcmp(chanuserrow[2], "") && uaccess > userinfoaccess) {
- if(!strcmp(chanuserrow[3], "0") || time(0) - atol(chanuserrow[3]) >= 30) {
- putsock(client, "PRIVMSG %s :[%s] %s", chan->name, user->nick, chanuserrow[2]);
- }
- }
- //SEEN
- if(chanuserrow) {
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[4]);
- }
- //DYNLIMIT
- if(row[6] && strcmp(row[6], "0")) {
- char nameBuf[CHANNELLEN + 10];
- sprintf(nameBuf, "dynlimit_%s", chan->name);
- if(!timeq_name_exists(nameBuf)) {
- //neonserv_event_join_dynlimit
- timeq_add_name(nameBuf, 30, neonserv_event_join_dynlimit, strdup(chan->name));
- }
- }
- //AUTOINVITE
- if(chanuserrow && !strcmp(chanuserrow[3], "0") && time(0) - atol(chanuserrow[3]) >= 30) {
- //TODO: autoinvite
- }
-}
-
-static TIMEQ_CALLBACK(neonserv_event_join_dynlimit) {
- char *chanName = data;
- struct ChanNode *chan = getChanByName(chanName);
- free(chanName);
- struct ClientSocket *client = getBotForChannel(chan);
- if(!client) return;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return;
- if(row[0] && strcmp(row[0], "0")) {
- putsock(client, "MODE %s +l %d", chan->name, chan->usercount + atoi(row[0]));
- }
-}
+++ /dev/null
-
-struct neonserv_event_notice_cache {
- struct ClientSocket *client;
- struct UserNode *user;
- struct ChanNode *chan;
- char *message;
-};
-
-static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup);
-static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message);
-
-static void neonserv_event_channotice(struct UserNode *user, struct ChanNode *chan, char *message) {
- struct ClientSocket *client = getBotForChannel(chan);
- if(!client) return; //we can't "see" this event
- if(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) return;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
- if(!(user->flags & USERFLAG_ISAUTHED)) {
- struct neonserv_event_notice_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->user = user;
- cache->chan = chan;
- cache->message = strdup(message);
- get_userauth(user, neonserv_event_notice_nick_lookup, cache);
- } else
- neonserv_event_notice_async1(client, user, chan, message);
-}
-
-static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup) {
- struct neonserv_event_notice_cache *cache = data;
- if(user) {
- neonserv_event_notice_async1(cache->client, cache->user, cache->chan, cache->message);
- }
- free(cache->message);
- free(cache);
-}
-
-static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) {
- MYSQL_RES *res;
- MYSQL_ROW row, defaultrow = NULL, chanuser;
- int uaccess = 0;
- printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return;
- if(!row[0] || !row[1]) {
- printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- defaultrow = mysql_fetch_row(res);
- }
- int noticeaccess = atoi((row[0] ? row[0] : defaultrow[0]));
- if((user->flags & USERFLAG_ISAUTHED)) {
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- chanuser = mysql_fetch_row(res);
- if(chanuser)
- uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0]));
- }
- int duration = 0;
- char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
- char *banmask = NULL;
- char *reason = "disallowed channel NOTICE";
- if(uaccess < noticeaccess) {
- switch(atoi((row[1] ? row[1] : defaultrow[1]))) {
- case 2: //TIMEBAN: 3min
- duration = 180;
- case 3: //TIMEBAN: 1h
- if(!duration)
- duration = 3600;
- banmask = generate_banmask(user, banmaskBuf);
- printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason));
- int banid = (int) mysql_insert_id(mysql_conn);
- char nameBuf[MAXLEN];
- char banidBuf[20];
- sprintf(nameBuf, "ban_%d", banid);
- sprintf(banidBuf, "%d", banid);
- timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
- case 1: //KICKBAN
- if(!banmask)
- banmask = generate_banmask(user, banmaskBuf);
- putsock(client, "MODE %s +b %s", chan->name, banmask);
- case 0: //KICK
- putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason);
- break;
- }
- }
-}
-
+++ /dev/null
-
-static void neonserv_event_part(struct ChanUser *chanuser, char *reason) {
- struct ChanNode *chan = chanuser->chan;
- struct UserNode *user = chanuser->user;
- MYSQL_RES *res;
- MYSQL_ROW chanuserrow;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
- if((user->flags & USERFLAG_ISAUTHED)) {
- printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- if((chanuserrow = mysql_fetch_row(res)) != NULL)
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]);
- }
-}
+++ /dev/null
-
-static void neonserv_event_quit(struct UserNode *user, char *reason) {
- MYSQL_RES *res;
- MYSQL_ROW chanuserrow;
- struct ChanUser *chanuser;
- if((user->flags & USERFLAG_ISAUTHED)) {
- for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) {
- printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `channel_name` = '%s' AND `user_user` = '%s'", escape_string(chanuser->chan->name), escape_string(user->auth));
- res = mysql_use();
- if((chanuserrow = mysql_fetch_row(res)) != NULL)
- printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]);
- }
- }
-}
+++ /dev/null
-
-struct neonserv_event_topic_cache {
- struct ClientSocket *client;
- struct UserNode *user;
- struct ChanNode *chan;
- char *new_topic;
-};
-
-static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup);
-static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic);
-
-static void neonserv_event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic) {
- struct ClientSocket *client = getBotForChannel(chan);
- if(!client) return; //we can't "see" this event
- if(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) return;
- loadChannelSettings(chan);
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
- if(!(user->flags & USERFLAG_ISAUTHED)) {
- struct neonserv_event_topic_cache *cache = malloc(sizeof(*cache));
- if (!cache) {
- perror("malloc() failed");
- return;
- }
- cache->client = client;
- cache->user = user;
- cache->chan = chan;
- cache->new_topic = strdup(new_topic);
- get_userauth(user, neonserv_event_topic_nick_lookup, cache);
- } else
- neonserv_event_topic_async1(client, user, chan, new_topic);
-}
-
-static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup) {
- struct neonserv_event_topic_cache *cache = data;
- if(user) {
- neonserv_event_topic_async1(cache->client, cache->user, cache->chan, cache->new_topic);
- }
- free(cache->new_topic);
- free(cache);
-}
-
-static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic) {
- MYSQL_RES *res;
- MYSQL_ROW row, defaultrow = NULL, chanuserrow;
- int uaccess = 0;
- printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) return;
- if(!row[0] || !row[1]) {
- printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'");
- res = mysql_use();
- defaultrow = mysql_fetch_row(res);
- }
- int changetopic = atoi((row[0] ? row[0] : defaultrow[0]));
- int topicsnarf = atoi((row[1] ? row[1] : defaultrow[1]));
- if((user->flags & USERFLAG_ISAUTHED)) {
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
- res = mysql_use();
- chanuserrow = mysql_fetch_row(res);
- if(chanuserrow)
- uaccess = ((atoi(chanuserrow[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuserrow[0]));
- }
- if(uaccess < changetopic) {
- //undo topic change
- struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid));
- struct ChanUser *chanuser = getChanUser(user, chan);
- if(!chanuser) return; //flying super cow?
- if(time(0) - chanuser->changeTime > BOTWAR_DETECTION_TIME) {
- chanuser->changeTime = time(0);
- chanuser->chageEvents = 1;
- } else {
- chanuser->chageEvents++;
- if(chanuser->chageEvents >= BOTWAR_DETECTION_EVENTS || chanuser->chageEvents < 0) {
- //BOTWAR!
- chanuser->changeTime = time(0);
- if(chanuser->chageEvents > 0) {
- putsock(client, "NOTICE @%s :%s %s", chan->name, get_language_string(user, "NS_BOTWAR_DETECTED"), (BOTWAR_ALERT_CHAN ? get_language_string(user, "NS_BOTWAR_REPORTED") : ""));
- if(BOTWAR_ALERT_CHAN) {
- struct ChanNode *alertchan = getChanByName(BOTWAR_ALERT_CHAN);
- struct ClientSocket *alertclient;
- if(alertchan && (alertclient = getBotForChannel(chan)) != NULL) {
- char msgBuf[MAXLEN];
- putsock(alertclient, "PRIVMSG %s :%s", alertchan->name, build_language_string(user, msgBuf, "NS_BOTWAR_ALERT", chan->name, user->nick));
- }
- }
- }
- chanuser->chageEvents = -2;
- return;
- }
- }
- reply(textclient, user, "NS_TOPIC_ACCESS", chan->name);
- putsock(client, "TOPIC %s :%s", chan->name, chan->topic);
- } else if(uaccess >= topicsnarf) {
- printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(new_topic), chan->channel_id);
- }
-}
-
+++ /dev/null
-#include "lang.h"
-#include "UserNode.h"
-#include "DBHelper.h"
-#include "mysqlConn.h"
-
-#define DEFAULT_LANG_TAG "EN"
-#define DEFAULT_LANG_NAME "English"
-
-static struct language **langdict;
-static struct language *lang_c;
-
-void init_lang() {
- langdict = calloc(MAXLANGUAGES, sizeof(*langdict));
-}
-
-void free_lang() {
-
-}
-
-void load_languages() {
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `lang`, `text` FROM `language` WHERE `ident` = 'name'");
- res = mysql_use();
- while((row = mysql_fetch_row(res)) != NULL) {
- load_language(row[0], row[1]);
- }
-}
-
-static struct language* add_language(char *langtag, char *langname) {
- int cindex;
- for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
- if(langdict[cindex] == NULL) break;
- if(!strcmp(langdict[cindex]->langname, langname) || !strcmp(langdict[cindex]->langtag, langtag))
- return langdict[cindex];
- }
- if(cindex == MAXLANGUAGES) return NULL;
- struct language *lang = malloc(sizeof(*lang));
- if (!lang) {
- perror("malloc() failed");
- return NULL;
- }
- lang->langtag = strdup(langtag);
- lang->langname = strdup(langname);
- struct language_table **entrys = calloc(27, sizeof(*entrys));
- lang->entrys = entrys;
- langdict[cindex] = lang;
- return lang;
-}
-
-static int get_entry_index(const char *ident) {
- const char *underscore = strstr(ident, "_");
- if(!underscore || !(underscore[1] >= 65 && underscore[1] <= 90)) return 26;
- return (underscore[1] - 'A');
-}
-
-void load_language(char *tag, char *name) {
- struct language *lang = get_language_by_tag(tag);
- if(lang == get_default_language()) return;
- if(lang) {
- //remove all entrys
- int cindex;
- struct language_table *entry, *next;
- for(cindex = 0; cindex < 27; cindex++) {
- for(entry = lang->entrys[cindex]; entry; entry = next) {
- next = entry->next;
- free(entry->ident);
- free(entry->text);
- free(entry);
- }
- lang->entrys[cindex] = NULL;
- }
- } else
- lang = add_language(tag, name);
- if(!lang) return;
- MYSQL_RES *res;
- MYSQL_ROW row;
- printf_mysql_query("SELECT `ident`, `text` FROM `language` WHERE `lang` = '%s' AND `ident` != 'name'", escape_string(tag));
- res = mysql_use();
- while((row = mysql_fetch_row(res)) != NULL) {
- register_language_string(lang, row[0], row[1]);
- }
-}
-
-struct language* get_language_by_tag(char *tag) {
- int cindex;
- for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
- if(langdict[cindex] == NULL) break;
- if(!stricmp(langdict[cindex]->langtag, tag))
- return langdict[cindex];
- }
- return NULL;
-}
-
-struct language* get_language_by_name(char *name) {
- int cindex;
- for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
- if(langdict[cindex] == NULL) break;
- if(!stricmp(langdict[cindex]->langname, name))
- return langdict[cindex];
- }
- return NULL;
-}
-
-struct language* get_default_language() {
- if(lang_c == NULL)
- lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
- return lang_c;
-}
-
-void register_default_language_table(const struct default_language_entry *msgtab) {
- if(lang_c == NULL)
- lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
- while(msgtab->ident) {
- register_language_string(lang_c, msgtab->ident, msgtab->text);
- msgtab++;
- }
-}
-
-void register_language_string(struct language *lang, char *ident, char *text) {
- int cindex = get_entry_index(ident);
- struct language_table *lang_entry = malloc(sizeof(*lang_entry));
- if (!lang_entry) {
- perror("malloc() failed");
- return;
- }
-
- lang_entry->ident = strdup(ident);
- //replace all:
- //$b to \002
- //$k to \003
- char txt[MAXLEN];
- strcpy(txt, text);
- char tmp[MAXLEN];
- int tmppos = 0;
- char *a, *b = txt;
- do {
- a = strstr(b, "$");
- if(a) *a = '\0';
- tmppos += sprintf(tmp + tmppos, "%s", b);
- if(a) {
- switch(a[1]) {
- case 'b':
- tmp[tmppos++] = '\002';
- break;
- case 'k':
- tmp[tmppos++] = '\003';
- break;
- default:
- //unknown - just write it
- tmppos += sprintf(tmp + tmppos, "$%c", a[1]);
- }
- b = a+2;
- }
- } while(a);
- lang_entry->text = strdup(tmp);
- lang_entry->next = lang->entrys[cindex];
- lang->entrys[cindex] = lang_entry;
-}
-
-char *get_language_string(struct UserNode *user, const char* msg_ident) {
- struct language* lang;
- if((user->flags & USERFLAG_ISAUTHED)) {
- loadUserSettings(user);
- lang = user->language;
- } else
- lang = lang_c;
- int cindex = get_entry_index(msg_ident);
- struct language_table* entry;
- for(entry = lang->entrys[cindex]; entry; entry = entry->next) {
- if(!strcmp(entry->ident, msg_ident))
- return entry->text;
- }
- if(lang == lang_c) return NULL;
- for(entry = lang_c->entrys[cindex]; entry; entry = entry->next) {
- if(!strcmp(entry->ident, msg_ident))
- return entry->text;
- }
- return NULL;
-}
-
-char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...) {
- char *formatStr = get_language_string(user, msg_ident);
- if(!formatStr) return NULL;
- if(buffer == NULL) {
- buffer = (char *)malloc((MAXLEN+1) * sizeof(char));
- if (!buffer) {
- perror("malloc() failed");
- return NULL;
- }
- }
- int pos;
- va_list arg_list;
- buffer[0] = '\0';
- va_start(arg_list, msg_ident);
- pos = vsnprintf(buffer, MAXLEN - 2, formatStr, arg_list);
- va_end(arg_list);
- if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
- buffer[pos] = '\0';
- return buffer;
-}
+++ /dev/null
-#ifndef _lang_h
-#define _lang_h
-
-#include "main.h"
-
-struct UserNode;
-
-struct default_language_entry {
- char *ident;
- char *text;
-};
-
-struct language_table {
- char *ident;
- char *text;
-
- struct language_table *next;
-};
-
-struct language {
- char *langtag;
- char *langname;
- struct language_table **entrys;
-};
-
-void init_lang();
-void free_lang();
-struct language* get_language_by_tag(char *tag);
-struct language* get_language_by_name(char *name);
-struct language* get_default_language();
-void load_languages();
-void load_language(char *tag, char *name);
-void register_language_string(struct language *lang, char *ident, char *text);
-void register_default_language_table(const struct default_language_entry *msgtab);
-char *get_language_string(struct UserNode *user, const char* msg_ident);
-char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...);
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "main.h"
-#include "ClientSocket.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "IRCEvents.h"
-#include "IRCParser.h"
-#include "modcmd.h"
-#include "WHOHandler.h"
-#include "bots.h"
-#include "mysqlConn.h"
-#include "HandleInfoHandler.h"
-#include "lang.h"
-#include "tools.h"
-#include "timeq.h"
-#include "EventLogger.h"
-#include "ModeNode.h"
-
-time_t start_time;
-
-void cleanup() {
- free_sockets();
- free_parser();
- free_UserNode();
- free_ChanNode();
- free_bind();
- free_modcmd();
- free_whoqueue();
- free_bots();
- free_mysql();
- free_handleinfohandler();
- free_lang();
-}
-
-int main(void)
-{
- start_time = time(0);
-
- init_mysql();
- init_lang();
- init_parser();
- init_UserNode();
- init_ChanNode();
- init_ModeNode();
- init_bind();
- init_modcmd();
- init_handleinfohandler();
- init_tools();
- init_bots();
-
- load_languages();
-
- time_t socket_wait;
- while(1) {
- socket_wait = time(0) + SOCKET_SELECT_TIME;
- do {
- socket_loop(SOCKET_SELECT_TIME);
- } while(time(0) < socket_wait);
- timeq_tick();
- loop_bots();
- clearTempUsers();
- destroyEvents();
- }
-}
-
-int stricmp (const char *s1, const char *s2)
-{
- if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
- if (s2 == NULL) return *s1;
- char c1, c2;
- while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
- {
- if (*s1 == '\0') break;
- ++s1; ++s2;
- }
- return c1 - c2;
-}
-
-int stricmplen (const char *s1, const char *s2, int len)
-{
- if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
- if (s2 == NULL) return *s1;
- char c1, c2;
- int i = 0;
- while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
- {
- i++;
- if (*s1 == '\0') break;
- ++s1; ++s2;
- if(i == len) break;
- }
- return c1 - c2;
-}
-
+++ /dev/null
-#ifndef _main_h
-#define _main_h
-
-#define NEONSERV_VERSION "5.0.1-dev"
-
-#include "config.h"
-#ifndef BOTWAR_ALERT_CHAN
-#define BOTWAR_ALERT_CHAN NULL
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <stdarg.h>
-#include <time.h>
-
-#if __GNUC__
-#define PRINTF_LIKE(M,N) __attribute__((format (printf, M, N)))
-#else
-#define PRINTF_LIKE(M,N)
-#endif
-
-#if __GNUC__ >= 2
-#define UNUSED_ARG(ARG) ARG __attribute__((unused))
-#elif defined(S_SPLINT_S)
-#define UNUSED_ARG(ARG) /*@unused@*/ ARG
-#define const /*@observer@*/ /*@temp@*/
-#else
-#define UNUSED_ARG(ARG) ARG
-#endif
-
-#define STRINGIFY_(x) #x
-#define STRINGIFY(x) STRINGIFY_(x)
-
-#if defined(__GNUC__)
-#if defined(__GNUC_PATCHLEVEL__)
-#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__)
-#else
-#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__)
-#endif
-#elif defined (__IMAGECRAFT__)
-#define COMPILER "ICCAVR"
-#else
-#define COMPILER "Unknown"
-#endif
-
-#define SOCKET_SELECT_TIME 2
-
-#define NICKLEN 30
-#define USERLEN 10
-#define AUTHLEN 32
-#define HOSTLEN 63
-#define REALLEN 50
-#define TOPICLEN 500
-#define CHANNELLEN 200
-#define MAXLEN 512
-#define TRIGGERLEN 50
-#define MAXNUMPARAMS 200 /* maximum number of parameters in one line */
-#define MAXLANGUAGES 5
-#define MAXMODES 6
-#define INVITE_TIMEOUT 30
-#define BOTWAR_DETECTION_TIME 7
-#define BOTWAR_DETECTION_EVENTS 6
-
-//valid nick chars
-#define VALID_NICK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{|}~[\\]^-_`"
-//the first char is a little bit different
-// 0 1 2 3 4 5 6
-// 1234567890123456789012345678901234567890123456789012345678 9012 62
-#define VALID_NICK_CHARS_FIRST "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~[\\]^_`"
-#define VALID_NICK_CHARS_FIRST_LEN 62
-
-#define TEMPUSER_LIST_INDEX VALID_NICK_CHARS_FIRST_LEN
-
-extern time_t start_time;
-
-int stricmp (const char *s1, const char *s2);
-int stricmplen (const char *s1, const char *s2, int len);
-
-#endif
\ No newline at end of file
+++ /dev/null
-
-#include "modcmd.h"
-#include "IRCEvents.h"
-#include "IRCParser.h"
-#include "ClientSocket.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "ChanUser.h"
-#include "WHOHandler.h"
-#include "lang.h"
-#include "mysqlConn.h"
-#include "DBHelper.h"
-#include "EventLogger.h"
-
-struct trigger_callback {
- int botid;
- trigger_callback_t *func;
-
- struct trigger_callback *next;
-};
-
-struct command_check_user_cache {
- struct ClientSocket *client, *textclient;
- struct UserNode *user;
- struct ChanNode *chan, *sent_chan;
- char **argv;
- int argc;
- char *message;
- struct cmd_binding *cbind;
-};
-
-static struct cmd_binding **cmd_binds;
-static struct cmd_function *cmd_functions = NULL;
-static struct trigger_callback *trigger_callbacks = NULL;
-static struct ClientSocket *tmp_text_client;
-
-static const struct default_language_entry msgtab[] = {
- {"MODCMD_LESS_PARAM_COUNT", "This command requires more parameters."},
- {"MODCMD_CHAN_REQUIRED", "You must provide the name of a channel that exists and the bot is on."},
- {"MODCMD_AUTH_REQUIRED", "You need to be authenticated with AuthServ to use this command."},
- {"MODCMD_CHAN_SUSPENDED", "This channel is currently suspended."},
- {"MODCMD_PRIVILEGED", "$b%s$b is a privileged command."}, /* {ARGS: "god"} */
- {"MODCMD_PUBCMD", "Public commands in $b%s$b are restricted."}, /* {ARGS: "#TestChan"} */
- {"MODCMD_ACCESS_DENIED", "Access denied."},
- {NULL, NULL}
-};
-
-static int get_binds_index(char first_char) {
- if(tolower(first_char) >= 'a' && tolower(first_char) <= 'z') {
- return tolower(first_char) - 'a';
- }
- return 26;
-}
-
-struct ClientSocket* get_prefered_bot(int botid) {
- struct ClientSocket *client;
- for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
- if(client->botid == botid && (client->flags & SOCKET_FLAG_PREFERRED))
- return client;
- }
- return NULL;
-}
-
-static char* get_channel_trigger(int botid, struct ChanNode *chan) {
- struct trigger_cache *trigger;
- for(trigger = chan->trigger; trigger; trigger = trigger->next) {
- if(trigger->botid == botid)
- return trigger->trigger;
- }
- struct trigger_callback *cb;
- for(cb = trigger_callbacks; cb; cb = cb->next) {
- if(cb->botid == botid)
- break;
- }
- char triggerStr[TRIGGERLEN];
- if(cb)
- cb->func(chan, triggerStr);
- else
- strcpy(triggerStr, "+");
- trigger = malloc(sizeof(*trigger));
- if (!trigger) {
- perror("malloc() failed");
- return 0;
- }
- trigger->botid = botid;
- trigger->trigger = strdup(triggerStr);
- trigger->next = chan->trigger;
- chan->trigger = trigger;
- return trigger->trigger;
-}
-
-static void handle_command_async(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct ChanNode *sent_chan, struct cmd_binding *cbind, char **argv, int argc);
-
-static USERAUTH_CALLBACK(command_checked_auth) {
- struct command_check_user_cache *cache = data;
- tmp_text_client = cache->textclient;
- handle_command_async(cache->client, user, cache->chan, cache->sent_chan, cache->cbind, cache->argv, cache->argc);
- free(cache->message);
- free(cache);
-}
-
-static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) {
- struct ChanNode *sent_chan = chan;
- if(message[0] == '#') {
- char *chanName = message;
- message = strstr(message, " ");
- if(!message) return;
- *message = '\0';
- message++;
- struct ChanNode *chan2 = getChanByName(chanName);
- if(chan2)
- chan = chan2;
- }
- message = strdup(message);
- int bind_index = get_binds_index(message[0]);
- char *args = strstr(message, " ");
- if(args) {
- *args = '\0';
- args++;
- }
- struct cmd_binding *cbind;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == client->botid && stricmp(cbind->cmd, message) == 0) {
- //get a text bot
- tmp_text_client = get_prefered_bot(client->botid);
- //parse the arguments...
- char *arga[MAXNUMPARAMS];
- char **argv;
- int argc = 0;
- if(args) {
- while(*args) {
- //skip leading spaces
- while (*args == ' ')
- *args++ = 0;
- arga[argc++] = args;
- if (argc >= MAXNUMPARAMS)
- break;
- while (*args != ' ' && *args)
- args++;
- }
- }
- argv = arga;
- if(argc != 0 && argv[0][0] == '#' && !(cbind->func->flags & CMDFLAG_CHAN_PARAM)) {
- struct ChanNode *chan2 = getChanByName(argv[0]);
- if(chan2) {
- argv += 1;
- argc -= 1;
- chan = chan2;
- }
- }
- if(cbind->parameters) {
- //userdefined parameters...
- char *uargs[MAXNUMPARAMS];
- int uargc = 0;
- char *a,*b = cbind->parameters;
- int allargs, argi;
- do {
- a = strstr(b, " ");
- if(a) *a = '\0';
- if(b[0] == '%') {
- b++;
- if(b[strlen(b)-1] == '-') {
- allargs = 1;
- b[strlen(b)-1] = '\0';
- argi = atoi(b);
- b[strlen(b)-1] = '-';
- } else {
- allargs = 0;
- argi = atoi(b);
- }
- if(argi > 0) {
- if(argi <= argc) {
- uargs[uargc++] = argv[argi-1];
- if(allargs) {
- for(argi++; argi <= argc; argi++)
- uargs[uargc++] = argv[argi-1];
- }
- }
- } else if(!strcmp(b, "c")) {
- uargs[uargc++] = (chan ? chan->name : NULL);
- } else if(!strcmp(b, "n")) {
- uargs[uargc++] = user->nick;
- }
- } else {
- uargs[uargc++] = b;
- }
- if(a) {
- *a = ' ';
- b = a+1;
- }
- } while(a);
- argv = uargs;
- argc = uargc;
- }
- if(argc < cbind->func->paramcount) {
- reply(tmp_text_client, user, "MODCMD_LESS_PARAM_COUNT");
- break;
- }
- if((cbind->func->flags & CMDFLAG_REQUIRE_CHAN) && !chan) {
- reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED");
- break;
- }
- if((cbind->func->flags & CMDFLAG_CHECK_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) {
- //check auth...
- struct command_check_user_cache *data = malloc(sizeof(*data));
- char **temp_argv = malloc(argc*sizeof(*temp_argv));
- if (!data || !temp_argv) {
- perror("malloc() failed");
- break;
- }
- memcpy(temp_argv, argv, argc*sizeof(*temp_argv));
- data->argv = temp_argv;
- data->argc = argc;
- data->client = client;
- data->user = user;
- data->chan = chan;
- data->sent_chan = sent_chan;
- data->message = message;
- data->cbind = cbind;
- data->textclient = tmp_text_client;
- get_userauth(user, command_checked_auth, data);
- return;
- } else
- handle_command_async(client, user, chan, sent_chan, cbind, argv, argc);
- break;
- }
- }
- free(message);
-}
-
-static void handle_command_async(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct ChanNode *sent_chan, struct cmd_binding *cbind, char **argv, int argc) {
- MYSQL_RES *res;
- MYSQL_ROW row;
- int uaccess;
- int eventflags = (cbind->func->flags & (CMDFLAG_LOG | CMDFLAG_OPLOG));
- if((cbind->func->flags & CMDFLAG_REQUIRE_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) {
- reply(tmp_text_client, user, "MODCMD_AUTH_REQUIRED");
- return;
- }
- if(sent_chan && sent_chan != chan) {
- //check pubcmd of this channel
- printf_mysql_query("SELECT `channel_pubcmd` FROM `channels` WHERE `channel_name` = '%s'", escape_string(sent_chan->name));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- uaccess = getChannelAccess(user, sent_chan, 1);
- if(row[0] && uaccess < atoi(row[0])) { //NOTE: HARDCODED DEFAULT: pubcmd = 0
- reply(tmp_text_client, user, "MODCMD_PUBCMD", sent_chan->name);
- return;
- }
- }
- }
- int global_access = ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access);
- if(global_access > 0) {
- int user_global_access = 0;
- printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- user_global_access = atoi(row[0]);
- }
- if(user_global_access < global_access) {
- if(!user_global_access)
- reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd);
- else
- reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED");
- return;
- }
- }
- if((cbind->func->flags & CMDFLAG_REGISTERED_CHAN)) {
- MYSQL_ROW defaults = NULL;
- char access_list[256];
- int access_pos = 0;
- int access_count = 0;
- int minaccess = 0;
- char *str_a, *str_b = cbind->func->channel_access, *str_c;
- if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS)
- str_b = cbind->channel_access;
- access_list[0] = '\0';
- if(str_b) {
- str_c = strdup(str_b);
- str_b = str_c;
- while((str_a = str_b)) {
- str_b = strstr(str_a, ",");
- if(str_b) {
- *str_b = '\0';
- str_b++;
- }
- if(*str_a == '#') {
- str_a++;
- access_pos += sprintf(access_list+access_pos, ", `%s`", str_a);
- access_count++;
- } else {
- if(atoi(str_a) > minaccess)
- minaccess = atoi(str_a);
- }
- }
- free(str_c);
- }
- if(!(chan->flags & CHANFLAG_REQUESTED_CHANINFO) || (sent_chan && sent_chan == chan) || access_count || minaccess) {
- printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- chan->flags |= CHANFLAG_CHAN_REGISTERED;
- chan->channel_id = atoi(row[0]);
- if((sent_chan && sent_chan == chan) || access_count || minaccess) {
- uaccess = getChannelAccess(user, chan, 0);
- if(uaccess < minaccess && isGodMode(user)) {
- eventflags |= CMDFLAG_OPLOG;
- } else if(uaccess < minaccess) {
- //ACCESS DENIED
- reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED");
- return;
- }
- if(!row[1] && !defaults) {
- printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list);
- defaults = mysql_fetch_row(mysql_use());
- }
- if(sent_chan && (sent_chan == chan) && uaccess < (row[1] ? atoi(row[1]) : atoi(defaults[1]))) {
- if(isGodMode(user)) {
- eventflags |= CMDFLAG_OPLOG;
- } else {
- //PUBCMD
- reply(tmp_text_client, user, "MODCMD_PUBCMD", chan->name);
- return;
- }
- }
- int i;
- for(i = 0; i < access_count; i++) {
- if(!row[2+i] && !defaults) {
- printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list);
- defaults = mysql_fetch_row(mysql_use());
- }
- if(uaccess < (row[2+i] ? atoi(row[2+i]) : atoi(defaults[2+i]))) {
- if(isGodMode(user)) {
- eventflags |= CMDFLAG_OPLOG;
- } else {
- reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED");
- return;
- }
- }
- }
- }
- }
- chan->flags |= CHANFLAG_REQUESTED_CHANINFO;
- }
- if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
- reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED");
- return;
- }
- printf_mysql_query("SELECT `botid`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) == NULL) {
- reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED");
- return;
- } else if(!strcmp(row[1], "1")) {
- reply(tmp_text_client, user, "MODCMD_CHAN_SUSPENDED");
- return;
- }
- }
- if((cbind->func->flags & CMDFLAG_REQUIRE_GOD) && !isGodMode(user)) {
- reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd);
- return;
- }
- struct Event *event = createEvent(client, user, chan, cbind->func->name, argv, argc, eventflags);
- cbind->func->func(client, user, chan, argv, argc, event);
-}
-
-static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
- fd_set fds;
- char *trigger;
- struct ClientSocket *client;
- FD_ZERO(&fds);
- for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
- if(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERRED) && !FD_ISSET(client->botid, &fds)) {
- FD_SET(client->botid, &fds);
- trigger = get_channel_trigger(client->botid, chan);
- if(stricmplen(message, trigger, strlen(trigger)) == 0) {
- handle_command(client, user, chan, message + strlen(trigger));
- }
- }
- }
- for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
- if(isUserOnChan(client->user, chan) && !FD_ISSET(client->botid, &fds)) {
- FD_SET(client->botid, &fds);
- trigger = get_channel_trigger(client->botid, chan);
- if(stricmplen(message, trigger, strlen(trigger)) == 0) {
- handle_command(client, user, chan, message + strlen(trigger));
- }
- }
- }
-}
-
-static void got_privmsg(struct UserNode *user, struct UserNode *target, char *message) {
- struct ClientSocket *client;
- for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
- if(client->user == target) {
- handle_command(client, user, NULL, message);
- }
- }
-}
-
-int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags) {
- struct cmd_function *cmdfunc;
- for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
- if(cmdfunc->botid == botid && strcmp(cmdfunc->name, name) == 0)
- return 0;
- }
- cmdfunc = malloc(sizeof(*cmdfunc));
- if (!cmdfunc) {
- perror("malloc() failed");
- return 0;
- }
- cmdfunc->botid = botid;
- cmdfunc->name = strdup(name);
- cmdfunc->func = func;
- cmdfunc->flags = flags;
- cmdfunc->paramcount = paramcount;
- cmdfunc->channel_access = channel_access;
- cmdfunc->global_access = global_access;
- cmdfunc->next = cmd_functions;
- cmd_functions = cmdfunc;
- return 1;
-}
-
-int set_trigger_callback(int botid, trigger_callback_t *func) {
- static struct trigger_callback *cb = NULL;
- for(cb = trigger_callbacks; cb; cb = cb->next) {
- if(cb->botid == botid)
- break;
- }
- if(!cb) {
- cb = malloc(sizeof(*cb));
- if (!cb) {
- perror("malloc() failed");
- return 0;
- }
- cb->botid = botid;
- cb->next = trigger_callbacks;
- trigger_callbacks = cb;
- }
- cb->func = func;
- return 1;
-}
-
-int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) {
- struct trigger_cache *trigger;
- for(trigger = chan->trigger; trigger; trigger = trigger->next) {
- if(trigger->botid == botid) {
- free(trigger->trigger);
- trigger->trigger = strdup(new_trigger);
- return 1;
- }
- }
- return 0;
-}
-
-int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) {
- int bind_index = get_binds_index(cmd[0]);
- struct cmd_binding *cbind;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
- return 0;
- }
- cbind = malloc(sizeof(*cbind));
- if (!cbind) {
- perror("malloc() failed");
- return 0;
- }
- cbind->botid = botid;
- cbind->cmd = strdup(cmd);
- cbind->func = func;
- cbind->parameters = NULL;
- cbind->global_access = 0;
- cbind->channel_access = NULL;
- cbind->flags = 0;
- cbind->next = cmd_binds[bind_index];
- cmd_binds[bind_index] = cbind;
- return 1;
-}
-
-int bind_cmd_to_command(int botid, char *cmd, char *func) {
- struct cmd_function *cmdfunc;
- for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
- if(cmdfunc->botid == botid && strcmp(cmdfunc->name, func) == 0)
- break;
- }
- if(!cmdfunc) return 0;
- int bind_index = get_binds_index(cmd[0]);
- struct cmd_binding *cbind;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
- return 0;
- }
- cbind = malloc(sizeof(*cbind));
- if (!cbind) {
- perror("malloc() failed");
- return 0;
- }
- cbind->botid = botid;
- cbind->cmd = strdup(cmd);
- cbind->func = cmdfunc;
- cbind->next = cmd_binds[bind_index];
- cbind->parameters = NULL;
- cbind->global_access = 0;
- cbind->channel_access = NULL;
- cbind->flags = 0;
- cmd_binds[bind_index] = cbind;
- return 1;
-}
-
-int unbind_cmd(int botid, char *cmd) {
- int bind_index = get_binds_index(cmd[0]);
- struct cmd_binding *cbind, *last = NULL;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
- if(last)
- last->next = cbind->next;
- else
- cmd_binds[bind_index] = cbind->next;
- free(cbind->cmd);
- if(cbind->parameters)
- free(cbind->parameters);
- free(cbind);
- return 1;
- } else
- last = cbind;
- }
- return 0;
-}
-
-struct cmd_function *find_cmd_function(int botid, char *name) {
- struct cmd_function *cmdfunc;
- for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
- if(cmdfunc->botid == botid && stricmp(cmdfunc->name, name) == 0)
- break;
- }
- return cmdfunc;
-}
-
-struct ClientSocket *getTextBot() {
- return tmp_text_client;
-}
-
-void init_modcmd() {
- cmd_binds = calloc(27, sizeof(*cmd_binds));
- bind_chanmsg(got_chanmsg);
- bind_privmsg(got_privmsg);
- register_default_language_table(msgtab);
-}
-
-void free_modcmd() {
- int i;
- for(i = 0; i < 27; i++) {
- struct cmd_binding *cbind, *next;
- for(cbind = cmd_binds[i]; cbind; cbind = next) {
- next = cbind->next;
- free(cbind->cmd);
- if(cbind->parameters)
- free(cbind->parameters);
- if(cbind->channel_access)
- free(cbind->channel_access);
- free(cbind);
- }
- }
- free(cmd_binds);
- struct cmd_function *cmdfunct, *next;
- for(cmdfunct = cmd_functions; cmdfunct; cmdfunct = next) {
- next = cmdfunct->next;
- free(cmdfunct->name);
- free(cmdfunct);
- }
- struct trigger_callback *cb, *next_cb;
- for(cb = trigger_callbacks; cb; cb = next_cb) {
- next_cb = cb->next;
- free(next_cb);
- }
- cmd_functions = NULL;
- trigger_callbacks = NULL;
-}
-
-void bind_set_parameters(int botid, char *cmd, char *parameters) {
- int bind_index = get_binds_index(cmd[0]);
- struct cmd_binding *cbind;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
- if(cbind->parameters)
- free(cbind->parameters);
- cbind->parameters = strdup(parameters);
- return;
- }
- }
-}
-
-void bind_set_global_access(int botid, char *cmd, int gaccess) {
- int bind_index = get_binds_index(cmd[0]);
- struct cmd_binding *cbind;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
- if(gaccess > -1) {
- cbind->global_access = gaccess;
- cbind->flags |= CMDFLAG_OVERRIDE_GLOBAL_ACCESS;
- } else {
- cbind->flags &= ~CMDFLAG_OVERRIDE_GLOBAL_ACCESS;
- }
- return;
- }
- }
-}
-
-void bind_set_channel_access(int botid, char *cmd, char *chanaccess) {
- int bind_index = get_binds_index(cmd[0]);
- struct cmd_binding *cbind;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
- if(cbind->channel_access)
- free(cbind->channel_access);
- if(chanaccess) {
- cbind->channel_access = strdup(chanaccess);
- cbind->flags |= CMDFLAG_OVERRIDE_CHANNEL_ACCESS;
- } else {
- cbind->channel_access = NULL;
- cbind->flags &= ~CMDFLAG_OVERRIDE_CHANNEL_ACCESS;
- }
- return;
- }
- }
-}
-
-struct cmd_binding *find_cmd_binding(int botid, char *cmd) {
- int bind_index = get_binds_index(cmd[0]);
- struct cmd_binding *cbind;
- for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
- if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
- return cbind;
- }
- }
- return NULL;
-}
-
+++ /dev/null
-#ifndef _modcmd_h
-#define _modcmd_h
-#include "main.h"
-
-#define CMDFLAG_REQUIRE_CHAN 0x0001
-#define CMDFLAG_REQUIRE_AUTH 0x0002
-#define CMDFLAG_REQUIRE_GOD 0x0004
-#define CMDFLAG_CHECK_AUTH 0x0008
-#define CMDFLAG_REGISTERED_CHAN 0x0010
-#define CMDFLAG_OVERRIDE_GLOBAL_ACCESS 0x0020
-#define CMDFLAG_OVERRIDE_CHANNEL_ACCESS 0x0040
-#define CMDFLAG_CHAN_PARAM 0x0080
-#define CMDFLAG_LOG 0x0100
-#define CMDFLAG_OPLOG 0x0200
-
-struct ClientSocket;
-struct UserNode;
-struct ChanNode;
-struct Event;
-
-#define CMD_BIND(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(struct UserNode *user), UNUSED_ARG(struct ChanNode *chan), UNUSED_ARG(char **argv), UNUSED_ARG(char argc), UNUSED_ARG(struct Event *event))
-typedef void cmd_bind_t(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char **argv, char argc, struct Event *event);
-typedef void trigger_callback_t(struct ChanNode *chan, char *trigger);
-
-struct cmd_function {
- char *name;
- int botid;
- cmd_bind_t *func;
- unsigned int flags;
- int paramcount;
- int global_access;
- char *channel_access;
-
- struct cmd_function *next;
-};
-
-struct cmd_binding {
- char *cmd;
- int botid;
- struct cmd_function *func;
- unsigned int flags;
- char *parameters;
- int global_access;
- char *channel_access;
-
- struct cmd_binding *next;
-};
-
-struct trigger_cache {
- int botid;
- char *trigger;
-
- struct trigger_cache *next;
-};
-
-void init_modcmd();
-void free_modcmd();
-struct ClientSocket* get_prefered_bot(int botid);
-int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags);
-int set_trigger_callback(int botid, trigger_callback_t *func);
-int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger);
-int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func);
-int bind_cmd_to_command(int botid, char *cmd, char *func);
-int unbind_cmd(int botid, char *cmd);
-struct cmd_function *find_cmd_function(int botid, char *name);
-struct ClientSocket *getTextBot();
-void bind_set_parameters(int botid, char *cmd, char *parameters);
-void bind_set_global_access(int botid, char *cmd, int gaccess);
-void bind_set_channel_access(int botid, char *cmd, char *chanaccess);
-struct cmd_binding *find_cmd_binding(int botid, char *cmd);
-
-#endif
\ No newline at end of file
--- /dev/null
+
+#define MYSQL_HOST "127.0.0.1"
+#define MYSQL_PORT 3306
+#define MYSQL_USER "neonserv"
+#define MYSQL_PASS ""
+#define MYSQL_BASE "neonserv"
+++ /dev/null
-
-#include "mysqlConn.h"
-
-struct used_result {
- MYSQL_RES *result;
- struct used_result *next;
-};
-
-struct escaped_string {
- char *string;
- struct escaped_string *next;
-};
-
-MYSQL *mysql_conn = NULL;
-static struct used_result *used_results;
-static struct escaped_string *escaped_strings;
-
-void check_mysql() {
- int errid;
- if((errid = mysql_ping(mysql_conn))) {
- if(mysql_errno(mysql_conn) == CR_SERVER_GONE_ERROR) {
- if(!mysql_real_connect(mysql_conn, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_BASE, MYSQL_PORT, NULL, 0)) {
- show_mysql_error();
- }
- } else {
- //mysql error
- show_mysql_error();
- }
- }
-}
-
-MYSQL_RES *mysql_use() {
- MYSQL_RES *res = mysql_store_result(mysql_conn);
- struct used_result *result = malloc(sizeof(*result));
- if (!result) {
- mysql_free_result(res);
- return NULL;
- }
- result->result = res;
- result->next = used_results;
- used_results = result;
- return res;
-}
-
-void mysql_free() {
- struct used_result *result, *next_result;
- for(result = used_results; result; result = next_result) {
- next_result = result->next;
- mysql_free_result(result->result);
- free(result);
- }
- used_results = NULL;
- struct escaped_string *escaped, *next_escaped;
- for(escaped = escaped_strings; escaped; escaped = next_escaped) {
- next_escaped = escaped->next;
- free(escaped->string);
- free(escaped);
- }
- escaped_strings = NULL;
-}
-
-void init_mysql() {
- mysql_conn = mysql_init(NULL);
- if (!mysql_real_connect(mysql_conn, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_BASE, MYSQL_PORT, NULL, 0)) {
- //error
- show_mysql_error();
- }
-}
-
-void free_mysql() {
- mysql_close(mysql_conn);
-}
-
-void show_mysql_error() {
- //show mysql_error()
- printf("MySQL Error: %s\n", mysql_error(mysql_conn));
-}
-
-void printf_mysql_query(const char *text, ...) {
- va_list arg_list;
- char queryBuf[MYSQLMAXLEN];
- int pos;
- queryBuf[0] = '\0';
- va_start(arg_list, text);
- pos = vsnprintf(queryBuf, MYSQLMAXLEN - 2, text, arg_list);
- va_end(arg_list);
- if (pos < 0 || pos > (MYSQLMAXLEN - 2)) pos = MYSQLMAXLEN - 2;
- queryBuf[pos] = '\0';
- printf("MySQL: %s\n", queryBuf);
- if(mysql_query(mysql_conn, queryBuf)) {
- check_mysql();
- if(mysql_query(mysql_conn, queryBuf)) {
- show_mysql_error();
- }
- }
-}
-
-char* escape_string(const char *str) {
- struct escaped_string *escapedstr = malloc(sizeof(*escapedstr));
- if (!escapedstr) {
- return NULL;
- }
- char escaped[strlen(str)*2+1];
- mysql_real_escape_string(mysql_conn, escaped, str, strlen(str));
- escapedstr->string = strdup(escaped);
- escapedstr->next = escaped_strings;
- escaped_strings = escapedstr;
- return escapedstr->string;
-}
+++ /dev/null
-#ifndef _MySQLConn_h
-#define _MySQLConn_h
-
-#include "main.h"
-#include <mysql.h>
-#include <mysql/errmsg.h>
-
-#define MYSQLMAXLEN 1024
-
-extern MYSQL *mysql_conn;
-
-void check_mysql();
-MYSQL_RES *mysql_use();
-void mysql_free();
-void init_mysql();
-void free_mysql();
-void show_mysql_error();
-void printf_mysql_query(const char *text, ...) PRINTF_LIKE(1, 2);
-char* escape_string(const char *str);
-
-#endif
\ No newline at end of file
--- /dev/null
+
+#include "BanNode.h"
+#include "ChanNode.h"
+#include "tools.h"
+
+struct BanNode* addChannelBan(struct ChanNode *chan, char *mask) {
+ struct BanNode *ban = malloc(sizeof(*ban));
+ ban->chan = chan;
+ ban->mask = strdup(mask);
+ ban->next = chan->bans;
+ chan->bans = ban;
+ return ban;
+}
+
+struct BanNode* getMatchingChannelBan(struct ChanNode *chan, char *mask) {
+ struct BanNode *cban;
+ for(cban = chan->bans; cban; cban = cban->next) {
+ if(!match(cban->mask, mask)) {
+ return cban;
+ }
+ }
+ return NULL;
+}
+
+void removeChannelBanMask(struct ChanNode *chan, char *mask) {
+ struct BanNode *cban, *last = NULL;
+ for(cban = chan->bans; cban; cban = cban->next) {
+ if(!strcmp(cban->mask, mask)) {
+ if(last)
+ last->next = cban->next;
+ else
+ chan->bans = cban->next;
+ free(cban->mask);
+ free(cban);
+ break;
+ } else
+ last = cban;
+ }
+}
+
+void removeChannelBan(struct BanNode *ban) {
+ struct BanNode *cban, *last = NULL;
+ struct ChanNode *chan = ban->chan;
+ for(cban = chan->bans; cban; cban = cban->next) {
+ if(cban == ban) {
+ if(last)
+ last->next = ban->next;
+ else
+ chan->bans = ban->next;
+ free(ban->mask);
+ free(ban);
+ break;
+ } else
+ last = cban;
+ }
+}
+
+void removeChannelBans(struct ChanNode *chan) {
+ struct BanNode *ban, *next;
+ for(ban = chan->bans; ban; ban = next) {
+ next = ban->next;
+ free(ban->mask);
+ free(ban);
+ }
+ chan->bans = NULL;
+}
--- /dev/null
+#ifndef _BanNode_h
+#define _BanNode_h
+#include "main.h"
+
+struct ChanNode;
+
+struct BanNode {
+ char *mask;
+ struct ChanNode *chan;
+
+ struct BanNode *next;
+};
+
+struct BanNode* addChannelBan(struct ChanNode *chan, char *mask);
+struct BanNode* getMatchingChannelBan(struct ChanNode *chan, char *mask);
+void removeChannelBanMask(struct ChanNode *chan, char *mask);
+void removeChannelBan(struct BanNode *ban);
+void removeChannelBans(struct ChanNode *chan);
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "UserNode.h"
+#include "BanNode.h"
+#include "modcmd.h"
+#include "ModeNode.h"
+
+static struct ChanNode **chanList;
+
+void init_ChanNode() {
+ /*
+ len pos chars
+ 26 0 a-z
+ 10 26 0-9
+ 10 36 {|}~[\]^_`
+ 1 46 *everything else*
+ ---------------------------
+ = 47
+ */
+ #define CHANNEL_LIST_SIZE 47
+ chanList = calloc(CHANNEL_LIST_SIZE, sizeof(*chanList));
+}
+
+void free_ChanNode() {
+ //kamikaze free all channels and chanusers
+ int i;
+ struct ChanNode *chan, *next;
+ struct ChanUser *chanuser, *next_chanuser;
+ for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
+ for(chan = chanList[i]; chan; chan = next) {
+ next = chan->next;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next_chanuser) {
+ next_chanuser = getChannelUsers(chan, chanuser);
+ free(chanuser);
+ }
+ freeChanNode(chan);
+ }
+ }
+ free(chanList);
+}
+
+int is_valid_chan(const char *name) {
+ unsigned int ii;
+ if (*name !='#')
+ return 0;
+ for (ii=1; name[ii]; ++ii) {
+ if ((name[ii] > 0) && (name[ii] <= 32))
+ return 0;
+ if (name[ii] == ',')
+ return 0;
+ if (name[ii] == '\xa0')
+ return 0;
+ }
+ return 1;
+}
+
+static int get_chanlist_entry(int name) {
+ if((name > 0 && name <= 32) || name == ',' || name == '\xa0') return -1; //invalid name
+ if(tolower(name) >= 97 && tolower(name) <= 122) {
+ return (tolower(name) - 97);
+ }
+ if(tolower(name) >= 48 && tolower(name) <= 57) {
+ return (tolower(name) - 48 + 26);
+ }
+ /* {|}~[\]^_` */
+ if(name == '{') return 36;
+ if(name == '|') return 37;
+ if(name == '}') return 38;
+ if(name == '~') return 39;
+ if(name == '[') return 40;
+ if(name == '\\') return 41;
+ if(name == ']') return 42;
+ if(name == '^') return 43;
+ if(name == '_') return 44;
+ if(name == '`') return 45;
+ return 46;
+}
+
+struct ChanNode* getChanByName(const char *name) { //case insensitive
+ int chanListIndex = get_chanlist_entry(name[1]);
+ if(chanListIndex == -1 || chanList[chanListIndex] == NULL)
+ return NULL;
+ struct ChanNode *chan;
+ for(chan = chanList[chanListIndex]; chan; chan = chan->next) {
+ if(!stricmp(name, chan->name))
+ return chan;
+ }
+ return NULL;
+}
+
+struct ChanNode* addChannel(const char *name) {
+ int chanListIndex = get_chanlist_entry(name[1]);
+ if(chanListIndex == -1 || !is_valid_chan(name))
+ return NULL;
+ struct ChanNode *chan = malloc(sizeof(*chan));
+ if (!chan)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ strcpy(chan->name, name);
+ chan->user = NULL;
+ chan->bans = NULL;
+ chan->usercount = 0;
+ chan->chanbot = NULL;
+ chan->topic[0] = 0;
+ chan->flags = 0;
+ /* mode lists */
+ chan->modes = createModeNode(chan);
+ chan->trigger = NULL;
+
+ chan->next = chanList[chanListIndex];
+ chanList[chanListIndex] = chan;
+ return chan;
+}
+
+int getChannelCount() {
+ int i, count = 0;
+ struct ChanNode *chan;
+ for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
+ for(chan = chanList[i]; chan; chan = chan->next) {
+ count++;
+ }
+ }
+ return count;
+}
+
+int getChanUserCount() {
+ int i, count = 0;
+ struct ChanNode *chan;
+ for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
+ for(chan = chanList[i]; chan; chan = chan->next) {
+ count += chan->usercount;
+ }
+ }
+ return count;
+}
+
+int getChanBanCount() {
+ int i, count = 0;
+ struct ChanNode *chan;
+ struct BanNode *ban;
+ for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
+ for(chan = chanList[i]; chan; chan = chan->next) {
+ for(ban = chan->bans; ban; ban = ban->next)
+ count ++;
+ }
+ }
+ return count;
+}
+
+void delChannel(struct ChanNode* chan, int freeChan) {
+ int chanListIndex = get_chanlist_entry(chan->name[1]);
+ if(chanListIndex == -1) return;
+ struct ChanNode *cchan, *last_chan = NULL;
+ for(cchan = chanList[chanListIndex]; cchan; cchan = cchan->next) {
+ if(cchan == chan) {
+ if(last_chan)
+ last_chan->next = chan->next;
+ else
+ chanList[chanListIndex] = chan->next;
+ break;
+ } else
+ last_chan = cchan;
+ }
+ if(chan->user) {
+ //free all chanusers
+ struct ChanUser *chanuser, *next;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
+ next = getChannelUsers(chan, chanuser);
+ removeChanUserFromLists(chanuser, 0, 1, 1);
+ }
+ }
+ if(freeChan)
+ freeChanNode(chan);
+ else
+ chan->next = NULL;
+}
+
+void freeChanNode(struct ChanNode* chan) {
+ if(chan->trigger) {
+ struct trigger_cache *trigger, *next_trigger;
+ for(trigger = chan->trigger; trigger; trigger = next_trigger) {
+ next_trigger = trigger->next;
+ free(trigger->trigger);
+ free(trigger);
+ }
+ }
+ freeModeNode(chan->modes);
+ if(chan->bans)
+ removeChannelBans(chan);
+ free(chan);
+}
+
+void checkChannelVisibility(struct ChanNode* chan) {
+ struct ChanUser *chanuser, *next;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(chanuser->user->flags & USERFLAG_ISBOT) {
+ chan->chanbot = chanuser->user;
+ return;
+ }
+ }
+ //free the channel...
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
+ next = getChannelUsers(chan, chanuser);
+ //remove the channel from the user's channel-list
+ removeChanUserFromLists(chanuser, 0, 1, 0);
+ if(!chanuser->user->channel) {
+ //free the user (no more channels)
+ delUser(chanuser->user, 1);
+ }
+ free(chanuser);
+ }
+ chan->user = NULL;
+ delChannel(chan, 1);
+}
--- /dev/null
+#ifndef _ChanNode_h
+#define _ChanNode_h
+#include "main.h"
+
+struct ChanUser;
+struct trigger_cache;
+struct ModeNode;
+
+#define CHANFLAG_RECEIVED_USERLIST 0x01
+#define CHANFLAG_REQUESTED_CHANINFO 0x02
+#define CHANFLAG_CHAN_REGISTERED 0x04
+#define CHANFLAG_HAVE_INVISIBLES 0x08
+
+struct ChanNode {
+ char name[CHANNELLEN+1];
+ char topic[TOPICLEN+1];
+ struct ChanUser *user;
+ unsigned int usercount;
+ unsigned char flags;
+ struct ModeNode *modes;
+ struct BanNode *bans;
+
+ struct UserNode *chanbot;
+ struct trigger_cache *trigger;
+ int channel_id;
+
+ struct ChanNode *next;
+};
+
+void init_ChanNode();
+void free_ChanNode();
+int is_valid_chan(const char *name);
+struct ChanNode* getChanByName(const char *name);
+struct ChanNode* addChannel(const char *chan);
+int getChannelCount();
+int getChanUserCount();
+int getChanBanCount();
+void delChannel(struct ChanNode* chan, int freeChan);
+void freeChanNode(struct ChanNode* chan);
+void checkChannelVisibility(struct ChanNode* chan);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "ChanUser.h"
+#include "ChanNode.h"
+#include "UserNode.h"
+
+struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user) {
+ struct ChanUser *chanuser = malloc(sizeof(*chan));
+ if (!chanuser)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ chanuser->flags = 0;
+ chanuser->user = user;
+ chanuser->chan = chan;
+
+ chanuser->changeTime = 0;
+
+ chanuser->next_user = chan->user;
+ chan->user = chanuser;
+ chan->usercount++;
+
+ chanuser->next_chan = user->channel;
+ user->channel = chanuser;
+
+ return chanuser;
+}
+
+struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user) {
+ struct ChanUser *chanuser = malloc(sizeof(*chan));
+ if (!chanuser)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ chanuser->flags = CHANUSERFLAG_INVISIBLE;
+ chanuser->user = user;
+ chanuser->chan = chan;
+
+ chanuser->changeTime = 0;
+
+ chanuser->next_user = chan->user;
+ chan->user = chanuser;
+ chan->usercount++;
+
+ return chanuser;
+}
+
+int isUserOnChan(struct UserNode *user, struct ChanNode *chan) {
+ struct ChanUser *chanuser;
+ for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
+ if(chanuser->chan == chan)
+ return 1;
+ }
+ return 0;
+}
+
+struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan) {
+ struct ChanUser *chanuser;
+ for(chanuser = user->channel; chanuser; chanuser = chanuser->next_chan) {
+ if(chanuser->chan == chan)
+ return chanuser;
+ }
+ return NULL;
+}
+
+struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last) {
+ if(last == NULL)
+ return chan->user;
+ else
+ return last->next_user;
+}
+
+struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last) {
+ if(last == NULL)
+ return user->channel;
+ else
+ return last->next_chan;
+}
+
+void delChanUser(struct ChanUser *chanuser, int freeChanUser) {
+ struct ChanUser *cchanuser, *last;
+ //remove it from the user's channel-list
+ if(!(chanuser->flags & CHANUSERFLAG_INVISIBLE)) {
+ last = NULL;
+ for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
+ if(cchanuser == chanuser) {
+ if(last)
+ last->next_chan = chanuser->next_chan;
+ else
+ chanuser->user->channel = chanuser->next_chan;
+ break;
+ } else
+ last = cchanuser;
+ }
+ }
+
+ //remove it from the channel's user-list
+ last = NULL;
+ for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
+ if(cchanuser == chanuser) {
+ chanuser->chan->usercount--;
+ if(last)
+ last->next_user = chanuser->next_user;
+ else
+ chanuser->chan->user = chanuser->next_user;
+ break;
+ } else
+ last = cchanuser;
+ }
+
+ if(freeChanUser)
+ free(chanuser);
+ else {
+ chanuser->next_chan = NULL;
+ chanuser->next_user = NULL;
+ }
+}
+
+void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int freeChanUser) {
+ struct ChanUser *cchanuser, *last;
+ if(remove_from_userlist) {
+ //remove it from the channel's user-list
+ last = NULL;
+ for(cchanuser = chanuser->chan->user; cchanuser; cchanuser = cchanuser->next_user) {
+ if(cchanuser == chanuser) {
+ chanuser->chan->usercount--;
+ if(last)
+ last->next_user = chanuser->next_user;
+ else
+ chanuser->chan->user = chanuser->next_user;
+ break;
+ } else
+ last = cchanuser;
+ }
+ chanuser->next_user = NULL;
+ }
+ if(remove_from_channellist) {
+ //remove it from the user's channel-list
+ last = NULL;
+ for(cchanuser = chanuser->user->channel; cchanuser; cchanuser = cchanuser->next_chan) {
+ if(cchanuser == chanuser) {
+ if(last)
+ last->next_chan = chanuser->next_chan;
+ else
+ chanuser->user->channel = chanuser->next_chan;
+ break;
+ } else
+ last = cchanuser;
+ }
+ chanuser->next_chan = NULL;
+ }
+
+ if(freeChanUser)
+ free(chanuser);
+}
+
--- /dev/null
+#ifndef _ChanUser_h
+#define _ChanUser_h
+#include "main.h"
+
+#define CHANUSERFLAG_OPPED 0x01
+#define CHANUSERFLAG_VOICED 0x02
+#define CHANUSERFLAG_INVISIBLE 0x04
+
+#define CHANUSERFLAG_OPPED_OR_VOICED (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED)
+
+struct ChanNode;
+struct UserNode;
+
+struct ChanUser {
+ unsigned char flags;
+ struct ChanNode *chan;
+ struct UserNode *user;
+
+ int chageEvents;
+ time_t changeTime;
+
+ struct ChanUser *next_user;
+ struct ChanUser *next_chan;
+};
+
+struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user);
+struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user);
+int isUserOnChan(struct UserNode *user, struct ChanNode *chan);
+struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan);
+struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last);
+struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last);
+void delChanUser(struct ChanUser *chanuser, int freeChanUser);
+void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int freeChanUser);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "ClientSocket.h"
+#include "IRCParser.h"
+#include "UserNode.h"
+
+struct socket_list {
+ struct ClientSocket *data;
+ unsigned count;
+};
+
+//the magic list :P
+static struct socket_list *sockets = NULL;
+static char buffer[BUF_SIZ];
+
+static void init_sockets() {
+ sockets = malloc(sizeof(*sockets));
+ if (!sockets)
+ {
+ perror("malloc() failed");
+ return;
+ }
+ sockets->data = NULL;
+ sockets->count = 0;
+}
+
+struct ClientSocket* create_socket(char *host, int port, char *pass, struct UserNode *user) {
+ if(sockets == NULL) init_sockets();
+ struct ClientSocket *client = malloc(sizeof(*client));
+ if (!client)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ client->host = strdup(host);
+ client->port = port;
+ printf("Connect: %s:%d", client->host, client->port);
+ client->pass = (pass == NULL ? NULL : strdup(pass));
+ client->user = user;
+ client->flags = 0;
+ client->bufferpos = 0;
+ client->traffic_in = 0;
+ client->traffic_out = 0;
+ client->connection_time = 0;
+ client->botid = 0;
+ client->clientid = 0;
+ client->next = sockets->data;
+ sockets->data = client;
+ return client;
+}
+
+int connect_socket(struct ClientSocket *client) {
+ if((client->flags & SOCKET_FLAG_CONNECTED)) return 1;
+ struct hostent *host;
+ struct sockaddr_in addr;
+ int sock;
+ if (!inet_aton(client->host, &addr.sin_addr))
+ {
+ host = gethostbyname(client->host);
+ if (!host)
+ {
+ herror("gethostbyname() failed");
+ return 0;
+ }
+ addr.sin_addr = *(struct in_addr*)host->h_addr;
+ }
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (sock == -1)
+ {
+ perror("socket() failed");
+ return 0;
+ }
+
+ addr.sin_port = htons(client->port);
+ addr.sin_family = AF_INET;
+
+ if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1)
+ {
+ perror("connect() failed");
+ return 0;
+ }
+
+ client->sock = sock;
+ client->flags |= SOCKET_FLAG_CONNECTED;
+ client->connection_time = time(0);
+
+ //send the IRC Headers
+ char sendBuf[512];
+ int len;
+
+ if(client->pass) {
+ len = sprintf(sendBuf, "PASS :%s\n", client->pass);
+ write_socket(client, sendBuf, len);
+ }
+ len = sprintf(sendBuf, "USER %s 0 0 :%s\n", client->user->ident, client->user->realname);
+ write_socket(client, sendBuf, len);
+ len = sprintf(sendBuf, "NICK %s\n", client->user->nick);
+ write_socket(client, sendBuf, len);
+
+ return 1;
+}
+
+int close_socket(struct ClientSocket *client) {
+ if(client == NULL) return 0;
+ if((client->flags & SOCKET_FLAG_CONNECTED))
+ close(client->sock);
+ struct ClientSocket *sock, *last_sock = NULL;
+ for (sock = sockets->data; sock; sock = sock->next) {
+ if(sock == client) {
+ if(last_sock)
+ last_sock->next = sock->next;
+ else
+ sockets->data = sock->next;
+ sockets->count--;
+ } else
+ last_sock = sock;
+ }
+ free(client->host);
+ free(client->pass);
+ free(client);
+ return 1;
+}
+
+int write_socket(struct ClientSocket *client, char* msg, int len) {
+ if(!(client->flags & SOCKET_FLAG_CONNECTED)) return 0;
+ printf("[send %d] %s", len, msg);
+ write(client->sock, msg, len);
+ client->traffic_out += len;
+ return 1;
+}
+
+void socket_loop(int timeout_seconds) {
+ if(sockets == NULL) return;
+ fd_set fds;
+ struct timeval timeout;
+ struct ClientSocket *sock;
+ int ret = 0, bytes, i;
+
+ FD_ZERO(&fds);
+ for (sock = sockets->data; sock; sock = sock->next) {
+ if(!(sock->flags & SOCKET_FLAG_CONNECTED)) continue; //skip disconnected sockets
+ FD_SET(sock->sock, &fds);
+ if(sock->sock > ret)
+ ret = sock->sock;
+ }
+ timeout.tv_sec = timeout_seconds;
+ timeout.tv_usec = 0;
+ ret = select(ret + 1, &fds, NULL, NULL, &timeout);
+ if(ret == 0) return;
+ for (sock = sockets->data; sock; sock = sock->next) {
+ if((sock->flags & SOCKET_FLAG_CONNECTED) && FD_ISSET(sock->sock, &fds)) {
+ if(sock->bufferpos != 0) {
+ bytes = read(sock->sock, buffer, sizeof(buffer));
+ if(bytes > 0) {
+ for(i = 0; i < bytes; i++) {
+ if(sock->bufferpos + i == BUF_SIZ*2) break; //buffer overflow
+ sock->buffer[sock->bufferpos + i] = buffer[i];
+ }
+ sock->bufferpos += i;
+ }
+ } else {
+ bytes = read(sock->sock, sock->buffer, sizeof(sock->buffer));
+ if(bytes > 0)
+ sock->bufferpos = bytes;
+ }
+ if(bytes <= 0) {
+ //error
+ sock->flags &= ~(SOCKET_FLAG_CONNECTED | SOCKET_FLAG_READY);
+ bot_disconnect(sock);
+ } else {
+ sock->traffic_in += bytes;
+ int used = parse_lines(sock, sock->buffer, sock->bufferpos);
+ if(used == sock->bufferpos + 1) {
+ //used all bytes so just reset the bufferpos
+ sock->bufferpos = 0;
+ } else {
+ for(i = 0; i < sock->bufferpos - used; i++) {
+ sock->buffer[i] = sock->buffer[i+used];
+ }
+ sock->bufferpos -= used;
+ }
+ }
+ }
+ }
+}
+
+void
+putsock(struct ClientSocket *client, const char *text, ...)
+{
+ va_list arg_list;
+ char sendBuf[MAXLEN];
+ int pos;
+ if (!(client->flags & SOCKET_FLAG_CONNECTED)) return;
+ sendBuf[0] = '\0';
+ va_start(arg_list, text);
+ pos = vsnprintf(sendBuf, MAXLEN - 2, text, arg_list);
+ va_end(arg_list);
+ if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
+ sendBuf[pos] = '\n';
+ sendBuf[pos+1] = '\0';
+ write_socket(client, sendBuf, pos+1);
+}
+
+struct ClientSocket* getBots(int flags, struct ClientSocket* last_bot) {
+ struct ClientSocket *sock = (last_bot ? last_bot->next : sockets->data);
+ if(sock == NULL) return NULL;
+ for (; sock; sock = sock->next) {
+ if(!flags || (sock->flags & flags) == flags)
+ return sock;
+ }
+ return NULL;
+}
+
+void free_sockets() {
+ if(!sockets) return;
+ struct ClientSocket *client, *next;
+ for (client = sockets->data; client; client = next) {
+ next = client->next;
+ if((client->flags & SOCKET_FLAG_CONNECTED))
+ close(client->sock);
+ free(client->host);
+ free(client->pass);
+ free(client);
+ }
+ free(sockets);
+ sockets = NULL;
+}
--- /dev/null
+#ifndef _ClientSocket_h
+#define _ClientSocket_h
+
+#include "main.h"
+
+#define SOCKET_FLAG_DEAD 0x01
+#define SOCKET_FLAG_CONNECTED 0x02
+#define SOCKET_FLAG_READY 0x04
+#define SOCKET_FLAG_PREFERRED 0x08 /* prefered bot to send datas to the IRC World (NOTICE's WHO's etc pp) */
+
+#define BUF_SIZ 512
+
+struct UserNode;
+struct trigger_cache;
+
+struct ClientSocket {
+ int sock;
+ unsigned char flags;
+ char buffer[BUF_SIZ*2]; //we need to store up to 2 full commands at once
+ unsigned int bufferpos;
+ char *host;
+ int port;
+ char *pass;
+ struct UserNode *user;
+ unsigned long traffic_in;
+ unsigned long traffic_out;
+ time_t connection_time;
+
+ int botid : 16;
+ int clientid : 16;
+
+ struct ClientSocket *next;
+};
+
+struct ClientSocket* create_socket(char *host, int port, char *pass, struct UserNode *user);
+int connect_socket(struct ClientSocket *client);
+int close_socket(struct ClientSocket *client);
+int write_socket(struct ClientSocket *client, char* msg, int len);
+void socket_loop(int timeout_seconds);
+void putsock(struct ClientSocket *client, const char *text, ...) PRINTF_LIKE(2, 3);
+struct ClientSocket* getBots(int flags, struct ClientSocket* last_bot);
+void free_sockets();
+
+#endif
\ No newline at end of file
--- /dev/null
+//Database of NeonServ V4 modifications for NeonServ V5
+
+ALTER TABLE `bots` CHANGE `botclass` `botclass` INT( 10 ) NOT NULL;
+
+ALTER TABLE `users` CHANGE `user_lang` `user_lang` VARCHAR( 6 ) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL;
+ALTER TABLE `users` ADD `user_reply_privmsg` TINYINT( 1 ) NOT NULL ;
+
+CREATE TABLE IF NOT EXISTS `godlog` (
+ `godlog_id` int(11) NOT NULL AUTO_INCREMENT,
+ `godlog_uid` int(11) NOT NULL,
+ `godlog_cid` int(15) NOT NULL,
+ `godlog_time` int(15) NOT NULL,
+ `godlog_cmd` varchar(512) NOT NULL,
+ PRIMARY KEY (`godlog_id`)
+) ENGINE=MyISAM;
+
+ALTER TABLE `channels` ADD `channel_lastgiveowner` INT( 11 ) NOT NULL AFTER `channel_lastvisit`;
+
+CREATE TABLE IF NOT EXISTS `owner_history` (
+`owner_history_id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
+`owner_history_cid` INT( 11 ) NOT NULL ,
+`owner_history_uid` INT( 11 ) NOT NULL ,
+`owner_history_time` INT( 11 ) NOT NULL ,
+INDEX ( `owner_history_cid` )
+) ENGINE = MYISAM ;
+
+ALTER TABLE `chanusers` ADD INDEX ( `chanuser_cid` ) ;
+ALTER TABLE `chanusers` ADD INDEX ( `chanuser_uid` ) ;
+
+ALTER TABLE `bot_binds` ADD `chan_access` VARCHAR( 256 ) NULL DEFAULT NULL AFTER `parameters`;
+
+ALTER TABLE `bot_binds` CHANGE `global_access` `global_access` INT( 3 ) NULL;
+
+ALTER TABLE `bans` CHANGE `ban_owner` `ban_owner` INT( 11 ) NOT NULL;
+
+ALTER TABLE `channels` ADD `channel_exttopic` TINYINT( 1 ) NOT NULL AFTER `channel_topicmask` ,
+ADD `channel_exttopic_topic` VARCHAR( 512 ) NOT NULL AFTER `channel_exttopic`;
+
+ALTER TABLE `bots` ADD `max_channels` INT( 5 ) NOT NULL ;
+
+ALTER TABLE `bot_binds` CHANGE `botid` `botclass` INT( 11 ) NOT NULL;
+ALTER TABLE `bots` DROP `whoisbot` ;
+ALTER TABLE `bots` DROP `bindFrom` ;
+
+CREATE TABLE IF NOT EXISTS `help` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `lang` varchar(6) NOT NULL,
+ `ident` varchar(64) NOT NULL,
+ `text` text NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+CREATE TABLE IF NOT EXISTS `language` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `lang` varchar(5) NOT NULL,
+ `ident` varchar(64) NOT NULL,
+ `text` varchar(256) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+ALTER TABLE `bot_channels` ADD `suspended` TINYINT( 1 ) NOT NULL;
+
+ALTER TABLE `users` ADD UNIQUE (`user_user`);
+
+ALTER TABLE `noinvite` ADD INDEX ( `cid`, `uid` );
\ No newline at end of file
--- /dev/null
+
+#include "DBHelper.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "mysqlConn.h"
+#include "lang.h"
+#include "tools.h"
+
+void _loadUserSettings(struct UserNode *user) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `user_lang`, `user_reply_privmsg`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ user->language = get_language_by_tag(row[0]);
+ if(user->language == NULL) user->language = get_default_language();
+ if(strcmp(row[1], "0"))
+ user->flags |= USERFLAG_REPLY_PRIVMSG;
+ if(strcmp(row[2], "0"))
+ user->flags |= USERFLAG_GOD_MODE;
+ } else
+ user->language = get_default_language();
+ user->flags |= USERFLAG_LOADED_SETTINGS;
+}
+
+int isGodMode(struct UserNode *user) {
+ loadUserSettings(user);
+ return (user->flags & USERFLAG_GOD_MODE);
+}
+
+int getChannelAccess(struct UserNode *user, struct ChanNode *chan, int override) {
+ if(!(user->flags & USERFLAG_ISAUTHED)) return 0;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int caccess = 0;
+ printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ if(strcmp(row[2], "0") && override)
+ caccess = atoi(row[1]);
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id);
+ //
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ int cflags = atoi(row[1]);
+ if(!(cflags & DB_CHANUSER_SUSPENDED) && atoi(row[0]) > caccess)
+ caccess = atoi(row[0]);
+ }
+ return caccess;
+ }
+ return 0;
+}
+
+char *getChanDefault(char *channel_setting) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_setting);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return "";
+ return row[0];
+}
+
+int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_override, int allow_501) {
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
+ if((user->flags & USERFLAG_ISIRCOP)) return 1;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_setting, chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return 0;
+ int require_access = atoi((row[0] ? row[0] : getChanDefault(channel_setting)));
+ if(require_access == 0) return 1;
+ if(!(user->flags & USERFLAG_ISAUTHED)) return 0;
+ int caccess = 0;
+ printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ int cflags = atoi(row[1]);
+ if(!(cflags & DB_CHANUSER_SUSPENDED))
+ caccess = atoi(row[0]);
+ }
+ }
+ if(caccess >= require_access) return 1;
+ if(caccess == 500 && require_access == 501 && allow_501) return 1;
+ return 0;
+}
+
+void _loadChannelSettings(struct ChanNode *chan) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chan->flags |= CHANFLAG_CHAN_REGISTERED;
+ chan->channel_id = atoi(row[0]);
+ }
+ chan->flags |= CHANFLAG_REQUESTED_CHANINFO;
+}
+
+//TODO: fix performance: we should cache the user access
+int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer) {
+ /* Don't protect if someone is attacking himself, or if the aggressor is an IRC Operator. */
+ if(victim == issuer || (issuer->flags & USERFLAG_ISIRCOP)) return 0;
+
+ /* Don't protect if no one is to be protected. */
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char protection;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
+ printf_mysql_query("SELECT `channel_protect` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if(!(row = mysql_fetch_row(res))) return 0;
+ if(row[0]) {
+ protection = (char) atoi(row[0]);
+ } else {
+ printf_mysql_query("SELECT `channel_protect` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ protection = (char) atoi(row[0]);
+ }
+ if(protection == 3) return 0;
+
+ /* Don't protect if the victim isn't added to the channel, unless we are to protect non-users also. */
+ int victim_access = getChannelAccess(victim, chan, 0);
+ if (!victim_access && protection != 0) return 0;
+
+ /* Protect if the aggressor isn't a user because at this point, the aggressor can only be less than or equal to the victim. */
+ int issuer_access = getChannelAccess(issuer, chan, 0);
+ if (!issuer_access) return 1;
+
+ /* If the aggressor was a user, then the victim can't be helped. */
+ if(!victim_access) return 0;
+
+ switch(protection) {
+ case 0:
+ case 1:
+ if(victim_access >= issuer_access) return 1;
+ break;
+ case 2:
+ if(victim_access > issuer_access) return 1;
+ break;
+ }
+ return 0;
+}
+
+char *getBanAffectingMask(struct ChanNode *chan, char *mask) {
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `ban_mask` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
+ res = mysql_use();
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(!match(row[0], mask))
+ return row[0];
+ }
+ return NULL;
+}
--- /dev/null
+#ifndef _DBHelper_h
+#define _DBHelper_h
+
+#include "main.h"
+struct UserNode;
+struct ChanNode;
+
+#define DB_CHANUSER_SUSPENDED 0x01
+#define DB_CHANUSER_AUTOINVITE 0x02
+#define DB_CHANUSER_NOAUTOOP 0x04
+
+void _loadUserSettings(struct UserNode* user);
+#define loadUserSettings(USER) if((USER->flags & USERFLAG_ISAUTHED) && !(USER->flags & USERFLAG_LOADED_SETTINGS)) _loadUserSettings(USER)
+int isGodMode(struct UserNode *user);
+char *getChanDefault(char *channel_setting);
+int getChannelAccess(struct UserNode *user, struct ChanNode *chan, int override);
+int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_override, int allow_501);
+void _loadChannelSettings(struct ChanNode *chan);
+#define loadChannelSettings(CHAN) if(!(CHAN->flags & CHANFLAG_REQUESTED_CHANINFO)) _loadChannelSettings(CHAN)
+int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer);
+
+char *getBanAffectingMask(struct ChanNode *chan, char *mask); //returns bans that match a given mask eg. *!*@ab* if you pass *!*@abcdefg.*
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "EventLogger.h"
+#include "modcmd.h"
+#include "mysqlConn.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "DBHelper.h"
+
+static struct Event *first_event = NULL, *last_event = NULL;
+
+struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags) {
+ struct Event *event = malloc(sizeof(*event));
+ if (!event)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ event->client = client;
+ event->user = user;
+ event->chan = chan;
+ event->event_time = time(0);
+ event->command = strdup(command);
+ char arguments[MAXLEN];
+ int argpos = 0;
+ int i;
+ for(i = 0; i < argc; i++)
+ argpos += sprintf(arguments + argpos, "%s ", args[i]);
+ arguments[(argpos ? argpos-1 : 0)] = '\0';
+ event->arguments = strdup(arguments);
+ event->flags = flags;
+ event->next = NULL;
+ if(last_event) {
+ last_event->next = event;
+ last_event = event;
+ } else {
+ last_event = event;
+ first_event = event;
+ }
+ return event;
+}
+
+void logEvent(struct Event *event) {
+ char fullcmd[MAXLEN];
+ sprintf(fullcmd, "%s %s", event->command, event->arguments);
+ if((event->flags & CMDFLAG_LOG) && event->chan) {
+ char *auth = ((event->user->flags & USERFLAG_ISAUTHED) ? event->user->auth : "*");
+ loadChannelSettings(event->chan);
+ if((event->chan->flags & CHANFLAG_CHAN_REGISTERED))
+ printf_mysql_query("INSERT INTO `events` (`cid`, `nick`, `auth`, `time`, `command`) VALUES ('%d', '%s', '%s', UNIX_TIMESTAMP(), '%s')", event->chan->channel_id, escape_string(event->user->nick), auth, escape_string(fullcmd));
+ }
+ if((event->flags & CMDFLAG_OPLOG)) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid;
+ char *auth = ((event->user->flags & USERFLAG_ISAUTHED) ? event->user->auth : "*");
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL)
+ userid = 0;
+ else
+ userid = atoi(row[0]);
+ loadChannelSettings(event->chan);
+ if((event->chan->flags & CHANFLAG_CHAN_REGISTERED))
+ printf_mysql_query("INSERT INTO `godlog` (`godlog_cid`, `godlog_uid`, `godlog_time`, `godlog_cmd`) VALUES ('%d', '%d', UNIX_TIMESTAMP(), '%s')", event->chan->channel_id, userid, escape_string(fullcmd));
+ }
+}
+
+static void destroyEvent(struct Event *event) {
+ if(event == first_event)
+ first_event = event->next;
+ if(event == last_event) {
+ struct Event *last;
+ for(last = first_event; last; last = last->next)
+ if(last->next == NULL) break;
+ last_event = last;
+ }
+ free(event->command);
+ free(event->arguments);
+ free(event);
+}
+
+void destroyEvents() {
+ time_t now = time(0);
+ while(first_event && now - first_event->event_time >= 60) {
+ destroyEvent(first_event);
+ }
+}
--- /dev/null
+#ifndef _EventLogger_h
+#define _EventLogger_h
+
+#include "main.h"
+struct ClientSocket;
+struct UserNode;
+struct ChanNode;
+
+struct Event {
+ struct ClientSocket *client;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ time_t event_time;
+ char *command;
+ char *arguments;
+ unsigned int flags; /* defined in modcmd.h */
+
+ struct Event *next;
+};
+
+struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags);
+void logEvent(struct Event *event);
+void destroyEvents();
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "HandleInfoHandler.h"
+#include "ClientSocket.h"
+#include "UserNode.h"
+#include "IRCEvents.h"
+#include "tools.h"
+
+#define AUTHSERV_NICK "AuthServ"
+
+struct HandleInfoQueueEntry {
+ struct ClientSocket *client;
+ void *callback;
+ void *data;
+
+ struct HandleInfoQueueEntry *next;
+};
+
+static struct HandleInfoQueueEntry *first_entry = NULL, *last_entry = NULL;
+
+static struct HandleInfoQueueEntry* addHandleInfoQueueEntry(struct ClientSocket *client) {
+ struct HandleInfoQueueEntry *entry = malloc(sizeof(*entry));
+ if (!entry)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ entry->next = NULL;
+ entry->client = client;
+ if(last_entry)
+ last_entry->next = entry;
+ else
+ last_entry = entry;
+ if(!first_entry)
+ first_entry = entry;
+ return entry;
+}
+
+static struct HandleInfoQueueEntry* getNextHandleInfoQueueEntry(struct ClientSocket *client, int freeEntry) {
+ if(!first_entry) return NULL;
+ struct HandleInfoQueueEntry *entry;
+ for(entry = first_entry; entry; entry = entry->next) {
+ if(entry->client == client)
+ break;
+ }
+ if(entry == NULL) return NULL;
+ if(freeEntry) {
+ if(entry == first_entry)
+ first_entry = entry->next;
+ if(entry == last_entry) {
+ struct HandleInfoQueueEntry *last;
+ for(last = first_entry; last; last = last->next)
+ if(last->next == NULL) break;
+ last_entry = last;
+ }
+ }
+ return entry;
+}
+
+void lookup_authname(char *auth, authlookup_callback_t callback, void *data) {
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->flags & SOCKET_FLAG_PREFERRED)
+ break;
+ }
+ if(bot == NULL) return;
+ struct HandleInfoQueueEntry* entry = addHandleInfoQueueEntry(bot);
+ entry->callback = callback;
+ entry->data = data;
+ putsock(bot, "PRIVMSG " AUTHSERV_NICK " :ACCOUNTINFO *%s", auth);
+}
+
+static void recv_notice(struct UserNode *user, struct UserNode *target, char *message) {
+ if(stricmp(user->nick, AUTHSERV_NICK)) return;
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->user == target) break;
+ }
+ if(!bot) return;
+ char *auth = NULL;
+ int do_match = 0, exists = 0;
+ char *tmp;
+ //messages to parse:
+ // Account * has not been registered.
+ // Account information for Skynet:
+ if(!match("Account * has not been registered.", message)) {
+ do_match = 1;
+ tmp = strstr(message, "\002");
+ auth = tmp+1;
+ tmp = strstr(auth, "\002");
+ *tmp = '\0';
+ }
+ if(!match("Account information for *", message)) {
+ do_match = 1;
+ exists = 1;
+ tmp = strstr(message, "\002");
+ auth = tmp+1;
+ tmp = strstr(auth, "\002");
+ *tmp = '\0';
+ }
+ if(do_match) {
+ struct HandleInfoQueueEntry* entry = getNextHandleInfoQueueEntry(bot, 1);
+ authlookup_callback_t *callback = entry->callback;
+ callback(auth, exists, entry->data);
+ free(entry);
+ }
+}
+
+void init_handleinfohandler() {
+ bind_privnotice(recv_notice);
+}
+
+void free_handleinfohandler() {
+ struct HandleInfoQueueEntry *entry, *next;
+ for(entry = first_entry; entry; entry = next) {
+ next = entry->next;
+ free(entry);
+ }
+ first_entry = NULL;
+ last_entry = NULL;
+}
--- /dev/null
+#ifndef _HandleInfoHandler_h
+#define _HandleInfoHandler_h
+
+#include "main.h"
+
+struct ClientSocket;
+struct UserNode;
+
+#define AUTHLOOKUP_CALLBACK(NAME) void NAME(UNUSED_ARG(char *auth), UNUSED_ARG(int exists), UNUSED_ARG(void *data))
+typedef AUTHLOOKUP_CALLBACK(authlookup_callback_t);
+
+void lookup_authname(char *auth, authlookup_callback_t callback, void *data);
+void init_handleinfohandler();
+void free_handleinfohandler();
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "IRCEvents.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "ClientSocket.h"
+#include "mysqlConn.h"
+
+struct binding {
+ void *func;
+ struct binding *next;
+};
+
+static void **binds;
+#define BIND_TYPE_JOIN 0
+#define BIND_TYPE_NICK 1
+#define BIND_TYPE_PART 2
+#define BIND_TYPE_QUIT 3
+#define BIND_TYPE_KICK 4
+#define BIND_TYPE_TOPIC 5
+#define BIND_TYPE_MODE 6
+#define BIND_TYPE_CHANMSG 7
+#define BIND_TYPE_PRIVMSG 8
+#define BIND_TYPE_CHANNOTICE 9
+#define BIND_TYPE_PRIVNOTICE 10
+#define BIND_TYPE_CHANCTCP 11
+#define BIND_TYPE_PRIVCTCP 12
+#define BIND_TYPE_INVITE 13
+#define BIND_TYPE_RAW 14
+#define BIND_TYPE_BOT_READY 15
+
+#define TOTAL_BIND_TYPES 16
+
+void init_bind() {
+ binds = calloc(TOTAL_BIND_TYPES, sizeof(*binds));
+}
+
+void free_bind() {
+ struct binding *cbind, *next;
+ int i;
+ for(i = 0; i < TOTAL_BIND_TYPES; i++) {
+ for(cbind = binds[i]; cbind; cbind = next) {
+ next = cbind->next;
+ free(cbind);
+ }
+ }
+ free(binds);
+}
+
+static int is_bound(unsigned char type, void *func) {
+ struct binding *cbind;
+ for(cbind = binds[type]; cbind; cbind = cbind->next) {
+ if(cbind->func == func)
+ return 1;
+ }
+ return 0;
+}
+
+#define FUNC_BIND(NAME,FUNCTYPE,TYPE) \
+int bind_##NAME(FUNCTYPE *func) { \
+ if(!is_bound(TYPE, func)) { \
+ struct binding *cbind = malloc(sizeof(*cbind)); \
+ if (!cbind) { \
+ perror("malloc() failed"); \
+ return 0; \
+ } \
+ cbind->func = func; \
+ cbind->next = binds[TYPE]; \
+ binds[TYPE] = cbind; \
+ return 1; \
+ } \
+ return 0; \
+}
+
+#define FUNC_UNBIND(NAME,FUNCTYPE,TYPE) \
+void unbind_##NAME(FUNCTYPE *func) { \
+ struct binding *cbind, *last = NULL, *next; \
+ for(cbind = binds[TYPE]; cbind; cbind = next) { \
+ next = cbind->next; \
+ if(cbind->func == func) { \
+ if(last) \
+ last->next = cbind->next; \
+ else \
+ binds[TYPE] = cbind->next; \
+ free(cbind); \
+ } else \
+ last = cbind; \
+ } \
+}
+
+#define FUNC_EVENT(NAME,FUNCTYPE,TYPE,PDECLARATION,PLIST) \
+int event_##NAME PDECLARATION { \
+ struct binding *cbind; \
+ pre_event(TYPE); \
+ for(cbind = binds[TYPE]; cbind; cbind = cbind->next) { \
+ FUNCTYPE *func = cbind->func; \
+ func PLIST; \
+ } \
+ post_event(TYPE); \
+ return 1; \
+}
+
+void pre_event(UNUSED_ARG(int type)) {
+
+}
+
+void post_event(UNUSED_ARG(int type)) {
+ mysql_free();
+}
+
+//EVENTS
+
+FUNC_BIND(join, join_func_t, BIND_TYPE_JOIN)
+FUNC_UNBIND(join, join_func_t, BIND_TYPE_JOIN)
+FUNC_EVENT(join, join_func_t, BIND_TYPE_JOIN, (struct ChanUser *chanuser), (chanuser))
+
+FUNC_BIND(nick, nick_func_t, BIND_TYPE_NICK)
+FUNC_UNBIND(nick, nick_func_t, BIND_TYPE_NICK)
+FUNC_EVENT(nick, nick_func_t, BIND_TYPE_NICK, (struct UserNode *user, char *new_nick), (user, new_nick))
+
+FUNC_BIND(part, part_func_t, BIND_TYPE_PART)
+FUNC_UNBIND(part, part_func_t, BIND_TYPE_PART)
+FUNC_EVENT(part, part_func_t, BIND_TYPE_PART, (struct ChanUser *chanuser, char *reason), (chanuser, reason))
+
+FUNC_BIND(quit, quit_func_t, BIND_TYPE_QUIT)
+FUNC_UNBIND(quit, quit_func_t, BIND_TYPE_QUIT)
+FUNC_EVENT(quit, quit_func_t, BIND_TYPE_QUIT, (struct UserNode *user, char *reason), (user, reason))
+
+FUNC_BIND(kick, kick_func_t, BIND_TYPE_KICK)
+FUNC_UNBIND(kick, kick_func_t, BIND_TYPE_KICK)
+FUNC_EVENT(kick, kick_func_t, BIND_TYPE_KICK, (struct UserNode *user, struct ChanUser *target, char *reason), (user, target, reason))
+
+FUNC_BIND(topic, topic_func_t, BIND_TYPE_TOPIC)
+FUNC_UNBIND(topic, topic_func_t, BIND_TYPE_TOPIC)
+FUNC_EVENT(topic, topic_func_t, BIND_TYPE_TOPIC, (struct UserNode *user, struct ChanNode *chan, const char *new_topic), (user, chan, new_topic))
+
+FUNC_BIND(mode, mode_func_t, BIND_TYPE_MODE)
+FUNC_UNBIND(mode, mode_func_t, BIND_TYPE_MODE)
+FUNC_EVENT(mode, mode_func_t, BIND_TYPE_MODE, (struct UserNode *user, struct ChanNode *chan, char *modes, char **args, int argc), (user, chan, modes, args, argc))
+
+FUNC_BIND(chanmsg, chanmsg_func_t, BIND_TYPE_CHANMSG)
+FUNC_UNBIND(chanmsg, chanmsg_func_t, BIND_TYPE_CHANMSG)
+FUNC_EVENT(chanmsg, chanmsg_func_t, BIND_TYPE_CHANMSG, (struct UserNode *user, struct ChanNode *chan, char *message), (user, chan, message))
+
+FUNC_BIND(privmsg, privmsg_func_t, BIND_TYPE_PRIVMSG)
+FUNC_UNBIND(privmsg, privmsg_func_t, BIND_TYPE_PRIVMSG)
+FUNC_EVENT(privmsg, privmsg_func_t, BIND_TYPE_PRIVMSG, (struct UserNode *user, struct UserNode *target, char *message), (user, target, message))
+
+FUNC_BIND(channotice, channotice_func_t, BIND_TYPE_CHANNOTICE)
+FUNC_UNBIND(channotice, channotice_func_t, BIND_TYPE_CHANNOTICE)
+FUNC_EVENT(channotice, channotice_func_t, BIND_TYPE_CHANNOTICE, (struct UserNode *user, struct ChanNode *chan, char *message), (user, chan, message))
+
+FUNC_BIND(privnotice, privnotice_func_t, BIND_TYPE_PRIVNOTICE)
+FUNC_UNBIND(privnotice, privnotice_func_t, BIND_TYPE_PRIVNOTICE)
+FUNC_EVENT(privnotice, privnotice_func_t, BIND_TYPE_PRIVNOTICE, (struct UserNode *user, struct UserNode *target, char *message), (user, target, message))
+
+FUNC_BIND(chanctcp, chanctcp_func_t, BIND_TYPE_CHANCTCP)
+FUNC_UNBIND(chanctcp, chanctcp_func_t, BIND_TYPE_CHANCTCP)
+FUNC_EVENT(chanctcp, chanctcp_func_t, BIND_TYPE_CHANCTCP, (struct UserNode *user, struct ChanNode *chan, char *command, char *text), (user, chan, command, text))
+
+FUNC_BIND(privctcp, privctcp_func_t, BIND_TYPE_PRIVCTCP)
+FUNC_UNBIND(privctcp, privctcp_func_t, BIND_TYPE_PRIVCTCP)
+FUNC_EVENT(privctcp, privctcp_func_t, BIND_TYPE_PRIVCTCP, (struct UserNode *user, struct UserNode *target, char *command, char *text), (user, target, command, text))
+
+FUNC_BIND(invite, invite_func_t, BIND_TYPE_INVITE)
+FUNC_UNBIND(invite, invite_func_t, BIND_TYPE_INVITE)
+FUNC_EVENT(invite, invite_func_t, BIND_TYPE_INVITE, (struct ClientSocket *client, struct UserNode *user, char *channel), (client, user, channel))
+
+FUNC_BIND(raw, raw_func_t, BIND_TYPE_RAW)
+FUNC_UNBIND(raw, raw_func_t, BIND_TYPE_RAW)
+FUNC_EVENT(raw, raw_func_t, BIND_TYPE_RAW, (struct ClientSocket *client, char *from, char *cmd, char **argv, int argc), (client, from, cmd, argv, argc))
+
+FUNC_BIND(bot_ready, bot_ready_func_t, BIND_TYPE_BOT_READY)
+FUNC_UNBIND(bot_ready, bot_ready_func_t, BIND_TYPE_BOT_READY)
+FUNC_EVENT(bot_ready, bot_ready_func_t, BIND_TYPE_BOT_READY, (struct ClientSocket *client), (client))
--- /dev/null
+#ifndef _IRCEvents_h
+#define _IRCEvents_h
+
+#include "main.h"
+
+struct UserNode;
+struct ChanNode;
+struct ChanUser;
+struct ClientSocket;
+
+void init_bind();
+void free_bind();
+
+typedef void join_func_t(struct ChanUser *chanuser);
+int bind_join(join_func_t *func);
+void unbind_join(join_func_t *func);
+int event_join(struct ChanUser *chanuser);
+
+typedef void nick_func_t(struct UserNode *user, char *new_nick);
+int bind_nick(nick_func_t *func);
+void unbind_nick(nick_func_t *func);
+int event_nick(struct UserNode *user, char *new_nick);
+
+typedef void part_func_t(struct ChanUser *chanuser, char *reason);
+int bind_part(part_func_t *func);
+void unbind_part(part_func_t *func);
+int event_part(struct ChanUser *chanuser, char *reason);
+
+typedef void quit_func_t(struct UserNode *user, char *reason);
+int bind_quit(quit_func_t *func);
+void unbind_quit(quit_func_t *func);
+int event_quit(struct UserNode *user, char *reason);
+
+typedef void kick_func_t(struct UserNode *user, struct ChanUser *target, char *reason);
+int bind_kick(kick_func_t *func);
+void unbind_kick(kick_func_t *func);
+int event_kick(struct UserNode *user, struct ChanUser *target, char *reason);
+
+typedef void topic_func_t(struct UserNode *user, struct ChanNode *chan, const char *new_topic);
+int bind_topic(topic_func_t *func);
+void unbind_topic(topic_func_t *func);
+int event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic);
+
+typedef void mode_func_t(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc);
+int bind_mode(mode_func_t *func);
+void unbind_mode(mode_func_t *func);
+int event_mode(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc);
+
+typedef void chanmsg_func_t(struct UserNode *user, struct ChanNode *chan, char *message);
+int bind_chanmsg(chanmsg_func_t *func);
+void unbind_chanmsg(chanmsg_func_t *func);
+int event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message);
+
+typedef void privmsg_func_t(struct UserNode *user, struct UserNode *target, char *message);
+int bind_privmsg(privmsg_func_t *func);
+void unbind_privmsg(privmsg_func_t *func);
+int event_privmsg(struct UserNode *user, struct UserNode *target, char *message);
+
+typedef void channotice_func_t(struct UserNode *user, struct ChanNode *chan, char *message);
+int bind_channotice(channotice_func_t *func);
+void unbind_channotice(channotice_func_t *func);
+int event_channotice(struct UserNode *user, struct ChanNode *chan, char *message);
+
+typedef void privnotice_func_t(struct UserNode *user, struct UserNode *target, char *message);
+int bind_privnotice(privnotice_func_t *func);
+void unbind_privnotice(privnotice_func_t *func);
+int event_privnotice(struct UserNode *user, struct UserNode *target, char *message);
+
+typedef void chanctcp_func_t(struct UserNode *user, struct ChanNode *chan, char *command, char *text);
+int bind_chanctcp(chanctcp_func_t *func);
+void unbind_chanctcp(chanctcp_func_t *func);
+int event_chanctcp(struct UserNode *user, struct ChanNode *chan, char *command, char *text);
+
+typedef void privctcp_func_t(struct UserNode *user, struct UserNode *target, char *command, char *text);
+int bind_privctcp(privctcp_func_t *func);
+void unbind_privctcp(privctcp_func_t *func);
+int event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text);
+
+typedef void invite_func_t(struct ClientSocket *client, struct UserNode *user, char *channel);
+int bind_invite(invite_func_t *func);
+void unbind_invite(invite_func_t *func);
+int event_invite(struct ClientSocket *client, struct UserNode *user, char *channel);
+
+typedef void raw_func_t(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
+int bind_raw(raw_func_t *func);
+void unbind_raw(raw_func_t *func);
+int event_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
+
+typedef void bot_ready_func_t(struct ClientSocket *client);
+int bind_bot_ready(bot_ready_func_t *func);
+void unbind_bot_ready(bot_ready_func_t *func);
+int event_bot_ready(struct ClientSocket *client);
+
+
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "IRCParser.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "IRCEvents.h"
+#include "ClientSocket.h"
+#include "WHOHandler.h"
+#include "lang.h"
+#include "DBHelper.h"
+#include "BanNode.h"
+#include "ModeNode.h"
+
+struct irc_cmd *irc_commands = NULL;
+
+static void parse_line(struct ClientSocket *client, char *line);
+static void register_irc_function(char *command, irc_cmd_t *func);
+static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc);
+
+int parse_lines(struct ClientSocket *client, char *lines, int len) {
+ int i, used = 0;
+ char *line = lines;
+ for(i = 0; i < len; i++) {
+ if(lines[i] == '\r') //just zero it out :D
+ lines[i] = 0;
+ if(lines[i] == '\n') {
+ lines[i] = 0;
+ parse_line(client, line);
+ line = lines+(i+1);
+ used = i+1;
+ }
+ }
+ return used;
+}
+
+static void parse_line(struct ClientSocket *client, char *line) {
+ int argc = 0;
+ char *argv[MAXNUMPARAMS];
+ printf("[recv %lu] %s\n", (unsigned long) strlen(line), line);
+ if(line[0] == ':')
+ line++;
+ else
+ argv[argc++] = NULL;
+ while(*line) {
+ //skip leading spaces
+ while (*line == ' ')
+ *line++ = 0;
+ if (*line == ':') {
+ //the rest is a single parameter
+ argv[argc++] = line + 1;
+ break;
+ }
+ argv[argc++] = line;
+ if (argc >= MAXNUMPARAMS)
+ break;
+ while (*line != ' ' && *line)
+ line++;
+ }
+ if(argc >= 2) {
+ parse_raw(client, argv[0], argv[1], argv+2, argc-2);
+ }
+}
+
+static void register_irc_function(char *command, irc_cmd_t *func) {
+ struct irc_cmd *irc_cmd = malloc(sizeof(*irc_cmd));
+ if (!irc_cmd)
+ {
+ perror("malloc() failed");
+ return;
+ }
+ irc_cmd->cmd = command;
+ irc_cmd->func = func;
+ irc_cmd->next = irc_commands;
+ irc_commands = irc_cmd;
+}
+
+static void parse_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc) {
+ struct irc_cmd *irc_cmd;
+ int ret = 0;
+ for(irc_cmd = irc_commands; irc_cmd; irc_cmd = irc_cmd->next) {
+ if(!stricmp(irc_cmd->cmd, cmd)) {
+ ret = irc_cmd->func(client, from, argv, argc);
+ break;
+ }
+ }
+ if(!irc_cmd) {
+ event_raw(client, from, cmd, argv, argc);
+ } else if(!ret) {
+ fprintf(stderr,"PARSE ERROR: %s\n", cmd);
+ }
+}
+
+static USERLIST_CALLBACK(got_channel_userlist) {
+ struct ChanUser *chanuser = data;
+ event_join(chanuser);
+}
+
+static IRC_CMD(raw_001) {
+ client->flags |= SOCKET_FLAG_READY;
+ event_bot_ready(client);
+ return 1;
+}
+
+static IRC_CMD(raw_join) {
+ if(from == NULL || argc < 1) return 0;
+ struct UserNode *user = getUserByMask(from);
+ struct ChanNode *chan = getChanByName(argv[0]);
+ if(!chan && !(user->flags & USERFLAG_ISBOT)) return 0;
+ if(user == NULL) {
+ user = addUserMask(from);
+ }
+ if(chan == NULL) {
+ chan = addChannel(argv[0]);
+ //request member list
+ chan->chanbot = user;
+ struct ChanUser *chanuser = addChanUser(chan, user); //it must be a bot
+ get_userlist(chan, got_channel_userlist, chanuser);
+ putsock(client, "MODE %s", chan->name);
+ putsock(client, "MODE %s +b", chan->name);
+ } else if(!isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
+ struct ChanUser *chanuser = addChanUser(chan, user);
+ event_join(chanuser);
+ }
+ return 1;
+}
+
+static IRC_CMD(raw_part) {
+ if(from == NULL || argc < 1) return 0;
+ struct UserNode *user = getUserByMask(from);
+ if(user == NULL) return 0;
+ struct ChanNode *chan = getChanByName(argv[0]);
+ if(chan == NULL) return 0;
+ if(isUserOnChan(user, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
+ struct ChanUser *chanuser = getChanUser(user, chan);
+ delChanUser(chanuser, 0); //we need to free the chanuser manually!
+ event_part(chanuser, (argc > 1 ? argv[1] : NULL));
+ free(chanuser);
+ if(chan->chanbot == user) {
+ //check if theres another bot in the channel - otherwise free it
+ checkChannelVisibility(chan);
+ }
+ }
+ if(user->channel == NULL && !(user->flags & USERFLAG_ISBOT)) {
+ //remove the user
+ delUser(user, 1);
+ }
+ return 1;
+}
+
+static IRC_CMD(raw_quit) {
+ if(from == NULL || argc < 1) return 0;
+ struct UserNode *user = getUserByMask(from);
+ if(user == NULL) return 0;
+ delUser(user, 0); //a little bit crazy, but we want to delete the user on the channel's userlists - but not the users channel list
+ event_quit(user, argv[0]);
+ if(user->flags & USERFLAG_ISBOT) {
+ //check if there are other bots in the users channel - otherwise free them
+ struct ChanUser *chanuser, *next;
+ for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
+ next = getUserChannels(user, chanuser);
+ checkChannelVisibility(chanuser->chan);
+ }
+ }
+ delUser(user, 1); //now we fully free the user
+ return 1;
+}
+
+void bot_disconnect(struct ClientSocket *client) {
+ struct UserNode *user = client->user;
+ struct ChanUser *chanuser, *next;
+ delUser(user, 0);
+ event_quit(user, "disconnected");
+ for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = next) {
+ next = getUserChannels(user, chanuser);
+ checkChannelVisibility(chanuser->chan);
+ free(chanuser);
+ }
+ user->channel = NULL;
+}
+
+static IRC_CMD(raw_kick) {
+ if(from == NULL || argc < 3) return 0;
+ struct UserNode *user = getUserByMask(from);
+ struct UserNode *target = getUserByNick(argv[1]);
+ struct ChanNode *chan = getChanByName(argv[0]);
+ if(chan == NULL || target == NULL) return 0;
+ if(isUserOnChan(target, chan) && (chan->flags & CHANFLAG_RECEIVED_USERLIST)) {
+ if(user == NULL) {
+ user = createTempUser(from);
+ user->flags |= USERFLAG_ISTMPUSER;
+ }
+ struct ChanUser *chanuser = getChanUser(target, chan);
+ delChanUser(chanuser, 0); //we need to free the chanuser manually!
+ event_kick(user, chanuser, argv[1]);
+ free(chanuser);
+ if(target->flags & USERFLAG_ISBOT) {
+ //check if theres another bot in the channel - otherwise free it
+ checkChannelVisibility(chan);
+ }
+ }
+ if(target->channel == NULL && !(target->flags & USERFLAG_ISBOT)) {
+ //remove the user
+ delUser(target, 1);
+ }
+ return 1;
+}
+
+static IRC_CMD(raw_topic) {
+ if(from == NULL || argc < 2) return 0;
+ struct UserNode *user = getUserByMask(from);
+ struct ChanNode *chan = getChanByName(argv[0]);
+ if(chan == NULL) return 0;
+ if(chan->chanbot != client->user) return 1; //just ignore it to prevent event duplicates
+ if(user == NULL) {
+ user = createTempUser(from);
+ user->flags |= USERFLAG_ISTMPUSER;
+ }
+ event_topic(user, chan, argv[1]);
+ strcpy(chan->topic, argv[1]);
+ return 1;
+}
+
+static IRC_CMD(raw_privmsg) {
+ if(from == NULL || argc < 2) return 0;
+ struct UserNode *user = getUserByMask(from);
+ if(user == NULL) {
+ user = createTempUser(from);
+ user->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(argv[0][0] == '#') { //Channel message
+ struct ChanNode *chan = getChanByName(argv[0]);
+ if(chan && chan->chanbot == client->user) {
+ if(argv[1][0] == '\001') {
+ char *cmd = &argv[1][1];
+ char *text = strstr(cmd, " ");
+ if(text) {
+ *text = '\0';
+ text++;
+ if(strlen(text) && text[strlen(text)-1] == '\001')
+ text[strlen(text)-1] = '\0';
+ } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
+ cmd[strlen(cmd)-1] = '\0';
+ event_chanctcp(user, chan, cmd, text);
+ } else
+ event_chanmsg(user, chan, argv[1]);
+ }
+ } else {
+ struct UserNode *target = getUserByNick(argv[0]);
+ if(target) {
+ if(argv[1][0] == '\001') {
+ char *cmd = &argv[1][1];
+ char *text = strstr(cmd, " ");
+ if(text) {
+ *text = '\0';
+ text++;
+ if(strlen(text) && text[strlen(text)-1] == '\001')
+ text[strlen(text)-1] = '\0';
+ } else if(strlen(cmd) && cmd[strlen(cmd)-1] == '\001')
+ cmd[strlen(cmd)-1] = '\0';
+ event_privctcp(user, target, cmd, text);
+ } else
+ event_privmsg(user, target, argv[1]);
+ }
+ }
+ return 1;
+}
+
+static IRC_CMD(raw_notice) {
+ if(from == NULL || argc < 2) return 0;
+ struct UserNode *user = getUserByMask(from);
+ if(user == NULL) {
+ user = createTempUser(from);
+ user->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(argv[0][0] == '#') { //Channel notice
+ struct ChanNode *chan = getChanByName(argv[0]);
+ if(chan && chan->chanbot == client->user)
+ event_channotice(user, chan, argv[1]);
+ } else {
+ struct UserNode *target = getUserByNick(argv[0]);
+ if(target)
+ event_privnotice(user, target, argv[1]);
+ }
+ return 1;
+}
+
+static IRC_CMD(raw_nick) {
+ if(from == NULL || argc == 0) return 0;
+ struct UserNode *user = getUserByMask(from);
+ if(user == NULL) return 0;
+ event_nick(user, argv[0]);
+ renameUser(user, argv[0]);
+ return 1;
+}
+
+static IRC_CMD(raw_ping) {
+ if(argc == 0) return 0;
+ putsock(client, "PONG :%s", argv[0]);
+ return 1;
+}
+
+static IRC_CMD(raw_354) {
+ recv_whohandler_354(client, argv, argc);
+ return 1;
+}
+
+static IRC_CMD(raw_315) {
+ recv_whohandler_315(client, argv, argc);
+ return 1;
+}
+
+static IRC_CMD(raw_324) { //MODE LIST
+ //Watchcat #pktest +stnzN
+ if(from == NULL || argc < 3) return 0;
+ struct ChanNode *chan = getChanByName(argv[1]);
+ if(chan == NULL) return 0;
+ parseModes(chan->modes, argv[2], argv+3, argc-3);
+ return 1;
+}
+
+static IRC_CMD(raw_invite) {
+ if(from == NULL || argc < 2) return 0;
+ struct UserNode *user = getUserByMask(from);
+ if(user == NULL) {
+ user = createTempUser(from);
+ user->flags |= USERFLAG_ISTMPUSER;
+ }
+ event_invite(client, user, argv[1]);
+ return 1;
+}
+
+static IRC_CMD(raw_mode) {
+ if(from == NULL || argc < 2) return 0;
+ struct UserNode *user = getUserByMask(from);
+ if(user == NULL) {
+ user = createTempUser(from);
+ user->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(argv[0][0] == '#') {
+ //ChannelMode
+ struct ChanNode *chan = getChanByName(argv[0]);
+ if(!chan) return 0;
+ if(chan->chanbot != client->user) return 1;
+ event_mode(user, chan, argv[1], argv+2, argc-2);
+ parseModes(chan->modes, argv[1], argv+2, argc-2);
+ } else {
+ //UserMode
+ }
+ return 1;
+}
+
+static IRC_CMD(raw_367) {
+ //Watchcat #pktest pk911!*@* TestBot!~bot@pktest.user.WebGamesNet 1315863279
+ struct ChanNode *chan = getChanByName(argv[1]);
+ if(!chan) return 0;
+ struct BanNode *ban;
+ while((ban = getMatchingChannelBan(chan, argv[2]))) {
+ removeChannelBan(ban);
+ }
+ addChannelBan(chan, argv[2]);
+ return 1;
+}
+
+void init_parser() {
+ //all the raws we receive...
+ register_irc_function("001", raw_001);
+ register_irc_function("324", raw_324);
+ register_irc_function("367", raw_367);
+ register_irc_function("INVITE", raw_invite);
+ register_irc_function("NOTICE", raw_notice);
+ register_irc_function("TOPIC", raw_topic);
+ register_irc_function("KICK", raw_kick);
+ register_irc_function("PART", raw_part);
+ register_irc_function("QUIT", raw_quit);
+ register_irc_function("JOIN", raw_join);
+ register_irc_function("MODE", raw_mode);
+ register_irc_function("NICK", raw_nick);
+ register_irc_function("354", raw_354);
+ register_irc_function("315", raw_315);
+ register_irc_function("PING", raw_ping);
+ register_irc_function("PRIVMSG", raw_privmsg);
+}
+
+void free_parser() {
+ struct irc_cmd *cmd, *next;
+ for(cmd = irc_commands; cmd; cmd = next) {
+ next = cmd->next;
+ free(cmd);
+ }
+}
+
+void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...) {
+ const char *reply_format = get_language_string(user, text);
+ if(reply_format == NULL)
+ reply_format = text;
+ loadUserSettings(user);
+ char formatBuf[MAXLEN];
+ sprintf(formatBuf, "%s %s :%s", ((user->flags & USERFLAG_REPLY_PRIVMSG) ? "PRIVMSG" : "NOTICE"), user->nick, reply_format);
+ va_list arg_list;
+ char sendBuf[MAXLEN];
+ int pos;
+ if (!(client->flags & SOCKET_FLAG_CONNECTED)) return;
+ sendBuf[0] = '\0';
+ va_start(arg_list, text);
+ pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list);
+ va_end(arg_list);
+ if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
+ sendBuf[pos] = '\n';
+ sendBuf[pos+1] = '\0';
+ write_socket(client, sendBuf, pos+1);
+}
+
+char* merge_argv(char **argv, int start, int end) {
+ return merge_argv_char(argv, start, end, ' ');
+}
+
+char* merge_argv_char(char **argv, int start, int end, char seperator) {
+ int i;
+ char *p = NULL;
+ for(i = start; i < end; i++) {
+ p = argv[i];
+ while(*p) p++;
+ *p = seperator;
+ }
+ if(p) *p = '\0';
+ return argv[start];
+}
--- /dev/null
+#ifndef _IRCParser_h
+#define _IRCParser_h
+
+#include "main.h"
+
+struct ClientSocket;
+struct UserNode;
+
+#define IRC_CMD(NAME) int NAME(struct ClientSocket *client, UNUSED_ARG(const char *from), UNUSED_ARG(char **argv), UNUSED_ARG(unsigned int argc))
+typedef IRC_CMD(irc_cmd_t);
+
+struct irc_cmd {
+ char *cmd;
+ irc_cmd_t *func;
+ struct irc_cmd *next;
+};
+
+int parse_lines(struct ClientSocket *client, char *lines, int len);
+void bot_disconnect(struct ClientSocket *client);
+void init_parser();
+void free_parser();
+void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...);
+char* merge_argv(char **argv, int start, int end);
+char* merge_argv_char(char **argv, int start, int end, char seperator);
+
+#endif
\ No newline at end of file
--- /dev/null
+CC = gcc
+SRC = EventLogger.c \
+ IRCEvents.c \
+ main.c \
+ ChanNode.c \
+ IRCParser.c \
+ ClientSocket.c \
+ UserNode.c \
+ ChanUser.c \
+ ModeNode.c \
+ BanNode.c \
+ WHOHandler.c \
+ modcmd.c \
+ mysqlConn.c \
+ lang.c \
+ HandleInfoHandler.c \
+ tools.c \
+ timeq.c \
+ DBHelper.c \
+ bots.c \
+ bot_NeonServ.c
+CMD = cmd_neonserv_access.c \
+ cmd_neonserv_addban.c \
+ cmd_neonserv_addtimeban.c \
+ cmd_neonserv_adduser.c \
+ cmd_neonserv_ban.c \
+ cmd_neonserv_bans.c \
+ cmd_neonserv_bind.c \
+ cmd_neonserv_chanservsync.c \
+ cmd_neonserv_clvl.c \
+ cmd_neonserv_command.c \
+ cmd_neonserv_csuspend.c \
+ cmd_neonserv_cunsuspend.c \
+ cmd_neonserv_delban.c \
+ cmd_neonserv_delme.c \
+ cmd_neonserv_deluser.c \
+ cmd_neonserv_deop.c \
+ cmd_neonserv_deopall.c \
+ cmd_neonserv_devoice.c \
+ cmd_neonserv_devoiceall.c \
+ cmd_neonserv_down.c \
+ cmd_neonserv_downall.c \
+ cmd_neonserv_emote.c \
+ cmd_neonserv_events.c \
+ cmd_neonserv_giveowner.c \
+ cmd_neonserv_god.c \
+ cmd_neonserv_help.c \
+ cmd_neonserv_invite.c \
+ cmd_neonserv_inviteme.c \
+ cmd_neonserv_kick.c \
+ cmd_neonserv_kickban.c \
+ cmd_neonserv_mdeluser.c \
+ cmd_neonserv_mode.c \
+ cmd_neonserv_move.c \
+ cmd_neonserv_myaccess.c \
+ cmd_neonserv_netinfo.c \
+ cmd_neonserv_notice.c \
+ cmd_neonserv_op.c \
+ cmd_neonserv_opall.c \
+ cmd_neonserv_oplog.c \
+ cmd_neonserv_peek.c \
+ cmd_neonserv_raw.c \
+ cmd_neonserv_recover.c \
+ cmd_neonserv_register.c \
+ cmd_neonserv_reloadlang.c \
+ cmd_neonserv_resync.c \
+ cmd_neonserv_say.c \
+ cmd_neonserv_search.c \
+ cmd_neonserv_set.c \
+ cmd_neonserv_setaccess.c \
+ cmd_neonserv_suspend.c \
+ cmd_neonserv_topic.c \
+ cmd_neonserv_trace.c \
+ cmd_neonserv_trim.c \
+ cmd_neonserv_unban.c \
+ cmd_neonserv_unbanall.c \
+ cmd_neonserv_unbanme.c \
+ cmd_neonserv_unbind.c \
+ cmd_neonserv_unregister.c \
+ cmd_neonserv_unsuspend.c \
+ cmd_neonserv_up.c \
+ cmd_neonserv_upall.c \
+ cmd_neonserv_users.c \
+ cmd_neonserv_uset.c \
+ cmd_neonserv_version.c \
+ cmd_neonserv_voice.c \
+ cmd_neonserv_voiceall.c \
+ cmd_neonserv_wipeinfo.c
+CMD_DEPS = main.h modcmd.h IRCParser.h UserNode.h ChanNode.h ChanUser.h ModeNode.h \
+ ClientSocket.h mysqlConn.h lang.h HandleInfoHandler.h WHOHandler.h DBHelper.h \
+ tools.h timeq.h version.h EventLogger.h bot_NeonServ.h IRCEvents.h BanNode.h
+OBJS = ${SRC:%.c=%.o} ${CMD:%.c=%.o}
+CFLAGS=-g -O2 -Wall -Wshadow -Werror
+LIBS=-I. -I/usr/include/mysql
+LINK=-lmysqlclient
+
+all: $(OBJS)
+
+install: $(OBJS)
+ chmod +x version.sh
+ ./version.sh
+ $(CC) $(LIBS) -c version.c $(CFLAGS)
+ $(CC) $(LIBS) -o neonserv $(OBJS) version.o $(CFLAGS) $(LINK)
+
+%.o: %.c
+ $(CC) $(LIBS) -c $< $(CFLAGS)
+
+clean:
+ rm $(OBJS) version.o
+
+depend: $(SRC)
+ mv Makefile Makefile.bak
+ grep -A1 -B10000 '^# DEPENDINGS' Makefile.bak > Makefile
+ $(CC) $(CFLAGS) -MM $(LIBS) $(SRC) >> Makefile
+ rm Makefile.bak
+
+# DEPENDINGS -- generated by make depend
+
+
--- /dev/null
+#include "ModeNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "UserNode.h"
+#include "BanNode.h"
+
+static int modes_with_strarg, modes_with_intarg, modes_count;
+
+unsigned int valid_modes[] = { /* Thats our mode list :P */
+ 1, 'b', CHANNEL_MODE_TYPE_A,
+ 2, 'o', CHANNEL_MODE_TYPE_A,
+ 3, 'v', CHANNEL_MODE_TYPE_A,
+ 4, 'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING | CHANNEL_MODE_KEY,
+ 5, 'a', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
+ 6, 'l', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
+ 7, 'f', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
+ 8, 'F', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
+ 9, 'c', CHANNEL_MODE_TYPE_D,
+ 10, 'C', CHANNEL_MODE_TYPE_D,
+ 11, 'i', CHANNEL_MODE_TYPE_D,
+ 12, 'm', CHANNEL_MODE_TYPE_D,
+ 13, 'M', CHANNEL_MODE_TYPE_D,
+ 14, 'n', CHANNEL_MODE_TYPE_D,
+ 15, 'N', CHANNEL_MODE_TYPE_D,
+ 16, 'p', CHANNEL_MODE_TYPE_D,
+ 17, 'r', CHANNEL_MODE_TYPE_D,
+ 18, 's', CHANNEL_MODE_TYPE_D,
+ 19, 't', CHANNEL_MODE_TYPE_D,
+ 20, 'u', CHANNEL_MODE_TYPE_D,
+ 21, 'D', CHANNEL_MODE_TYPE_D,
+ 22, 'd', CHANNEL_MODE_TYPE_D,
+ 23, 'R', CHANNEL_MODE_TYPE_D,
+ 24, 'z', CHANNEL_MODE_TYPE_D,
+// ^ maximum is 32!!!
+ 0x00, 0x00, 0x00
+};
+
+void init_ModeNode() {
+ unsigned int *mode, flag = 1;
+ modes_with_strarg = 0;
+ modes_with_intarg = 0;
+ modes_count = 0;
+ for (mode = valid_modes; mode[1]; mode += 3) {
+ if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING) {
+ mode[2] |= modes_with_strarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
+ modes_with_strarg++;
+ }
+ if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
+ mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
+ modes_with_intarg++;
+ }
+ modes_count++;
+ mode[0] = flag;
+ flag = flag << 1;
+ }
+}
+
+struct ModeNode *createModeNode(struct ChanNode *chan) {
+ struct ModeNode *modes = malloc(sizeof(*modes));
+ if (!modes)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ modes->chan = chan;
+ modes->modes = 0;
+ modes->allmodes = 0;
+ modes->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
+ modes->mode_int_args = calloc(modes_with_intarg, sizeof(int));
+ return modes;
+}
+
+void freeModeNode(struct ModeNode *modes) {
+ int i;
+ for(i = 0; i < modes_with_strarg; i++) {
+ if(modes->mode_str_args[i])
+ free(modes->mode_str_args[i]);
+ }
+ free(modes->mode_str_args);
+ free(modes->mode_int_args);
+ free(modes);
+}
+
+static unsigned int* getModeOptions(char mode) {
+ unsigned int *cmode;
+ for (cmode = valid_modes; cmode[1]; cmode += 3) {
+ if(cmode[1] == mode)
+ return cmode;
+ }
+ return NULL;
+}
+
+int isModeSet(struct ModeNode* modes, char modeChar) {
+ unsigned int *modeOpt = getModeOptions(modeChar);
+ return (modes->modes & modeOpt[0]);
+}
+
+int isModeAffected(struct ModeNode* modes, char modeChar) {
+ unsigned int *modeOpt = getModeOptions(modeChar);
+ return (modes->allmodes & modeOpt[0]);
+}
+
+void* getModeValue(struct ModeNode* modes, char modeChar) {
+ #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ unsigned int *modeOpt = getModeOptions(modeChar);
+ if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING)
+ return modes->mode_str_args[MODE_VALUE_INDEX];
+ if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER)
+ return &modes->mode_int_args[MODE_VALUE_INDEX];
+ return NULL;
+ #undef MODE_VALUE_INDEX
+}
+
+unsigned int getModeType(struct ModeNode* modes, char modeChar) {
+ #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ unsigned int *modeOpt = getModeOptions(modeChar);
+ if(!modeOpt) return 0;
+ return modeOpt[2];
+ #undef MODE_VALUE_INDEX
+}
+
+static void parseModesUserPriv(struct ModeNode* modes, unsigned char flag, int add, char *nick) {
+ if(modes->chan == NULL) return;
+ struct UserNode *user = getUserByNick(nick);
+ if(user == NULL) return;
+ struct ChanUser *chanuser = getChanUser(user, modes->chan);
+ if(chanuser == NULL) return;
+ if(add)
+ chanuser->flags |= flag;
+ else
+ chanuser->flags &= ~flag;
+}
+
+static void parseModesBan(struct ModeNode* modes, int add, char *mask) {
+ if(modes->chan == NULL) return;
+ if(add)
+ addChannelBan(modes->chan, mask);
+ else
+ removeChannelBanMask(modes->chan, mask);
+}
+
+void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc) {
+ int i, argpos = 0, add = 1;
+ #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
+ #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
+ #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ unsigned int *modeOpt;
+ for(i = 0; i < strlen(modeStr); i++) {
+ if(modeStr[i] == '+') {
+ add = 1;
+ continue;
+ }
+ if(modeStr[i] == '-') {
+ add = 0;
+ continue;
+ }
+ modeOpt = getModeOptions(modeStr[i]);
+ if(!modeOpt) continue; // unknown mode?
+ if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
+ if(argpos == argc) continue;
+ //special mode ;)
+ switch(modeStr[i]) {
+ case 'o':
+ parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, argv[argpos]);
+ break;
+ case 'v':
+ parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, argv[argpos]);
+ break;
+ case 'b':
+ parseModesBan(modes, add, argv[argpos]);
+ break;
+ default:
+ //we have an unknown TYPE_A mode???
+ break;
+ }
+ argpos++;
+ continue;
+ }
+ if(add) {
+ if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
+ if(argpos == argc) continue;
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
+ if(modes->mode_str_args[MODE_VALUE_INDEX])
+ free(modes->mode_str_args[MODE_VALUE_INDEX]);
+ modes->mode_str_args[MODE_VALUE_INDEX] = strdup(argv[argpos++]);
+ } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ modes->mode_int_args[MODE_VALUE_INDEX] = atoi(argv[argpos++]);
+ else
+ argpos++; //we simply don't know what to do with the argument...
+ }
+ modes->modes |= modeOpt[0];
+ modes->allmodes |= modeOpt[0];
+ } else {
+ modes->modes &= ~modeOpt[0];
+ modes->allmodes |= modeOpt[0];
+ if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
+ if(argpos == argc) continue;
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
+ free(modes->mode_str_args[MODE_VALUE_INDEX]);
+ modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
+ } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ modes->mode_int_args[MODE_VALUE_INDEX] = 0;
+ argpos++; //we don't need the argument when unsetting a mode...
+ }
+ }
+ }
+ #undef MODE_TYPE
+ #undef MODE_VALUE
+ #undef MODE_VALUE_INDEX
+}
+
+void parseModeString(struct ModeNode* modes, char *modeStr) {
+ int argc = 0;
+ char *args[modes_count+1];
+ char *a, *b = modeStr;
+ do {
+ a = strstr(b, " ");
+ if(a) *a = '\0';
+ args[argc++] = b;
+ if(a) b = a+1;
+ } while(a);
+ parseModes(modes, args[0], args+1, argc-1);
+}
+
+int parseMode(struct ModeNode* modes, int add, char mode, char *param) {
+ #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
+ #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
+ #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ unsigned int *modeOpt = getModeOptions(mode);
+ if(!modeOpt) return 0;
+ if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
+ if(!param) return 0;
+ //special mode ;)
+ switch(mode) {
+ case 'o':
+ parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, param);
+ break;
+ case 'v':
+ parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, param);
+ break;
+ case 'b':
+ parseModesBan(modes, add, param);
+ break;
+ default:
+ return 0; //we have an unknown TYPE_A mode???
+ }
+ }
+ if(add) {
+ if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
+ if(!param) return 0;
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
+ if(modes->mode_str_args[MODE_VALUE_INDEX])
+ free(modes->mode_str_args[MODE_VALUE_INDEX]);
+ modes->mode_str_args[MODE_VALUE_INDEX] = strdup(param);
+ } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ modes->mode_int_args[MODE_VALUE_INDEX] = atoi(param);
+ }
+ modes->modes |= modeOpt[0];
+ modes->allmodes |= modeOpt[0];
+ } else {
+ modes->modes &= ~modeOpt[0];
+ modes->allmodes |= modeOpt[0];
+ if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
+ if(!param) return 0;
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
+ free(modes->mode_str_args[MODE_VALUE_INDEX]);
+ modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
+ } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ modes->mode_int_args[MODE_VALUE_INDEX] = 0;
+ }
+ }
+ #undef MODE_TYPE
+ #undef MODE_VALUE
+ #undef MODE_VALUE_INDEX
+ return 1;
+}
+
+void getModeString(struct ModeNode* modes, char *modesStr) {
+ #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
+ #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
+ #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ char paramStr[MAXLEN];
+ modesStr[0] = '+';
+ unsigned int *mode;
+ int modePos = 1;
+ int paramPos = 0;
+ for (mode = valid_modes; mode[1]; mode += 3) {
+ if(modes->modes & mode[0]) {
+ modesStr[modePos++] = (char) mode[1];
+ if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
+ paramPos += sprintf(paramStr + paramPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
+ else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ paramPos += sprintf(paramStr + paramPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
+ }
+ }
+ }
+ paramStr[paramPos] = '\0';
+ strcpy(modesStr + modePos, paramStr);
+ #undef MODE_TYPE
+ #undef MODE_VALUE
+ #undef MODE_VALUE_INDEX
+}
+
+void getFullModeString(struct ModeNode* modes, char *modesStr) {
+ #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
+ #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
+ #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
+ char addMode[modes_count+1];
+ int addModePos = 0;
+ char addParams[MAXLEN];
+ addParams[0] = '\0';
+ int addParamsPos = 0;
+ char delMode[modes_count+1];
+ int delModePos = 0;
+ unsigned int *mode;
+ for (mode = valid_modes; mode[1]; mode += 3) {
+ if(modes->allmodes & mode[0]) {
+ if(modes->modes & mode[0]) {
+ addMode[addModePos++] = (char) mode[1];
+ if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
+ if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
+ addParamsPos += sprintf(addParams + addParamsPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
+ else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
+ addParamsPos += sprintf(addParams + addParamsPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
+ }
+ } else {
+ delMode[delModePos++] = (char) mode[1];
+ }
+ }
+ }
+ addMode[addModePos] = '\0';
+ delMode[delModePos] = '\0';
+ addParams[addParamsPos] = '\0';
+ sprintf(modesStr, "%s%s%s%s%s", (addModePos ? "+" : ""), addMode, (delModePos ? "-" : ""), delMode, addParams);
+ if(*modesStr == '\0') {
+ sprintf(modesStr, "+");
+ }
+ #undef MODE_TYPE
+ #undef MODE_VALUE
+ #undef MODE_VALUE_INDEX
+}
--- /dev/null
+#ifndef _ModeNode_h
+#define _ModeNode_h
+#include "main.h"
+
+struct ChanNode;
+
+//Types: http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
+#define CHANNEL_MODE_TYPE_A 0x01 /* ... special (addresses or users) ... */
+#define CHANNEL_MODE_TYPE_B 0x02 /* These modes always take a parameter. */
+#define CHANNEL_MODE_TYPE_C 0x03 /* These modes take a parameter only when set. */
+#define CHANNEL_MODE_TYPE_D 0x04 /* These modes never take a parameter. */
+#define CHANNEL_MODE_TYPE 0x07 /* bit mask to get the type */
+
+#define CHANNEL_MODE_VALUE_STRING 0x10
+#define CHANNEL_MODE_VALUE_INTEGER 0x20
+#define CHANNEL_MODE_VALUE 0x30 /* bit mask to get the value */
+
+#define CHANNEL_MODE_KEY 0x40 /* mode is a key - automatically add the current key as parameter on unset */
+
+#define CHANNEL_MODE_VALUE_INDEX_SHIFT 8
+#define CHANNEL_MODE_VALUE_INDEX_MASK (0xff << CHANNEL_MODE_VALUE_INDEX_SHIFT) /* this "bitrange" is reserved for storing the array indexes of the mode values */
+
+struct ModeNode {
+ struct ChanNode *chan;
+ unsigned int modes;
+ unsigned int allmodes;
+ char **mode_str_args;
+ int *mode_int_args;
+};
+
+extern unsigned int valid_modes[];
+
+void init_ModeNode();
+struct ModeNode *createModeNode(struct ChanNode *chan);
+void freeModeNode(struct ModeNode *modes);
+int isModeSet(struct ModeNode* modes, char modeChar);
+int isModeAffected(struct ModeNode* modes, char modeChar);
+void* getModeValue(struct ModeNode* modes, char modeChar);
+unsigned int getModeType(struct ModeNode* modes, char modeChar);
+void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc);
+void parseModeString(struct ModeNode* modes, char *modeStr);
+int parseMode(struct ModeNode* modes, int add, char mode, char *param);
+void getModeString(struct ModeNode* modes, char *modesStr);
+void getFullModeString(struct ModeNode* modes, char *modesStr);
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "UserNode.h"
+#include "ChanUser.h"
+#include "tools.h"
+
+static struct UserNode **userList;
+
+void init_UserNode() {
+ userList = calloc(VALID_NICK_CHARS_FIRST_LEN+1, sizeof(*userList));
+}
+
+void free_UserNode() {
+ //kamikaze free all users
+ //chanusers will be destroyed in free_ChanNode()
+ int i;
+ struct UserNode *user, *next;
+ for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
+ for(user = userList[i]; user; user = next) {
+ next = user->next;
+ free(user);
+ }
+ }
+ free(userList);
+}
+
+int is_valid_nick(const char *nick) {
+ unsigned int i;
+ //first char must be one of: a-zA-Z{|}~[\]^_`
+ if (!strchr(VALID_NICK_CHARS_FIRST, *nick))
+ return 0;
+ //all other chars must be one of: a-zA-Z0-9{|}~[\]^_`
+ for (i = 0; nick[i]; ++i)
+ if (!strchr(VALID_NICK_CHARS, nick[i]))
+ return 0;
+ if (strlen(nick) > NICKLEN)
+ return 0;
+ return 1;
+}
+
+static int get_nicklist_entry(int nick) {
+ int i;
+ char *valid_chars = VALID_NICK_CHARS_FIRST;
+ for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN; i++) {
+ if(valid_chars[i] == nick)
+ return i;
+ }
+ return -1; //ERROR!
+}
+
+struct UserNode* getUserByNick(const char *nick) { //case sensitive
+ int userListIndex = get_nicklist_entry(*nick);
+ if(userListIndex == -1 || userList[userListIndex] == NULL)
+ return NULL;
+ struct UserNode *user;
+ for(user = userList[userListIndex]; user; user = user->next) {
+ if(!stricmp(nick, user->nick))
+ return user;
+ }
+ return NULL;
+}
+
+struct UserNode* getUserByMask(const char *mask) { //case sensitive
+ char cmask[strlen(mask)+1];
+ strcpy(cmask, mask);
+ int i;
+ struct UserNode *user = NULL;
+ for(i = 0; i < strlen(mask); i++) {
+ if(cmask[i] == '!') {
+ cmask[i] = 0;
+ user = getUserByNick(&cmask[0]);
+ return user;
+ } else if(cmask[i] == '.') {
+ //it's a server
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+struct UserNode* searchUserByNick(const char *nick) { //case insensitive
+ if(!isalpha(*nick))
+ return getUserByNick(nick);
+
+ int userListIndex;
+ struct UserNode *user;
+
+ //search in the lower case "section"
+ userListIndex = get_nicklist_entry(tolower(*nick));
+ if(userListIndex != -1 && userList[userListIndex] != NULL) {
+ for(user = userList[userListIndex]; user; user = user->next) {
+ if(!stricmp(nick, user->nick))
+ return user;
+ }
+ }
+ //search in the upper case "section"
+ userListIndex = get_nicklist_entry(toupper(*nick));
+ if(userListIndex != -1 && userList[userListIndex] != NULL) {
+ for(user = userList[userListIndex]; user; user = user->next) {
+ if(!stricmp(nick, user->nick))
+ return user;
+ }
+ }
+ return NULL;
+}
+
+int countUsersWithHost(char *host) {
+ int i, count = 0;
+ struct UserNode *user;
+ for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
+ for(user = userList[i]; user; user = user->next) {
+ if(!strcmp(user->host, host)) {
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+char *getAuthFakehost(char *auth) {
+ int i;
+ struct UserNode *user;
+ for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
+ for(user = userList[i]; user; user = user->next) {
+ if((user->flags & USERFLAG_ISAUTHED) && !strcmp(user->auth, auth) && isFakeHost(user->host)) {
+ return user->host;
+ }
+ }
+ }
+ return NULL;
+}
+
+struct UserNode* getAllUsers(struct UserNode *last) {
+ if(last == NULL || last->next == NULL) {
+ int cindex;
+ if(last == NULL)
+ cindex = 0;
+ else
+ cindex = get_nicklist_entry(last->nick[0]) + 1;
+ while(userList[cindex] == NULL && cindex <= VALID_NICK_CHARS_FIRST_LEN)
+ cindex++;
+ if(cindex > VALID_NICK_CHARS_FIRST_LEN) return NULL;
+ return userList[cindex];
+ } else
+ return last->next;
+}
+
+int getUserCount() {
+ int i, count = 0;
+ struct UserNode *user;
+ for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) {
+ for(user = userList[i]; user; user = user->next) {
+ count++;
+ }
+ }
+ return count;
+}
+
+struct UserNode* addUser(const char *nick) {
+ int userListIndex = get_nicklist_entry(*nick);
+ if(userListIndex == -1 || !is_valid_nick(nick))
+ return NULL;
+ struct UserNode *user = malloc(sizeof(*user));
+ if (!user)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ strcpy(user->nick, nick);
+ user->created = time(0);
+ user->ident[0] = 0;
+ user->host[0] = 0;
+ user->realname[0] = 0;
+ user->flags = 0;
+ user->channel = NULL;
+ user->next = userList[userListIndex];
+ userList[userListIndex] = user;
+ return user;
+}
+
+struct UserNode* addUserMask(const char *mask) {
+ char cmask[strlen(mask)+1];
+ strcpy(cmask, mask);
+ int i, ii = 0;
+ struct UserNode *user = NULL;
+ for(i = 0; i < strlen(mask)+1; i++) {
+ if(cmask[i] == '!') {
+ cmask[i] = 0;
+ user = addUser(cmask);
+ if(user == NULL) return NULL;
+ ii = i+1;
+ } else if(cmask[i] == '.' && !user) {
+ //it's a server
+ return NULL;
+ } else if(cmask[i] == '@') {
+ if(user == NULL) return NULL;
+ cmask[i] = 0;
+ strcpy(user->ident, &cmask[ii]);
+ ii = i+1;
+ } else if(cmask[i] == '\0') {
+ if(user == NULL) return NULL;
+ strcpy(user->host, &cmask[ii]);
+ }
+ }
+ return user;
+}
+
+struct UserNode* createTempUser(const char *mask) {
+ //note: it could also be a server we have to create a temponary user for...
+ char cmask[strlen(mask)+1];
+ strcpy(cmask, mask);
+ int i, ii = 0;
+ struct UserNode *user = NULL;
+ for(i = 0; i < strlen(mask)+1; i++) {
+ if(cmask[i] == '!') {
+ cmask[i] = 0;
+ user = malloc(sizeof(*user));
+ if (!user)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ strcpy(user->nick, cmask);
+ user->created = time(0);
+ user->ident[0] = 0;
+ user->host[0] = 0;
+ user->realname[0] = 0;
+ user->flags = 0;
+ user->channel = NULL;
+ ii = i+1;
+ } else if(cmask[i] == '.' && !user) {
+ //it's a server
+ user = malloc(sizeof(*user));
+ if (!user)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ strcpy(user->host, cmask);
+ user->created = time(0);
+ user->ident[0] = 0;
+ user->host[0] = 0;
+ user->realname[0] = 0;
+ user->flags = USERFLAG_ISSERVER;
+ user->channel = NULL;
+ return user;
+ } else if(cmask[i] == '@') {
+ if(user == NULL) return NULL;
+ cmask[i] = 0;
+ strcpy(user->ident, &cmask[ii]);
+ ii = i+1;
+ } else if(cmask[i] == '\0') {
+ if(user == NULL) {
+ //nick only
+ user = malloc(sizeof(*user));
+ if (!user)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ strcpy(user->nick, cmask);
+ user->created = time(0);
+ user->ident[0] = 0;
+ user->host[0] = 0;
+ user->realname[0] = 0;
+ user->flags = 0;
+ user->channel = NULL;
+ return user;
+ }
+ strcpy(user->host, &cmask[ii]);
+ }
+ }
+ return user;
+}
+
+int renameUser(struct UserNode* user, const char *new_nick) {
+ if(!is_valid_nick(new_nick))
+ return 0;
+ if(user->nick[0] == *new_nick) {
+ strcpy(user->nick, new_nick);
+ return 1;
+ }
+ int userListIndex = get_nicklist_entry(*new_nick);
+ delUser(user, 0);
+ strcpy(user->nick, new_nick);
+ user->next = userList[userListIndex];
+ userList[userListIndex] = user;
+ return 1;
+}
+
+void delUser(struct UserNode* user, int freeUser) {
+ int userListIndex = get_nicklist_entry(user->nick[0]);
+ if(userListIndex == -1) return;
+ struct UserNode *cuser, *last_user = NULL;
+ for(cuser = userList[userListIndex]; cuser; cuser = cuser->next) {
+ if(cuser == user) {
+ if(last_user)
+ last_user->next = user->next;
+ else
+ userList[userListIndex] = user->next;
+ break;
+ } else
+ last_user = cuser;
+ }
+ if(user->channel) {
+ struct ChanUser *chanUser, *next;
+ for(chanUser = user->channel; chanUser; chanUser = next) {
+ next = chanUser->next_chan;
+ removeChanUserFromLists(chanUser, 1, 0, freeUser);
+ }
+ }
+ if(freeUser)
+ free(user);
+ else
+ user->next = NULL;
+}
+
+void clearTempUsers() {
+ int userListIndex = TEMPUSER_LIST_INDEX;
+ struct UserNode *cuser, *last_user = NULL, *next;
+ time_t now = time(0);
+ for(cuser = userList[userListIndex]; cuser; cuser = next) {
+ next = cuser->next;
+ if(cuser->flags & USERFLAG_FREETMPUSER || now - cuser->created >= 300) {
+ if(last_user)
+ last_user->next = cuser->next;
+ else
+ userList[userListIndex] = cuser->next;
+ break;
+ } else
+ last_user = cuser;
+ }
+}
--- /dev/null
+#ifndef _UserNode_h
+#define _UserNode_h
+#include "main.h"
+
+#define USERFLAG_ISBOT 0x0001
+#define USERFLAG_ISAUTHED 0x0002
+#define USERFLAG_ISIRCOP 0x0004
+#define USERFLAG_ISTMPUSER 0x0008
+#define USERFLAG_ISSERVER 0x0010
+#define USERFLAG_FREETMPUSER 0x0020
+#define USERFLAG_LOADED_SETTINGS 0x0040
+#define USERFLAG_REPLY_PRIVMSG 0x0080
+#define USERFLAG_GOD_MODE 0x0100
+
+#define USERFLAG_SCRIPTFLAG1 0x40000000
+#define USERFLAG_SCRIPTFLAG2 0x80000000
+
+struct ChanUser;
+struct language;
+
+struct UserNode {
+ char nick[NICKLEN+1];
+ char ident[USERLEN+1];
+ char host[HOSTLEN+1];
+ char realname[REALLEN+1];
+ char auth[AUTHLEN+1];
+ unsigned int flags;
+ time_t created;
+ struct ChanUser *channel;
+ struct language *language;
+
+ struct UserNode *next;
+};
+
+#define isNetworkService(USER) (USER->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))
+
+void init_UserNode();
+void free_UserNode();
+int is_valid_nick(const char *nick);
+struct UserNode* getUserByNick(const char *nick);
+struct UserNode* getUserByMask(const char *mask);
+int countUsersWithHost(char *host);
+char *getAuthFakehost(char *auth);
+struct UserNode* searchUserByNick(const char *nick);
+struct UserNode* getAllUsers(struct UserNode *last);
+int getUserCount();
+struct UserNode* addUser(const char *nick);
+struct UserNode* addUserMask(const char *mask);
+struct UserNode* createTempUser(const char *mask);
+int renameUser(struct UserNode* user, const char *new_nick);
+void delUser(struct UserNode* user, int freeUser);
+void clearTempUsers();
+
+#endif
--- /dev/null
+
+#include "WHOHandler.h"
+#include "ChanNode.h"
+#include "UserNode.h"
+#include "ChanUser.h"
+#include "ClientSocket.h"
+
+#define WHOQUEUETYPE_ISONQUEUE 0x01
+#define WHOQUEUETYPE_USERLIST 0x02
+#define WHOQUEUETYPE_USERAUTH 0x04
+#define WHOQUEUETYPE_CHECKTYPE 0x07
+#define WHOQUEUETYPE_FOUND 0x08
+
+struct WHOQueueEntry {
+ char type;
+ struct ClientSocket *client;
+ struct ChanNode *chan;
+ struct UserNode *user;
+ struct WHOQueueEntry *next;
+ void *callback;
+ void *data;
+};
+
+static struct WHOQueueEntry *first_entry = NULL, *last_entry = NULL;
+
+static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
+ struct WHOQueueEntry *entry = malloc(sizeof(*entry));
+ if (!entry)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ entry->next = NULL;
+ entry->client = client;
+ if(last_entry) {
+ last_entry->next = entry;
+ last_entry = entry;
+ } else {
+ last_entry = entry;
+ first_entry = entry;
+ }
+ return entry;
+}
+
+static struct WHOQueueEntry* getNextWHOQueueEntry(struct ClientSocket *client, int freeEntry) {
+ if(!first_entry) return NULL;
+ struct WHOQueueEntry *entry;
+ for(entry = first_entry; entry; entry = entry->next) {
+ if(entry->client == client)
+ break;
+ }
+ if(entry == NULL) return NULL;
+ if(freeEntry) {
+ if(entry == first_entry)
+ first_entry = entry->next;
+ if(entry == last_entry) {
+ struct WHOQueueEntry *last;
+ for(last = first_entry; last; last = last->next)
+ if(last->next == NULL) break;
+ last_entry = last;
+ }
+ }
+ return entry;
+}
+
+void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data) {
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(isUserOnChan(bot->user, chan))
+ break;
+ }
+ if(bot == NULL) return;
+ struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
+ entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST;
+ entry->chan = chan;
+ entry->callback = callback;
+ entry->data = data;
+ //WHO ".$channel->getName().",".$id." d%tuhnaf,".$id
+ putsock(bot, "WHO %s,%d %%tuhnaf,%d", chan->name, entry->type, entry->type);
+}
+
+void get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t callback, void *data) {
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(isUserOnChan(bot->user, chan))
+ break;
+ }
+ if(bot == NULL) return;
+ struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
+ entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST;
+ entry->chan = chan;
+ entry->callback = callback;
+ entry->data = data;
+ //WHO ".$channel->getName().",".$id." d%tuhnaf,".$id
+ putsock(bot, "WHO %s,%d d%%tuhnaf,%d", chan->name, entry->type, entry->type);
+}
+
+void get_userauth(struct UserNode *user, userauth_callback_t callback, void *data) {
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->flags & SOCKET_FLAG_PREFERRED)
+ break;
+ }
+ if(bot == NULL) bot = getBots(SOCKET_FLAG_READY, NULL);
+ struct WHOQueueEntry* entry = addWHOQueueEntry(bot);
+ entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERAUTH;
+ entry->user = user;
+ entry->callback = callback;
+ entry->data = data;
+ //WHO ".$user->getNick().",".$id." %tuhna,".$id
+ putsock(bot, "WHO %s,%d %%tuhna,%d", user->nick, entry->type, entry->type);
+}
+
+void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc) {
+ int i;
+ if(argc < 2) return;
+ int type = atoi(argv[1]);
+ if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
+ struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 0);
+ if(entry == NULL || (entry->type & WHOQUEUETYPE_CHECKTYPE) != (type & WHOQUEUETYPE_CHECKTYPE)) return;
+ if(type & WHOQUEUETYPE_USERLIST) {
+ if(argc < 7) return;
+ //:OGN2.OnlineGamesNet.net 354 skynet 1 pk910 2001:41d0:2:1d3b::babe skynet H@ pk910
+ struct ChanNode *chan = entry->chan;
+ //add the user toe the channel if he isn't added, yet and update its user data
+ //parse flags
+ int userflags = 0;
+ int chanuserflags = 0;
+ for(i = 0; i < strlen(argv[5]); i++) {
+ switch (argv[5][i]) {
+ case '@':
+ chanuserflags |= CHANUSERFLAG_OPPED;
+ break;
+ case '+':
+ chanuserflags |= CHANUSERFLAG_VOICED;
+ break;
+ case '*':
+ userflags |= USERFLAG_ISIRCOP;
+ break;
+ case '<':
+ chanuserflags |= CHANUSERFLAG_INVISIBLE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ struct UserNode *user;
+ if(chanuserflags & CHANUSERFLAG_INVISIBLE) {
+ user = createTempUser(argv[4]);
+ user->flags |= USERFLAG_ISTMPUSER;
+ chan->flags |= CHANFLAG_HAVE_INVISIBLES;
+ struct ChanUser *chanuser = addInvisibleChanUser(chan, user);
+ chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
+ } else {
+ user = getUserByNick(argv[4]);
+ if(user == NULL) {
+ user = addUser(argv[4]);
+ }
+ if(!isUserOnChan(user, chan)) {
+ struct ChanUser *chanuser = addChanUser(chan, user);
+ chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
+ }
+ }
+ user->flags = (user->flags & ~USERFLAG_ISIRCOP) | userflags;
+ if(!*user->ident)
+ strcpy(user->ident, argv[2]);
+ if(!*user->host)
+ strcpy(user->host, argv[3]);
+ if(!(user->flags & USERFLAG_ISAUTHED) && strcmp(argv[6], "0")) {
+ strcpy(user->auth, argv[6]);
+ user->flags |= USERFLAG_ISAUTHED;
+ }
+ } else if(type & WHOQUEUETYPE_USERAUTH) {
+ //:OGN2.OnlineGamesNet.net 354 Skynet 1 pk910 2001:41d0:2:1d3b::babe Skynet pk910
+ entry->type |= WHOQUEUETYPE_FOUND;
+ if(strcmp(argv[5], "0") && !(entry->user->flags & USERFLAG_ISAUTHED)) {
+ strcpy(entry->user->auth, argv[5]);
+ entry->user->flags |= USERFLAG_ISAUTHED;
+ }
+ userauth_callback_t *callback = entry->callback;
+ callback(client, entry->user->nick, entry->user, entry->data);
+ }
+}
+
+void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc) {
+ if(argc < 2) return;
+ char *typestr = strstr(argv[1], ",") + 1;
+ int type = atoi(typestr);
+ if(!(type & WHOQUEUETYPE_ISONQUEUE)) return;
+ struct WHOQueueEntry* entry = getNextWHOQueueEntry(client, 1);
+ if(entry == NULL || (entry->type & WHOQUEUETYPE_CHECKTYPE) != (type & WHOQUEUETYPE_CHECKTYPE)) return;
+ if(type & WHOQUEUETYPE_USERLIST) {
+ //:OGN2.OnlineGamesNet.net 315 skynet #pk910,1 :End of /WHO list.
+ entry->chan->flags |= CHANFLAG_RECEIVED_USERLIST;
+ userlist_callback_t *callback = entry->callback;
+ callback(client, entry->chan, entry->data);
+ if(entry->chan->flags & CHANFLAG_HAVE_INVISIBLES) {
+ //remove all invisible users again
+ struct ChanUser *chanuser, *next;
+ for(chanuser = getChannelUsers(entry->chan, NULL); chanuser; chanuser = next) {
+ next = getChannelUsers(entry->chan, chanuser);
+ if(chanuser->flags & CHANUSERFLAG_INVISIBLE) {
+ delChanUser(chanuser, 1);
+ }
+ }
+ }
+ } else if(type & WHOQUEUETYPE_USERAUTH) {
+ if(!(entry->type & WHOQUEUETYPE_FOUND)) {
+ userauth_callback_t *callback = entry->callback;
+ callback(client, entry->user->nick, NULL, entry->data);
+ }
+ }
+ free(entry);
+}
+
+void free_whoqueue() {
+ struct WHOQueueEntry *entry, *next;
+ for(entry = first_entry; entry; entry = next) {
+ next = entry->next;
+ free(entry);
+ }
+ first_entry = NULL;
+ last_entry = NULL;
+}
--- /dev/null
+#ifndef _WHOHandler_h
+#define _WHOHandler_h
+
+#include "main.h"
+
+struct ClientSocket;
+struct ChanNode;
+struct UserNode;
+
+#define USERLIST_CALLBACK(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(struct ChanNode *chan), UNUSED_ARG(void *data))
+typedef USERLIST_CALLBACK(userlist_callback_t);
+
+#define USERAUTH_CALLBACK(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(char *user_nick), UNUSED_ARG(struct UserNode *user), UNUSED_ARG(void *data))
+typedef USERAUTH_CALLBACK(userauth_callback_t);
+
+void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc);
+void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc);
+void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data);
+void get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t callback, void *data);
+void get_userauth(struct UserNode *user, userauth_callback_t callback, void *data);
+void free_whoqueue();
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "bot_NeonServ.h"
+#include "modcmd.h"
+#include "IRCEvents.h"
+#include "IRCParser.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "BanNode.h"
+#include "ModeNode.h"
+#include "ClientSocket.h"
+#include "mysqlConn.h"
+#include "lang.h"
+#include "HandleInfoHandler.h"
+#include "WHOHandler.h"
+#include "DBHelper.h"
+#include "tools.h"
+#include "timeq.h"
+#include "version.h"
+#include "EventLogger.h"
+#include "cmd_neonserv.h"
+
+#define BOTID 1
+
+static const struct default_language_entry msgtab[] = {
+ {"NS_USER_UNKNOWN", "User with nick $b%s$b does not exist."}, /* {ARGS: "TestUser"} */
+ {"NS_AUTH_UNKNOWN", "Account $b%s$b has not been registered."}, /* {ARGS: "TestAuth"} */
+ {"NS_USER_NEED_AUTH", "%s must first authenticate with $bAuthServ$b."}, /* {ARGS: "TestUser"} */
+ {"NS_YOU_NEED_AUTH", "You must first authenticate with $bAuthServ$b."},
+ {"NS_INVALID_ACCESS", "$b%d$b is an invalid access level."}, /* {ARGS: 1337} */
+ {"NS_ADDUSER_ALREADY_ADDED", "%s is already on the $b%s$b user list (with access %d)."}, /* {ARGS: "TestUser", "#TestChan", 123} */
+ {"NS_ADDUSER_DONE", "Added %s to the %s user list with access %d."}, /* {ARGS: "TestUser", "#TestChan", 123} */
+ {"NS_NOT_ON_USERLIST", "%s lacks access to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_NOT_ON_USERLIST_YOU", "You lack access to $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_NOT_ON_CHANNEL", "%s isn't currently in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_NOT_ON_CHANNEL_YOU", "You aren't currently in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_DELUSER_DONE", "Deleted %s (with access %d) from the %s user list."}, /* {ARGS: "TestUser", 123, "#TestChan"} */
+ {"NS_ACCESS_OUTRANKED", "You cannot give users access greater than or equal to your own."},
+ {"NS_USER_OUTRANKED", "$b%s$b outranks you (command has no effect)."}, /* {ARGS: "TestUser"} */
+ {"NS_ACCESS_DENIED", "Access denied."},
+ {"NS_NO_ACCESS", "You lack sufficient access to use this command."},
+ {"NS_USER_PROTECTED", "Sorry, $b%s$b is protected."}, /* {ARGS: "TestUser"} */
+ {"NS_SERVICE_IMMUNE", "$b%s$b may not be kicked, killed, banned, or deopped."}, /* {ARGS: "TestUser"} */
+ {"NS_TABLE_NONE", " None"},
+ {"NS_TABLE_COUNT", "Found $b%d$b matches."}, /* {ARGS: 5} */
+ {"NS_BAN_ALREADY_ADDED", "$b%s$b is already banned in %s."}, /* {ARGS: "*!*@moeeep.*", "#TestChan"} */
+ {"NS_INVALID_ACCESS_RANGE", "Invalid access range; minimum (%d) must be lower than maximum (%d)."}, /* {ARGS: 450, 400} */
+ {"NS_CLVL_DONE", "%s now has access $b%d$b in %s."}, /* {ARGS: "TestUser", 123, "#TestChan"} */
+ {"NS_A_LACKS_ACCESS_BUT_GOD_NICK", "%s lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "#TestChan"} */
+ {"NS_A_LACKS_ACCESS_BUT_GOD_AUTH", "%s (%s) lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", "#TestChan"} */
+ {"NS_A_ACCESS_NICK", "%s has access $b%d$b in %s."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */
+ {"NS_A_ACCESS_AUTH", "%s (%s) has access $b%d$b in %s."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */
+ {"NS_A_ACCESS_NICK_GOD", "%s has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */
+ {"NS_A_ACCESS_AUTH_GOD", "%s (%s) has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */
+ {"NS_A_SUSPENDED", "$b%s$b's access to %s has been suspended."}, /* {ARGS: "TestAuth", "#TestChan"} */
+ {"NS_A_IS_IRCOP", "%s is an $bIRC operator$b."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_USERS_HEADER", "%s users from level %d to %d:"}, /* {ARGS: "#TestChan", 1, 500} */
+ {"NS_USERS_HEADER_MATCH", "%s users from level %d to %d matching %s:"}, /* {ARGS: "#TestChan", 1, 500, "Test*"} */
+ {"NS_USERS_HEADER_ACCESS", "Access"},
+ {"NS_USERS_HEADER_ACCOUNT", "Accout"},
+ {"NS_USERS_HEADER_SEEN", "Last Seen"},
+ {"NS_USERS_HEADER_STATE", "Status"},
+ {"NS_USERS_COUNT", "There are $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
+ {"NS_USERS_COUNT_1", "There is $b%d$b user in %s."}, /* {ARGS: 1, "#TestChan"} */
+ {"NS_USERS_COUNT_MATCH", "There are $b%d$b users in %s. ($b%d$b matching your request)"}, /* {ARGS: 20, "#TestChan", 5} */
+ {"NS_USERS_COUNT_MATCH_1", "There is $b%d$b user in %s. ($b%d$b matching your request)"}, /* {ARGS: 1, "#TestChan", 1} */
+ {"NS_USERS_SEEN_HERE", "Here"},
+ {"NS_USERS_SEEN_INVISIBLE", "Here (invisible)"},
+ {"NS_USERS_SEEN_NEVER", "Never"},
+ {"NS_USERS_STATE_SUSPENDED", "Suspended"},
+ {"NS_USERS_STATE_NORMAL", "Normal"},
+ {"NS_SUSPEND_ALREADY", "$b%s$b is already suspended." }, /* {ARGS: "TestUser"} */
+ {"NS_SUSPEND_NOT", "$b%s$b is not suspended." }, /* {ARGS: "TestUser"} */
+ {"NS_SUSPEND_DONE", "$b%s$b's access to $b%s$b has been suspended." }, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_SUSPEND_RESTORED", "$b%s$b's access to $b%s$b has been restored." }, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_DELME_KEY", "To really remove yourself, you must use 'deleteme %s'."}, /* {ARGS: "abc123"} */
+ {"NS_DELME_DONE", "Your $b%d$b access has been deleted from $b%s$b."}, /* {ARGS: 123, "#TestChan"} */
+ {"NS_MYACCESS_HEADER", "Showing all channel entries for account $b%s$b:"}, /* {ARGS: "TestAuth"} */
+ {"NS_MYACCESS_HEADER_MATCH", "Showing all channel entries for account $b%s$b matching %s:"}, /* {ARGS: "TestAuth", "#Test*"} */
+ {"NS_MYACCESS_HEADER_NAME", "Name"},
+ {"NS_MYACCESS_HEADER_ACCESS", "Access"},
+ {"NS_MYACCESS_HEADER_FLAGS", "Flags"},
+ {"NS_MYACCESS_HEADER_INFO", "Info"},
+ {"NS_MYACCESS_COUNT", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s)."}, /* {ARGS: "TestUser", 15, 5} */
+ {"NS_MYACCESS_COUNT_MATCH", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s) ($b%d$b channels matching your request)."}, /* {ARGS: "TestUser", 15, 5, 7} */
+ {"NS_UP_ALREADY_OP", "You are already opped in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_UP_ALREADY_VOICE", "You are already voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_DOWN_ALREADY", "You are not opped or voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_MDELUSER_DONE", "Deleted $b%d$b account(s) matching $b%s$b with access from $b%d$b to $b%d$b from the %s user list."}, /* {ARGS: 10, "Test*", 1, 200, "#TestChan"} */
+ {"NS_TRIM_DURATION_TOO_SHORT", "You must include a minimum inactivity duration of at least %d seconds to trim."},
+ {"NS_TRIM_DONE", "Trimmed $b%d users$b with access from %d to %d from the %s user list who were inactive for at least %s."}, /* {ARGS: 10, 1, 100, "#TestChan", "10 days"} */
+ {"NS_GIVEOWNER_SELF", "You cannot give ownership to your own account."},
+ {"NS_GIVEOWNER_TIMEOUT", "You must wait %s before you can give ownership of $b%s$b to someone else."}, /* {ARGS: "5 hours", "#TestChan"} */
+ {"NS_GIVEOWNER_CONFIRM", "To really give ownership to $b%1$s$b, you must use 'giveownership *%1$s %2$s'."}, /* {ARGS: "TestUser", "abc123"} */
+ {"NS_GIVEOWNER_DONE", "Ownership of $b%s$b has been transferred to account $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */
+ {"NS_OP_FAIL", "$b%s$b could not op some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_OP_DONE", "Opped users in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_VOICE_FAIL", "$b%s$b could not voice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_VOICE_DONE", "Voiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_DEOP_FAIL", "$b%s$b could not deop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_DEOP_DONE", "Deopped users in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_DEVOICE_FAIL", "$b%s$b could not devoice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_DEVOICE_DONE", "Devoiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_OPALL_SECURITY", "$bWARNING$b: Opping all users on a channel is very insecure! If you still want do op all users on %s use: '$bopall FORCE$b [nick mask]'"},
+ {"NS_OPALL_DONE", "Opped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
+ {"NS_VOICEALL_DONE", "Voiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
+ {"NS_DEOPALL_DONE", "Deopped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
+ {"NS_DEVOICEALL_DONE", "Devoiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */
+ {"NS_KICK_DONE", "Kicked $b%d$b users from %s"}, /* {ARGS: 20, "#TestChan"} */
+ {"NS_KICK_FAIL", "$b%s$b could not kick some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_KICKBAN_DONE", "KickBanned $b%d$b users from %s"}, /* {ARGS: 10, "#TestChan"} */
+ {"NS_KICKBAN_FAIL", "$b%s$b could not kickban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_BAN_DONE", "$b%d$b masks added to the %s ban list. (matching %d users)"}, /* {ARGS: 5, "#TestChan", 15} */
+ {"NS_BAN_FAIL", "$b%s$b could not ban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_LAME_MASK", "$b%s$b is a little too general. Try making it more specific."}, /* {ARGS: "*!*@*"} */
+ {"NS_SET_HEADER", "Channel Settings for %s:"}, /* {ARGS: "#TestChan"} */
+ {"NS_SET_ON", "on"},
+ {"NS_SET_OFF", "off"},
+ {"NS_SET_UNKNOWN_SETTING", "$b%s$b is an unknown channel setting."}, /* {ARGS: "TestSetting"} */
+ {"NS_SET_CANNOT_SET", "That setting is above your current level, so you cannot change it."},
+ {"NS_SET_BADLEVEL", "You cannot change any setting to above your level."},
+ {"NS_SET_INVALID_OPTION", "$b%d$b is not a valid choice. Choose one:"}, /* {ARGS: 5} */
+ {"NS_SET_INVALID_BOOLEAN", "$b%s$b is an invalid binary value."}, /* {ARGS: 2} */
+ {"NS_SET_DEFAULTS_OWNER", "You must have access 500 in %s to reset it to the default options."}, /* {ARGS: "#TestChan"} */
+ {"NS_SET_DEFAULTS_CODE", "To reset %s's settings to the defaults, you must use 'set defaults %s'."}, /* {ARGS: "#TestChan", "abc123"} */
+ {"NS_SET_DEFAULTS_DONE", "All settings for %s have been reset to default values."}, /* {ARGS: "#TestChan"} */
+ {"NS_SET_TRIGGER_OWNER", "You must have access 500 in %s to change the channel trigger."}, /* {ARGS: "#TestChan"} */
+ {"NS_SET_HELP_USERINFO","(access to set the userinfo)"},
+ {"NS_SET_HELP_WIPEINFO","(access to clear the userinfo of other users)"},
+ {"NS_SET_HELP_INVITEME","(access to get invited by the bot)"},
+ {"NS_SET_HELP_ENFVOICE","(access to give voice to other users)"},
+ {"NS_SET_HELP_ENFOPS","(access to give op to their users)"},
+ {"NS_SET_HELP_GIVEOPS","(access to get op by the bot)"},
+ {"NS_SET_HELP_GIVEVOICE","(access to get voice by the bot)"},
+ {"NS_SET_HELP_KICK","(access to kick other users from the channel)"},
+ {"NS_SET_HELP_BAN","(access to ban other users from the channel)"},
+ {"NS_SET_HELP_STATICBAN","(access to add static bans to the channel banlist e.g. +addban)"},
+ {"NS_SET_HELP_PUBCMD","(access to do public commands in the channel e.g. +users)"},
+ {"NS_SET_HELP_ENFMODES","(access to override the modelock)"},
+ {"NS_SET_HELP_ENFTOPIC","(access to override the topicmask)"},
+ {"NS_SET_HELP_TOPICSNARF","(access to set the default topic by changing the topic with /TOPIC)"},
+ {"NS_SET_HELP_CHANGETOPIC","(access to change the topic)"},
+ {"NS_SET_HELP_SETTERS","(access to change this settings)"},
+ {"NS_SET_HELP_ADDUSER","(access to add an user to the userlist)"},
+ {"NS_SET_HELP_DELUSER","(access to delete an user from the userlist)"},
+ {"NS_SET_HELP_CLVL","(access to change the access of an user in the userlist)"},
+ {"NS_SET_HELP_RESYNC","(access to synchronize the channelrights (@,+) with the userlist)"},
+ {"NS_SET_HELP_SUSPEND","(access to suspend an user on the userlist)"},
+ {"NS_SET_OPTION_CTCPREACTION_0","Kick on disallowed CTCPs"},
+ {"NS_SET_OPTION_CTCPREACTION_1","Kickban on disallowed CTCPs"},
+ {"NS_SET_OPTION_CTCPREACTION_2","Short timed ban on disallowed CTCPs"},
+ {"NS_SET_OPTION_CTCPREACTION_3","Long timed ban on disallowed CTCPs"},
+ {"NS_SET_OPTION_NOTICEREACTION_0","Kick on disallowed NOTICEs"},
+ {"NS_SET_OPTION_NOTICEREACTION_1","Kickban on disallowed NOTICEs"},
+ {"NS_SET_OPTION_NOTICEREACTION_2","Short timed ban on disallowed NOTICEs"},
+ {"NS_SET_OPTION_NOTICEREACTION_3","Long timed ban on disallowed NOTICEs"},
+ {"NS_SET_OPTION_PROTECT_0","All users will be protected from users with equal or lower access."},
+ {"NS_SET_OPTION_PROTECT_1","All users with access will be protected from users with equal or lower access."},
+ {"NS_SET_OPTION_PROTECT_2","All users with access will be protected from user with lower access."},
+ {"NS_SET_OPTION_PROTECT_3","Nobody will be protected."},
+ {"NS_SET_OPTION_TOYS_0","Funcommands can't be used."},
+ {"NS_SET_OPTION_TOYS_1","Funcommands are possible but the reply will be sent as a notice."},
+ {"NS_SET_OPTION_TOYS_2","Funcommands are possible and the reply will be sent to the channel."},
+ {"NS_SET_OPTION_DYNLIMIT_0","off"},
+ {"NS_SET_OPTION_NODELETE_0","off (only bot masters)"},
+ {"NS_SET_OPTION_NODELETE_1","on (only bot masters)"},
+ {"NS_WIPEINFO_DONE", "Removed $b%s$b's infoline in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_TRACE_HEADER", "The following users were found:"},
+ {"NS_ADDBAN_DONE", "$b%s$b permantly added to the %s ban list. (matching %d users)"}, /* {ARGS: "*!*@Test.*", "#TestChan", 4} */
+ {"NS_BANS_HEADER_MASK", "Mask"},
+ {"NS_BANS_HEADER_SETBY", "Set By"},
+ {"NS_BANS_HEADER_TRIGGERED", "Triggered"},
+ {"NS_BANS_HEADER_EXPIRES", "Expires"},
+ {"NS_BANS_HEADER_REASON", "Reason"},
+ {"NS_DELBAN_BANNED_BY", "%s is banned by %s."}, /* {ARGS: "*!*@bla*", "*!*@b*"} */
+ {"NS_DELBAN_FAIL", "Sorry, no ban found for $b%s$b."}, /* {ARGS: "*!*@bla*"} */
+ {"NS_DELBAN_DONE", "Removed $b%s$b from the %s ban list."}, /* {ARGS: "*!*@bla.*", "#TestChan"} */
+ {"NS_NETINFO_HEADER", "$bNetwork information$b"},
+ {"NS_NETINFO_BOTS", "Bots:"},
+ {"NS_NETINFO_UPTIME", "Uptime:"},
+ {"NS_NETINFO_TRAFFIC", "Traffic:"},
+ {"NS_NETINFO_CACHE", "Cache:"},
+ {"NS_NETINFO_DATABASE", "Database:"},
+ {"NS_NETINFO_CHANNEL", " Channel:"},
+ {"NS_NETINFO_CHANNEL_BAN", " Bans:"},
+ {"NS_NETINFO_USER", " User:"},
+ {"NS_NETINFO_CHANUSER", " Channel-User:"},
+ {"NS_NETINFO_OTHER", " Other:"},
+ {"NS_NETINFO_VERSION", "Version:"},
+ {"NS_NETINFO_CODE", "Code:"},
+ {"NS_NETINFO_CODE_VALUE", "%s lines c code (view it at http://git.pk910.de/?p=NeonServV5.git;a=summary)"}, /* {ARGS: 20} */
+ {"NS_NETINFO_COMPILER", "Compiler:"},
+ {"NS_NETINFO_COMPILER_VALUE", "%s (%s)"}, /* {ARGS: "GCC 4.4.5", "Sun Sep 18 2011 at 05:21:33 CEST"} */
+ {"NS_EXTTOPIC_INVALID_ID", "ADVANCEDTOPIC is enabled and $b%s$b is an invalid TOPIC ID. Valid topic id's are: 1-9"}, /* {ARGS: 10} */
+ {"NS_EXTTOPIC_TOPICID", "Topic %d: %s"}, /* {ARGS: 5, "topic"} */
+ {"NS_TOPIC_DONE", "Topic is now '%s'."}, /* {ARGS: "i like you :D"} */
+ {"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!"}, /* {ARGS: "CowBot"} */
+ {"NS_CHANSERVSYNC_KEY", "If you really want to synchronize the %s userlist with %s use: chanservsync %s %s"}, /* {ARGS: "#TestChan", "CowBot", "CowBot", "abc123"} */
+ {"NS_CHANSERVSYNC_INUSE", "$bchanservsync$b is already in use by someone else. Please try again in a few seconds..."},
+ {"NS_CHANSERVSYNC_SYNCHRONIZING", "Synchronizing userlist in %s with $b%s$b..."}, /* {ARGS: "#TestChan", "CowBot"} */
+ {"NS_CHANSERVSYNC_SYNCHRONIZED", "Synchronized user $b%s$b: access $b%d$b"}, /* {ARGS: "TestUser", 123} */
+ {"NS_REGISTER_ALREADY", "%s is already registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */
+ {"NS_INVALID_CHANNEL_NAME", "%s is not a valid channel name."}, /* {ARGS: "#invalid"} */
+ {"NS_REGISTER_FULL", "the bot can not join more channels."},
+ {"NS_REGISTER_DISCONNECTED", "%s has been registered with a Bot, that is currently NOT connected. The Bot should join the channel, when it reconnects to the IRC-Network."}, /* {ARGS: "#TestChan"} */
+ {"NS_REGISTER_DONE", "$b%s$b is now registered to $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */
+ {"NS_UNREGISTER_NOT_REGISTERED", "$b%s$b is not registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */
+ {"NS_UNREGISTER_DONE", "$b%s$b unregistered."}, /* {ARGS: "#TestChan"} */
+ {"NS_RECOVER_DONE", "$b%s$b has been recovered."}, /* {ARGS: "#TestChan"} */
+ {"NS_RESYNC_DONE", "Synchronized users in $b%s$b with the userlist."}, /* {ARGS: "#TestChan"} */
+ {"NS_TIMEBAN_DURATION_TOO_SHORT", "You must specify a ban duration of at least %d seconds."}, /* {ARGS: 30} */
+ {"NS_TIMEBAN_DONE", "Banned $b%s$b from %s for %s. (matching %d users)"}, /* {ARGS: "*!*@bla*", "#TestChan", "2 hours", 5} */
+ {"NS_MODE_INVALID", "$b%c$b is an invalid set of channel modes."}, /* {ARGS: "+xyz"} */
+ {"NS_MODE_LOCKED", "Modes conflicting with $b%s$b are not allowed in %s."}, /* {ARGS: "+xyz", "#TestChan"} */
+ {"NS_MODE_DONE", "Channel modes are now $b%s$b."}, /* {ARGS: "+xyz"} */
+ {"NS_MODE_ENFOPS", "You may not op or deop users on $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_MODE_ENFVOICE", "You may not voice or devoice users on $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_MODE_CANBAN", "You may not ban or unban users on $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_GOD_ON", "Security override has been enabled."},
+ {"NS_GOD_OFF", "Security override has been disabled."},
+ {"NS_PEEK_HEADER", "$b%s$b Status:"}, /* {ARGS: "#TestChan"} */
+ {"NS_PEEK_TOPIC", "Topic: %s"}, /* {ARGS: "TOPIC"} */
+ {"NS_PEEK_MODES", "Modes: %s"}, /* {ARGS: "+xyz"} */
+ {"NS_PEEK_USERS", "Total Users: %d (%d ops, %d voices, %d regulars, %d invisible)"}, /* {ARGS: 20, 4, 6, 8, 2} */
+ {"NS_PEEK_OPS", "Ops:"},
+ {"NS_USET_GLOBAL", "$b--- Global ---$b"},
+ {"NS_USET_CHANNEL", "$b--- User options (channel) ---$b"},
+ {"NS_USET_NO_ACCESS", "no access"},
+ {"NS_USET_UNKNOWN_SETTING", "$b%s$b is an unknown uset setting."}, /* {ARGS: "TestSetting"} */
+ {"NS_RELOADLANG_UNKNOWN", "$b%s$b is an unknown language tag."}, /* {ARGS: "de"} */
+ {"NS_RELOADLANG_DONE", "$b%s$b (%s) reloaded."}, /* {ARGS: "Deutsch", "de"} */
+ {"NS_UNBAN_DONE", "$b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */
+ {"NS_UNBAN_FAIL", "$b%s$b could not unban some of the masks you provided."}, /* {ARGS: "NeonServ"} */
+ {"NS_UNBANALL_DONE", "all $b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */
+ {"NS_UNBANALL_FAIL", "$b%s$b could not find any bans in %s."}, /* {ARGS: "NeonServ", "#TestChan"} */
+ {"NS_UNBANME_DONE", "removed $b%d$b masks from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */
+ {"NS_UNBANME_FAIL", "$b%s$b could not find any bans matching %s."}, /* {ARGS: "NeonServ", "TestUser!TestIdent@TestUser.user.WebGamesNet"} */
+ {"NS_INVITE_RESTRICTION", "%s doesn't want to be invited to %s."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_INVITE_TIMEOUT", "%s has already been invited to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_INVITE_ON_CHAN", "%s is already in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_INVITE_DONE_USER", "You have been invited to join $b%s$b by %s. (Do $b/msg %s %1$s uset noinvite 1$b if you don't want to be invited to %1$s anymore.)"}, /* {ARGS: "#TestChan", "TestUser", "NeonServ"} */
+ {"NS_INVITE_DONE", "Invited $b%s$b to join %s."}, /* {ARGS: "TestUser", "#TestChan"} */
+ {"NS_INVITEME_ON_CHAN", "You are already in $b%s$b."}, /* {ARGS: "#TestChan"} */
+ {"NS_INVITEME_DONE", "You have been invited to join %s."}, /* {ARGS: "#TestChan"} */
+ {"NS_HELP_TOPIC", "No help on that topic."},
+ {"NS_CSUSPEND_ALREADY", "$b%s$b is already suspended."}, /* {ARGS: "#TestChan"} */
+ {"NS_CSUSPEND_DONE", "Channel $b%s$b has been temporarily suspended."}, /* {ARGS: "#TestChan"} */
+ {"NS_CUNSUSPEND_NOT", "$b%s$b is not suspended."}, /* {ARGS: "#TestChan"} */
+ {"NS_CUNSUSPEND_DONE", "Channel $b%s$b has been restored."}, /* {ARGS: "#TestChan"} */
+ {"NS_MOVE_SUSPENDED", "Moving cannot be performed if the source channel is suspended."},
+ {"NS_MOVE_SELF", "Moving cannot be performed if the source and target channels are the same."},
+ {"NS_MOVE_DONE", "Channel $b%s$b has been moved to $b%s$b."}, /* {ARGS: "#TestChan", "#NewTestChan"} */
+ {"NS_BIND_ALREADY", "$b%s$b is already bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */
+ {"NS_BIND_UNKNOWN", "$b%s$b is an undefined function."}, /* {ARGS: "TestFunction"} */
+ {"NS_BIND_DONE", "New command $b%s$b bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */
+ {"NS_UNBIND_NOT_FOUND", "There is no command called $b%s$b bound."}, /* {ARGS: "TestCommand"} */
+ {"NS_UNBIND_DONE", "Unbound command $b%s$b."}, /* {ARGS: "TestCommand"} */
+ {"NS_EVENTS_HEADER", "The following channel events were found:"},
+ {"NS_OPLOG_HEADER", "The following oper events were found:"},
+ {"NS_SEARCH_HEADER", "The following channels were found:"},
+ {"NS_COMMAND_BINDING", "$b%s$b is a binding of %s %s"}, /* {ARGS: "TestCommand", "TestFunction", "TestParameters"} */
+ {"NS_COMMAND_ACCESS", "You need at least %d channel access and %d oper access to execute this command."}, /* {ARGS: 500, 100} */
+ {"NS_TOPIC_ACCESS", "You lack sufficient access in %s to change the topic."}, /* {ARGS: "#TestChan"} */
+ {"NS_BOTWAR_DETECTED", "$b$k4BOTWAR DETECTED!$k Please check the channel configuration!$b"},
+ {"NS_BOTWAR_REPORTED", "A supporter has been informed to help you preventing botwars in the future."},
+ {"NS_BOTWAR_ALERT", "$b$k4BOTWAR ALERT:$k$b Botwar in $b%s$b detected. (opponent: $b%s$b) Please join and help them preventing Botwars."}, /* {ARGS: "#TestChan", "OtherBot"} */
+ {"NS_INVITE_FAIL", "$b%s$b is not registered with %s or suspended."}, /* {ARGS: "#TestChan", "NeonServ"} */
+ {"NS_SETACCESS_DONE", "$b%s$b has now %d global access."},
+ {NULL, NULL}
+};
+
+/* TODO:
+trim bans
+cmd_neonserv_open.c
+cmd_neonserv_info.c
+parse, check and set modelock
+cmd_neonserv_modcmd.c
+cmd_neonserv_allowregister.c
+cmd_neonserv_noregister.c
+cmd_neonserv_expire.c
+cmd_neonserv_unvisited.c
+cmd_neonserv_merge.c
+cmd_neonserv_dnrsearch.c
+cmd_neonserv_rename.c
+cmd_neonserv_iplocate.c
+cmd_neonserv_calc.c
+*/
+//EVENTS
+#include "event_neonserv_join.c"
+#include "event_neonserv_part.c"
+#include "event_neonserv_quit.c"
+//#include "event_neonserv_kick.c"
+//#include "event_neonserv_mode.c"
+#include "event_neonserv_ctcp.c"
+#include "event_neonserv_notice.c"
+#include "event_neonserv_invite.c"
+#include "event_neonserv_topic.c"
+
+struct ClientSocket *getBotForChannel(struct ChanNode *chan) {
+ struct ClientSocket *bot, *use_bot = NULL, *second_bot = NULL, *third_bot = NULL;
+ struct ChanUser *chanuser;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->botid != BOTID) continue;
+ if((chanuser = getChanUser(bot->user, chan)) != NULL) {
+ if((chanuser->flags & CHANUSERFLAG_OPPED)) {
+ use_bot = bot;
+ if(bot->flags & SOCKET_FLAG_PREFERRED) break;
+ } else if(bot->flags & SOCKET_FLAG_PREFERRED)
+ second_bot = bot;
+ else
+ third_bot = bot;
+ }
+ }
+ if(!use_bot) use_bot = second_bot;
+ if(!use_bot) use_bot = third_bot;
+ return use_bot;
+}
+
+static void neonserv_bot_ready(struct ClientSocket *client) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+
+ printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ putsock(client, "MODE %s +%s", client->user->nick, row[0]);
+ }
+
+ printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid);
+ res = mysql_use();
+
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ putsock(client, "JOIN %s %s", row[0], row[1]);
+ }
+}
+
+static void neonserv_trigger_callback(struct ChanNode *chan, char *trigger) {
+ strcpy(trigger, "+");
+}
+
+static void start_bots() {
+ struct UserNode *user;
+ struct ClientSocket *client;
+ MYSQL_RES *res, *res2;
+ MYSQL_ROW row;
+
+ printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID);
+ res = mysql_use();
+
+ while ((row = mysql_fetch_row(res)) != NULL) {
+
+ user = addUser(row[0]);
+ strcpy(user->ident, row[1]);
+ strcpy(user->realname, row[2]);
+ user->flags |= USERFLAG_ISBOT;
+ client = create_socket(row[3], atoi(row[4]), row[5], user);
+ client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0);
+ client->botid = BOTID;
+ client->clientid = atoi(row[7]);
+ connect_socket(client);
+ printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botclass` = '%d'", client->botid);
+ res2 = mysql_use();
+ while ((row = mysql_fetch_row(res2)) != NULL) {
+ if(bind_cmd_to_command(BOTID, row[0], row[1])) {
+ if(row[2] && strcmp(row[2], "")) {
+ bind_set_parameters(BOTID, row[0], row[2]);
+ }
+ if(row[3]) {
+ bind_set_global_access(BOTID, row[0], atoi(row[3]));
+ }
+ if(row[4]) {
+ bind_set_channel_access(BOTID, row[0], row[4]);
+ }
+ }
+ }
+ }
+
+ //load all timed bans
+ printf_mysql_query("SELECT `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_timeout` > 0");
+ res = mysql_use();
+ char nameBuf[20];
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(atol(row[1]) - time(0) > 0) {
+ sprintf(nameBuf, "ban_%s", row[0]);
+ timeq_add_name(nameBuf, atol(row[1]) - time(0), channel_ban_timeout, strdup(row[0]));
+ } else {
+ //timed out
+ printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[0]);
+ }
+ }
+}
+
+TIMEQ_CALLBACK(channel_ban_timeout) {
+ char *str_banid = data;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `ban_mask`, `channel_name` FROM `bans` LEFT JOIN `channels` ON `ban_channel` = `channel_id` WHERE `ban_id` = '%s'", str_banid);
+ res = mysql_use();
+ struct ChanNode *chan;
+ if((row = mysql_fetch_row(res)) != NULL && (chan = getChanByName(row[1])) != NULL) {
+ struct ClientSocket *use_bot = getBotForChannel(chan);
+ if(use_bot) {
+ putsock(use_bot, "MODE %s -b %s", chan->name, row[0]);
+ }
+ printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", str_banid);
+ }
+ free(str_banid);
+}
+
+void init_NeonServ() {
+
+ #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(BOTID, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS)
+ // NAME FUNCTION PARAMS PRIVS FLAGS
+ USER_COMMAND("adduser", neonserv_cmd_adduser, 2, "#channel_canadd", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("deluser", neonserv_cmd_deluser, 1, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("clvl", neonserv_cmd_clvl, 2, "#channel_canclvl", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("access", neonserv_cmd_access, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG);
+ USER_COMMAND("users", neonserv_cmd_users, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN);
+ USER_COMMAND("suspend", neonserv_cmd_suspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("unsuspend", neonserv_cmd_unsuspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("delme", neonserv_cmd_delme, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("myaccess", neonserv_cmd_myaccess, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
+ USER_COMMAND("up", neonserv_cmd_up, 0, "#channel_getop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("down", neonserv_cmd_down, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG);
+ USER_COMMAND("upall", neonserv_cmd_upall, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("downall", neonserv_cmd_downall, 0, NULL, CMDFLAG_LOG);
+ USER_COMMAND("mdeluser", neonserv_cmd_mdeluser, 2, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("trim", neonserv_cmd_trim, 2, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("giveowner", neonserv_cmd_giveowner, 1, "500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("op", neonserv_cmd_op, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("deop", neonserv_cmd_deop, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("voice", neonserv_cmd_voice, 1, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("devoice", neonserv_cmd_devoice, 1, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("opall", neonserv_cmd_opall, 0, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("deopall", neonserv_cmd_deopall, 0, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("voiceall", neonserv_cmd_voiceall, 0, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("devoiceall", neonserv_cmd_devoiceall,0, "#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("set", neonserv_cmd_set, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("kick", neonserv_cmd_kick, 1, "#channel_cankick", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("kickban", neonserv_cmd_kickban, 1, "#channel_cankick,#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("ban", neonserv_cmd_ban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("wipeinfo", neonserv_cmd_wipeinfo, 1, "#channel_wipeinfo", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("addban", neonserv_cmd_addban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("bans", neonserv_cmd_bans, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
+ USER_COMMAND("delban", neonserv_cmd_delban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("netinfo", neonserv_cmd_netinfo, 0, NULL, 0);
+ USER_COMMAND("topic", neonserv_cmd_topic, 0, "#channel_changetopic", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("chanservsync", neonserv_cmd_chanservsync, 0,"500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("resync", neonserv_cmd_resync, 0, "#channel_canresync", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("addtimeban", neonserv_cmd_addtimeban,2, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("mode", neonserv_cmd_mode, 1, "#channel_getop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("version", neonserv_cmd_version, 0, NULL, 0);
+ USER_COMMAND("peek", neonserv_cmd_peek, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN);
+ USER_COMMAND("uset", neonserv_cmd_uset, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
+ USER_COMMAND("unban", neonserv_cmd_unban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("unbanall", neonserv_cmd_unbanall, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("unbanme", neonserv_cmd_unbanme, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("invite", neonserv_cmd_invite, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("inviteme", neonserv_cmd_inviteme, 0, "#channel_getinvite", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG);
+ USER_COMMAND("help", neonserv_cmd_help, 0, NULL, 0);
+ USER_COMMAND("events", neonserv_cmd_events, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
+ USER_COMMAND("command", neonserv_cmd_command, 1, NULL, 0);
+ #undef USER_COMMAND
+
+ #define OPER_COMMAND(NAME,FUNCTION,PARAMCOUNT,GACCESS,FLAGS) register_command(BOTID, NAME, FUNCTION, PARAMCOUNT, NULL, GACCESS, FLAGS)
+ // NAME FUNCTION PARAMS ACCS FLAGS
+ OPER_COMMAND("trace", neonserv_cmd_trace, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
+ OPER_COMMAND("register", neonserv_cmd_register, 2, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("unregister", neonserv_cmd_unregister,1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("recover", neonserv_cmd_recover, 1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("say", neonserv_cmd_say, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("emote", neonserv_cmd_emote, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("notice", neonserv_cmd_notice, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("raw", neonserv_cmd_raw, 1, 800, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
+ OPER_COMMAND("god", neonserv_cmd_god, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
+ OPER_COMMAND("reloadlang", neonserv_cmd_reloadlang,1, 500, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
+ OPER_COMMAND("csuspend", neonserv_cmd_csuspend, 1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("cunsuspend", neonserv_cmd_cunsuspend,1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("move", neonserv_cmd_move, 2, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG);
+ OPER_COMMAND("bind", neonserv_cmd_bind, 2, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
+ OPER_COMMAND("unbind", neonserv_cmd_unbind, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
+ OPER_COMMAND("oplog", neonserv_cmd_oplog, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
+ OPER_COMMAND("search", neonserv_cmd_search, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
+ OPER_COMMAND("setaccess", neonserv_cmd_setaccess, 2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG);
+ #undef OPER_COMMAND
+
+ start_bots();
+
+ //register events
+ bind_bot_ready(neonserv_bot_ready);
+ bind_join(neonserv_event_join);
+ bind_part(neonserv_event_part);
+ bind_quit(neonserv_event_quit);
+ bind_chanctcp(neonserv_event_chanctcp);
+ bind_privctcp(neonserv_event_privctcp);
+ bind_channotice(neonserv_event_channotice);
+ bind_topic(neonserv_event_topic);
+ bind_invite(neonserv_event_invite);
+
+ set_trigger_callback(BOTID, neonserv_trigger_callback);
+
+ register_default_language_table(msgtab);
+}
+
+void loop_NeonServ() {
+
+}
+
+void free_NeonServ() {
+
+}
+
+#undef BOTID
--- /dev/null
+#ifndef _bot_NeonServ_h
+#define _bot_NeonServ_h
+
+#include "main.h"
+#include "timeq.h"
+
+struct ChanNode;
+
+void init_NeonServ();
+void loop_NeonServ();
+void free_NeonServ();
+
+TIMEQ_CALLBACK(channel_ban_timeout);
+struct ClientSocket *getBotForChannel(struct ChanNode *chan);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "bots.h"
+
+#include "bot_NeonServ.h"
+
+void init_bots() {
+ init_NeonServ();
+}
+
+void loop_bots() {
+ loop_NeonServ();
+}
+
+void free_bots() {
+ free_NeonServ();
+}
--- /dev/null
+#ifndef _bots_h
+#define _bots_h
+
+#include "main.h"
+
+void init_bots();
+void loop_bots();
+void free_bots();
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef _cmd_neonserv_h
+#define _cmd_neonserv_h
+#include "main.h"
+#include "modcmd.h"
+#include "IRCParser.h"
+#include "IRCEvents.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "ModeNode.h"
+#include "BanNode.h"
+#include "ClientSocket.h"
+#include "mysqlConn.h"
+#include "lang.h"
+#include "HandleInfoHandler.h"
+#include "WHOHandler.h"
+#include "DBHelper.h"
+#include "tools.h"
+#include "timeq.h"
+#include "version.h"
+#include "EventLogger.h"
+#include "bot_NeonServ.h"
+
+CMD_BIND(neonserv_cmd_access);
+CMD_BIND(neonserv_cmd_addban);
+CMD_BIND(neonserv_cmd_addtimeban);
+CMD_BIND(neonserv_cmd_adduser);
+CMD_BIND(neonserv_cmd_ban);
+CMD_BIND(neonserv_cmd_bans);
+CMD_BIND(neonserv_cmd_bind);
+CMD_BIND(neonserv_cmd_chanservsync);
+CMD_BIND(neonserv_cmd_clvl);
+CMD_BIND(neonserv_cmd_command);
+CMD_BIND(neonserv_cmd_csuspend);
+CMD_BIND(neonserv_cmd_cunsuspend);
+CMD_BIND(neonserv_cmd_delban);
+CMD_BIND(neonserv_cmd_delme);
+CMD_BIND(neonserv_cmd_deluser);
+CMD_BIND(neonserv_cmd_deop);
+CMD_BIND(neonserv_cmd_deopall);
+CMD_BIND(neonserv_cmd_devoice);
+CMD_BIND(neonserv_cmd_devoiceall);
+CMD_BIND(neonserv_cmd_down);
+CMD_BIND(neonserv_cmd_downall);
+CMD_BIND(neonserv_cmd_emote);
+CMD_BIND(neonserv_cmd_events);
+CMD_BIND(neonserv_cmd_giveowner);
+CMD_BIND(neonserv_cmd_god);
+CMD_BIND(neonserv_cmd_help);
+CMD_BIND(neonserv_cmd_invite);
+CMD_BIND(neonserv_cmd_inviteme);
+CMD_BIND(neonserv_cmd_kick);
+CMD_BIND(neonserv_cmd_kickban);
+CMD_BIND(neonserv_cmd_mdeluser);
+CMD_BIND(neonserv_cmd_mode);
+CMD_BIND(neonserv_cmd_move);
+CMD_BIND(neonserv_cmd_myaccess);
+CMD_BIND(neonserv_cmd_netinfo);
+CMD_BIND(neonserv_cmd_notice);
+CMD_BIND(neonserv_cmd_op);
+CMD_BIND(neonserv_cmd_opall);
+CMD_BIND(neonserv_cmd_oplog);
+CMD_BIND(neonserv_cmd_peek);
+CMD_BIND(neonserv_cmd_raw);
+CMD_BIND(neonserv_cmd_recover);
+CMD_BIND(neonserv_cmd_register);
+CMD_BIND(neonserv_cmd_reloadlang);
+CMD_BIND(neonserv_cmd_resync);
+CMD_BIND(neonserv_cmd_say);
+CMD_BIND(neonserv_cmd_search);
+CMD_BIND(neonserv_cmd_set);
+CMD_BIND(neonserv_cmd_setaccess);
+CMD_BIND(neonserv_cmd_suspend);
+CMD_BIND(neonserv_cmd_topic);
+CMD_BIND(neonserv_cmd_trace);
+CMD_BIND(neonserv_cmd_trim);
+CMD_BIND(neonserv_cmd_unban);
+CMD_BIND(neonserv_cmd_unbanall);
+CMD_BIND(neonserv_cmd_unbanme);
+CMD_BIND(neonserv_cmd_unbind);
+CMD_BIND(neonserv_cmd_unregister);
+CMD_BIND(neonserv_cmd_unsuspend);
+CMD_BIND(neonserv_cmd_up);
+CMD_BIND(neonserv_cmd_upall);
+CMD_BIND(neonserv_cmd_users);
+CMD_BIND(neonserv_cmd_uset);
+CMD_BIND(neonserv_cmd_version);
+CMD_BIND(neonserv_cmd_voice);
+CMD_BIND(neonserv_cmd_voiceall);
+CMD_BIND(neonserv_cmd_wipeinfo);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup);
+static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target);
+
+struct neonserv_cmd_access_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ char *nick;
+};
+
+CMD_BIND(neonserv_cmd_access) {
+ if(argc == 0) {
+ if(!(user->flags & USERFLAG_ISAUTHED)) {
+ struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->nick = strdup(user->nick);
+ get_userauth(user, neonserv_cmd_access_nick_lookup, cache);
+ } else
+ neonserv_cmd_access_async1(client, getTextBot(), user, chan, user->nick, user->auth, user);
+ }
+ else if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ neonserv_cmd_access_async1(client, getTextBot(), user, chan, NULL, argv[0], NULL);
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_access_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, cuser);
+ } else {
+ struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_access_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup) {
+ struct neonserv_cmd_access_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ if(!strcmp(cache->nick, cache->user->nick))
+ reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH");
+ else
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_access_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, user);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW user_row, chanuser_row;
+ int userid;
+ printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((user_row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(user_row[0]);
+ //check if the user is already added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((chanuser_row = mysql_fetch_row(res)) != NULL) {
+ //access output
+ if(nick)
+ reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_AUTH" : "NS_A_ACCESS_AUTH_GOD"), nick, auth, atoi(chanuser_row[0]), chan->name);
+ else
+ reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_NICK" : "NS_A_ACCESS_NICK_GOD"), auth, atoi(chanuser_row[0]), chan->name);
+ int cflags = atoi(chanuser_row[1]);
+ if(cflags & DB_CHANUSER_SUSPENDED)
+ reply(textclient, user, "NS_A_SUSPENDED", (nick ? nick : auth), chan->name);
+ if(chanuser_row[2] && strcmp(chanuser_row[2], ""))
+ reply(textclient, user, "[%s] %s", (nick ? nick : auth), chanuser_row[2]);
+ } else if(!strcmp(user_row[2], "1")) {
+ if(nick)
+ reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_AUTH", nick, auth, chan->name);
+ else
+ reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_NICK", auth, chan->name);
+ } else
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+ } else
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+ if(target && (target->flags & USERFLAG_ISIRCOP))
+ reply(textclient, user, "NS_A_IS_IRCOP", nick);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] nick|*auth|*!*@mask
+* argv[1-*] reason
+*/
+static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup);
+static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mas, char *reason);
+
+struct neonserv_cmd_addban_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *mask;
+ char *reason;
+};
+
+CMD_BIND(neonserv_cmd_addban) {
+ struct neonserv_cmd_addban_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->mask = strdup(argv[0]);
+ if(argc > 1) {
+ cache->reason = strdup(merge_argv(argv, 1, argc));
+ } else
+ cache->reason = NULL;
+ get_userlist(chan, neonserv_cmd_addban_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup) {
+ struct neonserv_cmd_addban_cache *cache = data;
+ neonserv_cmd_addban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, (cache->reason ? cache->reason : "Bye."));
+ free(cache->mask);
+ if(cache->reason)
+ free(cache->reason);
+ free(cache);
+}
+
+static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, char *reason) {
+ int match_count = 0;
+ char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ mask = make_banmask(mask, hostmask_buffer);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(mask, usermask)) {
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ return;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ return;
+ }
+ match_count++;
+ if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
+ reply(textclient, user, "NS_LAME_MASK", mask);
+ return;
+ }
+ }
+ }
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ //check if the provided mask is already banned by another ban
+ char *ban = getBanAffectingMask(chan, mask);
+ if(ban != NULL) {
+ reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name);
+ return;
+ }
+ //check if the provided mask affects any existing bans
+ printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
+ res = mysql_use();
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(!match(mask, row[0])) {
+ //remove the ban
+ printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]);
+ }
+ }
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ int userid;
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL)
+ userid = atoi(row[0]);
+ else
+ return;
+ //add the ban
+ printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%d', '%s')", chan->channel_id, escape_string(mask), userid, escape_string(reason));
+ putsock(client, "MODE %s +b %s", chan->name, mask);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(mask, usermask)) {
+ putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
+ }
+ }
+ reply(textclient, user, "NS_ADDBAN_DONE", mask, chan->name, match_count);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] nick|*auth|*!*@mask
+* argv[1] time
+* argv[2-*] reason
+*/
+static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup);
+static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason);
+
+struct neonserv_cmd_addtimeban_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *mask;
+ int duration;
+ char *reason;
+};
+
+CMD_BIND(neonserv_cmd_addtimeban) {
+ int duration = strToTime(user, argv[1]);
+ if(duration < 30) {
+ reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30);
+ return;
+ }
+ struct neonserv_cmd_addtimeban_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->mask = strdup(argv[0]);
+ cache->duration = duration;
+ if(argc > 2) {
+ cache->reason = strdup(merge_argv(argv, 2, argc));
+ } else
+ cache->reason = NULL;
+ get_userlist(chan, neonserv_cmd_addtimeban_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup) {
+ struct neonserv_cmd_addtimeban_cache *cache = data;
+ neonserv_cmd_addtimeban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, cache->duration, (cache->reason ? cache->reason : "Bye."));
+ free(cache->mask);
+ if(cache->reason)
+ free(cache->reason);
+ free(cache);
+}
+
+static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason) {
+ int match_count = 0;
+ char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ mask = make_banmask(mask, hostmask_buffer);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(mask, usermask)) {
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ return;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ return;
+ }
+ match_count++;
+ if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
+ reply(textclient, user, "NS_LAME_MASK", mask);
+ return;
+ }
+ }
+ }
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ //check if the provided mask is already banned by another ban
+ char *ban = getBanAffectingMask(chan, mask);
+ if(ban != NULL) {
+ reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name);
+ return;
+ }
+ //check if the provided mask affects any existing bans
+ printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
+ res = mysql_use();
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(!match(mask, row[0])) {
+ //remove the ban
+ printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]);
+ }
+ }
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ int userid;
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL)
+ userid = atoi(row[0]);
+ else
+ return;
+ //add the ban
+ printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(mask), (unsigned long) (time(0) + duration), userid, escape_string(reason));
+ int banid = (int) mysql_insert_id(mysql_conn);
+ putsock(client, "MODE %s +b %s", chan->name, mask);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(mask, usermask)) {
+ putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
+ }
+ }
+ char nameBuf[MAXLEN];
+ char banidBuf[20];
+ sprintf(nameBuf, "ban_%d", banid);
+ sprintf(banidBuf, "%d", banid);
+ timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
+ reply(textclient, user, "NS_TIMEBAN_DONE", mask, chan->name, timeToStr(user, duration, 2, nameBuf), match_count);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+* argv[1] - chan access
+*/
+static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup);
+static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup);
+static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int access);
+
+struct neonserv_cmd_adduser_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ int access;
+ char *nick;
+};
+
+CMD_BIND(neonserv_cmd_adduser) {
+ int caccess;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ caccess = atoi(argv[1]);
+ if(caccess <= 0 || caccess > 500) {
+ reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
+ return;
+ }
+ if(caccess >= getChannelAccess(user, chan, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_ACCESS_OUTRANKED");
+ return;
+ }
+ }
+ //check own access
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0]));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, event, argv[0], row[0], caccess);
+ } else {
+ //we need to create a new user...
+ //but first lookup the auth to check if it really exists
+ struct neonserv_cmd_adduser_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->access = caccess;
+ cache->nick = strdup(argv[0]);
+ lookup_authname(argv[0], neonserv_cmd_adduser_auth_lookup, cache);
+ }
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, caccess);
+ } else {
+ struct neonserv_cmd_adduser_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->access = caccess;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_adduser_nick_lookup, cache);
+ }
+ }
+}
+
+static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup) {
+ struct neonserv_cmd_adduser_cache *cache = data;
+ if(!exists) {
+ //AUTH_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick);
+ } else
+ neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->nick, auth, cache->access);
+ free(cache->nick);
+ free(cache);
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup) {
+ struct neonserv_cmd_adduser_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->access);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is already added
+ printf_mysql_query("SELECT `chanuser_access` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ reply(textclient, user, "NS_ADDUSER_ALREADY_ADDED", nick, chan->name, atoi(row[0]));
+ return;
+ }
+ } else {
+ printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth));
+ userid = (int) mysql_insert_id(mysql_conn);
+ }
+ printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chan->channel_id, userid, caccess);
+ reply(textclient, user, "NS_ADDUSER_DONE", nick, chan->name, caccess);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nick[,*auth[,*!*@mask[...]]]
+*/
+static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup);
+static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *masks);
+
+struct neonserv_cmd_ban_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *masks;
+};
+
+CMD_BIND(neonserv_cmd_ban) {
+ struct neonserv_cmd_ban_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->masks = strdup(merge_argv_char(argv, 0, argc, ','));
+ get_userlist_with_invisible(chan, neonserv_cmd_ban_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup) {
+ struct neonserv_cmd_ban_cache *cache = data;
+ neonserv_cmd_ban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->masks);
+ free(cache->masks);
+ free(cache);
+}
+
+static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *masks) {
+ int done_masks = 0, provided_masks = 0, skip, match_count, total_match;
+ char *mask, *nextmask;
+ char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ nextmask = masks;
+ while((mask = nextmask)) {
+ nextmask = strstr(mask, ",");
+ if(nextmask) {
+ *nextmask = '\0';
+ nextmask++;
+ }
+ provided_masks++;
+ skip = 0;
+ match_count = 0;
+ mask = make_banmask(mask, hostmask_buffer);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(mask, usermask)) {
+ cuser->flags |= USERFLAG_SCRIPTFLAG1; //we mark the user as 'matching'
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ skip = 1;
+ break;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ skip = 1;
+ break;
+ }
+ match_count++;
+ if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
+ skip = 1;
+ reply(textclient, user, "NS_LAME_MASK", mask);
+ break;
+ }
+ }
+ }
+ if(!skip) {
+ done_masks++;
+ modeBufferBan(modeBuf, mask);
+ }
+ }
+ total_match = 0; // count all users marked as 'matching'
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ if(cuser->flags & USERFLAG_SCRIPTFLAG1) {
+ cuser->flags &= ~USERFLAG_SCRIPTFLAG1;
+ total_match++;
+ }
+ }
+ freeModeBuffer(modeBuf);
+ if(done_masks == provided_masks)
+ reply(getTextBot(), user, "NS_BAN_DONE", done_masks, chan->name, total_match);
+ else
+ reply(getTextBot(), user, "NS_BAN_FAIL", client->user->nick);
+ if(done_masks)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] (optional) mask
+*/
+CMD_BIND(neonserv_cmd_bans) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ //ban list
+ int i, with_expire = 0, cindex = 0;
+ char triggered_str[MAXLEN], expires_str[MAXLEN];
+ struct Table *table;
+ printf_mysql_query("SELECT `ban_mask`, `user_user`, `ban_triggered`, `ban_timeout`, `ban_reason` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d'", chan->channel_id);
+ res = mysql_use();
+ table = table_init(5, mysql_num_rows(res) + 1, 0);
+ char *content[5];
+ //add a NULL row (we add values later)
+ content[0] = NULL;
+ content[1] = NULL;
+ content[2] = NULL;
+ content[3] = NULL;
+ content[4] = NULL;
+ table_add(table, content);
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(argc > 0 && match(argv[0], row[0])) continue;
+ content[0] = row[0];
+ content[1] = row[1];
+ content[2] = (strcmp(row[2], "0") ? timeToStr(user, (time(0) - atoi(row[2])), 2, triggered_str) : get_language_string(user, "NS_USERS_SEEN_NEVER"));
+ if(strcmp(row[3], "0")) {
+ if(!with_expire) {
+ //we're using expire times now...
+ for(i = 0; i < cindex; i++)
+ table_change_field(table, i+1, 3, get_language_string(user, "NS_USERS_SEEN_NEVER"));
+ with_expire = 1;
+ }
+ content[3] = timeToStr(user, (atoi(row[3]) - time(0)), 2, expires_str);
+ } else
+ content[3] = (with_expire ? get_language_string(user, "NS_USERS_SEEN_NEVER") : NULL);
+ content[4] = row[4];
+ cindex++;
+ table_add(table, content);
+ }
+ //now we add the table header
+ content[0] = get_language_string(user, "NS_BANS_HEADER_MASK");
+ content[1] = get_language_string(user, "NS_BANS_HEADER_SETBY");
+ content[2] = get_language_string(user, "NS_BANS_HEADER_TRIGGERED");
+ content[3] = (with_expire ? get_language_string(user, "NS_BANS_HEADER_EXPIRES") : NULL);
+ content[4] = get_language_string(user, "NS_BANS_HEADER_REASON");
+ table_change(table, 0, content);
+ char **table_lines = table_end(table);
+ for(i = 0; i < table->entrys; i++) {
+ reply(getTextBot(), user, table_lines[i]);
+ }
+ if(!cindex)
+ reply(getTextBot(), user, "NS_TABLE_NONE");
+ reply(getTextBot(), user, "NS_TABLE_COUNT", cindex);
+ table_free(table);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] command name
+* argv[1] command function
+* argv[2-*] parameters (optional)
+*/
+
+CMD_BIND(neonserv_cmd_bind) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0]));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ reply(getTextBot(), user, "NS_BIND_ALREADY", argv[0], row[0]);
+ return;
+ }
+ char *params;
+ if(argc > 2)
+ params = merge_argv(argv, 2, argc);
+ else
+ params = "";
+ struct cmd_function *function = find_cmd_function(client->botid, argv[1]);
+ if(!function) {
+ reply(getTextBot(), user, "NS_BIND_UNKNOWN", argv[1]);
+ return;
+ }
+ bind_cmd_to_function(client->botid, argv[0], function);
+ if(*params)
+ bind_set_parameters(client->botid, argv[0], params);
+ printf_mysql_query("INSERT INTO `bot_binds` (`botclass`, `command`, `function`, `parameters`) VALUES ('%d', '%s', '%s', '%s')", client->botid, escape_string(argv[0]), escape_string(function->name), params);
+ reply(getTextBot(), user, "NS_BIND_DONE", argv[0], function->name);
+ logEvent(event);
+}
--- /dev/null
+
+#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 == ' ');
+ 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) {
+ caccess = atoi(tokens[0]);
+ username = tokens[1];
+ } 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(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(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);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+* argv[1] - access
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup);
+static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess);
+
+struct neonserv_cmd_clvl_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+ int access;
+};
+
+CMD_BIND(neonserv_cmd_clvl) {
+ int caccess;
+ caccess = atoi(argv[1]);
+ if(caccess <= 0 || caccess > 500) {
+ reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
+ return;
+ }
+ if(caccess >= getChannelAccess(user, chan, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_ACCESS_OUTRANKED");
+ return;
+ }
+ }
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, event, argv[0], argv[0], caccess);
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, caccess);
+ } else {
+ struct neonserv_cmd_clvl_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[0]);
+ cache->access = caccess;
+ get_userauth(cuser, neonserv_cmd_clvl_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup) {
+ struct neonserv_cmd_clvl_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_clvl_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->access);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is already added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` 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]) >= getChannelAccess(user, chan, 1)) {
+ reply(textclient, user, "NS_USER_OUTRANKED", nick);
+ return;
+ }
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d' WHERE `chanuser_id` = '%s'", caccess, row[1]);
+ reply(textclient, user, "NS_CLVL_DONE", nick, caccess, chan->name);
+ logEvent(event);
+ return;
+ }
+ }
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-1] command
+*/
+static int neonserv_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan);
+static int neonserv_cmd_command_operaccess(struct cmd_binding *cbind);
+
+CMD_BIND(neonserv_cmd_command) {
+ char *ident;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ struct cmd_binding *cbind = find_cmd_binding(client->botid, argv[0]);
+ if (!cbind) {
+ reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]);
+ return;
+ }
+ ident = argv[0];
+ reply(getTextBot(), user, "NS_COMMAND_BINDING", cbind->cmd, cbind->func->name, (cbind->parameters ? cbind->parameters : ""));
+ if(chan)
+ reply(getTextBot(), user, "NS_COMMAND_ACCESS", neonserv_cmd_command_chanaccess(cbind, chan), neonserv_cmd_command_operaccess(cbind));
+ printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ char *lang;
+ if ((row = mysql_fetch_row(res)) != NULL)
+ lang = row[0];
+ else
+ lang = "en";
+ printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ if(stricmp(lang, "en")) {
+ printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident));
+ res = mysql_use();
+ }
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(cbind->func->name));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ if(stricmp(lang, "en")) {
+ printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(cbind->func->name));
+ res = mysql_use();
+ }
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ return;
+ }
+ }
+ }
+ }
+ char sendBuf[MAXLEN];
+ int sendBufPos = 0;
+ int i;
+ for(i = 0; i < strlen(row[0]); i++) {
+ switch(row[0][i]) {
+ case '\n':
+ if(sendBufPos) {
+ sendBuf[sendBufPos] = '\0';
+ reply(getTextBot(), user, "%s", sendBuf);
+ sendBufPos = 0;
+ }
+ break;
+ case '$':
+ switch(row[0][i+1]) {
+ case 'b':
+ sendBuf[sendBufPos++] = '\002';
+ i++;
+ break;
+ case 'k':
+ sendBuf[sendBufPos++] = '\003';
+ i++;
+ break;
+ case 'u':
+ sendBuf[sendBufPos++] = '\031';
+ i++;
+ break;
+ case 'C':
+ case 'S':
+ sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick);
+ i++;
+ break;
+ default:
+ sendBuf[sendBufPos++] = '$';
+ break;
+ }
+ break;
+ default:
+ sendBuf[sendBufPos++] = row[0][i];
+ break;
+ }
+ }
+ if(sendBufPos) {
+ sendBuf[sendBufPos] = '\0';
+ reply(getTextBot(), user, "%s", sendBuf);
+ sendBufPos = 0;
+ }
+}
+
+static int neonserv_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan) {
+ char access_list[256];
+ int access_pos = 0;
+ int access_count = 0;
+ int minaccess = 0;
+ char *str_a, *str_b = cbind->func->channel_access, *str_c;
+ if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS)
+ str_b = cbind->channel_access;
+ access_list[0] = '\0';
+ if(str_b) {
+ str_c = strdup(str_b);
+ str_b = str_c;
+ while((str_a = str_b)) {
+ str_b = strstr(str_a, ",");
+ if(str_b) {
+ *str_b = '\0';
+ str_b++;
+ }
+ if(*str_a == '#') {
+ str_a++;
+ access_pos += sprintf(access_list+access_pos, (access_pos ? ", `%s`" : "`%s`"), str_a);
+ access_count++;
+ } else {
+ if(atoi(str_a) > minaccess)
+ minaccess = atoi(str_a);
+ }
+ }
+ free(str_c);
+ }
+ if(access_count) {
+ MYSQL_RES *res;
+ MYSQL_ROW row, defaults = NULL;
+ printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ int i, caccess;
+ for(i = 0; i < access_count; i++) {
+ if(!row[i] && !defaults) {
+ printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list);
+ defaults = mysql_fetch_row(mysql_use());
+ }
+ caccess = (row[i] ? atoi(row[i]) : atoi(defaults[i]));
+ if(caccess > minaccess)
+ minaccess = caccess;
+ }
+ }
+ }
+ return minaccess;
+}
+
+static int neonserv_cmd_command_operaccess(struct cmd_binding *cbind) {
+ return ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - channel
+*/
+CMD_BIND(neonserv_cmd_csuspend) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char *channel = argv[0];
+ if(!is_valid_chan(channel)) {
+ reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
+ return;
+ }
+ int chanid;
+ printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chanid = atoi(row[0]);
+ } else {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ if(!strcmp(row[2], "1")) {
+ reply(getTextBot(), user, "NS_CSUSPEND_ALREADY", channel);
+ return;
+ }
+ int botid = atoi(row[0]);
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == botid)
+ break;
+ }
+ if(bot) {
+ putsock(bot, "PART %s :Channel suspended.", channel);
+ }
+ printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '1' WHERE `id` = '%s'", row[1]);
+ reply(getTextBot(), user, "NS_CSUSPEND_DONE", channel);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - channel
+*/
+CMD_BIND(neonserv_cmd_cunsuspend) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char *channel = argv[0];
+ if(!is_valid_chan(channel)) {
+ reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
+ return;
+ }
+ int chanid;
+ printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chanid = atoi(row[0]);
+ } else {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ if(!strcmp(row[2], "0")) {
+ reply(getTextBot(), user, "NS_CUNSUSPEND_NOT", channel);
+ return;
+ }
+ int botid = atoi(row[0]);
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == botid)
+ break;
+ }
+ if(bot) {
+ putsock(bot, "JOIN %s", channel);
+ }
+ printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '0' WHERE `id` = '%s'", row[1]);
+ reply(getTextBot(), user, "NS_CUNSUSPEND_DONE", channel);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] nick|*auth|*!*@mask
+*/
+
+CMD_BIND(neonserv_cmd_delban) {
+ char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
+ char *mask = make_banmask(argv[0], hostmask_buffer);
+ int matching_bans = 0;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ //check if the provided mask is already banned by another ban
+ char *ban = getBanAffectingMask(chan, mask);
+ if(ban != NULL) {
+ reply(getTextBot(), user, "NS_DELBAN_BANNED_BY", mask, ban);
+ return;
+ }
+ //check if the provided mask affects any existing bans
+ char nameBuf[20];
+ printf_mysql_query("SELECT `ban_mask`, `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id);
+ res = mysql_use();
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(!match(mask, row[0])) {
+ //remove the ban
+ if(strcmp(row[2], "0")) {
+ sprintf(nameBuf, "ban_%s", row[1]);
+ timeq_del_name(nameBuf);
+ }
+ printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]);
+ matching_bans++;
+ }
+ }
+ if(matching_bans) {
+ putsock(client, "MODE %s -b %s", chan->name, mask);
+ reply(getTextBot(), user, "NS_DELBAN_DONE", mask, chan->name);
+ logEvent(event);
+ } else
+ reply(getTextBot(), user, "NS_DELBAN_FAIL", mask);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - key
+*/
+
+CMD_BIND(neonserv_cmd_delme) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ //check key
+ int seed = 0;
+ char *tmp;
+ static char unregkey[16];
+ 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));
+ sprintf(unregkey, "%08x", seed);
+ if(argc < 1 || strcmp(argv[0], unregkey)) {
+ reply(getTextBot(), user, "NS_DELME_KEY", unregkey);
+ return;
+ } else {
+ //delete
+ printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]);
+ reply(getTextBot(), user, "NS_DELME_DONE", atoi(row[0]), chan->name);
+ logEvent(event);
+ return;
+ }
+ }
+ }
+ reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup);
+static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
+
+struct neonserv_cmd_deluser_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+};
+
+CMD_BIND(neonserv_cmd_deluser) {
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
+ } else {
+ struct neonserv_cmd_deluser_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_deluser_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup) {
+ struct neonserv_cmd_deluser_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_deluser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is already added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(textclient, user, "NS_USER_OUTRANKED", nick);
+ return;
+ }
+ }
+ //delete
+ printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]);
+ reply(textclient, user, "NS_DELUSER_DONE", nick, atoi(row[0]), chan->name);
+ logEvent(event);
+ return;
+ }
+ }
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nicks
+*/
+static USERLIST_CALLBACK(neonserv_cmd_deop_userlist_lookup);
+static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc);
+
+struct neonserv_cmd_deop_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char **argv;
+ int argc;
+};
+
+CMD_BIND(neonserv_cmd_deop) {
+ struct neonserv_cmd_deop_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->argv = calloc(argc, sizeof(char*));
+ int i;
+ for(i = 0; i < argc; i++) {
+ cache->argv[i] = strdup(argv[i]);
+ }
+ cache->argc = argc;
+ get_userlist(chan, neonserv_cmd_deop_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_deop_userlist_lookup) {
+ struct neonserv_cmd_deop_cache *cache = data;
+ neonserv_cmd_deop_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->argv, cache->argc);
+ int i;
+ for(i = 0; i < cache->argc; i++) {
+ free(cache->argv[i]);
+ }
+ free(cache);
+}
+
+static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) {
+ int i, done_users = 0;
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ for(i = 0; i < argc; i++) {
+ cuser = searchUserByNick(argv[i]);
+ if(!cuser) continue;
+ chanuser = getChanUser(cuser, chan);
+ if(!chanuser) continue;
+ if(isNetworkService(cuser)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
+ continue;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ continue;
+ }
+ done_users++;
+ if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue;
+ modeBufferDeop(modeBuf, argv[i]);
+ }
+ freeModeBuffer(modeBuf);
+ if(done_users == argc)
+ reply(textclient, user, "NS_DEOP_DONE", chan->name);
+ else
+ reply(textclient, user, "NS_DEOP_FAIL", client->user->nick);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] (optional) nick mask
+*/
+static USERLIST_CALLBACK(neonserv_cmd_deopall_userlist_lookup);
+static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc);
+
+struct neonserv_cmd_deopall_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char **argv;
+ int argc;
+};
+
+CMD_BIND(neonserv_cmd_deopall) {
+ struct neonserv_cmd_deopall_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->argv = calloc(argc, sizeof(char*));
+ int i;
+ for(i = 0; i < argc; i++) {
+ cache->argv[i] = strdup(argv[i]);
+ }
+ cache->argc = argc;
+ get_userlist(chan, neonserv_cmd_deopall_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_deopall_userlist_lookup) {
+ struct neonserv_cmd_deopall_cache *cache = data;
+ neonserv_cmd_deopall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->argv, cache->argc);
+ int i;
+ for(i = 0; i < cache->argc; i++) {
+ free(cache->argv[i]);
+ }
+ free(cache);
+}
+
+static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) {
+ int issuer_access, victim_access, done_users = 0;
+ char *nickmask = NULL;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ if(argc > 0)
+ nickmask = argv[0];
+ modeBuf = initModeBuffer(client, chan);
+ issuer_access = getChannelAccess(user, chan, 0);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(nickmask && match(nickmask, chanuser->user->nick)) continue;
+ victim_access = getChannelAccess(user, chan, 0);
+ if(victim_access >= issuer_access) continue;
+ if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue;
+ modeBufferDeop(modeBuf, chanuser->user->nick);
+ done_users++;
+ }
+ freeModeBuffer(modeBuf);
+ reply(getTextBot(), user, "NS_DEOPALL_DONE", done_users, chan->name);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nicks
+*/
+
+CMD_BIND(neonserv_cmd_devoice) {
+ int i, done_users = 0;
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ for(i = 0; i < argc; i++) {
+ cuser = searchUserByNick(argv[i]);
+ if(!cuser) continue;
+ chanuser = getChanUser(cuser, chan);
+ if(!chanuser) continue;
+ if(isUserProtected(chan, cuser, user)) {
+ reply(getTextBot(), user, "NS_USER_PROTECTED", cuser->nick);
+ continue;
+ }
+ done_users++;
+ if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue;
+ modeBufferDevoice(modeBuf, argv[i]);
+ }
+ freeModeBuffer(modeBuf);
+ if(done_users == argc)
+ reply(getTextBot(), user, "NS_DEVOICE_DONE", chan->name);
+ else
+ reply(getTextBot(), user, "NS_DEVOICE_FAIL", client->user->nick);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] (optional) nick mask
+*/
+
+CMD_BIND(neonserv_cmd_devoiceall) {
+ int issuer_access, victim_access, done_users = 0;
+ char *nickmask = NULL;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ check_mysql();
+ if(!checkChannelAccess(user, chan, "channel_canvoice", 1, 0)) {
+ reply(getTextBot(), user, "NS_ACCESS_DENIED");
+ return;
+ }
+ if(argc > 0)
+ nickmask = argv[0];
+ modeBuf = initModeBuffer(client, chan);
+ issuer_access = getChannelAccess(user, chan, 0);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(nickmask && match(nickmask, chanuser->user->nick)) continue;
+ victim_access = getChannelAccess(user, chan, 0);
+ if(victim_access >= issuer_access) continue;
+ if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue;
+ modeBufferDevoice(modeBuf, chanuser->user->nick);
+ done_users++;
+ }
+ freeModeBuffer(modeBuf);
+ reply(getTextBot(), user, "NS_DEVOICEALL_DONE", done_users, chan->name);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no arguments
+*/
+
+CMD_BIND(neonserv_cmd_down) {
+ struct ChanUser *chanuser = getChanUser(user, chan);
+ if(!chanuser) {
+ reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name);
+ return;
+ }
+ if((chanuser->flags & CHANUSERFLAG_OPPED)) {
+ putsock(client, "MODE %s -ov %s %s", chan->name, user->nick, user->nick);
+ logEvent(event);
+ } else if((chanuser->flags & CHANUSERFLAG_VOICED)) {
+ putsock(client, "MODE %s -v %s", chan->name, user->nick);
+ logEvent(event);
+ } else
+ reply(getTextBot(), user, "NS_DOWN_ALREADY", chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no arguments
+*/
+
+CMD_BIND(neonserv_cmd_downall) {
+ struct ChanUser *chanuser;
+ for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) {
+ chan = chanuser->chan;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) continue;
+ printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
+ if (mysql_fetch_row(mysql_use()) == NULL) continue;
+ int done = 0;
+ if((chanuser->flags & CHANUSERFLAG_OPPED)) {
+ putsock(client, "MODE %s -o %s", chan->name, user->nick);
+ done = 1;
+ }
+ if((chanuser->flags & CHANUSERFLAG_VOICED)) {
+ putsock(client, "MODE %s -v %s", chan->name, user->nick);
+ done = 1;
+ }
+ if(done) {
+ //event hack
+ event->chan = chan;
+ logEvent(event);
+ }
+ }
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] target
+* argv[1-*] message
+*/
+
+CMD_BIND(neonserv_cmd_emote) {
+ char *message = merge_argv(argv, 1, argc);
+ putsock(client, "PRIVMSG %s :\001ACTION %s\001", argv[0], message);
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] time
+* argv[1-*] match
+*/
+
+CMD_BIND(neonserv_cmd_events) {
+ char *str_match;
+ int duration = (argc ? strToTime(user, argv[0]) : 0);
+ if(argc > (duration ? 1 : 0))
+ str_match = merge_argv(argv, (duration ? 1 : 0), argc);
+ else
+ str_match = "";
+ if(!duration) duration = (60*60*24);
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `time`, `auth`, `nick`, `command` FROM `events` WHERE `cid` = '%d' AND `time` > '%lu' ORDER BY `time` ASC", chan->channel_id, ((unsigned long) time(0) - duration));
+ res = mysql_use();
+ int skip = mysql_num_rows(res) - 100;
+ int count = 0;
+ char timeBuf[50];
+ struct tm *timeinfo;
+ time_t event_time;
+ if(skip < 0) skip = 0;
+ reply(getTextBot(), user, "NS_EVENTS_HEADER");
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(skip) {
+ skip--;
+ continue;
+ }
+ if(*str_match && match(str_match, row[3])) continue;
+ count++;
+ event_time = (time_t) atol(row[0]);
+ timeinfo = localtime(&event_time);
+ strftime(timeBuf, 80, "%X %x", timeinfo);
+ reply(getTextBot(), user, "[%s] [%s:%s]: %s", timeBuf, row[2], row[1], row[3]);
+ }
+ reply(getTextBot(), user, "NS_TABLE_COUNT", count);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+* argv[1] - key
+*/
+
+#define GIVEOWNER_TIMEOUT 86400 /* 60*60*24 = 86400 */
+
+static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup);
+static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, char *key);
+
+struct neonserv_cmd_giveowner_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+ char *key;
+};
+
+CMD_BIND(neonserv_cmd_giveowner) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `channel_lastgiveowner` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return;
+ if(strcmp(row[0], "0") && (atoi(row[0]) + GIVEOWNER_TIMEOUT) > time(0)) {
+ char timeBuf[MAXLEN];
+ reply(getTextBot(), user, "NS_GIVEOWNER_TIMEOUT", timeToStr(user, (GIVEOWNER_TIMEOUT - (time(0) - atoi(row[0]))), 2, timeBuf), chan->name);
+ return;
+ }
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, event, argv[0], argv[0], (argc != 1 ? argv[1] : NULL));
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, (argc != 1 ? argv[1] : NULL));
+ } else {
+ struct neonserv_cmd_giveowner_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[0]);
+ cache->key = (argc != 1 ? strdup(argv[1]) : NULL);
+ get_userauth(cuser, neonserv_cmd_giveowner_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup) {
+ struct neonserv_cmd_giveowner_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_giveowner_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->key);
+ free(cache->nick);
+ if(cache->key)
+ free(cache->key);
+ free(cache);
+}
+
+static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, char *key) {
+ //we've got a valid auth now...
+ if(!stricmp(user->auth, auth)) {
+ reply(textclient, user, "NS_GIVEOWNER_SELF");
+ return;
+ }
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is already added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ int seed = 0;
+ char *tmp;
+ char giveownerkey[16];
+ 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));
+ sprintf(giveownerkey, "%08x", seed);
+ if(key && !stricmp(giveownerkey, key)) {
+ //give ownership
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '500' WHERE `chanuser_id` = '%s'", row[1]);
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '499' WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = (SELECT `user_id` FROM `users` WHERE `user_user` = '%s')", chan->channel_id, escape_string(user->auth));
+ printf_mysql_query("INSERT INTO `owner_history` (`owner_history_cid`, `owner_history_uid`, `owner_history_time`) VALUE ('%d', '%d', UNIX_TIMESTAMP())", chan->channel_id, userid);
+ reply(textclient, user, "NS_GIVEOWNER_DONE", chan->name, auth);
+ logEvent(event);
+ } else {
+ reply(textclient, user, "NS_GIVEOWNER_CONFIRM", auth, giveownerkey);
+ }
+ return;
+ }
+ }
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] (optional) on/off
+*/
+
+CMD_BIND(neonserv_cmd_god) {
+ if(argc > 0) {
+ if(!strcmp(argv[0], "0") || !stricmp(argv[0], "off") || !stricmp(argv[0], get_language_string(user, "NS_SET_OFF"))) {
+ if(isGodMode(user)) {
+ printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth));
+ user->flags &= ~USERFLAG_GOD_MODE;
+ }
+ reply(getTextBot(), user, "NS_GOD_OFF");
+ } else if(!strcmp(argv[0], "1") || !stricmp(argv[0], "on") || !stricmp(argv[0], get_language_string(user, "NS_SET_ON"))) {
+ if(!isGodMode(user)) {
+ printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth));
+ user->flags |= USERFLAG_GOD_MODE;
+ }
+ reply(getTextBot(), user, "NS_GOD_ON");
+ } else {
+ reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[0]);
+ return;
+ }
+ } else {
+ if(isGodMode(user)) {
+ printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth));
+ user->flags &= ~USERFLAG_GOD_MODE;
+ reply(getTextBot(), user, "NS_GOD_OFF");
+ } else {
+ printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth));
+ user->flags |= USERFLAG_GOD_MODE;
+ reply(getTextBot(), user, "NS_GOD_ON");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] index
+*/
+
+CMD_BIND(neonserv_cmd_help) {
+ char *ident;
+ if(argc)
+ ident = merge_argv(argv, 0, argc);
+ else
+ ident = "0";
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ char *lang;
+ if ((row = mysql_fetch_row(res)) != NULL)
+ lang = row[0];
+ else
+ lang = "en";
+ printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ if(stricmp(lang, "en")) {
+ printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident));
+ res = mysql_use();
+ }
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(getTextBot(), user, "NS_HELP_TOPIC");
+ return;
+ }
+ }
+ char sendBuf[MAXLEN];
+ int sendBufPos = 0;
+ int i;
+ for(i = 0; i < strlen(row[0]); i++) {
+ switch(row[0][i]) {
+ case '\n':
+ if(sendBufPos) {
+ sendBuf[sendBufPos] = '\0';
+ reply(getTextBot(), user, "%s", sendBuf);
+ sendBufPos = 0;
+ }
+ break;
+ case '$':
+ switch(row[0][i+1]) {
+ case 'b':
+ sendBuf[sendBufPos++] = '\002';
+ i++;
+ break;
+ case 'k':
+ sendBuf[sendBufPos++] = '\003';
+ i++;
+ break;
+ case 'u':
+ sendBuf[sendBufPos++] = '\031';
+ i++;
+ break;
+ case 'C':
+ case 'S':
+ sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick);
+ i++;
+ break;
+ default:
+ sendBuf[sendBufPos++] = '$';
+ break;
+ }
+ break;
+ default:
+ sendBuf[sendBufPos++] = row[0][i];
+ break;
+ }
+ }
+ if(sendBufPos) {
+ sendBuf[sendBufPos] = '\0';
+ reply(getTextBot(), user, "%s", sendBuf);
+ sendBufPos = 0;
+ }
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup);
+static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
+static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout);
+static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan);
+static int neonserv_cmd_invite_is_timeout(char *nick, char *chan);
+static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout);
+
+
+struct neonserv_cmd_invite_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+};
+
+struct neonserv_cmd_invite_timeout {
+ char *nick;
+ char *chan;
+
+ struct neonserv_cmd_invite_timeout *next;
+};
+
+static struct neonserv_cmd_invite_timeout *first_timeout = NULL, *last_timeout = NULL;
+
+CMD_BIND(neonserv_cmd_invite) {
+ if(neonserv_cmd_invite_is_timeout(argv[0], chan->name)) {
+ reply(getTextBot(), user, "NS_INVITE_TIMEOUT", argv[0], chan->name);
+ return;
+ }
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ } else if(getChanUser(cuser, chan)) {
+ reply(getTextBot(), user, "NS_INVITE_ON_CHAN", cuser->nick, chan->name);
+ /* BUG
+ This check does not work if the user is invisible (CHMODE +D/+d)
+ to fix this we'd need to request the full userlist...
+ this is really senseless to invite a simple user so we simply mark this bug as unsolvable.
+ */
+ return;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_invite_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
+ } else {
+ struct neonserv_cmd_invite_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_invite_nick_lookup, cache);
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup) {
+ struct neonserv_cmd_invite_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ } else
+ neonserv_cmd_invite_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, ((user->flags & USERFLAG_ISAUTHED) ? user->auth : NULL));
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
+ if(auth) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ //check if the user has set noinvite
+ printf_mysql_query("SELECT `id` FROM `noinvite` WHERE `uid` = '%s' AND `cid` = '%d'", row[0], chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ reply(textclient, user, "NS_INVITE_RESTRICTION", nick, chan->name);
+ return;
+ }
+ }
+ }
+ struct neonserv_cmd_invite_timeout *timeout = neonserv_cmd_invite_add_timeout(nick, chan->name);
+ timeq_add(INVITE_TIMEOUT, neonserv_cmd_invite_timeout_timeout, timeout);
+ putsock(client, "INVITE %s %s", nick, chan->name);
+ struct UserNode *tmpu = getUserByNick(nick);
+ if(!tmpu) {
+ tmpu = createTempUser(nick);
+ tmpu->flags |= USERFLAG_ISTMPUSER | (auth ? USERFLAG_ISAUTHED : 0);
+ if(auth)
+ strcpy(tmpu->auth, auth);
+ }
+ reply(textclient, tmpu, "NS_INVITE_DONE_USER", chan->name, user->nick, client->user->nick);
+ reply(textclient, user, "NS_INVITE_DONE", nick, chan->name);
+}
+
+static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout) {
+ struct neonserv_cmd_invite_timeout *entry = data;
+ neonserv_cmd_invite_del_timeout(entry);
+}
+
+static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan) {
+ struct neonserv_cmd_invite_timeout *entry = malloc(sizeof(*entry));
+ if (!entry) {
+ perror("malloc() failed");
+ return NULL;
+ }
+ entry->next = NULL;
+ entry->nick = strdup(nick);
+ entry->chan = strdup(chan);
+ if(last_timeout) {
+ last_timeout->next = entry;
+ last_timeout = entry;
+ } else {
+ last_timeout = entry;
+ first_timeout = entry;
+ }
+ return entry;
+}
+
+static int neonserv_cmd_invite_is_timeout(char *nick, char *chan) {
+ if(!first_timeout) return 0;
+ struct neonserv_cmd_invite_timeout *entry;
+ for(entry = first_timeout; entry; entry = entry->next) {
+ if(!stricmp(entry->nick, nick) && !stricmp(entry->chan, chan))
+ return 1;
+ }
+ return 0;
+}
+
+static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout) {
+ struct neonserv_cmd_invite_timeout *entry, *prev = NULL;
+ for(entry = first_timeout; entry; entry = entry->next) {
+ if(entry == timeout) {
+ if(prev)
+ prev->next = entry->next;
+ else
+ first_timeout = entry->next;
+ break;
+ } else
+ prev = entry;
+ }
+ if(last_timeout == timeout)
+ last_timeout = prev;
+ free(timeout->nick);
+ free(timeout->chan);
+ free(timeout);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no arguments
+*/
+
+CMD_BIND(neonserv_cmd_inviteme) {
+ if(getChanUser(user, chan)) {
+ reply(getTextBot(), user, "NS_INVITEME_ON_CHAN", chan->name);
+ /* BUG
+ This check does not work if the user is invisible (CHMODE +D/+d)
+ to fix this we'd need to request the full userlist...
+ this is really senseless to invite a simple user so we simply mark this bug as unsolvable.
+ */
+ return;
+ }
+ putsock(client, "INVITE %s %s", user->nick, chan->name);
+ reply(getTextBot(), user, "NS_INVITEME_DONE", chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] nick[,*auth[,*!*@mask[...]]]
+* argv[1-*] reason
+*/
+static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup);
+static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason);
+
+struct neonserv_cmd_kick_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *nicks;
+ char *reason;
+};
+
+CMD_BIND(neonserv_cmd_kick) {
+ struct neonserv_cmd_kick_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->nicks = strdup(argv[0]);
+ if(argc > 1) {
+ cache->reason = strdup(merge_argv(argv, 1, argc));
+ } else
+ cache->reason = NULL;
+ get_userlist_with_invisible(chan, neonserv_cmd_kick_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup) {
+ struct neonserv_cmd_kick_cache *cache = data;
+ neonserv_cmd_kick_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks, (cache->reason ? cache->reason : "Bye."));
+ free(cache->nicks);
+ if(cache->reason)
+ free(cache->reason);
+ free(cache);
+}
+
+static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason) {
+ int i, kicked_users = 0, provided_nicks = 0;
+ char *nick, *nextnick;
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ nextnick = nicks;
+ while((nick = nextnick)) {
+ nextnick = strstr(nick, ",");
+ if(nextnick) {
+ *nextnick = '\0';
+ nextnick++;
+ }
+ if(!*nick) continue;
+ if(is_ircmask(nick)) {
+ //KICK HOSTMASK
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ struct ChanUser *kick_chanuser[chan->usercount];
+ int kick_chanuser_pos = 0;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(nick, usermask)) {
+ provided_nicks++;
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ continue;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ continue;
+ }
+ kick_chanuser[kick_chanuser_pos++] = chanuser;
+ if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) {
+ kick_chanuser_pos = 0;
+ reply(textclient, user, "NS_LAME_MASK", nick);
+ break;
+ }
+ }
+ }
+ for(i = 0; i < kick_chanuser_pos; i++) {
+ kicked_users++;
+ putsock(client, "KICK %s %s :%s", chan->name, kick_chanuser[i]->user->nick, reason);
+ }
+ } else if(*nick == '*') {
+ //KICK AUTH
+ nick++;
+ cuser = NULL;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) {
+ provided_nicks++;
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ continue;
+ }
+ if(!cuser) {
+ //check if the user is protected
+ if(isUserProtected(chan, chanuser->user, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick);
+ break; //all other users are also protected...
+ }
+ cuser = chanuser->user;
+ }
+ kicked_users++;
+ putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
+ }
+ }
+ } else {
+ provided_nicks++;
+ cuser = NULL;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(!stricmp(chanuser->user->nick, nick)) {
+ cuser = chanuser->user;
+ }
+ }
+ if(!cuser) continue;
+ if(isNetworkService(cuser)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
+ continue;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ continue;
+ }
+ kicked_users++;
+ putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
+ }
+ }
+ if(kicked_users == provided_nicks)
+ reply(getTextBot(), user, "NS_KICK_DONE", kicked_users, chan->name);
+ else
+ reply(getTextBot(), user, "NS_KICK_FAIL", client->user->nick);
+ if(kicked_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] nick[,*auth[,*!*@mask[...]]]
+* argv[1-*] reason
+*/
+static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup);
+static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason);
+
+struct neonserv_cmd_kickban_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *nicks;
+ char *reason;
+};
+
+CMD_BIND(neonserv_cmd_kickban) {
+ struct neonserv_cmd_kickban_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->nicks = strdup(argv[0]);
+ if(argc > 1) {
+ cache->reason = strdup(merge_argv(argv, 1, argc));
+ } else
+ cache->reason = NULL;
+ get_userlist_with_invisible(chan, neonserv_cmd_kickban_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup) {
+ struct neonserv_cmd_kickban_cache *cache = data;
+ neonserv_cmd_kickban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks, (cache->reason ? cache->reason : "Bye."));
+ free(cache->nicks);
+ if(cache->reason)
+ free(cache->reason);
+ free(cache);
+}
+
+static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason) {
+ int i, kicked_users = 0, provided_nicks = 0;
+ char *nick, *nextnick;
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ nextnick = nicks;
+ while((nick = nextnick)) {
+ nextnick = strstr(nick, ",");
+ if(nextnick) {
+ *nextnick = '\0';
+ nextnick++;
+ }
+ if(!*nick) continue;
+ if(is_ircmask(nick)) {
+ //KICK HOSTMASK
+ struct ChanUser *kickban_chanuser[chan->usercount];
+ int kick_chanuser_pos = 0;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(nick, usermask)) {
+ provided_nicks++;
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ continue;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ continue;
+ }
+ kickban_chanuser[kick_chanuser_pos++] = chanuser;
+ if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) {
+ kick_chanuser_pos = 0;
+ reply(textclient, user, "NS_LAME_MASK", nick);
+ break;
+ }
+ }
+ }
+ for(i = 0; i < kick_chanuser_pos; i++) {
+ if(i == 0) {
+ putsock(client, "MODE %s +b %s", chan->name, nick);
+ }
+ kicked_users++;
+ putsock(client, "KICK %s %s :%s", chan->name, kickban_chanuser[i]->user->nick, reason);
+ }
+ } else if(*nick == '*') {
+ //KICK AUTH
+ nick++;
+ cuser = NULL;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) {
+ provided_nicks++;
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ continue;
+ }
+ if(!cuser) {
+ //check if the user is protected
+ if(isUserProtected(chan, chanuser->user, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick);
+ break; //all other users are also protected...
+ }
+ cuser = chanuser->user;
+ }
+ kicked_users++;
+ putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
+ putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
+ }
+ }
+ } else {
+ provided_nicks++;
+ cuser = searchUserByNick(nick);
+ if(!cuser) continue;
+ chanuser = getChanUser(cuser, chan);
+ if(!chanuser) continue;
+ if(isNetworkService(cuser)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
+ continue;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ continue;
+ }
+ kicked_users++;
+ putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
+ putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
+ }
+ }
+ if(kicked_users == provided_nicks)
+ reply(getTextBot(), user, "NS_KICKBAN_DONE", kicked_users, chan->name);
+ else
+ reply(getTextBot(), user, "NS_KICKBAN_FAIL", client->user->nick);
+ if(kicked_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] access (format: minaccess-maxaccess)
+* argv[1] pattern
+*/
+
+CMD_BIND(neonserv_cmd_mdeluser) {
+ if(!checkChannelAccess(user, chan, "channel_candel", 1, 0)) {
+ reply(getTextBot(), user, "NS_ACCESS_DENIED");
+ return;
+ }
+ int min_access, max_access;
+ char *seperator = strstr(argv[0], "-");
+ if(seperator) {
+ *seperator = '\0';
+ seperator++;
+ min_access = atoi(argv[0]);
+ max_access = atoi(seperator);
+ if(max_access > min_access) {
+ reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access);
+ return;
+ }
+ } else {
+ min_access = atoi(argv[0]);
+ max_access = min_access;
+ }
+ if(max_access >= getChannelAccess(user, chan, 1)) {
+ reply(getTextBot(), user, "NS_NO_ACCESS");
+ return;
+ }
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int del_count = 0;
+ printf_mysql_query("SELECT `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access);
+ res = mysql_use();
+ while((row = mysql_fetch_row(res)) != NULL) {
+ if(!match(argv[1], row[0])) {
+ del_count++;
+ printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]);
+ }
+ }
+ reply(getTextBot(), user, "NS_MDELUSER_DONE", del_count, argv[1], min_access, max_access, chan->name);
+ if(del_count)
+ logEvent(event);
+}
+
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - modes
+* argv[1-*] - parameters
+*/
+static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup);
+static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode);
+
+struct neonserv_cmd_mode_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *mode;
+};
+
+CMD_BIND(neonserv_cmd_mode) {
+ struct neonserv_cmd_mode_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->mode = strdup(merge_argv(argv, 0, argc));
+ get_userlist_with_invisible(chan, neonserv_cmd_mode_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup) {
+ struct neonserv_cmd_mode_cache *cache = data;
+ neonserv_cmd_mode_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mode);
+ free(cache->mode);
+ free(cache);
+}
+
+static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode) {
+ MYSQL_ROW row, defaults = NULL;
+ int i, arg, add = 1, skip = 0;
+ unsigned int modetype;
+ int db_canop, db_canvoice, db_canban, db_enfmodes;
+ struct ModeNode *modelock = createModeNode(NULL), *changemodes = createModeNode(NULL);
+ struct ModeBuffer *modeBuf;
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ modeBuf = initModeBuffer(client, chan);
+ printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ row = mysql_fetch_row(mysql_use());
+ if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL) {
+ printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
+ defaults = mysql_fetch_row(mysql_use());
+ }
+ db_canop = atoi((row[0] ? row[0] : defaults[0]));
+ db_canvoice = atoi((row[1] ? row[1] : defaults[1]));
+ db_canban = atoi((row[2] ? row[2] : defaults[2]));
+ db_enfmodes = atoi((row[3] ? row[3] : defaults[3]));
+ if(row[4])
+ parseModeString(modelock, row[4]);
+ else if(defaults[4])
+ parseModeString(modelock, defaults[4]);
+ int uaccess = getChannelAccess(user, chan, 0);
+ char *a, *b = mode;
+ char *argv[MAXNUMPARAMS];
+ char *carg;
+ char tmp[MAXLEN];
+ int argc = 0;
+ do {
+ a = strstr(b, " ");
+ if(a) *a = '\0';
+ argv[argc++] = b;
+ if(argc == MAXNUMPARAMS) break;
+ if(a) b = a+1;
+ } while(a);
+ arg = 0;
+ while(arg < argc) {
+ char *modeStr = argv[arg++];
+ for(i = 0; i < strlen(modeStr); i++) {
+ switch(modeStr[i]) {
+ case '+':
+ add = 1;
+ break;
+ case '-':
+ add = 0;
+ break;
+ case 'o':
+ case 'v':
+ if(arg == argc) {
+ reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
+ return;
+ }
+ carg = argv[arg++];
+ if(modeStr[i] == 'o') {
+ if(uaccess < db_canop) {
+ reply(textclient, user, "NS_MODE_ENFOPS", chan->name);
+ db_canop = -1;
+ break;
+ }
+ if(db_canop == -1) break;
+ } else {
+ if(uaccess < db_canvoice) {
+ reply(textclient, user, "NS_MODE_ENFVOICE", chan->name);
+ db_canvoice = -1;
+ break;
+ }
+ if(db_canvoice == -1) break;
+ }
+ cuser = searchUserByNick(carg);
+ if(!cuser) {
+ //check for an invisible user
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(!stricmp(chanuser->user->nick, carg)) {
+ cuser = chanuser->user;
+ break;
+ }
+ }
+ if(!cuser) break;
+ } else {
+ chanuser = getChanUser(cuser, chan);
+ if(!chanuser) break;
+ }
+ if(!(add ^ (chanuser->flags & (modeStr[i] == 'o' ? CHANUSERFLAG_OPPED : CHANUSERFLAG_VOICED)))) break;
+ if(!add) {
+ //check protection
+ if(modeStr[i] == 'o' && isNetworkService(cuser)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
+ break;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ break;
+ }
+ }
+ modeBufferSet(modeBuf, add, modeStr[i], carg);
+ break;
+ case 'b':
+ if(arg == argc) {
+ reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
+ return;
+ }
+ carg = argv[arg++];
+ if(uaccess < db_canban) {
+ reply(textclient, user, "NS_MODE_CANBAN", chan->name);
+ db_canban = -1;
+ break;
+ }
+ if(db_canban == -1) break;
+ char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3];
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ struct BanNode *ban;
+ int match_count = 0;
+ carg = make_banmask(carg, hostmask_buffer);
+ if(add) {
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ cuser = chanuser->user;
+ sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(!match(carg, usermask)) {
+ if(isNetworkService(chanuser->user)) {
+ reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
+ skip = 1;
+ break;
+ }
+ if(isUserProtected(chan, cuser, user)) {
+ reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
+ skip = 1;
+ break;
+ }
+ match_count++;
+ if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) {
+ skip = 1;
+ reply(textclient, user, "NS_LAME_MASK", carg);
+ break;
+ }
+ }
+ }
+ } else {
+ skip = 1;
+ for(ban = chan->bans; ban; ban = ban->next) {
+ if(!match(carg, ban->mask)) {
+ skip = 0;
+ break;
+ }
+ }
+ }
+ if(!skip) {
+ modeBufferSet(modeBuf, add, 'b', carg);
+ }
+ break;
+ default:
+ modetype = getModeType(modelock, modeStr[i]);
+ if(modetype == 0) {
+ reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
+ return;
+ }
+ if(isModeAffected(modelock, modeStr[i]) && add == !isModeSet(modelock, modeStr[i]) && uaccess < db_enfmodes) {
+ if(isGodMode(user))
+ event->flags |= CMDFLAG_OPLOG;
+ else {
+ getFullModeString(modelock, tmp);
+ reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
+ return;
+ }
+ }
+ if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) {
+ if(arg == argc) {
+ reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
+ return;
+ }
+ carg = argv[arg++];
+ if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
+ char *modelock_val = getModeValue(modelock, modeStr[i]);
+ if(stricmp(carg, modelock_val)) {
+ if(isGodMode(user))
+ event->flags |= CMDFLAG_OPLOG;
+ else {
+ getFullModeString(modelock, tmp);
+ reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
+ return;
+ }
+ }
+ }
+ if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
+ int *modelock_val = getModeValue(modelock, modeStr[i]);
+ if(atoi(carg) != *modelock_val) {
+ if(isGodMode(user))
+ event->flags |= CMDFLAG_OPLOG;
+ else {
+ getFullModeString(modelock, tmp);
+ reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
+ return;
+ }
+ }
+ }
+ } else
+ carg = NULL;
+ if((modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_D && isModeSet(chan->modes, modeStr[i]) == add)
+ break;
+ if(!isModeAffected(changemodes, modeStr[i])) {
+ if(!add && (modetype & CHANNEL_MODE_KEY)) {
+ if(isModeSet(chan->modes, modeStr[i])) {
+ char *current_val = getModeValue(chan->modes, modeStr[i]);
+ carg = current_val;
+ }
+ }
+ if(parseMode(changemodes, add, modeStr[i], carg)) {
+ if(carg) {
+ if(add && (modetype & CHANNEL_MODE_KEY) && isModeSet(chan->modes, modeStr[i])) {
+ char *current_val = getModeValue(chan->modes, modeStr[i]);
+ modeBufferSet(modeBuf, 0, modeStr[i], current_val);
+ flushModeBuffer(modeBuf);
+ }
+ if(!add && !isModeSet(chan->modes, modeStr[i])) break;
+ modeBufferSet(modeBuf, add, modeStr[i], carg);
+ } else {
+ modeBufferSimpleMode(modeBuf, add, modeStr[i]);
+ }
+ } else {
+ reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
+ return;
+ }
+ }
+ break;
+ }
+ }
+ }
+ getFullModeString(changemodes, tmp);
+ freeModeBuffer(modeBuf);
+ if(strcmp(tmp, "+"))
+ reply(textclient, user, "NS_MODE_DONE", tmp);
+
+ logEvent(event);
+ freeModeNode(modelock);
+ freeModeNode(changemodes);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - channel
+* argv[1] - new channel
+*/
+CMD_BIND(neonserv_cmd_move) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char *channel = argv[0];
+ char *new_channel = argv[1];
+ if(!is_valid_chan(new_channel)) {
+ reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", new_channel);
+ return;
+ }
+ if(!stricmp(channel, new_channel)) {
+ reply(getTextBot(), user, "NS_MOVE_SELF");
+ return;
+ }
+ printf_mysql_query("SELECT `channel_id` FROM `bot_channels` LEFT JOIN `channels` ON `channel_id` = `chanid` WHERE `channel_name` = '%s'", escape_string(new_channel));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ reply(getTextBot(), user, "NS_REGISTER_ALREADY", new_channel, client->user->nick);
+ return;
+ }
+ int chanid;
+ printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chanid = atoi(row[0]);
+ } else {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ if(!strcmp(row[2], "1")) {
+ reply(getTextBot(), user, "NS_MOVE_SUSPENDED");
+ return;
+ }
+ int botid = atoi(row[0]);
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == botid)
+ break;
+ }
+ if(bot) {
+ putsock(bot, "PART %s :Channel moved to %s.", channel, new_channel);
+ putsock(bot, "JOIN %s", new_channel);
+ }
+ printf_mysql_query("DELETE FROM `channels` WHERE `channel_name` = '%s'", escape_string(new_channel));
+ printf_mysql_query("UPDATE `channels` SET `channel_name` = '%s' WHERE `channel_id` = '%s'", escape_string(new_channel), row[1]);
+ struct ChanNode *channode = getChanByName(channel);
+ if(channode && channode->flags & CHANFLAG_REQUESTED_CHANINFO) {
+ channode->flags &= ~CHANFLAG_CHAN_REGISTERED;
+ channode->channel_id = 0;
+ }
+ channode = getChanByName(new_channel);
+ if(channode && channode->flags & CHANFLAG_REQUESTED_CHANINFO) {
+ channode->flags |= CHANFLAG_CHAN_REGISTERED;
+ channode->channel_id = atoi(row[1]);
+ }
+ reply(getTextBot(), user, "NS_MOVE_DONE", channel, new_channel);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup);
+static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch);
+
+struct neonserv_cmd_myaccess_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ char *nick;
+ char *chanmatch;
+};
+
+CMD_BIND(neonserv_cmd_myaccess) {
+ char *chanmatch = NULL;
+ if(argc == 0 || argv[0][0] == '#') {
+ if(argc != 0) {
+ chanmatch = argv[0];
+ }
+ if(!(user->flags & USERFLAG_ISAUTHED)) {
+ struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->nick = strdup(argv[0]);
+ cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL);
+ get_userauth(user, neonserv_cmd_myaccess_nick_lookup, cache);
+ } else
+ neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, user->nick, user->auth, chanmatch);
+ }
+ else if(argv[0][0] == '*') {
+ //we've got an auth
+ if(argc > 1 && argv[1][0] == '#') {
+ chanmatch = argv[1];
+ }
+ argv[0]++;
+ neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, NULL, argv[0], chanmatch);
+ } else {
+ if(argc > 1 && argv[1][0] == '#') {
+ chanmatch = argv[1];
+ }
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, chanmatch);
+ } else {
+ struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->nick = strdup(argv[0]);
+ cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL);
+ get_userauth(cuser, neonserv_cmd_myaccess_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup) {
+ struct neonserv_cmd_myaccess_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ if(!strcmp(cache->nick, cache->user->nick))
+ reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH");
+ else
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_myaccess_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->chanmatch);
+ if(cache->chanmatch)
+ free(cache->chanmatch);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch) {
+ //we've got a valid auth now...
+ MYSQL_RES *res, *default_res;
+ MYSQL_ROW user_row, chanuser_row, default_chan = NULL;
+ char flagBuf[5];
+ int userid, cflags, caccess, flagPos;
+ int i, total_count, match_count = 0, owner_count = 0;
+ struct Table *table;
+ printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ total_count = mysql_num_rows(res);
+ table = table_init(4, total_count + 1, 0);
+ char *content[4];
+ content[0] = get_language_string(user, "NS_MYACCESS_HEADER_NAME");
+ content[1] = get_language_string(user, "NS_MYACCESS_HEADER_ACCESS");
+ content[2] = get_language_string(user, "NS_MYACCESS_HEADER_FLAGS");
+ content[3] = get_language_string(user, "NS_MYACCESS_HEADER_INFO");
+ table_add(table, content);
+ if(chanmatch)
+ reply(textclient, user, "NS_MYACCESS_HEADER_MATCH", auth, chanmatch);
+ else
+ reply(textclient, user, "NS_MYACCESS_HEADER", auth);
+ if ((user_row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(user_row[0]);
+ //check if the user is already added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `channel_name`, `channel_getop`, `channel_getvoice` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' ORDER BY `chanuser_access` DESC, `channel_name` ASC", userid);
+ res = mysql_use();
+ while ((chanuser_row = mysql_fetch_row(res)) != NULL) {
+ if(!strcmp(chanuser_row[0], "500")) owner_count++;
+ if(chanmatch && match(chanmatch, chanuser_row[0])) continue;
+ match_count++;
+ if((!chanuser_row[4] || !chanuser_row[5]) && !default_chan) {
+ printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
+ default_res = mysql_use();
+ default_chan = mysql_fetch_row(default_res);
+ }
+ flagPos = 0;
+ content[0] = chanuser_row[3];
+ content[1] = chanuser_row[0];
+ cflags = atoi(chanuser_row[1]);
+ caccess = atoi(chanuser_row[0]);
+ if((cflags & DB_CHANUSER_SUSPENDED))
+ flagPos += sprintf(flagBuf + flagPos, "s");
+ if(caccess >= (chanuser_row[4] ? atoi(chanuser_row[4]) : atoi(default_chan[0])))
+ flagPos += sprintf(flagBuf + flagPos, "o");
+ if(caccess >= (chanuser_row[5] ? atoi(chanuser_row[5]) : atoi(default_chan[1])))
+ flagPos += sprintf(flagBuf + flagPos, "v");
+ if((cflags & DB_CHANUSER_AUTOINVITE))
+ flagPos += sprintf(flagBuf + flagPos, "i");
+ content[2] = flagBuf;
+ content[3] = chanuser_row[2];
+ table_add(table, content);
+ }
+ }
+ //send the table
+ char **table_lines = table_end(table);
+ for(i = 0; i < table->entrys; i++) {
+ reply(textclient, user, table_lines[i]);
+ }
+ if(!match_count)
+ reply(textclient, user, "NS_TABLE_NONE");
+ if(chanmatch) {
+ reply(textclient, user, "NS_MYACCESS_COUNT_MATCH", auth, total_count, owner_count, match_count, chanmatch);
+ } else {
+ reply(textclient, user, "NS_MYACCESS_COUNT", auth, total_count, owner_count);
+ }
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no args
+*/
+
+CMD_BIND(neonserv_cmd_netinfo) {
+ reply(getTextBot(), user, "NS_NETINFO_HEADER");
+ char tmp[MAXLEN];
+ struct Table *table;
+ table = table_init(2, 18, 0);
+ char *content[2];
+
+ content[0] = get_language_string(user, "NS_NETINFO_UPTIME");
+ content[1] = timeToStr(user, (time(0) - start_time), 3, tmp);
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_BOTS");
+ struct ClientSocket *cclient;
+ int bot_count = 0, connected_bot_count = 0;
+ float traffic_in = 0, traffic_out = 0;
+ for(cclient = getBots(0, NULL); cclient; cclient = getBots(0, cclient)) {
+ bot_count++;
+ if(cclient->flags & SOCKET_FLAG_READY)
+ connected_bot_count++;
+ traffic_in += cclient->traffic_in;
+ traffic_out += cclient->traffic_out;
+ }
+ sprintf(tmp, "%d (%d connected)", bot_count, connected_bot_count);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_TRAFFIC");
+ sprintf(tmp, "in: %.2f kb out: %.2f kb", traffic_in / 1024, traffic_out / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ int channel_count = getChannelCount();
+ float channel_memory = channel_count * sizeof(struct ChanNode);
+ int channel_ban_count = getChanBanCount();
+ float channel_ban_memory = channel_ban_count * sizeof(struct BanNode);
+ int user_count = getUserCount();
+ float user_memory = user_count * sizeof(struct UserNode);
+ int chanuser_count = getChanUserCount();
+ float chanuser_memory = chanuser_count * sizeof(struct ChanUser);
+ float total_memory = channel_memory + channel_ban_memory + user_memory + chanuser_memory;
+
+ content[0] = get_language_string(user, "NS_NETINFO_CACHE");
+ sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_CHANNEL");
+ sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", channel_count, channel_memory / 1024, channel_count, sizeof(struct ChanNode), channel_memory / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN");
+ sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", channel_ban_count, channel_ban_memory / 1024, channel_ban_count, sizeof(struct BanNode), channel_ban_memory / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_USER");
+ sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", user_count, user_memory / 1024, user_count, sizeof(struct UserNode), user_memory / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_CHANUSER");
+ sprintf(tmp, "%d %.2f kB (%d * %lu B = %.2f kB)", chanuser_count, chanuser_memory / 1024, chanuser_count, sizeof(struct ChanUser), chanuser_memory / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SHOW TABLE STATUS");
+ res = mysql_use();
+ int mysql_entrys[4];
+ float mysql_length[5];
+ total_memory = 0;
+ mysql_entrys[0] = 0; mysql_entrys[1] = 0; mysql_entrys[2] = 0; mysql_entrys[3] = 0;
+ mysql_length[0] = 0; mysql_length[1] = 0; mysql_length[2] = 0; mysql_length[3] = 0; mysql_length[4] = 0;
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(!stricmp(row[0], "channels")) {
+ mysql_entrys[0] = atoi(row[4]);
+ mysql_length[0] = atof(row[6]);
+ total_memory += atof(row[6]);
+ } else if(!stricmp(row[0], "bans")) {
+ mysql_entrys[1] = atoi(row[4]);
+ mysql_length[1] = atof(row[6]);
+ total_memory += atof(row[6]);
+ } else if(!stricmp(row[0], "users")) {
+ mysql_entrys[2] = atoi(row[4]);
+ mysql_length[2] = atof(row[6]);
+ total_memory += atof(row[6]);
+ } else if(!stricmp(row[0], "chanusers")) {
+ mysql_entrys[3] = atoi(row[4]);
+ mysql_length[3] = atof(row[6]);
+ total_memory += atof(row[6]);
+ } else {
+ mysql_length[4] += atof(row[6]);
+ total_memory += atof(row[6]);
+ }
+ }
+
+ content[0] = get_language_string(user, "NS_NETINFO_DATABASE");
+ sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_CHANNEL");
+ sprintf(tmp, "%d %.2f kB", mysql_entrys[0], mysql_length[0] / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN");
+ sprintf(tmp, "%d %.2f kB", mysql_entrys[1], mysql_length[1] / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_USER");
+ sprintf(tmp, "%d %.2f kB", mysql_entrys[2], mysql_length[2] / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_CHANUSER");
+ sprintf(tmp, "%d %.2f kB", mysql_entrys[3], mysql_length[3] / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_OTHER");
+ sprintf(tmp, "* %.2f kB", mysql_length[4] / 1024);
+ content[1] = tmp;
+ table_add(table, content);
+
+ if(strcmp(revision, ""))
+ sprintf(tmp, "%s (%s)", NEONSERV_VERSION, revision);
+ else
+ strcpy(tmp, NEONSERV_VERSION);
+ content[0] = get_language_string(user, "NS_NETINFO_VERSION");
+ content[1] = tmp;
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_COMPILER");
+ content[1] = build_language_string(user, tmp, "NS_NETINFO_COMPILER_VALUE", COMPILER, creation);
+ table_add(table, content);
+
+ content[0] = get_language_string(user, "NS_NETINFO_CODE");
+ content[1] = build_language_string(user, tmp, "NS_NETINFO_CODE_VALUE", codelines);
+ table_add(table, content);
+
+ char **table_lines = table_end(table);
+ int i;
+ for(i = 0; i < table->entrys; i++) {
+ reply(getTextBot(), user, table_lines[i]);
+ }
+ table_free(table);
+}
+
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] target
+* argv[1-*] message
+*/
+
+CMD_BIND(neonserv_cmd_notice) {
+ char *message = merge_argv(argv, 1, argc);
+ putsock(client, "NOTICE %s :%s", argv[0], message);
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nicks
+*/
+static USERLIST_CALLBACK(neonserv_cmd_op_userlist_lookup);
+static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks);
+
+struct neonserv_cmd_op_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *nicks;
+};
+
+CMD_BIND(neonserv_cmd_op) {
+ struct neonserv_cmd_op_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->nicks = strdup(merge_argv(argv, 0, argc));
+ get_userlist_with_invisible(chan, neonserv_cmd_op_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_op_userlist_lookup) {
+ struct neonserv_cmd_op_cache *cache = data;
+ neonserv_cmd_op_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks);
+ free(cache->nicks);
+ free(cache);
+}
+
+static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks) {
+ int total_users = 0, done_users = 0;
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ char *a, *b = nicks;
+ do {
+ a = strstr(b, " ");
+ if(a) *a = '\0';
+ total_users++;
+ cuser = searchUserByNick(b);
+ if(!cuser) {
+ //check for an invisible user
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(!stricmp(chanuser->user->nick, b)) {
+ cuser = chanuser->user;
+ break;
+ }
+ }
+ if(!cuser) continue;
+ } else {
+ chanuser = getChanUser(cuser, chan);
+ if(!chanuser) continue;
+ }
+ done_users++;
+ if(chanuser->flags & CHANUSERFLAG_OPPED) continue;
+ modeBufferOp(modeBuf, b);
+ if(a) {
+ b = a+1;
+ }
+ } while(a);
+ freeModeBuffer(modeBuf);
+ if(done_users == total_users)
+ reply(textclient, user, "NS_OP_DONE", chan->name);
+ else
+ reply(textclient, user, "NS_OP_FAIL", client->user->nick);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] "force"
+* argv[1] (optional) nick mask
+*/
+static USERLIST_CALLBACK(neonserv_cmd_opall_userlist_lookup);
+static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask);
+
+struct neonserv_cmd_opall_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *nickmask;
+};
+
+CMD_BIND(neonserv_cmd_opall) {
+ if(!argc || strcmp(argv[0], "FORCE")) {
+ reply(getTextBot(), user, "NS_OPALL_SECURITY", chan->name);
+ return;
+ }
+ struct neonserv_cmd_opall_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ if(argc > 1) {
+ cache->nickmask = strdup(argv[1]);
+ } else
+ cache->nickmask = NULL;
+ get_userlist_with_invisible(chan, neonserv_cmd_opall_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_opall_userlist_lookup) {
+ struct neonserv_cmd_opall_cache *cache = data;
+ neonserv_cmd_opall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask);
+ if(cache->nickmask)
+ free(cache->nickmask);
+ free(cache);
+}
+
+static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask) {
+ int done_users = 0;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(nickmask && match(nickmask, chanuser->user->nick)) continue;
+ if(chanuser->flags & CHANUSERFLAG_OPPED) continue;
+ modeBufferOp(modeBuf, chanuser->user->nick);
+ done_users++;
+ }
+ freeModeBuffer(modeBuf);
+ reply(textclient, user, "NS_OPALL_DONE", done_users, chan->name);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] time
+* argv[1-*] match
+*/
+
+CMD_BIND(neonserv_cmd_oplog) {
+ char *str_match;
+ int duration = (argc ? strToTime(user, argv[0]) : 0);
+ if(argc > (duration ? 1 : 0))
+ str_match = merge_argv(argv, (duration ? 1 : 0), argc);
+ else
+ str_match = "";
+ if(!duration) duration = (60*60*24);
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `godlog_time`, `user_user`, `channel_name`, `godlog_cmd` FROM `godlog` LEFT JOIN `channels` ON `godlog_cid` = `channel_id` LEFT JOIN `users` ON `godlog_uid` = `user_id` WHERE `godlog_time` > '%lu' ORDER BY `godlog_time` ASC", ((unsigned long) time(0) - duration));
+ res = mysql_use();
+ int skip = mysql_num_rows(res) - 100;
+ int count = 0;
+ char timeBuf[50];
+ struct tm *timeinfo;
+ time_t event_time;
+ if(skip < 0) skip = 0;
+ reply(getTextBot(), user, "NS_EVENTS_HEADER");
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(skip) {
+ skip--;
+ continue;
+ }
+ if(*str_match && match(str_match, row[3])) continue;
+ count++;
+ event_time = (time_t) atol(row[0]);
+ timeinfo = localtime(&event_time);
+ strftime(timeBuf, 80, "%X %x", timeinfo);
+ reply(getTextBot(), user, "[%s] [%s%s%s]: %s", timeBuf, row[1], (row[2] ? ":" : ""), (row[2] ? row[2] : ""), row[3]);
+ }
+ reply(getTextBot(), user, "NS_TABLE_COUNT", count);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no parameters
+*/
+static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup);
+static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan);
+
+struct neonserv_cmd_peek_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+};
+
+CMD_BIND(neonserv_cmd_peek) {
+ struct neonserv_cmd_peek_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ get_userlist_with_invisible(chan, neonserv_cmd_peek_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup) {
+ struct neonserv_cmd_peek_cache *cache = data;
+ neonserv_cmd_peek_async1(cache->client, cache->textclient, cache->user, chan);
+ free(cache);
+}
+
+static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan) {
+ reply(textclient, user, "NS_PEEK_HEADER", chan->name);
+ reply(textclient, user, "NS_PEEK_TOPIC", chan->topic);
+ char tmpStr[MAXLEN];
+ getModeString(chan->modes, tmpStr);
+ reply(textclient, user, "NS_PEEK_MODES", tmpStr);
+ struct ChanUser *chanuser;
+ int op_count = 0, voice_count = 0, normal_count = 0, invi_count = 0;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(chanuser->flags & CHANUSERFLAG_OPPED)
+ op_count++;
+ else if(chanuser->flags & CHANUSERFLAG_VOICED)
+ voice_count++;
+ else if(chanuser->flags & CHANUSERFLAG_VOICED)
+ invi_count++;
+ else
+ normal_count++;
+ }
+ reply(textclient, user, "NS_PEEK_USERS", op_count+voice_count+invi_count+normal_count, op_count, voice_count, normal_count, invi_count);
+ int tmpStrPos = 0;
+ int headerlen = 10 + strlen(user->nick);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(chanuser->flags & CHANUSERFLAG_OPPED) {
+ if(tmpStrPos + headerlen + strlen(chanuser->user->nick) + 2 >= 512) {
+ //clear buffer
+ reply(textclient, user, "%s", tmpStr);
+ tmpStrPos = 0;
+ }
+ tmpStrPos += sprintf(tmpStr + tmpStrPos, (tmpStrPos ? ", %s" : "%s"), chanuser->user->nick);
+ }
+ }
+ if(tmpStrPos) {
+ reply(textclient, user, "%s", tmpStr);
+ }
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] raw
+*/
+
+CMD_BIND(neonserv_cmd_raw) {
+ char *raw = merge_argv(argv, 0, argc);
+ putsock(client, "%s", raw);
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - channel
+*/
+CMD_BIND(neonserv_cmd_recover) {
+ MYSQL_RES *res;
+ MYSQL_ROW row, row2;
+ char *channel = argv[0];
+ if(!is_valid_chan(channel)) {
+ reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
+ return;
+ }
+ printf_mysql_query("SELECT `botid`, `bot_channels`.`id` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick);
+ return;
+ }
+ int chanid;
+ printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chanid = atoi(row[0]);
+ } else {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger` FROM `bots` WHERE `botclass` = '%d' ORDER BY `register_priority` DESC", client->botid);
+ res = mysql_use();
+ int botid = 0;
+ char *bottrigger;
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ //check channel count
+ printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]);
+ row2 = mysql_fetch_row(mysql_use());
+ if(atoi(row2[0]) < atoi(row[1])) {
+ botid = atoi(row[0]);
+ bottrigger = row[2];
+ break;
+ }
+ }
+ if(!botid) {
+ reply(getTextBot(), user, "NS_REGISTER_FULL");
+ return;
+ }
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == botid)
+ break;
+ }
+ if(bot) {
+ putsock(bot, "JOIN %s", channel);
+ } else
+ reply(getTextBot(), user, "NS_REGISTER_DISCONNECTED");
+ printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', '%s')", botid, chanid, bottrigger);
+ reply(getTextBot(), user, "NS_RECOVER_DONE", channel);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - channel
+* argv[0/1] - nick / *auth
+*/
+static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup);
+static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup);
+static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth);
+
+struct neonserv_cmd_register_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+ char *channel;
+};
+
+CMD_BIND(neonserv_cmd_register) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char *channel = argv[0];
+ if(!is_valid_chan(channel)) {
+ reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
+ return;
+ }
+ printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `bot_channels`.`chanid` = `channels`.`channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick);
+ return;
+ }
+ //check own access
+ if(argv[1][0] == '*') {
+ //we've got an auth
+ argv[1]++;
+ printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[1]));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ neonserv_cmd_register_async1(client, getTextBot(), user, chan, event, channel, row[0]);
+ } else {
+ //we need to create a new user...
+ //but first lookup the auth to check if it really exists
+ struct neonserv_cmd_register_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[1]);
+ cache->channel = strdup(channel);
+ lookup_authname(argv[1], neonserv_cmd_register_auth_lookup, cache);
+ }
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[1]);
+ if(!cuser) {
+ cuser = createTempUser(argv[1]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_register_async1(client, getTextBot(), user, chan, event, channel, cuser->auth);
+ } else {
+ struct neonserv_cmd_register_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[1]);
+ cache->channel = strdup(channel);
+ get_userauth(cuser, neonserv_cmd_register_nick_lookup, cache);
+ }
+ }
+}
+
+static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup) {
+ struct neonserv_cmd_register_cache *cache = data;
+ if(!exists) {
+ //AUTH_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick);
+ } else
+ neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, auth);
+ free(cache->channel);
+ free(cache->nick);
+ free(cache);
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup) {
+ struct neonserv_cmd_register_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, user->auth);
+ free(cache->channel);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row, row2;
+ int userid, adminid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL)
+ adminid = atoi(row[0]);
+ else
+ adminid = 0;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ } else {
+ printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth));
+ userid = (int) mysql_insert_id(mysql_conn);
+ }
+ printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger` FROM `bots` WHERE `botclass` = '%d' ORDER BY `register_priority` DESC", client->botid);
+ res = mysql_use();
+ int botid = 0;
+ char *bottrigger;
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ //check channel count
+ printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]);
+ row2 = mysql_fetch_row(mysql_use());
+ if(atoi(row2[0]) < atoi(row[1])) {
+ botid = atoi(row[0]);
+ bottrigger = row[2];
+ break;
+ }
+ }
+ if(!botid) {
+ reply(textclient, user, "NS_REGISTER_FULL");
+ return;
+ }
+ int chanid;
+ printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chanid = atoi(row[0]);
+ printf_mysql_query("UPDATE `channels` SET `channel_registered` = UNIX_TIMESTAMP(), `channel_registrator` = '%d' WHERE `channel_id` = '%d'", adminid, chanid);
+ } else {
+ printf_mysql_query("INSERT INTO `channels` (`channel_name`, `channel_registered`, `channel_registrator`) VALUES ('%s', UNIX_TIMESTAMP(), '%d')", escape_string(channel), adminid);
+ chanid = (int) mysql_insert_id(mysql_conn);
+ }
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == botid)
+ break;
+ }
+ if(bot) {
+ putsock(bot, "JOIN %s", channel);
+ } else
+ reply(textclient, user, "NS_REGISTER_DISCONNECTED");
+ printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', '%s')", botid, chanid, bottrigger);
+ printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d'", chanid);
+ printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chanid, userid, 500);
+ reply(textclient, user, "NS_REGISTER_DONE", channel, auth);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] language tag
+*/
+
+CMD_BIND(neonserv_cmd_reloadlang) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `text`, `lang` FROM `language` WHERE `ident` = 'name' AND `lang` = '%s'", escape_string(argv[0]));
+ res = mysql_use();
+ if((row = mysql_fetch_row(res)) != NULL) {
+ load_language(row[1], row[0]);
+ reply(getTextBot(), user, "NS_RELOADLANG_DONE", row[0], row[1]);
+ } else {
+ reply(getTextBot(), user, "NS_RELOADLANG_UNKNOWN", argv[0]);
+ }
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - usermask
+* argv[1] - min access
+* argv[2] - max access
+*/
+static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup);
+static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access);
+
+struct neonserv_cmd_resync_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ char *usermask;
+ int min_access;
+ int max_access;
+};
+
+CMD_BIND(neonserv_cmd_resync) {
+ int min_access = 0, max_access = 500;
+ char *usermask = NULL;
+ if(argc > 0)
+ usermask = argv[0];
+ if(argc > 2) {
+ min_access = atoi(argv[1]);
+ max_access = atoi(argv[2]);
+ }
+ struct neonserv_cmd_resync_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->usermask = (usermask ? strdup(usermask) : NULL);
+ cache->min_access = min_access;
+ cache->max_access = max_access;
+ get_userlist_with_invisible(chan, neonserv_cmd_resync_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup) {
+ struct neonserv_cmd_resync_cache *cache = data;
+ neonserv_cmd_resync_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access);
+ if(cache->usermask)
+ free(cache->usermask);
+ free(cache);
+}
+
+static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access) {
+ MYSQL_RES *res;
+ MYSQL_ROW row, defaults = NULL;
+ int i;
+ int resync_op = 1;
+ int resync_voice = 1;
+ if(usermask && usermask[0] == '@') {
+ resync_voice = 0;
+ usermask++;
+ if(!*usermask) usermask = NULL;
+ } else if(usermask && usermask[0] == '+') {
+ resync_op = 0;
+ usermask++;
+ if(!*usermask) usermask = NULL;
+ }
+ struct ChanUser *chanuser;
+ int db_enfops, db_enfvoice;
+ printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ row = mysql_fetch_row(mysql_use());
+ if(row[0] == NULL || row[1] == NULL) {
+ printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
+ defaults = mysql_fetch_row(mysql_use());
+ }
+ db_enfops = atoi((row[0] ? row[0] : defaults[0]));
+ db_enfvoice = atoi((row[1] ? row[1] : defaults[1]));
+ printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id);
+ res = mysql_use();
+ char *db_users[mysql_num_rows(res)];
+ int db_access[mysql_num_rows(res)];
+ int db_flags[mysql_num_rows(res)];
+ int db_count = 0;
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ db_users[db_count] = row[1];
+ db_access[db_count] = atoi(row[0]);
+ db_flags[db_count] = atoi(row[2]);
+ db_count++;
+ }
+ int caccess, cflags;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ caccess = 0;
+ cflags = 0;
+ if((chanuser->user->flags & USERFLAG_ISAUTHED)) {
+ for(i = 0; i < db_count; i++) {
+ if(!stricmp(db_users[i], chanuser->user->auth)) {
+ caccess = db_access[i];
+ cflags = db_flags[i];
+ break;
+ }
+ }
+ }
+ if((usermask && *usermask && match(usermask, row[1])) || caccess < min_access || caccess > max_access) continue;
+ if(caccess >= db_enfops) {
+ if(!(chanuser->flags & CHANUSERFLAG_OPPED) && resync_op)
+ modeBufferOp(modeBuf, chanuser->user->nick);
+ } else if(caccess >= db_enfvoice) {
+ if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
+ modeBufferDeop(modeBuf, chanuser->user->nick);
+ if(!(chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice)
+ modeBufferVoice(modeBuf, chanuser->user->nick);
+ } else {
+ if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
+ modeBufferDeop(modeBuf, chanuser->user->nick);
+ if((chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
+ modeBufferDevoice(modeBuf, chanuser->user->nick);
+ }
+
+ }
+ freeModeBuffer(modeBuf);
+ reply(textclient, user, "NS_RESYNC_DONE", chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] target
+* argv[1-*] message
+*/
+
+CMD_BIND(neonserv_cmd_say) {
+ char *message = merge_argv(argv, 1, argc);
+ putsock(client, "PRIVMSG %s :%s", argv[0], message);
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+#define CMD_SEARCH_FLAG_HAS_NODELETE 0x01
+#define CMD_SEARCH_FLAG_NOT_NODELETE 0x02
+#define CMD_SEARCH_FLAG_HAS_SUSPENDED 0x04
+#define CMD_SEARCH_FLAG_NOT_SUSPENDED 0x08
+
+struct neonserv_cmd_search_criteria {
+ char *name;
+ char *registrar;
+ unsigned int flags : 16;
+ unsigned int unvisited;
+ unsigned int registered;
+ unsigned int limit : 16;
+};
+
+CMD_BIND(neonserv_cmd_search) {
+ //ok parse the criterias
+ struct neonserv_cmd_search_criteria *criteria = malloc(sizeof(*criteria));
+ if (!criteria) {
+ perror("malloc() failed");
+ return;
+ }
+ memset(criteria, 0, sizeof(*criteria));
+ criteria->limit = 50;
+ int i, show_chans = 0, positive;
+ if(!stricmp(argv[0], "print")) {
+ show_chans = 1;
+ }
+ for(i = 1; i < argc; i += 2) {
+ if(argc <= i+1) {
+ reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT");
+ return;
+ }
+ if(!stricmp(argv[i], "name")) criteria->name = argv[i+1];
+ else if(!stricmp(argv[i], "registrar")) criteria->registrar = argv[i+1];
+ else if(!stricmp(argv[i], "unvisited")) criteria->unvisited = strToTime(user, argv[i+1]);
+ else if(!stricmp(argv[i], "registered")) criteria->registered = strToTime(user, argv[i+1]);
+ else if(!stricmp(argv[i], "flags")) {
+ if(argv[i+1][0] == '+') {
+ positive = 1;
+ argv[i+1]++;
+ } else if(argv[i+1][0] == '-') {
+ positive = 0;
+ argv[i+1]++;
+ } else
+ positive = 1;
+ if(!stricmp(argv[i+1], "nodelete")) {
+ if(positive)
+ criteria->flags |= CMD_SEARCH_FLAG_HAS_NODELETE;
+ else
+ criteria->flags |= CMD_SEARCH_FLAG_NOT_NODELETE;
+ } else if(!stricmp(argv[i+1], "suspended")) {
+ if(positive)
+ criteria->flags |= CMD_SEARCH_FLAG_HAS_SUSPENDED;
+ else
+ criteria->flags |= CMD_SEARCH_FLAG_NOT_SUSPENDED;
+ }
+ }
+ else if(!stricmp(argv[i], "limit")) {
+ criteria->limit = atoi(argv[i+1]);
+ }
+ }
+ int matches = 0;
+ reply(getTextBot(), user, "NS_SEARCH_HEADER");
+ MYSQL_RES *res, *res2;
+ MYSQL_ROW row, row2;
+ printf_mysql_query("SELECT `channel_name`, `user_user`, `channel_registered`, `channel_nodelete`, `suspended`, `channel_id` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botid` = '%d'", client->botid);
+ res = mysql_use();
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(show_chans && matches == criteria->limit) {
+ //too many
+ break;
+ }
+ if(criteria->name && match(criteria->name, row[0])) continue;
+ if(criteria->registrar && row[1] && match(criteria->registrar, row[1])) continue;
+ if(criteria->unvisited) {
+ printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' ORDER BY `chanuser_seen` DESC LIMIT 1", row[5]);
+ res2 = mysql_use();
+ row2 = mysql_fetch_row(res);
+ if(!row2) continue;
+ if((time(0) - atoi(row2[0])) < criteria->unvisited) continue;
+ }
+ if(criteria->registered && (time(0) - atoi(row[2])) < criteria->registered) continue;
+
+ if((criteria->flags & CMD_SEARCH_FLAG_HAS_NODELETE) && strcmp(row[3], "1")) continue;
+ if((criteria->flags & CMD_SEARCH_FLAG_NOT_NODELETE) && strcmp(row[3], "0")) continue;
+ if((criteria->flags & CMD_SEARCH_FLAG_HAS_SUSPENDED) && strcmp(row[4], "1")) continue;
+ if((criteria->flags & CMD_SEARCH_FLAG_NOT_SUSPENDED) && strcmp(row[4], "0")) continue;
+ matches++;
+ //output
+ if(show_chans) {
+ reply(getTextBot(), user, "%s", row[0]);
+ }
+ }
+ reply(getTextBot(), user, "NS_TABLE_COUNT", matches);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+typedef char* neonserv_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
+static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *argument);
+static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
+static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
+static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
+static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument);
+
+#define NS_VALID_FUNCTION 0x01
+#define NS_VALID_STRING 0x02
+#define NS_VALID_ACCESS 0x04
+#define NS_VALID_NO501 0x08
+#define NS_VALID_OPTIONS 0x10
+#define NS_VALID_NUMERIC 0x20
+#define NS_VALID_BOOLEAN 0x40
+
+#define NS_HAS_OPT 0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */
+#define NS_HAS_HELP 0x200 /* help (SET_HELP_{NAME}) - only shown if help is requested */
+
+static const struct {
+ const char *setting;
+ const char *chanfield;
+ unsigned int valid;
+ void *parameter;
+} channel_settings[] = {
+ {"TRIGGER", NULL, NS_VALID_FUNCTION, neonserv_cmd_set_trigger},
+ {"DEFAULTTOPIC", "channel_defaulttopic", NS_VALID_STRING, NULL},
+ {"TOPICMASK", "channel_topicmask", NS_VALID_STRING, NULL},
+ {"ADVANCEDTOPIC", "channel_exttopic", NS_VALID_BOOLEAN | NS_HAS_OPT, NULL},
+ {"GREETING", "channel_greeting", NS_VALID_STRING, NULL},
+ {"USERGREETING", "channel_usergreeting", NS_VALID_STRING, NULL},
+ {"USERINFO", "channel_userinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"WIPEINFO", "channel_wipeinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"MODES", "channel_modes", NS_VALID_FUNCTION, neonserv_cmd_set_modes},
+ {"INVITEME", "channel_getinvite", NS_VALID_ACCESS, NULL},
+ {"GIVEOPS", "channel_getop", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"GIVEVOICE", "channel_getvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"ENFOPS", "channel_canop", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"ENFVOICE", "channel_canvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"KICK", "channel_cankick", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"BAN", "channel_canban", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"STATICBAN", "channel_staticban", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"PUBCMD", "channel_pubcmd", NS_VALID_ACCESS, NULL},
+ {"ENFMODES", "channel_enfmodes", NS_VALID_ACCESS, NULL},
+ {"ENFTOPIC", "channel_enftopic", NS_VALID_ACCESS, NULL},
+ {"TOPICSNARF", "channel_topicsnarf", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"CHANGETOPIC", "channel_changetopic", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"SETTERS", "channel_setters", NS_VALID_ACCESS | NS_VALID_NO501 | NS_HAS_HELP, NULL},
+ {"ADDUSER", "channel_canadd", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"DELUSER", "channel_candel", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"CLVL", "channel_canclvl", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"RESYNC", "channel_canresync", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"SUSPEND", "channel_cansuspend", NS_VALID_ACCESS | NS_HAS_HELP, NULL},
+ {"NOTICEUSERS", "channel_notice", NS_VALID_ACCESS, NULL},
+ {"NOTICEREACTION", "channel_noticereaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
+ {"CTCPUSERS", "channel_ctcp", NS_VALID_ACCESS, NULL},
+ {"CTCPREACTION", "channel_ctcpreaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
+ {"PROTECT", "channel_protect", NS_VALID_OPTIONS | NS_HAS_OPT, "4"},
+ {"TOYS", "channel_toys", NS_VALID_OPTIONS | NS_HAS_OPT, "3"},
+ {"DYNLIMIT", "channel_dynlimit", NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit},
+ {"NODELETE", "channel_nodelete", NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete},
+ {NULL, NULL, 0, NULL}
+};
+
+#define MAX_QUERY_LEN 1024
+CMD_BIND(neonserv_cmd_set) {
+ int i, j;
+ if(argc && !strcmp(argv[0], "defaults")) {
+ //reset channel settings
+ int uaccess = getChannelAccess(user, chan, 0);
+ if(uaccess < 500) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name);
+ return;
+ }
+ }
+ int seed = 0;
+ char *tmp;
+ static char defaultskey[16];
+ 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));
+ sprintf(defaultskey, "%08x", seed);
+ if(argc > 1 && !strcmp(argv[1], defaultskey)) {
+ char query[MAX_QUERY_LEN];
+ int querypos = 0;
+ i = 0;
+ while(channel_settings[i].setting) {
+ if(channel_settings[i].chanfield)
+ querypos += sprintf(query + querypos, "`%s` = NULL, ", channel_settings[i].chanfield);
+ i++;
+ }
+ if(querypos) {
+ query[querypos-2] = '\0';
+ }
+ printf_mysql_query("UPDATE `channels` SET %s WHERE `channel_id` = '%d'", query, chan->channel_id);
+ reply(getTextBot(), user, "NS_SET_DEFAULTS_DONE", chan->name);
+ logEvent(event);
+ } else {
+ reply(getTextBot(), user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey);
+ }
+ } else if(argc && strcmp(argv[0], "help")) {
+ //find the correct command
+ i = 0;
+ j = 0;
+ char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL);
+ while(channel_settings[i].setting) {
+ if(!stricmp(channel_settings[i].setting, argv[0])) {
+ //setting found
+ if(channel_settings[i].valid & NS_VALID_FUNCTION) {
+ neonserv_cmd_set_function *func = channel_settings[i].parameter;
+ func(client, user, chan, event, channel_settings[i].setting, args);
+ } else {
+ neonserv_cmd_set_setting(client, user, chan, event, i, args);
+ }
+ j = 1;
+ break;
+ }
+ i++;
+ }
+ if(j == 0) {
+ //unknown setting
+ reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]);
+ }
+ } else {
+ char query[MAX_QUERY_LEN], *value, *org_value, *tmp, nameBuf[64];
+ int querypos = 0;
+ MYSQL_RES *res, *defaults_res;
+ MYSQL_ROW row, defaults;
+ struct Table *table;
+ char *content[2];
+ i = 0;
+ while(channel_settings[i].setting) {
+ if(channel_settings[i].chanfield)
+ querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield);
+ i++;
+ }
+ table = table_init(2, i, 0);
+ table_set_bold(table, 0, 1);
+ printf_mysql_query("SELECT `channel_id` %s FROM `channels` WHERE `channel_name` = 'defaults'", query);
+ defaults_res = mysql_use();
+ defaults = mysql_fetch_row(defaults_res);
+ printf_mysql_query("SELECT `channel_name` %s FROM `channels` WHERE `channel_id` = '%d'", query, chan->channel_id);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ i = 0;
+ j = 0;
+ reply(getTextBot(), user, "NS_SET_HEADER", chan->name);
+ while(channel_settings[i].setting) {
+ if(channel_settings[i].chanfield) {
+ j++;
+ org_value = (row[j] ? row[j] : defaults[j]);
+ } else if(channel_settings[i].valid & NS_VALID_FUNCTION) {
+ neonserv_cmd_set_function *func = channel_settings[i].parameter;
+ org_value = func(client, user, chan, event, NULL, NULL);
+ } else
+ org_value = "0";
+ value = org_value;
+ if(channel_settings[i].valid & NS_VALID_BOOLEAN) {
+ if(!strcmp(value, "0"))
+ value = get_language_string(user, "NS_SET_OFF");
+ else
+ value = get_language_string(user, "NS_SET_ON");
+ }
+ strcpy(query, value);
+ querypos = strlen(query);
+ if(channel_settings[i].valid & NS_HAS_OPT) {
+ sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[i].setting, org_value);
+ tmp = get_language_string(user, nameBuf);
+ if(tmp) {
+ querypos += sprintf(query+querypos, " - %s", tmp);
+ }
+ }
+ if(argc && channel_settings[i].valid & NS_HAS_HELP) {
+ sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[i].setting);
+ tmp = get_language_string(user, nameBuf);
+ if(tmp) {
+ querypos += sprintf(query+querypos, " - %s", tmp);
+ }
+ }
+ content[0] = (char*)channel_settings[i].setting;
+ content[1] = query;
+ table_add(table, content);
+ i++;
+ }
+ char **table_lines = table_end(table);
+ for(i = 0; i < table->entrys; i++) {
+ reply(getTextBot(), user, table_lines[i]);
+ }
+ table_free(table);
+ }
+}
+
+static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *args) {
+ char *value;
+ char nameBuf[64];
+ //get current value
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, chan->channel_id);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ if(row[0] == NULL) {
+ printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_settings[setting].chanfield);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ }
+ value = row[0];
+ if(args) {
+ //change the channel setting
+ //check the new argument
+ int valid = channel_settings[setting].valid;
+ if(valid & NS_VALID_STRING) {
+ if(!strcmp(args, "*")) {
+ args = "";
+ }
+ }
+ if(valid & NS_VALID_ACCESS) {
+ int caccess = atoi(args);
+ int max = ((valid & NS_VALID_NO501) ? 500 : 501);
+ if(caccess < 0 || caccess > max) {
+ reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
+ return;
+ }
+ int uaccess = getChannelAccess(user, chan, 0);
+ if(uaccess == 500) uaccess++;
+ if(atoi(value) > uaccess) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_SET_CANNOT_SET");
+ return;
+ }
+ }
+ if(caccess > uaccess) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_SET_BADLEVEL");
+ return;
+ }
+ }
+ sprintf(nameBuf, "%d", caccess);
+ args = nameBuf;
+ }
+ if(valid & NS_VALID_OPTIONS) {
+ int options = atoi((char *) channel_settings[setting].parameter);
+ int coption = atoi(args);
+ if(coption < 0 || coption >= options) {
+ reply(getTextBot(), user, "NS_SET_INVALID_OPTION", coption);
+ int i;
+ int nameBufPos = 0;
+ if(valid & NS_HAS_OPT) {
+ for(i = 0; i < options; i++) {
+ sprintf(nameBuf, "NS_SET_OPTION_%s_%d", channel_settings[setting].setting, i);
+ reply(getTextBot(), user, "\002%d\002 - %s", i, get_language_string(user, nameBuf));
+ }
+ } else {
+ for(i = 0; i < options; i++) {
+ nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i);
+ }
+ if(nameBufPos) {
+ nameBuf[nameBufPos-2] = '\0';
+ reply(getTextBot(), user, nameBuf);
+ }
+ }
+ return;
+ }
+ }
+ if(valid & NS_VALID_NUMERIC) {
+ sprintf(nameBuf, "%d", atoi(args));
+ args = nameBuf;
+ }
+ if(valid & NS_VALID_BOOLEAN) {
+ if(!strcmp(args, "0") || !stricmp(args, "off") || !stricmp(args, get_language_string(user, "NS_SET_OFF"))) {
+ args = "0";
+ } else if(!strcmp(args, "1") || !stricmp(args, "on") || !stricmp(args, get_language_string(user, "NS_SET_ON"))) {
+ args = "1";
+ } else {
+ reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", args);
+ return;
+ }
+ }
+ //valid - set it
+ value = args;
+ printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, escape_string(value), chan->channel_id);
+ logEvent(event);
+ }
+ reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value);
+ if(channel_settings[setting].valid & NS_HAS_HELP) {
+ sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[setting].setting);
+ reply(getTextBot(), user, " %s", get_language_string(user, nameBuf));
+ }
+}
+
+static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
+ char *trigger;
+ //get current trigger
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `trigger` FROM `bot_channels` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ trigger = row[0];
+ if(argument) {
+ int uaccess = getChannelAccess(user, chan, 0);
+ if(uaccess < 500) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_SET_TRIGGER_OWNER", chan->name);
+ return NULL;
+ }
+ }
+ if(strlen(argument) > 15)
+ argument[15] = '\0';
+ printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `chanid` = '%d' AND `botid` = '%d'", escape_string(argument), chan->channel_id, client->clientid);
+ trigger = argument;
+ changeChannelTrigger(client->botid, chan, trigger);
+ logEvent(event);
+ }
+ if(setting) {
+ reply(getTextBot(), user, "\002%s\002 %s", setting, trigger);
+ }
+ return trigger;
+}
+
+static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
+ char *value;
+ //get current value
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ if(row[0] == NULL) {
+ printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ }
+ value = row[0];
+ if(argument) {
+ //change the channel setting
+ //TODO: parse, check and set modelock
+ }
+ if(setting) {
+ reply(getTextBot(), user, "\002%s\002 %s", setting, value);
+ }
+ return value;
+}
+
+static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
+ char *value;
+ char tmp[64];
+ //get current value
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ if(row[0] == NULL) {
+ printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ }
+ value = row[0];
+ if(argument) {
+ //change the channel setting
+ sprintf(tmp, "%d", atoi(argument));
+ argument = tmp;
+ printf_mysql_query("UPDATE `channels` SET `channel_dynlimit` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
+ if(strcmp(argument, "0"))
+ putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument)));
+ else if(isModeSet(chan->modes, 'l'))
+ putsock(client, "MODE %s -l", chan->name);
+ value = argument;
+ logEvent(event);
+ }
+ if(setting) {
+ reply(getTextBot(), user, "\002%s\002 %s", setting, value);
+ }
+ return value;
+}
+
+static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) {
+ char *value;
+ //get current value
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ if(row[0] == NULL) {
+ printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ }
+ value = row[0];
+ if(argument && isGodMode(user)) {
+ //change the channel setting
+ if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
+ argument = "0";
+ } else if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) {
+ argument = "1";
+ } else {
+ reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument);
+ return NULL;
+ }
+ printf_mysql_query("UPDATE `channels` SET `channel_nodelete` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id);
+ event->flags |= CMDFLAG_OPLOG;
+ value = argument;
+ logEvent(event);
+ }
+ if(setting) {
+ reply(getTextBot(), user, "\002%s\002 %s", setting, value);
+ }
+ return value;
+}
+
+#undef MAX_QUERY_LEN
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+* argv[1] - global access
+*/
+static AUTHLOOKUP_CALLBACK(neonserv_cmd_setaccess_auth_lookup);
+static USERAUTH_CALLBACK(neonserv_cmd_setaccess_nick_lookup);
+static void neonserv_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int access);
+
+struct neonserv_cmd_setaccess_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ int access;
+ char *nick;
+};
+
+CMD_BIND(neonserv_cmd_setaccess) {
+ int caccess;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ caccess = atoi(argv[1]);
+ if(caccess < 0 || caccess > 1000) {
+ reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess);
+ return;
+ }
+ printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL || atoi(row[0]) < caccess) {
+ reply(getTextBot(), user, "NS_ACCESS_OUTRANKED");
+ return;
+ }
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0]));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ neonserv_cmd_setaccess_async1(client, getTextBot(), user, event, argv[0], row[0], caccess);
+ } else {
+ //we need to create a new user...
+ //but first lookup the auth to check if it really exists
+ struct neonserv_cmd_setaccess_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->access = caccess;
+ cache->nick = strdup(argv[0]);
+ lookup_authname(argv[0], neonserv_cmd_setaccess_auth_lookup, cache);
+ }
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_setaccess_async1(client, getTextBot(), user, event, argv[0], cuser->auth, caccess);
+ } else {
+ struct neonserv_cmd_setaccess_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->access = caccess;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_setaccess_nick_lookup, cache);
+ }
+ }
+}
+
+static AUTHLOOKUP_CALLBACK(neonserv_cmd_setaccess_auth_lookup) {
+ struct neonserv_cmd_setaccess_cache *cache = data;
+ if(!exists) {
+ //AUTH_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick);
+ } else
+ neonserv_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, cache->nick, auth, cache->access);
+ free(cache->nick);
+ free(cache);
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_setaccess_nick_lookup) {
+ struct neonserv_cmd_setaccess_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, user->nick, user->auth, cache->access);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int caccess) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `user_id`, `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ if(atoi(row[1]) != caccess)
+ printf_mysql_query("UPDATE `users` SET `user_access` = '%d' WHERE `user_id` = '%s'", caccess, row[0]);
+ } else {
+ printf_mysql_query("INSERT INTO `users` (`user_user`, `user_access`) VALUES ('%s', '%d')", escape_string(auth), caccess);
+ }
+ reply(textclient, user, "NS_SETACCESS_DONE", auth, caccess);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup);
+static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
+
+struct neonserv_cmd_suspend_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+};
+
+CMD_BIND(neonserv_cmd_suspend) {
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
+ } else {
+ struct neonserv_cmd_suspend_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_suspend_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup) {
+ struct neonserv_cmd_suspend_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_suspend_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid, cflags;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(textclient, user, "NS_USER_OUTRANKED", nick);
+ return;
+ }
+ }
+ //suspend
+ cflags = atoi(row[2]);
+ if(cflags & DB_CHANUSER_SUSPENDED) {
+ reply(textclient, user, "NS_SUSPEND_ALREADY", nick);
+ return;
+ }
+ cflags |= DB_CHANUSER_SUSPENDED;
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", cflags, row[1]);
+ reply(textclient, user, "NS_SUSPEND_DONE", nick, chan->name);
+ logEvent(event);
+ return;
+ }
+ }
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* ADVANCEDTOPIC enabled
+* argv[0] topic id
+* argv[1-*] topic
+*
+* ADVANCEDTOPIC disabled
+* argv[0-*] topic
+*/
+
+#define ADVANCEDTOPIC_MAXID 9
+
+CMD_BIND(neonserv_cmd_topic) {
+ MYSQL_RES *res;
+ MYSQL_ROW row, default_row = NULL;
+ int advanced_topic, i;
+ char *newtopic;
+ char *a,*b;
+
+ printf_mysql_query("SELECT `channel_exttopic`, `channel_exttopic_topic`, `channel_topicmask`, `channel_enftopic`, `channel_topicsnarf`, `channel_defaulttopic` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ if(!row[0] || !row[3] || !row[4]) {
+ printf_mysql_query("SELECT `channel_exttopic`, `channel_enftopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'");
+ default_row = mysql_fetch_row(mysql_use());
+ }
+
+ if(row[0] == NULL) {
+ advanced_topic = atoi(default_row[0]);
+ } else
+ advanced_topic = atoi(row[0]);
+ if(argc == 0) {
+ //default topic!
+ putsock(client, "TOPIC %s :%s", chan->name, row[5]);
+ reply(getTextBot(), user, "NS_TOPIC_DONE", row[5]);
+ logEvent(event);
+ return;
+ }
+ int uaccess = getChannelAccess(user, chan, 0);
+ if(uaccess >= atoi((row[3] ? row[3] : default_row[1]))) {
+ //just set the topic
+ newtopic = merge_argv(argv, 0, argc);
+ if(uaccess >= atoi((row[4] ? row[4] : default_row[2]))) {
+ //set the default topic
+ printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(newtopic), chan->channel_id);
+ }
+ putsock(client, "TOPIC %s :%s", chan->name, newtopic);
+ reply(getTextBot(), user, "NS_TOPIC_DONE", newtopic);
+ logEvent(event);
+ return;
+ }
+ if(advanced_topic) {
+ char *advtopics[ADVANCEDTOPIC_MAXID];
+ int topic_id = 0;
+ topic_id = atoi(argv[0]);
+ if(!topic_id || topic_id > ADVANCEDTOPIC_MAXID) {
+ reply(getTextBot(), user, "NS_EXTTOPIC_INVALID_ID", argv[0]);
+ return;
+ }
+ //parse topics
+ i = 0;
+ b = row[1];
+ while((a = strstr(b, "\n")) != NULL) {
+ *a = '\0';
+ if(i == ADVANCEDTOPIC_MAXID-1) break;
+ advtopics[i++] = b;
+ b = a+1;
+ }
+ advtopics[i++] = b;
+ for(;i < ADVANCEDTOPIC_MAXID;i++)
+ advtopics[i] = "";
+ if(argc < 2) {
+ //just show the topic with this id
+ reply(getTextBot(), user, "NS_EXTTOPIC_TOPICID", topic_id, advtopics[topic_id-1]);
+ return;
+ }
+ newtopic = merge_argv(argv, 1, argc);
+ if(!strcmp(newtopic, "*"))
+ newtopic = "";
+ advtopics[topic_id-1] = newtopic;
+ char topiclist[MAXLEN*2];
+ topiclist[0] = '\0';
+ int topiclistpos = 0;
+ for(i = 0; i < ADVANCEDTOPIC_MAXID; i++) {
+ if(topiclistpos + strlen(advtopics[i]) + 2 >= MAXLEN) break;
+ topiclistpos += sprintf(topiclist+topiclistpos, (i ? "\n%s" : "%s"), advtopics[i]);
+ }
+ printf_mysql_query("UPDATE `channels` SET `channel_exttopic_topic` = '%s' WHERE `channel_id` = '%d'", escape_string(topiclist), chan->channel_id);
+ //now build the new topic and set it...
+ topiclistpos = 0;
+ b = row[2];
+ while((a = strstr(b, "%")) != NULL) {
+ *a = '\0';
+ if(isdigit(a[1]) && a[1] - 48 > 0) {
+ topiclistpos += sprintf(topiclist + topiclistpos, "%s%s", b, advtopics[a[1] - 49]);
+ b = a+2;
+ } else {
+ topiclistpos += sprintf(topiclist + topiclistpos, "%s%%", b);
+ b = a+1;
+ }
+ }
+ topiclistpos += sprintf(topiclist + topiclistpos, "%s", b);
+ if(topiclistpos > MAXLEN)
+ topiclist[MAXLEN] = '\0';
+ putsock(client, "TOPIC %s :%s", chan->name, topiclist);
+ reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist);
+ logEvent(event);
+ } else {
+ newtopic = merge_argv(argv, 0, argc);
+ char topiclist[MAXLEN*2];
+ topiclist[0] = '\0';
+ int topiclistpos = 0;
+ b = row[2];
+ while((a = strstr(b, "*")) != NULL) {
+ *a = '\0';
+ topiclistpos += sprintf(topiclist + topiclistpos, "%s%s", b, newtopic);
+ b = a+1;
+ }
+ topiclistpos += sprintf(topiclist + topiclistpos, "%s", b);
+ if(topiclistpos > MAXLEN)
+ topiclist[MAXLEN] = '\0';
+ putsock(client, "TOPIC %s :%s", chan->name, topiclist);
+ reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist);
+ logEvent(event);
+ }
+}
+
+#undef ADVANCEDTOPIC_MAXID
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+#define NS_TRACE_CRITERIA_AUTHED 0x01
+#define NS_TRACE_CRITERIA_NUMCHAN 0x02
+
+struct neonserv_cmd_trace_criteria {
+ char *mask;
+ char *nick;
+ char *ident;
+ char *host;
+ char *account;
+ unsigned int flags : 4;
+ unsigned int authed : 1;
+ unsigned int used_channel : 5; //32 max
+ char *channel[10];
+ unsigned int numchannels;
+ unsigned int limit : 16;
+};
+
+CMD_BIND(neonserv_cmd_trace) {
+ //ok parse the criterias
+ struct neonserv_cmd_trace_criteria *criteria = malloc(sizeof(*criteria));
+ if (!criteria) {
+ perror("malloc() failed");
+ return;
+ }
+ memset(criteria, 0, sizeof(*criteria));
+ criteria->limit = 50;
+ int i, show_user = 0;
+ if(!stricmp(argv[0], "print")) {
+ show_user = 1;
+ }
+ for(i = 1; i < argc; i += 2) {
+ if(argc <= i+1) {
+ reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT");
+ return;
+ }
+ if(!stricmp(argv[i], "mask")) criteria->mask = argv[i+1];
+ else if(!stricmp(argv[i], "nick")) criteria->nick = argv[i+1];
+ else if(!stricmp(argv[i], "ident")) criteria->ident = argv[i+1];
+ else if(!stricmp(argv[i], "host")) criteria->host = argv[i+1];
+ else if(!stricmp(argv[i], "account")) criteria->account = argv[i+1];
+ else if(!stricmp(argv[i], "authed")) {
+ if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) {
+ criteria->authed = 1;
+ } else if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) {
+ criteria->authed = 0;
+ } else {
+ reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[i+1]);
+ return;
+ }
+ criteria->flags |= NS_TRACE_CRITERIA_AUTHED;
+ }
+ else if(!stricmp(argv[i], "channel")) criteria->channel[criteria->used_channel++] = argv[i+1];
+ else if(!stricmp(argv[i], "numchannels")) {
+ criteria->numchannels = atoi(argv[i+1]);
+ criteria->flags |= NS_TRACE_CRITERIA_NUMCHAN;
+ }
+ else if(!stricmp(argv[i], "limit")) {
+ criteria->limit = atoi(argv[i+1]);
+ }
+ }
+ char tmp[MAXLEN];
+ int matches = 0;
+ struct UserNode *cuser;
+ reply(getTextBot(), user, "NS_TRACE_HEADER");
+ for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) {
+ if(show_user && matches == criteria->limit) {
+ //too many
+ break;
+ }
+ if(criteria->mask) {
+ sprintf(tmp, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
+ if(match(criteria->mask, tmp)) continue;
+ }
+ if(criteria->nick && match(criteria->nick, cuser->nick)) continue;
+ if(criteria->ident && match(criteria->ident, cuser->ident)) continue;
+ if(criteria->host && match(criteria->host, cuser->host)) continue;
+ if(criteria->account && (!(cuser->flags & USERFLAG_ISAUTHED) || match(criteria->account, cuser->auth))) continue;
+ if((criteria->flags & NS_TRACE_CRITERIA_AUTHED) && (criteria->authed ^ (cuser->flags & USERFLAG_ISAUTHED))) continue;
+ if((criteria->flags & NS_TRACE_CRITERIA_NUMCHAN)) {
+ int ccount = 0;
+ struct ChanUser *chanuser;
+ for(chanuser = getUserChannels(cuser, NULL); chanuser; chanuser = getUserChannels(cuser, chanuser))
+ ccount++;
+ if(ccount < criteria->numchannels)
+ continue;
+ }
+ matches++;
+ //output
+ if(show_user) {
+ reply(getTextBot(), user, "%s!%s@%s %s", cuser->nick, cuser->ident, cuser->host, ((cuser->flags & USERFLAG_ISAUTHED) ? cuser->auth : "*"));
+ }
+ }
+ reply(getTextBot(), user, "NS_TABLE_COUNT", matches);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] target (format: minaccess-maxaccess/users/bans)
+* argv[1] duration
+*/
+static USERLIST_CALLBACK(neonserv_cmd_trim_userlist_lookup);
+static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int min_access, int max_access, int duration);
+
+struct neonserv_cmd_trim_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ int min_access;
+ int max_access;
+ int duration;
+};
+
+CMD_BIND(neonserv_cmd_trim) {
+ if(stricmp(argv[0], "bans") && !checkChannelAccess(user, chan, "channel_candel", 0, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_ACCESS_DENIED");
+ return;
+ }
+ }
+ int min_access, max_access;
+ if(!stricmp(argv[0], "users")) {
+ min_access = 1;
+ max_access = getChannelAccess(user, chan, 0) - 1;
+ } else if(!stricmp(argv[0], "bans")) {
+ if(!checkChannelAccess(user, chan, "channel_staticban", 0, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_ACCESS_DENIED");
+ return;
+ }
+ }
+ //TODO: TRIM BANS
+ return;
+ } else {
+ char *seperator = strstr(argv[0], "-");
+ if(seperator) {
+ *seperator = '\0';
+ seperator++;
+ min_access = atoi(argv[0]);
+ max_access = atoi(seperator);
+ if(max_access < min_access) {
+ reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access);
+ return;
+ }
+ } else {
+ min_access = atoi(argv[0]);
+ max_access = min_access;
+ }
+ if(max_access >= getChannelAccess(user, chan, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(getTextBot(), user, "NS_NO_ACCESS");
+ return;
+ }
+ }
+ }
+ //parse duration...
+ int duration = strToTime(user, argv[1]);
+ if(duration < 30) {
+ reply(getTextBot(), user, "NS_TRIM_DURATION_TOO_SHORT", 30);
+ return;
+ }
+ struct neonserv_cmd_trim_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->min_access = min_access;
+ cache->max_access = max_access;
+ cache->duration = duration;
+ get_userlist_with_invisible(chan, neonserv_cmd_trim_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_trim_userlist_lookup) {
+ struct neonserv_cmd_trim_cache *cache = data;
+ //got userlist
+ neonserv_cmd_trim_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->min_access, cache->max_access, cache->duration);
+ free(cache);
+}
+
+static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int min_access, int max_access, int duration) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int trim_count = 0, is_here;
+ struct ChanUser *chanuser;
+ printf_mysql_query("SELECT `chanuser_seen`, `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access);
+ res = mysql_use();
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ if(!strcmp(row[0], "0") || time(0) - atoi(row[0]) >= duration) {
+ //check if the user is currently in the channel
+ is_here = 0;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if((chanuser->user->flags & USERFLAG_ISAUTHED) && !strcmp(chanuser->user->auth, row[1])) {
+ is_here = 1;
+ break;
+ }
+ }
+ if(!is_here) {
+ //delete the user
+ trim_count++;
+ printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[2]);
+ }
+ }
+ }
+ char timeBuf[MAXLEN];
+ reply(getTextBot(), user, "NS_TRIM_DONE", trim_count, min_access, max_access, chan->name, timeToStr(user, duration, 3, timeBuf));
+ if(trim_count)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nick[,*auth[,*!*@mask[...]]]
+*/
+struct neonserv_cmd_unban_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ struct ModeBuffer *modeBuf;
+ int provided_masks, done_masks, pending_whos, unbanned_masks;
+};
+
+static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup);
+static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user);
+static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask);
+static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache);
+
+CMD_BIND(neonserv_cmd_unban) {
+ char *mask, *nextmask;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ nextmask = merge_argv_char(argv, 0, argc, ',');
+ struct neonserv_cmd_unban_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->modeBuf = modeBuf;
+ cache->done_masks = 0;
+ cache->provided_masks = 0;
+ cache->unbanned_masks = 0;
+ while((mask = nextmask)) {
+ nextmask = strstr(mask, ",");
+ if(nextmask) {
+ *nextmask = '\0';
+ nextmask++;
+ }
+ cache->provided_masks++;
+ if(is_valid_nick(mask)) {
+ struct UserNode *cuser = getUserByNick(mask);
+ if(!cuser) {
+ cuser = createTempUser(mask);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ get_userauth(cuser, neonserv_cmd_unban_userauth_lookup, cache);
+ cache->pending_whos++;
+ } else {
+ neonserv_cmd_unban_nick(cache, cuser);
+ }
+ } else {
+ neonserv_cmd_unban_mask(cache, mask);
+ }
+ }
+ if(!cache->pending_whos)
+ neonserv_cmd_unban_finish(cache);
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup) {
+ struct neonserv_cmd_unban_cache *cache = data;
+ cache->pending_whos--;
+ if(user)
+ neonserv_cmd_unban_nick(cache, user);
+ else
+ neonserv_cmd_unban_mask(cache, user_nick);
+ if(!cache->pending_whos)
+ neonserv_cmd_unban_finish(cache);
+}
+
+static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user) {
+ int matches = 0;
+ struct BanNode *ban;
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
+ for(ban = cache->chan->bans; ban; ban = ban->next) {
+ if(!match(ban->mask, usermask)) {
+ modeBufferUnban(cache->modeBuf, ban->mask);
+ cache->unbanned_masks++;
+ matches++;
+ }
+ }
+ if(matches)
+ cache->done_masks++;
+}
+
+static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask) {
+ char banmask[NICKLEN+USERLEN+HOSTLEN+3];
+ int matches = 0;
+ struct BanNode *ban;
+ mask = make_banmask(mask, banmask);
+ for(ban = cache->chan->bans; ban; ban = ban->next) {
+ if(!match(mask, ban->mask)) {
+ modeBufferUnban(cache->modeBuf, ban->mask);
+ cache->unbanned_masks++;
+ matches++;
+ }
+ }
+ if(matches)
+ cache->done_masks++;
+ else {
+ for(ban = cache->chan->bans; ban; ban = ban->next) {
+ if(!match(ban->mask, mask)) {
+ reply(cache->textclient, cache->user, "NS_DELBAN_BANNED_BY", mask, ban->mask);
+ break;
+ }
+ }
+ }
+}
+
+static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache) {
+ freeModeBuffer(cache->modeBuf);
+ if(cache->done_masks == cache->provided_masks)
+ reply(cache->textclient, cache->user, "NS_UNBAN_DONE", cache->unbanned_masks, cache->chan->name);
+ else
+ reply(cache->textclient, cache->user, "NS_UNBAN_FAIL", cache->client->user->nick);
+ if(cache->done_masks)
+ logEvent(cache->event);
+ free(cache);
+}
+
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nothing
+*/
+
+CMD_BIND(neonserv_cmd_unbanall) {
+ struct ModeBuffer *modeBuf;
+ int bans = 0;
+ struct BanNode *ban;
+ modeBuf = initModeBuffer(client, chan);
+ for(ban = chan->bans; ban; ban = ban->next) {
+ modeBufferUnban(modeBuf, ban->mask);
+ bans++;
+ }
+ freeModeBuffer(modeBuf);
+ if(bans) {
+ reply(getTextBot(), user, "NS_UNBANALL_DONE", bans, chan->name);
+ logEvent(event);
+ } else
+ reply(getTextBot(), user, "NS_UNBANALL_FAIL", client->user->nick, chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nothing
+*/
+
+CMD_BIND(neonserv_cmd_unbanme) {
+ struct ModeBuffer *modeBuf;
+ int bans = 0;
+ struct BanNode *ban;
+ modeBuf = initModeBuffer(client, chan);
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
+ for(ban = chan->bans; ban; ban = ban->next) {
+ if(!match(ban->mask, usermask)) {
+ modeBufferUnban(modeBuf, ban->mask);
+ bans++;
+ }
+ }
+ freeModeBuffer(modeBuf);
+ if(bans) {
+ reply(getTextBot(), user, "NS_UNBANME_DONE", bans, chan->name);
+ logEvent(event);
+ } else
+ reply(getTextBot(), user, "NS_UNBANME_FAIL", client->user->nick, usermask);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] command name
+*/
+
+CMD_BIND(neonserv_cmd_unbind) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `id` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0]));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]);
+ return;
+ }
+ unbind_cmd(client->botid, argv[0]);
+ printf_mysql_query("DELETE FROM `bot_binds` WHERE `id` = '%s'", row[0]);
+ reply(getTextBot(), user, "NS_UNBIND_DONE", argv[0]);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - channel
+*/
+CMD_BIND(neonserv_cmd_unregister) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ char *channel = argv[0];
+ if(!is_valid_chan(channel)) {
+ reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
+ return;
+ }
+ int chanid;
+ printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chanid = atoi(row[0]);
+ } else {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick);
+ return;
+ }
+ int botid = atoi(row[0]);
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == botid)
+ break;
+ }
+ if(bot && strcmp(row[2], "1")) {
+ putsock(bot, "PART %s :Channel unregistered.", channel);
+ }
+ printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]);
+ reply(getTextBot(), user, "NS_UNREGISTER_DONE", channel);
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup);
+static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
+
+struct neonserv_cmd_unsuspend_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+};
+
+CMD_BIND(neonserv_cmd_unsuspend) {
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
+ } else {
+ struct neonserv_cmd_unsuspend_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_unsuspend_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup) {
+ struct neonserv_cmd_unsuspend_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_unsuspend_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid, cflags;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(textclient, user, "NS_USER_OUTRANKED", nick);
+ return;
+ }
+ }
+ //unsuspend
+ cflags = atoi(row[2]);
+ if(!(cflags & DB_CHANUSER_SUSPENDED)) {
+ reply(textclient, user, "NS_SUSPEND_NOT", nick);
+ return;
+ }
+ cflags &= ~DB_CHANUSER_SUSPENDED;
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", cflags, row[1]);
+ reply(textclient, user, "NS_SUSPEND_RESTORED", nick, chan->name);
+ logEvent(event);
+ return;
+ }
+ }
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no arguments
+*/
+
+CMD_BIND(neonserv_cmd_up) {
+ struct ChanUser *chanuser = getChanUser(user, chan);
+ if(!chanuser) {
+ reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name);
+ return;
+ }
+ check_mysql();
+ loadChannelSettings(chan);
+ MYSQL_RES *res, *default_res;
+ MYSQL_ROW row, default_row;
+ int chan_getop, chan_getvoice, caccess;
+ printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return;
+ if(!row[0] || !row[1]) {
+ printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
+ default_res = mysql_use();
+ if ((default_row = mysql_fetch_row(default_res)) == NULL) return;
+ chan_getop = (row[0] ? atoi(row[0]) : atoi(default_row[0]));
+ chan_getvoice = (row[1] ? atoi(row[1]) : atoi(default_row[1]));
+ } else {
+ chan_getop = atoi(row[0]);
+ chan_getvoice = atoi(row[1]);
+ }
+ caccess = getChannelAccess(user, chan, 1);
+ if(caccess >= chan_getop) {
+ if(!(chanuser->flags & CHANUSERFLAG_OPPED)) {
+ putsock(client, "MODE %s +o %s", chan->name, user->nick);
+ logEvent(event);
+ } else
+ reply(getTextBot(), user, "NS_UP_ALREADY_OP", chan->name);
+ } else if(caccess >= chan_getvoice) {
+ if(!(chanuser->flags & CHANUSERFLAG_VOICED)) {
+ putsock(client, "MODE %s +v %s", chan->name, user->nick);
+ logEvent(event);
+ } else
+ reply(getTextBot(), user, "NS_UP_ALREADY_VOICE", chan->name);
+ } else
+ reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no arguments
+*/
+
+CMD_BIND(neonserv_cmd_upall) {
+ MYSQL_RES *res, *default_res;
+ MYSQL_ROW row, default_row;
+ struct ChanUser *chanuser;
+ int userid, chan_getop, chan_getvoice, caccess;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", user->auth);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL)
+ return;
+ userid = atoi(row[0]);
+ printf_mysql_query("SELECT `chanuser_access`, `channel_getop`, `channel_getvoice`, `channel_name`, `channel_id` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d'", userid);
+ res = mysql_use();
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ chan = getChanByName(row[3]);
+ if(!chan) continue;
+ printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%s' AND `botclass` = '%d'", row[4], client->botid);
+ if (mysql_fetch_row(mysql_use()) == NULL) continue;
+ if(!(chanuser = getChanUser(user, chan))) continue;
+ if(!row[1] || !row[2]) {
+ printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
+ default_res = mysql_use();
+ if ((default_row = mysql_fetch_row(default_res)) == NULL) return;
+ chan_getop = (row[1] ? atoi(row[1]) : atoi(default_row[0]));
+ chan_getvoice = (row[2] ? atoi(row[2]) : atoi(default_row[1]));
+ } else {
+ chan_getop = atoi(row[1]);
+ chan_getvoice = atoi(row[2]);
+ }
+ caccess = atoi(row[0]);
+ int done = 0;
+ if(caccess >= chan_getop) {
+ if(!(chanuser->flags & CHANUSERFLAG_OPPED)) {
+ putsock(client, "MODE %s +o %s", chan->name, user->nick);
+ done = 1;
+ }
+ } else if(caccess >= chan_getvoice) {
+ if(!(chanuser->flags & CHANUSERFLAG_VOICED)) {
+ putsock(client, "MODE %s +v %s", chan->name, user->nick);
+ done = 1;
+ }
+ }
+ if(done) {
+ event->chan = chan;
+ logEvent(event);
+ }
+ }
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - usermask
+* argv[1] - min access
+* argv[2] - max access
+*/
+static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup);
+static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access);
+
+struct neonserv_cmd_users_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ char *usermask;
+ int min_access;
+ int max_access;
+};
+
+CMD_BIND(neonserv_cmd_users) {
+ int min_access = 1, max_access = 500;
+ char *usermask = NULL;
+ if(argc > 0)
+ usermask = argv[0];
+ if(argc > 2) {
+ min_access = atoi(argv[1]);
+ max_access = atoi(argv[2]);
+ }
+ struct neonserv_cmd_users_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->usermask = (usermask ? strdup(usermask) : NULL);
+ cache->min_access = min_access;
+ cache->max_access = max_access;
+ get_userlist_with_invisible(chan, neonserv_cmd_users_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup) {
+ struct neonserv_cmd_users_cache *cache = data;
+ neonserv_cmd_users_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access);
+ if(cache->usermask)
+ free(cache->usermask);
+ free(cache);
+}
+
+static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int content_count = 0, cflags, is_here, caccess, i;
+ char seenstr[MAXLEN];
+ struct Table *table;
+ struct ChanUser *chanuser;
+ printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_seen`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id);
+ res = mysql_use();
+ table = table_init(4, mysql_num_rows(res) + 1, 0);
+ if(usermask)
+ reply(textclient, user, "NS_USERS_HEADER_MATCH", chan->name, min_access, max_access, usermask);
+ else
+ reply(textclient, user, "NS_USERS_HEADER", chan->name, min_access, max_access);
+ char *content[4];
+ content[0] = get_language_string(user, "NS_USERS_HEADER_ACCESS");
+ content[1] = get_language_string(user, "NS_USERS_HEADER_ACCOUNT");
+ content[2] = get_language_string(user, "NS_USERS_HEADER_SEEN");
+ content[3] = get_language_string(user, "NS_USERS_HEADER_STATE");
+ table_add(table, content);
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ caccess = atoi(row[0]);
+ if((!usermask || !match(usermask, row[1])) && caccess >= min_access && caccess <= max_access) {
+ content[0] = row[0];
+ content[1] = row[1];
+ is_here = 0;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if((chanuser->user->flags & USERFLAG_ISAUTHED) && !strcmp(chanuser->user->auth, row[1])) {
+ if((chanuser->flags & CHANUSERFLAG_INVISIBLE))
+ is_here = 2;
+ else {
+ is_here = 1;
+ break;
+ }
+ }
+ }
+ if(is_here) {
+ content[2] = get_language_string(user, (is_here == 2 ? "NS_USERS_SEEN_INVISIBLE" : "NS_USERS_SEEN_HERE"));
+ } else if(!strcmp(row[2], "0")) {
+ content[2] = get_language_string(user, "NS_USERS_SEEN_NEVER");
+ } else {
+ timeToStr(user, (time(0) - atoi(row[2])), 2, seenstr);
+ content[2] = seenstr; //generate time
+ }
+ cflags = atoi(row[3]);
+ if(cflags & DB_CHANUSER_SUSPENDED)
+ content[3] = get_language_string(user, "NS_USERS_STATE_SUSPENDED");
+ else
+ content[3] = get_language_string(user, "NS_USERS_STATE_NORMAL");
+ content_count++;
+ table_add(table, content);
+ }
+ }
+ //send the table
+ char **table_lines = table_end(table);
+ for(i = 0; i < table->entrys; i++) {
+ reply(textclient, user, table_lines[i]);
+ }
+ if(!content_count)
+ reply(textclient, user, "NS_TABLE_NONE");
+ if(usermask || min_access != 1 || max_access != 500)
+ reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_MATCH_1" : "NS_USERS_COUNT_MATCH"), table->length - 1, chan->name, content_count);
+ else
+ reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_1" : "NS_USERS_COUNT"), table->length - 1, chan->name);
+ table_free(table);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+CMD_BIND(neonserv_cmd_uset) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ loadUserSettings(user);
+ if(argc > 0) {
+ if(!stricmp(argv[0], "language")) {
+ struct language* lang;
+ if(argc > 1) {
+ if((lang = get_language_by_tag(argv[1])) == NULL && (lang = get_language_by_name(argv[1])) == NULL) {
+ lang = user->language;
+ } else {
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ printf_mysql_query("UPDATE `users` SET `user_lang` = '%s' WHERE `user_id` = '%s'", escape_string(lang->langtag), row[0]);
+ } else {
+ printf_mysql_query("INSERT INTO `users` (`user_user`, `user_lang`) VALUES ('%s', '%s')", escape_string(user->auth), escape_string(lang->langtag));
+ }
+ struct UserNode *cuser;
+ for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) {
+ if((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))
+ cuser->language = lang;
+ }
+ }
+ } else
+ lang = user->language;
+ reply(getTextBot(), user, "\002Language \002%s", lang->langname);
+ char tmp[MAXLEN];
+ int tmppos = 0;
+ lang = get_default_language();
+ tmppos = sprintf(tmp, "%s (%s)", lang->langname, lang->langtag);
+ printf_mysql_query("SELECT `lang`,`text` FROM `language` WHERE `ident` = 'name'");
+ res = mysql_use();
+ while((row = mysql_fetch_row(res)) != NULL) {
+ tmppos += sprintf(tmp + tmppos, ", %s (%s)", row[1], row[0]);
+ }
+ reply(getTextBot(), user, " %s", tmp);
+ } else if(!stricmp(argv[0], "noinvite") && chan) {
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
+ reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED");
+ return;
+ }
+ printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ int noinvite = (row ? 1 : 0);
+ if(argc > 1) {
+ if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) {
+ if(noinvite) {
+ printf_mysql_query("DELETE FROM `noinvite` WHERE `id` = '%s'", row[0]);
+ noinvite = 0;
+ }
+ } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) {
+ if(!noinvite) {
+ int userid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ } else {
+ printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(user->auth));
+ userid = (int) mysql_insert_id(mysql_conn);
+ }
+ printf_mysql_query("INSERT INTO `noinvite` (`uid`, `cid`) VALUES ('%d', '%d')", userid, chan->channel_id);
+ noinvite = 1;
+ }
+ }
+ }
+ reply(getTextBot(), user, "\002NoInvite \002%s", (noinvite ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
+ } else if((!stricmp(argv[0], "autoinvite") || !stricmp(argv[0], "noautoop") || !stricmp(argv[0], "info")) && chan) {
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
+ reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED");
+ return;
+ }
+ printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ if(row) {
+ int flags = atoi(row[0]);
+ if(!stricmp(argv[0], "autoinvite")) {
+ int getInvite = 0;
+ if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite")))
+ getInvite = 1;
+ else if(row[3] && atoi(row[2]) >= atoi(row[3]))
+ getInvite = 1;
+ if(getInvite && argc > 1) {
+ if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) {
+ if(flags & DB_CHANUSER_AUTOINVITE) {
+ flags &= ~DB_CHANUSER_AUTOINVITE;
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
+ }
+ } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) {
+ if(!(flags & DB_CHANUSER_AUTOINVITE)) {
+ flags |= DB_CHANUSER_AUTOINVITE;
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
+ }
+ }
+ }
+ if(getInvite)
+ reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
+ else
+ reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS"));
+ } else if(!stricmp(argv[0], "noautoop")) {
+ if(argc > 1) {
+ if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) {
+ if(flags & DB_CHANUSER_NOAUTOOP) {
+ flags &= ~DB_CHANUSER_NOAUTOOP;
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
+ }
+ } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) {
+ if(!(flags & DB_CHANUSER_NOAUTOOP)) {
+ flags |= DB_CHANUSER_NOAUTOOP;
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]);
+ }
+ }
+ }
+ reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
+ } else if(!stricmp(argv[0], "info")) {
+ char *infoline;
+ if(argc > 1) {
+ infoline = merge_argv(argv, 1, argc);
+ if(!strcmp(infoline, "*"))
+ infoline = "";
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_infoline` = '%s' WHERE `chanuser_id` = '%s'", escape_string(infoline), row[4]);
+ } else
+ infoline = row[1];
+ reply(getTextBot(), user, "\002Info \002%s", infoline);
+ }
+ } else
+ reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan);
+ } else
+ reply(getTextBot(), user, "NS_USET_UNKNOWN_SETTING", argv[0]);
+ } else {
+ //view all options
+ reply(getTextBot(), user, "NS_USET_GLOBAL");
+ reply(getTextBot(), user, "\002Language \002%s", user->language->langname);
+ if(!chan) return;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
+ reply(getTextBot(), user, "NS_USET_CHANNEL");
+ printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ reply(getTextBot(), user, "\002NoInvite \002%s", (row ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
+ printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ row = mysql_fetch_row(res);
+ if(row) {
+ int flags = atoi(row[0]);
+ int getInvite = 0;
+ if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite")))
+ getInvite = 1;
+ else if(row[3] && atoi(row[2]) >= atoi(row[3]))
+ getInvite = 1;
+ if(getInvite)
+ reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
+ else
+ reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS"));
+ reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF")));
+ reply(getTextBot(), user, "\002Info \002%s", row[1]);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* no args
+*/
+
+CMD_BIND(neonserv_cmd_version) {
+ reply(getTextBot(), user, "\002NeonServ " NEONSERV_VERSION "\002 (%s), written by pk910", (strcmp(revision, "") ? revision : "-"));
+ reply(getTextBot(), user, "Build (#%s) %s (%s lines, " COMPILER ")", compilation, creation, codelines);
+ reply(getTextBot(), user, "NeonServ source can be found on: http://git.pk910.de/?p=NeonServV5.git");
+ //helpers :D
+ reply(getTextBot(), user, "special thanks to:");
+ reply(getTextBot(), user, " Zer0n, TeaTow (testing and ideas current version)");
+ reply(getTextBot(), user, " Buchman, Zer0n (translating current version)");
+ reply(getTextBot(), user, " Patschi95, DerGrinch, Darkfly, Zer0n, Buschman (testing and ideas older versions)");
+ reply(getTextBot(), user, " Buschman, Georg, richard (translating older versions)");
+ reply(getTextBot(), user, "and all the other users that reported all these nasty bugs :D");
+ reply(getTextBot(), user, "\002If you found a bug or if you have a good idea report it on http://bugtrack.pk910.de/git_view.php?p=NeonServV5.git\002");
+
+}
\ No newline at end of file
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*] nicks
+*/
+static USERLIST_CALLBACK(neonserv_cmd_voice_userlist_lookup);
+static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks);
+
+struct neonserv_cmd_voice_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *nicks;
+};
+
+CMD_BIND(neonserv_cmd_voice) {
+ struct neonserv_cmd_voice_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ cache->nicks = strdup(merge_argv(argv, 0, argc));
+ get_userlist_with_invisible(chan, neonserv_cmd_voice_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_voice_userlist_lookup) {
+ struct neonserv_cmd_voice_cache *cache = data;
+ neonserv_cmd_voice_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks);
+ free(cache->nicks);
+ free(cache);
+}
+
+static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks) {
+ int total_users = 0, done_users = 0;
+ struct UserNode *cuser;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ char *a, *b = nicks;
+ do {
+ a = strstr(b, " ");
+ if(a) *a = '\0';
+ total_users++;
+ cuser = searchUserByNick(b);
+ if(!cuser) {
+ //check for an invisible user
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(!stricmp(chanuser->user->nick, b)) {
+ cuser = chanuser->user;
+ break;
+ }
+ }
+ if(!cuser) continue;
+ } else {
+ chanuser = getChanUser(cuser, chan);
+ if(!chanuser) continue;
+ }
+ done_users++;
+ if(chanuser->flags & CHANUSERFLAG_VOICED) continue;
+ modeBufferVoice(modeBuf, b);
+ if(a) {
+ b = a+1;
+ }
+ } while(a);
+ freeModeBuffer(modeBuf);
+ if(done_users == total_users)
+ reply(textclient, user, "NS_VOICE_DONE", chan->name);
+ else
+ reply(textclient, user, "NS_VOICE_FAIL", client->user->nick);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] (optional) nick mask
+*/
+static USERLIST_CALLBACK(neonserv_cmd_voiceall_userlist_lookup);
+static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask);
+
+struct neonserv_cmd_voiceall_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct Event *event;
+ char *nickmask;
+};
+
+CMD_BIND(neonserv_cmd_voiceall) {
+ struct neonserv_cmd_voiceall_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->event = event;
+ if(argc > 0) {
+ cache->nickmask = strdup(argv[0]);
+ } else
+ cache->nickmask = NULL;
+ get_userlist_with_invisible(chan, neonserv_cmd_voiceall_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_voiceall_userlist_lookup) {
+ struct neonserv_cmd_voiceall_cache *cache = data;
+ neonserv_cmd_voiceall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask);
+ if(cache->nickmask)
+ free(cache->nickmask);
+ free(cache);
+}
+
+static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask) {
+ int done_users = 0;
+ struct ChanUser *chanuser;
+ struct ModeBuffer *modeBuf;
+ modeBuf = initModeBuffer(client, chan);
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if(nickmask && match(nickmask, chanuser->user->nick)) continue;
+ if(chanuser->flags & CHANUSERFLAG_VOICED) continue;
+ modeBufferVoice(modeBuf, chanuser->user->nick);
+ done_users++;
+ }
+ freeModeBuffer(modeBuf);
+ reply(textclient, user, "NS_VOICEALL_DONE", done_users, chan->name);
+ if(done_users)
+ logEvent(event);
+}
--- /dev/null
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0] - nick / *auth
+*/
+static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup);
+static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth);
+
+struct neonserv_cmd_wipeinfo_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ struct Event *event;
+ char *nick;
+};
+
+CMD_BIND(neonserv_cmd_wipeinfo) {
+ if(argv[0][0] == '*') {
+ //we've got an auth
+ argv[0]++;
+ neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]);
+ } else {
+ struct UserNode *cuser = getUserByNick(argv[0]);
+ if(!cuser) {
+ cuser = createTempUser(argv[0]);
+ cuser->flags |= USERFLAG_ISTMPUSER;
+ }
+ if(cuser->flags & USERFLAG_ISAUTHED) {
+ neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth);
+ } else {
+ struct neonserv_cmd_wipeinfo_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->chan = chan;
+ cache->event = event;
+ cache->nick = strdup(argv[0]);
+ get_userauth(cuser, neonserv_cmd_wipeinfo_nick_lookup, cache);
+ }
+ }
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup) {
+ struct neonserv_cmd_wipeinfo_cache *cache = data;
+ if(!user) {
+ //USER_DOES_NOT_EXIST
+ reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
+ }
+ else if(!(user->flags & USERFLAG_ISAUTHED)) {
+ //USER_NOT_AUTHED
+ reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
+ }
+ else
+ neonserv_cmd_wipeinfo_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth);
+ free(cache->nick);
+ free(cache);
+}
+
+static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) {
+ //we've got a valid auth now...
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int userid;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ //check if the user is already added
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) {
+ if(isGodMode(user)) {
+ event->flags |= CMDFLAG_OPLOG;
+ } else {
+ reply(textclient, user, "NS_USER_OUTRANKED", nick);
+ return;
+ }
+ }
+ //delete
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_infoline` = '' WHERE `chanuser_id` = '%s'", row[1]);
+ reply(textclient, user, "NS_WIPEINFO_DONE", nick, chan->name);
+ logEvent(event);
+ return;
+ }
+ }
+ reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name);
+}
--- /dev/null
+
+#define MYSQL_HOST "127.0.0.1"
+#define MYSQL_PORT 3306
+#define MYSQL_USER "neonserv"
+#define MYSQL_PASS ""
+#define MYSQL_BASE "neonserv"
--- /dev/null
+
+struct neonserv_event_ctcp_cache {
+ struct ClientSocket *client;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ char *command;
+ char *text;
+};
+
+static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup);
+static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text);
+static int neonserv_ctcp(char *buffer, char *command, char *text);
+
+static void neonserv_event_chanctcp(struct UserNode *user, struct ChanNode *chan, char *command, char *text) {
+ struct ClientSocket *client = getBotForChannel(chan);
+ if(!client) return; //we can't "see" this event
+ if(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) return;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
+ if(!(user->flags & USERFLAG_ISAUTHED)) {
+ struct neonserv_event_ctcp_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->user = user;
+ cache->chan = chan;
+ cache->command = strdup(command);
+ cache->text = (text ? strdup(text) : NULL);
+ get_userauth(user, neonserv_event_ctcp_nick_lookup, cache);
+ } else
+ neonserv_event_ctcp_async1(client, user, chan, command, text);
+}
+
+static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup) {
+ struct neonserv_event_ctcp_cache *cache = data;
+ if(user) {
+ neonserv_event_ctcp_async1(cache->client, cache->user, cache->chan, cache->command, cache->text);
+ }
+ free(cache->command);
+ if(cache->text)
+ free(cache->text);
+ free(cache);
+}
+
+static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text) {
+ MYSQL_RES *res;
+ MYSQL_ROW row, defaultrow = NULL, chanuser;
+ int uaccess = 0;
+ printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return;
+ if(!row[0] || !row[1]) {
+ printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ defaultrow = mysql_fetch_row(res);
+ }
+ int ctcpaccess = atoi((row[0] ? row[0] : defaultrow[0]));
+ if((user->flags & USERFLAG_ISAUTHED)) {
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ chanuser = mysql_fetch_row(res);
+ if(chanuser)
+ uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0]));
+ }
+ int duration = 0;
+ char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
+ char *banmask = NULL;
+ char *reason = "disallowed channel CTCP";
+ if(uaccess < ctcpaccess) {
+ switch(atoi((row[1] ? row[1] : defaultrow[1]))) {
+ case 2: //TIMEBAN: 3min
+ duration = 180;
+ case 3: //TIMEBAN: 1h
+ if(!duration)
+ duration = 3600;
+ banmask = generate_banmask(user, banmaskBuf);
+ printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason));
+ int banid = (int) mysql_insert_id(mysql_conn);
+ char nameBuf[MAXLEN];
+ char banidBuf[20];
+ sprintf(nameBuf, "ban_%d", banid);
+ sprintf(banidBuf, "%d", banid);
+ timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
+ case 1: //KICKBAN
+ if(!banmask)
+ banmask = generate_banmask(user, banmaskBuf);
+ putsock(client, "MODE %s +b %s", chan->name, banmask);
+ case 0: //KICK
+ putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason);
+ break;
+ }
+ }
+}
+
+static void neonserv_event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text) {
+ char ctcpBuf[MAXLEN];
+ if(neonserv_ctcp(ctcpBuf, command, text)) {
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->user == target) break;
+ }
+ if(bot)
+ putsock(bot, "NOTICE %s :\001%s\001", user->nick, ctcpBuf);
+ }
+}
+
+static int neonserv_ctcp(char *buffer, char *command, char *text) {
+ if(!stricmp(command, "VERSION")) {
+ sprintf(buffer, "VERSION NeonServ v" NEONSERV_VERSION " by pk910 (%s)", (strcmp(revision, "") ? revision : "-"));
+ return 1;
+ }
+ if(!stricmp(command, "FINGER")) {
+ sprintf(buffer, "FINGER NeonServ v" NEONSERV_VERSION " (%s) build %s lines C code using " COMPILER " (see +netinfo)", (strcmp(revision, "") ? revision : "-"), codelines);
+ return 1;
+ }
+ if(!stricmp(command, "PING")) {
+ sprintf(buffer, "PING %s", (text ? text : "0"));
+ return 1;
+ }
+ if(!stricmp(command, "TIME")) {
+ time_t rawtime;
+ struct tm *timeinfo;
+ char timeBuf[80];
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime(timeBuf, 80, "%c", timeinfo);
+ sprintf(buffer, "TIME %s", timeBuf);
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+
+static void neonserv_event_invite(struct ClientSocket *client, struct UserNode *user, char *channel) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(client, user, "NS_INVITE_FAIL", channel, client->user->nick);
+ return;
+ }
+ int botid = atoi(row[0]);
+ struct ClientSocket *bot;
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == botid)
+ break;
+ }
+ if(bot) {
+ struct ChanNode *chan = getChanByName(channel);
+ if(chan && isUserOnChan(bot->user, chan)) {
+ reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name);
+ } else
+ putsock(bot, "JOIN %s", channel);
+ }
+}
+
--- /dev/null
+
+struct neonserv_event_join_cache {
+ struct ClientSocket *client;
+ struct ChanUser *chanuser;
+};
+
+static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup);
+static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser);
+static TIMEQ_CALLBACK(neonserv_event_join_dynlimit);
+
+static void neonserv_event_join(struct ChanUser *chanuser) {
+ struct UserNode *user = chanuser->user;
+ struct ClientSocket *client = getBotForChannel(chanuser->chan);
+ if(!client) return; //we can't "see" this event
+ if(user->flags & USERFLAG_ISBOT) {
+ putsock(client, "MODE %s +o %s", chanuser->chan->name, chanuser->user->nick);
+ return;
+ }
+ loadChannelSettings(chanuser->chan);
+ if(!(chanuser->chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
+ char *ban;
+ char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+ sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
+ if((ban = getBanAffectingMask(chanuser->chan, usermask)) != NULL && !(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `ban_reason`, `user_user` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d' AND `ban_mask` = '%s'", chanuser->chan->channel_id, escape_string(ban));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ putsock(client, "MODE %s +b %s", chanuser->chan->name, ban);
+ putsock(client, "KICK %s %s :(%s) %s", chanuser->chan->name, chanuser->user->nick, (row[1] ? row[1] : client->user->nick), row[0]);
+ return;
+ }
+ }
+ if(!(user->flags & USERFLAG_ISAUTHED)) {
+ struct neonserv_event_join_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->chanuser = chanuser;
+ get_userauth(user, neonserv_event_join_nick_lookup, cache);
+ } else
+ neonserv_event_join_async1(client, chanuser);
+}
+
+static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup) {
+ struct neonserv_event_join_cache *cache = data;
+ if(user) {
+ neonserv_event_join_async1(cache->client, cache->chanuser);
+ }
+ free(cache);
+}
+
+static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser) {
+ struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid));
+ struct ChanNode *chan = chanuser->chan;
+ struct UserNode *user = chanuser->user;
+ struct ModeBuffer *modeBuf;
+ MYSQL_RES *res;
+ MYSQL_ROW row, chanuserrow, defaultrow = NULL;
+ printf_mysql_query("SELECT `channel_maxusers`, `channel_greeting`, `channel_usergreeting`, `channel_getop`, `channel_getvoice`, `channel_userinfo`, `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return;
+ if(!row[3] || !row[4]) {
+ printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_userinfo` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ defaultrow = mysql_fetch_row(res);
+ }
+ if(chan->usercount > atoi(row[0])) {
+ //update maxusers
+ printf_mysql_query("UPDATE `channels` SET `channel_maxusers` = '%d' WHERE `channel_id` = '%d'", chan->usercount, chan->channel_id);
+ }
+ if((user->flags & USERFLAG_ISAUTHED)) {
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `chanuser_seen`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ chanuserrow = mysql_fetch_row(res);
+ } else
+ chanuserrow = NULL;
+ int userflags = (chanuserrow ? atoi(chanuserrow[1]) : 0);
+ int uaccess = ((chanuserrow && !(userflags & DB_CHANUSER_SUSPENDED)) ? atoi(chanuserrow[0]) : 0);
+ //GREETING
+ char greeting[MAXLEN];
+ int greetingPos = 0;
+ char *a, *b = (chanuserrow && *row[2] ? row[2] : row[1]);
+ do {
+ if(!b) break;
+ a = strstr(b, "$");
+ if(a) *a = '\0';
+ greetingPos += sprintf(greeting + greetingPos, "%s", b);
+ if(!a) break;
+ switch(a[1]) {
+ case '\0':
+ a = NULL;
+ break;
+ case 'A':
+ greetingPos += sprintf(greeting + greetingPos, "%d", uaccess);
+ break;
+ case 'B':
+ greetingPos += sprintf(greeting + greetingPos, "%s", client->user->nick);
+ break;
+ case 'N':
+ greetingPos += sprintf(greeting + greetingPos, "%s", user->nick);
+ break;
+ case 'H':
+ greetingPos += sprintf(greeting + greetingPos, "%s@%s", user->ident, user->host);
+ break;
+ case 'U':
+ greetingPos += sprintf(greeting + greetingPos, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"));
+ break;
+ default:
+ greeting[greetingPos++] = '$';
+ greeting[greetingPos++] = a[1];
+ break;
+ }
+ if(a)
+ b = a+2;
+ } while(a);
+ if(greetingPos)
+ reply(textclient, user, "[%s] %s", chan->name, greeting);
+ //USER RIGHTS
+ if(!(userflags & DB_CHANUSER_NOAUTOOP)) {
+ int getop = atoi((row[3] ? row[3] : defaultrow[0]));
+ int getvoice = atoi((row[4] ? row[4] : defaultrow[1]));
+ modeBuf = initModeBuffer(client, chan);
+ if(uaccess >= getop && uaccess != 0) { //we disallow auto op for all users
+ modeBufferOp(modeBuf, user->nick);
+ } else if(uaccess >= getvoice) {
+ modeBufferVoice(modeBuf, user->nick);
+ }
+ freeModeBuffer(modeBuf);
+ }
+ //INFOLINE
+ int userinfoaccess = atoi((row[5] ? row[5] : defaultrow[2]));
+ if(chanuserrow && strcmp(chanuserrow[2], "") && uaccess > userinfoaccess) {
+ if(!strcmp(chanuserrow[3], "0") || time(0) - atol(chanuserrow[3]) >= 30) {
+ putsock(client, "PRIVMSG %s :[%s] %s", chan->name, user->nick, chanuserrow[2]);
+ }
+ }
+ //SEEN
+ if(chanuserrow) {
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[4]);
+ }
+ //DYNLIMIT
+ if(row[6] && strcmp(row[6], "0")) {
+ char nameBuf[CHANNELLEN + 10];
+ sprintf(nameBuf, "dynlimit_%s", chan->name);
+ if(!timeq_name_exists(nameBuf)) {
+ //neonserv_event_join_dynlimit
+ timeq_add_name(nameBuf, 30, neonserv_event_join_dynlimit, strdup(chan->name));
+ }
+ }
+ //AUTOINVITE
+ if(chanuserrow && !strcmp(chanuserrow[3], "0") && time(0) - atol(chanuserrow[3]) >= 30) {
+ //TODO: autoinvite
+ }
+}
+
+static TIMEQ_CALLBACK(neonserv_event_join_dynlimit) {
+ char *chanName = data;
+ struct ChanNode *chan = getChanByName(chanName);
+ free(chanName);
+ struct ClientSocket *client = getBotForChannel(chan);
+ if(!client) return;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return;
+ if(row[0] && strcmp(row[0], "0")) {
+ putsock(client, "MODE %s +l %d", chan->name, chan->usercount + atoi(row[0]));
+ }
+}
--- /dev/null
+
+struct neonserv_event_notice_cache {
+ struct ClientSocket *client;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ char *message;
+};
+
+static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup);
+static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message);
+
+static void neonserv_event_channotice(struct UserNode *user, struct ChanNode *chan, char *message) {
+ struct ClientSocket *client = getBotForChannel(chan);
+ if(!client) return; //we can't "see" this event
+ if(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) return;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
+ if(!(user->flags & USERFLAG_ISAUTHED)) {
+ struct neonserv_event_notice_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->user = user;
+ cache->chan = chan;
+ cache->message = strdup(message);
+ get_userauth(user, neonserv_event_notice_nick_lookup, cache);
+ } else
+ neonserv_event_notice_async1(client, user, chan, message);
+}
+
+static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup) {
+ struct neonserv_event_notice_cache *cache = data;
+ if(user) {
+ neonserv_event_notice_async1(cache->client, cache->user, cache->chan, cache->message);
+ }
+ free(cache->message);
+ free(cache);
+}
+
+static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) {
+ MYSQL_RES *res;
+ MYSQL_ROW row, defaultrow = NULL, chanuser;
+ int uaccess = 0;
+ printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return;
+ if(!row[0] || !row[1]) {
+ printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ defaultrow = mysql_fetch_row(res);
+ }
+ int noticeaccess = atoi((row[0] ? row[0] : defaultrow[0]));
+ if((user->flags & USERFLAG_ISAUTHED)) {
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ chanuser = mysql_fetch_row(res);
+ if(chanuser)
+ uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0]));
+ }
+ int duration = 0;
+ char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3];
+ char *banmask = NULL;
+ char *reason = "disallowed channel NOTICE";
+ if(uaccess < noticeaccess) {
+ switch(atoi((row[1] ? row[1] : defaultrow[1]))) {
+ case 2: //TIMEBAN: 3min
+ duration = 180;
+ case 3: //TIMEBAN: 1h
+ if(!duration)
+ duration = 3600;
+ banmask = generate_banmask(user, banmaskBuf);
+ printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason));
+ int banid = (int) mysql_insert_id(mysql_conn);
+ char nameBuf[MAXLEN];
+ char banidBuf[20];
+ sprintf(nameBuf, "ban_%d", banid);
+ sprintf(banidBuf, "%d", banid);
+ timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf));
+ case 1: //KICKBAN
+ if(!banmask)
+ banmask = generate_banmask(user, banmaskBuf);
+ putsock(client, "MODE %s +b %s", chan->name, banmask);
+ case 0: //KICK
+ putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason);
+ break;
+ }
+ }
+}
+
--- /dev/null
+
+static void neonserv_event_part(struct ChanUser *chanuser, char *reason) {
+ struct ChanNode *chan = chanuser->chan;
+ struct UserNode *user = chanuser->user;
+ MYSQL_RES *res;
+ MYSQL_ROW chanuserrow;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
+ if((user->flags & USERFLAG_ISAUTHED)) {
+ printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ if((chanuserrow = mysql_fetch_row(res)) != NULL)
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]);
+ }
+}
--- /dev/null
+
+static void neonserv_event_quit(struct UserNode *user, char *reason) {
+ MYSQL_RES *res;
+ MYSQL_ROW chanuserrow;
+ struct ChanUser *chanuser;
+ if((user->flags & USERFLAG_ISAUTHED)) {
+ for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) {
+ printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `channel_name` = '%s' AND `user_user` = '%s'", escape_string(chanuser->chan->name), escape_string(user->auth));
+ res = mysql_use();
+ if((chanuserrow = mysql_fetch_row(res)) != NULL)
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]);
+ }
+ }
+}
--- /dev/null
+
+struct neonserv_event_topic_cache {
+ struct ClientSocket *client;
+ struct UserNode *user;
+ struct ChanNode *chan;
+ char *new_topic;
+};
+
+static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup);
+static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic);
+
+static void neonserv_event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic) {
+ struct ClientSocket *client = getBotForChannel(chan);
+ if(!client) return; //we can't "see" this event
+ if(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) return;
+ loadChannelSettings(chan);
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
+ if(!(user->flags & USERFLAG_ISAUTHED)) {
+ struct neonserv_event_topic_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->user = user;
+ cache->chan = chan;
+ cache->new_topic = strdup(new_topic);
+ get_userauth(user, neonserv_event_topic_nick_lookup, cache);
+ } else
+ neonserv_event_topic_async1(client, user, chan, new_topic);
+}
+
+static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup) {
+ struct neonserv_event_topic_cache *cache = data;
+ if(user) {
+ neonserv_event_topic_async1(cache->client, cache->user, cache->chan, cache->new_topic);
+ }
+ free(cache->new_topic);
+ free(cache);
+}
+
+static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic) {
+ MYSQL_RES *res;
+ MYSQL_ROW row, defaultrow = NULL, chanuserrow;
+ int uaccess = 0;
+ printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) return;
+ if(!row[0] || !row[1]) {
+ printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'");
+ res = mysql_use();
+ defaultrow = mysql_fetch_row(res);
+ }
+ int changetopic = atoi((row[0] ? row[0] : defaultrow[0]));
+ int topicsnarf = atoi((row[1] ? row[1] : defaultrow[1]));
+ if((user->flags & USERFLAG_ISAUTHED)) {
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
+ res = mysql_use();
+ chanuserrow = mysql_fetch_row(res);
+ if(chanuserrow)
+ uaccess = ((atoi(chanuserrow[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuserrow[0]));
+ }
+ if(uaccess < changetopic) {
+ //undo topic change
+ struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid));
+ struct ChanUser *chanuser = getChanUser(user, chan);
+ if(!chanuser) return; //flying super cow?
+ if(time(0) - chanuser->changeTime > BOTWAR_DETECTION_TIME) {
+ chanuser->changeTime = time(0);
+ chanuser->chageEvents = 1;
+ } else {
+ chanuser->chageEvents++;
+ if(chanuser->chageEvents >= BOTWAR_DETECTION_EVENTS || chanuser->chageEvents < 0) {
+ //BOTWAR!
+ chanuser->changeTime = time(0);
+ if(chanuser->chageEvents > 0) {
+ putsock(client, "NOTICE @%s :%s %s", chan->name, get_language_string(user, "NS_BOTWAR_DETECTED"), (BOTWAR_ALERT_CHAN ? get_language_string(user, "NS_BOTWAR_REPORTED") : ""));
+ if(BOTWAR_ALERT_CHAN) {
+ struct ChanNode *alertchan = getChanByName(BOTWAR_ALERT_CHAN);
+ struct ClientSocket *alertclient;
+ if(alertchan && (alertclient = getBotForChannel(chan)) != NULL) {
+ char msgBuf[MAXLEN];
+ putsock(alertclient, "PRIVMSG %s :%s", alertchan->name, build_language_string(user, msgBuf, "NS_BOTWAR_ALERT", chan->name, user->nick));
+ }
+ }
+ }
+ chanuser->chageEvents = -2;
+ return;
+ }
+ }
+ reply(textclient, user, "NS_TOPIC_ACCESS", chan->name);
+ putsock(client, "TOPIC %s :%s", chan->name, chan->topic);
+ } else if(uaccess >= topicsnarf) {
+ printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(new_topic), chan->channel_id);
+ }
+}
+
--- /dev/null
+#include "lang.h"
+#include "UserNode.h"
+#include "DBHelper.h"
+#include "mysqlConn.h"
+
+#define DEFAULT_LANG_TAG "EN"
+#define DEFAULT_LANG_NAME "English"
+
+static struct language **langdict;
+static struct language *lang_c;
+
+void init_lang() {
+ langdict = calloc(MAXLANGUAGES, sizeof(*langdict));
+}
+
+void free_lang() {
+
+}
+
+void load_languages() {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `lang`, `text` FROM `language` WHERE `ident` = 'name'");
+ res = mysql_use();
+ while((row = mysql_fetch_row(res)) != NULL) {
+ load_language(row[0], row[1]);
+ }
+}
+
+static struct language* add_language(char *langtag, char *langname) {
+ int cindex;
+ for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
+ if(langdict[cindex] == NULL) break;
+ if(!strcmp(langdict[cindex]->langname, langname) || !strcmp(langdict[cindex]->langtag, langtag))
+ return langdict[cindex];
+ }
+ if(cindex == MAXLANGUAGES) return NULL;
+ struct language *lang = malloc(sizeof(*lang));
+ if (!lang) {
+ perror("malloc() failed");
+ return NULL;
+ }
+ lang->langtag = strdup(langtag);
+ lang->langname = strdup(langname);
+ struct language_table **entrys = calloc(27, sizeof(*entrys));
+ lang->entrys = entrys;
+ langdict[cindex] = lang;
+ return lang;
+}
+
+static int get_entry_index(const char *ident) {
+ const char *underscore = strstr(ident, "_");
+ if(!underscore || !(underscore[1] >= 65 && underscore[1] <= 90)) return 26;
+ return (underscore[1] - 'A');
+}
+
+void load_language(char *tag, char *name) {
+ struct language *lang = get_language_by_tag(tag);
+ if(lang == get_default_language()) return;
+ if(lang) {
+ //remove all entrys
+ int cindex;
+ struct language_table *entry, *next;
+ for(cindex = 0; cindex < 27; cindex++) {
+ for(entry = lang->entrys[cindex]; entry; entry = next) {
+ next = entry->next;
+ free(entry->ident);
+ free(entry->text);
+ free(entry);
+ }
+ lang->entrys[cindex] = NULL;
+ }
+ } else
+ lang = add_language(tag, name);
+ if(!lang) return;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `ident`, `text` FROM `language` WHERE `lang` = '%s' AND `ident` != 'name'", escape_string(tag));
+ res = mysql_use();
+ while((row = mysql_fetch_row(res)) != NULL) {
+ register_language_string(lang, row[0], row[1]);
+ }
+}
+
+struct language* get_language_by_tag(char *tag) {
+ int cindex;
+ for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
+ if(langdict[cindex] == NULL) break;
+ if(!stricmp(langdict[cindex]->langtag, tag))
+ return langdict[cindex];
+ }
+ return NULL;
+}
+
+struct language* get_language_by_name(char *name) {
+ int cindex;
+ for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
+ if(langdict[cindex] == NULL) break;
+ if(!stricmp(langdict[cindex]->langname, name))
+ return langdict[cindex];
+ }
+ return NULL;
+}
+
+struct language* get_default_language() {
+ if(lang_c == NULL)
+ lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
+ return lang_c;
+}
+
+void register_default_language_table(const struct default_language_entry *msgtab) {
+ if(lang_c == NULL)
+ lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
+ while(msgtab->ident) {
+ register_language_string(lang_c, msgtab->ident, msgtab->text);
+ msgtab++;
+ }
+}
+
+void register_language_string(struct language *lang, char *ident, char *text) {
+ int cindex = get_entry_index(ident);
+ struct language_table *lang_entry = malloc(sizeof(*lang_entry));
+ if (!lang_entry) {
+ perror("malloc() failed");
+ return;
+ }
+
+ lang_entry->ident = strdup(ident);
+ //replace all:
+ //$b to \002
+ //$k to \003
+ char txt[MAXLEN];
+ strcpy(txt, text);
+ char tmp[MAXLEN];
+ int tmppos = 0;
+ char *a, *b = txt;
+ do {
+ a = strstr(b, "$");
+ if(a) *a = '\0';
+ tmppos += sprintf(tmp + tmppos, "%s", b);
+ if(a) {
+ switch(a[1]) {
+ case 'b':
+ tmp[tmppos++] = '\002';
+ break;
+ case 'k':
+ tmp[tmppos++] = '\003';
+ break;
+ default:
+ //unknown - just write it
+ tmppos += sprintf(tmp + tmppos, "$%c", a[1]);
+ }
+ b = a+2;
+ }
+ } while(a);
+ lang_entry->text = strdup(tmp);
+ lang_entry->next = lang->entrys[cindex];
+ lang->entrys[cindex] = lang_entry;
+}
+
+char *get_language_string(struct UserNode *user, const char* msg_ident) {
+ struct language* lang;
+ if((user->flags & USERFLAG_ISAUTHED)) {
+ loadUserSettings(user);
+ lang = user->language;
+ } else
+ lang = lang_c;
+ int cindex = get_entry_index(msg_ident);
+ struct language_table* entry;
+ for(entry = lang->entrys[cindex]; entry; entry = entry->next) {
+ if(!strcmp(entry->ident, msg_ident))
+ return entry->text;
+ }
+ if(lang == lang_c) return NULL;
+ for(entry = lang_c->entrys[cindex]; entry; entry = entry->next) {
+ if(!strcmp(entry->ident, msg_ident))
+ return entry->text;
+ }
+ return NULL;
+}
+
+char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...) {
+ char *formatStr = get_language_string(user, msg_ident);
+ if(!formatStr) return NULL;
+ if(buffer == NULL) {
+ buffer = (char *)malloc((MAXLEN+1) * sizeof(char));
+ if (!buffer) {
+ perror("malloc() failed");
+ return NULL;
+ }
+ }
+ int pos;
+ va_list arg_list;
+ buffer[0] = '\0';
+ va_start(arg_list, msg_ident);
+ pos = vsnprintf(buffer, MAXLEN - 2, formatStr, arg_list);
+ va_end(arg_list);
+ if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
+ buffer[pos] = '\0';
+ return buffer;
+}
--- /dev/null
+#ifndef _lang_h
+#define _lang_h
+
+#include "main.h"
+
+struct UserNode;
+
+struct default_language_entry {
+ char *ident;
+ char *text;
+};
+
+struct language_table {
+ char *ident;
+ char *text;
+
+ struct language_table *next;
+};
+
+struct language {
+ char *langtag;
+ char *langname;
+ struct language_table **entrys;
+};
+
+void init_lang();
+void free_lang();
+struct language* get_language_by_tag(char *tag);
+struct language* get_language_by_name(char *name);
+struct language* get_default_language();
+void load_languages();
+void load_language(char *tag, char *name);
+void register_language_string(struct language *lang, char *ident, char *text);
+void register_default_language_table(const struct default_language_entry *msgtab);
+char *get_language_string(struct UserNode *user, const char* msg_ident);
+char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "main.h"
+#include "ClientSocket.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "IRCEvents.h"
+#include "IRCParser.h"
+#include "modcmd.h"
+#include "WHOHandler.h"
+#include "bots.h"
+#include "mysqlConn.h"
+#include "HandleInfoHandler.h"
+#include "lang.h"
+#include "tools.h"
+#include "timeq.h"
+#include "EventLogger.h"
+#include "ModeNode.h"
+
+time_t start_time;
+
+void cleanup() {
+ free_sockets();
+ free_parser();
+ free_UserNode();
+ free_ChanNode();
+ free_bind();
+ free_modcmd();
+ free_whoqueue();
+ free_bots();
+ free_mysql();
+ free_handleinfohandler();
+ free_lang();
+}
+
+int main(void)
+{
+ start_time = time(0);
+
+ init_mysql();
+ init_lang();
+ init_parser();
+ init_UserNode();
+ init_ChanNode();
+ init_ModeNode();
+ init_bind();
+ init_modcmd();
+ init_handleinfohandler();
+ init_tools();
+ init_bots();
+
+ load_languages();
+
+ time_t socket_wait;
+ while(1) {
+ socket_wait = time(0) + SOCKET_SELECT_TIME;
+ do {
+ socket_loop(SOCKET_SELECT_TIME);
+ } while(time(0) < socket_wait);
+ timeq_tick();
+ loop_bots();
+ clearTempUsers();
+ destroyEvents();
+ }
+}
+
+int stricmp (const char *s1, const char *s2)
+{
+ if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
+ if (s2 == NULL) return *s1;
+ char c1, c2;
+ while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
+ {
+ if (*s1 == '\0') break;
+ ++s1; ++s2;
+ }
+ return c1 - c2;
+}
+
+int stricmplen (const char *s1, const char *s2, int len)
+{
+ if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
+ if (s2 == NULL) return *s1;
+ char c1, c2;
+ int i = 0;
+ while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
+ {
+ i++;
+ if (*s1 == '\0') break;
+ ++s1; ++s2;
+ if(i == len) break;
+ }
+ return c1 - c2;
+}
+
--- /dev/null
+#ifndef _main_h
+#define _main_h
+
+#define NEONSERV_VERSION "5.0.1-dev"
+
+#include "../mysqlConfig.h"
+#ifndef BOTWAR_ALERT_CHAN
+#define BOTWAR_ALERT_CHAN NULL
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <time.h>
+
+#if __GNUC__
+#define PRINTF_LIKE(M,N) __attribute__((format (printf, M, N)))
+#else
+#define PRINTF_LIKE(M,N)
+#endif
+
+#if __GNUC__ >= 2
+#define UNUSED_ARG(ARG) ARG __attribute__((unused))
+#elif defined(S_SPLINT_S)
+#define UNUSED_ARG(ARG) /*@unused@*/ ARG
+#define const /*@observer@*/ /*@temp@*/
+#else
+#define UNUSED_ARG(ARG) ARG
+#endif
+
+#define STRINGIFY_(x) #x
+#define STRINGIFY(x) STRINGIFY_(x)
+
+#if defined(__GNUC__)
+#if defined(__GNUC_PATCHLEVEL__)
+#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__)
+#else
+#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__)
+#endif
+#elif defined (__IMAGECRAFT__)
+#define COMPILER "ICCAVR"
+#else
+#define COMPILER "Unknown"
+#endif
+
+#define SOCKET_SELECT_TIME 2
+
+#define NICKLEN 30
+#define USERLEN 10
+#define AUTHLEN 32
+#define HOSTLEN 63
+#define REALLEN 50
+#define TOPICLEN 500
+#define CHANNELLEN 200
+#define MAXLEN 512
+#define TRIGGERLEN 50
+#define MAXNUMPARAMS 200 /* maximum number of parameters in one line */
+#define MAXLANGUAGES 5
+#define MAXMODES 6
+#define INVITE_TIMEOUT 30
+#define BOTWAR_DETECTION_TIME 7
+#define BOTWAR_DETECTION_EVENTS 6
+
+//valid nick chars
+#define VALID_NICK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{|}~[\\]^-_`"
+//the first char is a little bit different
+// 0 1 2 3 4 5 6
+// 1234567890123456789012345678901234567890123456789012345678 9012 62
+#define VALID_NICK_CHARS_FIRST "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~[\\]^_`"
+#define VALID_NICK_CHARS_FIRST_LEN 62
+
+#define TEMPUSER_LIST_INDEX VALID_NICK_CHARS_FIRST_LEN
+
+extern time_t start_time;
+
+int stricmp (const char *s1, const char *s2);
+int stricmplen (const char *s1, const char *s2, int len);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "modcmd.h"
+#include "IRCEvents.h"
+#include "IRCParser.h"
+#include "ClientSocket.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "ChanUser.h"
+#include "WHOHandler.h"
+#include "lang.h"
+#include "mysqlConn.h"
+#include "DBHelper.h"
+#include "EventLogger.h"
+
+struct trigger_callback {
+ int botid;
+ trigger_callback_t *func;
+
+ struct trigger_callback *next;
+};
+
+struct command_check_user_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ struct ChanNode *chan, *sent_chan;
+ char **argv;
+ int argc;
+ char *message;
+ struct cmd_binding *cbind;
+};
+
+static struct cmd_binding **cmd_binds;
+static struct cmd_function *cmd_functions = NULL;
+static struct trigger_callback *trigger_callbacks = NULL;
+static struct ClientSocket *tmp_text_client;
+
+static const struct default_language_entry msgtab[] = {
+ {"MODCMD_LESS_PARAM_COUNT", "This command requires more parameters."},
+ {"MODCMD_CHAN_REQUIRED", "You must provide the name of a channel that exists and the bot is on."},
+ {"MODCMD_AUTH_REQUIRED", "You need to be authenticated with AuthServ to use this command."},
+ {"MODCMD_CHAN_SUSPENDED", "This channel is currently suspended."},
+ {"MODCMD_PRIVILEGED", "$b%s$b is a privileged command."}, /* {ARGS: "god"} */
+ {"MODCMD_PUBCMD", "Public commands in $b%s$b are restricted."}, /* {ARGS: "#TestChan"} */
+ {"MODCMD_ACCESS_DENIED", "Access denied."},
+ {NULL, NULL}
+};
+
+static int get_binds_index(char first_char) {
+ if(tolower(first_char) >= 'a' && tolower(first_char) <= 'z') {
+ return tolower(first_char) - 'a';
+ }
+ return 26;
+}
+
+struct ClientSocket* get_prefered_bot(int botid) {
+ struct ClientSocket *client;
+ for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+ if(client->botid == botid && (client->flags & SOCKET_FLAG_PREFERRED))
+ return client;
+ }
+ return NULL;
+}
+
+static char* get_channel_trigger(int botid, struct ChanNode *chan) {
+ struct trigger_cache *trigger;
+ for(trigger = chan->trigger; trigger; trigger = trigger->next) {
+ if(trigger->botid == botid)
+ return trigger->trigger;
+ }
+ struct trigger_callback *cb;
+ for(cb = trigger_callbacks; cb; cb = cb->next) {
+ if(cb->botid == botid)
+ break;
+ }
+ char triggerStr[TRIGGERLEN];
+ if(cb)
+ cb->func(chan, triggerStr);
+ else
+ strcpy(triggerStr, "+");
+ trigger = malloc(sizeof(*trigger));
+ if (!trigger) {
+ perror("malloc() failed");
+ return 0;
+ }
+ trigger->botid = botid;
+ trigger->trigger = strdup(triggerStr);
+ trigger->next = chan->trigger;
+ chan->trigger = trigger;
+ return trigger->trigger;
+}
+
+static void handle_command_async(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct ChanNode *sent_chan, struct cmd_binding *cbind, char **argv, int argc);
+
+static USERAUTH_CALLBACK(command_checked_auth) {
+ struct command_check_user_cache *cache = data;
+ tmp_text_client = cache->textclient;
+ handle_command_async(cache->client, user, cache->chan, cache->sent_chan, cache->cbind, cache->argv, cache->argc);
+ free(cache->message);
+ free(cache);
+}
+
+static void handle_command(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) {
+ struct ChanNode *sent_chan = chan;
+ if(message[0] == '#') {
+ char *chanName = message;
+ message = strstr(message, " ");
+ if(!message) return;
+ *message = '\0';
+ message++;
+ struct ChanNode *chan2 = getChanByName(chanName);
+ if(chan2)
+ chan = chan2;
+ }
+ message = strdup(message);
+ int bind_index = get_binds_index(message[0]);
+ char *args = strstr(message, " ");
+ if(args) {
+ *args = '\0';
+ args++;
+ }
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == client->botid && stricmp(cbind->cmd, message) == 0) {
+ //get a text bot
+ tmp_text_client = get_prefered_bot(client->botid);
+ //parse the arguments...
+ char *arga[MAXNUMPARAMS];
+ char **argv;
+ int argc = 0;
+ if(args) {
+ while(*args) {
+ //skip leading spaces
+ while (*args == ' ')
+ *args++ = 0;
+ arga[argc++] = args;
+ if (argc >= MAXNUMPARAMS)
+ break;
+ while (*args != ' ' && *args)
+ args++;
+ }
+ }
+ argv = arga;
+ if(argc != 0 && argv[0][0] == '#' && !(cbind->func->flags & CMDFLAG_CHAN_PARAM)) {
+ struct ChanNode *chan2 = getChanByName(argv[0]);
+ if(chan2) {
+ argv += 1;
+ argc -= 1;
+ chan = chan2;
+ }
+ }
+ if(cbind->parameters) {
+ //userdefined parameters...
+ char *uargs[MAXNUMPARAMS];
+ int uargc = 0;
+ char *a,*b = cbind->parameters;
+ int allargs, argi;
+ do {
+ a = strstr(b, " ");
+ if(a) *a = '\0';
+ if(b[0] == '%') {
+ b++;
+ if(b[strlen(b)-1] == '-') {
+ allargs = 1;
+ b[strlen(b)-1] = '\0';
+ argi = atoi(b);
+ b[strlen(b)-1] = '-';
+ } else {
+ allargs = 0;
+ argi = atoi(b);
+ }
+ if(argi > 0) {
+ if(argi <= argc) {
+ uargs[uargc++] = argv[argi-1];
+ if(allargs) {
+ for(argi++; argi <= argc; argi++)
+ uargs[uargc++] = argv[argi-1];
+ }
+ }
+ } else if(!strcmp(b, "c")) {
+ uargs[uargc++] = (chan ? chan->name : NULL);
+ } else if(!strcmp(b, "n")) {
+ uargs[uargc++] = user->nick;
+ }
+ } else {
+ uargs[uargc++] = b;
+ }
+ if(a) {
+ *a = ' ';
+ b = a+1;
+ }
+ } while(a);
+ argv = uargs;
+ argc = uargc;
+ }
+ if(argc < cbind->func->paramcount) {
+ reply(tmp_text_client, user, "MODCMD_LESS_PARAM_COUNT");
+ break;
+ }
+ if((cbind->func->flags & CMDFLAG_REQUIRE_CHAN) && !chan) {
+ reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED");
+ break;
+ }
+ if((cbind->func->flags & CMDFLAG_CHECK_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) {
+ //check auth...
+ struct command_check_user_cache *data = malloc(sizeof(*data));
+ char **temp_argv = malloc(argc*sizeof(*temp_argv));
+ if (!data || !temp_argv) {
+ perror("malloc() failed");
+ break;
+ }
+ memcpy(temp_argv, argv, argc*sizeof(*temp_argv));
+ data->argv = temp_argv;
+ data->argc = argc;
+ data->client = client;
+ data->user = user;
+ data->chan = chan;
+ data->sent_chan = sent_chan;
+ data->message = message;
+ data->cbind = cbind;
+ data->textclient = tmp_text_client;
+ get_userauth(user, command_checked_auth, data);
+ return;
+ } else
+ handle_command_async(client, user, chan, sent_chan, cbind, argv, argc);
+ break;
+ }
+ }
+ free(message);
+}
+
+static void handle_command_async(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct ChanNode *sent_chan, struct cmd_binding *cbind, char **argv, int argc) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int uaccess;
+ int eventflags = (cbind->func->flags & (CMDFLAG_LOG | CMDFLAG_OPLOG));
+ if((cbind->func->flags & CMDFLAG_REQUIRE_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) {
+ reply(tmp_text_client, user, "MODCMD_AUTH_REQUIRED");
+ return;
+ }
+ if(sent_chan && sent_chan != chan) {
+ //check pubcmd of this channel
+ printf_mysql_query("SELECT `channel_pubcmd` FROM `channels` WHERE `channel_name` = '%s'", escape_string(sent_chan->name));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ uaccess = getChannelAccess(user, sent_chan, 1);
+ if(row[0] && uaccess < atoi(row[0])) { //NOTE: HARDCODED DEFAULT: pubcmd = 0
+ reply(tmp_text_client, user, "MODCMD_PUBCMD", sent_chan->name);
+ return;
+ }
+ }
+ }
+ int global_access = ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access);
+ if(global_access > 0) {
+ int user_global_access = 0;
+ printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ user_global_access = atoi(row[0]);
+ }
+ if(user_global_access < global_access) {
+ if(!user_global_access)
+ reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd);
+ else
+ reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED");
+ return;
+ }
+ }
+ if((cbind->func->flags & CMDFLAG_REGISTERED_CHAN)) {
+ MYSQL_ROW defaults = NULL;
+ char access_list[256];
+ int access_pos = 0;
+ int access_count = 0;
+ int minaccess = 0;
+ char *str_a, *str_b = cbind->func->channel_access, *str_c;
+ if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS)
+ str_b = cbind->channel_access;
+ access_list[0] = '\0';
+ if(str_b) {
+ str_c = strdup(str_b);
+ str_b = str_c;
+ while((str_a = str_b)) {
+ str_b = strstr(str_a, ",");
+ if(str_b) {
+ *str_b = '\0';
+ str_b++;
+ }
+ if(*str_a == '#') {
+ str_a++;
+ access_pos += sprintf(access_list+access_pos, ", `%s`", str_a);
+ access_count++;
+ } else {
+ if(atoi(str_a) > minaccess)
+ minaccess = atoi(str_a);
+ }
+ }
+ free(str_c);
+ }
+ if(!(chan->flags & CHANFLAG_REQUESTED_CHANINFO) || (sent_chan && sent_chan == chan) || access_count || minaccess) {
+ printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ chan->flags |= CHANFLAG_CHAN_REGISTERED;
+ chan->channel_id = atoi(row[0]);
+ if((sent_chan && sent_chan == chan) || access_count || minaccess) {
+ uaccess = getChannelAccess(user, chan, 0);
+ if(uaccess < minaccess && isGodMode(user)) {
+ eventflags |= CMDFLAG_OPLOG;
+ } else if(uaccess < minaccess) {
+ //ACCESS DENIED
+ reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED");
+ return;
+ }
+ if(!row[1] && !defaults) {
+ printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list);
+ defaults = mysql_fetch_row(mysql_use());
+ }
+ if(sent_chan && (sent_chan == chan) && uaccess < (row[1] ? atoi(row[1]) : atoi(defaults[1]))) {
+ if(isGodMode(user)) {
+ eventflags |= CMDFLAG_OPLOG;
+ } else {
+ //PUBCMD
+ reply(tmp_text_client, user, "MODCMD_PUBCMD", chan->name);
+ return;
+ }
+ }
+ int i;
+ for(i = 0; i < access_count; i++) {
+ if(!row[2+i] && !defaults) {
+ printf_mysql_query("SELECT `channel_id`, `channel_pubcmd` %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list);
+ defaults = mysql_fetch_row(mysql_use());
+ }
+ if(uaccess < (row[2+i] ? atoi(row[2+i]) : atoi(defaults[2+i]))) {
+ if(isGodMode(user)) {
+ eventflags |= CMDFLAG_OPLOG;
+ } else {
+ reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED");
+ return;
+ }
+ }
+ }
+ }
+ }
+ chan->flags |= CHANFLAG_REQUESTED_CHANINFO;
+ }
+ if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) {
+ reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED");
+ return;
+ }
+ printf_mysql_query("SELECT `botid`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) == NULL) {
+ reply(tmp_text_client, user, "MODCMD_CHAN_REQUIRED");
+ return;
+ } else if(!strcmp(row[1], "1")) {
+ reply(tmp_text_client, user, "MODCMD_CHAN_SUSPENDED");
+ return;
+ }
+ }
+ if((cbind->func->flags & CMDFLAG_REQUIRE_GOD) && !isGodMode(user)) {
+ reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd);
+ return;
+ }
+ struct Event *event = createEvent(client, user, chan, cbind->func->name, argv, argc, eventflags);
+ cbind->func->func(client, user, chan, argv, argc, event);
+}
+
+static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) {
+ fd_set fds;
+ char *trigger;
+ struct ClientSocket *client;
+ FD_ZERO(&fds);
+ for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+ if(isUserOnChan(client->user, chan) && (client->flags & SOCKET_FLAG_PREFERRED) && !FD_ISSET(client->botid, &fds)) {
+ FD_SET(client->botid, &fds);
+ trigger = get_channel_trigger(client->botid, chan);
+ if(stricmplen(message, trigger, strlen(trigger)) == 0) {
+ handle_command(client, user, chan, message + strlen(trigger));
+ }
+ }
+ }
+ for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+ if(isUserOnChan(client->user, chan) && !FD_ISSET(client->botid, &fds)) {
+ FD_SET(client->botid, &fds);
+ trigger = get_channel_trigger(client->botid, chan);
+ if(stricmplen(message, trigger, strlen(trigger)) == 0) {
+ handle_command(client, user, chan, message + strlen(trigger));
+ }
+ }
+ }
+}
+
+static void got_privmsg(struct UserNode *user, struct UserNode *target, char *message) {
+ struct ClientSocket *client;
+ for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) {
+ if(client->user == target) {
+ handle_command(client, user, NULL, message);
+ }
+ }
+}
+
+int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags) {
+ struct cmd_function *cmdfunc;
+ for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
+ if(cmdfunc->botid == botid && strcmp(cmdfunc->name, name) == 0)
+ return 0;
+ }
+ cmdfunc = malloc(sizeof(*cmdfunc));
+ if (!cmdfunc) {
+ perror("malloc() failed");
+ return 0;
+ }
+ cmdfunc->botid = botid;
+ cmdfunc->name = strdup(name);
+ cmdfunc->func = func;
+ cmdfunc->flags = flags;
+ cmdfunc->paramcount = paramcount;
+ cmdfunc->channel_access = channel_access;
+ cmdfunc->global_access = global_access;
+ cmdfunc->next = cmd_functions;
+ cmd_functions = cmdfunc;
+ return 1;
+}
+
+int set_trigger_callback(int botid, trigger_callback_t *func) {
+ static struct trigger_callback *cb = NULL;
+ for(cb = trigger_callbacks; cb; cb = cb->next) {
+ if(cb->botid == botid)
+ break;
+ }
+ if(!cb) {
+ cb = malloc(sizeof(*cb));
+ if (!cb) {
+ perror("malloc() failed");
+ return 0;
+ }
+ cb->botid = botid;
+ cb->next = trigger_callbacks;
+ trigger_callbacks = cb;
+ }
+ cb->func = func;
+ return 1;
+}
+
+int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger) {
+ struct trigger_cache *trigger;
+ for(trigger = chan->trigger; trigger; trigger = trigger->next) {
+ if(trigger->botid == botid) {
+ free(trigger->trigger);
+ trigger->trigger = strdup(new_trigger);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func) {
+ int bind_index = get_binds_index(cmd[0]);
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
+ return 0;
+ }
+ cbind = malloc(sizeof(*cbind));
+ if (!cbind) {
+ perror("malloc() failed");
+ return 0;
+ }
+ cbind->botid = botid;
+ cbind->cmd = strdup(cmd);
+ cbind->func = func;
+ cbind->parameters = NULL;
+ cbind->global_access = 0;
+ cbind->channel_access = NULL;
+ cbind->flags = 0;
+ cbind->next = cmd_binds[bind_index];
+ cmd_binds[bind_index] = cbind;
+ return 1;
+}
+
+int bind_cmd_to_command(int botid, char *cmd, char *func) {
+ struct cmd_function *cmdfunc;
+ for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
+ if(cmdfunc->botid == botid && strcmp(cmdfunc->name, func) == 0)
+ break;
+ }
+ if(!cmdfunc) return 0;
+ int bind_index = get_binds_index(cmd[0]);
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0)
+ return 0;
+ }
+ cbind = malloc(sizeof(*cbind));
+ if (!cbind) {
+ perror("malloc() failed");
+ return 0;
+ }
+ cbind->botid = botid;
+ cbind->cmd = strdup(cmd);
+ cbind->func = cmdfunc;
+ cbind->next = cmd_binds[bind_index];
+ cbind->parameters = NULL;
+ cbind->global_access = 0;
+ cbind->channel_access = NULL;
+ cbind->flags = 0;
+ cmd_binds[bind_index] = cbind;
+ return 1;
+}
+
+int unbind_cmd(int botid, char *cmd) {
+ int bind_index = get_binds_index(cmd[0]);
+ struct cmd_binding *cbind, *last = NULL;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+ if(last)
+ last->next = cbind->next;
+ else
+ cmd_binds[bind_index] = cbind->next;
+ free(cbind->cmd);
+ if(cbind->parameters)
+ free(cbind->parameters);
+ free(cbind);
+ return 1;
+ } else
+ last = cbind;
+ }
+ return 0;
+}
+
+struct cmd_function *find_cmd_function(int botid, char *name) {
+ struct cmd_function *cmdfunc;
+ for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) {
+ if(cmdfunc->botid == botid && stricmp(cmdfunc->name, name) == 0)
+ break;
+ }
+ return cmdfunc;
+}
+
+struct ClientSocket *getTextBot() {
+ return tmp_text_client;
+}
+
+void init_modcmd() {
+ cmd_binds = calloc(27, sizeof(*cmd_binds));
+ bind_chanmsg(got_chanmsg);
+ bind_privmsg(got_privmsg);
+ register_default_language_table(msgtab);
+}
+
+void free_modcmd() {
+ int i;
+ for(i = 0; i < 27; i++) {
+ struct cmd_binding *cbind, *next;
+ for(cbind = cmd_binds[i]; cbind; cbind = next) {
+ next = cbind->next;
+ free(cbind->cmd);
+ if(cbind->parameters)
+ free(cbind->parameters);
+ if(cbind->channel_access)
+ free(cbind->channel_access);
+ free(cbind);
+ }
+ }
+ free(cmd_binds);
+ struct cmd_function *cmdfunct, *next;
+ for(cmdfunct = cmd_functions; cmdfunct; cmdfunct = next) {
+ next = cmdfunct->next;
+ free(cmdfunct->name);
+ free(cmdfunct);
+ }
+ struct trigger_callback *cb, *next_cb;
+ for(cb = trigger_callbacks; cb; cb = next_cb) {
+ next_cb = cb->next;
+ free(next_cb);
+ }
+ cmd_functions = NULL;
+ trigger_callbacks = NULL;
+}
+
+void bind_set_parameters(int botid, char *cmd, char *parameters) {
+ int bind_index = get_binds_index(cmd[0]);
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+ if(cbind->parameters)
+ free(cbind->parameters);
+ cbind->parameters = strdup(parameters);
+ return;
+ }
+ }
+}
+
+void bind_set_global_access(int botid, char *cmd, int gaccess) {
+ int bind_index = get_binds_index(cmd[0]);
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+ if(gaccess > -1) {
+ cbind->global_access = gaccess;
+ cbind->flags |= CMDFLAG_OVERRIDE_GLOBAL_ACCESS;
+ } else {
+ cbind->flags &= ~CMDFLAG_OVERRIDE_GLOBAL_ACCESS;
+ }
+ return;
+ }
+ }
+}
+
+void bind_set_channel_access(int botid, char *cmd, char *chanaccess) {
+ int bind_index = get_binds_index(cmd[0]);
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+ if(cbind->channel_access)
+ free(cbind->channel_access);
+ if(chanaccess) {
+ cbind->channel_access = strdup(chanaccess);
+ cbind->flags |= CMDFLAG_OVERRIDE_CHANNEL_ACCESS;
+ } else {
+ cbind->channel_access = NULL;
+ cbind->flags &= ~CMDFLAG_OVERRIDE_CHANNEL_ACCESS;
+ }
+ return;
+ }
+ }
+}
+
+struct cmd_binding *find_cmd_binding(int botid, char *cmd) {
+ int bind_index = get_binds_index(cmd[0]);
+ struct cmd_binding *cbind;
+ for(cbind = cmd_binds[bind_index]; cbind; cbind = cbind->next) {
+ if(cbind->botid == botid && strcmp(cbind->cmd, cmd) == 0) {
+ return cbind;
+ }
+ }
+ return NULL;
+}
+
--- /dev/null
+#ifndef _modcmd_h
+#define _modcmd_h
+#include "main.h"
+
+#define CMDFLAG_REQUIRE_CHAN 0x0001
+#define CMDFLAG_REQUIRE_AUTH 0x0002
+#define CMDFLAG_REQUIRE_GOD 0x0004
+#define CMDFLAG_CHECK_AUTH 0x0008
+#define CMDFLAG_REGISTERED_CHAN 0x0010
+#define CMDFLAG_OVERRIDE_GLOBAL_ACCESS 0x0020
+#define CMDFLAG_OVERRIDE_CHANNEL_ACCESS 0x0040
+#define CMDFLAG_CHAN_PARAM 0x0080
+#define CMDFLAG_LOG 0x0100
+#define CMDFLAG_OPLOG 0x0200
+
+struct ClientSocket;
+struct UserNode;
+struct ChanNode;
+struct Event;
+
+#define CMD_BIND(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(struct UserNode *user), UNUSED_ARG(struct ChanNode *chan), UNUSED_ARG(char **argv), UNUSED_ARG(char argc), UNUSED_ARG(struct Event *event))
+typedef void cmd_bind_t(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char **argv, char argc, struct Event *event);
+typedef void trigger_callback_t(struct ChanNode *chan, char *trigger);
+
+struct cmd_function {
+ char *name;
+ int botid;
+ cmd_bind_t *func;
+ unsigned int flags;
+ int paramcount;
+ int global_access;
+ char *channel_access;
+
+ struct cmd_function *next;
+};
+
+struct cmd_binding {
+ char *cmd;
+ int botid;
+ struct cmd_function *func;
+ unsigned int flags;
+ char *parameters;
+ int global_access;
+ char *channel_access;
+
+ struct cmd_binding *next;
+};
+
+struct trigger_cache {
+ int botid;
+ char *trigger;
+
+ struct trigger_cache *next;
+};
+
+void init_modcmd();
+void free_modcmd();
+struct ClientSocket* get_prefered_bot(int botid);
+int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags);
+int set_trigger_callback(int botid, trigger_callback_t *func);
+int changeChannelTrigger(int botid, struct ChanNode *chan, char *new_trigger);
+int bind_cmd_to_function(int botid, char *cmd, struct cmd_function *func);
+int bind_cmd_to_command(int botid, char *cmd, char *func);
+int unbind_cmd(int botid, char *cmd);
+struct cmd_function *find_cmd_function(int botid, char *name);
+struct ClientSocket *getTextBot();
+void bind_set_parameters(int botid, char *cmd, char *parameters);
+void bind_set_global_access(int botid, char *cmd, int gaccess);
+void bind_set_channel_access(int botid, char *cmd, char *chanaccess);
+struct cmd_binding *find_cmd_binding(int botid, char *cmd);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "mysqlConn.h"
+
+struct used_result {
+ MYSQL_RES *result;
+ struct used_result *next;
+};
+
+struct escaped_string {
+ char *string;
+ struct escaped_string *next;
+};
+
+MYSQL *mysql_conn = NULL;
+static struct used_result *used_results;
+static struct escaped_string *escaped_strings;
+
+void check_mysql() {
+ int errid;
+ if((errid = mysql_ping(mysql_conn))) {
+ if(mysql_errno(mysql_conn) == CR_SERVER_GONE_ERROR) {
+ if(!mysql_real_connect(mysql_conn, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_BASE, MYSQL_PORT, NULL, 0)) {
+ show_mysql_error();
+ }
+ } else {
+ //mysql error
+ show_mysql_error();
+ }
+ }
+}
+
+MYSQL_RES *mysql_use() {
+ MYSQL_RES *res = mysql_store_result(mysql_conn);
+ struct used_result *result = malloc(sizeof(*result));
+ if (!result) {
+ mysql_free_result(res);
+ return NULL;
+ }
+ result->result = res;
+ result->next = used_results;
+ used_results = result;
+ return res;
+}
+
+void mysql_free() {
+ struct used_result *result, *next_result;
+ for(result = used_results; result; result = next_result) {
+ next_result = result->next;
+ mysql_free_result(result->result);
+ free(result);
+ }
+ used_results = NULL;
+ struct escaped_string *escaped, *next_escaped;
+ for(escaped = escaped_strings; escaped; escaped = next_escaped) {
+ next_escaped = escaped->next;
+ free(escaped->string);
+ free(escaped);
+ }
+ escaped_strings = NULL;
+}
+
+void init_mysql() {
+ mysql_conn = mysql_init(NULL);
+ if (!mysql_real_connect(mysql_conn, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_BASE, MYSQL_PORT, NULL, 0)) {
+ //error
+ show_mysql_error();
+ }
+}
+
+void free_mysql() {
+ mysql_close(mysql_conn);
+}
+
+void show_mysql_error() {
+ //show mysql_error()
+ printf("MySQL Error: %s\n", mysql_error(mysql_conn));
+}
+
+void printf_mysql_query(const char *text, ...) {
+ va_list arg_list;
+ char queryBuf[MYSQLMAXLEN];
+ int pos;
+ queryBuf[0] = '\0';
+ va_start(arg_list, text);
+ pos = vsnprintf(queryBuf, MYSQLMAXLEN - 2, text, arg_list);
+ va_end(arg_list);
+ if (pos < 0 || pos > (MYSQLMAXLEN - 2)) pos = MYSQLMAXLEN - 2;
+ queryBuf[pos] = '\0';
+ printf("MySQL: %s\n", queryBuf);
+ if(mysql_query(mysql_conn, queryBuf)) {
+ check_mysql();
+ if(mysql_query(mysql_conn, queryBuf)) {
+ show_mysql_error();
+ }
+ }
+}
+
+char* escape_string(const char *str) {
+ struct escaped_string *escapedstr = malloc(sizeof(*escapedstr));
+ if (!escapedstr) {
+ return NULL;
+ }
+ char escaped[strlen(str)*2+1];
+ mysql_real_escape_string(mysql_conn, escaped, str, strlen(str));
+ escapedstr->string = strdup(escaped);
+ escapedstr->next = escaped_strings;
+ escaped_strings = escapedstr;
+ return escapedstr->string;
+}
--- /dev/null
+#ifndef _MySQLConn_h
+#define _MySQLConn_h
+
+#include "main.h"
+#include <mysql.h>
+#include <mysql/errmsg.h>
+
+#define MYSQLMAXLEN 1024
+
+extern MYSQL *mysql_conn;
+
+void check_mysql();
+MYSQL_RES *mysql_use();
+void mysql_free();
+void init_mysql();
+void free_mysql();
+void show_mysql_error();
+void printf_mysql_query(const char *text, ...) PRINTF_LIKE(1, 2);
+char* escape_string(const char *str);
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "timeq.h"
+
+static struct timeq_entry *timeq_events;
+
+void timeq_tick() {
+ struct timeq_entry *entry, *next;
+ time_t now = time(0);
+ for(entry = timeq_events; entry; entry = next) {
+ if(entry->execute <= now) {
+ entry->callback(entry->data);
+ next = entry->next;
+ free(entry);
+ } else
+ break;
+ }
+ timeq_events = entry;
+}
+
+struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data) {
+ time_t now = time(0);
+ struct timeq_entry *entry = malloc(sizeof(*entry));
+ if (!entry)
+ {
+ perror("malloc() failed");
+ return NULL;
+ }
+ entry->execute = now + seconds;
+ entry->callback = callback;
+ entry->data = data;
+ entry->name = NULL;
+ struct timeq_entry *next, *prev = NULL;
+ for(next = timeq_events; next; next = next->next) {
+ if(next->execute >= entry->execute)
+ break;
+ else
+ prev = next;
+ }
+ if(prev == NULL) {
+ entry->next = timeq_events;
+ timeq_events = entry;
+ } else {
+ entry->next = next;
+ prev->next = entry;
+ }
+ return entry;
+}
+
+struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data) {
+ struct timeq_entry *entry = timeq_add(seconds, callback, data);
+ entry->name = strdup(name);
+ return entry;
+}
+
+int timeq_del(struct timeq_entry* entry) {
+ struct timeq_entry *centry, *last = NULL;
+ for(centry = timeq_events; centry; centry = centry->next) {
+ if(centry == entry) {
+ if(last)
+ last->next = centry->next;
+ else
+ timeq_events = centry->next;
+ if(centry->name)
+ free(centry->name);
+ free(centry);
+ return 1;
+ } else {
+ last = centry;
+ }
+ }
+ return 0;
+}
+
+int timeq_del_name(char *name) {
+ struct timeq_entry *centry, *last = NULL;
+ for(centry = timeq_events; centry; centry = centry->next) {
+ if(centry->name && !stricmp(centry->name, name)) {
+ if(last)
+ last->next = centry->next;
+ else
+ timeq_events = centry->next;
+ free(centry->name);
+ free(centry);
+ return 1;
+ } else {
+ last = centry;
+ }
+ }
+ return 0;
+}
+
+int timeq_name_exists(char *name) {
+ struct timeq_entry *centry;
+ for(centry = timeq_events; centry; centry = centry->next) {
+ if(centry->name && !stricmp(centry->name, name)) {
+ return 1;
+ }
+ }
+ return 0;
+}
--- /dev/null
+#ifndef _timeq_h
+#define _timeq_h
+
+#include "main.h"
+
+#define TIMEQ_CALLBACK(NAME) void NAME(UNUSED_ARG(void *data))
+typedef TIMEQ_CALLBACK(timeq_callback_t);
+
+struct timeq_entry {
+ char *name;
+ time_t execute;
+ timeq_callback_t *callback;
+ void *data;
+
+ struct timeq_entry *next;
+};
+
+void timeq_tick();
+struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data);
+struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data);
+int timeq_del(struct timeq_entry* entry);
+int timeq_del_name(char *name);
+int timeq_name_exists(char *name);
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "tools.h"
+#include "UserNode.h"
+#include "ChanNode.h"
+#include "lang.h"
+#include "ClientSocket.h"
+
+static const struct default_language_entry msgtab[] = {
+ {"TIME_MASK_2_ITEMS", "%s and %s"}, /* {ARGS: "2 days", "1 hour"} */
+ {"TIME_MASK_3_ITEMS", "%s, %s and %s"}, /* {ARGS: "2 days", "1 hour", "20 minutes"} */
+ {"TIME_YEAR", "year"},
+ {"TIME_YEARS", "years"},
+ {"TIME_MONTH", "month"},
+ {"TIME_MONTHS", "months"},
+ {"TIME_WEEK", "week"},
+ {"TIME_WEEKS", "weeks"},
+ {"TIME_DAY", "day"},
+ {"TIME_DAYS", "days"},
+ {"TIME_HOUR", "hour"},
+ {"TIME_HOURS", "hours"},
+ {"TIME_MINUTE", "minute"},
+ {"TIME_MINUTES", "minutes"},
+ {"TIME_SECOND", "second"},
+ {"TIME_SECONDS", "seconds"},
+ {NULL, NULL}
+};
+
+/* copied from IRCU 2.10.12 match.c */
+/*
+ * Compare if a given string (name) matches the given
+ * mask (which can contain wild cards: '*' - match any
+ * number of chars, '?' - match any single character.
+ *
+ * return 0, if match
+ * 1, if no match
+ *
+ * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
+ * Rewritten by Timothy Vogelsang (netski), net@astrolink.org
+ */
+int match(const char *mask, const char *name)
+{
+ const char *m = mask, *n = name;
+ const char *m_tmp = mask, *n_tmp = name;
+ int star_p;
+
+ for (;;) switch (*m) {
+ case '\0':
+ if (!*n)
+ return 0;
+ backtrack:
+ if (m_tmp == mask)
+ return 1;
+ m = m_tmp;
+ n = ++n_tmp;
+ if (*n == '\0')
+ return 1;
+ break;
+ case '\\':
+ m++;
+ /* allow escaping to force capitalization */
+ if (*m++ != *n++)
+ goto backtrack;
+ break;
+ case '*': case '?':
+ for (star_p = 0; ; m++) {
+ if (*m == '*')
+ star_p = 1;
+ else if (*m == '?') {
+ if (!*n++)
+ goto backtrack;
+ } else break;
+ }
+ if (star_p) {
+ if (!*m)
+ return 0;
+ else if (*m == '\\') {
+ m_tmp = ++m;
+ if (!*m)
+ return 1;
+ for (n_tmp = n; *n && *n != *m; n++) ;
+ } else {
+ m_tmp = m;
+ for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ;
+ }
+ }
+ /* and fall through */
+ default:
+ if (!*n)
+ return *m != '\0';
+ if (tolower(*m) != tolower(*n))
+ goto backtrack;
+ m++;
+ n++;
+ break;
+ }
+}
+
+
+//TABLES
+struct Table *table_init(int width, int length, int flags) {
+ int row;
+ struct Table *table = malloc(sizeof(*table));
+ table->contents = malloc(length * sizeof(*table->contents));
+ for(row = 0; row < length; row++) {
+ table->contents[row] = calloc(width, sizeof(*table->contents[row]));
+ }
+ table->length = length;
+ table->width = width;
+ table->flags = flags;
+ table->col_flags = calloc(length, sizeof(int));
+ table->entrys = 0;
+ table->maxwidth = calloc(length, sizeof(int));
+ table->table_lines = NULL;
+ return table;
+}
+
+int table_add(struct Table *table, char **entry) {
+ int col;
+ if(table->entrys == table->length) return 0;
+ for(col = 0; col < table->width; col++) {
+ table->contents[table->entrys][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
+ if(table->contents[table->entrys][col])
+ table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
+ if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
+ table->maxwidth[col] = strlen(entry[col]);
+ }
+ table->entrys++;
+ return 1;
+}
+
+int table_change(struct Table *table, int row, char **entry) {
+ int col;
+ if(row >= table->length) return 0;
+ for(col = 0; col < table->width; col++) {
+ if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
+ free(table->contents[row][col]);
+ table->contents[row][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
+ if(table->contents[row][col])
+ table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
+ if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
+ table->maxwidth[col] = strlen(entry[col]);
+ }
+ return 1;
+}
+
+int table_change_field(struct Table *table, int row, int col, char *entry) {
+ if(row >= table->length) return 0;
+ if(col >= table->width) return 0;
+ if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
+ free(table->contents[row][col]);
+ table->contents[row][col] = (((table->flags & TABLE_FLAG_USE_POINTER) || !entry) ? entry : strdup(entry));
+ if(table->contents[row][col])
+ table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
+ if(entry && strlen(entry) > table->maxwidth[col])
+ table->maxwidth[col] = strlen(entry);
+ return 1;
+}
+
+int table_set_bold(struct Table *table, int collum, int bold) {
+ if(bold)
+ table->col_flags[collum] |= TABLE_FLAG_COL_BOLD;
+ else
+ table->col_flags[collum] &= ~TABLE_FLAG_COL_BOLD;
+ return 1;
+}
+
+char **table_end(struct Table *table) {
+ int row, col, tablewidth = 0, pos,i;
+ if(!table->entrys) return NULL;
+ for(col = 0; col < table->width; col++) {
+ tablewidth += table->maxwidth[col]+1;
+ if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
+ tablewidth += 2;
+ }
+ table->table_lines = malloc(table->entrys * sizeof(table->table_lines));
+ for(row = 0; row < table->entrys; row++) {
+ table->table_lines[row] = malloc(tablewidth * sizeof(*table->table_lines[row]));
+ pos = 0;
+ for(col = 0; col < table->width; col++) {
+ if(!(table->col_flags[col] & TABLE_FLAG_COL_CONTENTS)) continue;
+ if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
+ table->table_lines[row][pos++] = '\002';
+ for(i = 0; i < strlen(table->contents[row][col]); i++) {
+ table->table_lines[row][pos++] = table->contents[row][col][i];
+ }
+ if(col < table->width-1) {
+ for(;i < table->maxwidth[col]; i++) {
+ table->table_lines[row][pos++] = ' ';
+ }
+ table->table_lines[row][pos++] = ' ';
+ } else
+ table->table_lines[row][pos++] = '\0';
+
+ if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
+ table->table_lines[row][pos++] = '\002';
+ }
+ }
+ return table->table_lines;
+}
+
+void table_free(struct Table *table) {
+ int row, col;
+ for(row = 0; row < table->length; row++) {
+ if(!(table->flags & TABLE_FLAG_USE_POINTER) && table->entrys > row) {
+ for(col = 0; col < table->width; col++) {
+ if(table->contents[row][col])
+ free(table->contents[row][col]);
+ }
+ }
+ free(table->contents[row]);
+ }
+ free(table->contents);
+ free(table->col_flags);
+ free(table->maxwidth);
+ if(table->table_lines) {
+ for(row = 0; row < table->entrys; row++) {
+ free(table->table_lines[row]);
+ }
+ free(table->table_lines);
+ }
+ free(table);
+}
+
+char* timeToStr(struct UserNode *user, int seconds, int items, char *buf) {
+ char item[items][MAXLEN];
+ int tmp, citem = 0;
+ if(citem != items && seconds >= 31536000) { //60*60*24*365 = 31536000
+
+ tmp = seconds / 31536000;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_YEAR" : "TIME_YEARS"));
+ seconds -= tmp * 31536000;
+ }
+ if(citem != items && seconds >= 86400) { //60*60*24 = 86400
+ tmp = seconds / 86400;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_DAY" : "TIME_DAYS"));
+ seconds -= tmp * 86400;
+ }
+ if(citem != items && seconds >= 3600) { //60*60 = 3600
+ tmp = seconds / 3600;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_HOUR" : "TIME_HOURS"));
+ seconds -= tmp * 3600;
+ }
+ if(citem != items && seconds >= 60) {
+ tmp = seconds / 60;
+ sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_MINUTE" : "TIME_MINUTES"));
+ seconds -= tmp * 60;
+ }
+ if(citem != items && seconds >= 1) {
+ sprintf(item[citem++], "%d %s", seconds, get_language_string(user, seconds == 1 ? "TIME_SECOND" : "TIME_SECONDS"));
+ }
+ if(citem == 2) {
+ build_language_string(user, buf, "TIME_MASK_2_ITEMS", item[0], item[1]);
+ } else if(citem == 3) {
+ build_language_string(user, buf, "TIME_MASK_3_ITEMS", item[0], item[1], item[2]);
+ } else {
+ int i, ii, p = 0;
+ for(i = 0; i < citem; i++) {
+ for(ii = 0; ii < strlen(item[i]); ii++) {
+ buf[p++] = item[i][ii];
+ }
+ buf[p++] = ' ';
+ }
+ buf[(p ? p-1 : 0)] = '\0';
+ }
+ return buf;
+}
+
+int strToTime(struct UserNode *user, char *str) {
+ /*
+ * y = year = 365 days
+ * M = month = 30 days
+ * w = week = 7 days
+ * d = day
+ * h = hour
+ * m = minute
+ * (s) = second
+ */
+ int total_time = 0, cvalue;
+ char *p, tmpchar;
+ 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++;
+ tmpchar = *p;
+ *p = '\0';
+ if(p - str > 1) { //unit has more than one char
+ if(!stricmp(str, "year") || !stricmp(str, "year") || !stricmp(str, get_language_string(user, "TIME_YEAR")) || !stricmp(str, get_language_string(user, "TIME_YEARS")))
+ unit_multiplikator = 31536000; //60*60*24*365 = 31536000
+ else if(!stricmp(str, "month") || !stricmp(str, "months") || !stricmp(str, get_language_string(user, "TIME_MONTH")) || !stricmp(str, get_language_string(user, "TIME_MONTHS")))
+ unit_multiplikator = 2592000; //60*60*24*30 = 2592000
+ else if(!stricmp(str, "week") || !stricmp(str, "weeks") || !stricmp(str, get_language_string(user, "TIME_WEEK")) || !stricmp(str, get_language_string(user, "TIME_WEEKS")))
+ unit_multiplikator = 604800; //60*60*24*7 = 604800
+ else if(!stricmp(str, "day") || !stricmp(str, "days") || !stricmp(str, get_language_string(user, "TIME_DAY")) || !stricmp(str, get_language_string(user, "TIME_DAYS")))
+ unit_multiplikator = 86400; //60*60*24 = 86400
+ else if(!stricmp(str, "hour") || !stricmp(str, "hours") || !stricmp(str, get_language_string(user, "TIME_HOUR")) || !stricmp(str, get_language_string(user, "TIME_HOURS")))
+ unit_multiplikator = 3600; //60*60 = 3600
+ else if(!stricmp(str, "minute") || !stricmp(str, "minutes") || !stricmp(str, "min") || !stricmp(str, "mins") || !stricmp(str, get_language_string(user, "TIME_MINUTE")) || !stricmp(str, get_language_string(user, "TIME_MINUTES")))
+ unit_multiplikator = 60;
+ else
+ unit_multiplikator = 1;
+ } else {
+ switch(*str) {
+ case 'y':
+ unit_multiplikator = 31536000; //60*60*24*365 = 31536000
+ break;
+ case 'M':
+ unit_multiplikator = 2592000; //60*60*24*30 = 2592000
+ break;
+ case 'w':
+ unit_multiplikator = 604800; //60*60*24*7 = 604800
+ break;
+ case 'd':
+ unit_multiplikator = 86400; //60*60*24 = 86400
+ break;
+ case 'h':
+ unit_multiplikator = 3600; //60*60 = 3600
+ break;
+ case 'm':
+ unit_multiplikator = 60;
+ break;
+ default:
+ unit_multiplikator = 1;
+ break;
+ }
+ }
+ total_time += (cvalue * unit_multiplikator);
+ *p = tmpchar;
+ str = p;
+ }
+ return total_time;
+}
+
+struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan) {
+ struct ModeBuffer *modeBuf = malloc(sizeof(*modeBuf));
+ if(!modeBuf) {
+ perror("malloc() failed");
+ return NULL;
+ }
+ modeBuf->client = client;
+ modeBuf->chan = chan;
+ modeBuf->addCount = 0;
+ modeBuf->delCount = 0;
+ return modeBuf;
+}
+
+void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param) {
+ if(add) {
+ modeBuf->addModes[modeBuf->addCount] = mode;
+ modeBuf->addModesParams[modeBuf->addCount] = (param ? strdup(param) : NULL);
+ modeBuf->addCount++;
+ modeBuf->addModes[modeBuf->addCount] = '\0';
+ } else {
+ modeBuf->delModes[modeBuf->delCount] = mode;
+ modeBuf->delModesParams[modeBuf->delCount] = (param ? strdup(param) : NULL);
+ modeBuf->delCount++;
+ modeBuf->delModes[modeBuf->delCount] = '\0';
+ }
+ if(modeBuf->addCount + modeBuf->delCount == MAXMODES)
+ flushModeBuffer(modeBuf);
+}
+
+void flushModeBuffer(struct ModeBuffer *modeBuf) {
+ char modeStr[MAXMODES+3];
+ int modePos = 0;
+ char paramStr[MAXLEN];
+ int paramPos = 0;
+ int i;
+ if(modeBuf->addCount) {
+ modeStr[modePos++] = '+';
+ for(i = 0; i < modeBuf->addCount; i++) {
+ modeStr[modePos++] = modeBuf->addModes[i];
+ if(modeBuf->addModesParams[i]) {
+ paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->addModesParams[i]);
+ }
+ }
+ modeBuf->addCount = 0;
+ }
+ if(modeBuf->delCount) {
+ modeStr[modePos++] = '-';
+ for(i = 0; i < modeBuf->delCount; i++) {
+ modeStr[modePos++] = modeBuf->delModes[i];
+ if(modeBuf->delModesParams[i]) {
+ paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->delModesParams[i]);
+ }
+ }
+ modeBuf->delCount = 0;
+ }
+ modeStr[modePos++] = '\0';
+ putsock(modeBuf->client, "MODE %s %s%s", modeBuf->chan->name, modeStr, paramStr);
+}
+
+void freeModeBuffer(struct ModeBuffer *modeBuf) {
+ if(modeBuf->addCount + modeBuf->delCount)
+ flushModeBuffer(modeBuf);
+ free(modeBuf);
+}
+
+int is_ircmask(const char *text) {
+ while (*text && (isalnum((char)*text) || strchr("-_[]|\\`^{}?*", *text)))
+ text++;
+ if (*text++ != '!')
+ return 0;
+ while (*text && *text != '@' && !isspace((char)*text))
+ text++;
+ if (*text++ != '@')
+ return 0;
+ while (*text && !isspace((char)*text))
+ text++;
+ return !*text;
+}
+
+char* generate_banmask(struct UserNode *user, char *buffer) {
+ char *userhost = user->host;
+
+ if(isFakeHost(user->host)) {
+ sprintf(buffer, "*!*@%s", userhost);
+ return buffer;
+ }
+
+ //check if the hostname has more than 4 connections (trusted host)
+ if(countUsersWithHost(userhost) > 4) {
+ sprintf(buffer, "*!%s@%s", user->ident, userhost);
+ return buffer;
+ } else {
+ sprintf(buffer, "*!*@%s", userhost);
+ return buffer;
+ }
+}
+
+char* make_banmask(char *input, char* buffer) {
+ char *nick = NULL, *ident = NULL, *host = NULL;
+ char tmp[HOSTLEN];
+ char *p;
+ if((p = strstr(input, "!"))) {
+ nick = input;
+ *p = '\0';
+ ident = p+1;
+ if((p = strstr(ident, "@"))) {
+ *p = '\0';
+ host = p+1;
+ }
+ } else if((p = strstr(input, "@"))) {
+ ident = input;
+ *p = '\0';
+ host = p+1;
+ } else if((p = strstr(input, "."))) {
+ host = input;
+ } else if(*input == '*' && input[1] != '\0' && !strstr(input+1, "*")) {
+ //AUTH MASK
+ p = getAuthFakehost(input+1);
+ if(p)
+ host = p;
+ else {
+ sprintf(tmp, "%s.*", input+1);
+ host = tmp;
+ }
+ } else {
+ struct UserNode *user = searchUserByNick(input);
+ if(user)
+ return generate_banmask(user, buffer);
+ else
+ nick = input;
+ }
+ if(nick && *nick == '\0') nick = NULL;
+ if(ident && *ident == '\0') ident = NULL;
+ if(host && *host == '\0') host = NULL;
+ sprintf(buffer, "%s!%s@%s", (nick ? nick : "*"), (ident ? ident : "*"), (host ? host : "*"));
+ return buffer;
+}
+
+int isFakeHost(char *host) {
+ char *p1, *p2 = host;
+
+ //find the last dot to identify if the hostmask is a fake host
+ while((p1 = strstr(p2, "."))) {
+ p2 = p1 + 1;
+ }
+ //TLD database: http://www.iana.org/domains/root/db/
+ //the longest TLD i found was 6 chars long (ignoring the stange exotic ones :D)
+ //but we even ignore '.museum' and '.travel' so we can say that the TLD of our mask needs to be less than 4 chars to be a real domain
+ return (strlen(p2+1) > 4);
+}
+
+void init_tools() {
+ register_default_language_table(msgtab);
+}
--- /dev/null
+#ifndef _tools_h
+#define _tools_h
+
+#include "main.h"
+
+#define TABLE_FLAG_USE_POINTER 0x01
+#define TABLE_FLAG_COL_BOLD 0x02
+#define TABLE_FLAG_COL_CONTENTS 0x04
+
+struct ClientSocket;
+struct UserNode;
+struct ChanNode;
+
+struct Table {
+ char ***contents;
+ int length;
+ int width;
+ int flags;
+ int *col_flags;
+
+ int entrys;
+ int *maxwidth;
+
+ char **table_lines; //we just store this to free it in table_free
+};
+
+struct ModeBuffer {
+ struct ClientSocket *client;
+ struct ChanNode *chan;
+ char addModes[MAXMODES];
+ char delModes[MAXMODES];
+ char *addModesParams[MAXMODES];
+ char *delModesParams[MAXMODES];
+ int addCount;
+ int delCount;
+};
+
+int match(const char *mask, const char *name);
+
+struct Table *table_init(int width, int length, int flags);
+int table_add(struct Table *table, char **entry);
+int table_change(struct Table *table, int row, char **entry);
+int table_change_field(struct Table *table, int row, int col, char *entry);
+int table_set_bold(struct Table *table, int collum, int bold);
+char **table_end(struct Table *table);
+void table_free(struct Table *table);
+
+char* timeToStr(struct UserNode *user, int seconds, int items, char *buf);
+int strToTime(struct UserNode *user, char *str);
+
+struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan);
+#define modeBufferSimpleMode(MODEBUF,ADD,MODE) modeBufferSet(MODEBUF, ADD, MODE, NULL)
+#define modeBufferOp(MODEBUF,USER) modeBufferSet(MODEBUF, 1, 'o', USER)
+#define modeBufferDeop(MODEBUF,USER) modeBufferSet(MODEBUF, 0, 'o', USER)
+#define modeBufferVoice(MODEBUF,USER) modeBufferSet(MODEBUF, 1, 'v', USER)
+#define modeBufferDevoice(MODEBUF,USER) modeBufferSet(MODEBUF, 0, 'v', USER)
+#define modeBufferBan(MODEBUF,MASK) modeBufferSet(MODEBUF, 1, 'b', MASK)
+#define modeBufferUnban(MODEBUF,MASK) modeBufferSet(MODEBUF, 0, 'b', MASK)
+void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param);
+void flushModeBuffer(struct ModeBuffer *modeBuf);
+void freeModeBuffer(struct ModeBuffer *modeBuf);
+
+int is_ircmask(const char *text);
+
+char* generate_banmask(struct UserNode *user, char *buffer);
+char* make_banmask(char *input, char* buffer);
+int isFakeHost(char *host);
+
+void init_tools();
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef _version_h
+#define _version_h
+
+#include "main.h"
+
+extern const char *compilation;
+extern const char *creation;
+extern const char *revision;
+extern const char *codelines;
+
+#endif
\ No newline at end of file
--- /dev/null
+#! /bin/sh
+echo "Extracting version.c ..."
+
+if test -r version.c
+then
+ compilation=`sed -n 's/^const char \*compilation = \"\(.*\)\";/\1/p' < version.c`
+ if test ! "$compilation" ; then compilation=0; fi
+else
+ compilation=0
+fi
+
+compilation=`expr $compilation + 1`
+
+creation=`date | \
+awk '{if (NF == 6) \
+ { print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \
+else \
+ { print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'`
+
+codelines=`find . -type f -regex '\./.*\.h' -or -regex '\./.*\.c' |xargs cat|wc -l`
+
+svn_revision=`svn info | grep Revision | grep -o -E '[0-9]+'`
+if test "x$svn_revision" = "x" ; then
+ svn_revision=`git log -n 1 --pretty="format:%h"`
+ if test "x$svn_revision" = "x" ; then
+ svn_revision="0"
+ else
+ git_commitcount=`git rev-list --all --no-merges | wc -l | sed "s/[ \t]//g"`
+ svn_revision="git-$git_commitcount-$svn_revision"
+ fi
+else
+ svn_revision="svn-$svn_revision"
+fi
+
+
+/bin/cat > version.c <<!SUB!THIS!
+//Auto generated file!
+
+#include "version.h"
+
+const char *compilation = "$compilation";
+const char *creation = "$creation";
+const char *revision = "$svn_revision";
+const char *codelines = "$codelines";
+
+!SUB!THIS!
+
+++ /dev/null
-
-#include "timeq.h"
-
-static struct timeq_entry *timeq_events;
-
-void timeq_tick() {
- struct timeq_entry *entry, *next;
- time_t now = time(0);
- for(entry = timeq_events; entry; entry = next) {
- if(entry->execute <= now) {
- entry->callback(entry->data);
- next = entry->next;
- free(entry);
- } else
- break;
- }
- timeq_events = entry;
-}
-
-struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data) {
- time_t now = time(0);
- struct timeq_entry *entry = malloc(sizeof(*entry));
- if (!entry)
- {
- perror("malloc() failed");
- return NULL;
- }
- entry->execute = now + seconds;
- entry->callback = callback;
- entry->data = data;
- entry->name = NULL;
- struct timeq_entry *next, *prev = NULL;
- for(next = timeq_events; next; next = next->next) {
- if(next->execute >= entry->execute)
- break;
- else
- prev = next;
- }
- if(prev == NULL) {
- entry->next = timeq_events;
- timeq_events = entry;
- } else {
- entry->next = next;
- prev->next = entry;
- }
- return entry;
-}
-
-struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data) {
- struct timeq_entry *entry = timeq_add(seconds, callback, data);
- entry->name = strdup(name);
- return entry;
-}
-
-int timeq_del(struct timeq_entry* entry) {
- struct timeq_entry *centry, *last = NULL;
- for(centry = timeq_events; centry; centry = centry->next) {
- if(centry == entry) {
- if(last)
- last->next = centry->next;
- else
- timeq_events = centry->next;
- if(centry->name)
- free(centry->name);
- free(centry);
- return 1;
- } else {
- last = centry;
- }
- }
- return 0;
-}
-
-int timeq_del_name(char *name) {
- struct timeq_entry *centry, *last = NULL;
- for(centry = timeq_events; centry; centry = centry->next) {
- if(centry->name && !stricmp(centry->name, name)) {
- if(last)
- last->next = centry->next;
- else
- timeq_events = centry->next;
- free(centry->name);
- free(centry);
- return 1;
- } else {
- last = centry;
- }
- }
- return 0;
-}
-
-int timeq_name_exists(char *name) {
- struct timeq_entry *centry;
- for(centry = timeq_events; centry; centry = centry->next) {
- if(centry->name && !stricmp(centry->name, name)) {
- return 1;
- }
- }
- return 0;
-}
+++ /dev/null
-#ifndef _timeq_h
-#define _timeq_h
-
-#include "main.h"
-
-#define TIMEQ_CALLBACK(NAME) void NAME(UNUSED_ARG(void *data))
-typedef TIMEQ_CALLBACK(timeq_callback_t);
-
-struct timeq_entry {
- char *name;
- time_t execute;
- timeq_callback_t *callback;
- void *data;
-
- struct timeq_entry *next;
-};
-
-void timeq_tick();
-struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data);
-struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data);
-int timeq_del(struct timeq_entry* entry);
-int timeq_del_name(char *name);
-int timeq_name_exists(char *name);
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include "tools.h"
-#include "UserNode.h"
-#include "ChanNode.h"
-#include "lang.h"
-#include "ClientSocket.h"
-
-static const struct default_language_entry msgtab[] = {
- {"TIME_MASK_2_ITEMS", "%s and %s"}, /* {ARGS: "2 days", "1 hour"} */
- {"TIME_MASK_3_ITEMS", "%s, %s and %s"}, /* {ARGS: "2 days", "1 hour", "20 minutes"} */
- {"TIME_YEAR", "year"},
- {"TIME_YEARS", "years"},
- {"TIME_MONTH", "month"},
- {"TIME_MONTHS", "months"},
- {"TIME_WEEK", "week"},
- {"TIME_WEEKS", "weeks"},
- {"TIME_DAY", "day"},
- {"TIME_DAYS", "days"},
- {"TIME_HOUR", "hour"},
- {"TIME_HOURS", "hours"},
- {"TIME_MINUTE", "minute"},
- {"TIME_MINUTES", "minutes"},
- {"TIME_SECOND", "second"},
- {"TIME_SECONDS", "seconds"},
- {NULL, NULL}
-};
-
-/* copied from IRCU 2.10.12 match.c */
-/*
- * Compare if a given string (name) matches the given
- * mask (which can contain wild cards: '*' - match any
- * number of chars, '?' - match any single character.
- *
- * return 0, if match
- * 1, if no match
- *
- * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu)
- * Rewritten by Timothy Vogelsang (netski), net@astrolink.org
- */
-int match(const char *mask, const char *name)
-{
- const char *m = mask, *n = name;
- const char *m_tmp = mask, *n_tmp = name;
- int star_p;
-
- for (;;) switch (*m) {
- case '\0':
- if (!*n)
- return 0;
- backtrack:
- if (m_tmp == mask)
- return 1;
- m = m_tmp;
- n = ++n_tmp;
- if (*n == '\0')
- return 1;
- break;
- case '\\':
- m++;
- /* allow escaping to force capitalization */
- if (*m++ != *n++)
- goto backtrack;
- break;
- case '*': case '?':
- for (star_p = 0; ; m++) {
- if (*m == '*')
- star_p = 1;
- else if (*m == '?') {
- if (!*n++)
- goto backtrack;
- } else break;
- }
- if (star_p) {
- if (!*m)
- return 0;
- else if (*m == '\\') {
- m_tmp = ++m;
- if (!*m)
- return 1;
- for (n_tmp = n; *n && *n != *m; n++) ;
- } else {
- m_tmp = m;
- for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ;
- }
- }
- /* and fall through */
- default:
- if (!*n)
- return *m != '\0';
- if (tolower(*m) != tolower(*n))
- goto backtrack;
- m++;
- n++;
- break;
- }
-}
-
-
-//TABLES
-struct Table *table_init(int width, int length, int flags) {
- int row;
- struct Table *table = malloc(sizeof(*table));
- table->contents = malloc(length * sizeof(*table->contents));
- for(row = 0; row < length; row++) {
- table->contents[row] = calloc(width, sizeof(*table->contents[row]));
- }
- table->length = length;
- table->width = width;
- table->flags = flags;
- table->col_flags = calloc(length, sizeof(int));
- table->entrys = 0;
- table->maxwidth = calloc(length, sizeof(int));
- table->table_lines = NULL;
- return table;
-}
-
-int table_add(struct Table *table, char **entry) {
- int col;
- if(table->entrys == table->length) return 0;
- for(col = 0; col < table->width; col++) {
- table->contents[table->entrys][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
- if(table->contents[table->entrys][col])
- table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
- if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
- table->maxwidth[col] = strlen(entry[col]);
- }
- table->entrys++;
- return 1;
-}
-
-int table_change(struct Table *table, int row, char **entry) {
- int col;
- if(row >= table->length) return 0;
- for(col = 0; col < table->width; col++) {
- if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
- free(table->contents[row][col]);
- table->contents[row][col] = ((table->flags & TABLE_FLAG_USE_POINTER) || !entry[col] ? entry[col] : strdup(entry[col]));
- if(table->contents[row][col])
- table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
- if(entry[col] && strlen(entry[col]) > table->maxwidth[col])
- table->maxwidth[col] = strlen(entry[col]);
- }
- return 1;
-}
-
-int table_change_field(struct Table *table, int row, int col, char *entry) {
- if(row >= table->length) return 0;
- if(col >= table->width) return 0;
- if(table->contents[row][col] && !(table->flags & TABLE_FLAG_USE_POINTER))
- free(table->contents[row][col]);
- table->contents[row][col] = (((table->flags & TABLE_FLAG_USE_POINTER) || !entry) ? entry : strdup(entry));
- if(table->contents[row][col])
- table->col_flags[col] |= TABLE_FLAG_COL_CONTENTS;
- if(entry && strlen(entry) > table->maxwidth[col])
- table->maxwidth[col] = strlen(entry);
- return 1;
-}
-
-int table_set_bold(struct Table *table, int collum, int bold) {
- if(bold)
- table->col_flags[collum] |= TABLE_FLAG_COL_BOLD;
- else
- table->col_flags[collum] &= ~TABLE_FLAG_COL_BOLD;
- return 1;
-}
-
-char **table_end(struct Table *table) {
- int row, col, tablewidth = 0, pos,i;
- if(!table->entrys) return NULL;
- for(col = 0; col < table->width; col++) {
- tablewidth += table->maxwidth[col]+1;
- if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
- tablewidth += 2;
- }
- table->table_lines = malloc(table->entrys * sizeof(table->table_lines));
- for(row = 0; row < table->entrys; row++) {
- table->table_lines[row] = malloc(tablewidth * sizeof(*table->table_lines[row]));
- pos = 0;
- for(col = 0; col < table->width; col++) {
- if(!(table->col_flags[col] & TABLE_FLAG_COL_CONTENTS)) continue;
- if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
- table->table_lines[row][pos++] = '\002';
- for(i = 0; i < strlen(table->contents[row][col]); i++) {
- table->table_lines[row][pos++] = table->contents[row][col][i];
- }
- if(col < table->width-1) {
- for(;i < table->maxwidth[col]; i++) {
- table->table_lines[row][pos++] = ' ';
- }
- table->table_lines[row][pos++] = ' ';
- } else
- table->table_lines[row][pos++] = '\0';
-
- if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
- table->table_lines[row][pos++] = '\002';
- }
- }
- return table->table_lines;
-}
-
-void table_free(struct Table *table) {
- int row, col;
- for(row = 0; row < table->length; row++) {
- if(!(table->flags & TABLE_FLAG_USE_POINTER) && table->entrys > row) {
- for(col = 0; col < table->width; col++) {
- if(table->contents[row][col])
- free(table->contents[row][col]);
- }
- }
- free(table->contents[row]);
- }
- free(table->contents);
- free(table->col_flags);
- free(table->maxwidth);
- if(table->table_lines) {
- for(row = 0; row < table->entrys; row++) {
- free(table->table_lines[row]);
- }
- free(table->table_lines);
- }
- free(table);
-}
-
-char* timeToStr(struct UserNode *user, int seconds, int items, char *buf) {
- char item[items][MAXLEN];
- int tmp, citem = 0;
- if(citem != items && seconds >= 31536000) { //60*60*24*365 = 31536000
-
- tmp = seconds / 31536000;
- sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_YEAR" : "TIME_YEARS"));
- seconds -= tmp * 31536000;
- }
- if(citem != items && seconds >= 86400) { //60*60*24 = 86400
- tmp = seconds / 86400;
- sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_DAY" : "TIME_DAYS"));
- seconds -= tmp * 86400;
- }
- if(citem != items && seconds >= 3600) { //60*60 = 3600
- tmp = seconds / 3600;
- sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_HOUR" : "TIME_HOURS"));
- seconds -= tmp * 3600;
- }
- if(citem != items && seconds >= 60) {
- tmp = seconds / 60;
- sprintf(item[citem++], "%d %s", tmp, get_language_string(user, tmp == 1 ? "TIME_MINUTE" : "TIME_MINUTES"));
- seconds -= tmp * 60;
- }
- if(citem != items && seconds >= 1) {
- sprintf(item[citem++], "%d %s", seconds, get_language_string(user, seconds == 1 ? "TIME_SECOND" : "TIME_SECONDS"));
- }
- if(citem == 2) {
- build_language_string(user, buf, "TIME_MASK_2_ITEMS", item[0], item[1]);
- } else if(citem == 3) {
- build_language_string(user, buf, "TIME_MASK_3_ITEMS", item[0], item[1], item[2]);
- } else {
- int i, ii, p = 0;
- for(i = 0; i < citem; i++) {
- for(ii = 0; ii < strlen(item[i]); ii++) {
- buf[p++] = item[i][ii];
- }
- buf[p++] = ' ';
- }
- buf[(p ? p-1 : 0)] = '\0';
- }
- return buf;
-}
-
-int strToTime(struct UserNode *user, char *str) {
- /*
- * y = year = 365 days
- * M = month = 30 days
- * w = week = 7 days
- * d = day
- * h = hour
- * m = minute
- * (s) = second
- */
- int total_time = 0, cvalue;
- char *p, tmpchar;
- 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++;
- tmpchar = *p;
- *p = '\0';
- if(p - str > 1) { //unit has more than one char
- if(!stricmp(str, "year") || !stricmp(str, "year") || !stricmp(str, get_language_string(user, "TIME_YEAR")) || !stricmp(str, get_language_string(user, "TIME_YEARS")))
- unit_multiplikator = 31536000; //60*60*24*365 = 31536000
- else if(!stricmp(str, "month") || !stricmp(str, "months") || !stricmp(str, get_language_string(user, "TIME_MONTH")) || !stricmp(str, get_language_string(user, "TIME_MONTHS")))
- unit_multiplikator = 2592000; //60*60*24*30 = 2592000
- else if(!stricmp(str, "week") || !stricmp(str, "weeks") || !stricmp(str, get_language_string(user, "TIME_WEEK")) || !stricmp(str, get_language_string(user, "TIME_WEEKS")))
- unit_multiplikator = 604800; //60*60*24*7 = 604800
- else if(!stricmp(str, "day") || !stricmp(str, "days") || !stricmp(str, get_language_string(user, "TIME_DAY")) || !stricmp(str, get_language_string(user, "TIME_DAYS")))
- unit_multiplikator = 86400; //60*60*24 = 86400
- else if(!stricmp(str, "hour") || !stricmp(str, "hours") || !stricmp(str, get_language_string(user, "TIME_HOUR")) || !stricmp(str, get_language_string(user, "TIME_HOURS")))
- unit_multiplikator = 3600; //60*60 = 3600
- else if(!stricmp(str, "minute") || !stricmp(str, "minutes") || !stricmp(str, "min") || !stricmp(str, "mins") || !stricmp(str, get_language_string(user, "TIME_MINUTE")) || !stricmp(str, get_language_string(user, "TIME_MINUTES")))
- unit_multiplikator = 60;
- else
- unit_multiplikator = 1;
- } else {
- switch(*str) {
- case 'y':
- unit_multiplikator = 31536000; //60*60*24*365 = 31536000
- break;
- case 'M':
- unit_multiplikator = 2592000; //60*60*24*30 = 2592000
- break;
- case 'w':
- unit_multiplikator = 604800; //60*60*24*7 = 604800
- break;
- case 'd':
- unit_multiplikator = 86400; //60*60*24 = 86400
- break;
- case 'h':
- unit_multiplikator = 3600; //60*60 = 3600
- break;
- case 'm':
- unit_multiplikator = 60;
- break;
- default:
- unit_multiplikator = 1;
- break;
- }
- }
- total_time += (cvalue * unit_multiplikator);
- *p = tmpchar;
- str = p;
- }
- return total_time;
-}
-
-struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan) {
- struct ModeBuffer *modeBuf = malloc(sizeof(*modeBuf));
- if(!modeBuf) {
- perror("malloc() failed");
- return NULL;
- }
- modeBuf->client = client;
- modeBuf->chan = chan;
- modeBuf->addCount = 0;
- modeBuf->delCount = 0;
- return modeBuf;
-}
-
-void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param) {
- if(add) {
- modeBuf->addModes[modeBuf->addCount] = mode;
- modeBuf->addModesParams[modeBuf->addCount] = (param ? strdup(param) : NULL);
- modeBuf->addCount++;
- modeBuf->addModes[modeBuf->addCount] = '\0';
- } else {
- modeBuf->delModes[modeBuf->delCount] = mode;
- modeBuf->delModesParams[modeBuf->delCount] = (param ? strdup(param) : NULL);
- modeBuf->delCount++;
- modeBuf->delModes[modeBuf->delCount] = '\0';
- }
- if(modeBuf->addCount + modeBuf->delCount == MAXMODES)
- flushModeBuffer(modeBuf);
-}
-
-void flushModeBuffer(struct ModeBuffer *modeBuf) {
- char modeStr[MAXMODES+3];
- int modePos = 0;
- char paramStr[MAXLEN];
- int paramPos = 0;
- int i;
- if(modeBuf->addCount) {
- modeStr[modePos++] = '+';
- for(i = 0; i < modeBuf->addCount; i++) {
- modeStr[modePos++] = modeBuf->addModes[i];
- if(modeBuf->addModesParams[i]) {
- paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->addModesParams[i]);
- }
- }
- modeBuf->addCount = 0;
- }
- if(modeBuf->delCount) {
- modeStr[modePos++] = '-';
- for(i = 0; i < modeBuf->delCount; i++) {
- modeStr[modePos++] = modeBuf->delModes[i];
- if(modeBuf->delModesParams[i]) {
- paramPos += sprintf(paramStr + paramPos, " %s", modeBuf->delModesParams[i]);
- }
- }
- modeBuf->delCount = 0;
- }
- modeStr[modePos++] = '\0';
- putsock(modeBuf->client, "MODE %s %s%s", modeBuf->chan->name, modeStr, paramStr);
-}
-
-void freeModeBuffer(struct ModeBuffer *modeBuf) {
- if(modeBuf->addCount + modeBuf->delCount)
- flushModeBuffer(modeBuf);
- free(modeBuf);
-}
-
-int is_ircmask(const char *text) {
- while (*text && (isalnum((char)*text) || strchr("-_[]|\\`^{}?*", *text)))
- text++;
- if (*text++ != '!')
- return 0;
- while (*text && *text != '@' && !isspace((char)*text))
- text++;
- if (*text++ != '@')
- return 0;
- while (*text && !isspace((char)*text))
- text++;
- return !*text;
-}
-
-char* generate_banmask(struct UserNode *user, char *buffer) {
- char *userhost = user->host;
-
- if(isFakeHost(user->host)) {
- sprintf(buffer, "*!*@%s", userhost);
- return buffer;
- }
-
- //check if the hostname has more than 4 connections (trusted host)
- if(countUsersWithHost(userhost) > 4) {
- sprintf(buffer, "*!%s@%s", user->ident, userhost);
- return buffer;
- } else {
- sprintf(buffer, "*!*@%s", userhost);
- return buffer;
- }
-}
-
-char* make_banmask(char *input, char* buffer) {
- char *nick = NULL, *ident = NULL, *host = NULL;
- char tmp[HOSTLEN];
- char *p;
- if((p = strstr(input, "!"))) {
- nick = input;
- *p = '\0';
- ident = p+1;
- if((p = strstr(ident, "@"))) {
- *p = '\0';
- host = p+1;
- }
- } else if((p = strstr(input, "@"))) {
- ident = input;
- *p = '\0';
- host = p+1;
- } else if((p = strstr(input, "."))) {
- host = input;
- } else if(*input == '*' && input[1] != '\0' && !strstr(input+1, "*")) {
- //AUTH MASK
- p = getAuthFakehost(input+1);
- if(p)
- host = p;
- else {
- sprintf(tmp, "%s.*", input+1);
- host = tmp;
- }
- } else {
- struct UserNode *user = searchUserByNick(input);
- if(user)
- return generate_banmask(user, buffer);
- else
- nick = input;
- }
- if(nick && *nick == '\0') nick = NULL;
- if(ident && *ident == '\0') ident = NULL;
- if(host && *host == '\0') host = NULL;
- sprintf(buffer, "%s!%s@%s", (nick ? nick : "*"), (ident ? ident : "*"), (host ? host : "*"));
- return buffer;
-}
-
-int isFakeHost(char *host) {
- char *p1, *p2 = host;
-
- //find the last dot to identify if the hostmask is a fake host
- while((p1 = strstr(p2, "."))) {
- p2 = p1 + 1;
- }
- //TLD database: http://www.iana.org/domains/root/db/
- //the longest TLD i found was 6 chars long (ignoring the stange exotic ones :D)
- //but we even ignore '.museum' and '.travel' so we can say that the TLD of our mask needs to be less than 4 chars to be a real domain
- return (strlen(p2+1) > 4);
-}
-
-void init_tools() {
- register_default_language_table(msgtab);
-}
+++ /dev/null
-#ifndef _tools_h
-#define _tools_h
-
-#include "main.h"
-
-#define TABLE_FLAG_USE_POINTER 0x01
-#define TABLE_FLAG_COL_BOLD 0x02
-#define TABLE_FLAG_COL_CONTENTS 0x04
-
-struct ClientSocket;
-struct UserNode;
-struct ChanNode;
-
-struct Table {
- char ***contents;
- int length;
- int width;
- int flags;
- int *col_flags;
-
- int entrys;
- int *maxwidth;
-
- char **table_lines; //we just store this to free it in table_free
-};
-
-struct ModeBuffer {
- struct ClientSocket *client;
- struct ChanNode *chan;
- char addModes[MAXMODES];
- char delModes[MAXMODES];
- char *addModesParams[MAXMODES];
- char *delModesParams[MAXMODES];
- int addCount;
- int delCount;
-};
-
-int match(const char *mask, const char *name);
-
-struct Table *table_init(int width, int length, int flags);
-int table_add(struct Table *table, char **entry);
-int table_change(struct Table *table, int row, char **entry);
-int table_change_field(struct Table *table, int row, int col, char *entry);
-int table_set_bold(struct Table *table, int collum, int bold);
-char **table_end(struct Table *table);
-void table_free(struct Table *table);
-
-char* timeToStr(struct UserNode *user, int seconds, int items, char *buf);
-int strToTime(struct UserNode *user, char *str);
-
-struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan);
-#define modeBufferSimpleMode(MODEBUF,ADD,MODE) modeBufferSet(MODEBUF, ADD, MODE, NULL)
-#define modeBufferOp(MODEBUF,USER) modeBufferSet(MODEBUF, 1, 'o', USER)
-#define modeBufferDeop(MODEBUF,USER) modeBufferSet(MODEBUF, 0, 'o', USER)
-#define modeBufferVoice(MODEBUF,USER) modeBufferSet(MODEBUF, 1, 'v', USER)
-#define modeBufferDevoice(MODEBUF,USER) modeBufferSet(MODEBUF, 0, 'v', USER)
-#define modeBufferBan(MODEBUF,MASK) modeBufferSet(MODEBUF, 1, 'b', MASK)
-#define modeBufferUnban(MODEBUF,MASK) modeBufferSet(MODEBUF, 0, 'b', MASK)
-void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param);
-void flushModeBuffer(struct ModeBuffer *modeBuf);
-void freeModeBuffer(struct ModeBuffer *modeBuf);
-
-int is_ircmask(const char *text);
-
-char* generate_banmask(struct UserNode *user, char *buffer);
-char* make_banmask(char *input, char* buffer);
-int isFakeHost(char *host);
-
-void init_tools();
-
-#endif
\ No newline at end of file
+++ /dev/null
-#ifndef _version_h
-#define _version_h
-
-#include "main.h"
-
-extern const char *compilation;
-extern const char *creation;
-extern const char *revision;
-extern const char *codelines;
-
-#endif
\ No newline at end of file
+++ /dev/null
-#! /bin/sh
-echo "Extracting version.c ..."
-
-if test -r version.c
-then
- compilation=`sed -n 's/^const char \*compilation = \"\(.*\)\";/\1/p' < version.c`
- if test ! "$compilation" ; then compilation=0; fi
-else
- compilation=0
-fi
-
-compilation=`expr $compilation + 1`
-
-creation=`date | \
-awk '{if (NF == 6) \
- { print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \
-else \
- { print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'`
-
-codelines=`find . -type f -regex '\./.*\.h' -or -regex '\./.*\.c' |xargs cat|wc -l`
-
-svn_revision=`svn info | grep Revision | grep -o -E '[0-9]+'`
-if test "x$svn_revision" = "x" ; then
- svn_revision=`git log -n 1 --pretty="format:%h"`
- if test "x$svn_revision" = "x" ; then
- svn_revision="0"
- else
- git_commitcount=`git rev-list --all --no-merges | wc -l | sed "s/[ \t]//g"`
- svn_revision="git-$git_commitcount-$svn_revision"
- fi
-else
- svn_revision="svn-$svn_revision"
-fi
-
-
-/bin/cat >version.c <<!SUB!THIS!
-//Auto generated file!
-
-#include "version.h"
-
-const char *compilation = "$compilation";
-const char *creation = "$creation";
-const char *revision = "$svn_revision";
-const char *codelines = "$codelines";
-
-!SUB!THIS!
-