1 /* X-Chat
2  * Copyright (C) 1998-2006 Peter Zelezny.
3  * Copyright (C) 2006 Damjan Jovanovic
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  * Wayne Conrad, 3 Apr 1999: Color-coded DCC file transfer status windows
20  * Bernhard Valenti <bernhard.valenti@gmx.net> 2000-11-21: Fixed DCC send behind nat
21  *
22  * 2001-03-08 Added support for getting "dcc_ip" config parameter.
23  * Jim Seymour (jseymour@LinxNet.com)
24  */
25 
26 /* Required to make lseek use off64_t, but doesn't work on Windows */
27 #define _FILE_OFFSET_BITS 64
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include <errno.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 
37 #define WANTSOCKET
38 #define WANTARPA
39 #define WANTDNS
40 #include "inet.h"
41 
42 #ifdef WIN32
43 #include <windows.h>
44 #include <io.h>
45 #else
46 #include <unistd.h>
47 #endif
48 
49 #include "hexchat.h"
50 #include "util.h"
51 #include "fe.h"
52 #include "outbound.h"
53 #include "inbound.h"
54 #include "network.h"
55 #include "plugin.h"
56 #include "server.h"
57 #include "text.h"
58 #include "url.h"
59 #include "hexchatc.h"
60 
61 /* Setting _FILE_OFFSET_BITS to 64 doesn't change lseek to use off64_t on Windows, so override lseek to the version that does */
62 #if defined(WIN32) && (!defined(__MINGW32__) && !defined(__MINGW64__))
63 	#define lseek _lseeki64
64 #endif
65 
66 /* interval timer to detect timeouts */
67 static int timeout_timer = 0;
68 
69 static char *dcctypes[] = { "SEND", "RECV", "CHAT", "CHAT" };
70 
71 struct dccstat_info dccstat[] = {
72 	{N_("Waiting"), 1 /*black */ },
73 	{N_("Active"), 12 /*cyan */ },
74 	{N_("Failed"), 4 /*red */ },
75 	{N_("Done"), 3 /*green */ },
76 	{N_("Connect"), 1 /*black */ },
77 	{N_("Aborted"), 4 /*red */ },
78 };
79 
80 static int dcc_global_throttle;	/* 0x1 = sends, 0x2 = gets */
81 static gint64 dcc_sendcpssum, dcc_getcpssum;
82 
83 static struct DCC *new_dcc (void);
84 static void dcc_close (struct DCC *dcc, enum dcc_state dccstat, int destroy);
85 static gboolean dcc_send_data (GIOChannel *, GIOCondition, struct DCC *);
86 static gboolean dcc_read (GIOChannel *, GIOCondition, struct DCC *);
87 static gboolean dcc_read_ack (GIOChannel *source, GIOCondition condition, struct DCC *dcc);
88 static int dcc_check_timeouts (void);
89 
new_id(void)90 static int new_id(void)
91 {
92 	static int id = 0;
93 	if (id == 0)
94 	{
95 		/* start the first ID at a random number for pseudo security */
96 		/* 1 - 255 */
97 		id = RAND_INT(255) + 1;
98 		/* ignore overflows, since it can go to 2 billion */
99 	}
100 	return id++;
101 }
102 
103 static double
timeval_diff(GTimeVal * greater,GTimeVal * less)104 timeval_diff (GTimeVal *greater,
105 				 GTimeVal *less)
106 {
107 	long usecdiff;
108 	double result;
109 
110 	result = greater->tv_sec - less->tv_sec;
111 	usecdiff = (long) greater->tv_usec - less->tv_usec;
112 	result += (double) usecdiff / 1000000;
113 
114 	return result;
115 }
116 
117 static void
dcc_unthrottle(struct DCC * dcc)118 dcc_unthrottle (struct DCC *dcc)
119 {
120 	/* don't unthrottle here, but delegate to funcs */
121 	if (dcc->type == TYPE_RECV)
122 		dcc_read (NULL, 0, dcc);
123 	else
124 		dcc_send_data (NULL, 0, dcc);
125 }
126 
127 static void
dcc_calc_cps(struct DCC * dcc)128 dcc_calc_cps (struct DCC *dcc)
129 {
130 	GTimeVal now;
131 	gint64 oldcps;
132 	double timediff, startdiff;
133 	int glob_throttle_bit, wasthrottled;
134 	gint64 *cpssum;
135 	int glob_limit;
136 	goffset pos, posdiff;
137 
138 	g_get_current_time (&now);
139 
140 	/* the pos we use for sends is an average
141 		between pos and ack */
142 	if (dcc->type == TYPE_SEND)
143 	{
144 		/* carefull to avoid 32bit overflow */
145 		pos = dcc->pos - ((dcc->pos - dcc->ack) / 2);
146 		glob_throttle_bit = 0x1;
147 		cpssum = &dcc_sendcpssum;
148 		glob_limit = prefs.hex_dcc_global_max_send_cps;
149 	}
150 	else
151 	{
152 		pos = dcc->pos;
153 		glob_throttle_bit = 0x2;
154 		cpssum = &dcc_getcpssum;
155 		glob_limit = prefs.hex_dcc_global_max_get_cps;
156 	}
157 
158 	if (!dcc->firstcpstv.tv_sec && !dcc->firstcpstv.tv_usec)
159 		dcc->firstcpstv = now;
160 	else
161 	{
162 		startdiff = timeval_diff (&now, &dcc->firstcpstv);
163 		if (startdiff < 1)
164 			startdiff = 1;
165 		else if (startdiff > CPS_AVG_WINDOW)
166 			startdiff = CPS_AVG_WINDOW;
167 
168 		timediff = timeval_diff (&now, &dcc->lastcpstv);
169 		if (timediff > startdiff)
170 			timediff = startdiff = 1;
171 
172 		posdiff = pos - dcc->lastcpspos;
173 		oldcps = dcc->cps;
174 		dcc->cps = (gint64) ((posdiff / timediff) * (timediff / startdiff) + dcc->cps * (1.0 - (timediff / startdiff)));
175 
176 		*cpssum += dcc->cps - oldcps;
177 	}
178 
179 	dcc->lastcpspos = pos;
180 	dcc->lastcpstv = now;
181 
182 	/* now check cps against set limits... */
183 	wasthrottled = dcc->throttled;
184 
185 	/* check global limits first */
186 	dcc->throttled &= ~0x2;
187 	if (glob_limit > 0 && *cpssum >= glob_limit)
188 	{
189 		dcc_global_throttle |= glob_throttle_bit;
190 		if (dcc->maxcps >= 0)
191 			dcc->throttled |= 0x2;
192 	}
193 	else
194 		dcc_global_throttle &= ~glob_throttle_bit;
195 
196 	/* now check per-connection limit */
197 	if (dcc->maxcps > 0 && dcc->cps > dcc->maxcps)
198 		dcc->throttled |= 0x1;
199 	else
200 		dcc->throttled &= ~0x1;
201 
202 	/* take action */
203 	if (wasthrottled && !dcc->throttled)
204 		dcc_unthrottle (dcc);
205 }
206 
207 static void
dcc_remove_from_sum(struct DCC * dcc)208 dcc_remove_from_sum (struct DCC *dcc)
209 {
210 	if (dcc->dccstat != STAT_ACTIVE)
211 		return;
212 	if (dcc->type == TYPE_SEND)
213 		dcc_sendcpssum -= dcc->cps;
214 	else if (dcc->type == TYPE_RECV)
215 		dcc_getcpssum -= dcc->cps;
216 }
217 
218 gboolean
is_dcc(struct DCC * dcc)219 is_dcc (struct DCC *dcc)
220 {
221 	GSList *list = dcc_list;
222 	while (list)
223 	{
224 		if (list->data == dcc)
225 			return TRUE;
226 		list = list->next;
227 	}
228 	return FALSE;
229 }
230 
231 gboolean
is_dcc_completed(struct DCC * dcc)232 is_dcc_completed (struct DCC *dcc)
233 {
234 	if (dcc != NULL)
235 		return (dcc->dccstat == STAT_FAILED || dcc->dccstat == STAT_DONE || dcc->dccstat == STAT_ABORTED);
236 
237 	return FALSE;
238 }
239 
240 /* this is called by timeout_timer every 1 second. */
241 
242 int
dcc_check_timeouts(void)243 dcc_check_timeouts (void)
244 {
245 	struct DCC *dcc;
246 	time_t tim = time (0);
247 	GSList *next, *list = dcc_list;
248 
249 	while (list)
250 	{
251 		dcc = (struct DCC *) list->data;
252 		next = list->next;
253 
254 		switch (dcc->dccstat)
255 		{
256 		case STAT_ACTIVE:
257 			dcc_calc_cps (dcc);
258 			fe_dcc_update (dcc);
259 
260 			if (dcc->type == TYPE_SEND || dcc->type == TYPE_RECV)
261 			{
262 				if (prefs.hex_dcc_stall_timeout > 0)
263 				{
264 					if (!dcc->throttled
265 						&& tim - dcc->lasttime > prefs.hex_dcc_stall_timeout)
266 					{
267 						EMIT_SIGNAL (XP_TE_DCCSTALL, dcc->serv->front_session,
268 										 dcctypes[dcc->type],
269 										 file_part (dcc->file), dcc->nick, NULL, 0);
270 						dcc_close (dcc, STAT_ABORTED, FALSE);
271 					}
272 				}
273 			}
274 			break;
275 		case STAT_QUEUED:
276 			if (dcc->type == TYPE_SEND || dcc->type == TYPE_CHATSEND)
277 			{
278 				if (tim - dcc->offertime > prefs.hex_dcc_timeout)
279 				{
280 					if (prefs.hex_dcc_timeout > 0)
281 					{
282 						EMIT_SIGNAL (XP_TE_DCCTOUT, dcc->serv->front_session,
283 										 dcctypes[dcc->type],
284 										 file_part (dcc->file), dcc->nick, NULL, 0);
285 						dcc_close (dcc, STAT_ABORTED, FALSE);
286 					}
287 				}
288 			}
289 			break;
290 		case STAT_DONE:
291 		case STAT_FAILED:
292 		case STAT_ABORTED:
293 			if (prefs.hex_dcc_remove)
294 				dcc_close (dcc, 0, TRUE);
295 			break;
296 		default:
297 			break;
298 		}
299 		list = next;
300 	}
301 	return 1;
302 }
303 
304 static int
dcc_lookup_proxy(char * host,struct sockaddr_in * addr)305 dcc_lookup_proxy (char *host, struct sockaddr_in *addr)
306 {
307 	struct hostent *h;
308 	static char *cache_host = NULL;
309 	static guint32 cache_addr;
310 
311 	/* too lazy to thread this, so we cache results */
312 	if (cache_host)
313 	{
314 		if (strcmp (host, cache_host) == 0)
315 		{
316 			memcpy (&addr->sin_addr, &cache_addr, 4);
317 			return TRUE;
318 		}
319 		g_free (cache_host);
320 		cache_host = NULL;
321 	}
322 
323 	h = gethostbyname (host);
324 	if (h != NULL && h->h_length == 4 && h->h_addr_list[0] != NULL)
325 	{
326 		memcpy (&addr->sin_addr, h->h_addr, 4);
327 		memcpy (&cache_addr, h->h_addr, 4);
328 		cache_host = g_strdup (host);
329 		/* cppcheck-suppress memleak */
330 		return TRUE;
331 	}
332 
333 	return FALSE;
334 }
335 
336 #define DCC_USE_PROXY() (prefs.hex_net_proxy_host[0] && prefs.hex_net_proxy_type>0 && prefs.hex_net_proxy_type<5 && prefs.hex_net_proxy_use!=1)
337 
338 static int
dcc_connect_sok(struct DCC * dcc)339 dcc_connect_sok (struct DCC *dcc)
340 {
341 	int sok;
342 	struct sockaddr_in addr;
343 
344 	sok = socket (AF_INET, SOCK_STREAM, 0);
345 	if (sok == -1)
346 		return -1;
347 
348 	memset (&addr, 0, sizeof (addr));
349 	addr.sin_family = AF_INET;
350 	if (DCC_USE_PROXY ())
351 	{
352 		if (!dcc_lookup_proxy (prefs.hex_net_proxy_host, &addr))
353 		{
354 			closesocket (sok);
355 			return -1;
356 		}
357 		addr.sin_port = htons (prefs.hex_net_proxy_port);
358 	}
359 	else
360 	{
361 		addr.sin_port = htons (dcc->port);
362 		addr.sin_addr.s_addr = htonl (dcc->addr);
363 	}
364 
365 	set_nonblocking (sok);
366 	connect (sok, (struct sockaddr *) &addr, sizeof (addr));
367 
368 	return sok;
369 }
370 
371 static void
dcc_close(struct DCC * dcc,enum dcc_state dccstat,int destroy)372 dcc_close (struct DCC *dcc, enum dcc_state dccstat, int destroy)
373 {
374 	if (dcc->wiotag)
375 	{
376 		fe_input_remove (dcc->wiotag);
377 		dcc->wiotag = 0;
378 	}
379 
380 	if (dcc->iotag)
381 	{
382 		fe_input_remove (dcc->iotag);
383 		dcc->iotag = 0;
384 	}
385 
386 	if (dcc->sok != -1)
387 	{
388 		closesocket (dcc->sok);
389 		dcc->sok = -1;
390 	}
391 
392 	dcc_remove_from_sum (dcc);
393 
394 	if (dcc->fp != -1)
395 	{
396 		close (dcc->fp);
397 		dcc->fp = -1;
398 
399 		if(dccstat == STAT_DONE)
400 		{
401 			/* if we just completed a dcc receive, move the */
402 			/* completed file to the completed directory */
403 			if(dcc->type == TYPE_RECV)
404 			{
405 				/* mgl: change this to handle the case where dccwithnick is set */
406 				move_file (prefs.hex_dcc_dir, prefs.hex_dcc_completed_dir,
407 									 file_part (dcc->destfile), prefs.hex_dcc_permissions);
408 			}
409 
410 		}
411 	}
412 
413 	dcc->dccstat = dccstat;
414 	if (dcc->dccchat)
415 	{
416 		g_free (dcc->dccchat);
417 		dcc->dccchat = NULL;
418 	}
419 
420 	if (destroy)
421 	{
422 		dcc_list = g_slist_remove (dcc_list, dcc);
423 		fe_dcc_remove (dcc);
424 		g_free (dcc->proxy);
425 		g_free (dcc->file);
426 		g_free (dcc->destfile);
427 		g_free (dcc->nick);
428 		g_free (dcc);
429 		if (dcc_list == NULL && timeout_timer != 0)
430 		{
431 			fe_timeout_remove (timeout_timer);
432 			timeout_timer = 0;
433 		}
434 		return;
435 	}
436 
437 	fe_dcc_update (dcc);
438 }
439 
440 void
dcc_abort(session * sess,struct DCC * dcc)441 dcc_abort (session *sess, struct DCC *dcc)
442 {
443 	if (dcc)
444 	{
445 		switch (dcc->dccstat)
446 		{
447 		case STAT_QUEUED:
448 		case STAT_CONNECTING:
449 		case STAT_ACTIVE:
450 			dcc_close (dcc, STAT_ABORTED, FALSE);
451 			switch (dcc->type)
452 			{
453 			case TYPE_CHATSEND:
454 			case TYPE_CHATRECV:
455 				EMIT_SIGNAL (XP_TE_DCCCHATABORT, sess, dcc->nick, NULL, NULL,
456 								 NULL, 0);
457 				break;
458 			case TYPE_SEND:
459 				EMIT_SIGNAL (XP_TE_DCCSENDABORT, sess, dcc->nick,
460 								 file_part (dcc->file), NULL, NULL, 0);
461 				break;
462 			case TYPE_RECV:
463 				EMIT_SIGNAL (XP_TE_DCCRECVABORT, sess, dcc->nick,
464 								 dcc->file, NULL, NULL, 0);
465 			}
466 			break;
467 		default:
468 			dcc_close (dcc, 0, TRUE);
469 		}
470 	}
471 }
472 
473 void
dcc_notify_kill(struct server * serv)474 dcc_notify_kill (struct server *serv)
475 {
476 	struct server *replaceserv = 0;
477 	struct DCC *dcc;
478 	GSList *list = dcc_list;
479 	if (serv_list)
480 		replaceserv = (struct server *) serv_list->data;
481 	while (list)
482 	{
483 		dcc = (struct DCC *) list->data;
484 		if (dcc->serv == serv)
485 			dcc->serv = replaceserv;
486 		list = list->next;
487 	}
488 }
489 
490 struct DCC *
dcc_write_chat(char * nick,char * text)491 dcc_write_chat (char *nick, char *text)
492 {
493 	struct DCC *dcc;
494 	int len;
495 
496 	dcc = find_dcc (nick, "", TYPE_CHATRECV);
497 	if (!dcc)
498 		dcc = find_dcc (nick, "", TYPE_CHATSEND);
499 	if (dcc && dcc->dccstat == STAT_ACTIVE)
500 	{
501 		len = strlen (text);
502 		tcp_send_real (NULL, dcc->sok, dcc->serv->write_converter, text, len);
503 		send (dcc->sok, "\n", 1, 0);
504 		dcc->size += len;
505 		fe_dcc_update (dcc);
506 		return dcc;
507 	}
508 	return NULL;
509 }
510 
511 /* returns: 0 - ok
512 				1 - the dcc is closed! */
513 
514 static int
dcc_chat_line(struct DCC * dcc,char * line)515 dcc_chat_line (struct DCC *dcc, char *line)
516 {
517 	session *sess;
518 	char *word[PDIWORDS];
519 	char *po;
520 	int ret, i;
521 	char portbuf[32];
522 	message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT;
523 
524 	line = text_convert_invalid (line, -1, dcc->serv->read_converter, unicode_fallback_string, NULL);
525 
526 	sess = find_dialog (dcc->serv, dcc->nick);
527 	if (!sess)
528 		sess = dcc->serv->front_session;
529 
530 	sprintf (portbuf, "%d", dcc->port);
531 
532 	word[0] = "DCC Chat Text";
533 	word[1] = net_ip (dcc->addr);
534 	word[2] = portbuf;
535 	word[3] = dcc->nick;
536 	word[4] = line;
537 	for (i = 5; i < PDIWORDS; i++)
538 		word[i] = "\000";
539 
540 	ret = plugin_emit_print (sess, word, 0);
541 
542 	/* did the plugin close it? */
543 	if (!g_slist_find (dcc_list, dcc))
544 	{
545 		g_free (line);
546 		return 1;
547 	}
548 
549 	/* did the plugin eat the event? */
550 	if (ret)
551 	{
552 		g_free (line);
553 		return 0;
554 	}
555 
556 	url_check_line (line);
557 
558 	if (line[0] == 1 && !g_ascii_strncasecmp (line + 1, "ACTION", 6))
559 	{
560 		po = strchr (line + 8, '\001');
561 		if (po)
562 			po[0] = 0;
563 		inbound_action (sess, dcc->serv->nick, dcc->nick, "", line + 8, FALSE,
564 							 FALSE, &no_tags);
565 	} else
566 	{
567 		inbound_privmsg (dcc->serv, dcc->nick, "", line, FALSE, &no_tags);
568 	}
569 	g_free (line);
570 	return 0;
571 }
572 
573 static gboolean
dcc_read_chat(GIOChannel * source,GIOCondition condition,struct DCC * dcc)574 dcc_read_chat (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
575 {
576 	int i, len, dead;
577 	char portbuf[32];
578 	char lbuf[2050];
579 
580 	while (1)
581 	{
582 		if (dcc->throttled)
583 		{
584 			fe_input_remove (dcc->iotag);
585 			dcc->iotag = 0;
586 			return FALSE;
587 		}
588 
589 		if (!dcc->iotag)
590 			dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc);
591 
592 		len = recv (dcc->sok, lbuf, sizeof (lbuf) - 2, 0);
593 		if (len < 1)
594 		{
595 			if (len < 0)
596 			{
597 				if (would_block ())
598 					return TRUE;
599 			}
600 			sprintf (portbuf, "%d", dcc->port);
601 			EMIT_SIGNAL (XP_TE_DCCCHATF, dcc->serv->front_session, dcc->nick,
602 							 net_ip (dcc->addr), portbuf,
603 							 errorstring ((len < 0) ? sock_error () : 0), 0);
604 			dcc_close (dcc, STAT_FAILED, FALSE);
605 			return TRUE;
606 		}
607 		i = 0;
608 		lbuf[len] = 0;
609 		while (i < len)
610 		{
611 			switch (lbuf[i])
612 			{
613 			case '\r':
614 				break;
615 			case '\n':
616 				dcc->dccchat->linebuf[dcc->dccchat->pos] = 0;
617 				dead = dcc_chat_line (dcc, dcc->dccchat->linebuf);
618 
619 				if (dead || !dcc->dccchat) /* the dcc has been closed, don't use (DCC *)! */
620 					return TRUE;
621 
622 				dcc->pos += dcc->dccchat->pos;
623 				dcc->dccchat->pos = 0;
624 				fe_dcc_update (dcc);
625 				break;
626 			default:
627 				dcc->dccchat->linebuf[dcc->dccchat->pos] = lbuf[i];
628 				if (dcc->dccchat->pos < (sizeof (dcc->dccchat->linebuf) - 1))
629 					dcc->dccchat->pos++;
630 			}
631 			i++;
632 		}
633 	}
634 }
635 
636 static void
dcc_calc_average_cps(struct DCC * dcc)637 dcc_calc_average_cps (struct DCC *dcc)
638 {
639 	time_t sec;
640 
641 	sec = time (0) - dcc->starttime;
642 	if (sec < 1)
643 		sec = 1;
644 	if (dcc->type == TYPE_SEND)
645 		dcc->cps = (dcc->ack - dcc->resumable) / sec;
646 	else
647 		dcc->cps = (dcc->pos - dcc->resumable) / sec;
648 }
649 
650 static void
dcc_send_ack(struct DCC * dcc)651 dcc_send_ack (struct DCC *dcc)
652 {
653 	/* send in 32-bit big endian */
654 	guint32 pos = htonl (dcc->pos & 0xffffffff);
655 	send (dcc->sok, (char *) &pos, 4, 0);
656 }
657 
658 static gboolean
dcc_read(GIOChannel * source,GIOCondition condition,struct DCC * dcc)659 dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
660 {
661 	char *old;
662 	char buf[4096];
663 	int n;
664 	gboolean need_ack = FALSE;
665 
666 	if (dcc->fp == -1)
667 	{
668 
669 		/* try to create the download dir (even if it exists, no harm) */
670 		g_mkdir (prefs.hex_dcc_dir, 0700);
671 
672 		if (dcc->resumable)
673 		{
674 			gchar *filename_fs = g_filename_from_utf8(dcc->destfile, -1, NULL, NULL, NULL);
675 			dcc->fp = g_open(dcc->destfile, O_WRONLY | O_APPEND | OFLAGS, 0);
676 			g_free (filename_fs);
677 
678 			dcc->pos = dcc->resumable;
679 			dcc->ack = dcc->resumable;
680 		}
681 		else
682 		{
683 			gchar *filename_fs;
684 
685 			if (g_access (dcc->destfile, F_OK) == 0)
686 			{
687 				n = 0;
688 				do
689 				{
690 					n++;
691 					g_snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n);
692 				}
693 				while (g_access (buf, F_OK) == 0);
694 
695 				old = dcc->destfile;
696 				dcc->destfile = g_strdup (buf);
697 
698 				EMIT_SIGNAL (XP_TE_DCCRENAME, dcc->serv->front_session,
699 								 old, dcc->destfile, NULL, NULL, 0);
700 				g_free (old);
701 			}
702 
703 			filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
704 			dcc->fp = g_open (filename_fs, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT, prefs.hex_dcc_permissions);
705 			g_free (filename_fs);
706 		}
707 	}
708 	if (dcc->fp == -1)
709 	{
710 		/* the last executed function is open(), errno should be valid */
711 		EMIT_SIGNAL (XP_TE_DCCFILEERR, dcc->serv->front_session, dcc->destfile,
712 						 errorstring (errno), NULL, NULL, 0);
713 		dcc_close (dcc, STAT_FAILED, FALSE);
714 		return TRUE;
715 	}
716 	while (1)
717 	{
718 		if (dcc->throttled)
719 		{
720 			if (need_ack)
721 				dcc_send_ack (dcc);
722 
723 			fe_input_remove (dcc->iotag);
724 			dcc->iotag = 0;
725 			return FALSE;
726 		}
727 
728 		if (!dcc->iotag)
729 			dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read, dcc);
730 
731 		n = recv (dcc->sok, buf, sizeof (buf), 0);
732 		if (n < 1)
733 		{
734 			if (n < 0)
735 			{
736 				if (would_block ())
737 				{
738 					if (need_ack)
739 						dcc_send_ack (dcc);
740 					return TRUE;
741 				}
742 			}
743 			EMIT_SIGNAL (XP_TE_DCCRECVERR, dcc->serv->front_session, dcc->file,
744 							 dcc->destfile, dcc->nick,
745 							 errorstring ((n < 0) ? sock_error () : 0), 0);
746 			/* send ack here? but the socket is dead */
747 			/*if (need_ack)
748 				dcc_send_ack (dcc);*/
749 			dcc_close (dcc, STAT_FAILED, FALSE);
750 			return TRUE;
751 		}
752 
753 		if (write (dcc->fp, buf, n) == -1) /* could be out of hdd space */
754 		{
755 			EMIT_SIGNAL (XP_TE_DCCRECVERR, dcc->serv->front_session, dcc->file,
756 							 dcc->destfile, dcc->nick, errorstring (errno), 0);
757 			if (need_ack)
758 				dcc_send_ack (dcc);
759 			dcc_close (dcc, STAT_FAILED, FALSE);
760 			return TRUE;
761 		}
762 
763 		dcc->lasttime = time (0);
764 		dcc->pos += n;
765 		need_ack = TRUE;	/* send ack when we're done recv()ing */
766 
767 		if (dcc->pos >= dcc->size)
768 		{
769 			dcc_send_ack (dcc);
770 			dcc_close (dcc, STAT_DONE, FALSE);
771 			dcc_calc_average_cps (dcc);	/* this must be done _after_ dcc_close, or dcc_remove_from_sum will see the wrong value in dcc->cps */
772 			/* cppcheck-suppress deallocuse */
773 			sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
774 			EMIT_SIGNAL (XP_TE_DCCRECVCOMP, dcc->serv->front_session,
775 							 dcc->file, dcc->destfile, dcc->nick, buf, 0);
776 			return TRUE;
777 		}
778 	}
779 }
780 
781 static void
dcc_open_query(server * serv,char * nick)782 dcc_open_query (server *serv, char *nick)
783 {
784 	if (prefs.hex_gui_autoopen_dialog)
785 		open_query (serv, nick, FALSE);
786 }
787 
788 static gboolean
dcc_did_connect(GIOChannel * source,GIOCondition condition,struct DCC * dcc)789 dcc_did_connect (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
790 {
791 	int er;
792 
793 #ifdef WIN32
794 	if (condition & G_IO_ERR)
795 	{
796 		int len;
797 
798 		/* find the last errno for this socket */
799 		len = sizeof (er);
800 		getsockopt (dcc->sok, SOL_SOCKET, SO_ERROR, (char *)&er, &len);
801 		EMIT_SIGNAL (XP_TE_DCCCONFAIL, dcc->serv->front_session,
802 						 dcctypes[dcc->type], dcc->nick, errorstring (er),
803 						 NULL, 0);
804 		dcc->dccstat = STAT_FAILED;
805 		fe_dcc_update (dcc);
806 		return FALSE;
807 	}
808 
809 #else
810 	struct sockaddr_in addr;
811 
812 	memset (&addr, 0, sizeof (addr));
813 	addr.sin_port = htons (dcc->port);
814 	addr.sin_family = AF_INET;
815 	addr.sin_addr.s_addr = htonl (dcc->addr);
816 
817 	/* check if it's already connected; This always fails on winXP */
818 	if (connect (dcc->sok, (struct sockaddr *) &addr, sizeof (addr)) != 0)
819 	{
820 		er = sock_error ();
821 		if (er != EISCONN)
822 		{
823 			EMIT_SIGNAL (XP_TE_DCCCONFAIL, dcc->serv->front_session,
824 							 dcctypes[dcc->type], dcc->nick, errorstring (er),
825 							 NULL, 0);
826 			dcc->dccstat = STAT_FAILED;
827 			fe_dcc_update (dcc);
828 			return FALSE;
829 		}
830 	}
831 #endif
832 
833 	return TRUE;
834 }
835 
836 static gboolean
dcc_connect_finished(GIOChannel * source,GIOCondition condition,struct DCC * dcc)837 dcc_connect_finished (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
838 {
839 	char host[128];
840 
841 	if (dcc->iotag)
842 	{
843 		fe_input_remove (dcc->iotag);
844 		dcc->iotag = 0;
845 	}
846 
847 	if (!dcc_did_connect (source, condition, dcc))
848 		return TRUE;
849 
850 	dcc->dccstat = STAT_ACTIVE;
851 	g_snprintf (host, sizeof host, "%s:%d", net_ip (dcc->addr), dcc->port);
852 
853 	switch (dcc->type)
854 	{
855 	case TYPE_RECV:
856 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read, dcc);
857 		EMIT_SIGNAL (XP_TE_DCCCONRECV, dcc->serv->front_session,
858 						 dcc->nick, host, dcc->file, NULL, 0);
859 		break;
860 	case TYPE_SEND:
861 		/* passive send */
862 		dcc->fastsend = prefs.hex_dcc_fast_send;
863 		if (dcc->fastsend)
864 			dcc->wiotag = fe_input_add (dcc->sok, FIA_WRITE, dcc_send_data, dcc);
865 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_ack, dcc);
866 		dcc_send_data (NULL, 0, (gpointer)dcc);
867 		EMIT_SIGNAL (XP_TE_DCCCONSEND, dcc->serv->front_session,
868 						 dcc->nick, host, dcc->file, NULL, 0);
869 		break;
870 	case TYPE_CHATSEND:	/* pchat */
871 		dcc_open_query (dcc->serv, dcc->nick);
872 	case TYPE_CHATRECV:	/* normal chat */
873 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc);
874 		dcc->dccchat = g_new0 (struct dcc_chat, 1);
875 		EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session,
876 						 dcc->nick, host, NULL, NULL, 0);
877 		break;
878 	}
879 	dcc->starttime = time (0);
880 	dcc->lasttime = dcc->starttime;
881 	fe_dcc_update (dcc);
882 
883 	return TRUE;
884 }
885 
886 static gboolean
read_proxy(struct DCC * dcc)887 read_proxy (struct DCC *dcc)
888 {
889 	struct proxy_state *proxy = dcc->proxy;
890 	while (proxy->bufferused < proxy->buffersize)
891 	{
892 		int ret = recv (dcc->sok, &proxy->buffer[proxy->bufferused],
893 						proxy->buffersize - proxy->bufferused, 0);
894 		if (ret > 0)
895 			proxy->bufferused += ret;
896 		else
897 		{
898 			if (would_block ())
899 				return FALSE;
900 			else
901 			{
902 				dcc->dccstat = STAT_FAILED;
903 				fe_dcc_update (dcc);
904 				if (dcc->iotag)
905 				{
906 					fe_input_remove (dcc->iotag);
907 					dcc->iotag = 0;
908 				}
909 				return FALSE;
910 			}
911 		}
912 	}
913 	return TRUE;
914 }
915 
916 static gboolean
write_proxy(struct DCC * dcc)917 write_proxy (struct DCC *dcc)
918 {
919 	struct proxy_state *proxy = dcc->proxy;
920 	while (proxy->bufferused < proxy->buffersize)
921 	{
922 		int ret = send (dcc->sok, &proxy->buffer[proxy->bufferused],
923 						proxy->buffersize - proxy->bufferused, 0);
924 		if (ret >= 0)
925 			proxy->bufferused += ret;
926 		else
927 		{
928 			if (would_block ())
929 				return FALSE;
930 			else
931 			{
932 				dcc->dccstat = STAT_FAILED;
933 				fe_dcc_update (dcc);
934 				if (dcc->wiotag)
935 				{
936 					fe_input_remove (dcc->wiotag);
937 					dcc->wiotag = 0;
938 				}
939 				return FALSE;
940 			}
941 		}
942 	}
943 	return TRUE;
944 }
945 
946 static gboolean
proxy_read_line(struct DCC * dcc)947 proxy_read_line (struct DCC *dcc)
948 {
949 	struct proxy_state *proxy = dcc->proxy;
950 	while (1)
951 	{
952 		proxy->buffersize = proxy->bufferused + 1;
953 		if (!read_proxy (dcc))
954 			return FALSE;
955 		if (proxy->buffer[proxy->bufferused - 1] == '\n'
956 			|| proxy->bufferused == MAX_PROXY_BUFFER)
957 		{
958 			proxy->buffer[proxy->bufferused - 1] = 0;
959 			return TRUE;
960 		}
961 	}
962 }
963 
964 static gboolean
dcc_wingate_proxy_traverse(GIOChannel * source,GIOCondition condition,struct DCC * dcc)965 dcc_wingate_proxy_traverse (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
966 {
967 	struct proxy_state *proxy = dcc->proxy;
968 	if (proxy->phase == 0)
969 	{
970 		proxy->buffersize = g_snprintf ((char*) proxy->buffer, MAX_PROXY_BUFFER,
971 										"%s %d\r\n", net_ip(dcc->addr),
972 										dcc->port);
973 		proxy->bufferused = 0;
974 		dcc->wiotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX,
975 									dcc_wingate_proxy_traverse, dcc);
976 		++proxy->phase;
977 	}
978 	if (proxy->phase == 1)
979 	{
980 		if (!read_proxy (dcc))
981 			return TRUE;
982 		fe_input_remove (dcc->wiotag);
983 		dcc->wiotag = 0;
984 		dcc_connect_finished (source, 0, dcc);
985 	}
986 	return TRUE;
987 }
988 
989 struct sock_connect
990 {
991 	char version;
992 	char type;
993 	guint16 port;
994 	guint32 address;
995 	char username[10];
996 };
997 static gboolean
dcc_socks_proxy_traverse(GIOChannel * source,GIOCondition condition,struct DCC * dcc)998 dcc_socks_proxy_traverse (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
999 {
1000 	struct proxy_state *proxy = dcc->proxy;
1001 
1002 	if (proxy->phase == 0)
1003 	{
1004 		struct sock_connect sc;
1005 		sc.version = 4;
1006 		sc.type = 1;
1007 		sc.port = htons (dcc->port);
1008 		sc.address = htonl (dcc->addr);
1009 		g_strlcpy (sc.username, prefs.hex_irc_user_name, sizeof (sc.username));
1010 		memcpy (proxy->buffer, &sc, sizeof (sc));
1011 		proxy->buffersize = 8 + strlen (sc.username) + 1;
1012 		proxy->bufferused = 0;
1013 		dcc->wiotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX,
1014 									dcc_socks_proxy_traverse, dcc);
1015 		++proxy->phase;
1016 	}
1017 
1018 	if (proxy->phase == 1)
1019 	{
1020 		if (!write_proxy (dcc))
1021 			return TRUE;
1022 		fe_input_remove (dcc->wiotag);
1023 		dcc->wiotag = 0;
1024 		proxy->bufferused = 0;
1025 		proxy->buffersize = 8;
1026 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX,
1027 									dcc_socks_proxy_traverse, dcc);
1028 		++proxy->phase;
1029 	}
1030 
1031 	if (proxy->phase == 2)
1032 	{
1033 		if (!read_proxy (dcc))
1034 			return TRUE;
1035 		fe_input_remove (dcc->iotag);
1036 		dcc->iotag = 0;
1037 		if (proxy->buffer[1] == 90)
1038 			dcc_connect_finished (source, 0, dcc);
1039 		else
1040 		{
1041 			dcc->dccstat = STAT_FAILED;
1042 			fe_dcc_update (dcc);
1043 		}
1044 	}
1045 
1046 	return TRUE;
1047 }
1048 
1049 struct sock5_connect1
1050 {
1051         char version;
1052         char nmethods;
1053         char method;
1054 };
1055 static gboolean
dcc_socks5_proxy_traverse(GIOChannel * source,GIOCondition condition,struct DCC * dcc)1056 dcc_socks5_proxy_traverse (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
1057 {
1058 	struct proxy_state *proxy = dcc->proxy;
1059 	int auth = prefs.hex_net_proxy_auth && prefs.hex_net_proxy_user[0] && prefs.hex_net_proxy_pass[0];
1060 
1061 	if (proxy->phase == 0)
1062 	{
1063 		struct sock5_connect1 sc1;
1064 
1065 		sc1.version = 5;
1066 		sc1.nmethods = 1;
1067 		sc1.method = 0;
1068 		if (auth)
1069 			sc1.method = 2;
1070 		memcpy (proxy->buffer, &sc1, 3);
1071 		proxy->buffersize = 3;
1072 		proxy->bufferused = 0;
1073 		dcc->wiotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX,
1074 									dcc_socks5_proxy_traverse, dcc);
1075 		++proxy->phase;
1076 	}
1077 
1078 	if (proxy->phase == 1)
1079 	{
1080 		if (!write_proxy (dcc))
1081 			return TRUE;
1082 		fe_input_remove (dcc->wiotag);
1083 		dcc->wiotag = 0;
1084 		proxy->bufferused = 0;
1085 		proxy->buffersize = 2;
1086 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX,
1087 									dcc_socks5_proxy_traverse, dcc);
1088 		++proxy->phase;
1089 	}
1090 
1091 	if (proxy->phase == 2)
1092 	{
1093 		if (!read_proxy (dcc))
1094 			return TRUE;
1095 		fe_input_remove (dcc->iotag);
1096 		dcc->iotag = 0;
1097 
1098 		/* did the server say no auth required? */
1099 		if (proxy->buffer[0] == 5 && proxy->buffer[1] == 0)
1100 			auth = 0;
1101 
1102 		/* Set up authentication I/O */
1103 		if (auth)
1104 		{
1105 			int len_u=0, len_p=0;
1106 
1107 			/* authentication sub-negotiation (RFC1929) */
1108 			if ( proxy->buffer[0] != 5 || proxy->buffer[1] != 2 )  /* UPA not supported by server */
1109 			{
1110 				PrintText (dcc->serv->front_session, "SOCKS\tServer doesn't support UPA authentication.\n");
1111 				dcc->dccstat = STAT_FAILED;
1112 				fe_dcc_update (dcc);
1113 				return TRUE;
1114 			}
1115 
1116 			memset (proxy->buffer, 0, MAX_PROXY_BUFFER);
1117 
1118 			/* form the UPA request */
1119 			len_u = strlen (prefs.hex_net_proxy_user);
1120 			len_p = strlen (prefs.hex_net_proxy_pass);
1121 			proxy->buffer[0] = 1;
1122 			proxy->buffer[1] = len_u;
1123 			memcpy (proxy->buffer + 2, prefs.hex_net_proxy_user, len_u);
1124 			proxy->buffer[2 + len_u] = len_p;
1125 			memcpy (proxy->buffer + 3 + len_u, prefs.hex_net_proxy_pass, len_p);
1126 
1127 			proxy->buffersize = 3 + len_u + len_p;
1128 			proxy->bufferused = 0;
1129 			dcc->wiotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX,
1130 										dcc_socks5_proxy_traverse, dcc);
1131 			++proxy->phase;
1132 		}
1133 		else
1134 		{
1135 			if (proxy->buffer[0] != 5 || proxy->buffer[1] != 0)
1136 			{
1137 				PrintText (dcc->serv->front_session, "SOCKS\tAuthentication required but disabled in settings.\n");
1138 				dcc->dccstat = STAT_FAILED;
1139 				fe_dcc_update (dcc);
1140 				return TRUE;
1141 			}
1142 			proxy->phase += 2;
1143 		}
1144 	}
1145 
1146 	if (proxy->phase == 3)
1147 	{
1148 		if (!write_proxy (dcc))
1149 			return TRUE;
1150 		fe_input_remove (dcc->wiotag);
1151 		dcc->wiotag = 0;
1152 		proxy->buffersize = 2;
1153 		proxy->bufferused = 0;
1154 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX,
1155 									dcc_socks5_proxy_traverse, dcc);
1156 		++proxy->phase;
1157 	}
1158 
1159 	if (proxy->phase == 4)
1160 	{
1161 		if (!read_proxy (dcc))
1162 			return TRUE;
1163 		if (dcc->iotag)
1164 		{
1165 			fe_input_remove (dcc->iotag);
1166 			dcc->iotag = 0;
1167 		}
1168 		if (proxy->buffer[1] != 0)
1169 		{
1170 			PrintText (dcc->serv->front_session, "SOCKS\tAuthentication failed. "
1171 							 "Is username and password correct?\n");
1172 			dcc->dccstat = STAT_FAILED;
1173 			fe_dcc_update (dcc);
1174 			return TRUE;
1175 		}
1176 		++proxy->phase;
1177 	}
1178 
1179 	if (proxy->phase == 5)
1180 	{
1181 		proxy->buffer[0] = 5;	/* version (socks 5) */
1182 		proxy->buffer[1] = 1;	/* command (connect) */
1183 		proxy->buffer[2] = 0;	/* reserved */
1184 		proxy->buffer[3] = 1;	/* address type (IPv4) */
1185 		proxy->buffer[4] = (dcc->addr >> 24) & 0xFF;	/* IP address */
1186 		proxy->buffer[5] = (dcc->addr >> 16) & 0xFF;
1187 		proxy->buffer[6] = (dcc->addr >> 8) & 0xFF;
1188 		proxy->buffer[7] = (dcc->addr & 0xFF);
1189 		proxy->buffer[8] = (dcc->port >> 8) & 0xFF;		/* port */
1190 		proxy->buffer[9] = (dcc->port & 0xFF);
1191 		proxy->buffersize = 10;
1192 		proxy->bufferused = 0;
1193 		dcc->wiotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX,
1194 									dcc_socks5_proxy_traverse, dcc);
1195 		++proxy->phase;
1196 	}
1197 
1198 	if (proxy->phase == 6)
1199 	{
1200 		if (!write_proxy (dcc))
1201 			return TRUE;
1202 		fe_input_remove (dcc->wiotag);
1203 		dcc->wiotag = 0;
1204 		proxy->buffersize = 4;
1205 		proxy->bufferused = 0;
1206 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX,
1207 									dcc_socks5_proxy_traverse, dcc);
1208 		++proxy->phase;
1209 	}
1210 
1211 	if (proxy->phase == 7)
1212 	{
1213 		if (!read_proxy (dcc))
1214 			return TRUE;
1215 		if (proxy->buffer[0] != 5 || proxy->buffer[1] != 0)
1216 		{
1217 			fe_input_remove (dcc->iotag);
1218 			dcc->iotag = 0;
1219 			if (proxy->buffer[1] == 2)
1220 				PrintText (dcc->serv->front_session, "SOCKS\tProxy refused to connect to host (not allowed).\n");
1221 			else
1222 				PrintTextf (dcc->serv->front_session, "SOCKS\tProxy failed to connect to host (error %d).\n", proxy->buffer[1]);
1223 			dcc->dccstat = STAT_FAILED;
1224 			fe_dcc_update (dcc);
1225 			return TRUE;
1226 		}
1227 		switch (proxy->buffer[3])
1228 		{
1229 			case 1: proxy->buffersize += 6; break;
1230 			case 3: proxy->buffersize += 1; break;
1231 			case 4: proxy->buffersize += 18; break;
1232 		};
1233 		++proxy->phase;
1234 	}
1235 
1236 	if (proxy->phase == 8)
1237 	{
1238 		if (!read_proxy (dcc))
1239 			return TRUE;
1240 		/* handle domain name case */
1241 		if (proxy->buffer[3] == 3)
1242 		{
1243 			proxy->buffersize = 5 + proxy->buffer[4] + 2;
1244 		}
1245 		/* everything done? */
1246 		if (proxy->bufferused == proxy->buffersize)
1247 		{
1248 			fe_input_remove (dcc->iotag);
1249 			dcc->iotag = 0;
1250 			dcc_connect_finished (source, 0, dcc);
1251 		}
1252 	}
1253 	return TRUE;
1254 }
1255 
1256 static gboolean
dcc_http_proxy_traverse(GIOChannel * source,GIOCondition condition,struct DCC * dcc)1257 dcc_http_proxy_traverse (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
1258 {
1259 	struct proxy_state *proxy = dcc->proxy;
1260 
1261 	if (proxy->phase == 0)
1262 	{
1263 		char buf[256];
1264 		char auth_data[128];
1265 		char auth_data2[68];
1266 		int n, n2;
1267 
1268 		n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n",
1269                                           net_ip(dcc->addr), dcc->port);
1270 		if (prefs.hex_net_proxy_auth)
1271 		{
1272 			n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s",
1273 							prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass);
1274 			base64_encode (auth_data, auth_data2, n2);
1275 			n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data);
1276 		}
1277 		n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n");
1278 		proxy->buffersize = n;
1279 		proxy->bufferused = 0;
1280 		memcpy (proxy->buffer, buf, proxy->buffersize);
1281 		dcc->wiotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX,
1282 									dcc_http_proxy_traverse, dcc);
1283 		++proxy->phase;
1284 	}
1285 
1286 	if (proxy->phase == 1)
1287 	{
1288 		if (!write_proxy (dcc))
1289 			return TRUE;
1290 		fe_input_remove (dcc->wiotag);
1291 		dcc->wiotag = 0;
1292 		proxy->bufferused = 0;
1293 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX,
1294 										dcc_http_proxy_traverse, dcc);
1295 		++proxy->phase;
1296 	}
1297 
1298 	if (proxy->phase == 2)
1299 	{
1300 		if (!proxy_read_line (dcc))
1301 			return TRUE;
1302 		/* "HTTP/1.0 200 OK" */
1303 		if (proxy->bufferused < 12 ||
1304 			 memcmp (proxy->buffer, "HTTP/", 5) || memcmp (proxy->buffer + 9, "200", 3))
1305 		{
1306 			fe_input_remove (dcc->iotag);
1307 			dcc->iotag = 0;
1308 			PrintText (dcc->serv->front_session, proxy->buffer);
1309 			dcc->dccstat = STAT_FAILED;
1310 			fe_dcc_update (dcc);
1311 			return TRUE;
1312 		}
1313 		proxy->bufferused = 0;
1314 		++proxy->phase;
1315 	}
1316 
1317 	if (proxy->phase == 3)
1318 	{
1319 		while (1)
1320 		{
1321 			/* read until blank line */
1322 			if (proxy_read_line (dcc))
1323 			{
1324 				if (proxy->bufferused < 1 ||
1325 					(proxy->bufferused == 2 && proxy->buffer[0] == '\r'))
1326 				{
1327 					break;
1328 				}
1329 				if (proxy->bufferused > 1)
1330 					PrintText (dcc->serv->front_session, proxy->buffer);
1331 				proxy->bufferused = 0;
1332 			}
1333 			else
1334 				return TRUE;
1335 		}
1336 		fe_input_remove (dcc->iotag);
1337 		dcc->iotag = 0;
1338 		dcc_connect_finished (source, 0, dcc);
1339 	}
1340 
1341 	return TRUE;
1342 }
1343 
1344 static gboolean
dcc_proxy_connect(GIOChannel * source,GIOCondition condition,struct DCC * dcc)1345 dcc_proxy_connect (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
1346 {
1347 	fe_input_remove (dcc->iotag);
1348 	dcc->iotag = 0;
1349 
1350 	if (!dcc_did_connect (source, condition, dcc))
1351 		return TRUE;
1352 
1353 	dcc->proxy = g_new0 (struct proxy_state, 1);
1354 
1355 	switch (prefs.hex_net_proxy_type)
1356 	{
1357 		case 1: return dcc_wingate_proxy_traverse (source, condition, dcc);
1358 		case 2: return dcc_socks_proxy_traverse (source, condition, dcc);
1359 		case 3: return dcc_socks5_proxy_traverse (source, condition, dcc);
1360 		case 4: return dcc_http_proxy_traverse (source, condition, dcc);
1361 	}
1362 	return TRUE;
1363 }
1364 
1365 static int dcc_listen_init (struct DCC *, struct session *);
1366 
1367 static void
dcc_connect(struct DCC * dcc)1368 dcc_connect (struct DCC *dcc)
1369 {
1370 	int ret;
1371 	char tbuf[400];
1372 
1373 	if (dcc->dccstat == STAT_CONNECTING)
1374 		return;
1375 	dcc->dccstat = STAT_CONNECTING;
1376 
1377 	if (dcc->pasvid && dcc->port == 0)
1378 	{
1379 		/* accepted a passive dcc send */
1380 		ret = dcc_listen_init (dcc, dcc->serv->front_session);
1381 		if (!ret)
1382 		{
1383 			dcc_close (dcc, STAT_FAILED, FALSE);
1384 			return;
1385 		}
1386 		/* possible problems with filenames containing spaces? */
1387 		if (dcc->type == TYPE_RECV)
1388 			g_snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
1389 					"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT " %d" :
1390 					"DCC SEND %s %u %d %" G_GUINT64_FORMAT " %d", dcc->file,
1391 					dcc->addr, dcc->port, dcc->size, dcc->pasvid);
1392 		else
1393 			g_snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d",
1394 				dcc->addr, dcc->port, dcc->pasvid);
1395 		dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
1396 	}
1397 	else
1398 	{
1399 		dcc->sok = dcc_connect_sok (dcc);
1400 		if (dcc->sok == -1)
1401 		{
1402 			dcc->dccstat = STAT_FAILED;
1403 			fe_dcc_update (dcc);
1404 			return;
1405 		}
1406 		if (DCC_USE_PROXY ())
1407 			dcc->iotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX, dcc_proxy_connect, dcc);
1408 		else
1409 			dcc->iotag = fe_input_add (dcc->sok, FIA_WRITE|FIA_EX, dcc_connect_finished, dcc);
1410 	}
1411 
1412 	fe_dcc_update (dcc);
1413 }
1414 
1415 static gboolean
dcc_send_data(GIOChannel * source,GIOCondition condition,struct DCC * dcc)1416 dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
1417 {
1418 	char *buf;
1419 	int len, sent, sok = dcc->sok;
1420 
1421 	if (prefs.hex_dcc_blocksize < 1) /* this is too little! */
1422 		prefs.hex_dcc_blocksize = 1024;
1423 
1424 	if (prefs.hex_dcc_blocksize > 102400)	/* this is too much! */
1425 		prefs.hex_dcc_blocksize = 102400;
1426 
1427 	if (dcc->throttled)
1428 	{
1429 		fe_input_remove (dcc->wiotag);
1430 		dcc->wiotag = 0;
1431 		return FALSE;
1432 	}
1433 
1434 	if (!dcc->fastsend)
1435 	{
1436 		if (dcc->ack < (dcc->pos & 0xFFFFFFFF))
1437 			return TRUE;
1438 	}
1439 	else if (!dcc->wiotag)
1440 		dcc->wiotag = fe_input_add (sok, FIA_WRITE, dcc_send_data, dcc);
1441 
1442 	buf = g_malloc (prefs.hex_dcc_blocksize);
1443 
1444 	lseek (dcc->fp, dcc->pos, SEEK_SET);
1445 	len = read (dcc->fp, buf, prefs.hex_dcc_blocksize);
1446 	if (len < 1)
1447 		goto abortit;
1448 	sent = send (sok, buf, len, 0);
1449 
1450 	if (sent < 0 && !(would_block ()))
1451 	{
1452 abortit:
1453 		g_free (buf);
1454 		EMIT_SIGNAL (XP_TE_DCCSENDFAIL, dcc->serv->front_session,
1455 						 file_part (dcc->file), dcc->nick,
1456 						 errorstring (sock_error ()), NULL, 0);
1457 		dcc_close (dcc, STAT_FAILED, FALSE);
1458 		return TRUE;
1459 	}
1460 	if (sent > 0)
1461 	{
1462 		dcc->pos += sent;
1463 		dcc->lasttime = time (0);
1464 	}
1465 
1466 	/* have we sent it all yet? */
1467 	if (dcc->pos >= dcc->size)
1468 	{
1469 		/* it's all sent now, so remove the WRITE/SEND handler */
1470 		if (dcc->wiotag)
1471 		{
1472 			fe_input_remove (dcc->wiotag);
1473 			dcc->wiotag = 0;
1474 		}
1475 	}
1476 
1477 	g_free (buf);
1478 
1479 	return TRUE;
1480 }
1481 
1482 static gboolean
dcc_handle_new_ack(struct DCC * dcc)1483 dcc_handle_new_ack (struct DCC *dcc)
1484 {
1485 	guint32 ack;
1486 	char buf[16];
1487 	gboolean done = FALSE;
1488 
1489 	memcpy (&ack, dcc->ack_buf, 4);
1490 	dcc->ack = ntohl (ack);
1491 
1492 	/* this could mess up when xfering >32bit files */
1493 	if (dcc->size <= 0xffffffff)
1494 	{
1495 		/* fix for BitchX */
1496 		if (dcc->ack < dcc->resumable)
1497 			dcc->ackoffset = TRUE;
1498 		if (dcc->ackoffset)
1499 			dcc->ack += dcc->resumable;
1500 	}
1501 
1502 	/* DCC complete check */
1503 	if (dcc->pos >= dcc->size && dcc->ack >= (dcc->size & 0xffffffff))
1504 	{
1505 		dcc->ack = dcc->size;	/* force 100% ack for >4 GB */
1506 		dcc_close (dcc, STAT_DONE, FALSE);
1507 		dcc_calc_average_cps (dcc);	/* this must be done _after_ dcc_close, or dcc_remove_from_sum will see the wrong value in dcc->cps */
1508 		/* cppcheck-suppress deallocuse */
1509 		sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
1510 		EMIT_SIGNAL (XP_TE_DCCSENDCOMP, dcc->serv->front_session,
1511 						 file_part (dcc->file), dcc->nick, buf, NULL, 0);
1512 		done = TRUE;
1513 	}
1514 	else if ((!dcc->fastsend) && (dcc->ack >= (dcc->pos & 0xffffffff)))
1515 	{
1516 		dcc_send_data (NULL, 0, (gpointer)dcc);
1517 	}
1518 
1519 	/* take the top 32 of "bytes send" and bottom 32 of "ack" */
1520 	dcc->ack = (dcc->pos & G_GINT64_CONSTANT (0xffffffff00000000)) |
1521 					(dcc->ack & 0xffffffff);
1522 	/* dcc->ack is only used for CPS and PERCENTAGE calcs from now on... */
1523 
1524 	return done;
1525 }
1526 
1527 static gboolean
dcc_read_ack(GIOChannel * source,GIOCondition condition,struct DCC * dcc)1528 dcc_read_ack (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
1529 {
1530 	int len;
1531 
1532 	while (1)
1533 	{
1534 		/* try to fill up 4 bytes */
1535 		len = recv (dcc->sok, dcc->ack_buf, 4 - dcc->ack_pos, 0);
1536 		if (len < 1)
1537 		{
1538 			if (len < 0)
1539 			{
1540 				if (would_block ())	/* ok - keep waiting */
1541 					return TRUE;
1542 			}
1543 			EMIT_SIGNAL (XP_TE_DCCSENDFAIL, dcc->serv->front_session,
1544 							 file_part (dcc->file), dcc->nick,
1545 							 errorstring ((len < 0) ? sock_error () : 0), NULL, 0);
1546 			dcc_close (dcc, STAT_FAILED, FALSE);
1547 			return TRUE;
1548 		}
1549 
1550 		dcc->ack_pos += len;
1551 		if (dcc->ack_pos >= 4)
1552 		{
1553 			dcc->ack_pos = 0;
1554 			if (dcc_handle_new_ack (dcc))
1555 				return TRUE;
1556 		}
1557 		/* loop again until would_block() returns true */
1558 	}
1559 }
1560 
1561 static gboolean
dcc_accept(GIOChannel * source,GIOCondition condition,struct DCC * dcc)1562 dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
1563 {
1564 	char host[128];
1565 	struct sockaddr_in CAddr;
1566 	int sok;
1567 	socklen_t len;
1568 
1569 	len = sizeof (CAddr);
1570 	sok = accept (dcc->sok, (struct sockaddr *) &CAddr, &len);
1571 	fe_input_remove (dcc->iotag);
1572 	dcc->iotag = 0;
1573 	closesocket (dcc->sok);
1574 	if (sok < 0)
1575 	{
1576 		dcc->sok = -1;
1577 		dcc_close (dcc, STAT_FAILED, FALSE);
1578 		return TRUE;
1579 	}
1580 	set_nonblocking (sok);
1581 	dcc->sok = sok;
1582 	dcc->addr = ntohl (CAddr.sin_addr.s_addr);
1583 
1584 	if (dcc->pasvid)
1585 		return dcc_connect_finished (NULL, 0, dcc);
1586 
1587 	dcc->dccstat = STAT_ACTIVE;
1588 	dcc->lasttime = dcc->starttime = time (0);
1589 	dcc->fastsend = prefs.hex_dcc_fast_send;
1590 
1591 	g_snprintf (host, sizeof (host), "%s:%d", net_ip (dcc->addr), dcc->port);
1592 
1593 	switch (dcc->type)
1594 	{
1595 	case TYPE_SEND:
1596 		if (dcc->fastsend)
1597 			dcc->wiotag = fe_input_add (sok, FIA_WRITE, dcc_send_data, dcc);
1598 		dcc->iotag = fe_input_add (sok, FIA_READ|FIA_EX, dcc_read_ack, dcc);
1599 		dcc_send_data (NULL, 0, (gpointer)dcc);
1600 		EMIT_SIGNAL (XP_TE_DCCCONSEND, dcc->serv->front_session,
1601 						 dcc->nick, host, dcc->file, NULL, 0);
1602 		break;
1603 
1604 	case TYPE_CHATSEND:
1605 		dcc_open_query (dcc->serv, dcc->nick);
1606 		dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc);
1607 		dcc->dccchat = g_new0 (struct dcc_chat, 1);
1608 		EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session,
1609 						 dcc->nick, host, NULL, NULL, 0);
1610 		break;
1611 	default:
1612 		break;
1613 	}
1614 
1615 	fe_dcc_update (dcc);
1616 
1617 	return TRUE;
1618 }
1619 
1620 guint32
dcc_get_my_address(session * sess)1621 dcc_get_my_address (session *sess)	/* the address we'll tell the other person */
1622 {
1623 	struct hostent *dns_query;
1624 	guint32 addr = 0;
1625 
1626 	if (prefs.hex_dcc_ip_from_server && sess->server->dcc_ip)
1627 		addr = sess->server->dcc_ip;
1628 	else if (prefs.hex_dcc_ip[0])
1629 	{
1630 	   dns_query = gethostbyname ((const char *) prefs.hex_dcc_ip);
1631 
1632 	   if (dns_query != NULL &&
1633 	       dns_query->h_length == 4 &&
1634 	       dns_query->h_addr_list[0] != NULL)
1635 		{
1636 			/*we're offered at least one IPv4 address: we take the first*/
1637 			addr = *((guint32*) dns_query->h_addr_list[0]);
1638 		}
1639 	}
1640 
1641 	return addr;
1642 }
1643 
1644 static int
dcc_listen_init(struct DCC * dcc,session * sess)1645 dcc_listen_init (struct DCC *dcc, session *sess)
1646 {
1647 	guint32 my_addr;
1648 	struct sockaddr_in SAddr;
1649 	int i, bindretval = -1;
1650 	socklen_t len;
1651 
1652 	dcc->sok = socket (AF_INET, SOCK_STREAM, 0);
1653 	if (dcc->sok == -1)
1654 		return FALSE;
1655 
1656 	memset (&SAddr, 0, sizeof (struct sockaddr_in));
1657 
1658 	len = sizeof (SAddr);
1659 	getsockname (dcc->serv->sok, (struct sockaddr *) &SAddr, &len);
1660 
1661 	SAddr.sin_family = AF_INET;
1662 
1663 	/*if local_ip is specified use that*/
1664 	if (prefs.local_ip != 0xffffffff)
1665 	{
1666 		my_addr = prefs.local_ip;
1667 		SAddr.sin_addr.s_addr = prefs.local_ip;
1668 	}
1669 	/*otherwise use the default*/
1670 	else
1671 		my_addr = SAddr.sin_addr.s_addr;
1672 
1673 	/*if we have a valid portrange try to use that*/
1674 	if (prefs.hex_dcc_port_first > 0)
1675 	{
1676 		SAddr.sin_port = 0;
1677 		i = 0;
1678 		while ((prefs.hex_dcc_port_last > ntohs(SAddr.sin_port)) &&
1679 				(bindretval == -1))
1680 		{
1681 			SAddr.sin_port = htons (prefs.hex_dcc_port_first + i);
1682 			i++;
1683 			/*printf("Trying to bind against port: %d\n",ntohs(SAddr.sin_port));*/
1684 			bindretval = bind (dcc->sok, (struct sockaddr *) &SAddr, sizeof (SAddr));
1685 		}
1686 
1687 		/* with a small port range, reUseAddr is needed */
1688 		len = 1;
1689 		setsockopt (dcc->sok, SOL_SOCKET, SO_REUSEADDR, (char *) &len, sizeof (len));
1690 
1691 	} else
1692 	{
1693 		/* try random port */
1694 		SAddr.sin_port = 0;
1695 		bindretval = bind (dcc->sok, (struct sockaddr *) &SAddr, sizeof (SAddr));
1696 	}
1697 
1698 	if (bindretval == -1)
1699 	{
1700 		/* failed to bind */
1701 		PrintText (sess, "Failed to bind to any address or port.\n");
1702 		return FALSE;
1703 	}
1704 
1705 	len = sizeof (SAddr);
1706 	getsockname (dcc->sok, (struct sockaddr *) &SAddr, &len);
1707 
1708 	dcc->port = ntohs (SAddr.sin_port);
1709 
1710 	/*if we have a dcc_ip, we use that, so the remote client can connect*/
1711 	/*else we try to take an address from hex_dcc_ip*/
1712 	/*if something goes wrong we tell the client to connect to our LAN ip*/
1713 	dcc->addr = dcc_get_my_address (sess);
1714 
1715 	/*if nothing else worked we use the address we bound to*/
1716 	if (dcc->addr == 0)
1717 	   dcc->addr = my_addr;
1718 
1719 	dcc->addr = ntohl (dcc->addr);
1720 
1721 	set_nonblocking (dcc->sok);
1722 	listen (dcc->sok, 1);
1723 	set_blocking (dcc->sok);
1724 
1725 	dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_accept, dcc);
1726 
1727 	return TRUE;
1728 }
1729 
1730 static struct session *dccsess;
1731 static char *dccto;				  /* lame!! */
1732 static gint64 dccmaxcps;
1733 static int recursive = FALSE;
1734 
1735 static void
dcc_send_wild(char * file)1736 dcc_send_wild (char *file)
1737 {
1738 	dcc_send (dccsess, dccto, file, dccmaxcps, 0);
1739 }
1740 
1741 void
dcc_send(struct session * sess,char * to,char * filename,gint64 maxcps,int passive)1742 dcc_send (struct session *sess, char *to, char *filename, gint64 maxcps, int passive)
1743 {
1744 	char outbuf[512];
1745 	GFileInfo *file_info;
1746 	GFile *file;
1747 	struct DCC *dcc;
1748 	gchar *filename_fs;
1749 	GFileType file_type;
1750 	goffset file_size;
1751 
1752 	filename = expand_homedir (filename);
1753 
1754 	if (!recursive && (strchr (filename, '*') || strchr (filename, '?')))
1755 	{
1756 		char path[256];
1757 		char wild[256];
1758 
1759 		safe_strcpy (wild, file_part (filename), sizeof (wild));
1760 		path_part (filename, path, sizeof (path));
1761 		if (path[0] != '/' || path[1] != '\0')
1762 			path[strlen (path) - 1] = 0;	/* remove trailing slash */
1763 
1764 		dccsess = sess;
1765 		dccto = to;
1766 		dccmaxcps = maxcps;
1767 
1768 		g_free (filename);
1769 
1770 		recursive = TRUE;
1771 		for_files (path, wild, dcc_send_wild);
1772 		recursive = FALSE;
1773 
1774 		return;
1775 	}
1776 
1777 	dcc = new_dcc ();
1778 	if (!dcc)
1779 	{
1780 		g_free (filename);
1781 		return;
1782 	}
1783 
1784 	dcc->file = filename;
1785 	dcc->maxcps = maxcps;
1786 
1787 	filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
1788 	if (filename_fs == NULL)
1789 	{
1790 		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
1791 		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
1792 
1793 		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
1794 
1795 		return;
1796 	}
1797 
1798 	file = g_file_new_for_path (filename_fs);
1799 	if (file == NULL)
1800 	{
1801 		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
1802 		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
1803 
1804 		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
1805 
1806 		g_free (filename_fs);
1807 
1808 		return;
1809 	}
1810 
1811 	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
1812 
1813 	g_object_unref (file);
1814 
1815 	if (file_info == NULL)
1816 	{
1817 		PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
1818 		PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
1819 
1820 		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
1821 
1822 		g_free (filename_fs);
1823 
1824 		return;
1825 	}
1826 
1827 	file_type = g_file_info_get_file_type (file_info);
1828 	file_size = g_file_info_get_size (file_info);
1829 
1830 	g_object_unref (file_info);
1831 
1832 	if (*file_part (filename) == '\0' || file_type == G_FILE_TYPE_DIRECTORY || file_size <= 0)
1833 	{
1834 		PrintText (sess, "Cannot send directories or empty files.\n");
1835 
1836 		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
1837 
1838 		g_free (filename_fs);
1839 
1840 		return;
1841 	}
1842 
1843 	dcc->starttime = dcc->offertime = time (0);
1844 	dcc->serv = sess->server;
1845 	dcc->dccstat = STAT_QUEUED;
1846 	dcc->size = file_size;
1847 	dcc->type = TYPE_SEND;
1848 	dcc->fp = g_open (filename_fs, OFLAGS | O_RDONLY, 0);
1849 
1850 	g_free (filename_fs);
1851 
1852 	if (dcc->fp == -1)
1853 	{
1854 		PrintText (sess, "Cannot send directories or empty files.\n");
1855 
1856 		dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
1857 
1858 		return;
1859 	}
1860 
1861 	if (passive || dcc_listen_init (dcc, sess))
1862 	{
1863 		char havespaces = 0;
1864 		while (*filename)
1865 		{
1866 			if (*filename == ' ')
1867 			{
1868 				if (prefs.hex_dcc_send_fillspaces)
1869 				    *filename = '_';
1870 				else
1871 				havespaces = 1;
1872 			}
1873 			filename++;
1874 		}
1875 		dcc->nick = g_strdup (to);
1876 		if (prefs.hex_gui_autoopen_send)
1877 		{
1878 			if (fe_dcc_open_send_win (TRUE))	/* already open? add */
1879 				fe_dcc_add (dcc);
1880 		} else
1881 			fe_dcc_add (dcc);
1882 
1883 		if (passive)
1884 		{
1885 			dcc->pasvid = new_id();
1886 			g_snprintf (outbuf, sizeof (outbuf), (havespaces) ?
1887 					"DCC SEND \"%s\" 199 0 %" G_GUINT64_FORMAT " %d" :
1888 					"DCC SEND %s 199 0 %" G_GUINT64_FORMAT " %d",
1889 					file_part (dcc->file),
1890 					dcc->size, dcc->pasvid);
1891 		}
1892 		else
1893 		{
1894 			g_snprintf (outbuf, sizeof (outbuf), (havespaces) ?
1895 					"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT :
1896 					"DCC SEND %s %u %d %" G_GUINT64_FORMAT,
1897 					file_part (dcc->file), dcc->addr,
1898 					dcc->port, dcc->size);
1899 		}
1900 		sess->server->p_ctcp (sess->server, to, outbuf);
1901 
1902 		EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file),
1903 							to, dcc->file, NULL, 0);
1904 	}
1905 	else
1906 	{
1907 		dcc_close (dcc, 0, TRUE);
1908 	}
1909 }
1910 
1911 static struct DCC *
find_dcc_from_id(int id,int type)1912 find_dcc_from_id (int id, int type)
1913 {
1914 	struct DCC *dcc;
1915 	GSList *list = dcc_list;
1916 	while (list)
1917 	{
1918 		dcc = (struct DCC *) list->data;
1919 		if (dcc->pasvid == id &&
1920 			 dcc->dccstat == STAT_QUEUED && dcc->type == type)
1921 		return dcc;
1922 		list = list->next;
1923 	}
1924 	return NULL;
1925 }
1926 
1927 static struct DCC *
find_dcc_from_port(int port,int type)1928 find_dcc_from_port (int port, int type)
1929 {
1930 	struct DCC *dcc;
1931 	GSList *list = dcc_list;
1932 	while (list)
1933 	{
1934 		dcc = (struct DCC *) list->data;
1935 		if (dcc->port == port &&
1936 			 dcc->dccstat == STAT_QUEUED && dcc->type == type)
1937 			return dcc;
1938 		list = list->next;
1939 	}
1940 	return NULL;
1941 }
1942 
1943 struct DCC *
find_dcc(char * nick,char * file,int type)1944 find_dcc (char *nick, char *file, int type)
1945 {
1946 	GSList *list = dcc_list;
1947 	struct DCC *dcc;
1948 	while (list)
1949 	{
1950 		dcc = (struct DCC *) list->data;
1951 		if (nick == NULL || !rfc_casecmp (nick, dcc->nick))
1952 		{
1953 			if (type == -1 || dcc->type == type)
1954 			{
1955 				if (!file[0])
1956 					return dcc;
1957 				if (!g_ascii_strcasecmp (file, file_part (dcc->file)))
1958 					return dcc;
1959 				if (!g_ascii_strcasecmp (file, dcc->file))
1960 					return dcc;
1961 			}
1962 		}
1963 		list = list->next;
1964 	}
1965 	return NULL;
1966 }
1967 
1968 /* called when we receive a NICK change from server */
1969 
1970 void
dcc_change_nick(struct server * serv,char * oldnick,char * newnick)1971 dcc_change_nick (struct server *serv, char *oldnick, char *newnick)
1972 {
1973 	struct DCC *dcc;
1974 	GSList *list = dcc_list;
1975 
1976 	while (list)
1977 	{
1978 		dcc = (struct DCC *) list->data;
1979 		if (dcc->serv == serv)
1980 		{
1981 			if (!serv->p_cmp (dcc->nick, oldnick))
1982 			{
1983 				g_free (dcc->nick);
1984 				dcc->nick = g_strdup (newnick);
1985 			}
1986 		}
1987 		list = list->next;
1988 	}
1989 }
1990 
1991 /* is the destination file the same? new_dcc is not opened yet */
1992 
1993 static gboolean
is_same_file(struct DCC * dcc,struct DCC * new_dcc)1994 is_same_file (struct DCC *dcc, struct DCC *new_dcc)
1995 {
1996 	gboolean result = FALSE;
1997 	gchar *filename_fs = NULL, *new_filename_fs = NULL;
1998 	GFile *file = NULL, *new_file = NULL;
1999 	GFileInfo *file_info = NULL, *new_file_info = NULL;
2000 	char *file_id = NULL, *new_file_id = NULL;
2001 	char *filesystem_id = NULL, *new_filesystem_id = NULL;
2002 
2003 	/* if it's the same filename, must be same */
2004 	if (strcmp (dcc->destfile, new_dcc->destfile) == 0)
2005 	{
2006 		return TRUE;
2007 	}
2008 
2009 	filename_fs = g_filename_from_utf8 (dcc->file, -1, NULL, NULL, NULL);
2010 	if (filename_fs == NULL)
2011 	{
2012 		goto exit;
2013 	}
2014 
2015 	new_filename_fs = g_filename_from_utf8 (new_dcc->file, -1, NULL, NULL, NULL);
2016 	if (new_filename_fs == NULL)
2017 	{
2018 		goto exit;
2019 	}
2020 
2021 	file = g_file_new_for_path (filename_fs);
2022 	if (file == NULL)
2023 	{
2024 		goto exit;
2025 	}
2026 
2027 	new_file = g_file_new_for_path (new_filename_fs);
2028 	if (new_file == NULL)
2029 	{
2030 		goto exit;
2031 	}
2032 
2033 	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NONE, NULL, NULL);
2034 	if (file_info == NULL)
2035 	{
2036 		goto exit;
2037 	}
2038 
2039 	new_file_info = g_file_query_info (new_file, G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NONE, NULL, NULL);
2040 	if (new_file_info == NULL)
2041 	{
2042 		goto exit;
2043 	}
2044 
2045 	file_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
2046 	new_file_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
2047 
2048 	filesystem_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
2049 	new_filesystem_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
2050 
2051 	if (file_id != NULL && new_file_id != NULL && filesystem_id != NULL && new_filesystem_id != NULL && strcmp (file_id, new_file_id) == 0 && strcmp (filesystem_id, new_filesystem_id) == 0)
2052 	{
2053 		result = TRUE;
2054 	}
2055 
2056 exit:
2057 	g_free (filename_fs);
2058 	g_free (new_filename_fs);
2059 
2060 	if (file != NULL)
2061 	{
2062 		g_object_unref (file);
2063 	}
2064 
2065 	if (new_file != NULL)
2066 	{
2067 		g_object_unref (new_file);
2068 	}
2069 
2070 	if (file_info != NULL)
2071 	{
2072 		g_object_unref (file_info);
2073 	}
2074 
2075 	if (new_file_info != NULL)
2076 	{
2077 		g_object_unref (new_file_info);
2078 	}
2079 
2080 	g_free (file_id);
2081 	g_free (new_file_id);
2082 	g_free(filesystem_id);
2083 	g_free(new_filesystem_id);
2084 
2085 	return result;
2086 }
2087 
2088 static void
update_is_resumable(struct DCC * dcc)2089 update_is_resumable (struct DCC *dcc)
2090 {
2091 	gchar *filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
2092 
2093 	dcc->resumable = 0;
2094 
2095 	/* Check the file size */
2096 	if (filename_fs != NULL && g_access(filename_fs, W_OK) == 0)
2097 	{
2098 		GFile *file = g_file_new_for_path (filename_fs);
2099 		if (file != NULL)
2100 		{
2101 			GFileInfo *file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
2102 
2103 			if (file_info != NULL)
2104 			{
2105 				goffset file_size_offset = g_file_info_get_size (file_info);
2106 				guint64 file_size = (file_size_offset >= 0) ? (guint64) file_size_offset : 0;
2107 				if (file_size < dcc->size)
2108 				{
2109 					dcc->resumable = file_size;
2110 					dcc->pos = file_size;
2111 				}
2112 				else
2113 				{
2114 					dcc->resume_error = 2;
2115 				}
2116 
2117 				g_object_unref (file_info);
2118 			}
2119 			else
2120 			{
2121 				dcc->resume_errno = errno;
2122 				dcc->resume_error = 1;
2123 			}
2124 
2125 			g_object_unref(file);
2126 		}
2127 		else
2128 		{
2129 			dcc->resume_errno = errno;
2130 			dcc->resume_error = 1;
2131 		}
2132 	}
2133 	else
2134 	{
2135 		dcc->resume_errno = errno;
2136 		dcc->resume_error = 1;
2137 	}
2138 
2139 	g_free (filename_fs);
2140 
2141 	/* Now verify that this DCC is not already in progress from someone else */
2142 	if (dcc->resumable)
2143 	{
2144 		GSList *list = dcc_list;
2145 		struct DCC *d;
2146 		while (list)
2147 		{
2148 			d = list->data;
2149 			if (d->type == TYPE_RECV && d->dccstat != STAT_ABORTED &&
2150 				 d->dccstat != STAT_DONE && d->dccstat != STAT_FAILED &&
2151 				 d->dccstat != STAT_QUEUED)
2152 			{
2153 				if (d != dcc && is_same_file (d, dcc))
2154 				{
2155 					dcc->resume_error = 3;	/* dccgui.c uses it */
2156 					dcc->resumable = 0;
2157 					dcc->pos = 0;
2158 					break;
2159 				}
2160 			}
2161 			list = list->next;
2162 		}
2163 	}
2164 }
2165 
2166 void
dcc_get(struct DCC * dcc)2167 dcc_get (struct DCC *dcc)
2168 {
2169 	switch (dcc->dccstat)
2170 	{
2171 	case STAT_QUEUED:
2172 		if (dcc->type != TYPE_CHATSEND)
2173 		{
2174 			if (dcc->type == TYPE_RECV && prefs.hex_dcc_auto_resume && dcc->resumable)
2175 			{
2176 				dcc_resume (dcc);
2177 			}
2178 			else
2179 			{
2180 				dcc->resumable = 0;
2181 				dcc->pos = 0;
2182 				dcc_connect (dcc);
2183 			}
2184 		}
2185 		break;
2186 	case STAT_DONE:
2187 	case STAT_FAILED:
2188 	case STAT_ABORTED:
2189 		dcc_close (dcc, 0, TRUE);
2190 		break;
2191 	default:
2192 		break;
2193 	}
2194 }
2195 
2196 /* for "Save As..." dialog */
2197 
2198 void
dcc_get_with_destfile(struct DCC * dcc,char * file)2199 dcc_get_with_destfile (struct DCC *dcc, char *file)
2200 {
2201 	g_free (dcc->destfile);
2202 	dcc->destfile = g_strdup (file);	/* utf-8 */
2203 
2204 	/* since destfile changed, must check resumability again */
2205 	update_is_resumable (dcc);
2206 
2207 	dcc_get (dcc);
2208 }
2209 
2210 void
dcc_get_nick(struct session * sess,char * nick)2211 dcc_get_nick (struct session *sess, char *nick)
2212 {
2213 	struct DCC *dcc;
2214 	GSList *list = dcc_list;
2215 	while (list)
2216 	{
2217 		dcc = (struct DCC *) list->data;
2218 		if (!sess->server->p_cmp (nick, dcc->nick))
2219 		{
2220 			if (dcc->dccstat == STAT_QUEUED && dcc->type == TYPE_RECV)
2221 			{
2222 				update_is_resumable (dcc);
2223 				if (prefs.hex_dcc_auto_resume && dcc->resumable)
2224 				{
2225 					dcc_resume (dcc);
2226 				}
2227 				else
2228 				{
2229 					dcc->pos = 0;
2230 					dcc->ack = 0;
2231 					dcc_connect (dcc);
2232 				}
2233 				return;
2234 			}
2235 		}
2236 		list = list->next;
2237 	}
2238 	if (sess)
2239 		EMIT_SIGNAL (XP_TE_DCCIVAL, sess, NULL, NULL, NULL, NULL, 0);
2240 }
2241 
2242 static struct DCC *
new_dcc(void)2243 new_dcc (void)
2244 {
2245 	struct DCC *dcc = g_new0 (struct DCC, 1);
2246 	dcc->sok = -1;
2247 	dcc->fp = -1;
2248 	dcc_list = g_slist_prepend (dcc_list, dcc);
2249 	if (timeout_timer == 0)
2250 	{
2251 		timeout_timer = fe_timeout_add_seconds (1, dcc_check_timeouts, NULL);
2252 	}
2253 	return dcc;
2254 }
2255 
2256 void
dcc_chat(struct session * sess,char * nick,int passive)2257 dcc_chat (struct session *sess, char *nick, int passive)
2258 {
2259 	char outbuf[512];
2260 	struct DCC *dcc;
2261 
2262 	dcc = find_dcc (nick, "", TYPE_CHATSEND);
2263 	if (dcc)
2264 	{
2265 		switch (dcc->dccstat)
2266 		{
2267 		case STAT_ACTIVE:
2268 		case STAT_QUEUED:
2269 		case STAT_CONNECTING:
2270 			EMIT_SIGNAL (XP_TE_DCCCHATREOFFER, sess, nick, NULL, NULL, NULL, 0);
2271 			return;
2272 		case STAT_ABORTED:
2273 		case STAT_FAILED:
2274 			dcc_close (dcc, 0, TRUE);
2275 			break;
2276 		case STAT_DONE:
2277 			break;
2278 		}
2279 	}
2280 	dcc = find_dcc (nick, "", TYPE_CHATRECV);
2281 	if (dcc)
2282 	{
2283 		switch (dcc->dccstat)
2284 		{
2285 		case STAT_QUEUED:
2286 			dcc_connect (dcc);
2287 			break;
2288 		case STAT_FAILED:
2289 		case STAT_ABORTED:
2290 			dcc_close (dcc, 0, TRUE);
2291 			break;
2292 		default:
2293 			break;
2294 		}
2295 		return;
2296 	}
2297 	/* offer DCC CHAT */
2298 
2299 	dcc = new_dcc ();
2300 	if (!dcc)
2301 		return;
2302 	dcc->starttime = dcc->offertime = time (0);
2303 	dcc->serv = sess->server;
2304 	dcc->dccstat = STAT_QUEUED;
2305 	dcc->type = TYPE_CHATSEND;
2306 	dcc->nick = g_strdup (nick);
2307 	if (passive || dcc_listen_init (dcc, sess))
2308 	{
2309 		if (prefs.hex_gui_autoopen_chat)
2310 		{
2311 			if (fe_dcc_open_chat_win (TRUE))	/* already open? add only */
2312 				fe_dcc_add (dcc);
2313 		} else
2314 			fe_dcc_add (dcc);
2315 
2316 		if (passive)
2317 		{
2318 			dcc->pasvid = new_id ();
2319 			g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat 199 %d %d",
2320 						 dcc->port, dcc->pasvid);
2321 		} else
2322 		{
2323 			g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat %u %d",
2324 						 dcc->addr, dcc->port);
2325 		}
2326 		dcc->serv->p_ctcp (dcc->serv, nick, outbuf);
2327 		EMIT_SIGNAL (XP_TE_DCCCHATOFFERING, sess, nick, NULL, NULL, NULL, 0);
2328 	} else
2329 	{
2330 		dcc_close (dcc, 0, TRUE);
2331 	}
2332 }
2333 
2334 static void
dcc_malformed(struct session * sess,char * nick,char * data)2335 dcc_malformed (struct session *sess, char *nick, char *data)
2336 {
2337 	EMIT_SIGNAL (XP_TE_MALFORMED, sess, nick, data, NULL, NULL, 0);
2338 }
2339 
2340 int
dcc_resume(struct DCC * dcc)2341 dcc_resume (struct DCC *dcc)
2342 {
2343 	char tbuf[500];
2344 
2345 	update_is_resumable (dcc);
2346 
2347 	if (dcc->dccstat == STAT_QUEUED && dcc->resumable)
2348 	{
2349 		dcc->resume_sent = 1;
2350 		/* filename contains spaces? Quote them! */
2351 		g_snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ?
2352 					  "DCC RESUME \"%s\" %d %" G_GUINT64_FORMAT :
2353 					  "DCC RESUME %s %d %" G_GUINT64_FORMAT,
2354 					  dcc->file, dcc->port, dcc->resumable);
2355 
2356 		if (dcc->pasvid)
2357  			sprintf (tbuf + strlen (tbuf), " %d", dcc->pasvid);
2358 
2359 		dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
2360 		return 1;
2361 	}
2362 
2363 	return 0;
2364 }
2365 
2366 static void
dcc_confirm_send(void * ud)2367 dcc_confirm_send (void *ud)
2368 {
2369 	struct DCC *dcc = (struct DCC *) ud;
2370 	dcc_get (dcc);
2371 }
2372 
2373 static void
dcc_deny_send(void * ud)2374 dcc_deny_send (void *ud)
2375 {
2376 	struct DCC *dcc = (struct DCC *) ud;
2377 	dcc_abort (dcc->serv->front_session, dcc);
2378 }
2379 
2380 static void
dcc_confirm_chat(void * ud)2381 dcc_confirm_chat (void *ud)
2382 {
2383 	struct DCC *dcc = (struct DCC *) ud;
2384 	dcc_connect (dcc);
2385 }
2386 
2387 static void
dcc_deny_chat(void * ud)2388 dcc_deny_chat (void *ud)
2389 {
2390 	struct DCC *dcc = (struct DCC *) ud;
2391 	dcc_abort (dcc->serv->front_session, dcc);
2392 }
2393 
2394 static struct DCC *
dcc_add_chat(session * sess,char * nick,int port,guint32 addr,int pasvid)2395 dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
2396 {
2397 	struct DCC *dcc;
2398 
2399 	dcc = new_dcc ();
2400 	if (dcc)
2401 	{
2402 		dcc->serv = sess->server;
2403 		dcc->type = TYPE_CHATRECV;
2404 		dcc->dccstat = STAT_QUEUED;
2405 		dcc->addr = addr;
2406 		dcc->port = port;
2407 		dcc->pasvid = pasvid;
2408 		dcc->nick = g_strdup (nick);
2409 		dcc->starttime = time (0);
2410 
2411 		EMIT_SIGNAL (XP_TE_DCCCHATOFFER, sess->server->front_session, nick,
2412 						 NULL, NULL, NULL, 0);
2413 
2414 		if (prefs.hex_gui_autoopen_chat)
2415 		{
2416 			if (fe_dcc_open_chat_win (TRUE))	/* already open? add only */
2417 				fe_dcc_add (dcc);
2418 		} else
2419 			fe_dcc_add (dcc);
2420 
2421 		if (prefs.hex_dcc_auto_chat)
2422 		{
2423 			dcc_connect (dcc);
2424 		}
2425 		else
2426 		{
2427 			char buff[128];
2428 			g_snprintf (buff, sizeof (buff), "%s is offering DCC Chat. Do you want to accept?", nick);
2429 			fe_confirm (buff, dcc_confirm_chat, dcc_deny_chat, dcc);
2430 		}
2431 	}
2432 
2433 	return dcc;
2434 }
2435 
2436 static struct DCC *
dcc_add_file(session * sess,char * file,guint64 size,int port,char * nick,guint32 addr,int pasvid)2437 dcc_add_file (session *sess, char *file, guint64 size, int port, char *nick, guint32 addr, int pasvid)
2438 {
2439 	struct DCC *dcc;
2440 	char tbuf[512];
2441 
2442 	dcc = new_dcc ();
2443 	if (dcc)
2444 	{
2445 		dcc->file = g_strdup (file);
2446 
2447 		dcc->destfile = g_malloc (strlen (prefs.hex_dcc_dir) + strlen (nick) +
2448 										  strlen (file) + 4);
2449 
2450 		strcpy (dcc->destfile, prefs.hex_dcc_dir);
2451 		if (prefs.hex_dcc_dir[strlen (prefs.hex_dcc_dir) - 1] != G_DIR_SEPARATOR)
2452 			strcat (dcc->destfile, G_DIR_SEPARATOR_S);
2453 		if (prefs.hex_dcc_save_nick)
2454 		{
2455 #ifdef WIN32
2456 			char *t = strlen (dcc->destfile) + dcc->destfile;
2457 			strcpy (t, nick);
2458 			while (*t)
2459 			{
2460 				if (*t == '\\' || *t == '|')
2461 					*t = '_';
2462 				t++;
2463 			}
2464 #else
2465 			strcat (dcc->destfile, nick);
2466 #endif
2467 			strcat (dcc->destfile, ".");
2468 		}
2469 		strcat (dcc->destfile, file);
2470 
2471 		dcc->resumable = 0;
2472 		dcc->pos = 0;
2473 		dcc->serv = sess->server;
2474 		dcc->type = TYPE_RECV;
2475 		dcc->dccstat = STAT_QUEUED;
2476 		dcc->addr = addr;
2477 		dcc->port = port;
2478 		dcc->pasvid = pasvid;
2479 		dcc->size = size;
2480 		dcc->nick = g_strdup (nick);
2481 		dcc->maxcps = prefs.hex_dcc_max_get_cps;
2482 
2483 		update_is_resumable (dcc);
2484 
2485 		if (prefs.hex_dcc_auto_recv == 1)
2486 		{
2487 			g_snprintf (tbuf, sizeof (tbuf), _("%s is offering \"%s\". Do you want to accept?"), nick, file);
2488 			fe_confirm (tbuf, dcc_confirm_send, dcc_deny_send, dcc);
2489 		}
2490 		else if (prefs.hex_dcc_auto_recv == 2)
2491 		{
2492 			dcc_get (dcc);
2493 		}
2494 		if (prefs.hex_gui_autoopen_recv)
2495 		{
2496 			if (fe_dcc_open_recv_win (TRUE))	/* was already open? just add*/
2497 				fe_dcc_add (dcc);
2498 		} else
2499 			fe_dcc_add (dcc);
2500 	}
2501 	sprintf (tbuf, "%" G_GUINT64_FORMAT, size);
2502 	g_snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port);
2503 	EMIT_SIGNAL (XP_TE_DCCSENDOFFER, sess->server->front_session, nick,
2504 					 file, tbuf, tbuf + 24, 0);
2505 
2506 	return dcc;
2507 }
2508 
2509 void
handle_dcc(struct session * sess,char * nick,char * word[],char * word_eol[],const message_tags_data * tags_data)2510 handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
2511 				const message_tags_data *tags_data)
2512 {
2513 	char tbuf[512];
2514 	struct DCC *dcc;
2515 	char *type = word[5];
2516 	int port, pasvid = 0;
2517 	guint32 addr;
2518 	guint64 size;
2519 	int psend = 0;
2520 
2521 	if (!g_ascii_strcasecmp (type, "CHAT"))
2522 	{
2523 		port = atoi (word[8]);
2524 		addr = strtoul (word[7], NULL, 10);
2525 
2526 		if (port == 0)
2527 			pasvid = atoi (word[9]);
2528 		else if (word[9][0] != 0)
2529 		{
2530 			pasvid = atoi (word[9]);
2531 			psend = 1;
2532 		}
2533 
2534 		if (!addr /*|| (port < 1024 && port != 0)*/
2535 			|| port > 0xffff || (port == 0 && pasvid == 0))
2536 		{
2537 			dcc_malformed (sess, nick, word_eol[4] + 2);
2538 			return;
2539 		}
2540 
2541 		if (psend)
2542 		{
2543 			dcc = find_dcc_from_id (pasvid, TYPE_CHATSEND);
2544 			if (dcc)
2545 			{
2546 				dcc->addr = addr;
2547 				dcc->port = port;
2548 				dcc_connect (dcc);
2549 			} else
2550 			{
2551 				dcc_malformed (sess, nick, word_eol[4] + 2);
2552 			}
2553 			return;
2554 		}
2555 
2556 		dcc = find_dcc (nick, "", TYPE_CHATSEND);
2557 		if (dcc)
2558 			dcc_close (dcc, 0, TRUE);
2559 
2560 		dcc = find_dcc (nick, "", TYPE_CHATRECV);
2561 		if (dcc)
2562 			dcc_close (dcc, 0, TRUE);
2563 
2564 		dcc_add_chat (sess, nick, port, addr, pasvid);
2565 		return;
2566 	}
2567 
2568 	if (!g_ascii_strcasecmp (type, "Resume"))
2569 	{
2570 		port = atoi (word[7]);
2571 
2572 		if (port == 0)
2573 		{ /* PASSIVE */
2574 			pasvid = atoi(word[9]);
2575 			dcc = find_dcc_from_id(pasvid, TYPE_SEND);
2576 		} else
2577 		{
2578 			dcc = find_dcc_from_port (port, TYPE_SEND);
2579 		}
2580 		if (!dcc)
2581 			dcc = find_dcc (nick, word[6], TYPE_SEND);
2582 		if (dcc)
2583 		{
2584 			size = g_ascii_strtoull (word[8], NULL, 10);
2585 			dcc->resumable = size;
2586 			if (dcc->resumable < dcc->size)
2587 			{
2588 				dcc->pos = dcc->resumable;
2589 				dcc->ack = dcc->resumable;
2590 				lseek (dcc->fp, dcc->pos, SEEK_SET);
2591 
2592 				/* Checking if dcc is passive and if filename contains spaces */
2593 				if (dcc->pasvid)
2594 					g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
2595 							"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT " %d" :
2596 							"DCC ACCEPT %s %d %" G_GUINT64_FORMAT " %d",
2597 							file_part (dcc->file), port, dcc->resumable, dcc->pasvid);
2598 				else
2599 					g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
2600 							"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT :
2601 							"DCC ACCEPT %s %d %" G_GUINT64_FORMAT,
2602 							file_part (dcc->file), port, dcc->resumable);
2603 
2604 				dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
2605 			}
2606 			sprintf (tbuf, "%" G_GUINT64_FORMAT, dcc->pos);
2607 			EMIT_SIGNAL_TIMESTAMP (XP_TE_DCCRESUMEREQUEST, sess, nick,
2608 										  file_part (dcc->file), tbuf, NULL, 0,
2609 										  tags_data->timestamp);
2610 		}
2611 		return;
2612 	}
2613 	if (!g_ascii_strcasecmp (type, "Accept"))
2614 	{
2615 		port = atoi (word[7]);
2616 		dcc = find_dcc_from_port (port, TYPE_RECV);
2617 		if (dcc && dcc->dccstat == STAT_QUEUED)
2618 		{
2619 			dcc_connect (dcc);
2620 		}
2621 		return;
2622 	}
2623 	if (!g_ascii_strcasecmp (type, "SEND"))
2624 	{
2625 		char *file = file_part (word[6]);
2626 
2627 		port = atoi (word[8]);
2628 		addr = strtoul (word[7], NULL, 10);
2629 		size = g_ascii_strtoull (word[9], NULL, 10);
2630 
2631 		if (port == 0) /* Passive dcc requested */
2632 			pasvid = atoi (word[10]);
2633 		else if (word[10][0] != 0)
2634 		{
2635 			/* Requesting passive dcc.
2636 			 * Destination user of an active dcc is giving his
2637 			 * TRUE address/port/pasvid data.
2638 			 * This information will be used later to
2639 			 * establish the connection to the user.
2640 			 * We can recognize this type of dcc using word[10]
2641 			 * because this field is always null (no pasvid)
2642 			 * in normal dcc sends.
2643 			 */
2644 			pasvid = atoi (word[10]);
2645 			psend = 1;
2646 		}
2647 
2648 
2649 		if (!addr || !size /*|| (port < 1024 && port != 0)*/
2650 			|| port > 0xffff || (port == 0 && pasvid == 0))
2651 		{
2652 			dcc_malformed (sess, nick, word_eol[4] + 2);
2653 			return;
2654 		}
2655 
2656 		if (psend)
2657 		{
2658 			/* Third Step of Passive send.
2659 			 * Connecting to the destination and finally
2660 			 * sending file.
2661 			 */
2662 			dcc = find_dcc_from_id (pasvid, TYPE_SEND);
2663 			if (dcc)
2664 			{
2665 				dcc->addr = addr;
2666 				dcc->port = port;
2667 				dcc_connect (dcc);
2668 			} else
2669 			{
2670 				dcc_malformed (sess, nick, word_eol[4] + 2);
2671 			}
2672 			return;
2673 		}
2674 
2675 		dcc_add_file (sess, file, size, port, nick, addr, pasvid);
2676 
2677 	} else
2678 	{
2679 		EMIT_SIGNAL_TIMESTAMP (XP_TE_DCCGENERICOFFER, sess->server->front_session,
2680 									  word_eol[4] + 2, nick, NULL, NULL, 0,
2681 									  tags_data->timestamp);
2682 	}
2683 }
2684 
2685 void
dcc_show_list(struct session * sess)2686 dcc_show_list (struct session *sess)
2687 {
2688 	int i = 0;
2689 	struct DCC *dcc;
2690 	GSList *list = dcc_list;
2691 
2692 	EMIT_SIGNAL (XP_TE_DCCHEAD, sess, NULL, NULL, NULL, NULL, 0);
2693 	while (list)
2694 	{
2695 		dcc = (struct DCC *) list->data;
2696 		i++;
2697 		PrintTextf (sess, " %s  %-10.10s %-7.7s %-7" G_GUINT64_FORMAT " %-7" G_GUINT64_FORMAT " %s\n",
2698 					 dcctypes[dcc->type], dcc->nick,
2699 					 _(dccstat[dcc->dccstat].name), dcc->size, dcc->pos,
2700 					 file_part (dcc->file));
2701 		list = list->next;
2702 	}
2703 	if (!i)
2704 		PrintText (sess, _("No active DCCs\n"));
2705 }
2706