extern int handle_help_command(t_connection * c, char const * text) { unsigned int i,j; char comm[MAX_COMMAND_LEN]; if (hfd == NULL) { /* an error ocured opening readonly the help file, helpfile_unload was called, or helpfile_init hasn't been called */ message_send_text(c,message_type_error,c,"Oops ! There is a problem with the help file. Please contact the administrator of the server."); return 0; } std::rewind(hfd); for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */ for (; text[i]==' '; i++); if (text[i]=='/') /* skip / in front of command (if present) */ i++; for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get comm */ if (j<sizeof(comm)-1) comm[j++] = text[i]; comm[j] = '\0'; /* just read the whole file and dump only the commands */ if (comm[0]=='\0') { list_commands(c); return 0; } if (describe_command(c,comm)==0) return 0; /* no description was found for this command. inform the user */ message_send_text(c,message_type_error,c," no help available for that command"); return 0; }
static void mail_func_delete(t_connection * c, std::istream& istr) { if (!c) { ERROR0("got NULL connection"); return; } std::string token; istr >> token; if (token.empty()) { message_send_text(c,message_type_error,c,"Please specify which message to delete. Use the following syntax: /mail delete {<index>|all} ."); return; } t_account * user = conn_get_account(c); Mailbox mbox(account_get_uid(user)); if (token == "all") { mbox.clear(); message_send_text(c, message_type_info, c, "Successfully deleted messages."); } else { if (std::find_if(token.begin(), token.end(), NonNumericChar) != token.end()) { message_send_text(c,message_type_error,c,"Invalid index. Please use /mail delete {<index>|all} where <index> is a number."); return; } mbox.erase(std::atoi(token.c_str())); message_send_text(c,message_type_info,c, "Succesfully deleted message."); } }
static int list_commands(t_connection * c) { char * line; int i; message_send_text(c, message_type_info, c, "Chat commands:"); std::rewind(hfd); while ((line = file_get_line(hfd)) != NULL) { for (i = 0; line[i] == ' ' && line[i] != '\0'; i++); /* skip spaces in front of %command */ if (line[i] == '%') /* is this a command ? */ { char *p, *buffer; int al; int skip; unsigned int length, position; /* ok. now we must see if there are any aliases */ length = MAX_COMMAND_LEN + 1; position = 0; buffer = (char*)xmalloc(length + 1); /* initial memory allocation = pretty fair */ p = line + i; do { al = 0; skip = 0; for (i = 1; p[i] != ' ' && p[i] != '\0' && p[i] != '#'; i++); /* skip command */ if (p[i] == ' ') al = 1; /* we have something after the command.. must remember that */ p[i] = '\0'; /* end the string at the end of the command */ p[0] = '/'; /* change the leading character (% or space) read from the help file to / */ if (!(command_get_group(p) & account_get_command_groups(conn_get_account(c)))) skip = 1; if (length < std::strlen(p) + position + 1) /* if we don't have enough space in the buffer then get some */ length = std::strlen(p) + position + 1; /* the new length */ buffer = (char*)xrealloc(buffer, length + 1); buffer[position++] = ' '; /* put a space before each alias */ /* add the alias to the output string */ std::strcpy(buffer + position, p); position += std::strlen(p); if (al) { for (; p[i + 1] == ' ' && p[i + 1] != '\0' && p[i + 1] != '#'; i++); /* skip spaces */ if (p[i + 1] == '\0' || p[i + 1] == '#') { al = 0; continue; } p += i; /* jump to the next command */ } } while (al); if (!skip) message_send_text(c, message_type_info, c, buffer); /* print out the buffer */ xfree(buffer); } } file_get_line(NULL); // clear file_get_line buffer return 0; }
// Displays channel_name's topic to connection c int class_topic::display(t_connection * c, std::string channel_name) { if ((channel_name.size() + 1) > MAX_CHANNELNAME_LEN || channel_name.empty() == true) { eventlog(eventlog_level_error, __FUNCTION__, "got invalid channel name length"); return -1; } class_topic::t_topic * topic = this->topiclist.get(channel_name); if (topic == nullptr) return -1; if (topic->topicstr.empty()) { eventlog(eventlog_level_error, __FUNCTION__, "topic is empty"); return -1; } //send parts of topic string as separate message if there's a newline character std::regex rgx("\\\\n+"); std::sregex_token_iterator iter(topic->topicstr.begin(), topic->topicstr.end(), rgx, -1), end; for (bool first = true; iter != end; ++iter) { std::string msg(iter->str()); if (first == true) { msg.insert(0, topic->channel_name + " topic: "); first = false; } message_send_text(c, message_type_info, c, msg); } return 0; }
extern int handle_anongame_search(t_connection * c, t_packet const *packet) { if (account_get_auth_ladderban(conn_get_account(c))==1) { message_send_text(c,message_type_error,c,"Sorry, the following option is no longer available for your account."); return _client_anongame_cancel(c); } if (conn_get_latency(c) > 300) //todo: pick not allowed ping { message_send_text(c,message_type_error,c,"Your ping is too high, Please try again later."); return _client_anongame_cancel(c); } return _handle_anongame_search(c, packet); }
static int _handle_notice_command(t_connection * conn, int numparams, char ** params, char * text) { if ((numparams>=1)&&(text)) { int i; char ** e; e = irc_get_listelems(params[0]); /* FIXME: support wildcards! */ for (i=0; ((e)&&(e[i])); i++) { if (conn_get_state(conn)==conn_state_loggedin) { t_connection * user; if ((user = connlist_find_connection_by_accountname(e[i]))) { message_send_text(user,message_type_notice,conn,text); } else { irc_send(conn,ERR_NOSUCHNICK,":No such user"); } } } if (e) irc_unget_listelems(e); } else irc_send(conn,ERR_NEEDMOREPARAMS,"NOTICE :Not enough parameters"); return 0; }
static void mail_func_send(t_connection * c, const char * str) { int i; char *dest; char const *p,*myname; t_account * recv; t_mailbox * mailbox; if (c==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (str==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command string"); return; } for(i=0;str[i]==' ';i++); /* skip any spaces */ if (str[i]=='\0') { /* the %mail send command has no receiver */ message_send_text(c,message_type_error,c,"You must specify the receiver"); message_send_text(c,message_type_error,c,"Syntax: /mail send <receiver> <message>"); return; } p=str+i; /* set ip at the start of receiver string */ for(i=1;p[i]!=' ' && p[i]!='\0';i++); /* skip the receiver string */ if (p[i]=='\0') { /* it seems user forgot to write any message */ message_send_text(c,message_type_error,c,"Your message is empty!"); message_send_text(c,message_type_error,c,"Syntax: /mail send <receiver> <message>"); return; } dest=xmalloc(i+1); memmove(dest,p,i); dest[i]='\0'; /* copy receiver in his separate string */ if ((recv=accountlist_find_account(dest))==NULL) { /* is dest a valid account on this server ? */ message_send_text(c,message_type_error,c,"Receiver UNKNOWN!"); xfree(dest); return; } xfree(dest); /* free dest here, the sooner the better */ if ((mailbox=mailbox_open(recv, mbox_mode_write))==NULL) { message_send_text(c,message_type_error,c,"There was an error completing your request!"); return; } if (get_mail_quota(recv)<=mailbox_count(mailbox)) { /* check quota */ message_send_text(c,message_type_error,c,"Receiver has reached his mail quota. Your message will NOT be sent."); mailbox_close(mailbox); return; } myname=conn_get_username(c); /* who am i ? */ if (mailbox_deliver(mailbox,myname,p+i+1)<0) message_send_text(c,message_type_error,c,"There was an error completing your request!"); else message_send_text(c,message_type_info,c,"Your mail has been sent successfully."); mailbox_close(mailbox); }
static int describe_command(t_connection * c, char const * comm) { char * line; int i; /* ok. the client requested help for a specific command */ while ((line=file_get_line(hfd))!=NULL) { for (i=0;line[i]==' ' && line[i]!='\0';i++); /* skip spaces in front of %command */ if (line[i]=='%') /* is this a command ? */ { char *p; int al; /* ok. now we must see if there are any aliases */ p=line+i; do { al=0; for (i=1;p[i]!=' ' && p[i]!='\0' && p[i]!='#';i++); /* skip command */ if (p[i]==' ') al=1; /* we have something after the command.. must remember that */ p[i]='\0'; /* end the string at the end of the command */ if (strcasecmp(comm,p+1)==0) /* is this the command the user asked for help ? */ { while ((line=file_get_line(hfd))!=NULL) { /* write everything until we get another % or EOF */ for (i=0;line[i]==' ';i++); /* skip spaces in front of a possible % */ if (line[i]=='%') { break; /* we reached another command */ } if (line[0]!='#') { /* is this a whole line comment ? */ /* truncate the line when a comment starts */ for (;line[i]!='\0' && line[i]!='#';i++); if (line[i]=='#') line[i]='\0'; message_send_text(c,message_type_info,c,line); } } return 0; } if (al) { for (;p[i+1]==' ' && p[i+1]!='\0';i++); /* skip spaces */ if (p[i+1]=='\0') { al=0; continue; } p+=i; /* jump to the next command */ } } while (al); } } file_get_line(NULL); // clear file_get_line buffer return -1; }
extern int handle_mail_command(t_connection * c, char const * text) { if (!prefs_get_mail_support()) { message_send_text(c,message_type_error,c,"This server has NO mail support."); return -1; } std::istringstream istr(text); std::string token; /* stkip "/mail" */ istr >> token; /* get the mail function */ token.clear(); istr >> token; switch (identify_mail_function(token.c_str())) { case MAIL_FUNC_SEND: mail_func_send(c, istr); break; case MAIL_FUNC_READ: mail_func_read(c, istr); break; case MAIL_FUNC_DELETE: mail_func_delete(c, istr); break; case MAIL_FUNC_HELP: message_send_text(c, message_type_info, c, "The mail command supports the following patterns."); mail_usage(c); break; default: message_send_text(c, message_type_error, c, "The command its incorrect. Use one of the following patterns."); mail_usage(c); } return 0; }
extern int handle_mail_command(t_connection * c, char const * text) { unsigned int i,j; char comm[MAX_FUNC_LEN]; if (!prefs_get_mail_support()) { message_send_text(c,message_type_error,c,"This server has NO mail support."); return -1; } for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip /mail command */ for (; text[i]==' '; i++); /* skip any spaces after it */ for (j=0; text[i]!=' ' && text[i]!='\0' && j<sizeof(comm)-1; i++) /* get function */ if (j<sizeof(comm)-1) comm[j++] = text[i]; comm[j] = '\0'; switch (identify_mail_function(comm)) { case MAIL_FUNC_SEND: mail_func_send(c,text+i); break; case MAIL_FUNC_READ: mail_func_read(c,text+i); break; case MAIL_FUNC_DELETE: mail_func_delete(c,text+i); break; case MAIL_FUNC_HELP: message_send_text(c,message_type_info,c,"The mail command supports the following patterns."); mail_usage(c); break; default: message_send_text(c,message_type_error,c,"The command its incorrect. Use one of the following patterns."); mail_usage(c); } return 0; }
static void mail_func_send(t_connection * c, std::istream& istr) { if (!c) { ERROR0("got NULL connection"); return; } std::string dest; istr >> dest; if (dest.empty()) { message_send_text(c, message_type_error, c, "You must specify the receiver"); message_send_text(c, message_type_error, c, "Syntax: /mail send <receiver> <message>"); return; } std::string message; std::getline(istr, message); std::string::size_type pos(message.find_first_not_of(" \t")); if (pos == std::string::npos) { message_send_text(c, message_type_error, c, "Your message is empty!"); message_send_text(c, message_type_error, c, "Syntax: /mail send <receiver> <message>"); return; } t_account * recv = accountlist_find_account(dest.c_str()); if (!recv) { message_send_text(c, message_type_error, c, "Receiver UNKNOWN!"); return; } Mailbox mbox(account_get_uid(recv)); if (get_mail_quota(recv) <= mbox.size()) { message_send_text(c, message_type_error, c, "Receiver has reached his mail quota. Your message will NOT be sent."); return; } try { mbox.deliver(conn_get_username(c), message.substr(pos)); message_send_text(c, message_type_info, c, "Your mail has been sent successfully."); } catch (const Mailbox::DeliverError&) { message_send_text(c, message_type_error, c, "There was an error completing your request!"); } }
extern int describe_command(t_connection * c, char const * cmd) { char * line; int i; /* ok. the client requested help for a specific command */ std::rewind(hfd); while ((line = file_get_line(hfd)) != NULL) { for (i = 0; line[i] == ' ' && line[i] != '\0'; i++); /* skip spaces in front of %command */ if (line[i] == '%') /* is this a command ? */ { char *p; int al; /* ok. now we must see if there are any aliases */ p = line + i; do { al = 0; for (i = 1; p[i] != ' ' && p[i] != '\0' && p[i] != '#'; i++); /* skip command */ if (p[i] == ' ') al = 1; /* we have something after the command.. must remember that */ p[i] = '\0'; /* end the string at the end of the command */ if (strcasecmp(cmd, p + 1) == 0) /* is this the command the user asked for help ? */ { while ((line = file_get_line(hfd)) != NULL) { /* write everything until we get another % or EOF */ for (i = 0; line[i] == ' '; i++); /* skip spaces in front of a possible % */ if (line[i] == '%') { break; /* we reached another command */ } if (line[0] != '#' && line[i] != '\0') { /* is this a whole line comment ? */ /* truncate the line when a comment starts */ for (; line[i] != '\0' && line[i] != '#'; i++); if (line[i] == '#') line[i] = '\0'; // replace tabs with 3 spaces line = (char*)str_replace(line, "\t", " "); // if text starts with slash then make it colored int j = 0; for (; line[j] == ' ' || line[j] == '\t'; j++); if (line[j] == '/') message_send_text(c, message_type_error, c, line); else message_send_text(c, message_type_info, c, line); } } return 0; } if (al) { for (; p[i + 1] == ' ' && p[i + 1] != '\0'; i++); /* skip spaces */ if (p[i + 1] == '\0') { al = 0; continue; } p += i; /* jump to the next command */ } } while (al); } } file_get_line(NULL); // clear file_get_line buffer /* no description was found for this command. inform the user */ message_send_text(c, message_type_error, c, "No help available for that command"); return -1; }
static int _handle_privmsg_command(t_connection * conn, int numparams, char ** params, char * text) { if ((numparams>=1)&&(text)) { int i; char ** e; e = irc_get_listelems(params[0]); /* FIXME: support wildcards! */ /* start amadeo: code was sent by some unkown fellow of pvpgn (maybe u wanna give us your name for any credits), it adds nick-registration, i changed some things here and there... */ for (i=0; ((e)&&(e[i])); i++) { if (strcasecmp(e[i],"NICKSERV")==0) { char * pass; char * p; pass = std::strchr(text,' '); if (pass) *pass++ = '\0'; if (strcasecmp(text,"identify")==0) { switch (conn_get_state(conn)) { case conn_state_bot_password: { if (pass) { t_hash h; for (p = pass; *p; p++) if (std::isupper((int)*p)) *p = std::tolower(*p); bnet_hash(&h,std::strlen(pass),pass); irc_authenticate(conn,hash_get_str(h)); } else { message_send_text(conn,message_type_notice,NULL,"Syntax: IDENTIFY <password> (max 16 characters)"); } break; } case conn_state_loggedin: { message_send_text(conn,message_type_notice,NULL,"You don't need to IDENTIFY"); break; } default: ; eventlog(eventlog_level_trace,__FUNCTION__,"got /msg in unexpected connection state (%s)",conn_state_get_str(conn_get_state(conn))); } } else if (strcasecmp(text,"register")==0) { unsigned int j; t_hash passhash; t_account * temp; char msgtemp[MAX_IRC_MESSAGE_LEN]; char * username=(char *)conn_get_loggeduser(conn); if (account_check_name(username)<0) { message_send_text(conn,message_type_error,conn,"Account name contains invalid symbol!"); break; } if(!prefs_get_allow_new_accounts()) { message_send_text(conn,message_type_error,conn,"Account creation is not allowed"); break; } if (!pass || pass[0]=='\0' || (std::strlen(pass)>16) ) { message_send_text(conn,message_type_error,conn,"Syntax: REGISTER <password> (max 16 characters)"); break; } for (j=0; j<std::strlen(pass); j++) if (std::isupper((int)pass[j])) pass[j] = std::tolower((int)pass[j]); bnet_hash(&passhash,std::strlen(pass),pass); snprintf(msgtemp, sizeof(msgtemp), "Trying to create account \"%s\" with password \"%s\"",username,pass); message_send_text(conn,message_type_info,conn,msgtemp); temp = accountlist_create_account(username,hash_get_str(passhash)); if (!temp) { message_send_text(conn,message_type_error,conn,"Failed to create account!"); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" not created (failed)",conn_get_socket(conn),username); conn_unget_chatname(conn,username); break; } snprintf(msgtemp, sizeof(msgtemp), "Account "UID_FORMAT" created.",account_get_uid(temp)); message_send_text(conn,message_type_info,conn,msgtemp); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" created",conn_get_socket(conn),username); conn_unget_chatname(conn,username); } else { char tmp[MAX_IRC_MESSAGE_LEN+1]; message_send_text(conn,message_type_notice,NULL,"Invalid arguments for NICKSERV"); snprintf(tmp, sizeof(tmp), ":Unrecognized command \"%s\"", text); message_send_text(conn,message_type_notice,NULL,tmp); } } else if (conn_get_state(conn)==conn_state_loggedin) { if (e[i][0]=='#') { /* channel message */ t_channel * channel; if ((channel = channellist_find_channel_by_name(irc_convert_ircname(e[i]),NULL,NULL))) { if ((std::strlen(text)>=9)&&(std::strncmp(text,"\001ACTION ",8)==0)&&(text[std::strlen(text)-1]=='\001')) { /* at least "\001ACTION \001" */ /* it's a CTCP ACTION message */ text = text + 8; text[std::strlen(text)-1] = '\0'; channel_message_send(channel,message_type_emote,conn,text); } else { channel_message_log(channel, conn, 1, text); channel_message_send(channel,message_type_talk,conn,text); } } else { irc_send(conn,ERR_NOSUCHCHANNEL,":No such channel"); } } else { /* whisper */ t_connection * user; if ((user = connlist_find_connection_by_accountname(e[i]))) { message_send_text(user,message_type_whisper,conn,text); } else { irc_send(conn,ERR_NOSUCHNICK,":No such user"); } } } } if (e) irc_unget_listelems(e); } else irc_send(conn,ERR_NEEDMOREPARAMS,"PRIVMSG :Not enough parameters"); return 0; }
extern int handle_irc_welcome(t_connection * conn) { char temp[MAX_IRC_MESSAGE_LEN]; std::time_t temptime; char const * tempname; char const * temptimestr; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } tempname = conn_get_loggeduser(conn); if ((34+std::strlen(tempname)+1)<=MAX_IRC_MESSAGE_LEN) std::sprintf(temp,":Welcome to the %s IRC Network %s",prefs_get_irc_network_name(), tempname); else std::sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_WELCOME,temp); if ((14+std::strlen(server_get_hostname())+10+std::strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+1)<=MAX_IRC_MESSAGE_LEN) std::sprintf(temp,":Your host is %s, running "PVPGN_SOFTWARE" "PVPGN_VERSION,server_get_hostname()); else std::sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_YOURHOST,temp); temptime = server_get_starttime(); /* FIXME: This should be build time */ temptimestr = std::ctime(&temptime); if ((25+std::strlen(temptimestr)+1)<=MAX_IRC_MESSAGE_LEN) std::sprintf(temp,":This server was created %s",temptimestr); /* FIXME: is ctime() portable? */ else std::sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_CREATED,temp); /* we don't give mode information on MYINFO we give it on ISUPPORT */ if ((std::strlen(server_get_hostname())+7+std::strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+9+1)<=MAX_IRC_MESSAGE_LEN) std::sprintf(temp,"%s "PVPGN_SOFTWARE" "PVPGN_VERSION" - -",server_get_hostname()); else std::sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_MYINFO,temp); std::sprintf(temp,"NICKLEN=%d TOPICLEN=%d CHANNELLEN=%d PREFIX=%s CHANTYPES="CHANNEL_TYPE" NETWORK=%s IRCD="PVPGN_SOFTWARE, MAX_CHARNAME_LEN, MAX_TOPIC_LEN, MAX_CHANNELNAME_LEN, CHANNEL_PREFIX, prefs_get_irc_network_name()); if((std::strlen(temp))<=MAX_IRC_MESSAGE_LEN) irc_send(conn,RPL_ISUPPORT,temp); else { std::sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_ISUPPORT,temp); } irc_send_motd(conn); message_send_text(conn,message_type_notice,NULL,"This is an experimental service"); conn_set_state(conn,conn_state_bot_password); if (conn_get_ircpass(conn)) { message_send_text(conn,message_type_notice,NULL,"Trying to authenticate with PASS ..."); irc_authenticate(conn,conn_get_ircpass(conn)); } else { message_send_text(conn,message_type_notice,NULL,"No PASS command received. Please identify yourself by /msg NICKSERV identify <password>."); } return 0; }
static void mail_usage(t_connection * c) { message_send_text(c,message_type_info,c,"to print this information:"); message_send_text(c,message_type_info,c," /mail help"); message_send_text(c,message_type_info,c,"to print an index of you messages:"); message_send_text(c,message_type_info,c," /mail [read]"); message_send_text(c,message_type_info,c,"to send a message:"); message_send_text(c,message_type_info,c," /mail send <receiver> <message>"); message_send_text(c,message_type_info,c,"to read a message:"); message_send_text(c,message_type_info,c," /mail read <index num>"); message_send_text(c,message_type_info,c,"to delete a message:"); message_send_text(c,message_type_info,c," /mail delete {<index>|all}"); message_send_text(c,message_type_info,c,"Commands may be abbreviated as follows:"); message_send_text(c,message_type_info,c," help: h"); message_send_text(c,message_type_info,c," read: r"); message_send_text(c,message_type_info,c," send: s"); message_send_text(c,message_type_info,c," delete: del"); }
static void mail_func_delete(t_connection * c, const char * str) { t_account * user; t_mailbox * mailbox; const char * p; char tmp[256]; /* that should be enough */ int i; if (c==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (str==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command string"); return; } for(i=0;str[i]==' ';i++); p=str+i; if (*p=='\0') { message_send_text(c,message_type_error,c,"Please specify which message to delete. Use the following syntax: /mail delete {<index>|all} ."); return; } if ((user=conn_get_account(c))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return; } if ((mailbox=mailbox_open(user, mbox_mode_write))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL mailbox"); return; } if (strcmp(p,"all")==0) { int rez; if ((rez=mailbox_delete_all(mailbox))<0) { message_send_text(c,message_type_error,c,"There was an error completing your request."); mailbox_close(mailbox); return; } sprintf(tmp,"Successfuly deleted %d messages.",rez); message_send_text(c,message_type_info,c,tmp); } else { int idx; for(i=0;p[i]>='0' && p[i]<='9' && p[i]!='\0';i++); if (p[i]!='\0' && p[i]!=' ') { message_send_text(c,message_type_error,c,"Invalid index. Please use /mail delete {<index>|all} where <index> is a number."); mailbox_close(mailbox); return; } idx=atoi(p); if (idx<1 || idx>mailbox_count(mailbox)) { message_send_text(c,message_type_error,c,"That index is out of range."); mailbox_close(mailbox); return; } if (mailbox_delete(mailbox,idx)<0) { message_send_text(c,message_type_error,c,"There was an error completing your request."); mailbox_close(mailbox); return; } sprintf(tmp,"Succesfully deleted message #%02d.",idx); message_send_text(c,message_type_info,c,tmp); } mailbox_close(mailbox); }
static void mail_func_read(t_connection * c, const char * str) { t_account * user; t_mailbox * mailbox; const char *p; char tmp[256]; int i; if (c==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return; } if (str==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command string"); return; } for(i=0;str[i]==' ';i++); p=str+i; if ((user=conn_get_account(c))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL account"); return; } mailbox=mailbox_open(user, mbox_mode_read); if (*p=='\0') { /* user wants to see the mail summary */ struct maillist_struct *maill, *mp; unsigned int idx; if (!mailbox_count(mailbox)) { message_send_text(c,message_type_info,c,"You have no mail."); mailbox_close(mailbox); return; } if ((maill=mailbox_get_list(mailbox))==NULL) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL maillist"); mailbox_close(mailbox); return; } sprintf(tmp,"You have %d messages. Your mail qouta is set to %d.",mailbox_count(mailbox),get_mail_quota(user)); message_send_text(c,message_type_info,c,tmp); message_send_text(c,message_type_info,c,"ID Sender Date"); message_send_text(c,message_type_info,c,"-------------------------------------"); for(mp=maill,idx=1;mp!=NULL;mp=mp->next,idx++) { sprintf(tmp,"%02u %-14s %s",idx,mp->sender,ctime(&mp->timestamp)); clean_str(tmp); /* ctime() appends an newline that we get cleaned */ message_send_text(c,message_type_info,c,tmp); } message_send_text(c,message_type_info,c,"Use /mail read <ID> to read the content of any message"); mailbox_unget_list(maill); } else { /* user wants to read a message */ int idx; t_mail * mail; for(i=0;p[i]>='0' && p[i]<='9' && p[i]!='\0';i++); if (p[i]!='\0' && p[i]!=' ') { message_send_text(c,message_type_error,c,"Invalid index. Please use /mail read <index> where <index> is a number."); mailbox_close(mailbox); return; } idx=atoi(p); if (idx<1 || idx>mailbox_count(mailbox)) { message_send_text(c,message_type_error,c,"That index is out of range."); mailbox_close(mailbox); return; } if ((mail=mailbox_read(mailbox,idx))==NULL) { message_send_text(c,message_type_error,c,"There was an error completing your request."); mailbox_close(mailbox); return; } sprintf(tmp,"Message #%d from %s on %s:",idx,mail->sender,clean_str(ctime(&mail->timestamp))); message_send_text(c,message_type_info,c,tmp); message_send_text(c,message_type_info,c,mail->message); mailbox_unread(mail); } mailbox_close(mailbox); }
extern int handle_bot_packet(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } if (packet_get_class(packet)!=packet_class_raw) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } { char const * const linestr=packet_get_str_const(packet,0,MAX_MESSAGE_LEN); if (packet_get_size(packet)<2) /* empty line */ return 0; if (!linestr) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] line too long",conn_get_socket(c)); return 0; } switch (conn_get_state(c)) { case conn_state_connected: conn_add_flags(c,MF_PLUG); conn_set_clienttag(c,CLIENTTAG_BNCHATBOT_UINT); { char const * temp=linestr; if (temp[0]=='\004') /* FIXME: no echo, ignore for now (we always do no echo) */ temp = &temp[1]; if (temp[0]=='\0') /* empty line */ { conn_set_state(c,conn_state_bot_username); /* don't look for ^D or reset tag and flags */ break; } conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,temp)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),temp); { char const * const msg="\r\nPassword: "******"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 1 /* don't echo */ packet_append_ntstring(rpacket,conn_get_loggeduser(c)); #endif packet_append_ntstring(rpacket,msg); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } break; case conn_state_bot_username: conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,linestr)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),linestr); { char const * const temp="\r\nPassword: "******"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 1 /* don't echo */ packet_append_ntstring(rpacket,linestr); #endif packet_append_ntstring(rpacket,temp); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } break; case conn_state_bot_password: { char const * const tempa="\r\nLogin failed.\r\n\r\nUsername: "******"\r\nAccount has no bot access.\r\n\r\nUsername: "******"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (connlist_find_connection_by_accountname(loggeduser)) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (already logged in)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (!(account = accountlist_find_account(loggeduser))) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (bad account)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if ((oldstrhash1 = account_get_pass(account))) { if (hash_set_str(&oldpasshash1,oldstrhash1)<0) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (corrupted passhash1?)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } testpass = xstrdup(linestr); { unsigned int i; for (i=0; i<strlen(testpass); i++) if (isupper((int)testpass[i])) testpass[i] = tolower((int)testpass[i]); } if (bnet_hash(&trypasshash1,strlen(testpass),testpass)<0) /* FIXME: force to lowercase */ { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (unable to hash password)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); xfree((void *)testpass); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } xfree((void *)testpass); if (hash_eq(trypasshash1,oldpasshash1)!=1) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (wrong password)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (account_get_auth_botlogin(account)!=1) /* default to false */ { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (no bot access)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempb); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } else if (account_get_auth_lock(account)==1) /* default to false */ { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (this account is locked)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempb); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } eventlog(eventlog_level_info,__FUNCTION__,"[%d] \"%s\" bot logged in (correct password)",conn_get_socket(c), loggeduser); } else { eventlog(eventlog_level_info,__FUNCTION__,"[%d] \"%s\" bot logged in (no password)",conn_get_socket(c), loggeduser); } if (!(rpacket = packet_create(packet_class_raw))) /* if we got this far, let them log in even if this fails */ eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); else { packet_append_ntstring(rpacket,"\r\n"); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } bnetd_log(loggeduser, addr_num_to_ip_str(conn_get_addr(c)), "BOT", "LOGIN", NULL, 1, 0); conn_login(c,account,loggeduser); message_send_text(c,message_type_uniqueid,c,loggeduser); if (conn_set_channel(c,CHANNEL_NAME_CHAT)<0) conn_set_channel(c,CHANNEL_NAME_BANNED); /* should not fail */ } break; case conn_state_loggedin: { t_channel const * channel; conn_set_idletime(c); if ((channel = conn_get_channel(c))) channel_message_log(channel,c,1,linestr); /* we don't log game commands currently */ if (linestr[0]=='/') handle_command(c,linestr); else if (channel && !conn_quota_exceeded(c,linestr)) channel_message_send(channel,message_type_talk,c,linestr); /* else discard */ } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown bot connection state %d",conn_get_socket(c),(int)conn_get_state(c)); } } return 0; }
static void mail_func_read(t_connection * c, std::istream& istr) { if (!c) { ERROR0("got NULL connection"); return; } std::string token; istr >> token; t_account * user = conn_get_account(c); Mailbox mbox(account_get_uid(user)); if (token.empty()) { /* user wants to see the mail summary */ if (mbox.empty()) { message_send_text(c,message_type_info,c,"You have no mail."); return; } MailList mlist; mbox.readAll(mlist); std::ostringstream ostr; ostr << "You have " << mbox.size() << " messages. Your mail quote is set to " << get_mail_quota(user) << '.'; message_send_text(c, message_type_info, c, ostr.str().c_str()); message_send_text(c, message_type_info, c, "ID Sender Date"); message_send_text(c, message_type_info, c, "-------------------------------------"); for(MailList::const_iterator it(mlist.begin()); it != mlist.end(); ++it) { ostr.str(""); ostr << std::setfill('0') << std::setw(2) << std::right << (it - mlist.begin()) << " " << std::setfill(' ') << std::setw(14) << std::left << it->sender() << ' '; char buff[128]; std::strftime(buff, sizeof(buff), "%a %b %d %H:%M:%S %Y", std::localtime(&it->timestamp())); ostr << buff; message_send_text(c, message_type_info, c, ostr.str().c_str()); } message_send_text(c,message_type_info,c,"Use /mail read <ID> to read the content of any message"); } else { /* user wants to read a message */ if (std::find_if(token.begin(), token.end(), NonNumericChar) != token.end()) { message_send_text(c,message_type_error,c,"Invalid index. Please use /mail read <index> where <index> is a number."); return; } try { unsigned idx = std::atoi(token.c_str()); Mail mail(mbox.read(idx)); std::ostringstream ostr; ostr << "Message #" << idx << " from " << mail.sender() << " on "; char buff[128]; std::strftime(buff, sizeof(buff), "%a %b %d %H:%M:%S %Y", std::localtime(&mail.timestamp())); ostr << buff << ':'; message_send_text(c, message_type_info, c, ostr.str().c_str()); message_send_text(c, message_type_info, c, mail.message().c_str()); } catch (const Mailbox::ReadError&) { message_send_text(c,message_type_error,c,"There was an error completing your request."); } } }
// handle command // /log read user startline // /log find user substr startline extern int handle_log_command(t_connection * c, char const *text) { const char *subcommand, *username; long startline = 0; std::map<long, char*> lines; // split command args std::vector<std::string> args = split_command(text, 4); if (args[1].empty() || args[2].empty() || (args[1].at(0) != 'r' && args[1].at(0) != 'f')) // check start symbols for subcommand { describe_command(c, args[0].c_str()); return -1; } subcommand = args[1].c_str(); // sub command username = args[2].c_str(); // username if (!accountlist_find_account(username)) { message_send_text(c, message_type_error, c, localize(c, "Invalid user.")); return -1; } std::string title = localize(c, "{}'s log output", username); // read if (subcommand[0] == 'r') { if (!args[3].empty()) startline = atoi(args[3].c_str()); lines = userlog_read(username, startline); } // find else if (subcommand[0] == 'f') { if (args[3].empty()) { describe_command(c, args[0].c_str()); return -1; } const char * search = args[3].c_str(); title += localize(c, " by occurrence \"{}\"", search); if (!args[4].empty()) startline = atoi(args[4].c_str()); lines = userlog_find_text(username, search, startline); } title += ":"; message_send_text(c, message_type_info, c, title); int linelen = 0; int paddedlen = 0; std::string linenum; // send each log line to user for (std::map<long, char*>::reverse_iterator it = lines.rbegin(); it != lines.rend(); ++it) { int linelen = floor(log10(static_cast<double>(abs(it->first)))) + 1; // get length of integer (line number) if (linelen > paddedlen) paddedlen = linelen; linenum = std_to_string(it->first); // pad left to max line length linenum.insert(linenum.begin(), paddedlen - linenum.size(), '0'); message_send_text(c, message_type_info, c, linenum + ": " + std::string(it->second)); } return 0; }