/* SYNTAX: KNOCKOUT [<seconds>] <nick> <reason> */ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, IRC_CHANNEL_REC *channel) { KNOCKOUT_REC *rec; char *nick, *reason, *timeoutstr, *str; void *free_arg; int timeleft; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!IS_IRC_CHANNEL(channel)) cmd_return_error(CMDERR_NOT_JOINED); if (is_numeric(data, ' ')) { /* first argument is the timeout */ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nick, &reason)) return; timeleft = atoi(timeoutstr); } else { timeleft = 0; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &reason)) return; } if (timeleft == 0) timeleft = settings_get_int("knockout_time"); if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); signal_emit("command ban", 3, nick, server, channel); str = g_strdup_printf("%s %s", nick, reason); signal_emit("command kick", 3, str, server, channel); g_free(str); /* create knockout record */ rec = g_new(KNOCKOUT_REC, 1); rec->timeleft = timeleft; rec->channel = channel; rec->ban = ban_get_mask(channel, nick); server->knockoutlist = g_slist_append(server->knockoutlist, rec); cmd_params_free(free_arg); }
static void server_rejoin_channels(IRC_SERVER_REC *server) { GSList *tmp, *next; GString *channels, *keys; int use_keys; g_return_if_fail(IS_IRC_SERVER(server)); channels = g_string_new(NULL); keys = g_string_new(NULL); use_keys = FALSE; for (tmp = server->rejoin_channels; tmp != NULL; tmp = next) { REJOIN_REC *rec = tmp->data; next = tmp->next; if (rec->joining) { /* we missed the join (failed) message, remove from rejoins.. */ rejoin_destroy(server, rec); continue; } rec->joining = TRUE; g_string_sprintfa(channels, "%s,", rec->channel); if (rec->key == NULL) g_string_append(keys, "x,"); else { g_string_sprintfa(keys, "%s,", rec->key); use_keys = TRUE; } } if (channels->len > 0) { g_string_truncate(channels, channels->len-1); g_string_truncate(keys, keys->len-1); if (use_keys) g_string_sprintfa(channels, " %s", keys->str); server->channels_join(SERVER(server), channels->str, TRUE); } g_string_free(channels, TRUE); g_string_free(keys, TRUE); }
/* SYNTAX: DCC SERVER [+|-scf] [port] */ static void cmd_dcc_server(const char *data, IRC_SERVER_REC *server) { void *free_arg; GIOChannel *handle; SERVER_DCC_REC *dcc; IPADDR own_ip; char *flags, *port; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 2, &flags, &port)) return; dcc = dcc_server_find_port(port); if (dcc != NULL) { /* Server is already running, update it */ dcc_server_update_flags(dcc, flags); cmd_params_free(free_arg); return; } /* start listening */ if (!IS_IRC_SERVER(server) || !server->connected) { cmd_param_error(CMDERR_NOT_CONNECTED); } handle = dcc_listen_port(net_sendbuffer_handle(server->handle), &own_ip, atoi(port)); if (handle == NULL) { cmd_param_error(CMDERR_ERRNO); } dcc = dcc_server_create(server, flags); dcc->handle = handle; dcc->port = atoi(port); dcc->tagconn = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_server_listen, dcc); signal_emit("dcc server started", 1, dcc); cmd_params_free(free_arg); }
/* SYNTAX: SETHOST <host> <password> (non-ircops) SETHOST <ident> <host> (ircops) */ static void cmd_sethost(const char *data, IRC_SERVER_REC *server) { GSList *tmp; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); /* Save all the joined channels in server to window binds, since the server will soon /PART + /JOIN us in all channels. */ for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { CHANNEL_REC *channel = tmp->data; window_bind_add(window_item_window(channel), server->tag, channel->visible_name); } irc_send_cmdv(server, "SETHOST %s", data); }
/* timeout function: send /ISON commands to server to check if someone in notify list is in IRC */ static void notifylist_timeout_server(IRC_SERVER_REC *server) { MODULE_SERVER_REC *mserver; GSList *tmp; GString *cmd; char *nick, *ptr; int len; g_return_if_fail(server != NULL); if (!IS_IRC_SERVER(server)) return; mserver = MODULE_DATA(server); if (mserver->ison_count > 0) { /* still not received all replies to previous /ISON commands.. */ return; } cmd = g_string_new(NULL); for (tmp = notifies; tmp != NULL; tmp = tmp->next) { NOTIFYLIST_REC *rec = tmp->data; if (!notifylist_ircnets_match(rec, server->connrec->chatnet)) continue; nick = g_strdup(rec->mask); ptr = strchr(nick, '!'); if (ptr != NULL) *ptr = '\0'; len = strlen(nick); if (cmd->len+len+1 > 510) ison_send(server, cmd); g_string_sprintfa(cmd, "%s ", nick); g_free(nick); } if (cmd->len > 0) ison_send(server, cmd); g_string_free(cmd, TRUE); }
/* SYNTAX: PART [<channels>] [<message>] */ static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *channame, *msg; void *free_arg; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg)) return; if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*msg == '\0') msg = (char *) settings_get_str("part_message"); irc_send_cmdv(server, *msg == '\0' ? "PART %s" : "PART %s :%s", channame, msg); cmd_params_free(free_arg); }
static void sig_disconnected(IRC_SERVER_REC *server) { SERVER_QUERY_REC *rec; int n; g_return_if_fail(server != NULL); if (!IS_IRC_SERVER(server)) return; rec = server->chanqueries; g_return_if_fail(rec != NULL); for (n = 0; n < CHANNEL_QUERIES; n++) g_slist_free(rec->queries[n]); g_slist_free(rec->current_queries); g_free(rec); server->chanqueries = NULL; }
/* SYNTAX: NCTCP <targets> <ctcp command> [<ctcp data>] */ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server) { char *target, *ctcpcmd, *ctcpdata; void *free_arg; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) return; if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); g_strup(ctcpcmd); g_string_sprintf(tmpstr, "NOTICE %s :\001%s %s\001", target, ctcpcmd, ctcpdata); irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd); cmd_params_free(free_arg); }
static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item, int set) { IRC_CHANNEL_REC *chanrec; char *channel, *nicks; void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !IS_IRC_SERVER(server)) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channel, &nicks)) return; if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED); if (*nicks == '\0') { if (strcmp(data, "*") != 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); /* /BAN * or /UNBAN * - ban/unban everyone */ nicks = (char *) data; } chanrec = irc_channel_find(server, channel); if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); if (!chanrec->wholist) cmd_param_error(CMDERR_CHAN_NOT_SYNCED); if (set) ban_set(chanrec, nicks); else { if (is_numeric(nicks, '\0')) { /* unban with ban number */ BAN_REC *ban = g_slist_nth_data(chanrec->banlist, atoi(nicks)-1); if (ban != NULL) nicks = ban->ban; } ban_remove(chanrec, nicks); } cmd_params_free(free_arg); }
static void sig_message_own_public(SERVER_REC *server, const char *msg, const char *target, const char *origtarget) { char *nickmode; if (IS_IRC_SERVER(server) && target != NULL && *target == '@' && ischannel(target[1])) { /* Hybrid 6 feature, send msg to all ops in channel */ nickmode = channel_get_nickmode(channel_find(server, target+1), server->nick); printformat_module("fe-common/core", server, target+1, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT, TXT_OWN_MSG_CHANNEL, server->nick, target, msg, nickmode); signal_stop(); } }
static void notifylist_deinit_server(IRC_SERVER_REC *server) { MODULE_SERVER_REC *mserver; NOTIFY_NICK_REC *rec; g_return_if_fail(server != NULL); if (!IS_IRC_SERVER(server)) return; mserver = MODULE_DATA(server); while (mserver->notify_users != NULL) { rec = mserver->notify_users->data; mserver->notify_users = g_slist_remove(mserver->notify_users, rec); notify_nick_destroy(rec); } g_free(mserver); }
static int channel_rejoin(IRC_SERVER_REC *server, const char *channel) { IRC_CHANNEL_REC *chanrec; REJOIN_REC *rec; g_return_val_if_fail(IS_IRC_SERVER(server), 0); g_return_val_if_fail(channel != NULL, 0); chanrec = irc_channel_find(server, channel); if (chanrec == NULL || chanrec->joined) return 0; if (!settings_get_bool("channels_rejoin_unavailable")) { chanrec->left = TRUE; channel_destroy(CHANNEL(chanrec)); return 0; } rec = rejoin_find(server, channel); if (rec != NULL) { /* already exists */ rec->joining = FALSE; /* update channel key */ g_free_and_null(rec->key); if (channel_have_key(chanrec)) rec->key = g_strdup(chanrec->key); } else { /* new rejoin */ rec = g_new0(REJOIN_REC, 1); rec->channel = g_strdup(channel); if (channel_have_key(chanrec)) rec->key = g_strdup(chanrec->key); server->rejoin_channels = g_slist_append(server->rejoin_channels, rec); signal_emit("channel rejoin new", 2, server, rec); } chanrec->left = TRUE; channel_destroy(CHANNEL(chanrec)); return 1; }
/* SYNTAX: OPER [<nick>] <password> */ static void cmd_oper(const char *data, IRC_SERVER_REC *server) { char *nick, *password; void *free_arg; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2, &nick, &password)) return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*password == '\0') { password = nick; nick = server->nick; } irc_send_cmdv(server, "OPER %s %s", nick, password); cmd_params_free(free_arg); }
/* SYNTAX: AWAY [-one | -all] [<reason>] */ static void cmd_away(const char *data, IRC_SERVER_REC *server) { GHashTable *optlist; char *reason; void *free_arg; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, "away", &optlist, &reason)) return; if (g_hash_table_lookup(optlist, "one") != NULL) server_send_away(server, reason); else g_slist_foreach(servers, (GFunc) server_send_away, reason); cmd_params_free(free_arg); }
/* 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); }
/* something is going to be printed to screen, print our current netsplit message before it. */ static void sig_print_starting(TEXT_DEST_REC *dest) { NETJOIN_SERVER_REC *rec; if (printing_joins) return; if (!IS_IRC_SERVER(dest->server)) return; if (!(dest->level & MSGLEVEL_PUBLIC)) return; if (!server_ischannel(dest->server, dest->target)) return; rec = netjoin_find_server(IRC_SERVER(dest->server)); if (rec != NULL && rec->netjoins != NULL) print_netjoins(rec, dest->target); }
/* Deinitialize flood protection */ static void flood_deinit_server(IRC_SERVER_REC *server) { MODULE_SERVER_REC *mserver; g_return_if_fail(server != NULL); if (!IS_IRC_SERVER(server)) return; mserver = MODULE_DATA(server); if (mserver != NULL && mserver->floodlist != NULL) { flood_timecheck = 0; g_hash_table_foreach(mserver->floodlist, (GHFunc) flood_hash_destroy, NULL); g_hash_table_destroy(mserver->floodlist); } g_free(mserver); MODULE_DATA_UNSET(server); }
void channel_set_singlemode(IRC_SERVER_REC *server, const char *channel, const char *nicks, const char *mode) { GString *str; int num, modepos; char **nick, **nicklist; g_return_if_fail(IS_IRC_SERVER(server)); g_return_if_fail(channel != NULL && nicks != NULL && mode != NULL); if (*nicks == '\0') return; num = modepos = 0; str = g_string_new(NULL); nicklist = g_strsplit(nicks, " ", -1); for (nick = nicklist; *nick != NULL; nick++) { if (**nick == '\0') continue; if (num == 0) { g_string_sprintf(str, "MODE %s %s", channel, mode); modepos = str->len; } else { /* insert the mode string */ g_string_insert(str, modepos, mode); } g_string_sprintfa(str, " %s", *nick); if (++num == server->max_modes_in_cmd) { /* max. modes / command reached, send to server */ irc_send_cmd(server, str->str); num = 0; } } if (num > 0) irc_send_cmd(server, str->str); g_strfreev(nicklist); g_string_free(str, TRUE); }
static int flood_timeout(void) { MODULE_SERVER_REC *mserver; GSList *tmp; time_t now; /* remove the old people from flood lists */ now = time(NULL); for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *rec = tmp->data; if (!IS_IRC_SERVER(rec)) continue; mserver = MODULE_DATA(rec); g_hash_table_foreach_remove(mserver->floodlist, (GHRFunc) flood_hash_check_remove, &now); } return 1; }
/* SYNTAX: KICK [<channel>] <nicks> [<reason>] */ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *channame, *nicks, *reason; void *free_arg; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &nicks, &reason)) return; if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (!ischannel(*channame)) cmd_param_error(CMDERR_NOT_JOINED); g_string_sprintf(tmpstr, "KICK %s %s :%s", channame, nicks, reason); irc_send_cmd_split(server, tmpstr->str, 3, server->max_kicks_in_cmd); cmd_params_free(free_arg); }
/* SYNTAX: TOPIC [-delete] [<channel>] [<topic>] */ static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *channame, *topic; void *free_arg; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, item, "topic", &optlist, &channame, &topic)) return; irc_send_cmdv(server, *topic == '\0' && g_hash_table_lookup(optlist, "delete") == NULL ? "TOPIC %s" : "TOPIC %s :%s", channame, topic); cmd_params_free(free_arg); }
IRC_SERVER_REC *notifylist_ison(const char *nick, const char *serverlist) { GSList *tmp; g_return_val_if_fail(nick != NULL, FALSE); g_return_val_if_fail(serverlist != NULL, FALSE); if (*serverlist != '\0') return notifylist_ison_serverlist(nick, serverlist); /* any server.. */ for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *server = tmp->data; if (IS_IRC_SERVER(server) && notifylist_ison_server(server, nick)) return tmp->data; } return NULL; }
static void event_nick(IRC_SERVER_REC *server, const char *data, const char *orignick) { GSList *tmp; if (!IS_IRC_SERVER(server)) return; if (g_ascii_strcasecmp(orignick, server->nick) != 0) return; if (*data == ':') data++; for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if (rec->connected && rec->server == server) { g_free(rec->nick); rec->nick = g_strdup(data); } } }
static void sig_message_own_public(SERVER_REC *server, const char *msg, const char *target, const char *origtarget) { const char *oldtarget; char *nickmode; oldtarget = target; target = skip_target(target); if (IS_IRC_SERVER(server) && target != oldtarget) { /* Hybrid 6 / Bahamut feature, send msg to all ops / ops+voices in channel */ nickmode = channel_get_nickmode(channel_find(server, target), server->nick); printformat_module("fe-common/core", server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT, TXT_OWN_MSG_CHANNEL, server->nick, oldtarget, msg, nickmode); signal_stop(); } }
/* timeout function: knockout */ static void knockout_timeout_server(IRC_SERVER_REC *server) { GSList *tmp, *next; time_t now; g_return_if_fail(server != NULL); if (!IS_IRC_SERVER(server)) return; now = time(NULL); for (tmp = server->knockoutlist; tmp != NULL; tmp = next) { KNOCKOUT_REC *rec = tmp->data; next = tmp->next; if (rec->unban_time <= now) { /* timeout, unban. */ ban_remove(rec->channel, rec->ban); knockout_destroy(server, rec); } } }
static IRC_SERVER_REC *notifylist_ison_serverlist(const char *nick, const char *taglist) { IRC_SERVER_REC *server; char **list, **tmp; g_return_val_if_fail(nick != NULL, NULL); g_return_val_if_fail(taglist != NULL, NULL); list = g_strsplit(taglist, " ", -1); server = NULL; for (tmp = list; *tmp != NULL; tmp++) { server = (IRC_SERVER_REC *) server_find_chatnet(*tmp); if (IS_IRC_SERVER(server) && notifylist_ison_server(server, nick)) break; } g_strfreev(list); return tmp == NULL ? NULL : server; }
/* SYNTAX: PING <nicks> */ static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GTimeVal tv; char *str; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '\0' || strcmp(data, "*") == 0) { if (!IS_IRC_ITEM(item)) cmd_return_error(CMDERR_NOT_JOINED); data = item->name; } g_get_current_time(&tv); str = g_strdup_printf("%s PING %ld %ld", data, tv.tv_sec, tv.tv_usec); signal_emit("command ctcp", 3, str, server, item); g_free(str); }
/* SYNTAX: WALL [<channel>] <message> */ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *channame, *msg, *args; void *free_arg; IRC_CHANNEL_REC *chanrec; GSList *tmp, *nicks; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg)) return; if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanrec = irc_channel_find(server, channame); if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); /* send notice to all ops */ nicks = NULL; g_hash_table_foreach(chanrec->nicks, (GHFunc) cmd_wall_hash, &nicks); args = g_strconcat(chanrec->name, " ", msg, NULL); msg = parse_special_string(settings_get_str("wall_format"), SERVER(server), item, args, NULL); g_free(args); for (tmp = nicks; tmp != NULL; tmp = tmp->next) { NICK_REC *rec = tmp->data; if (g_strcasecmp(rec->nick, server->nick) != 0) irc_send_cmdv(server, "NOTICE %s :%s", rec->nick, msg); } g_free(msg); g_slist_free(nicks); cmd_params_free(free_arg); }
/* SYNTAX: LIST [-yes] [<channel>] */ static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *str; void *free_arg; g_return_if_fail(data != NULL); if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, "list", &optlist, &str)) return; if (*str == '\0' && g_hash_table_lookup(optlist, "yes") == NULL) cmd_param_error(CMDERR_NOT_GOOD_IDEA); irc_send_cmdv(server, "LIST %s", str); cmd_params_free(free_arg); /* add default redirection */ server_redirect_default((SERVER_REC *) server, "bogus command list"); }
static void event_connected(IRC_SERVER_REC *server) { GSList *tmp; const char *chatnet; if (!IS_IRC_SERVER(server)) return; chatnet = server->connrec->chatnet; for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if (rec->connected && rec->server == NULL && (g_strcmp0(rec->listen->ircnet, "*") == 0 || (chatnet != NULL && g_ascii_strcasecmp(chatnet, rec->listen->ircnet) == 0))) { proxy_outdata(rec, ":%s NOTICE %s :Connected to server\r\n", rec->proxy_address, rec->nick); rec->server = server; proxy_client_reset_nick(rec); } } }