static void dcc_chat_passive(CHAT_DCC_REC *dcc) { IPADDR own_ip; int port; GIOChannel *handle; char host[MAX_IP_LEN]; g_return_if_fail(IS_DCC_CHAT(dcc)); if (dcc->addrstr[0] == '\0' || dcc->starttime != 0 || dcc->handle != NULL) { /* already sent a chat request / already chatting */ return; } handle = dcc_listen(net_sendbuffer_handle(dcc->server->handle), &own_ip, &port); if (handle == NULL) cmd_return_error(CMDERR_ERRNO); dcc->handle = handle; dcc->tagconn = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_listen, dcc); /* Let's send the reply to the other client! */ dcc_ip2str(&own_ip, host); irc_send_cmdv(dcc->server, "PRIVMSG %s :\001DCC CHAT CHAT %s %d %d\001", dcc->nick, host, port, dcc->pasv_id); }
static void sig_dcc_list_print(CHAT_DCC_REC *dcc) { if (!IS_DCC_CHAT(dcc)) return; printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_LIST_LINE_CHAT, dcc->id, "CHAT"); }
/* input function: DCC CHAT - someone tried to connect to our socket */ static void dcc_chat_listen(CHAT_DCC_REC *dcc) { IPADDR ip; GIOChannel *handle; int port; g_return_if_fail(IS_DCC_CHAT(dcc)); /* accept connection */ handle = net_accept(dcc->handle, &ip, &port); if (handle == NULL) return; /* TODO: add paranoia check - see dcc-files.c */ net_disconnect(dcc->handle); g_source_remove(dcc->tagconn); dcc->tagconn = -1; dcc->starttime = time(NULL); dcc->handle = handle; dcc->sendbuf = net_sendbuffer_create(handle, 0); memcpy(&dcc->addr, &ip, sizeof(IPADDR)); net_ip2host(&dcc->addr, dcc->addrstr); dcc->port = port; dcc->tagread = g_input_add(handle, G_INPUT_READ, (GInputFunction) dcc_chat_input, dcc); signal_emit("dcc connected", 1, dcc); }
/* 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 dcc_ctcp_reply_redirect(CHAT_DCC_REC *dcc, const char *msg) { g_return_if_fail(msg != NULL); g_return_if_fail(IS_DCC_CHAT(dcc)); signal_emit("ctcp reply dcc", 6, dcc->server, msg, dcc->nick, "dcc", dcc->mynick, dcc); }
static void dcc_request(CHAT_DCC_REC *dcc) { if (!IS_DCC_CHAT(dcc)) return; printformat(dcc->server, NULL, MSGLEVEL_DCC, ischannel(*dcc->target) ? IRCTXT_DCC_CHAT_CHANNEL : IRCTXT_DCC_CHAT, dcc->id, dcc->addrstr, dcc->port, dcc->target); }
/* Send `data' to dcc chat. */ void dcc_chat_send(CHAT_DCC_REC *dcc, const char *data) { g_return_if_fail(IS_DCC_CHAT(dcc)); g_return_if_fail(dcc->sendbuf != NULL); g_return_if_fail(data != NULL); net_sendbuffer_send(dcc->sendbuf, data, strlen(data)); net_sendbuffer_send(dcc->sendbuf, "\n", 1); }
static void sig_dcc_destroyed(CHAT_DCC_REC *dcc) { if (!IS_DCC_CHAT(dcc)) return; dcc_remove_chat_refs(dcc); if (dcc->sendbuf != NULL) net_sendbuffer_destroy(dcc->sendbuf, FALSE); g_free(dcc->id); }
static void dcc_closed(CHAT_DCC_REC *dcc) { char *sender; if (!IS_DCC_CHAT(dcc)) return; sender = g_strconcat("=", dcc->id, NULL); printformat(dcc->server, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_DISCONNECTED, dcc->id); g_free(sender); }
static void dcc_chat_action(CHAT_DCC_REC *dcc, const char *msg) { char *sender; g_return_if_fail(IS_DCC_CHAT(dcc)); g_return_if_fail(msg != NULL); sender = g_strconcat("=", dcc->id, NULL); if (query_find(NULL, sender) == NULL) completion_last_message_add(sender); signal_emit("message dcc action", 2, dcc, msg); g_free(sender); }
/* DCC CHAT: text received */ static void dcc_chat_msg(CHAT_DCC_REC *dcc, const char *msg) { char *event, *cmd, *ptr; int reply; g_return_if_fail(IS_DCC_CHAT(dcc)); g_return_if_fail(msg != NULL); reply = FALSE; if (g_ascii_strncasecmp(msg, "CTCP_MESSAGE ", 13) == 0) { /* bitchx (and ircii?) sends this */ msg += 13; dcc->mirc_ctcp = FALSE; } else if (g_ascii_strncasecmp(msg, "CTCP_REPLY ", 11) == 0) { /* bitchx (and ircii?) sends this */ msg += 11; reply = TRUE; dcc->mirc_ctcp = FALSE; } else if (*msg == 1) { /* Use the mirc style CTCPs from now on.. */ dcc->mirc_ctcp = TRUE; } /* Handle only DCC CTCPs */ if (*msg != 1) return; /* get ctcp command, remove \001 chars */ event = g_strconcat(reply ? "dcc reply " : "dcc ctcp ", msg+1, NULL); if (event[strlen(event)-1] == 1) event[strlen(event)-1] = '\0'; cmd = event + (reply ? 10 : 9); ptr = strchr(cmd, ' '); if (ptr != NULL) *ptr++ = '\0'; else ptr = ""; cmd = g_ascii_strup(cmd, -1); ascii_strdown(event+9); if (!signal_emit(event, 2, dcc, ptr)) { signal_emit(reply ? "default dcc reply" : "default dcc ctcp", 3, dcc, cmd, ptr); } g_free(cmd); g_free(event); signal_stop(); }
CHAT_DCC_REC *dcc_chat_find_id(const char *id) { GSList *tmp; g_return_val_if_fail(id != NULL, NULL); for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { CHAT_DCC_REC *dcc = tmp->data; if (IS_DCC_CHAT(dcc) && dcc->id != NULL && g_ascii_strcasecmp(dcc->id, id) == 0) return dcc; } return NULL; }
static CHAT_DCC_REC *dcc_chat_find_nick(IRC_SERVER_REC *server, const char *nick) { GSList *tmp; g_return_val_if_fail(nick != NULL, NULL); for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { CHAT_DCC_REC *dcc = tmp->data; if (IS_DCC_CHAT(dcc) && dcc->server == server && g_ascii_strcasecmp(dcc->nick, nick) == 0) return dcc; } return NULL; }
static void sig_dcc_destroyed(CHAT_DCC_REC *dcc) { int i; if (!IS_DCC_CHAT(dcc)) return; for (i = 0; i < queuelist->len; i++) { GSList *qlist = g_ptr_array_index(queuelist, i); for (; qlist != NULL; qlist = qlist->next) { DCC_QUEUE_REC *rec = qlist->data; if (rec != NULL && rec->chat == dcc) rec->chat = NULL; } } }
static void dcc_chat_connect(CHAT_DCC_REC *dcc) { g_return_if_fail(IS_DCC_CHAT(dcc)); if (dcc->addrstr[0] == '\0' || dcc->starttime != 0 || dcc->handle != NULL) { /* already sent a chat request / already chatting */ return; } dcc->handle = dcc_connect_ip(&dcc->addr, dcc->port); if (dcc->handle != NULL) { dcc->tagconn = g_input_add(dcc->handle, G_INPUT_WRITE | G_INPUT_READ, (GInputFunction) sig_chat_connected, dcc); } else { /* error connecting */ signal_emit("dcc error connect", 1, dcc); dcc_destroy(DCC(dcc)); } }
static void sig_dcc_destroyed(CHAT_DCC_REC *dcc) { QUERY_REC *query; char *nick; if (!IS_DCC_CHAT(dcc)) return; nick = g_strconcat("=", dcc->id, NULL); query = query_find(NULL, nick); if (query != NULL) { /* DCC chat closed, close the query with it. */ if (dcc->connection_lost) query->unwanted = TRUE; query_destroy(query); } else { /* remove nick from msg completion since it won't work anymore */ completion_last_message_remove(nick); } g_free(nick); }
/* callback: DCC CHAT - connect finished */ static void sig_chat_connected(CHAT_DCC_REC *dcc) { g_return_if_fail(IS_DCC_CHAT(dcc)); if (net_geterror(dcc->handle) != 0) { /* error connecting */ signal_emit("dcc error connect", 1, dcc); dcc_destroy(DCC(dcc)); return; } /* connect ok. */ g_source_remove(dcc->tagconn); dcc->tagconn = -1; dcc->starttime = time(NULL); dcc->sendbuf = net_sendbuffer_create(dcc->handle, 0); dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_input, dcc); signal_emit("dcc connected", 1, dcc); }
static void dcc_connected(CHAT_DCC_REC *dcc) { char *sender; if (!IS_DCC_CHAT(dcc)) return; sender = g_strconcat("=", dcc->id, NULL); printformat(dcc->server, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_CONNECTED, dcc->id, dcc->addrstr, dcc->port); if (query_find(NULL, sender) == NULL) { int level = settings_get_level("autocreate_query_level"); int autocreate_dccquery = (level & MSGLEVEL_DCCMSGS) != 0; if (!autocreate_dccquery) completion_last_message_add(sender); else irc_query_create(dcc->servertag, sender, TRUE); } g_free(sender); }
static void dcc_chat_msg(CHAT_DCC_REC *dcc, const char *msg) { QUERY_REC *query; char *sender, *freemsg; g_return_if_fail(IS_DCC_CHAT(dcc)); g_return_if_fail(msg != NULL); sender = g_strconcat("=", dcc->id, NULL); query = query_find(NULL, sender); if (settings_get_bool("emphasis")) msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg); else freemsg = NULL; if (query == NULL) completion_last_message_add(sender); signal_emit("message dcc", 2, dcc, msg); g_free_not_null(freemsg); g_free(sender); }
/* DCC CLOSE CHAT <nick> - check only from chat_ids in open DCC chats, the default handler will check from DCC chat requests */ static void cmd_dcc_close(char *data, SERVER_REC *server) { GSList *tmp, *next; char *nick; void *free_arg; int found; g_return_if_fail(data != NULL); if (g_ascii_strncasecmp(data, "CHAT ", 5) != 0 || !cmd_get_params(data, &free_arg, 2, NULL, &nick)) return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); found = FALSE; for (tmp = dcc_conns; tmp != NULL; tmp = next) { CHAT_DCC_REC *dcc = tmp->data; next = tmp->next; if (IS_DCC_CHAT(dcc) && dcc->id != NULL && g_ascii_strcasecmp(dcc->id, nick) == 0) { found = TRUE; if (!dcc_is_connected(dcc) && IS_IRC_SERVER(server)) dcc_reject(DCC(dcc), IRC_SERVER(server)); else { /* don't send DCC REJECT after DCC chat is already open */ dcc_close(DCC(dcc)); } } } if (found) signal_stop(); cmd_params_free(free_arg); }
static void dcc_chat_ctcp(CHAT_DCC_REC *dcc, const char *cmd, const char *data) { g_return_if_fail(IS_DCC_CHAT(dcc)); signal_emit("message dcc ctcp", 3, dcc, cmd, data); }