Пример #1
0
/* input function: DCC GET received data */
static void sig_dccget_receive(DCC_REC *dcc)
{
	int ret;

	g_return_if_fail(dcc != NULL);

	for (;;) {
		ret = net_receive(dcc->handle, dcc->databuf, dcc->databufsize);
		if (ret == 0) break;

		if (ret < 0) {
			/* socket closed - transmit complete,
			   or other side died.. */
			signal_emit("dcc closed", 1, dcc);
			dcc_destroy(dcc);
			return;
		}

		write(dcc->fhandle, dcc->databuf, ret);
		dcc->transfd += ret;
	}

	/* send number of total bytes received */
	if (dcc->count_pos <= 0)
		dcc_get_send_received(dcc);

	signal_emit("dcc transfer update", 1, dcc);
}
Пример #2
0
/* input function: DCC SEND - we're ready to send more data */
static void dcc_send_data(DCC_REC *dcc)
{
	int ret;

	g_return_if_fail(dcc != NULL);

	if (!dcc->fastsend && !dcc->gotalldata) {
		/* haven't received everything we've send there yet.. */
		return;
	}

	ret = read(dcc->fhandle, dcc->databuf, dcc->databufsize);
	if (ret <= 0) {
		/* end of file .. or some error .. */
		if (dcc->fastsend) {
			/* no need to call this function anymore..
			   in fact it just eats all the cpu.. */
			dcc->waitforend = TRUE;
			g_source_remove(dcc->tagwrite);
			dcc->tagwrite = -1;
		} else {
			signal_emit("dcc closed", 1, dcc);
			dcc_destroy(dcc);
		}
		return;
	}

	ret = net_transmit(dcc->handle, dcc->databuf, ret);
	if (ret > 0) dcc->transfd += ret;
	dcc->gotalldata = FALSE;

	lseek(dcc->fhandle, dcc->transfd, SEEK_SET);

	signal_emit("dcc transfer update", 1, dcc);
}
Пример #3
0
void irc_dcc_deinit(void)
{
	while (dcc_conns != NULL)
		dcc_destroy(dcc_conns->data);

	dcc_chat_deinit();
	dcc_get_deinit();
	dcc_send_deinit();
	dcc_resume_deinit();
	dcc_autoget_deinit();
	dcc_server_deinit();

	signal_remove("event connected", (SIGNAL_FUNC) sig_connected);
	signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
	signal_remove("server nick changed", (SIGNAL_FUNC) sig_server_nick_changed);
	signal_remove("ctcp msg", (SIGNAL_FUNC) ctcp_msg);
	signal_remove("ctcp reply", (SIGNAL_FUNC) ctcp_reply);
	signal_remove("ctcp msg dcc", (SIGNAL_FUNC) ctcp_msg_dcc);
	signal_remove("ctcp reply dcc", (SIGNAL_FUNC) ctcp_reply_dcc);
	signal_remove("ctcp reply dcc reject", (SIGNAL_FUNC) ctcp_reply_dcc_reject);
	signal_remove("event 401", (SIGNAL_FUNC) event_no_such_nick);
	command_unbind("dcc", (SIGNAL_FUNC) cmd_dcc);
	command_unbind("dcc close", (SIGNAL_FUNC) cmd_dcc_close);

	g_source_remove(dcc_timeouttag);
}
Пример #4
0
void dcc_get_connect(GET_DCC_REC *dcc)
{
	if (dcc->get_type == DCC_GET_DEFAULT) {
		dcc->get_type = settings_get_bool("dcc_autorename") ?
			DCC_GET_RENAME : DCC_GET_OVERWRITE;
	}

	if (dcc->from_dccserver) {
		sig_dccget_connected(dcc);
		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_dccget_connected,
				    dcc);
	} else {
		/* error connecting */
		signal_emit("dcc error connect", 1, dcc);
		dcc_destroy(DCC(dcc));
	}
}
Пример #5
0
/* Handle incoming DCC CTCP replies */
static void dcc_ctcp_reply(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr)
{
    char *params, *cmd, *subcmd, *args;
    int type;
    DCC_REC *dcc;

    g_return_if_fail(data != NULL);
    g_return_if_fail(sender != NULL);

    params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &cmd, &subcmd, &args);

    if (g_strcasecmp(cmd, "REJECT") == 0)
    {
        type = dcc_str2type(subcmd);
        dcc = dcc_find_item(type, sender, type == DCC_TYPE_CHAT ? NULL : args);
        if (dcc != NULL)
        {
            signal_emit("dcc closed", 1, dcc);
            dcc_destroy(dcc);
        }
    }
    else
    {
        /* unknown dcc ctcp reply */
        signal_emit("dcc unknown reply", 3, data, sender, sendaddr);
    }

    g_free(params);
}
Пример #6
0
static void event_no_such_nick(char *data, IRC_SERVER_REC *server)
{
    char *params, *nick;
    GSList *tmp, *next;

    g_return_if_fail(data != NULL);

    params = event_get_params(data, 2, NULL, &nick);

    /* check if we've send any dcc requests to this nick.. */
    for (tmp = dcc_conns; tmp != NULL; tmp = next)
    {
        DCC_REC *rec = tmp->data;

        next = tmp->next;
        if (g_strcasecmp(rec->nick, nick) == 0 && rec->starttime == 0)
        {
            /* timed out. */
            signal_emit("dcc closed", 1, rec);
            dcc_destroy(rec);
        }
    }

    g_free(params);
}
Пример #7
0
static void dcc_resume_rec(DCC_REC *dcc)
{
	char *str;

	g_return_if_fail(dcc != NULL);

	dcc->get_type = DCC_GET_RESUME;
	dcc->file = dcc_get_download_path(dcc->arg);

	dcc->fhandle = open(dcc->file, O_WRONLY, dcc_file_create_mode);
	if (dcc->fhandle == -1) {
		signal_emit("dcc error file not found", 2, dcc, dcc->file);
		dcc_destroy(dcc);
		return;
	}

	dcc->transfd = lseek(dcc->fhandle, 0, SEEK_END);
	if (dcc->transfd < 0) dcc->transfd = 0;
	dcc->skipped = dcc->transfd;

	str = g_strdup_printf("DCC RESUME %s %d %lu",
			      dcc->arg, dcc->port, dcc->transfd);
	dcc_ctcp_message(dcc->nick, dcc->server, dcc->chat, FALSE, str);
	g_free(str);
}
Пример #8
0
/* callback: net_connect() finished for DCC GET */
static void sig_dccget_connected(DCC_REC *dcc)
{
	struct stat statbuf;
	char *fname;

	g_return_if_fail(dcc != NULL);

	if (net_geterror(dcc->handle) != 0) {
		/* error connecting */
		signal_emit("dcc error connect", 1, dcc);
		dcc_destroy(dcc);
		return;
	}

	g_source_remove(dcc->tagconn);

	g_free_not_null(dcc->file);
	dcc->file = dcc_get_download_path(dcc->arg);

	/* if some plugin wants to change the file name/path here.. */
	signal_emit("dcc get receive", 1, dcc);

	if (stat(dcc->file, &statbuf) == 0 && dcc->get_type == DCC_GET_RENAME) {
		/* file exists, rename.. */
		fname = get_rename_file(dcc->file);
		g_free(dcc->file);
		dcc->file = fname;
	}

	if (dcc->get_type != DCC_GET_RESUME) {
		dcc->fhandle = open(dcc->file, O_WRONLY | O_TRUNC | O_CREAT, dcc_file_create_mode);
		if (dcc->fhandle == -1) {
			signal_emit("dcc error file create", 2, dcc, dcc->file);
			dcc_destroy(dcc);
			return;
		}
	}

	dcc->databufsize = settings_get_int("dcc_block_size");
        if (dcc->databufsize <= 0) dcc->databufsize = 2048;
	dcc->databuf = g_malloc(dcc->databufsize);

	dcc->starttime = time(NULL);
	dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ,
				   (GInputFunction) sig_dccget_receive, dcc);
	signal_emit("dcc connected", 1, dcc);
}
Пример #9
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);
}
Пример #10
0
/* input function: DCC SEND - received some data */
static void dcc_send_read_size(DCC_REC *dcc)
{
	guint32 bytes;
	int ret;

	g_return_if_fail(dcc != NULL);

	if (dcc->count_pos == 4)
		return;

	/* we need to get 4 bytes.. */
	ret = net_receive(dcc->handle, dcc->count_buf+dcc->count_pos, 4-dcc->count_pos);
	if (ret == -1) {
		signal_emit("dcc closed", 1, dcc);
		dcc_destroy(dcc);
		return;
	}

	dcc->count_pos += ret;

	if (dcc->count_pos != 4)
		return;

	memcpy(&bytes, dcc->count_buf, 4);
	bytes = (guint32) ntohl(bytes);

	dcc->gotalldata = bytes == dcc->transfd;
	dcc->count_pos = 0;

	if (!dcc->fastsend) {
		/* send more data.. */
		dcc_send_data(dcc);
	}

	if (dcc->waitforend && dcc->gotalldata) {
		/* file is sent */
		signal_emit("dcc closed", 1, dcc);
		dcc_destroy(dcc);
	}
}
Пример #11
0
static void dcc_get_connect(DCC_REC *dcc)
{
	dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
				     source_host_ok ? source_host_ip : NULL);
	if (dcc->handle != -1) {
		dcc->tagread = g_input_add(dcc->handle, G_INPUT_WRITE|G_INPUT_READ|G_INPUT_EXCEPTION,
					   (GInputFunction) sig_dccget_connected, dcc);
	} else {
		/* error connecting */
		signal_emit("dcc error connect", 1, dcc);
		dcc_destroy(dcc);
	}
}
Пример #12
0
static void sig_query_destroyed(QUERY_REC *query)
{
	DCC_REC *dcc;

	if (*query->nick != '=')
		return;

	dcc = dcc_find_item(DCC_TYPE_CHAT, query->nick+1, NULL);
	if (dcc != NULL && !dcc->destroyed) {
		/* DCC query window closed, close the dcc chat too. */
		signal_emit("dcc closed", 1, dcc);
		dcc_destroy(dcc);
	}
}
Пример #13
0
void irc_dcc_deinit(void)
{
    dcc_chat_deinit();
    dcc_files_deinit();

    signal_remove("server connected", (SIGNAL_FUNC) dcc_server_connected);
    signal_remove("server disconnected", (SIGNAL_FUNC) dcc_server_disconnected);
    signal_remove("ctcp reply dcc", (SIGNAL_FUNC) dcc_ctcp_reply);
    signal_remove("ctcp msg dcc", (SIGNAL_FUNC) dcc_ctcp_msg);
    command_unbind("dcc", (SIGNAL_FUNC) cmd_dcc);
    command_unbind("dcc close", (SIGNAL_FUNC) cmd_dcc_close);
    signal_remove("event 401", (SIGNAL_FUNC) event_no_such_nick);

    g_source_remove(dcc_timeouttag);

    while (dcc_conns != NULL)
        dcc_destroy(dcc_conns->data);
}
Пример #14
0
/* callback: DCC CHAT - net_connect_nonblock() finished */
static void sig_chat_connected(DCC_REC *dcc)
{
	g_return_if_fail(dcc != NULL);

	g_source_remove(dcc->tagread);
	if (net_geterror(dcc->handle) != 0) {
		/* error connecting */
		signal_emit("dcc error connect", 1, dcc);
		dcc_destroy(dcc);
		return;
	}

	/* connect ok. */
	dcc->starttime = time(NULL);
	dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ,
				   (GInputFunction) dcc_chat_input, dcc);

	signal_emit("dcc connected", 1, dcc);
}
Пример #15
0
static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server,
			 const char *sender, const char *sendaddr,
			 const char *target, DCC_REC *chat)
{
	char *type, *arg, *portstr, *sizestr;
	void *free_arg;
	long size;
        int port;
	DCC_REC *dcc;

	g_return_if_fail(data != NULL);
	g_return_if_fail(sender != NULL);

	if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_NOQUOTES,
			    &type, &arg, &portstr, &sizestr))
		return;

	port = atoi(portstr);
	size = atol(sizestr);

	dcc = dcc_find_by_port(sender, port);
	if (dcc == NULL || !is_resume_type(type) ||
	    !is_resume_ok(type, dcc) || !is_accept_ok(type, dcc)) {
		cmd_params_free(free_arg);
		return;
	}

	if (lseek(dcc->fhandle, size, SEEK_SET) != size) {
		/* error, or trying to seek after end of file */
		signal_emit("dcc closed", 1, dcc);
		dcc_destroy(dcc);
	} else {
		dcc->transfd = dcc->skipped = size;

		if (dcc->type == DCC_TYPE_SEND)
			dcc_resume_send(dcc, port);
		else
			dcc_get_connect(dcc);
	}

	cmd_params_free(free_arg);
}
Пример #16
0
static void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server)
{
    char *str;

    g_return_if_fail(dcc != NULL);

    if (dcc->server != NULL) server = dcc->server;
    if (server != NULL && (dcc->type != DCC_TYPE_CHAT || dcc->starttime == 0))
    {
        signal_emit("dcc rejected", 1, dcc);
        str = g_strdup_printf("NOTICE %s :\001DCC REJECT %s %s\001",
                              dcc->nick, dcc_type2str(SWAP_SENDGET(dcc->type)), dcc->arg);

        irc_send_cmd(server, str);
        g_free(str);
    }

    signal_emit("dcc closed", 1, dcc);
    dcc_destroy(dcc);
}
Пример #17
0
static void dcc_chat_connect(DCC_REC *dcc)
{
	g_return_if_fail(dcc != NULL);

	if (dcc->addrstr[0] == '\0' || dcc->starttime != 0) {
		/* already sent a chat request / already chatting */
		return;
	}

	dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
				     source_host_ok ? source_host_ip : NULL);
	if (dcc->handle != -1) {
		dcc->tagread = g_input_add(dcc->handle, G_INPUT_WRITE|G_INPUT_READ|G_INPUT_EXCEPTION,
					   (GInputFunction) sig_chat_connected, dcc);
	} else {
		/* error connecting */
		signal_emit("dcc error connect", 1, dcc);
		dcc_destroy(dcc);
	}
}
Пример #18
0
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));
	}
}
Пример #19
0
/* 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);
}
Пример #20
0
/* input function: DCC CHAT received some data.. */
static void dcc_chat_input(DCC_REC *dcc)
{
        char tmpbuf[512], *str;
	int recvlen, ret;

	g_return_if_fail(dcc != NULL);

	do {
		recvlen = net_receive(dcc->handle, tmpbuf, sizeof(tmpbuf));

		ret = line_split(tmpbuf, recvlen, &str, (LINEBUF_REC **) &dcc->databuf);
		if (ret == -1) {
			/* connection lost */
			signal_emit("dcc closed", 1, dcc);
			dcc_destroy(dcc);
			break;
		}

		if (ret > 0) {
			dcc->transfd += ret;
			signal_emit("dcc chat message", 2, dcc, str);
		}
	} while (ret > 0);
}
Пример #21
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);
}
Пример #22
0
/* Handle incoming DCC CTCP messages */
static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr, char *target, DCC_REC *chat)
{
    char *params, *type, *arg, *addrstr, *portstr, *sizestr, *str;
    const char *cstr;
    DCC_REC *dcc;
    gulong size;
    int port;

    g_return_if_fail(data != NULL);
    g_return_if_fail(sender != NULL);

    params = cmd_get_params(data, 5 | PARAM_FLAG_NOQUOTES,
			    &type, &arg, &addrstr, &portstr, &sizestr);

    if (sscanf(portstr, "%d", &port) != 1) port = 0;
    if (sscanf(sizestr, "%lu", &size) != 1) size = 0;

    dcc = dcc_create(SWAP_SENDGET(dcc_str2type(type)), -1, sender, arg, server, chat);
    dcc_get_address(addrstr, &dcc->addr);
    net_ip2host(&dcc->addr, dcc->addrstr);
    dcc->port = port;
    dcc->size = size;

    switch (dcc->type)
    {
	case DCC_TYPE_GET:
	    cstr = settings_get_str("dcc_autoget_masks");
	    /* check that autoget masks match */
	    if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || irc_masks_match(cstr, sender, sendaddr)) &&
                /* check file size limit, FIXME: it's possible to send a bogus file size and then just send what ever sized file.. */
		(settings_get_int("dcc_max_autoget_size") <= 0 || (settings_get_int("dcc_max_autoget_size") > 0 && size <= settings_get_int("dcc_max_autoget_size")*1024)))
            {
                /* automatically get */
                str = g_strdup_printf("GET %s %s", dcc->nick, dcc->arg);
                signal_emit("command dcc", 2, str, server);
                g_free(str);
            }
            else
            {
                /* send request */
                signal_emit("dcc request", 1, dcc);
            }
            break;

	case DCC_TYPE_CHAT:
	    cstr = settings_get_str("dcc_autochat_masks");
	    if (*cstr != '\0' && irc_masks_match(cstr, sender, sendaddr))
	    {
                /* automatically accept chat */
                str = g_strdup_printf("CHAT %s", dcc->nick);
                signal_emit("command dcc", 2, str, server);
                g_free(str);
	    }
	    else
	    {
		/* send request */
		signal_emit("dcc request", 1, dcc);
	    }
	    break;

	case DCC_TYPE_RESUME:
	case DCC_TYPE_ACCEPT:
            /* handle this in dcc-files.c */
            dcc_destroy(dcc);
            break;

        default:
            /* unknown DCC command */
            signal_emit("dcc unknown ctcp", 3, data, sender, sendaddr);
            dcc_destroy(dcc);
            break;
    }

    g_free(params);
}
Пример #23
0
/* 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);
}
Пример #24
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);
}
Пример #25
0
void dcc_close(DCC_REC *dcc)
{
	signal_emit("dcc closed", 1, dcc);
        dcc_destroy(dcc);
}
Пример #26
0
/* callback: net_connect() finished for DCC GET */
void sig_dccget_connected(GET_DCC_REC *dcc)
{
	struct stat statbuf;
	char *fname, *tempfname, *str;
        int ret, ret_errno, temphandle, old_umask;

	if (!dcc->from_dccserver) {
		if (net_geterror(dcc->handle) != 0) {
			/* error connecting */
			signal_emit("dcc error connect", 1, dcc);
			dcc_destroy(DCC(dcc));
			return;
		}

		g_source_remove(dcc->tagconn);
		dcc->tagconn = -1;
	}

	g_free_not_null(dcc->file);
	dcc->file = dcc_get_download_path(dcc->arg);

	/* if some plugin wants to change the file name/path here.. */
	signal_emit("dcc get receive", 1, dcc);

	if (stat(dcc->file, &statbuf) == 0 &&
	    dcc->get_type == DCC_GET_RENAME) {
		/* file exists, rename.. */
		fname = dcc_get_rename_file(dcc->file);
		g_free(dcc->file);
		dcc->file = fname;
	}

	if (dcc->get_type != DCC_GET_RESUME) {
		int dcc_file_create_mode = octal2dec(settings_get_int("dcc_file_create_mode"));

		/* we want to overwrite the file, remove it here.
		   if it gets created after this, we'll fail. */
		unlink(dcc->file);

		/* just to make sure we won't run into race conditions
		   if download_path is in some global temp directory */
		tempfname = g_strconcat(dcc->file, ".XXXXXX", NULL);

                old_umask = umask(0077);
		temphandle = mkstemp(tempfname);
		umask(old_umask);

		if (temphandle == -1)
			ret = -1;
		else
			ret = fchmod(temphandle, dcc_file_create_mode);

		close(temphandle);

		if (ret != -1) {
			ret = link(tempfname, dcc->file);

			if (ret == -1 &&
			    /* Linux */
			    (errno == EPERM ||
			     /* FUSE */
			     errno == ENOSYS ||
			     /* BSD */
			     errno == EOPNOTSUPP)) {
				/* hard links aren't supported - some people
				   want to download stuff to FAT/NTFS/etc
				   partitions, so fallback to rename() */
				ret = rename(tempfname, dcc->file);
			}
		}

		/* if ret = 0, we're the file owner now */
		dcc->fhandle = ret == -1 ? -1 :
			open(dcc->file, O_WRONLY | O_TRUNC);

		/* close/remove the temp file */
		ret_errno = errno;
		unlink(tempfname);
		g_free(tempfname);

		if (dcc->fhandle == -1) {
			signal_emit("dcc error file create", 3,
				    dcc, dcc->file, g_strerror(ret_errno));
			dcc_destroy(DCC(dcc));
			return;
		}
	}

	dcc->starttime = time(NULL);
	if (dcc->size == 0) {
		dcc_close(DCC(dcc));
		return;
	}
	dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ,
				   (GInputFunction) sig_dccget_receive, dcc);
	signal_emit("dcc connected", 1, dcc);

	if (dcc->from_dccserver) {
		str = g_strdup_printf("121 %s %d\n",
				      dcc->server ? dcc->server->nick : "??", 0);
		net_transmit(dcc->handle, str, strlen(str));
	}
}
Пример #27
0
/* Handle incoming DCC CTCP messages */
static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr, char *target, DCC_REC *chat)
{
    char *type, *arg, *addrstr, *portstr, *sizestr, *str;
    void *free_arg;
    const char *cstr;
    DCC_REC *dcc, *olddcc;
    long size;
    int dcctype, port;

    g_return_if_fail(data != NULL);
    g_return_if_fail(sender != NULL);

    if (!cmd_get_params(data, &free_arg, 5 | PARAM_FLAG_NOQUOTES,
			&type, &arg, &addrstr, &portstr, &sizestr))
	    return;

    if (sscanf(portstr, "%d", &port) != 1) port = 0;
    if (sscanf(sizestr, "%ld", &size) != 1) size = 0;

    dcctype = SWAP_SENDGET(dcc_str2type(type));
    olddcc = dcc_find_item(dcctype, sender,
			   dcctype == DCC_TYPE_CHAT ? NULL : arg);
    if (olddcc != NULL) {
	    /* same DCC request offered again */
	    if (olddcc->type == DCC_TYPE_CHAT &&
		olddcc->handle != -1 && olddcc->starttime == 0) {
		    /* we requested dcc chat, they requested
		       dcc chat from us .. allow it. */
		    dcc_destroy(olddcc);
	    } else {
		    /* if the connection isn't open, update the port,
		       otherwise just ignore */
		    if (olddcc->handle == -1)
			    olddcc->port = port;
		    cmd_params_free(free_arg);
		    return;
	    }
    }

    dcc = dcc_create(dcctype, -1, sender, arg, server, chat);
    dcc_get_address(addrstr, &dcc->addr);
    net_ip2host(&dcc->addr, dcc->addrstr);
    dcc->port = port;
    dcc->size = size;

    switch (dcc->type)
    {
	case DCC_TYPE_GET:
	    cstr = settings_get_str("dcc_autoget_masks");
	    /* check that autoget masks match */
	    if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || masks_match(SERVER(server), cstr, sender, sendaddr)) &&
                /* check file size limit, FIXME: it's possible to send a bogus file size and then just send what ever sized file.. */
		(settings_get_int("dcc_max_autoget_size") <= 0 || (settings_get_int("dcc_max_autoget_size") > 0 && size <= settings_get_int("dcc_max_autoget_size")*1024)))
            {
                /* automatically get */
                str = g_strdup_printf("GET %s %s", dcc->nick, dcc->arg);
                signal_emit("command dcc", 2, str, server);
                g_free(str);
            }
            else
            {
                /* send request */
                signal_emit("dcc request", 1, dcc);
            }
            break;

	case DCC_TYPE_CHAT:
	    cstr = settings_get_str("dcc_autochat_masks");
	    if (olddcc != NULL ||
		(*cstr != '\0' && masks_match(SERVER(server), cstr, sender, sendaddr)))
	    {
                /* automatically accept chat */
                str = g_strdup_printf("CHAT %s", dcc->nick);
                signal_emit("command dcc", 2, str, server);
                g_free(str);
	    }
	    else
	    {
		/* send request */
		signal_emit("dcc request", 1, dcc);
	    }
	    break;

	case DCC_TYPE_RESUME:
	case DCC_TYPE_ACCEPT:
            /* handle this in dcc-files.c */
            dcc_destroy(dcc);
            break;

        default:
            /* unknown DCC command */
            signal_emit("dcc unknown ctcp", 3, data, sender, sendaddr);
            dcc_destroy(dcc);
            break;
    }

    cmd_params_free(free_arg);
}