static void get_users_from_chan(struct socket_info *sinfo, char *params) { char *channel; char cmode; struct clientinfo user; channel = strtok(params, " "); channel = strtok(NULL, " "); channel = strtok(NULL, " "); user.nick = strtok(NULL, " "); user.ident = NULL; user.address = NULL; user.server = GetServerBySocket(sinfo); if (user.nick[0] == ':') user.nick++; do { /* if it's not a char allowed at the beginning of the nick it's probably a mode char */ if (!isnickstartchar(user.nick[0])) { cmode = user.nick[0]; user.nick++; } AddUserToChannel(&user, channel); botevent(EV_HERE,sinfo,user.nick,channel,NULL); /* next User */ user.nick = strtok(NULL, " "); } while (user.nick != NULL); }
void loadanopedb() { char accname[50]; char md5_pass[40]; char email[EMAILLEN+1]; int acclvl; char channelname[CHANLEN+1]; char owner[50]; char entrymsg[200]; User *uptr,*owner_ptr; Chan *chan_ptr; MYSQL_RES *result; MYSQL_ROW row; char *pass; if (!reconnect_to_db()) { fprintf(stderr,"Cannot connect to db\n"); operlog("Cannot connect to db"); return; } mysql_query(&mysql2,"SELECT display,pass,email FROM anope_ns_core"); if ((result = mysql_use_result(&mysql2)) == NULL) { printf("CRITICAL: Cannot load anope user db: mysql_use_result returned NULL !\n"); return; } while ((row = mysql_fetch_row(result))) { bzero(accname,50); bzero(md5_pass,40); bzero(email,EMAILLEN); strncpy(accname,row[0],50); if (row[1][0] == '\0') { printf("ANOPE ERROR: User %s does not have any pass !\n",accname); continue; } if (me.anopemd5 == 0) { pass = md5_hash(row[1]); strncpy(md5_pass,pass,40); free(pass); } else strncpy(md5_pass,row[1],40); strncpy(email,row[2],EMAILLEN); if (find_user(accname)) continue; uptr = AddUser(accname,1); uptr->lastseen = time(NULL); uptr->options = 0; uptr->timeout = TIMEOUT_DFLT; bzero(uptr->vhost,HOSTLEN); bzero(uptr->md5_pass,34); strncpy(uptr->md5_pass,md5_pass,32); strncpy(uptr->email,email,EMAILLEN); } mysql_query(&mysql2,"SELECT name,founder,entry_message FROM anope_cs_info"); if ((result = mysql_use_result(&mysql2)) == NULL) { printf("CRITICAL: Cannot load anope chan db: mysql_use_result returned NULL !\n"); return; } while((row = mysql_fetch_row(result))) { strncpy(channelname,row[0],CHANLEN); strncpy(owner,row[1],50); strncpy(entrymsg,row[2],200); if (find_channel(channelname)) continue; owner_ptr = find_user(owner); if (!owner_ptr) { fprintf(stderr,"ANOPE ERROR: Cannot load channel %s with owner %s : find_user returned NULL !!\n",channelname,owner); continue; } chan_ptr = CreateChannel(channelname,owner,time(NULL)); chan_ptr->autolimit = 0; strncpy(chan_ptr->entrymsg,entrymsg,sizeof(chan_ptr->entrymsg)-1); bzero(chan_ptr->mlock,50); } mysql_query(&mysql2,"SELECT channel,display,level FROM anope_cs_access"); if ((result = mysql_use_result(&mysql2)) == NULL) { printf("CRITICAL: Cannot load anope channel access db: mysql_use_result returned NULL !\n"); return; } while((row = mysql_fetch_row(result))) { strncpy(channelname,row[0],CHANLEN); strncpy(accname,row[1],50); acclvl = strtol(row[2],NULL,10); chan_ptr = find_channel(channelname); if (!chan_ptr) { fprintf(stderr,"ANOPE ERROR: Cannot load access for user %s for channel %s : find_channel returned NULL !!\n",accname,channelname); continue; } uptr = find_user(accname); if (!uptr) { fprintf(stderr,"ANOPE ERROR: Cannot load access for user %s for channel %s : find_user returned NULL !!\n",accname,channelname); continue; } if (find_cflag(accname,channelname)) continue; if (acclvl < CHLEV_OWNER) AddUserToChannel(uptr,chan_ptr,acclvl,0); } mysql_close(&mysql); }
void loadchandb() { char channelname[CHANLEN+1]; char owner[NICKLEN+1]; User *owner_ptr; User *user_ptr; Chan *chan_ptr; char accname[NICKLEN+MASKLEN+1]; int acclvl, automode, uflags; int options; char entrymsg[250]; MYSQL_RES *result; MYSQL_ROW row; Cflag *cflag; if (!reconnect_to_db()) { fprintf(stderr,"Cannot connect to db\n"); operlog("Cannot connect to db"); return; } mysql_query(&mysql,"SELECT * FROM child_chans"); if ((result = mysql_use_result(&mysql)) == NULL) { printf("CRITICAL: Cannot load chan table: mysql_use_result returned NULL\n"); return; } while ((row = mysql_fetch_row(result))) { strncpy(channelname,row[0],CHANLEN); strncpy(owner,row[1],NICKLEN); strncpy(entrymsg,row[2],200); options = strtol(row[3],NULL,10); owner_ptr = find_user(owner); if (!owner_ptr) { fprintf(stderr,"ERROR: Cannot load channel %s with owner %s : find_user returned NULL !!\n",channelname,owner); continue; } if (vv) printf("Adding channel %s with owner %s (%p) and options %d\n",channelname,owner,owner_ptr,options); if (find_channel(channelname)) continue; chan_ptr = CreateChannel(channelname,owner,atoi(row[6])); chan_ptr->regtime = strtol(row[7], NULL, 10); if (vv) printf("Channel %s added (%p)\n",channelname,chan_ptr); chan_ptr->options = options; chan_ptr->autolimit = atoi(row[5]); strncpy(chan_ptr->entrymsg,entrymsg,sizeof(chan_ptr->entrymsg)-1); chan_ptr->entrymsg[250] = '\0'; strncpy(chan_ptr->mlock,row[4],50); chan_ptr->mlock[50] = '\0'; strncpy(chan_ptr->topic, row[8], TOPICLEN); } mysql_query(&mysql,"SELECT * from child_chan_access"); if ((result = mysql_use_result(&mysql)) == NULL) { printf("CRITICAL: Cannot load chan access table: mysql_use_result returned NULL!\n"); return; } while ((row = mysql_fetch_row(result))) { strncpy(channelname,row[0],CHANLEN); strncpy(accname,row[1],NICKLEN+MASKLEN); acclvl = strtol(row[2],NULL,10); automode = strtol(row[3],NULL,10); chan_ptr = find_channel(channelname); if (!chan_ptr) { fprintf(stderr,"ERROR: Cannot load access for user %s for channel %s : find_channel returned NULL !!\n",accname,channelname); continue; } user_ptr = find_user(accname); if (!user_ptr && !IsMask(accname)) { fprintf(stderr,"ERROR: Cannot load access for user %s for channel %s : find_user returned NULL !!\n",accname,channelname); continue; } if (find_cflag(accname,channelname)) continue; if (vv) printf("Adding user %s (%p) for channel %s with level %d\n",accname,user_ptr,channelname,acclvl); if (acclvl < CHLEV_OWNER && !IsMask(accname)) { uflags = strtol(row[5], NULL, 10); cflag = AddUserToChannel(user_ptr,chan_ptr,acclvl,uflags); cflag->automode = automode; cflag->suspended = strtol(row[4], NULL, 10); } if (IsMask(accname)) AddMaskToChannel(accname,chan_ptr,acclvl); if (vv) printf("User %s added for channel %s\n",accname,channelname); } mysql_close(&mysql); }
void *ClientHandler(void *arg) { struct Client *client = ((struct Client *)arg); struct ParsedMsg msg; struct ThreadChanList chan_list = { .size = 0, .head = NULL }; struct NamesList name_list = { .cnt = 0, .names = NULL }; struct ThreadChanNode *ptr; union RegistrationFlags registered; char raw_msg[IRC_MSG_MAX_LENGTH]; char send_msg[IRC_MSG_MAX_LENGTH]; char nick[IRC_NICK_BUF_SIZE]; ssize_t bytes = 0; int ret, index, connect = 1; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); registered.clear = 0; memset(&raw_msg, 0, IRC_MSG_MAX_LENGTH); memset(&send_msg, 0, IRC_MSG_MAX_LENGTH); memset(&nick, 0, IRC_NICK_BUF_SIZE); while (registered.flags.user == 0 || registered.flags.nick == 0) { if ((bytes = IRCMsgRead(client->sockfd, raw_msg)) < 0) { printf("disconnected\n"); registered.flags.fail = 1; break; } printf("raw: %s len %d\n", raw_msg, (int)strlen(raw_msg)); FormParsedMsg(raw_msg, &msg); if (msg.cmd == IRCCMD_QUIT) { registered.flags.fail = 1; break; } if (msg.cmd == IRCCMD_USER) { registered.flags.user = 1; } else if (msg.cmd == IRCCMD_NICK) { if (registered.flags.nick == 0) { if (msg.cnt == 0) { ErrorHandler(client->sockfd, "nickname parameter expected for a command and isn’t found", ERR_ERRONEUSNICKNAME); FreeParsedMsg(&msg); continue; } if (msg.params[0][0] == '#') { ErrorHandler(client->sockfd, "USER NICK: #nick invalid", ERR_ERRONEUSNICKNAME); FreeParsedMsg(&msg); continue; } ret = AddUser(&all_users, msg.params[0], client); if (ret == IRC_USERERR_EXIST) { ErrorHandler(client->sockfd, "NICK already exist", ERR_NICKNAMEINUSE); FreeParsedMsg(&msg); continue; } else if (ret == IRC_USERERR_NICK) { ErrorHandler(client->sockfd, "INCORRECT NICK", ERR_ERRONEUSNICKNAME); FreeParsedMsg(&msg); continue; } else if (ret == IRC_USERERR_CANTADD) { ErrorHandler(client->sockfd, "USER CANT ADD", IRC_USERERR_CANTADD); FreeParsedMsg(&msg); registered.flags.fail = 1; } else { ret = strlen(msg.params[0]); strncpy(nick, msg.params[0], ret); nick[ret] = '\0'; registered.flags.nick = 1; } } } FreeParsedMsg(&msg); } if (!registered.flags.fail) { printf("successfully registered user: %s\n", nick); registered.flags.connect = 1; SendConnectMsg(&all_users, "anonimus", nick); while (registered.flags.connect) { if ((bytes = IRCMsgRead(client->sockfd, raw_msg)) < 0) { printf("disconnected...\n"); break; } printf("raw: %s len %d\n", raw_msg, (int)strlen(raw_msg)); FormParsedMsg(raw_msg, &msg); switch (msg.cmd) { case IRCCMD_QUIT: registered.flags.connect = 0; if (chan_list.size > 0) { if (FormSendMsg(send_msg, raw_msg, nick) == 0) { for (ptr = chan_list.head; ptr != NULL; ptr = ptr->next) SendMsgToChannel(&all_chan, &all_users, ptr->chan, nick, send_msg); } } break; case IRCCMD_JOIN: if (msg.cnt == 0) { ErrorHandler(client->sockfd, "JOIN :Not enough parameters", ERR_NEEDMOREPARAMS); break; } if (AddUserToChannel(&all_chan, &all_users, msg.params[0], nick) == 0) { printf("add to channel %s\n", msg.params[0]); chan_list.head = ThrListAddFront(&chan_list, msg.params[0]); if (FormSendMsg(send_msg, raw_msg, nick) == 0) { SendMsgToUser(&all_users, nick, send_msg); SendMsgToChannel(&all_chan, &all_users, msg.params[0], nick, send_msg); pthread_mutex_lock(&client->send_lock); SendChannelList(client->sockfd, &all_chan, &all_users, msg.params[0], "anonimous", nick); pthread_mutex_unlock(&client->send_lock); } printf("TO SEND: %s\n", send_msg); } else { ErrorHandler(client->sockfd, "Cannot join channel", ERR_CHANNELISFULL); } break; case IRCCMD_PRIVMSG: if (msg.cnt == 2) { if (FormSendMsg(send_msg, raw_msg, nick) == 0) { printf("send %s \nto %s len %d\n", send_msg, msg.params[0], (int)strlen(send_msg)); if (msg.params[0][0] == '#') { if (SendMsgToChannel(&all_chan, &all_users, msg.params[0], nick, send_msg) < 0) perror("SendMsgToChannel failed"); } else { SendMsgToUser(&all_users, msg.params[0], send_msg); } } } else { ErrorHandler(client->sockfd, "PRIVMSG: Not enough parameters", ERR_NEEDMOREPARAMS); } break; case IRCCMD_PART: if (msg.cnt != 0) { RemoveUserFromChannel(&all_chan, &all_users, msg.params[0], nick); chan_list.head = DeleteThrNode(&chan_list, msg.params[0]); if (FormSendMsg(send_msg, raw_msg, nick) == 0) { printf("send %s \nto %s\n", send_msg, msg.params[0]); SendMsgToUser(&all_users, nick, send_msg); SendMsgToChannel(&all_chan, &all_users, msg.params[0], nick, send_msg); } } else { ErrorHandler(client->sockfd, "PART: Not enough parameters", ERR_NEEDMOREPARAMS); } break; case IRCCMD_NICK: if (msg.cnt == 0) { ErrorHandler(client->sockfd, "nickname parameter expected for a command and isn’t found", ERR_ERRONEUSNICKNAME); break; } if (msg.params[0][0] == '#') { ErrorHandler(client->sockfd, "USER NICK: #nick invalid", ERR_ERRONEUSNICKNAME); break; } printf("change nick: %s -> %s\n", nick, msg.params[0]); if ((ret = RenameUser(&all_users, nick, msg.params[0])) == 0) { ret = strlen(msg.params[0]); strncpy(nick, msg.params[0], ret); nick[ret] = '\0'; } else { if (ret == IRC_USERERR_NOTFOUND) { ErrorHandler(client->sockfd, "User not found", ERR_NICKNAMEINUSE); } else if (ret == IRC_USERERR_EXIST) { ErrorHandler(client->sockfd, "User exist", ERR_NICKNAMEINUSE); } perror("RenameUser"); } break; case IRCCMD_PING: if (msg.cnt == 1) { FormPongMsg(&all_users, raw_msg, nick); } else { ErrorHandler(client->sockfd, "PING: Not enough parameters", ERR_NEEDMOREPARAMS); } break; case IRCCMD_LIST: pthread_mutex_lock(&client->send_lock); SendAllChannelsList(client->sockfd, &all_chan, &all_users, "anonimous", nick); pthread_mutex_unlock(&client->send_lock); break; } FreeParsedMsg(&msg); } } if (chan_list.size > 0) { for (ptr = chan_list.head; ptr != NULL; ptr = ptr->next) RemoveUserFromChannel(&all_chan, &all_users, ptr->chan, nick); FreeThreadList(&chan_list); } close(client->sockfd); pthread_mutex_destroy(&client->send_lock); DelUser(&all_users, (const char *)&nick); free(client); printf("close... %s\n", nick); pthread_exit(NULL); } int main(int argc, char *argv[]) { struct sockaddr_in ser_addr, cl_addr; struct Client *client; int listen_sock, connect; socklen_t len = (socklen_t)sizeof(struct sockaddr_in); pthread_attr_t attr; const int kOpt = 1; if (argc != 3) { printf("format: IP_ADDR PORT\n"); exit(EXIT_FAILURE); } listen_sock = socket(AF_INET, SOCK_STREAM, 0); if (listen_sock < 0) { perror("socket"); exit(EXIT_FAILURE); } if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &kOpt, sizeof(int)) == -1 ) { perror("setsockopt"); } memset(&ser_addr, 0, sizeof(struct sockaddr_in)); ser_addr.sin_family = AF_INET; ser_addr.sin_addr.s_addr = inet_addr(argv[1]); ser_addr.sin_port = htons(atoi(argv[2])); if (bind(listen_sock, (struct sockaddr *)&ser_addr, len) < 0) { perror("bind"); exit(EXIT_FAILURE); } if (listen(listen_sock, IRC_USERS_MAX) < 0) { perror("listen"); exit(EXIT_FAILURE); } UsersInit(&all_users); ChannelsInit(&all_chan); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); while (1) { if ((connect = accept(listen_sock, (struct sockaddr *)&cl_addr, &len)) > 0) { client = (struct Client *)malloc(sizeof(struct Client)); if (client == NULL) { perror("malloc"); break; } client->sockfd = connect; pthread_mutex_init(&client->send_lock, NULL); if (pthread_create(&(client->pid), &attr, ClientHandler, (void *)client) > 0) { perror("pthread_create"); } } else { perror("accept"); break; } } pthread_attr_destroy(&attr); pthread_mutex_destroy(&all_users.lock); pthread_mutex_destroy(&all_chan.lock); close(listen_sock); return 0; }