/* SYNTAX: HILIGHT [-nick | -nonick] [-mask | -regexp | -word] [-color <color>] [-level <level>] [-channels <channels>] <text> */ static void cmd_hilight(const char *data) { GHashTable *optlist; HILIGHT_REC *rec; char *colorarg, *levelarg, *chanarg, *text; char **channels; void *free_arg; g_return_if_fail(data != NULL); if (*data == '\0') { cmd_hilight_show(); return; } if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, "hilight", &optlist, &text)) return; chanarg = g_hash_table_lookup(optlist, "channels"); levelarg = g_hash_table_lookup(optlist, "level"); colorarg = g_hash_table_lookup(optlist, "color"); if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1); rec = hilight_find(text, channels); if (rec == NULL) { rec = g_new0(HILIGHT_REC, 1); rec->text = g_strdup(text); rec->channels = channels; } else { g_free_and_null(rec->color); g_strfreev(channels); hilight_remove_config(rec); hilights = g_slist_remove(hilights, rec); } rec->level = (levelarg == NULL || *levelarg == '\0') ? 0 : level2bits(replace_chars(levelarg, ',', ' ')); rec->nick = settings_get_bool("hilight_only_nick") && (rec->level == 0 || (rec->level & DEFAULT_HILIGHT_LEVEL) == rec->level) ? g_hash_table_lookup(optlist, "nonick") == NULL : g_hash_table_lookup(optlist, "nick") != NULL; rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL; rec->fullword = g_hash_table_lookup(optlist, "word") != NULL; rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; if (colorarg != NULL && *colorarg != '\0') rec->color = g_strdup(colorarg); hilights = g_slist_append(hilights, rec); hilight_add_config(rec); hilight_print(g_slist_index(hilights, rec)+1, rec); cmd_params_free(free_arg); }
static void cmd_completion(const char *data) { GHashTable *optlist; CONFIG_NODE *node; GSList *tmp; char *key, *value; void *free_arg; int len; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, "completion", &optlist, &key, &value)) return; node = iconfig_node_traverse("completions", *value != '\0'); if (node != NULL && node->type != NODE_TYPE_BLOCK) { /* FIXME: remove after 0.8.5 */ iconfig_node_remove(mainconfig->mainnode, node); node = iconfig_node_traverse("completions", *value != '\0'); } if (node == NULL || (node->value == NULL && *value == '\0')) { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_NO_COMPLETIONS); cmd_params_free(free_arg); return; } if (g_hash_table_lookup(optlist, "delete") != NULL && *key != '\0') { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_COMPLETION_REMOVED, key); iconfig_set_str("completions", key, NULL); signal_emit("completion removed", 1, key); } else if (*key != '\0' && *value != '\0') { int automatic = g_hash_table_lookup(optlist, "auto") != NULL; node = config_node_section(node, key, NODE_TYPE_BLOCK); iconfig_node_set_str(node, "value", value); if (automatic) iconfig_node_set_bool(node, "auto", TRUE); else iconfig_node_set_str(node, "auto", NULL); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_COMPLETION_LINE, key, value, automatic ? "yes" : "no"); signal_emit("completion added", 1, key); } else { printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_COMPLETION_HEADER); len = strlen(key); for (tmp = node->value; tmp != NULL; tmp = tmp->next) { node = tmp->data; if (len == 0 || g_strncasecmp(node->key, key, len) == 0) { printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_COMPLETION_LINE, node->key, config_node_get_str(node, "value", ""), config_node_get_bool(node, "auto", FALSE) ? "yes" : "no"); } } printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, TXT_COMPLETION_FOOTER); } cmd_params_free(free_arg); }
/* SYNTAX: STATUSBAR ADD|MODIFY [-disable | -nodisable] [-type window|root] [-placement top|bottom] [-position #] [-visible always|active|inactive] <statusbar> */ static void cmd_statusbar_add_modify(const char *data, void *server, void *witem) { GHashTable *optlist; CONFIG_NODE *node; char *name, *type, *placement, *visible; void *free_arg; int error; int add = GPOINTER_TO_INT(signal_get_user_data()); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_STRIP_TRAILING_WS, "statusbar add", &optlist, &name)) return; if (*name == '\0') { cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); } error = 0; type = NULL; data = g_hash_table_lookup(optlist, "type"); if (data != NULL) { if (g_ascii_strcasecmp(data, "window") == 0) type = "window"; else if (g_ascii_strcasecmp(data, "root") == 0) type = "root"; else { printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_STATUSBAR_UNKNOWN_TYPE, data); error++; } } placement = NULL; data = g_hash_table_lookup(optlist, "placement"); if (data != NULL) { if (g_ascii_strcasecmp(data, "top") == 0) placement = "top"; else if (g_ascii_strcasecmp(data, "bottom") == 0) placement = "bottom"; else { printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_STATUSBAR_UNKNOWN_PLACEMENT, data); error++; } } visible = NULL; data = g_hash_table_lookup(optlist, "visible"); if (data != NULL) { if (g_ascii_strcasecmp(data, "always") == 0) visible = "always"; else if (g_ascii_strcasecmp(data, "active") == 0) visible = "active"; else if (g_ascii_strcasecmp(data, "inactive") == 0) visible = "inactive"; else { printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_STATUSBAR_UNKNOWN_VISIBILITY, data); error++; } } if (!error) { node = sbar_node(name, add); if (node == NULL && !add && sbar_node_isdefault(name)) { /* If this node is a default status bar, we need to create it in the config * to configure it */ node = sbar_node(name, TRUE); } if (node == NULL) { printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_STATUSBAR_NOT_FOUND, name); error++; } } if (error) { cmd_params_free(free_arg); return; } if (g_hash_table_lookup(optlist, "nodisable")) iconfig_node_set_str(node, "disabled", NULL); if (g_hash_table_lookup(optlist, "disable")) iconfig_node_set_bool(node, "disabled", TRUE); if (type != NULL) iconfig_node_set_str(node, "type", type); if (placement != NULL) iconfig_node_set_str(node, "placement", placement); data = g_hash_table_lookup(optlist, "position"); if (data != NULL) iconfig_node_set_int(node, "position", atoi(data)); if (visible != NULL) iconfig_node_set_str(node, "visible", visible); read_statusbar_config(); cmd_params_free(free_arg); }
/* SYNTAX: QUERY [-window] [-<server tag>] <nick> [<message>] */ static void cmd_query(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; QUERY_REC *query; char *nick, *msg; void *free_arg; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS, "query", &optlist, &nick, &msg)) return; if (*nick == '\0') { /* remove current query */ cmd_unquery("", server, item); cmd_params_free(free_arg); return; } server = cmd_options_get_server("query", optlist, server); if (server == NULL) { cmd_params_free(free_arg); return; } if (*nick != '=' && (server == NULL || !server->connected)) cmd_param_error(CMDERR_NOT_CONNECTED); if (g_hash_table_lookup(optlist, "window") != NULL) { signal_add("query created", (SIGNAL_FUNC) signal_query_created_curwin); } query = query_find(server, nick); if (query == NULL) query = CHAT_PROTOCOL(server)-> query_create(server->tag, nick, FALSE); else { /* query already exists, set it active */ WINDOW_REC *window = window_item_window(query); if (window != active_win) window_set_active(window); window_item_set_active(active_win, (WI_ITEM_REC *) query); } if (g_hash_table_lookup(optlist, "window") != NULL) { signal_remove("query created", (SIGNAL_FUNC) signal_query_created_curwin); } if (*msg != '\0') { msg = g_strdup_printf("-nick %s %s", nick, msg); signal_emit("command msg", 3, msg, server, query); g_free(msg); } cmd_params_free(free_arg); }
/* Handle incoming DCC CTCP messages */ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr, char *target, DCC_REC *chat) { char *type, *arg, *addrstr, *portstr, *sizestr, *str; void *free_arg; const char *cstr; DCC_REC *dcc; long size; int port; g_return_if_fail(data != NULL); g_return_if_fail(sender != NULL); if (!cmd_get_params(data, &free_arg, 5 | PARAM_FLAG_NOQUOTES, &type, &arg, &addrstr, &portstr, &sizestr)) return; if (sscanf(portstr, "%d", &port) != 1) port = 0; if (sscanf(sizestr, "%ld", &size) != 1) size = 0; dcc = dcc_create(SWAP_SENDGET(dcc_str2type(type)), -1, sender, arg, server, chat); dcc_get_address(addrstr, &dcc->addr); net_ip2host(&dcc->addr, dcc->addrstr); dcc->port = port; dcc->size = size; switch (dcc->type) { case DCC_TYPE_GET: cstr = settings_get_str("dcc_autoget_masks"); /* check that autoget masks match */ if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || masks_match(SERVER(server), cstr, sender, sendaddr)) && /* check file size limit, FIXME: it's possible to send a bogus file size and then just send what ever sized file.. */ (settings_get_int("dcc_max_autoget_size") <= 0 || (settings_get_int("dcc_max_autoget_size") > 0 && size <= settings_get_int("dcc_max_autoget_size")*1024))) { /* automatically get */ str = g_strdup_printf("GET %s %s", dcc->nick, dcc->arg); signal_emit("command dcc", 2, str, server); g_free(str); } else { /* send request */ signal_emit("dcc request", 1, dcc); } break; case DCC_TYPE_CHAT: cstr = settings_get_str("dcc_autochat_masks"); if (*cstr != '\0' && masks_match(SERVER(server), cstr, sender, sendaddr)) { /* automatically accept chat */ str = g_strdup_printf("CHAT %s", dcc->nick); signal_emit("command dcc", 2, str, server); g_free(str); } else { /* send request */ signal_emit("dcc request", 1, dcc); } break; case DCC_TYPE_RESUME: case DCC_TYPE_ACCEPT: /* handle this in dcc-files.c */ dcc_destroy(dcc); break; default: /* unknown DCC command */ signal_emit("dcc unknown ctcp", 3, data, sender, sendaddr); dcc_destroy(dcc); break; } cmd_params_free(free_arg); }
/* SYNTAX: MSG [-<server tag>] [-channel | -nick] <targets> <message> */ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *target, *origtarget, *msg, *recoded; void *free_arg; int free_ret, target_type = SEND_TARGET_NICK; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST, "msg", &optlist, &target, &msg)) return; if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); server = cmd_options_get_server("msg", optlist, server); if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); origtarget = target; free_ret = FALSE; if (strcmp(target, ",") == 0 || strcmp(target, ".") == 0) { target = parse_special(&target, server, item, NULL, &free_ret, NULL, 0); if (target != NULL && *target == '\0') { if (free_ret) g_free(target); target = NULL; free_ret = FALSE; } } if (target != NULL) { if (strcmp(target, "*") == 0) { /* send to active channel/query */ if (item == NULL) cmd_param_error(CMDERR_NOT_JOINED); target_type = IS_CHANNEL(item) ? SEND_TARGET_CHANNEL : SEND_TARGET_NICK; target = (char *) window_item_get_target(item); } else if (g_hash_table_lookup(optlist, "channel") != NULL) target_type = SEND_TARGET_CHANNEL; else if (g_hash_table_lookup(optlist, "nick") != NULL) target_type = SEND_TARGET_NICK; else { /* Need to rely on server_ischannel(). If the protocol doesn't really know if it's channel or nick based on the name, it should just assume it's nick, because when typing text to channels it's always sent with /MSG -channel. */ target_type = server_ischannel(server, target) ? SEND_TARGET_CHANNEL : SEND_TARGET_NICK; } } recoded = recode_out(server, msg, target); if (target != NULL) { signal_emit("server sendmsg", 4, server, target, recoded, GINT_TO_POINTER(target_type)); } signal_emit(target != NULL && target_type == SEND_TARGET_CHANNEL ? "message own_public" : "message own_private", 4, server, recoded, target, origtarget); g_free(recoded); if (free_ret && target != NULL) g_free(target); cmd_params_free(free_arg); }
/* SYNTAX: IRCNET ADD [-kicks <count>] [-msgs <count>] [-modes <count>] [-whois <count>] [-cmdspeed <ms>] [-cmdmax <count>] [-nick <nick>] [-user <user>] [-realname <name>] [-host <host>] [-autosendcmd <cmd>] <name> */ static void cmd_ircnet_add(const char *data) { GHashTable *optlist; char *name, *value; void *free_arg; IRCNET_REC *rec; if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, "ircnet add", &optlist, &name)) return; if (*name == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); rec = ircnet_find(name); if (rec == NULL) { rec = g_new0(IRCNET_REC, 1); rec->name = g_strdup(name); } else { if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick); if (g_hash_table_lookup(optlist, "user")) g_free_and_null(rec->username); if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname); if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); rec->own_ip = NULL; } if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd); } value = g_hash_table_lookup(optlist, "kicks"); if (value != NULL) rec->max_kicks = atoi(value); value = g_hash_table_lookup(optlist, "msgs"); if (value != NULL) rec->max_msgs = atoi(value); value = g_hash_table_lookup(optlist, "modes"); if (value != NULL) rec->max_modes = atoi(value); value = g_hash_table_lookup(optlist, "whois"); if (value != NULL) rec->max_whois = atoi(value); value = g_hash_table_lookup(optlist, "cmdspeed"); if (value != NULL) rec->cmd_queue_speed = atoi(value); value = g_hash_table_lookup(optlist, "cmdmax"); if (value != NULL) rec->max_cmds_at_once = atoi(value); value = g_hash_table_lookup(optlist, "nick"); if (value != NULL && *value != '\0') rec->nick = g_strdup(value); value = g_hash_table_lookup(optlist, "user"); if (value != NULL && *value != '\0') rec->username = g_strdup(value); value = g_hash_table_lookup(optlist, "realname"); if (value != NULL && *value != '\0') rec->realname = g_strdup(value); value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); rec->own_ip = NULL; } value = g_hash_table_lookup(optlist, "autosendcmd"); if (value != NULL && *value != '\0') rec->autosendcmd = g_strdup(value); ircnet_create(rec); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_IRCNET_ADDED, name); cmd_params_free(free_arg); }
/* SYNTAX: DCC CHAT [-passive] [<nick>] */ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) { void *free_arg; CHAT_DCC_REC *dcc; IPADDR own_ip; GIOChannel *handle; GHashTable *optlist; int p_id; char *nick, host[MAX_IP_LEN]; int port; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, "dcc chat", &optlist, &nick)) return; if (*nick == '\0') { dcc = DCC_CHAT(dcc_find_request_latest(DCC_CHAT_TYPE)); if (dcc != NULL) { if (!dcc_is_passive(dcc)) dcc_chat_connect(dcc); else dcc_chat_passive(dcc); } cmd_params_free(free_arg); return; } dcc = dcc_chat_find_id(nick); if (dcc != NULL && dcc_is_waiting_user(dcc)) { if (!dcc_is_passive(dcc)) { /* found from dcc chat requests, we're the connecting side */ dcc_chat_connect(dcc); } else { /* We are accepting a passive DCC CHAT. */ dcc_chat_passive(dcc); } cmd_params_free(free_arg); return; } if (dcc != NULL && dcc_is_listening(dcc) && dcc->server == server) { /* sending request again even while old request is still waiting, remove it. */ dcc_destroy(DCC(dcc)); } if (!IS_IRC_SERVER(server) || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); dcc = dcc_chat_create(server, NULL, nick, "chat"); if (dcc == NULL) { cmd_params_free(free_arg); g_warn_if_reached(); return; } if (g_hash_table_lookup(optlist, "passive") == NULL) { /* Standard DCC CHAT... let's listen for incoming connections */ handle = dcc_listen(net_sendbuffer_handle(server->handle), &own_ip, &port); if (handle == NULL) cmd_param_error(CMDERR_ERRNO); dcc->handle = handle; dcc->tagconn = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_listen, dcc); /* send the chat request */ signal_emit("dcc request send", 1, dcc); dcc_ip2str(&own_ip, host); irc_send_cmdv(server, "PRIVMSG %s :\001DCC CHAT CHAT %s %d\001", nick, host, port); } else { /* Passive protocol... we want the other side to listen */ /* send the chat request */ dcc->port = 0; signal_emit("dcc request send", 1, dcc); /* generate a random id */ p_id = rand() % 64; dcc->pasv_id = p_id; /* 16843009 is the long format of 1.1.1.1, we use a fake IP since the other side shouldn't care of it: they will send the address for us to connect to in the reply */ irc_send_cmdv(server, "PRIVMSG %s :\001DCC CHAT CHAT 16843009 0 %d\001", nick, p_id); } cmd_params_free(free_arg); }
/* NOTE: -network replaces the old -ircnet flag. */ static void cmd_ignore(const char *data) { GHashTable *optlist; IGNORE_REC *rec; char *patternarg, *chanarg, *mask, *levels, *timestr, *servertag; char **channels; void *free_arg; int new_ignore, msecs, level; if (*data == '\0') { cmd_ignore_show(); return; } if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, "ignore", &optlist, &mask, &levels)) return; patternarg = g_hash_table_lookup(optlist, "pattern"); chanarg = g_hash_table_lookup(optlist, "channels"); servertag = g_hash_table_lookup(optlist, "network"); /* Allow -ircnet for backwards compatibility */ if (!servertag) servertag = g_hash_table_lookup(optlist, "ircnet"); if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*levels == '\0') levels = "ALL"; level = level2bits(levels, NULL); msecs = 0; timestr = g_hash_table_lookup(optlist, "time"); if (timestr != NULL) { if (!parse_time_interval(timestr, &msecs)) cmd_param_error(CMDERR_INVALID_TIME); } if (active_win->active_server != NULL && server_ischannel(active_win->active_server, mask)) { chanarg = mask; mask = NULL; } channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(chanarg, ",", -1); rec = patternarg != NULL ? NULL: ignore_find_noact(servertag, mask, channels, (level & MSGLEVEL_NO_ACT)); new_ignore = rec == NULL; if (rec == NULL) { rec = g_new0(IGNORE_REC, 1); rec->mask = mask == NULL || *mask == '\0' || g_strcmp0(mask, "*") == 0 ? NULL : g_strdup(mask); rec->channels = channels; } else { g_free_and_null(rec->pattern); g_strfreev(channels); } rec->level = combine_level(rec->level, levels); if (rec->level == MSGLEVEL_NO_ACT) { /* If only NO_ACT was specified add all levels; it makes no * sense on its own. */ rec->level |= MSGLEVEL_ALL; } if (new_ignore && rec->level == 0) { /* tried to unignore levels from nonexisting ignore */ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_IGNORE_NOT_FOUND, rec->mask); g_free(rec->mask); g_strfreev(rec->channels); g_free(rec); cmd_params_free(free_arg); return; } rec->servertag = (servertag == NULL || *servertag == '\0') ? NULL : g_strdup(servertag); rec->pattern = (patternarg == NULL || *patternarg == '\0') ? NULL : g_strdup(patternarg); rec->exception = g_hash_table_lookup(optlist, "except") != NULL; rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; rec->fullword = g_hash_table_lookup(optlist, "full") != NULL; rec->replies = g_hash_table_lookup(optlist, "replies") != NULL; if (msecs != 0) rec->unignore_time = time(NULL)+msecs/1000; if (new_ignore) ignore_add_rec(rec); else ignore_update_rec(rec); cmd_params_free(free_arg); }
/* SYNTAX: WHOIS [-<server tag>] [<server>] [<nicks>] */ static void cmd_whois(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *qserver, *query, *event_402, *str; void *free_arg; int free_nick; CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS, "whois", &optlist, &qserver, &query)) return; /* -<server tag> */ server = IRC_SERVER(cmd_options_get_server("whois", optlist, SERVER(server))); if (server == NULL) { cmd_params_free(free_arg); return; } if (*query == '\0') { query = qserver; qserver = ""; } if (*query == '\0') { QUERY_REC *queryitem = QUERY(item); if (queryitem == NULL) query = server->nick; else query = qserver = queryitem->name; } if (g_strcmp0(query, "*") == 0 && g_hash_table_lookup(optlist, "yes") == NULL) cmd_param_error(CMDERR_NOT_GOOD_IDEA); event_402 = "event 402"; if (*qserver == '\0') g_string_printf(tmpstr, "WHOIS %s", query); else { g_string_printf(tmpstr, "WHOIS %s %s", qserver, query); if (g_ascii_strcasecmp(qserver, query) == 0) event_402 = "whois event not found"; } query = get_redirect_nicklist(query, &free_nick); str = g_strconcat(qserver, " ", query, NULL); server_redirect_event(server, "whois", 1, str, TRUE, NULL, "event 318", "whois end", "event 402", event_402, "event 301", "whois away", /* 301 can come as a reply to /MSG, /WHOIS or /WHOWAS */ "event 313", "whois oper", "event 401", (settings_get_bool("auto_whowas") ? "whois try whowas" : "whois event not found"), "event 311", "whois event", "", "whois default event", NULL); g_free(str); server->whois_found = FALSE; irc_send_cmd_split(server, tmpstr->str, 2, server->max_whois_in_cmd); if (free_nick) g_free(query); cmd_params_free(free_arg); }
/* SYNTAX: KNOCKOUT [<time>] <nicks> <reason> */ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, IRC_CHANNEL_REC *channel) { KNOCKOUT_REC *rec; char *nicks, *reason, *timeoutstr, *kickcmd, *bancmd, *recoded; char **nicklist, *spacenicks, *banmasks; void *free_arg; int timeleft; GSList *ptr; CMD_IRC_SERVER(server); if (!IS_IRC_CHANNEL(channel)) cmd_return_error(CMDERR_NOT_JOINED); if (i_isdigit(*data)) { /* first argument is the timeout */ if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nicks, &reason)) return; if (!parse_time_interval(timeoutstr, &timeleft)) cmd_param_error(CMDERR_INVALID_TIME); } else { if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nicks, &reason)) return; timeleft = settings_get_time("knockout_time"); } if (*nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); nicklist = g_strsplit(nicks, ",", -1); spacenicks = g_strjoinv(" ", nicklist); g_strfreev(nicklist); banmasks = ban_get_masks(channel, spacenicks, 0); g_free(spacenicks); recoded = recode_out(SERVER(server), reason, channel->name); kickcmd = g_strdup_printf("%s %s %s", channel->name, nicks, recoded); g_free(recoded); bancmd = *banmasks == '\0'? NULL : g_strdup_printf("%s %s", channel->name, banmasks); if (settings_get_bool("kick_first_on_kickban")) { signal_emit("command kick", 3, kickcmd, server, channel); if (bancmd != NULL) signal_emit("command ban", 3, bancmd, server, channel); } else { if (bancmd != NULL) signal_emit("command ban", 3, bancmd, server, channel); signal_emit("command kick", 3, kickcmd, server, channel); } g_free(kickcmd); g_free_not_null(bancmd); if (*banmasks == '\0') g_free(banmasks); else { /* check if we already have this knockout */ for (ptr = server->knockoutlist; ptr != NULL; ptr = ptr->next) { rec = ptr->data; if (channel == rec->channel && !g_strcmp0(rec->ban, banmasks)) break; } if (ptr == NULL) { rec = g_new(KNOCKOUT_REC, 1); rec->channel = channel; rec->ban = banmasks; server->knockoutlist = g_slist_append(server->knockoutlist, rec); } rec->unban_time = time(NULL)+timeleft/1000; } cmd_params_free(free_arg); }
static void cmd_server_add(const char *data) { GHashTable *optlist; SERVER_SETUP_REC *rec; char *addr, *portstr, *password, *value, *chatnet; void *free_arg; int port; if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS, "server add", &optlist, &addr, &portstr, &password)) return; if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); port = *portstr == '\0' ? DEFAULT_SERVER_ADD_PORT : atoi(portstr); chatnet = g_hash_table_lookup(optlist, "network"); rec = server_setup_find(addr, port, chatnet); if (rec == NULL) { rec = create_server_setup(optlist); if (rec == NULL) { cmd_params_free(free_arg); return; } rec->address = g_strdup(addr); rec->port = port; } else { value = g_hash_table_lookup(optlist, "port"); if (value != NULL && *value != '\0') rec->port = atoi(value); if (*password != '\0') g_free_and_null(rec->password); if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); rec->own_ip4 = rec->own_ip6 = NULL; } } if (g_hash_table_lookup(optlist, "6")) rec->family = AF_INET6; else if (g_hash_table_lookup(optlist, "4")) rec->family = AF_INET; if (g_hash_table_lookup(optlist, "ssl")) rec->use_ssl = TRUE; value = g_hash_table_lookup(optlist, "ssl_tpm"); if (value != NULL) rec->ssl_tpm = g_strdup(value); value = g_hash_table_lookup(optlist, "ssl_cert"); if (value != NULL && *value != '\0') rec->ssl_cert = g_strdup(value); value = g_hash_table_lookup(optlist, "ssl_pkey"); if (value != NULL && *value != '\0') rec->ssl_pkey = g_strdup(value); if (g_hash_table_lookup(optlist, "ssl_verify")) rec->ssl_verify = TRUE; value = g_hash_table_lookup(optlist, "ssl_cafile"); if (value != NULL && *value != '\0') rec->ssl_cafile = g_strdup(value); value = g_hash_table_lookup(optlist, "ssl_capath"); if (value != NULL && *value != '\0') rec->ssl_capath = g_strdup(value); if ((rec->ssl_cafile != NULL && rec->ssl_cafile[0] != '\0') || (rec->ssl_capath != NULL && rec->ssl_capath[0] != '\0')) rec->ssl_verify = TRUE; if ((rec->ssl_cert != NULL && rec->ssl_cert[0] != '\0') || rec->ssl_verify == TRUE) rec->use_ssl = TRUE; if (g_hash_table_lookup(optlist, "auto")) rec->autoconnect = TRUE; if (g_hash_table_lookup(optlist, "noauto")) rec->autoconnect = FALSE; if (g_hash_table_lookup(optlist, "proxy")) rec->no_proxy = FALSE; if (g_hash_table_lookup(optlist, "noproxy")) rec->no_proxy = TRUE; if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password); value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); rec->own_ip4 = rec->own_ip6 = NULL; } signal_emit("server add fill", 2, rec, optlist); server_setup_add(rec); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_SETUPSERVER_ADDED, addr, port); cmd_params_free(free_arg); }
/** * Sets the key for a nick / channel in a server * @param data command * @param server irssi server record * @param item irssi window/item */ void cmd_setkey(const char *data, SERVER_REC * server, WI_ITEM_REC * item) { GHashTable *optlist; char contactName[CONTACT_SIZE] = "", encryptedKey[150] = ""; const char *target, *key; void *free_arg; if (IsNULLorEmpty(data)) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 No parameters. Usage: /setkey [-<server tag>] [<nick | #channel>] <key>"); return; } if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST, "setkey", &optlist, &target, &key)) return; if (*target == '\0') { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 No parameters. Usage: /setkey [-<server tag>] [<nick | #channel>] <key>"); cmd_params_free(free_arg); return; } server = cmd_options_get_server("setkey", optlist, server); if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); if (*key == '\0') { // one paramter given - it's the key key = target; if (item != NULL) target = window_item_get_target(item); else { printtext(NULL, NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Please define nick/#channel. Usage: /setkey [-<server tag>] [<nick | #channel>] <key>"); cmd_params_free(free_arg); return; } } encrypt_key((char *)key, encryptedKey); if (getIniSectionForContact(server, target, contactName) == FALSE) return; if (setIniValue(contactName, "key", encryptedKey, iniPath) == -1) { ZeroMemory(encryptedKey, sizeof(encryptedKey)); printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH ERROR:\002 Unable to write to blow.ini, probably out of space or permission denied."); cmd_params_free(free_arg); return; } ZeroMemory(encryptedKey, sizeof(encryptedKey)); printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Key for %s@%s successfully set!", target, server->tag); cmd_params_free(free_arg); }
static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr, char **rawlog_file) { CHAT_PROTOCOL_REC *proto; SERVER_CONNECT_REC *conn; GHashTable *optlist; char *addr, *portstr, *password, *nick, *chatnet, *host, *tmp; void *free_arg; g_return_val_if_fail(data != NULL, NULL); if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_OPTIONS, "connect", &optlist, &addr, &portstr, &password, &nick)) return NULL; if (plus_addr != NULL) *plus_addr = *addr == '+'; if (*addr == '+') addr++; if (*addr == '\0') { signal_emit("error command", 1, GINT_TO_POINTER(CMDERR_NOT_ENOUGH_PARAMS)); cmd_params_free(free_arg); return NULL; } if (strcmp(password, "-") == 0) *password = '******'; /* check if -<chatnet> option is used to specify chat protocol */ proto = chat_protocol_find_net(optlist); /* connect to server */ chatnet = proto == NULL ? NULL : g_hash_table_lookup(optlist, proto->chatnet); if (chatnet == NULL) chatnet = g_hash_table_lookup(optlist, "network"); conn = server_create_conn(proto != NULL ? proto->id : -1, addr, atoi(portstr), chatnet, password, nick); if (proto == NULL) proto = chat_protocol_find_id(conn->chat_type); if (proto->not_initialized) { /* trying to use protocol that isn't yet initialized */ signal_emit("chat protocol unknown", 1, proto->name); server_connect_unref(conn); cmd_params_free(free_arg); return NULL; } if (strchr(addr, '/') != NULL) conn->unix_socket = TRUE; if (g_hash_table_lookup(optlist, "6") != NULL) conn->family = AF_INET6; else if (g_hash_table_lookup(optlist, "4") != NULL) conn->family = AF_INET; if (g_hash_table_lookup(optlist, "ssl") != NULL) conn->use_ssl = TRUE; if ((tmp = g_hash_table_lookup(optlist, "ssl_cert")) != NULL) conn->ssl_cert = g_strdup(tmp); if ((tmp = g_hash_table_lookup(optlist, "ssl_pkey")) != NULL) conn->ssl_pkey = g_strdup(tmp); if (g_hash_table_lookup(optlist, "ssl_verify") != NULL) conn->ssl_verify = TRUE; if ((tmp = g_hash_table_lookup(optlist, "ssl_cafile")) != NULL) conn->ssl_cafile = g_strdup(tmp); if ((tmp = g_hash_table_lookup(optlist, "ssl_capath")) != NULL) conn->ssl_capath = g_strdup(tmp); if ((conn->ssl_capath != NULL && conn->ssl_capath[0] != '\0') || (conn->ssl_cafile != NULL && conn->ssl_cafile[0] != '\0')) conn->ssl_verify = TRUE; if ((conn->ssl_cert != NULL && conn->ssl_cert[0] != '\0') || conn->ssl_verify) conn->use_ssl = TRUE; if (g_hash_table_lookup(optlist, "!") != NULL) conn->no_autojoin_channels = TRUE; if (g_hash_table_lookup(optlist, "noproxy") != NULL) g_free_and_null(conn->proxy); *rawlog_file = g_strdup(g_hash_table_lookup(optlist, "rawlog")); host = g_hash_table_lookup(optlist, "host"); if (host != NULL && *host != '\0') { IPADDR ip4, ip6; if (net_gethostbyname(host, &ip4, &ip6) == 0) server_connect_own_ip_save(conn, &ip4, &ip6); } cmd_params_free(free_arg); return conn; }
/* SYNTAX: SCROLLBACK GOTO <+|-linecount>|<linenum>|<timestamp> */ static void cmd_scrollback_goto(gchar *data) { GList *pos; gchar *arg1, *arg2; void *free_arg; gint lines; if (!cmd_get_params(data, &free_arg, 2, &arg1, &arg2)) return; if (*arg2 == '\0' && (*arg1 == '-' || *arg1 == '+')) { /* go forward/backward n lines */ if (sscanf(arg1 + (*arg1 == '-' ? 0 : 1), "%d", &lines) == 1) gui_window_scroll(active_win, lines); } else if (*arg2 == '\0' && strchr(arg1, ':') == NULL && strchr(arg1, '.') == NULL && sscanf(arg1, "%d", &lines) == 1) { /* go to n'th line. */ pos = g_list_nth(WINDOW_GUI(active_win)->lines, lines); if (pos != NULL) scrollback_goto_pos(active_win, pos); } else { struct tm tm; time_t stamp; gint day, month; /* [dd.mm | -<days ago>] hh:mi[:ss] */ stamp = time(NULL); if (*arg1 == '-') { /* -<days ago> */ if (sscanf(arg1+1, "%d", &day) == 1) stamp -= day*3600*24; memcpy(&tm, localtime(&stamp), sizeof(struct tm)); } else if (*arg2 != '\0') { /* dd.mm */ if (sscanf(arg1, "%d.%d", &day, &month) == 2) { month--; memcpy(&tm, localtime(&stamp), sizeof(struct tm)); if (tm.tm_mon < month) tm.tm_year--; tm.tm_mon = month; tm.tm_mday = day; stamp = mktime(&tm); } } else { /* move time argument to arg2 */ arg2 = arg1; } /* hh:mi[:ss] */ memcpy(&tm, localtime(&stamp), sizeof(struct tm)); tm.tm_sec = 0; sscanf(arg2, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec); stamp = mktime(&tm); if (stamp > time(NULL) && arg1 == arg2) { /* we used /SB GOTO 23:59 or something, we want to jump to previous day's 23:59 time instead of into future. */ stamp -= 3600*24; } if (stamp > time(NULL)) { /* we're still looking into future, don't bother checking */ cmd_params_free(free_arg); return; } /* find the first line after timestamp */ for (pos = WINDOW_GUI(active_win)->lines; pos != NULL; pos = pos->next) { LINE_REC *rec = pos->data; if (rec->time >= stamp) { scrollback_goto_pos(active_win, pos); break; } } } cmd_params_free(free_arg); }
/* SYNTAX: HILIGHT [-nick | -word | -line] [-mask | -full | -regexp] [-color <color>] [-actcolor <color>] [-level <level>] [-channels <channels>] <text> */ static void cmd_hilight(const char *data) { GHashTable *optlist; HILIGHT_REC *rec; char *colorarg, *actcolorarg, *levelarg, *priorityarg, *chanarg, *text; char **channels; void *free_arg; g_return_if_fail(data != NULL); if (*data == '\0') { cmd_hilight_show(); return; } if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, "hilight", &optlist, &text)) return; chanarg = g_hash_table_lookup(optlist, "channels"); levelarg = g_hash_table_lookup(optlist, "level"); priorityarg = g_hash_table_lookup(optlist, "priority"); colorarg = g_hash_table_lookup(optlist, "color"); actcolorarg = g_hash_table_lookup(optlist, "actcolor"); if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1); rec = hilight_find(text, channels); if (rec == NULL) { rec = g_new0(HILIGHT_REC, 1); /* default to nick/word hilighting */ rec->nick = TRUE; rec->word = TRUE; rec->text = g_strdup(text); rec->channels = channels; } else { g_strfreev(channels); } rec->level = (levelarg == NULL || *levelarg == '\0') ? 0 : level2bits(replace_chars(levelarg, ',', ' ')); rec->priority = priorityarg == NULL ? 0 : atoi(priorityarg); if (g_hash_table_lookup(optlist, "line") != NULL) { rec->word = FALSE; rec->nick = FALSE; } if (g_hash_table_lookup(optlist, "word") != NULL) { rec->word = TRUE; rec->nick = FALSE; } if (g_hash_table_lookup(optlist, "nick") != NULL) rec->nick = TRUE; rec->nickmask = g_hash_table_lookup(optlist, "mask") != NULL; rec->fullword = g_hash_table_lookup(optlist, "full") != NULL; rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; if (colorarg != NULL) { g_free_and_null(rec->color); if (*colorarg != '\0') rec->color = g_strdup(colorarg); } if (actcolorarg != NULL) { g_free_and_null(rec->act_color); if (*actcolorarg != '\0') rec->act_color = g_strdup(actcolorarg); } hilight_create(rec); hilight_print(g_slist_index(hilights, rec)+1, rec); cmd_params_free(free_arg); reset_cache(); }
/* SYNTAX: RECONNECT <tag> [<quit message>] */ static void cmd_reconnect(const char *data, SERVER_REC *server) { SERVER_CONNECT_REC *conn; RECONNECT_REC *rec; char *tag, *msg; void *free_arg; int tagnum; if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) return; if (*tag != '\0' && g_strcmp0(tag, "*") != 0) server = server_find_tag(tag); if (server != NULL) { /* reconnect connected server */ conn = server_connect_copy_skeleton(server->connrec, TRUE); if (server->connected) reconnect_save_status(conn, server); msg = g_strconcat("* ", *msg == '\0' ? "Reconnecting" : msg, NULL); signal_emit("command disconnect", 2, msg, server); g_free(msg); conn->reconnection = TRUE; server_connect(conn); server_connect_unref(conn); cmd_params_free(free_arg); return; } if (g_ascii_strcasecmp(tag, "all") == 0) { /* reconnect all servers in reconnect queue */ reconnect_all(); cmd_params_free(free_arg); return; } if (*data == '\0') { /* reconnect to first server in reconnection list */ if (reconnects == NULL) cmd_param_error(CMDERR_NOT_CONNECTED); rec = reconnects->data; } else { if (g_ascii_strncasecmp(tag, "RECON-", 6) == 0) tag += 6; tagnum = atoi(tag); rec = tagnum <= 0 ? NULL : reconnect_find_tag(tagnum); } if (rec == NULL) { signal_emit("server reconnect not found", 1, data); } else { conn = rec->conn; server_connect_ref(conn); server_reconnect_destroy(rec); server_connect(conn); server_connect_unref(conn); } cmd_params_free(free_arg); }
/* SYNTAX: DCC SEND <nick> <file> */ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { char *target, *fname, *str, *ptr; void *free_arg; char host[MAX_IP_LEN]; int hfile, hlisten, port; long fsize; DCC_REC *dcc, *chat; IPADDR own_ip; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &fname)) return; if (*target == '\0' || *fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); /* if we're in dcc chat, send the request via it. */ chat = item_get_dcc(item); if (chat != NULL && (chat->mirc_ctcp || g_strcasecmp(target, chat->nick) != 0)) chat = NULL; if ((server == NULL || !server->connected) && chat == NULL) cmd_param_error(CMDERR_NOT_CONNECTED); if (dcc_find_item(DCC_TYPE_SEND, target, fname)) { signal_emit("dcc error send exists", 2, target, fname); cmd_params_free(free_arg); return; } str = convert_home(fname); if (!g_path_is_absolute(str)) { char *path; g_free(str); path = convert_home(settings_get_str("dcc_upload_path")); str = g_strconcat(path, G_DIR_SEPARATOR_S, fname, NULL); g_free(path); } hfile = open(str, O_RDONLY); g_free(str); if (hfile == -1) { signal_emit("dcc error file not found", 2, target, fname); cmd_params_free(free_arg); return; } fsize = lseek(hfile, 0, SEEK_END); lseek(hfile, 0, SEEK_SET); /* get the IP address we use with IRC server */ if (net_getsockname(chat != NULL ? chat->handle : net_sendbuffer_handle(server->handle), &own_ip, NULL) == -1) { close(hfile); cmd_param_error(CMDERR_ERRNO); } /* start listening */ port = settings_get_int("dcc_port"); hlisten = net_listen(&own_ip, &port); if (hlisten == -1) { close(hfile); cmd_param_error(CMDERR_ERRNO); } /* skip path, change all spaces to _ */ fname = g_strdup(g_basename(fname)); for (ptr = fname; *ptr != '\0'; ptr++) if (*ptr == ' ') *ptr = '_'; dcc = dcc_create(DCC_TYPE_SEND, hlisten, target, fname, server, chat); dcc->port = port; dcc->size = fsize; dcc->fhandle = hfile; dcc->tagconn = g_input_add(hlisten, G_INPUT_READ, (GInputFunction) dcc_send_init, dcc); /* send DCC request */ dcc_make_address(&own_ip, host); str = g_strdup_printf("DCC SEND %s %s %d %lu", fname, host, port, fsize); dcc_ctcp_message(target, server, chat, FALSE, str); g_free(str); g_free(fname); cmd_params_free(free_arg); }