Initial push, working with MintIRCd

master
Pentium44 2020-11-24 14:24:02 -08:00
commit 0f32a18d73
8 changed files with 723 additions and 0 deletions

14
Makefile Normal file
View File

@ -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)

27
src/dictionary.h Normal file
View File

@ -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}
};

224
src/functions.c Normal file
View File

@ -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;
}

11
src/functions.h Normal file
View File

@ -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);

39
src/irc.c Normal file
View File

@ -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;
}

5
src/irc.h Normal file
View File

@ -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);

397
src/main.c Normal file
View File

@ -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 <password> - Register your username\r\n" \
"PRIVMSG %s :@login <password> - Login to services\r\n" \
"PRIVMSG %s :@claim <channel> <user password> - Register IRC channel to your nickname\r\n" \
"PRIVMSG %s :@release <nickname> <user password> - Release your nickname if someone else logs on with it.\r\n" \
"PRIVMSG %s :@topic <channel> \"<channel topic>\" <user password> - 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 <address> <port> <nick> <owner>\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;
}

6
src/main.h Normal file
View File

@ -0,0 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>