/* * New command: /me+ <action message> */ void cmd_crypt_action(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { // New command: /me+ <action message> char bf_dest[1000]=""; const char *target; if (data==NULL || (strlen(data) < 2)) goto action_error; if (item!=NULL) target=window_item_get_target(item); else goto action_error; // generally refuse an action size of more than 512 byte, as everything above will never arrive complete anyway if (strlen(data) >= 512) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 /me+ \002error\002: message argument exceeds buffer size!"); return; } if (FiSH_encrypt(server, (char *)data, target, bf_dest)==0) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 /me+ \002error\002: Encryption disabled or no key found for %s.", target); return; } bf_dest[512]='\0'; irc_send_cmdv((IRC_SERVER_REC *)server, "PRIVMSG %s :\001ACTION %s\001\n", target, bf_dest); signal_emit("message irc own_action", 3, server, data, target); return; action_error: printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Usage: /me+ <action message>"); }
/** * 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 (WritePrivateProfileString(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); }
void cmd_keyx(const char *target, SERVER_REC * server, WI_ITEM_REC * item) { if (IsNULLorEmpty(target)) { if (item != NULL) target = window_item_get_target(item); else { printtext(NULL, NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Please define nick/#channel. Usage: /keyx <nick/#channel>"); return; } } if (ischannel(*target)) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 KeyXchange does not work for channels!"); return; } DH1080_gen(g_myPrivKey, g_myPubKey); irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s %s", target, "DH1080_INIT", g_myPubKey); printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Sent my DH1080 public key to %s, waiting for reply ...", target); }
/* * Change back to default blow.ini password, irssi syntax: /unsetinipw */ static void cmd_unsetinipw(const char *arg, SERVER_REC *server, WI_ITEM_REC *item) { unsetiniFlag=1; cmd_setinipw("Some_boogie_dummy_key", server, item); unsetiniFlag=0; if (WritePrivateProfileString("FiSH", "ini_password_Hash", "\0", iniPath) == -1) { 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."); return; } printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Changed back to default blow.ini password, you won't have to enter it on start-up anymore!"); }
/* SYNTAX: CTCP <targets> <ctcp command> [<ctcp data>] */ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target; char *ctcpcmd, *ctcpdata; void *free_arg; CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) return; if (strcmp(target, "*") == 0) target = item == NULL ? NULL : window_item_get_target(item); if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); g_strup(ctcpcmd); if (*ctcpdata == '\0') g_string_sprintf(tmpstr, "PRIVMSG %s :\001%s\001", target, ctcpcmd); else { char *recoded; recoded = recode_out(SERVER(server), ctcpdata, target); g_string_sprintf(tmpstr, "PRIVMSG %s :\001%s %s\001", target, ctcpcmd, recoded); g_free(recoded); } irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd); cmd_params_free(free_arg); }
/* SYNTAX: NOTICE <targets> <message> */ static void cmd_notice(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target, *msg; char *recoded; void *free_arg; CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) return; if (strcmp(target, "*") == 0) target = item == NULL ? NULL : window_item_get_target(item); if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); recoded = recode_out(SERVER(server), msg, target); g_string_sprintf(tmpstr, "NOTICE %s :%s", target, recoded); g_free(recoded); irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd); cmd_params_free(free_arg); }
static void cmd_ctcp(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target; char *ctcpcmd, *ctcpdata; void *free_arg; CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) return; if (g_strcmp0(target, "*") == 0) target = item == NULL ? "" : window_item_get_target(item); if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*target == '=') { /* don't handle DCC CTCPs */ cmd_params_free(free_arg); return; } ascii_strup(ctcpcmd); signal_emit("message irc own_ctcp", 4, server, ctcpcmd, ctcpdata, target); cmd_params_free(free_arg); }
void cmd_key(const char *data, SERVER_REC * server, WI_ITEM_REC * item) { GHashTable *optlist; char *target; char contactName[CONTACT_SIZE] = "", theKey[KEYBUF_SIZE] = ""; void *free_arg; if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST, "key", &optlist, &target)) return; if (item != NULL && IsNULLorEmpty(target)) target = (char *)window_item_get_target(item); if (IsNULLorEmpty(target)) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Please define nick/#channel. Usage: /key [-<server tag>] [<nick | #channel>]"); return; } server = cmd_options_get_server("key", optlist, server); if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); target = (char *)g_strchomp(target); if (getIniSectionForContact(server, target, contactName) == FALSE) return; if (getContactKey(contactName, theKey) == FALSE) { ZeroMemory(theKey, KEYBUF_SIZE); printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Key for %s@%s not found or invalid!", target, server->tag); return; } printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 Key for %s@%s: %s", target, server->tag, theKey); ZeroMemory(theKey, KEYBUF_SIZE); }
void cmd_delkey(const char *data, SERVER_REC * server, WI_ITEM_REC * item) { GHashTable *optlist; char *target; char contactName[CONTACT_SIZE] = ""; void *free_arg; if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS | PARAM_FLAG_GETREST, "delkey", &optlist, &target)) return; if (item != NULL && IsNULLorEmpty(target)) target = (char *)window_item_get_target(item); if (IsNULLorEmpty(target)) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 No parameters. Usage: /delkey [-<server tag>] [<nick | #channel>]"); return; } server = cmd_options_get_server("delkey", optlist, server); if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); target = (char *)g_strchomp(target); if (getIniSectionForContact(server, target, contactName) == FALSE) return; if (deleteIniValue(contactName, "key", iniPath) == 1) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Key for %s@%s successfully removed!", target, server->tag); } else { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 No key found for %s@%s", target, server->tag); } }
/* * Set encrypted topic for current channel, irssi syntax: /topic+ <your topic> */ void cmd_crypt_topic(const char *data, SERVER_REC * server, WI_ITEM_REC * item) { char bf_dest[1000] = ""; const char *target; if (data == 0 || *data == '\0') goto topic_error; if (item != NULL) target = window_item_get_target(item); else goto topic_error; if (!ischannel(*target)) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 Please change to the channel window where you want to set the topic!"); goto topic_error; } // generally refuse a topic size of more than 512 byte, as everything above will never arrive complete anyway if (strlen(data) >= 512) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 /topic+ error: topic length exceeds buffer size!"); goto topic_error; } // encrypt a message (using key for target) if (FiSH_encrypt(server, (char *)data, target, bf_dest) == 0) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 /topic+ error: Encryption disabled or no key found for %s.", target); goto topic_error; } bf_dest[512] = '\0'; irc_send_cmdv((IRC_SERVER_REC *) server, "TOPIC %s :%s\n", target, bf_dest); return; topic_error: printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Usage: /topic+ <your new topic>"); }
/* * Handle /me IRC command. */ static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { int ret; const char *target; char *msg, *otrmsg = NULL; QUERY_REC *query; query = QUERY(item); key_gen_check(); if (!query || !query->server) { goto end; } CMD_IRC_SERVER(server); if (!IS_IRC_QUERY(query)) { goto end; } if (!server || !server->connected) { cmd_return_error(CMDERR_NOT_CONNECTED); } target = window_item_get_target(item); ret = asprintf(&msg, OTR_IRC_MARKER_ME "%s", data); if (ret < 0) { goto end; } /* Critical section. On error, message MUST NOT be sent */ ret = otr_send(query->server, msg, target, &otrmsg); free(msg); if (!otrmsg) { goto end; } signal_stop(); if (otrmsg) { /* Send encrypted message */ irssi_send_message(SERVER(server), target, otrmsg); otrl_message_free(otrmsg); } signal_emit("message irc own_action", 3, server, data, item->visible_name); end: return; }
/* SYNTAX: VER [<nick> | <channel> | *] */ static void cmd_ver(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *str; g_return_if_fail(data != NULL); CMD_IRC_SERVER(server); if (*data == '\0' && !IS_QUERY(item)) cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); str = g_strdup_printf("%s VERSION", *data == '\0' ? window_item_get_target(item) : data); signal_emit("command ctcp", 3, str, server, item); g_free(str); }
WINDOW_REC *window_find_closest(void *server, const char *name, int level) { WINDOW_REC *window,*namewindow=NULL; WI_ITEM_REC *item; int i; /* match by name */ item = name == NULL ? NULL : window_item_find(server, name); if (item != NULL) { namewindow = window_item_window(item); if (namewindow != NULL && ((namewindow->level & level) != 0 || !settings_get_bool("window_check_level_first"))) { /* match, but if multiple windows have the same level we could be choosing a bad one here, eg. name=nick1 would get nick2's query instead of generic msgs window. And check for prefixed !channel name --Borys */ if (g_ascii_strcasecmp(name, item->visible_name) == 0 || g_ascii_strcasecmp(name, (char *) window_item_get_target((WI_ITEM_REC *) item)) == 0) return namewindow; } } /* prefer windows without items */ for (i = 0; i < 2; i++) { /* match by level */ if (level != MSGLEVEL_HILIGHT) level &= ~(MSGLEVEL_HILIGHT | MSGLEVEL_NOHILIGHT); window = window_find_level(server, level); if (window != NULL && (i == 1 || window->items == NULL)) return window; /* match by level - ignore server */ window = window_find_level(NULL, level); if (window != NULL && (i == 1 || window->items == NULL)) return window; } /* still return item's window if we didnt find anything */ if (namewindow != NULL) return namewindow; /* fallback to active */ return active_win; }
/* * New command: /notice+ <nick/#channel> <notice message> */ void cmd_crypt_notice(const char *data, SERVER_REC * server, WI_ITEM_REC * item) { char bf_dest[1000] = "", *msg; const char *target; void *free_arg = NULL; if (data == NULL || (strlen(data) < 3)) goto notice_error; if (!cmd_get_params(data, &free_arg, 1, &target)) goto notice_error; msg = strchr(data, ' '); if (IsNULLorEmpty(target) || IsNULLorEmpty(msg)) goto notice_error; msg++; // point to the notice message // generally refuse a notice size of more than 512 byte, as everything above will never arrive complete anyway if (strlen(msg) >= 512) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 /notice+ \002error\002: message argument exceeds buffer size!"); return; } if (FiSH_encrypt(server, msg, target, bf_dest) == 0) { printtext(server, target, MSGLEVEL_CRAP, "\002FiSH:\002 /notice+ \002error\002: Encryption disabled or no key found for %s.", target); return; } bf_dest[512] = '\0'; irc_send_cmdv((IRC_SERVER_REC *) server, "NOTICE %s :%s\n", target, bf_dest); signal_emit("message irc own_notice", 3, server, msg, target); cmd_params_free(free_arg); return; notice_error: if (free_arg) cmd_params_free(free_arg); printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Usage: /notice+ <nick/#channel> <notice message>"); }
static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { char *line, *str, *target; g_return_if_fail(data != NULL); if (item == NULL) return; if (*data == '\0') { /* empty line, forget it. */ signal_stop(); return; } line = settings_get_bool("expand_escapes") ? expand_escapes(data, server, item) : g_strdup(data); /* check for automatic nick completion */ if (completion_auto && IS_CHANNEL(item)) { str = auto_complete(CHANNEL(item), line); if (str != NULL) { g_free(line); line = str; } } /* the nick is quoted in case it contains '-' character. also spaces should work too now :) The nick is also escaped in case it contains '\' characters */ target = escape_string(window_item_get_target(item)); str = g_strdup_printf(IS_CHANNEL(item) ? "-channel \"%s\" %s" : IS_QUERY(item) ? "-nick \"%s\" %s" : "%s %s", target, line); g_free(target); signal_emit("command msg", 3, str, server, item); g_free(str); g_free(line); signal_stop(); }
/* SYNTAX: PING [<nick> | <channel> | *] */ static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GTimeVal tv; char *str; CMD_IRC_SERVER(server); if (*data == '\0') { if (!IS_QUERY(item)) cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); data = window_item_get_target(item); } 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); }
static void cmd_nctcp(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target, *text; void *free_arg; CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text)) return; if (g_strcmp0(target, "*") == 0) target = item == NULL ? "" : window_item_get_target(item); if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); signal_emit("message irc own_notice", 3, server, text, target); cmd_params_free(free_arg); }
/* SYNTAX: ME <message> */ static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target; char *recoded; CMD_IRC_SERVER(server); if (!IS_IRC_ITEM(item)) return; if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); target = window_item_get_target(item); recoded = recode_out(SERVER(server), data, target); signal_emit("message irc own_action", 3, server, recoded, item->visible_name); irc_send_cmdv(server, "PRIVMSG %s :\001ACTION %s\001", target, recoded); g_free(recoded); }
/* SYNTAX: ME <message> */ static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target; char *subdata; char **splitdata; int n = 0; CMD_IRC_SERVER(server); if (!IS_IRC_ITEM(item)) return; if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); target = window_item_get_target(item); splitdata = irc_server_split_action(server, target, data); while ((subdata = splitdata[n++])) { irc_server_send_action(server, target, subdata); signal_emit("message irc own_action", 3, server, subdata, item->visible_name); } g_strfreev(splitdata); }
static void cmd_notice(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { const char *target, *msg; char *recoded; void *free_arg; CMD_IRC_SERVER(server); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) return; if (strcmp(target, "*") == 0) target = item == NULL ? "" : window_item_get_target(item); if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); recoded = recode_out(SERVER(server), msg, target); signal_emit("message irc own_notice", 3, server, recoded, target); g_free(recoded); cmd_params_free(free_arg); }
/* SYNTAX: ME <message> */ static void cmd_me(const char *data, XMPP_SERVER_REC *server, WI_ITEM_REC *item) { const char *target; char *str, *recoded; int type; CMD_XMPP_SERVER(server); if (*data == '\0') return; g_strstrip((char *)data); if (*data == '\0') return; target = window_item_get_target(item); type = IS_CHANNEL(item) ? SEND_TARGET_CHANNEL : SEND_TARGET_NICK; if (type == SEND_TARGET_NICK) signal_emit("message xmpp own_action", 4, server, data, target, SEND_TARGET_NICK); str = g_strconcat("/me ", data, (void *)NULL); recoded = recode_out(SERVER(server), str, target); g_free(str); server->send_message(SERVER(server), target, recoded, type); g_free(recoded); }
/* 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; 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; } } if (target != NULL) { char **splitmsgs; char **tmp = NULL; char *singlemsg[] = { msg, NULL }; char *m; int n = 0; /* * If split_message is NULL, the server doesn't need to split * long messages. */ if (server->split_message != NULL) splitmsgs = tmp = server->split_message(server, target, msg); else splitmsgs = singlemsg; while ((m = splitmsgs[n++])) { signal_emit("server sendmsg", 4, server, target, m, GINT_TO_POINTER(target_type)); signal_emit(target_type == SEND_TARGET_CHANNEL ? "message own_public" : "message own_private", 4, server, m, target, origtarget); } g_strfreev(tmp); } else { signal_emit("message own_private", 4, server, msg, target, origtarget); } if (free_ret && target != NULL) g_free(target); cmd_params_free(free_arg); }
static void handle_exec(const char *args, GHashTable *optlist, WI_ITEM_REC *item) { PROCESS_REC *rec; char *target, *level; int notice, signum, interactive, target_nick, target_channel; /* check that there's no unknown options. we allowed them because signals can be used as options, but there should be only one unknown option: the signal name/number. */ signum = cmd_options_get_signal("exec", optlist); if (signum == -2) return; if (*args == '\0') { exec_show_list(); return; } target = NULL; notice = FALSE; if (g_hash_table_lookup(optlist, "in") != NULL) { rec = process_find(g_hash_table_lookup(optlist, "in"), TRUE); if (rec != NULL) { net_sendbuffer_send(rec->out, args, strlen(args)); net_sendbuffer_send(rec->out, "\n", 1); } return; } /* check if args is a process ID or name. if it's ID but not found, complain about it and fail immediately */ rec = process_find(args, *args == '%'); if (*args == '%' && rec == NULL) return; /* common options */ target_channel = target_nick = FALSE; if (g_hash_table_lookup(optlist, "out") != NULL) { /* redirect output to active channel/query */ if (item == NULL) cmd_return_error(CMDERR_NOT_JOINED); target = (char *) window_item_get_target(item); target_channel = IS_CHANNEL(item); target_nick = IS_QUERY(item); } else if (g_hash_table_lookup(optlist, "msg") != NULL) { /* redirect output to /msg <nick> */ target = g_hash_table_lookup(optlist, "msg"); } else if (g_hash_table_lookup(optlist, "notice") != NULL) { target = g_hash_table_lookup(optlist, "notice"); notice = TRUE; } /* options that require process ID/name as argument */ if (rec == NULL && (signum != -1 || g_hash_table_lookup(optlist, "close") != NULL)) { printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown process name: %s", args); return; } if (g_hash_table_lookup(optlist, "close") != NULL) { /* forcibly close the process */ process_destroy(rec, -1); return; } if (signum != -1) { /* send a signal to process */ kill(rec->pid, signum); return; } interactive = g_hash_table_lookup(optlist, "interactive") != NULL; if (*args == '%') { /* do something to already existing process */ char *name; if (target != NULL) { /* redirect output to target */ g_free_and_null(rec->target); rec->target = g_strdup(target); rec->notice = notice; } name = g_hash_table_lookup(optlist, "name"); if (name != NULL) { /* change window name */ g_free_not_null(rec->name); rec->name = *name == '\0' ? NULL : g_strdup(name); } else if (target == NULL && (rec->target_item == NULL || interactive)) { /* no parameters given, redirect output to the active window */ g_free_and_null(rec->target); rec->target_win = active_win; if (rec->target_item != NULL) exec_wi_destroy(rec->target_item); if (interactive) { rec->target_item = exec_wi_create(active_win, rec); } } return; } /* starting a new process */ rec = g_new0(PROCESS_REC, 1); rec->pid = -1; rec->shell = g_hash_table_lookup(optlist, "nosh") == NULL; process_exec(rec, args); if (rec->pid == -1) { /* pipe() or fork() failed */ g_free(rec); cmd_return_error(CMDERR_ERRNO); } rec->id = process_get_new_id(); rec->target = g_strdup(target); rec->target_win = active_win; rec->target_channel = target_channel; rec->target_nick = target_nick; rec->args = g_strdup(args); rec->notice = notice; rec->silent = g_hash_table_lookup(optlist, "-") != NULL; rec->quiet = g_hash_table_lookup(optlist, "quiet") != NULL; rec->name = g_strdup(g_hash_table_lookup(optlist, "name")); level = g_hash_table_lookup(optlist, "level"); rec->level = level == NULL ? MSGLEVEL_CLIENTCRAP : level2bits(level); rec->read_tag = g_input_add(rec->in, G_INPUT_READ, (GInputFunction) sig_exec_input_reader, rec); processes = g_slist_append(processes, rec); if (rec->target == NULL && interactive) rec->target_item = exec_wi_create(active_win, rec); signal_emit("exec new", 1, rec); }
void cmd_setinipw(const char *iniPW, SERVER_REC *server, WI_ITEM_REC *item) { int i=0, pw_len, re_enc=0; char B64digest[50], SHA256digest[35]; char bfKey[512], new_iniKey[KEYBUF_SIZE], old_iniKey[KEYBUF_SIZE], *fptr, *ok_ptr, line_buf[1000], iniPath_new[300]; FILE *h_ini, *h_ini_new; if (!unsetiniFlag) { pw_len=strlen(iniPW); if (pw_len < 1 || (size_t)pw_len > sizeof(new_iniKey)) { printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 No parameters. Usage: /setinipw <sekure_blow.ini_password>"); return; } if (strfcpy(new_iniKey, (char *)iniPW, sizeof(new_iniKey))==NULL) return; ZeroMemory(iniPW, pw_len); pw_len=strlen(new_iniKey); if (pw_len < 8) { printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Password too short, at least 8 characters needed! Usage: /setinipw <sekure_blow.ini_password>"); return; } SHA256_memory(new_iniKey, pw_len, SHA256digest); ZeroMemory(new_iniKey, sizeof(new_iniKey)); for (i=0; i<40872; i++) SHA256_memory(SHA256digest, 32, SHA256digest); htob64(SHA256digest, B64digest, 32); } strcpy(old_iniKey, iniKey); if (unsetiniFlag) strcpy(iniKey, default_iniKey); // unsetinipw -> use default blow.ini key else strcpy(iniKey, B64digest); // this is used for encrypting blow.ini for (i=0; i<30752; i++) SHA256_memory(SHA256digest, 32, SHA256digest); htob64(SHA256digest, B64digest, 32); // this is used to verify the entered password ZeroMemory(SHA256digest, sizeof(SHA256digest)); // re-encrypt blow.ini with new password strcpy(iniPath_new, iniPath); strcat(iniPath_new, "_new"); h_ini_new=fopen(iniPath_new, "w"); h_ini=fopen(iniPath,"r"); if (h_ini && h_ini_new) { while (!feof(h_ini)) { fptr=fgets(line_buf, sizeof(line_buf)-2, h_ini); if (fptr) { ok_ptr=strstr(line_buf, "+OK "); if (ok_ptr) { re_enc=1; strtok(ok_ptr+4, " \n\r"); decrypt_string(old_iniKey, ok_ptr+4, bfKey, strlen(ok_ptr+4)); ZeroMemory(ok_ptr+4, strlen(ok_ptr+4)+1); encrypt_string(iniKey, bfKey, ok_ptr+4, strlen(bfKey)); strcat(line_buf, "\n"); } if (fprintf(h_ini_new, "%s", line_buf) < 0) { ZeroMemory(B64digest, sizeof(B64digest)); ZeroMemory(bfKey, sizeof(bfKey)); ZeroMemory(line_buf, sizeof(line_buf)); ZeroMemory(old_iniKey, sizeof(old_iniKey)); fclose(h_ini); fclose(h_ini_new); remove(iniPath_new); printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH ERROR:\002 Unable to write new blow.ini, probably out of disc space."); return; } } } ZeroMemory(bfKey, sizeof(bfKey)); ZeroMemory(line_buf, sizeof(line_buf)); ZeroMemory(old_iniKey, sizeof(old_iniKey)); fclose(h_ini); fclose(h_ini_new); remove(iniPath); rename(iniPath_new, iniPath); } else return; if (WritePrivateProfileString("FiSH", "ini_password_Hash", B64digest, iniPath) == -1) { ZeroMemory(B64digest, sizeof(B64digest)); 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."); return; } ZeroMemory(B64digest, sizeof(B64digest)); if (re_enc) printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH: Re-encrypted blow.ini\002 with new password."); if (!unsetiniFlag) printtext(server, item!=NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 blow.ini password hash saved."); }
void cmd_setinipw(const char *iniPW, SERVER_REC * server, WI_ITEM_REC * item) { int pw_len, re_enc = 0; char B64digest[50] = { '\0' }; char key[32] = { '\0' }; char hash[32] = { '\0' }; char new_iniKey[KEYBUF_SIZE], old_iniKey[KEYBUF_SIZE], iniPath_new[300]; strcpy(old_iniKey, iniKey); if (iniPW != NULL) { pw_len = strlen(iniPW); if (pw_len < 1 || (size_t) pw_len > sizeof(new_iniKey)) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 No parameters. Usage: /setinipw <sekure_blow.ini_password>"); return; } if (strfcpy(new_iniKey, (char *)iniPW, sizeof(new_iniKey)) == NULL) return; ZeroMemory(iniPW, pw_len); pw_len = strlen(new_iniKey); if (pw_len < 8) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 Password too short, at least 8 characters needed! Usage: /setinipw <sekure_blow.ini_password>"); return; } key_from_password(new_iniKey, key); htob64(key, B64digest, 32); ZeroMemory(new_iniKey, sizeof(new_iniKey)); strcpy(iniKey, B64digest); // this is used for encrypting blow.ini } else { strcpy(iniKey, default_iniKey); // use default blow.ini key } key_hash(key, hash); htob64(hash, B64digest, 32); // this is used to verify the entered password ZeroMemory(hash, sizeof(hash)); ZeroMemory(key, sizeof(key)); // re-encrypt blow.ini with new password strcpy(iniPath_new, iniPath); strcat(iniPath_new, "_new"); re_enc = recrypt_ini_file(iniPath, iniPath_new, old_iniKey); if (re_enc < 0) { ZeroMemory(B64digest, sizeof(B64digest)); ZeroMemory(old_iniKey, sizeof(old_iniKey)); printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH ERROR:\002 Unable to write new blow.ini, probably out of disc space."); return; } else { ZeroMemory(old_iniKey, sizeof(old_iniKey)); } if (setIniValue("FiSH", "ini_password_Hash", B64digest, iniPath) == -1) { ZeroMemory(B64digest, sizeof(B64digest)); 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."); return; } ZeroMemory(B64digest, sizeof(B64digest)); if (re_enc) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH: Re-encrypted blow.ini\002 with new password."); } if (iniPW != NULL) { printtext(server, item != NULL ? window_item_get_target(item) : NULL, MSGLEVEL_CRAP, "\002FiSH:\002 blow.ini password hash saved."); } }