Пример #1
0
/* 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;
        IPADDR ip;
	char **params, *fname;
	int paramcount, fileparams;
	int port, len, quoted = FALSE;
        long size;

	/* SEND <file name> <address> <port> <size> [...] */
	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);

	dcc_str2ip(params[fileparams], &ip);
	port = atoi(params[fileparams+1]);
	size = atol(params[fileparams+2]);

	params[fileparams] = NULL;
        fname = g_strjoinv(" ", params);
	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;
	}

	dcc = DCC_GET(dcc_find_request(DCC_GET_TYPE, nick, fname));
	if (dcc != NULL) {
		/* same DCC request offered again, remove the old one */
		dcc_destroy(DCC(dcc));
	}

	dcc = dcc_get_create(server, chat, nick, fname);
	dcc->target = g_strdup(target);
        memcpy(&dcc->addr, &ip, sizeof(ip));
	net_ip2host(&dcc->addr, dcc->addrstr);
	dcc->port = port;
	dcc->size = size;
        dcc->file_quoted = quoted;

	signal_emit("dcc request", 2, dcc, addr);

        g_free(fname);
}
Пример #2
0
/* CTCP REPLY: REJECT */
static void ctcp_reply_dcc_reject(IRC_SERVER_REC *server, const char *data,
				  const char *nick, const char *addr,
				  DCC_REC *chat)
{
        DCC_REC *dcc;

	/* default REJECT handler checks args too -
	   we don't care about it in DCC chats. */
	if (g_ascii_strncasecmp(data, "CHAT", 4) == 0 &&
	    (data[4] == '\0' || data[4] == ' ')) {
		dcc = dcc_find_request(DCC_CHAT_TYPE, nick, NULL);
		if (dcc != NULL) dcc_close(dcc);
		signal_stop();
	}
}
Пример #3
0
/* CTCP REPLY: REJECT */
static void ctcp_reply_dcc_reject(IRC_SERVER_REC *server, const char *data,
				  const char *nick, const char *addr,
				  DCC_REC *chat)
{
        DCC_REC *dcc;
	char *type, *args;

	type = g_strdup(data);
	args = strchr(type, ' ');
        if (args != NULL) *args++ = '\0'; else args = "";

	dcc = dcc_find_request(dcc_str2type(type), nick, args);
	if (dcc != NULL) dcc_close(dcc);

        g_free(type);
}
Пример #4
0
/* 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);
}
Пример #5
0
/* CTCP: DCC CHAT */
static void ctcp_msg_dcc_chat(IRC_SERVER_REC *server, const char *data,
			      const char *nick, const char *addr,
			      const char *target, CHAT_DCC_REC *chat)
{
        CHAT_DCC_REC *dcc;
	char **params;
	int paramcount;
        int passive, autoallow = FALSE;

        /* CHAT <unused> <address> <port> */
	/* CHAT <unused> <address> 0 <id> (DCC CHAT passive protocol) */
	params = g_strsplit(data, " ", -1);
	paramcount = g_strv_length(params);

	if (paramcount < 3) {
		g_strfreev(params);
		return;
	}
	passive = paramcount == 4 && g_strcmp0(params[2], "0") == 0;

	if (nick == NULL)
		nick = "";

	dcc = DCC_CHAT(dcc_find_request(DCC_CHAT_TYPE, nick, NULL));
	if (dcc != NULL) {
		if (dcc_is_listening(dcc)) {
			/* we requested dcc chat, they requested
			   dcc chat from us .. allow it. */
			dcc_destroy(DCC(dcc));
			autoallow = TRUE;
		} else if (!dcc_is_passive(dcc)) {
			/* we already have one dcc chat request
			   from this nick, remove it. */
			dcc_destroy(DCC(dcc));
		} else if (passive) {
			if (dcc->pasv_id != atoi(params[3])) {
				/* IDs don't match! */
				dcc_destroy(DCC(dcc));
			} else {
				/* IDs are ok! Update address and port and
				   connect! */
				dcc->target = g_strdup(target);
				dcc->port = atoi(params[2]);
				dcc_str2ip(params[1], &dcc->addr);
				net_ip2host(&dcc->addr, dcc->addrstr);

				dcc_chat_connect(dcc);
				g_strfreev(params);
				return;
			}
		}
	}

	dcc = dcc_chat_create(server, chat, nick, params[0]);
	if (dcc == NULL) {
		g_strfreev(params);
		g_warn_if_reached();
		return;
	}
	dcc->target = g_strdup(target);
	dcc->port = atoi(params[2]);

	if (passive)
		dcc->pasv_id = atoi(params[3]);

	dcc_str2ip(params[1], &dcc->addr);
	net_ip2host(&dcc->addr, dcc->addrstr);

	signal_emit("dcc request", 2, dcc, addr);

	if (autoallow || DCC_CHAT_AUTOACCEPT(dcc, server, nick, addr)) {
		if (passive) {
			/* Passive DCC... let's set up a listening socket
			   and send reply back */
			dcc_chat_passive(dcc);
		} else {
			dcc_chat_connect(dcc);
		}
	}
	g_strfreev(params);
}
Пример #6
0
static int dcc_send_one_file(int queue, const char *target, const char *fname,
			     IRC_SERVER_REC *server, CHAT_DCC_REC *chat)
{
	struct stat st;
	char *str;
	char host[MAX_IP_LEN];
	int hfile, port;
        SEND_DCC_REC *dcc;
	IPADDR own_ip;
        GIOChannel *handle;

	if (dcc_find_request(DCC_SEND_TYPE, target, fname)) {
	        signal_emit("dcc error send exists", 2, target, fname);
		return FALSE;
	}

        str = dcc_send_get_file(fname);
	hfile = open(str, O_RDONLY);
	g_free(str);

	if (hfile == -1) {
		signal_emit("dcc error file open", 3, target, fname,
			    GINT_TO_POINTER(errno));
		return FALSE;
	}

	if (fstat(hfile, &st) < 0) {
		g_warning("fstat() failed: %s", strerror(errno));
		close(hfile);
		return FALSE;
	}

        /* start listening */
	handle = dcc_listen(chat != NULL ? chat->handle :
			    net_sendbuffer_handle(server->handle),
			    &own_ip, &port);
	if (handle == NULL) {
		close(hfile);
		g_warning("dcc_listen() failed: %s", strerror(errno));
		return FALSE;
	}

	fname = g_basename(fname);

	/* Replace all the spaces with underscore so that lesser
	   intellgent clients can communicate.. */
	if (!settings_get_bool("dcc_send_replace_space_with_underscore"))
		str = NULL;
	else {
		str = g_strdup(fname);
		g_strdelimit(str, " ", '_');
		fname = str;
	}

	dcc = dcc_send_create(server, chat, target, fname);
	g_free(str);

	dcc->handle = handle;
	dcc->port = port;
	dcc->size = st.st_size;
	dcc->fhandle = hfile;
	dcc->queue = queue;
        dcc->file_quoted = strchr(fname, ' ') != NULL;
	dcc->tagconn = g_input_add(handle, G_INPUT_READ,
				   (GInputFunction) dcc_send_connected, dcc);

	/* send DCC request */
	signal_emit("dcc request send", 1, dcc);

	dcc_ip2str(&own_ip, host);
	str = g_strdup_printf(dcc->file_quoted ?
			      "DCC SEND \"%s\" %s %d %"PRIuUOFF_T :
			      "DCC SEND %s %s %d %"PRIuUOFF_T,
			      dcc->arg, host, port, dcc->size);
	dcc_ctcp_message(server, target, chat, FALSE, str);
	g_free(str);

	return TRUE;
}