commit 0f32a18d738a8e573d239cd89ff07fac05c2ea05 Author: Pentium44 Date: Tue Nov 24 14:24:02 2020 -0800 Initial push, working with MintIRCd diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0105c42 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +# Make CServ + +CC=gcc +EXECUTABLE=cserv +OBJECTS=src/irc.o src/functions.o src/main.o +FLAGS=-Wall + +all: main + +main: $(OBJECTS) + $(CC) $(OBJECTS) -o $(EXECUTABLE) $(FLAGS) + +clean: + rm src/*o $(EXECUTABLE) diff --git a/src/dictionary.h b/src/dictionary.h new file mode 100644 index 0000000..79af08d --- /dev/null +++ b/src/dictionary.h @@ -0,0 +1,27 @@ +/* reply database */ +struct { + char *quote; + char *reply; +} dictionary [] = { + {"xD", "Whats so funny now?"}, + {"k\r\n", "Can you not."}, + {"anime", "Okay. I am sorry you don't have a life, but I am going to stab you now."}, + {"time to eat", "if you were a bot, no eating is required ;)"}, + {"dinner", "if you were a bot, no eating is required ;)"}, + {"food", "if you were a bot, no eating is required ;)"}, + {">.>", "<.<"}, + {">_>", ">.>"}, + {"<.<", ">_>"}, + {"*bot*: install gentoo", "fien."}, + {"*bot*, install gentoo", "fien."}, + {"*bot*: are you a bot", "Nofuckingshit"}, + {"*bot*, are you a bot", "Nofuckingshit"}, + {"wat", "what*"}, + {"wut", "what*"}, + {"weeaboo", "go die, weeaboo for life c:"}, + {":(", "whats wrong?"}, + {":c", "whats with the sad faces?"}, + {"D:", "no sad faces!"}, + //{"", ""}, + {0, 0} +}; diff --git a/src/functions.c b/src/functions.c new file mode 100644 index 0000000..ae9a2ee --- /dev/null +++ b/src/functions.c @@ -0,0 +1,224 @@ +#include "main.h" +#include "functions.h" +#include "irc.h" + +/* Remove carriage return from string */ +const char *remove_creturn(char *str) { + str = strtok(str, "\r"); + return str; +} + +/* str_replace function - from stakoverflow */ +char *str_replace(char *orig, char *rep, char *with) { + char *result, *buf, *ins; + int replen, withlen, frontlen, count; + + // check arguments + if (!orig) { + return NULL; + } + + if (!rep) { + rep = ""; + } + replen = strlen(rep); + + if (!with) { + with = ""; + } + withlen = strlen(with); + + ins = orig; + for (count = 0; buf = strstr(ins, rep); ++count) { + ins = buf + replen; + } + + buf = result = malloc(strlen(orig) + (withlen - replen) * count + 1); + + if (!result) { + return NULL; + } + + while (count--) { + ins = strstr(orig, rep); + frontlen = ins - orig; + buf = strncpy(buf, orig, frontlen) + frontlen; + buf = strcpy(buf, with) + withlen; + orig += frontlen + replen; // move to next "end of rep" + } + + strcpy(buf, orig); + return result; +} + +char *bot_nick_exists(char *str, char *nick) { + char *searchstr = strstr(str, nick); + if(searchstr) { + return "0"; + } + return "1"; +} + +int rand_int() { + int r = rand() % 50; + return r+1; +} + +int join_channels(int fd, char *filefd) { + FILE *filename = fopen(filefd, "r"); + + char *search = " "; + + if(filename != NULL) { + /* buffer for each topic line */ + char line[2048]; + char channel[256]; + char sendbuf[2305]; + + /* read the file */ + while(fgets(line, sizeof(line), filename) != NULL) { + + if(strncmp("\n", line, 1)==0) { + continue; + } + + char *linetok; + linetok = strtok(line, search); + + /* join the channels!*/ + sprintf(sendbuf, "JOIN %s\r\n", linetok); + irc_send(fd, sendbuf); + sleep(1); + } + + } + else + { + return 1; + } + + return 0; +} + +int set_channel_owner(char *owner, const char *channel, char *filefd) { + FILE *file; + + char line[1024]; + if((file = fopen(filefd, "r"))) { + while(fgets(line, sizeof(line), file)!=NULL) { + char *dotok = strtok(line, " "); + if(strncmp(channel, dotok, strlen(channel))==0) { + fclose(file); + return 1; + } + } + fclose(file); + } + + if((file = fopen(filefd, "a"))) { + fprintf(file, "%s %s\n", channel, owner); + fclose(file); + return 0; + } + + return 1; +} + +int check_user_passwd(char *nick, const char *pass, char *filefd) { + FILE *file; + + char line[1024]; + if((file = fopen(filefd, "r"))) { + while(fgets(line, sizeof(line), file)!=NULL) { + /* check if user exists */ + char *dotok = strtok(line, " "); + if(strncmp(nick, dotok, strlen(nick))==0) { + dotok = strtok(NULL, " "); + if(strncmp(pass, dotok, strlen(pass))==0) { + /* password correct */ + fclose(file); + return 0; + } + else + { + /* password incorrect */ + fclose(file); + return 1; + } + } + } + fclose(file); + } + + /* user does not exist */ + return 2; +} + +int check_channel_owner(char *nick, const char *channel, char *filefd) { + FILE *file; + + char line[1024]; + if((file = fopen(filefd, "r"))) { + while(fgets(line, sizeof(line), file)!=NULL) { + /* check if user exists */ + char *dotok = strtok(line, " "); + if(strncmp(channel, dotok, strlen(channel))==0) { + dotok = strtok(NULL, " "); + if(strncmp(nick, dotok, strlen(nick))==0) { + /* owns channel */ + fclose(file); + return 0; + } + else + { + /* doesn't */ + fclose(file); + return 1; + } + } + } + fclose(file); + } + + /* channel not registered */ + return 2; +} + +// Not using this anymore +/* +int set_topic(char *channel, char *topic, char *filefd) { + FILE *file; + + char line[1024]; + if((file = fopen(filefd, "r"))) { + while(fgets(line, sizeof(line), file)!=NULL) { + char *dotok = strtok(line, " "); + if(strncmp(channel, dotok, strlen(channel))==0) { + fclose(file); + return 1; + } + } + fclose(file); + } + + if((file = fopen(filefd, "a"))) { + fprintf(file, "%s¤%s\n", channel, topic); + fclose(file); + return 0; + } + + return 1; +} +*/ + +int register_nick(char *nick, const char *pass, char *filefd) { + FILE *file; + + if((file = fopen(filefd, "a"))) { + fprintf(file, "%s %s\n", nick, pass); + fclose(file); + return 0; + } + + return 1; +} diff --git a/src/functions.h b/src/functions.h new file mode 100644 index 0000000..2420168 --- /dev/null +++ b/src/functions.h @@ -0,0 +1,11 @@ +/* functions */ +const char *remove_creturn(char *str); +char *str_replace(char *orig, char *rep, char *with); +char *bot_nick_exists(char *str, char *nick); +int rand_int(); +int join_channels(int fd, char *filefd); +int set_channel_owner(char *owner, const char *channel, char *filefd); +int check_user_passwd(char *nick, const char *pass, char *filefd); +int check_channel_owner(char *nick, const char *channel, char *filefd); +//int set_topic(char *channel, char *topic, char *filefd); +int register_nick(char *nick, const char *pass, char *filefd); diff --git a/src/irc.c b/src/irc.c new file mode 100644 index 0000000..8c5da51 --- /dev/null +++ b/src/irc.c @@ -0,0 +1,39 @@ +#include "main.h" +#include "irc.h" + +int irc_send(int socketfd, char *out) { + printf(">> %s", out); + return send(socketfd, out, strlen(out), 0); +} + +int irc_connect(char *server, int port, int *socketfd) { + struct sockaddr_in servaddr; + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + + struct hostent *serv_host = gethostbyname(server); + if (serv_host == NULL) { + return 0; + } + + bcopy((char *)serv_host->h_addr, + (char *)&servaddr.sin_addr.s_addr, + serv_host->h_length); + + if((*socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return 0; + } + + if(connect(*socketfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { + return 0; + } + + return 1; +} + +int irc_read(int socketfd, char *in) { + int n; + n = read(socketfd, in, SOCKBUFIN); + return n; +} diff --git a/src/irc.h b/src/irc.h new file mode 100644 index 0000000..0525237 --- /dev/null +++ b/src/irc.h @@ -0,0 +1,5 @@ +#define SOCKBUFIN 43008 + +int irc_send(int socketfd, char *out); +int irc_connect(char *server, int port, int *socketfd); +int irc_read(int socketfd, char *in); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..eda622f --- /dev/null +++ b/src/main.c @@ -0,0 +1,397 @@ +#include "main.h" +#include "irc.h" +#include "functions.h" +#include "dictionary.h" +#define BUF 36864 +#define LINEBUF 4096 + +char *owner, *nick; + +char *process_string(char *in, int n) { + int ii = -1, o, i, e; + char *nothing = "0"; + char *buf = malloc(8128); + + for(i = 0; i < n; i++) { + + ii++; + buf[ii] = in[i]; + + if((i > 0 && in[i] == '\n' && in[i-1] == '\r') || ii == 512) { + + buf[ii + 1] = '\0'; + o = ii; + ii = -1; + + printf("<< %s", buf); + + in[n] = 0; + if (!strncmp(buf, "PING", 4)) { + buf[1] = 'O'; + sleep(2); + return buf; + } + + if(buf[0] == ':') { + char *name; + char *cmd; + char *chan; + char *e; + char *pass; + char *topic; + char *topicchan; + char *msg; + char *b = malloc(4096); + + name = buf+1; + e = strchr(name,'!'); + if (!e) + return nothing; + *e = 0; + + cmd = strchr(e+1,' '); + if (!cmd) + return nothing; + cmd++; + e = strchr(cmd,' '); + if (!e) + return nothing; + *e = 0; + + chan = e+1; + e = strchr(chan,' '); + if (!e) + e = strchr(chan,'\r'); + if (!e) + e = strchr(chan,'\n'); + if (e) + *e = 0; + + if (!strcmp(cmd, "JOIN")) { + if(strncmp(name, nick, strlen(nick))==0) { + return nothing; + } else { + sprintf(b,"PRIVMSG %s :Welcome %s\r\n",chan,name); + return b; + } + } else if(!strcmp(cmd, "PRIVMSG")) { + + msg = strchr(e+1, ':'); + if(!msg) + return nothing; + if(msg) + msg++; + + int k; + + char *usestr = NULL; + char *searchstr; + for(k=0;dictionary[k].quote != 0;k++) { + if(strncmp(bot_nick_exists(dictionary[k].quote, nick), "0", 1)) { + usestr = str_replace(dictionary[k].quote, + "*bot*", nick); + } + + if(usestr==NULL) { + searchstr = dictionary[k].quote; + } else { + searchstr = usestr; + } + + if(strncmp(msg, searchstr, strlen(searchstr))==0) { + sprintf(b,"PRIVMSG %s :%s, %s\r\n",chan, + name,dictionary[k].reply); + free(searchstr); + return b; + } + + free(searchstr); + } + + /*if(strncmp(msg, "@topic", 4)==0) { + if(strncmp(name, owner, strlen(owner))==0) { + (void)set_topic(e, topic, "./channels.log"); + sprintf(b,"PRIVMSG %s :Topic set.\r\n", name); + return b; + } else { + sprintf(b,"PRIVMSG %s :You are not the owner, you cannot set topics.\r\n", name); + return b; + } + }*/ + + if(strncmp(msg, "@help", 5)==0) { + memset(b,0,sizeof(b)); + sprintf(b,"PRIVMSG %s :---HELP---\r\n" \ + "PRIVMSG %s :@register - Register your username\r\n" \ + "PRIVMSG %s :@login - Login to services\r\n" \ + "PRIVMSG %s :@claim - Register IRC channel to your nickname\r\n" \ + "PRIVMSG %s :@release - Release your nickname if someone else logs on with it.\r\n" \ + "PRIVMSG %s :@topic \"\" - Set your channel topic if you own the channel.\r\n", + name, name, name, name, name, name); + return b; + } + + if(strncmp(msg, "@topic", 6)==0) { + memset(b,0,sizeof(b)); + topicchan = strchr(msg, ' '); + if(!topicchan) { + sprintf(b,"PRIVMSG %s :You must provide a channel!.\r\n", name); + return b; + } + if(topicchan) + topicchan++; + + topic = strchr(topicchan, ' '); + + if(!topic) { + sprintf(b,"PRIVMSG %s :Provide a topic\r\n", name); + return b; + } + if(topic) + *topic = 0; + + topic++; + + topic = strchr(topic, '"'); + + if(!topic) { + sprintf(b,"PRIVMSG %s :Provide your topic in quotes! (Ex: \"this topic is what it is\")\r\n", name); + return b; + } + if(topic) { + *topic = 0; + topic++; + } + + e = strchr(topic, '"'); + + if(!e) { + sprintf(b,"PRIVMSG %s :Close your topic quotes!\r\n", name); + return b; + } + + /* + if(e) { + *e = 0; + } + */ + + char *pass = strtok(e, " "); + + pass = strtok(NULL, " "); + + if(!pass) { + sprintf(b,"PRIVMSG %s :Please provide your password!\r\n", name); + return b; + } + + if(check_user_passwd(name, remove_creturn(pass), "./users.log")==2) { + sprintf(b,"PRIVMSG %s :This user is not registered.\r\n", name); + return b; + } else if(check_user_passwd(name, remove_creturn(pass), "./users.log")==1) { + sprintf(b,"PRIVMSG %s :Wrong password. (%s)\r\n", name, remove_creturn(pass)); + return b; + } + + if(check_channel_owner(name, topicchan, "./owners.log")==1) { + sprintf(b,"PRIVMSG %s :You're not the channel owner!\r\n", name); + return b; + } else if(check_channel_owner(name, topicchan, "./owners.log")==2) { + sprintf(b,"PRIVMSG %s :Channel not registered!\r\n", name); + return b; + } else { + topic[strlen(topic)-1] = 0; /* strip last quote from string */ + sprintf(b,"JOIN %s\r\nTOPIC %s :%s\r\nPRIVMSG %s :Topic for %s set to \"%s\".\r\n", topicchan, topicchan, topic, name, topicchan, topic); + return b; + } + + } + + if(strncmp(msg, "@release", 8)==0) { + memset(b,0,sizeof(b)); + e = strchr(msg, ' '); + if(!e) { + sprintf(b,"PRIVMSG %s :You must provide a username.\r\n", name); + return b; + } + if(e) + e++; + + pass = strtok(e, " "); + pass = strtok(NULL, " "); + if(!pass) { + sprintf(b,"PRIVMSG %s :You must provide your password to claim your nickname!\r\n", name); + return b; + } + + if(strncmp(e, nick, strlen(nick))==0) { + sprintf(b,"PRIVMSG %s :Cannot claim %s\r\n", name, nick); + return b; + } + + if(check_user_passwd(e, remove_creturn(pass), "./users.log")==2) { + sprintf(b,"PRIVMSG %s :This user is not registered.\r\n", name); + return b; + } + if(check_user_passwd(e, remove_creturn(pass), "./users.log")==1) { + sprintf(b,"PRIVMSG %s :Wrong password. (%s)\r\n", name, pass); + return b; + } + + sprintf(b,"SETNICK %s\r\n", remove_creturn(e)); + return b; + + + } + + if(strncmp(msg, "@claim", 6)==0) { + memset(b,0,sizeof(b)); + e = strchr(msg, ' '); + if(!e) + return nothing; + if(e) + e++; + + pass = strtok(e, " "); + pass = strtok(NULL, " "); + if(!pass) { + sprintf(b,"PRIVMSG %s :You must provide a password to grab a channel!\r\n", name); + return b; + } + + if(check_user_passwd(name, remove_creturn(pass), "./users.log")==2) { + sprintf(b,"PRIVMSG %s :You are not registered, see @help\r\n", name); + return b; + } + if(check_user_passwd(name, remove_creturn(pass), "./users.log")==1) { + sprintf(b,"PRIVMSG %s :Wrong password. (%s)\r\n", name, pass); + return b; + } + + if(set_channel_owner(name, e, "./owners.log")==0) { + sprintf(b,"JOIN %s\r\nPRIVMSG %s :You now own %s\r\n", remove_creturn(e), name, e); + return b; + } else { + sprintf(b,"PRIVMSG %s :Failed to set you as owner (%s)\r\n", name, remove_creturn(e)); + return b; + } + } + + if(strncmp(msg, "@login", 6)==0) { + memset(b,0,sizeof(b)); + e = strchr(msg, ' '); + if(!e) + return nothing; + if(e) + e++; + + if(check_user_passwd(name, remove_creturn(e), "./users.log")==2) { + sprintf(b,"PRIVMSG %s :You are not registered, see @help\r\n", name); + return b; + } + if(check_user_passwd(name, remove_creturn(e), "./users.log")==1) { + sprintf(b,"PRIVMSG %s :Wrong password. (%s)\r\n", name, remove_creturn(e)); + return b; + } + + sprintf(b,"HOST %s\r\nPRIVMSG %s :You're now known as %s (hidden/%s)\r\n", name, name, name, name); + return b; + } + + if(strncmp(msg, "@register", 9)==0) { + memset(b,0,sizeof(b)); + e = strchr(msg, ' '); + if(!e) { + sprintf(b,"PRIVMSG %s :You must provide a password.\r\n", name); + return b; + } + if(e) + e++; + + if(check_user_passwd(name, remove_creturn(e), "./users.log")!=2) { + sprintf(b,"PRIVMSG %s :This user already exists.\r\n", name); + return b; + } + + if(register_nick(name, remove_creturn(e), "./users.log")==0) { + sprintf(b,"PRIVMSG %s :You now own %s (password: %s)\r\n", name, name, remove_creturn(e)); + return b; + } else { + sprintf(b,"PRIVMSG %s :Failed to register %s\r\n", name, name); + return b; + } + } + + return nothing; + } else { + return nothing; + } + } + } + + } // for loop + + free(buf); // Free memory allocated with malloc + +} + +int main(int argc, char **argv) { + int socketfd, n; + char in[BUF+1], out[BUF+1], c[512]; + char *pos, *action; + + if(argc != 5) { + printf("Usage: %s
\n", argv[0]); + exit(1); + } else if(atoi(argv[2]) < 1 || atoi(argv[2]) > 50000) { + printf("Invalid port specified.\n"); + exit(1); + } else if(irc_connect(argv[1], atoi(argv[2]), &socketfd) == 0) { + printf("Failed to connect to %s.\n", argv[1]); + exit(1); + } + + nick = argv[3]; + owner = argv[4]; + + if(strlen(nick)>48) { + printf("Error: irc bot nickname too long\n"); + exit(1); + } + + if(strlen(owner)>48) { + printf("Error: bot owner nickname too long\n"); + exit(1); + } + + /* write to buffer */ + sprintf(c, "NICK %s\r\n", nick); + irc_send(socketfd, c); + sprintf(c, "USER %s %s %s :%s\r\n", nick, nick, nick, nick); + irc_send(socketfd, c); + + /* do the service jobs */ + if(join_channels(socketfd, "./owners.log") == 2) { + return 1; + } + + while(1) { + in[0] = 0; + n = irc_read(socketfd, in); + + if (n > 0) { + char *str = process_string(in, n); + if(strncmp(str, "0", 1)!=0) { + irc_send(socketfd, str); + free(str); + fflush(stderr); + } + if(strncmp(str, "QUIT", 4)==0) { + fflush(stderr); + free(str); + break; + } + } // if(n > 0) + } // while(1) + return 0; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..40abc66 --- /dev/null +++ b/src/main.h @@ -0,0 +1,6 @@ +#include +#include +#include +#include +#include +#include