/* SYNTAX: NAMES [-yes] [<channels>] */ static void cmd_names(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '\0') cmd_return_error(CMDERR_NOT_GOOD_IDEA); if (strcmp(data, "*") == 0) { if (!IS_IRC_CHANNEL(item)) cmd_return_error(CMDERR_NOT_JOINED); data = item->name; } if (g_strcasecmp(data, "-YES") == 0) irc_send_cmd(server, "NAMES"); else irc_send_cmdv(server, "NAMES %s", data); }
static void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server) { char *str; g_return_if_fail(dcc != NULL); if (dcc->server != NULL) server = dcc->server; if (server != NULL && (dcc->type != DCC_TYPE_CHAT || dcc->starttime == 0)) { signal_emit("dcc rejected", 1, dcc); str = g_strdup_printf("NOTICE %s :\001DCC REJECT %s %s\001", dcc->nick, dcc_type2str(SWAP_SENDGET(dcc->type)), dcc->arg); irc_send_cmd(server, str); g_free(str); } signal_emit("dcc closed", 1, dcc); dcc_destroy(dcc); }
/* command: DCC CHAT */ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) { DCC_REC *dcc; IPADDR own_ip; char *str, host[MAX_IP_LEN]; int port, handle; g_return_if_fail(data != NULL); if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = dcc_find_item(DCC_TYPE_CHAT, data, NULL); if (dcc != NULL) { /* found from dcc list - so we're the connecting side.. */ dcc_chat_connect(dcc); return; } /* send dcc chat request */ if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (net_getsockname(server->handle, &own_ip, NULL) == -1) cmd_return_error(CMDERR_ERRNO); port = settings_get_int("dcc_port"); handle = net_listen(&own_ip, &port); if (handle == -1) cmd_return_error(CMDERR_ERRNO); dcc = dcc_create(DCC_TYPE_CHAT, handle, data, "chat", server, NULL); dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_listen, dcc); /* send the request */ dcc_make_address(&own_ip, host); str = g_strdup_printf("PRIVMSG %s :\001DCC CHAT CHAT %s %d\001", data, host, port); irc_send_cmd(server, str); g_free(str); }
static void query_send(IRC_SERVER_REC *server, int query) { SERVER_QUERY_REC *rec; IRC_CHANNEL_REC *chanrec; GSList *chans; char *cmd, *chanstr_commas, *chanstr; int onlyone, count; rec = server->chanqueries; /* get the list of channels to query */ onlyone = (server->no_multi_who && query == CHANNEL_QUERY_WHO) || (server->no_multi_mode && CHANNEL_IS_MODE_QUERY(query)); if (onlyone) { chans = rec->queries[query]; rec->queries[query] = g_slist_remove_link(rec->queries[query], chans); chanrec = chans->data; chanstr_commas = g_strdup(chanrec->name); chanstr = g_strdup(chanrec->name); count = 1; } else { char *chanstr_spaces; chans = rec->queries[query]; count = g_slist_length(chans); if (count > server->max_query_chans) { GSList *lastchan; lastchan = g_slist_nth(rec->queries[query], server->max_query_chans-1); count = server->max_query_chans; rec->queries[query] = lastchan->next; lastchan->next = NULL; } else { rec->queries[query] = NULL; } chanstr_commas = gslistptr_to_string(chans, G_STRUCT_OFFSET(IRC_CHANNEL_REC, name), ","); chanstr_spaces = gslistptr_to_string(chans, G_STRUCT_OFFSET(IRC_CHANNEL_REC, name), " "); chanstr = g_strconcat(chanstr_commas, " ", chanstr_spaces, NULL); g_free(chanstr_spaces); } rec->current_query_type = query; rec->current_queries = chans; switch (query) { case CHANNEL_QUERY_MODE: cmd = g_strdup_printf("MODE %s", chanstr_commas); /* the stop-event is received once for each channel, and we want to print 329 event (channel created). */ server_redirect_event(server, "mode channel", count, chanstr, -1, "chanquery abort", "event 324", "chanquery mode", "event 329", "event 329", "", "chanquery abort", NULL); break; case CHANNEL_QUERY_WHO: cmd = g_strdup_printf("WHO %s", chanstr_commas); server_redirect_event(server, "who", server->one_endofwho ? 1 : count, chanstr, -1, "chanquery abort", "event 315", "chanquery who end", "event 352", "silent event who", "", "chanquery abort", NULL); break; case CHANNEL_QUERY_BMODE: cmd = g_strdup_printf("MODE %s b", chanstr_commas); /* check all the multichannel problems with all mode requests - if channels are joined manually irssi could ask modes separately but afterwards join the two b/e/I modes together */ server_redirect_event(server, "mode b", count, chanstr, -1, "chanquery abort", "event 367", "chanquery ban", "event 368", "chanquery ban end", "", "chanquery abort", NULL); break; default: cmd = NULL; } irc_send_cmd(server, cmd); g_free(chanstr); g_free(chanstr_commas); g_free(cmd); }
static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args, const char *data) { GSList *tmp; if (!client->connected) { handle_client_connect_cmd(client, cmd, args); return; } if (g_strcmp0(cmd, "QUIT") == 0) { remove_client(client); return; } if (g_strcmp0(cmd, "PING") == 0) { /* Reply to PING, if the target parameter is either proxy_adress, our own nick or empty. */ char *params, *origin, *target; params = event_get_params(args, 2, &origin, &target); if (*target == '\0' || g_ascii_strcasecmp(target, client->proxy_address) == 0 || g_ascii_strcasecmp(target, client->nick) == 0) { proxy_outdata(client, ":%s PONG %s :%s\r\n", client->proxy_address, client->proxy_address, origin); g_free(params); return; } g_free(params); } if (g_strcmp0(cmd, "PROXY") == 0) { if (g_ascii_strcasecmp(args, "CTCP ON") == 0) { /* client wants all ctcps */ client->want_ctcp = 1; for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if ((g_ascii_strcasecmp(client->listen->ircnet,rec->listen->ircnet) == 0) && /* kludgy way to check if the clients aren't the same */ (client->recv_tag != rec->recv_tag)) { if (rec->want_ctcp == 1) proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n", rec->proxy_address, rec->nick, rec->listen->ircnet); rec->want_ctcp = 0; } } proxy_outdata(client, ":%s NOTICE %s :You're now receiving CTCPs sent to %s\r\n", client->proxy_address, client->nick,client->listen->ircnet); } else if (g_ascii_strcasecmp(args, "CTCP OFF") == 0) { /* client wants proxy to handle all ctcps */ client->want_ctcp = 0; proxy_outdata(client, ":%s NOTICE %s :Proxy is now handling itself CTCPs sent to %s\r\n", client->proxy_address, client->nick, client->listen->ircnet); } else { signal_emit("proxy client command", 3, client, args, data); } return; } if (client->server == NULL || !client->server->connected) { proxy_outdata(client, ":%s NOTICE %s :Not connected to server\r\n", client->proxy_address, client->nick); return; } /* check if the command could be redirected */ if (g_strcmp0(cmd, "WHO") == 0) grab_who(client, args); else if (g_strcmp0(cmd, "WHOWAS") == 0) proxy_redirect_event(client, "whowas", 1, args, -1); else if (g_strcmp0(cmd, "WHOIS") == 0) { char *p; /* convert dots to spaces */ for (p = args; *p != '\0'; p++) if (*p == ',') *p = ' '; proxy_redirect_event(client, "whois", 1, args, TRUE); } else if (g_strcmp0(cmd, "ISON") == 0) proxy_redirect_event(client, "ison", 1, args, -1); else if (g_strcmp0(cmd, "USERHOST") == 0) proxy_redirect_event(client, "userhost", 1, args, -1); else if (g_strcmp0(cmd, "MODE") == 0) { /* convert dots to spaces */ char *slist, *str, mode, *p; int argc; p = strchr(args, ' '); if (p != NULL) *p++ = '\0'; mode = p == NULL ? '\0' : *p; slist = g_strdup(args); argc = 1; for (p = slist; *p != '\0'; p++) { if (*p == ',') { *p = ' '; argc++; } } /* get channel mode / bans / exception / invite list */ str = g_strdup_printf("%s %s", args, slist); switch (mode) { case '\0': proxy_redirect_event(client, "mode channel", argc, str, -1); break; case 'b': proxy_redirect_event(client, "mode b", argc, str, -1); break; case 'e': proxy_redirect_event(client, "mode e", argc, str, -1); break; case 'I': proxy_redirect_event(client, "mode I", argc, str, -1); break; } g_free(str); g_free(slist); } else if (g_strcmp0(cmd, "PRIVMSG") == 0) { /* send the message to other clients as well */ char *params, *target, *msg; params = event_get_params(args, 2 | PARAM_FLAG_GETREST, &target, &msg); proxy_outserver_all_except(client, "PRIVMSG %s", args); ignore_next = TRUE; if (*msg != '\001' || msg[strlen(msg)-1] != '\001') { signal_emit(ischannel(*target) ? "message own_public" : "message own_private", 4, client->server, msg, target, target); } else if (strncmp(msg+1, "ACTION ", 7) == 0) { /* action */ msg[strlen(msg)-1] = '\0'; signal_emit("message irc own_action", 3, client->server, msg+8, target); } else { /* CTCP */ char *p; msg[strlen(msg)-1] = '\0'; p = strchr(msg, ' '); if (p != NULL) *p++ = '\0'; else p = ""; signal_emit("message irc own_ctcp", 4, client->server, msg+1, p, target); } ignore_next = FALSE; g_free(params); } else if (g_strcmp0(cmd, "PING") == 0) { proxy_redirect_event(client, "ping", 1, NULL, TRUE); } else if (g_strcmp0(cmd, "AWAY") == 0) { /* set the away reason */ if (args != NULL) { g_free(client->server->away_reason); client->server->away_reason = g_strdup(args); } } irc_send_cmd(client->server, data); }
/* * putchan_raw <server_tag> <#chan> <text> * Use this instead of putserv so that can see own message * * "raw" because putchan in Tcl will do some string fixing on text * * all command parameters should be using unicode (internal) encoding. */ int putchan_raw(ClientData clientData, Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]) { (void) clientData; if (objc != 4) { Tcl_Obj* str = Tcl_ObjPrintf("wrong # args: should be \"putchan_raw" " server_tag channel text\""); Tcl_SetObjResult(interp, str); return TCL_ERROR; } Tcl_Obj* const server_tag = objv[1]; Tcl_Obj* const target = objv[2]; Tcl_Obj* const msg = objv[3]; // find the server in Irssi. SERVER_REC* server_rec = server_find_tag(Tcl_GetString(server_tag)); if (server_rec == NULL) { Tcl_Obj* str = Tcl_ObjPrintf("server with tag '%s' not found", Tcl_GetString(server_tag)); Tcl_SetObjResult(interp, str); return TCL_ERROR; } // find the channel on this server in Irssi. CHANNEL_REC* channel_rec = channel_find(server_rec, Tcl_GetString(target)); if (channel_rec == NULL) { Tcl_Obj* str = Tcl_ObjPrintf("channel '%s' not found on server '%s'", Tcl_GetString(target), Tcl_GetString(server_tag)); Tcl_SetObjResult(interp, str); return TCL_ERROR; } // create the full command string to send to the IRC server. // PRIVMSG <target> :<msg> // this is how we used to create the command but I am concerned it // is not dealing with encoding correctly. //Tcl_Obj* send_str = Tcl_ObjPrintf("PRIVMSG %s :%s", target, msg); // try to be more careful with how we build the string. // -1 means take everything up to first NULL. Tcl_Obj* send_str = Tcl_NewStringObj("PRIVMSG ", -1); if (!send_str) { return TCL_ERROR; } Tcl_AppendObjToObj(send_str, target); Tcl_AppendToObj(send_str, " :", strlen(" :")); Tcl_AppendObjToObj(send_str, msg); // send the command to the server. // from ByteArrObj docs: // "Obtaining the string representation of a byte-array object (by calling Tcl_GetStringFromObj) produces a properly formed UTF-8 sequence with a one-to-one mapping between the bytes in the internal representation and the UTF-8 characters in the string representation." irc_send_cmd((IRC_SERVER_REC*) server_rec, Tcl_GetString(send_str)); // this frees the object. unsure if I actually need to call this, but it // seems like it doesn't matter if I do! Tcl_DecrRefCount(send_str); // write the message to Irssi so we see it ourselves. print_message_public(server_rec, channel_rec, Tcl_GetString(target), server_rec->nick, NULL, Tcl_GetString(msg)); //signal_emit("message own_public", 3, server, text, chan); return TCL_OK; }
extern int irc_welcome(t_connection * conn) { char temp[MAX_IRC_MESSAGE_LEN]; time_t temptime; char const * tempname; char const * temptimestr; char const * filename; FILE *fp; char * line, * formatted_line; char send_line[MAX_IRC_MESSAGE_LEN]; char motd_failed = 0; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } tempname = conn_get_loggeduser(conn); if ((34+strlen(tempname)+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":Welcome to the %s IRC Network %s",prefs_get_irc_network_name(), tempname); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_WELCOME,temp); if ((14+strlen(server_get_hostname())+10+strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":Your host is %s, running "PVPGN_SOFTWARE" "PVPGN_VERSION,server_get_hostname()); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_YOURHOST,temp); temptime = server_get_starttime(); /* FIXME: This should be build time */ temptimestr = ctime(&temptime); if ((25+strlen(temptimestr)+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":This server was created %s",temptimestr); /* FIXME: is ctime() portable? */ else 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 ((strlen(server_get_hostname())+7+strlen(PVPGN_SOFTWARE" "PVPGN_VERSION)+9+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,"%s "PVPGN_SOFTWARE" "PVPGN_VERSION" - -",server_get_hostname()); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_MYINFO,temp); if((conn_get_wol(conn) == 1)) sprintf(temp,"NICKLEN=%d TOPICLEN=%d CHANNELLEN=%d PREFIX="CHANNEL_PREFIX" CHANTYPES="CHANNEL_TYPE" NETWORK=%s IRCD="PVPGN_SOFTWARE, WOL_NICKNAME_LEN, MAX_TOPIC_LEN, CHANNEL_NAME_LEN, prefs_get_irc_network_name()); else sprintf(temp,"NICKLEN=%d TOPICLEN=%d CHANNELLEN=%d PREFIX="CHANNEL_PREFIX" CHANTYPES="CHANNEL_TYPE" NETWORK=%s IRCD="PVPGN_SOFTWARE, CHAR_NAME_LEN, MAX_TOPIC_LEN, CHANNEL_NAME_LEN, prefs_get_irc_network_name()); if((strlen(temp))<=MAX_IRC_MESSAGE_LEN) irc_send(conn,RPL_ISUPPORT,temp); else { sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_ISUPPORT,temp); } if ((3+strlen(server_get_hostname())+22+1)<=MAX_IRC_MESSAGE_LEN) sprintf(temp,":- %s, "PVPGN_SOFTWARE" "PVPGN_VERSION", built on %s",server_get_hostname(),temptimestr); else sprintf(temp,":Maximum length exceeded"); irc_send(conn,RPL_MOTDSTART,temp); if ((filename = prefs_get_motdfile())) { if ((fp = fopen(filename,"r"))) { while ((line=file_get_line(fp))) { if ((formatted_line = message_format_line(conn,line))) { formatted_line[0]=' '; sprintf(send_line,":-%s",formatted_line); irc_send(conn,RPL_MOTD,send_line); xfree(formatted_line); } } file_get_line(NULL); // clear file_get_line buffer fclose(fp); } else motd_failed = 1; } else motd_failed = 1; if (motd_failed) { irc_send(conn,RPL_MOTD,":- Failed to load motd, sending default motd "); irc_send(conn,RPL_MOTD,":- ====================================================== "); irc_send(conn,RPL_MOTD,":- http://www.pvpgn.org "); irc_send(conn,RPL_MOTD,":- ====================================================== "); } irc_send(conn,RPL_ENDOFMOTD,":End of /MOTD command"); irc_send_cmd(conn,"NOTICE",":This is an experimental service."); conn_set_state(conn,conn_state_bot_password); if (connlist_find_connection_by_accountname(conn_get_loggeduser(conn))) { irc_send_cmd(conn,"NOTICE","This account is already logged in, use another account."); return -1; } if (conn_get_ircpass(conn)) { irc_send_cmd(conn,"NOTICE",":Trying to authenticate with PASS ..."); irc_authenticate(conn,conn_get_ircpass(conn)); } else { irc_send_cmd(conn,"NOTICE",":No PASS command received. Please identify yourself by /msg NICKSERV identify <password>."); } return 0; }
extern int irc_authenticate(t_connection * conn, char const * passhash) { t_hash h1; t_hash h2; t_account * a; char const * temphash; char const * username; char const * tempapgar; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return 0; } if (!passhash) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL passhash"); return 0; } username = conn_get_loggeduser(conn); if (!username) { /* redundant sanity check */ eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn->protocol.loggeduser"); return 0; } a = accountlist_find_account(username); if (!a) { irc_send_cmd(conn,"NOTICE",":Authentication failed."); /* user does not exist */ return 0; } if (connlist_find_connection_by_account(a) && prefs_get_kick_old_login()==0) { irc_send_cmd(conn,"NOTICE",":Authentication rejected (already logged in) "); } else if (account_get_auth_lock(a)==1) { irc_send_cmd(conn,"NOTICE",":Authentication rejected (account is locked) "); } else { if((conn_get_wol(conn) == 1)) { temphash = account_get_wol_apgar(a); tempapgar = conn_wol_get_apgar(conn); if(temphash == NULL) { account_set_wol_apgar(a,tempapgar); temphash = account_get_wol_apgar(a); } if(tempapgar == NULL) { irc_send_cmd(conn,"NOTICE",":Authentication failed."); /* bad APGAR */ conn_increment_passfail_count(conn); return 0; } if(strcmp(temphash,tempapgar) == 0) { bnetd_log(username, addr_num_to_ip_str(conn_get_addr(conn)), "IRC", "LOGIN", NULL, 1, 0); conn_login(conn,a,username); conn_set_state(conn,conn_state_loggedin); conn_set_clienttag(conn,CLIENTTAG_WWOL_UINT); /* WWOL hope here is ok */ return 1; } else { conn_increment_passfail_count(conn); return 0; } } hash_set_str(&h1,passhash); temphash = account_get_pass(a); hash_set_str(&h2,temphash); if (hash_eq(h1,h2)) { bnetd_log(username, addr_num_to_ip_str(conn_get_addr(conn)), "IRC", "LOGIN", NULL, 1, 0); conn_login(conn,a,username); conn_set_state(conn,conn_state_loggedin); conn_set_clienttag(conn,CLIENTTAG_IIRC_UINT); /* IIRC hope here is ok */ irc_send_cmd(conn,"NOTICE",":Authentication successful. You are now logged in."); return 1; } else { irc_send_cmd(conn,"NOTICE",":Authentication failed."); /* wrong password */ conn_increment_passfail_count(conn); } } return 0; }