static int dcc_ctcp_resume_parse(int type, const char *data, const char *nick, FILE_DCC_REC **dcc, uoff_t *size, int *pasv_id) { char **params; int paramcount, fileparams; int port; /* RESUME|ACCEPT <file name> <port> <size> */ /* RESUME|ACCEPT <file name> 0 <size> <id> (passive protocol) */ params = g_strsplit(data, " ", -1); paramcount = strarray_length(params); if (paramcount < 3) return 0; fileparams = get_file_params_count_resume(params, paramcount); if (paramcount >= fileparams + 2) { port = atoi(params[fileparams]); *size = str_to_uofft(params[fileparams+1]); *pasv_id = ((port == 0) && (paramcount == fileparams + 3)) ? atoi(params[fileparams+2]) : -1; *dcc = dcc_resume_find(type, nick, port); g_strfreev(params); /* If the ID is different then the DCC cannot be resumed */ return ((*dcc != NULL) && ((*dcc)->pasv_id == *pasv_id)); } g_strfreev(params); return FALSE; }
/* DCC SERVER: text received */ static void dcc_server_msg(SERVER_DCC_REC *dcc, const char *msg) { g_return_if_fail(IS_DCC_SERVER(dcc)); g_return_if_fail(msg != NULL); /* Check for CHAT protocol */ if (g_strncasecmp(msg, "100 ", 4) == 0) { msg += 4; /* Check if this server is accepting chat requests.*/ if (dcc->accept_chat) { /* Connect and start DCC Chat */ char *str; CHAT_DCC_REC *dccchat = dcc_chat_create(dcc->server, NULL, msg, "chat"); dccchat->starttime = time(NULL); dccchat->handle = dcc->handle; dccchat->sendbuf = net_sendbuffer_create(dccchat->handle, 0); memcpy(&dccchat->addr, &dcc->addr, sizeof(IPADDR)); net_ip2host(&dccchat->addr, dccchat->addrstr); dccchat->port = dcc->port; dccchat->tagread = g_input_add(dccchat->handle, G_INPUT_READ, (GInputFunction) dcc_chat_input, dccchat); dcc->connection_established = 1; signal_emit("dcc connected", 1, dccchat); str = g_strdup_printf("101 %s\n", (dccchat->server) ? dccchat->server->nick : "??"); net_sendbuffer_send(dccchat->sendbuf, str, strlen(str)); g_free(str); } } /* Check for FSERVE protocol */ if (g_strncasecmp(msg, "110 ", 4) == 0) { msg += 4; /* Check if this server is accepting fserve requests.*/ if (dcc->accept_fserve) { /* TODO - Connect and start DCC Fserve */ } } /* Check for SEND protocol */ if (g_strncasecmp(msg, "120 ", 4) == 0) { msg += 4; /* Check if this server is accepting send requests.*/ if (dcc->accept_send) { /* Connect and start DCC Send */ GET_DCC_REC *dccget; char **params, *fname, *nick; int paramcount, len, quoted = FALSE; uoff_t size; /* 120 clientnickname filesize filename */ params = g_strsplit(msg, " ", -1); paramcount = strarray_length(params); if (paramcount < 3) { g_strfreev(params); signal_stop(); return; } nick = params[0]; size = str_to_uofft(params[1]); fname = g_strjoinv(" ", ¶ms[2]); len = strlen(fname); if (len > 1 && *fname == '"' && fname[len-1] == '"') { /* "file name" - MIRC sends filenames with spaces like this */ fname[len-1] = '\0'; g_memmove(fname, fname+1, len); quoted = TRUE; } dccget = dcc_get_create(dcc->server, NULL, nick, fname); dccget->handle = dcc->handle; dccget->target = g_strdup(dcc->server ? dcc->server->nick : "??"); memcpy(&dccget->addr, &dcc->addr, sizeof(dcc->addr)); if (dccget->addr.family == AF_INET) { net_ip2host(&dccget->addr, dccget->addrstr); } else { /* with IPv6, show it to us as it was sent */ memcpy(dccget->addrstr, dcc->addrstr, sizeof(dccget->addrstr)); } dccget->port = dcc->port; dccget->size = size; dccget->file_quoted = quoted; dccget->from_dccserver = 1; dcc->connection_established = 1; signal_emit("dcc request", 2, dccget, dccget->addrstr); g_strfreev(params); g_free(fname); } } signal_stop(); }
/* CTCP: DCC SEND */ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr, const char *target, CHAT_DCC_REC *chat) { GET_DCC_REC *dcc; SEND_DCC_REC *temp_dcc; IPADDR ip; char *address, **params, *fname; int paramcount, fileparams; int port, len, quoted = FALSE; uoff_t size; int p_id = -1; int passive = FALSE; /* SEND <file name> <address> <port> <size> [...] */ /* SEND <file name> <address> 0 <size> <id> (DCC SEND passive protocol) */ params = g_strsplit(data, " ", -1); paramcount = strarray_length(params); if (paramcount < 4) { signal_emit("dcc error ctcp", 5, "SEND", data, nick, addr, target); g_strfreev(params); return; } fileparams = get_file_params_count(params, paramcount); address = g_strdup(params[fileparams]); dcc_str2ip(address, &ip); port = atoi(params[fileparams+1]); size = str_to_uofft(params[fileparams+2]); /* If this DCC uses passive protocol then store the id for later use. */ if (paramcount == fileparams + 4) { p_id = atoi(params[fileparams+3]); passive = TRUE; } fname = get_file_name(params, fileparams); g_strfreev(params); len = strlen(fname); if (len > 1 && *fname == '"' && fname[len-1] == '"') { /* "file name" - MIRC sends filenames with spaces like this */ fname[len-1] = '\0'; g_memmove(fname, fname+1, len); quoted = TRUE; } if (passive && port != 0) { /* This is NOT a DCC SEND request! This is a reply to our passive request. We MUST check the IDs and then connect to the remote host. */ temp_dcc = DCC_SEND(dcc_find_request(DCC_SEND_TYPE, nick, fname)); if (temp_dcc != NULL && p_id == temp_dcc->pasv_id) { temp_dcc->target = g_strdup(target); temp_dcc->port = port; temp_dcc->size = size; temp_dcc->file_quoted = quoted; memcpy(&temp_dcc->addr, &ip, sizeof(IPADDR)); if (temp_dcc->addr.family == AF_INET) net_ip2host(&temp_dcc->addr, temp_dcc->addrstr); else { /* with IPv6, show it to us as it was sent */ strocpy(temp_dcc->addrstr, address, sizeof(temp_dcc->addrstr)); } /* This new signal is added to let us invoke dcc_send_connect() which is found in dcc-send.c */ signal_emit("dcc reply send pasv", 1, temp_dcc); g_free(address); g_free(fname); return; } else if (temp_dcc != NULL && p_id != temp_dcc->pasv_id) { /* IDs don't match... remove the old DCC SEND and return */ dcc_destroy(DCC(temp_dcc)); g_free(address); g_free(fname); return; } } dcc = DCC_GET(dcc_find_request(DCC_GET_TYPE, nick, fname)); if (dcc != NULL) dcc_destroy(DCC(dcc)); /* remove the old DCC */ dcc = dcc_get_create(server, chat, nick, fname); dcc->target = g_strdup(target); if (passive && port == 0) dcc->pasv_id = p_id; /* Assign the ID to the DCC */ memcpy(&dcc->addr, &ip, sizeof(ip)); if (dcc->addr.family == AF_INET) net_ip2host(&dcc->addr, dcc->addrstr); else { /* with IPv6, show it to us as it was sent */ strocpy(dcc->addrstr, address, sizeof(dcc->addrstr)); } dcc->port = port; dcc->size = size; dcc->file_quoted = quoted; signal_emit("dcc request", 2, dcc, addr); g_free(address); g_free(fname); }