static void event_privmsg(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { char *params, *target, *msg, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); if (nick == NULL) nick = server->real_address; if (addr == NULL) addr = ""; if (fe_channel_is_opchannel(server, target)) { /* Hybrid 6 feature, send msg to all ops in channel */ target = (char *)fe_channel_skip_prefix(server, target); recoded = recode_in(SERVER(server), msg, target); signal_emit("message irc op_public", 5, server, recoded, nick, addr, get_visible_target(server, target)); } else { recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick); signal_emit(server_ischannel(SERVER(server), target) ? "message public" : "message private", 5, server, recoded, nick, addr, get_visible_target(server, target)); } g_free(params); g_free(recoded); }
static void channel_change_topic(IRC_SERVER_REC *server, const char *channel, const char *topic, const char *setby, time_t settime) { CHANNEL_REC *chanrec; char *recoded = NULL; chanrec = channel_find(SERVER(server), channel); if (chanrec == NULL) return; /* the topic may be send out encoded, so we need to recode it back or /topic <tab> will not work properly */ recoded = recode_in(SERVER(server), topic, channel); if (topic != NULL) { g_free_not_null(chanrec->topic); chanrec->topic = recoded == NULL ? NULL : g_strdup(recoded); } g_free(recoded); g_free_not_null(chanrec->topic_by); chanrec->topic_by = g_strdup(setby); chanrec->topic_time = settime; signal_emit("channel topic changed", 1, chanrec); }
/* input function: DCC CHAT received some data.. */ void dcc_chat_input(CHAT_DCC_REC *dcc) { char *str; int ret; g_return_if_fail(IS_DCC_CHAT(dcc)); do { ret = net_sendbuffer_receive_line(dcc->sendbuf, &str, 1); if (ret == -1) { /* connection lost */ dcc->connection_lost = TRUE; dcc_close(DCC(dcc)); break; } if (ret > 0) { char *recoded; dcc->transfd += ret; recoded = recode_in(SERVER(dcc->server), str, dcc->nick); signal_emit("dcc chat message", 2, dcc, recoded); g_free(recoded); } } while (ret > 0); }
static void send_message(SERVER_REC *server, const char *target, const char *msg, int target_type) { LmMessage *lmsg; char *str, *recoded; if (!IS_XMPP_SERVER(server)) return; g_return_if_fail(target != NULL); g_return_if_fail(msg != NULL); if (target_type == SEND_TARGET_CHANNEL) { recoded = xmpp_recode_out(target); lmsg = lm_message_new_with_sub_type(recoded, LM_MESSAGE_TYPE_MESSAGE, LM_MESSAGE_SUB_TYPE_GROUPCHAT); } else { str = rosters_resolve_name(XMPP_SERVER(server), target); recoded = xmpp_recode_out(str != NULL ? str : target); g_free(str); lmsg = lm_message_new_with_sub_type(recoded, LM_MESSAGE_TYPE_MESSAGE, LM_MESSAGE_SUB_TYPE_CHAT); } g_free(recoded); /* ugly from irssi: recode the sent message back */ str = recode_in(server, msg, target); recoded = xmpp_recode_out(str); g_free(str); lm_message_node_add_child(lmsg->node, "body", recoded); g_free(recoded); signal_emit("xmpp send message", 2, server, lmsg); lm_message_unref(lmsg); }
static void event_quit(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { char *recoded; g_return_if_fail(data != NULL); if (*data == ':') data++; /* quit message */ recoded = recode_in(SERVER(server), data, nick); signal_emit("message quit", 4, server, nick, addr, recoded); g_free(recoded); }
static void event_privmsg(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { char *params, *target, *msg, *recoded; char *chantypes; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); if (nick == NULL) nick = server->real_address; if (addr == NULL) addr = ""; if ( (*target == '@' || *target == '+' || *target == '%') && ischannel(target[1]) && server && server->prefix[(unsigned char)*target] && ( (chantypes = g_hash_table_lookup(server->isupport, "CHANTYPES")) || (chantypes = "#&"), !strchr(chantypes, *target) ) ) { /* Hybrid 6 feature, send msg to all ops/voiced in channel */ recoded = recode_in(SERVER(server), msg, target+1); signal_emit(*target == '%' ? "message irc halfop_public" : *target == '+' ? "message irc voice_public" : "message irc op_public", 5, server, recoded, nick, addr, get_visible_target(server, target+1)); } else { recoded = recode_in(SERVER(server), msg, ischannel(*target) ? target : nick); signal_emit(ischannel(*target) ? "message public" : "message private", 5, server, recoded, nick, addr, get_visible_target(server, target)); } g_free(params); g_free(recoded); }
static void event_whois_away(IRC_SERVER_REC *server, const char *data) { char *params, *nick, *awaymsg, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 3, NULL, &nick, &awaymsg); recoded = recode_in(SERVER(server), awaymsg, nick); printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOIS_AWAY, nick, recoded); g_free(params); g_free(recoded); }
static void ctcp_action(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr, const char *target) { char *recoded; g_return_if_fail(data != NULL); recoded = recode_in(SERVER(server), data, target); signal_emit("message irc action", 5, server, recoded, nick, addr, get_visible_target(server, target)); g_free(recoded); }
static void event_whowas(IRC_SERVER_REC *server, const char *data) { char *params, *nick, *user, *host, *realname, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname); recoded = recode_in(SERVER(server), realname, nick); printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOWAS, nick, user, host, recoded); g_free(params); g_free(recoded); }
static void event_topic(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { char *params, *channel, *topic, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &topic); recoded = recode_in(SERVER(server), topic, channel); signal_emit("message topic", 5, server, get_visible_target(server, channel), recoded, nick, addr); g_free(params); g_free(recoded); }
static void event_topic_get(IRC_SERVER_REC *server, const char *data) { const char *channel; char *params, *topic, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 3, NULL, &channel, &topic); recoded = recode_in(SERVER(server), topic, channel); channel = get_visible_target(server, channel); printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_TOPIC, channel, recoded); g_free(params); g_free(recoded); }
static void event_kick(IRC_SERVER_REC *server, const char *data, const char *kicker, const char *addr) { char *params, *channel, *nick, *reason, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 3 | PARAM_FLAG_GETREST, &channel, &nick, &reason); recoded = recode_in(SERVER(server), reason, channel); signal_emit("message kick", 6, server, get_visible_target(server, channel), nick, kicker, addr, recoded); g_free(params); g_free(recoded); }
static void print_event_received(IRC_SERVER_REC *server, const char *data, const char *nick, int target_param) { char *target, *args, *ptr, *ptr2, *recoded; int format; g_return_if_fail(data != NULL); /* skip first param, it's always our nick */ ptr = strchr(data, ' '); if (ptr == NULL) return; ptr++; if (!target_param || *ptr == ':' || (ptr2 = strchr(ptr, ' ')) == NULL) target = NULL; else { /* target parameter expected and present */ target = g_strndup(ptr, (int) (ptr2-ptr)); } /* param1 param2 ... :last parameter */ if (*ptr == ':') { /* only one parameter */ args = g_strdup(ptr+1); } else { args = g_strdup(ptr); ptr = strstr(args, " :"); if (ptr != NULL) g_memmove(ptr+1, ptr+2, strlen(ptr+1)); } recoded = recode_in(SERVER(server), args, NULL); format = nick == NULL || server->real_address == NULL || strcmp(nick, server->real_address) == 0 ? IRCTXT_DEFAULT_EVENT : IRCTXT_DEFAULT_EVENT_SERVER; printformat(server, target, MSGLEVEL_CRAP, format, nick, recoded, current_server_event); g_free(recoded); g_free(args); g_free(target); }
static void sig_message_own_public(SERVER_REC *server, char *msg, char *target) { WINDOW_REC *window; CHANNEL_REC *channel; char *nick, *nickmode, *freemsg = NULL, *recoded; gboolean print_channel; g_return_if_fail(server != NULL); g_return_if_fail(msg != NULL); g_return_if_fail(target != NULL); if (!IS_XMPP_SERVER(server)) return; channel = channel_find(server, target); if (channel == NULL || channel->ownnick == NULL) return; nick = channel->ownnick->nick; nickmode = channel_get_nickmode(CHANNEL(channel), nick); window = (channel == NULL) ? NULL : window_item_window((WI_ITEM_REC *)channel); print_channel = (window == NULL || window->active != (WI_ITEM_REC *) channel); if (!print_channel && settings_get_bool("print_active_channel") && window != NULL && g_slist_length(window->items) > 1) print_channel = TRUE; if (settings_get_bool("emphasis")) msg = freemsg = expand_emphasis((WI_ITEM_REC *)channel, msg); /* ugly from irssi: recode the sent message back for printing */ recoded = recode_in(SERVER(server), msg, target); if (!print_channel) printformat_module(CORE_MODULE_NAME, server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT, TXT_OWN_MSG, nick, recoded, nickmode); else printformat_module(CORE_MODULE_NAME, server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT, TXT_OWN_MSG_CHANNEL, nick, target, recoded, nickmode); g_free(recoded); g_free(nickmode); g_free_not_null(freemsg); signal_stop(); /* emit signal for chat-completion */ }
static void event_notice(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { char *params, *target, *msg, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); recoded = recode_in(SERVER(server), msg, target); if (nick == NULL) { nick = server->real_address == NULL ? server->connrec->address : server->real_address; } signal_emit("message irc notice", 5, server, recoded, nick, addr, get_visible_target(server, target)); g_free(params); g_free(recoded); }
static void event_whois_channels(IRC_SERVER_REC *server, const char *data) { char *params, *nick, *chans, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 3, NULL, &nick, &chans); /* sure - we COULD print the channel names as-is, but since the colors, bolds, etc. are mostly just to fool people, I think we should show the channel names as they REALLY are so they could even be joined without any extra tricks. */ chans = show_lowascii(chans); if (settings_get_bool("whois_hide_safe_channel_id")) hide_safe_channel_id(server, chans); recoded = recode_in(SERVER(server), chans, nick); printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOIS_CHANNELS, nick, recoded); g_free(chans); g_free(params); g_free(recoded); }
static void event_who(IRC_SERVER_REC *server, const char *data) { char *params, *nick, *channel, *user, *host, *stat, *realname, *hops; char *serv, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 8, NULL, &channel, &user, &host, &serv, &nick, &stat, &realname); /* split hops/realname */ hops = realname; while (*realname != '\0' && *realname != ' ') realname++; if (*realname == ' ') *realname++ = '\0'; recoded = recode_in(SERVER(server), realname, nick); printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHO, channel, nick, stat, hops, user, host, recoded, serv); g_free(params); g_free(recoded); }
static void event_away(IRC_SERVER_REC *server, const char *data) { char *params, *nick, *awaymsg, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 3, NULL, &nick, &awaymsg); recoded = recode_in(SERVER(server), awaymsg, nick); if (!settings_get_bool("show_away_once") || last_away_nick == NULL || g_strcasecmp(last_away_nick, nick) != 0 || last_away_msg == NULL || g_strcasecmp(last_away_msg, awaymsg) != 0) { /* don't show the same away message from the same nick all the time */ g_free_not_null(last_away_nick); g_free_not_null(last_away_msg); last_away_nick = g_strdup(nick); last_away_msg = g_strdup(awaymsg); printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_NICK_AWAY, nick, recoded); } g_free(params); g_free(recoded); }
/* * Decrypt a base64 cipher text (using key for target) */ int FiSH_decrypt(const SERVER_REC * serverRec, char *msg_ptr, const char *target, GString* decrypted_msg) { char contactName[CONTACT_SIZE] = ""; char theKey[KEYBUF_SIZE] = ""; char bf_dest[1000] = ""; char myMark[20] = ""; char *recoded; int msg_len, i, mark_broken_block = 0, action_found = 0, markPos; if (IsNULLorEmpty(msg_ptr) || decrypted_msg == NULL || IsNULLorEmpty(target)) return 0; if (settings_get_bool("process_incoming") == 0) return 0; if (strncmp(msg_ptr, "+OK ", 4) == 0) msg_ptr += 4; // TODO: Maybe remove this? else if (strncmp(msg_ptr, "mcps ", 5) == 0) msg_ptr += 5; else return 0; // don't process, blowcrypt-prefix not found // Verify base64 string msg_len = strlen(msg_ptr); if ((strspn(msg_ptr, B64) != (size_t) msg_len) || (msg_len < 12)) return 0; if (getIniSectionForContact(serverRec, target, contactName) == FALSE) return 0; if (getContactKey(contactName, theKey) == FALSE) return 0; // usually a received message does not exceed 512 chars, but we want to prevent evil buffer overflow if (msg_len >= (int)(sizeof(bf_dest) * 1.5)) msg_ptr[(int)(sizeof(bf_dest) * 1.5) - 20] = '\0'; // block-align blowcrypt strings if truncated by IRC server (each block is 12 chars long) // such a truncated block is destroyed and not needed anymore if (msg_len != (msg_len / 12) * 12) { msg_len = (msg_len / 12) * 12; msg_ptr[msg_len] = '\0'; strncpy(myMark, settings_get_str("mark_broken_block"), sizeof(myMark)); if (*myMark == '\0' || isNoChar(*myMark)) mark_broken_block = 0; else mark_broken_block = 1; } decrypt_string(theKey, msg_ptr, bf_dest, msg_len); ZeroMemory(theKey, KEYBUF_SIZE); if (*bf_dest == '\0') return 0; // don't process, decrypted msg is bad // recode message again, last time it was the encrypted message... if (settings_get_bool("recode") && serverRec != NULL) { recoded = recode_in(serverRec, bf_dest, target); if (recoded) { strncpy(bf_dest, recoded, sizeof(bf_dest)); ZeroMemory(recoded, strlen(recoded)); g_free(recoded); } } i = 0; while (bf_dest[i] != 0x0A && bf_dest[i] != 0x0D && bf_dest[i] != '\0') i++; bf_dest[i] = '\0'; // in case of wrong key, decrypted message might have control characters -> cut message if (strncmp(bf_dest, "\001ACTION ", 8) == 0) { // ACTION message found if (bf_dest[i - 1] == '\001') bf_dest[i - 1] = '\0'; // remove 0x01 control character action_found = 1; } // append broken-block-mark? if (mark_broken_block) strcat(bf_dest, myMark); // append crypt-mark? strncpy(myMark, settings_get_str("mark_encrypted"), sizeof(myMark)); if (*myMark != '\0') { markPos = settings_get_int("mark_position"); if (markPos == 0 || action_found) strcat(bf_dest, myMark); // append mark at the end (default for ACTION messages) else { // prefix mark i = strlen(myMark); memmove(bf_dest + i, bf_dest, strlen(bf_dest) + 1); strncpy(bf_dest, myMark, i); } } g_string_assign(decrypted_msg, bf_dest); ZeroMemory(bf_dest, sizeof(bf_dest)); return 1; }
/* * Decrypt a base64 cipher text (using key for target) */ int FiSH_decrypt(const SERVER_REC *server, char *msg_ptr, char *msg_bak, const char *target) { char contactName[CONTACT_SIZE]="", theKey[KEYBUF_SIZE]="", bf_dest[1000]=""; char myMark[20]="", markPos[20]="", *recoded; int msg_len, i, mark_broken_block=0, action_found=0; if (IsNULLorEmpty(msg_ptr) || msg_bak==NULL || IsNULLorEmpty(target)) return 0; if (GetBlowIniSwitch("FiSH", "process_incoming", "1") == 0) return 0; if (strncmp(msg_ptr, "+OK ", 4)==0) msg_ptr += 4; else if (strncmp(msg_ptr, "mcps ", 5)==0) msg_ptr += 5; else return 0; // don't process, blowcrypt-prefix not found // Verify base64 string msg_len=strlen(msg_ptr); if ((strspn(msg_ptr, B64) != (size_t)msg_len) || (msg_len < 12)) return 0; if (GetIniSectionForContact(server, target, contactName)==FALSE) return 0; if (LoadKeyForContact(contactName, theKey)==FALSE) return 0; // usually a received message does not exceed 512 chars, but we want to prevent evil buffer overflow if (msg_len >= (int)(sizeof(bf_dest)*1.5)) msg_ptr[(int)(sizeof(bf_dest)*1.5)-20]='\0'; // block-align blowcrypt strings if truncated by IRC server (each block is 12 chars long) // such a truncated block is destroyed and not needed anymore if (msg_len != (msg_len/12)*12) { msg_len=(msg_len/12)*12; msg_ptr[msg_len]='\0'; GetPrivateProfileString("FiSH", "mark_broken_block", " \002&\002", myMark, sizeof(myMark), iniPath); if (*myMark=='\0' || isNoChar(*myMark)) mark_broken_block=0; else mark_broken_block=1; } decrypt_string(theKey, msg_ptr, bf_dest, msg_len); ZeroMemory(theKey, KEYBUF_SIZE); if (*bf_dest=='\0') return 0; // don't process, decrypted msg is bad #ifdef FiSH_USE_IRSSI_RECODE // recode message again, last time it was the encrypted message... if (settings_get_bool("recode") && server!=NULL) { recoded = recode_in(server, bf_dest, target); if (recoded) { strncpy(bf_dest, recoded, sizeof(bf_dest)); ZeroMemory(recoded, strlen(recoded)); g_free(recoded); } } #endif i=0; while (bf_dest[i] != 0x0A && bf_dest[i] != 0x0D && bf_dest[i] != '\0') i++; bf_dest[i]='\0'; // in case of wrong key, decrypted message might have control characters -> cut message if (strncmp(bf_dest, "\001ACTION ", 8)==0) { // ACTION message found if (bf_dest[i-1] == '\001') bf_dest[i-1] = '\0'; // remove 0x01 control character action_found = 1; } // append broken-block-mark? if (mark_broken_block) strcat(bf_dest, myMark); // append crypt-mark? if (GetBlowIniSwitch(contactName, "mark_encrypted", "1") != 0) { GetPrivateProfileString("FiSH", "mark_encrypted", "", myMark, sizeof(myMark), iniPath); // global setting if (*myMark != '\0') { GetPrivateProfileString("FiSH", "mark_position", "0", markPos, sizeof(markPos), iniPath); if (*markPos=='0' || action_found) strcat(bf_dest, myMark); // append mark at the end (default for ACTION messages) else { // prefix mark i=strlen(myMark); memmove(bf_dest+i, bf_dest, strlen(bf_dest)+1); strncpy(bf_dest, myMark, i); } } } strcpy(msg_bak, bf_dest); // copy decrypted message back (overwriting the base64 cipher text) ZeroMemory(bf_dest, sizeof(bf_dest)); return 1; }