/* handle receiving DCC - GET/RESUME. */ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func, DCC_GET_FUNC pasv_accept_func) { GET_DCC_REC *dcc; GSList *tmp, *next; char *nick, *arg, *fname; void *free_arg; int found; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST | PARAM_FLAG_STRIP_TRAILING_WS, &nick, &arg)) return; if (*nick == '\0') { dcc = DCC_GET(dcc_find_request_latest(DCC_GET_TYPE)); if (dcc != NULL) { if (!dcc_is_passive(dcc)) accept_func(dcc); else pasv_accept_func(dcc); } cmd_params_free(free_arg); return; } fname = cmd_get_quoted_param(&arg); found = FALSE; for (tmp = dcc_conns; tmp != NULL; tmp = next) { GET_DCC_REC *dcc = tmp->data; next = tmp->next; if (IS_DCC_GET(dcc) && g_ascii_strcasecmp(dcc->nick, nick) == 0 && (dcc_is_waiting_user(dcc) || dcc->from_dccserver) && (*fname == '\0' || g_strcmp0(dcc->arg, fname) == 0)) { found = TRUE; if (!dcc_is_passive(dcc)) accept_func(dcc); else pasv_accept_func(dcc); } } if (!found) signal_emit("dcc error get not found", 1, nick); cmd_params_free(free_arg); }
DCC_REC *dcc_find_request_latest(int type) { DCC_REC *latest; GSList *tmp; latest = NULL; for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { DCC_REC *dcc = tmp->data; if (dcc->type == type && dcc_is_waiting_user(dcc)) latest = dcc; } return latest; }
/* handle receiving DCC - GET/RESUME. */ void cmd_dcc_receive(const char *data, DCC_GET_FUNC accept_func) { GET_DCC_REC *dcc; GSList *tmp, *next; char *nick, *fname; void *free_arg; int found; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &fname)) return; if (*nick == '\0') { dcc = DCC_GET(dcc_find_request_latest(DCC_GET_TYPE)); if (dcc != NULL) accept_func(dcc); cmd_params_free(free_arg); return; } found = FALSE; for (tmp = dcc_conns; tmp != NULL; tmp = next) { GET_DCC_REC *dcc = tmp->data; next = tmp->next; if (IS_DCC_GET(dcc) && dcc_is_waiting_user(dcc) && g_strcasecmp(dcc->nick, nick) == 0 && (*fname == '\0' || strcmp(dcc->arg, fname) == 0)) { found = TRUE; accept_func(dcc); } } if (!found) signal_emit("dcc error get not found", 1, nick); 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); }